AForge.Math.Geometry.LineSegment.LocateProjection C# (CSharp) Method

LocateProjection() private method

private LocateProjection ( DoublePoint point ) : ProjectionLocation
point DoublePoint
return ProjectionLocation
        private ProjectionLocation LocateProjection( DoublePoint point )
        {
            // Modified from http://www.codeguru.com/forum/showthread.php?t=194400

            /*  How do I find the distance from a point to a line segment?

                Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
                Let P be the point of perpendicular projection of C on AB.  The parameter
                r, which indicates P's position along AB, is computed by the dot product
                of AC and AB divided by the square of the length of AB:

                (1)     AC dot AB
                    r = ---------
                        ||AB||^2

                r has the following meaning:

                    r=0      P = A
                    r=1      P = B
                    r<0      P is on the backward extension of AB (and distance C-AB is distance C-A)
                    r>1      P is on the forward extension of AB (and distance C-AB is distance C-B)
                    0<r<1    P is interior to AB (and distance C-AB(segment) is distance C-AB(line))

                The length of the line segment AB is computed by:

                    L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )

                and the dot product of two 2D vectors, U dot V, is computed:

                    D = (Ux * Vx) + (Uy * Vy)

                So (1) expands to:

                        (Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
                    r = -------------------------------
                             (Bx-Ax)^2 + (By-Ay)^2
            */

            // the above is modified here to compare the numerator and denominator, rather than doing the division
            DoublePoint abDelta = end - start;
            DoublePoint acDelta = point - start;

            double numerator   = acDelta.X * abDelta.X + acDelta.Y * abDelta.Y;
            double denomenator = abDelta.X * abDelta.X + abDelta.Y * abDelta.Y;

            ProjectionLocation result = ( numerator < 0 ) ? ProjectionLocation.RayA : ( numerator > denomenator ) ? ProjectionLocation.RayB : ProjectionLocation.SegmentAB;

            return result;
        }

Usage Example

Example #1
0
        /// <summary>
        /// Finds, provided it exists, the intersection point with the specified <see cref="LineSegment"/>.
        /// </summary>
        ///
        /// <param name="other"><see cref="LineSegment"/> to find intersection with.</param>
        ///
        /// <returns>Returns intersection point with the specified <see cref="LineSegment"/>, or <see langword="null"/>, if
        /// the two segments do not intersect.</returns>
        ///
        /// <remarks><para>If the two segments do not intersect, the method returns <see langword="null"/>. If the two
        /// segments share multiple points, this throws an <see cref="InvalidOperationException"/>.
        /// </para></remarks>
        ///
        /// <exception cref="InvalidOperationException">Thrown if the segments overlap - if they have
        /// multiple points in common.</exception>
        ///
        public Point?GetIntersectionWith(LineSegment other)
        {
            Point?result = null;

            if ((line.Slope == other.line.Slope) || (line.IsVertical && other.line.IsVertical))
            {
                if (line.Intercept == other.line.Intercept)
                {
                    // Collinear segments. Inspect and handle.
                    // Consider this segment AB and other as CD. (start/end in both cases)
                    // There are three cases:
                    // 0 shared points: C and D both project onto the same ray of AB
                    // 1 shared point: One of A or B equals one of C or D, and the other of C/D
                    //      projects on the correct ray.
                    // Many shared points.

                    ProjectionLocation projC = LocateProjection(other.start), projD = LocateProjection(other.end);

                    if ((projC != ProjectionLocation.SegmentAB) && (projC == projD))
                    {
                        // no shared points
                        result = null;
                    }
                    else if (((start == other.start) && (projD == ProjectionLocation.RayA)) ||
                             ((start == other.end) && (projC == ProjectionLocation.RayA)))
                    {
                        // shared start point
                        result = start;
                    }
                    else if (((end == other.start) && (projD == ProjectionLocation.RayB)) ||
                             ((end == other.end) && (projC == ProjectionLocation.RayB)))
                    {
                        // shared end point
                        result = end;
                    }
                    else
                    {
                        // overlapping
                        throw new InvalidOperationException("Overlapping segments do not have a single intersection point.");
                    }
                }
            }
            else
            {
                result = GetIntersectionWith(other.line);

                if ((result.HasValue) && (other.LocateProjection(result.Value) != ProjectionLocation.SegmentAB))
                {
                    // the intersection is on the extended line of this segment
                    result = null;
                }
            }

            return(result);
        }
All Usage Examples Of AForge.Math.Geometry.LineSegment::LocateProjection