internal bool SegmentIntersection(xy p, xy q, out xy pt1, out xy pt2) { TriSegIntersect ti = new TriSegIntersect(); if (this.PointInside(p)) { ti.Add(p); } if (this.PointInside(q)) { ti.Add(q); } xy z1, z2; SegIntersection si = ut.GetSegIntersection(a, b, p, q, out z1, out z2); if (si == SegIntersection.Overlap) { pt1 = z1; pt2 = z2; return(true); } if (si == SegIntersection.Point) { ti.Add(z1); } si = ut.GetSegIntersection(b, c, p, q, out z1, out z2); if (si == SegIntersection.Overlap) { pt1 = z1; pt2 = z2; return(true); } if (si == SegIntersection.Point) { ti.Add(z1); } si = ut.GetSegIntersection(c, a, p, q, out z1, out z2); if (si == SegIntersection.Overlap) { pt1 = z1; pt2 = z2; return(true); } if (si == SegIntersection.Point) { ti.Add(z1); } if (ti.q1 == null) { pt1 = null; pt2 = null; return(false); } pt1 = ti.q1; if (ti.q2 != null) { pt2 = ti.q2; } else { pt2 = null; } return(true); }
public static void SplitSegment(List <seginfo2d> result, seg2d s1, Poly2dWithExtraStuff p2) { foreach (seg2d s2 in p2.segs) { if (fp.eq_inches(s1.a, s2.a) && fp.eq_inches(s1.b, s2.b)) { // same segment. result.Add(new seginfo2d(s1, SegmentInfo.Same)); // nothing else can happen. stop now. return; } else if (fp.eq_inches(s1.a, s2.b) && fp.eq_inches(s1.b, s2.a)) { // same segment, but reversed result.Add(new seginfo2d(s1, SegmentInfo.Opposite)); // nothing else can happen. stop now. return; } else { xy q1; xy q2; SegIntersection si = ut.GetSegIntersection(s1, s2, out q1, out q2); if (si == SegIntersection.Point) { if ( fp.eq_inches(q1, s1.a) || fp.eq_inches(q1, s1.b) ) { // an endpoint. this doesn't count as a hit. // ignore this } else { SplitSegment(result, new seg2d(s1.a, q1), p2); SplitSegment(result, new seg2d(q1, s1.b), p2); return; } } else if (si == SegIntersection.Overlap) { SegmentInfo dir; xy v1 = (s1.b - s1.a).normalize_in_place(); xy v2 = (s2.b - s2.a).normalize_in_place(); if (fp.eq_unitvec(v1, v2)) { dir = SegmentInfo.Same; } else { dir = SegmentInfo.Opposite; } if ( fp.eq_inches(s1.a, q1) && fp.eq_inches(s1.b, q2) ) { result.Add(new seginfo2d(s1, dir)); } else if ( fp.eq_inches(s1.a, q2) && fp.eq_inches(s1.b, q1) ) { result.Add(new seginfo2d(s1, dir)); } else if (fp.eq_inches(s1.a, q1)) { result.Add(new seginfo2d(new seg2d(s1.a, q2), dir)); SplitSegment(result, new seg2d(q2, s1.b), p2); } else if (fp.eq_inches(s1.a, q2)) { result.Add(new seginfo2d(new seg2d(s1.a, q1), dir)); SplitSegment(result, new seg2d(q1, s1.b), p2); } else if (fp.eq_inches(s1.b, q1)) { SplitSegment(result, new seg2d(s1.a, q2), p2); result.Add(new seginfo2d(new seg2d(q2, s1.b), dir)); } else if (fp.eq_inches(s1.b, q2)) { SplitSegment(result, new seg2d(s1.a, q1), p2); result.Add(new seginfo2d(new seg2d(q1, s1.b), dir)); } else { // both q1 and q2 are somewhere inside s1 xy z1 = q1 - s1.a; xy z2 = q2 - s1.a; if (z1.magnitude_squared() < z2.magnitude_squared()) { // q1 is closer SplitSegment(result, new seg2d(s1.a, q1), p2); result.Add(new seginfo2d(new seg2d(q1, q2), dir)); SplitSegment(result, new seg2d(q2, s1.b), p2); } else { // q2 is closer SplitSegment(result, new seg2d(s1.a, q2), p2); result.Add(new seginfo2d(new seg2d(q2, q1), dir)); SplitSegment(result, new seg2d(q1, s1.b), p2); } } return; } } } result.Add(new seginfo2d(s1, p2)); }