using System;
namespace BBIWARG.Utility
{
///
/// Values for describing if something is on, above or below a line.
///
public enum LineSide
{
onLine = 0,
above = 1,
below = 2
}
///
/// Line lass which represents a infinity line in 2 dimensional space.
///
public class Line2D
{
///
/// direction vector of the line
///
public Vector2D Direction { get; private set; }
///
/// one point on the line
///
public Vector2D PointOnLine { get; private set; }
///
/// Standard constructor which sets the essential attributes.
///
/// a point on the line
/// the direction of the line
public Line2D(Vector2D pointOnLine, Vector2D direction)
{
PointOnLine = pointOnLine;
Direction = direction.normalize();
}
///
/// Computes angle between current and an second line in degrees.
///
/// second line
/// angle between this and line in degrees
public float getAngleBetween(Line2D line)
{
float angle = Direction.getAngleBetween(line.Direction);
return Math.Min(angle, 180 - angle);
}
///
/// Computes the intersection of two lines, iff the lines do not intersect it returns null.
///
/// the second line
/// the intersection or null iff the lines do not intersect
public Vector2D getIntersection(Line2D line)
{
Vector2D p = PointOnLine;
Vector2D r = Direction;
Vector2D q = line.PointOnLine;
Vector2D s = line.Direction;
float r_cross_s = r.crossProduct(s);
float q_p_cross_s = (q - p).crossProduct(s);
if (r_cross_s == 0.0)
return null;
float t = q_p_cross_s / r_cross_s;
return p + t * r;
}
///
/// Calculates whether a point is above, below or on this line.
///
/// point which is used to compute the side
/// LineSide.above iff point is above this, LineSide.below iff point is below this, LineSide.onLine iff point is on this line
public LineSide onSide(Vector2D point)
{
float ratio = Direction.Y / Direction.X;
float horizontalDifference = point.X - PointOnLine.X;
float newY = PointOnLine.Y + ratio * horizontalDifference;
if (newY < point.Y) return LineSide.above;
else if (newY > point.Y) return LineSide.below;
else return LineSide.onLine;
}
///
/// Projects a point on this line.
///
/// point which is projected
/// the point on the line with minimal distance to input point
public Vector2D projectToLine(Vector2D point)
{
float px = point.X, py = point.Y, dx = Direction.X, dy = Direction.Y, ox = PointOnLine.X, oy = PointOnLine.Y;
float diffx = px - ox;
float diffy = py - oy;
float diff_d = diffx * dx + diffy * dy;
float d_d = dx * dx + dy * dy;
float q = diff_d / d_d;
float newX = ox + q * dx;
float newY = oy + q * dy;
return new Vector2D(newX, newY);
}
}
}