Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extGeoprocessingExtensions / src / com / iver / cit / gvsig / geoprocess / impl / topology / lineclean / fmap / LineCleanVisitor.java @ 33358

History | View | Annotate | Download (27.8 KB)

1
/*
2
 * Created on 10-oct-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: LineCleanVisitor.java 13881 2007-09-19 16:22:04Z jaume $
47
 * $Log$
48
 * Revision 1.4  2007-09-19 16:09:14  jaume
49
 * removed unnecessary imports
50
 *
51
 * Revision 1.3  2007/07/12 11:10:24  azabala
52
 * bug 2617 solved (clean fails with multilinestring geometries)
53
 *
54
 * Revision 1.2  2007/03/06 16:48:14  caballero
55
 * Exceptions
56
 *
57
 * Revision 1.1  2006/12/21 17:23:27  azabala
58
 * *** empty log message ***
59
 *
60
 * Revision 1.1  2006/12/04 19:42:23  azabala
61
 * *** empty log message ***
62
 *
63
 * Revision 1.7  2006/11/14 18:34:16  azabala
64
 * *** empty log message ***
65
 *
66
 * Revision 1.6  2006/11/14 18:01:09  azabala
67
 * removed system.out.println
68
 *
69
 * Revision 1.5  2006/11/13 20:41:08  azabala
70
 * *** empty log message ***
71
 *
72
 * Revision 1.4  2006/10/19 16:06:48  azabala
73
 * *** empty log message ***
74
 *
75
 * Revision 1.3  2006/10/17 18:27:24  azabala
76
 * *** empty log message ***
77
 *
78
 * Revision 1.1  2006/10/10 18:50:17  azabala
79
 * First version in CVS
80
 *
81
 *
82
 */
83
package com.iver.cit.gvsig.geoprocess.impl.topology.lineclean.fmap;
84

    
85
import java.util.ArrayList;
86
import java.util.Arrays;
87
import java.util.Collections;
88
import java.util.Comparator;
89
import java.util.Iterator;
90

    
91
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
92
import com.hardcode.gdbms.engine.values.Value;
93
import com.hardcode.gdbms.engine.values.ValueFactory;
94
import com.iver.cit.gvsig.exceptions.visitors.ProcessVisitorException;
95
import com.iver.cit.gvsig.exceptions.visitors.StartVisitorException;
96
import com.iver.cit.gvsig.exceptions.visitors.StopWriterVisitorException;
97
import com.iver.cit.gvsig.exceptions.visitors.VisitorException;
98
import com.iver.cit.gvsig.fmap.core.IFeature;
99
import com.iver.cit.gvsig.fmap.core.IGeometry;
100
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
101
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
102
import com.iver.cit.gvsig.fmap.drivers.ILayerDefinition;
103
import com.iver.cit.gvsig.fmap.layers.FBitSet;
104
import com.iver.cit.gvsig.fmap.layers.FLayer;
105
import com.iver.cit.gvsig.fmap.layers.FLyrVect;
106
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
107
import com.iver.cit.gvsig.fmap.layers.layerOperations.AlphanumericData;
108
import com.iver.cit.gvsig.fmap.layers.layerOperations.VectorialData;
109
import com.iver.cit.gvsig.fmap.operations.strategies.FeatureVisitor;
110
import com.iver.cit.gvsig.fmap.operations.strategies.Strategy;
111
import com.iver.cit.gvsig.fmap.operations.strategies.StrategyManager;
112
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureFactory;
113
import com.iver.cit.gvsig.geoprocess.core.fmap.FeaturePersisterProcessor2;
114
import com.iver.cit.gvsig.geoprocess.core.fmap.FeatureProcessor;
115
import com.iver.cit.gvsig.geoprocess.core.fmap.XTypes;
116
import com.iver.cit.gvsig.util.SnappingCoordinateMap;
117
import com.vividsolutions.jts.geom.Coordinate;
118
import com.vividsolutions.jts.geom.Geometry;
119
import com.vividsolutions.jts.geom.GeometryCollection;
120
import com.vividsolutions.jts.geom.GeometryFactory;
121
import com.vividsolutions.jts.geom.LineString;
122
import com.vividsolutions.jts.geom.MultiLineString;
123
import com.vividsolutions.jts.geom.MultiPoint;
124
import com.vividsolutions.jts.geom.Point;
125
import com.vividsolutions.jts.geomgraph.Node;
126
import com.vividsolutions.jts.geomgraph.NodeFactory;
127
import com.vividsolutions.jts.geomgraph.SnappingNodeMap;
128
import com.vividsolutions.jts.linearref.LengthIndexedLine;
129
import com.vividsolutions.jts.linearref.LinearLocation;
130
import com.vividsolutions.jts.linearref.LocationIndexedLine;
131
import com.vividsolutions.jts.operation.overlay.SnappingOverlayOperation;
132

    
133
/**
134
 * <p>
135
 * This visitor operates with features whose geometries are lines. <br>
136
 * For each visited feature, it looks for features in its proximity (spatial
137
 * query). If these features hasnt been processed, it intersects the visited
138
 * feature with all of the neighbour features. If intersection points are not
139
 * nodes (end points), it ignores them. split the
140
 * </p>
141
 * 
142
 * @author azabala
143
 */
144
public class LineCleanVisitor implements FeatureVisitor {
145

    
146
        /**
147
         * Recordset of the layer we are working with
148
         */
149
        protected SelectableDataSource recordset;
150

    
151
        /**
152
         * Layer which we are cleaning
153
         */
154
        protected FLyrVect layerToClean;
155

    
156
        /**
157
         * marks if we are going to clean only layer selection
158
         */
159
        protected boolean cleanOnlySelection;
160

    
161
        /*
162
         * TODO Meter esto en preferencias
163
         */
164
        public final static double DEFAULT_SNAP = 0.1;
165

    
166
        protected double snapTolerance = DEFAULT_SNAP;
167

    
168
        /**
169
         * It marks all processed features (to ignore them in future intersections)
170
         */
171
        protected FBitSet processedFeatures;
172

    
173
        /**
174
         * Strategy of the layer we are working with.
175
         */
176
        protected Strategy strategy;
177

    
178
        /**
179
         * Saves features resulting of cleaning process
180
         */
181
        protected FeatureProcessor featureProcessor;
182

    
183
        protected ILayerDefinition layerDefinition;
184

    
185
        /**
186
         * Saves pseudonodes found
187
         */
188
        protected FeatureProcessor intersectProcessor;
189

    
190
        protected ILayerDefinition intersectDefinition;
191

    
192
        /**
193
         * Counter of new features
194
         */
195
        int fid = 0;
196

    
197
        /**
198
         * It caches all written pseudonodes, to avoid writing the same pseudonode
199
         * twice.
200
         * 
201
         */
202
        SnappingCoordinateMap snapCoordMap;
203

    
204
        /**
205
         * Constructor.
206
         * 
207
         * @param processor
208
         * @param intersectsProcessor
209
         * @param cleanOnlySelection
210
         * @param layerDefinition
211
         * @param intersectDefinition
212
         * @param firstLayer
213
         * @param source
214
         * @param snapCoordMap
215
         */
216
        public LineCleanVisitor(FeatureProcessor processor,
217
                        FeaturePersisterProcessor2 intersectsProcessor,
218
                        boolean cleanOnlySelection, ILayerDefinition layerDefinition,
219
                        ILayerDefinition intersectDefinition, FLyrVect firstLayer,
220
                        SelectableDataSource source, SnappingCoordinateMap snapCoordMap) {
221
                this.featureProcessor = processor;
222
                this.cleanOnlySelection = cleanOnlySelection;
223
                processedFeatures = new FBitSet();
224
                this.layerDefinition = layerDefinition;
225
                this.intersectProcessor = intersectsProcessor;
226
                this.intersectDefinition = intersectDefinition;
227
                this.layerToClean = firstLayer;
228
                this.recordset = source;
229
                this.strategy = StrategyManager.getStrategy(layerToClean);
230
                this.snapCoordMap = snapCoordMap;
231
        }
232

    
233
        public void setLayerDefinition(ILayerDefinition layerDefinition) {
234
                this.layerDefinition = layerDefinition;
235
        }
236

    
237
        private boolean checkForLineGeometry(Geometry geometry) {
238
                if (geometry instanceof LineString)
239
                        return true;
240
                if (geometry instanceof MultiLineString)
241
                        return true;
242
                if (geometry instanceof GeometryCollection) {
243
                        GeometryCollection col = (GeometryCollection) geometry;
244
                        for (int i = 0; i < col.getNumGeometries(); i++) {
245
                                if (!checkForLineGeometry(col.getGeometryN(i)))
246
                                        return false;
247
                        }
248
                        return true;
249
                }
250
                return false;
251
        }
252

    
253
        public void visit(IGeometry g, final int index) throws VisitorException,
254
                        StopWriterVisitorException, ProcessVisitorException {
255
                // first, we check it isnt a null geometry and the geometry type
256
                // is correct
257
                if (g == null)
258
                        return;
259
                int geometryType = g.getGeometryType();
260
                if (geometryType != XTypes.ARC && geometryType != XTypes.LINE
261
                                && geometryType != XTypes.MULTI)
262
                        return;
263

    
264
                // after that, if we are going to clean only selected features, we
265
                // check if this feature is selected
266
                if (cleanOnlySelection) {
267
                        try {
268
                                if (!layerToClean.getRecordset().getSelection().get(index))
269
                                        return;
270
                        } catch (ReadDriverException e) {
271
                                throw new ProcessVisitorException(recordset.getName(), e,
272
                                                "Error verificando seleccion en CLEAN");
273
                        }
274
                }// if cleanOnly
275

    
276
                final Geometry jtsGeo = g.toJTSGeometry();
277

    
278
                // we check if jts geometry is a line (or a line collection)
279
                if (!checkForLineGeometry(jtsGeo))
280
                        return;
281

    
282
                final SnappingNodeMap nodes = new SnappingNodeMap(new NodeFactory(),
283
                                snapTolerance);
284
                /*
285
                 * Se nos plantea una problematica. Tenemos dos features: A y B, y he
286
                 * calculado la interseccion de A y B. Ahora, hay dos alternativas: -a)
287
                 * nunca mas calcular esta intersecci?n, pero almacenar su resultado en
288
                 * SnappingNodeMap. As?, en una segunda pasada, con todos los "Nodos"
289
                 * calculados, podr?amos fragmentar las lineas de forma individual.
290
                 * PROBLEMA: SnappingNodeMap ir?a creciendo, almacenando todos los nodos
291
                 * de una capa....(si se apoya sobre un IndexedShpDriver, no tendr?a por
292
                 * qu?)
293
                 * 
294
                 * 
295
                 * -b) Calcular la intersecci?n en los dos sentidos: A int B, y luego al
296
                 * procesar B, B int A. En este caso, pasamos ol?mpicamente del bitset
297
                 * 
298
                 * De momento, por simplicidad, seguimos la alternativa -b)
299
                 */
300

    
301
                final boolean onlySelection = cleanOnlySelection;
302
                try {
303
                        strategy.process(new FeatureVisitor() {
304

    
305
                                SnappingOverlayOperation overlayOp = null;
306

    
307
                                /**
308
                                 * From a given geometry, it returns its nodes (coordinate for a
309
                                 * point, extreme coordinates for a line, first coordinate for a
310
                                 * polygon)
311
                                 */
312
                                private Coordinate[] getNodesFor(Geometry processedGeometry) {
313
                                        Coordinate[] geomNodes = null;
314
                                        if (processedGeometry instanceof LineString) {
315
                                                LineString line = (LineString) processedGeometry;
316
                                                geomNodes = new Coordinate[2];
317
                                                geomNodes[0] = line.getCoordinateN(0);
318
                                                geomNodes[1] = line
319
                                                                .getCoordinateN(line.getNumPoints() - 1);
320
                                        } else if (processedGeometry instanceof MultiLineString) {
321
                                                MultiLineString lines = (MultiLineString) processedGeometry;
322
                                                int numLines = lines.getNumGeometries();
323
                                                geomNodes = new Coordinate[2 * numLines];
324
                                                int index = 0;
325
                                                for (int i = 0; i < numLines; i++) {
326
                                                        LineString line = (LineString) lines
327
                                                                        .getGeometryN(i);
328
                                                        geomNodes[index] = line.getCoordinateN(0);
329
                                                        index++;
330
                                                        geomNodes[index] = line.getCoordinateN(line
331
                                                                        .getNumPoints() - 1);
332
                                                        index++;
333
                                                }
334
                                        } else if (processedGeometry instanceof GeometryCollection) {
335
                                                GeometryCollection col = (GeometryCollection) processedGeometry;
336
                                                ArrayList coordinates = new ArrayList();
337
                                                for (int i = 0; i < col.getNumGeometries(); i++) {
338
                                                        Geometry geom = col.getGeometryN(i);
339
                                                        Coordinate[] newNodes = getNodesFor(geom);
340
                                                        coordinates.addAll(Arrays.asList(newNodes));
341
                                                }
342
                                        }
343
                                        // else {
344
                                        // System.out
345
                                        // .println("Este proceso solo debe trabajar con lineas");
346
                                        // System.out.println(processedGeometry.getGeometryType());
347
                                        // }
348
                                        return geomNodes;
349
                                }
350

    
351
                                /**
352
                                 * Checks if a coordinate is on a node of a given set of nodes
353
                                 * 
354
                                 * @param coord
355
                                 * @param nodes
356
                                 * @return
357
                                 */
358
                                private boolean checkIsNode(Coordinate coord, Coordinate[] nodes) {
359
                                        for (int i = 0; i < nodes.length; i++) {
360
                                                if (coord.distance(nodes[i]) <= snapTolerance)
361
                                                        return true;
362
                                        }
363
                                        return false;
364
                                }
365

    
366
                                /**
367
                                 * From a given geometry, and the intersection of this geometry
368
                                 * with another geometry, it creates a new node with these
369
                                 * intersections if its points are not coincident with the nodes
370
                                 * of the original goemetry.
371
                                 * 
372
                                 * @throws VisitorException
373
                                 * 
374
                                 */
375
                                private void processIntersections(
376
                                                com.vividsolutions.jts.geomgraph.SnappingNodeMap nodes,
377
                                                Geometry processedGeometry, Geometry intersections,
378
                                                int fid1, int fid2) throws VisitorException {
379

    
380
                                        Coordinate[] geomNodes = getNodesFor(processedGeometry);
381
                                        if (intersections instanceof Point) {
382
                                                Point p = (Point) intersections;
383
                                                Coordinate coord = p.getCoordinate();
384
                                                if (!checkIsNode(coord, geomNodes)) {
385
                                                        nodes.addNode(coord);
386

    
387
                                                        /*
388
                                                         * We are computing intersections twice: A
389
                                                         * intersection B and B intersection A. This is
390
                                                         * simpler than manage caches. With this logic, we
391
                                                         * avoid to write the same pseudonode twice
392
                                                         * 
393
                                                         */
394
                                                        if (snapCoordMap.containsKey(coord))
395
                                                                return;
396
                                                        else {
397
                                                                snapCoordMap.put(coord, coord);
398
                                                                IFeature feature = createIntersectFeature(
399
                                                                                coord, fid1, fid2);
400
                                                                intersectProcessor.processFeature(feature);
401
                                                        }
402
                                                }
403
                                        } else if (intersections instanceof MultiPoint) {
404
                                                MultiPoint points = (MultiPoint) intersections;
405
                                                for (int i = 0; i < points.getNumGeometries(); i++) {
406
                                                        Coordinate coord = ((Point) points.getGeometryN(i))
407
                                                                        .getCoordinate();
408
                                                        if (!checkIsNode(coord, geomNodes)) {
409
                                                                nodes.addNode(coord);
410
                                                                if (snapCoordMap.containsKey(coord))
411
                                                                        return;
412
                                                                else {
413
                                                                        snapCoordMap.put(coord, coord);
414
                                                                        IFeature feature = createIntersectFeature(
415
                                                                                        coord, fid1, fid2);
416
                                                                        intersectProcessor.processFeature(feature);
417
                                                                }
418
                                                        }
419
                                                }
420
                                        } else if (intersections instanceof LineString) {
421
                                                LineString line = (LineString) intersections;
422
                                                int numPoints = line.getCoordinates().length;
423
                                                Coordinate coord1 = line.getCoordinateN(0);
424
                                                Coordinate coord2 = line.getCoordinateN(numPoints - 1);
425
                                                if (!checkIsNode(coord1, geomNodes)) {
426
                                                        nodes.addNode(coord1);
427
                                                        if (snapCoordMap.containsKey(coord1))
428
                                                                return;
429
                                                        else {
430
                                                                snapCoordMap.put(coord1, coord1);
431
                                                                IFeature feature = createIntersectFeature(
432
                                                                                coord1, fid1, fid2);
433
                                                                intersectProcessor.processFeature(feature);
434
                                                        }
435
                                                }
436
                                                if (!checkIsNode(coord2, geomNodes)) {
437
                                                        nodes.addNode(coord2);
438
                                                        if (snapCoordMap.containsKey(coord2))
439
                                                                return;
440
                                                        else {
441
                                                                snapCoordMap.put(coord2, coord2);
442
                                                                IFeature feature = createIntersectFeature(
443
                                                                                coord2, fid1, fid2);
444
                                                                intersectProcessor.processFeature(feature);
445
                                                        }
446
                                                }
447
                                        } else if (intersections instanceof GeometryCollection) {
448
                                                GeometryCollection col = (GeometryCollection) intersections;
449
                                                for (int i = 0; i < col.getNumGeometries(); i++) {
450

    
451
                                                        // El tema est? en que aqu? el calculo de los nodos
452
                                                        // de la geometria intersectada se repite cada vez
453
                                                        // revisar, pues MultiLineString puede ser un
454
                                                        // resultado habitual
455
                                                        processIntersections(nodes, processedGeometry, col
456
                                                                        .getGeometryN(i), fid1, fid2);
457
                                                }
458
                                        }
459
                                        // else if (intersections instanceof Polygon) {
460
                                        // System.out
461
                                        // .println("Un poligono interseccion de 2 lineas???");
462
                                        // }// else
463

    
464
                                }
465

    
466
                                public void visit(IGeometry g2, int indexOverlay)
467
                                                throws VisitorException, StopWriterVisitorException,
468
                                                ProcessVisitorException {
469

    
470
                                        if (g2 == null)
471
                                                return;
472

    
473
                                        if (index == indexOverlay)
474
                                                return;
475

    
476
                                        if (onlySelection) {
477
                                                try {
478
                                                        if (!layerToClean.getRecordset().getSelection()
479
                                                                        .get(indexOverlay))
480
                                                                return;
481
                                                } catch (ReadDriverException e) {
482
                                                        throw new ProcessVisitorException(recordset
483
                                                                        .getName(), e,
484
                                                                        "Error verificando seleccion en clean");
485
                                                }// geometry g is not selected
486
                                        }// if onlySelection
487

    
488
                                        int geometryType = g2.getGeometryType();
489
                                        if (geometryType != XTypes.ARC
490
                                                        && geometryType != XTypes.LINE
491
                                                        && geometryType != XTypes.MULTI)
492
                                                return;
493

    
494
                                        /*
495
                                         * TODO De momento no vamos a tener en cuenta que la
496
                                         * interseccion ya ha sido calculada... (Ver comentario al
497
                                         * instanciar SnappingNodeMap) // ya ha sido tratado
498
                                         * if(processedFeatures.get(indexOverlay)) return;
499
                                         */
500
                                        Geometry jtsGeo2 = g2.toJTSGeometry();
501
                                        if (!checkForLineGeometry(jtsGeo2))
502
                                                return;
503

    
504
                                        if (overlayOp == null)
505
                                                overlayOp = new SnappingOverlayOperation(jtsGeo,
506
                                                                jtsGeo2, snapTolerance);
507
                                        else {
508
                                                overlayOp.setSecondGeometry(jtsGeo2);
509
                                        }
510

    
511
                                        Geometry intersections = overlayOp
512
                                                        .getResultGeometry(SnappingOverlayOperation.INTERSECTION);
513

    
514
                                        processIntersections(nodes, jtsGeo, intersections, index,
515
                                                        indexOverlay);
516

    
517
                                        // IFeature cleanedFeature;
518
                                        // try {
519
                                        // cleanedFeature = createFeature(newGeoJts,
520
                                        // index, indexOverlay);
521
                                        // } catch (DriverException e) {
522
                                        // throw new VisitException(
523
                                        // "Error al crear el feature resultante del CLEAN");
524
                                        // }
525
                                        // featureProcessor.processFeature(cleanedFeature);
526

    
527
                                }
528

    
529
                                public String getProcessDescription() {
530
                                        return "Computing intersections of a polygon with its adjacents";
531
                                }
532

    
533
                                public void stop(FLayer layer)
534
                                                throws StopWriterVisitorException, VisitorException {
535
                                }
536

    
537
                                public boolean start(FLayer layer) throws StartVisitorException {
538
                                        return true;
539
                                }
540
                        }, g.getBounds2D());
541
                        // At this point, nodes variable (SnappingNodeMap)
542
                        // has all intersections of the visited feature with the rest of
543
                        // features of the layer
544

    
545
                        // It computes linear distance of a point on the given jtsGeo linear
546
                        // geometry
547
                        boolean rightGeometry = true;
548
                        if (nodes.values().size() > 0) {
549
                                
550
                                LengthIndexedLine lengthLine = new LengthIndexedLine(jtsGeo);
551
                                Iterator nodesIt = nodes.iterator();
552
                                ArrayList nodeIntersections = new ArrayList();
553
                                while (nodesIt.hasNext()) {
554
                                        Node node = (Node) nodesIt.next();
555
                                        Coordinate coord = node.getCoordinate();
556
                                        double lengthOfNode = lengthLine.indexOf(coord);
557
                                        LineIntersection inters = new LineIntersection();
558
                                        inters.coordinate = coord;
559
                                        inters.lenght = lengthOfNode;
560
                                        nodeIntersections.add(inters);
561
                                }
562
                                
563
                                if (nodeIntersections.size() > 0) {
564
                                        // We sort the intersections by distance along the line
565
                                        // (dynamic
566
                                        // segmentation)
567
                                        rightGeometry = false;
568
                                        Collections.sort(nodeIntersections, new Comparator() {
569
                                                public int compare(Object arg0, Object arg1) {
570
                                                        LineIntersection l1 = (LineIntersection) arg0;
571
                                                        LineIntersection l2 = (LineIntersection) arg1;
572
                                                        if (l1.lenght > l2.lenght)
573
                                                                return 1;
574
                                                        else if (l1.lenght < l2.lenght)
575
                                                                return -1;
576
                                                        else
577
                                                                return 0;
578
                                                }
579
                                        });
580

    
581
                                        LinearLocation lastLocation = null;
582
                                        LineIntersection lastIntersection = null;
583
                                        LocationIndexedLine indexedLine = new LocationIndexedLine(
584
                                                        jtsGeo);
585
                                        for (int i = 0; i < nodeIntersections.size(); i++) {
586
                                                Geometry solution = null;
587
                                                LineIntersection li = (LineIntersection) nodeIntersections
588
                                                                .get(i);
589

    
590
                                                LinearLocation location = indexedLine
591
                                                                .indexOf(li.coordinate);// es posible que esto
592
                                                                                                                // est? mal por no
593
                                                                                                                // pasarle una longitud.
594
                                                                                                                // REVISAR
595
                                                if (lastLocation == null) {
596
                                                        LinearLocation from = new LinearLocation(0, 0d);
597
                                                        
598
//                                                        solution = splitLineString(jtsGeo, from, location,
599
//                                                                        null, li);
600
//                                                        
601
                                                        
602
                                                        solution = indexedLine.extractLine(from, location);
603
                                                        
604
                                                        
605
                                                        lastLocation = location;
606
                                                        lastIntersection = li;
607
                                                        /*
608
                                                         * Construimos una linea desde el primer punto hasta
609
                                                         * el punto contenido en LineIntersection, con todos
610
                                                         * los puntos intermedios de la linea.
611
                                                         * 
612
                                                         * 
613
                                                         * 
614
                                                         */
615
                                                } else {
616
                                                        // Construimos una linea entre lastIntersection y la
617
                                                        // intersection
618
                                                        // actual
619
                                                        LinearLocation locationFrom = lastLocation;
620
                                                        
621
//                                                        solution = splitLineString(jtsGeo, locationFrom,
622
//                                                                        location, lastIntersection, li);
623
                                                        
624
                                                        solution = indexedLine.extractLine(locationFrom, location);
625
                                                        lastLocation = location;
626
                                                        lastIntersection = li;
627

    
628
                                                }
629

    
630
                                                IFeature feature = createFeature(solution, index);
631
                                                featureProcessor.processFeature(feature);
632
                                                // TODO Podriamos guardar los puntos de interseccion
633
                                                // para
634
                                                // mostrar al usuario que puntos eran pseudonodos
635
                                        }// for
636

    
637
                                        // a?adimos el ultimo segmento
638
//                                        Coordinate[] geomCoords = jtsGeo.getCoordinates();
639
//                                        ArrayList coordinates = new ArrayList();
640
//                                        coordinates.add(lastIntersection.coordinate);
641
//                                        int startIndex = lastLocation.getSegmentIndex() + 1;
642
//                                        for (int i = startIndex; i < geomCoords.length; i++) {
643
//                                                coordinates.add(geomCoords[i]);
644
//                                        }
645
//                                        Coordinate[] solutionCoords = new Coordinate[coordinates
646
//                                                        .size()];
647
//                                        coordinates.toArray(solutionCoords);
648
//                                        IFeature lastFeature = createFeature(new GeometryFactory()
649
//                                                        .createLineString(solutionCoords), index);
650
                                        LinearLocation endLocation = new LinearLocation();
651
                                        endLocation.setToEnd(jtsGeo);
652
                                        Geometry geo = indexedLine.extractLine(lastLocation, endLocation);
653
                                        IFeature lastFeature = createFeature(geo, index);
654
                                        featureProcessor.processFeature(lastFeature);
655

    
656
                                }
657
                        } 
658
                        if(rightGeometry){
659
                                IFeature feature = createFeature(g, index);
660
                                featureProcessor.processFeature(feature);
661
                        }
662
                        
663

    
664
                } catch (ReadDriverException e) {
665
                        throw new ProcessVisitorException(recordset.getName(), e,
666
                                        "Error buscando los overlays que intersectan con un feature");
667
                } 
668
        }
669
        
670
        
671
        
672
        
673
        
674
        
675
        
676
//Dada una linea, una localizacion de partida (from), una localizaci?n de llegada (to), y dos puntos de interseccion (from) devuelve la linea entre from y to
677
        private Geometry splitLineString(Geometry linearGeometry,
678
                        LinearLocation from, LinearLocation to, LineIntersection fromInt,
679
                        LineIntersection toInt) {
680
                Coordinate[] geomCoords = linearGeometry.getCoordinates();
681
                ArrayList coordinates = new ArrayList();
682
                if (fromInt != null)
683
                        coordinates.add(fromInt.coordinate);
684
                int startIndex = from.getSegmentIndex();
685
                /*
686
                 * segmentIndex siempre referencia al punto inmediatamente anterior del
687
                 * lineString. Nos interesa sumar 1, a no ser que sea el primer punto
688
                 * del linestring
689
                 */
690
                if (startIndex != 0)
691
                        startIndex++;
692

    
693
                for (int i = startIndex; i <= to.getSegmentIndex(); i++) {
694
                        coordinates.add(geomCoords[i]);
695
                }
696
                coordinates.add(toInt.coordinate);
697
                Coordinate[] solutionCoords = new Coordinate[coordinates.size()];
698
                coordinates.toArray(solutionCoords);
699
                return new GeometryFactory().createLineString(solutionCoords);
700

    
701
        }
702

    
703
        class LineIntersection {
704
                Coordinate coordinate;
705

    
706
                double lenght;
707
        }
708

    
709
        public String getProcessDescription() {
710
                return "Cleaning lines of a vectorial line layer";
711
        }
712

    
713
        public void stop(FLayer layer) throws StopWriterVisitorException,
714
                        VisitorException {
715
                this.featureProcessor.finish();
716
                this.intersectProcessor.finish();
717
        }
718

    
719
        public boolean start(FLayer layer) throws StartVisitorException {
720
                if (layer instanceof AlphanumericData && layer instanceof VectorialData) {
721
                        try {
722
                                layerToClean = (FLyrVect) layer;
723
                                recordset = ((AlphanumericData) layer).getRecordset();
724
                                strategy = StrategyManager.getStrategy(layerToClean);
725
                                featureProcessor.start();
726
                                intersectProcessor.start();
727
                        } catch (ReadDriverException e) {
728
                                return false;
729
                        }
730
                        return true;
731
                }
732
                return false;
733
        }
734

    
735
        private IFeature createFeature(Geometry jtsGeometry, int firstLayerIndex)
736
                        throws ReadDriverException {
737
                IFeature solution = null;
738
                IGeometry cleanedGeometry = FConverter.jts_to_igeometry(jtsGeometry);
739
                FieldDescription[] fields = layerDefinition.getFieldsDesc();
740
                int numFields = fields.length;
741
                Value[] featureAttr = new Value[fields.length];
742
                for (int indexField = 0; indexField < numFields; indexField++) {
743
                        // for each field of firstRs
744
                        String fieldName = recordset.getFieldName(indexField);
745
                        for (int j = 0; j < fields.length; j++) {
746
                                if (fieldName.equalsIgnoreCase(fields[j].getFieldName())) {
747
                                        featureAttr[j] = recordset.getFieldValue(firstLayerIndex,
748
                                                        indexField);
749
                                        break;
750
                                }// if
751
                        }// for
752
                }// for
753
                // now we put null values
754
                for (int i = 0; i < featureAttr.length; i++) {
755
                        if (featureAttr[i] == null)
756
                                featureAttr[i] = ValueFactory.createNullValue();
757
                }
758
                solution = FeatureFactory.createFeature(featureAttr, cleanedGeometry);
759
                return solution;
760
        }
761

    
762
        private IFeature createIntersectFeature(Coordinate coord, int fid1, int fid2) {
763
                IFeature solution = null;
764
                Point point = FConverter.geomFactory.createPoint(coord);
765
                IGeometry cleanedGeometry = FConverter.jts_to_igeometry(point);
766
                Value[] values = new Value[2];
767
                values[0] = ValueFactory.createValue(fid1);
768
                values[1] = ValueFactory.createValue(fid2);
769
                solution = FeatureFactory.createFeature(values, cleanedGeometry);
770
                return solution;
771
        }
772

    
773
        private IFeature createFeature(IGeometry g, int firstLayerIndex)
774
                        throws ReadDriverException {
775
                IFeature solution = null;
776
                FieldDescription[] fields = layerDefinition.getFieldsDesc();
777
                int numFields = fields.length;
778
                Value[] featureAttr = new Value[fields.length];
779
                for (int indexField = 0; indexField < numFields; indexField++) {
780
                        // for each field of firstRs
781
                        String fieldName = recordset.getFieldName(indexField);
782
                        for (int j = 0; j < fields.length; j++) {
783
                                if (fieldName.equalsIgnoreCase(fields[j].getFieldName())) {
784
                                        featureAttr[j] = recordset.getFieldValue(firstLayerIndex,
785
                                                        indexField);
786
                                        break;
787
                                }// if
788
                        }// for
789
                }// for
790
                // now we put null values
791
                for (int i = 0; i < featureAttr.length; i++) {
792
                        if (featureAttr[i] == null)
793
                                featureAttr[i] = ValueFactory.createNullValue();
794
                }
795
                solution = FeatureFactory.createFeature(featureAttr, g);
796
                return solution;
797
        }
798

    
799
        // public static void main(String[] args) {
800
        // DriverManager dm = new DriverManager();
801
        // dm.setValidation(new DriverValidation() {
802
        // public boolean validate(Driver d) {
803
        // return ((d instanceof ObjectDriver)
804
        // || (d instanceof FileDriver) || (d instanceof DBDriver));
805
        // }
806
        // });
807
        // dm.loadDrivers(new File(
808
        // "../_fwAndami/gvSIG/extensiones/com.iver.cit.gvsig/drivers"));
809
        // LayerFactory
810
        // .setDriversPath("../_fwAndami/gvSIG/extensiones/com.iver.cit.gvsig/drivers");
811
        //
812
        // // Setup del factory de DataSources
813
        // DataSourceFactory dsf = LayerFactory.getDataSourceFactory();
814
        // dsf.setDriverManager(dm);
815
        //
816
        // // Setup de las tablas
817
        // // dsf.addFileDataSource("gdbms dbf driver", "nodes", "c:/nodes.dbf");
818
        // // dsf.addFileDataSource("gdbms dbf driver", "edges", "c:/edges.dbf");
819
        //
820
        // IProjection prj = CRSFactory.getCRS("EPSG:23030");
821
        // File shpFile = new File("C:/JUMP/datos/cauces_gv.shp");
822
        // try {
823
        // FLyrVect lyr = (FLyrVect) LayerFactory.createLayer("Ejes",
824
        // "gvSIG shp driver", shpFile, prj);
825
        // System.out.println(lyr.getSource().getShapeCount());
826
        //
827
        // LayerDefinition definition = new LayerDefinition();
828
        // FieldDescription cauNom = new FieldDescription();
829
        // cauNom.setFieldName("CAUNOM");
830
        // cauNom.setFieldType(XTypes.CHAR);
831
        // cauNom.setFieldLength(10);
832
        // cauNom.setFieldDecimalCount(0);
833
        // definition.setFieldsDesc(new FieldDescription[]{cauNom});
834
        // definition.setShapeType(XTypes.LINE);
835
        //
836
        //
837
        //
838
        //
839
        // // LineCleanVisitor visitor = new LineCleanVisitor(
840
        // // new FeatureProcessor() {
841
        // //
842
        // // public void processFeature(IRow feature) {
843
        // // // TODO Auto-generated method stub
844
        // //
845
        // // }
846
        // //
847
        // // public void finish() {
848
        // // // TODO Auto-generated method stub
849
        // //
850
        // // }
851
        // //
852
        // // public void start() throws EditionException {
853
        // // // TODO Auto-generated method stub
854
        // //
855
        // // }
856
        // // }, false, definition);
857
        // Strategy str = StrategyManager.getStrategy(lyr);
858
        // // str.process(visitor);
859
        //
860
        // // } catch (com.iver.cit.gvsig.fmap.DriverException e) {
861
        // // // TODO Auto-generated catch block
862
        // // e.printStackTrace();
863
        // // } catch (DriverIOException e) {
864
        // // // TODO Auto-generated catch block
865
        // // e.printStackTrace();
866
        // // } catch (VisitException e) {
867
        // // // TODO Auto-generated catch block
868
        // // e.printStackTrace();
869
        // // }
870
        // }
871

    
872
}