Statistics
| Revision:

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
}