Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.jts / src / main / java / org / gvsig / fmap / geom / jts / util / JTSUtils.java @ 47669

History | View | Annotate | Download (32.7 KB)

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

    
25
import com.vividsolutions.jts.geom.Coordinate;
26
import com.vividsolutions.jts.geom.CoordinateSequence;
27
import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
28
import com.vividsolutions.jts.geom.CoordinateSequences;
29
import com.vividsolutions.jts.geom.GeometryCollection;
30
import com.vividsolutions.jts.geom.GeometryFactory;
31
import com.vividsolutions.jts.geom.LineSegment;
32
import com.vividsolutions.jts.geom.LineString;
33
import com.vividsolutions.jts.geom.LinearRing;
34
import com.vividsolutions.jts.geom.MultiLineString;
35
import com.vividsolutions.jts.geom.MultiPoint;
36
import com.vividsolutions.jts.geom.MultiPolygon;
37
import com.vividsolutions.jts.geom.Triangle;
38
import com.vividsolutions.jts.linearref.LengthLocationMap;
39
import com.vividsolutions.jts.linearref.LinearLocation;
40
import com.vividsolutions.jts.linearref.LocationIndexedLine;
41
import com.vividsolutions.jts.operation.buffer.BufferParameters;
42
import com.vividsolutions.jts.operation.buffer.OffsetCurveBuilder;
43
import com.vividsolutions.jts.util.GeometricShapeFactory;
44
import java.util.ArrayList;
45
import java.util.List;
46
import org.cresques.cts.IProjection;
47
import org.gvsig.fmap.geom.Geometry;
48
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_BEVEL;
49
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_MITRE;
50
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_ROUND;
51
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
52
import org.gvsig.fmap.geom.exception.CreateGeometryException;
53
import org.gvsig.fmap.geom.jts.GeometryJTS;
54
import org.gvsig.fmap.geom.jts.aggregate.MultiLine2D;
55
import org.gvsig.fmap.geom.jts.aggregate.MultiLine2DM;
56
import org.gvsig.fmap.geom.jts.aggregate.MultiLine3D;
57
import org.gvsig.fmap.geom.jts.aggregate.MultiLine3DM;
58
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint2D;
59
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint2DM;
60
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint3D;
61
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint3DM;
62
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon2D;
63
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon2DM;
64
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon3D;
65
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon3DM;
66
import org.gvsig.fmap.geom.jts.complex.DefaultComplex;
67
import org.gvsig.fmap.geom.jts.mgeom.MCoordinate;
68
import org.gvsig.fmap.geom.jts.mgeom.MCoordinateSequence;
69
import org.gvsig.fmap.geom.jts.mgeom.MGeometryFactory;
70
import org.gvsig.fmap.geom.jts.primitive.curve.line.Line2D;
71
import org.gvsig.fmap.geom.jts.primitive.curve.line.Line2DM;
72
import org.gvsig.fmap.geom.jts.primitive.curve.line.Line3D;
73
import org.gvsig.fmap.geom.jts.primitive.curve.line.Line3DM;
74
import org.gvsig.fmap.geom.jts.primitive.point.Point2D;
75
import org.gvsig.fmap.geom.jts.primitive.point.Point2DM;
76
import org.gvsig.fmap.geom.jts.primitive.point.Point3D;
77
import org.gvsig.fmap.geom.jts.primitive.point.Point3DM;
78
import org.gvsig.fmap.geom.jts.primitive.point.PointJTS;
79
import org.gvsig.fmap.geom.jts.primitive.ring.Ring2D;
80
import org.gvsig.fmap.geom.jts.primitive.ring.Ring2DM;
81
import org.gvsig.fmap.geom.jts.primitive.ring.Ring3D;
82
import org.gvsig.fmap.geom.jts.primitive.ring.Ring3DM;
83
import org.gvsig.fmap.geom.jts.primitive.surface.polygon.Polygon2D;
84
import org.gvsig.fmap.geom.jts.primitive.surface.polygon.Polygon2DM;
85
import org.gvsig.fmap.geom.jts.primitive.surface.polygon.Polygon3D;
86
import org.gvsig.fmap.geom.jts.primitive.surface.polygon.Polygon3DM;
87
import org.gvsig.fmap.geom.primitive.Line;
88
import org.gvsig.fmap.geom.primitive.Point;
89
import org.gvsig.fmap.geom.primitive.Polygon;
90
import org.gvsig.fmap.geom.primitive.Primitive;
91
import org.gvsig.fmap.geom.primitive.Ring;
92
import org.gvsig.fmap.geom.type.GeometryType;
93
import org.slf4j.Logger;
94
import org.slf4j.LoggerFactory;
95

    
96
/**
97
 * @author fdiaz
98
 *
99
 */
100
public class JTSUtils {
101

    
102
    public static final Logger logger = LoggerFactory.getLogger(JTSUtils.class);
103

    
104
    private static class MyMGeometryFactory extends MGeometryFactory {
105

    
106
        /**
107
         *
108
         */
109
        private static final long serialVersionUID = -8174926092714691479L;
110

    
111
        @Override
112
        public com.vividsolutions.jts.geom.Point createPoint(CoordinateSequence coordinates) {
113
            if(!(coordinates instanceof MCoordinateSequence)){
114
                if (coordinates != null) {
115
                    coordinates = new MCoordinateSequence(coordinates);
116
                }
117
            }
118
            return (com.vividsolutions.jts.geom.Point) new com.vividsolutions.jts.geom.Point(coordinates, this);
119
        }
120

    
121
        @Override
122
        public LinearRing createLinearRing(CoordinateSequence coordinates) {
123
            if(!(coordinates instanceof MCoordinateSequence)){
124
                if (coordinates != null) {
125
                    coordinates = new MCoordinateSequence(coordinates);
126
                }
127
            }
128
            return super.createLinearRing(coordinates);
129
        }
130

    
131
        @Override
132
        public LineString createLineString(CoordinateSequence coordinates) {
133
            if(!(coordinates instanceof MCoordinateSequence)){
134
                if (coordinates != null) {
135
                    coordinates = new MCoordinateSequence(coordinates);
136
                }
137
            }
138
            return super.createLineString(coordinates);
139
        }
140

    
141
        @Override
142
        public MultiPoint createMultiPoint(CoordinateSequence coordinates) {
143
            if(!(coordinates instanceof MCoordinateSequence)){
144
                if (coordinates != null) {
145
                    coordinates = new MCoordinateSequence(coordinates);
146
                }
147
            }
148
            return super.createMultiPoint(coordinates);
149
        }
150

    
151
    }
152

    
153

    
154
    private static final com.vividsolutions.jts.geom.GeometryFactory factory =
155
        new com.vividsolutions.jts.geom.GeometryFactory();
156

    
157
    private static final com.vividsolutions.jts.geom.GeometryFactory mfactory = new MyMGeometryFactory();
158

    
159
    public static Point createPoint(GeometryType type, IProjection proj, Coordinate coordinate) throws CreateGeometryException {
160

    
161
        Point p;
162
        switch (type.getSubType()) {
163
        case Geometry.SUBTYPES.GEOM2D:
164
            p = new Point2D(proj, coordinate);
165
            break;
166
        case Geometry.SUBTYPES.GEOM2DM:
167
            p = new Point2DM(proj, coordinate);
168
            break;
169
        case Geometry.SUBTYPES.GEOM3D:
170
            p = new Point3D(proj, coordinate);
171
            break;
172
        case Geometry.SUBTYPES.GEOM3DM:
173
            p = new Point3DM(proj, coordinate);
174
            break;
175
        default:
176
            p = (Point) type.create();
177
            for (int i = 0; i < p.getDimension(); i++) {
178
                p.setCoordinateAt(i, coordinate.getOrdinate(i));
179
            }
180
            p.setProjection(proj);
181
            break;
182
        }
183
        return p;
184
    }
185

    
186
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(CoordinateSequence coordinates){
187
        com.vividsolutions.jts.geom.GeometryFactory theFactory = JTSUtils.factory;
188
        if(coordinates.size()>0 && coordinates.getCoordinate(0) instanceof MCoordinate){
189
            theFactory = mfactory;
190
        }
191
        return theFactory;
192
    }
193

    
194
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(Coordinate coordinate) {
195
        com.vividsolutions.jts.geom.GeometryFactory theFactory = JTSUtils.factory;
196
        if(coordinate instanceof MCoordinate){
197
            theFactory = mfactory;
198
        }
199
        return theFactory;
200
    }
201

    
202
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(Coordinate[] coordinates) {
203
        com.vividsolutions.jts.geom.GeometryFactory theFactory = JTSUtils.factory;
204
        if(coordinates.length>0 && coordinates[0] instanceof MCoordinate){
205
                theFactory = mfactory;
206
        }
207
        return theFactory;
208
    }
209

    
210
    public static LineString createJTSLineString(CoordinateSequence coordinates) {
211
        return getFactory(coordinates).createLineString(coordinates);
212
    }
213

    
214
    public static LinearRing createJTSLinearRing(CoordinateSequence coordinates) {
215
        GeometryFactory fact = getFactory(coordinates);
216
        return fact.createLinearRing(CoordinateSequences.ensureValidRing(fact.getCoordinateSequenceFactory(), coordinates));
217
    }
218

    
219
    public static LinearRing createJTSLinearRing(Coordinate[] coordinates) {
220
        GeometryFactory fact = getFactory(coordinates);
221
        CoordinateSequenceFactory coordinateSequenceFactory = fact.getCoordinateSequenceFactory();
222
        return fact.createLinearRing(CoordinateSequences.ensureValidRing(coordinateSequenceFactory, coordinateSequenceFactory.create(coordinates)));
223
    }
224

    
225
    public static MultiPoint createJTSMultiPoint(CoordinateSequence coordinates) {
226
        return getFactory(coordinates).createMultiPoint(coordinates);
227
    }
228

    
229
    public static Geometry createGeometry(IProjection proj, com.vividsolutions.jts.geom.Geometry jtsGeom) {
230
        return createGeometry(proj, jtsGeom, null);
231
    }
232
    
233
    public static Geometry createGeometry(IProjection proj, com.vividsolutions.jts.geom.Geometry jtsGeom, GeometryType typeWhenEmpty) {
234
        if(jtsGeom.isEmpty()){
235
            if(typeWhenEmpty == null){
236
                 return null;
237
            }
238
            try {
239
                return typeWhenEmpty.create();
240
            } catch (CreateGeometryException ex) {
241
                return null;
242
            }
243
        }
244
        if (jtsGeom instanceof com.vividsolutions.jts.geom.Point) {
245
            Coordinate coordinate = jtsGeom.getCoordinate();
246
            if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
247
                if (Double.isNaN(coordinate.z)) {
248
                    return new Point2DM(proj, coordinate);
249
                } else {
250
                    return new Point3DM(proj, coordinate);
251
                }
252
            } else {
253
                if (Double.isNaN(coordinate.z)) {
254
                    return new Point2D(proj, coordinate);
255
                } else {
256
                    return new Point3D(proj, coordinate);
257
                }
258
            }
259
        }
260

    
261
        if (jtsGeom instanceof com.vividsolutions.jts.geom.LineString) {
262
            Coordinate[] coordinates = jtsGeom.getCoordinates();
263
            Coordinate coordinate = jtsGeom.getCoordinate();
264
            com.vividsolutions.jts.geom.LineString lineString = (com.vividsolutions.jts.geom.LineString) jtsGeom;
265
            if (!lineString.isEmpty()) {
266
                Line line;
267
                if (jtsGeom.getFactory() instanceof MGeometryFactory) {
268
                    if (coordinate!=null && Double.isNaN(coordinate.z)) {
269
                        line = new Line2DM(coordinates);
270
                    } else {
271
                        line = new Line3DM(coordinates);
272
                    }
273
                } else {
274
                    if (coordinate!=null && Double.isNaN(coordinate.z)) {
275
                        line = new Line2D(coordinates);
276
                    } else {
277
                        line = new Line3D(coordinates);
278
                    }
279
                }
280
                line.setProjection(proj);
281
                return line;
282
            }
283
        }
284

    
285
        if (jtsGeom instanceof com.vividsolutions.jts.geom.Polygon && !jtsGeom.isEmpty()) {
286
            Polygon polygon;
287
            com.vividsolutions.jts.geom.Polygon polygonJTS = (com.vividsolutions.jts.geom.Polygon)jtsGeom;
288
            Coordinate[] coordinates = polygonJTS.getExteriorRing().getCoordinates();
289
            Coordinate coordinate = jtsGeom.getCoordinate();
290
            if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
291
                if (Double.isNaN(coordinate.z)) {
292
                    polygon = new Polygon2DM(coordinates);
293
                } else {
294
                    polygon = new Polygon3DM(coordinates);
295
                }
296
            } else {
297
                if (Double.isNaN(coordinate.z)) {
298
                    polygon = new Polygon2D(coordinates);
299
                } else {
300
                    polygon = new Polygon3D(coordinates);
301
                }
302
            }
303
            polygon.setProjection(proj);
304
            for(int i = 0; i<polygonJTS.getNumInteriorRing(); i++){
305
                LineString ringJTS = polygonJTS.getInteriorRingN(i);
306
                coordinates = ringJTS.getCoordinates();
307
                coordinate = ringJTS.getCoordinate();
308
                Ring ring;
309
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
310
                    if (Double.isNaN(coordinate.z)) {
311
                        ring = new Ring2DM(coordinates);
312
                    } else {
313
                        ring = new Ring3DM(coordinates);
314
                    }
315
                } else {
316
                    if (Double.isNaN(coordinate.z)) {
317
                        ring = new Ring2D(coordinates);
318
                    } else {
319
                        ring = new Ring3D(coordinates);
320
                    }
321
                }
322
                ring.setProjection(proj);
323
                polygon.addInteriorRing(ring);
324
            }
325
            return polygon;
326
        }
327

    
328
        if (jtsGeom instanceof com.vividsolutions.jts.geom.GeometryCollection) {
329
            GeometryCollection collection = (com.vividsolutions.jts.geom.GeometryCollection)jtsGeom;
330
            Coordinate coordinate = collection.getCoordinate();
331
            MultiPrimitive multiprimitive = null;
332
            if (jtsGeom instanceof MultiLineString) {
333
                    if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
334
                        if (Double.isNaN(coordinate.z)) {
335
                            multiprimitive = new MultiLine2DM();
336
                        } else {
337
                            multiprimitive = new MultiLine3DM();
338
                        }
339
                    } else {
340
                        if (Double.isNaN(coordinate.z)) {
341
                            multiprimitive = new MultiLine2D();
342
                        } else {
343
                            multiprimitive = new MultiLine3D();
344
                        }
345
                    }
346
            } else if (jtsGeom instanceof MultiPolygon) {
347
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
348
                    if (Double.isNaN(coordinate.z)) {
349
                        multiprimitive = new MultiPolygon2DM();
350
                    } else {
351
                        multiprimitive = new MultiPolygon3DM();
352
                    }
353
                } else {
354
                    if (Double.isNaN(coordinate.z)) {
355
                        multiprimitive = new MultiPolygon2D();
356
                    } else {
357
                        multiprimitive = new MultiPolygon3D();
358
                    }
359
                }
360
            } else if (jtsGeom instanceof MultiPoint) {
361
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
362
                    if (Double.isNaN(coordinate.z)) {
363
                        multiprimitive = new MultiPoint2DM();
364
                    } else {
365
                        multiprimitive = new MultiPoint3DM();
366
                    }
367
                } else {
368
                    if (Double.isNaN(coordinate.z)) {
369
                        multiprimitive = new MultiPoint2D();
370
                    } else {
371
                        multiprimitive = new MultiPoint3D();
372
                    }
373
                }
374
            }
375

    
376
            if (multiprimitive != null) {
377
                for (int i = 0; i < collection.getNumGeometries(); i++) {
378
                    com.vividsolutions.jts.geom.Geometry geometry = collection.getGeometryN(i);
379
                    multiprimitive.addPrimitive((Primitive) createGeometry(proj, geometry));
380
                }
381
                multiprimitive.setProjection(proj);
382
                return multiprimitive;
383
            } else {
384
                int subtype;
385
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
386
                    if (Double.isNaN(coordinate.z)) {
387
                        subtype = Geometry.SUBTYPES.GEOM2DM;
388
                    } else {
389
                        subtype = Geometry.SUBTYPES.GEOM3DM;
390
                    }
391
                } else {
392
                    if (Double.isNaN(coordinate.z)) {
393
                        subtype = Geometry.SUBTYPES.GEOM2D;
394
                    } else {
395
                        subtype = Geometry.SUBTYPES.GEOM3D;
396
                    }
397
                }
398
                DefaultComplex complex = new DefaultComplex(subtype);
399
                for (int i = 0; i < collection.getNumGeometries(); i++) {
400
                    com.vividsolutions.jts.geom.Geometry geometry = collection.getGeometryN(i);
401
                    complex.addPrimitive((Primitive) createGeometry(proj, geometry));
402
                }
403
                complex.setProjection(proj);
404
                return complex;
405
            }
406
        }
407

    
408
        return null;
409
    }
410

    
411
    /**
412
     * This function is called when the we need force types, that is the
413
     * destination
414
     * type does not match with the input geometry type
415
     *
416
     * @param g
417
     * @param sourceType
418
     * @param destinationType
419
     * @return
420
     */
421
    public static com.vividsolutions.jts.geom.Geometry convertTypes(com.vividsolutions.jts.geom.Geometry g,
422
        int sourceType, int destinationType) {
423

    
424
        com.vividsolutions.jts.geom.GeometryFactory theFactory = g.getFactory();
425

    
426
        if ((sourceType == Geometry.TYPES.CURVE || sourceType == Geometry.TYPES.SPLINE
427
            || sourceType == Geometry.TYPES.ARC || sourceType == Geometry.TYPES.ELLIPTICARC
428
            || sourceType == Geometry.TYPES.CIRCUMFERENCE || sourceType == Geometry.TYPES.PERIELLIPSE)
429
            && destinationType == Geometry.TYPES.MULTISURFACE) {
430
            if (g instanceof MultiLineString) {
431
                com.vividsolutions.jts.geom.Polygon[] poly = new com.vividsolutions.jts.geom.Polygon[((MultiLineString) g).getNumGeometries()];
432
                for (int i = 0; i < ((MultiLineString) g).getNumGeometries(); i++) {
433
                    com.vividsolutions.jts.geom.Geometry lineString = ((MultiLineString) g).getGeometryN(i);
434
                    poly[i] = convertLineStringToPolygon((LineString) lineString);
435
                }
436
                return theFactory.createMultiPolygon(poly);
437
            } else {
438
                return convertLineStringToPolygon((LineString) g);
439
            }
440
        }
441

    
442
        if ((sourceType == Geometry.TYPES.CIRCLE || sourceType == Geometry.TYPES.ELLIPSE
443
            || sourceType == Geometry.TYPES.ELLIPTICARC || sourceType == Geometry.TYPES.FILLEDSPLINE)
444
            && destinationType == Geometry.TYPES.MULTICURVE) {
445
            if (g instanceof com.vividsolutions.jts.geom.Polygon) {
446
                com.vividsolutions.jts.geom.Polygon poly = (com.vividsolutions.jts.geom.Polygon) g;
447
                LineString lineString = theFactory.createLinearRing(poly.getCoordinates());
448
                return theFactory.createMultiLineString(new LineString[] { lineString });
449
            }
450
        }
451
        return g;
452
    }
453

    
454
    private static com.vividsolutions.jts.geom.Polygon convertLineStringToPolygon(LineString line) {
455
        Coordinate[] coordinates = line.getCoordinates();
456
        com.vividsolutions.jts.geom.GeometryFactory theFactory = line.getFactory();
457
        LinearRing shell = theFactory.createLinearRing(coordinates);
458
        com.vividsolutions.jts.geom.Polygon pol = theFactory.createPolygon(shell, null);
459
        return pol;
460
    }
461

    
462
    public static MCoordinate createMCoordinate(double x, double y, double m) {
463
        return MCoordinate.create2dWithMeasure(x, y, m);
464
    }
465

    
466
    public static MCoordinate createMCoordinate(double x, double y, double z, double m) {
467
        return MCoordinate.create3dWithMeasure(x, y, z, m);
468
    }
469

    
470
    /**
471
     * @param init
472
     * @param middle
473
     * @param end
474
     * @return
475
     */
476
    public static Coordinate getCircumcentre(Point init, Point middle, Point end) {
477
        Triangle triangle =
478
            new Triangle(((PointJTS) init).getJTSCoordinate(),
479
                ((PointJTS) middle).getJTSCoordinate(),
480
                ((PointJTS) end).getJTSCoordinate());
481
        return triangle.circumcentre();
482
    }
483

    
484
    public static LineString createJTSLineStringFromArcPoints(Point centre, double radius, double startAngle, double endAngle){
485
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
486
        shapeFactory.setCentre(((PointJTS)centre).getJTSCoordinate());
487
        shapeFactory.setSize(radius*2);
488
        return shapeFactory.createArc(startAngle, endAngle);
489
    }
490

    
491
    public static MultiLineString createJTSMultiLineString(LineString[] lineStrings) {
492
        com.vividsolutions.jts.geom.GeometryFactory theFactory = JTSUtils.factory;
493
        if(lineStrings.length>0){
494
            theFactory = lineStrings[0].getFactory();
495
        }
496
        return theFactory.createMultiLineString(lineStrings);
497
    }
498

    
499
    /**
500
     * @param coordinates
501
     * @param interiorRings
502
     * @return
503
     */
504
    public static com.vividsolutions.jts.geom.Polygon createJTSPolygon(ArrayListCoordinateSequence coordinates,
505
        List<Ring> interiorRings) {
506
        com.vividsolutions.jts.geom.GeometryFactory theFactory = getFactory(coordinates);
507

    
508
        LinearRing shell = theFactory.createLinearRing(coordinates);
509
        LinearRing[] holes = new LinearRing[interiorRings.size()];
510
        for(int i=0; i<interiorRings.size(); i++){
511
            Ring ring = interiorRings.get(i);
512
            holes[i] = (LinearRing) ((GeometryJTS) ring).getJTS();
513
        }
514
        return theFactory.createPolygon(shell, holes);
515
    }
516

    
517

    
518
    /**
519
     * @param coordinates
520
     * @return
521
     */
522
    public static com.vividsolutions.jts.geom.Polygon createJTSPolygon(ArrayListCoordinateSequence coordinates) {
523
        com.vividsolutions.jts.geom.GeometryFactory theFactory = getFactory(coordinates);
524

    
525
        LinearRing shell = theFactory.createLinearRing(coordinates);
526
        return theFactory.createPolygon(shell);
527
    }
528

    
529
    public static com.vividsolutions.jts.geom.MultiPolygon createJTSMultiPolygon(com.vividsolutions.jts.geom.Polygon[] polygons){
530
        com.vividsolutions.jts.geom.GeometryFactory theFactory = JTSUtils.factory;
531
        if(polygons.length>0){
532
            theFactory = polygons[0].getFactory();
533
        }
534
        return theFactory.createMultiPolygon(polygons);
535
    }
536

    
537
    /**
538
     * Returns the intersection point between an ellipse and her minor axis.
539
     *
540
     * @param init
541
     * @param end
542
     * @param ydist
543
     * @return
544
     */
545
    public static Coordinate getPointAtYAxisInEllipse(Point init, Point end, Double ydist) {
546

    
547
        LineSegment segment = new LineSegment(((PointJTS) init).getJTSCoordinate(),
548
            ((PointJTS) end).getJTSCoordinate());
549
        Coordinate middle = segment.midPoint();
550

    
551
        LineSegment midSegment = new LineSegment(middle, ((PointJTS) end).getJTSCoordinate());
552
        double modulus = midSegment.getLength();
553

    
554
        //Mayor semi-axis unitary vector
555
        Coordinate uni = new Coordinate((end.getX()-middle.x)/modulus, (end.getY()-middle.y)/modulus);
556

    
557
        //Minor axis unitary vector
558
        Coordinate perpUni = new Coordinate(-uni.y,uni.x);
559

    
560
        Coordinate point = new Coordinate(middle.x+(perpUni.x*ydist), middle.y+(perpUni.y*ydist));
561

    
562
        return point;
563
    }
564

    
565
    /**
566
     * Returns the middle point between two points.
567
     *
568
     * @param init
569
     * @param end
570
     * @return
571
     */
572
    public static Coordinate getMidPoint(Point init, Point end) {
573

    
574
        LineSegment segment = new LineSegment(((PointJTS) init).getJTSCoordinate(),
575
            ((PointJTS) end).getJTSCoordinate());
576
        Coordinate middle = segment.midPoint();
577
        return middle;
578
    }
579

    
580
    /**
581
     * @param coordinate
582
     * @return
583
     */
584
    public static com.vividsolutions.jts.geom.Geometry createJTSPoint(Coordinate coordinate) {
585
        return getFactory(coordinate).createPoint(coordinate);
586
    }
587

    
588
    /**
589
     * @param coordinates
590
     * @return
591
     */
592
    public static com.vividsolutions.jts.geom.Geometry createJTSPolygon(Coordinate[] coordinates) {
593
        return getFactory(coordinates).createPolygon(coordinates);
594
    }
595

    
596
    public static BufferParameters getBufferParameters(){
597
        BufferParameters bufParams = new BufferParameters();
598
        bufParams.setSingleSided(true);
599
        bufParams.setEndCapStyle(BufferParameters.CAP_FLAT);
600
        bufParams.setJoinStyle(BufferParameters.CAP_ROUND);
601
        return bufParams;
602
    }
603
    
604
    public static BufferParameters getBufferParameters(int joinStyle, int endCapStyle){
605
        BufferParameters bufParams = new BufferParameters();
606
        bufParams.setSingleSided(true);
607
        bufParams.setEndCapStyle(endCapStyle);
608
        bufParams.setJoinStyle(joinStyle);
609
        bufParams.setQuadrantSegments(calculateQuadrantSegments(joinStyle));
610
        return bufParams;
611
    }
612
    
613
    public static int calculateQuadrantSegments(int joinStyle) throws IllegalArgumentException {
614
        int quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
615
        switch(joinStyle){
616
            case JOIN_STYLE_ROUND:
617
                quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
618
                break;
619
            case JOIN_STYLE_MITRE:
620
                quadrantSegments = - (int) BufferParameters.DEFAULT_MITRE_LIMIT;
621
                break;
622
            case JOIN_STYLE_BEVEL:
623
                quadrantSegments = 0;
624
                break;
625
            default:
626
                throw new IllegalArgumentException("Invalid jointStyle "+joinStyle);
627
        }
628
        return quadrantSegments;
629
    }
630

    
631
    /**
632
     * Creates a offset from a closed line at a distance
633
     *
634
     * @param proj
635
     * @param coordinates
636
     * @param distance
637
     * @return
638
     */
639
    public static Geometry offsetClosedLine(IProjection proj, ArrayListCoordinateSequence coordinates, double distance) {
640
        com.vividsolutions.jts.geom.Geometry jtsGeom = JTSUtils.createJTSPolygon(coordinates);
641
        com.vividsolutions.jts.geom.Geometry geomJTS = jtsGeom.buffer(distance);
642
        return jtsPolygonToJtsMultiLineString(geomJTS, proj);
643
    }
644

    
645
    /**
646
     * Creates a offset from a closed line at a distance
647
     *
648
     * @param proj
649
     * @param coordinates
650
     * @param joinStyle
651
     * @param distance
652
     * @return
653
     */
654
    public static Geometry offsetClosedLine(IProjection proj, ArrayListCoordinateSequence coordinates, int joinStyle, double distance) {
655
        com.vividsolutions.jts.geom.Geometry jtsGeom = JTSUtils.createJTSPolygon(coordinates);
656
        com.vividsolutions.jts.geom.Geometry geomJTS = jtsGeom.buffer(distance, calculateQuadrantSegments(joinStyle), BufferParameters.CAP_FLAT);
657
        return jtsPolygonToJtsMultiLineString(geomJTS, proj);
658
    }
659

    
660
    protected static Geometry jtsPolygonToJtsMultiLineString(com.vividsolutions.jts.geom.Geometry geomJTS, IProjection proj) {
661
        if (geomJTS instanceof com.vividsolutions.jts.geom.Polygon) {
662
            com.vividsolutions.jts.geom.Polygon polygonJTS = (com.vividsolutions.jts.geom.Polygon) geomJTS;
663
            LineString shell = polygonJTS.getExteriorRing();
664
            int numHoles = polygonJTS.getNumInteriorRing();
665
            if (numHoles > 0) {
666
                LineString[] lineStrings = new LineString[numHoles + 1];
667
                lineStrings[0] = shell;
668
                for (int i = 0; i < numHoles; i++) {
669
                    LineString hole = polygonJTS.getInteriorRingN(i);
670
                    lineStrings[i + 1] = hole;
671
                }
672
                return JTSUtils.createGeometry(proj, JTSUtils.createJTSMultiLineString(lineStrings));
673
            }
674
            return JTSUtils.createGeometry(proj, shell);
675
        } else if (geomJTS instanceof com.vividsolutions.jts.geom.MultiPolygon) {
676
            MultiPolygon multiPolygonJTS = (com.vividsolutions.jts.geom.MultiPolygon) geomJTS;
677
            List<LineString> lineStringList = new ArrayList<>();
678
            for (int i = 0; i < multiPolygonJTS.getNumGeometries(); i++) {
679
                com.vividsolutions.jts.geom.Polygon polygonJTS =
680
                        (com.vividsolutions.jts.geom.Polygon) multiPolygonJTS.getGeometryN(i);
681
                lineStringList.add(polygonJTS.getExteriorRing());
682
                int numHoles = polygonJTS.getNumInteriorRing();
683
                if (numHoles > 0) {
684
                    for (int h = 0; h < numHoles; h++) {
685
                        LineString hole = polygonJTS.getInteriorRingN(i);
686
                        lineStringList.add(hole);
687
                    }
688
                }
689
            }
690
            return JTSUtils.createGeometry(proj, JTSUtils.createJTSMultiLineString(lineStringList.toArray(new LineString[lineStringList.size()])));
691
        }
692
        //No deber?a pasar por aqu?
693
        logger.warn("offsetClosedLine does not return or Polygon JTS or MultiPolygon JTS");
694
        return null;
695
    }
696

    
697
    /**
698
     * Creates a raw offset of a open line at a distance.
699
     *
700
     * @param coordinates
701
     * @param distance
702
     * @return
703
     */
704
    public static Geometry offsetRawOpenLine(IProjection proj, ArrayListCoordinateSequence coordinates, double distance) {
705
        com.vividsolutions.jts.geom.GeometryFactory theFactory = getFactory(coordinates);
706

    
707
        BufferParameters bufParams = JTSUtils.getBufferParameters();
708
        LineString jtsGeom = JTSUtils.createJTSLineString(coordinates);
709

    
710
         OffsetCurveBuilder ocb = new
711
         OffsetCurveBuilder(theFactory.getPrecisionModel(), bufParams);
712
         Coordinate[] coords = ocb.getOffsetCurve(jtsGeom.getCoordinates(), distance);
713
         CoordinateSequence coordSequence = theFactory.getCoordinateSequenceFactory().create(coords);
714
         com.vividsolutions.jts.geom.Geometry offsetGeom = JTSUtils.createJTSLineString(coordSequence);
715

    
716
         return JTSUtils.createGeometry(proj, offsetGeom);
717
    }
718

    
719
    /*
720
     *
721
     */
722
    public static double straightLineThroughTwoPointsEquation(double x1, double x2, double y1, double y2, double x) {
723
        if (x2 - x1 == 0.0) {
724
            return Double.POSITIVE_INFINITY;
725
        }
726
        return ((y2 - y1) * (x - x1) / (x2 - x1)) + y1;
727
    }
728

    
729
    
730
    public static Point extractPointFromLine(GeometryJTS geom, double len) {
731
        com.vividsolutions.jts.geom.Geometry jts = geom.getJTS();
732
        LinearLocation location = LengthLocationMap.getLocation(jts, len);
733

    
734
        LineString lineComp = (LineString) jts.getGeometryN(location.getComponentIndex());
735
        Coordinate coordinate = lineComp.getCoordinateN(location.getSegmentIndex());
736
        if (!(location.getSegmentIndex() >= lineComp.getNumPoints() - 1)){
737
            Coordinate p1 = lineComp.getCoordinateN(location.getSegmentIndex() + 1);
738
            coordinate = pointAlongSegmentByFraction(coordinate, p1, location.getSegmentFraction());
739
        }
740
        
741
        GeometryType type = geom.getGeometryType();
742
        
743
        if(type.hasZ() && type.hasM()){
744
            return new Point3DM(geom.getProjection(), coordinate);
745
        }
746
        if(type.hasZ()){
747
            return new Point3D(geom.getProjection(), coordinate);
748
        }
749
        if(type.hasM()){
750
            return new Point2DM(geom.getProjection(), coordinate);
751
        }
752
        return new Point2D(geom.getProjection(), coordinate);
753
        
754
    }
755

    
756
    
757
    private static Coordinate pointAlongSegmentByFraction(Coordinate p0, Coordinate p1, double frac) {
758
        if (frac <= 0.0) {
759
            return p0;
760
        }
761
        if (frac >= 1.0) {
762
            return p1;
763
        }
764

    
765
        double x = (p1.x - p0.x) * frac + p0.x;
766
        double y = (p1.y - p0.y) * frac + p0.y;
767
        // interpolate Z value. If either input Z is NaN, result z will be NaN as well.
768
        double z = (p1.z - p0.z) * frac + p0.z;
769
        if (p0 instanceof MCoordinate && p1 instanceof MCoordinate) {
770
            // interpolate M value. If either input M is NaN, result M will be NaN as well.
771
            double m = (((MCoordinate)p1).m - ((MCoordinate)p0).m) * frac + ((MCoordinate)p0).m;
772
            return new MCoordinate(x, y, z, m);
773
        }
774
        
775
        return new Coordinate(x, y, z);
776
    }
777
    
778
    public static double getPathLengthFromLine(GeometryJTS geom, Point point) {
779
        LocationIndexedLine lil = new LocationIndexedLine(geom.getJTS());
780
        LinearLocation pointLocation = lil.indexOf(((PointJTS)point).getJTSCoordinate());
781
        
782
        LinearLocation startLocation = lil.getStartIndex();
783
        
784
        com.vividsolutions.jts.geom.Geometry geomJTS = lil.extractLine(startLocation, pointLocation);
785
        
786
        return geomJTS.getLength();
787
    }
788
    
789
}