public bool Intersect(LineSegment a, LineSegment b, bool ignoreEndPointIntersects, out List <LineSegmentIntersect> intersects) { float ua = (b.End.X - b.Start.X) * (a.Start.Y - b.Start.Y) - (b.End.Y - b.Start.Y) * (a.Start.X - b.Start.X); float ub = (a.End.X - a.Start.X) * (a.Start.Y - b.Start.Y) - (a.End.Y - a.Start.Y) * (a.Start.X - b.Start.X); float denominator = (b.End.Y - b.Start.Y) * (a.End.X - a.Start.X) - (b.End.X - b.Start.X) * (a.End.Y - a.Start.Y); intersects = null; const float small = 0.01f; if (Math.Abs(denominator) <= small) { if (Math.Abs(ua) <= small && Math.Abs(ub) <= small) { // lines are coincident: // lacking other algorithms which actually work, // roll some expensive distance tests to find intersection points if (a.Start.DistanceFromLineSegment(b) <= small) { intersects = new List <LineSegmentIntersect>(); intersects.Add(new LineSegmentIntersect(LineSegmentIntersectType.StartA, a.Start)); } if (a.End.DistanceFromLineSegment(b) <= small) { if (intersects == null) { intersects = new List <LineSegmentIntersect>(); } intersects.Add(new LineSegmentIntersect(LineSegmentIntersectType.EndA, a.End)); } if (b.Start.DistanceFromLineSegment(a) <= small) { if (intersects == null) { intersects = new List <LineSegmentIntersect>(); } intersects.Add(new LineSegmentIntersect(LineSegmentIntersectType.MidPointA, b.Start)); } if (b.End.DistanceFromLineSegment(a) <= small) { if (intersects == null) { intersects = new List <LineSegmentIntersect>(); } intersects.Add(new LineSegmentIntersect(LineSegmentIntersectType.MidPointA, b.End)); } } } else { ua /= denominator; ub /= denominator; if (ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1) { LineSegmentIntersectType type = LineSegmentIntersectType.MidPointA; if (ua <= small) { type = LineSegmentIntersectType.StartA; } else if (1 - ua <= small) { type = LineSegmentIntersectType.EndA; } intersects = new List <LineSegmentIntersect>(); intersects.Add(new LineSegmentIntersect(type, a.Start + new Vector(ua * (a.End.X - a.Start.X), ua * (a.End.Y - a.Start.Y)))); } } if (intersects != null && ignoreEndPointIntersects) { for (int index = 0; index < intersects.Count; ++index) { var intersect = intersects[index]; if (intersect.Position.Distance(a.Start) <= small || intersect.Position.Distance(b.Start) <= small || intersect.Position.Distance(a.End) <= small || intersect.Position.Distance(b.End) <= small) { intersects.RemoveAt(index); --index; } } } return(intersects != null); }
public LineSegmentIntersect(LineSegmentIntersectType type, Vector pos) { Type = type; Position = pos; }