Revision 45205 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

View differences:

GeometryUtils.java
23 23
 */
24 24
package org.gvsig.fmap.geom;
25 25

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

  
42 56
/**
43 57
 *
......
381 395
                return Geometry.SUBTYPES.UNKNOWN;
382 396
        }
383 397
    }    
398
    
399
    /**
400
     * Creates a circle as of center and radius.
401
     *
402
     * @param center
403
     *            of new circle
404
     * @param radius
405
     *            of new circle
406
     * @param subtype
407
     *            subtype of circle. See {@link Geometry.SUBTYPES}
408
     * @return The circle created with center and radius
409
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
410
     */
411
    public static Circle createCircle(Point center, double radius, int subtype)
412
            throws CreateGeometryException {
413
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
414
        Circle circle = (Circle) geomManager.create(Geometry.TYPES.CIRCLE, subtype);
415
        circle.setPoints(center, radius);
416

  
417
        return circle;
418
    }
419

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

  
440
        return circle;
441
    }
442
    
443
    /**
444
     * 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.
445
     *
446
     * @param firstPoint
447
     * @param secondPoint
448
     * @param thirdPoint
449
     * @param fourthPoint
450
     * @param fifthPoint
451
     * @param subtype
452
     *            subtype of circle. See {@link Geometry.SUBTYPES}
453
     * @return The circle created from three points received as parameters.
454
     * @throws org.gvsig.fmap.geom.exception.CreateGeometryException
455
     */
456
    public static Circle createCircle(Point firstPoint, Point secondPoint, Point thirdPoint, Point fourthPoint, Point fifthPoint, int subtype) throws CreateGeometryException {
457
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
458
        EuclideanLine2D line1 = euclideanManager.createLine2D(firstPoint.getX(), firstPoint.getY(), secondPoint.getX(), secondPoint.getY());
459
        EuclideanLine2D line2 = euclideanManager.createLine2D(thirdPoint.getX(), thirdPoint.getY(), fourthPoint.getX(), fourthPoint.getY());
460
        return createCircle(line1, line2, fifthPoint, subtype);
461
    }
462

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

  
479
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
480
        EuclideanManager euclideanManager = ToolsUtilLocator.getEuclideanManager();
481
        
482
        try {
483
            EuclideanLine2D perpendicular;
484
            EuclideanLine2D bisector;
485
            if (line1.isParallel(line2)) {
486

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

  
501
            } else {
502

  
503
                EuclideanLine2D[] bisectors = line1.getBisectors(line2);
504

  
505
                double distance1 = bisectors[0].getDistance(point.getX(), point.getY());
506
                double distance2 = bisectors[1].getDistance(point.getX(), point.getY());
507

  
508
                bisector = bisectors[0];
509
                if (distance1 > distance2) {
510
                    bisector = bisectors[1];
511
                }
512
            }
513

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

  
532
            perpendicular = bisector.getPerpendicular(point.getX(), point.getY());
533
            Point2D intersection = bisector.getIntersection(perpendicular);
534
            Double radius = line1.getDistance(intersection.getX(), intersection.getY());
535
            return createCircle(
536
                    geomManager.createPoint(intersection.getX(), intersection.getY(), subtype), 
537
                    radius, 
538
                    subtype);
539

  
540
        } catch (GeometryOperationNotSupportedException | GeometryOperationException ex) {
541
            throw new CreateGeometryException(Geometry.TYPES.CIRCLE, subtype, ex);
542
        }
543
    }
544

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

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

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

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

  
642
        Arc arc = (Arc) GeometryLocator.getGeometryManager().create(Geometry.TYPES.ARC, subtype);
643
        arc.setPoints(start, middle, end);
644
        return arc;
645

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

  
668
            Point origen = createPoint(0, 0, subtype);
669
            Arc ellipse = createArc(
670
                    origen,
671
                    lengthAxisA / 2,
672
                    0,
673
                    2 * Math.PI,
674
                    subtype);
675

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

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

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

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

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

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

  
825
        points.forEach((point) -> {
826
            spline.addVertex(point);
827
        });
828

  
829
        return spline;
830
    }
831

  
832

  
833

  
834

  
384 835
}

Also available in: Unified diff