Statistics
| Revision:

root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / vectorTools / union / UnionAlgorithm.java @ 248

History | View | Annotate | Download (9.75 KB)

1

    
2

    
3
package es.unex.sextante.vectorTools.union;
4

    
5
import com.vividsolutions.jts.geom.Geometry;
6
import com.vividsolutions.jts.geom.GeometryCollection;
7
import com.vividsolutions.jts.geom.GeometryFactory;
8

    
9
import es.unex.sextante.additionalInfo.AdditionalInfoVectorLayer;
10
import es.unex.sextante.core.GeoAlgorithm;
11
import es.unex.sextante.core.Sextante;
12
import es.unex.sextante.dataObjects.IFeature;
13
import es.unex.sextante.dataObjects.IFeatureIterator;
14
import es.unex.sextante.dataObjects.IVectorLayer;
15
import es.unex.sextante.dataObjects.vectorFilters.BoundingBoxFilter;
16
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
17
import es.unex.sextante.exceptions.IteratorException;
18
import es.unex.sextante.exceptions.RepeatedParameterNameException;
19
import es.unex.sextante.outputs.OutputVectorLayer;
20

    
21

    
22
public class UnionAlgorithm extends GeoAlgorithm {
23

    
24
   public static final String LAYER1 = "LAYER1";
25
   public static final String LAYER2 = "LAYER2";
26
   public static final String RESULT = "RESULT";
27

    
28
   private Geometry           m_ClipGeometry;
29

    
30

    
31
   @Override
32
   public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
33

    
34
      final IVectorLayer layer1 = m_Parameters.getParameterValueAsVectorLayer(LAYER1);
35
      final IVectorLayer layer2 = m_Parameters.getParameterValueAsVectorLayer(LAYER2);
36

    
37
      if (!m_bIsAutoExtent) {
38
         layer1.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
39
         layer2.addFilter(new BoundingBoxFilter(m_AnalysisExtent));
40
      }
41

    
42
      final Class[] fieldTypes = new Class[layer1.getFieldCount() + layer2.getFieldCount()];
43
      final String[] sFieldNames = new String[fieldTypes.length];
44

    
45
      for (int i = 0; i < layer1.getFieldCount(); i++) {
46

    
47
              Class fieldType = layer1.getFieldType(i);
48
                      fieldTypes[i] = fieldType;
49
                      sFieldNames[i] = layer1.getFieldName(i);
50
      }
51
      for (int i = 0; i < layer2.getFieldCount(); i++) {
52
              Class fieldType = layer2.getFieldType(i);
53
              int targetIndex = i + layer1.getFieldCount() ;
54
              fieldTypes[targetIndex] = fieldType;
55
              sFieldNames[targetIndex] = checkAttrName(layer2.getFieldName(i), targetIndex, sFieldNames);
56
      }
57

    
58
      final IVectorLayer intersection = getTempVectorLayer(IVectorLayer.SHAPE_TYPE_POLYGON, fieldTypes, sFieldNames);
59

    
60
      final IVectorLayer output = getNewVectorLayer(RESULT, Sextante.getText("Union"), IVectorLayer.SHAPE_TYPE_POLYGON,
61
               fieldTypes, sFieldNames);
62

    
63
      //first we do an intersection
64

    
65
      setProgressText(Sextante.getText("Intersection") + "(1/4)");
66
      IFeatureIterator iter = layer1.iterator();
67

    
68
      int i = 0;
69
      int iShapeCount = layer1.getShapesCount();
70
      while (iter.hasNext() && setProgress(i, iShapeCount)) {
71
         final IFeature feature = iter.next();
72
         final Object[] values = feature.getRecord().getValues();
73
         final Geometry g = feature.getGeometry();
74
         final IFeatureIterator iter2 = layer2.iterator();
75
         while (iter2.hasNext()) {
76
            final IFeature feature2 = iter2.next();
77
            final Geometry g2 = feature2.getGeometry();
78
            if (g2.intersects(g)) {
79
               final Object[] values2 = feature2.getRecord().getValues();
80
               final Geometry inter = g.intersection(g2);
81
               final Object[] resultValues = new Object[values.length + values2.length];
82

    
83
                                // Inicializo values con unos valores por defecto porque
84
                                // DBFStoreProvider no admite valores null para estos
85
                                // tipos. Si se arregla/cambia DBFStoreProvider
86
                                // para que en caso de llegarle un valor null
87
                                // ponga el valor por defecto, esto se
88
                                // podr?a eliminar
89
               initializeDefaultValues(fieldTypes, resultValues);
90

    
91
               System.arraycopy(values, 0, resultValues, 0, values.length);
92
               System.arraycopy(values2, 0, resultValues, values.length, values2.length);
93
               intersection.addFeature(inter, resultValues);
94
            }
95
         }
96
         iter2.close();
97
         i++;
98
      }
99

    
100

    
101
      iter.close();
102

    
103

    
104
      if (m_Task.isCanceled()) {
105
         return false;
106
      }
107

    
108
      //copy the resulting features to the final layer
109
      setProgressText(Sextante.getText("Copying_entities") + "(2/4)");
110
      //intersection.close();
111
      try {
112
         intersection.postProcess();
113
      }
114
      catch (final Exception e) {
115
         throw new GeoAlgorithmExecutionException(e.getMessage());
116
      }
117
      intersection.open();
118
      iter = intersection.iterator();
119

    
120
      i = 0;
121
      iShapeCount = intersection.getShapesCount();
122
      while (iter.hasNext() && setProgress(i, iShapeCount)) {
123
         final IFeature feature = iter.next();
124
         output.addFeature(feature);
125
      }
126
      iter.close();
127

    
128
      //Now we calculate difference between layer 1 and intersection
129
      //and add the resulting entities to the final layer
130
      m_ClipGeometry = computeJtsClippingPoly(intersection);
131
      setProgressText(Sextante.getText("Copying_entities") + "(3/4)");
132
      iter = layer1.iterator();
133
      i = 0;
134
      iShapeCount = layer1.getShapesCount();
135
      while (iter.hasNext() && setProgress(i, iShapeCount)) {
136
         final IFeature feature = iter.next();
137
         final Geometry g = difference(feature.getGeometry());
138
         if (g != null && !g.isEmpty()) {
139
            final Object[] values = feature.getRecord().getValues();
140
            final Object[] resultValues = new Object[output.getFieldCount()];
141
            initializeDefaultValues(fieldTypes, resultValues);
142
            System.arraycopy(values, 0, resultValues, 0, values.length);
143
            output.addFeature(g, resultValues);
144
         }
145
         i++;
146
      }
147
      iter.close();
148

    
149
      if (m_Task.isCanceled()) {
150
         return false;
151
      }
152

    
153
      //And now the same difference but with layer2
154
      setProgressText(Sextante.getText("Copying_entities") + "(4/4)");
155
      iter = layer2.iterator();
156
      i = 0;
157
      iShapeCount = layer1.getShapesCount();
158
      while (iter.hasNext() && setProgress(i, iShapeCount)) {
159
         final IFeature feature = iter.next();
160
         final Geometry g = difference(feature.getGeometry());
161
         if (g != null && !g.isEmpty()) {
162

    
163
            final Object[] values = feature.getRecord().getValues();
164
            final Object[] resultValues = new Object[output.getFieldCount()];
165
            initializeDefaultValues(fieldTypes, resultValues);
166
            System.arraycopy(values, 0, resultValues, resultValues.length-values.length, values.length);
167
            output.addFeature(g, resultValues);
168
         }
169
         i++;
170
      }
171
      iter.close();
172

    
173
      intersection.close();
174

    
175
      return !m_Task.isCanceled();
176

    
177
   }
178

    
179

    
180
   public Geometry difference(final Geometry g) throws GeoAlgorithmExecutionException {
181

    
182
      if (g == null) {
183
         return null;
184
      }
185

    
186
      final Geometry env = g.getEnvelope();
187
      if (env == null || m_ClipGeometry == null) {
188
         return null;
189
      }
190
      if (!env.intersects(m_ClipGeometry.getEnvelope())) {
191
         return null;
192
      }
193
      if (g.intersects(m_ClipGeometry)) {
194
         try {
195
            final Geometry newGeom = g.difference(m_ClipGeometry);
196
            return newGeom;
197
         }
198
         catch (final com.vividsolutions.jts.geom.TopologyException e) {
199
            if (!g.isValid()) {
200
               throw new GeoAlgorithmExecutionException("Wrong input geometry");
201
            }
202
            if (!m_ClipGeometry.isValid()) {
203
               throw new GeoAlgorithmExecutionException("Wrong clipping geometry");
204
            }
205
         }
206
      }
207
      return null;
208
   }
209

    
210

    
211
   private Geometry computeJtsClippingPoly(final IVectorLayer layer) throws IteratorException {
212

    
213
      Geometry currentGeometry;
214
      Geometry geometry = null;
215
      final GeometryFactory geomFact = new GeometryFactory();
216

    
217
      final IFeatureIterator iter = layer.iterator();
218
      while (iter.hasNext()) {
219
         final IFeature feature = iter.next();
220
         currentGeometry = feature.getGeometry();
221
         if (geometry == null) {
222
            geometry = currentGeometry;
223
         }
224
         else {
225
            final Geometry[] geoms = new Geometry[2];
226
            geoms[0] = geometry;
227
            geoms[1] = currentGeometry;
228
            final GeometryCollection gc = geomFact.createGeometryCollection(geoms);
229
            geometry = gc.buffer(0d);
230
         }
231
      }
232
      iter.close();
233

    
234
      return geometry;
235

    
236
   }
237

    
238

    
239
   @Override
240
   public void defineCharacteristics() {
241

    
242
      setName(Sextante.getText("Union"));
243
      setGroup(Sextante.getText("Tools_for_polygon_layers"));
244
      setUserCanDefineAnalysisExtent(true);
245

    
246
      try {
247
         m_Parameters.addInputVectorLayer(LAYER1, Sextante.getText("Layer_1"), AdditionalInfoVectorLayer.SHAPE_TYPE_POLYGON, true);
248
         m_Parameters.addInputVectorLayer(LAYER2, Sextante.getText("Layer_2"), AdditionalInfoVectorLayer.SHAPE_TYPE_POLYGON, true);
249
         addOutputVectorLayer(RESULT, Sextante.getText("Capa_union"), OutputVectorLayer.SHAPE_TYPE_POLYGON);
250
      }
251
      catch (final RepeatedParameterNameException e) {
252
         Sextante.addErrorToLog(e);
253
      }
254

    
255
   }
256

    
257

    
258
   public Geometry clipGeometry(final Geometry g) throws GeoAlgorithmExecutionException {
259

    
260
      if (g == null) {
261
         return null;
262
      }
263

    
264
      final Geometry env = g.getEnvelope();
265
      if (env == null) {
266
         return null;
267
      }
268
      if (!env.intersects(m_ClipGeometry.getEnvelope())) {
269
         return null;
270
      }
271
      if (g.intersects(m_ClipGeometry)) {
272
         try {
273
            final Geometry newGeom = g.symDifference(m_ClipGeometry);
274
            return newGeom;
275
         }
276
         catch (final com.vividsolutions.jts.geom.TopologyException e) {
277
            if (!g.isValid()) {
278
               throw new GeoAlgorithmExecutionException("Wrong input geometry");
279
            }
280
            if (!m_ClipGeometry.isValid()) {
281
               throw new GeoAlgorithmExecutionException("Wrong clipping geometry");
282
            }
283
         }
284
      }
285
      return null;
286
   }
287

    
288
}