Package org.geomajas.gwt.client.spatial

Source Code of org.geomajas.gwt.client.spatial.Mathlib

/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2011 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/

package org.geomajas.gwt.client.spatial;

import org.geomajas.geometry.Coordinate;
import org.geomajas.gwt.client.spatial.geometry.Geometry;
import org.geomajas.gwt.client.spatial.geometry.LineString;
import org.geomajas.gwt.client.spatial.geometry.LinearRing;
import org.geomajas.gwt.client.spatial.geometry.MultiLineString;
import org.geomajas.gwt.client.spatial.geometry.MultiPolygon;
import org.geomajas.gwt.client.spatial.geometry.Point;
import org.geomajas.gwt.client.spatial.geometry.Polygon;

/**
* General math library.
*
* @author Pieter De Graef
*/
public final class Mathlib {

  public static final double ZERO = 0.00001;

  /**
   * Calculates whether or not 2 line-segments intersect.
   *
   * @param c1
   *            First coordinate of the first line-segment.
   * @param c2
   *            Second coordinate of the first line-segment.
   * @param c3
   *            First coordinate of the second line-segment.
   * @param c4
   *            Second coordinate of the second line-segment.
   * @return Returns true or false.
   */
  public static boolean lineIntersects(Coordinate c1, Coordinate c2, Coordinate c3, Coordinate c4) {
    LineSegment ls1 = new LineSegment(c1, c2);
    LineSegment ls2 = new LineSegment(c3, c4);
    return ls1.intersects(ls2);
  }

  /**
   * Calculates the intersection point of 2 lines.
   *
   * @param c1
   *            First coordinate of the first line.
   * @param c2
   *            Second coordinate of the first line.
   * @param c3
   *            First coordinate of the second line.
   * @param c4
   *            Second coordinate of the second line.
   * @return Returns a coordinate.
   */
  public static Coordinate lineIntersection(Coordinate c1, Coordinate c2, Coordinate c3, Coordinate c4) {
    LineSegment ls1 = new LineSegment(c1, c2);
    LineSegment ls2 = new LineSegment(c3, c4);
    return ls1.getIntersection(ls2);
  }

  /**
   * Calculates the intersection point of 2 line segments.
   *
   * @param c1
   *            Start point of the first line segment.
   * @param c2
   *            End point of the first line segment.
   * @param c3
   *            Start point of the second line segment.
   * @param c4
   *            End point of the second line segment.
   * @return Returns a coordinate or null if not a single intersection point.
   */
  public Coordinate lineSegmentIntersection(Coordinate c1, Coordinate c2, Coordinate c3, Coordinate c4) {
    LineSegment ls1 = new LineSegment(c1, c2);
    LineSegment ls2 = new LineSegment(c3, c4);
    return ls1.getIntersectionSegments(ls2);
  }

  /**
   * Distance between 2 points.
   *
   * @param c1
   *            First coordinate
   * @param c2
   *            Second coordinate
   */
  public static double distance(Coordinate c1, Coordinate c2) {
    double a = c1.getX() - c2.getX();
    double b = c1.getY() - c2.getY();
    return Math.sqrt(a * a + b * b);
  }

  /**
   * Distance between a point and a line.
   *
   * @param c1
   *            First coordinate of the line.
   * @param c2
   *            Second coordinate of the line.
   * @param c3
   *            Coordinate to calculate distance to line from.
   */
  public static double distance(Coordinate c1, Coordinate c2, Coordinate c3) {
    LineSegment ls = new LineSegment(c1, c2);
    return ls.distance(c3);
  }

  /**
   * Does a certain coordinate touch a given geometry?
   *
   * @param geometry
   *            The geometry to check against.
   * @param coordinate
   *            The position to check.
   * @return Returns true if the coordinate touches the geometry.
   */
  public static boolean touches(Geometry geometry, Coordinate coordinate) {
    if (geometry instanceof MultiPolygon) {
      for (int i = 0; i < geometry.getNumGeometries(); i++) {
        if (touches(geometry.getGeometryN(i), coordinate)) {
          return true;
        }
      }
      return false;
    } else if (geometry instanceof Polygon) {
      Polygon polygon = (Polygon) geometry;
      if (touchesLineString(polygon.getExteriorRing(), coordinate)) {
        return true;
      }
      for (int n = 0; n < polygon.getNumInteriorRing(); n++) {
        if (touchesLineString(polygon.getInteriorRingN(n), coordinate)) {
          return true;
        }
      }
      return false;
    } else if (geometry instanceof MultiLineString) {
      for (int i = 0; i < geometry.getNumGeometries(); i++) {
        if (touchesLineString((LineString) geometry.getGeometryN(i), coordinate)) {
          return true;
        }
      }
      return false;
    } else if (geometry instanceof LineString) {
      return touchesLineString((LineString) geometry, coordinate);
    } else if (geometry instanceof Point) {
      Coordinate c = geometry.getCoordinates()[0];
      Vector2D v1 = new Vector2D(c.getX(), c.getY());
      Vector2D v2 = new Vector2D(coordinate.getX(), coordinate.getY());
      return (v1.distance(v2) < ZERO);
    }
    return false;
  }

  /**
   * Is a certain coordinate within a given geometry?
   *
   * @param geometry
   *            The geometry to check against. Only if it has {@link LinearRing}'s, can the coordinate be inside.
   * @param coordinate
   *            The position that is possibly within the geometry.
   * @return Returns true if the coordinate is within the geometry.
   */
  public static boolean isWithin(Geometry geometry, Coordinate coordinate) {
    if (geometry instanceof MultiPolygon) {
      for (int i = 0; i < geometry.getNumGeometries(); i++) {
        if (isWithin(geometry.getGeometryN(i), coordinate)) {
          return true;
        }
      }
    } else if (geometry instanceof Polygon) {
      Polygon polygon = (Polygon) geometry;
      if (isWithinRing(polygon.getExteriorRing(), coordinate)) {
        for (int i = 0; i < polygon.getNumInteriorRing(); i++) {
          if (isWithinRing(polygon.getInteriorRingN(i), coordinate)) {
            return false;
          }
        }
        return true;
      }
    } else if (geometry instanceof LinearRing) {
      return isWithinRing((LinearRing) geometry, coordinate);
    }
    return false;
  }

  //-------------------------------------------------------------------------
  // Private methods:
  //-------------------------------------------------------------------------

  /**
   * @private
   */
  private static boolean touchesLineString(LineString lineString, Coordinate coordinate) {
    // First loop over the end-points. This will be the most common case, certainly if we take snapping into
    // account...
    for (int i = 0; i < lineString.getNumPoints(); i++) {
      if (lineString.getCoordinateN(i).equals(coordinate)) {
        return true;
      }
    }

    // Now loop over the edges:
    for (int i = 1; i < lineString.getNumPoints(); i++) {
      LineSegment edge = new LineSegment(lineString.getCoordinateN(i - 1), lineString.getCoordinateN(i));
      if (edge.distance(coordinate) < ZERO) {
        return true;
      }
    }

    return false;
  }

  /**
   * @private
   */
  private static boolean isWithinRing(LinearRing linearRing, Coordinate coordinate) {
    int counter = 0;
    int num = linearRing.getNumPoints();
    Coordinate c1 = linearRing.getCoordinateN(0);
    for (int i = 1; i <= num; i++) {
      Coordinate c2 = linearRing.getCoordinateN(i % num); // this way, it should work to concatenate all ring
      // coordinate arrays of a polygon....(if they all have an equal number of coordinates)
      if (coordinate.getY() > Math.min(c1.getY(), c2.getY())) { // some checks to try and avoid the expensive
        // intersect calculation.
        if (coordinate.getY() <= Math.max(c1.getY(), c2.getY())) {
          if (coordinate.getX() <= Math.max(c1.getX(), c2.getX())) {
            if (c1.getY() != c2.getY()) {
              double xIntercept = (coordinate.getY() - c1.getY()) * (c2.getX() - c1.getX())
                  / (c2.getY() - c1.getY()) + c1.getX();
              if (c1.getX() == c2.getX() || coordinate.getX() <= xIntercept) {
                counter++;
              }
            }
          }
        }
      }
      c1 = c2;
    }
    if (counter % 2 == 0) {
      return false;
    }
    return true;
  }
}
TOP

Related Classes of org.geomajas.gwt.client.spatial.Mathlib

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.