Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.geometry / org.gvsig.fmap.geometry.api / src / main / java / org / gvsig / fmap / geom / GeometryUtils.java @ 45308

History | View | Annotate | Download (32.6 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;
25

    
26
import java.awt.geom.Point2D;
27
import java.util.List;
28
import java.util.Objects;
29
import org.apache.commons.lang3.StringUtils;
30
import org.cresques.cts.IProjection;
31
import org.gvsig.euclidean.EuclideanLine2D;
32
import org.gvsig.euclidean.EuclideanManager;
33
import org.gvsig.fmap.geom.aggregate.MultiLine;
34
import org.gvsig.fmap.geom.aggregate.MultiPoint;
35
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
36
import org.gvsig.fmap.geom.exception.CreateEnvelopeException;
37
import org.gvsig.fmap.geom.exception.CreateGeometryException;
38
import org.gvsig.fmap.geom.operation.GeometryOperationException;
39
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
40
import org.gvsig.fmap.geom.primitive.Arc;
41
import org.gvsig.fmap.geom.primitive.Circle;
42
import org.gvsig.fmap.geom.primitive.Ellipse;
43
import org.gvsig.fmap.geom.primitive.Envelope;
44
import org.gvsig.fmap.geom.primitive.Line;
45
import org.gvsig.fmap.geom.primitive.Point;
46
import org.gvsig.fmap.geom.primitive.Polygon;
47
import org.gvsig.fmap.geom.primitive.Spline;
48
import org.gvsig.fmap.geom.type.GeometryType;
49
import org.gvsig.tools.exception.BaseException;
50
import org.gvsig.tools.util.ToolsUtilLocator;
51

    
52
/**
53
 *
54
 * @author jjdelcerro
55
 */
56
@SuppressWarnings("UseSpecificCatch")
57
public class GeometryUtils {
58

    
59
    private GeometryUtils() {
60
        
61
    }
62
    
63
    public static GeometryType getGeometryType(int geometryType, int geometrySubType) {
64
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
65
        try {
66
            return geomManager.getGeometryType(geometryType, geometrySubType);
67
        } catch (Exception ex) {
68
            return null;
69
        }
70
    }
71
    
72
    public static boolean isSubtype(int geomTypeParent, int geomTypeChild) {
73
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
74
        return geomManager.isSubtype(geomTypeParent, geomTypeChild);
75
    }
76

    
77
    public static boolean canAggregate(int geomTypeParent, int geomTypeChild) {
78
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
79
        return geomManager.canAggregate(geomTypeParent, geomTypeChild);
80
    }
81
    
82
    public static Envelope createEnvelope(int subType) {
83
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
84
        try {
85
            return geomManager.createEnvelope(subType);
86
        } catch (CreateEnvelopeException ex) {
87
            return null;
88
        }
89
    }
90
    
91
    public static Envelope createEnvelope(double minX, double minY, double maxX,
92
        double maxY, int subType) {
93
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
94
        try {
95
            return geomManager.createEnvelope(minX, minY, maxX, maxY, subType);
96
        } catch (CreateEnvelopeException ex) {
97
            return null;
98
        }
99
    }
100
    
101
    public static Line createLine(int subType) {
102
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
103
        try {
104
            return geomManager.createLine(subType);
105
        } catch (CreateGeometryException ex) {
106
            return null;
107
        }
108
    }
109
    
110
    public static MultiLine createMultiLine(int subType) {
111
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
112
        try {
113
            return geomManager.createMultiLine(subType);
114
        } catch (CreateGeometryException ex) {
115
            return null;
116
        }
117
    }
118
    
119
    public static Polygon createPolygon(int subType) {
120
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
121
        try {
122
            return geomManager.createPolygon(subType);
123
        } catch (CreateGeometryException ex) {
124
            return null;
125
        }
126
    }
127
        
128
    public static MultiPolygon createMultiPolygon(int subType) {
129
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
130
        try {
131
            return geomManager.createMultiPolygon(subType);
132
        } catch (CreateGeometryException ex) {
133
            return null;
134
        }
135
    }
136
        
137
    public static Point createPoint(double x, double y) {
138
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
139
        try {
140
            return geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
141
        } catch (CreateGeometryException ex) {
142
            return null;
143
        }
144
    }
145
    
146
    public static Point createPoint(double x, double y, double z) {
147
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
148
        try {
149
            Point p = geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM3D);
150
            p.setCoordinateAt(Geometry.DIMENSIONS.Z, z);
151
            return p;
152
        } catch (CreateGeometryException ex) {
153
            return null;
154
        }
155
    }
156
    
157
    public static Point createPoint(double x, double y, double z, double m) {
158
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
159
        try {
160
            Point p = geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM3DM);
161
            p.setCoordinateAt(Geometry.DIMENSIONS.Z, z);
162
            p.setCoordinateAt(p.getDimension()-1, m);
163
            return p;
164
        } catch (CreateGeometryException ex) {
165
            return null;
166
        }
167
    }
168

    
169
    public static Point createPoint(Point center, double radius, double angle) {
170
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
171
        return GeometryUtils.createPoint(
172
                center.getX() + radius * Math.cos(angle),
173
                center.getY() + radius * Math.sin(angle)
174
        );
175
    }
176
    
177
    
178
    public static Geometry createFrom(Object data) {
179
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
180
        try {
181
            return geomManager.createFrom(data);
182
        } catch (GeometryException ex) {
183
            return null;
184
        }
185
    }
186
    
187
    public static Geometry createFrom(String wkt, String srs) {
188
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
189
        try {
190
            return geomManager.createFrom(wkt, srs);
191
        } catch (GeometryException ex) {
192
            return null;
193
        }
194
    }
195

    
196
    public static Geometry createFrom(String wkt, IProjection srs) {
197
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
198
        try {
199
            return geomManager.createFrom(wkt, srs);
200
        } catch (GeometryException ex) {
201
            return null;
202
        }
203
    }
204
    
205
    public static Geometry createFrom(String wkt) {
206
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
207
        try {
208
            return geomManager.createFrom(wkt);
209
        } catch (GeometryException ex) {
210
            return null;
211
        }
212
    }
213
    
214
    public static Object convertTo(Geometry geom, String format) {
215
        try {
216
            return geom.convertTo(format);
217
        } catch (Exception ex) {
218
            return null;
219
        }
220
    }
221
        
222
    public static String toWKT(Geometry geom) {
223
        try {
224
            return geom.convertToWKT();
225
        } catch (Exception ex) {
226
            return null;
227
        }
228
    }
229

    
230
    public static byte[] toWKB(Geometry geom) {
231
        try {
232
            return geom.convertToWKB();
233
        } catch (Exception ex) {
234
            return null;
235
        }
236
    }
237
    
238
    public static byte[] toEWKB(Geometry geom) {
239
        try {
240
            return geom.convertToEWKB();
241
        } catch (Exception ex) {
242
            return null;
243
        }
244
    }
245
    
246
    public static boolean intersects(Geometry geom1, Geometry geom2) {
247
        try {
248
            return geom1.intersects(geom2);
249
        } catch (Exception ex) {
250
            return false;
251
        }
252
    }
253

    
254
    public static String getGeometryTypeName(int type) {
255
        switch (type) {
256
            case Geometry.TYPES.GEOMETRY:
257
                return "Geometry";
258
            case Geometry.TYPES.POINT:
259
                return "Point";
260
            case Geometry.TYPES.CURVE:
261
                return "Curve";
262
            case Geometry.TYPES.SURFACE:
263
                return "Surface";
264
            case Geometry.TYPES.SOLID:
265
                return "Solid";
266
            case Geometry.TYPES.AGGREGATE:
267
                return "Aggregate";
268
            case Geometry.TYPES.MULTIPOINT:
269
                return "Multipoint";
270
            case Geometry.TYPES.MULTICURVE:
271
                return "Multicurve";
272
            case Geometry.TYPES.MULTISURFACE:
273
                return "Multisurface";
274
            case Geometry.TYPES.MULTISOLID:
275
                return "Multisolid";
276
            case Geometry.TYPES.CIRCLE:
277
                return "Circle";
278
            case Geometry.TYPES.ARC:
279
                return "Arc";
280
            case Geometry.TYPES.ELLIPSE:
281
                return "Ellipse";
282
            case Geometry.TYPES.SPLINE:
283
                return "Spline";
284
            case Geometry.TYPES.ELLIPTICARC:
285
                return "Ellipticarc";
286
            case Geometry.TYPES.COMPLEX:
287
                return "Complex";
288
            case Geometry.TYPES.LINE:
289
                return "Line";
290
            case Geometry.TYPES.POLYGON:
291
                return "Polygon";
292
            case Geometry.TYPES.RING:
293
                return "Ring";
294
            case Geometry.TYPES.MULTILINE:
295
                return "Multiline";
296
            case Geometry.TYPES.MULTIPOLYGON:
297
                return "Multipolygon";
298
            case Geometry.TYPES.CIRCUMFERENCE:
299
                return "Circumference";
300
            case Geometry.TYPES.PERIELLIPSE:
301
                return "Periellipse";
302
            case Geometry.TYPES.FILLEDSPLINE:
303
                return "Filledspline";
304
            default:
305
                return "Geometry";
306
        }
307
    }
308

    
309
    public static String getGeometrySubtypeName(int subtype) {
310
        switch (subtype) {
311
            case Geometry.SUBTYPES.GEOM2D:
312
                return "2D";
313
            case Geometry.SUBTYPES.GEOM3D:
314
                return "3D";
315
            case Geometry.SUBTYPES.GEOM2DM:
316
                return "2DM";
317
            case Geometry.SUBTYPES.GEOM3DM:
318
                return "3DM";
319
            default:
320
                return "Unknown";
321
        }
322
    }    
323
    
324
    public static int getGeometryType(String typeName) {
325
        if( StringUtils.isBlank(typeName) ) {
326
            return Geometry.TYPES.UNKNOWN;
327
        }
328
        switch(typeName.toLowerCase()) {
329
            case "geometry":
330
                return Geometry.TYPES.GEOMETRY;
331
            case "point":
332
                    return Geometry.TYPES.POINT;
333
            case "curve":
334
                    return Geometry.TYPES.CURVE;
335
            case "surface":
336
                    return Geometry.TYPES.SURFACE;
337
            case "solid":
338
                    return Geometry.TYPES.SOLID;
339
            case "aggregate":
340
                    return Geometry.TYPES.AGGREGATE;
341
            case "multipoint":
342
                    return Geometry.TYPES.MULTIPOINT;
343
            case "multicurve":
344
                    return Geometry.TYPES.MULTICURVE;
345
            case "multisurface":
346
                    return Geometry.TYPES.MULTISURFACE;
347
            case "multisolid":
348
                    return Geometry.TYPES.MULTISOLID;
349
            case "circle":
350
                    return Geometry.TYPES.CIRCLE;
351
            case "arc":
352
                    return Geometry.TYPES.ARC;
353
            case "ellipse":
354
                    return Geometry.TYPES.ELLIPSE;
355
            case "spline":
356
                    return Geometry.TYPES.SPLINE;
357
            case "ellipticarc":
358
                    return Geometry.TYPES.ELLIPTICARC;
359
            case "complex":
360
                    return Geometry.TYPES.COMPLEX;
361
            case "line":
362
                    return Geometry.TYPES.LINE;
363
            case "polygon":
364
                    return Geometry.TYPES.POLYGON;
365
            case "ring":
366
                    return Geometry.TYPES.RING;
367
            case "multiline":
368
                    return Geometry.TYPES.MULTILINE;
369
            case "multipolygon":
370
                    return Geometry.TYPES.MULTIPOLYGON;
371
            case "circumference":
372
                    return Geometry.TYPES.CIRCUMFERENCE;
373
            case "periellipse":
374
                    return Geometry.TYPES.PERIELLIPSE;
375
            case "filledspline":
376
                    return Geometry.TYPES.FILLEDSPLINE;
377
            default:
378
                return Geometry.TYPES.UNKNOWN;
379
        }
380
    }
381

    
382
    public static int getGeometrySubtype(String subtype) {
383
        if( StringUtils.isBlank(subtype) ) {
384
            return Geometry.SUBTYPES.UNKNOWN;
385
        }
386
        switch(subtype.toUpperCase()) {
387
            case "GEOM2D":
388
            case "2D":
389
                    return Geometry.SUBTYPES.GEOM2D;
390
            case "GEOM3D":
391
            case "3D":
392
                    return Geometry.SUBTYPES.GEOM3D;
393
            case "GEOM2DM":
394
            case "2DM":
395
                    return Geometry.SUBTYPES.GEOM2DM;
396
            case "GEOM3DM":
397
            case "3DM":
398
                    return Geometry.SUBTYPES.GEOM3DM;
399
            default:
400
                return Geometry.SUBTYPES.UNKNOWN;
401
        }
402
    }    
403
    
404
    /**
405
     * Creates a circle as of center and radius.
406
     *
407
     * @param center
408
     *            of new circle
409
     * @param radius
410
     *            of new circle
411
     * @param subtype
412
     *            subtype of circle. See {@link Geometry.SUBTYPES}
413
     * @return The circle created with center and radius
414
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
415
     */
416
    public static Circle createCircle(Point center, double radius, int subtype)
417
            throws CreateGeometryException {
418
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
419
        Circle circle = (Circle) geomManager.create(Geometry.TYPES.CIRCLE, subtype);
420
        circle.setPoints(center, radius);
421

    
422
        return circle;
423
    }
424

    
425
    /**
426
     * Creates a circle from three points.
427
     *
428
     * @param firstPoint
429
     *            of circle
430
     * @param secondPoint
431
     *            of circle
432
     * @param thirdPoint
433
     *            of circle
434
     * @param subtype
435
     *            subtype of circle. See {@link Geometry.SUBTYPES}
436
     * @return The circle created from three points received as parameters.
437
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
438
     */
439
    public static Circle createCircle(Point firstPoint, Point secondPoint,
440
            Point thirdPoint, int subtype) throws CreateGeometryException {
441
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
442
        Circle circle = (Circle) geomManager.create(Geometry.TYPES.CIRCLE, subtype);
443
        circle.setPoints(firstPoint, secondPoint, thirdPoint);
444

    
445
        return circle;
446
    }
447
    
448
    /**
449
     * Creates a circle from five points.The first two points are two points on a tangent to the circle.The next two are two points on another tangent to the circle.The last one is a point near the center of the circle.
450
     *
451
     * @param firstPoint
452
     * @param secondPoint
453
     * @param thirdPoint
454
     * @param fourthPoint
455
     * @param fifthPoint
456
     * @param subtype
457
     *            subtype of circle. See {@link Geometry.SUBTYPES}
458
     * @return The circle created from three points received as parameters.
459
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
460
     */
461
    public static Circle createCircle(Point firstPoint, Point secondPoint, Point thirdPoint, Point fourthPoint, Point fifthPoint, int subtype) throws CreateGeometryException {
462
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
463
        EuclideanLine2D line1 = euclideanManager.createLine2D(firstPoint.getX(), firstPoint.getY(), secondPoint.getX(), secondPoint.getY());
464
        EuclideanLine2D line2 = euclideanManager.createLine2D(thirdPoint.getX(), thirdPoint.getY(), fourthPoint.getX(), fourthPoint.getY());
465
        return createCircle(line1, line2, fifthPoint, subtype);
466
    }
467

    
468
    /**
469
     * Creates a circle from two tangents and one point.
470
     *
471
     * @param line1
472
     *            A tangent line
473
     * @param line2
474
     *            Another tangent line
475
     * @param point
476
     *            A point near the center of the circle.
477
     * @param subtype
478
     *            subtype of circle. See {@link Geometry.SUBTYPES}
479
     * @return The circle created from two tangents and one point received as parameters.
480
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
481
     */
482
    public static Circle createCircle(EuclideanLine2D line1, EuclideanLine2D line2, Point point, int subtype) throws CreateGeometryException {
483

    
484
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
485
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
486
        
487
        try {
488
            EuclideanLine2D perpendicular;
489
            EuclideanLine2D bisector;
490
            if (line1.isParallel(line2)) {
491

    
492
                if (Objects.equals(line1.getYIntercept(), line2.getYIntercept())
493
                        || (Objects.equals(Math.abs(line1.getYIntercept()), 0.0)
494
                        && Objects.equals(Math.abs(line2.getYIntercept()), 0.0))) { //Same lines
495
                    perpendicular = line1.getPerpendicular(point.getX(), point.getY());
496
                    Point2D intersection = line1.getIntersection(perpendicular);
497
                    return createCircle(point, point.distance(geomManager.createPoint(intersection.getX(), intersection.getY(), subtype)), subtype);
498
                } else if (Double.isInfinite(line1.getSlope())) { //Parallel and vertical lines
499
                    Point center = createPoint(-(line2.getC() + line1.getC()) / 2.0, point.getY(), subtype);
500
                    double radius = line1.getDistance(center.getX(), center.getY());
501
                    return createCircle(center, radius, subtype);
502
                } else { //Parallel lines
503
                    bisector = euclideanManager.createLine2D(line1.getA(), line1.getB(), (line2.getC()+line1.getC())/2);
504
                }
505

    
506
            } else {
507

    
508
                EuclideanLine2D[] bisectors = line1.getBisectors(line2);
509

    
510
                double distance1 = bisectors[0].getDistance(point.getX(), point.getY());
511
                double distance2 = bisectors[1].getDistance(point.getX(), point.getY());
512

    
513
                bisector = bisectors[0];
514
                if (distance1 > distance2) {
515
                    bisector = bisectors[1];
516
                }
517
            }
518

    
519
            if (Double.isInfinite(bisector.getSlope())) {
520
                Point2D intersection = line1.getIntersection(line2);
521
                Point center = createPoint(intersection.getX(), point.getY(), subtype);
522
                Double radius = line1.getDistance(center.getX(), center.getY());
523
                return createCircle(center, radius, subtype);
524
            } else if (bisector.getSlope() == 0.0) {
525
                if (line1.isParallel(line2)) { //Objects.equals(m0, m1)) { //Same slope
526
                    Point center = createPoint(point.getX(), bisector.getYIntercept(), subtype);
527
                    Double radius = line1.getDistance(center.getX(), center.getY());
528
                    return createCircle(center, radius, subtype);
529
                } else {
530
                    Point2D intersection = line1.getIntersection(line2);
531
                    Point center = createPoint(point.getX(), intersection.getY(), subtype);
532
                    Double radius = line1.getDistance(center.getX(), center.getY());
533
                    return createCircle(center, radius, subtype);
534
                }
535
            }
536

    
537
            perpendicular = bisector.getPerpendicular(point.getX(), point.getY());
538
            Point2D intersection = bisector.getIntersection(perpendicular);
539
            Double radius = line1.getDistance(intersection.getX(), intersection.getY());
540
            return createCircle(
541
                    geomManager.createPoint(intersection.getX(), intersection.getY(), subtype), 
542
                    radius, 
543
                    subtype);
544

    
545
        } catch (GeometryOperationNotSupportedException | GeometryOperationException ex) {
546
            throw new CreateGeometryException(Geometry.TYPES.CIRCLE, subtype, ex);
547
        }
548
    }
549

    
550
    /**
551
     * Creates a circle from two tangent geometries and the radius.
552
     *
553
     * @param geometry1
554
     *            A tangent geometry
555
     * @param geometry2
556
     *            Another tangent geometry
557
     * @param radius
558
     *            the radius of the cicle.
559
     * @param firstPoint
560
     *            a point near tangent point of geometry1
561
     * @param secondPoint
562
     *            a point near tangent point of geometry2
563
     * @param subtype
564
     *            subtype of circle. See {@link Geometry.SUBTYPES}
565
     * @return The circle created from two tangent geometries and the radius received as parameters.
566
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
567
     */
568
    public static Circle createCircle(Geometry geometry1, Geometry geometry2, double radius, Point firstPoint, Point secondPoint, int subtype) throws CreateGeometryException {
569
        
570
        try {
571
            Geometry buffer1 = geometry1.buffer(radius);
572
            MultiLine lines1 = buffer1.toLines();
573
            
574
            Geometry buffer2 = geometry2.buffer(radius);
575
            MultiLine lines2 = buffer2.toLines();
576
            
577
            Geometry intersection = lines1.intersection(lines2);
578
            
579
            Point center = null;
580
            if(intersection!=null){
581
                MultiPoint points = intersection.toPoints();
582

    
583
                double distance = Double.POSITIVE_INFINITY;
584
                for (int i = 0; i < points.getPrimitivesNumber(); i++) {
585
                    Point point = points.getPointAt(i);
586
                    double pointDistance = point.distance(firstPoint)+point.distance(secondPoint);
587
                    if(pointDistance<distance){
588
                        center = point;
589
                        distance = pointDistance;
590
                    }
591
                }
592
            }
593
            if(center == null){
594
                return null;
595
            }
596
            return createCircle(center, radius, subtype);
597
           
598
        } catch (GeometryOperationNotSupportedException | GeometryOperationException | GeometryException ex) {
599
            throw new CreateGeometryException(Geometry.TYPES.CIRCLE, subtype, ex);
600
        }
601
        
602
    }
603

    
604
    /**
605
     * Creates an arc as of center, radius, start angle and extension angle.
606
     *
607
     * @param center
608
     *            center of arc.
609
     * @param radius
610
     *            of arc.
611
     * @param startAngle
612
     *            of arc in radians
613
     * @param angleExt
614
     *            of arc in radians
615
     * @param subtype
616
     *            subtype of arc. See {@link Geometry.SUBTYPES}
617
     * @return The arc created with center, radius, start angle and extension
618
     *         angle.
619
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
620
     */
621
    public static Arc createArc(Point center, double radius, double startAngle,
622
            double angleExt, int subtype) throws CreateGeometryException {
623
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
624
        Arc arc = (Arc) geomManager.create(Geometry.TYPES.ARC, subtype);
625
        arc.setPoints(center, radius, startAngle, angleExt);
626
        return arc;
627
    }
628

    
629
    /**
630
     * Creates an arc as of three points.
631
     *
632
     * @param start
633
     *            point of arc
634
     * @param middle
635
     *            point of arc. It can be any point of arc.
636
     * @param end
637
     *            point of arc
638
     * @param subtype
639
     *            of arc. See {@link Geometry.SUBTYPES}
640
     * @return The arc created that it start at start point, cross middle
641
     *         point and end at end point.
642
     * @throws org.gvsig.tools.exception.BaseException
643
     */
644
    public static Arc createArc(Point start, Point middle, Point end, int subtype)
645
            throws BaseException {
646

    
647
        Arc arc = (Arc) GeometryLocator.getGeometryManager().create(Geometry.TYPES.ARC, subtype);
648
        arc.setPoints(start, middle, end);
649
        return arc;
650

    
651
    }
652
    
653
    /**
654
     * Creates an ellipse from start and end point of A axis and half length
655
     * of B axis.
656
     *
657
     * @param firstPointAxisA
658
     *            first point of A axis
659
     * @param secondPointAxisA
660
     *            second point of B axis
661
     * @param halfLengthAxisB
662
     *            half length of B axis
663
     * @param subtype
664
     *            of ellipse See {@link Geometry.SUBTYPES}
665
     * @return The ellipse created
666
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
667
     */
668
    public static Arc createEllipse(Point firstPointAxisA, Point secondPointAxisA,
669
            double halfLengthAxisB, int subtype) throws CreateGeometryException {
670
        try {
671
            double lengthAxisA = secondPointAxisA.distance(firstPointAxisA);
672

    
673
            Point origen = createPoint(0, 0, subtype);
674
            Arc ellipse = createArc(
675
                    origen,
676
                    lengthAxisA / 2,
677
                    0,
678
                    2 * Math.PI,
679
                    subtype);
680

    
681
            ellipse.scale(origen, 1, halfLengthAxisB * 2 / lengthAxisA);
682
            final EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
683
            EuclideanLine2D axisA = euclideanManager.createLine2D(
684
                    firstPointAxisA.getX(),
685
                    firstPointAxisA.getY(), 
686
                    secondPointAxisA.getX(),
687
                    secondPointAxisA.getY());
688
            double angle = axisA.getAngle();
689
            ellipse.rotate(angle, 0, 0);
690
            Point centerOfEllipse = getMidPoint(firstPointAxisA, secondPointAxisA, subtype);
691
            ellipse.move(centerOfEllipse.getX(), centerOfEllipse.getY());
692
            return ellipse;
693
        } catch (GeometryOperationNotSupportedException | GeometryOperationException e) {
694
            throw new CreateGeometryException(Geometry.TYPES.ARC, subtype, e);
695
        }
696
    }
697
    
698
    /**
699
     * Creates a filled ellipse from start and end point of A axis and half length
700
     * of B axis.
701
     *
702
     * @param firstPointAxisA
703
     *            first point of A axis
704
     * @param secondPointAxisA
705
     *            second point of B axis
706
     * @param halfLengthAxisB
707
     *            half length of B axis
708
     * @param subtype
709
     *            of ellipse See {@link Geometry.SUBTYPES}
710
     * @return The ellipse created
711
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
712
     */
713
    public static Ellipse createFilledEllipse(Point firstPointAxisA,
714
            Point secondPointAxisA, double halfLengthAxisB, int subtype)
715
            throws CreateGeometryException {
716
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
717
        Ellipse ellipse = (Ellipse) geomManager.create(Geometry.TYPES.ELLIPSE, subtype);
718
        ellipse.setPoints(firstPointAxisA, secondPointAxisA, halfLengthAxisB);
719
        return ellipse;
720
    }
721

    
722
    /**
723
     * Gets center point of three points.
724
     *
725
     * @param a
726
     *            Point one
727
     * @param b
728
     *            Point two
729
     * @param c
730
     *            Point three
731
     * @param subtype
732
     *            of point created. See {@link Geometry.SUBTYPES}
733
     * @return Point center.
734
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
735
     */
736
    public static Point getCenter(Point a, Point b, Point c, int subtype)
737
            throws CreateGeometryException {
738

    
739
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
740
        
741
        Point midPointAC = getMidPoint(a, c, subtype);
742
        EuclideanLine2D lineAC = euclideanManager.createLine2D(a.getX(), a.getY(), c.getX(), c.getY());
743
        EuclideanLine2D bisectorAC = lineAC.getPerpendicular(midPointAC.getX(), midPointAC.getY());
744
        
745
        Point midPointBC = getMidPoint(b, c, subtype);
746
        EuclideanLine2D lineBC = euclideanManager.createLine2D(b.getX(), b.getY(), c.getX(), c.getY());
747
        EuclideanLine2D bisectorBC = lineBC.getPerpendicular(midPointBC.getX(), midPointBC.getY());
748
        
749
        Point2D intersection = bisectorAC.getIntersection(bisectorBC);
750
        
751
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
752
        return geomManager.createPoint(intersection.getX(), intersection.getY(), subtype);
753
    }
754

    
755
    /**
756
     * Gets midpoint of two points
757
     *
758
     * @param a
759
     *            Point one
760
     * @param b
761
     *            Point two
762
     * @param subtype
763
     *            of point created. See {@link Geometry.SUBTYPES}
764
     * @return Mid point of points.
765
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
766
     */
767
    public static Point getMidPoint(Point a, Point b, int subtype)
768
            throws CreateGeometryException {
769
        double x = (a.getX() + b.getX()) / 2;
770
        double y = (a.getY() + b.getY()) / 2;
771
        return createPoint(x, y, subtype);
772
    }
773

    
774
    /**
775
     * Creates line as of two point coordinates.
776
     *
777
     * @param x1
778
     *            The X1 coordinate
779
     * @param y1
780
     *            The y1 coordinate
781
     * @param x2
782
     *            The X2 coordinate
783
     * @param y2
784
     *            The y2 coordinate
785
     * @param subtype
786
     *            of line. See {@link Geometry.SUBTYPES}
787
     * @return The Line created.
788
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
789
     */
790
    public static Line createLine(double x1, double y1, double x2, double y2,
791
            int subtype) throws CreateGeometryException {
792
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
793
        Line line = (Line) geomManager.create(Geometry.TYPES.CURVE, subtype);
794
        line.addVertex(x1, y1);
795
        line.addVertex(x2, y2);
796
        return line;
797
    }
798
    
799
    /**
800
     * Creates line as of two point objects.
801
     *
802
     * @param p1
803
     *            First point
804
     * @param p2
805
     *            Second point
806
     * @param subtype
807
     *            of line. See {@link Geometry.SUBTYPES}
808
     * @return The Line created.
809
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
810
     */
811
    public static Line createLine(Point p1, Point p2, int subtype)
812
            throws CreateGeometryException {
813
        return createLine(p1.getX(), p1.getY(), p2.getX(), p2.getY(),
814
                subtype);
815
    }
816

    
817
    /**
818
     * Create Spline from point list
819
     *
820
     * @param points
821
     * @param subtype
822
     * @return
823
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
824
     */
825
    public static Spline createSpline(List<Point> points, int subtype)
826
            throws CreateGeometryException {
827
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
828
        Spline spline = (Spline) geomManager.create(Geometry.TYPES.SPLINE, subtype);
829

    
830
        points.forEach((point) -> {
831
            spline.addVertex(point);
832
        });
833

    
834
        return spline;
835
    }
836

    
837

    
838
    /**
839
     * Calculate the angle between points p1 and p2 with vertex at vertex point
840
     * 
841
     * @param vertex
842
     * @param p1
843
     * @param p2
844
     * @return 
845
     */
846
    public static double calculateAngle(Point vertex, Point p1, Point p2){
847
        double angle = Math.atan2(
848
                p2.getY() - vertex.getY(), 
849
                p2.getX() - vertex.getX()
850
        ) - Math.atan2(
851
                p1.getY() - vertex.getY(), 
852
                p1.getX() - vertex.getX()
853
        ); 
854
        if (angle<0){
855
            return 2*Math.PI+angle;
856
        }
857
        return angle;
858
    }
859
    
860
    /**
861
     * Find the angle in the counterclockwise direction between 
862
     * the horizontal line and point p relative to the vertex
863
     * 
864
     * @param vertex
865
     * @param p
866
     * @return 
867
     */
868
    public static double calculateAngle(Point vertex, Point p){
869

    
870
        double angle = Math.atan2(
871
                p.getY() - vertex.getY(), 
872
                p.getX() - vertex.getX()
873
        ) - Math.atan2(
874
                0, 
875
                1
876
        ); 
877
        if (angle<0){
878
            return 2*Math.PI+angle;
879
        }
880
        return angle;
881
    }
882
    
883
    public static boolean areThreePointsInLine(Point a, Point b, Point c){
884
        if(a.equals(b) || a.equals(c) || b.equals(c)){
885
            return true;
886
        }
887
        return ((b.getX()-a.getX())/(c.getX()-b.getX()) == (b.getY()-a.getY())/(c.getY()-b.getY()));
888
    }
889

    
890
}