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

History | View | Annotate | Download (29 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 java.util.ArrayList;
26
import java.util.List;
27

    
28
import com.vividsolutions.jts.geom.Coordinate;
29
import com.vividsolutions.jts.geom.CoordinateSequence;
30
import com.vividsolutions.jts.geom.GeometryCollection;
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.operation.buffer.BufferParameters;
39
import com.vividsolutions.jts.operation.buffer.OffsetCurveBuilder;
40
import com.vividsolutions.jts.util.GeometricShapeFactory;
41
import org.cresques.cts.IProjection;
42

    
43
import org.hibernate.spatial.jts.mgeom.MCoordinateSequence;
44
import org.hibernate.spatial.jts.mgeom.MGeometryFactory;
45
import org.slf4j.Logger;
46
import org.slf4j.LoggerFactory;
47

    
48
import org.gvsig.fmap.geom.Geometry;
49
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_BEVEL;
50
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_MITRE;
51
import static org.gvsig.fmap.geom.Geometry.JOIN_STYLE_ROUND;
52
import org.gvsig.fmap.geom.GeometryException;
53
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
54
import org.gvsig.fmap.geom.exception.CreateGeometryException;
55
import org.gvsig.fmap.geom.jts.GeometryJTS;
56
import org.gvsig.fmap.geom.jts.MCoordinate;
57
import org.gvsig.fmap.geom.jts.aggregate.MultiLine2D;
58
import org.gvsig.fmap.geom.jts.aggregate.MultiLine2DM;
59
import org.gvsig.fmap.geom.jts.aggregate.MultiLine3D;
60
import org.gvsig.fmap.geom.jts.aggregate.MultiLine3DM;
61
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint2D;
62
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint2DM;
63
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint3D;
64
import org.gvsig.fmap.geom.jts.aggregate.MultiPoint3DM;
65
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon2D;
66
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon2DM;
67
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon3D;
68
import org.gvsig.fmap.geom.jts.aggregate.MultiPolygon3DM;
69
import org.gvsig.fmap.geom.jts.complex.DefaultComplex;
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

    
94
/**
95
 * @author fdiaz
96
 *
97
 */
98
public class JTSUtils {
99

    
100
    public static final Logger logger = LoggerFactory.getLogger(JTSUtils.class);
101

    
102
    private static class MyMGeometryFactory extends org.hibernate.spatial.jts.mgeom.MGeometryFactory {
103

    
104
        /**
105
         *
106
         */
107
        private static final long serialVersionUID = -8174926092714691479L;
108

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

    
118
        public LinearRing createLinearRing(CoordinateSequence coordinates) {
119
            if(!(coordinates instanceof MCoordinateSequence)){
120
                if (coordinates != null) {
121
                    coordinates = new MCoordinateSequence(coordinates);
122
                }
123
            }
124
            return super.createLinearRing(coordinates);
125
        }
126

    
127
        @Override
128
        public LineString createLineString(CoordinateSequence coordinates) {
129
            if(!(coordinates instanceof MCoordinateSequence)){
130
                if (coordinates != null) {
131
                    coordinates = new MCoordinateSequence(coordinates);
132
                }
133
            }
134
            return super.createLineString(coordinates);
135
        }
136

    
137
        public MultiPoint createMultiPoint(CoordinateSequence coordinates) {
138
            if(!(coordinates instanceof MCoordinateSequence)){
139
                if (coordinates != null) {
140
                    coordinates = new MCoordinateSequence(coordinates);
141
                }
142
            }
143
            return super.createMultiPoint(coordinates);
144
        }
145

    
146
    }
147

    
148

    
149
    private static final com.vividsolutions.jts.geom.GeometryFactory factory =
150
        new com.vividsolutions.jts.geom.GeometryFactory();
151

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

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

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

    
181
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(CoordinateSequence coordinates){
182
        com.vividsolutions.jts.geom.GeometryFactory factory = JTSUtils.factory;
183
        if(coordinates.size()>0 && coordinates.getCoordinate(0) instanceof org.hibernate.spatial.jts.mgeom.MCoordinate){
184
            factory = mfactory;
185
        }
186
        return factory;
187
    }
188

    
189
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(Coordinate coordinate) {
190
        com.vividsolutions.jts.geom.GeometryFactory factory = JTSUtils.factory;
191
        if(coordinate instanceof org.hibernate.spatial.jts.mgeom.MCoordinate){
192
            factory = mfactory;
193
        }
194
        return factory;
195
    }
196

    
197
    public static com.vividsolutions.jts.geom.GeometryFactory getFactory(Coordinate[] coordinates) {
198
        com.vividsolutions.jts.geom.GeometryFactory factory = JTSUtils.factory;
199
        if(coordinates.length>0 && coordinates[0] instanceof org.hibernate.spatial.jts.mgeom.MCoordinate){
200
                factory = mfactory;
201
        }
202
        return factory;
203
    }
204

    
205
    public static LineString createJTSLineString(CoordinateSequence coordinates) {
206
        return getFactory(coordinates).createLineString(coordinates);
207
    }
208

    
209
    public static LinearRing createJTSLinearRing(CoordinateSequence coordinates) {
210
        return getFactory(coordinates).createLinearRing(coordinates);
211
    }
212

    
213
    public static MultiPoint createJTSMultiPoint(CoordinateSequence coordinates) {
214
        return getFactory(coordinates).createMultiPoint(coordinates);
215
    }
216

    
217
    public static Geometry createGeometry(IProjection proj, com.vividsolutions.jts.geom.Geometry jtsGeom) {
218
        if (jtsGeom instanceof com.vividsolutions.jts.geom.Point) {
219
            Coordinate coordinate = jtsGeom.getCoordinate();
220
            if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
221
                if (Double.isNaN(coordinate.z)) {
222
                    return new Point2DM(proj, coordinate);
223
                } else {
224
                    return new Point3DM(proj, coordinate);
225
                }
226
            } else {
227
                if (Double.isNaN(coordinate.z)) {
228
                    return new Point2D(proj, coordinate);
229
                } else {
230
                    return new Point3D(proj, coordinate);
231
                }
232
            }
233
        }
234

    
235
        if (jtsGeom instanceof com.vividsolutions.jts.geom.LineString) {
236
            Coordinate[] coordinates = jtsGeom.getCoordinates();
237
            Coordinate coordinate = jtsGeom.getCoordinate();
238
            com.vividsolutions.jts.geom.LineString lineString = (com.vividsolutions.jts.geom.LineString) jtsGeom;
239
            if (!lineString.isEmpty()) {
240
                Line line;
241
                if (jtsGeom.getFactory() instanceof MGeometryFactory) {
242
                    if (coordinate!=null && Double.isNaN(coordinate.z)) {
243
                        line = new Line2DM(coordinates);
244
                    } else {
245
                        line = new Line3DM(coordinates);
246
                    }
247
                } else {
248
                    if (coordinate!=null && Double.isNaN(coordinate.z)) {
249
                        line = new Line2D(coordinates);
250
                    } else {
251
                        line = new Line3D(coordinates);
252
                    }
253
                }
254
                line.setProjection(proj);
255
                return line;
256
            }
257
        }
258

    
259
        if (jtsGeom instanceof com.vividsolutions.jts.geom.Polygon && !jtsGeom.isEmpty()) {
260
            Polygon polygon;
261
            com.vividsolutions.jts.geom.Polygon polygonJTS = (com.vividsolutions.jts.geom.Polygon)jtsGeom;
262
            Coordinate[] coordinates = polygonJTS.getExteriorRing().getCoordinates();
263
            Coordinate coordinate = jtsGeom.getCoordinate();
264
            if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
265
                if (Double.isNaN(coordinate.z)) {
266
                    polygon = new Polygon2DM(coordinates);
267
                } else {
268
                    polygon = new Polygon3DM(coordinates);
269
                }
270
            } else {
271
                if (Double.isNaN(coordinate.z)) {
272
                    polygon = new Polygon2D(coordinates);
273
                } else {
274
                    polygon = new Polygon3D(coordinates);
275
                }
276
            }
277
            polygon.setProjection(proj);
278
            for(int i = 0; i<polygonJTS.getNumInteriorRing(); i++){
279
                LineString ringJTS = polygonJTS.getInteriorRingN(i);
280
                coordinates = ringJTS.getCoordinates();
281
                coordinate = ringJTS.getCoordinate();
282
                Ring ring;
283
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
284
                    if (Double.isNaN(coordinate.z)) {
285
                        ring = new Ring2DM(coordinates);
286
                    } else {
287
                        ring = new Ring3DM(coordinates);
288
                    }
289
                } else {
290
                    if (Double.isNaN(coordinate.z)) {
291
                        ring = new Ring2D(coordinates);
292
                    } else {
293
                        ring = new Ring3D(coordinates);
294
                    }
295
                }
296
                ring.setProjection(proj);
297
                polygon.addInteriorRing(ring);
298
            }
299
            return polygon;
300
        }
301

    
302
        if (jtsGeom instanceof com.vividsolutions.jts.geom.GeometryCollection) {
303
            GeometryCollection collection = (com.vividsolutions.jts.geom.GeometryCollection)jtsGeom;
304
            Coordinate coordinate = collection.getCoordinate();
305
            MultiPrimitive multiprimitive = null;
306
            if (jtsGeom instanceof MultiLineString) {
307
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
308
                    if (Double.isNaN(coordinate.z)) {
309
                        multiprimitive = new MultiLine2DM();
310
                    } else {
311
                        multiprimitive = new MultiLine3DM();
312
                    }
313
                } else {
314
                    if (Double.isNaN(coordinate.z)) {
315
                        multiprimitive = new MultiLine2D();
316
                    } else {
317
                        multiprimitive = new MultiLine3D();
318
                    }
319
                }
320
            } else if (jtsGeom instanceof MultiPolygon) {
321
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
322
                    if (Double.isNaN(coordinate.z)) {
323
                        multiprimitive = new MultiPolygon2DM();
324
                    } else {
325
                        multiprimitive = new MultiPolygon3DM();
326
                    }
327
                } else {
328
                    if (Double.isNaN(coordinate.z)) {
329
                        multiprimitive = new MultiPolygon2D();
330
                    } else {
331
                        multiprimitive = new MultiPolygon3D();
332
                    }
333
                }
334
            } else if (jtsGeom instanceof MultiPoint) {
335
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
336
                    if (Double.isNaN(coordinate.z)) {
337
                        multiprimitive = new MultiPoint2DM();
338
                    } else {
339
                        multiprimitive = new MultiPoint3DM();
340
                    }
341
                } else {
342
                    if (Double.isNaN(coordinate.z)) {
343
                        multiprimitive = new MultiPoint2D();
344
                    } else {
345
                        multiprimitive = new MultiPoint3D();
346
                    }
347
                }
348
            }
349

    
350
            if (multiprimitive != null) {
351
                for (int i = 0; i < collection.getNumGeometries(); i++) {
352
                    com.vividsolutions.jts.geom.Geometry geometry = collection.getGeometryN(i);
353
                    multiprimitive.addPrimitive((Primitive) createGeometry(proj, geometry));
354
                }
355
                multiprimitive.setProjection(proj);
356
                return multiprimitive;
357
            } else {
358
                int subtype;
359
                if (jtsGeom.getFactory() instanceof MyMGeometryFactory) {
360
                    if (Double.isNaN(coordinate.z)) {
361
                        subtype = Geometry.SUBTYPES.GEOM2DM;
362
                    } else {
363
                        subtype = Geometry.SUBTYPES.GEOM3DM;
364
                    }
365
                } else {
366
                    if (Double.isNaN(coordinate.z)) {
367
                        subtype = Geometry.SUBTYPES.GEOM2D;
368
                    } else {
369
                        subtype = Geometry.SUBTYPES.GEOM3D;
370
                    }
371
                }
372
                DefaultComplex complex = new DefaultComplex(subtype);
373
                for (int i = 0; i < collection.getNumGeometries(); i++) {
374
                    com.vividsolutions.jts.geom.Geometry geometry = collection.getGeometryN(i);
375
                    complex.addPrimitive((Primitive) createGeometry(proj, geometry));
376
                }
377
                complex.setProjection(proj);
378
                return complex;
379
            }
380
        }
381

    
382
        return null;
383
    }
384

    
385
    /**
386
     * This function is called when the we need force types, that is the
387
     * destination
388
     * type does not match with the input geometry type
389
     *
390
     * @param g
391
     * @param sourceType
392
     * @param destinationType
393
     * @return
394
     */
395
    public static com.vividsolutions.jts.geom.Geometry convertTypes(com.vividsolutions.jts.geom.Geometry g,
396
        int sourceType, int destinationType) {
397

    
398
        com.vividsolutions.jts.geom.GeometryFactory factory = g.getFactory();
399

    
400
        if ((sourceType == Geometry.TYPES.CURVE || sourceType == Geometry.TYPES.SPLINE
401
            || sourceType == Geometry.TYPES.ARC || sourceType == Geometry.TYPES.ELLIPTICARC
402
            || sourceType == Geometry.TYPES.CIRCUMFERENCE || sourceType == Geometry.TYPES.PERIELLIPSE)
403
            && destinationType == Geometry.TYPES.MULTISURFACE) {
404
            if (g instanceof MultiLineString) {
405
                com.vividsolutions.jts.geom.Polygon[] poly = new com.vividsolutions.jts.geom.Polygon[((MultiLineString) g).getNumGeometries()];
406
                for (int i = 0; i < ((MultiLineString) g).getNumGeometries(); i++) {
407
                    com.vividsolutions.jts.geom.Geometry lineString = ((MultiLineString) g).getGeometryN(i);
408
                    poly[i] = convertLineStringToPolygon((LineString) lineString);
409
                }
410
                return factory.createMultiPolygon(poly);
411
            } else {
412
                return convertLineStringToPolygon((LineString) g);
413
            }
414
        }
415

    
416
        if ((sourceType == Geometry.TYPES.CIRCLE || sourceType == Geometry.TYPES.ELLIPSE
417
            || sourceType == Geometry.TYPES.ELLIPTICARC || sourceType == Geometry.TYPES.FILLEDSPLINE)
418
            && destinationType == Geometry.TYPES.MULTICURVE) {
419
            if (g instanceof com.vividsolutions.jts.geom.Polygon) {
420
                com.vividsolutions.jts.geom.Polygon poly = (com.vividsolutions.jts.geom.Polygon) g;
421
                LineString lineString = factory.createLinearRing(poly.getCoordinates());
422
                return factory.createMultiLineString(new LineString[] { lineString });
423
            }
424
        }
425
        return g;
426
    }
427

    
428
    private static com.vividsolutions.jts.geom.Polygon convertLineStringToPolygon(LineString line) {
429
        Coordinate[] coordinates = line.getCoordinates();
430
        com.vividsolutions.jts.geom.GeometryFactory factory = line.getFactory();
431
        LinearRing shell = factory.createLinearRing(coordinates);
432
        com.vividsolutions.jts.geom.Polygon pol = factory.createPolygon(shell, null);
433
        return pol;
434
    }
435

    
436
    public static MCoordinate createMCoordinate(double x, double y, double m) {
437
        return MCoordinate.create2dWithMeasure(x, y, m);
438
    }
439

    
440
    public static MCoordinate createMCoordinate(double x, double y, double z, double m) {
441
        return MCoordinate.create3dWithMeasure(x, y, z, m);
442
    }
443

    
444
    /**
445
     * @param init
446
     * @param middle
447
     * @param end
448
     * @return
449
     */
450
    public static Coordinate getCircumcentre(Point init, Point middle, Point end) {
451
        Triangle triangle =
452
            new Triangle(((PointJTS) init).getJTSCoordinate(),
453
                ((PointJTS) middle).getJTSCoordinate(),
454
                ((PointJTS) end).getJTSCoordinate());
455
        return triangle.circumcentre();
456
    }
457

    
458
    public static LineString createJTSLineStringFromArcPoints(Point centre, double radius, double startAngle, double endAngle){
459
        GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
460
        shapeFactory.setCentre(((PointJTS)centre).getJTSCoordinate());
461
        shapeFactory.setSize(radius*2);
462
        return shapeFactory.createArc(startAngle, endAngle);
463
    }
464

    
465
    public static MultiLineString createJTSMultiLineString(LineString[] lineStrings) {
466
        com.vividsolutions.jts.geom.GeometryFactory factory = JTSUtils.factory;
467
        if(lineStrings.length>0){
468
            factory = lineStrings[0].getFactory();
469
        }
470
        return factory.createMultiLineString(lineStrings);
471
    }
472

    
473
    /**
474
     * @param coordinates
475
     * @param interiorRings
476
     * @return
477
     * @throws GeometryException
478
     */
479
    public static com.vividsolutions.jts.geom.Polygon createJTSPolygon(ArrayListCoordinateSequence coordinates,
480
        List<Ring> interiorRings) {
481
        com.vividsolutions.jts.geom.GeometryFactory factory = getFactory(coordinates);
482

    
483
        LinearRing shell = factory.createLinearRing(coordinates);
484
        LinearRing[] holes = new LinearRing[interiorRings.size()];
485
        for(int i=0; i<interiorRings.size(); i++){
486
            Ring ring = interiorRings.get(i);
487
            holes[i] = (LinearRing) ((GeometryJTS) ring).getJTS();
488
        }
489
        return factory.createPolygon(shell, holes);
490
    }
491

    
492

    
493
    /**
494
     * @param coordinates
495
     * @return
496
     * @throws GeometryException
497
     */
498
    public static com.vividsolutions.jts.geom.Polygon createJTSPolygon(ArrayListCoordinateSequence coordinates) {
499
        com.vividsolutions.jts.geom.GeometryFactory factory = getFactory(coordinates);
500

    
501
        LinearRing shell = factory.createLinearRing(coordinates);
502
        return factory.createPolygon(shell);
503
    }
504

    
505
    public static com.vividsolutions.jts.geom.MultiPolygon createJTSMultiPolygon(com.vividsolutions.jts.geom.Polygon[] polygons){
506
        com.vividsolutions.jts.geom.GeometryFactory factory = JTSUtils.factory;
507
        if(polygons.length>0){
508
            factory = polygons[0].getFactory();
509
        }
510
        return factory.createMultiPolygon(polygons);
511
    }
512

    
513
    /**
514
     * Returns the intersection point between an ellipse and her minor axis.
515
     *
516
     * @param init
517
     * @param middle
518
     * @param end
519
     * @return
520
     */
521
    public static Coordinate getPointAtYAxisInEllipse(Point init, Point end, Double ydist) {
522

    
523
        LineSegment segment = new LineSegment(((PointJTS) init).getJTSCoordinate(),
524
            ((PointJTS) end).getJTSCoordinate());
525
        Coordinate middle = segment.midPoint();
526

    
527
        LineSegment midSegment = new LineSegment(middle, ((PointJTS) end).getJTSCoordinate());
528
        double modulus = midSegment.getLength();
529

    
530
        //Mayor semi-axis unitary vector
531
        Coordinate uni = new Coordinate((end.getX()-middle.x)/modulus, (end.getY()-middle.y)/modulus);
532

    
533
        //Minor axis unitary vector
534
        Coordinate perpUni = new Coordinate(-uni.y,uni.x);
535

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

    
538
        return point;
539
    }
540

    
541
    /**
542
     * Returns the middle point between two points.
543
     *
544
     * @param init
545
     * @param middle
546
     * @param end
547
     * @return
548
     */
549
    public static Coordinate getMidPoint(Point init, Point end) {
550

    
551
        LineSegment segment = new LineSegment(((PointJTS) init).getJTSCoordinate(),
552
            ((PointJTS) end).getJTSCoordinate());
553
        Coordinate middle = segment.midPoint();
554
        return middle;
555
    }
556

    
557
    /**
558
     * @param coordinate
559
     * @return
560
     */
561
    public static com.vividsolutions.jts.geom.Geometry createJTSPoint(Coordinate coordinate) {
562
        return getFactory(coordinate).createPoint(coordinate);
563
    }
564

    
565
    /**
566
     * @param coord
567
     * @return
568
     */
569
    public static com.vividsolutions.jts.geom.Geometry createJTSPolygon(Coordinate[] coordinates) {
570
        return getFactory(coordinates).createPolygon(coordinates);
571
    }
572

    
573
    public static BufferParameters getBufferParameters(){
574
        BufferParameters bufParams = new BufferParameters();
575
        bufParams.setSingleSided(true);
576
        bufParams.setEndCapStyle(BufferParameters.CAP_FLAT);
577
        bufParams.setJoinStyle(BufferParameters.CAP_ROUND);
578
        return bufParams;
579
    }
580
    
581
    public static BufferParameters getBufferParameters(int joinStyle, int endCapStyle){
582
        BufferParameters bufParams = new BufferParameters();
583
        bufParams.setSingleSided(true);
584
        bufParams.setEndCapStyle(endCapStyle);
585
        bufParams.setJoinStyle(joinStyle);
586
        bufParams.setQuadrantSegments(calculateQuadrantSegments(joinStyle));
587
        return bufParams;
588
    }
589
    
590
    public static int calculateQuadrantSegments(int joinStyle) throws IllegalArgumentException {
591
        int quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
592
        switch(joinStyle){
593
            case JOIN_STYLE_ROUND:
594
                quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS;
595
                break;
596
            case JOIN_STYLE_MITRE:
597
                quadrantSegments = - (int) BufferParameters.DEFAULT_MITRE_LIMIT;
598
                break;
599
            case JOIN_STYLE_BEVEL:
600
                quadrantSegments = 0;
601
                break;
602
            default:
603
                throw new IllegalArgumentException("Invalid jointStyle "+joinStyle);
604
        }
605
        return quadrantSegments;
606
    }
607

    
608
    /**
609
     * Creates a offset from a closed line at a distance
610
     *
611
     * @param proj
612
     * @param coordinates
613
     * @param distance
614
     * @return
615
     */
616
    public static Geometry offsetClosedLine(IProjection proj, ArrayListCoordinateSequence coordinates, double distance) {
617
        com.vividsolutions.jts.geom.Geometry jtsGeom = JTSUtils.createJTSPolygon(coordinates);
618
        com.vividsolutions.jts.geom.Geometry geomJTS = jtsGeom.buffer(distance);
619
        return jtsPolygonToJtsMultiLineString(geomJTS, proj);
620
    }
621

    
622
    /**
623
     * Creates a offset from a closed line at a distance
624
     *
625
     * @param proj
626
     * @param coordinates
627
     * @param joinStyle
628
     * @param distance
629
     * @return
630
     */
631
    public static Geometry offsetClosedLine(IProjection proj, ArrayListCoordinateSequence coordinates, int joinStyle, double distance) {
632
        com.vividsolutions.jts.geom.Geometry jtsGeom = JTSUtils.createJTSPolygon(coordinates);
633
        com.vividsolutions.jts.geom.Geometry geomJTS = jtsGeom.buffer(distance, calculateQuadrantSegments(joinStyle), BufferParameters.CAP_FLAT);
634
        return jtsPolygonToJtsMultiLineString(geomJTS, proj);
635
    }
636

    
637
    protected static Geometry jtsPolygonToJtsMultiLineString(com.vividsolutions.jts.geom.Geometry geomJTS, IProjection proj) {
638
        if (geomJTS instanceof com.vividsolutions.jts.geom.Polygon) {
639
            com.vividsolutions.jts.geom.Polygon polygonJTS = (com.vividsolutions.jts.geom.Polygon) geomJTS;
640
            LineString shell = polygonJTS.getExteriorRing();
641
            int numHoles = polygonJTS.getNumInteriorRing();
642
            if (numHoles > 0) {
643
                LineString[] lineStrings = new LineString[numHoles + 1];
644
                lineStrings[0] = shell;
645
                for (int i = 0; i < numHoles; i++) {
646
                    LineString hole = polygonJTS.getInteriorRingN(i);
647
                    lineStrings[i + 1] = hole;
648
                }
649
                return JTSUtils.createGeometry(proj, JTSUtils.createJTSMultiLineString(lineStrings));
650
            }
651
            return JTSUtils.createGeometry(proj, shell);
652
        } else if (geomJTS instanceof com.vividsolutions.jts.geom.MultiPolygon) {
653
            MultiPolygon multiPolygonJTS = (com.vividsolutions.jts.geom.MultiPolygon) geomJTS;
654
            List<LineString> lineStringList = new ArrayList<>();
655
            for (int i = 0; i < multiPolygonJTS.getNumGeometries(); i++) {
656
                com.vividsolutions.jts.geom.Polygon polygonJTS =
657
                        (com.vividsolutions.jts.geom.Polygon) multiPolygonJTS.getGeometryN(i);
658
                lineStringList.add(polygonJTS.getExteriorRing());
659
                int numHoles = polygonJTS.getNumInteriorRing();
660
                if (numHoles > 0) {
661
                    for (int h = 0; h < numHoles; h++) {
662
                        LineString hole = polygonJTS.getInteriorRingN(i);
663
                        lineStringList.add(hole);
664
                    }
665
                }
666
            }
667
            return JTSUtils.createGeometry(proj, JTSUtils.createJTSMultiLineString(lineStringList.toArray(new LineString[lineStringList.size()])));
668
        }
669
        //No deber?a pasar por aqu?
670
        logger.warn("offsetClosedLine does not return or Polygon JTS or MultiPolygon JTS");
671
        return null;
672
    }
673

    
674
    /**
675
     * Creates a raw offset of a open line at a distance.
676
     *
677
     * @param coordinates
678
     * @param distance
679
     * @return
680
     */
681
    public static Geometry offsetRawOpenLine(IProjection proj, ArrayListCoordinateSequence coordinates, double distance) {
682
        com.vividsolutions.jts.geom.GeometryFactory factory = getFactory(coordinates);
683

    
684
        BufferParameters bufParams = JTSUtils.getBufferParameters();
685
        LineString jtsGeom = JTSUtils.createJTSLineString(coordinates);
686

    
687
         OffsetCurveBuilder ocb = new
688
         OffsetCurveBuilder(factory.getPrecisionModel(), bufParams);
689
         Coordinate[] coords = ocb.getOffsetCurve(jtsGeom.getCoordinates(), distance);
690
         CoordinateSequence coordSequence = factory.getCoordinateSequenceFactory().create(coords);
691
         com.vividsolutions.jts.geom.Geometry offsetGeom = JTSUtils.createJTSLineString(coordSequence);
692

    
693
         return JTSUtils.createGeometry(proj, offsetGeom);
694
    }
695

    
696
    /*
697
     *
698
     */
699
    public static double straightLineThroughTwoPointsEquation(double x1, double x2, double y1, double y2, double x) {
700
        if (x2 - x1 == 0.0) {
701
            return Double.POSITIVE_INFINITY;
702
        }
703
        return ((y2 - y1) * (x - x1) / (x2 - x1)) + y1;
704
    }
705

    
706
}