package rescuecore2.misc.geometry;
import static rescuecore2.misc.geometry.GeometryTools2D.nearlyZero;
import rescuecore2.misc.geometry.spatialindex.Indexable;
import rescuecore2.misc.geometry.spatialindex.Region;
import rescuecore2.misc.geometry.spatialindex.LineRegion;
/**
A line segment in 2D space. Lines are immutable.
*/
public class Line2D implements Indexable {
private Point2D origin;
private Point2D end;
private Vector2D direction;
private LineRegion region;
/**
Create a new line segment.
@param origin The origin of the line.
@param direction The direction of the line.
*/
public Line2D(Point2D origin, Vector2D direction) {
this.origin = origin;
this.direction = direction;
this.end = origin.plus(direction);
}
/**
Create a new line segment.
@param origin The origin of the line.
@param end The end of the line.
*/
public Line2D(Point2D origin, Point2D end) {
this.origin = origin;
this.end = end;
this.direction = end.minus(origin);
}
/**
Create a new line segment.
@param x The x coordinate of the origin.
@param y The y coordinate of the origin.
@param dx The x component of the direction.
@param dy The y component of the direction.
*/
public Line2D(double x, double y, double dx, double dy) {
this(new Point2D(x, y), new Vector2D(dx, dy));
}
/**
Get a point along this line.
@param t The distance along the direction vector to create the point.
@return A new Point2D.
*/
public Point2D getPoint(double t) {
return origin.translate(t * direction.getX(), t * direction.getY());
}
/**
Get the origin of this line segment.
@return The origin.
*/
public Point2D getOrigin() {
return origin;
}
/**
Get the endpoint of this line segment.
@return The endpoint.
*/
public Point2D getEndPoint() {
return end;
}
/**
Get the direction of this line segment.
@return The direction vector.
*/
public Vector2D getDirection() {
return direction;
}
@Override
public String toString() {
return "Line from " + origin + " towards " + end + " (direction = " + direction + ")";
}
/**
Find out how far along this line the intersection point with another line is.
@param other The other line.
@return How far along this line (in terms of this line's direction vector) the intersection point is, or NaN if the lines are parallel.
*/
public double getIntersection(Line2D other) {
double bxax = direction.getX();
double dycy = other.direction.getY();
double byay = direction.getY();
double dxcx = other.direction.getX();
double cxax = other.origin.getX() - origin.getX();
double cyay = other.origin.getY() - origin.getY();
double d = (bxax * dycy) - (byay * dxcx);
double t = (cxax * dycy) - (cyay * dxcx);
if (nearlyZero(d)) {
// d is close to zero: lines are parallel so no intersection
return Double.NaN;
}
return t / d;
}
@Override
public Region getBoundingRegion() {
if (region == null) {
region = new LineRegion(origin.getX(), origin.getY(), end.getX(), end.getY());
}
return region;
}
}