
// GeomOps.java
// Murat Öksüzer, April 2021
// https://www.smartycoder.com/2021/04/geometry-model-jts-tutorial-1.html
// Modified by Andrew Davison, ad@coe.psu.ac.th, March 2023

/* Uses a variety of geometry methods:
      * getArea()
      * getLength()
      * distance(), DistanceOp and nearestPoints(), isWithinDistance()
      * contains(), within(), coveredBy()
      * intersects(), intersection(), disjoint()
      * crosses(), touches(), overlaps()
      * equals() [object and Geometry], equalsExact()

   Usage:
    > compile GeomOps.java
    > run GeomOps

  When prompted, press <enter> on the command line to move 
  to the next example.
*/


import org.locationtech.jts.geom.*;
import org.locationtech.jts.operation.distance.DistanceOp;

public class GeomOps
{
  private static GeomsViewer gv = Utils.view("Geom Ops");


  public static void main(String[] args)
  {
    area();
    lengths();
    dists();
    contains();
    covers();
    intersects();
    crosses();
    touches();
    equals();

    gv.close();
  }  // end of main()


  private static void area()
  {
    System.out.println("-- area() --");
    gv.setTitle("-- area() --");
    double[] coords = { 150,60, 200,150, 90,150, 150,60 };
    Geometry poly = Utils.makeGeometry(coords, Utils.POLY);
    gv.add(poly);
    System.out.println("Area: " + poly.getArea());

    Utils.waitEnter();
    gv.clear();
  } /* area() */



  private static void lengths()
  {
    System.out.println("\n-- lengths() --");
    gv.setTitle("-- lengths() --");
    double[] coords = {
        150,60, 200,150, 80, 80, 40,160, 50, 60  };
    Geometry ls = Utils.makeGeometry(coords, Utils.LINE);
    System.out.printf("Line Length: %.2f\n", ls.getLength());
    gv.add(ls);

    double[] coords1 = {
        60, 250, 160, 270, 170, 330, 100,350, 50, 280, 60, 250 };
    Geometry poly = Utils.makeGeometry(coords1, Utils.POLY);
    System.out.printf("Poly Perimeter: %.2f\n", poly.getLength());
    gv.add(poly);

    Utils.waitEnter();
    gv.clear();
  } /* lengths() */



  private static void dists()
  {
    System.out.println("\n-- dists() --");
    gv.setTitle("-- dists() --");
    double[] coords = {
        250,60, 300,150, 190,150, 250,60 };
    Geometry poly = Utils.makeGeometry(coords, Utils.POLY);
    gv.add(poly);

    Geometry point = Utils.makePoint(100, 100);
    gv.add(point);

    double distance = poly.distance(point);
    DistanceOp op = new DistanceOp(poly, point);
    Coordinate[] nearestPoints = op.nearestPoints();

    boolean within103 = point.isWithinDistance(poly, 103);
    boolean within102 = point.isWithinDistance(poly, 102);

    System.out.printf("Distance: %.2f\n", distance);
    System.out.println("Point within 103 pixels of poly? " + within103);
    System.out.println("Within 102? " + within102);

    Utils.waitEnter();
    gv.clear();
  } /* dists() */



  private static void contains()
  {
    System.out.println("\n-- contains() --");
    gv.setTitle("-- contains() --");
    double[] coords = {
        250, 60,  300, 150,  190, 150,  250, 60 };
    Geometry poly = Utils.makeGeometry(coords, Utils.POLY);
    gv.add(poly);

    Geometry point1 = Utils.makePoint(100, 100);
    gv.add("Point1", point1);

    Geometry point2 = Utils.makePoint(250, 85);
    gv.add("Point2", point2);

    boolean polyHasPoint1 = poly.contains(point1);
    boolean polyHasPoint2 = poly.contains(point2);

    boolean point1inPoly = point1.within(poly);
    boolean point2inPoly = point2.within(poly);

    System.out.println("Polygon contains point1? " + polyHasPoint1);
    System.out.println("Point1 within poly? " + point1inPoly);
    System.out.println();
    System.out.println("Polygon contains point2? " + polyHasPoint2);
    System.out.println("Point2 within poly? " + point2inPoly);

    Utils.waitEnter();
    gv.clear();
  } /* contains() */




  private static void covers()
  {
    System.out.println("\n-- covers() --");
    gv.setTitle("-- covers() --");
    double[] coords = {
        250,110, 300,200, 190,200, 250,110 };
    Geometry poly = Utils.makeGeometry(coords, Utils.POLY);
    gv.add(poly);

    double[] quadCoords = {
        110,80, 370,90, 370,250, 100,250, 110,80 };
    Geometry quad = Utils.makeGeometry(quadCoords, Utils.POLY);
    gv.add(quad);

    System.out.println("Quad covers triangle? "  + quad.covers(poly));
    System.out.println("Triangle covered by quad? "  + poly.coveredBy(quad));

    Utils.waitEnter();
    gv.clear();
  } /* covers() */




  private static void intersects()
  {
    System.out.println("\n-- intersects() --");
    gv.setTitle("-- intersects() --");
    double[] coords = { 50,50, 150,150 };
    Geometry line1 = Utils.makeGeometry(coords, Utils.LINE);
    gv.add("line1", line1);

    Geometry line2 = Utils.makeGeometry(
              new double[] {80,40, 30,250 }, Utils.LINE);
    gv.add("line2", line2);

    System.out.println("Line1 and Line2 intersects? " +
                       line1.intersects(line2));
    Point intersectionPoint = (Point) line1.intersection(line2);
    gv.add(intersectionPoint);


    Geometry line3 = Utils.makeGeometry(
              new double[] {210,75, 350,170}, Utils.LINE);
    gv.add("line3", line3);

    System.out.println("Line3 and Line1 intersects? " +
                        line3.intersects(line1));

    System.out.println("Line3 and Line1 disjoint? " + 
                        line3.disjoint(line1));

    Utils.waitEnter();
    gv.clear();
  } /* intersects() */



  private static void crosses()
  {
    System.out.println("\n-- crosses() --");
    gv.setTitle("-- crosses() --");
    double[] coords1 = {
        60,60, 110,110,  155, 60, 60, 60 };

    double[] coords2 = {
        150,120, 300,120, 300,180, 150,180, 150,120 };

    double[] coords3 = { 40,75, 350,120 };

    double[] coords4 = { 210,160, 350,250 };

    Geometry tri = Utils.makeGeometry(coords1, Utils.POLY);
    gv.add(tri);

    Geometry poly = Utils.makeGeometry(coords2, Utils.POLY);
    gv.add(poly);

    Geometry line1 = Utils.makeGeometry(coords3, Utils.LINE);
    gv.add("line1", line1);

    Geometry line2 = Utils.makeGeometry(coords4, Utils.LINE);
    gv.add("line2", line2);

    System.out.println("triangle crosses line1: " + tri.crosses(line1) );
    System.out.println("line1 crosses poly: " + line1.crosses(poly) );
    System.out.println("line1 crosses tri: " + line1.crosses(tri) );
    System.out.println("poly crosses line2: " + poly.crosses(line2) );
    System.out.println("line2 crosses poly: " + line2.crosses(poly) );

    Utils.waitEnter();
    gv.clear();
  } /* crosses */



  private static void touches()
  {
    System.out.println("\n-- touches() --");
    gv.setTitle("-- touches() --");
    double[] coords1 = {
        60,60, 110,110, 155, 60, 60, 60 };

    double[] coords2 = {
        155,60, 250,150, 310, 40, 155, 60 };

    double[] coords3 = {
        150,120, 300,120, 300,180, 150,180, 150,120 };

    Geometry poly1 = Utils.makeGeometry(coords1, Utils.POLY);
    gv.add("poly1", poly1);
    Geometry poly2 = Utils.makeGeometry(coords2, Utils.POLY);
    gv.add("poly2", poly2);
    Geometry poly3 = Utils.makeGeometry(coords3, Utils.POLY);
    gv.add("poly3", poly3);

    System.out.println("poly1 touches poly2: " + poly1.touches(poly2));
    System.out.println("poly1 intersects poly2: " + poly1.intersects(poly2));
    System.out.println("poly1 overlaps poly2: " + poly1.overlaps(poly2));
    System.out.println();

    System.out.println("poly1 touches poly3: " + poly1.touches(poly3));
    System.out.println("poly1 intersects poly3: " + poly1.intersects(poly3));
    System.out.println("poly1 overlaps poly3: " + poly1.overlaps(poly3));
    System.out.println();

    System.out.println("poly3 touches poly1: " + poly3.touches(poly1));
    System.out.println("poly3 intersects poly1: " + poly3.intersects(poly1));
    System.out.println("poly3 overlaps poly1: " + poly3.overlaps(poly1));
    System.out.println();

    System.out.println("poly3 touches poly2: " + poly3.touches(poly2));
    System.out.println("poly3 intersects poly2: " + poly3.intersects(poly2));
    System.out.println("poly3 overlaps poly2: " + poly3.overlaps(poly2));
    System.out.println();

    System.out.println("poly2 touches poly3: " + poly2.touches(poly3));
    System.out.println("poly2 intersects poly3: " + poly2.intersects(poly3));
    System.out.println("poly2 overlaps poly3: " + poly2.overlaps(poly3));

    Utils.waitEnter();
    gv.clear();
  } /* touches() */



  private static void equals()
  {
    System.out.println("\n-- equals() --");
    gv.setTitle("-- equals() --");
    double[] coords1 = { 60,60, 150,60, 350, 60 };
    Geometry line1 = Utils.makeGeometry(coords1, Utils.LINE);
    System.out.println("line1: " + line1.toString());
    gv.add("line1", line1);

    double[] coords2 = { 350,60, 60,60 };
    Geometry line2 = Utils.makeGeometry(coords2, Utils.LINE);
    System.out.println("line2: " + line2.toString());
    gv.add("line2", line2);

    System.out.println("line1 equals (Object)line2: " +
                       line1.equals((Object)line2));

    System.out.println("line1 equals line2: " + line1.equals(line2));

    System.out.println("line1 equals (Geometry)line2: " +
                       line1.equals((Geometry)line2));

    System.out.println("line1 equalsExact line2: " +
                       line1.equalsExact(line2));

    Utils.waitEnter();
  } /* equals() */


}  // end of GeomOps class
