root / trunk / extensions / extGeoProcessing / src / com / iver / cit / gvsig / geoprocess / impl / spatialjoin / fmap / IntersectSpatialJoinVisitor.java @ 15641
History | View | Annotate | Download (10.9 KB)
1 | 5918 | azabala | /*
|
---|---|---|---|
2 | * Created on 01-mar-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 | 13874 | jaume | * Revision 1.3 2007-09-19 16:08:13 jaume
|
49 | * ReadExpansionFileException removed from this context
|
||
50 | *
|
||
51 | * Revision 1.2 2007/03/06 16:47:58 caballero
|
||
52 | 10626 | caballero | * Exceptions
|
53 | *
|
||
54 | * Revision 1.1 2006/06/20 18:20:45 azabala
|
||
55 | 5918 | azabala | * first version in cvs
|
56 | *
|
||
57 | * Revision 1.2 2006/06/02 18:21:28 azabala
|
||
58 | * *** empty log message ***
|
||
59 | *
|
||
60 | * Revision 1.1 2006/05/24 21:09:47 azabala
|
||
61 | * primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing
|
||
62 | *
|
||
63 | * Revision 1.4 2006/03/21 19:29:36 azabala
|
||
64 | * *** empty log message ***
|
||
65 | *
|
||
66 | * Revision 1.3 2006/03/14 18:32:46 fjp
|
||
67 | * Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n.
|
||
68 | *
|
||
69 | * Revision 1.2 2006/03/07 21:01:33 azabala
|
||
70 | * *** empty log message ***
|
||
71 | *
|
||
72 | * Revision 1.1 2006/03/06 19:48:39 azabala
|
||
73 | * *** empty log message ***
|
||
74 | *
|
||
75 | * Revision 1.1 2006/03/05 19:59:47 azabala
|
||
76 | * *** empty log message ***
|
||
77 | *
|
||
78 | *
|
||
79 | */
|
||
80 | package com.iver.cit.gvsig.geoprocess.impl.spatialjoin.fmap; |
||
81 | |||
82 | import java.util.ArrayList; |
||
83 | import java.util.Iterator; |
||
84 | import java.util.Map; |
||
85 | |||
86 | 10626 | caballero | import com.hardcode.gdbms.driver.exceptions.ReadDriverException; |
87 | 5918 | azabala | import com.hardcode.gdbms.engine.values.Value; |
88 | import com.hardcode.gdbms.engine.values.ValueFactory; |
||
89 | 10626 | caballero | import com.iver.cit.gvsig.exceptions.expansionfile.ExpansionFileReadException; |
90 | import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException; |
||
91 | import com.iver.cit.gvsig.exceptions.visitors.StartVisitorException; |
||
92 | import com.iver.cit.gvsig.exceptions.visitors.StopVisitorException; |
||
93 | import com.iver.cit.gvsig.exceptions.visitors.VisitorException; |
||
94 | 5918 | azabala | import com.iver.cit.gvsig.fmap.core.IFeature; |
95 | import com.iver.cit.gvsig.fmap.core.IGeometry; |
||
96 | import com.iver.cit.gvsig.fmap.drivers.FieldDescription; |
||
97 | import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition; |
||
98 | import com.iver.cit.gvsig.fmap.drivers.LayerDefinition; |
||
99 | import com.iver.cit.gvsig.fmap.drivers.SHPLayerDefinition; |
||
100 | import com.iver.cit.gvsig.fmap.layers.FLayer; |
||
101 | import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
||
102 | import com.iver.cit.gvsig.fmap.layers.SelectableDataSource; |
||
103 | import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
||
104 | import com.iver.cit.gvsig.geoprocess.core.fmap.DefinitionUtils; |
||
105 | import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory; |
||
106 | import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
||
107 | import com.iver.cit.gvsig.geoprocess.core.fmap.SummarizationFunction; |
||
108 | import com.iver.cit.gvsig.geoprocess.core.fmap.XTypes; |
||
109 | |||
110 | /**
|
||
111 | * This visitor implements Intersect Geometry Spatial Join.
|
||
112 | 10626 | caballero | *
|
113 | 5918 | azabala | * It is a particular case of 1-M relationship (a feature of layer A always be
|
114 | * related to M feature of layer B)
|
||
115 | * It allows to apply a sumarization function over numeric values of target
|
||
116 | * layer (sum, avg, min, max). If it doesnt find any feature of target layer
|
||
117 | * wich intersects with a given feature of source layer, these values will have
|
||
118 | * 0d value.
|
||
119 | 10626 | caballero | *
|
120 | 5918 | azabala | * @author azabala
|
121 | 10626 | caballero | *
|
122 | 5918 | azabala | */
|
123 | public class IntersectSpatialJoinVisitor implements SpatialJoinVisitor { |
||
124 | 10626 | caballero | |
125 | 5918 | azabala | /**
|
126 | * Needed to create layer definition
|
||
127 | */
|
||
128 | private FLyrVect sourceLayer;
|
||
129 | /**
|
||
130 | * Reads data of features for the source layer
|
||
131 | */
|
||
132 | private SelectableDataSource sourceRecordset;
|
||
133 | |||
134 | /**
|
||
135 | * Recordset of this layer
|
||
136 | */
|
||
137 | private SelectableDataSource targetRecordset;
|
||
138 | |||
139 | /**
|
||
140 | * Strategy to do querys against target Layer
|
||
141 | */
|
||
142 | private Strategy strategy;
|
||
143 | |||
144 | /**
|
||
145 | * Maps for each numerical field of target layer its sumarization functions
|
||
146 | */
|
||
147 | private Map fields_sumarizeFunc; |
||
148 | |||
149 | /**
|
||
150 | * Visitor that finds features of target layer that intersects with a given
|
||
151 | * feature of source layer
|
||
152 | */
|
||
153 | private IntersectsFinderFeatureVisitor visitor;
|
||
154 | |||
155 | /**
|
||
156 | * Processes results of dissolve operations (save them in a file, or cache
|
||
157 | * them in memory, etc)
|
||
158 | */
|
||
159 | private FeatureProcessor featureProcessor;
|
||
160 | |||
161 | private LayerDefinition resultLayerDefinition;
|
||
162 | 10626 | caballero | |
163 | 5918 | azabala | private boolean onlySecondLyrSelection; |
164 | |||
165 | public IntersectSpatialJoinVisitor(FLyrVect sourceLayer,
|
||
166 | FLyrVect targetLayer, |
||
167 | 10626 | caballero | Map fields_sumarizeFunct,
|
168 | FeatureProcessor processor) throws ReadDriverException {
|
||
169 | 5918 | azabala | this.sourceLayer = sourceLayer;
|
170 | this.sourceRecordset = sourceLayer.getRecordset();
|
||
171 | this.featureProcessor = processor;
|
||
172 | this.fields_sumarizeFunc = fields_sumarizeFunct;
|
||
173 | this.targetRecordset = targetLayer.getRecordset();
|
||
174 | this.visitor = new IntersectsFinderFeatureVisitor(fields_sumarizeFunc); |
||
175 | } |
||
176 | |||
177 | 10626 | caballero | public void visit(IGeometry g, int index) throws VisitorException, ProcessVisitorException { |
178 | 5918 | azabala | if(g == null) |
179 | return;
|
||
180 | IFeature solution = null;
|
||
181 | visitor.setQueryGeometry(g.toJTSGeometry()); |
||
182 | try {
|
||
183 | if(onlySecondLyrSelection)
|
||
184 | 10626 | caballero | visitor.setSelection(targetRecordset.getSelection()); |
185 | 5918 | azabala | strategy.process(visitor, g.getBounds2D()); |
186 | solution = createFeature(g, index, visitor.getNumIntersections()); |
||
187 | featureProcessor.processFeature(solution); |
||
188 | resetFunctions(); |
||
189 | visitor.clearIntersections(); |
||
190 | 10626 | caballero | } catch (ReadDriverException e) {
|
191 | throw new ProcessVisitorException(targetRecordset.getName(),e, |
||
192 | 5918 | azabala | "Error al buscar las intersecciones de una geometria durante un spatial join");
|
193 | 13874 | jaume | } |
194 | 5918 | azabala | } |
195 | 10626 | caballero | |
196 | 5918 | azabala | public String getProcessDescription() { |
197 | return "Spatial joining by intersects criteria"; |
||
198 | } |
||
199 | 10626 | caballero | |
200 | 5918 | azabala | public void resetFunctions(){ |
201 | Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
|
||
202 | while (fieldsIt.hasNext()) {
|
||
203 | String field = (String) fieldsIt.next(); |
||
204 | 10626 | caballero | SummarizationFunction[] functions =
|
205 | 5918 | azabala | (SummarizationFunction[]) fields_sumarizeFunc.get(field);
|
206 | for (int i = 0; i < functions.length; i++) { |
||
207 | functions[i].reset(); |
||
208 | }// for
|
||
209 | }// while
|
||
210 | } |
||
211 | 10626 | caballero | |
212 | |||
213 | 5918 | azabala | private IFeature createFeature(IGeometry g, int index, int numIntersections) |
214 | 10626 | caballero | throws ReadDriverException {
|
215 | 5918 | azabala | IFeature solution = null;
|
216 | int numSourceFields = this.sourceRecordset.getFieldCount(); |
||
217 | ArrayList values = new ArrayList(); |
||
218 | for (int i = 0; i < numSourceFields; i++) { |
||
219 | values.add(sourceRecordset.getFieldValue(index, i)); |
||
220 | } |
||
221 | //target layer
|
||
222 | Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
|
||
223 | while (fieldsIt.hasNext()) {
|
||
224 | String field = (String) fieldsIt.next(); |
||
225 | 10626 | caballero | SummarizationFunction[] functions =
|
226 | 5918 | azabala | (SummarizationFunction[]) fields_sumarizeFunc.get(field);
|
227 | for (int i = 0; i < functions.length; i++) { |
||
228 | values.add(functions[i].getSumarizeValue()); |
||
229 | }// for
|
||
230 | }// while
|
||
231 | values.add(ValueFactory.createValue(numIntersections)); |
||
232 | Value[] attrs = new Value[values.size()]; |
||
233 | values.toArray(attrs); |
||
234 | solution = FeatureFactory.createFeature(attrs, g); |
||
235 | return solution;
|
||
236 | } |
||
237 | |||
238 | 10626 | caballero | public void stop(FLayer layer) throws StopVisitorException { |
239 | 5918 | azabala | featureProcessor.finish(); |
240 | |||
241 | } |
||
242 | |||
243 | 10626 | caballero | public boolean start(FLayer layer) throws StartVisitorException { |
244 | this.featureProcessor.start();
|
||
245 | return true; |
||
246 | 5918 | azabala | } |
247 | 10626 | caballero | |
248 | |||
249 | 5918 | azabala | public ILayerDefinition getResultLayerDefinition(){
|
250 | if(this.resultLayerDefinition == null){ |
||
251 | ArrayList fields = new ArrayList(); |
||
252 | resultLayerDefinition = new SHPLayerDefinition();
|
||
253 | //result layer will be exactly similar to firstLayer with
|
||
254 | //new attributes
|
||
255 | try {
|
||
256 | resultLayerDefinition.setShapeType(sourceLayer.getShapeType()); |
||
257 | 10626 | caballero | } catch (ReadDriverException e) {
|
258 | 5918 | azabala | // TODO Auto-generated catch block
|
259 | e.printStackTrace(); |
||
260 | } |
||
261 | 10626 | caballero | |
262 | 5918 | azabala | //first layer attributes
|
263 | int numFields = 0; |
||
264 | try {
|
||
265 | numFields = sourceRecordset.getFieldCount(); |
||
266 | 10626 | caballero | } catch (ReadDriverException e) {
|
267 | 5918 | azabala | // TODO Auto-generated catch block
|
268 | e.printStackTrace(); |
||
269 | } |
||
270 | 10626 | caballero | |
271 | 5918 | azabala | FieldDescription fieldDesc = null;
|
272 | for(int i = 0; i < numFields; i++){ |
||
273 | fieldDesc = new FieldDescription();
|
||
274 | try {
|
||
275 | fieldDesc.setFieldName(sourceRecordset.getFieldName(i)); |
||
276 | int fieldType = sourceRecordset.getFieldType(i);
|
||
277 | fieldDesc.setFieldType(fieldType); |
||
278 | fieldDesc.setFieldLength(DefinitionUtils. |
||
279 | getDataTypeLength(fieldType)); |
||
280 | fieldDesc.setFieldDecimalCount(DefinitionUtils.NUM_DECIMALS); |
||
281 | 10626 | caballero | } catch (ReadDriverException e) {
|
282 | 5918 | azabala | // TODO Auto-generated catch block
|
283 | e.printStackTrace(); |
||
284 | } |
||
285 | fields.add(fieldDesc); |
||
286 | }//for
|
||
287 | 10626 | caballero | |
288 | 5918 | azabala | //target layer attributes
|
289 | Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator();
|
||
290 | while(fieldsIt.hasNext()){
|
||
291 | String field = (String) fieldsIt.next(); |
||
292 | SummarizationFunction[] functions =
|
||
293 | (SummarizationFunction[]) fields_sumarizeFunc.get(field);
|
||
294 | for(int i = 0; i < functions.length; i++){ |
||
295 | fieldDesc = new FieldDescription();
|
||
296 | // to avoid truncation of field names (f.example shp)
|
||
297 | //we only catch three first letters
|
||
298 | String shortName = null; |
||
299 | if(field.length() > 3) |
||
300 | shortName = field.substring(0,3); |
||
301 | else
|
||
302 | shortName = field; |
||
303 | fieldDesc.setFieldName( |
||
304 | shortName + "_" + functions[i].toString());
|
||
305 | fieldDesc.setFieldType(XTypes.DOUBLE); |
||
306 | int fieldLenght = DefinitionUtils.getDataTypeLength(XTypes.DOUBLE);
|
||
307 | fieldDesc.setFieldLength(fieldLenght); |
||
308 | fieldDesc.setFieldDecimalCount(DefinitionUtils.NUM_DECIMALS); |
||
309 | fields.add(fieldDesc); |
||
310 | }//for
|
||
311 | }//while
|
||
312 | 10626 | caballero | |
313 | 5918 | azabala | //finally, we add to the result schema of M-N spatial join
|
314 | //the number of features intersected of layer b
|
||
315 | fieldDesc = new FieldDescription();
|
||
316 | fieldDesc.setFieldName("NUM_RELA");
|
||
317 | fieldDesc.setFieldType(XTypes.INTEGER); |
||
318 | fieldDesc.setFieldLength(DefinitionUtils. |
||
319 | getDataTypeLength(XTypes.INTEGER)); |
||
320 | fields.add(fieldDesc); |
||
321 | 10626 | caballero | |
322 | 5918 | azabala | FieldDescription[] fieldsDesc = null; |
323 | if(fields.size() == 0){ |
||
324 | fieldsDesc = new FieldDescription[0]; |
||
325 | }else{
|
||
326 | fieldsDesc = new FieldDescription[fields.size()];
|
||
327 | fields.toArray(fieldsDesc); |
||
328 | } |
||
329 | resultLayerDefinition.setFieldsDesc(fieldsDesc); |
||
330 | }//if result == null
|
||
331 | return resultLayerDefinition;
|
||
332 | } |
||
333 | |||
334 | public void setFeatureProcessor(FeatureProcessor processor) { |
||
335 | this.featureProcessor = processor;
|
||
336 | } |
||
337 | |||
338 | public void setCancelableStrategy(Strategy secondLyrStrategy) { |
||
339 | this.strategy = secondLyrStrategy;
|
||
340 | } |
||
341 | |||
342 | public void setOnlySecondLyrSelection(boolean onlySecondLayerSelection) { |
||
343 | this.onlySecondLyrSelection = onlySecondLayerSelection;
|
||
344 | } |
||
345 | |||
346 | } |