root / trunk / extensions / extGeoProcessing / src / com / iver / cit / gvsig / geoprocess / difference / fmap / DifferenceVisitor.java @ 5412
History | View | Annotate | Download (10.1 KB)
1 | 5412 | azabala | /*
|
---|---|---|---|
2 | * Created on 22-feb-2006
|
||
3 | *
|
||
4 | * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
||
5 | *
|
||
6 | * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
||
7 | *
|
||
8 | * This program is free software; you can redistribute it and/or
|
||
9 | * modify it under the terms of the GNU General Public License
|
||
10 | * as published by the Free Software Foundation; either version 2
|
||
11 | * of the License, or (at your option) any later version.
|
||
12 | *
|
||
13 | * This program is distributed in the hope that it will be useful,
|
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
16 | * GNU General Public License for more details.
|
||
17 | *
|
||
18 | * You should have received a copy of the GNU General Public License
|
||
19 | * along with this program; if not, write to the Free Software
|
||
20 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
||
21 | *
|
||
22 | * For more information, contact:
|
||
23 | *
|
||
24 | * Generalitat Valenciana
|
||
25 | * Conselleria d'Infraestructures i Transport
|
||
26 | * Av. Blasco Ib??ez, 50
|
||
27 | * 46010 VALENCIA
|
||
28 | * SPAIN
|
||
29 | *
|
||
30 | * +34 963862235
|
||
31 | * gvsig@gva.es
|
||
32 | * www.gvsig.gva.es
|
||
33 | *
|
||
34 | * or
|
||
35 | *
|
||
36 | * IVER T.I. S.A
|
||
37 | * Salamanca 50
|
||
38 | * 46005 Valencia
|
||
39 | * Spain
|
||
40 | *
|
||
41 | * +34 963163400
|
||
42 | * dac@iver.es
|
||
43 | */
|
||
44 | /* CVS MESSAGES:
|
||
45 | *
|
||
46 | * $Id$
|
||
47 | * $Log$
|
||
48 | * Revision 1.1 2006-05-24 21:11:38 azabala
|
||
49 | * primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing
|
||
50 | *
|
||
51 | * Revision 1.4 2006/05/01 19:15:18 azabala
|
||
52 | * *** empty log message ***
|
||
53 | *
|
||
54 | * Revision 1.3 2006/03/26 20:02:25 azabala
|
||
55 | * *** empty log message ***
|
||
56 | *
|
||
57 | * Revision 1.2 2006/03/07 21:01:33 azabala
|
||
58 | * *** empty log message ***
|
||
59 | *
|
||
60 | * Revision 1.1 2006/03/06 19:48:39 azabala
|
||
61 | * *** empty log message ***
|
||
62 | *
|
||
63 | * Revision 1.2 2006/03/05 19:58:10 azabala
|
||
64 | * *** empty log message ***
|
||
65 | *
|
||
66 | * Revision 1.1 2006/02/26 20:53:28 azabala
|
||
67 | * *** empty log message ***
|
||
68 | *
|
||
69 | *
|
||
70 | */
|
||
71 | package com.iver.cit.gvsig.geoprocess.difference.fmap; |
||
72 | |||
73 | import com.hardcode.gdbms.engine.data.driver.DriverException; |
||
74 | import com.hardcode.gdbms.engine.values.Value; |
||
75 | import com.hardcode.gdbms.engine.values.ValueFactory; |
||
76 | import com.iver.cit.gvsig.fmap.core.IFeature; |
||
77 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
78 | import com.iver.cit.gvsig.fmap.core.v02.FConverter; |
||
79 | import com.iver.cit.gvsig.fmap.drivers.FieldDescription; |
||
80 | import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition; |
||
81 | import com.iver.cit.gvsig.fmap.edition.EditionException; |
||
82 | import com.iver.cit.gvsig.fmap.layers.FBitSet; |
||
83 | import com.iver.cit.gvsig.fmap.layers.FLayer; |
||
84 | import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
||
85 | import com.iver.cit.gvsig.fmap.layers.SelectableDataSource; |
||
86 | import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData; |
||
87 | import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData; |
||
88 | import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
||
89 | import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
||
90 | import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
||
91 | import com.iver.cit.gvsig.geoprocess.convexhull.fmap.ScalableUnionVisitor; |
||
92 | import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory; |
||
93 | import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
||
94 | import com.vividsolutions.jts.geom.Geometry; |
||
95 | import com.vividsolutions.jts.geom.GeometryCollection; |
||
96 | import com.vividsolutions.jts.geom.MultiPolygon; |
||
97 | import com.vividsolutions.jts.geom.Polygon; |
||
98 | import com.vividsolutions.jts.precision.EnhancedPrecisionOp; |
||
99 | |||
100 | public class DifferenceVisitor implements FeatureVisitor { |
||
101 | |||
102 | /**
|
||
103 | * Allows to get attributes of first layer features which is being
|
||
104 | * differenced
|
||
105 | */
|
||
106 | SelectableDataSource firstRs; |
||
107 | |||
108 | /**
|
||
109 | * Number of fields of first layer recordset
|
||
110 | */
|
||
111 | int numFieldsA;
|
||
112 | |||
113 | /**
|
||
114 | * looks for overlay features of the processed feauture by spatial criteria
|
||
115 | * (queryByEnvelope)
|
||
116 | */
|
||
117 | FLyrVect overlayLayer; |
||
118 | |||
119 | /**
|
||
120 | * Strategy to process overlaylayer, allowing cancelations
|
||
121 | */
|
||
122 | Strategy strategy; |
||
123 | |||
124 | /**
|
||
125 | * this flag marks if visitor only must process overlay layer selection
|
||
126 | */
|
||
127 | boolean onlyOverlayLayerSelected;
|
||
128 | |||
129 | /**
|
||
130 | * It processes features resulting of intersetions. It could saves them in
|
||
131 | * persistent datastore, caching them, reprocess them, reprojects them, etc.
|
||
132 | */
|
||
133 | FeatureProcessor featureProcessor; |
||
134 | |||
135 | /**
|
||
136 | * Schema of result layer
|
||
137 | */
|
||
138 | ILayerDefinition layerDefinition; |
||
139 | |||
140 | /**
|
||
141 | * Constructor
|
||
142 | *
|
||
143 | * @param overlayLayer
|
||
144 | * @param processor
|
||
145 | * @throws DriverException
|
||
146 | */
|
||
147 | public DifferenceVisitor(FLyrVect overlayLayer, FeatureProcessor processor,
|
||
148 | Strategy strategy, boolean onlySelection) throws DriverException { |
||
149 | this.overlayLayer = overlayLayer;
|
||
150 | this.featureProcessor = processor;
|
||
151 | this.strategy = strategy;
|
||
152 | this.onlyOverlayLayerSelected = onlySelection;
|
||
153 | } |
||
154 | |||
155 | /**
|
||
156 | * Inner class to process with a given strategy all geometries of overlay layer
|
||
157 | * that overlays with a given geometry of input layer.
|
||
158 | * @author azabala
|
||
159 | *
|
||
160 | */
|
||
161 | class UnionOverlaysVisitor implements FeatureVisitor { |
||
162 | /**
|
||
163 | * Result of the strategy process (union of overlays of a IGeometry)
|
||
164 | */
|
||
165 | Geometry overlayGeometry; |
||
166 | |||
167 | /**
|
||
168 | * Flag to process or not selections of overlay layer
|
||
169 | */
|
||
170 | boolean overlayLayerSelected = true; |
||
171 | |||
172 | Geometry getUnionOfOverlays() { |
||
173 | return overlayGeometry;
|
||
174 | } |
||
175 | |||
176 | public void visit(IGeometry g, int index) throws VisitException { |
||
177 | if (overlayLayerSelected) {
|
||
178 | try {
|
||
179 | if (!overlayLayer.getRecordset().getSelection().get(index))
|
||
180 | return;
|
||
181 | } catch (com.iver.cit.gvsig.fmap.DriverException e) {
|
||
182 | throw new VisitException( |
||
183 | "Error en diferencia: verificando si un posible overlay esta seleccionado",
|
||
184 | e); |
||
185 | }// geometry g is not selected
|
||
186 | } |
||
187 | Geometry actualGeometry = g.toJTSGeometry(); |
||
188 | if (overlayGeometry == null) { |
||
189 | overlayGeometry = actualGeometry; |
||
190 | } else {
|
||
191 | /*
|
||
192 | * Geometry[] geoms = new Geometry[2];
|
||
193 | * geoms[0] = actualGeometry;
|
||
194 | * geoms[1] = overlayGeometry;
|
||
195 | * GeometryCollection gc = geomFact.
|
||
196 | * createGeometryCollection(geoms);
|
||
197 | * geometry = gc.buffer(0);
|
||
198 | */
|
||
199 | overlayGeometry = actualGeometry.union(overlayGeometry); |
||
200 | }// if
|
||
201 | |||
202 | }// visit
|
||
203 | |||
204 | public String getProcessDescription() { |
||
205 | return ""; |
||
206 | } |
||
207 | |||
208 | public void stop(FLayer layer) { |
||
209 | } |
||
210 | |||
211 | public boolean start(FLayer layer) { |
||
212 | return true; |
||
213 | } |
||
214 | }//UnionOverlaysVisitor
|
||
215 | |||
216 | |||
217 | public void visit(IGeometry g, final int index) throws VisitException { |
||
218 | Geometry firstJts = g.toJTSGeometry(); |
||
219 | Geometry solution = null;
|
||
220 | try {
|
||
221 | UnionOverlaysVisitor unionVisitor = new UnionOverlaysVisitor();
|
||
222 | unionVisitor.overlayLayerSelected = onlyOverlayLayerSelected; |
||
223 | strategy.process(unionVisitor, g.getBounds2D()); |
||
224 | // now we compute difference of firstJts and overlaysUnion
|
||
225 | Geometry overlays = unionVisitor.getUnionOfOverlays(); |
||
226 | if (overlays != null) { |
||
227 | solution = EnhancedPrecisionOp.difference(firstJts, overlays); |
||
228 | } else {
|
||
229 | solution = firstJts; |
||
230 | } |
||
231 | if (!(solution instanceof Polygon)) { |
||
232 | if (!(solution instanceof MultiPolygon)) { |
||
233 | // intersection of adjacent polygons is a linestring
|
||
234 | // but we are not interested in it
|
||
235 | return;
|
||
236 | } |
||
237 | } |
||
238 | featureProcessor.processFeature(createFeature(solution, index)); |
||
239 | |||
240 | } catch (com.iver.cit.gvsig.fmap.DriverException e) {
|
||
241 | throw new VisitException( |
||
242 | "Error buscando los overlays que intersectan con un feature");
|
||
243 | } catch (DriverException e) {
|
||
244 | throw new VisitException( |
||
245 | "Error al guardar feature en el geoproceso diferencia");
|
||
246 | } |
||
247 | } |
||
248 | |||
249 | public void stop(FLayer layer) { |
||
250 | featureProcessor.finish(); |
||
251 | } |
||
252 | |||
253 | public boolean start(FLayer layer) { |
||
254 | if (layer instanceof AlphanumericData && layer instanceof VectorialData) { |
||
255 | try {
|
||
256 | this.firstRs = ((AlphanumericData) layer).getRecordset();
|
||
257 | numFieldsA = firstRs.getFieldCount(); |
||
258 | this.featureProcessor.start();
|
||
259 | } catch (com.iver.cit.gvsig.fmap.DriverException e) {
|
||
260 | return false; |
||
261 | } catch (DriverException e) {
|
||
262 | return false; |
||
263 | } catch (EditionException e) {
|
||
264 | return false; |
||
265 | } |
||
266 | |||
267 | return true; |
||
268 | } |
||
269 | return false; |
||
270 | } |
||
271 | |||
272 | /**
|
||
273 | *
|
||
274 | * @param jtsGeometry
|
||
275 | * @param firstLayerIndex
|
||
276 | * @return
|
||
277 | * @throws DriverException
|
||
278 | *
|
||
279 | * FIXME Revisar. Para el caso de la Union, hay que hacer dos pasadas:
|
||
280 | * diferencia A-B y diferencia B-A. Pero los features tienen que tener el
|
||
281 | * esquema de la intersecci?n. ?Como saber el lugar que ocupa cada atributo
|
||
282 | * en el esquema ILayerDefinition, en el caso de que dos capas tuviesen
|
||
283 | * atributos con el mismo nombre?) De momento, se buscar? en
|
||
284 | * ILayerDefinition la posicion que ocupa un campo a partir de su nombre.
|
||
285 | * Esto obliga a que 2 campos no tomen el mismo nombre
|
||
286 | */
|
||
287 | private IFeature createFeature(Geometry jtsGeometry, int firstLayerIndex) |
||
288 | throws DriverException {
|
||
289 | IFeature solution = null;
|
||
290 | IGeometry diffGeometry = FConverter.jts_to_igeometry(jtsGeometry); |
||
291 | FieldDescription[] fields = layerDefinition.getFieldsDesc();
|
||
292 | Value[] featureAttr = new Value[fields.length]; |
||
293 | for (int indexField = 0; indexField < numFieldsA; indexField++) { |
||
294 | // for each field of firstRs
|
||
295 | String fieldName = firstRs.getFieldName(indexField);
|
||
296 | for (int j = 0; j < fields.length; j++) { |
||
297 | if (fieldName.equalsIgnoreCase(fields[j].getFieldName())) {
|
||
298 | featureAttr[j] = firstRs.getFieldValue(firstLayerIndex, |
||
299 | indexField); |
||
300 | break;
|
||
301 | }// if
|
||
302 | }// for
|
||
303 | }// for
|
||
304 | // now we put null values
|
||
305 | for (int i = 0; i < featureAttr.length; i++) { |
||
306 | if (featureAttr[i] == null) |
||
307 | featureAttr[i] = ValueFactory.createNullValue(); |
||
308 | } |
||
309 | solution = FeatureFactory.createFeature(featureAttr, diffGeometry); |
||
310 | return solution;
|
||
311 | } |
||
312 | |||
313 | /*
|
||
314 | * Value[] featureAttr = new Value[numFieldsA]; for (int indexField = 0;
|
||
315 | * indexField < numFieldsA; indexField++) { featureAttr[indexField] =
|
||
316 | * firstRs.getFieldValue(firstLayerIndex, indexField); } solution =
|
||
317 | * FeatureFactory.createFeature(featureAttr, diffGeometry); return solution;
|
||
318 | */
|
||
319 | |||
320 | public void setFeatureProcessor(FeatureProcessor featureProcessor) { |
||
321 | this.featureProcessor = featureProcessor;
|
||
322 | } |
||
323 | |||
324 | public String getProcessDescription() { |
||
325 | return "Computing differences between two layers"; |
||
326 | } |
||
327 | |||
328 | public ILayerDefinition getLayerDefinition() {
|
||
329 | return layerDefinition;
|
||
330 | } |
||
331 | |||
332 | public void setLayerDefinition(ILayerDefinition layerDefinition) { |
||
333 | this.layerDefinition = layerDefinition;
|
||
334 | } |
||
335 | |||
336 | } |