Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_geometries / src / org / gvsig / fmap / geom / util / Converter.java @ 21047

History | View | Annotate | Download (34.7 KB)

1
/* gvSIG. Sistema de Informaci�n Geogr�fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *  Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib��ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *      +34 963862235
28
 *   gvsig@gva.es
29
 *      www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   IVER T.I. S.A
34
 *   Salamanca 50
35
 *   46005 Valencia
36
 *   Spain
37
 *
38
 *   +34 963163400
39
 *   dac@iver.es
40
 */
41
package org.gvsig.fmap.geom.util;
42

    
43
import java.awt.Shape;
44
import java.awt.geom.AffineTransform;
45
import java.awt.geom.Area;
46
import java.awt.geom.NoninvertibleTransformException;
47
import java.awt.geom.PathIterator;
48
import java.awt.geom.Rectangle2D;
49
import java.lang.reflect.Array;
50
import java.util.ArrayList;
51

    
52
import org.apache.log4j.Logger;
53
import org.gvsig.fmap.geom.Geometry;
54
import org.gvsig.fmap.geom.GeometryFactory;
55
import org.gvsig.fmap.geom.aggregate.BaseMultiPrimitive;
56
import org.gvsig.fmap.geom.aggregate.MultiCurve2D;
57
import org.gvsig.fmap.geom.aggregate.MultiPoint2D;
58
import org.gvsig.fmap.geom.aggregate.MultiSurface2D;
59
import org.gvsig.fmap.geom.primitive.Curve2D;
60
import org.gvsig.fmap.geom.primitive.FShape;
61
import org.gvsig.fmap.geom.primitive.GeneralPathX;
62
import org.gvsig.fmap.geom.primitive.Point2D;
63
import org.gvsig.fmap.geom.primitive.Surface2D;
64

    
65
import com.vividsolutions.jts.algorithm.CGAlgorithms;
66
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
67
import com.vividsolutions.jts.geom.Coordinate;
68
import com.vividsolutions.jts.geom.CoordinateArrays;
69
import com.vividsolutions.jts.geom.Envelope;
70
import com.vividsolutions.jts.geom.GeometryCollection;
71
import com.vividsolutions.jts.geom.LineString;
72
import com.vividsolutions.jts.geom.LinearRing;
73
import com.vividsolutions.jts.geom.MultiLineString;
74
import com.vividsolutions.jts.geom.MultiPolygon;
75
import com.vividsolutions.jts.geom.Point;
76
import com.vividsolutions.jts.geom.Polygon;
77

    
78

    
79
/**
80
 * Clase con varios m�todos est�ticos utilizados para pasar de java2d a jts y
81
 * viceversa.
82
 *
83
 * @author fjp
84
 */
85
public class Converter {
86
        
87
        private static Logger logger = Logger.getLogger(Converter.class);
88
        
89
        /**
90
         * �QU� PODEMOS HACER CON LOS MULTIPOINT??? => DEBER�AMOS TRABAJAR CON UN
91
         * ARRAY DE PUNTOS EN FShape.....Pensarlo bien.
92
         */
93
        public final static com.vividsolutions.jts.geom.GeometryFactory geomFactory = new com.vividsolutions.jts.geom.GeometryFactory();
94
        public static CGAlgorithms cga = new RobustCGAlgorithms();
95
        // private final static AffineTransform at = new AffineTransform();
96
        //private static double POINT_MARKER_SIZE = 3.0;
97

    
98
        /**
99
         * Es la m�xima distancia que permitimos que el trazo aproximado
100
         * difiera del trazo real.
101
         */
102
        public static double FLATNESS =0.8;// Por ejemplo. Cuanto m�s peque�o, m�s segmentos necesitar� la curva
103

    
104

    
105
        //returns true if testPoint is a point in the pointList list.
106
        static boolean pointInList(Coordinate testPoint, Coordinate[] pointList) {
107
                int t;
108
                int numpoints;
109
                Coordinate p;
110

    
111
                numpoints = Array.getLength(pointList);
112

    
113
                for (t = 0; t < numpoints; t++) {
114
                        p = pointList[t];
115

    
116
                        if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
117
                                        ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
118
                        ) {
119
                                return true;
120
                        }
121
                }
122

    
123
                return false;
124
        }
125

    
126
        /**
127
         * Receives a JTS Geometry and returns a fmap IGeometry
128
         * @param jtsGeometry jts Geometry
129
         * @return IGeometry of FMap
130
         * @author azabala
131
         */
132
        public static Geometry jts_to_igeometry(com.vividsolutions.jts.geom.Geometry jtsGeometry){
133
                FShape shape = Converter.jts_to_java2d(jtsGeometry);
134
                return GeometryFactory.createGeometry(shape);
135
        }
136

    
137
        /**
138
         * Convierte un MultiPoint2D a un MultiPoint de JTS
139
         * @param geom
140
         * @return
141
         */        
142
        public com.vividsolutions.jts.geom.Geometry geometryToJts(MultiPoint2D geom) {
143
                Coordinate[] theGeoms = new Coordinate[geom.getPrimitivesNumber()];
144
                for (int i = 0; i < theGeoms.length; i++) {
145
                        java.awt.geom.Point2D p = (java.awt.geom.Point2D) geom.getPrimitiveAt(i)
146
                                        .getHandlers(Geometry.SELECTHANDLER)[0].getPoint();
147
                        Coordinate c = new Coordinate(p.getX(), p.getY());
148
                        theGeoms[i] = c;
149
                }
150
                com.vividsolutions.jts.geom.MultiPoint geomCol = new com.vividsolutions.jts.geom.GeometryFactory()
151
                                .createMultiPoint(theGeoms);
152
                return geomCol;
153
        }
154
        
155
        /**
156
         * Convierte una MultiCurve2D en una MultiLineString de JTS
157
         * @param geom
158
         * @return
159
         */
160
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiCurve2D geom) {
161
                LineString[] lines = new LineString[geom.getPrimitivesNumber()];
162
        for (int i = 0; i < lines.length; i++){
163
                lines[i] = (LineString) geometryToJts(((Curve2D) geom.getPrimitiveAt(i)));
164
        }
165
        return new com.vividsolutions.jts.geom.GeometryFactory().createMultiLineString(lines);                
166
        }        
167
        
168
        /**
169
         * Convierte una MultiSurface2D en un MultiPolygon de JTS
170
         * @return
171
         */
172
        public com.vividsolutions.jts.geom.Geometry geometryToJts(MultiSurface2D geom) {
173
                Polygon[] polygons = new Polygon[geom.getPrimitivesNumber()];
174
        for (int i = 0; i < polygons.length; i++){
175
                polygons[i] = (Polygon) geometryToJts(((Surface2D)geom.getPrimitiveAt(i)));
176
        }
177
        return new com.vividsolutions.jts.geom.GeometryFactory().createMultiPolygon(polygons);                
178
        }        
179

    
180
        /**
181
         * Convierte una BaseMultiPrimitive en una GeometryCollection de JTS
182
         * @return
183
         */
184
        public com.vividsolutions.jts.geom.Geometry geometryToJts(BaseMultiPrimitive geom) {
185
                com.vividsolutions.jts.geom.Geometry[] geometriesAux = new LineString[geom.getPrimitivesNumber()];
186
                for (int i = 0; i < geometriesAux.length; i++) {
187
                        geometriesAux[i] = geometryToJts(((Geometry) geom.getPrimitiveAt(i)));
188
                }
189
                return new com.vividsolutions.jts.geom.GeometryFactory().createGeometryCollection(geometriesAux);
190
        }
191
        
192
        
193
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(Geometry geom) {
194
                logger.debug(geom.getClass());
195
                logger.debug(geom.getShapeType());
196
         return java2d_to_jts((Shape)geom, geom.getShapeType());
197
        }
198
        
199
        public static com.vividsolutions.jts.geom.Geometry java2d_to_jts(FShape shp) {
200
                return java2d_to_jts(shp, shp.getShapeType());
201
        }        
202
        /**
203
         * Convierte un FShape a una Geometry del JTS. Para ello, utilizamos un
204
         * "flattened PathIterator". El flattened indica que las curvas las pasa a
205
         * segmentos de l�nea recta AUTOMATICAMENTE!!!.
206
         *
207
         * @param shp FShape que se quiere convertir.
208
         *
209
         * @return Geometry de JTS.
210
         */
211
        private static com.vividsolutions.jts.geom.Geometry java2d_to_jts(Shape shp, int shapeType) {
212

    
213

    
214
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
215
                Coordinate coord;
216
                //Coordinate[] coords;
217
                ArrayList arrayCoords = null;
218
                ArrayList arrayLines;
219
                LineString lin;
220
                //LinearRing linRing;
221
                //LinearRing linRingExt = null;
222
                int theType;
223
                int numParts = 0;
224

    
225
                //                 Use this array to store segment coordinate data
226
                double[] theData = new double[6];
227
                PathIterator theIterator;
228

    
229
                logger.debug(shp.toString());
230
                
231
                switch (shapeType) {
232
                        case FShape.POINT:
233
            case FShape.POINT + FShape.Z:
234
                                org.gvsig.fmap.geom.primitive.Point2D p = (org.gvsig.fmap.geom.primitive.Point2D) shp;
235
                                coord = new Coordinate(p.getX(), p.getY());
236
                                geoJTS = geomFactory.createPoint(coord);
237

    
238
                                break;
239

    
240
                        case FShape.LINE:
241
                        case FShape.ARC:
242
            case FShape.LINE + FShape.Z:
243
                                arrayLines = new ArrayList();
244
                                theIterator = shp.getPathIterator(null, FLATNESS);
245

    
246
                                while (!theIterator.isDone()) {
247
                                        //while not done
248
                                        theType = theIterator.currentSegment(theData);
249

    
250
                                        //Populate a segment of the new
251
                                        // GeneralPathX object.
252
                                        //Process the current segment to populate a new
253
                                        // segment of the new GeneralPathX object.
254
                                        switch (theType) {
255
                                                case PathIterator.SEG_MOVETO:
256

    
257
                                                        // System.out.println("SEG_MOVETO");
258
                                                        if (arrayCoords == null) {
259
                                                                arrayCoords = new ArrayList();
260
                                                        } else {
261
                                                                lin = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
262
                                                                                        arrayCoords));
263
                                                                arrayLines.add(lin);
264
                                                                arrayCoords = new ArrayList();
265
                                                        }
266

    
267
                                                        numParts++;
268
                                                        arrayCoords.add(new Coordinate(theData[0],
269
                                                                        theData[1]));
270

    
271
                                                        break;
272

    
273
                                                case PathIterator.SEG_LINETO:
274

    
275
                                                        // System.out.println("SEG_LINETO");
276
                                                        arrayCoords.add(new Coordinate(theData[0],
277
                                                                        theData[1]));
278

    
279
                                                        break;
280

    
281
                                                case PathIterator.SEG_QUADTO:
282
                                                        System.out.println("Not supported here");
283

    
284
                                                        break;
285

    
286
                                                case PathIterator.SEG_CUBICTO:
287
                                                        System.out.println("Not supported here");
288

    
289
                                                        break;
290

    
291
                                                case PathIterator.SEG_CLOSE:
292
                                                        // A�adimos el primer punto para cerrar.
293
                                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
294
                                                        arrayCoords.add(new Coordinate(firstCoord.x,
295
                                                                        firstCoord.y));
296

    
297
                                                        break;
298
                                        } //end switch
299

    
300
                                        theIterator.next();
301
                                } //end while loop
302

    
303
                                lin = new com.vividsolutions.jts.geom.GeometryFactory().createLineString(CoordinateArrays.toCoordinateArray(
304
                                                        arrayCoords));
305

    
306
                                // CAMBIO: ENTREGAMOS SIEMPRE MULTILINESTRING, QUE ES
307
                                // LO QUE HACE TODO EL MUNDO CUANDO ESCRIBE EN POSTGIS
308
                                // O CON GEOTOOLS
309
                                // if (numParts > 1) // Generamos una MultiLineString
310
                                //  {
311
                                        arrayLines.add(lin);
312
                                        geoJTS = geomFactory.createMultiLineString(com.vividsolutions.jts.geom.GeometryFactory.toLineStringArray(
313
                                                                arrayLines));
314
                                /* } else {
315
                                        geoJTS = lin;
316
                                } */
317

    
318
                                break;
319

    
320
                        case FShape.POLYGON:
321
                        case FShape.CIRCLE:
322
                        case FShape.ELLIPSE:
323
            case FShape.POLYGON + FShape.Z:
324
                                arrayLines = new ArrayList();
325

    
326
                                ArrayList shells = new ArrayList();
327
                                ArrayList holes = new ArrayList();
328
                                Coordinate[] points = null;
329

    
330
                                theIterator = shp.getPathIterator(null, FLATNESS);
331

    
332
                                while (!theIterator.isDone()) {
333
                                        //while not done
334
                                        theType = theIterator.currentSegment(theData);
335

    
336
                                        //Populate a segment of the new
337
                                        // GeneralPathX object.
338
                                        //Process the current segment to populate a new
339
                                        // segment of the new GeneralPathX object.
340
                                        switch (theType) {
341
                                                case PathIterator.SEG_MOVETO:
342

    
343
                                                        // System.out.println("SEG_MOVETO");
344
                                                        if (arrayCoords == null) {
345
                                                                arrayCoords = new ArrayList();
346
                                                        } else {
347
                                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
348

    
349
                                                                try {
350
                                                                        LinearRing ring = geomFactory.createLinearRing(points);
351

    
352
                                                                        if (CGAlgorithms.isCCW(points)) {
353
                                                                                holes.add(ring);
354
                                                                        } else {
355
                                                                                shells.add(ring);
356
                                                                        }
357
                                                                } catch (Exception e) {
358
                                                                        /* (jaume) caso cuando todos los puntos son iguales
359
                                                                         * devuelvo el propio punto
360
                                                                         */
361
                                                                        boolean same = true;
362
                                                                        for (int i = 0; i < points.length-1 && same; i++) {
363
                                                                                if (points[i].x != points[i+1].x ||
364
                                                                                                points[i].y != points[i+1].y /*||
365
                                                                                                points[i].z != points[i+1].z*/
366
                                                                                                ) same = false;
367
                                                                        }
368
                                                                        if (same)
369
                                                                                return geomFactory.createPoint(points[0]);
370
                                                                        /*
371
                                                                         * caso cuando es una l�nea de 3 puntos, no creo un LinearRing, sino
372
                                                                         * una linea
373
                                                                         */
374
                                                                        if (points.length>1 && points.length<=3)
375
                                                                                // return geomFactory.createLineString(points);
376
                                                                                return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
377

    
378
                                                                        System.err.println(
379
                                                                                "Caught Topology exception in GMLLinearRingHandler");
380

    
381
                                                                        return null;
382
                                                                }
383

    
384
                                                                /* if (numParts == 1)
385
                                                                   {
386
                                                                           linRingExt = new GeometryFactory().createLinearRing(
387
                                                                                  CoordinateArrays.toCoordinateArray(arrayCoords));
388
                                                                   }
389
                                                                   else
390
                                                                   {
391
                                                                           linRing = new GeometryFactory().createLinearRing(
392
                                                                                          CoordinateArrays.toCoordinateArray(arrayCoords));
393
                                                                           arrayLines.add(linRing);
394
                                                                   } */
395
                                                                arrayCoords = new ArrayList();
396
                                                        }
397

    
398
                                                        numParts++;
399
                                                        arrayCoords.add(new Coordinate(theData[0],
400
                                                                        theData[1]));
401

    
402
                                                        break;
403

    
404
                                                case PathIterator.SEG_LINETO:
405

    
406
                                                        // System.out.println("SEG_LINETO");
407
                                                        arrayCoords.add(new Coordinate(theData[0],
408
                                                                        theData[1]));
409

    
410
                                                        break;
411

    
412
                                                case PathIterator.SEG_QUADTO:
413
                                                        System.out.println("SEG_QUADTO Not supported here");
414

    
415
                                                        break;
416

    
417
                                                case PathIterator.SEG_CUBICTO:
418
                                                        System.out.println("SEG_CUBICTO Not supported here");
419

    
420
                                                        break;
421

    
422
                                                case PathIterator.SEG_CLOSE:
423

    
424
                                                        // A�adimos el primer punto para cerrar.
425
                                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
426
                                                        arrayCoords.add(new Coordinate(firstCoord.x,
427
                                                                        firstCoord.y));
428

    
429
                                                        break;
430
                                        } //end switch
431

    
432
                                        // System.out.println("theData[0] = " + theData[0] + " theData[1]=" + theData[1]);
433
                                        theIterator.next();
434
                                } //end while loop
435

    
436
                                arrayCoords.add(arrayCoords.get(0));
437
                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
438

    
439
                                try {
440
                                        LinearRing ring = geomFactory.createLinearRing(points);
441

    
442
                                        if (CGAlgorithms.isCCW(points)) {
443
                                                holes.add(ring);
444
                                        } else {
445
                                                shells.add(ring);
446
                                        }
447
                                } catch (Exception e) {
448
                                        /* (jaume) caso cuando todos los puntos son iguales
449
                                         * devuelvo el propio punto
450
                                         */
451
                                        boolean same = true;
452
                                        for (int i = 0; i < points.length-1 && same; i++) {
453
                                                if (points[i].x != points[i+1].x ||
454
                                                                points[i].y != points[i+1].y /*||
455
                                                                points[i].z != points[i+1].z*/
456
                                                                ) same = false;
457
                                        }
458
                                        if (same)
459
                                                return geomFactory.createPoint(points[0]);
460
                                        /*
461
                                         * caso cuando es una l�nea de 3 puntos, no creo un LinearRing, sino
462
                                         * una linea
463
                                         */
464
                                        if (points.length>1 && points.length<=3)
465
                                                // return geomFactory.createLineString(points);
466
                                                return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
467
                                        System.err.println(
468
                                                "Caught Topology exception in GMLLinearRingHandler");
469

    
470
                                        return null;
471
                                }
472

    
473
                                /* linRing = new GeometryFactory().createLinearRing(
474
                                   CoordinateArrays.toCoordinateArray(arrayCoords)); */
475

    
476
                                // System.out.println("NumParts = " + numParts);
477
                                //now we have a list of all shells and all holes
478
                                ArrayList holesForShells = new ArrayList(shells.size());
479

    
480
                                for (int i = 0; i < shells.size(); i++) {
481
                                        holesForShells.add(new ArrayList());
482
                                }
483

    
484
                                //find homes
485
                                for (int i = 0; i < holes.size(); i++) {
486
                                        LinearRing testRing = (LinearRing) holes.get(i);
487
                                        LinearRing minShell = null;
488
                                        Envelope minEnv = null;
489
                                        Envelope testEnv = testRing.getEnvelopeInternal();
490
                                        Coordinate testPt = testRing.getCoordinateN(0);
491
                                        LinearRing tryRing = null;
492

    
493
                                        for (int j = 0; j < shells.size(); j++) {
494
                                                tryRing = (LinearRing) shells.get(j);
495

    
496
                                                Envelope tryEnv = tryRing.getEnvelopeInternal();
497

    
498
                                                if (minShell != null) {
499
                                                        minEnv = minShell.getEnvelopeInternal();
500
                                                }
501

    
502
                                                boolean isContained = false;
503
                                                Coordinate[] coordList = tryRing.getCoordinates();
504

    
505
                                                if (tryEnv.contains(testEnv) &&
506
                                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
507
                                                                (pointInList(testPt, coordList)))) {
508
                                                        isContained = true;
509
                                                }
510

    
511
                                                // check if this new containing ring is smaller than the current minimum ring
512
                                                if (isContained) {
513
                                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
514
                                                                minShell = tryRing;
515
                                                        }
516
                                                }
517
                                        }
518

    
519
                                        if (minShell == null) {
520
//                                                System.out.println(
521
//                                                        "polygon found with a hole thats not inside a shell");
522
//azabala: we do the assumption that this hole is really a shell (polygon)
523
//whose point werent digitized in the right order
524
Coordinate[] cs = testRing.getCoordinates();
525
Coordinate[] reversed = new Coordinate[cs.length];
526
int pointIndex = 0;
527
for(int z = cs.length-1; z >= 0; z--){
528
        reversed[pointIndex] = cs[z];
529
        pointIndex++;
530
}
531
LinearRing newRing = geomFactory.createLinearRing(reversed);
532
shells.add(newRing);
533
holesForShells.add(new ArrayList());
534
                                        } else {
535
                                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
536
                                        }
537
                                }
538

    
539
                                Polygon[] polygons = new Polygon[shells.size()];
540

    
541
                                for (int i = 0; i < shells.size(); i++) {
542
                                        polygons[i] = geomFactory.createPolygon((LinearRing) shells.get(
543
                                                                i),
544
                                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(
545
                                                                new LinearRing[0]));
546
                                }
547
                                // CAMBIO: ENTREGAMOS SIEMPRE MULTILINESTRING, QUE ES
548
                                // LO QUE HACE TODO EL MUNDO CUANDO ESCRIBE EN POSTGIS
549
                                // O CON GEOTOOLS
550
                                // if (numParts > 1) // Generamos una MultiLineString
551

    
552
                                /* if (polygons.length == 1) {
553
                                        return polygons[0];
554
                                } */
555

    
556
                                // FIN CAMBIO
557

    
558
                                holesForShells = null;
559
                                shells = null;
560
                                holes = null;
561

    
562
                                //its a multi part
563
                                geoJTS = geomFactory.createMultiPolygon(polygons);
564

    
565
                                /* if (numParts > 1) // Generamos un Polygon con agujeros
566
                                   {
567
                                    arrayLines.add(linRing);
568
                                           // geoJTS = new GeometryFactory().createPolygon(linRingExt,
569
                                                           // GeometryFactory.toLinearRingArray(arrayLines));
570
                                    geoJTS = new GeometryFactory().buildGeometry(arrayLines);
571

572
                                    // geoJTS = Polygonizer.class.
573
                                   }
574
                                   else
575
                                   {
576
                                           geoJTS = new GeometryFactory().createPolygon(linRing,null);
577
                                   } */
578
                                break;
579
                }
580

    
581
                return geoJTS;
582
        }
583

    
584
        /**
585
         * Converts JTS Geometry objects into Java 2D Shape objects
586
         *
587
         * @param geo Geometry de JTS.
588
         *
589
         * @return FShape.
590
         */
591
        public static FShape jts_to_java2d(com.vividsolutions.jts.geom.Geometry geo) {
592
                FShape shpNew = null;
593

    
594
                try {
595
                        if (geo instanceof Point) {
596
                                shpNew = new org.gvsig.fmap.geom.primitive.Point2D(null, null, ((Point) geo).getX(), ((Point) geo).getY());
597
                        }
598

    
599
                        if (geo.isEmpty()) {
600
                                shpNew = null;
601
                        }
602

    
603
                        if (geo instanceof Polygon) {
604
                                shpNew = new Surface2D(null, null, toShape((Polygon) geo));
605
                        }
606

    
607
                        if (geo instanceof MultiPolygon) {
608
                                shpNew = new Surface2D(null, null, toShape((MultiPolygon) geo));
609
                        }
610

    
611
                        if (geo instanceof LineString) {
612
                                shpNew = new Curve2D(null, null, toShape((LineString) geo));
613
                        }
614

    
615
                        if (geo instanceof MultiLineString) {
616
                                shpNew = new Curve2D(null, null, toShape((MultiLineString) geo));
617
                        }
618

    
619
                        /* OJO: CON ALGO COMO FSHAPE NO S� C�MO PODEMOS IMPLEMENTAR UN GeometryCollection
620
                         * No sabremos si queremos una l�nea o un pol�gono.....
621
                         *  if (geometry instanceof GeometryCollection) {
622
                                  return toShape((GeometryCollection) geometry);
623
                           } */
624
                        return shpNew;
625
                } catch (NoninvertibleTransformException e) {
626
                        // TODO Auto-generated catch block
627
                        e.printStackTrace();
628
                }
629

    
630
                return null;
631
        }
632

    
633
        /**
634
         * DOCUMENT ME!
635
         *
636
         * @param p DOCUMENT ME!
637
         *
638
         * @return DOCUMENT ME!
639
         */
640
        private static GeneralPathX toShape(Polygon p) {
641
                GeneralPathX resul = new GeneralPathX();
642
                Coordinate coord;
643

    
644
                for (int i = 0; i < p.getExteriorRing().getNumPoints(); i++) {
645
                        coord = p.getExteriorRing().getCoordinateN(i);
646

    
647
                        if (i == 0) {
648
                                resul.moveTo(coord.x,coord.y);
649
                        } else {
650
                                resul.lineTo(coord.x,coord.y);
651
                        }
652
                }
653

    
654
                for (int j = 0; j < p.getNumInteriorRing(); j++) {
655
                        LineString hole = p.getInteriorRingN(j);
656

    
657
                        for (int k = 0; k < hole.getNumPoints(); k++) {
658
                                coord = hole.getCoordinateN(k);
659

    
660
                                if (k == 0) {
661
                                        resul.moveTo(coord.x, coord.y);
662
                                } else {
663
                                        resul.lineTo(coord.x, coord.y);
664
                                }
665
                        }
666
                }
667

    
668
                return resul;
669
        }
670

    
671
        /**
672
         * DOCUMENT ME!
673
         *
674
         * @param modelCoordinates DOCUMENT ME!
675
         *
676
         * @return DOCUMENT ME!
677
         *
678
         * @throws NoninvertibleTransformException DOCUMENT ME!
679
         *
680
        private Coordinate[] toViewCoordinates(Coordinate[] modelCoordinates)
681
                throws NoninvertibleTransformException {
682
                Coordinate[] viewCoordinates = new Coordinate[modelCoordinates.length];
683

684
                for (int i = 0; i < modelCoordinates.length; i++) {
685
                        FPoint2D point2D = coordinate2FPoint2D(modelCoordinates[i]);
686
                        viewCoordinates[i] = new Coordinate(point2D.getX(), point2D.getY());
687
                }
688

689
                return viewCoordinates;
690
        } */
691

    
692
        /* private Shape toShape(GeometryCollection gc)
693
           throws NoninvertibleTransformException {
694
           GeometryCollectionShape shape = new GeometryCollectionShape();
695
           for (int i = 0; i < gc.getNumGeometries(); i++) {
696
                   Geometry g = (Geometry) gc.getGeometryN(i);
697
                   shape.add(toShape(g));
698
           }
699
           return shape;
700
           } */
701
        private static GeneralPathX toShape(MultiLineString mls)
702
                throws NoninvertibleTransformException {
703
                GeneralPathX path = new GeneralPathX();
704

    
705
                for (int i = 0; i < mls.getNumGeometries(); i++) {
706
                        LineString lineString = (LineString) mls.getGeometryN(i);
707
                        path.append(toShape(lineString), false);
708
                }
709

    
710
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
711
                //converted to GeneralPathXs. [Jon Aquino]
712
                return path;
713
        }
714

    
715
        /**
716
         * DOCUMENT ME!
717
         *
718
         * @param lineString DOCUMENT ME!
719
         *
720
         * @return DOCUMENT ME!
721
         *
722
         * @throws NoninvertibleTransformException DOCUMENT ME!
723
         */
724
        private static GeneralPathX toShape(LineString lineString)
725
                throws NoninvertibleTransformException {
726
                GeneralPathX shape = new GeneralPathX();
727
                org.gvsig.fmap.geom.primitive.Point2D viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(0));
728
                shape.moveTo(viewPoint.getX(), viewPoint.getY());
729

    
730
                for (int i = 1; i < lineString.getNumPoints(); i++) {
731
                        viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(i));
732
                        shape.lineTo(viewPoint.getX(), viewPoint.getY());
733
                }
734

    
735
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
736
                //converted to GeneralPathXs. [Jon Aquino]
737
                return shape;
738
        }
739

    
740
        /* TODO No se usa
741
         * DOCUMENT ME!
742
         *
743
         * @param point DOCUMENT ME!
744
         *
745
         * @return DOCUMENT ME!
746
         *
747
         * @throws NoninvertibleTransformException DOCUMENT ME!
748
         *
749
        private static Point2D toShape(Point point)
750
                throws NoninvertibleTransformException {
751
                Point2D viewPoint = coordinate2FPoint2D(point.getCoordinate());
752

753
                return viewPoint;
754
        }
755
*/
756
        
757
        /**
758
         * 
759
         */
760
        private static GeneralPathX toShape(MultiPolygon mp)
761
        throws NoninvertibleTransformException {
762
        GeneralPathX path = new GeneralPathX();
763

    
764
        for (int i = 0; i < mp.getNumGeometries(); i++) {
765
                Polygon polygon = (Polygon) mp.getGeometryN(i);
766
                path.append(toShape(polygon), false);
767
        }
768

    
769
        //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
770
        //converted to GeneralPathXs. [Jon Aquino]
771
        return path;
772
}
773
        /**
774
         * DOCUMENT ME!
775
         *
776
         * @param coord DOCUMENT ME!
777
         *
778
         * @return DOCUMENT ME!
779
         */
780
        public static org.gvsig.fmap.geom.primitive.Point2D coordinate2FPoint2D(Coordinate coord) {
781
                return new org.gvsig.fmap.geom.primitive.Point2D(null, null, coord.x, coord.y); //,coord.z);
782
        }
783

    
784
        /**
785
         * Convierte una Geometry de JTS a GeneralPathX.
786
         *
787
         * @param geometry Geometry a convertir.
788
         *
789
         * @return GeneralPathX.
790
         *
791
         * @throws NoninvertibleTransformException
792
         * @throws IllegalArgumentException
793
         */
794
        public static GeneralPathX toShape(com.vividsolutions.jts.geom.Geometry geometry)
795
                throws NoninvertibleTransformException {
796
                if (geometry.isEmpty()) {
797
                        return new GeneralPathX();
798
                }
799

    
800
                if (geometry instanceof Polygon) {
801
                        return toShape((Polygon) geometry);
802
                }
803

    
804
                if (geometry instanceof MultiPolygon) {
805
                        return toShape((MultiPolygon) geometry);
806
                }
807

    
808
                if (geometry instanceof LineString) {
809
                        return toShape((LineString) geometry);
810
                }
811

    
812
                if (geometry instanceof MultiLineString) {
813
                        return toShape((MultiLineString) geometry);
814
                }
815

    
816
                if (geometry instanceof GeometryCollection) {
817
                        return toShape((GeometryCollection) geometry);
818
                }
819

    
820
                throw new IllegalArgumentException("Unrecognized Geometry class: " +
821
                        geometry.getClass());
822
        }
823

    
824

    
825
    public static GeneralPathX transformToInts(GeneralPathX gp, AffineTransform at) {
826
        GeneralPathX newGp = new GeneralPathX();
827
        PathIterator theIterator;
828
        int theType;
829
        int numParts = 0;
830
        double[] theData = new double[6];
831
        java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
832
        java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
833
        boolean bFirst = true;
834
        int xInt, yInt, antX = -1, antY = -1;
835

    
836
        theIterator = gp.getPathIterator(null); //, flatness);
837

    
838
        while (!theIterator.isDone()) {
839
            theType = theIterator.currentSegment(theData);
840
            switch (theType) {
841
                case PathIterator.SEG_MOVETO:
842
                    numParts++;
843
                    ptSrc.setLocation(theData[0], theData[1]);
844
                    at.transform(ptSrc, ptDst);
845
                    antX = (int) ptDst.getX();
846
                    antY = (int) ptDst.getY();
847
                    newGp.moveTo(antX, antY);
848
                    bFirst = true;
849
                    break;
850

    
851
                case PathIterator.SEG_LINETO:
852
                    ptSrc.setLocation(theData[0], theData[1]);
853
                    at.transform(ptSrc, ptDst);
854
                    xInt = (int) ptDst.getX();
855
                    yInt = (int) ptDst.getY();
856
                    if ((bFirst) || ((xInt != antX) || (yInt != antY)))
857
                    {
858
                        newGp.lineTo(xInt, yInt);
859
                        antX = xInt;
860
                        antY = yInt;
861
                        bFirst = false;
862
                    }
863
                    break;
864

    
865
                case PathIterator.SEG_QUADTO:
866
                    System.out.println("Not supported here");
867

    
868
                    break;
869

    
870
                case PathIterator.SEG_CUBICTO:
871
                    System.out.println("Not supported here");
872

    
873
                    break;
874

    
875
                case PathIterator.SEG_CLOSE:
876
                    newGp.closePath();
877

    
878
                    break;
879
            } //end switch
880

    
881
            theIterator.next();
882
        } //end while loop
883

    
884
        return newGp;
885
    }
886
    public static FShape transformToInts(Geometry gp, AffineTransform at) {
887
        GeneralPathX newGp = new GeneralPathX();
888
        double[] theData = new double[6];
889
        double[] aux = new double[6];
890

    
891
        // newGp.reset();
892
        PathIterator theIterator;
893
        int theType;
894
        int numParts = 0;
895

    
896
        java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
897
        java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
898
        boolean bFirst = true;
899
        int xInt, yInt, antX = -1, antY = -1;
900

    
901

    
902
        theIterator = gp.getPathIterator(null); //, flatness);
903
        int numSegmentsAdded = 0;
904
        while (!theIterator.isDone()) {
905
            theType = theIterator.currentSegment(theData);
906

    
907
            switch (theType) {
908
                case PathIterator.SEG_MOVETO:
909
                    numParts++;
910
                    ptSrc.setLocation(theData[0], theData[1]);
911
                    at.transform(ptSrc, ptDst);
912
                    antX = (int) ptDst.getX();
913
                    antY = (int) ptDst.getY();
914
                    newGp.moveTo(antX, antY);
915
                    numSegmentsAdded++;
916
                    bFirst = true;
917
                    break;
918

    
919
                case PathIterator.SEG_LINETO:
920
                    ptSrc.setLocation(theData[0], theData[1]);
921
                    at.transform(ptSrc, ptDst);
922
                    xInt = (int) ptDst.getX();
923
                    yInt = (int) ptDst.getY();
924
                    if ((bFirst) || ((xInt != antX) || (yInt != antY)))
925
                    {
926
                        newGp.lineTo(xInt, yInt);
927
                        antX = xInt;
928
                        antY = yInt;
929
                        bFirst = false;
930
                        numSegmentsAdded++;
931
                    }
932
                    break;
933

    
934
                case PathIterator.SEG_QUADTO:
935
                    at.transform(theData,0,aux,0,2);
936
                    newGp.quadTo(aux[0], aux[1], aux[2], aux[3]);
937
                    numSegmentsAdded++;
938
                    break;
939

    
940
                case PathIterator.SEG_CUBICTO:
941
                    at.transform(theData,0,aux,0,3);
942
                    newGp.curveTo(aux[0], aux[1], aux[2], aux[3], aux[4], aux[5]);
943
                    numSegmentsAdded++;
944
                    break;
945

    
946
                case PathIterator.SEG_CLOSE:
947
                    if (numSegmentsAdded < 3)
948
                        newGp.lineTo(antX, antY);
949
                    newGp.closePath();
950

    
951
                    break;
952
            } //end switch
953

    
954
            theIterator.next();
955
        } //end while loop
956

    
957
        FShape shp = null;
958
        switch (gp.getShapeType())
959
        {
960
            case FShape.POINT: //Tipo punto
961
            case FShape.POINT + FShape.Z:
962
                shp = new org.gvsig.fmap.geom.primitive.Point2D(null, null, ptDst.getX(), ptDst.getY());
963
                break;
964

    
965
            case FShape.LINE:
966
            case FShape.LINE + FShape.Z:
967
            case FShape.ARC:
968
                    shp = new Curve2D(null, null, newGp);
969
                break;
970

    
971
            case FShape.POLYGON:
972
            case FShape.POLYGON + FShape.Z:
973
            case FShape.CIRCLE:
974
            case FShape.ELLIPSE:
975

    
976
                shp = new Surface2D(null, null, newGp);
977
                break;
978
        }
979
        return shp;
980
    }
981

    
982
    public static Rectangle2D convertEnvelopeToRectangle2D(Envelope jtsR)
983
    {
984
        Rectangle2D.Double r = new Rectangle2D.Double(jtsR.getMinX(),
985
                jtsR.getMinY(), jtsR.getWidth(), jtsR.getHeight());
986
        return r;
987
    }
988

    
989
    public static Envelope convertRectangle2DtoEnvelope(Rectangle2D r)
990
    {
991
            Envelope e = new Envelope(r.getX(), r.getX() + r.getWidth(), r.getY(),
992
                        r.getY() + r.getHeight());
993
            return e;
994
    }
995

    
996
    /**
997
     * Return a correct polygon (no hole)
998
     * @param coordinates
999
     * @return
1000
     */
1001
    public static Geometry getExteriorPolygon(Coordinate[] coordinates)
1002
    {
1003
            // isCCW = true => it's a hole
1004
            Coordinate[] vs=new Coordinate[coordinates.length];
1005
        if (CGAlgorithms.isCCW(coordinates)){
1006
                for (int i=vs.length-1;i>=0;i--){
1007
                        vs[i]=coordinates[i];
1008
                }
1009
        }else{
1010
                vs=coordinates;
1011
        }
1012
        LinearRing ring = geomFactory.createLinearRing(vs);
1013

    
1014
        try {
1015
                        return GeometryFactory.createPolygon2D(toShape(ring));
1016
                } catch (NoninvertibleTransformException e) {
1017
                        e.printStackTrace();
1018
                }
1019
                return null;
1020
    }
1021

    
1022
    public static boolean isCCW(Point2D[] points)
1023
    {
1024
            Coordinate[] vs=new Coordinate[points.length];
1025
            for (int i=points.length-1;i>=0;i--){
1026
                    vs[i] = new Coordinate(points[i].getX(), points[i].getY());
1027
            }
1028

    
1029
        return CGAlgorithms.isCCW(vs);
1030
    }
1031

    
1032
    public static boolean isCCW(Surface2D pol)
1033
    {
1034
            com.vividsolutions.jts.geom.Geometry jtsGeom = Converter.java2d_to_jts(pol);
1035
            if (jtsGeom.getNumGeometries() == 1)
1036
            {
1037
                    Coordinate[] coords = jtsGeom.getCoordinates();
1038
                    return CGAlgorithms.isCCW(coords);
1039
            }
1040
            return false;
1041

    
1042
    }
1043

    
1044

    
1045
    /**
1046
     * Return a hole (CCW ordered points)
1047
     * @param coordinates
1048
     * @return
1049
     */
1050
    public static Geometry getHole(Coordinate[] coordinates)
1051
    {
1052
            // isCCW = true => it's a hole
1053
            Coordinate[] vs=new Coordinate[coordinates.length];
1054
        if (CGAlgorithms.isCCW(coordinates)){
1055
                vs=coordinates;
1056

    
1057
        }else{
1058
                for (int i=vs.length-1;i>=0;i--){
1059
                        vs[i]=coordinates[i];
1060
                }
1061
        }
1062
        LinearRing ring = geomFactory.createLinearRing(vs);
1063

    
1064
        try {
1065
                        return GeometryFactory.createPolygon2D(toShape(ring));
1066
                } catch (NoninvertibleTransformException e) {
1067
                        e.printStackTrace();
1068
                }
1069
                return null;
1070
    }
1071

    
1072
        public static Shape getExteriorPolygon(GeneralPathX gp) {
1073
                Area area = new Area(gp);
1074
                area.isSingular();
1075
                return area;
1076

    
1077

    
1078

    
1079
        }
1080
        /**
1081
         * Use it ONLY for NOT multipart polygons.
1082
         * @param pol
1083
         * @return
1084
         */
1085
        public static Geometry getNotHolePolygon(Surface2D pol) {
1086
                // isCCW == true => hole
1087
                Coordinate[] coords;
1088
                ArrayList arrayCoords = null;
1089
                int theType;
1090
                int numParts = 0;
1091

    
1092
                //                 Use this array to store segment coordinate data
1093
                double[] theData = new double[6];
1094
                PathIterator theIterator;
1095

    
1096
                                ArrayList shells = new ArrayList();
1097
                                ArrayList holes = new ArrayList();
1098
                                Coordinate[] points = null;
1099

    
1100
                                theIterator = pol.getPathIterator(null, FLATNESS);
1101

    
1102
                                while (!theIterator.isDone()) {
1103
                                        //while not done
1104
                                        theType = theIterator.currentSegment(theData);
1105

    
1106
                                        //Populate a segment of the new
1107
                                        // GeneralPathX object.
1108
                                        //Process the current segment to populate a new
1109
                                        // segment of the new GeneralPathX object.
1110
                                        switch (theType) {
1111
                                                case PathIterator.SEG_MOVETO:
1112

    
1113
                                                        // System.out.println("SEG_MOVETO");
1114
                                                        if (arrayCoords == null) {
1115
                                                                arrayCoords = new ArrayList();
1116
                                                        } else {
1117
                                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
1118

    
1119
                                                                try {
1120
                                                                        LinearRing ring = geomFactory.createLinearRing(points);
1121

    
1122
                                                                        if (CGAlgorithms.isCCW(points)) {
1123
                                                                                holes.add(ring);
1124
                                                                        } else {
1125
                                                                                shells.add(ring);
1126
                                                                        }
1127
                                                                } catch (Exception e) {
1128
                                                                        System.err.println(
1129
                                                                                "Caught Topology exception in GMLLinearRingHandler");
1130

    
1131
                                                                        return null;
1132
                                                                }
1133

    
1134
                                                                /* if (numParts == 1)
1135
                                                                   {
1136
                                                                           linRingExt = new GeometryFactory().createLinearRing(
1137
                                                                                  CoordinateArrays.toCoordinateArray(arrayCoords));
1138
                                                                   }
1139
                                                                   else
1140
                                                                   {
1141
                                                                           linRing = new GeometryFactory().createLinearRing(
1142
                                                                                          CoordinateArrays.toCoordinateArray(arrayCoords));
1143
                                                                           arrayLines.add(linRing);
1144
                                                                   } */
1145
                                                                arrayCoords = new ArrayList();
1146
                                                        }
1147

    
1148
                                                        numParts++;
1149
                                                        arrayCoords.add(new Coordinate(theData[0],
1150
                                                                        theData[1]));
1151

    
1152
                                                        break;
1153

    
1154
                                                case PathIterator.SEG_LINETO:
1155

    
1156
                                                        // System.out.println("SEG_LINETO");
1157
                                                        arrayCoords.add(new Coordinate(theData[0],
1158
                                                                        theData[1]));
1159

    
1160
                                                        break;
1161

    
1162
                                                case PathIterator.SEG_QUADTO:
1163
                                                        System.out.println("SEG_QUADTO Not supported here");
1164

    
1165
                                                        break;
1166

    
1167
                                                case PathIterator.SEG_CUBICTO:
1168
                                                        System.out.println("SEG_CUBICTO Not supported here");
1169

    
1170
                                                        break;
1171

    
1172
                                                case PathIterator.SEG_CLOSE:
1173

    
1174
                                                        // A�adimos el primer punto para cerrar.
1175
                                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1176
                                                        arrayCoords.add(new Coordinate(firstCoord.x,
1177
                                                                        firstCoord.y));
1178

    
1179
                                                        break;
1180
                                        } //end switch
1181

    
1182
                                        // System.out.println("theData[0] = " + theData[0] + " theData[1]=" + theData[1]);
1183
                                        theIterator.next();
1184
                                } //end while loop
1185

    
1186
                                arrayCoords.add(arrayCoords.get(0));
1187
                                coords = CoordinateArrays.toCoordinateArray(arrayCoords);
1188

    
1189

    
1190
                if (numParts == 1)
1191
                {
1192
                        return getExteriorPolygon(coords);
1193
                }
1194
                return GeometryFactory.createGeometry(pol);
1195

    
1196
        }
1197

    
1198

    
1199
    /* public static GeometryCollection convertFGeometryCollection(FGeometryCollection fGeomC)
1200
    {
1201

1202
        geomFactory.createGeometryCollection(theGeoms);
1203
    } */
1204
}