Statistics
| Revision:

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