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 @ 40559

History | View | Annotate | Download (53.9 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
                                     * A loop is not needed here because manager 
138
                                     * correctly creates and appends a primitive (surface)
139
                                     * each time there is a move_to in the GeneralPathX
140
                                     */
141
                                        shpNew = geomManager.createMultiSurface(toShape((MultiPolygon) geo), SUBTYPES.GEOM2D);
142
                                }
143

    
144
                                if (geo instanceof LineString) {
145
                                        shpNew = geomManager.createCurve(toShape((LineString) geo), SUBTYPES.GEOM2D);
146
                                }
147

    
148
                                if (geo instanceof MultiLineString) {
149
                                        shpNew = geomManager.create(TYPES.MULTICURVE, SUBTYPES.GEOM2D);
150
                                        for (int i = 0; i < ((MultiLineString)geo).getNumGeometries(); i++) {
151
                                                com.vividsolutions.jts.geom.Geometry g = ((MultiLineString)geo).getGeometryN(i);
152
                                                Curve c = geomManager.createCurve(toShape((LineString) g), SUBTYPES.GEOM2D);
153
                                                ((MultiCurve)shpNew).addCurve(c);
154
                                        }
155
                                }
156
                        }catch(CreateGeometryException e){
157
                                logger.error("Error creating a geometry", e);
158
                        }
159

    
160
                        return shpNew;
161
                } catch (NoninvertibleTransformException e) {
162
                        e.printStackTrace();
163
                }
164

    
165
                return null;
166
        }
167

    
168
        /**
169
         * Convierte un MultiPoint2D a un MultiPoint de JTS
170
         * @param geom
171
         * @return
172
         */
173
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiPoint geom) {
174
                Coordinate[] theGeoms = new Coordinate[geom.getPrimitivesNumber()];
175
                for (int i = 0; i < theGeoms.length; i++) {
176
                        java.awt.geom.Point2D p = geom.getPrimitiveAt(i)
177
                        .getHandlers(Geometry.SELECTHANDLER)[0].getPoint();
178
                        Coordinate c = new Coordinate(p.getX(), p.getY());
179
                        theGeoms[i] = c;
180
                }
181
                com.vividsolutions.jts.geom.MultiPoint geomCol = 
182
                        new com.vividsolutions.jts.geom.GeometryFactory().createMultiPoint(theGeoms);
183
                return geomCol;
184
        }
185

    
186
        /**
187
         * Convierte una MultiCurve2D en una MultiLineString de JTS
188
         * @param geom
189
         * @return
190
         */
191
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiCurve geom) {
192
                LineString[] lines = new LineString[geom.getPrimitivesNumber()];
193
                for (int i = 0; i < lines.length; i++) {
194
                        lines[i] = (LineString) geometryToJts((geom.getPrimitiveAt(i)));
195
                }
196
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiLineString(lines);
197
        }
198
        
199
        public static com.vividsolutions.jts.geom.Geometry multiCurveToJts(MultiCurve geom, int srid) {
200
                LineString[] lines = new LineString[geom.getPrimitivesNumber()];
201
                for (int i = 0; i < lines.length; i++){
202
                        lines[i] = (LineString) curveToJts((geom.getPrimitiveAt(i)), srid);
203
                }
204
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiLineString(lines);
205
        }
206

    
207
        /**
208
         * Convierte una MultiSurface2D en un MultiPolygon de JTS
209
         * @return
210
         */
211
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(MultiSurface geom) {
212
                Polygon[] polygons = new Polygon[geom.getPrimitivesNumber()];
213
                for (int i = 0; i < polygons.length; i++){
214
                        polygons[i] = (Polygon) geometryToJts((geom.getPrimitiveAt(i)));
215
                }
216
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiPolygon(polygons);
217
        }
218

    
219
        /**
220
         * Convierte una BaseMultiPrimitive en una GeometryCollection de JTS
221
         * @return
222
         */
223
        public com.vividsolutions.jts.geom.Geometry geometryToJts(MultiPrimitive geom) {
224
                com.vividsolutions.jts.geom.Geometry[] geometriesAux = new LineString[geom.getPrimitivesNumber()];
225
                for (int i = 0; i < geometriesAux.length; i++) {
226
                        geometriesAux[i] = geometryToJts((geom.getPrimitiveAt(i)));
227
                }
228
                return new com.vividsolutions.jts.geom.GeometryFactory().createGeometryCollection(geometriesAux);
229
        }
230

    
231
        public static com.vividsolutions.jts.geom.Geometry geometryToJtsWithSRID(Geometry geom, int srid) {
232
                return geometryToJts(geom, geom.getType(), srid);
233
        }
234
        
235
        public static com.vividsolutions.jts.geom.Geometry geometryToJtsWithSRIDForcingType(Geometry geom, int srid, int type) {
236
                return geometryToJts(geom, type, srid);
237
        }
238

    
239

    
240
        public static com.vividsolutions.jts.geom.Geometry geometryToJts(Geometry geom) {
241
                return geometryToJts(geom, geom.getType(), -1);
242
        }
243

    
244
        private static boolean isClosed(Coordinate firstCoordinate, Coordinate lastCoordinate){
245
                double diff = Math.abs(lastCoordinate.x - firstCoordinate.x);
246
                if (diff > 0.000001) {
247
                        return false;
248
                }
249
                diff = Math.abs(lastCoordinate.y - firstCoordinate.y);
250
                if (diff > 0.000001) {
251
                        return false;
252
                }
253
                return true;
254
        }
255

    
256
        private static com.vividsolutions.jts.geom.Geometry curveToJts(Geometry shp, int srid){
257
                ArrayList arrayLines;
258
                LineString lin = null;
259
                int theType;
260
                int numParts = 0;
261
                double[] dataLine = new double[3];
262
                double[] dataQuad = new double[3];
263
                double[] dataCubic = new double[3];
264
                ArrayList arrayCoords = null;
265
                Coordinate coord;
266
                int subType = shp.getGeometryType().getSubType();
267
                boolean is3D = subType == 1 || subType == 3;
268

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

    
279
                //while (!theIterator.isDone()) {
280
                int nPoint = 0;
281
                for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
282
                        theType = gp.getTypeAt(nType);
283
                        switch (theType) {
284
                        case PathIterator.SEG_MOVETO:
285
                        case PathIterator.SEG_LINETO: //Se lee un punto
286
                                dataLine = gp.get3DCoordinatesAt(nPoint);
287
                                nPoint ++;
288
                                break;
289
                        case PathIterator.SEG_QUADTO: //Se leen dos puntos
290
                                dataLine = gp.get3DCoordinatesAt(nPoint);
291
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
292
                                nPoint += 2;
293
                                break;
294
                        case PathIterator.SEG_CUBICTO: //Se leen tres puntos
295
                                dataLine = gp.get3DCoordinatesAt(nPoint);
296
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
297
                                dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
298
                                nPoint += 3;
299
                                break;
300
                        }
301

    
302
                        switch (theType) {
303
                        case PathIterator.SEG_MOVETO:
304
                                if (arrayCoords == null) {
305
                                        arrayCoords = new ArrayList();
306
                                } else {
307
                                        lin = geomFactory.createLineString(
308
                                                        CoordinateArrays.toCoordinateArray(arrayCoords));
309
                                        lin.setSRID(srid);
310
                                        arrayLines.add(lin);
311
                                        arrayCoords = new ArrayList();
312
                                }
313

    
314
                                numParts++;
315
                                if(is3D)
316
                                        coord = new Coordinate(dataLine[0], dataLine[1], dataLine[2]);
317
                                else
318
                                        coord = new Coordinate(dataLine[0], dataLine[1]);
319

    
320
                                arrayCoords.add(coord);
321
                                break;
322

    
323
                        case PathIterator.SEG_LINETO:
324
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
325
                                break;
326

    
327
                        case PathIterator.SEG_QUADTO:
328
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
329
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
330
                                break;
331

    
332
                        case PathIterator.SEG_CUBICTO:
333
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
334
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
335
                                loadArrayCoordinates(arrayCoords, is3D, dataCubic);
336
                                break;
337

    
338
                        case PathIterator.SEG_CLOSE:
339
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
340
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
341
                                break;
342
                        } //end switch
343

    
344
                        //theIterator.next();
345
                } //end while loop
346

    
347
                if (arrayCoords.size() < 2) {
348

    
349
                } else {
350
                        lin = new com.vividsolutions.jts.geom.GeometryFactory().createLineString(
351
                                        CoordinateArrays.toCoordinateArray(arrayCoords));
352
                        lin.setSRID(srid);
353
                }
354

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

    
385
                switch (sourceType) {
386
                case Geometry.TYPES.POINT:
387
                        if(is3D) {
388
                                org.gvsig.fmap.geom.primitive.impl.Point2DZ p = (org.gvsig.fmap.geom.primitive.impl.Point2DZ) shp;
389
                                coord = new Coordinate(p.getX(), p.getY(), p.getCoordinateAt(Geometry.DIMENSIONS.Z));
390
                        } else {
391
                                org.gvsig.fmap.geom.primitive.impl.Point2D p = (org.gvsig.fmap.geom.primitive.impl.Point2D) shp;
392
                                coord = new Coordinate(p.getX(), p.getY());
393
                        }
394
                        geoJTS = geomFactory.createPoint(coord);
395
                        geoJTS.setSRID(srid);
396
                        break;
397

    
398
                case Geometry.TYPES.CURVE:
399
                case Geometry.TYPES.ARC:
400
        case Geometry.TYPES.SPLINE:
401
                        arrayLines = new ArrayList();
402
                        
403
                        //El pathIterator no tiene en cuenta coordenadas 3D, por lo que de usar este, las Z's se perder?n
404
                        //Las splines vienen con todos los puntos calculados por lo que no es necesario un 
405
                        //iterador que interpole. Por esto obtenemos el mismo resultado recorriendo los puntos.
406
                        //Tiene su riesgo pero hasta que se soporte el 3D en el iterador funciona para todos los casos
407
                        
408
                        //theIterator = pol.getPathIterator(null, manager.getFlatness());
409
                        GeneralPathX gp = shp.getGeneralPath();
410

    
411
                        //while (!theIterator.isDone()) {
412
                        int nPoint = 0;
413
                        for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
414
                                theType = gp.getTypeAt(nType);
415
                                switch (theType) {
416
                                case PathIterator.SEG_MOVETO:
417
                                case PathIterator.SEG_LINETO: //Se lee un punto
418
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
419
                                        nPoint ++;
420
                                        break;
421
                                case PathIterator.SEG_QUADTO: //Se leen dos puntos
422
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
423
                                        dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
424
                                        nPoint += 2;
425
                                        break;
426
                                case PathIterator.SEG_CUBICTO: //Se leen tres puntos
427
                                        dataLine = gp.get3DCoordinatesAt(nPoint);
428
                                        dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
429
                                        dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
430
                                        nPoint += 3;
431
                                        break;
432
                                }
433

    
434
                                //Populate a segment of the new
435
                                // GeneralPathX object.
436
                                //Process the current segment to populate a new
437
                                // segment of the new GeneralPathX object.
438
                                switch (theType) {
439
                                case PathIterator.SEG_MOVETO:
440
                                        if (arrayCoords == null) {
441
                                                arrayCoords = new ArrayList();
442
                                        } else {
443
                                                lin = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(arrayCoords));
444
                                                lin.setSRID(srid);
445
                                                arrayLines.add(lin);
446
                                                arrayCoords = new ArrayList();
447
                                        }
448

    
449
                                        numParts++;
450
                                        if(is3D)
451
                                                coord = new Coordinate(dataLine[0], dataLine[1], dataLine[2]);
452
                                        else
453
                                                coord = new Coordinate(dataLine[0], dataLine[1]);
454
                                        
455
                                        arrayCoords.add(coord);
456
                                        break;
457

    
458
                                case PathIterator.SEG_LINETO:
459
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
460
                                        break;
461

    
462
                                case PathIterator.SEG_QUADTO:
463
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
464
                                        loadArrayCoordinates(arrayCoords, is3D, dataQuad);
465
                                        break;
466

    
467
                                case PathIterator.SEG_CUBICTO:
468
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
469
                                        loadArrayCoordinates(arrayCoords, is3D, dataQuad);
470
                                        loadArrayCoordinates(arrayCoords, is3D, dataCubic);
471
                                        break;
472

    
473
                                case PathIterator.SEG_CLOSE:
474
                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
475
                                        loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
476
                                        break;
477
                                } //end switch
478

    
479
                                //theIterator.next();
480
                        } //end while loop
481

    
482
                        if (arrayCoords.size() < 2) {
483
                                break;
484
                        }
485
                        lin = new com.vividsolutions.jts.geom.GeometryFactory().createLineString(
486
                                        CoordinateArrays.toCoordinateArray(arrayCoords));
487

    
488
                        lin.setSRID(srid);
489
                        // CAMBIO: ENTREGAMOS SIEMPRE MULTILINESTRING, QUE ES
490
                        // LO QUE HACE TO_DO EL MUNDO CUANDO ESCRIBE EN POSTGIS
491
                        // O CON GEOTOOLS
492
                        // if (numParts > 1) // Generamos una MultiLineString
493
                        //  {
494
                        arrayLines.add(lin);
495
                        geoJTS = geomFactory.createMultiLineString(
496
                                        com.vividsolutions.jts.geom.GeometryFactory.toLineStringArray(arrayLines));
497
                        geoJTS.setSRID(srid);
498
                        break;
499

    
500
                case Geometry.TYPES.SURFACE:
501
                case Geometry.TYPES.CIRCLE:
502
                case Geometry.TYPES.ELLIPSE:
503
                        arrayLines = new ArrayList();
504

    
505
                        ArrayList shells = new ArrayList();
506
                        ArrayList holes = new ArrayList();
507
                        Coordinate[] points = null;
508

    
509
                        //El pathIterator no tiene en cuenta coordenadas 3D, pero para la creaci?n de elipses y circulos
510
                        //es necesario el iterador que interpole puntos. El resultado es que en la creaci?n de geometr?as de este
511
                        //tipo no se puede asignar la Z porque se perder?a, pero gvSIG tampoco dispone de esta funci?n, as? que
512
                        //no se nota. Una vez creadas las geometr?a de tipo Elipse y circulo cuando las editamos ya tendr?n todos
513
                        //los puntos calculados y se toman como l?neas por lo que ya se podr?a asignar la Z.
514
                        
515
                        PathIterator theIterator = shp.getPathIterator(null, manager.getFlatness());
516
                        while (!theIterator.isDone()) {
517
                                theType = theIterator.currentSegment(dataLine);
518
                                
519
                                switch (theType) {
520
                                case PathIterator.SEG_MOVETO:
521
                                        if (arrayCoords == null) {
522
                                                arrayCoords = new ArrayList();
523
                                        } else {
524
                                                points = CoordinateArrays.toCoordinateArray(arrayCoords);
525

    
526
                                                try {
527
                                                        LinearRing ring = geomFactory.createLinearRing(points);
528

    
529
                                                        if (CGAlgorithms.isCCW(points)) {
530
                                                                holes.add(ring);
531
                                                        } else {
532
                                                                shells.add(ring);
533
                                                        }
534
                                                } catch (Exception e) {
535
                                                        boolean same = true;
536
                                                        for (int i = 0; i < points.length-1 && same; i++) {
537
                                                                if (points[i].x != points[i+1].x ||
538
                                                                                points[i].y != points[i+1].y /*||
539
                                                                                points[i].z != points[i+1].z*/
540
                                                                ) {
541
                                                                        same = false;
542
                                                                }
543
                                                        }
544
                                                        if (same) {
545
                                                                return geomFactory.createPoint(points[0]);
546
                                                        }
547
                                                        if (points.length>1 && points.length <= 3) {
548
                                                                // return geomFactory.createLineString(points);
549
                                                                return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
550
                                                        }
551

    
552
                                                        System.err.println(
553
                                                        "Caught Topology exception in GMLLinearRingHandler");
554

    
555
                                                        return null;
556
                                                }
557
                                                arrayCoords = new ArrayList();
558
                                        }
559

    
560
                                        numParts++;
561
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
562
                                        break;
563

    
564
                                case PathIterator.SEG_LINETO:
565
                                        loadArrayCoordinates(arrayCoords, is3D, dataLine);
566
                                        break;
567

    
568
                                case PathIterator.SEG_QUADTO:
569
                                        break;
570

    
571
                                case PathIterator.SEG_CUBICTO:
572
                                        break;
573

    
574
                                case PathIterator.SEG_CLOSE:
575
                                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
576
                                        loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
577
                                        break;
578
                                } //end switch
579

    
580
                                theIterator.next();
581
                        } //end while loop
582

    
583

    
584
                        Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
585
                        Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
586
                        if (!isClosed(firstCoord, lastCoord)) {
587
                                arrayCoords.add(firstCoord);
588
                        }
589
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
590

    
591
                        try {
592
                                LinearRing ring = geomFactory.createLinearRing(points);
593

    
594
                                if (CGAlgorithms.isCCW(points)) {
595
                                        holes.add(ring);
596
                                } else {
597
                                        shells.add(ring);
598
                                }
599
                                ring.setSRID(srid);
600
                        } catch (Exception e) {
601
                                boolean same = true;
602
                                for (int i = 0; i < points.length-1 && same; i++) {
603
                                        if (points[i].x != points[i+1].x ||
604
                                                        points[i].y != points[i+1].y /*||
605
                                                        points[i].z != points[i+1].z*/
606
                                        ) {
607
                                                same = false;
608
                                        }
609
                                }
610
                                if (same) {
611
                                        geoJTS = geomFactory.createPoint(points[0]);
612
                                        geoJTS.setSRID(srid);
613
                                        return geoJTS;
614
                                }
615
                                /*
616
                                 * caso cuando es una linea de 3 puntos, no creo un LinearRing, sino
617
                                 * una linea
618
                                 */
619
                                if (points.length > 1 && points.length <= 3) {
620
                                        // return geomFactory.createLineString(points);
621
                                        geoJTS = geomFactory.createMultiLineString(new LineString[] { geomFactory.createLineString(points) });
622
                                        geoJTS.setSRID(srid);
623
                                        return geoJTS;
624
                                }
625
                                System.err.println("Caught Topology exception in GMLLinearRingHandler");
626

    
627
                                return null;
628
                        }
629

    
630
                        /* linRing = new GeometryFactory().createLinearRing(
631
                         CoordinateArrays.toCoordinateArray(arrayCoords)); */
632

    
633
                        // System.out.println("NumParts = " + numParts);
634
                        //now we have a list of all shells and all holes
635
                        ArrayList holesForShells = new ArrayList(shells.size());
636

    
637
                        for (int i = 0; i < shells.size(); i++) {
638
                                holesForShells.add(new ArrayList());
639
                        }
640

    
641
                        //find homes
642
                        for (int i = 0; i < holes.size(); i++) {
643
                                LinearRing testRing = (LinearRing) holes.get(i);
644
                                LinearRing minShell = null;
645
                                Envelope minEnv = null;
646
                                Envelope testEnv = testRing.getEnvelopeInternal();
647
                                Coordinate testPt = testRing.getCoordinateN(0);
648
                                LinearRing tryRing = null;
649

    
650
                                for (int j = 0; j < shells.size(); j++) {
651
                                        tryRing = (LinearRing) shells.get(j);
652

    
653
                                        Envelope tryEnv = tryRing.getEnvelopeInternal();
654

    
655
                                        if (minShell != null) {
656
                                                minEnv = minShell.getEnvelopeInternal();
657
                                        }
658

    
659
                                        boolean isContained = false;
660
                                        Coordinate[] coordList = tryRing.getCoordinates();
661

    
662
                                        if (tryEnv.contains(testEnv) &&
663
                                                        (CGAlgorithms.isPointInRing(testPt, coordList) ||
664
                                                                        (pointInList(testPt, coordList)))) {
665
                                                isContained = true;
666
                                        }
667

    
668
                                        // check if this new containing ring is smaller than the current minimum ring
669
                                        if (isContained) {
670
                                                if ((minShell == null) || minEnv.contains(tryEnv)) {
671
                                                        minShell = tryRing;
672
                                                }
673
                                        }
674
                                }
675

    
676
                                if (minShell == null) {
677
                                        //                                        System.out.println(
678
                                        //                                        polygon found with a hole thats not inside a shell);
679
                                        //                                        azabala: we do the assumption that this hole is really a shell (polygon)
680
                                        //                                        whose point werent digitized in the right order
681
                                        Coordinate[] cs = testRing.getCoordinates();
682
                                        Coordinate[] reversed = new Coordinate[cs.length];
683
                                        int pointIndex = 0;
684
                                        for(int z = cs.length-1; z >= 0; z--){
685
                                                reversed[pointIndex] = cs[z];
686
                                                pointIndex++;
687
                                        }
688
                                        LinearRing newRing = geomFactory.createLinearRing(reversed);
689
                                        shells.add(newRing);
690
                                        holesForShells.add(new ArrayList());
691
                                } else {
692
                                        ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
693
                                }
694
                        }
695

    
696
                        Polygon[] polygons = new Polygon[shells.size()];
697

    
698
                        for (int i = 0; i < shells.size(); i++) {
699
                                polygons[i] = geomFactory.createPolygon(
700
                                                (LinearRing) shells.get(i),
701
                                                (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
702
                                polygons[i].setSRID(srid);
703
                        }
704
                        // CAMBIO: ENTREGAMOS SIEMPRE MULTILINESTRING, QUE ES
705
                        // LO QUE HACE TO_DO EL MUNDO CUANDO ESCRIBE EN POSTGIS
706
                        // O CON GEOTOOLS
707
                        // if (numParts > 1) // Generamos una MultiLineString
708

    
709
                        /* if (polygons.length == 1) {
710
                         return polygons[0];
711
                         } */
712

    
713
                        // FIN CAMBIO
714

    
715
                        holesForShells = null;
716
                        shells = null;
717
                        holes = null;
718

    
719
                        if (polygons.length == 1) {
720
                                geoJTS = polygons[0];
721
                        } else {
722
                                // its a multi part
723
                                geoJTS = geomFactory.createMultiPolygon(polygons);
724
                        }
725
                        geoJTS.setSRID(srid);
726
                        //its a multi part
727
                        //geoJTS = geomFactory.createMultiPolygon(polygons);
728
                        //geoJTS.setSRID(srid);
729

    
730
                        break;
731

    
732
                case Geometry.TYPES.MULTICURVE:
733
                        geoJTS = multiCurveToJts((MultiCurve)shp, srid);
734
                        geoJTS.setSRID(srid);
735
                        break;
736

    
737
                case Geometry.TYPES.MULTIPOINT:
738
                        geoJTS = geometryToJts((MultiPoint)shp);
739
                        geoJTS.setSRID(srid);
740
                        break;
741

    
742
                case Geometry.TYPES.MULTISURFACE:
743
                        geoJTS = multiSurfaceToJts((MultiSurface)shp, srid);
744
                        geoJTS.setSRID(srid);
745
                        break;
746
                }
747

    
748
                if(destinationType != sourceType)
749
                        geoJTS = convertTypes(geoJTS, sourceType, destinationType);
750
                
751
                geoJTS.setSRID(srid);
752
                return geoJTS;
753
        }
754
        
755
        /**
756
         * This function is called when the we need force types, that is the destination 
757
         * type does not match with the input geometry type
758
         * @param g
759
         * @param sourceType
760
         * @param destinationType
761
         * @return
762
         */
763
        private static com.vividsolutions.jts.geom.Geometry convertTypes(
764
                        com.vividsolutions.jts.geom.Geometry g,
765
                        int sourceType,
766
                        int destinationType) {
767
                if((sourceType == Geometry.TYPES.CURVE || 
768
                        sourceType == Geometry.TYPES.SPLINE || 
769
                        sourceType == Geometry.TYPES.ARC) 
770
                        && destinationType == Geometry.TYPES.MULTISURFACE) {
771
                        if(g instanceof MultiLineString) {
772
                                Polygon[] poly = new Polygon[((MultiLineString)g).getNumGeometries()];
773
                                for (int i = 0; i < ((MultiLineString)g).getNumGeometries(); i++) {
774
                                        com.vividsolutions.jts.geom.Geometry lineString = ((MultiLineString)g).getGeometryN(i);
775
                                        poly[i] = convertLineStringToPolygon((LineString)lineString);
776
                                }
777
                                return geomFactory.createMultiPolygon(poly);
778
                        } else
779
                                return convertLineStringToPolygon((LineString)g);
780
                }
781
                
782
                if((sourceType == Geometry.TYPES.CIRCLE || 
783
                        sourceType == Geometry.TYPES.ELLIPSE) && 
784
                        destinationType == Geometry.TYPES.MULTICURVE) {
785
                        if(g instanceof Polygon) {
786
                                Polygon poly = (Polygon)g; 
787
                                LineString lineString = geomFactory.createLinearRing(poly.getCoordinates());
788
                                return geomFactory.createMultiLineString(new LineString[]{lineString});
789
                        }
790
                }
791
                return g;
792
        }
793

    
794
        private static com.vividsolutions.jts.geom.Polygon convertLineStringToPolygon(LineString line) {
795
                Coordinate[] coordinates = line.getCoordinates();
796
                LinearRing shell = geomFactory.createLinearRing(coordinates);
797
                Polygon pol = geomFactory.createPolygon(shell, null);
798
                return pol;
799
        }
800
        
801
        /**
802
         * DOCUMENT ME!
803
         *
804
         * @param p DOCUMENT ME!
805
         *
806
         * @return DOCUMENT ME!
807
         */
808
        private static GeneralPathX toShape(Polygon p) {
809
                GeneralPathX resul = new GeneralPathX();
810
                Coordinate coord;
811

    
812
                for (int i = 0; i < p.getExteriorRing().getNumPoints(); i++) {
813
                        coord = p.getExteriorRing().getCoordinateN(i);
814

    
815
                        if (i == 0) {
816
                                resul.moveTo(coord.x, coord.y);
817
                        } else {
818
                                resul.lineTo(coord.x, coord.y);
819
                        }
820
                }
821

    
822
                for (int j = 0; j < p.getNumInteriorRing(); j++) {
823
                        LineString hole = p.getInteriorRingN(j);
824

    
825
                        for (int k = 0; k < hole.getNumPoints(); k++) {
826
                                coord = hole.getCoordinateN(k);
827

    
828
                                if (k == 0) {
829
                                        resul.moveTo(coord.x, coord.y);
830
                                } else {
831
                                        resul.lineTo(coord.x, coord.y);
832
                                }
833
                        }
834
                }
835

    
836
                return resul;
837
        }
838

    
839

    
840
        private static GeneralPathX toShape(MultiLineString mls)
841
        throws NoninvertibleTransformException, CreateGeometryException {
842
                GeneralPathX path = new GeneralPathX();
843

    
844
                for (int i = 0; i < mls.getNumGeometries(); i++) {
845
                        LineString lineString = (LineString) mls.getGeometryN(i);
846
                        path.append(toShape(lineString).getPathIterator(null), false);
847
                }
848

    
849
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
850
                //converted to GeneralPathXs. [Jon Aquino]
851
                return path;
852
        }
853

    
854
        /**
855
         * DOCUMENT ME!
856
         *
857
         * @param lineString DOCUMENT ME!
858
         *
859
         * @return DOCUMENT ME!
860
         *
861
         * @throws NoninvertibleTransformException DOCUMENT ME!
862
         * @throws CreateGeometryException 
863
         */
864
        private static GeneralPathX toShape(LineString lineString)
865
        throws NoninvertibleTransformException, CreateGeometryException {
866
                GeneralPathX shape = new GeneralPathX();
867
                org.gvsig.fmap.geom.primitive.Point viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(0));
868
                shape.moveTo(viewPoint.getX(), viewPoint.getY());
869

    
870
                for (int i = 1; i < lineString.getNumPoints(); i++) {
871
                        viewPoint = coordinate2FPoint2D(lineString.getCoordinateN(i));
872
                        shape.lineTo(viewPoint.getX(), viewPoint.getY());
873
                }
874

    
875
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
876
                //converted to GeneralPathXs. [Jon Aquino]
877
                return shape;
878
        }
879

    
880

    
881
        /**
882
         *
883
         */
884
        private static GeneralPathX toShape(MultiPolygon mp)
885
        throws NoninvertibleTransformException {
886
                GeneralPathX path = new GeneralPathX();
887

    
888
                for (int i = 0; i < mp.getNumGeometries(); i++) {
889
                        Polygon polygon = (Polygon) mp.getGeometryN(i);
890
                        path.append(toShape(polygon).getPathIterator(null), false);
891
                }
892

    
893
                //BasicFeatureRenderer expects LineStrings and MultiLineStrings to be
894
                //converted to GeneralPathXs. [Jon Aquino]
895
                return path;
896
        }
897
        /**
898
         * DOCUMENT ME!
899
         *
900
         * @param coord DOCUMENT ME!
901
         *
902
         * @return DOCUMENT ME!
903
         * @throws CreateGeometryException 
904
         */
905
        public static org.gvsig.fmap.geom.primitive.Point coordinate2FPoint2D(Coordinate coord) throws CreateGeometryException {
906
                return geomManager.createPoint(coord.x, coord.y, SUBTYPES.GEOM2D); //,coord.z);
907
        }
908

    
909
        /**
910
         * Convierte una Geometry de JTS a GeneralPathX.
911
         *
912
         * @param geometry Geometry a convertir.
913
         *
914
         * @return GeneralPathX.
915
         *
916
         * @throws NoninvertibleTransformException
917
         * @throws CreateGeometryException 
918
         * @throws IllegalArgumentException
919
         */
920
        public static GeneralPathX toShape(com.vividsolutions.jts.geom.Geometry geometry)
921
        throws NoninvertibleTransformException, CreateGeometryException {
922
                if (geometry.isEmpty()) {
923
                        return new GeneralPathX();
924
                }
925

    
926
                if (geometry instanceof Polygon) {
927
                        return toShape((Polygon) geometry);
928
                }
929

    
930
                if (geometry instanceof MultiPolygon) {
931
                        return toShape((MultiPolygon) geometry);
932
                }
933

    
934
                if (geometry instanceof LineString) {
935
                        return toShape((LineString) geometry);
936
                }
937

    
938
                if (geometry instanceof MultiLineString) {
939
                        return toShape((MultiLineString) geometry);
940
                }
941

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

    
946
                throw new IllegalArgumentException("Unrecognized Geometry class: " +
947
                                geometry.getClass());
948
        }
949

    
950

    
951
        public static GeneralPathX transformToInts(GeneralPathX gp, AffineTransform at) {
952
                GeneralPathX newGp = new GeneralPathX();
953
                PathIterator theIterator;
954
                int theType;
955
                int numParts = 0;
956
                double[] theData = new double[6];
957
                java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
958
                java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
959
                boolean bFirst = true;
960
                int xInt, yInt, antX = -1, antY = -1;
961

    
962
                theIterator = gp.getPathIterator(null); //, flatness);
963

    
964
                while (!theIterator.isDone()) {
965
                        theType = theIterator.currentSegment(theData);
966
                        switch (theType) {
967
                        case PathIterator.SEG_MOVETO:
968
                                numParts++;
969
                                ptSrc.setLocation(theData[0], theData[1]);
970
                                at.transform(ptSrc, ptDst);
971
                                antX = (int) ptDst.getX();
972
                                antY = (int) ptDst.getY();
973
                                newGp.moveTo(antX, antY);
974
                                bFirst = true;
975
                                break;
976

    
977
                        case PathIterator.SEG_LINETO:
978
                                ptSrc.setLocation(theData[0], theData[1]);
979
                                at.transform(ptSrc, ptDst);
980
                                xInt = (int) ptDst.getX();
981
                                yInt = (int) ptDst.getY();
982
                                if ((bFirst) || ((xInt != antX) || (yInt != antY)))
983
                                {
984
                                        newGp.lineTo(xInt, yInt);
985
                                        antX = xInt;
986
                                        antY = yInt;
987
                                        bFirst = false;
988
                                }
989
                                break;
990

    
991
                        case PathIterator.SEG_QUADTO:
992
                                System.out.println("Not supported here");
993

    
994
                                break;
995

    
996
                        case PathIterator.SEG_CUBICTO:
997
                                System.out.println("Not supported here");
998

    
999
                                break;
1000

    
1001
                        case PathIterator.SEG_CLOSE:
1002
                                newGp.closePath();
1003

    
1004
                                break;
1005
                        } //end switch
1006

    
1007
                        theIterator.next();
1008
                } //end while loop
1009

    
1010
                return newGp;
1011
        }
1012
        public static Geometry transformToInts(Geometry gp, AffineTransform at) throws CreateGeometryException {
1013
                GeneralPathX newGp = new GeneralPathX();
1014
                double[] theData = new double[6];
1015
                double[] aux = new double[6];
1016

    
1017
                // newGp.reset();
1018
                PathIterator theIterator;
1019
                int theType;
1020
                int numParts = 0;
1021

    
1022
                java.awt.geom.Point2D ptDst = new java.awt.geom.Point2D.Double();
1023
                java.awt.geom.Point2D ptSrc = new java.awt.geom.Point2D.Double();
1024
                boolean bFirst = true;
1025
                int xInt, yInt, antX = -1, antY = -1;
1026

    
1027

    
1028
                theIterator = gp.getPathIterator(null); //, flatness);
1029
                int numSegmentsAdded = 0;
1030
                while (!theIterator.isDone()) {
1031
                        theType = theIterator.currentSegment(theData);
1032

    
1033
                        switch (theType) {
1034
                        case PathIterator.SEG_MOVETO:
1035
                                numParts++;
1036
                                ptSrc.setLocation(theData[0], theData[1]);
1037
                                at.transform(ptSrc, ptDst);
1038
                                antX = (int) ptDst.getX();
1039
                                antY = (int) ptDst.getY();
1040
                                newGp.moveTo(antX, antY);
1041
                                numSegmentsAdded++;
1042
                                bFirst = true;
1043
                                break;
1044

    
1045
                        case PathIterator.SEG_LINETO:
1046
                                ptSrc.setLocation(theData[0], theData[1]);
1047
                                at.transform(ptSrc, ptDst);
1048
                                xInt = (int) ptDst.getX();
1049
                                yInt = (int) ptDst.getY();
1050
                                if ((bFirst) || ((xInt != antX) || (yInt != antY)))
1051
                                {
1052
                                        newGp.lineTo(xInt, yInt);
1053
                                        antX = xInt;
1054
                                        antY = yInt;
1055
                                        bFirst = false;
1056
                                        numSegmentsAdded++;
1057
                                }
1058
                                break;
1059

    
1060
                        case PathIterator.SEG_QUADTO:
1061
                                at.transform(theData,0,aux,0,2);
1062
                                newGp.quadTo(aux[0], aux[1], aux[2], aux[3]);
1063
                                numSegmentsAdded++;
1064
                                break;
1065

    
1066
                        case PathIterator.SEG_CUBICTO:
1067
                                at.transform(theData,0,aux,0,3);
1068
                                newGp.curveTo(aux[0], aux[1], aux[2], aux[3], aux[4], aux[5]);
1069
                                numSegmentsAdded++;
1070
                                break;
1071

    
1072
                        case PathIterator.SEG_CLOSE:
1073
                                if (numSegmentsAdded < 3) {
1074
                                        newGp.lineTo(antX, antY);
1075
                                }
1076
                                newGp.closePath();
1077

    
1078
                                break;
1079
                        } //end switch
1080

    
1081
                        theIterator.next();
1082
                } //end while loop
1083

    
1084
                Geometry shp = null;
1085
                switch (gp.getType())
1086
                {
1087
                case Geometry.TYPES.POINT:
1088
                        shp = geomManager.createPoint(ptDst.getX(), ptDst.getY(), SUBTYPES.GEOM2D); 
1089
                        break;
1090

    
1091
                case Geometry.TYPES.CURVE:
1092
                case Geometry.TYPES.ARC:
1093
                        try {
1094
                                shp = geomManager.createCurve(newGp, SUBTYPES.GEOM2D);
1095
                        } catch (CreateGeometryException e1) {
1096
                                logger.error("Error creating a curve", e1);
1097
                        }
1098
                        break;
1099

    
1100
                case Geometry.TYPES.SURFACE:
1101
                case Geometry.TYPES.CIRCLE:
1102
                case Geometry.TYPES.ELLIPSE:
1103

    
1104
                        try {
1105
                                shp = geomManager.createSurface(newGp, SUBTYPES.GEOM2D);
1106
                        } catch (CreateGeometryException e) {
1107
                                logger.error("Error creating a surface", e);
1108
                        }
1109
                        break;
1110
                }
1111
                return shp;
1112
        }
1113

    
1114
        public static Rectangle2D convertEnvelopeToRectangle2D(Envelope jtsR) {
1115
                Rectangle2D.Double r = new Rectangle2D.Double(jtsR.getMinX(),
1116
                                jtsR.getMinY(), jtsR.getWidth(), jtsR.getHeight());
1117
                return r;
1118
        }
1119

    
1120
        public static Envelope convertEnvelopeToJTS(org.gvsig.fmap.geom.primitive.Envelope r) {
1121
                Envelope e = new Envelope(r.getMinimum(0), r.getMaximum(0), r.getMinimum(1),
1122
                                r.getMaximum(1));
1123
                return e;
1124
        }
1125

    
1126
        /**
1127
         * Return a correct polygon (no hole)
1128
         * @param coordinates
1129
         * @return
1130
         */
1131
        public static Geometry getExteriorPolygon(Coordinate[] coordinates) {
1132
                // isCCW = true => it's a hole
1133
                Coordinate[] vs = new Coordinate[coordinates.length];
1134
                if (CGAlgorithms.isCCW(coordinates)) {
1135
                        for (int i = vs.length-1;i >= 0; i--){
1136
                                vs[i] = coordinates[i];
1137
                        }
1138
                } else {
1139
                        vs = coordinates;
1140
                }
1141
                LinearRing ring = geomFactory.createLinearRing(vs);
1142

    
1143
                try {
1144
                        Surface surface = (Surface)manager.create(TYPES.SURFACE, SUBTYPES.GEOM2D);
1145
                        surface.setGeneralPath(toShape(ring));
1146
                        return surface;
1147
                } catch (NoninvertibleTransformException e) {
1148
                        e.printStackTrace();
1149
                } catch (CreateGeometryException e) {
1150
                        e.printStackTrace();
1151
                }
1152
                return null;
1153
        }
1154

    
1155
        public static boolean isCCW(Point[] points) {
1156
                int length = points.length;
1157
                Coordinate[] vs;
1158

    
1159
                if (points[0].getX() != points[length-1].getX() || points[0].getY() != points[length-1].getY()) {
1160
                        vs=new Coordinate[length+1];
1161
                        vs[points.length] = new Coordinate(points[0].getX(), points[0].getY());
1162
                } else {
1163
                        vs=new Coordinate[length];
1164
                }
1165
                for (int i = 0; i < length; i++) {
1166
                        vs[i] = new Coordinate(points[i].getX(), points[i].getY());
1167
                }
1168

    
1169
                return CGAlgorithms.isCCW(vs);
1170
        }
1171

    
1172
        public static boolean isCCW(Surface pol) {
1173
                com.vividsolutions.jts.geom.Geometry jtsGeom = Converter.geometryToJts(pol);
1174
                if (jtsGeom.getNumGeometries() == 1) {
1175
                        Coordinate[] coords = jtsGeom.getCoordinates();
1176
                        return CGAlgorithms.isCCW(coords);
1177
                }
1178
                return false;
1179
        }
1180

    
1181
        /**
1182
         * Return a hole (CCW ordered points)
1183
         * @param coordinates
1184
         * @return
1185
         */
1186
        public static Geometry getHole(Coordinate[] coordinates) {
1187
                Coordinate[] vs = new Coordinate[coordinates.length];
1188
                if (CGAlgorithms.isCCW(coordinates)) {
1189
                        vs=coordinates;
1190

    
1191
                }else{
1192
                        for (int i = vs.length-1; i >= 0; i--) {
1193
                                vs[i] = coordinates[i];
1194
                        }
1195
                }
1196
                LinearRing ring = geomFactory.createLinearRing(vs);
1197

    
1198
                try {
1199
                        Surface surface = (Surface)manager.create(TYPES.SURFACE, SUBTYPES.GEOM2D);
1200
                        surface.setGeneralPath(toShape(ring));
1201
                        return surface;
1202
                } catch (NoninvertibleTransformException e) {
1203
                        e.printStackTrace();
1204
                } catch (CreateGeometryException e) {
1205
                        e.printStackTrace();
1206
                }
1207
                return null;
1208
        }
1209

    
1210
        public static Shape getExteriorPolygon(GeneralPathX gp) {
1211
                Area area = new Area(gp);
1212
                area.isSingular();
1213
                return area;
1214
        }
1215
        
1216
        /**
1217
         * Use it ONLY for NOT multipart polygons.
1218
         * @param pol
1219
         * @return
1220
         */
1221
        public static Geometry getNotHolePolygon(Surface pol) {
1222
                // isCCW == true => hole
1223
                Coordinate[] coords;
1224
                ArrayList arrayCoords = null;
1225
                int theType;
1226
                int numParts = 0;
1227

    
1228
                //Use this array to store segment coordinate data
1229
                double[] theData = new double[4];
1230

    
1231
                ArrayList shells = new ArrayList();
1232
                ArrayList holes = new ArrayList();
1233
                Coordinate[] points = null;
1234
                
1235
                int subType = pol.getGeometryType().getSubType();
1236
                boolean is3D = subType == 1 || subType == 3;
1237
                
1238
                //El pathIterator no tiene en cuenta coordenadas 3D
1239
                //theIterator = pol.getPathIterator(null, manager.getFlatness());
1240
                GeneralPathX gp = pol.getGeneralPath();
1241

    
1242
                //while (!theIterator.isDone()) {
1243
                for (int nPoint = 0; nPoint < gp.getNumCoords(); nPoint++) {
1244
                        theData = gp.getCoordinatesAt(nPoint);
1245
                        theType = gp.getTypeAt(nPoint);
1246

    
1247
                        //Populate a segment of the new
1248
                        // GeneralPathX object.
1249
                        //Process the current segment to populate a new
1250
                        // segment of the new GeneralPathX object.
1251
                        switch (theType) {
1252
                        case PathIterator.SEG_MOVETO:
1253

    
1254
                                // System.out.println("SEG_MOVETO");
1255
                                if (arrayCoords == null) {
1256
                                        arrayCoords = new ArrayList();
1257
                                } else {
1258
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1259

    
1260
                                        try {
1261
                                                LinearRing ring = geomFactory.createLinearRing(points);
1262

    
1263
                                                if (CGAlgorithms.isCCW(points)) {
1264
                                                        holes.add(ring);
1265
                                                } else {
1266
                                                        shells.add(ring);
1267
                                                }
1268
                                        } catch (Exception e) {
1269
                                                System.err.println("Caught Topology exception in GMLLinearRingHandler");
1270

    
1271
                                                return null;
1272
                                        }
1273
                                        arrayCoords = new ArrayList();
1274
                                }
1275

    
1276
                                numParts++;
1277
                                if(is3D)
1278
                                        arrayCoords.add(new Coordinate(theData[0], theData[1], theData[2]));
1279
                                else
1280
                                        arrayCoords.add(new Coordinate(theData[0], theData[1]));
1281

    
1282
                                break;
1283

    
1284
                        case PathIterator.SEG_LINETO:
1285
                                if(is3D)
1286
                                        arrayCoords.add(new Coordinate(theData[0], theData[1], theData[2]));
1287
                                else
1288
                                        arrayCoords.add(new Coordinate(theData[0], theData[1]));
1289
                                break;
1290
                        case PathIterator.SEG_QUADTO:
1291
                                System.out.println("SEG_QUADTO Not supported here");
1292
                                break;
1293
                        case PathIterator.SEG_CUBICTO:
1294
                                System.out.println("SEG_CUBICTO Not supported here");
1295
                                break;
1296
                        case PathIterator.SEG_CLOSE:
1297
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1298
                                if(is3D)
1299
                                        arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y, firstCoord.z));
1300
                                else
1301
                                        arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
1302
                                break;
1303
                        } //end switch
1304

    
1305
                        //theIterator.next();
1306
                } //end while loop
1307

    
1308
                arrayCoords.add(arrayCoords.get(0));
1309
                coords = CoordinateArrays.toCoordinateArray(arrayCoords);
1310

    
1311
                if (numParts == 1) {
1312
                        return getExteriorPolygon(coords);
1313
                }
1314
                return pol;
1315
        }
1316

    
1317
        /**
1318
         * Metodo creado para construir un MultiSurface formado por varias surface
1319
         * 
1320
         * @author Leticia Riestra
1321
         * @param geom
1322
         * @return
1323
         */
1324
        public static com.vividsolutions.jts.geom.Geometry multiSurfaceToJts(MultiSurface geom, int srid) {
1325
                Polygon[] polygons = new Polygon[geom.getPrimitivesNumber()];
1326
                for (int i = 0; i < polygons.length; i++) {
1327
                        Primitive primit = geom.getPrimitiveAt(i);
1328
                        MultiPolygon polygon = null;
1329
                        if(primit.getType() == Geometry.TYPES.ELLIPSE || primit.getType() == Geometry.TYPES.CIRCLE)
1330
                                polygon = (MultiPolygon)ellipseToJts((geom.getPrimitiveAt(i)), srid);
1331
                        else
1332
                                polygon = (MultiPolygon)surfaceToJts((geom.getPrimitiveAt(i)), srid);
1333
                        
1334
                        polygons[i] = (Polygon)polygon.getGeometryN(0);//(Polygon) surfaceToJts((geom.getPrimitiveAt(i)), srid);
1335
                }
1336
                return new com.vividsolutions.jts.geom.GeometryFactory().createMultiPolygon(polygons);
1337
        }
1338
        
1339
        private static com.vividsolutions.jts.geom.Geometry surfaceToJts(Geometry shp, int srid) {
1340
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
1341
                int theType;
1342
                int numParts = 0;
1343
                ArrayList arrayCoords = null;
1344
                int subType = shp.getGeometryType().getSubType();
1345
                boolean is3D = subType == 1 || subType == 3;
1346
                double[] dataLine = new double[3];
1347
                double[] dataQuad = new double[3];
1348
                double[] dataCubic = new double[3];
1349

    
1350

    
1351
                ArrayList shells = new ArrayList();
1352
                ArrayList holes = new ArrayList();
1353
                Coordinate[] points = null;
1354
                
1355
                //El pathIterator no tiene en cuenta coordenadas 3D. En este caso no 
1356
                //necesitamos un iterador que interpole porque las SURFACE vienen con todos
1357
                //los puntos calculados, as? que hacemos un recorrido en vez de usar el 
1358
                //iterador para poder obtener la Z y no perderla.
1359
                
1360
                //theIterator = shp.getPathIterator(null, manager.getFlatness());
1361
                GeneralPathX gp = shp.getGeneralPath();
1362

    
1363
                //while (!theIterator.isDone()) {
1364
                int nPoint = 0;
1365
                for (int nType = 0; nType < gp.getNumTypes(); nType++) {        
1366
                        theType = gp.getTypeAt(nType);
1367
                        switch (theType) {
1368
                        case PathIterator.SEG_MOVETO:
1369
                        case PathIterator.SEG_LINETO: //Se lee un punto
1370
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1371
                                nPoint ++;
1372
                                break;
1373
                        case PathIterator.SEG_QUADTO: //Se leen dos puntos
1374
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1375
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
1376
                                nPoint += 2;
1377
                                break;
1378
                        case PathIterator.SEG_CUBICTO: //Se leen tres puntos
1379
                                dataLine = gp.get3DCoordinatesAt(nPoint);
1380
                                dataQuad = gp.get3DCoordinatesAt(nPoint + 1);
1381
                                dataCubic = gp.get3DCoordinatesAt(nPoint + 2);
1382
                                nPoint += 3;
1383
                                break;
1384
                        }
1385
                        //theType = theIterator.currentSegment(theData);
1386

    
1387
                        switch (theType) {
1388
                        case PathIterator.SEG_MOVETO:
1389

    
1390
                                // System.out.println("SEG_MOVETO");
1391
                                if (arrayCoords == null) {
1392
                                        arrayCoords = new ArrayList();
1393
                                } else {
1394
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1395

    
1396
                                        try {
1397
                                                LinearRing ring = geomFactory.createLinearRing(points);
1398

    
1399
                                                if (CGAlgorithms.isCCW(points)) {
1400
                                                        holes.add(ring);
1401
                                                } else {
1402
                                                        shells.add(ring);
1403
                                                }
1404
                                        } catch (Exception e) {
1405
                                                boolean same = true;
1406
                                                for (int i = 0; i < points.length-1 && same; i++) {
1407
                                                        if (points[i].x != points[i+1].x ||
1408
                                                                        points[i].y != points[i+1].y /*||
1409
                                                                        points[i].z != points[i+1].z*/
1410
                                                        ) {
1411
                                                                same = false;
1412
                                                        }
1413
                                                }
1414
                                                if (same) {
1415
                                                        return geomFactory.createPoint(points[0]);
1416
                                                }
1417

    
1418
                                                if (points.length > 1 && points.length <= 3) {
1419
                                                        // return geomFactory.createLineString(points);
1420
                                                        return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
1421
                                                }
1422

    
1423
                                                System.err.println(
1424
                                                "Caught Topology exception in GMLLinearRingHandler");
1425

    
1426
                                                return null;
1427
                                        }
1428

    
1429
                                        arrayCoords = new ArrayList();
1430
                                }
1431

    
1432
                                numParts++;
1433
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1434
                                break;
1435

    
1436
                        case PathIterator.SEG_LINETO:
1437
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1438
                                break;
1439

    
1440
                        case PathIterator.SEG_QUADTO:
1441
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1442
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
1443
                                break;
1444

    
1445
                        case PathIterator.SEG_CUBICTO:
1446
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1447
                                loadArrayCoordinates(arrayCoords, is3D, dataQuad);
1448
                                loadArrayCoordinates(arrayCoords, is3D, dataCubic);
1449
                                break;
1450

    
1451
                        case PathIterator.SEG_CLOSE:
1452
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1453
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
1454
                                break;
1455
                        } //end switch
1456

    
1457
                        //theIterator.next();
1458
                } //end while loop
1459

    
1460

    
1461
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1462
                Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
1463
                
1464
                if (!isClosed(firstCoord, lastCoord)) {
1465
                        arrayCoords.add(firstCoord);
1466
                }
1467
                points = CoordinateArrays.toCoordinateArray(arrayCoords);
1468

    
1469
                try {
1470
                        LinearRing ring = geomFactory.createLinearRing(points);
1471

    
1472
                        if (CGAlgorithms.isCCW(points)) {
1473
                                holes.add(ring);
1474
                        } else {
1475
                                shells.add(ring);
1476
                        }
1477
                        ring.setSRID(srid);
1478
                } catch (Exception e) {
1479
                        boolean same = true;
1480
                        for (int i = 0; i < points.length-1 && same; i++) {
1481
                                if (points[i].x != points[i+1].x ||
1482
                                                points[i].y != points[i+1].y /*||
1483
                                                points[i].z != points[i+1].z*/
1484
                                ) {
1485
                                        same = false;
1486
                                }
1487
                        }
1488
                        if (same) {
1489
                                geoJTS = geomFactory.createPoint(points[0]);
1490
                                geoJTS.setSRID(srid);
1491
                                return geoJTS;
1492
                        }
1493
                        if (points.length > 1 && points.length <= 3) {
1494
                                // return geomFactory.createLineString(points);
1495
                                geoJTS = geomFactory
1496
                                .createMultiLineString(new LineString[] { geomFactory
1497
                                                .createLineString(points) });
1498
                                geoJTS.setSRID(srid);
1499
                                return geoJTS;
1500
                        }
1501
                        System.err.println(
1502
                        "Caught Topology exception in GMLLinearRingHandler");
1503

    
1504
                        return null;
1505
                }
1506

    
1507
                /* linRing = new GeometryFactory().createLinearRing(
1508
                 CoordinateArrays.toCoordinateArray(arrayCoords)); */
1509

    
1510
                // System.out.println("NumParts = " + numParts);
1511
                //now we have a list of all shells and all holes
1512
                ArrayList holesForShells = new ArrayList(shells.size());
1513

    
1514
                for (int i = 0; i < shells.size(); i++) {
1515
                        holesForShells.add(new ArrayList());
1516
                }
1517

    
1518
                //find homes
1519
                for (int i = 0; i < holes.size(); i++) {
1520
                        LinearRing testRing = (LinearRing) holes.get(i);
1521
                        LinearRing minShell = null;
1522
                        Envelope minEnv = null;
1523
                        Envelope testEnv = testRing.getEnvelopeInternal();
1524
                        Coordinate testPt = testRing.getCoordinateN(0);
1525
                        LinearRing tryRing = null;
1526

    
1527
                        for (int j = 0; j < shells.size(); j++) {
1528
                                tryRing = (LinearRing) shells.get(j);
1529

    
1530
                                Envelope tryEnv = tryRing.getEnvelopeInternal();
1531

    
1532
                                if (minShell != null) {
1533
                                        minEnv = minShell.getEnvelopeInternal();
1534
                                }
1535

    
1536
                                boolean isContained = false;
1537
                                Coordinate[] coordList = tryRing.getCoordinates();
1538

    
1539
                                if (tryEnv.contains(testEnv) &&
1540
                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
1541
                                                                (pointInList(testPt, coordList)))) {
1542
                                        isContained = true;
1543
                                }
1544

    
1545
                                // check if this new containing ring is smaller than the current minimum ring
1546
                                if (isContained) {
1547
                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
1548
                                                minShell = tryRing;
1549
                                        }
1550
                                }
1551
                        }
1552

    
1553
                        if (minShell == null) {
1554
                                //                                        System.out.println(
1555
                                //                                        polygon found with a hole thats not inside a shell);
1556
                                //                                        azabala: we do the assumption that this hole is really a shell (polygon)
1557
                                //                                        whose point werent digitized in the right order
1558
                                Coordinate[] cs = testRing.getCoordinates();
1559
                                Coordinate[] reversed = new Coordinate[cs.length];
1560
                                int pointIndex = 0;
1561
                                for(int z = cs.length-1; z >= 0; z--){
1562
                                        reversed[pointIndex] = cs[z];
1563
                                        pointIndex++;
1564
                                }
1565
                                LinearRing newRing = geomFactory.createLinearRing(reversed);
1566
                                shells.add(newRing);
1567
                                holesForShells.add(new ArrayList());
1568
                        } else {
1569
                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
1570
                        }
1571
                }
1572

    
1573
                Polygon[] polygons = new Polygon[shells.size()];
1574

    
1575
                for (int i = 0; i < shells.size(); i++) {
1576
                        polygons[i] = geomFactory.createPolygon(
1577
                                        (LinearRing) shells.get(i),
1578
                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
1579
                        polygons[i].setSRID(srid);
1580
                }
1581
                
1582

    
1583
                holesForShells = null;
1584
                shells = null;
1585
                holes = null;
1586

    
1587
                geoJTS = geomFactory.createMultiPolygon(polygons);
1588
                geoJTS.setSRID(srid);
1589
                
1590
                return geoJTS;
1591
        }
1592
        
1593
        private static com.vividsolutions.jts.geom.Geometry ellipseToJts(Geometry shp, int srid) {
1594
                com.vividsolutions.jts.geom.Geometry geoJTS = null;
1595
                int theType;
1596
                int numParts = 0;
1597
                ArrayList arrayCoords = null;
1598
                int subType = shp.getGeometryType().getSubType();
1599
                boolean is3D = subType == 1 || subType == 3;
1600
                double[] dataLine = new double[3];
1601

    
1602

    
1603
                ArrayList shells = new ArrayList();
1604
                ArrayList holes = new ArrayList();
1605
                Coordinate[] points = null;
1606
                
1607
                //El pathIterator no tiene en cuenta coordenadas 3D, pero para la creaci?n de elipses y circulos
1608
                //es necesario el iterador que interpole puntos. El resultado es que en la creaci?n de geometr?as de este
1609
                //tipo no se puede asignar la Z porque se perder?a, pero gvSIG tampoco dispone de esta funci?n, as? que
1610
                //no se nota. Una vez creadas las geometr?a de tipo Elipse y circulo cuando las editamos ya tendr?n todos
1611
                //los puntos calculados y se toman como l?neas por lo que ya se podr?a asignar la Z.
1612
                
1613
                PathIterator theIterator = shp.getPathIterator(null, manager.getFlatness());
1614
                while (!theIterator.isDone()) {
1615
                        theType = theIterator.currentSegment(dataLine);
1616

    
1617
                        switch (theType) {
1618
                        case PathIterator.SEG_MOVETO:
1619
                                if (arrayCoords == null) {
1620
                                        arrayCoords = new ArrayList();
1621
                                } else {
1622
                                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
1623

    
1624
                                        try {
1625
                                                LinearRing ring = geomFactory.createLinearRing(points);
1626

    
1627
                                                if (CGAlgorithms.isCCW(points)) {
1628
                                                        holes.add(ring);
1629
                                                } else {
1630
                                                        shells.add(ring);
1631
                                                }
1632
                                        } catch (Exception e) {
1633
                                                boolean same = true;
1634
                                                for (int i = 0; i < points.length-1 && same; i++) {
1635
                                                        if (points[i].x != points[i+1].x ||
1636
                                                                        points[i].y != points[i+1].y /*||
1637
                                                                        points[i].z != points[i+1].z*/
1638
                                                        ) {
1639
                                                                same = false;
1640
                                                        }
1641
                                                }
1642
                                                if (same) {
1643
                                                        return geomFactory.createPoint(points[0]);
1644
                                                }
1645

    
1646
                                                if (points.length > 1 && points.length <= 3) {
1647
                                                        // return geomFactory.createLineString(points);
1648
                                                        return geomFactory.createMultiLineString(new LineString[] {geomFactory.createLineString(points)});
1649
                                                }
1650

    
1651
                                                System.err.println(
1652
                                                "Caught Topology exception in GMLLinearRingHandler");
1653

    
1654
                                                return null;
1655
                                        }
1656

    
1657
                                        arrayCoords = new ArrayList();
1658
                                }
1659

    
1660
                                numParts++;
1661
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1662
                                break;
1663

    
1664
                        case PathIterator.SEG_LINETO:
1665
                                loadArrayCoordinates(arrayCoords, is3D, dataLine);
1666
                                break;
1667

    
1668
                        case PathIterator.SEG_QUADTO:
1669
                                break;
1670

    
1671
                        case PathIterator.SEG_CUBICTO:
1672
                                break;
1673

    
1674
                        case PathIterator.SEG_CLOSE:
1675
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1676
                                loadArrayCoordinates(arrayCoords, is3D, new double[]{firstCoord.x, firstCoord.y, firstCoord.z});
1677
                                break;
1678
                        } //end switch
1679

    
1680
                        theIterator.next();
1681
                } //end while loop
1682

    
1683

    
1684
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
1685
                Coordinate lastCoord = (Coordinate) arrayCoords.get(arrayCoords.size() - 1);
1686
                
1687
                if (!isClosed(firstCoord, lastCoord)) {
1688
                        arrayCoords.add(firstCoord);
1689
                }
1690
                points = CoordinateArrays.toCoordinateArray(arrayCoords);
1691

    
1692
                try {
1693
                        LinearRing ring = geomFactory.createLinearRing(points);
1694

    
1695
                        if (CGAlgorithms.isCCW(points)) {
1696
                                holes.add(ring);
1697
                        } else {
1698
                                shells.add(ring);
1699
                        }
1700
                        ring.setSRID(srid);
1701
                } catch (Exception e) {
1702
                        boolean same = true;
1703
                        for (int i = 0; i < points.length-1 && same; i++) {
1704
                                if (points[i].x != points[i+1].x ||
1705
                                                points[i].y != points[i+1].y /*||
1706
                                                points[i].z != points[i+1].z*/
1707
                                ) {
1708
                                        same = false;
1709
                                }
1710
                        }
1711
                        if (same) {
1712
                                geoJTS = geomFactory.createPoint(points[0]);
1713
                                geoJTS.setSRID(srid);
1714
                                return geoJTS;
1715
                        }
1716
                        if (points.length > 1 && points.length <= 3) {
1717
                                // return geomFactory.createLineString(points);
1718
                                geoJTS = geomFactory
1719
                                .createMultiLineString(new LineString[] { geomFactory
1720
                                                .createLineString(points) });
1721
                                geoJTS.setSRID(srid);
1722
                                return geoJTS;
1723
                        }
1724
                        System.err.println(
1725
                        "Caught Topology exception in GMLLinearRingHandler");
1726

    
1727
                        return null;
1728
                }
1729

    
1730
                /* linRing = new GeometryFactory().createLinearRing(
1731
                 CoordinateArrays.toCoordinateArray(arrayCoords)); */
1732

    
1733
                // System.out.println("NumParts = " + numParts);
1734
                //now we have a list of all shells and all holes
1735
                ArrayList holesForShells = new ArrayList(shells.size());
1736

    
1737
                for (int i = 0; i < shells.size(); i++) {
1738
                        holesForShells.add(new ArrayList());
1739
                }
1740

    
1741
                //find homes
1742
                for (int i = 0; i < holes.size(); i++) {
1743
                        LinearRing testRing = (LinearRing) holes.get(i);
1744
                        LinearRing minShell = null;
1745
                        Envelope minEnv = null;
1746
                        Envelope testEnv = testRing.getEnvelopeInternal();
1747
                        Coordinate testPt = testRing.getCoordinateN(0);
1748
                        LinearRing tryRing = null;
1749

    
1750
                        for (int j = 0; j < shells.size(); j++) {
1751
                                tryRing = (LinearRing) shells.get(j);
1752

    
1753
                                Envelope tryEnv = tryRing.getEnvelopeInternal();
1754

    
1755
                                if (minShell != null) {
1756
                                        minEnv = minShell.getEnvelopeInternal();
1757
                                }
1758

    
1759
                                boolean isContained = false;
1760
                                Coordinate[] coordList = tryRing.getCoordinates();
1761

    
1762
                                if (tryEnv.contains(testEnv) &&
1763
                                                (CGAlgorithms.isPointInRing(testPt, coordList) ||
1764
                                                                (pointInList(testPt, coordList)))) {
1765
                                        isContained = true;
1766
                                }
1767

    
1768
                                // check if this new containing ring is smaller than the current minimum ring
1769
                                if (isContained) {
1770
                                        if ((minShell == null) || minEnv.contains(tryEnv)) {
1771
                                                minShell = tryRing;
1772
                                        }
1773
                                }
1774
                        }
1775

    
1776
                        if (minShell == null) {
1777
                                //                                        System.out.println(
1778
                                //                                        polygon found with a hole thats not inside a shell);
1779
                                //                                        azabala: we do the assumption that this hole is really a shell (polygon)
1780
                                //                                        whose point werent digitized in the right order
1781
                                Coordinate[] cs = testRing.getCoordinates();
1782
                                Coordinate[] reversed = new Coordinate[cs.length];
1783
                                int pointIndex = 0;
1784
                                for(int z = cs.length-1; z >= 0; z--){
1785
                                        reversed[pointIndex] = cs[z];
1786
                                        pointIndex++;
1787
                                }
1788
                                LinearRing newRing = geomFactory.createLinearRing(reversed);
1789
                                shells.add(newRing);
1790
                                holesForShells.add(new ArrayList());
1791
                        } else {
1792
                                ((ArrayList) holesForShells.get(shells.indexOf(minShell))).add(testRing);
1793
                        }
1794
                }
1795

    
1796
                Polygon[] polygons = new Polygon[shells.size()];
1797

    
1798
                for (int i = 0; i < shells.size(); i++) {
1799
                        polygons[i] = geomFactory.createPolygon(
1800
                                        (LinearRing) shells.get(i),
1801
                                        (LinearRing[]) ((ArrayList) holesForShells.get(i)).toArray(new LinearRing[0]));
1802
                        polygons[i].setSRID(srid);
1803
                }
1804
                
1805

    
1806
                holesForShells = null;
1807
                shells = null;
1808
                holes = null;
1809

    
1810
                geoJTS = geomFactory.createMultiPolygon(polygons);
1811
                geoJTS.setSRID(srid);
1812
                
1813
                return geoJTS;
1814
        }
1815
        
1816
        /**
1817
         * Loads one element in the <code>List</code> of coordinates with the 
1818
         * data contained in the array of doubles 
1819
         * @param arrayCoords
1820
         * @param is3D
1821
         * @param data
1822
         */
1823
        private static void loadArrayCoordinates(List arrayCoords, boolean is3D, double[] data) {
1824
                if(is3D)
1825
                        arrayCoords.add(new Coordinate(data[0], data[1], data[2]));
1826
                else
1827
                        arrayCoords.add(new Coordinate(data[0], data[1]));
1828
        }
1829

    
1830
}