Statistics
| Revision:

root / trunk / libraries / libFMap / src / com / iver / cit / gvsig / fmap / core / v02 / FConverter.java @ 1005

History | View | Annotate | Download (17 KB)

1
/*
2
 * Created on 08-jun-2004
3
 *
4
 * TODO To change the template for this generated file go to
5
 * Window - Preferences - Java - Code Generation - Code and Comments
6
 */
7
package com.iver.cit.gvsig.fmap.core.v02;
8

    
9
import com.iver.cit.gvsig.fmap.core.FPoint2D;
10
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
11
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
12
import com.iver.cit.gvsig.fmap.core.FShape;
13
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
14

    
15
import com.vividsolutions.jts.algorithm.CGAlgorithms;
16
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
17
import com.vividsolutions.jts.geom.Coordinate;
18
import com.vividsolutions.jts.geom.CoordinateArrays;
19
import com.vividsolutions.jts.geom.Envelope;
20
import com.vividsolutions.jts.geom.Geometry;
21
import com.vividsolutions.jts.geom.GeometryCollection;
22
import com.vividsolutions.jts.geom.GeometryFactory;
23
import com.vividsolutions.jts.geom.LineString;
24
import com.vividsolutions.jts.geom.LinearRing;
25
import com.vividsolutions.jts.geom.MultiLineString;
26
import com.vividsolutions.jts.geom.MultiPolygon;
27
import com.vividsolutions.jts.geom.Point;
28
import com.vividsolutions.jts.geom.Polygon;
29

    
30
import java.awt.geom.AffineTransform;
31
import java.awt.geom.NoninvertibleTransformException;
32
import java.awt.geom.PathIterator;
33
import java.awt.geom.Point2D;
34

    
35
import java.lang.reflect.Array;
36

    
37
import java.util.ArrayList;
38

    
39

    
40
/**
41
 * Clase con varios m?todos est?ticos utilizados para pasar de java2d a jts y
42
 * viceversa.
43
 *
44
 * @author fjp
45
 */
46
public class FConverter {
47
        /**
48
         * ?QU? PODEMOS HACER CON LOS MULTIPOINT??? => DEBER?AMOS TRABAJAR CON UN
49
         * ARRAY DE PUNTOS EN FShape.....Pensarlo bien.
50
         */
51
        private final static GeometryFactory geomFactory = new GeometryFactory();
52
        protected static CGAlgorithms cga = new RobustCGAlgorithms();
53
        private final static AffineTransform at = new AffineTransform();
54
        private static double POINT_MARKER_SIZE = 3.0;
55
        private static PointConverter pointConverter = new PointConverter() {
56
                        /* (non-Javadoc)
57
                         * @see com.iver.cit.opensig.fmap.FConverter.PointConverter#toViewPoint(com.vividsolutions.jts.geom.Coordinate)
58
                         */
59
                        public Point2D toViewPoint(Coordinate modelCoordinate)
60
                                throws NoninvertibleTransformException {
61
                                // TODO Auto-generated method stub
62
                                return null;
63
                        }
64
                };
65

    
66
        //returns true if testPoint is a point in the pointList list.
67
        static boolean pointInList(Coordinate testPoint, Coordinate[] pointList) {
68
                int t;
69
                int numpoints;
70
                Coordinate p;
71

    
72
                numpoints = Array.getLength(pointList);
73

    
74
                for (t = 0; t < numpoints; t++) {
75
                        p = pointList[t];
76

    
77
                        if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
78
                                        ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
79
                        ) {
80
                                return true;
81
                        }
82
                }
83

    
84
                return false;
85
        }
86

    
87
        /**
88
         * Convierte un FShape a una Geometry del JTS. Para ello, utilizamos un
89
         * "flattened PathIterator". El flattened indica que las curvas las pasa a
90
         * segmentos de l?nea recta AUTOMATICAMENTE!!!.
91
         *
92
         * @param shp FShape que se quiere convertir.
93
         *
94
         * @return Geometry de JTS.
95
         */
96
        public static Geometry java2d_to_jts(FShape shp) {
97
                double flatness = 0.8; // Por ejemplo. Cuanto m?s peque?o, m?s segmentos necesitar? la curva
98

    
99
                // Es la m?xima distancia que permitimos que el trazo aproximado
100
                // difiera del trazo real.
101
                Geometry geoJTS = null;
102
                Coordinate coord;
103
                Coordinate[] coords;
104
                ArrayList arrayCoords = null;
105
                ArrayList arrayLines;
106
                LineString lin;
107
                LinearRing linRing;
108
                LinearRing linRingExt = null;
109
                int theType;
110
                int numParts = 0;
111

    
112
                //                 Use this array to store segment coordinate data
113
                double[] theData = new double[6];
114
                PathIterator theIterator;
115

    
116
                switch (shp.getShapeType()) {
117
                        case FShape.POINT:
118

    
119
                                FPoint2D p = (FPoint2D) shp;
120
                                coord = new Coordinate(p.getX(), p.getY());
121
                                geoJTS = new GeometryFactory().createPoint(coord);
122

    
123
                                break;
124

    
125
                        case FShape.LINE:
126
                                arrayLines = new ArrayList();
127
                                theIterator = shp.getPathIterator(null); //, flatness);
128

    
129
                                while (!theIterator.isDone()) {
130
                                        //while not done
131
                                        theType = theIterator.currentSegment(theData);
132

    
133
                                        //Populate a segment of the new
134
                                        // GeneralPathX object.
135
                                        //Process the current segment to populate a new
136
                                        // segment of the new GeneralPathX object.
137
                                        switch (theType) {
138
                                                case PathIterator.SEG_MOVETO:
139

    
140
                                                        // System.out.println("SEG_MOVETO");
141
                                                        if (arrayCoords == null) {
142
                                                                arrayCoords = new ArrayList();
143
                                                        } else {
144
                                                                lin = new GeometryFactory().createLineString(CoordinateArrays.toCoordinateArray(
145
                                                                                        arrayCoords));
146
                                                                arrayLines.add(lin);
147
                                                                arrayCoords = new ArrayList();
148
                                                        }
149

    
150
                                                        numParts++;
151
                                                        arrayCoords.add(new Coordinate(theData[0],
152
                                                                        theData[1]));
153

    
154
                                                        break;
155

    
156
                                                case PathIterator.SEG_LINETO:
157

    
158
                                                        // System.out.println("SEG_LINETO");
159
                                                        arrayCoords.add(new Coordinate(theData[0],
160
                                                                        theData[1]));
161

    
162
                                                        break;
163

    
164
                                                case PathIterator.SEG_QUADTO:
165
                                                        System.out.println("Not supported here");
166

    
167
                                                        break;
168

    
169
                                                case PathIterator.SEG_CUBICTO:
170
                                                        System.out.println("Not supported here");
171

    
172
                                                        break;
173

    
174
                                                case PathIterator.SEG_CLOSE:
175
                                                        System.out.println("SEG_CLOSE");
176

    
177
                                                        // A?adimos el primer punto para cerrar.
178
                                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
179
                                                        arrayCoords.add(new Coordinate(firstCoord.x,
180
                                                                        firstCoord.y));
181

    
182
                                                        break;
183
                                        } //end switch
184

    
185
                                        theIterator.next();
186
                                } //end while loop
187

    
188
                                lin = new GeometryFactory().createLineString(CoordinateArrays.toCoordinateArray(
189
                                                        arrayCoords));
190

    
191
                                if (numParts > 1) // Generamos una MultiLineString
192
                                 {
193
                                        arrayLines.add(lin);
194
                                        geoJTS = new GeometryFactory().createMultiLineString(GeometryFactory.toLineStringArray(
195
                                                                arrayLines));
196
                                } else {
197
                                        geoJTS = lin;
198
                                }
199

    
200
                                break;
201

    
202
                        case FShape.POLYGON:
203
                                arrayLines = new ArrayList();
204

    
205
                                ArrayList shells = new ArrayList();
206
                                ArrayList holes = new ArrayList();
207
                                Coordinate[] points = null;
208

    
209
                                theIterator = shp.getPathIterator(at, flatness);
210

    
211
                                while (!theIterator.isDone()) {
212
                                        //while not done
213
                                        theType = theIterator.currentSegment(theData);
214

    
215
                                        //Populate a segment of the new
216
                                        // GeneralPathX object.
217
                                        //Process the current segment to populate a new
218
                                        // segment of the new GeneralPathX object.
219
                                        switch (theType) {
220
                                                case PathIterator.SEG_MOVETO:
221

    
222
                                                        // System.out.println("SEG_MOVETO");
223
                                                        if (arrayCoords == null) {
224
                                                                arrayCoords = new ArrayList();
225
                                                        } else {
226
                                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
227

    
228
                                                                try {
229
                                                                        LinearRing ring = geomFactory.createLinearRing(points);
230

    
231
                                                                        if (CGAlgorithms.isCCW(points)) {
232
                                                                                holes.add(ring);
233
                                                                        } else {
234
                                                                                shells.add(ring);
235
                                                                        }
236
                                                                } catch (Exception e) {
237
                                                                        System.err.println(
238
                                                                                "Caught Topology exception in GMLLinearRingHandler");
239

    
240
                                                                        return null;
241
                                                                }
242

    
243
                                                                /* if (numParts == 1)
244
                                                                   {
245
                                                                           linRingExt = new GeometryFactory().createLinearRing(
246
                                                                                  CoordinateArrays.toCoordinateArray(arrayCoords));
247
                                                                   }
248
                                                                   else
249
                                                                   {
250
                                                                           linRing = new GeometryFactory().createLinearRing(
251
                                                                                          CoordinateArrays.toCoordinateArray(arrayCoords));
252
                                                                           arrayLines.add(linRing);
253
                                                                   } */
254
                                                                arrayCoords = new ArrayList();
255
                                                        }
256

    
257
                                                        numParts++;
258
                                                        arrayCoords.add(new Coordinate(theData[0],
259
                                                                        theData[1]));
260

    
261
                                                        break;
262

    
263
                                                case PathIterator.SEG_LINETO:
264

    
265
                                                        // System.out.println("SEG_LINETO");
266
                                                        arrayCoords.add(new Coordinate(theData[0],
267
                                                                        theData[1]));
268

    
269
                                                        break;
270

    
271
                                                case PathIterator.SEG_QUADTO:
272
                                                        System.out.println("SEG_QUADTO Not supported here");
273

    
274
                                                        break;
275

    
276
                                                case PathIterator.SEG_CUBICTO:
277
                                                        System.out.println("SEG_CUBICTO Not supported here");
278

    
279
                                                        break;
280

    
281
                                                case PathIterator.SEG_CLOSE:
282

    
283
                                                        // A?adimos el primer punto para cerrar.
284
                                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
285
                                                        arrayCoords.add(new Coordinate(firstCoord.x,
286
                                                                        firstCoord.y));
287

    
288
                                                        break;
289
                                        } //end switch
290

    
291
                                        // System.out.println("theData[0] = " + theData[0] + " theData[1]=" + theData[1]);
292
                                        theIterator.next();
293
                                } //end while loop
294

    
295
                                // arrayCoords.add(arrayCoords.get(0));
296
                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
297

    
298
                                try {
299
                                        LinearRing ring = geomFactory.createLinearRing(points);
300

    
301
                                        if (CGAlgorithms.isCCW(points)) {
302
                                                holes.add(ring);
303
                                        } else {
304
                                                shells.add(ring);
305
                                        }
306
                                } catch (Exception e) {
307
                                        System.err.println(
308
                                                "Caught Topology exception in GMLLinearRingHandler");
309

    
310
                                        return null;
311
                                }
312

    
313
                                /* linRing = new GeometryFactory().createLinearRing(
314
                                   CoordinateArrays.toCoordinateArray(arrayCoords)); */
315

    
316
                                // System.out.println("NumParts = " + numParts);
317
                                //now we have a list of all shells and all holes
318
                                ArrayList holesForShells = new ArrayList(shells.size());
319

    
320
                                for (int i = 0; i < shells.size(); i++) {
321
                                        holesForShells.add(new ArrayList());
322
                                }
323

    
324
                                //find homes
325
                                for (int i = 0; i < holes.size(); i++) {
326
                                        LinearRing testRing = (LinearRing) holes.get(i);
327
                                        LinearRing minShell = null;
328
                                        Envelope minEnv = null;
329
                                        Envelope testEnv = testRing.getEnvelopeInternal();
330
                                        Coordinate testPt = testRing.getCoordinateN(0);
331
                                        LinearRing tryRing;
332

    
333
                                        for (int j = 0; j < shells.size(); j++) {
334
                                                tryRing = (LinearRing) shells.get(j);
335

    
336
                                                Envelope tryEnv = tryRing.getEnvelopeInternal();
337

    
338
                                                if (minShell != null) {
339
                                                        minEnv = minShell.getEnvelopeInternal();
340
                                                }
341

    
342
                                                boolean isContained = false;
343
                                                Coordinate[] coordList = tryRing.getCoordinates();
344

    
345
                                                if (tryEnv.contains(testEnv) &&
346
                                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
347
                                                                (pointInList(testPt, coordList)))) {
348
                                                        isContained = true;
349
                                                }
350

    
351
                                                // check if this new containing ring is smaller than the current minimum ring
352
                                                if (isContained) {
353
                                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
354
                                                                minShell = tryRing;
355
                                                        }
356
                                                }
357
                                        }
358

    
359
                                        if (minShell == null) {
360
                                                System.out.println(
361
                                                        "polygon found with a hole thats not inside a shell");
362
                                        } else {
363
                                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
364
                                        }
365
                                }
366

    
367
                                Polygon[] polygons = new Polygon[shells.size()];
368

    
369
                                for (int i = 0; i < shells.size(); i++) {
370
                                        polygons[i] = geomFactory.createPolygon((LinearRing) shells.get(
371
                                                                i),
372
                                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(
373
                                                                new LinearRing[0]));
374
                                }
375

    
376
                                if (polygons.length == 1) {
377
                                        return polygons[0];
378
                                }
379

    
380
                                holesForShells = null;
381
                                shells = null;
382
                                holes = null;
383

    
384
                                //its a multi part
385
                                geoJTS = geomFactory.createMultiPolygon(polygons);
386

    
387
                                /* if (numParts > 1) // Generamos un Polygon con agujeros
388
                                   {
389
                                    arrayLines.add(linRing);
390
                                           // geoJTS = new GeometryFactory().createPolygon(linRingExt,
391
                                                           // GeometryFactory.toLinearRingArray(arrayLines));
392
                                    geoJTS = new GeometryFactory().buildGeometry(arrayLines);
393
                                
394
                                    // geoJTS = Polygonizer.class.
395
                                   }
396
                                   else
397
                                   {
398
                                           geoJTS = new GeometryFactory().createPolygon(linRing,null);
399
                                   } */
400
                                break;
401
                }
402

    
403
                return geoJTS;
404
        }
405

    
406
        /**
407
         * Converts JTS Geometry objects into Java 2D Shape objects
408
         *
409
         * @param geo Geometry de JTS.
410
         *
411
         * @return FShape.
412
         */
413
        public static FShape jts_to_java2d(Geometry geo) {
414
                FShape shpNew = null;
415

    
416
                try {
417
                        if (geo instanceof Point) {
418
                                shpNew = new FPoint2D(((Point) geo).getX(), ((Point) geo).getY());
419
                        }
420

    
421
                        if (geo.isEmpty()) {
422
                                shpNew = null;
423
                        }
424

    
425
                        if (geo instanceof Polygon) {
426
                                shpNew = new FPolygon2D(toShape((Polygon) geo));
427
                        }
428

    
429
                        if (geo instanceof MultiPolygon) {
430
                                shpNew = new FPolygon2D(toShape((MultiPolygon) geo));
431
                        }
432

    
433
                        if (geo instanceof LineString) {
434
                                shpNew = new FPolyline2D(toShape((LineString) geo));
435
                        }
436

    
437
                        if (geo instanceof MultiLineString) {
438
                                shpNew = new FPolyline2D(toShape((MultiLineString) geo));
439
                        }
440

    
441
                        /* OJO: CON ALGO COMO FSHAPE NO S? C?MO PODEMOS IMPLEMENTAR UN GeometryCollection
442
                         * No sabremos si queremos una l?nea o un pol?gono.....
443
                         *  if (geometry instanceof GeometryCollection) {
444
                                  return toShape((GeometryCollection) geometry);
445
                           } */
446
                        return shpNew;
447
                } catch (NoninvertibleTransformException e) {
448
                        // TODO Auto-generated catch block
449
                        e.printStackTrace();
450
                }
451

    
452
                return null;
453
        }
454

    
455
        /**
456
         * DOCUMENT ME!
457
         *
458
         * @param p DOCUMENT ME!
459
         *
460
         * @return DOCUMENT ME!
461
         */
462
        private static GeneralPathX toShape(Polygon p) {
463
                GeneralPathX resul = new GeneralPathX();
464
                Coordinate coord;
465

    
466
                for (int i = 0; i < p.getExteriorRing().getNumPoints(); i++) {
467
                        coord = p.getExteriorRing().getCoordinateN(i);
468

    
469
                        if (i == 0) {
470
                                resul.moveTo((float) coord.x, (float) coord.y);
471
                        } else {
472
                                resul.lineTo((float) coord.x, (float) coord.y);
473
                        }
474
                }
475

    
476
                for (int j = 0; j < p.getNumInteriorRing(); j++) {
477
                        LineString hole = p.getInteriorRingN(j);
478

    
479
                        for (int k = 0; k < hole.getNumPoints(); k++) {
480
                                coord = hole.getCoordinateN(k);
481

    
482
                                if (k == 0) {
483
                                        resul.moveTo((float) coord.x, (float) coord.y);
484
                                } else {
485
                                        resul.lineTo((float) coord.x, (float) coord.y);
486
                                }
487
                        }
488
                }
489

    
490
                return resul;
491
        }
492

    
493
        /**
494
         * DOCUMENT ME!
495
         *
496
         * @param modelCoordinates DOCUMENT ME!
497
         *
498
         * @return DOCUMENT ME!
499
         *
500
         * @throws NoninvertibleTransformException DOCUMENT ME!
501
         */
502
        private Coordinate[] toViewCoordinates(Coordinate[] modelCoordinates)
503
                throws NoninvertibleTransformException {
504
                Coordinate[] viewCoordinates = new Coordinate[modelCoordinates.length];
505

    
506
                for (int i = 0; i < modelCoordinates.length; i++) {
507
                        FPoint2D point2D = toViewPoint(modelCoordinates[i]);
508
                        viewCoordinates[i] = new Coordinate(point2D.getX(), point2D.getY());
509
                }
510

    
511
                return viewCoordinates;
512
        }
513

    
514
        /* private Shape toShape(GeometryCollection gc)
515
           throws NoninvertibleTransformException {
516
           GeometryCollectionShape shape = new GeometryCollectionShape();
517
           for (int i = 0; i < gc.getNumGeometries(); i++) {
518
                   Geometry g = (Geometry) gc.getGeometryN(i);
519
                   shape.add(toShape(g));
520
           }
521
           return shape;
522
           } */
523
        private static GeneralPathX toShape(MultiLineString mls)
524
                throws NoninvertibleTransformException {
525
                GeneralPathX path = new GeneralPathX();
526

    
527
                for (int i = 0; i < mls.getNumGeometries(); i++) {
528
                        LineString lineString = (LineString) mls.getGeometryN(i);
529
                        path.append(toShape(lineString), false);
530
                }
531

    
532
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
533
                //converted to GeneralPathXs. [Jon Aquino]
534
                return path;
535
        }
536

    
537
        /**
538
         * DOCUMENT ME!
539
         *
540
         * @param lineString DOCUMENT ME!
541
         *
542
         * @return DOCUMENT ME!
543
         *
544
         * @throws NoninvertibleTransformException DOCUMENT ME!
545
         */
546
        private static GeneralPathX toShape(LineString lineString)
547
                throws NoninvertibleTransformException {
548
                GeneralPathX shape = new GeneralPathX();
549
                FPoint2D viewPoint = toViewPoint(lineString.getCoordinateN(0));
550
                shape.moveTo((float) viewPoint.getX(), (float) viewPoint.getY());
551

    
552
                for (int i = 1; i < lineString.getNumPoints(); i++) {
553
                        viewPoint = toViewPoint(lineString.getCoordinateN(i));
554
                        shape.lineTo((float) viewPoint.getX(), (float) viewPoint.getY());
555
                }
556

    
557
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
558
                //converted to GeneralPathXs. [Jon Aquino]
559
                return shape;
560
        }
561

    
562
        /**
563
         * DOCUMENT ME!
564
         *
565
         * @param point DOCUMENT ME!
566
         *
567
         * @return DOCUMENT ME!
568
         *
569
         * @throws NoninvertibleTransformException DOCUMENT ME!
570
         */
571
        private static FPoint2D toShape(Point point)
572
                throws NoninvertibleTransformException {
573
                FPoint2D viewPoint = toViewPoint(point.getCoordinate());
574

    
575
                return viewPoint;
576
        }
577

    
578
        /**
579
         * DOCUMENT ME!
580
         *
581
         * @param coord DOCUMENT ME!
582
         *
583
         * @return DOCUMENT ME!
584
         */
585
        private static FPoint2D toViewPoint(Coordinate coord) {
586
                return new FPoint2D(coord.x, coord.y); //,coord.z);
587
        }
588

    
589
        /**
590
         * Convierte una Geometry de JTS a GeneralPathX.
591
         *
592
         * @param geometry Geometry a convertir.
593
         *
594
         * @return GeneralPathX.
595
         *
596
         * @throws NoninvertibleTransformException 
597
         * @throws IllegalArgumentException
598
         */
599
        public static GeneralPathX toShape(Geometry geometry)
600
                throws NoninvertibleTransformException {
601
                if (geometry.isEmpty()) {
602
                        return new GeneralPathX();
603
                }
604

    
605
                if (geometry instanceof Polygon) {
606
                        return toShape((Polygon) geometry);
607
                }
608

    
609
                if (geometry instanceof MultiPolygon) {
610
                        return toShape((MultiPolygon) geometry);
611
                }
612

    
613
                if (geometry instanceof LineString) {
614
                        return toShape((LineString) geometry);
615
                }
616

    
617
                if (geometry instanceof MultiLineString) {
618
                        return toShape((MultiLineString) geometry);
619
                }
620

    
621
                if (geometry instanceof GeometryCollection) {
622
                        return toShape((GeometryCollection) geometry);
623
                }
624

    
625
                throw new IllegalArgumentException("Unrecognized Geometry class: " +
626
                        geometry.getClass());
627
        }
628

    
629
        /**
630
         * Interfazaz para convertir una Coordinate de JTS a Point2D.
631
         *
632
         */
633
        public static interface PointConverter {
634
                /**
635
                 * DOCUMENT ME!
636
                 *
637
                 * @param modelCoordinate DOCUMENT ME!
638
                 *
639
                 * @return DOCUMENT ME!
640
                 *
641
                 * @throws NoninvertibleTransformException DOCUMENT ME!
642
                 */
643
                public Point2D toViewPoint(Coordinate modelCoordinate)
644
                        throws NoninvertibleTransformException;
645
        }
646
}