Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGeoProcessing / src / com / iver / cit / gvsig / geoprocess / impl / union / fmap / UnionGeoprocess.java @ 13874

History | View | Annotate | Download (13.4 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 13874 2007-09-19 16:12:18Z jaume $
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.expansionfile.ExpansionFileReadException;
118
import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException;
119
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
120
import com.iver.cit.gvsig.fmap.core.FShape;
121
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
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
                                schemaManager.createSchema(createLayerDefinition());
359
                                writer.preProcess();
360

    
361
                                Strategy strategy = StrategyManager.getStrategy(firstLayer);
362
                                Strategy strategy2 = StrategyManager.getStrategy(overlayLayer);
363
                                DeferredFeaturePersisterProcessor featureProcessor =
364
                                        new DeferredFeaturePersisterProcessor(writer);
365

    
366
                                IntersectVisitor visitor = new IntersectVisitor(overlayLayer,
367
                                                                                                                        featureProcessor,
368
                                                                                                                        strategy2,
369
                                                                                                                        onlyClipLayerSelection);
370
                                //FIXME Meter las selecciones
371
                                currentMessage = FIRST_PASS_NOTE;
372
                                if(onlyFirstLayerSelection){
373
                                        FBitSet selection = firstLayer.getRecordset().getSelection();
374
                                        strategy.process(visitor, selection, cancelMonitor);
375
                                }else{
376
                                        strategy.process(visitor, cancelMonitor);
377
                                }
378

    
379
                                currentMessage = SECOND_PASS_NOTE;
380
                                DifferenceVisitor visitor2 = new DifferenceVisitor(overlayLayer,
381
                                                featureProcessor, strategy2, onlyClipLayerSelection);
382
                                visitor2.setLayerDefinition(resultLayerDefinition);
383
                                if(onlyFirstLayerSelection){
384
                                        FBitSet selection = firstLayer.getRecordset().getSelection();
385
                                        strategy.process(visitor2, selection, cancelMonitor);
386
                                }else{
387
                                        strategy.process(visitor2, cancelMonitor);
388
                                }
389
                                currentMessage = THIRD_PASS_NOTE;
390
                                DifferenceVisitor visitor3 = new DifferenceVisitor(firstLayer,
391
                                                featureProcessor, strategy, onlyFirstLayerSelection);
392
                                visitor3.setLayerDefinition(resultLayerDefinition);
393
                                if(onlyClipLayerSelection){
394
                                        FBitSet selection = overlayLayer.getRecordset().getSelection();
395
                                        strategy2.process(visitor3, selection, cancelMonitor);
396
                                }else{
397
                                        strategy2.process(visitor3, cancelMonitor);
398
                                }
399
                                writer.postProcess();
400

    
401
                        } catch (SchemaEditionException e) {
402
                                throw new GeoprocessException("Error al crear el esquema/fichero de la nueva capa");
403
                        } catch (ReadDriverException e) {
404
                                throw new GeoprocessException("Error de driver al calcular el geoproceso interseccion");
405
                        } catch (ProcessVisitorException e) {
406
                                throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion");
407
                        } catch (VisitorException e) {
408
                                throw new GeoprocessException("Error al procesar el feature de una capa durante el geoproceso interseccion");
409
                        } finally{
410
                                finished = true;
411
                        }
412
                }
413

    
414
                public boolean isDefined() {
415
                        return cancelMonitor.isDeterminatedProcess();
416
                }
417

    
418
                public boolean isCanceled() {
419
                        return cancelMonitor.isCanceled();
420
                }
421

    
422
                public boolean isFinished() {
423
                        return finished;
424
                }
425
                /* (non-Javadoc)
426
                 * @see com.iver.utiles.swing.threads.IMonitorableTask#finished()
427
                 */
428
                public void finished() {
429
                        // TODO Auto-generated method stub
430
                        
431
                }
432
        }
433

    
434
}
435