Revision 5412
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/NearestFeatureVisitor.java | ||
---|---|---|
1 |
/* |
|
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 |
* Revision 1.1 2006-05-24 21:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.2 2006/03/07 21:01:33 azabala |
|
52 |
* *** empty log message *** |
|
53 |
* |
|
54 |
* Revision 1.1 2006/03/06 19:48:39 azabala |
|
55 |
* *** empty log message *** |
|
56 |
* |
|
57 |
* Revision 1.1 2006/03/05 19:59:47 azabala |
|
58 |
* *** empty log message *** |
|
59 |
* |
|
60 |
* |
|
61 |
*/ |
|
62 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
63 |
|
|
64 |
|
|
65 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
|
66 |
import com.iver.cit.gvsig.fmap.layers.FLayer; |
|
67 |
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData; |
|
68 |
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
|
69 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
70 |
import com.vividsolutions.jts.geom.Geometry; |
|
71 |
/** |
|
72 |
* This Visitor looks for the nearest feature of a FLayer B |
|
73 |
* to a specified feature of a FLayer A. |
|
74 |
* @author azabala |
|
75 |
* |
|
76 |
*/ |
|
77 |
public class NearestFeatureVisitor implements FeatureVisitor { |
|
78 |
|
|
79 |
private Geometry queryGeometry; |
|
80 |
private int solutionIndex = -1; |
|
81 |
private double shortestDist = Double.MAX_VALUE; |
|
82 |
|
|
83 |
public NearestFeatureVisitor(Geometry geometry){ |
|
84 |
this.queryGeometry = geometry; |
|
85 |
} |
|
86 |
|
|
87 |
public NearestFeatureVisitor(){ |
|
88 |
} |
|
89 |
|
|
90 |
public void visit(IGeometry g, int index) throws VisitException { |
|
91 |
double dist = queryGeometry.distance(g.toJTSGeometry()); |
|
92 |
if(dist < shortestDist){ |
|
93 |
shortestDist = dist; |
|
94 |
solutionIndex = index; |
|
95 |
}//if |
|
96 |
} |
|
97 |
|
|
98 |
public int getNearestFeatureIndex(){ |
|
99 |
return solutionIndex; |
|
100 |
} |
|
101 |
|
|
102 |
public double getShortestDist(){ |
|
103 |
return shortestDist; |
|
104 |
} |
|
105 |
|
|
106 |
public boolean hasFoundShortest(){ |
|
107 |
return solutionIndex != -1; |
|
108 |
} |
|
109 |
|
|
110 |
public void stop(FLayer layer) { |
|
111 |
} |
|
112 |
|
|
113 |
public boolean start(FLayer layer) { |
|
114 |
if (layer instanceof VectorialData) { |
|
115 |
return true; |
|
116 |
} |
|
117 |
return false; |
|
118 |
} |
|
119 |
|
|
120 |
public String getProcessDescription() { |
|
121 |
return "Looking nearest geometry for a spatial join"; |
|
122 |
} |
|
123 |
|
|
124 |
|
|
125 |
public void setQueryGeometry(Geometry queryGeometry) { |
|
126 |
this.queryGeometry = queryGeometry; |
|
127 |
} |
|
128 |
|
|
129 |
} |
|
130 |
|
|
0 | 131 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/SpatialJoinVisitor.java | ||
---|---|---|
1 |
/* |
|
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 |
* Revision 1.1 2006-05-24 21:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.4 2006/03/15 18:34:31 azabala |
|
52 |
* *** empty log message *** |
|
53 |
* |
|
54 |
* Revision 1.3 2006/03/14 18:32:46 fjp |
|
55 |
* Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n. |
|
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.1 2006/03/05 19:59:47 azabala |
|
64 |
* *** empty log message *** |
|
65 |
* |
|
66 |
* |
|
67 |
*/ |
|
68 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
69 |
|
|
70 |
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition; |
|
71 |
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
|
72 |
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
|
73 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
|
74 |
import com.iver.cit.gvsig.geoprocess.core.fmap.GeoprocessException; |
|
75 |
|
|
76 |
/** |
|
77 |
* Spatial Join is a geoprocess that tries to relate two layers |
|
78 |
* from its geometry field. To do that it could establish two strategies: |
|
79 |
* <ul> |
|
80 |
*<li> |
|
81 |
* Relate a geometry with the nearest geometry of the second layer |
|
82 |
* (1-1 cardinality). |
|
83 |
* </li> |
|
84 |
* <li> |
|
85 |
* Relate a geometry with all the geometries of second layer that verifies |
|
86 |
* a spatial relationship: contained, intersects, etc (1-M cardinality). |
|
87 |
* </li> |
|
88 |
* </ul> |
|
89 |
* SpatialJoinVisitor is a base interface for Visitor that does the |
|
90 |
* process of relationship |
|
91 |
* @author azabala |
|
92 |
* |
|
93 |
*/ |
|
94 |
public interface SpatialJoinVisitor extends FeatureVisitor { |
|
95 |
/** |
|
96 |
* Responsability to create ILayerDefinition is of the visitor, |
|
97 |
* because differents visitor will create differents layer definitions |
|
98 |
* (1-1 join or 1-N join) |
|
99 |
* @return |
|
100 |
* @throws GeoprocessException |
|
101 |
*/ |
|
102 |
public ILayerDefinition getResultLayerDefinition() throws GeoprocessException; |
|
103 |
public void setFeatureProcessor(FeatureProcessor processor); |
|
104 |
public void setCancelableStrategy(Strategy secondLyrStrategy); |
|
105 |
public void setOnlySecondLyrSelection(boolean onlySecondLayerSelection); |
|
106 |
} |
|
107 |
|
|
0 | 108 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/IntersectSpatialJoinVisitor.java | ||
---|---|---|
1 |
/* |
|
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 |
* Revision 1.1 2006-05-24 21:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.4 2006/03/21 19:29:36 azabala |
|
52 |
* *** empty log message *** |
|
53 |
* |
|
54 |
* Revision 1.3 2006/03/14 18:32:46 fjp |
|
55 |
* Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n. |
|
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.1 2006/03/05 19:59:47 azabala |
|
64 |
* *** empty log message *** |
|
65 |
* |
|
66 |
* |
|
67 |
*/ |
|
68 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
69 |
|
|
70 |
import java.util.ArrayList; |
|
71 |
import java.util.Iterator; |
|
72 |
import java.util.Map; |
|
73 |
|
|
74 |
import com.hardcode.gdbms.engine.values.Value; |
|
75 |
import com.iver.cit.gvsig.fmap.DriverException; |
|
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.drivers.FieldDescription; |
|
79 |
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition; |
|
80 |
import com.iver.cit.gvsig.fmap.drivers.LayerDefinition; |
|
81 |
import com.iver.cit.gvsig.fmap.drivers.SHPLayerDefinition; |
|
82 |
import com.iver.cit.gvsig.fmap.edition.EditionException; |
|
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.operations.strategies.Strategy; |
|
87 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
88 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory; |
|
89 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
|
90 |
import com.iver.cit.gvsig.geoprocess.core.fmap.SummarizationFunction; |
|
91 |
import com.iver.cit.gvsig.geoprocess.core.fmap.XTypes; |
|
92 |
|
|
93 |
/** |
|
94 |
* This visitor implement Intersect Geometry Spatial Join. |
|
95 |
* |
|
96 |
* It is a particular case of 1-M relationship (a feature of layer A always be |
|
97 |
* related to M feature of layer B) |
|
98 |
* |
|
99 |
* @author azabala |
|
100 |
* |
|
101 |
*/ |
|
102 |
public class IntersectSpatialJoinVisitor implements SpatialJoinVisitor { |
|
103 |
|
|
104 |
/** |
|
105 |
* Needed to create layer definition |
|
106 |
*/ |
|
107 |
private FLyrVect sourceLayer; |
|
108 |
/** |
|
109 |
* Reads data of features for the source layer |
|
110 |
*/ |
|
111 |
private SelectableDataSource sourceRecordset; |
|
112 |
|
|
113 |
/** |
|
114 |
* Recordset of this layer |
|
115 |
*/ |
|
116 |
private SelectableDataSource targetRecordset; |
|
117 |
|
|
118 |
/** |
|
119 |
* Strategy to do querys against target Layer |
|
120 |
*/ |
|
121 |
private Strategy strategy; |
|
122 |
|
|
123 |
/** |
|
124 |
* Maps for each numerical field of target layer its sumarization functions |
|
125 |
*/ |
|
126 |
private Map fields_sumarizeFunc; |
|
127 |
|
|
128 |
/** |
|
129 |
* Visitor that finds features of target layer that intersects with a given |
|
130 |
* feature of source layer |
|
131 |
*/ |
|
132 |
private IntersectsFinderFeatureVisitor visitor; |
|
133 |
|
|
134 |
/** |
|
135 |
* Processes results of dissolve operations (save them in a file, or cache |
|
136 |
* them in memory, etc) |
|
137 |
*/ |
|
138 |
private FeatureProcessor featureProcessor; |
|
139 |
|
|
140 |
private LayerDefinition resultLayerDefinition; |
|
141 |
|
|
142 |
private boolean onlySecondLyrSelection; |
|
143 |
|
|
144 |
public IntersectSpatialJoinVisitor(FLyrVect sourceLayer, |
|
145 |
FLyrVect targetLayer, |
|
146 |
Map fields_sumarizeFunct, |
|
147 |
FeatureProcessor processor) throws DriverException { |
|
148 |
this.sourceLayer = sourceLayer; |
|
149 |
this.sourceRecordset = sourceLayer.getRecordset(); |
|
150 |
this.featureProcessor = processor; |
|
151 |
this.fields_sumarizeFunc = fields_sumarizeFunct; |
|
152 |
this.targetRecordset = targetLayer.getRecordset(); |
|
153 |
this.visitor = new IntersectsFinderFeatureVisitor(fields_sumarizeFunc); |
|
154 |
} |
|
155 |
|
|
156 |
public void visit(IGeometry g, int index) throws VisitException { |
|
157 |
IFeature solution = null; |
|
158 |
visitor.setQueryGeometry(g.toJTSGeometry()); |
|
159 |
try { |
|
160 |
if(onlySecondLyrSelection) |
|
161 |
visitor.setSelection(targetRecordset.getSelection()); |
|
162 |
strategy.process(visitor, g.getBounds2D()); |
|
163 |
solution = createFeature(g, index, visitor.getNumIntersections()); |
|
164 |
featureProcessor.processFeature(solution); |
|
165 |
resetFunctions(); |
|
166 |
} catch (DriverException e) { |
|
167 |
throw new VisitException( |
|
168 |
"Error al buscar las intersecciones de una geometria durante un spatial join"); |
|
169 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
170 |
throw new VisitException( |
|
171 |
"Error al buscar las intersecciones de una geometria durante un spatial join"); |
|
172 |
} |
|
173 |
} |
|
174 |
|
|
175 |
public String getProcessDescription() { |
|
176 |
return "Spatial joining by intersects criteria"; |
|
177 |
} |
|
178 |
|
|
179 |
public void resetFunctions(){ |
|
180 |
Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator(); |
|
181 |
while (fieldsIt.hasNext()) { |
|
182 |
String field = (String) fieldsIt.next(); |
|
183 |
SummarizationFunction[] functions = |
|
184 |
(SummarizationFunction[]) fields_sumarizeFunc.get(field); |
|
185 |
for (int i = 0; i < functions.length; i++) { |
|
186 |
functions[i].reset(); |
|
187 |
}// for |
|
188 |
}// while |
|
189 |
} |
|
190 |
|
|
191 |
|
|
192 |
private IFeature createFeature(IGeometry g, int index, int numIntersections) |
|
193 |
throws com.hardcode.gdbms.engine.data.driver.DriverException { |
|
194 |
IFeature solution = null; |
|
195 |
int numSourceFields = this.sourceRecordset.getFieldCount(); |
|
196 |
ArrayList values = new ArrayList(); |
|
197 |
for (int i = 0; i < numSourceFields; i++) { |
|
198 |
values.add(sourceRecordset.getFieldValue(index, i)); |
|
199 |
} |
|
200 |
//target layer |
|
201 |
Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator(); |
|
202 |
while (fieldsIt.hasNext()) { |
|
203 |
String field = (String) fieldsIt.next(); |
|
204 |
SummarizationFunction[] functions = |
|
205 |
(SummarizationFunction[]) fields_sumarizeFunc.get(field); |
|
206 |
for (int i = 0; i < functions.length; i++) { |
|
207 |
values.add(functions[i].getSumarizeValue()); |
|
208 |
}// for |
|
209 |
}// while |
|
210 |
//values.add(ValueFactory.createValue(numIntersections)); |
|
211 |
Value[] attrs = new Value[values.size()]; |
|
212 |
values.toArray(attrs); |
|
213 |
solution = FeatureFactory.createFeature(attrs, g); |
|
214 |
return solution; |
|
215 |
} |
|
216 |
|
|
217 |
public void stop(FLayer layer) { |
|
218 |
featureProcessor.finish(); |
|
219 |
|
|
220 |
} |
|
221 |
|
|
222 |
public boolean start(FLayer layer) { |
|
223 |
try { |
|
224 |
this.featureProcessor.start(); |
|
225 |
} catch (EditionException e) { |
|
226 |
return false; |
|
227 |
} |
|
228 |
return true; |
|
229 |
} |
|
230 |
|
|
231 |
|
|
232 |
public ILayerDefinition getResultLayerDefinition(){ |
|
233 |
if(this.resultLayerDefinition == null){ |
|
234 |
ArrayList fields = new ArrayList(); |
|
235 |
resultLayerDefinition = new SHPLayerDefinition(); |
|
236 |
//result layer will be exactly similar to firstLayer with |
|
237 |
//new attributes |
|
238 |
try { |
|
239 |
resultLayerDefinition.setShapeType(sourceLayer.getShapeType()); |
|
240 |
} catch (DriverException e) { |
|
241 |
// TODO Auto-generated catch block |
|
242 |
e.printStackTrace(); |
|
243 |
} |
|
244 |
|
|
245 |
//first layer attributes |
|
246 |
int numFields = 0; |
|
247 |
try { |
|
248 |
numFields = sourceRecordset.getFieldCount(); |
|
249 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
250 |
// TODO Auto-generated catch block |
|
251 |
e.printStackTrace(); |
|
252 |
} |
|
253 |
FieldDescription fieldDesc = null; |
|
254 |
for(int i = 0; i < numFields; i++){ |
|
255 |
fieldDesc = new FieldDescription(); |
|
256 |
try { |
|
257 |
fieldDesc.setFieldName(sourceRecordset.getFieldName(i)); |
|
258 |
fieldDesc.setFieldType(sourceRecordset.getFieldType(i)); |
|
259 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
260 |
// TODO Auto-generated catch block |
|
261 |
e.printStackTrace(); |
|
262 |
} |
|
263 |
fields.add(fieldDesc); |
|
264 |
} |
|
265 |
//target layer attributes |
|
266 |
|
|
267 |
Iterator fieldsIt = fields_sumarizeFunc.keySet().iterator(); |
|
268 |
while(fieldsIt.hasNext()){ |
|
269 |
String field = (String) fieldsIt.next(); |
|
270 |
SummarizationFunction[] functions = |
|
271 |
(SummarizationFunction[]) fields_sumarizeFunc.get(field); |
|
272 |
for(int i = 0; i < functions.length; i++){ |
|
273 |
fieldDesc = new FieldDescription(); |
|
274 |
fieldDesc.setFieldLength(10); |
|
275 |
fieldDesc.setFieldDecimalCount(4); |
|
276 |
//to avoid truncation of field names (f.example shp) |
|
277 |
//we only catch three first letters |
|
278 |
String shortName = null; |
|
279 |
if(field.length() > 3) |
|
280 |
shortName = field.substring(0,3); |
|
281 |
else |
|
282 |
shortName = field; |
|
283 |
fieldDesc.setFieldName( |
|
284 |
shortName + "_" + functions[i].toString()); |
|
285 |
fieldDesc.setFieldType(XTypes.DOUBLE); |
|
286 |
|
|
287 |
fields.add(fieldDesc); |
|
288 |
}//for |
|
289 |
}//while |
|
290 |
|
|
291 |
FieldDescription[] fieldsDesc = null; |
|
292 |
if(fields.size() == 0){ |
|
293 |
fieldsDesc = new FieldDescription[0]; |
|
294 |
}else{ |
|
295 |
fieldsDesc = new FieldDescription[fields.size()]; |
|
296 |
fields.toArray(fieldsDesc); |
|
297 |
} |
|
298 |
resultLayerDefinition.setFieldsDesc(fieldsDesc); |
|
299 |
}//if result == null |
|
300 |
return resultLayerDefinition; |
|
301 |
} |
|
302 |
|
|
303 |
public void setFeatureProcessor(FeatureProcessor processor) { |
|
304 |
this.featureProcessor = processor; |
|
305 |
} |
|
306 |
|
|
307 |
public void setCancelableStrategy(Strategy secondLyrStrategy) { |
|
308 |
this.strategy = secondLyrStrategy; |
|
309 |
} |
|
310 |
|
|
311 |
public void setOnlySecondLyrSelection(boolean onlySecondLayerSelection) { |
|
312 |
this.onlySecondLyrSelection = onlySecondLayerSelection; |
|
313 |
} |
|
314 |
|
|
315 |
} |
|
0 | 316 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/NearestHeuristicSpatialJoinVisitor.java | ||
---|---|---|
1 |
/* |
|
2 |
* Created on 25-abr-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:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.1 2006/05/01 19:09:09 azabala |
|
52 |
* Intento de optimizar el spatial join por vecino mas proximo (no funciona) |
|
53 |
* |
|
54 |
* |
|
55 |
*/ |
|
56 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
57 |
|
|
58 |
import java.awt.geom.Rectangle2D; |
|
59 |
import java.util.Stack; |
|
60 |
|
|
61 |
import com.iver.cit.gvsig.fmap.DriverException; |
|
62 |
import com.iver.cit.gvsig.fmap.core.IFeature; |
|
63 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
|
64 |
import com.iver.cit.gvsig.fmap.layers.FBitSet; |
|
65 |
import com.iver.cit.gvsig.fmap.layers.FLayer; |
|
66 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
|
67 |
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
|
68 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
69 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
|
70 |
import com.vividsolutions.jts.geom.Envelope; |
|
71 |
import com.vividsolutions.jts.geom.Geometry; |
|
72 |
import com.vividsolutions.jts.geom.GeometryFactory; |
|
73 |
import com.vividsolutions.jts.operation.distance.DistanceOp; |
|
74 |
/** |
|
75 |
* This visitor does nearest feature spatial join by applying an heuristic |
|
76 |
* strategy (in constract with NearestSpatialJoinVisitor, that does a |
|
77 |
* secuential scanning). |
|
78 |
* <br> |
|
79 |
* Which heuristic does this visitor apply? |
|
80 |
* It obtains second layer (target layer in spatial join) full extent, |
|
81 |
* and subdivide it in 4 envelopes. After that, it computes the distance |
|
82 |
* of the geometry we want to join with second layer, and computes |
|
83 |
* 4 distances with each one of the envelopes. Then, it recursively subdivide |
|
84 |
* the Envelope at the shortest distance. |
|
85 |
* <br> |
|
86 |
* This process is repeated recursively until we obtain a nearest envelope |
|
87 |
* of a parametrized dimension. After that, it makes a spatial query with |
|
88 |
* this envelope on the layer B. If this query doesnt return, repeat the |
|
89 |
* spatial query with the envelope that originated this envelope (we take |
|
90 |
* the parent node in the quad-tree structure). |
|
91 |
* <br> |
|
92 |
* A critical aspect is optimization of the number of levels of quad-tree. |
|
93 |
* |
|
94 |
* If we take very few levels, the spatial query will return a lot of |
|
95 |
* candidates to nearest, so we wont get advantage of this stuff. |
|
96 |
* |
|
97 |
* If we take a lot of levels, we wont get result in the spatial queries, |
|
98 |
* and we'll have to do a lot of querys. |
|
99 |
* |
|
100 |
* @author azabala |
|
101 |
* |
|
102 |
* FIXME EL ALGORITMO FALLA!!!!!!!! EL QUADTREE ES UNA ESTRUCTURA |
|
103 |
* BUENA PARA RECTANGULOS, PERO PARA PUNTOS CREO QUE NO FUNCIONA. |
|
104 |
* NO TIENE EN CUENTA LOS EXTREMOS DE LOS RECTANGULOS |
|
105 |
* |
|
106 |
*/ |
|
107 |
public class NearestHeuristicSpatialJoinVisitor extends NearestSpatialJoinVisitor { |
|
108 |
|
|
109 |
private QuadTreeUtil quadTree = new QuadTreeUtil(); |
|
110 |
/** |
|
111 |
* Full extent of the layer where we are looking for |
|
112 |
* features to join by spatial criteria |
|
113 |
*/ |
|
114 |
private Envelope targetLayerEnv = null; |
|
115 |
/** |
|
116 |
* |
|
117 |
* @param sourceLayer |
|
118 |
* @param targetLayer |
|
119 |
* @param processor |
|
120 |
* @throws DriverException |
|
121 |
*/ |
|
122 |
public NearestHeuristicSpatialJoinVisitor(FLyrVect sourceLayer, |
|
123 |
FLyrVect targetLayer, |
|
124 |
FeatureProcessor processor) throws DriverException { |
|
125 |
super(sourceLayer, targetLayer, processor); |
|
126 |
|
|
127 |
Rectangle2D rect = targetLayer.getFullExtent(); |
|
128 |
targetLayerEnv = new Envelope(rect.getMinX(), |
|
129 |
rect.getMaxX(), |
|
130 |
rect.getMinY(), |
|
131 |
rect.getMaxY()); |
|
132 |
|
|
133 |
} |
|
134 |
// TODO If we need a class to look for nearest feature to a given |
|
135 |
//feature, move to a public class |
|
136 |
class LookForNearest implements FeatureVisitor{ |
|
137 |
/** |
|
138 |
* Index of the nearest processed feature to the given geometry |
|
139 |
*/ |
|
140 |
int nearestFeatureIndex = -1; |
|
141 |
/** |
|
142 |
* min distance of the features processed in the search of |
|
143 |
* nearest feature |
|
144 |
*/ |
|
145 |
double minDistance = Double.MAX_VALUE; |
|
146 |
/** |
|
147 |
* Geometry whose nearest feature we want to locate |
|
148 |
*/ |
|
149 |
Geometry firstG; |
|
150 |
/** |
|
151 |
* It this selectin is != null, in our search we will only |
|
152 |
* consideer features selected. |
|
153 |
*/ |
|
154 |
FBitSet selection; |
|
155 |
|
|
156 |
public boolean hasFoundShortest(){ |
|
157 |
return nearestFeatureIndex != -1; |
|
158 |
} |
|
159 |
|
|
160 |
public int getNearestFeatureIndex(){ |
|
161 |
return nearestFeatureIndex; |
|
162 |
} |
|
163 |
|
|
164 |
public void setSelection(FBitSet bitSet){ |
|
165 |
this.selection = bitSet; |
|
166 |
} |
|
167 |
|
|
168 |
public void setGeometry(Geometry firstG){ |
|
169 |
this.firstG = firstG; |
|
170 |
} |
|
171 |
|
|
172 |
public void visit(IGeometry g, int index) throws VisitException { |
|
173 |
if(selection != null){ |
|
174 |
if(! selection.get(index)){ |
|
175 |
return; |
|
176 |
} |
|
177 |
} |
|
178 |
double dist = firstG.distance(g.toJTSGeometry()); |
|
179 |
if(dist < minDistance){ |
|
180 |
minDistance = dist; |
|
181 |
nearestFeatureIndex = index; |
|
182 |
}//if |
|
183 |
} |
|
184 |
public String getProcessDescription() { |
|
185 |
return ""; |
|
186 |
} |
|
187 |
public void stop(FLayer layer) { |
|
188 |
} |
|
189 |
public boolean start(FLayer layer) { |
|
190 |
return true; |
|
191 |
} |
|
192 |
}; |
|
193 |
/** |
|
194 |
* Processes a Feature of source layer, looking for its nearest feature of |
|
195 |
* target layer and taking attributes from it |
|
196 |
*/ |
|
197 |
public void visit(IGeometry g, int sourceIndex) throws VisitException { |
|
198 |
final Geometry geometry = g.toJTSGeometry(); |
|
199 |
Stack stackOfEnvelopes = quadTree.getNearestEnvelopeOfIdealDimension(geometry, |
|
200 |
targetLayerEnv); |
|
201 |
LookForNearest visitor = new LookForNearest(); |
|
202 |
visitor.setGeometry(geometry); |
|
203 |
while((stackOfEnvelopes.size() > 0) ) { |
|
204 |
Envelope envelope = (Envelope) stackOfEnvelopes.pop(); |
|
205 |
Rectangle2D.Double rect = new Rectangle2D.Double(envelope.getMinX(), |
|
206 |
envelope.getMinY(), |
|
207 |
envelope.getWidth(), |
|
208 |
envelope.getHeight()); |
|
209 |
try { |
|
210 |
if(onlySecondLayerSelection){ |
|
211 |
visitor.setSelection(targetRecordset.getSelection()); |
|
212 |
} |
|
213 |
strategy.process(visitor, rect); |
|
214 |
if(visitor.hasFoundShortest()){ |
|
215 |
int targetIndex = visitor.getNearestFeatureIndex(); |
|
216 |
IFeature joinedFeature = createFeature(g, |
|
217 |
sourceIndex, |
|
218 |
targetIndex); |
|
219 |
this.featureProcessor.processFeature(joinedFeature); |
|
220 |
return; |
|
221 |
} |
|
222 |
} catch (DriverException e) { |
|
223 |
throw new VisitException("Error accediendo a los datos buscando el feature mas proximo", e); |
|
224 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
225 |
throw new VisitException("Error accediendo a los datos buscando el feature mas proximo", e); |
|
226 |
} |
|
227 |
}//while |
|
228 |
|
|
229 |
} |
|
230 |
|
|
231 |
/** |
|
232 |
* FIXME Refinar muy mucho, pero de momento me vale para hacer la busqueda |
|
233 |
* de la geometria mas proxima a una dada mediante subdivisi?n del espacio. |
|
234 |
* |
|
235 |
* @author azabala |
|
236 |
* |
|
237 |
*/ |
|
238 |
class QuadTreeUtil{ |
|
239 |
double DEFAULT_IDEAL_DIMENSION = 500d; |
|
240 |
|
|
241 |
double idealDimension = DEFAULT_IDEAL_DIMENSION; |
|
242 |
|
|
243 |
public void setIdealDimension(double idealDimension){ |
|
244 |
this.idealDimension = idealDimension; |
|
245 |
} |
|
246 |
|
|
247 |
public double distance(Geometry geo, Envelope rect){ |
|
248 |
GeometryFactory geoFact = new GeometryFactory(); |
|
249 |
Geometry poly = geoFact.toGeometry(rect); |
|
250 |
return DistanceOp.distance(geo, poly); |
|
251 |
} |
|
252 |
|
|
253 |
public double getMaxDimension(Envelope env){ |
|
254 |
double w = env.getWidth(); |
|
255 |
double h = env.getHeight(); |
|
256 |
return (w > h ? w : h); |
|
257 |
} |
|
258 |
|
|
259 |
|
|
260 |
public Stack getNearestEnvelopeOfIdealDimension(Geometry nearest, |
|
261 |
Envelope originalEnvelope){ |
|
262 |
//stack with all the hierarchical envelopes of the solution quad |
|
263 |
Stack solution = new Stack(); |
|
264 |
Envelope firstsolution = originalEnvelope; |
|
265 |
//the last try will be the full extent |
|
266 |
solution.push(firstsolution); |
|
267 |
double maxDimension = getMaxDimension(originalEnvelope); |
|
268 |
while(maxDimension > idealDimension){ |
|
269 |
Envelope[] quads = getNextQtreeLevel(firstsolution); |
|
270 |
double d0 = distance(nearest, quads[0]); |
|
271 |
double d1 = distance(nearest, quads[1]); |
|
272 |
double d2 = distance(nearest, quads[2]); |
|
273 |
double d3 = distance(nearest, quads[3]); |
|
274 |
if(d0 <= d1 && d0 <= d2 && d0 <= d3 ) |
|
275 |
firstsolution = quads[0]; |
|
276 |
else if(d1 <= d0 && d1 <= d2 && d1 <= d3) |
|
277 |
firstsolution = quads[1]; |
|
278 |
else if(d2 <= d0 && d2 <= d1 && d2 <= d3) |
|
279 |
firstsolution = quads[2]; |
|
280 |
else |
|
281 |
firstsolution = quads[3]; |
|
282 |
solution.push(firstsolution); |
|
283 |
maxDimension = getMaxDimension(firstsolution); |
|
284 |
} |
|
285 |
return solution; |
|
286 |
|
|
287 |
} |
|
288 |
|
|
289 |
public Envelope[] getNextQtreeLevel(Envelope rect){ |
|
290 |
Envelope[] solution = new Envelope[4]; |
|
291 |
int SW = 0; |
|
292 |
int SE = 1; |
|
293 |
int NW = 2; |
|
294 |
int NE = 3; |
|
295 |
double xMin = rect.getMinX(); |
|
296 |
double xMax = rect.getMaxX(); |
|
297 |
double yMin = rect.getMinY(); |
|
298 |
double yMax = rect.getMaxY(); |
|
299 |
double xCenter = (xMin + xMax) / 2d; |
|
300 |
double yCenter = (yMin + yMax) / 2d; |
|
301 |
Envelope r1 = new Envelope(xMin, xCenter, yMin, yCenter); |
|
302 |
Envelope r2 = new Envelope(xCenter, xMax, yMin, yCenter); |
|
303 |
Envelope r3 = new Envelope(xMin, xCenter, yCenter, yMax); |
|
304 |
Envelope r4 = new Envelope(xCenter, xMax, yCenter, yMax); |
|
305 |
solution[SW] = r1; |
|
306 |
solution[SE] = r2; |
|
307 |
solution[NW] = r3; |
|
308 |
solution[NE] = r4; |
|
309 |
return solution; |
|
310 |
} |
|
311 |
} |
|
312 |
|
|
313 |
} |
|
314 |
|
|
0 | 315 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/NearestSpatialJoinVisitor.java | ||
---|---|---|
1 |
/* |
|
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 |
* Revision 1.1 2006-05-24 21:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.6 2006/05/01 19:08:41 azabala |
|
52 |
* documentacion, y algunos metodos pasados de private a "friendly" -sin modificador- |
|
53 |
* |
|
54 |
* Revision 1.5 2006/03/21 19:29:36 azabala |
|
55 |
* *** empty log message *** |
|
56 |
* |
|
57 |
* Revision 1.4 2006/03/15 18:34:31 azabala |
|
58 |
* *** empty log message *** |
|
59 |
* |
|
60 |
* Revision 1.3 2006/03/14 18:32:46 fjp |
|
61 |
* Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n. |
|
62 |
* |
|
63 |
* Revision 1.2 2006/03/07 21:01:33 azabala |
|
64 |
* *** empty log message *** |
|
65 |
* |
|
66 |
* Revision 1.1 2006/03/06 19:48:39 azabala |
|
67 |
* *** empty log message *** |
|
68 |
* |
|
69 |
* Revision 1.1 2006/03/05 19:59:47 azabala |
|
70 |
* *** empty log message *** |
|
71 |
* |
|
72 |
* |
|
73 |
*/ |
|
74 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
75 |
|
|
76 |
import com.hardcode.gdbms.engine.values.Value; |
|
77 |
import com.iver.cit.gvsig.fmap.DriverException; |
|
78 |
import com.iver.cit.gvsig.fmap.core.IFeature; |
|
79 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
|
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.FLayer; |
|
83 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
|
84 |
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource; |
|
85 |
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
|
86 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
87 |
import com.iver.cit.gvsig.geoprocess.core.fmap.DefinitionUtils; |
|
88 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory; |
|
89 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
|
90 |
import com.iver.cit.gvsig.geoprocess.core.fmap.GeoprocessException; |
|
91 |
|
|
92 |
/** |
|
93 |
* This visitor implement Nearest Geometry Spatial Join. |
|
94 |
* |
|
95 |
* It is a particular case of 1-1 relationship |
|
96 |
* (a feature of layer A always be related to a feature of layer B) |
|
97 |
* |
|
98 |
* If two features of layer B are at the same distance of a feature of layer A, |
|
99 |
* we will took the first one analized. |
|
100 |
* |
|
101 |
* In this visitor we apply a secuential scaning strategy: given a geometry |
|
102 |
* of layer A, we check distances with all geometries of layer B return |
|
103 |
* the geometry at the min distance. |
|
104 |
* |
|
105 |
* |
|
106 |
* @author azabala |
|
107 |
* |
|
108 |
*/ |
|
109 |
public class NearestSpatialJoinVisitor implements SpatialJoinVisitor { |
|
110 |
/** |
|
111 |
* Needed to create layer definition |
|
112 |
*/ |
|
113 |
FLyrVect sourceLayer; |
|
114 |
/** |
|
115 |
* Reads data of features for the source layer |
|
116 |
*/ |
|
117 |
SelectableDataSource sourceRecordset; |
|
118 |
|
|
119 |
/** |
|
120 |
* Reads data of features for the target layer |
|
121 |
*/ |
|
122 |
FLyrVect targetLayer; |
|
123 |
|
|
124 |
/** |
|
125 |
* Recordset of this layer |
|
126 |
*/ |
|
127 |
SelectableDataSource targetRecordset; |
|
128 |
|
|
129 |
/** |
|
130 |
* Strategy to do querys against target Layer |
|
131 |
*/ |
|
132 |
Strategy strategy; |
|
133 |
|
|
134 |
/** |
|
135 |
* Processes results of dissolve operations (save them in a file, or cache |
|
136 |
* them in memory, etc) |
|
137 |
*/ |
|
138 |
FeatureProcessor featureProcessor; |
|
139 |
|
|
140 |
/** |
|
141 |
* It looks for nearest feature to a given feature |
|
142 |
*/ |
|
143 |
private NearestFeatureVisitor lookForNearestVisitor; |
|
144 |
|
|
145 |
/** |
|
146 |
* Schema of the result layer |
|
147 |
*/ |
|
148 |
ILayerDefinition layerDefinition; |
|
149 |
/** |
|
150 |
* flag to process only selections of second layer |
|
151 |
*/ |
|
152 |
boolean onlySecondLayerSelection; |
|
153 |
|
|
154 |
/** |
|
155 |
* Constructor. It receives layer with which we want to do a spatial join |
|
156 |
* |
|
157 |
* @param targetRecordset |
|
158 |
* @throws DriverException |
|
159 |
*/ |
|
160 |
public NearestSpatialJoinVisitor(FLyrVect sourceLayer, |
|
161 |
FLyrVect targetLayer, |
|
162 |
FeatureProcessor processor) throws DriverException { |
|
163 |
this.sourceLayer = sourceLayer; |
|
164 |
this.sourceRecordset = sourceLayer.getRecordset(); |
|
165 |
this.targetLayer = targetLayer; |
|
166 |
this.targetRecordset = targetLayer.getRecordset(); |
|
167 |
this.featureProcessor = processor; |
|
168 |
this.lookForNearestVisitor = new NearestFeatureVisitor(); |
|
169 |
} |
|
170 |
|
|
171 |
/** |
|
172 |
* Processes a Feature of source layer, looking for its nearest feature of |
|
173 |
* target layer and taking attributes from it |
|
174 |
*/ |
|
175 |
public void visit(IGeometry g, int sourceIndex) throws VisitException { |
|
176 |
lookForNearestVisitor.setQueryGeometry(g.toJTSGeometry()); |
|
177 |
try { |
|
178 |
if(onlySecondLayerSelection) |
|
179 |
strategy.process(lookForNearestVisitor, targetRecordset.getSelection()); |
|
180 |
else |
|
181 |
strategy.process(lookForNearestVisitor); |
|
182 |
int targetIndex = lookForNearestVisitor.getNearestFeatureIndex(); |
|
183 |
IFeature joinedFeature = createFeature(g, sourceIndex, targetIndex); |
|
184 |
this.featureProcessor.processFeature(joinedFeature); |
|
185 |
} catch (DriverException e) { |
|
186 |
throw new VisitException( |
|
187 |
"Problemas accediendo a los datos durante un nearest spatial join"); |
|
188 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
189 |
throw new VisitException( |
|
190 |
"Problemas accediendo a los datos durante un nearest spatial join"); |
|
191 |
} |
|
192 |
} |
|
193 |
|
|
194 |
public void stop(FLayer layer) { |
|
195 |
this.featureProcessor.finish(); |
|
196 |
|
|
197 |
} |
|
198 |
|
|
199 |
public boolean start(FLayer layer) { |
|
200 |
try { |
|
201 |
this.featureProcessor.start(); |
|
202 |
} catch (EditionException e) { |
|
203 |
return false; |
|
204 |
} |
|
205 |
return true; |
|
206 |
} |
|
207 |
|
|
208 |
public String getProcessDescription() { |
|
209 |
return "Spatial joining by nearest criteria"; |
|
210 |
} |
|
211 |
|
|
212 |
IFeature createFeature(IGeometry g, int sourceLayerIndex, int targetLayerIndex) throws DriverException, com.hardcode.gdbms.engine.data.driver.DriverException { |
|
213 |
IFeature solution = null; |
|
214 |
int numFieldsA = sourceRecordset.getFieldCount(); |
|
215 |
int numFieldsB = targetRecordset.getFieldCount(); |
|
216 |
Value[] featureAttr = new Value[numFieldsA + numFieldsB]; |
|
217 |
for (int indexField = 0; indexField < numFieldsA; indexField++) { |
|
218 |
featureAttr[indexField] = sourceRecordset |
|
219 |
.getFieldValue(sourceLayerIndex,indexField); |
|
220 |
} |
|
221 |
for (int indexFieldB = 0; indexFieldB < numFieldsB; indexFieldB++) { |
|
222 |
featureAttr[numFieldsA + indexFieldB] = |
|
223 |
targetRecordset.getFieldValue(targetLayerIndex, indexFieldB); |
|
224 |
} |
|
225 |
solution = FeatureFactory.createFeature(featureAttr, g); |
|
226 |
return solution; |
|
227 |
} |
|
228 |
|
|
229 |
public ILayerDefinition getResultLayerDefinition() throws GeoprocessException{ |
|
230 |
if(layerDefinition == null){ |
|
231 |
try { |
|
232 |
layerDefinition = DefinitionUtils. |
|
233 |
mergeLayerDefinitions(sourceLayer, targetLayer); |
|
234 |
} catch (Exception e) { |
|
235 |
throw new GeoprocessException("Problemas al crear el esquema de la capa solucion de un spatial join"); |
|
236 |
} |
|
237 |
} |
|
238 |
return layerDefinition; |
|
239 |
} |
|
240 |
|
|
241 |
public void setFeatureProcessor(FeatureProcessor processor) { |
|
242 |
this.featureProcessor = processor; |
|
243 |
} |
|
244 |
|
|
245 |
public void setCancelableStrategy(Strategy secondLyrStrategy) { |
|
246 |
this.strategy = secondLyrStrategy; |
|
247 |
|
|
248 |
} |
|
249 |
|
|
250 |
public void setOnlySecondLyrSelection(boolean onlySecondLayerSelection) { |
|
251 |
this.onlySecondLayerSelection = onlySecondLayerSelection; |
|
252 |
} |
|
253 |
|
|
254 |
} |
|
0 | 255 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/SpatiallyIndexedSpatialJoinVisitor.java | ||
---|---|---|
1 |
/* |
|
2 |
* Created on 02-may-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:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.1 2006/05/02 18:58:47 azabala |
|
52 |
* first version in cvs |
|
53 |
* |
|
54 |
* |
|
55 |
*/ |
|
56 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
57 |
|
|
58 |
import java.awt.geom.Rectangle2D; |
|
59 |
import java.util.List; |
|
60 |
|
|
61 |
import com.iver.cit.gvsig.fmap.DriverException; |
|
62 |
import com.iver.cit.gvsig.fmap.core.IFeature; |
|
63 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
|
64 |
import com.iver.cit.gvsig.fmap.drivers.DriverIOException; |
|
65 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
|
66 |
import com.iver.cit.gvsig.fmap.layers.ReadableVectorial; |
|
67 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
68 |
import com.iver.cit.gvsig.fmap.spatialindex.INearestNeighbourFinder; |
|
69 |
import com.iver.cit.gvsig.fmap.spatialindex.ISpatialIndex; |
|
70 |
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor; |
|
71 |
import com.vividsolutions.jts.geom.Geometry; |
|
72 |
/** |
|
73 |
* This visitor does spatial join with nearest neighbour |
|
74 |
* criteria by using an spatial index with nearest neighbour |
|
75 |
* searching capabilities.<br> |
|
76 |
* By now, RTreeSptLib is the only spatial index that is also |
|
77 |
* a INearestNeigbourFinder implementation. |
|
78 |
* <br> |
|
79 |
* @author azabala |
|
80 |
* |
|
81 |
*/ |
|
82 |
public class SpatiallyIndexedSpatialJoinVisitor extends |
|
83 |
NearestSpatialJoinVisitor { |
|
84 |
/** |
|
85 |
* Geometry.distance() is a costly operation. Thats the reason |
|
86 |
* for we are only using a nearest neighbour. |
|
87 |
* TODO SpatialIndex works with Rectangle2D, and this may be a simplification |
|
88 |
* that drives to errors. Make aditional probes to use a number of default |
|
89 |
* neighbours |
|
90 |
*/ |
|
91 |
static final int DEFAULT_NUM_NEIGBOURS = 1; |
|
92 |
/** |
|
93 |
* Number of neighbours that nearestFinder must |
|
94 |
* found. |
|
95 |
*/ |
|
96 |
int numOfNeighbours = DEFAULT_NUM_NEIGBOURS; |
|
97 |
/** |
|
98 |
* Spetialized instance in nearest neighbour searchs. |
|
99 |
*/ |
|
100 |
private INearestNeighbourFinder nearestFinder; |
|
101 |
/** |
|
102 |
* Constructor |
|
103 |
* @param sourceLayer |
|
104 |
* @param targetLayer |
|
105 |
* @param processor |
|
106 |
* @throws DriverException |
|
107 |
*/ |
|
108 |
public SpatiallyIndexedSpatialJoinVisitor(FLyrVect sourceLayer, |
|
109 |
FLyrVect targetLayer, |
|
110 |
FeatureProcessor processor) throws DriverException { |
|
111 |
super(sourceLayer, targetLayer, processor); |
|
112 |
initialize(); |
|
113 |
} |
|
114 |
|
|
115 |
void initialize(){ |
|
116 |
ISpatialIndex spatialIndex = |
|
117 |
targetLayer.getISpatialIndex(); |
|
118 |
if(spatialIndex instanceof INearestNeighbourFinder) |
|
119 |
nearestFinder = (INearestNeighbourFinder)spatialIndex; |
|
120 |
else |
|
121 |
throw new IllegalArgumentException("La segunda capa de spatial join ha de tener un ?ndice espacial de tipo RTreeSptLib para usar este visitor"); |
|
122 |
} |
|
123 |
|
|
124 |
|
|
125 |
|
|
126 |
/** |
|
127 |
* Processes a Feature of source layer, looking for its nearest feature of |
|
128 |
* target layer and taking attributes from it |
|
129 |
*/ |
|
130 |
public void visit(IGeometry g, int sourceIndex) throws VisitException { |
|
131 |
try { |
|
132 |
//no se si el rtree har? la busqueda bien si el rectangulo |
|
133 |
//de busqueda no est? insertado. Hacer las pruebas (si no, |
|
134 |
//a?adimos ahora y borramos luego) |
|
135 |
Geometry gJts = g.toJTSGeometry(); |
|
136 |
Rectangle2D rect = g.getBounds2D(); |
|
137 |
List nearestLst = nearestFinder. |
|
138 |
findNNearest(numOfNeighbours, rect); |
|
139 |
int targetIndex = -1;//index of nearest neighbour |
|
140 |
double nearestDistance = Double.MAX_VALUE; |
|
141 |
ReadableVectorial rv = targetLayer.getSource(); |
|
142 |
for(int i = 0; i < nearestLst.size(); i++){ |
|
143 |
int index2 = ((Integer)nearestLst.get(i)).intValue(); |
|
144 |
IGeometry g2 = rv.getShape(index2); |
|
145 |
Geometry g2Jts = g2.toJTSGeometry(); |
|
146 |
double dist = gJts.distance(g2Jts); |
|
147 |
if(dist <= nearestDistance){ |
|
148 |
//by adding <=, we follow the convention that |
|
149 |
//if two features are at the same distance, take |
|
150 |
//the last as nearest neighbour |
|
151 |
nearestDistance = dist; |
|
152 |
targetIndex = index2; |
|
153 |
}//if |
|
154 |
}//for |
|
155 |
if(targetIndex == -1) |
|
156 |
throw new VisitException("Problemas durante el spatial join, no se encontr? un vecino mas proximo"); |
|
157 |
IFeature joinedFeature; |
|
158 |
|
|
159 |
joinedFeature = createFeature(g, sourceIndex, targetIndex); |
|
160 |
this.featureProcessor.processFeature(joinedFeature); |
|
161 |
} catch (DriverException e) { |
|
162 |
throw new VisitException("Error de driver al escribir un feature resultante de un spatial join", e); |
|
163 |
} catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { |
|
164 |
throw new VisitException("Error de driver al escribir un feature resultante de un spatial join", e); |
|
165 |
} catch (DriverIOException e) { |
|
166 |
throw new VisitException("Error accediendo a datos de la capa destino en spatial join", e); |
|
167 |
} |
|
168 |
|
|
169 |
} |
|
170 |
|
|
171 |
} |
|
172 |
|
|
0 | 173 |
trunk/extensions/extGeoProcessing/src/com/iver/cit/gvsig/geoprocess/spatialjoin/fmap/IntersectsFinderFeatureVisitor.java | ||
---|---|---|
1 |
/* |
|
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 |
* Revision 1.1 2006-05-24 21:09:47 azabala |
|
49 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing |
|
50 |
* |
|
51 |
* Revision 1.2 2006/03/07 21:01:33 azabala |
|
52 |
* *** empty log message *** |
|
53 |
* |
|
54 |
* Revision 1.1 2006/03/06 19:48:39 azabala |
|
55 |
* *** empty log message *** |
|
56 |
* |
|
57 |
* Revision 1.1 2006/03/05 19:59:47 azabala |
|
58 |
* *** empty log message *** |
|
59 |
* |
|
60 |
* |
|
61 |
*/ |
|
62 |
package com.iver.cit.gvsig.geoprocess.spatialjoin.fmap; |
|
63 |
|
|
64 |
import java.util.ArrayList; |
|
65 |
import java.util.Iterator; |
|
66 |
import java.util.List; |
|
67 |
import java.util.Map; |
|
68 |
|
|
69 |
import com.hardcode.gdbms.engine.data.driver.DriverException; |
|
70 |
import com.hardcode.gdbms.engine.values.NumericValue; |
|
71 |
import com.hardcode.gdbms.engine.values.Value; |
|
72 |
import com.iver.cit.gvsig.fmap.core.IGeometry; |
|
73 |
import com.iver.cit.gvsig.fmap.layers.FBitSet; |
|
74 |
import com.iver.cit.gvsig.fmap.layers.FLayer; |
|
75 |
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource; |
|
76 |
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData; |
|
77 |
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData; |
|
78 |
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor; |
|
79 |
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException; |
|
80 |
import com.iver.cit.gvsig.geoprocess.core.fmap.SummarizationFunction; |
|
81 |
import com.vividsolutions.jts.geom.Geometry; |
|
82 |
/** |
|
83 |
* Given a feature of JOIN source layer, |
|
84 |
* it looks for intersecting geometries of JOIN target layer and applies |
|
85 |
* a sumarization function to its numeric fields. |
|
86 |
* |
|
87 |
* @author azabala |
|
88 |
* |
|
89 |
*/ |
|
90 |
public class IntersectsFinderFeatureVisitor implements FeatureVisitor { |
|
91 |
/** |
|
92 |
* Reads atributes of target layer |
|
93 |
*/ |
|
94 |
SelectableDataSource targetRecordset; |
|
95 |
/** |
|
96 |
* Geometry of layer A whose intersections of layer B |
|
97 |
* we are looking for |
|
98 |
*/ |
|
99 |
private Geometry queryGeometry; |
|
100 |
/** |
|
101 |
* It has indexes of intersections |
|
102 |
*/ |
|
103 |
private List intersectIndexes = null; |
|
104 |
/** |
|
105 |
* Relates a set of sumarization functions with a numeric field |
|
106 |
* name |
|
107 |
*/ |
|
108 |
Map fields_sumarizationFun = null; |
|
109 |
|
|
110 |
private FBitSet selection; |
|
111 |
|
|
112 |
public IntersectsFinderFeatureVisitor(Geometry geometry, Map functions) { |
|
113 |
this.queryGeometry = geometry; |
|
114 |
this.fields_sumarizationFun = functions; |
|
115 |
intersectIndexes = new ArrayList(); |
|
116 |
} |
|
117 |
|
|
118 |
public IntersectsFinderFeatureVisitor(Map functions) { |
|
119 |
this.fields_sumarizationFun = functions; |
|
120 |
intersectIndexes = new ArrayList(); |
|
121 |
} |
|
122 |
|
|
123 |
public void visit(IGeometry g, int index) throws VisitException { |
|
124 |
if(selection != null){ |
|
125 |
if(! selection.get(index)){ |
|
126 |
//dont process feature because is not selected |
Also available in: Unified diff