Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.impl / src / main / java / org / gvsig / fmap / geom / util / Converter.java @ 41437

History | View | Annotate | Download (54.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.geom.util;
25

    
26
import java.awt.Shape;
27
import java.awt.geom.AffineTransform;
28
import java.awt.geom.Area;
29
import java.awt.geom.NoninvertibleTransformException;
30
import java.awt.geom.PathIterator;
31
import java.awt.geom.Rectangle2D;
32
import java.lang.reflect.Array;
33
import java.util.ArrayList;
34
import java.util.List;
35

    
36
import org.gvsig.fmap.geom.Geometry;
37
import org.gvsig.fmap.geom.GeometryLocator;
38
import org.gvsig.fmap.geom.GeometryManager;
39
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
40
import org.gvsig.fmap.geom.Geometry.TYPES;
41
import org.gvsig.fmap.geom.aggregate.MultiCurve;
42
import org.gvsig.fmap.geom.aggregate.MultiPoint;
43
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
44
import org.gvsig.fmap.geom.aggregate.MultiSurface;
45
import org.gvsig.fmap.geom.exception.CreateGeometryException;
46
import org.gvsig.fmap.geom.primitive.Curve;
47
import org.gvsig.fmap.geom.primitive.GeneralPathX;
48
import org.gvsig.fmap.geom.primitive.Primitive;
49
import org.gvsig.fmap.geom.primitive.Surface;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

    
53
import com.vividsolutions.jts.algorithm.CGAlgorithms;
54
import com.vividsolutions.jts.algorithm.RobustCGAlgorithms;
55
import com.vividsolutions.jts.geom.Coordinate;
56
import com.vividsolutions.jts.geom.CoordinateArrays;
57
import com.vividsolutions.jts.geom.Envelope;
58
import com.vividsolutions.jts.geom.GeometryCollection;
59
import com.vividsolutions.jts.geom.LineString;
60
import com.vividsolutions.jts.geom.LinearRing;
61
import com.vividsolutions.jts.geom.MultiLineString;
62
import com.vividsolutions.jts.geom.MultiPolygon;
63
import com.vividsolutions.jts.geom.Point;
64
import com.vividsolutions.jts.geom.Polygon;
65

    
66
/**
67
 * Clase con varios metodos estaticos utilizados para pasar de java2d a jts
68
 * y viceversa.
69
 * 
70
 * @author fjp
71
 * @deprecated to be removed or moved from API to implementation in gvSIG 2.1.0
72
 */
73
public class Converter {
74
        private static final GeometryManager geomManager = GeometryLocator.getGeometryManager();
75
        private static final Logger logger = LoggerFactory.getLogger(Converter.class);
76
        public final static com.vividsolutions.jts.geom.GeometryFactory geomFactory = new com.vividsolutions.jts.geom.GeometryFactory();
77
        public static CGAlgorithms cga = new RobustCGAlgorithms();
78

    
79
        private static GeometryManager manager = GeometryLocator.getGeometryManager();
80

    
81
        //returns true if testPoint is a point in the pointList list.
82
        static boolean pointInList(Coordinate testPoint, Coordinate[] pointList) {
83
                int t;
84
                int numpoints;
85
                Coordinate p;
86

    
87
                numpoints = Array.getLength(pointList);
88

    
89
                for (t = 0; t < numpoints; t++) {
90
                        p = pointList[t];
91

    
92
                        if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
93
                                        ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
94
                        ) {
95
                                return true;
96
                        }
97
                }
98

    
99
                return false;
100
        }
101

    
102
        /**
103
         * Receives a JTS Geometry and returns a DAL Geometry
104
         * @param jtsGeometry jts Geometry
105
         * @return IGeometry of FMap
106
         * @author azabala
107
         * @throws CreateGeometryException 
108
         */
109
        public static Geometry jtsToGeometry(com.vividsolutions.jts.geom.Geometry geo) throws CreateGeometryException{
110
                Geometry shpNew = null;
111

    
112
                try {
113
                        if (geo instanceof Point) {
114
                                shpNew = geomManager.createPoint(((Point) geo).getX(),((Point) geo).getY(), SUBTYPES.GEOM2D);
115
                        }
116

    
117
                        if (geo.isEmpty()) {
118
                                shpNew = null;
119
                        }
120

    
121
                        try{
122
                                if (geo instanceof com.vividsolutions.jts.geom.MultiPoint) {
123
                                        shpNew = geomManager.create(TYPES.MULTIPOINT, SUBTYPES.GEOM2D);
124
                                        for (int i = 0; i < geo.getNumGeometries(); i++) {
125
                                                Point point = (Point) geo.getGeometryN(i);
126
                                                ((MultiPoint)shpNew).addPoint((org.gvsig.fmap.geom.primitive.Point) jtsToGeometry(point));
127
                                        }
128
                                        
129
                                }
130
                                
131
                                if (geo instanceof Polygon) {
132
                                        shpNew = geomManager.createSurface(toShape((Polygon) geo), SUBTYPES.GEOM2D);
133
                                }
134

    
135
                                if (geo instanceof MultiPolygon) {
136
                                    /*
137
                                     * We need a loop because a global path would not
138
                                     * differentiate between move-to inside a polygon (holes)
139
                                     * and move-to from one polygon to another
140
                                     */
141
                                    MultiSurface msu = geomManager.createMultiSurface(SUBTYPES.GEOM2D);
142
                                    MultiPolygon mpo = (MultiPolygon) geo;
143
                                    Surface itemsu = null;
144
                                    int npo = mpo.getNumGeometries();
145
                                    for (int i=0; i<npo; i++) {
146
                                        itemsu = geomManager.createSurface(
147
                                            toShape((Polygon) mpo.getGeometryN(i)), SUBTYPES.GEOM2D);
148
                                        msu.addPrimitive(itemsu);
149
                                    }
150
                                        shpNew = msu;
151
                                }
152

    
153
                                if (geo instanceof LineString) {
154
                                        shpNew = geomManager.createCurve(toShape((LineString) geo), SUBTYPES.GEOM2D);
155
                                }
156

    
157
                                if (geo instanceof MultiLineString) {
158
                                        shpNew = geomManager.create(TYPES.MULTICURVE, SUBTYPES.GEOM2D);
159
                                        for (int i = 0; i < ((MultiLineString)geo).getNumGeometries(); i++) {
160
                                                com.vividsolutions.jts.geom.Geometry g = ((MultiLineString)geo).getGeometryN(i);
161
                                                Curve c = geomManager.createCurve(toShape((LineString) g), SUBTYPES.GEOM2D);
162
                                                ((MultiCurve)shpNew).addCurve(c);
163
                                        }
164
                                }
165
                        }catch(CreateGeometryException e){
166
                                logger.error("Error creating a geometry", e);
167
                        }
168

    
169
                        return shpNew;
170
                } catch (NoninvertibleTransformException e) {
171
                        e.printStackTrace();
172
                }
173

    
174
                return null;
175
        }
176

    
177
        /**
178
         * Convierte un MultiPoint2D a un MultiPoint de JTS
179
         * @param geom
180
         * @return
181
         */
182
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiPoint geom) {
183
                Coordinate[] theGeoms = new Coordinate[geom.getPrimitivesNumber()];
184
                for (int i = 0; i < theGeoms.length; i++) {
185
                        java.awt.geom.Point2D p = geom.getPrimitiveAt(i)
186
                        .getHandlers(Geometry.SELECTHANDLER)[0].getPoint();
187
                        Coordinate c = new Coordinate(p.getX(), p.getY());
188
                        theGeoms[i] = c;
189
                }
190
                com.vividsolutions.jts.geom.MultiPoint geomCol = 
191
                        new com.vividsolutions.jts.geom.GeometryFactory().createMultiPoint(theGeoms);
192
                return geomCol;
193
        }
194

    
195
        /**
196
         * Convierte una MultiCurve2D en una MultiLineString de JTS
197
         * @param geom
198
         * @return
199
         */
200
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiCurve geom) {
201
                LineString[] lines = new LineString[geom.getPrimitivesNumber()];
202
                for (int i = 0; i < lines.length; i++) {
203
                        lines[i] = (LineString) geometryToJts((geom.getPrimitiveAt(i)));
204
                }
205
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiLineString(lines);
206
        }
207
        
208
        public static com.vividsolutions.jts.geom.Geometry multiCurveToJts(MultiCurve geom, int srid) {
209
                LineString[] lines = new LineString[geom.getPrimitivesNumber()];
210
                for (int i = 0; i < lines.length; i++){
211
                        lines[i] = (LineString) curveToJts((geom.getPrimitiveAt(i)), srid);
212
                }
213
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiLineString(lines);
214
        }
215

    
216
        /**
217
         * Convierte una MultiSurface2D en un MultiPolygon de JTS
218
         * @return
219
         */
220
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiSurface geom) {
221
                Polygon[] polygons = new Polygon[geom.getPrimitivesNumber()];
222
                for (int i = 0; i < polygons.length; i++){
223
                        polygons[i] = (Polygon) geometryToJts((geom.getPrimitiveAt(i)));
224
                }
225
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiPolygon(polygons);
226
        }
227

    
228
        /**
229
         * Convierte una BaseMultiPrimitive en una GeometryCollection de JTS
230
         * @return
231
         */
232
        public com.vividsolutions.jts.geom.Geometry geometryToJts(MultiPrimitive geom) {
233
                com.vividsolutions.jts.geom.Geometry[] geometriesAux = new LineString[geom.getPrimitivesNumber()];
234
                for (int i = 0; i < geometriesAux.length; i++) {
235
                        geometriesAux[i] = geometryToJts((geom.getPrimitiveAt(i)));
236
                }
237
                return new com.vividsolutions.jts.geom.GeometryFactory().createGeometryCollection(geometriesAux);
238
        }
239

    
240
        public static com.vividsolutions.jts.geom.Geometry geometryToJtsWithSRID(Geometry geom, int srid) {
241
                return geometryToJts(geom, geom.getType(), srid);
242
        }
243
        
244
        public static com.vividsolutions.jts.geom.Geometry geometryToJtsWithSRIDForcingType(Geometry geom, int srid, int type) {
245
                return geometryToJts(geom, type, srid);
246
        }
247

    
248

    
249
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(Geometry geom) {
250
                return geometryToJts(geom, geom.getType(), -1);
251
        }
252

    
253
        private static boolean isClosed(Coordinate firstCoordinate, Coordinate lastCoordinate){
254
                double diff = Math.abs(lastCoordinate.x - firstCoordinate.x);
255
                if (diff > 0.000001) {
256
                        return false;
257
                }
258
                diff = Math.abs(lastCoordinate.y - firstCoordinate.y);
259
                if (diff > 0.000001) {
260
                        return false;
261
                }
262
                return true;
263
        }
264

    
265
        private static com.vividsolutions.jts.geom.Geometry curveToJts(Geometry shp, int srid){
266
                ArrayList arrayLines;
267
                LineString lin = null;
268
                int theType;
269
                int numParts = 0;
270
                double[] dataLine = new double[3];
271
                double[] dataQuad = new double[3];
272
                double[] dataCubic = new double[3];
273
                ArrayList arrayCoords = null;
274
                Coordinate coord;
275
                int subType = shp.getGeometryType().getSubType();
276
                boolean is3D = subType == 1 || subType == 3;
277

    
278
                arrayLines = new ArrayList();
279
                
280
                //El pathIterator no tiene en cuenta coordenadas 3D, por lo que de usar este, las Z's se perder?n
281
                //Las splines vienen con todos los puntos calculados por lo que no es necesario un 
282
                //iterador que interpole. Por esto obtenemos el mismo resultado recorriendo los puntos.
283
                //Tiene su riesgo pero hasta que se soporte el 3D en el iterador funciona para todos los casos
284
                
285
                //theIterator = pol.getPathIterator(null, manager.getFlatness());
286
                GeneralPathX gp = shp.getGeneralPath();
287

    
288
                //while (!theIterator.isDone()) {
289
                int nPoint = 0;
290
                for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
291
                        theType = gp.getTypeAt(nType);
292
                        switch (theType) {
293
                        case PathIterator.SEG_MOVETO:
294
                        case PathIterator.SEG_LINETO: //Se lee un punto
295
                                dataLine = gp.get3DCoordinatesAt(nPoint);
296
                                nPoint ++;
297
                                break;
298
                        case PathIterator.SEG_QUADTO: //Se leen dos puntos
299
                                dataLine = gp.get3DCoordinatesAt(nPoint);
300
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
301
                                nPoint += 2;
302
                                break;
303
                        case PathIterator.SEG_CUBICTO: //Se leen tres puntos
304
                                dataLine = gp.get3DCoordinatesAt(nPoint);
305
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
306
                                dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
307
                                nPoint += 3;
308
                                break;
309
                        }
310

    
311
                        switch (theType) {
312
                        case PathIterator.SEG_MOVETO:
313
                                if (arrayCoords == null) {
314
                                        arrayCoords = new ArrayList();
315
                                } else {
316
                                        lin = geomFactory.createLineString(
317
                                                        CoordinateArrays.toCoordinateArray(arrayCoords));
318
                                        lin.setSRID(srid);
319
                                        arrayLines.add(lin);
320
                                        arrayCoords = new ArrayList();
321
                                }
322

    
323
                                numParts++;
324
                                if(is3D)
325
                                        coord = new Coordinate(dataLine[0], dataLine[1], dataLine[2]);
326
                                else
327
                                        coord = new Coordinate(dataLine[0], dataLine[1]);
328

    
329
                                arrayCoords.add(coord);
330
                                break;
331

    
332
                        case PathIterator.SEG_LINETO:
333
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
334
                                break;
335

    
336
                        case PathIterator.SEG_QUADTO:
337
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
338
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
339
                                break;
340

    
341
                        case PathIterator.SEG_CUBICTO:
342
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
343
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
344
                                loadArrayCoordinates(arrayCoords, is3D, dataCubic);
345
                                break;
346

    
347
                        case PathIterator.SEG_CLOSE:
348
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
349
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
350
                                break;
351
                        } //end switch
352

    
353
                        //theIterator.next();
354
                } //end while loop
355

    
356
                if (arrayCoords.size() < 2) {
357

    
358
                } else {
359
                        lin = new com.vividsolutions.jts.geom.GeometryFactory().createLineString(
360
                                        CoordinateArrays.toCoordinateArray(arrayCoords));
361
                        lin.setSRID(srid);
362
                }
363

    
364
                return lin;
365
        }
366
        
367
        /**
368
         * Convierte un Geometry de DAL a una Geometry del JTS. Para ello, utilizamos un
369
         * flattened PathIterator. El flattened indica que las curvas las pasa a
370
         * segmentos de linea recta AUTOMATICAMENTE!!!.
371
         *
372
         * @param shp FShape que se quiere convertir.
373
         *
374
         * @return Geometry de JTS.
375
         */
376
        private static com.vividsolutions.jts.geom.Geometry geometryToJts(
377
                        Geometry shp, int destinationType, int srid) {
378
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
379
                Coordinate coord;
380
                ArrayList arrayCoords = null;
381
                ArrayList arrayLines;
382
                LineString lin;
383
                int theType;
384
                int numParts = 0;
385
                int sourceType = shp.getGeometryType().getType();
386
                int subType = shp.getGeometryType().getSubType();
387
                boolean is3D = subType == 1 || subType == 3;
388
                
389
                //Use this array to store segment coordinate data
390
                double[] dataLine = new double[3];
391
                double[] dataQuad = new double[3];
392
                double[] dataCubic = new double[3];
393

    
394
                switch (sourceType) {
395
                case Geometry.TYPES.POINT:
396
                        if(is3D) {
397
                                org.gvsig.fmap.geom.primitive.impl.Point2DZ p = (org.gvsig.fmap.geom.primitive.impl.Point2DZ) shp;
398
                                coord = new Coordinate(p.getX(), p.getY(), p.getCoordinateAt(Geometry.DIMENSIONS.Z));
399
                        } else {
400
                                org.gvsig.fmap.geom.primitive.impl.Point2D p = (org.gvsig.fmap.geom.primitive.impl.Point2D) shp;
401
                                coord = new Coordinate(p.getX(), p.getY());
402
                        }
403
                        geoJTS = geomFactory.createPoint(coord);
404
                        geoJTS.setSRID(srid);
405
                        break;
406

    
407
                case Geometry.TYPES.CURVE:
408
                case Geometry.TYPES.ARC:
409
        case Geometry.TYPES.SPLINE:
410
        case Geometry.TYPES.ELLIPTICARC:
411

    
412
                        arrayLines = new ArrayList();
413
                        
414
                        //El pathIterator no tiene en cuenta coordenadas 3D, por lo que de usar este, las Z's se perder?n
415
                        //Las splines vienen con todos los puntos calculados por lo que no es necesario un 
416
                        //iterador que interpole. Por esto obtenemos el mismo resultado recorriendo los puntos.
417
                        //Tiene su riesgo pero hasta que se soporte el 3D en el iterador funciona para todos los casos
418
                        
419
                        //theIterator = pol.getPathIterator(null, manager.getFlatness());
420
                        GeneralPathX gp = shp.getGeneralPath();
421

    
422
                        //while (!theIterator.isDone()) {
423
                        int nPoint = 0;
424
                        for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
425
                                theType = gp.getTypeAt(nType);
426
                                switch (theType) {
427
                                case PathIterator.SEG_MOVETO:
428
                                case PathIterator.SEG_LINETO: //Se lee un punto
429
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
430
                                        nPoint ++;
431
                                        break;
432
                                case PathIterator.SEG_QUADTO: //Se leen dos puntos
433
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
434
                                        dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
435
                                        nPoint += 2;
436
                                        break;
437
                                case PathIterator.SEG_CUBICTO: //Se leen tres puntos
438
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
439
                                        dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
440
                                        dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
441
                                        nPoint += 3;
442
                                        break;
443
                                }
444

    
445
                                //Populate a segment of the new
446
                                // GeneralPathX object.
447
                                //Process the current segment to populate a new
448
                                // segment of the new GeneralPathX object.
449
                                switch (theType) {
450
                                case PathIterator.SEG_MOVETO:
451
                                        if (arrayCoords == null) {
452
                                                arrayCoords = new ArrayList();
453
                                        } else {
454
                                                lin = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(arrayCoords));
455
                                                lin.setSRID(srid);
456
                                                arrayLines.add(lin);
457
                                                arrayCoords = new ArrayList();
458
                                        }
459

    
460
                                        numParts++;
461
                                        if(is3D)
462
                                                coord = new Coordinate(dataLine[0], dataLine[1], dataLine[2]);
463
                                        else
464
                                                coord = new Coordinate(dataLine[0], dataLine[1]);
465
                                        
466
                                        arrayCoords.add(coord);
467
                                        break;
468

    
469
                                case PathIterator.SEG_LINETO:
470
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
471
                                        break;
472

    
473
                                case PathIterator.SEG_QUADTO:
474
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
475
                                        loadArrayCoordinates(arrayCoords, is3D, dataQuad);
476
                                        break;
477

    
478
                                case PathIterator.SEG_CUBICTO:
479
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
480
                                        loadArrayCoordinates(arrayCoords, is3D, dataQuad);
481
                                        loadArrayCoordinates(arrayCoords, is3D, dataCubic);
482
                                        break;
483

    
484
                                case PathIterator.SEG_CLOSE:
485
                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
486
                                        loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
487
                                        break;
488
                                } //end switch
489

    
490
                                //theIterator.next();
491
                        } //end while loop
492

    
493
                        if (arrayCoords.size() < 2) {
494
                                break;
495
                        }
496
                        lin = new com.vividsolutions.jts.geom.GeometryFactory().createLineString(
497
                                        CoordinateArrays.toCoordinateArray(arrayCoords));
498

    
499
                        lin.setSRID(srid);
500
                        geoJTS = lin;
501
                        
502
                        /*
503
                         * We were creating always a multilinestring here, but
504
                         * we have decided that we should return the correct type
505
                         * (linestring) and other parts of the application will have
506
                         * to solve the problem, it there is a problem with this.
507
                         * 
508
                        arrayLines.add(lin);
509
                        geoJTS = geomFactory.createMultiLineString(
510
                                        com.vividsolutions.jts.geom.GeometryFactory.toLineStringArray(arrayLines));
511
                        geoJTS.setSRID(srid);
512
                        */
513
                        break;
514

    
515
                case Geometry.TYPES.SURFACE:
516
                case Geometry.TYPES.CIRCLE:
517
                case Geometry.TYPES.ELLIPSE:
518
                        arrayLines = new ArrayList();
519

    
520
                        ArrayList shells = new ArrayList();
521
                        ArrayList holes = new ArrayList();
522
                        Coordinate[] points = null;
523

    
524
                        //El pathIterator no tiene en cuenta coordenadas 3D, pero para la creaci?n de elipses y circulos
525
                        //es necesario el iterador que interpole puntos. El resultado es que en la creaci?n de geometr?as de este
526
                        //tipo no se puede asignar la Z porque se perder?a, pero gvSIG tampoco dispone de esta funci?n, as? que
527
                        //no se nota. Una vez creadas las geometr?a de tipo Elipse y circulo cuando las editamos ya tendr?n todos
528
                        //los puntos calculados y se toman como l?neas por lo que ya se podr?a asignar la Z.
529
                        
530
                        PathIterator theIterator = shp.getPathIterator(null, manager.getFlatness());
531
                        while (!theIterator.isDone()) {
532
                                theType = theIterator.currentSegment(dataLine);
533
                                
534
                                switch (theType) {
535
                                case PathIterator.SEG_MOVETO:
536
                                        if (arrayCoords == null) {
537
                                                arrayCoords = new ArrayList();
538
                                        } else {
539
                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
540

    
541
                                                try {
542
                                                        LinearRing ring = geomFactory.createLinearRing(points);
543

    
544
                                                        if (CGAlgorithms.isCCW(points)) {
545
                                                                holes.add(ring);
546
                                                        } else {
547
                                                                shells.add(ring);
548
                                                        }
549
                                                } catch (Exception e) {
550
                                                        boolean same = true;
551
                                                        for (int i = 0; i < points.length-1 && same; i++) {
552
                                                                if (points[i].x != points[i+1].x ||
553
                                                                                points[i].y != points[i+1].y /*||
554
                                                                                points[i].z != points[i+1].z*/
555
                                                                ) {
556
                                                                        same = false;
557
                                                                }
558
                                                        }
559
                                                        if (same) {
560
                                                                return geomFactory.createPoint(points[0]);
561
                                                        }
562
                                                        if (points.length>1 && points.length <= 3) {
563
                                                                // return geomFactory.createLineString(points);
564
                                                                return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
565
                                                        }
566

    
567
                                                        System.err.println(
568
                                                        "Caught Topology exception in GMLLinearRingHandler");
569

    
570
                                                        return null;
571
                                                }
572
                                                arrayCoords = new ArrayList();
573
                                        }
574

    
575
                                        numParts++;
576
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
577
                                        break;
578

    
579
                                case PathIterator.SEG_LINETO:
580
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
581
                                        break;
582

    
583
                                case PathIterator.SEG_QUADTO:
584
                                        break;
585

    
586
                                case PathIterator.SEG_CUBICTO:
587
                                        break;
588

    
589
                                case PathIterator.SEG_CLOSE:
590
                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
591
                                        loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
592
                                        break;
593
                                } //end switch
594

    
595
                                theIterator.next();
596
                        } //end while loop
597

    
598

    
599
                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
600
                        Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
601
                        if (!isClosed(firstCoord, lastCoord)) {
602
                                arrayCoords.add(firstCoord);
603
                        }
604
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
605

    
606
                        try {
607
                                LinearRing ring = geomFactory.createLinearRing(points);
608

    
609
                                if (CGAlgorithms.isCCW(points)) {
610
                                        holes.add(ring);
611
                                } else {
612
                                        shells.add(ring);
613
                                }
614
                                ring.setSRID(srid);
615
                        } catch (Exception e) {
616
                                boolean same = true;
617
                                for (int i = 0; i < points.length-1 && same; i++) {
618
                                        if (points[i].x != points[i+1].x ||
619
                                                        points[i].y != points[i+1].y /*||
620
                                                        points[i].z != points[i+1].z*/
621
                                        ) {
622
                                                same = false;
623
                                        }
624
                                }
625
                                if (same) {
626
                                        geoJTS = geomFactory.createPoint(points[0]);
627
                                        geoJTS.setSRID(srid);
628
                                        return geoJTS;
629
                                }
630
                                /*
631
                                 * caso cuando es una linea de 3 puntos, no creo un LinearRing, sino
632
                                 * una linea
633
                                 */
634
                                if (points.length > 1 && points.length <= 3) {
635
                                        // return geomFactory.createLineString(points);
636
                                        geoJTS = geomFactory.createMultiLineString(new LineString[] { geomFactory.createLineString(points) });
637
                                        geoJTS.setSRID(srid);
638
                                        return geoJTS;
639
                                }
640
                                System.err.println("Caught Topology exception in GMLLinearRingHandler");
641

    
642
                                return null;
643
                        }
644

    
645
                        /* linRing = new GeometryFactory().createLinearRing(
646
                         CoordinateArrays.toCoordinateArray(arrayCoords)); */
647

    
648
                        // System.out.println("NumParts = " + numParts);
649
                        //now we have a list of all shells and all holes
650
                        ArrayList holesForShells = new ArrayList(shells.size());
651

    
652
                        for (int i = 0; i < shells.size(); i++) {
653
                                holesForShells.add(new ArrayList());
654
                        }
655

    
656
                        //find homes
657
                        for (int i = 0; i < holes.size(); i++) {
658
                                LinearRing testRing = (LinearRing) holes.get(i);
659
                                LinearRing minShell = null;
660
                                Envelope minEnv = null;
661
                                Envelope testEnv = testRing.getEnvelopeInternal();
662
                                Coordinate testPt = testRing.getCoordinateN(0);
663
                                LinearRing tryRing = null;
664

    
665
                                for (int j = 0; j < shells.size(); j++) {
666
                                        tryRing = (LinearRing) shells.get(j);
667

    
668
                                        Envelope tryEnv = tryRing.getEnvelopeInternal();
669

    
670
                                        if (minShell != null) {
671
                                                minEnv = minShell.getEnvelopeInternal();
672
                                        }
673

    
674
                                        boolean isContained = false;
675
                                        Coordinate[] coordList = tryRing.getCoordinates();
676

    
677
                                        if (tryEnv.contains(testEnv) &&
678
                                                        (CGAlgorithms.isPointInRing(testPt, coordList) ||
679
                                                                        (pointInList(testPt, coordList)))) {
680
                                                isContained = true;
681
                                        }
682

    
683
                                        // check if this new containing ring is smaller than the current minimum ring
684
                                        if (isContained) {
685
                                                if ((minShell == null) || minEnv.contains(tryEnv)) {
686
                                                        minShell = tryRing;
687
                                                }
688
                                        }
689
                                }
690

    
691
                                if (minShell == null) {
692
                                        //                                        System.out.println(
693
                                        //                                        polygon found with a hole thats not inside a shell);
694
                                        //                                        azabala: we do the assumption that this hole is really a shell (polygon)
695
                                        //                                        whose point werent digitized in the right order
696
                                        Coordinate[] cs = testRing.getCoordinates();
697
                                        Coordinate[] reversed = new Coordinate[cs.length];
698
                                        int pointIndex = 0;
699
                                        for(int z = cs.length-1; z >= 0; z--){
700
                                                reversed[pointIndex] = cs[z];
701
                                                pointIndex++;
702
                                        }
703
                                        LinearRing newRing = geomFactory.createLinearRing(reversed);
704
                                        shells.add(newRing);
705
                                        holesForShells.add(new ArrayList());
706
                                } else {
707
                                        ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
708
                                }
709
                        }
710

    
711
                        Polygon[] polygons = new Polygon[shells.size()];
712

    
713
                        for (int i = 0; i < shells.size(); i++) {
714
                                polygons[i] = geomFactory.createPolygon(
715
                                                (LinearRing) shells.get(i),
716
                                                (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
717
                                polygons[i].setSRID(srid);
718
                        }
719
                        // CAMBIO: ENTREGAMOS SIEMPRE MULTILINESTRING, QUE ES
720
                        // LO QUE HACE TO_DO EL MUNDO CUANDO ESCRIBE EN POSTGIS
721
                        // O CON GEOTOOLS
722
                        // if (numParts > 1) // Generamos una MultiLineString
723

    
724
                        /* if (polygons.length == 1) {
725
                         return polygons[0];
726
                         } */
727

    
728
                        // FIN CAMBIO
729

    
730
                        holesForShells = null;
731
                        shells = null;
732
                        holes = null;
733

    
734
                        if (polygons.length == 1) {
735
                                geoJTS = polygons[0];
736
                        } else {
737
                                // its a multi part
738
                                geoJTS = geomFactory.createMultiPolygon(polygons);
739
                        }
740
                        geoJTS.setSRID(srid);
741
                        //its a multi part
742
                        //geoJTS = geomFactory.createMultiPolygon(polygons);
743
                        //geoJTS.setSRID(srid);
744

    
745
                        break;
746

    
747
                case Geometry.TYPES.MULTICURVE:
748
                        geoJTS = multiCurveToJts((MultiCurve)shp, srid);
749
                        geoJTS.setSRID(srid);
750
                        break;
751

    
752
                case Geometry.TYPES.MULTIPOINT:
753
                        geoJTS = geometryToJts((MultiPoint)shp);
754
                        geoJTS.setSRID(srid);
755
                        break;
756

    
757
                case Geometry.TYPES.MULTISURFACE:
758
                        geoJTS = multiSurfaceToJts((MultiSurface)shp, srid);
759
                        geoJTS.setSRID(srid);
760
                        break;
761
                }
762

    
763
                if(destinationType != sourceType)
764
                        geoJTS = convertTypes(geoJTS, sourceType, destinationType);
765
                
766
                geoJTS.setSRID(srid);
767
                return geoJTS;
768
        }
769
        
770
        /**
771
         * This function is called when the we need force types, that is the destination 
772
         * type does not match with the input geometry type
773
         * @param g
774
         * @param sourceType
775
         * @param destinationType
776
         * @return
777
         */
778
        private static com.vividsolutions.jts.geom.Geometry convertTypes(
779
                        com.vividsolutions.jts.geom.Geometry g,
780
                        int sourceType,
781
                        int destinationType) {
782
                if((sourceType == Geometry.TYPES.CURVE || 
783
                        sourceType == Geometry.TYPES.SPLINE || 
784
                        sourceType == Geometry.TYPES.ARC ||
785
                        sourceType == Geometry.TYPES.ELLIPTICARC) 
786
                        && destinationType == Geometry.TYPES.MULTISURFACE) {
787
                        if(g instanceof MultiLineString) {
788
                                Polygon[] poly = new Polygon[((MultiLineString)g).getNumGeometries()];
789
                                for (int i = 0; i < ((MultiLineString)g).getNumGeometries(); i++) {
790
                                        com.vividsolutions.jts.geom.Geometry lineString = ((MultiLineString)g).getGeometryN(i);
791
                                        poly[i] = convertLineStringToPolygon((LineString)lineString);
792
                                }
793
                                return geomFactory.createMultiPolygon(poly);
794
                        } else
795
                                return convertLineStringToPolygon((LineString)g);
796
                }
797
                
798
                if((sourceType == Geometry.TYPES.CIRCLE || 
799
                        sourceType == Geometry.TYPES.ELLIPSE) && 
800
                        destinationType == Geometry.TYPES.MULTICURVE) {
801
                        if(g instanceof Polygon) {
802
                                Polygon poly = (Polygon)g; 
803
                                LineString lineString = geomFactory.createLinearRing(poly.getCoordinates());
804
                                return geomFactory.createMultiLineString(new LineString[]{lineString});
805
                        }
806
                }
807
                return g;
808
        }
809

    
810
        private static com.vividsolutions.jts.geom.Polygon convertLineStringToPolygon(LineString line) {
811
                Coordinate[] coordinates = line.getCoordinates();
812
                LinearRing shell = geomFactory.createLinearRing(coordinates);
813
                Polygon pol = geomFactory.createPolygon(shell, null);
814
                return pol;
815
        }
816
        
817
        /**
818
         * DOCUMENT ME!
819
         *
820
         * @param p DOCUMENT ME!
821
         *
822
         * @return DOCUMENT ME!
823
         */
824
        private static GeneralPathX toShape(Polygon p) {
825
                GeneralPathX resul = new GeneralPathX();
826
                Coordinate coord;
827

    
828
                for (int i = 0; i < p.getExteriorRing().getNumPoints(); i++) {
829
                        coord = p.getExteriorRing().getCoordinateN(i);
830

    
831
                        if (i == 0) {
832
                                resul.moveTo(coord.x, coord.y);
833
                        } else {
834
                                resul.lineTo(coord.x, coord.y);
835
                        }
836
                }
837

    
838
                for (int j = 0; j < p.getNumInteriorRing(); j++) {
839
                        LineString hole = p.getInteriorRingN(j);
840

    
841
                        for (int k = 0; k < hole.getNumPoints(); k++) {
842
                                coord = hole.getCoordinateN(k);
843

    
844
                                if (k == 0) {
845
                                        resul.moveTo(coord.x, coord.y);
846
                                } else {
847
                                        resul.lineTo(coord.x, coord.y);
848
                                }
849
                        }
850
                }
851

    
852
                return resul;
853
        }
854

    
855

    
856
        private static GeneralPathX toShape(MultiLineString mls)
857
        throws NoninvertibleTransformException, CreateGeometryException {
858
                GeneralPathX path = new GeneralPathX();
859

    
860
                for (int i = 0; i < mls.getNumGeometries(); i++) {
861
                        LineString lineString = (LineString) mls.getGeometryN(i);
862
                        path.append(toShape(lineString).getPathIterator(null), false);
863
                }
864

    
865
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
866
                //converted to GeneralPathXs. [Jon Aquino]
867
                return path;
868
        }
869

    
870
        /**
871
         * DOCUMENT ME!
872
         *
873
         * @param lineString DOCUMENT ME!
874
         *
875
         * @return DOCUMENT ME!
876
         *
877
         * @throws NoninvertibleTransformException DOCUMENT ME!
878
         * @throws CreateGeometryException 
879
         */
880
        private static GeneralPathX toShape(LineString lineString)
881
        throws NoninvertibleTransformException, CreateGeometryException {
882
                GeneralPathX shape = new GeneralPathX();
883
                org.gvsig.fmap.geom.primitive.Point viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(0));
884
                shape.moveTo(viewPoint.getX(), viewPoint.getY());
885

    
886
                for (int i = 1; i < lineString.getNumPoints(); i++) {
887
                        viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(i));
888
                        shape.lineTo(viewPoint.getX(), viewPoint.getY());
889
                }
890

    
891
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
892
                //converted to GeneralPathXs. [Jon Aquino]
893
                return shape;
894
        }
895

    
896

    
897
        /**
898
         *
899
         */
900
        private static GeneralPathX toShape(MultiPolygon mp)
901
        throws NoninvertibleTransformException {
902
                GeneralPathX path = new GeneralPathX();
903

    
904
                for (int i = 0; i < mp.getNumGeometries(); i++) {
905
                        Polygon polygon = (Polygon) mp.getGeometryN(i);
906
                        path.append(toShape(polygon).getPathIterator(null), false);
907
                }
908

    
909
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
910
                //converted to GeneralPathXs. [Jon Aquino]
911
                return path;
912
        }
913
        /**
914
         * DOCUMENT ME!
915
         *
916
         * @param coord DOCUMENT ME!
917
         *
918
         * @return DOCUMENT ME!
919
         * @throws CreateGeometryException 
920
         */
921
        public static org.gvsig.fmap.geom.primitive.Point coordinate2FPoint2D(Coordinate coord) throws CreateGeometryException {
922
                return geomManager.createPoint(coord.x, coord.y, SUBTYPES.GEOM2D); //,coord.z);
923
        }
924

    
925
        /**
926
         * Convierte una Geometry de JTS a GeneralPathX.
927
         *
928
         * @param geometry Geometry a convertir.
929
         *
930
         * @return GeneralPathX.
931
         *
932
         * @throws NoninvertibleTransformException
933
         * @throws CreateGeometryException 
934
         * @throws IllegalArgumentException
935
         */
936
        public static GeneralPathX toShape(com.vividsolutions.jts.geom.Geometry geometry)
937
        throws NoninvertibleTransformException, CreateGeometryException {
938
                if (geometry.isEmpty()) {
939
                        return new GeneralPathX();
940
                }
941

    
942
                if (geometry instanceof Polygon) {
943
                        return toShape((Polygon) geometry);
944
                }
945

    
946
                if (geometry instanceof MultiPolygon) {
947
                        return toShape((MultiPolygon) geometry);
948
                }
949

    
950
                if (geometry instanceof LineString) {
951
                        return toShape((LineString) geometry);
952
                }
953

    
954
                if (geometry instanceof MultiLineString) {
955
                        return toShape((MultiLineString) geometry);
956
                }
957

    
958
                if (geometry instanceof GeometryCollection) {
959
                        return toShape(geometry);
960
                }
961

    
962
                throw new IllegalArgumentException("Unrecognized Geometry class: " +
963
                                geometry.getClass());
964
        }
965

    
966

    
967
        public static GeneralPathX transformToInts(GeneralPathX gp, AffineTransform at) {
968
                GeneralPathX newGp = new GeneralPathX();
969
                PathIterator theIterator;
970
                int theType;
971
                int numParts = 0;
972
                double[] theData = new double[6];
973
                java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
974
                java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
975
                boolean bFirst = true;
976
                int xInt, yInt, antX = -1, antY = -1;
977

    
978
                theIterator = gp.getPathIterator(null); //, flatness);
979

    
980
                while (!theIterator.isDone()) {
981
                        theType = theIterator.currentSegment(theData);
982
                        switch (theType) {
983
                        case PathIterator.SEG_MOVETO:
984
                                numParts++;
985
                                ptSrc.setLocation(theData[0], theData[1]);
986
                                at.transform(ptSrc, ptDst);
987
                                antX = (int) ptDst.getX();
988
                                antY = (int) ptDst.getY();
989
                                newGp.moveTo(antX, antY);
990
                                bFirst = true;
991
                                break;
992

    
993
                        case PathIterator.SEG_LINETO:
994
                                ptSrc.setLocation(theData[0], theData[1]);
995
                                at.transform(ptSrc, ptDst);
996
                                xInt = (int) ptDst.getX();
997
                                yInt = (int) ptDst.getY();
998
                                if ((bFirst) || ((xInt != antX) || (yInt != antY)))
999
                                {
1000
                                        newGp.lineTo(xInt, yInt);
1001
                                        antX = xInt;
1002
                                        antY = yInt;
1003
                                        bFirst = false;
1004
                                }
1005
                                break;
1006

    
1007
                        case PathIterator.SEG_QUADTO:
1008
                                System.out.println("Not supported here");
1009

    
1010
                                break;
1011

    
1012
                        case PathIterator.SEG_CUBICTO:
1013
                                System.out.println("Not supported here");
1014

    
1015
                                break;
1016

    
1017
                        case PathIterator.SEG_CLOSE:
1018
                                newGp.closePath();
1019

    
1020
                                break;
1021
                        } //end switch
1022

    
1023
                        theIterator.next();
1024
                } //end while loop
1025

    
1026
                return newGp;
1027
        }
1028
        public static Geometry transformToInts(Geometry gp, AffineTransform at) throws CreateGeometryException {
1029
                GeneralPathX newGp = new GeneralPathX();
1030
                double[] theData = new double[6];
1031
                double[] aux = new double[6];
1032

    
1033
                // newGp.reset();
1034
                PathIterator theIterator;
1035
                int theType;
1036
                int numParts = 0;
1037

    
1038
                java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
1039
                java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
1040
                boolean bFirst = true;
1041
                int xInt, yInt, antX = -1, antY = -1;
1042

    
1043

    
1044
                theIterator = gp.getPathIterator(null); //, flatness);
1045
                int numSegmentsAdded = 0;
1046
                while (!theIterator.isDone()) {
1047
                        theType = theIterator.currentSegment(theData);
1048

    
1049
                        switch (theType) {
1050
                        case PathIterator.SEG_MOVETO:
1051
                                numParts++;
1052
                                ptSrc.setLocation(theData[0], theData[1]);
1053
                                at.transform(ptSrc, ptDst);
1054
                                antX = (int) ptDst.getX();
1055
                                antY = (int) ptDst.getY();
1056
                                newGp.moveTo(antX, antY);
1057
                                numSegmentsAdded++;
1058
                                bFirst = true;
1059
                                break;
1060

    
1061
                        case PathIterator.SEG_LINETO:
1062
                                ptSrc.setLocation(theData[0], theData[1]);
1063
                                at.transform(ptSrc, ptDst);
1064
                                xInt = (int) ptDst.getX();
1065
                                yInt = (int) ptDst.getY();
1066
                                if ((bFirst) || ((xInt != antX) || (yInt != antY)))
1067
                                {
1068
                                        newGp.lineTo(xInt, yInt);
1069
                                        antX = xInt;
1070
                                        antY = yInt;
1071
                                        bFirst = false;
1072
                                        numSegmentsAdded++;
1073
                                }
1074
                                break;
1075

    
1076
                        case PathIterator.SEG_QUADTO:
1077
                                at.transform(theData,0,aux,0,2);
1078
                                newGp.quadTo(aux[0], aux[1], aux[2], aux[3]);
1079
                                numSegmentsAdded++;
1080
                                break;
1081

    
1082
                        case PathIterator.SEG_CUBICTO:
1083
                                at.transform(theData,0,aux,0,3);
1084
                                newGp.curveTo(aux[0], aux[1], aux[2], aux[3], aux[4], aux[5]);
1085
                                numSegmentsAdded++;
1086
                                break;
1087

    
1088
                        case PathIterator.SEG_CLOSE:
1089
                                if (numSegmentsAdded < 3) {
1090
                                        newGp.lineTo(antX, antY);
1091
                                }
1092
                                newGp.closePath();
1093

    
1094
                                break;
1095
                        } //end switch
1096

    
1097
                        theIterator.next();
1098
                } //end while loop
1099

    
1100
                Geometry shp = null;
1101
                switch (gp.getType())
1102
                {
1103
                case Geometry.TYPES.POINT:
1104
                        shp = geomManager.createPoint(ptDst.getX(), ptDst.getY(), SUBTYPES.GEOM2D); 
1105
                        break;
1106

    
1107
                case Geometry.TYPES.CURVE:
1108
        case Geometry.TYPES.ARC:
1109
        case Geometry.TYPES.ELLIPTICARC:
1110
                        try {
1111
                                shp = geomManager.createCurve(newGp, SUBTYPES.GEOM2D);
1112
                        } catch (CreateGeometryException e1) {
1113
                                logger.error("Error creating a curve", e1);
1114
                        }
1115
                        break;
1116

    
1117
                case Geometry.TYPES.SURFACE:
1118
                case Geometry.TYPES.CIRCLE:
1119
                case Geometry.TYPES.ELLIPSE:
1120

    
1121
                        try {
1122
                                shp = geomManager.createSurface(newGp, SUBTYPES.GEOM2D);
1123
                        } catch (CreateGeometryException e) {
1124
                                logger.error("Error creating a surface", e);
1125
                        }
1126
                        break;
1127
                }
1128
                return shp;
1129
        }
1130

    
1131
        public static Rectangle2D convertEnvelopeToRectangle2D(Envelope jtsR) {
1132
                Rectangle2D.Double r = new Rectangle2D.Double(jtsR.getMinX(),
1133
                                jtsR.getMinY(), jtsR.getWidth(), jtsR.getHeight());
1134
                return r;
1135
        }
1136

    
1137
        public static Envelope convertEnvelopeToJTS(org.gvsig.fmap.geom.primitive.Envelope r) {
1138
                Envelope e = new Envelope(r.getMinimum(0), r.getMaximum(0), r.getMinimum(1),
1139
                                r.getMaximum(1));
1140
                return e;
1141
        }
1142

    
1143
        /**
1144
         * Return a correct polygon (no hole)
1145
         * @param coordinates
1146
         * @return
1147
         */
1148
        public static Geometry getExteriorPolygon(Coordinate[] coordinates) {
1149
                // isCCW = true => it's a hole
1150
                Coordinate[] vs = new Coordinate[coordinates.length];
1151
                if (CGAlgorithms.isCCW(coordinates)) {
1152
                        for (int i = vs.length-1;i >= 0; i--){
1153
                                vs[i] = coordinates[i];
1154
                        }
1155
                } else {
1156
                        vs = coordinates;
1157
                }
1158
                LinearRing ring = geomFactory.createLinearRing(vs);
1159

    
1160
                try {
1161
                        Surface surface = (Surface)manager.create(TYPES.SURFACE, SUBTYPES.GEOM2D);
1162
                        surface.setGeneralPath(toShape(ring));
1163
                        return surface;
1164
                } catch (NoninvertibleTransformException e) {
1165
                        e.printStackTrace();
1166
                } catch (CreateGeometryException e) {
1167
                        e.printStackTrace();
1168
                }
1169
                return null;
1170
        }
1171

    
1172
        public static boolean isCCW(Point[] points) {
1173
                int length = points.length;
1174
                Coordinate[] vs;
1175

    
1176
                if (points[0].getX() != points[length-1].getX() || points[0].getY() != points[length-1].getY()) {
1177
                        vs=new Coordinate[length+1];
1178
                        vs[points.length] = new Coordinate(points[0].getX(), points[0].getY());
1179
                } else {
1180
                        vs=new Coordinate[length];
1181
                }
1182
                for (int i = 0; i < length; i++) {
1183
                        vs[i] = new Coordinate(points[i].getX(), points[i].getY());
1184
                }
1185

    
1186
                return CGAlgorithms.isCCW(vs);
1187
        }
1188

    
1189
        public static boolean isCCW(Surface pol) {
1190
                com.vividsolutions.jts.geom.Geometry jtsGeom = Converter.geometryToJts(pol);
1191
                if (jtsGeom.getNumGeometries() == 1) {
1192
                        Coordinate[] coords = jtsGeom.getCoordinates();
1193
                        return CGAlgorithms.isCCW(coords);
1194
                }
1195
                return false;
1196
        }
1197

    
1198
        /**
1199
         * Return a hole (CCW ordered points)
1200
         * @param coordinates
1201
         * @return
1202
         */
1203
        public static Geometry getHole(Coordinate[] coordinates) {
1204
                Coordinate[] vs = new Coordinate[coordinates.length];
1205
                if (CGAlgorithms.isCCW(coordinates)) {
1206
                        vs=coordinates;
1207

    
1208
                }else{
1209
                        for (int i = vs.length-1; i >= 0; i--) {
1210
                                vs[i] = coordinates[i];
1211
                        }
1212
                }
1213
                LinearRing ring = geomFactory.createLinearRing(vs);
1214

    
1215
                try {
1216
                        Surface surface = (Surface)manager.create(TYPES.SURFACE, SUBTYPES.GEOM2D);
1217
                        surface.setGeneralPath(toShape(ring));
1218
                        return surface;
1219
                } catch (NoninvertibleTransformException e) {
1220
                        e.printStackTrace();
1221
                } catch (CreateGeometryException e) {
1222
                        e.printStackTrace();
1223
                }
1224
                return null;
1225
        }
1226

    
1227
        public static Shape getExteriorPolygon(GeneralPathX gp) {
1228
                Area area = new Area(gp);
1229
                area.isSingular();
1230
                return area;
1231
        }
1232
        
1233
        /**
1234
         * Use it ONLY for NOT multipart polygons.
1235
         * @param pol
1236
         * @return
1237
         */
1238
        public static Geometry getNotHolePolygon(Surface pol) {
1239
                // isCCW == true => hole
1240
                Coordinate[] coords;
1241
                ArrayList arrayCoords = null;
1242
                int theType;
1243
                int numParts = 0;
1244

    
1245
                //Use this array to store segment coordinate data
1246
                double[] theData = new double[4];
1247

    
1248
                ArrayList shells = new ArrayList();
1249
                ArrayList holes = new ArrayList();
1250
                Coordinate[] points = null;
1251
                
1252
                int subType = pol.getGeometryType().getSubType();
1253
                boolean is3D = subType == 1 || subType == 3;
1254
                
1255
                //El pathIterator no tiene en cuenta coordenadas 3D
1256
                //theIterator = pol.getPathIterator(null, manager.getFlatness());
1257
                GeneralPathX gp = pol.getGeneralPath();
1258

    
1259
                //while (!theIterator.isDone()) {
1260
                for (int nPoint = 0; nPoint < gp.getNumCoords(); nPoint++) {
1261
                        theData = gp.getCoordinatesAt(nPoint);
1262
                        theType = gp.getTypeAt(nPoint);
1263

    
1264
                        //Populate a segment of the new
1265
                        // GeneralPathX object.
1266
                        //Process the current segment to populate a new
1267
                        // segment of the new GeneralPathX object.
1268
                        switch (theType) {
1269
                        case PathIterator.SEG_MOVETO:
1270

    
1271
                                // System.out.println("SEG_MOVETO");
1272
                                if (arrayCoords == null) {
1273
                                        arrayCoords = new ArrayList();
1274
                                } else {
1275
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1276

    
1277
                                        try {
1278
                                                LinearRing ring = geomFactory.createLinearRing(points);
1279

    
1280
                                                if (CGAlgorithms.isCCW(points)) {
1281
                                                        holes.add(ring);
1282
                                                } else {
1283
                                                        shells.add(ring);
1284
                                                }
1285
                                        } catch (Exception e) {
1286
                                                System.err.println("Caught Topology exception in GMLLinearRingHandler");
1287

    
1288
                                                return null;
1289
                                        }
1290
                                        arrayCoords = new ArrayList();
1291
                                }
1292

    
1293
                                numParts++;
1294
                                if(is3D)
1295
                                        arrayCoords.add(new Coordinate(theData[0], theData[1], theData[2]));
1296
                                else
1297
                                        arrayCoords.add(new Coordinate(theData[0], theData[1]));
1298

    
1299
                                break;
1300

    
1301
                        case PathIterator.SEG_LINETO:
1302
                                if(is3D)
1303
                                        arrayCoords.add(new Coordinate(theData[0], theData[1], theData[2]));
1304
                                else
1305
                                        arrayCoords.add(new Coordinate(theData[0], theData[1]));
1306
                                break;
1307
                        case PathIterator.SEG_QUADTO:
1308
                                System.out.println("SEG_QUADTO Not supported here");
1309
                                break;
1310
                        case PathIterator.SEG_CUBICTO:
1311
                                System.out.println("SEG_CUBICTO Not supported here");
1312
                                break;
1313
                        case PathIterator.SEG_CLOSE:
1314
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1315
                                if(is3D)
1316
                                        arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y, firstCoord.z));
1317
                                else
1318
                                        arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
1319
                                break;
1320
                        } //end switch
1321

    
1322
                        //theIterator.next();
1323
                } //end while loop
1324

    
1325
                arrayCoords.add(arrayCoords.get(0));
1326
                coords = CoordinateArrays.toCoordinateArray(arrayCoords);
1327

    
1328
                if (numParts == 1) {
1329
                        return getExteriorPolygon(coords);
1330
                }
1331
                return pol;
1332
        }
1333

    
1334
        /**
1335
         * Metodo creado para construir un MultiSurface formado por varias surface
1336
         * 
1337
         * @author Leticia Riestra
1338
         * @param geom
1339
         * @return
1340
         */
1341
        public static com.vividsolutions.jts.geom.Geometry multiSurfaceToJts(MultiSurface geom, int srid) {
1342
                Polygon[] polygons = new Polygon[geom.getPrimitivesNumber()];
1343
                for (int i = 0; i < polygons.length; i++) {
1344
                        Primitive primit = geom.getPrimitiveAt(i);
1345
                        MultiPolygon polygon = null;
1346
                        if(primit.getType() == Geometry.TYPES.ELLIPSE || primit.getType() == Geometry.TYPES.CIRCLE)
1347
                                polygon = (MultiPolygon)ellipseToJts((geom.getPrimitiveAt(i)), srid);
1348
                        else
1349
                                polygon = (MultiPolygon)surfaceToJts((geom.getPrimitiveAt(i)), srid);
1350
                        
1351
                        polygons[i] = (Polygon)polygon.getGeometryN(0);//(Polygon) surfaceToJts((geom.getPrimitiveAt(i)), srid);
1352
                }
1353
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiPolygon(polygons);
1354
        }
1355
        
1356
        private static com.vividsolutions.jts.geom.Geometry surfaceToJts(Geometry shp, int srid) {
1357
            try {
1358
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
1359
                int theType;
1360
                int numParts = 0;
1361
                ArrayList arrayCoords = null;
1362
                int subType = shp.getGeometryType().getSubType();
1363
                boolean is3D = subType == 1 || subType == 3;
1364
                double[] dataLine = new double[3];
1365
                double[] dataQuad = new double[3];
1366
                double[] dataCubic = new double[3];
1367

    
1368

    
1369
                ArrayList shells = new ArrayList();
1370
                ArrayList holes = new ArrayList();
1371
                Coordinate[] points = null;
1372
                
1373
                //El pathIterator no tiene en cuenta coordenadas 3D. En este caso no 
1374
                //necesitamos un iterador que interpole porque las SURFACE vienen con todos
1375
                //los puntos calculados, as? que hacemos un recorrido en vez de usar el 
1376
                //iterador para poder obtener la Z y no perderla.
1377
                
1378
                //theIterator = shp.getPathIterator(null, manager.getFlatness());
1379
                GeneralPathX gp = shp.getGeneralPath();
1380

    
1381
                //while (!theIterator.isDone()) {
1382
                int nPoint = 0;
1383
                for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
1384
                        theType = gp.getTypeAt(nType);
1385
                        switch (theType) {
1386
                        case PathIterator.SEG_MOVETO:
1387
                        case PathIterator.SEG_LINETO: //Se lee un punto
1388
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1389
                                nPoint ++;
1390
                                break;
1391
                        case PathIterator.SEG_QUADTO: //Se leen dos puntos
1392
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1393
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
1394
                                nPoint += 2;
1395
                                break;
1396
                        case PathIterator.SEG_CUBICTO: //Se leen tres puntos
1397
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1398
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
1399
                                dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
1400
                                nPoint += 3;
1401
                                break;
1402
                        }
1403
                        //theType = theIterator.currentSegment(theData);
1404

    
1405
                        switch (theType) {
1406
                        case PathIterator.SEG_MOVETO:
1407

    
1408
                                // System.out.println("SEG_MOVETO");
1409
                                if (arrayCoords == null) {
1410
                                        arrayCoords = new ArrayList();
1411
                                } else {
1412
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1413

    
1414
                                        try {
1415
                                                LinearRing ring = geomFactory.createLinearRing(points);
1416

    
1417
                                                if (CGAlgorithms.isCCW(points)) {
1418
                                                        holes.add(ring);
1419
                                                } else {
1420
                                                        shells.add(ring);
1421
                                                }
1422
                                        } catch (Exception e) {
1423
                                                boolean same = true;
1424
                                                for (int i = 0; i < points.length-1 && same; i++) {
1425
                                                        if (points[i].x != points[i+1].x ||
1426
                                                                        points[i].y != points[i+1].y /*||
1427
                                                                        points[i].z != points[i+1].z*/
1428
                                                        ) {
1429
                                                                same = false;
1430
                                                        }
1431
                                                }
1432
                                                if (same) {
1433
                                                        return geomFactory.createPoint(points[0]);
1434
                                                }
1435

    
1436
                                                if (points.length > 1 && points.length <= 3) {
1437
                                                        // return geomFactory.createLineString(points);
1438
                                                        return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
1439
                                                }
1440

    
1441
                                                System.err.println(
1442
                                                "Caught Topology exception in GMLLinearRingHandler");
1443

    
1444
                                                return null;
1445
                                        }
1446

    
1447
                                        arrayCoords = new ArrayList();
1448
                                }
1449

    
1450
                                numParts++;
1451
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1452
                                break;
1453

    
1454
                        case PathIterator.SEG_LINETO:
1455
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1456
                                break;
1457

    
1458
                        case PathIterator.SEG_QUADTO:
1459
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1460
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
1461
                                break;
1462

    
1463
                        case PathIterator.SEG_CUBICTO:
1464
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1465
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
1466
                                loadArrayCoordinates(arrayCoords, is3D, dataCubic);
1467
                                break;
1468

    
1469
                        case PathIterator.SEG_CLOSE:
1470
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1471
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
1472
                                break;
1473
                        } //end switch
1474

    
1475
                        //theIterator.next();
1476
                } //end while loop
1477

    
1478

    
1479
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1480
                Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
1481
                
1482
                if (!isClosed(firstCoord, lastCoord)) {
1483
                        arrayCoords.add(firstCoord);
1484
                }
1485
                points = CoordinateArrays.toCoordinateArray(arrayCoords);
1486

    
1487
                try {
1488
                        LinearRing ring = geomFactory.createLinearRing(points);
1489

    
1490
                        if (CGAlgorithms.isCCW(points)) {
1491
                                holes.add(ring);
1492
                        } else {
1493
                                shells.add(ring);
1494
                        }
1495
                        ring.setSRID(srid);
1496
                } catch (Exception e) {
1497
                        boolean same = true;
1498
                        for (int i = 0; i < points.length-1 && same; i++) {
1499
                                if (points[i].x != points[i+1].x ||
1500
                                                points[i].y != points[i+1].y /*||
1501
                                                points[i].z != points[i+1].z*/
1502
                                ) {
1503
                                        same = false;
1504
                                }
1505
                        }
1506
                        if (same) {
1507
                                geoJTS = geomFactory.createPoint(points[0]);
1508
                                geoJTS.setSRID(srid);
1509
                                return geoJTS;
1510
                        }
1511
                        if (points.length > 1 && points.length <= 3) {
1512
                                // return geomFactory.createLineString(points);
1513
                                geoJTS = geomFactory
1514
                                .createMultiLineString(new LineString[] { geomFactory
1515
                                                .createLineString(points) });
1516
                                geoJTS.setSRID(srid);
1517
                                return geoJTS;
1518
                        }
1519
                        System.err.println(
1520
                        "Caught Topology exception in GMLLinearRingHandler");
1521

    
1522
                        return null;
1523
                }
1524

    
1525
                /* linRing = new GeometryFactory().createLinearRing(
1526
                 CoordinateArrays.toCoordinateArray(arrayCoords)); */
1527

    
1528
                // System.out.println("NumParts = " + numParts);
1529
                //now we have a list of all shells and all holes
1530
                ArrayList holesForShells = new ArrayList(shells.size());
1531

    
1532
                for (int i = 0; i < shells.size(); i++) {
1533
                        holesForShells.add(new ArrayList());
1534
                }
1535

    
1536
                //find homes
1537
                for (int i = 0; i < holes.size(); i++) {
1538
                        LinearRing testRing = (LinearRing) holes.get(i);
1539
                        LinearRing minShell = null;
1540
                        Envelope minEnv = null;
1541
                        Envelope testEnv = testRing.getEnvelopeInternal();
1542
                        Coordinate testPt = testRing.getCoordinateN(0);
1543
                        LinearRing tryRing = null;
1544

    
1545
                        for (int j = 0; j < shells.size(); j++) {
1546
                                tryRing = (LinearRing) shells.get(j);
1547

    
1548
                                Envelope tryEnv = tryRing.getEnvelopeInternal();
1549

    
1550
                                if (minShell != null) {
1551
                                        minEnv = minShell.getEnvelopeInternal();
1552
                                }
1553

    
1554
                                boolean isContained = false;
1555
                                Coordinate[] coordList = tryRing.getCoordinates();
1556

    
1557
                                if (tryEnv.contains(testEnv) &&
1558
                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
1559
                                                                (pointInList(testPt, coordList)))) {
1560
                                        isContained = true;
1561
                                }
1562

    
1563
                                // check if this new containing ring is smaller than the current minimum ring
1564
                                if (isContained) {
1565
                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
1566
                                                minShell = tryRing;
1567
                                        }
1568
                                }
1569
                        }
1570

    
1571
                        if (minShell == null) {
1572
                                //                                        System.out.println(
1573
                                //                                        polygon found with a hole thats not inside a shell);
1574
                                //                                        azabala: we do the assumption that this hole is really a shell (polygon)
1575
                                //                                        whose point werent digitized in the right order
1576
                                Coordinate[] cs = testRing.getCoordinates();
1577
                                Coordinate[] reversed = new Coordinate[cs.length];
1578
                                int pointIndex = 0;
1579
                                for(int z = cs.length-1; z >= 0; z--){
1580
                                        reversed[pointIndex] = cs[z];
1581
                                        pointIndex++;
1582
                                }
1583
                                LinearRing newRing = geomFactory.createLinearRing(reversed);
1584
                                shells.add(newRing);
1585
                                holesForShells.add(new ArrayList());
1586
                        } else {
1587
                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
1588
                        }
1589
                }
1590

    
1591
                Polygon[] polygons = new Polygon[shells.size()];
1592

    
1593
                for (int i = 0; i < shells.size(); i++) {
1594
                        polygons[i] = geomFactory.createPolygon(
1595
                                        (LinearRing) shells.get(i),
1596
                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
1597
                        polygons[i].setSRID(srid);
1598
                }
1599
                
1600

    
1601
                holesForShells = null;
1602
                shells = null;
1603
                holes = null;
1604

    
1605
                geoJTS = geomFactory.createMultiPolygon(polygons);
1606
                geoJTS.setSRID(srid);
1607
                
1608
                return geoJTS;
1609
            } catch(RuntimeException ex) {
1610
                    logger.debug("Can't convert surface to jts.",ex);
1611
                    throw  ex;
1612
            }
1613

    
1614
        }
1615
        
1616
        private static com.vividsolutions.jts.geom.Geometry ellipseToJts(Geometry shp, int srid) {
1617
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
1618
                int theType;
1619
                int numParts = 0;
1620
                ArrayList arrayCoords = null;
1621
                int subType = shp.getGeometryType().getSubType();
1622
                boolean is3D = subType == 1 || subType == 3;
1623
                double[] dataLine = new double[3];
1624

    
1625

    
1626
                ArrayList shells = new ArrayList();
1627
                ArrayList holes = new ArrayList();
1628
                Coordinate[] points = null;
1629
                
1630
                //El pathIterator no tiene en cuenta coordenadas 3D, pero para la creaci?n de elipses y circulos
1631
                //es necesario el iterador que interpole puntos. El resultado es que en la creaci?n de geometr?as de este
1632
                //tipo no se puede asignar la Z porque se perder?a, pero gvSIG tampoco dispone de esta funci?n, as? que
1633
                //no se nota. Una vez creadas las geometr?a de tipo Elipse y circulo cuando las editamos ya tendr?n todos
1634
                //los puntos calculados y se toman como l?neas por lo que ya se podr?a asignar la Z.
1635
                
1636
                PathIterator theIterator = shp.getPathIterator(null, manager.getFlatness());
1637
                while (!theIterator.isDone()) {
1638
                        theType = theIterator.currentSegment(dataLine);
1639

    
1640
                        switch (theType) {
1641
                        case PathIterator.SEG_MOVETO:
1642
                                if (arrayCoords == null) {
1643
                                        arrayCoords = new ArrayList();
1644
                                } else {
1645
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1646

    
1647
                                        try {
1648
                                                LinearRing ring = geomFactory.createLinearRing(points);
1649

    
1650
                                                if (CGAlgorithms.isCCW(points)) {
1651
                                                        holes.add(ring);
1652
                                                } else {
1653
                                                        shells.add(ring);
1654
                                                }
1655
                                        } catch (Exception e) {
1656
                                                boolean same = true;
1657
                                                for (int i = 0; i < points.length-1 && same; i++) {
1658
                                                        if (points[i].x != points[i+1].x ||
1659
                                                                        points[i].y != points[i+1].y /*||
1660
                                                                        points[i].z != points[i+1].z*/
1661
                                                        ) {
1662
                                                                same = false;
1663
                                                        }
1664
                                                }
1665
                                                if (same) {
1666
                                                        return geomFactory.createPoint(points[0]);
1667
                                                }
1668

    
1669
                                                if (points.length > 1 && points.length <= 3) {
1670
                                                        // return geomFactory.createLineString(points);
1671
                                                        return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
1672
                                                }
1673

    
1674
                                                System.err.println(
1675
                                                "Caught Topology exception in GMLLinearRingHandler");
1676

    
1677
                                                return null;
1678
                                        }
1679

    
1680
                                        arrayCoords = new ArrayList();
1681
                                }
1682

    
1683
                                numParts++;
1684
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1685
                                break;
1686

    
1687
                        case PathIterator.SEG_LINETO:
1688
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1689
                                break;
1690

    
1691
                        case PathIterator.SEG_QUADTO:
1692
                                break;
1693

    
1694
                        case PathIterator.SEG_CUBICTO:
1695
                                break;
1696

    
1697
                        case PathIterator.SEG_CLOSE:
1698
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1699
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
1700
                                break;
1701
                        } //end switch
1702

    
1703
                        theIterator.next();
1704
                } //end while loop
1705

    
1706

    
1707
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1708
                Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
1709
                
1710
                if (!isClosed(firstCoord, lastCoord)) {
1711
                        arrayCoords.add(firstCoord);
1712
                }
1713
                points = CoordinateArrays.toCoordinateArray(arrayCoords);
1714

    
1715
                try {
1716
                        LinearRing ring = geomFactory.createLinearRing(points);
1717

    
1718
                        if (CGAlgorithms.isCCW(points)) {
1719
                                holes.add(ring);
1720
                        } else {
1721
                                shells.add(ring);
1722
                        }
1723
                        ring.setSRID(srid);
1724
                } catch (Exception e) {
1725
                        boolean same = true;
1726
                        for (int i = 0; i < points.length-1 && same; i++) {
1727
                                if (points[i].x != points[i+1].x ||
1728
                                                points[i].y != points[i+1].y /*||
1729
                                                points[i].z != points[i+1].z*/
1730
                                ) {
1731
                                        same = false;
1732
                                }
1733
                        }
1734
                        if (same) {
1735
                                geoJTS = geomFactory.createPoint(points[0]);
1736
                                geoJTS.setSRID(srid);
1737
                                return geoJTS;
1738
                        }
1739
                        if (points.length > 1 && points.length <= 3) {
1740
                                // return geomFactory.createLineString(points);
1741
                                geoJTS = geomFactory
1742
                                .createMultiLineString(new LineString[] { geomFactory
1743
                                                .createLineString(points) });
1744
                                geoJTS.setSRID(srid);
1745
                                return geoJTS;
1746
                        }
1747
                        System.err.println(
1748
                        "Caught Topology exception in GMLLinearRingHandler");
1749

    
1750
                        return null;
1751
                }
1752

    
1753
                /* linRing = new GeometryFactory().createLinearRing(
1754
                 CoordinateArrays.toCoordinateArray(arrayCoords)); */
1755

    
1756
                // System.out.println("NumParts = " + numParts);
1757
                //now we have a list of all shells and all holes
1758
                ArrayList holesForShells = new ArrayList(shells.size());
1759

    
1760
                for (int i = 0; i < shells.size(); i++) {
1761
                        holesForShells.add(new ArrayList());
1762
                }
1763

    
1764
                //find homes
1765
                for (int i = 0; i < holes.size(); i++) {
1766
                        LinearRing testRing = (LinearRing) holes.get(i);
1767
                        LinearRing minShell = null;
1768
                        Envelope minEnv = null;
1769
                        Envelope testEnv = testRing.getEnvelopeInternal();
1770
                        Coordinate testPt = testRing.getCoordinateN(0);
1771
                        LinearRing tryRing = null;
1772

    
1773
                        for (int j = 0; j < shells.size(); j++) {
1774
                                tryRing = (LinearRing) shells.get(j);
1775

    
1776
                                Envelope tryEnv = tryRing.getEnvelopeInternal();
1777

    
1778
                                if (minShell != null) {
1779
                                        minEnv = minShell.getEnvelopeInternal();
1780
                                }
1781

    
1782
                                boolean isContained = false;
1783
                                Coordinate[] coordList = tryRing.getCoordinates();
1784

    
1785
                                if (tryEnv.contains(testEnv) &&
1786
                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
1787
                                                                (pointInList(testPt, coordList)))) {
1788
                                        isContained = true;
1789
                                }
1790

    
1791
                                // check if this new containing ring is smaller than the current minimum ring
1792
                                if (isContained) {
1793
                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
1794
                                                minShell = tryRing;
1795
                                        }
1796
                                }
1797
                        }
1798

    
1799
                        if (minShell == null) {
1800
                                //                                        System.out.println(
1801
                                //                                        polygon found with a hole thats not inside a shell);
1802
                                //                                        azabala: we do the assumption that this hole is really a shell (polygon)
1803
                                //                                        whose point werent digitized in the right order
1804
                                Coordinate[] cs = testRing.getCoordinates();
1805
                                Coordinate[] reversed = new Coordinate[cs.length];
1806
                                int pointIndex = 0;
1807
                                for(int z = cs.length-1; z >= 0; z--){
1808
                                        reversed[pointIndex] = cs[z];
1809
                                        pointIndex++;
1810
                                }
1811
                                LinearRing newRing = geomFactory.createLinearRing(reversed);
1812
                                shells.add(newRing);
1813
                                holesForShells.add(new ArrayList());
1814
                        } else {
1815
                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
1816
                        }
1817
                }
1818

    
1819
                Polygon[] polygons = new Polygon[shells.size()];
1820

    
1821
                for (int i = 0; i < shells.size(); i++) {
1822
                        polygons[i] = geomFactory.createPolygon(
1823
                                        (LinearRing) shells.get(i),
1824
                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
1825
                        polygons[i].setSRID(srid);
1826
                }
1827
                
1828

    
1829
                holesForShells = null;
1830
                shells = null;
1831
                holes = null;
1832

    
1833
                geoJTS = geomFactory.createMultiPolygon(polygons);
1834
                geoJTS.setSRID(srid);
1835
                
1836
                return geoJTS;
1837
        }
1838
        
1839
        /**
1840
         * Loads one element in the <code>List</code> of coordinates with the 
1841
         * data contained in the array of doubles 
1842
         * @param arrayCoords
1843
         * @param is3D
1844
         * @param data
1845
         */
1846
        private static void loadArrayCoordinates(List arrayCoords, boolean is3D, double[] data) {
1847
                if(is3D)
1848
                        arrayCoords.add(new Coordinate(data[0], data[1], data[2]));
1849
                else
1850
                        arrayCoords.add(new Coordinate(data[0], data[1]));
1851
        }
1852

    
1853
}