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 / SpatiallyIndexedSpatialJoinOperation.java @ 741

History | View | Annotate | Download (11.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2012 gvSIG Association.
5
 *
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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
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
 */
24
package org.gvsig.geoprocess.algorithm.spatialjoin;
25

    
26
import java.util.ArrayList;
27
import java.util.Iterator;
28
import java.util.List;
29

    
30
import com.vividsolutions.jts.geom.Geometry;
31

    
32
import es.unex.sextante.core.Sextante;
33

    
34
import org.gvsig.fmap.dal.exception.DataException;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.Feature;
37
import org.gvsig.fmap.dal.feature.FeatureIndex;
38
import org.gvsig.fmap.dal.feature.FeatureIndexes;
39
import org.gvsig.fmap.dal.feature.FeatureSelection;
40
import org.gvsig.fmap.dal.feature.FeatureSet;
41
import org.gvsig.fmap.dal.feature.FeatureStore;
42
import org.gvsig.fmap.dal.feature.exception.FeatureIndexException;
43
import org.gvsig.fmap.geom.exception.CreateGeometryException;
44
import org.gvsig.fmap.geom.primitive.Envelope;
45
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
46
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
47
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
48
import org.gvsig.geoprocess.lib.sextante.dataObjects.FlyrVectIVectorLayer;
49
import org.gvsig.tools.dispose.DisposableIterator;
50

    
51
/**
52
 *
53
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
54
 */
55
public class SpatiallyIndexedSpatialJoinOperation extends GeometryOperation {
56
        private FeatureStore               storeOverlay        = null;
57
        private FeatureSelection           featureSelection    = null;
58

    
59
        /**
60
         * Geometry.distance() is a costly operation. Thats the reason for we are
61
         * only using a nearest neighbor. TODO SpatialIndex works with Rectangle2D,
62
         * and this may be a simplification that drives to errors. Make additional
63
         * probes to use a number of default neighbors
64
         */
65
        static final int                  DEFAULT_NUM_NEIGBOURS = 1;
66

    
67
        /**
68
         * Number of neighbors that nearestFinder must found.
69
         */
70
        int                               numOfNeighbours       = DEFAULT_NUM_NEIGBOURS;
71

    
72
        /**
73
         * Specialized instance in nearest neighbor search.
74
         */
75
        private FeatureIndex              index                 = null;
76

    
77
        public SpatiallyIndexedSpatialJoinOperation(FlyrVectIVectorLayer targetLayer, String indexName, AbstractSextanteGeoProcess p) {
78
                super(p);
79
                FeatureIndexes indexes = targetLayer.getFeatureStore().getIndexes();
80
                index = indexes.getFeatureIndex(indexName);
81
                storeOverlay = targetLayer.getFeatureStore();
82
        }
83

    
84
        /*
85
         * (non-Javadoc)
86
         * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.Feature)
87
         */
88
        @SuppressWarnings({ "unchecked", "deprecation" })
89
        public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, Feature featureInput) {
90
            boolean addedFeature = false;
91
                if(g == null)
92
                        return lastEditFeature;
93

    
94
                if(featureSelection == null) {
95
                        try {
96
                                featureSelection = storeOverlay.getFeatureSelection();
97
                        } catch (DataException e1) {
98
                                //Sin selecci?n tiramos
99
                        }
100
                }
101

    
102
                try {
103
                        Geometry gJts = GeometryUtil.geomToJTS(g);
104
            Envelope rect = null;
105
                    rect = g.getEnvelope();
106
                        FeatureSet featSetMatch = index.getMatchFeatureSet(rect);
107
                        FeatureSet featSetNearest = index.getNearestFeatureSet(numOfNeighbours, rect);
108
                        double nearestDistance = Double.MAX_VALUE;
109
            Iterator it = featSetMatch.iterator();
110

    
111
            //Recorremos el featSetMatch para calcular la nearestDistance
112
            while(it.hasNext()) {
113
                Feature feat = (Feature)it.next();
114
                if( featureSelection != null &&
115
                    !featureSelection.isEmpty() &&
116
                    !featureSelection.isSelected(feat))
117
                    continue;
118
                List geomList = feat.getGeometries();
119

    
120
                if(geomList == null) {
121
                    org.gvsig.fmap.geom.Geometry g2 = feat.getDefaultGeometry();
122
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
123
                    double dist = gJts.distance(g2Jts);
124
                    if (dist <= nearestDistance) {
125
                        nearestDistance = dist;
126
                    }
127
                    continue;
128
                }
129

    
130
                Iterator<org.gvsig.fmap.geom.Geometry> itGeom = geomList.iterator();
131
                while(itGeom.hasNext()) {
132
                    org.gvsig.fmap.geom.Geometry g2 = itGeom.next();
133
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
134
                    double dist = gJts.distance(g2Jts);
135
                    if (dist <= nearestDistance) {
136
                        nearestDistance = dist;
137
                    }
138
                }
139
            }
140
//            it.dispose();
141

    
142
            //Recorremos el featSetNearest para calcular la nearestDistance
143
            it = featSetNearest.iterator();
144
            while(it.hasNext()) {
145
                Feature feat = (Feature)it.next();
146
                if( featureSelection != null &&
147
                    !featureSelection.isEmpty() &&
148
                    !featureSelection.isSelected(feat))
149
                    continue;
150
                List geomList = feat.getGeometries();
151

    
152
                if(geomList == null) {
153
                    org.gvsig.fmap.geom.Geometry g2 = feat.getDefaultGeometry();
154
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
155
                    double dist = gJts.distance(g2Jts);
156
                    if (dist <= nearestDistance) {
157
                        nearestDistance = dist;
158
                    }
159
                    continue;
160
                }
161

    
162
                Iterator<org.gvsig.fmap.geom.Geometry> itGeom = geomList.iterator();
163
                while(itGeom.hasNext()) {
164
                    org.gvsig.fmap.geom.Geometry g2 = itGeom.next();
165
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
166
                    double dist = gJts.distance(g2Jts);
167
                    if (dist <= nearestDistance) {
168
                        nearestDistance = dist;
169
                    }
170
                }
171
            }
172
//            it.dispose();
173

    
174
            //Recorremos el featSetMatch para obtener las geometr?as que est?n a una distancia igual o menor a la nearestDistance
175

    
176
            it = featSetMatch.iterator();
177
            while (it.hasNext()) {
178
                Feature feat = (Feature) it.next();
179
                if (featureSelection != null && !featureSelection.isEmpty()
180
                    && !featureSelection.isSelected(feat))
181
                    continue;
182
                List geomList = feat.getGeometries();
183

    
184
                if (geomList == null) {
185
                    org.gvsig.fmap.geom.Geometry g2 = feat.getDefaultGeometry();
186
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
187
                    double dist = gJts.distance(g2Jts);
188
                    if (dist <= nearestDistance) {
189
                        buildFeature(featureInput, feat, new Double(
190
                            nearestDistance), g);
191
                        addedFeature= true;
192
                    }
193
                     continue;
194
                }
195

    
196
                Iterator<org.gvsig.fmap.geom.Geometry> itGeom =
197
                    geomList.iterator();
198
                while (itGeom.hasNext()) {
199
                    org.gvsig.fmap.geom.Geometry g2 = itGeom.next();
200
                    Geometry g2Jts = GeometryUtil.geomToJTS(g2);
201
                    double dist = gJts.distance(g2Jts);
202
                    if (dist <= nearestDistance) {
203
                        buildFeature(featureInput, feat, new Double(
204
                            nearestDistance), g);
205
                        addedFeature= true;
206
                    }
207
                }
208
            }
209
//            it.dispose();
210

    
211

    
212
            //Recorremos el featSetNearest para obtener las geometr?as que est?n a una distancia igual o menor a la nearestDistance
213
            //si no se ha a?adido todav?a ninguna feature
214

    
215
            if (!addedFeature) {
216
                it = featSetNearest.iterator();
217
                while (it.hasNext()) {
218
                    Feature feat = (Feature) it.next();
219

    
220
                    if (featureSelection != null && !featureSelection.isEmpty()
221
                        && !featureSelection.isSelected(feat))
222
                        continue;
223
                    List geomList = feat.getGeometries();
224

    
225
                    if (geomList == null) {
226
                        org.gvsig.fmap.geom.Geometry g2 =
227
                            feat.getDefaultGeometry();
228
                        Geometry g2Jts = GeometryUtil.geomToJTS(g2);
229
                        double dist = gJts.distance(g2Jts);
230
                        if (dist <= nearestDistance) {
231
                            buildFeature(featureInput, feat, new Double(
232
                                nearestDistance), g);
233
                            addedFeature = true;
234
                        }
235
                        continue;
236
                    }
237

    
238
                    Iterator<org.gvsig.fmap.geom.Geometry> itGeom =
239
                        geomList.iterator();
240
                    while (itGeom.hasNext()) {
241
                        org.gvsig.fmap.geom.Geometry g2 = itGeom.next();
242
                        Geometry g2Jts = GeometryUtil.geomToJTS(g2);
243
                        double dist = gJts.distance(g2Jts);
244
                        if (dist <= nearestDistance && !addedFeature) {
245
                            buildFeature(featureInput, feat, new Double(
246
                                nearestDistance), g);
247
                            addedFeature = true;
248
                        }
249
                    }
250
                }
251
//                it.dispose();
252
            }
253

    
254
                } catch(FeatureIndexException e) {
255
                        Sextante.addErrorToLog(e);
256
                } catch (DataException e) {
257
                        Sextante.addErrorToLog(e);
258
                }
259

    
260
                return lastEditFeature;
261
        }
262

    
263
        /**
264
         * Builds a feature and adds it to the output file
265
         * @param feat1
266
         * @param feat2
267
         * @param value
268
         * @param g
269
         * @throws DataException
270
         */
271
        private void buildFeature(Feature feat1, Feature feat2, Object value, org.gvsig.fmap.geom.Geometry g) throws DataException {
272
                EditableFeature outFeat = persister.getOutputFeatureStore().createNewFeature();
273
                int sizeFeat1 = feat1.getType().size() - 1;
274

    
275
                for (int i = 0; i < sizeFeat1; i++)
276
                        outFeat.set(i, feat1.get(i));
277

    
278
                for (int i = sizeFeat1; i < sizeFeat1 + feat2.getType().size() - 1; i++)
279
                        outFeat.set(i, feat2.get(i - sizeFeat1));
280

    
281
                outFeat.set(outFeat.getType().size() - 2, value);
282
                try {
283
                        persister.addFeature(outFeat, g);
284
                } catch (CreateGeometryException e) {
285
                        Sextante.addErrorToLog(e);
286
                }
287
        }
288

    
289
        /*
290
         * (non-Javadoc)
291
         * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.EditableFeature)
292
         */
293
        public void invoke(org.gvsig.fmap.geom.Geometry g, EditableFeature featureInput) {
294

    
295
        }
296

    
297
}