123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- using System;
- namespace BBIWARG.Utility
- {
- /// <summary>
- /// Values for describing if something is on, above or below a line.
- /// </summary>
- public enum LineSide
- {
- onLine = 0,
- above = 1,
- below = 2
- }
- /// <summary>
- /// Line lass which represents a infinity line in 2 dimensional space.
- /// </summary>
- public class Line2D
- {
- /// <summary>
- /// direction vector of the line
- /// </summary>
- public Vector2D Direction { get; private set; }
- /// <summary>
- /// one point on the line
- /// </summary>
- public Vector2D PointOnLine { get; private set; }
- /// <summary>
- /// Standard constructor which sets the essential attributes.
- /// </summary>
- /// <param name="pointOnLine">a point on the line</param>
- /// <param name="direction">the direction of the line</param>
- public Line2D(Vector2D pointOnLine, Vector2D direction)
- {
- PointOnLine = pointOnLine;
- Direction = direction.normalize();
- }
- /// <summary>
- /// Computes angle between current and an second line in degrees.
- /// </summary>
- /// <param name="line">second line</param>
- /// <returns>angle between this and line in degrees</returns>
- public float getAngleBetween(Line2D line)
- {
- float angle = Direction.getAngleBetween(line.Direction);
- return Math.Min(angle, 180 - angle);
- }
- /// <summary>
- /// Computes the intersection of two lines, iff the lines do not intersect it returns null.
- /// </summary>
- /// <param name="line">the second line</param>
- /// <returns>the intersection or null iff the lines do not intersect</returns>
- 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;
- }
- /// <summary>
- /// Calculates whether a point is above, below or on this line.
- /// </summary>
- /// <param name="point">point which is used to compute the side</param>
- /// <returns>LineSide.above iff point is above this, LineSide.below iff point is below this, LineSide.onLine iff point is on this line</returns>
- 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;
- }
- /// <summary>
- /// Projects a point on this line.
- /// </summary>
- /// <param name="point">point which is projected</param>
- /// <returns>the point on the line with minimal distance to input point</returns>
- 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);
- }
- }
- }
|