Package org.geomajas.gwt.client.spatial

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

/*
* 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;

/**
* Representation of a LineSegment, mainly for mathematical purposes. Can calculate much needed line to line and line to
* point calculations.
*
* @author Pieter De Graef
*/
public class LineSegment {

  /**
   * The line-segment's first(begin) coordinate.
   */
  private Coordinate c1;

  /**
   * The line-segment's last(end) coordinate.
   */
  private Coordinate c2;

  // -------------------------------------------------------------------------
  // Constructors:
  // -------------------------------------------------------------------------

  public LineSegment() {
    c1 = null;
    c2 = null;
  }

  public LineSegment(Coordinate c1, Coordinate c2) {
    this.c1 = c1;
    this.c2 = c2;
  }

  // -------------------------------------------------------------------------
  // Class specific functions:
  // -------------------------------------------------------------------------

  /**
   * Return the length of the linesegment.
   */
  public double getLength() {
    double deltaX = this.c2.getX() - this.c1.getX();
    double deltaY = this.c2.getY() - this.c1.getY();
    return Math.sqrt(deltaX * deltaX + deltaY * deltaY);
  }

  /**
   * Return the middle point of this linesegment.
   */
  public Coordinate getMiddlePoint() {
    double x = this.x1() + 0.5 * (this.x2() - this.x1());
    double y = this.y1() + 0.5 * (this.y2() - this.y1());
    return new Coordinate(x, y);
  }

  /**
   * Return the distance from a point to this linesegment. If the point is not perpendicular to the linesegment, the
   * closest endpoint will be returned.
   *
   * @param c
   *            The {@link Coordinate} to check distance from.
   */
  public double distance(Coordinate c) {
    Coordinate nearest = this.nearest(c);
    LineSegment ls = new LineSegment(c, nearest);
    return ls.getLength();
  }

  /**
   * Does this linesegment intersect with another or not?
   *
   * @param lineSegment
   *            The other linesegment.
   * @return Returns true if they intersect in 1 point, false otherwise.
   */
  public boolean intersects(LineSegment lineSegment) {
    double x1 = this.x1();
    double y1 = this.y1();
    double x2 = this.x2();
    double y2 = this.y2();
    double x3 = lineSegment.x1();
    double y3 = lineSegment.y1();
    double x4 = lineSegment.x2();
    double y4 = lineSegment.y2();

    double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    if (denom == 0) {
      return false;
    }
    double u1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
    double u2 = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
    return (u1 > 0 && u1 < 1 && u2 > 0 && u2 < 1);
  }

  /**
   * Return the intersection point of 2 lines. Yes you are reading this correctly! For this function the LineSegments
   * are treated as lines. This means that the intersection point does not necessarily lie on the LineSegment (in that
   * case, the {@link #intersects} function would return false).
   *
   * @param lineSegment
   *            The other LineSegment.
   * @return A {@link Coordinate} representing the intersection point.
   */
  public Coordinate getIntersection(LineSegment lineSegment) { // may not be on either one of the line segments.
    // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
    double x1 = this.x1();
    double y1 = this.y1();
    double x2 = this.x2();
    double y2 = this.y2();
    double x3 = lineSegment.x1();
    double y3 = lineSegment.y1();
    double x4 = lineSegment.x2();
    double y4 = lineSegment.y2();

    double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    double u1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;

    double x = x1 + u1 * (x2 - x1);
    double y = y1 + u1 * (y2 - y1);
    return new Coordinate(x, y);
  }

  /**
   * Return the intersection point of 2 line segments if they intersect in 1 point.
   *
   * @param lineSegment
   *            The other LineSegment.
   * @return A {@link Coordinate} representing the intersection point (so on both line segments), null if segments are
   *         not intersecting or corresponding lines are coinciding.
   */
  public Coordinate getIntersectionSegments(LineSegment lineSegment) {
    // http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
    double x1 = this.x1();
    double y1 = this.y1();
    double x2 = this.x2();
    double y2 = this.y2();
    double x3 = lineSegment.x1();
    double y3 = lineSegment.y1();
    double x4 = lineSegment.x2();
    double y4 = lineSegment.y2();

    double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    if (denom == 0) {
      return null;
    }

    double u1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
    if (u1 <= 0 || u1 >= 1) {
      return null;
    }
    double u2 = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
    if (u2 <= 0 || u2 >= 1) {
      return null;
    }
    double x = x1 + u1 * (x2 - x1);
    double y = y1 + u1 * (y2 - y1);
    return new Coordinate(x, y);
  }

  /**
   * Calculate which point on the LineSegment is nearest to the given coordinate. Will be perpendicular or one of the
   * end-points.
   *
   * @param c
   *            The coordinate to check.
   * @return The point on the LineSegment nearest to the given coordinate.
   */
  public Coordinate nearest(Coordinate c) {
    double len = this.getLength();

    double u = (c.getX() - this.c1.getX()) * (this.c2.getX() - this.c1.getX()) + (c.getY() - this.c1.getY())
        * (this.c2.getY() - this.c1.getY());
    u = u / (len * len);

    if (u < 0.00001 || u > 1) {
      // Shortest point not within LineSegment, so take closest end-point.
      LineSegment ls1 = new LineSegment(c, this.c1);
      LineSegment ls2 = new LineSegment(c, this.c2);
      double len1 = ls1.getLength();
      double len2 = ls2.getLength();
      if (len1 < len2) {
        return this.c1;
      }
      return this.c2;
    } else {
      // Intersecting point is on the line, use the formula: P = P1 + u (P2 - P1)
      double x1 = this.c1.getX() + u * (this.c2.getX() - this.c1.getX());
      double y1 = this.c1.getY() + u * (this.c2.getY() - this.c1.getY());
      return new Coordinate(x1, y1);
    }
  }

  //-------------------------------------------------------------------------
  // Getters
  //-------------------------------------------------------------------------

  public double x1() {
    return this.c1.getX();
  }

  public double y1() {
    return this.c1.getY();
  }

  public double x2() {
    return this.c2.getX();
  }

  public double y2() {
    return this.c2.getY();
  }

  public Coordinate getC1() {
    return this.c1;
  }

  public Coordinate getC2() {
    return this.c2;
  }
}
TOP

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

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.