public bool Contains(Segment segment) { return (segment == Intersection(segment)); }
public Segment Intersection(Segment segment) { // if either segment is empty, the intersection is also empty if (IsEmpty || segment.IsEmpty) return Segment.Empty; // if the segments are equal, just return a new equal segment if (this == segment) return new Segment(_p1, _p2, _isP1Excluded, _isP2Excluded); // if either segment is a Point, just see if the point is contained in the other segment if (IsPoint) return segment.Contains(_p1) ? new Segment(_p1) : Segment.Empty; if (segment.IsPoint) return Contains(segment._p1) ? new Segment(segment._p1) : Segment.Empty; // okay, no easy answer, so let's do the math... Point p1 = _p1; Vector v1 = _p2 - _p1; Point p2 = segment._p1; Vector v2 = segment._p2 - segment._p1; Vector endpointVector = p2 - p1; double xProd = Vector.CrossProduct(v1, v2); // if segments are not parallel, then look for intersection on each segment if (!DoubleHelper.AreVirtuallyEqual(Slope, segment.Slope)) { // check for intersection on other segment double s = (Vector.CrossProduct(endpointVector, v1)) / xProd; if (s < 0 || s > 1) return Segment.Empty; // check for intersection on this segment s = (Vector.CrossProduct(endpointVector, v2)) / xProd; if (s < 0 || s > 1) return Segment.Empty; // intersection of segments is a point return new Segment(p1 + s * v1); } // segments are parallel xProd = Vector.CrossProduct(endpointVector, v1); if (xProd * xProd > 1.0e-06 * v1.LengthSquared * endpointVector.LengthSquared) { // segments do not intersect return Segment.Empty; } // intersection is overlapping segment Segment result = new Segment(); // to determine the overlapping segment, create reference segments where the endpoints are *not* excluded Segment refThis = new Segment(_p1, _p2); Segment refSegment = new Segment(segment._p1, segment._p2); // check whether this segment is contained in the other segment bool includeThisP1 = refSegment.Contains(refThis._p1); bool includeThisP2 = refSegment.Contains(refThis._p2); if (includeThisP1 && includeThisP2) { result._p1 = _p1; result._p2 = _p2; result._isP1Excluded = _isP1Excluded || !segment.Contains(_p1); result._isP2Excluded = _isP2Excluded || !segment.Contains(_p2); return result; } // check whether the other segment is contained in this segment bool includeSegmentP1 = refThis.Contains(refSegment._p1); bool includeSegmentP2 = refThis.Contains(refSegment._p2); if (includeSegmentP1 && includeSegmentP2) { result._p1 = segment._p1; result._p2 = segment._p2; result._isP1Excluded = segment._isP1Excluded || !Contains(segment._p1); result._isP2Excluded = segment._isP2Excluded || !Contains(segment._p2); return result; } // the intersection must include one endpoint from this segment and one endpoint from the other segment if (includeThisP1) { result._p1 = _p1; result._isP1Excluded = _isP1Excluded || !segment.Contains(_p1); } else { result._p1 = _p2; result._isP1Excluded = _isP2Excluded || !segment.Contains(_p2); } if (includeSegmentP1) { result._p2 = segment._p1; result._isP2Excluded = segment._isP1Excluded || !Contains(segment._p1); } else { result._p2 = segment._p2; result._isP2Excluded = segment._isP2Excluded || !Contains(segment._p2); } return result; }
public static bool AreVirtuallyEqual(Segment s1, Segment s2) { // note: Segment struct already uses "virtually equal" approach return (s1 == s2); }