gvsig-geoprocess / org.gvsig.geoprocess / trunk / org.gvsig.geoprocess / org.gvsig.geoprocess.algorithm / org.gvsig.geoprocess.algorithm.spatialjoin / src / main / java / org / gvsig / geoprocess / algorithm / spatialjoin / SpatialJoinAlgorithm.java @ 1009
History | View | Annotate | Download (11.3 KB)
1 | 237 | cordinyana | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 175 | cordinyana | *
|
4 | 245 | cordinyana | * Copyright (C) 2007-2012 gvSIG Association.
|
5 | 175 | cordinyana | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | * as published by the Free Software Foundation; either version 2
|
||
9 | * of the License, or (at your option) any later version.
|
||
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | 237 | cordinyana | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 245 | cordinyana | *
|
21 | * For any additional information, do not hesitate to contact us
|
||
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 175 | cordinyana | */
|
24 | package org.gvsig.geoprocess.algorithm.spatialjoin; |
||
25 | |||
26 | import java.util.ArrayList; |
||
27 | import java.util.HashMap; |
||
28 | import java.util.Iterator; |
||
29 | |||
30 | 961 | fdiaz | import es.unex.sextante.core.Sextante; |
31 | import es.unex.sextante.dataObjects.IVectorLayer; |
||
32 | import es.unex.sextante.exceptions.GeoAlgorithmExecutionException; |
||
33 | import es.unex.sextante.exceptions.RepeatedParameterNameException; |
||
34 | import es.unex.sextante.exceptions.UnsupportedOutputChannelException; |
||
35 | import es.unex.sextante.gui.algorithm.GeoAlgorithmParametersPanel; |
||
36 | import es.unex.sextante.outputs.OutputVectorLayer; |
||
37 | |||
38 | 175 | cordinyana | import org.gvsig.fmap.dal.DALLocator; |
39 | import org.gvsig.fmap.dal.DataManager; |
||
40 | import org.gvsig.fmap.dal.DataTypes; |
||
41 | 960 | fdiaz | import org.gvsig.fmap.dal.feature.Feature; |
42 | 175 | cordinyana | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
43 | 960 | fdiaz | import org.gvsig.fmap.dal.feature.FeatureReference; |
44 | 175 | cordinyana | import org.gvsig.fmap.dal.feature.FeatureStore; |
45 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
46 | 960 | fdiaz | import org.gvsig.fmap.geom.Geometry; |
47 | import org.gvsig.fmap.geom.GeometryLocator; |
||
48 | import org.gvsig.fmap.geom.GeometryManager; |
||
49 | import org.gvsig.fmap.geom.SpatialIndex; |
||
50 | import org.gvsig.fmap.geom.SpatialIndexFactory; |
||
51 | 175 | cordinyana | import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation; |
52 | import org.gvsig.geoprocess.algorithm.dissolve.DissolveRule; |
||
53 | import org.gvsig.geoprocess.algorithm.dissolve.IDissolveRule; |
||
54 | import org.gvsig.geoprocess.algorithm.dissolve.Summary; |
||
55 | 218 | cordinyana | import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess; |
56 | 225 | cordinyana | import org.gvsig.geoprocess.lib.sextante.dataObjects.FlyrVectIVectorLayer; |
57 | 960 | fdiaz | import org.gvsig.tools.dynobject.DynObject; |
58 | import org.gvsig.tools.exception.BaseException; |
||
59 | import org.gvsig.tools.visitor.VisitCanceledException; |
||
60 | import org.gvsig.tools.visitor.Visitor; |
||
61 | 175 | cordinyana | |
62 | /**
|
||
63 | * Spatial join algorithm
|
||
64 | * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
|
||
65 | */
|
||
66 | 191 | cordinyana | public class SpatialJoinAlgorithm extends AbstractSextanteGeoProcess { |
67 | |||
68 | 336 | nbrodin | public static final String NEW_FIELD = "NUM_RELA"; |
69 | public static final String RESULT = "RESULT"; |
||
70 | public static final String LAYER1 = "LAYER1"; |
||
71 | public static final String LAYER2 = "LAYER2"; |
||
72 | public static final String SELECTGEOM_INPUT = "SELECTGEOM_INPUT"; |
||
73 | public static final String SELECTGEOM_OVERLAY = "SELECTGEOM_OVERLAY"; |
||
74 | public static final String NEAREST = "NEAREST"; |
||
75 | public static final String FUNCTION_LIST = "FUNCTION_LIST"; |
||
76 | public static final String Summary[] = {"Min", "Max", "Sum", "Avg"}; |
||
77 | private boolean funcList[] = new boolean[Summary.length]; |
||
78 | private HashMap<String, String> funcMap = new HashMap<String, String>(); |
||
79 | 960 | fdiaz | |
80 | 175 | cordinyana | public void defineCharacteristics(){ |
81 | 244 | cordinyana | setName(getTranslation("Spatialjoin"));
|
82 | setGroup(getTranslation("basic_vect_algorithms"));
|
||
83 | 175 | cordinyana | // setGeneratesUserDefinedRasterOutput(false);
|
84 | 960 | fdiaz | |
85 | 175 | cordinyana | try {
|
86 | 960 | fdiaz | m_Parameters.addInputVectorLayer(LAYER1, |
87 | 244 | cordinyana | getTranslation("Input_layer"),
|
88 | 960 | fdiaz | IVectorLayer.SHAPE_TYPE_WRONG, |
89 | 175 | cordinyana | true);
|
90 | 960 | fdiaz | m_Parameters.addInputVectorLayer(LAYER2, |
91 | 244 | cordinyana | getTranslation("Input_layer"),
|
92 | 960 | fdiaz | IVectorLayer.SHAPE_TYPE_WRONG, |
93 | 175 | cordinyana | true);
|
94 | 960 | fdiaz | m_Parameters.addBoolean(SELECTGEOM_INPUT, |
95 | 336 | nbrodin | getTranslation("Selected_geometries_input_layer"), false); |
96 | 960 | fdiaz | m_Parameters.addBoolean(SELECTGEOM_OVERLAY, |
97 | 336 | nbrodin | getTranslation("Selected_geometries_overlay_layer"), false); |
98 | m_Parameters.addBoolean(NEAREST, getTranslation("use_the_nearest"), false); |
||
99 | 244 | cordinyana | m_Parameters.addString(FUNCTION_LIST, |
100 | getTranslation("Function_list"));
|
||
101 | 175 | cordinyana | } catch (RepeatedParameterNameException e) {
|
102 | Sextante.addErrorToLog(e); |
||
103 | } |
||
104 | 254 | nbrodin | addOutputVectorLayer(RESULT,getTranslation("Spatialjoin"),
|
105 | 175 | cordinyana | OutputVectorLayer.SHAPE_TYPE_UNDEFINED); |
106 | } |
||
107 | 960 | fdiaz | |
108 | 175 | cordinyana | public boolean processAlgorithm() throws GeoAlgorithmExecutionException { |
109 | 271 | nbrodin | if(existsOutPutFile(SpatialJoinAlgorithm.RESULT, 0)) { |
110 | throw new GeoAlgorithmExecutionException(getTranslation("file_exists")); |
||
111 | } |
||
112 | 960 | fdiaz | IVectorLayer layer1 = m_Parameters.getParameterValueAsVectorLayer(LAYER1); //Capa de entrada
|
113 | IVectorLayer layer2 = m_Parameters.getParameterValueAsVectorLayer(LAYER2); //Capa de revestimiento
|
||
114 | 336 | nbrodin | boolean selectedGeomInput = m_Parameters.getParameter(SELECTGEOM_INPUT).getParameterValueAsBoolean();
|
115 | boolean selectedGeomOverlay = m_Parameters.getParameter(SELECTGEOM_OVERLAY).getParameterValueAsBoolean();
|
||
116 | 175 | cordinyana | boolean nearest = m_Parameters.getParameterValueAsBoolean(NEAREST);
|
117 | String functionList = m_Parameters.getParameterValueAsString(FUNCTION_LIST);
|
||
118 | loadSummary(functionList); |
||
119 | |||
120 | 960 | fdiaz | FlyrVectIVectorLayer inputLayer = null;
|
121 | FlyrVectIVectorLayer overlayLayer = null;
|
||
122 | if(layer2 instanceof FlyrVectIVectorLayer && layer1 instanceof FlyrVectIVectorLayer) { |
||
123 | overlayLayer = ((FlyrVectIVectorLayer)layer2); //Capa de revestimiento
|
||
124 | inputLayer = ((FlyrVectIVectorLayer)layer1); //Capa de entrada
|
||
125 | } else
|
||
126 | 175 | cordinyana | return false; |
127 | |||
128 | DataManager dataManager = DALLocator.getDataManager(); |
||
129 | |||
130 | //Builds the output and computes the operation
|
||
131 | try {
|
||
132 | 960 | fdiaz | FeatureType featureTypeInputLayer = inputLayer.getFeatureStore().getDefaultFeatureType(); //Capa de entrada
|
133 | FeatureType featureTypeOverlayLayer = overlayLayer.getFeatureStore().getDefaultFeatureType(); //Capa de revestimiento
|
||
134 | |||
135 | 175 | cordinyana | GeometryOperation operation = null;
|
136 | FeatureStore outFeatStore = null;
|
||
137 | 960 | fdiaz | |
138 | 244 | cordinyana | if (nearest) {
|
139 | outFeatStore = |
||
140 | 960 | fdiaz | buildOutPutStoreFromUnion(featureTypeInputLayer, featureTypeOverlayLayer, |
141 | inputLayer.getShapeType(), getTranslation("SpatialJoin"),
|
||
142 | 244 | cordinyana | RESULT, "DIST", Double.class); |
143 | 175 | cordinyana | |
144 | 244 | cordinyana | operation = |
145 | 960 | fdiaz | new SpatiallyIndexedSpatialJoinOperation(overlayLayer, createIndex(overlayLayer.getFeatureStore(), selectedGeomOverlay), this); |
146 | 244 | cordinyana | } else {
|
147 | outFeatStore = |
||
148 | 960 | fdiaz | buildSpatialJoinOutPutStore(featureTypeInputLayer, |
149 | inputLayer.getShapeType(), getTranslation("SpatialJoin"),
|
||
150 | 244 | cordinyana | RESULT); |
151 | IDissolveRule rule = new DissolveRule(0, funcMap); |
||
152 | Summary summary = |
||
153 | new Summary(rule, outFeatStore.getDefaultFeatureType());
|
||
154 | operation = |
||
155 | 960 | fdiaz | new IntersectsSpatialJoinOperation(overlayLayer,
|
156 | createIndex(overlayLayer.getFeatureStore(), selectedGeomOverlay), summary, this);
|
||
157 | 244 | cordinyana | } |
158 | 960 | fdiaz | |
159 | 223 | cordinyana | operation.setTaskStatus(getStatus()); |
160 | 960 | fdiaz | operation.computesGeometryOperation(inputLayer.getFeatureStore(), |
161 | outFeatStore, |
||
162 | attrNames, |
||
163 | selectedGeomInput, |
||
164 | selectedGeomOverlay, |
||
165 | true);
|
||
166 | } catch (Exception e) { |
||
167 | 175 | cordinyana | Sextante.addErrorToLog(e); |
168 | 960 | fdiaz | } |
169 | 175 | cordinyana | |
170 | return true; |
||
171 | } |
||
172 | |||
173 | 960 | fdiaz | private SpatialIndex createIndex(FeatureStore store, boolean selectionOnly) throws BaseException{ |
174 | GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
||
175 | |||
176 | 1009 | fdiaz | SpatialIndexFactory factory = geomManager.getSpatialIndexFactory(geomManager.SPATIALINDEX_DEFAULT_RTREE); |
177 | 960 | fdiaz | DynObject parameters = factory.createParameters(); |
178 | |||
179 | SpatialIndex index = (SpatialIndex) factory.create(parameters, geomManager); |
||
180 | final SpatialIndex wrappedIndex = store.wrapSpatialIndex(index);
|
||
181 | |||
182 | Visitor visitor = new Visitor() {
|
||
183 | |||
184 | @Override
|
||
185 | public void visit(Object obj) throws VisitCanceledException, BaseException { |
||
186 | Feature f=(Feature) obj; |
||
187 | Geometry g = f.getDefaultGeometry(); |
||
188 | FeatureReference ref = f.getReference(); |
||
189 | wrappedIndex.insert(g, ref); |
||
190 | } |
||
191 | }; |
||
192 | if(selectionOnly){
|
||
193 | store.getFeatureSelection().accept(visitor); |
||
194 | } else {
|
||
195 | store.accept(visitor); |
||
196 | } |
||
197 | |||
198 | return wrappedIndex;
|
||
199 | } |
||
200 | |||
201 | 175 | cordinyana | /**
|
202 | * Checks if the parameter is in Summary list
|
||
203 | * @param it
|
||
204 | * @return the position in the list
|
||
205 | */
|
||
206 | private int isInList(String it) { |
||
207 | for (int i = 0; i < Summary.length; i++) { |
||
208 | if(Summary[i].compareTo(it) == 0) |
||
209 | return i;
|
||
210 | } |
||
211 | return -1; |
||
212 | } |
||
213 | 960 | fdiaz | |
214 | 175 | cordinyana | /**
|
215 | * Loads the list of functions to use
|
||
216 | * @param functionList
|
||
217 | */
|
||
218 | private void loadSummary(String functionList) { |
||
219 | String[] attrList = functionList.split(";"); |
||
220 | for (int i = 0; i < attrList.length; i++) { |
||
221 | String[] func = attrList[i].split(","); |
||
222 | for (int j = 1; j < func.length; j++) { |
||
223 | int pos = isInList(func[j]);
|
||
224 | if(pos != -1) { |
||
225 | funcList[pos] = true;
|
||
226 | funcMap.put(Summary[pos], func[0]);
|
||
227 | } |
||
228 | } |
||
229 | } |
||
230 | } |
||
231 | 960 | fdiaz | |
232 | 175 | cordinyana | /**
|
233 | 960 | fdiaz | * Builds the output FeatureStore
|
234 | 175 | cordinyana | * @param featureType
|
235 | * @return FeatureStore
|
||
236 | */
|
||
237 | protected FeatureStore buildSpatialJoinOutPutStore(FeatureType featureType1,
|
||
238 | int shapeType,
|
||
239 | 960 | fdiaz | String sextanteLayerName,
|
240 | 175 | cordinyana | String sextanteLayerLabel) {
|
241 | ArrayList<Class> typesList = new ArrayList<Class>(); |
||
242 | ArrayList<String> attr = new ArrayList<String>(); |
||
243 | 960 | fdiaz | |
244 | 175 | cordinyana | Iterator it = featureType1.iterator();
|
245 | while( it.hasNext() ) {
|
||
246 | FeatureAttributeDescriptor attribute = (FeatureAttributeDescriptor)it.next(); |
||
247 | if (attribute.getDataType().getType() != DataTypes.GEOMETRY) {
|
||
248 | attr.add(attribute.getName()); |
||
249 | typesList.add(attribute.getObjectClass()); |
||
250 | } |
||
251 | } |
||
252 | 960 | fdiaz | |
253 | 175 | cordinyana | for (int i = 0; i < funcList.length; i++) { |
254 | if(funcList[i]) {
|
||
255 | String fieldName = funcMap.get(Summary[i]);
|
||
256 | if(fieldName.length() >= 6) |
||
257 | fieldName = fieldName.substring(0, 7); |
||
258 | attr.add(fieldName + "_" + Summary[i]);
|
||
259 | typesList.add(Double.class);
|
||
260 | } |
||
261 | } |
||
262 | 960 | fdiaz | |
263 | 175 | cordinyana | attr.add(NEW_FIELD); |
264 | typesList.add(Integer.class);
|
||
265 | 960 | fdiaz | |
266 | 175 | cordinyana | attrNames = new String[attr.size()]; |
267 | attr.toArray(attrNames); |
||
268 | Class[] types = new Class[typesList.size()]; |
||
269 | typesList.toArray(types); |
||
270 | 960 | fdiaz | |
271 | 175 | cordinyana | try {
|
272 | IVectorLayer output = getNewVectorLayer(sextanteLayerLabel, |
||
273 | sextanteLayerName, |
||
274 | shapeType, types, attrNames); |
||
275 | 225 | cordinyana | return ((FlyrVectIVectorLayer)output).getFeatureStore();
|
276 | 175 | cordinyana | } catch (UnsupportedOutputChannelException e) {
|
277 | Sextante.addErrorToLog(e); |
||
278 | } catch (GeoAlgorithmExecutionException e) {
|
||
279 | Sextante.addErrorToLog(e); |
||
280 | } |
||
281 | return null; |
||
282 | } |
||
283 | 244 | cordinyana | |
284 | @Override
|
||
285 | public Class<? extends GeoAlgorithmParametersPanel> getCustomParametersPanelClass() { |
||
286 | return SpatialJoinParametersPanel.class;
|
||
287 | } |
||
288 | 175 | cordinyana | } |