using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; 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 { /// /// one point on the line /// public Vector2D PointOnLine { get; private set; } /// /// direction vector of the line /// public Vector2D Direction { get; private set; } /// /// Standard constructor which sets the essential attributes. /// /// /// 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); } /// /// 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 yPerX = Direction.Y / Direction.X; float xDiff = point.X - PointOnLine.X; float newY = PointOnLine.Y + yPerX * xDiff; 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 /// th 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); } /// /// 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; } } }