Revision 725
org.gvsig.topology/trunk/org.gvsig.topology/org.gvsig.topology.lib/org.gvsig.topology.lib.api/src/main/java/org/gvsig/topology/lib/api/TopologyDataSet.java | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
package org.gvsig.topology.lib.api; |
25 | 25 |
|
26 |
import org.gvsig.expressionevaluator.Expression; |
|
26 | 27 |
import org.gvsig.fmap.dal.exception.DataException; |
27 | 28 |
import org.gvsig.fmap.dal.feature.EditableFeature; |
28 | 29 |
import org.gvsig.fmap.dal.feature.Feature; |
29 | 30 |
import org.gvsig.fmap.dal.feature.FeatureReference; |
30 | 31 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
32 |
import org.gvsig.fmap.geom.Geometry; |
|
33 |
import org.gvsig.fmap.geom.SpatialIndex; |
|
31 | 34 |
import org.gvsig.tools.util.PropertiesSupport; |
32 | 35 |
import org.gvsig.tools.visitor.VisitCanceledException; |
33 | 36 |
import org.gvsig.tools.visitor.Visitor; |
... | ... | |
69 | 72 |
public void update(EditableFeature feature) throws DataException; |
70 | 73 |
|
71 | 74 |
public long getSize(); |
75 |
|
|
76 |
public SpatialIndex getSpatialIndex(); |
|
77 |
|
|
78 |
public Iterable<FeatureReference> query(Geometry geom); |
|
79 |
|
|
80 |
public Feature findFirst(Expression expression); |
|
81 |
|
|
72 | 82 |
} |
org.gvsig.topology/trunk/org.gvsig.topology/org.gvsig.topology.lib/org.gvsig.topology.lib.impl/src/main/java/org/gvsig/topology/lib/impl/DefaultTopologyDataSet.java | ||
---|---|---|
23 | 23 |
*/ |
24 | 24 |
package org.gvsig.topology.lib.impl; |
25 | 25 |
|
26 |
import java.util.Iterator; |
|
26 | 27 |
import java.util.Map; |
28 |
import org.apache.commons.collections.IteratorUtils; |
|
27 | 29 |
import org.apache.commons.lang3.StringUtils; |
30 |
import org.apache.commons.lang3.mutable.MutableObject; |
|
31 |
import org.gvsig.expressionevaluator.Expression; |
|
28 | 32 |
import org.gvsig.fmap.dal.EditingNotification; |
29 | 33 |
import org.gvsig.fmap.dal.EditingNotificationManager; |
30 | 34 |
import org.gvsig.fmap.dal.exception.DataException; |
... | ... | |
33 | 37 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
34 | 38 |
import org.gvsig.fmap.dal.feature.FeatureReference; |
35 | 39 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
40 |
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory; |
|
36 | 41 |
import org.gvsig.fmap.dal.feature.FeatureType; |
37 | 42 |
import org.gvsig.fmap.dal.swing.DALSwingLocator; |
38 | 43 |
import org.gvsig.fmap.geom.Geometry; |
44 |
import org.gvsig.fmap.geom.GeometryLocator; |
|
45 |
import org.gvsig.fmap.geom.GeometryManager; |
|
46 |
import org.gvsig.fmap.geom.SpatialIndex; |
|
39 | 47 |
import org.gvsig.fmap.geom.type.GeometryType; |
40 | 48 |
import org.gvsig.tools.exception.BaseException; |
41 | 49 |
import org.gvsig.tools.util.PropertiesSupportHelper; |
... | ... | |
48 | 56 |
import org.gvsig.topology.lib.api.TopologyManager; |
49 | 57 |
import org.json.JSONObject; |
50 | 58 |
import org.gvsig.topology.lib.api.TopologyServices; |
59 |
import org.slf4j.Logger; |
|
60 |
import org.slf4j.LoggerFactory; |
|
51 | 61 |
|
52 | 62 |
/** |
53 | 63 |
* |
... | ... | |
56 | 66 |
@SuppressWarnings({"EqualsAndHashcode","UseSpecificCatch"}) |
57 | 67 |
public class DefaultTopologyDataSet implements TopologyDataSet { |
58 | 68 |
|
69 |
private final static Logger LOGGER = LoggerFactory.getLogger(DefaultTopologyDataSet.class); |
|
70 |
|
|
59 | 71 |
private TopologyServices services; |
60 | 72 |
private String name; |
61 | 73 |
private FeatureStore store; |
62 | 74 |
private boolean needFinishEditing; |
63 | 75 |
private String fullName; |
64 | 76 |
private PropertiesSupportHelper propertiesHelper; |
65 |
|
|
77 |
private MutableObject<SpatialIndex> spatialIndex = null; |
|
78 |
|
|
66 | 79 |
public DefaultTopologyDataSet() { |
67 | 80 |
this.services = null; |
68 | 81 |
this.name = null; |
... | ... | |
323 | 336 |
return this.propertiesHelper.getProperties(); |
324 | 337 |
} |
325 | 338 |
|
339 |
public SpatialIndex getSpatialIndex() { |
|
340 |
if( this.spatialIndex == null ) { |
|
341 |
this.spatialIndex = new MutableObject<>(); |
|
342 |
FeatureStore theStore = this.getStore(); |
|
343 |
FeatureStoreProviderFactory storeFactory = (FeatureStoreProviderFactory) theStore.getProviderFactory(); |
|
344 |
if( storeFactory.useLocalIndexesCanImprovePerformance()==FeatureStoreProviderFactory.YES ) { |
|
345 |
try { |
|
346 |
GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
|
347 |
final SpatialIndex geomIndex = geomManager.createSpatialIndex( |
|
348 |
GeometryManager.SPATIALINDEX_DEFAULT_QUADTREE, |
|
349 |
null |
|
350 |
); |
|
351 |
final SpatialIndex dataIndex = theStore.wrapSpatialIndex(geomIndex); |
|
352 |
try { |
|
353 |
store.accept(new Visitor() { |
|
354 |
@Override |
|
355 |
public void visit(Object o) throws VisitCanceledException, BaseException { |
|
356 |
Feature f = (Feature) o; |
|
357 |
Geometry geom = f.getDefaultGeometry(); |
|
358 |
if (geom != null) { |
|
359 |
dataIndex.insert(geom, f); |
|
360 |
} |
|
361 |
} |
|
362 |
}); |
|
363 |
} catch (VisitCanceledException ex) { |
|
364 |
} |
|
365 |
this.spatialIndex.setValue(dataIndex); |
|
366 |
} catch (Exception ex) { |
|
367 |
LOGGER.warn("Can't create spatial index", ex); |
|
368 |
} |
|
369 |
} |
|
370 |
} |
|
371 |
return this.spatialIndex.getValue(); |
|
372 |
} |
|
373 |
|
|
374 |
public Iterable<FeatureReference> query(Geometry geom) { |
|
375 |
SpatialIndex index = this.getSpatialIndex(); |
|
376 |
if( index == null ) { |
|
377 |
return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR; |
|
378 |
} |
|
379 |
final Iterator it = index.query(geom); |
|
380 |
if( it == null ) { |
|
381 |
return (Iterable<FeatureReference>) IteratorUtils.EMPTY_ITERATOR; |
|
382 |
} |
|
383 |
return new Iterable<FeatureReference>() { |
|
384 |
@Override |
|
385 |
public Iterator<FeatureReference> iterator() { |
|
386 |
return it; |
|
387 |
} |
|
388 |
}; |
|
389 |
} |
|
390 |
|
|
391 |
@Override |
|
392 |
public Feature findFirst(Expression filter) { |
|
393 |
try { |
|
394 |
return this.getStore().findFirst(filter); |
|
395 |
} catch (Exception ex) { |
|
396 |
return null; |
|
397 |
} |
|
398 |
} |
|
399 |
|
|
326 | 400 |
} |
org.gvsig.topology/trunk/org.gvsig.topology/org.gvsig.topology.lib/org.gvsig.topology.lib.impl/src/main/java/org/gvsig/topology/rule/MustNotOverlapPolygonRule.java | ||
---|---|---|
28 | 28 |
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator; |
29 | 29 |
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
30 | 30 |
import org.gvsig.fmap.dal.feature.Feature; |
31 |
import org.gvsig.fmap.dal.feature.FeatureSet; |
|
32 |
import org.gvsig.fmap.dal.feature.FeatureStore; |
|
31 |
import org.gvsig.fmap.dal.feature.FeatureReference; |
|
33 | 32 |
import org.gvsig.fmap.geom.Geometry; |
34 |
import org.gvsig.tools.dispose.DisposableIterator; |
|
35 |
import org.gvsig.tools.dispose.DisposeUtils; |
|
36 | 33 |
import org.gvsig.tools.dynobject.DynObject; |
37 | 34 |
import org.gvsig.tools.task.SimpleTaskStatus; |
38 | 35 |
import org.gvsig.topology.lib.spi.AbstractTopologyRule; |
... | ... | |
60 | 57 |
"CreateFeature", |
61 | 58 |
"Create Feature", |
62 | 59 |
"The Create Feature fix creates a new polygon feature out " |
63 |
+ "of the error shape and removes the portion of "
|
|
64 |
+ "overlap from each of the features, causing the "
|
|
65 |
+ "error to create a planar representation of the "
|
|
66 |
+ "feature geometry. This fix can be applied to "
|
|
67 |
+ "one or more selected Must Not Overlap errors."
|
|
60 |
+ "of the error shape and removes the portion of " |
|
61 |
+ "overlap from each of the features, causing the " |
|
62 |
+ "error to create a planar representation of the " |
|
63 |
+ "feature geometry. This fix can be applied to " |
|
64 |
+ "one or more selected Must Not Overlap errors." |
|
68 | 65 |
); |
69 | 66 |
} |
70 | 67 |
|
71 | 68 |
@Override |
72 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) {
|
|
69 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) { |
|
73 | 70 |
try { |
74 | 71 |
// TODO |
75 | 72 |
} catch (Exception ex) { |
... | ... | |
87 | 84 |
"Subtract", |
88 | 85 |
"Subtract", |
89 | 86 |
"The Subtract fix removes the overlapping portion of " |
90 |
+ "geometry from each feature that is causing the "
|
|
91 |
+ "error and leaves a gap or void in its place. "
|
|
92 |
+ "This fix can be applied to one or more selected "
|
|
93 |
+ "Must Not Overlap errors."
|
|
87 |
+ "geometry from each feature that is causing the " |
|
88 |
+ "error and leaves a gap or void in its place. " |
|
89 |
+ "This fix can be applied to one or more selected " |
|
90 |
+ "Must Not Overlap errors." |
|
94 | 91 |
); |
95 | 92 |
} |
96 | 93 |
|
97 | 94 |
@Override |
98 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) {
|
|
95 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) { |
|
99 | 96 |
try { |
100 | 97 |
// TODO |
101 | 98 |
} catch (Exception ex) { |
... | ... | |
113 | 110 |
"Merge", |
114 | 111 |
"Merge", |
115 | 112 |
"The Merge fix adds the portion of overlap from one feature " |
116 |
+ "and subtracts it from the others that are "
|
|
117 |
+ "violating the rule. You need to pick the feature "
|
|
118 |
+ "that receives the portion of overlap using the "
|
|
119 |
+ "Merge dialog box. This fix can be applied to one "
|
|
120 |
+ "Must Not Overlap error only."
|
|
113 |
+ "and subtracts it from the others that are " |
|
114 |
+ "violating the rule. You need to pick the feature " |
|
115 |
+ "that receives the portion of overlap using the " |
|
116 |
+ "Merge dialog box. This fix can be applied to one " |
|
117 |
+ "Must Not Overlap error only." |
|
121 | 118 |
); |
122 | 119 |
} |
123 | 120 |
|
124 | 121 |
@Override |
125 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) {
|
|
122 |
public void execute(TopologyRule rule, TopologyReportLine line, DynObject parameters) { |
|
126 | 123 |
try { |
127 | 124 |
// TODO |
128 | 125 |
} catch (Exception ex) { |
... | ... | |
130 | 127 |
} |
131 | 128 |
} |
132 | 129 |
} |
133 |
|
|
130 |
|
|
134 | 131 |
private String geomName; |
135 | 132 |
private Expression expression = null; |
136 | 133 |
private ExpressionBuilder expressionBuilder = null; |
137 |
|
|
134 |
|
|
138 | 135 |
public MustNotOverlapPolygonRule( |
139 | 136 |
TopologyPlan plan, |
140 | 137 |
TopologyRuleFactory factory |
... | ... | |
144 | 141 |
this.addAction(new MergeAction()); |
145 | 142 |
this.addAction(new SubtractAction()); |
146 | 143 |
} |
147 |
|
|
144 |
|
|
148 | 145 |
public MustNotOverlapPolygonRule( |
149 | 146 |
TopologyPlan plan, |
150 | 147 |
TopologyRuleFactory factory, |
... | ... | |
160 | 157 |
@Override |
161 | 158 |
protected void check(SimpleTaskStatus taskStatus, TopologyReport report, Feature feature1) throws Exception { |
162 | 159 |
try { |
163 |
if( this.expression == null ) {
|
|
160 |
if (this.expression == null) {
|
|
164 | 161 |
ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager(); |
165 | 162 |
this.expression = manager.createExpression(); |
166 | 163 |
this.expressionBuilder = manager.createExpressionBuilder(); |
167 | 164 |
this.geomName = feature1.getType().getDefaultGeometryAttributeName(); |
168 |
}
|
|
165 |
} |
|
169 | 166 |
Geometry polygon = feature1.getDefaultGeometry(); |
170 |
this.expression.setPhrase( |
|
171 |
this.expressionBuilder.ifnull( |
|
172 |
this.expressionBuilder.column(this.geomName), |
|
173 |
this.expressionBuilder.constant(false), |
|
174 |
this.expressionBuilder.ST_Overlaps( |
|
175 |
this.expressionBuilder.column(this.geomName), |
|
176 |
this.expressionBuilder.geometry(polygon) |
|
177 |
) |
|
178 |
).toString() |
|
179 |
); |
|
180 |
FeatureStore store = this.getDataSet1().getStore(); |
|
181 |
FeatureSet set = null; |
|
182 |
DisposableIterator it = null; |
|
183 |
try { |
|
184 |
Feature f = store.findFirst(this.expression); |
|
185 |
if( f!=null ) { |
|
167 |
if( polygon==null ) { |
|
168 |
return; |
|
169 |
} |
|
170 |
TopologyDataSet theDataSet = this.getDataSet1(); |
|
171 |
if (theDataSet.getSpatialIndex() != null) { |
|
172 |
for (FeatureReference reference : theDataSet.query(polygon)) { |
|
173 |
if (reference.equals(feature1.getReference())) { |
|
174 |
continue; |
|
175 |
} |
|
176 |
Feature feature = reference.getFeature(); |
|
177 |
if (polygon.overlaps(feature.getDefaultGeometry())) { |
|
178 |
report.addLine(this, |
|
179 |
theDataSet, |
|
180 |
null, |
|
181 |
polygon, |
|
182 |
feature1.getReference(), |
|
183 |
null, |
|
184 |
false, |
|
185 |
"The polygon overlay with others." |
|
186 |
); |
|
187 |
break; |
|
188 |
} |
|
189 |
} |
|
190 |
} else { |
|
191 |
this.expression.setPhrase( |
|
192 |
this.expressionBuilder.ifnull( |
|
193 |
this.expressionBuilder.column(this.geomName), |
|
194 |
this.expressionBuilder.constant(false), |
|
195 |
this.expressionBuilder.ST_Overlaps( |
|
196 |
this.expressionBuilder.column(this.geomName), |
|
197 |
this.expressionBuilder.geometry(polygon) |
|
198 |
) |
|
199 |
).toString() |
|
200 |
); |
|
201 |
if (theDataSet.findFirst(this.expression) != null) { |
|
186 | 202 |
report.addLine(this, |
187 |
this.getDataSet1(),
|
|
203 |
theDataSet,
|
|
188 | 204 |
null, |
189 | 205 |
polygon, |
190 | 206 |
feature1.getReference(), |
... | ... | |
193 | 209 |
"The polygon overlay with others." |
194 | 210 |
); |
195 | 211 |
} |
196 |
} finally { |
|
197 |
DisposeUtils.disposeQuietly(set); |
|
198 |
DisposeUtils.disposeQuietly(it); |
|
199 | 212 |
} |
200 |
} catch(Exception ex) { |
|
213 |
} catch (Exception ex) {
|
|
201 | 214 |
LOGGER.warn("Can't check feature.", ex); |
202 | 215 |
} finally { |
203 | 216 |
} |
Also available in: Unified diff