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 @ 1259

History | View | Annotate | Download (7.65 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.Iterator;
27

    
28
import org.apache.commons.lang3.mutable.MutableDouble;
29
import org.apache.commons.lang3.mutable.MutableObject;
30

    
31
import es.unex.sextante.core.Sextante;
32
import java.util.List;
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.FeatureAttributeDescriptor;
38
import org.gvsig.fmap.dal.feature.FeatureIndex;
39
import org.gvsig.fmap.dal.feature.FeatureIndexes;
40
import org.gvsig.fmap.dal.feature.FeatureReference;
41
import org.gvsig.fmap.dal.feature.FeatureSelection;
42
import org.gvsig.fmap.dal.feature.FeatureSet;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44
import org.gvsig.fmap.geom.Geometry;
45
import org.gvsig.fmap.geom.GeometryLocator;
46
import org.gvsig.fmap.geom.GeometryManager;
47
import org.gvsig.fmap.geom.SpatialIndex;
48
import org.gvsig.fmap.geom.exception.CreateGeometryException;
49
import org.gvsig.fmap.geom.primitive.Envelope;
50
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
51
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
52
import org.gvsig.geoprocess.lib.sextante.dataObjects.FlyrVectIVectorLayer;
53
import org.gvsig.tools.exception.BaseException;
54
import org.gvsig.tools.namestranslator.NamesTranslator;
55
import org.gvsig.tools.visitor.VisitCanceledException;
56
import org.gvsig.tools.visitor.Visitor;
57

    
58
/**
59
 *
60
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
61
 */
62
public class SpatiallyIndexedSpatialJoinOperation extends GeometryOperation {
63

    
64
    private FeatureStore storeOverlay = null;
65
    private FeatureSelection featureSelection = null;
66

    
67
    /**
68
     * Geometry.distance() is a costly operation. Thats the reason for we are
69
     * only using a nearest neighbor. TODO SpatialIndex works with Rectangle2D,
70
     * and this may be a simplification that drives to errors. Make additional
71
     * probes to use a number of default neighbors
72
     */
73
    static final int DEFAULT_NUM_NEIGBOURS = 1;
74

    
75
    /**
76
     * Number of neighbors that nearestFinder must found.
77
     */
78
    int numOfNeighbours = DEFAULT_NUM_NEIGBOURS;
79

    
80
    /**
81
     * Specialized instance in nearest neighbor search.
82
     */
83
    private SpatialIndex index = null;
84

    
85
    public SpatiallyIndexedSpatialJoinOperation(FlyrVectIVectorLayer targetLayer, SpatialIndex index, AbstractSextanteGeoProcess p) {
86
        super(p);
87
        this.index = index;
88
        storeOverlay = targetLayer.getFeatureStore();
89
    }
90

    
91
    /*
92
         * (non-Javadoc)
93
         * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.Feature)
94
     */
95
    @SuppressWarnings({"unchecked", "deprecation"})
96
    public EditableFeature invoke(final org.gvsig.fmap.geom.Geometry g, Feature featureInput) {
97
        final MutableObject<Feature> foundFeature = new MutableObject<Feature>(null);
98
        boolean addedFeature = false;
99
        if (g == null) {
100
            return lastEditFeature;
101
        }
102

    
103
        try {
104
            final MutableDouble nearestDistance = new MutableDouble(Double.POSITIVE_INFINITY);
105

    
106
            index.query(g, new Visitor() {
107

    
108
                @Override
109
                public void visit(Object obj) throws VisitCanceledException, BaseException {
110
                    FeatureReference ref = (FeatureReference) obj;
111
                    Feature feat = ref.getFeature();
112
                    Geometry g2 = feat.getDefaultGeometry();
113
                    double dist = g.distance(g2);
114
                    if (dist <= nearestDistance.getValue()) {
115
                        nearestDistance.setValue(dist);
116
                        foundFeature.setValue(feat.getCopy());
117
                    }
118
                }
119
            });
120

    
121
            Iterator<?> iterator = index.queryNearest(g);
122
            while (iterator.hasNext()) {
123
                FeatureReference ref = (FeatureReference) iterator.next();
124
                Feature feat = ref.getFeature();
125
                Geometry g2 = feat.getDefaultGeometry();
126
                double dist = g.distance(g2);
127
                if (dist <= nearestDistance.getValue()) {
128
                    nearestDistance.setValue(dist);
129
                    foundFeature.setValue(feat.getCopy());
130
                }
131
            }
132

    
133
            if (foundFeature != null) {
134
                buildFeature(featureInput, foundFeature.getValue(), new Double(nearestDistance.getValue()), g);
135
                addedFeature = true;
136
            }
137

    
138
        } catch (Exception e) {
139
            Sextante.addErrorToLog(e);
140
        }
141

    
142
        return lastEditFeature;
143
    }
144

    
145
    /**
146
     * Builds a feature and adds it to the output file
147
     *
148
     * @param feat1
149
     * @param feat2
150
     * @param value
151
     * @param g
152
     * @throws DataException
153
     */
154
    private void buildFeature(Feature feat1, Feature feat2, Object value, org.gvsig.fmap.geom.Geometry g) throws DataException {
155
        EditableFeature outFeat = persister.getOutputFeatureStore().createNewFeature();
156
        NamesTranslator nameTranslator;
157
        try {
158
            nameTranslator = ((SpatialJoinAlgorithm) this.process).namesTranslator;
159
        } catch (Exception ex) {
160
            nameTranslator = null;
161
        }
162
        if (nameTranslator != null) {
163
            for (FeatureAttributeDescriptor attr1 : feat1.getType().getAttributeDescriptors()) {
164
                String attrName = attr1.getName();
165
                String translation = nameTranslator.getTranslation(attrName);
166
                Object fValue = feat1.get(attrName);
167
                if (translation!=null && !translation.isEmpty()) {
168
                    outFeat.set(translation, fValue);
169
                }
170
            }
171
            for (FeatureAttributeDescriptor attr2 : feat2.getType().getAttributeDescriptors()) {
172
                String attrName = attr2.getName();
173
                List<String> translation = nameTranslator.getAllTranslations(attrName);
174
                Object fValue = feat2.get(attrName);
175
                if (translation!=null && !translation.isEmpty()) {
176
                    outFeat.set(translation.get(translation.size() - 1), fValue);
177
                }
178
            }
179
            outFeat.set(nameTranslator.getTranslation("DIST"), (Object) value);
180
        } else {
181
            outFeat.copyFrom(feat2);
182
            outFeat.copyFrom(feat1);
183
            outFeat.set("DIST", (Object) value);
184
        }
185

    
186
        try {
187
            persister.addFeature(outFeat, g);
188
        } catch (CreateGeometryException e) {
189
            Sextante.addErrorToLog(e);
190
        }
191
    }
192

    
193
    /*
194
         * (non-Javadoc)
195
         * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.EditableFeature)
196
     */
197
    public void invoke(org.gvsig.fmap.geom.Geometry g, EditableFeature featureInput) {
198

    
199
    }
200

    
201
}