Revision 1119

View differences:

org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.100/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyLibrary.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
package org.gvsig.geoprocess.algorithm.fusespatially;
25

  
26
import org.gvsig.geoprocess.algorithm.base.core.AlgorithmAbstractLibrary;
27
import org.gvsig.i18n.Messages;
28
import org.gvsig.tools.library.LibraryException;
29

  
30
/**
31
 * Initialization of FuseSpatiallyLibrary library.
32
 * 
33
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
34
 */
35
public class FuseSpatiallyLibrary extends AlgorithmAbstractLibrary {
36

  
37
    @Override
38
    protected void doInitialize() throws LibraryException {
39

  
40
    }
41

  
42
    @Override
43
    protected void doPostInitialize() throws LibraryException {
44
        Messages.addResourceFamily(
45
            "org.gvsig.geoprocess.algorithm.fusespatially.fusespatially",
46
            FuseSpatiallyLibrary.class.getClassLoader(), FuseSpatiallyLibrary.class
47
                .getClass().getName());
48

  
49
        registerGeoProcess(new FuseSpatiallyAlgorithm());
50
    }
51

  
52
}
0 53

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.100/org.gvsig.geoprocess.algorithm/org.gvsig.geoprocess.algorithm.fusespatially/src/main/java/org/gvsig/geoprocess/algorithm/fusespatially/FuseSpatiallyAlgorithm.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
package org.gvsig.geoprocess.algorithm.fusespatially;
25

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

  
29
import org.gvsig.fmap.dal.exception.DataException;
30
import org.gvsig.fmap.dal.feature.Feature;
31
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
32
import org.gvsig.fmap.dal.feature.FeatureSet;
33
import org.gvsig.fmap.dal.feature.FeatureStore;
34
import org.gvsig.geoprocess.algorithm.dissolve.DissolveAlgorithm;
35
import org.gvsig.geoprocess.lib.sextante.AbstractSextanteGeoProcess;
36
import org.gvsig.geoprocess.lib.sextante.dataObjects.FlyrVectIVectorLayer;
37
import org.gvsig.tools.task.SimpleTaskStatus;
38

  
39
import es.unex.sextante.core.Sextante;
40
import es.unex.sextante.dataObjects.IVectorLayer;
41
import es.unex.sextante.exceptions.GeoAlgorithmExecutionException;
42
import es.unex.sextante.exceptions.RepeatedParameterNameException;
43
import es.unex.sextante.exceptions.UnsupportedOutputChannelException;
44
import es.unex.sextante.outputs.OutputVectorLayer;
45
import java.util.Iterator;
46

  
47
/**
48
 * Fuse spatially algorithm
49
 * @author <a href="mailto:nachobrodin@gmail.com">Nacho Brodin</a>
50
 */
51
public class FuseSpatiallyAlgorithm extends AbstractSextanteGeoProcess {
52

  
53
	public static final String         RESULT            = "RESULT";
54
	public static final String         RESULT_TABLE      = "RESULT_TABLE";
55
	public static final String         LAYER             = "LAYER";
56
	public static final String         SELECTED_GEOM     = "SELECTED_GEOM";
57
	private AbstractSextanteGeoProcess process           = null;
58
	private String                     fid               = "FID";
59

  
60
	/*
61
	 * (non-Javadoc)
62
	 * @see es.unex.sextante.core.GeoAlgorithm#defineCharacteristics()
63
	 */
64
	public void defineCharacteristics(){
65
        setName(getTranslation("fusespatially"));
66
        setGroup(getTranslation("basic_vect_algorithms"));
67
        // setGeneratesUserDefinedRasterOutput(false);
68
		try {
69
			m_Parameters.addInputVectorLayer(LAYER, getTranslation("Input_layer"), IVectorLayer.SHAPE_TYPE_WRONG, true);
70
			m_Parameters.addBoolean(SELECTED_GEOM, getTranslation("Selected_geometries_fuse"), false);
71
			addOutputVectorLayer(RESULT, getTranslation("fuse_spatially") + " ", OutputVectorLayer.SHAPE_TYPE_UNDEFINED);
72
			addOutputVectorLayer(RESULT_TABLE, getTranslation("fuse_spatially") + "_" + getTranslation("Table") + " ", OutputVectorLayer.SHAPE_TYPE_UNDEFINED);
73
		} catch (RepeatedParameterNameException e) {
74
			Sextante.addErrorToLog(e);
75
		}
76
	}
77

  
78
	public void setParentProcess(AbstractSextanteGeoProcess process) {
79
		this.process = process;
80
	}
81

  
82
	/*
83
	 * (non-Javadoc)
84
	 * @see es.unex.sextante.core.GeoAlgorithm#processAlgorithm()
85
	 */
86
	public boolean processAlgorithm() throws GeoAlgorithmExecutionException {
87
		if(existsOutPutFile(DissolveAlgorithm.RESULT, 0)) {
88
    		throw new GeoAlgorithmExecutionException(getTranslation("file_exists"));
89
    	}
90
		IVectorLayer layer = m_Parameters.getParameterValueAsVectorLayer(LAYER);
91
		boolean selectedGeom = m_Parameters.getParameterValueAsBoolean(SELECTED_GEOM);
92

  
93
		FeatureStore storeLayer = null;
94
		if(layer instanceof FlyrVectIVectorLayer)
95
			storeLayer = ((FlyrVectIVectorLayer)layer).getFeatureStore();
96
		else
97
			return false;
98

  
99
		try {
100
			String[] attrNames = new String[]{"FID"};
101
			Class[] types = new Class[] {Integer.class};
102

  
103
			FeatureStore outFeatStore = buildFuseSpatiallyOutPutStore(attrNames, types,
104
					layer.getShapeType(), getTranslation("fusespatially"), RESULT);
105

  
106
			return execute(storeLayer, outFeatStore, layer.getShapeType(), selectedGeom, getStatus(), "FID", true);
107
		} catch (DataException e) {
108
			Sextante.addErrorToLog(e);
109
			return false;
110
		}
111
	}
112

  
113
	/**
114
	 * @param inputStoreLayer
115
	 * @param outFeatStore
116
	 * @param shapeType
117
	 * @param selectedGeom
118
	 * @param status
119
	 * @param idField
120
	 * @param createTable
121
	 * @return boolean
122
	 * @throws DataException
123
	 */
124
	public boolean execute(FeatureStore inputStoreLayer,
125
			FeatureStore outFeatStore,
126
			int shapeType,
127
			boolean selectedGeom,
128
			SimpleTaskStatus status,
129
			String idField,
130
			boolean createTable) throws DataException {
131
		FeatureStore outFeatStoreTable = null;
132
		String[] attrNamesTable = null;
133
		if(createTable) {
134
			attrNamesTable = new String[inputStoreLayer.getDefaultFeatureType().size() + 1];
135
			Class[] typesTable = new Class[inputStoreLayer.getDefaultFeatureType().size() + 1];
136
			attrNamesTable[0] = fid;
137
			typesTable[0] = Integer.class;
138
			for (int i = 0; i < inputStoreLayer.getDefaultFeatureType().size(); i++) {
139
				FeatureAttributeDescriptor attrDesc = inputStoreLayer.getDefaultFeatureType().getAttributeDescriptor(i);
140
				attrNamesTable[i + 1] = attrDesc.getName();
141
				typesTable[i + 1] = attrDesc.getDataType().getDefaultClass();
142
			}
143

  
144
			attrNamesTable = checkFields(attrNamesTable);
145
			outFeatStoreTable = buildFuseSpatiallyOutPutStore(attrNamesTable, typesTable,
146
				shapeType, getTranslation("fusespatially") + "_Table", RESULT_TABLE);
147
		}
148

  
149
		FuseSpatiallyOperationFast2 operation = new FuseSpatiallyOperationFast2(this);
150
		operation.setTaskStatus(getStatus());
151
		operation.computesGeometryOperation(inputStoreLayer,
152
				outFeatStore,
153
				outFeatStoreTable,
154
				new String[]{fid},
155
				attrNamesTable,
156
				selectedGeom,
157
				false,
158
				idField);
159

  
160
		if(getTaskMonitor().isCanceled())
161
			return false;
162
		/*computesGeometryOperation(inputStoreLayer, outFeatStore, outFeatStoreTable,
163
				attrNames, attrNamesTable, selectedGeom, status, idField);*/
164
		return true;
165
	}
166

  
167
	/**
168
	 * Removes duplicate fields
169
	 * @param names
170
	 * @return
171
	 */
172
	public String[] checkFields(String[] names) {
173
		if(names.length <= 1)
174
			return names;
175
		int cont = 0;
176

  
177
		int i = 1;
178
		while(i < names.length) {
179
			if(names[0].compareTo(names[i]) == 0) {
180
				names[0] = "FID_" + cont;
181
				i = 0;
182
				cont ++;
183
			}
184
			i ++;
185
		}
186
		return names;
187
	}
188

  
189

  
190
	/**
191
	 * Computes a complete operation over the input FeatureStore. The result of this operation
192
	 * is stored in the output FeatureStore. This method will call once for each geometry.
193
	 * @param inFeatStore
194
	 *        Input FeatureStore
195
	 * @param outFeatStore
196
	 *        Output FeatureStore
197
	 * @param attrNames
198
	 *        List of attributes to build the output feature store
199
	 * @param selectedGeom
200
	 *        If it is true only the selected geometries will be processed
201
	 * @deprecated This method uses FuseSpatiallyOperation which is deprecated
202
	 * @throws DataException
203
	 */
204
	@SuppressWarnings("deprecation")
205
	public void computesGeometryOperation(FeatureStore inFeatStore,
206
									FeatureStore outFeatStore,
207
									FeatureStore outFeatStoreTable,
208
									String[] attrNames,
209
									String[] attrNamesTable,
210
									boolean selectedGeom,
211
									SimpleTaskStatus status,
212
									String idField) throws DataException {
213
		FeatureSet featuresSet = null;
214
		Iterator it = null;
215

  
216
		if(selectedGeom) {
217
			featuresSet = (FeatureSet)inFeatStore.getSelection();
218
		} else {
219
			featuresSet = inFeatStore.getFeatureSet();
220
		}
221

  
222
		it = featuresSet.iterator();
223
		int numberOfFeatures = (int)featuresSet.getSize();
224
        if (status != null) {
225
            status.setRangeOfValues(0, numberOfFeatures);
226
        }
227

  
228
        //Stack<Feature> featList = new Stack<Feature>();
229
        List<Feature> featList = new ArrayList<Feature>();
230
		while( it.hasNext() ) {
231
			Feature feature = (Feature)it.next();
232
			featList.add(feature);
233
		}
234

  
235

  
236
		FuseSpatiallyOperation operation = new FuseSpatiallyOperation(featList,
237
				outFeatStoreTable,
238
				attrNamesTable,
239
				idField,
240
				this);
241
		operation.setFeatureStore(outFeatStore, attrNames);
242
		int size = featList.size();
243
		operation.setGeoProcess(this, size);
244

  
245
		while (featList.size() > 0 && !m_Task.isCanceled()) {
246
			Feature f = featList.remove(featList.size() - 1);
247
			operation.invoke(f.getDefaultGeometry(), f);
248
			setProgress(size - featList.size(), size);
249
		}
250

  
251
		if(operation.getWriter() != null)
252
			operation.getWriter().end();
253
	}
254

  
255
	public boolean setProgress(int step, int size) {
256
		if(process != null)
257
			return process.setProgress(step, size);
258
		else
259
			return super.setProgress(step, size);
260
	}
261

  
262
	/**
263
	 * Builds the output FeatureStore
264
	 * @param featureType
265
	 * @return FeatureStore
266
	 */
267
	@SuppressWarnings("unchecked")
268
	protected FeatureStore buildFuseSpatiallyOutPutStore(String[] attrNames,
269
											Class[] types,
270
											int shapeType,
271
											String sextanteLayerName,
272
											String sextanteLayerLabel) {
273

  
274

  
275
		try {
276
			IVectorLayer output = getNewVectorLayer(sextanteLayerLabel,
277
													sextanteLayerName,
278
													shapeType, types, attrNames);
279
			return ((FlyrVectIVectorLayer)output).getFeatureStore();
280
		} catch (UnsupportedOutputChannelException e) {
281
			Sextante.addErrorToLog(e);
282
        } catch (GeoAlgorithmExecutionException e) {
283
            Sextante.addErrorToLog(e);
284
        }
285
		return null;
286
	}
287

  
288
}
0 289

  
org.gvsig.geoprocess/tags/org.gvsig.geoprocess-2.2.100/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.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63

  
64
import com.vividsolutions.jts.geom.Geometry;
65
import java.util.Iterator;
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
		Iterator 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.100/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.100/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.100/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.slf4j.Logger;
63
import org.slf4j.LoggerFactory;
64

  
65
import com.vividsolutions.jts.geom.Geometry;
66
import java.util.Iterator;
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 outFeatStoreTable
130
	 * @param attrNames
131
	 *        List of attributes to build the output feature store
132
	 * @param attrNamesTable
133
	 * @param selectedGeomInput
134
	 * @param selectedGeomOutput
135
	 * @param idField
136
	 * @param selectedGeom
137
	 *        If it is true only the selected geometries will be processed
138
	 * @throws DataException
139
	 */
140
	@SuppressWarnings("deprecation")
141
	public void computesGeometryOperation(FeatureStore inFeatStore,
142
									FeatureStore outFeatStore,
143
									FeatureStore outFeatStoreTable,
144
									String[] attrNames,
145
									String[] attrNamesTable,
146
									boolean selectedGeomInput,
147
									boolean selectedGeomOutput,
148
									String idField) throws DataException {
149
		this.outFeatStoreTable = outFeatStoreTable;
150
		this.nameIdField = idField;
151
		this.inFeatureStore = inFeatStore;
152
		this.selectedGeomInput = selectedGeomInput;
153
		this.selectedGeomOverlay = selectedGeomOutput;
154
		FeatureSet featuresSet = null;
155
		featuresSet = inFeatStore.getFeatureSet();
156

  
157
		setFeatureStore(outFeatStore, attrNames);
158
		Iterator it = null;
159

  
160
		if(selectedGeomInput) {
161
            FeatureSelection ds = inFeatStore.getFeatureSelection();
162
            it = ds.iterator();
163
            numberOfFeatures = (int) ds.getSelectedCount();
164
		} else {
165
			it = featuresSet.iterator();
166
			numberOfFeatures = (int)featuresSet.getSize();
167
		}
168

  
169
        if (status != null)
170
            status.setRangeOfValues(0, numberOfFeatures);
171
        if(process != null)
172
            process.setProgress(0, numberOfFeatures);
173

  
174
        //Crear lista de elementos
175
		int iCount = 0;
176
		while( it.hasNext() && !process.getTaskMonitor().isCanceled()) {
177
			Feature feat = ((Feature)it.next()).getCopy();
178
			Element el = new Element();
179
			el.feat = feat;
180
			el.id = iCount;
181
			featureList.add(el);
182
            if (status != null && process != null)
183
                status.setCurValue(iCount);
184
            if(process != null)
185
                process.setProgress(iCount, numberOfFeatures);
186
			iCount ++;
187
		}
188
//		it.dispose();
189

  
190
		//Crear listas de solapes para cada feature
191
		iCount = 0;
192
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
193
			Element elem1 = featureList.get(iCount);
194
			org.gvsig.fmap.geom.Geometry geom1 = elem1.feat.getDefaultGeometry();
195
			if (status != null)
196
                status.setCurValue(iCount);
197
            if(process != null)
198
                process.setProgress(iCount, numberOfFeatures);
199

  
200
			for (int i = iCount + 1; i < featureList.size(); i++) {
201
				Element elem2 = featureList.get(i);
202
				org.gvsig.fmap.geom.Geometry geom2 = elem2.feat.getDefaultGeometry();
203
				if(areBBoxesOverlaping(geom1, geom2)) {
204
					if(elem1.jtsGeom == null) {
205
						elem1.jtsGeom = GeometryUtil.geomToJTS(geom1);
206
					}
207
					elem2.jtsGeom = GeometryUtil.geomToJTS(geom2);
208
					if(elem1.jtsGeom.intersects(elem2.jtsGeom))	{
209
						elem1.overlapList.add(elem2);
210
						elem2.overlapList.add(elem1);
211
					}
212
				}
213
			}
214
			iCount ++;
215
		}
216

  
217
		iCount = 0;
218
		int iFeat = 0;
219
		while (iCount < featureList.size() && !process.getTaskMonitor().isCanceled()) {
220
			Element elem1 = featureList.get(iCount);
221
			if (status != null)
222
                status.setCurValue(iCount);
223
            if(process != null)
224
                process.setProgress(iCount, numberOfFeatures);
225

  
226
			if(!elem1.insertedToJoin) {
227
				buildListToJoin(elem1, iFeat);
228
				iFeat ++;
229
			}
230

  
231
			iCount ++;
232
		}
233

  
234
		if(persister != null)
235
			persister.end();
236

  
237
	}
238

  
239
	private boolean areBBoxesOverlaping(org.gvsig.fmap.geom.Geometry g1, org.gvsig.fmap.geom.Geometry g2) {
240
		if(g1.getEnvelope().getMaximum(0) < g2.getEnvelope().getMinimum(0))
241
			return false;
242
		if(g1.getEnvelope().getMinimum(0) > g2.getEnvelope().getMaximum(0))
243
			return false;
244
		if(g1.getEnvelope().getMaximum(1) < g2.getEnvelope().getMinimum(1))
245
			return false;
246
		if(g1.getEnvelope().getMinimum(1) > g2.getEnvelope().getMaximum(1))
247
			return false;
248
		return true;
249
	}
250

  
251
	/**
252
	 * Computes the union of the list of geometries
253
	 * @param listResult
254
	 * @param elem1
255
	 * @return
256
	 */
257
	private Geometry computesUnion(List<Geometry> listResult, Element elem1) {
258
		int splitValue = 500;
259
		Geometry newGeom = null;
260
		if(listResult.size() > splitValue) {
261
			List<List<Geometry>> list = splitList(listResult, splitValue);
262
			List<Geometry> result = new ArrayList<Geometry>();
263
			for (int i = 0; i < list.size(); i++) {
264
				Geometry aux = GeometryUtil.geometryUnion(list.get(i), elem1.feat.getDefaultGeometry().getGeometryType().getType());
265
				result.add(aux);
266
			}
267
			for (int i = 0; i < result.size(); i++) {
268
				newGeom = GeometryUtil.geometryUnion(result, elem1.feat.getDefaultGeometry().getGeometryType().getType());
269
			}
270
		} else {
271
			newGeom = GeometryUtil.geometryUnion(listResult, elem1.feat.getDefaultGeometry().getGeometryType().getType());
272
		}
273
		return newGeom;
274
	}
275

  
276
	private Geometry computesUnion2(List<Geometry> listResult, Element elem1) {
277
		Geometry newGeom = null;
278
		for (int i = 1; i < listResult.size(); i++) {
279
			if(i == 1)
280
				newGeom = JTSFacade.union(listResult.get(0), listResult.get(1));
281
			else
282
				newGeom = JTSFacade.union(newGeom, listResult.get(i));
283
		}
284
		return newGeom;
285
	}
286

  
287
	private Geometry computesUnion3(List<Geometry> listResult) {
288
		Geometry newGeom = null;
289
		int iCount = 0;
290
		int max = listResult.size();
291
		if(process != null)
292
			process.setName("Generating union");
293
		while(listResult.size() > 1) {
294
			List<Geometry> list = new ArrayList<Geometry>();
295
			if (status != null)
296
                status.setCurValue(iCount);
297
            if(process != null)
298
                process.setProgress(iCount, max);
299
			for (int i = 0; i < listResult.size(); i = i + 2) {
300
				if(i == (listResult.size() - 1))
301
					list.add(listResult.get(i));
302
				else {
303
					newGeom = JTSFacade.union(listResult.get(i), listResult.get(i + 1));
304
					list.add(newGeom);
305
				}
306
			}
307
			listResult = list;
308
		}
309
		return newGeom;
310
	}
311

  
312
	/**
313
	 * Splits the array of geometries to compute its union because JTS cannot support
314
	 * a lot of geometries
315
	 * @param list
316
	 * @param n
317
	 * @return
318
	 */
319
	private List<List<Geometry>> splitList(List<Geometry> list, int n) {
320
		int elements = (int)(list.size() / n);
321
		List<List<Geometry>> l = new ArrayList<List<Geometry>>();
322
		for (int i = 0; i < elements; i++) {
323
			l.add(list.subList((i * n), (i * n) + n));
324
		}
325
		if(elements * n < list.size()) {
326
			l.add(list.subList((elements * n), list.size()));
327
		}
328
		return l;
329
	}
330

  
331
	/**
332
	 * Builds the union of all lists
333
	 * @param listResult
334
	 * @param listToJoin
335
	 */
336
	private void buildListToJoin(Element elem, int iFeat) {
337
		Geometry newGeom = null;
338

  
339
		if(elem.overlapList.size() == 0) {
340
			if(!elem.insertedToJoin)
341
				elem.insertedToJoin = true;
342
			try {
343
				insertInTable(outFeatStoreTable, elem.feat, iFeat);
344
				addFeatureToOutput(elem.feat.getDefaultGeometry(), elem.feat, iFeat);
345
			} catch (DataException e) {
346
				logger.info("Imposible insertar en la tabla", e);
347
			} catch (CreateGeometryException e) {
348
				logger.info("Error a?adiendo geometr?a", e);
349
			}
350
		} else {
351
			List<Geometry> listResult = new ArrayList<Geometry>();
352
			NodeTree subtree = new NodeTree(elem, null);
353
			//Hacemos un recorrido en profundidad del ?rbol para a?adir
354
			//todos los elementos a la lista de geometrias a unir sin
355
			//repetir ninguna.
356
			while (subtree != null) {
357
				if(!subtree.element.insertedToJoin) {
358
					listResult.add(subtree.element.jtsGeom);
359
					try {
360
						insertInTable(outFeatStoreTable, subtree.element.feat, iFeat);
361
					} catch (DataException e) {
362
						logger.info("Imposible insertar en la tabla", e);
363
					}
364
					subtree.element.insertedToJoin = true;
365
				}
366

  
367
				boolean back = false;
368

  
369
				Element l = subtree.getNext();
370
				if(l == null)
371
					back = true;
372

  
373
				while(!back && l.insertedToJoin) {
374
					l = subtree.getNext();
375
					if(l == null)
376
						back = true;
377
				}
378

  
379
				if(back) {
380
					subtree = subtree.parent;
381
					continue;
382
				}
383
				subtree = new NodeTree(l, subtree);
384
			}
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff