Statistics
| Revision:

root / trunk / extensions / extGeoProcessing / src / com / iver / gvsig / geoprocessing / impl / union / UnionGeoprocess.java @ 4447

History | View | Annotate | Download (13.6 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 4447 2006-03-15 18:35:56Z azabala $
47
* $Log$
48
* Revision 1.7  2006-03-15 18:34:41  azabala
49
* *** empty log message ***
50
*
51
* Revision 1.6  2006/03/14 18:32:46  fjp
52
* Cambio con LayerDefinition para que sea compatible con la definici?n de tablas tambi?n.
53
*
54
* Revision 1.5  2006/03/07 21:01:33  azabala
55
* *** empty log message ***
56
*
57
* Revision 1.4  2006/03/06 19:48:39  azabala
58
* *** empty log message ***
59
*
60
* Revision 1.3  2006/02/26 20:55:37  azabala
61
* *** empty log message ***
62
*
63
* Revision 1.2  2006/02/20 19:43:51  azabala
64
* *** empty log message ***
65
*
66
* Revision 1.1  2006/02/19 20:55:34  azabala
67
* *** empty log message ***
68
*
69
*
70
*/
71
package com.iver.gvsig.geoprocessing.impl.union;
72

    
73
import java.util.Map;
74

    
75
import com.iver.cit.gvsig.fmap.DriverException;
76
import com.iver.cit.gvsig.fmap.core.IFeature;
77
import com.iver.cit.gvsig.fmap.core.IGeometry;
78
import com.iver.cit.gvsig.fmap.drivers.DriverIOException;
79
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
80
import com.iver.cit.gvsig.fmap.edition.EditionException;
81
import com.iver.cit.gvsig.fmap.layers.FBitSet;
82
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
83
import com.iver.cit.gvsig.fmap.operations.CancellableMonitorable;
84
import com.iver.cit.gvsig.fmap.operations.DefaultCancellableMonitorable;
85
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
86
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
87
import com.iver.cit.gvsig.fmap.operations.strategies.VisitException;
88
import com.iver.gvsig.geoprocessing.impl.AbstractGeoprocess;
89
import com.iver.gvsig.geoprocessing.impl.difference.DifferenceVisitor;
90
import com.iver.gvsig.geoprocessing.impl.intersection.IntersectVisitor;
91
import com.iver.gvsig.geoprocessing.impl.jtsprocessors.DeferredFeaturePersisterProcessor;
92
import com.iver.gvsig.geoprocessing.impl.jtsprocessors.FeaturePersisterProcessor2;
93
import com.iver.gvsig.geoprocessing.model.GeoprocessException;
94
import com.iver.gvsig.geoprocessing.model.IOverlayGeoprocess;
95
import com.iver.gvsig.geoprocessing.schemabuilder.DefinitionUtils;
96
import com.iver.gvsig.geoprocessing.schemabuilder.XTypes;
97
import com.iver.utiles.swing.threads.IMonitorableTask;
98
/**
99
 * Union geoprocess is known like "spatial or" because is an overlay
100
 * geoprocess (it computes intersections between features of
101
 * two layers) formed for geometries of one layer or another.
102
 * <br>
103
 *  Algorithm makes these three passes:
104
 *  a) computing intersections and saves them in a temp file.
105
 *  b) computing differences with first layer.
106
 *  c) computing differences with second layer.
107
 * @author azabala
108
 *
109
 *TODO Is very similar to ClipGeoprocess. Build an overlay abstract class.
110
 *
111
 *
112
 */
113
public class UnionGeoprocess extends AbstractGeoprocess 
114
                                                        implements IOverlayGeoprocess {
115
        
116
        /**
117
         * overlay layer
118
         */
119
        private FLyrVect overlayLayer;
120
        
121
        /**
122
         * Schema of the result layer
123
         */
124
        private ILayerDefinition resultLayerDefinition;
125
        /**
126
         * flag to only clip selection of input layer
127
         */
128
        private boolean onlyFirstLayerSelection = false;
129
        /**
130
         * flag to only clip with selection of clipping layer
131
         */
132
        private boolean onlyClipLayerSelection = false;
133
        
134
        /**
135
         * Constructor 
136
         *
137
         */
138
        public UnionGeoprocess(FLyrVect inputLayer){
139
                setFirstOperand(inputLayer);
140
        }
141
        
142
        public void setSecondOperand(FLyrVect secondLayer) {
143
                this.overlayLayer = secondLayer;
144
        }
145

    
146
        public void setFirstOperand(FLyrVect firstLayer) {
147
                this.firstLayer = firstLayer;
148

    
149
        }
150

    
151
        public void setParameters(Map params) throws GeoprocessException {
152
                Boolean firstLayerSelection = (Boolean) params.get("firstlayerselection");
153
                if(firstLayerSelection != null)
154
                        this.onlyFirstLayerSelection = firstLayerSelection.booleanValue();
155
                
156
                Boolean secondLayerSelection = (Boolean) params.get("secondlayerselection");
157
                if(secondLayerSelection != null)
158
                        this.onlyClipLayerSelection = secondLayerSelection.booleanValue();
159

    
160
        }
161

    
162
        public void checkPreconditions() throws GeoprocessException {
163
                if (firstLayer == null)
164
                        throw new GeoprocessException("Union: capa de entrada a null");
165
                if (overlayLayer == null)
166
                        throw new GeoprocessException("Union: capa de union a null");
167
                if(this.writer == null || 
168
                   this.schemaManager == null){
169
                        throw new GeoprocessException("Operacion de union sin especificar capa de resultados");
170
                }
171
                try {
172
                        if(firstLayer.getShapeType() != XTypes.POLYGON){
173
                                throw new GeoprocessException("Primera capa de union no es de pol?gonos");
174
                        }
175
                        if(overlayLayer.getShapeType() != XTypes.POLYGON){
176
                                throw new GeoprocessException("Segunda capa de union no es de pol?gonos");
177
                        }
178
                } catch (com.iver.cit.gvsig.fmap.DriverException e) {
179
                        throw new GeoprocessException("Error al tratar de chequear si las capas a unir son de pol?gonos");
180
                }
181

    
182
        }
183
        
184
        /**
185
         * Runs execution of this geoprocess.
186
         */
187
        public void process() throws GeoprocessException {
188
                /*
189
                 * Lo vamos a hacer en tres pasadas:
190
                 * a) intersecciones con el geoproceso Intersection,
191
                 * guardando en el fichero del usuario.
192
                 * b) diferencias de first con overlay, guardando en el
193
                 * mismo fichero
194
                 * c) diferencias de overlay con first, guardando en el 
195
                 * mismo fichero
196
                 */
197
                try {
198
                        //FIXME Esto lo tenemos que hacer FUERA (en la GUI)
199
                        this.schemaManager.createOrAlterSchema(createLayerDefinition());
200
                        writer.preProcess();
201
                        
202
                        Strategy strategy = StrategyManager.getStrategy(firstLayer);
203
                        Strategy strategy2 = StrategyManager.getStrategy(overlayLayer);
204
                        FeaturePersisterProcessor2 featureProcessor =
205
                                new FeaturePersisterProcessor2(writer);
206
                        
207
                        IntersectVisitor visitor = new IntersectVisitor(overlayLayer, 
208
                                                                                                                featureProcessor,
209
                                                                                                                strategy2, 
210
                                                                                                                onlyClipLayerSelection);
211
                        strategy.process(visitor);
212
                        
213
                        //diferencias entre input y overlay
214
                        writer.preProcess();
215
                        DifferenceVisitor visitor2 = new DifferenceVisitor(overlayLayer,
216
                                        featureProcessor, strategy2, onlyClipLayerSelection);
217
                        strategy.process(visitor2);
218
                        
219
                        writer.preProcess();
220
                        DifferenceVisitor visitor3 = new DifferenceVisitor(this.firstLayer,
221
                                        featureProcessor, strategy, onlyFirstLayerSelection);
222
                        strategy2.process(visitor3);
223
                        
224
                } catch (EditionException e) {
225
                        throw new GeoprocessException("Error al crear el esquema/fichero de la nueva capa");
226
                } catch (DriverException e) {
227
                        throw new GeoprocessException("Error de driver al calcular el geoproceso interseccion");
228
                } catch (VisitException e) {
229
                        throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion");
230
                } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
231
                        // TODO Auto-generated catch block
232
                        e.printStackTrace();
233
                }
234
                
235
        }
236

    
237
        public void cancel() {
238
                // TODO Auto-generated method stub
239

    
240
        }
241

    
242
        public ILayerDefinition createLayerDefinition() {
243
                if(resultLayerDefinition == null){
244
                        try {
245
                                resultLayerDefinition = DefinitionUtils.
246
                                                mergeLayerDefinitions(firstLayer, overlayLayer);
247
                        } catch (Exception e) {
248
                                //TODO Quizas createLayerDefinition deberia lanzar
249
                                //una excepcion
250
                                e.printStackTrace();
251
                        }
252
                }
253
                return resultLayerDefinition;
254
        }
255

    
256
        
257
        
258
        public FBitSet getOverlays(IGeometry firstLayerGeometry, int index) {
259
                // TODO Auto-generated method stub
260
                return null;
261
        }
262

    
263
        public IFeature[] computeIntersection(IGeometry firsLayerGeometry, int firstLayerFeatureIndex, IGeometry secondLayerGeometry, int secondLayerFeatureIndex) {
264
                // TODO Auto-generated method stub
265
                return null;
266
        }
267

    
268
        public IMonitorableTask createTask() {
269
                try {
270
                        return new UnionMonitorableTask();
271
                } catch (DriverIOException e) {
272
                        return null;
273
                }
274
        }
275
        
276
        /**
277
         * IMonitorableTask that allows to run diff geoprocess in background,
278
         * with cancelation requests.
279
         * 
280
         * @author azabala
281
         * 
282
         * FIXME INTERNACIONALIZAR TODOS LOS TEXTOS
283
         * 
284
         */
285
        class UnionMonitorableTask implements IMonitorableTask {
286
                private CancellableMonitorable cancelMonitor = null;
287

    
288
                // FIXME INTERNACIONALIZAR ESTO
289
                String FIRST_PASS_MESSAGE = "Computing intersections: ";
290
                String SECOND_PASS_MESSAGE = "Computing A-B difference:";
291
                String THIRD_PASS_MESSAGE = "Computing B-A difference:";
292
                
293
                String currentMessage = "";
294
                private boolean finished = false;
295

    
296
                UnionMonitorableTask() throws DriverIOException {
297
                        initialize();
298
                }
299
                void initialize() throws DriverIOException {
300
                        cancelMonitor = createCancelMonitor();
301
                        currentMessage = "Initializing...";
302
                }
303

    
304
                private CancellableMonitorable createCancelMonitor()
305
                                throws DriverIOException {
306
                        DefaultCancellableMonitorable monitor = new 
307
                                                        DefaultCancellableMonitorable();
308
                        monitor.setInitialStep(0);
309
                        monitor.setDeterminatedProcess(true);
310
                        int numSteps = 0;
311
                        //num steps = 2 * firstlayer (intersect + diff A-B)
312
                        //+ second layer (diff B-A)
313
                        if (onlyFirstLayerSelection) {
314
                                FBitSet selection = firstLayer.getRecordset().getSelection();
315
                                numSteps += (2 * selection.cardinality());
316
                        } else {
317
                                numSteps += 2 * firstLayer.getSource().getShapeCount();
318
                        }
319
                        if(onlyClipLayerSelection) {
320
                                FBitSet selection = overlayLayer.getRecordset().getSelection();
321
                                numSteps += (2 * selection.cardinality());
322
                        }else{
323
                                numSteps += 2 * overlayLayer.getSource().getShapeCount();
324
                        }
325
                        monitor.setFinalStep(numSteps);
326
                        return monitor;
327
                }
328

    
329
                public int getInitialStep() {
330
                        return cancelMonitor.getInitialStep();
331
                }
332

    
333
                public int getFinishStep() {
334
                        return cancelMonitor.getFinalStep();
335
                }
336

    
337
                public int getCurrentStep() {
338
                        return cancelMonitor.getCurrentStep();
339
                }
340

    
341
                public String getStatusMessage() {
342
                        // FIXME Cambiar esto por un mecanismo de eventos,
343
                        // de forma que la tarea lo que tenga sea un escuchador
344
                        // que cambie el mensaje de estado segun los eventos
345
                        // de tareas que se est?n realizando
346
                        return "Union Geoprocess...";
347
                }
348

    
349
                public String getNote() {
350
                        // FIXME Cambiar esto por un mecanismo de eventos,
351
                        // de forma que la tarea lo que tenga sea un escuchador
352
                        // que cambie el mensaje de estado segun los eventos
353
                        // de tareas que se est?n realizando
354
                        return currentMessage + getCurrentStep() + " of " + getFinishStep();
355
                }
356

    
357
                public void cancel() {
358
                        ((DefaultCancellableMonitorable) cancelMonitor).setCanceled(true);
359
                }
360

    
361
                public void run() throws GeoprocessException {
362

    
363
                        try {
364
                                //FIXME Esto lo tenemos que hacer FUERA (en la GUI)
365
                                schemaManager.createOrAlterSchema(createLayerDefinition());
366
                                writer.preProcess();
367
                                
368
                                Strategy strategy = StrategyManager.getStrategy(firstLayer);
369
                                Strategy strategy2 = StrategyManager.getStrategy(overlayLayer);
370
                                DeferredFeaturePersisterProcessor featureProcessor =
371
                                        new DeferredFeaturePersisterProcessor(writer);
372
                                
373
                                IntersectVisitor visitor = new IntersectVisitor(overlayLayer, 
374
                                                                                                                        featureProcessor,
375
                                                                                                                        strategy2, 
376
                                                                                                                        onlyClipLayerSelection);
377
                                //FIXME Meter las selecciones
378
                                currentMessage = FIRST_PASS_MESSAGE;
379
                                if(onlyFirstLayerSelection){
380
                                        FBitSet selection = firstLayer.getRecordset().getSelection();
381
                                        strategy.process(visitor, selection, cancelMonitor);
382
                                }else{
383
                                        strategy.process(visitor, cancelMonitor);
384
                                }
385
                                
386
                                currentMessage = SECOND_PASS_MESSAGE;
387
                                DifferenceVisitor visitor2 = new DifferenceVisitor(overlayLayer,
388
                                                featureProcessor, strategy2, onlyClipLayerSelection);
389
                                if(onlyFirstLayerSelection){
390
                                        FBitSet selection = firstLayer.getRecordset().getSelection();
391
                                        strategy.process(visitor2, selection, cancelMonitor);
392
                                }else{
393
                                        strategy.process(visitor2, cancelMonitor);
394
                                }
395
                                currentMessage = THIRD_PASS_MESSAGE;
396
                                DifferenceVisitor visitor3 = new DifferenceVisitor(firstLayer,
397
                                                featureProcessor, strategy, onlyFirstLayerSelection);
398
                                if(onlyClipLayerSelection){
399
                                        FBitSet selection = overlayLayer.getRecordset().getSelection();
400
                                        strategy2.process(visitor3, selection, cancelMonitor);
401
                                }else{
402
                                        strategy2.process(visitor3, cancelMonitor);
403
                                }
404
                                writer.postProcess();
405
                                
406
                        } catch (EditionException e) {
407
                                throw new GeoprocessException("Error al crear el esquema/fichero de la nueva capa");
408
                        } catch (DriverException e) {
409
                                throw new GeoprocessException("Error de driver al calcular el geoproceso interseccion");
410
                        } catch (VisitException e) {
411
                                throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion");
412
                        } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
413
                                // TODO Auto-generated catch block
414
                                e.printStackTrace();
415
                        }finally{
416
                                finished = true;
417
                        }
418
                }
419

    
420
                public boolean isDefined() {
421
                        return cancelMonitor.isDeterminatedProcess();
422
                }
423

    
424
                public boolean isCanceled() {
425
                        return cancelMonitor.isCanceled();
426
                }
427

    
428
                public boolean isFinished() {
429
                        return finished;
430
                }
431
        }
432

    
433
}
434