using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace bbiwarg.Utility { /// /// Class to represent a segment of a line, a line between two points. /// public class LineSegment2D { /// /// first point of the lineSegment /// public Vector2D P1 { get; private set; } /// /// second point of the lineSegment /// public Vector2D P2 { get; private set; } /// /// direction vector of the line which contains the lineSegment /// public Vector2D Direction { get { return Line.Direction; } } /// /// line which contains the lineSegment /// public Line2D Line { get; private set; } /// /// length of the LineSegment /// public float Length { get; private set; } /// /// Standard contructor which sets the essential attributes. /// /// first point of LineSegment /// second point of LineSegment public LineSegment2D(Vector2D p1, Vector2D p2) { //endpoints P1 = p1; P2 = p2; Line = new Line2D(P1, P2 - P1); Length = P1.getDistanceTo(P2); } /// /// Computes the intersection of two LineSegments, iff they do not intersect returns null. /// /// second LineSegment /// Intersection iff its defined, else null public bool intersectsWith(LineSegment2D ls) { Vector2D intersection = Line.getIntersection(ls.Line); return (intersection != null && intersection.isInBox(P1, P2) && intersection.isInBox(ls.P1, ls.P2)); } /// /// Computes the Distance of two parallel LineSegments, iff they are not parallel it returns 0. /// /// second LineSegment /// Distance between the LineSegment public float getParallelDistanceTo(LineSegment2D line) { if (Line.onSide(line.P1) != Line.onSide(line.P2)) return 0; Vector2D a1 = Line.projectToLine(line.P1); Vector2D a2 = Line.projectToLine(line.P2); float distanceA1 = a1.getDistanceTo(line.P1); float distanceA2 = a2.getDistanceTo(line.P2); return Math.Min(distanceA1, distanceA2); } /// /// Computes the vertical distance between two lineSegments. the vertical distance is the minimal distance between the LineSegments after they are projected on a horizontal line. /// /// second LineSegment /// the vertical distance public float getVerticalDistanceTo(LineSegment2D line) { Vector2D a1 = Line.projectToLine(line.P1); Vector2D a2 = Line.projectToLine(line.P2); if (P1.isInBox(a1, a2) || P2.isInBox(a1, a2)) return 0; float distanceP1A1 = P1.getDistanceTo(a1); float distanceP1A2 = P1.getDistanceTo(a2); float distanceP2A1 = P2.getDistanceTo(a1); float distanceP2A2 = P2.getDistanceTo(a2); return Math.Min(Math.Min(distanceP1A1, distanceP1A2), Math.Min(distanceP2A1, distanceP2A2)); } /// /// Computes the shortest distance of a point to the LineSegment. /// /// the point for distance calculation /// the distance public float getDistanceTo(Vector2D point) { // http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment float l2 = (P1 - P2).dotProduct(P1 - P2); // i.e. |w-v|^2 - avoid a sqrt if (l2 == 0.0) return point.getDistanceTo(P1); // v == w case // Consider the line extending the segment, parameterized as v + t (w - v). // We find projection of point p onto the line. // It falls where t = [(p-v) . (w-v)] / |w-v|^2 float t = (point - P1).dotProduct(P2 - P1) / l2; if (t < 0.0) return point.getDistanceTo(P1); // Beyond the 'v' end of the segment else if (t > 1.0) return point.getDistanceTo(P2); // Beyond the 'w' end of the segment Vector2D projection = P1 + t * (P2 - P1); // Projection falls on the segment return point.getDistanceTo(projection); } public override string ToString() { return (int)P1.X + "|" + (int)P1.Y + " --- " + (int)P2.X + "|" + (int)P2.Y; } } }