Revision 614

View differences:

org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.15/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperationFast.java
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
/*
25

  
26
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
27
 *
28
 * Copyright (C) 2010 Generalitat Valenciana.
29
 *
30
 * This program is free software; you can redistribute it and/or
31
 * modify it under the terms of the GNU General Public License
32
 * as published by the Free Software Foundation; either version 2
33
 * of the License, or (at your option) any later version.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38
 * GNU General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU General Public License
41
 * along with this program; if not, write to the Free Software
42
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
43
 */
44

  
45
package org.gvsig.geoprocess.algorithm.fusespatially;
46

  
47
import java.util.ArrayList;
48
import java.util.List;
49

  
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.feature.EditableFeature;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.FeatureSelection;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
59
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
60
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
61
import org.gvsig.tools.dispose.DisposableIterator;
62
import org.slf4j.Logger;
63
import org.slf4j.LoggerFactory;
64

  
65
import com.vividsolutions.jts.geom.Geometry;
66
/**
67
 * Fuse spatially operation
68
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
69
 */
70
public class FuseSpatiallyOperationFast extends GeometryOperation {
71
	private static Logger 			         logger    		    = LoggerFactory.getLogger(FuseSpatiallyOperationFast.class.getName());
72
	private ArrayList<Element>               featureList        = null; 
73
	private String                           nameIdField        = null;
74
	private FeatureStore                     outFeatStoreTable  = null;
75
	
76
	class Element {
77
		public int                 id              = -1;
78
		public Feature             feat            = null;
79
		public List<Element>       overlapList     = new ArrayList<Element>();
80
		public boolean             insertedToJoin  = false;
81
		public Geometry            jtsGeom         = null;
82
	}
83
	
84
	public FuseSpatiallyOperationFast(AbstractSextanteGeoProcess process) {
85
		super(process);
86
		featureList = new ArrayList<Element>();
87
	}
88

  
89
	@Override
90
	public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g,
91
			Feature featureInput) {
92
		// TODO Auto-generated method stub
93
		return null;
94
	}
95

  
96
	@Override
97
	public void invoke(org.gvsig.fmap.geom.Geometry g,
98
			EditableFeature featureInput) {
99
		// TODO Auto-generated method stub
100
		
101
	}
102
	
103
	/**
104
	 * Computes a complete operation over the input FeatureStore. The result of this operation
105
	 * is stored in the output FeatureStore. This method will call once for each geometry.
106
	 * @param inFeatStore
107
	 *        Input FeatureStore
108
	 * @param outFeatStore
109
	 *        Output FeatureStore
110
	 * @param attrNames
111
	 *        List of attributes to build the output feature store
112
	 * @param selectedGeom
113
	 *        If it is true only the selected geometries will be processed
114
	 * @throws DataException
115
	 */
116
	@SuppressWarnings("deprecation")
117
	public void computesGeometryOperation(FeatureStore inFeatStore,
118
									FeatureStore outFeatStore,
119
									FeatureStore outFeatStoreTable,
120
									String[] attrNames,
121
									String[] attrNamesTable,
122
									boolean selectedGeomInput,
123
									boolean selectedGeomOutput,
124
									String idField) throws DataException {
125
		this.outFeatStoreTable = outFeatStoreTable;
126
		this.nameIdField = idField;
127
		this.inFeatureStore = inFeatStore;
128
		this.selectedGeomInput = selectedGeomInput;
129
		this.selectedGeomOverlay = selectedGeomOutput;
130
		FeatureSet featuresSet = null;
131
		featuresSet = inFeatStore.getFeatureSet();
132
		
133
		setFeatureStore(outFeatStore, attrNames);
134
		DisposableIterator it = null;
135

  
136
		if(selectedGeomInput) {
137
            FeatureSelection ds = inFeatStore.getFeatureSelection();
138
            it = ds.iterator();
139
            numberOfFeatures = (int) ds.getSelectedCount();
140
		} else {
141
			it = featuresSet.iterator();
142
			numberOfFeatures = (int)featuresSet.getSize();
143
		}
144
		
145
        if (status != null) 
146
            status.setRangeOfValues(0, numberOfFeatures);
147
        if(process != null) 
148
            process.setProgress(0, numberOfFeatures);
149
		
150
        //Crear lista de elementos
151
		int iCount = 0;
152
		while( it.hasNext() && !process.getTaskMonitor().isCanceled()) {
153
			Feature feat = (Feature)it.next();
154
			Element el = new Element();
155
			el.feat = feat;
156
			el.id = iCount;
157
			featureList.add(el);
158
            if (status != null && process != null) 
159
                status.setCurValue(iCount);
160
            if(process != null) 
161
                process.setProgress(iCount, numberOfFeatures);
162
			iCount ++;
163
		}
164
		it.dispose();
165
		
166
		//Crear listas de solapes para cada feature
167
		iCount = 0;
168
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
169
			Element elem1 = featureList.get(iCount);
170
			org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry();
171
			if (status != null)  
172
                status.setCurValue(iCount);
173
            if(process != null)
174
                process.setProgress(iCount, numberOfFeatures);
175
            
176
			for (int i = iCount + 1; i < featureList.size(); i++) {
177
				Element elem2 = featureList.get(i);
178
				org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry();
179
				if(areBBoxesOverlaping(geom1, geom2)) {
180
					if(elem1.jtsGeom == null)
181
						elem1.jtsGeom = GeometryUtil.geomToJTS(geom1);
182
					elem2.jtsGeom = GeometryUtil.geomToJTS(geom2);
183
					if(elem1.jtsGeom.intersects(elem2.jtsGeom))	{
184
						elem1.overlapList.add(elem2);
185
						elem2.overlapList.add(elem1);
186
					}
187
				}
188
			}
189
			iCount ++;
190
		}
191
		
192
		//Se calculan las listas de geometrias a unir
193
		//Para cada feature se obtiene su lista de elementos que solapan y para 
194
		//cada elemento que solapa se obtiene su lista. Finalmente todas se unen y 
195
		//y se hace un insert de una feature nueva
196
		List<Geometry> listResult = new ArrayList<Geometry>();
197
		iCount = 0;
198
		int iFeat = 0;
199
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
200
			Element elem1 = featureList.get(iCount);
201
			if (status != null) 
202
                status.setCurValue(iCount);
203
            if(process != null) 
204
                process.setProgress(iCount, numberOfFeatures);
205
      
206
			if(!elem1.insertedToJoin) {
207
				elem1.insertedToJoin = true;
208
				listResult.clear();
209
				try {
210
					insertInTable(outFeatStoreTable, elem1.feat, iFeat);
211
				} catch (DataException e) {
212
					logger.info("Imposible insertar en la tabla", e);
213
				}
214
				listResult.add(elem1.jtsGeom);
215
				
216
				buildListToJoin(listResult, elem1.overlapList, iFeat);
217
				
218
				Geometry newGeom = computesUnion(listResult, elem1);
219
				
220
				try {
221
					addFeatureToOutput(newGeom, elem1.feat, iFeat);
222
				} catch (CreateGeometryException e) {
223
					logger.info("Error a?adiendo geometr?a", e);
224
				} catch (DataException e) {
225
					logger.info("Error a?adiendo geometr?a", e);
226
				}
227
				iFeat ++;
228
			}
229
			iCount ++;
230
		}
231

  
232
		if(persister != null)
233
			persister.end();
234
		
235
	}
236
	
237
	private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) {
238
		if(g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0))
239
			return false;
240
		if(g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0))
241
			return false;
242
		if(g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1))
243
			return false;
244
		if(g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1))
245
			return false;
246
		return true;
247
	}
248
	
249
	/**
250
	 * Computes the union of the list of geometries
251
	 * @param listResult
252
	 * @param elem1
253
	 * @return
254
	 */
255
	private Geometry computesUnion(List<Geometry> listResult, Element elem1) {
256
		int splitValue = 500;
257
		Geometry newGeom = null;
258
		if(listResult.size() > splitValue) {
259
			List<List<Geometry>> list = splitList(listResult, splitValue);
260
			List<Geometry> result = new ArrayList<Geometry>();
261
			for (int i = 0; i < list.size(); i++) {
262
				Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType());
263
				result.add(aux);
264
			}
265
			for (int i = 0; i < result.size(); i++) {
266
				newGeom = GeometryUtil.geometryUnion(result, elem1.feat.getDefaultGeometry().getGeometryType().getType());
267
			}
268
		} else {
269
			newGeom = GeometryUtil.geometryUnion(listResult, elem1.feat.getDefaultGeometry().getGeometryType().getType());	
270
		}
271
		return newGeom;
272
	}
273
	
274
	/**
275
	 * Splits the array of geometries to compute its union because JTS cannot support
276
	 * a lot of geometries
277
	 * @param list
278
	 * @param n
279
	 * @return
280
	 */
281
	private List<List<Geometry>> splitList(List<Geometry> list, int n) {
282
		int elements = (int)(list.size() / n);
283
		List<List<Geometry>> l = new ArrayList<List<Geometry>>();
284
		for (int i = 0; i < elements; i++) {
285
			l.add(list.subList((i * n), (i * n) + n));
286
		}
287
		if(elements * n < list.size()) {
288
			l.add(list.subList((elements * n), list.size()));
289
		}
290
		return l;
291
	}
292
	
293
	/**
294
	 * Builds the union of all lists 
295
	 * @param listResult
296
	 * @param listToJoin
297
	 */
298
	private void buildListToJoin(List<Geometry> listResult, List<Element> listToJoin, int reference) {
299
		for (int i = 0; i < listToJoin.size(); i++) {
300
			Element elem = listToJoin.get(i);
301
			if(!elem.insertedToJoin) {
302
				elem.insertedToJoin = true;
303
				buildListToJoin(listResult, elem.overlapList, reference);
304
				try {
305
					insertInTable(outFeatStoreTable, elem.feat, reference);
306
				} catch (DataException e) {
307
					logger.info("Imposible insertar en la tabla", e);
308
				}
309
				listResult.add(elem.jtsGeom);
310
			}
311
		}
312
	}
313
	
314
	/**
315
	 * Adds a feature to the output
316
	 * @param newGeom
317
	 * @param feat
318
	 * @param newFeatID
319
	 * @throws DataException
320
	 * @throws CreateGeometryException
321
	 */
322
	private void addFeatureToOutput(Geometry newGeom, 
323
			Feature feat, 
324
			int newFeatID) throws DataException, CreateGeometryException {
325
		//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos
326
		if(outFeatStoreTable != null) { 
327
			lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID);
328
		} else {
329
			//Si no hay tabla se ponen todos los campos de la tabla de entrada
330
			String[] fieldNames = persister.getFieldNamesWithoutGeom();
331
			ArrayList<String> fields = new ArrayList<String>();
332
			ArrayList<Object> values = new ArrayList<Object>();
333
			fields.add(nameIdField);
334
			values.add(newFeatID);
335
			for (int j = 0; j < fieldNames.length; j++) {
336
				Object obj = feat.get(fieldNames[j]);
337
				if(obj != null && fieldNames[j].compareTo(nameIdField) != 0) {
338
					fields.add(fieldNames[j]);
339
					values.add(obj);
340
				}
341
			}
342
			lastEditFeature = persister.addFeature(newGeom, fields, values);
343
		}
344
	}
345
	
346
	/**
347
	 * Insert in the output table a new feature with the fields of the input feature. Moreover 
348
	 * exists a field that is an identifier which is a reference to the fusion layer.
349
	 * @param outFeatureStoreTable
350
	 * @param f
351
	 * @throws DataException
352
	 */
353
	private void insertInTable(FeatureStore outFeatureStoreTable, Feature f, int reference) throws DataException {
354
		if(outFeatureStoreTable == null)
355
			return;
356
		EditableFeature edFeat = outFeatureStoreTable.createNewFeature();
357
		edFeat.set(nameIdField, reference);
358
		FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors();
359
		for (int j = 0; j < attrList.length; j++) {
360
			if(attrList[j].getName().compareTo("GEOMETRY") != 0) {
361
				edFeat.set(attrList[j].getName(), f.get(attrList[j].getName()));
362
			}
363
		}
364
		outFeatureStoreTable.insert(edFeat);
365
	}
366
	
367
}
368

  
0 369

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.15/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperation_Old.java
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
/*
25

  
26
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
27
 *
28
 * Copyright (C) 2010 Generalitat Valenciana.
29
 *
30
 * This program is free software; you can redistribute it and/or
31
 * modify it under the terms of the GNU General Public License
32
 * as published by the Free Software Foundation; either version 2
33
 * of the License, or (at your option) any later version.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38
 * GNU General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU General Public License
41
 * along with this program; if not, write to the Free Software
42
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
43
 */
44

  
45
package org.gvsig.geoprocess.algorithm.fusespatially;
46

  
47
import java.util.ArrayList;
48
import java.util.Iterator;
49
import java.util.List;
50

  
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.Feature;
54
import org.gvsig.fmap.dal.feature.FeatureSet;
55
import org.gvsig.fmap.dal.feature.FeatureStore;
56
import org.gvsig.fmap.geom.GeometryLocator;
57
import org.gvsig.fmap.geom.GeometryManager;
58
import org.gvsig.fmap.geom.exception.CreateGeometryException;
59
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
60
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
61
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
62

  
63
import com.vividsolutions.jts.geom.Geometry;
64
/**
65
 * Fuse spatially operation
66
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
67
 */
68
public class FuseSpatiallyOperation_Old extends GeometryOperation {
69
	private FeatureStore                     inFeatStore      = null;
70
	protected GeometryManager                geomManager      = GeometryLocator.getGeometryManager();
71
	private FeatureSet                       featureSet       = null;
72
	private int                              id               = 0;
73
	private long                             nFeatures        = 0;
74
	private boolean[]                        featProcessed    = null;
75

  
76
	public FuseSpatiallyOperation_Old(FeatureStore inFeatStore, boolean selectedGeom, AbstractSextanteGeoProcess p) throws DataException {
77
		super(p);
78
		this.inFeatStore = inFeatStore;
79
		
80
		if(selectedGeom) {
81
			featureSet = (FeatureSet)inFeatStore.getSelection();
82
		} else
83
			featureSet = inFeatStore.getFeatureSet();
84
		nFeatures = featureSet.getSize();
85
		featProcessed = new boolean[(int)nFeatures];
86
	}
87

  
88
	/*
89
	 * (non-Javadoc)
90
	 * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.Feature)
91
	 */
92
	public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, Feature feature) {
93
		if(g == null)
94
			return lastEditFeature;
95
		
96
		try {
97
			Geometry inputJTSGeom = GeometryUtil.geomToJTS(g);
98
			Geometry union = null; 
99
			
100
			Iterator it = featureSet.fastIterator();
101
			int index = 0;
102
			while(it.hasNext()) {
103
				Feature f = (Feature)it.next();
104
				if(featProcessed[index])
105
					continue;
106
				org.gvsig.fmap.geom.Geometry geom = feature.getDefaultGeometry();
107
				Geometry jtsGeom = GeometryUtil.geomToJTS(geom); //Multigeometry support
108
				if(inputJTSGeom.intersects(jtsGeom)) {
109
					inputJTSGeom = inputJTSGeom.union(jtsGeom);
110
					featProcessed[index] = true;
111
				}
112
				index ++;
113
				continue;
114
			}
115

  
116
			lastEditFeature = persister.addFeature(inputJTSGeom, "FID", id);
117
		} catch (DataException e) {
118
			return null;
119
		} catch (CreateGeometryException e) {
120
			return null;
121
		}
122
		id++;
123
		return lastEditFeature;
124
	}
125
	
126
	/*
127
	 * (non-Javadoc)
128
	 * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.EditableFeature)
129
	 */
130
	public void invoke(org.gvsig.fmap.geom.Geometry g, EditableFeature feature) {
131
		if(g == null)
132
			return;
133
	}
134
	
135
	/*
136
	 * (non-Javadoc)
137
	 * @see org.gvsig.geoprocess.algorithm.base.core.IOperation#getResult()
138
	 */
139
	public Object getResult() {
140
		return lastEditFeature;
141
	}
142
	
143
}
144

  
0 145

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.15/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperation.java
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
/*
25

  
26
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
27
 *
28
 * Copyright (C) 2010 Generalitat Valenciana.
29
 *
30
 * This program is free software; you can redistribute it and/or
31
 * modify it under the terms of the GNU General Public License
32
 * as published by the Free Software Foundation; either version 2
33
 * of the License, or (at your option) any later version.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38
 * GNU General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU General Public License
41
 * along with this program; if not, write to the Free Software
42
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
43
 */
44

  
45
package org.gvsig.geoprocess.algorithm.fusespatially;
46

  
47
import java.util.ArrayList;
48
import java.util.List;
49
import java.util.Stack;
50

  
51
import org.gvsig.fmap.dal.exception.DataException;
52
import org.gvsig.fmap.dal.feature.EditableFeature;
53
import org.gvsig.fmap.dal.feature.Feature;
54
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
55
import org.gvsig.fmap.dal.feature.FeatureStore;
56
import org.gvsig.fmap.geom.GeometryLocator;
57
import org.gvsig.fmap.geom.GeometryManager;
58
import org.gvsig.fmap.geom.exception.CreateGeometryException;
59
import org.gvsig.geoprocess.algorithm.base.core.DALFeaturePersister;
60
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
61
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
62
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
63

  
64
import com.vividsolutions.jts.geom.Geometry;
65
/**
66
 * Fuse spatially operation
67
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
68
 * @deprecated Uses FuseSpatiallyOperationFast
69
 */
70
public class FuseSpatiallyOperation extends GeometryOperation {
71
	protected GeometryManager                geomManager           = GeometryLocator.getGeometryManager();
72
	private int                              id                    = 0;
73
	private List<Feature>                    featList              = null;
74
	private FeatureStore                     outFeatureStoreTable  = null;
75
	private String                           idField               = "FID";
76
	
77
	public FuseSpatiallyOperation(List<Feature> f, 
78
			FeatureStore outFeatStoreTable, 
79
			String[] fieldNames, 
80
			String idField, 
81
			AbstractSextanteGeoProcess p) throws DataException {
82
		super(p);
83
		this.featList = f;
84
		this.outFeatureStoreTable = outFeatStoreTable;
85
		this.idField = idField;
86
	}
87
	
88
	public FuseSpatiallyOperation(Stack<Feature> f, 
89
			FeatureStore outFeatStoreTable, 
90
			String[] fieldNames, 
91
			AbstractSextanteGeoProcess p) throws DataException {
92
		super(p);
93
		this.featList = f;
94
		this.outFeatureStoreTable = outFeatStoreTable;
95
	}
96
	
97
	/*
98
	 * (non-Javadoc)
99
	 * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.Feature)
100
	 */
101
	public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g, Feature feature) {
102
		try {
103
			Geometry jtsInputGeom = GeometryUtil.geomToJTS(g);
104
			insertInTable(feature);
105
			
106
			int cont = featList.size() - 1;
107
			while(cont >= 0 && !process.getTaskMonitor().isCanceled()) {
108
				Feature f = featList.get(cont);
109
				g = f.getDefaultGeometry();
110
				Geometry jtsGeom = GeometryUtil.geomToJTS(g); //Multigeometry support
111
				if(jtsGeom.intersects(jtsInputGeom)) {
112
					jtsInputGeom = jtsInputGeom.union(jtsGeom);
113
					featList.remove(cont);
114
					process.setProgress(procesSize - featList.size(), procesSize);
115
					cont = featList.size();
116
					insertInTable(f);
117
				}
118
				cont --;
119
			}
120

  
121
			//Cuando no genera dos capas mete los campos de la feature de entrada en la de salida perdiendose el resto
122
			if(outFeatureStoreTable == null) { 
123
				String[] fieldNames = persister.getFieldNamesWithoutGeom();
124
				ArrayList<String> fields = new ArrayList<String>();
125
				ArrayList<Object> values = new ArrayList<Object>();
126
				fields.add(idField);
127
				values.add(id);
128
				for (int j = 0; j < fieldNames.length; j++) {
129
					Object obj = feature.get(fieldNames[j]);
130
					if(obj != null && fieldNames[j].compareTo(idField) != 0) {
131
						fields.add(fieldNames[j]);
132
						values.add(obj);
133
					}
134
				}
135
				lastEditFeature = persister.addFeature(jtsInputGeom, fields, values);
136
			} else
137
				lastEditFeature = persister.addFeature(jtsInputGeom, idField, id);
138
		} catch (DataException e) {
139
			return null;
140
		} catch (CreateGeometryException e) {
141
			return null;
142
		}
143
		id++;
144
		return lastEditFeature;
145
	}
146
	
147
	private void insertInTable(Feature f) throws DataException {
148
		if(outFeatureStoreTable == null)
149
			return;
150
		EditableFeature edFeat = outFeatureStoreTable.createNewFeature();
151
		edFeat.set(idField, id);
152
		FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors();
153
		for (int j = 0; j < attrList.length; j++) {
154
			if(attrList[j].getName().compareTo("GEOMETRY") != 0) {
155
				edFeat.set(attrList[j].getName(), f.get(attrList[j].getName()));
156
			}
157
		}
158
		outFeatureStoreTable.insert(edFeat);
159
	}
160
	
161
	/**
162
	 * Removes duplicate fields
163
	 * @param names
164
	 * @return
165
	 */
166
	public static String[] checkFields(String[] names) {
167
		if(names.length <= 1)
168
			return names;
169
		int cont = 0;
170

  
171
		int i = 1;
172
		while(i < names.length) {
173
			if(names[0].compareTo(names[i]) == 0) {
174
				names[0] = "FID_" + cont;
175
				i = 0;
176
				cont ++;
177
			}
178
			i ++;
179
		}
180
		return names;
181
	}
182
	
183
	/*
184
	 * (non-Javadoc)
185
	 * @see org.gvsig.geoprocess.algorithm.base.core.GeometryOperation#invoke(org.gvsig.fmap.geom.Geometry, org.gvsig.fmap.dal.feature.EditableFeature)
186
	 */
187
	public void invoke(org.gvsig.fmap.geom.Geometry g, EditableFeature feature) {
188
		if(g == null)
189
			return;
190
	}
191
	
192
	/*
193
	 * (non-Javadoc)
194
	 * @see org.gvsig.geoprocess.algorithm.base.core.IOperation#getResult()
195
	 */
196
	public Object getResult() {
197
		return lastEditFeature;
198
	}
199
	
200
	public DALFeaturePersister getWriter() {
201
		return persister;
202
	}
203
	
204
}
205

  
0 206

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.15/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperationFast2.java
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
/*
25

  
26
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
27
 *
28
 * Copyright (C) 2010 Generalitat Valenciana.
29
 *
30
 * This program is free software; you can redistribute it and/or
31
 * modify it under the terms of the GNU General Public License
32
 * as published by the Free Software Foundation; either version 2
33
 * of the License, or (at your option) any later version.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38
 * GNU General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU General Public License
41
 * along with this program; if not, write to the Free Software
42
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
43
 */
44

  
45
package org.gvsig.geoprocess.algorithm.fusespatially;
46

  
47
import java.util.ArrayList;
48
import java.util.List;
49

  
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.feature.EditableFeature;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.FeatureSelection;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
59
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
60
import org.gvsig.geoprocess.algorithm.base.util.JTSFacade;
61
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
62
import org.gvsig.tools.dispose.DisposableIterator;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

  
66
import com.vividsolutions.jts.geom.Geometry;
67
/**
68
 * Fuse spatially operation
69
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
70
 */
71
public class FuseSpatiallyOperationFast2 extends GeometryOperation {
72
	private static Logger 			         logger    		    = LoggerFactory.getLogger(FuseSpatiallyOperationFast2.class.getName());
73
	private ArrayList<Element>               featureList        = null; 
74
	private String                           nameIdField        = null;
75
	private FeatureStore                     outFeatStoreTable  = null;
76
	private NodeTree                         baseTree           = null;
77
	
78
	class Element {
79
		public int                 id              = -1;
80
		public Feature             feat            = null;
81
		public List<Element>       overlapList     = new ArrayList<Element>();
82
		public boolean             insertedToJoin  = false;
83
		public Geometry            jtsGeom         = null;
84
	}
85
	
86
	class NodeTree {
87
		public Element       element     = null;
88
		public int           pos         = 0;
89
		public NodeTree       parent      = null;
90
		
91
		public NodeTree(Element node, NodeTree parent) {
92
			this.element = node;
93
			this.parent = parent;
94
		}
95
		
96
		public Element getNext() {
97
			if(pos < element.overlapList.size())
98
				return element.overlapList.get(pos++);
99
			return null;
100
		}
101
	}
102
	
103
	public FuseSpatiallyOperationFast2(AbstractSextanteGeoProcess process) {
104
		super(process);
105
		featureList = new ArrayList<Element>();
106
	}
107

  
108
	@Override
109
	public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g,
110
			Feature featureInput) {
111
		// TODO Auto-generated method stub
112
		return null;
113
	}
114

  
115
	@Override
116
	public void invoke(org.gvsig.fmap.geom.Geometry g,
117
			EditableFeature featureInput) {
118
		// TODO Auto-generated method stub
119
		
120
	}
121
	
122
	/**
123
	 * Computes a complete operation over the input FeatureStore. The result of this operation
124
	 * is stored in the output FeatureStore. This method will call once for each geometry.
125
	 * @param inFeatStore
126
	 *        Input FeatureStore
127
	 * @param outFeatStore
128
	 *        Output FeatureStore
129
	 * @param attrNames
130
	 *        List of attributes to build the output feature store
131
	 * @param selectedGeom
132
	 *        If it is true only the selected geometries will be processed
133
	 * @throws DataException
134
	 */
135
	@SuppressWarnings("deprecation")
136
	public void computesGeometryOperation(FeatureStore inFeatStore,
137
									FeatureStore outFeatStore,
138
									FeatureStore outFeatStoreTable,
139
									String[] attrNames,
140
									String[] attrNamesTable,
141
									boolean selectedGeomInput,
142
									boolean selectedGeomOutput,
143
									String idField) throws DataException {
144
		this.outFeatStoreTable = outFeatStoreTable;
145
		this.nameIdField = idField;
146
		this.inFeatureStore = inFeatStore;
147
		this.selectedGeomInput = selectedGeomInput;
148
		this.selectedGeomOverlay = selectedGeomOutput;
149
		FeatureSet featuresSet = null;
150
		featuresSet = inFeatStore.getFeatureSet();
151
		
152
		setFeatureStore(outFeatStore, attrNames);
153
		DisposableIterator it = null;
154

  
155
		if(selectedGeomInput) {
156
            FeatureSelection ds = inFeatStore.getFeatureSelection();
157
            it = ds.iterator();
158
            numberOfFeatures = (int) ds.getSelectedCount();
159
		} else {
160
			it = featuresSet.iterator();
161
			numberOfFeatures = (int)featuresSet.getSize();
162
		}
163
		
164
        if (status != null) 
165
            status.setRangeOfValues(0, numberOfFeatures);
166
        if(process != null) 
167
            process.setProgress(0, numberOfFeatures);
168
		
169
        //Crear lista de elementos
170
		int iCount = 0;
171
		while( it.hasNext() && !process.getTaskMonitor().isCanceled()) {
172
			Feature feat = (Feature)it.next();
173
			Element el = new Element();
174
			el.feat = feat;
175
			el.id = iCount;
176
			featureList.add(el);
177
            if (status != null && process != null) 
178
                status.setCurValue(iCount);
179
            if(process != null) 
180
                process.setProgress(iCount, numberOfFeatures);
181
			iCount ++;
182
		}
183
		it.dispose();
184
		
185
		//Crear listas de solapes para cada feature
186
		iCount = 0;
187
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
188
			Element elem1 = featureList.get(iCount);
189
			org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry();
190
			if (status != null)  
191
                status.setCurValue(iCount);
192
            if(process != null)
193
                process.setProgress(iCount, numberOfFeatures);
194
            
195
			for (int i = iCount + 1; i < featureList.size(); i++) {
196
				Element elem2 = featureList.get(i);
197
				org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry();
198
				if(areBBoxesOverlaping(geom1, geom2)) {
199
					if(elem1.jtsGeom == null)
200
						elem1.jtsGeom = GeometryUtil.geomToJTS(geom1);
201
					elem2.jtsGeom = GeometryUtil.geomToJTS(geom2);
202
					if(elem1.jtsGeom.intersects(elem2.jtsGeom))	{
203
						elem1.overlapList.add(elem2);
204
						elem2.overlapList.add(elem1);
205
					}
206
				}
207
			}
208
			iCount ++;
209
		}
210
		
211
		iCount = 0;
212
		int iFeat = 0;
213
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
214
			Element elem1 = featureList.get(iCount);
215
			if (status != null) 
216
                status.setCurValue(iCount);
217
            if(process != null) 
218
                process.setProgress(iCount, numberOfFeatures);
219
      
220
			if(!elem1.insertedToJoin) {
221
				buildListToJoin(elem1, iFeat);
222
				iFeat ++;
223
			}
224
			
225
			iCount ++;
226
		}
227

  
228
		if(persister != null)
229
			persister.end();
230
		
231
	}
232
	
233
	private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) {
234
		if(g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0))
235
			return false;
236
		if(g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0))
237
			return false;
238
		if(g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1))
239
			return false;
240
		if(g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1))
241
			return false;
242
		return true;
243
	}
244
	
245
	/**
246
	 * Computes the union of the list of geometries
247
	 * @param listResult
248
	 * @param elem1
249
	 * @return
250
	 */
251
	private Geometry computesUnion(List<Geometry> listResult, Element elem1) {
252
		int splitValue = 500;
253
		Geometry newGeom = null;
254
		if(listResult.size() > splitValue) {
255
			List<List<Geometry>> list = splitList(listResult, splitValue);
256
			List<Geometry> result = new ArrayList<Geometry>();
257
			for (int i = 0; i < list.size(); i++) {
258
				Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType());
259
				result.add(aux);
260
			}
261
			for (int i = 0; i < result.size(); i++) {
262
				newGeom = GeometryUtil.geometryUnion(result, elem1.feat.getDefaultGeometry().getGeometryType().getType());
263
			}
264
		} else {
265
			newGeom = GeometryUtil.geometryUnion(listResult, elem1.feat.getDefaultGeometry().getGeometryType().getType());	
266
		}
267
		return newGeom;
268
	}
269
	
270
	private Geometry computesUnion2(List<Geometry> listResult, Element elem1) {
271
		Geometry newGeom = null;
272
		for (int i = 1; i < listResult.size(); i++) {
273
			if(i == 1)
274
				newGeom = JTSFacade.union(listResult.get(0), listResult.get(1));
275
			else
276
				newGeom = JTSFacade.union(newGeom, listResult.get(i));
277
		}
278
		return newGeom;
279
	}
280
	
281
	private Geometry computesUnion3(List<Geometry> listResult) {
282
		Geometry newGeom = null;
283
		int iCount = 0;
284
		int max = listResult.size();
285
		if(process != null)
286
			process.setName("Generating union");
287
		while(listResult.size() > 1) {
288
			List<Geometry> list = new ArrayList<Geometry>();
289
			if (status != null)  
290
                status.setCurValue(iCount);
291
            if(process != null)
292
                process.setProgress(iCount, max);
293
			for (int i = 0; i < listResult.size(); i = i + 2) {
294
				if(i == (listResult.size() - 1))
295
					list.add(listResult.get(i));
296
				else {
297
					newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1));
298
					list.add(newGeom);
299
				}
300
			}
301
			listResult = list;
302
		}
303
		return newGeom;
304
	}
305
	
306
	/**
307
	 * Splits the array of geometries to compute its union because JTS cannot support
308
	 * a lot of geometries
309
	 * @param list
310
	 * @param n
311
	 * @return
312
	 */
313
	private List<List<Geometry>> splitList(List<Geometry> list, int n) {
314
		int elements = (int)(list.size() / n);
315
		List<List<Geometry>> l = new ArrayList<List<Geometry>>();
316
		for (int i = 0; i < elements; i++) {
317
			l.add(list.subList((i * n), (i * n) + n));
318
		}
319
		if(elements * n < list.size()) {
320
			l.add(list.subList((elements * n), list.size()));
321
		}
322
		return l;
323
	}
324
	
325
	/**
326
	 * Builds the union of all lists 
327
	 * @param listResult
328
	 * @param listToJoin
329
	 */
330
	private void buildListToJoin(Element elem, int iFeat) {
331
		Geometry newGeom = null;
332
		
333
		if(elem.overlapList.size() == 0) {
334
			if(!elem.insertedToJoin)
335
				elem.insertedToJoin = true;
336
			try {
337
				insertInTable(outFeatStoreTable, elem.feat, iFeat);
338
				addFeatureToOutput(elem.feat.getDefaultGeometry(), elem.feat, iFeat);
339
			} catch (DataException e) {
340
				logger.info("Imposible insertar en la tabla", e);
341
			} catch (CreateGeometryException e) {
342
				logger.info("Error a?adiendo geometr?a", e);
343
			}
344
		} else {
345
			List<Geometry> listResult = new ArrayList<Geometry>();
346
			NodeTree subtree = new NodeTree(elem, null);
347
			//Hacemos un recorrido en profundidad del ?rbol para a?adir
348
			//todos los elementos a la lista de geometrias a unir sin
349
			//repetir ninguna.
350
			while (subtree != null) {
351
				if(!subtree.element.insertedToJoin) {
352
					listResult.add(subtree.element.jtsGeom);
353
					try {
354
						insertInTable(outFeatStoreTable, subtree.element.feat, iFeat);
355
					} catch (DataException e) {
356
						logger.info("Imposible insertar en la tabla", e);
357
					}
358
					subtree.element.insertedToJoin = true;
359
				}
360
				
361
				boolean back = false;
362
				
363
				Element l = subtree.getNext();
364
				if(l == null) 
365
					back = true;
366
				
367
				while(!back && l.insertedToJoin) {
368
					l = subtree.getNext();
369
					if(l == null) 
370
						back = true;
371
				}
372
				
373
				if(back) {
374
					subtree = subtree.parent;
375
					continue;
376
				}
377
				subtree = new NodeTree(l, subtree);
378
			}
379
			newGeom = computesUnion3(listResult);
380
			
381
			try {
382
				addFeatureToOutput(newGeom, elem.feat, iFeat);
383
			} catch (DataException e) {
384
				logger.info("Imposible insertar en la tabla", e);
385
			} catch (CreateGeometryException e) {
386
				logger.info("Error a?adiendo geometr?a", e);
387
			}
388
		}
389
		
390
	}
391
	
392
	/**
393
	 * Adds a feature to the output
394
	 * @param newGeom
395
	 * @param feat
396
	 * @param newFeatID
397
	 * @throws DataException
398
	 * @throws CreateGeometryException
399
	 */
400
	private void addFeatureToOutput(org.gvsig.fmap.geom.Geometry newGeom, 
401
			Feature feat, 
402
			int newFeatID) throws DataException, CreateGeometryException {
403
		//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos
404
		if(outFeatStoreTable != null) { 
405
			lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID);
406
		} else {
407
			//Si no hay tabla se ponen todos los campos de la tabla de entrada
408
			String[] fieldNames = persister.getFieldNamesWithoutGeom();
409
			ArrayList<String> fields = new ArrayList<String>();
410
			ArrayList<Object> values = new ArrayList<Object>();
411
			fields.add(nameIdField);
412
			values.add(newFeatID);
413
			for (int j = 0; j < fieldNames.length; j++) {
414
				Object obj = feat.get(fieldNames[j]);
415
				if(obj != null && fieldNames[j].compareTo(nameIdField) != 0) {
416
					fields.add(fieldNames[j]);
417
					values.add(obj);
418
				}
419
			}
420
			lastEditFeature = persister.addFeature(newGeom, fields, values);
421
		}
422
	}
423
	
424
	/**
425
	 * Adds a feature to the output
426
	 * @param newGeom
427
	 * @param feat
428
	 * @param newFeatID
429
	 * @throws DataException
430
	 * @throws CreateGeometryException
431
	 */
432
	private void addFeatureToOutput(Geometry newGeom, 
433
			Feature feat, 
434
			int newFeatID) throws DataException, CreateGeometryException {
435
		//Si hay una tabla aparte esta capa solo lleva el id como referencia a la tabla de campos
436
		if(outFeatStoreTable != null) { 
437
			lastEditFeature = persister.addFeature(newGeom, nameIdField, newFeatID);
438
		} else {
439
			//Si no hay tabla se ponen todos los campos de la tabla de entrada
440
			String[] fieldNames = persister.getFieldNamesWithoutGeom();
441
			ArrayList<String> fields = new ArrayList<String>();
442
			ArrayList<Object> values = new ArrayList<Object>();
443
			fields.add(nameIdField);
444
			values.add(newFeatID);
445
			for (int j = 0; j < fieldNames.length; j++) {
446
				Object obj = feat.get(fieldNames[j]);
447
				if(obj != null && fieldNames[j].compareTo(nameIdField) != 0) {
448
					fields.add(fieldNames[j]);
449
					values.add(obj);
450
				}
451
			}
452
			lastEditFeature = persister.addFeature(newGeom, fields, values);
453
		}
454
	}
455
	
456
	/**
457
	 * Insert in the output table a new feature with the fields of the input feature. Moreover 
458
	 * exists a field that is an identifier which is a reference to the fusion layer.
459
	 * @param outFeatureStoreTable
460
	 * @param f
461
	 * @throws DataException
462
	 */
463
	private void insertInTable(FeatureStore outFeatureStoreTable, Feature f, int reference) throws DataException {
464
		if(outFeatureStoreTable == null)
465
			return;
466
		EditableFeature edFeat = outFeatureStoreTable.createNewFeature();
467
		edFeat.set(nameIdField, reference);
468
		FeatureAttributeDescriptor[] attrList = f.getType().getAttributeDescriptors();
469
		for (int j = 0; j < attrList.length; j++) {
470
			if(attrList[j].getName().compareTo("GEOMETRY") != 0) {
471
				edFeat.set(attrList[j].getName(), f.get(attrList[j].getName()));
472
			}
473
		}
474
		outFeatureStoreTable.insert(edFeat);
475
	}
476
	
477
}
478

  
0 479

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.15/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyOperationFast3.java
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
/*
25

  
26
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
27
 *
28
 * Copyright (C) 2010 Generalitat Valenciana.
29
 *
30
 * This program is free software; you can redistribute it and/or
31
 * modify it under the terms of the GNU General Public License
32
 * as published by the Free Software Foundation; either version 2
33
 * of the License, or (at your option) any later version.
34
 *
35
 * This program is distributed in the hope that it will be useful,
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38
 * GNU General Public License for more details.
39
 *
40
 * You should have received a copy of the GNU General Public License
41
 * along with this program; if not, write to the Free Software
42
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
43
 */
44

  
45
package org.gvsig.geoprocess.algorithm.fusespatially;
46

  
47
import java.util.ArrayList;
48
import java.util.List;
49

  
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.feature.EditableFeature;
52
import org.gvsig.fmap.dal.feature.Feature;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.FeatureSelection;
55
import org.gvsig.fmap.dal.feature.FeatureSet;
56
import org.gvsig.fmap.dal.feature.FeatureStore;
57
import org.gvsig.fmap.geom.exception.CreateGeometryException;
58
import org.gvsig.geoprocess.algorithm.base.core.GeometryOperation;
59
import org.gvsig.geoprocess.algorithm.base.util.GeometryUtil;
60
import org.gvsig.geoprocess.algorithm.base.util.JTSFacade;
61
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
62
import org.gvsig.tools.dispose.DisposableIterator;
63
import org.slf4j.Logger;
64
import org.slf4j.LoggerFactory;
65

  
66
import com.vividsolutions.jts.geom.Geometry;
67
/**
68
 * Fuse spatially operation
69
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
70
 */
71
public class FuseSpatiallyOperationFast3 extends GeometryOperation {
72
	private static Logger 			         logger    		    = LoggerFactory.getLogger(FuseSpatiallyOperationFast3.class.getName());
73
	private ArrayList<Element>               featureList        = null; 
74
	private String                           nameIdField        = null;
75
	private FeatureStore                     outFeatStoreTable  = null;
76
	private NodeTree                         baseTree           = null;
77
	
78
	class Element {
79
		public int                 id              = -1;
80
		public Feature             feat            = null;
81
		public List<Element>       overlapList     = new ArrayList<Element>();
82
		public boolean             insertedToJoin  = false;
83
		public Geometry            jtsGeom         = null;
84
	}
85
	
86
	class NodeTree {
87
		public Element       element     = null;
88
		public int           pos         = 0;
89
		public NodeTree       parent      = null;
90
		
91
		public NodeTree(Element node, NodeTree parent) {
92
			this.element = node;
93
			this.parent = parent;
94
		}
95
		
96
		public Element getNext() {
97
			if(pos < element.overlapList.size())
98
				return element.overlapList.get(pos++);
99
			return null;
100
		}
101
	}
102
	
103
	public FuseSpatiallyOperationFast3(AbstractSextanteGeoProcess process) {
104
		super(process);
105
		featureList = new ArrayList<Element>();
106
	}
107

  
108
	@Override
109
	public EditableFeature invoke(org.gvsig.fmap.geom.Geometry g,
110
			Feature featureInput) {
111
		// TODO Auto-generated method stub
112
		return null;
113
	}
114

  
115
	@Override
116
	public void invoke(org.gvsig.fmap.geom.Geometry g,
117
			EditableFeature featureInput) {
118
		// TODO Auto-generated method stub
119
		
120
	}
121
	
122
	/**
123
	 * Computes a complete operation over the input FeatureStore. The result of this operation
124
	 * is stored in the output FeatureStore. This method will call once for each geometry.
125
	 * @param inFeatStore
126
	 *        Input FeatureStore
127
	 * @param outFeatStore
128
	 *        Output FeatureStore
129
	 * @param attrNames
130
	 *        List of attributes to build the output feature store
131
	 * @param selectedGeom
132
	 *        If it is true only the selected geometries will be processed
133
	 * @throws DataException
134
	 */
135
	@SuppressWarnings("deprecation")
136
	public void computesGeometryOperation(FeatureStore inFeatStore,
137
									FeatureStore outFeatStore,
138
									FeatureStore outFeatStoreTable,
139
									String[] attrNames,
140
									String[] attrNamesTable,
141
									boolean selectedGeomInput,
142
									boolean selectedGeomOutput,
143
									String idField) throws DataException {
144
		this.outFeatStoreTable = outFeatStoreTable;
145
		this.nameIdField = idField;
146
		this.inFeatureStore = inFeatStore;
147
		this.selectedGeomInput = selectedGeomInput;
148
		this.selectedGeomOverlay = selectedGeomOutput;
149
		FeatureSet featuresSet = null;
150
		featuresSet = inFeatStore.getFeatureSet();
151
		
152
		setFeatureStore(outFeatStore, attrNames);
153
		DisposableIterator it = null;
154

  
155
		if(selectedGeomInput) {
156
            FeatureSelection ds = inFeatStore.getFeatureSelection();
157
            it = ds.iterator();
158
            numberOfFeatures = (int) ds.getSelectedCount();
159
		} else {
160
			it = featuresSet.iterator();
161
			numberOfFeatures = (int)featuresSet.getSize();
162
		}
163
		
164
        if (status != null) 
165
            status.setRangeOfValues(0, numberOfFeatures);
166
        if(process != null) 
167
            process.setProgress(0, numberOfFeatures);
168
		
169
        //Crear lista de elementos
170
		int iCount = 0;
171
		while( it.hasNext() && !process.getTaskMonitor().isCanceled()) {
172
			Feature feat = (Feature)it.next();
173
			Element el = new Element();
174
			el.feat = feat;
175
			el.id = iCount;
176
			featureList.add(el);
177
            if (status != null && process != null) 
178
                status.setCurValue(iCount);
179
            if(process != null) 
180
                process.setProgress(iCount, numberOfFeatures);
181
			iCount ++;
182
		}
183
		it.dispose();
184
		
185
		//Crear listas de solapes para cada feature
186
		iCount = 0;
187
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
188
			Element elem1 = featureList.get(iCount);
189
			org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry();
190
			if (status != null)  
191
                status.setCurValue(iCount);
192
            if(process != null)
193
                process.setProgress(iCount, numberOfFeatures);
194
            
195
			for (int i = iCount + 1; i < featureList.size(); i++) {
196
				Element elem2 = featureList.get(i);
197
				org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry();
198
				if(areBBoxesOverlaping(geom1, geom2)) {
199
					if(elem1.jtsGeom == null)
200
						elem1.jtsGeom = GeometryUtil.geomToJTS(geom1);
201
					elem2.jtsGeom = GeometryUtil.geomToJTS(geom2);
202
					if(elem1.jtsGeom.intersects(elem2.jtsGeom))	{
203
						elem1.overlapList.add(elem2);
204
						elem2.overlapList.add(elem1);
205
					}
206
				}
207
			}
208
			iCount ++;
209
		}
210
		
211
		iCount = 0;
212
		int iFeat = 0;
213
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
214
			Element elem1 = featureList.get(iCount);
215
			if (status != null) 
216
                status.setCurValue(iCount);
217
            if(process != null) 
218
                process.setProgress(iCount, numberOfFeatures);
219
      
220
			if(!elem1.insertedToJoin) {
221
				buildListToJoin(elem1, iFeat);
222
				iFeat ++;
223
			}
224
			iCount ++;
225
		}
226

  
227
		if(persister != null)
228
			persister.end();
229
		
230
	}
231
	
232
	private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) {
233
		if(g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0))
234
			return false;
235
		if(g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0))
236
			return false;
237
		if(g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1))
238
			return false;
239
		if(g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1))
240
			return false;
241
		return true;
242
	}
243
	
244
	/**
245
	 * Computes the union of the list of geometries
246
	 * @param listResult
247
	 * @param elem1
248
	 * @return
249
	 */
250
	private Geometry computesUnion(List<Geometry> listResult, Element elem1) {
251
		int splitValue = 500;
252
		Geometry newGeom = null;
253
		if(listResult.size() > splitValue) {
254
			List<List<Geometry>> list = splitList(listResult, splitValue);
255
			List<Geometry> result = new ArrayList<Geometry>();
256
			for (int i = 0; i < list.size(); i++) {
257
				Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType());
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff