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 static bool IsEmpty(Point point)
 {
     return(DoubleHelper.IsNaN(point.X) && DoubleHelper.IsNaN(point.Y));
 }