root / trunk / extensions / extGeoProcessing / src / com / iver / cit / gvsig / geoprocess / impl / union / fmap / UnionGeoprocess.java @ 29575
History | View | Annotate | Download (13.5 KB)
1 |
/*
|
---|---|
2 |
* Created on 17-feb-2006
|
3 |
*
|
4 |
* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
|
5 |
*
|
6 |
* Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
|
7 |
*
|
8 |
* This program is free software; you can redistribute it and/or
|
9 |
* modify it under the terms of the GNU General Public License
|
10 |
* as published by the Free Software Foundation; either version 2
|
11 |
* of the License, or (at your option) any later version.
|
12 |
*
|
13 |
* This program is distributed in the hope that it will be useful,
|
14 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
* GNU General Public License for more details.
|
17 |
*
|
18 |
* You should have received a copy of the GNU General Public License
|
19 |
* along with this program; if not, write to the Free Software
|
20 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
|
21 |
*
|
22 |
* For more information, contact:
|
23 |
*
|
24 |
* Generalitat Valenciana
|
25 |
* Conselleria d'Infraestructures i Transport
|
26 |
* Av. Blasco Ib??ez, 50
|
27 |
* 46010 VALENCIA
|
28 |
* SPAIN
|
29 |
*
|
30 |
* +34 963862235
|
31 |
* gvsig@gva.es
|
32 |
* www.gvsig.gva.es
|
33 |
*
|
34 |
* or
|
35 |
*
|
36 |
* IVER T.I. S.A
|
37 |
* Salamanca 50
|
38 |
* 46005 Valencia
|
39 |
* Spain
|
40 |
*
|
41 |
* +34 963163400
|
42 |
* dac@iver.es
|
43 |
*/
|
44 |
/* CVS MESSAGES:
|
45 |
*
|
46 |
* $Id: UnionGeoprocess.java 29575 2009-06-26 10:31:21Z jmvivo $
|
47 |
* $Log$
|
48 |
* Revision 1.6 2007-09-19 16:08:38 jaume
|
49 |
* ReadExpansionFileException removed from this context
|
50 |
*
|
51 |
* Revision 1.5 2007/08/07 16:10:20 azabala
|
52 |
* centrilizing JTS in JTSFacade and allowing all geometry types (not only Polygon)
|
53 |
*
|
54 |
* Revision 1.4 2007/05/15 07:24:19 cesar
|
55 |
* Add the finished method for execution from Event Dispatch Thread
|
56 |
*
|
57 |
* Revision 1.3 2007/03/06 16:47:58 caballero
|
58 |
* Exceptions
|
59 |
*
|
60 |
* Revision 1.2 2006/06/29 07:33:57 fjp
|
61 |
* Cambios ISchemaManager y IFieldManager por terminar
|
62 |
*
|
63 |
* Revision 1.1 2006/06/20 18:20:45 azabala
|
64 |
* first version in cvs
|
65 |
*
|
66 |
* Revision 1.2 2006/06/08 18:25:49 azabala
|
67 |
* modificaciones para admitir capas de shapeType MULTI
|
68 |
*
|
69 |
* Revision 1.1 2006/05/24 21:09:11 azabala
|
70 |
* primera version en cvs despues de refactoring orientado a crear un framework extensible de geoprocessing
|
71 |
*
|
72 |
* Revision 1.12 2006/05/01 19:04:47 azabala
|
73 |
* la cancelacion no solo para el ITask que ejecuta el geoproceso, adem?s llama al metodo cancel() del mismo (que se supone que deber?a hacer un drop() con los resultados del geoproceso inconcluso)
|
74 |
*
|
75 |
* Revision 1.11 2006/03/26 20:03:18 azabala
|
76 |
* *** empty log message ***
|
77 |
*
|
78 |
* Revision 1.10 2006/03/23 21:05:29 azabala
|
79 |
* *** empty log message ***
|
80 |
*
|
81 |
* Revision 1.9 2006/03/21 19:29:45 azabala
|
82 |
* *** empty log message ***
|
83 |
*
|
84 |
* Revision 1.8 2006/03/17 19:53:53 azabala
|
85 |
* *** empty log message ***
|
86 |
*
|
87 |
* Revision 1.7 2006/03/15 18:34:41 azabala
|
88 |
* *** empty log message ***
|
89 |
*
|
90 |
* Revision 1.6 2006/03/14 18:32:46 fjp
|
91 |
* Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n.
|
92 |
*
|
93 |
* Revision 1.5 2006/03/07 21:01:33 azabala
|
94 |
* *** empty log message ***
|
95 |
*
|
96 |
* Revision 1.4 2006/03/06 19:48:39 azabala
|
97 |
* *** empty log message ***
|
98 |
*
|
99 |
* Revision 1.3 2006/02/26 20:55:37 azabala
|
100 |
* *** empty log message ***
|
101 |
*
|
102 |
* Revision 1.2 2006/02/20 19:43:51 azabala
|
103 |
* *** empty log message ***
|
104 |
*
|
105 |
* Revision 1.1 2006/02/19 20:55:34 azabala
|
106 |
* *** empty log message ***
|
107 |
*
|
108 |
*
|
109 |
*/
|
110 |
package com.iver.cit.gvsig.geoprocess.impl.union.fmap; |
111 |
|
112 |
import java.util.Map; |
113 |
|
114 |
import com.hardcode.gdbms.driver.exceptions.ReadDriverException; |
115 |
import com.hardcode.gdbms.driver.exceptions.SchemaEditionException; |
116 |
import com.iver.andami.PluginServices; |
117 |
import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException; |
118 |
import com.iver.cit.gvsig.exceptions.visitors.VisitorException; |
119 |
import com.iver.cit.gvsig.fmap.core.FShape; |
120 |
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition; |
121 |
import com.iver.cit.gvsig.fmap.edition.writers.shp.MultiShpWriter; |
122 |
import com.iver.cit.gvsig.fmap.layers.FBitSet; |
123 |
import com.iver.cit.gvsig.fmap.layers.FLyrVect; |
124 |
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy; |
125 |
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager; |
126 |
import com.iver.cit.gvsig.geoprocess.core.fmap.AbstractGeoprocess; |
127 |
import com.iver.cit.gvsig.geoprocess.core.fmap.DeferredFeaturePersisterProcessor; |
128 |
import com.iver.cit.gvsig.geoprocess.core.fmap.DefinitionUtils; |
129 |
import com.iver.cit.gvsig.geoprocess.core.fmap.GeoprocessException; |
130 |
import com.iver.cit.gvsig.geoprocess.core.fmap.IOverlayGeoprocess; |
131 |
import com.iver.cit.gvsig.geoprocess.impl.difference.fmap.DifferenceVisitor; |
132 |
import com.iver.cit.gvsig.geoprocess.impl.intersection.fmap.IntersectVisitor; |
133 |
import com.iver.utiles.swing.threads.CancellableMonitorable; |
134 |
import com.iver.utiles.swing.threads.DefaultCancellableMonitorable; |
135 |
import com.iver.utiles.swing.threads.IMonitorableTask; |
136 |
/**
|
137 |
* Union geoprocess is known like "spatial or" because is an overlay
|
138 |
* geoprocess (it computes intersections between features of
|
139 |
* two layers) formed for geometries of one layer or another.
|
140 |
* <br>
|
141 |
* Algorithm makes these three passes:
|
142 |
* a) computing intersections and saves them in a temp file.
|
143 |
* b) computing differences with first layer.
|
144 |
* c) computing differences with second layer.
|
145 |
* @author azabala
|
146 |
*
|
147 |
*TODO Is very similar to ClipGeoprocess. Build an overlay abstract class.
|
148 |
*
|
149 |
*
|
150 |
*/
|
151 |
public class UnionGeoprocess extends AbstractGeoprocess |
152 |
implements IOverlayGeoprocess {
|
153 |
|
154 |
/**
|
155 |
* overlay layer
|
156 |
*/
|
157 |
private FLyrVect overlayLayer;
|
158 |
|
159 |
/**
|
160 |
* Schema of the result layer
|
161 |
*/
|
162 |
private ILayerDefinition resultLayerDefinition;
|
163 |
/**
|
164 |
* flag to only clip selection of input layer
|
165 |
*/
|
166 |
private boolean onlyFirstLayerSelection = false; |
167 |
/**
|
168 |
* flag to only clip with selection of clipping layer
|
169 |
*/
|
170 |
private boolean onlyClipLayerSelection = false; |
171 |
|
172 |
/**
|
173 |
* Constructor
|
174 |
*
|
175 |
*/
|
176 |
public UnionGeoprocess(FLyrVect inputLayer){
|
177 |
setFirstOperand(inputLayer); |
178 |
} |
179 |
|
180 |
public void setSecondOperand(FLyrVect secondLayer) { |
181 |
this.overlayLayer = secondLayer;
|
182 |
} |
183 |
|
184 |
public void setFirstOperand(FLyrVect firstLayer) { |
185 |
this.firstLayer = firstLayer;
|
186 |
|
187 |
} |
188 |
|
189 |
public void setParameters(Map params) throws GeoprocessException { |
190 |
Boolean firstLayerSelection = (Boolean) params.get("firstlayerselection"); |
191 |
if(firstLayerSelection != null) |
192 |
this.onlyFirstLayerSelection = firstLayerSelection.booleanValue();
|
193 |
|
194 |
Boolean secondLayerSelection = (Boolean) params.get("secondlayerselection"); |
195 |
if(secondLayerSelection != null) |
196 |
this.onlyClipLayerSelection = secondLayerSelection.booleanValue();
|
197 |
|
198 |
} |
199 |
|
200 |
public void checkPreconditions() throws GeoprocessException { |
201 |
if (firstLayer == null) |
202 |
throw new GeoprocessException("Union: capa de entrada a null"); |
203 |
if (overlayLayer == null) |
204 |
throw new GeoprocessException("Union: capa de union a null"); |
205 |
if(this.writer == null || |
206 |
this.schemaManager == null){ |
207 |
throw new GeoprocessException("Operacion de union sin especificar capa de resultados"); |
208 |
} |
209 |
|
210 |
/*
|
211 |
TODO: REVISAR EL CASO DE PUNTOS + PUNTOS: NO HAY QUE CALCULAR NADA
|
212 |
try {
|
213 |
if(firstLayer.getShapeType() != XTypes.POLYGON
|
214 |
&& firstLayer.getShapeType() != XTypes.MULTI){
|
215 |
throw new GeoprocessException("Primera capa de union no es de pol?gonos");
|
216 |
}
|
217 |
if(overlayLayer.getShapeType() != XTypes.POLYGON
|
218 |
&& overlayLayer.getShapeType() != XTypes.MULTI){
|
219 |
throw new GeoprocessException("Segunda capa de union no es de pol?gonos");
|
220 |
}
|
221 |
} catch (ReadDriverException e) {
|
222 |
throw new GeoprocessException("Error al tratar de chequear si las capas a unir son de pol?gonos");
|
223 |
}
|
224 |
*/
|
225 |
|
226 |
} |
227 |
|
228 |
/**
|
229 |
* Runs execution of this geoprocess.
|
230 |
*/
|
231 |
public void process() throws GeoprocessException { |
232 |
try {
|
233 |
createTask().run(); |
234 |
} catch (Exception e) { |
235 |
throw new GeoprocessException(); |
236 |
} |
237 |
} |
238 |
|
239 |
public void cancel() { |
240 |
// TODO Auto-generated method stub
|
241 |
|
242 |
} |
243 |
|
244 |
public ILayerDefinition createLayerDefinition() {
|
245 |
if(resultLayerDefinition == null){ |
246 |
try {
|
247 |
resultLayerDefinition = DefinitionUtils. |
248 |
mergeLayerDefinitions(firstLayer, overlayLayer); |
249 |
resultLayerDefinition.setShapeType(FShape.MULTI); |
250 |
} catch (Exception e) { |
251 |
//TODO Quizas createLayerDefinition deberia lanzar
|
252 |
//una excepcion
|
253 |
e.printStackTrace(); |
254 |
} |
255 |
} |
256 |
return resultLayerDefinition;
|
257 |
} |
258 |
|
259 |
public IMonitorableTask createTask() {
|
260 |
try {
|
261 |
return new UnionMonitorableTask(); |
262 |
} catch (Exception e) { |
263 |
return null; |
264 |
} |
265 |
} |
266 |
|
267 |
/**
|
268 |
* IMonitorableTask that allows to run diff geoprocess in background,
|
269 |
* with cancelation requests.
|
270 |
*
|
271 |
* @author azabala
|
272 |
*
|
273 |
* FIXME INTERNACIONALIZAR TODOS LOS TEXTOS
|
274 |
*
|
275 |
*/
|
276 |
class UnionMonitorableTask implements IMonitorableTask { |
277 |
private CancellableMonitorable cancelMonitor = null; |
278 |
String UNION_MESSAGE = PluginServices.getText(this, "Mensaje_union"); |
279 |
String FIRST_PASS_NOTE = PluginServices.getText(this, "Mensaje_primera_pasada_union"); |
280 |
String SECOND_PASS_NOTE = PluginServices.getText(this, "Mensaje_segunda_pasada_union"); |
281 |
String THIRD_PASS_NOTE = PluginServices.getText(this, "Mensaje_tercera_pasada_union"); |
282 |
String OF = PluginServices.getText(this, "De"); |
283 |
|
284 |
|
285 |
String currentMessage = ""; |
286 |
private boolean finished = false; |
287 |
|
288 |
UnionMonitorableTask() throws ReadDriverException {
|
289 |
initialize(); |
290 |
} |
291 |
void initialize() throws ReadDriverException { |
292 |
cancelMonitor = createCancelMonitor(); |
293 |
currentMessage = "Initializing...";
|
294 |
} |
295 |
|
296 |
private CancellableMonitorable createCancelMonitor() throws ReadDriverException { |
297 |
DefaultCancellableMonitorable monitor = new
|
298 |
DefaultCancellableMonitorable(); |
299 |
monitor.setInitialStep(0);
|
300 |
monitor.setDeterminatedProcess(true);
|
301 |
int numSteps = 0; |
302 |
//num steps = 2 * firstlayer (intersect + diff A-B)
|
303 |
//+ second layer (diff B-A)
|
304 |
if (onlyFirstLayerSelection) {
|
305 |
FBitSet selection = firstLayer.getRecordset().getSelection(); |
306 |
numSteps += (2 * selection.cardinality());
|
307 |
} else {
|
308 |
numSteps += 2 * firstLayer.getSource().getShapeCount();
|
309 |
} |
310 |
if(onlyClipLayerSelection) {
|
311 |
FBitSet selection = overlayLayer.getRecordset().getSelection(); |
312 |
numSteps += (2 * selection.cardinality());
|
313 |
}else{
|
314 |
numSteps += 2 * overlayLayer.getSource().getShapeCount();
|
315 |
} |
316 |
monitor.setFinalStep(numSteps); |
317 |
return monitor;
|
318 |
} |
319 |
|
320 |
public int getInitialStep() { |
321 |
return cancelMonitor.getInitialStep();
|
322 |
} |
323 |
|
324 |
public int getFinishStep() { |
325 |
return cancelMonitor.getFinalStep();
|
326 |
} |
327 |
|
328 |
public int getCurrentStep() { |
329 |
return cancelMonitor.getCurrentStep();
|
330 |
} |
331 |
|
332 |
public String getStatusMessage() { |
333 |
return UNION_MESSAGE;
|
334 |
} |
335 |
|
336 |
public String getNote() { |
337 |
return currentMessage + " "+ |
338 |
getCurrentStep() + " "+
|
339 |
OF + " " + getFinishStep();
|
340 |
} |
341 |
|
342 |
public void cancel() { |
343 |
((DefaultCancellableMonitorable) cancelMonitor).setCanceled(true);
|
344 |
UnionGeoprocess.this.cancel(); |
345 |
} |
346 |
|
347 |
public void run() throws GeoprocessException { |
348 |
/*
|
349 |
* Lo vamos a hacer en tres pasadas:
|
350 |
* a) intersecciones con el geoproceso Intersection,
|
351 |
* guardando en el fichero del usuario.
|
352 |
* b) diferencias de first con overlay, guardando en el
|
353 |
* mismo fichero
|
354 |
* c) diferencias de overlay con first, guardando en el
|
355 |
* mismo fichero
|
356 |
*/
|
357 |
try {
|
358 |
if (!(writer instanceof MultiShpWriter)){ |
359 |
schemaManager.createSchema(createLayerDefinition()); |
360 |
} |
361 |
writer.preProcess(); |
362 |
|
363 |
Strategy strategy = StrategyManager.getStrategy(firstLayer); |
364 |
Strategy strategy2 = StrategyManager.getStrategy(overlayLayer); |
365 |
DeferredFeaturePersisterProcessor featureProcessor = |
366 |
new DeferredFeaturePersisterProcessor(writer);
|
367 |
|
368 |
IntersectVisitor visitor = new IntersectVisitor(overlayLayer,
|
369 |
featureProcessor, |
370 |
strategy2, |
371 |
onlyClipLayerSelection); |
372 |
//FIXME Meter las selecciones
|
373 |
currentMessage = FIRST_PASS_NOTE; |
374 |
if(onlyFirstLayerSelection){
|
375 |
FBitSet selection = firstLayer.getRecordset().getSelection(); |
376 |
strategy.process(visitor, selection, cancelMonitor); |
377 |
}else{
|
378 |
strategy.process(visitor, cancelMonitor); |
379 |
} |
380 |
|
381 |
currentMessage = SECOND_PASS_NOTE; |
382 |
DifferenceVisitor visitor2 = new DifferenceVisitor(overlayLayer,
|
383 |
featureProcessor, strategy2, onlyClipLayerSelection); |
384 |
visitor2.setLayerDefinition(resultLayerDefinition); |
385 |
if(onlyFirstLayerSelection){
|
386 |
FBitSet selection = firstLayer.getRecordset().getSelection(); |
387 |
strategy.process(visitor2, selection, cancelMonitor); |
388 |
}else{
|
389 |
strategy.process(visitor2, cancelMonitor); |
390 |
} |
391 |
currentMessage = THIRD_PASS_NOTE; |
392 |
DifferenceVisitor visitor3 = new DifferenceVisitor(firstLayer,
|
393 |
featureProcessor, strategy, onlyFirstLayerSelection); |
394 |
visitor3.setLayerDefinition(resultLayerDefinition); |
395 |
if(onlyClipLayerSelection){
|
396 |
FBitSet selection = overlayLayer.getRecordset().getSelection(); |
397 |
strategy2.process(visitor3, selection, cancelMonitor); |
398 |
}else{
|
399 |
strategy2.process(visitor3, cancelMonitor); |
400 |
} |
401 |
writer.postProcess(); |
402 |
|
403 |
} catch (SchemaEditionException e) {
|
404 |
throw new GeoprocessException("Error al crear el esquema/fichero de la nueva capa"); |
405 |
} catch (ReadDriverException e) {
|
406 |
throw new GeoprocessException("Error de driver al calcular el geoproceso interseccion"); |
407 |
} catch (ProcessVisitorException e) {
|
408 |
throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion"); |
409 |
} catch (VisitorException e) {
|
410 |
throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion"); |
411 |
} finally{
|
412 |
finished = true;
|
413 |
} |
414 |
} |
415 |
|
416 |
public boolean isDefined() { |
417 |
return cancelMonitor.isDeterminatedProcess();
|
418 |
} |
419 |
|
420 |
public boolean isCanceled() { |
421 |
return cancelMonitor.isCanceled();
|
422 |
} |
423 |
|
424 |
public boolean isFinished() { |
425 |
return finished;
|
426 |
} |
427 |
/* (non-Javadoc)
|
428 |
* @see com.iver.utiles.swing.threads.IMonitorableTask#finished()
|
429 |
*/
|
430 |
public void finished() { |
431 |
// TODO Auto-generated method stub
|
432 |
|
433 |
} |
434 |
} |
435 |
|
436 |
} |
437 |
|