private static void AdjustResultForIntersectionWithSide( ref Nullable<Point> result, ref double distance, Segment intersection, Point point ) { if( !intersection.IsEmpty ) { if( intersection.Contains( point ) ) { distance = 0; result = point; return; } double p1Distance = PointHelper.DistanceBetween( point, intersection.P1 ); double p2Distance = double.PositiveInfinity; if( !intersection.IsPoint ) { p2Distance = PointHelper.DistanceBetween( point, intersection.P2 ); } if( Math.Min( p1Distance, p2Distance ) < distance ) { if( p1Distance < p2Distance ) { distance = p1Distance; result = intersection.P1; } else { distance = p2Distance; result = intersection.P2; } } } }
public static Nullable<Point> GetNearestPointOfIntersectionBetweenRectAndSegment( Rect rect, Segment segment, Point point ) { Nullable<Point> result = null; double distance = double.PositiveInfinity; Segment leftIntersection = segment.Intersection( new Segment( rect.BottomLeft, rect.TopLeft ) ); Segment topIntersection = segment.Intersection( new Segment( rect.TopLeft, rect.TopRight ) ); Segment rightIntersection = segment.Intersection( new Segment( rect.TopRight, rect.BottomRight ) ); Segment bottomIntersection = segment.Intersection( new Segment( rect.BottomRight, rect.BottomLeft ) ); RectHelper.AdjustResultForIntersectionWithSide( ref result, ref distance, leftIntersection, point ); RectHelper.AdjustResultForIntersectionWithSide( ref result, ref distance, topIntersection, point ); RectHelper.AdjustResultForIntersectionWithSide( ref result, ref distance, rightIntersection, point ); RectHelper.AdjustResultForIntersectionWithSide( ref result, ref distance, bottomIntersection, point ); return result; }
public static bool AreVirtuallyEqual( Segment s1, Segment s2 ) { // note: Segment struct already uses "virtually equal" approach return ( s1 == s2 ); }
public Segment Intersection( Segment segment ) { // if either segment is empty, the intersection is also empty if( this.IsEmpty || segment.IsEmpty ) return Segment.Empty; // if the segments are equal, just return a new equal segment if( this == segment ) return new Segment( this._p1, this._p2, this._isP1Excluded, this._isP2Excluded ); // if either segment is a Point, just see if the point is contained in the other segment if( this.IsPoint ) return segment.Contains( this._p1 ) ? new Segment( this._p1 ) : Segment.Empty; if( segment.IsPoint ) return this.Contains( segment._p1 ) ? new Segment( segment._p1 ) : Segment.Empty; // okay, no easy answer, so let's do the math... Point p1 = this._p1; Vector v1 = this._p2 - this._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( this._p1, this._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 = this._p1; result._p2 = this._p2; result._isP1Excluded = this._isP1Excluded || !segment.Contains( this._p1 ); result._isP2Excluded = this._isP2Excluded || !segment.Contains( this._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 || !this.Contains( segment._p1 ); result._isP2Excluded = segment._isP2Excluded || !this.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 = this._p1; result._isP1Excluded = this._isP1Excluded || !segment.Contains( this._p1 ); } else { result._p1 = this._p2; result._isP1Excluded = this._isP2Excluded || !segment.Contains( this._p2 ); } if( includeSegmentP1 ) { result._p2 = segment._p1; result._isP2Excluded = segment._isP1Excluded || !this.Contains( segment._p1 ); } else { result._p2 = segment._p2; result._isP2Excluded = segment._isP2Excluded || !this.Contains( segment._p2 ); } return result; }
public bool Contains( Segment segment ) { return ( segment == this.Intersection( segment ) ); }
private static void AdjustResultForIntersectionWithSide(ref Nullable <Point> result, ref double distance, Segment intersection, Point point) { if (!intersection.IsEmpty) { if (intersection.Contains(point)) { distance = 0; result = point; return; } double p1Distance = PointHelper.DistanceBetween(point, intersection.P1); double p2Distance = double.PositiveInfinity; if (!intersection.IsPoint) { p2Distance = PointHelper.DistanceBetween(point, intersection.P2); } if (Math.Min(p1Distance, p2Distance) < distance) { if (p1Distance < p2Distance) { distance = p1Distance; result = intersection.P1; } else { distance = p2Distance; result = intersection.P2; } } } }
public static Nullable <Point> GetNearestPointOfIntersectionBetweenRectAndSegment(Rect rect, Segment segment, Point point) { Nullable <Point> result = null; double distance = double.PositiveInfinity; Segment leftIntersection = segment.Intersection(new Segment(rect.BottomLeft, rect.TopLeft)); Segment topIntersection = segment.Intersection(new Segment(rect.TopLeft, rect.TopRight)); Segment rightIntersection = segment.Intersection(new Segment(rect.TopRight, rect.BottomRight)); Segment bottomIntersection = segment.Intersection(new Segment(rect.BottomRight, rect.BottomLeft)); RectHelper.AdjustResultForIntersectionWithSide(ref result, ref distance, leftIntersection, point); RectHelper.AdjustResultForIntersectionWithSide(ref result, ref distance, topIntersection, point); RectHelper.AdjustResultForIntersectionWithSide(ref result, ref distance, rightIntersection, point); RectHelper.AdjustResultForIntersectionWithSide(ref result, ref distance, bottomIntersection, point); return(result); }