AForge.Math.Geometry.PointsCloud.GetFurthestPointsFromLine C# (CSharp) Method

GetFurthestPointsFromLine() public static method

Find two furhtest points from the specified line.

The method finds two furhtest points from the specified line, where one point is on one side from the line and the second point is on another side from the line.

public static GetFurthestPointsFromLine ( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2, IntPoint &furthestPoint1, IntPoint &furthestPoint2 ) : void
cloud IEnumerable Collection of points to search furthest points in.
linePoint1 IntPoint First point forming the line.
linePoint2 IntPoint Second point forming the line.
furthestPoint1 IntPoint First found furthest point.
furthestPoint2 IntPoint Second found furthest point (which is on the /// opposite side from the line compared to the );
return void
        public static void GetFurthestPointsFromLine( IEnumerable<IntPoint> cloud, IntPoint linePoint1, IntPoint linePoint2,
            out IntPoint furthestPoint1, out IntPoint furthestPoint2 )
        {
            double d1, d2;

            GetFurthestPointsFromLine( cloud, linePoint1, linePoint2,
                out furthestPoint1, out d1, out furthestPoint2, out d2 );
        }

Same methods

PointsCloud::GetFurthestPointsFromLine ( IEnumerable cloud, IntPoint linePoint1, IntPoint linePoint2, IntPoint &furthestPoint1, double &distance1, IntPoint &furthestPoint2, double &distance2 ) : void

Usage Example

Example #1
0
        /// <summary>
        /// Find corners of quadrilateral or triangular area, which contains the specified collection of points.
        /// </summary>
        ///
        /// <param name="cloud">Collection of points to search quadrilateral for.</param>
        ///
        /// <returns>Returns a list of 3 or 4 points, which are corners of the quadrilateral or
        /// triangular area filled by specified collection of point. The first point in the list
        /// is the point with lowest X coordinate (and with lowest Y if there are several points
        /// with the same X value). The corners are provided in counter clockwise order
        /// (<a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian
        /// coordinate system</a>).</returns>
        ///
        /// <remarks><para>The method makes an assumption that the specified collection of points
        /// form some sort of quadrilateral/triangular area. With this assumption it tries to find corners
        /// of the area.</para>
        ///
        /// <para><note>The method does not search for <b>bounding</b> quadrilateral/triangular area,
        /// where all specified points are <b>inside</b> of the found quadrilateral/triangle. Some of the
        /// specified points potentially may be outside of the found quadrilateral/triangle, since the
        /// method takes corners only from the specified collection of points, but does not calculate such
        /// to form true bounding quadrilateral/triangle.</note></para>
        ///
        /// <para>See <see cref="QuadrilateralRelativeDistortionLimit"/> property for additional information.</para>
        /// </remarks>
        ///
        public static List <IntPoint> FindQuadrilateralCorners(IEnumerable <IntPoint> cloud)
        {
            // quadrilateral's corners
            var corners = new List <IntPoint>( );

            // get bounding rectangle of the points list
            IntPoint minXY, maxXY;

            PointsCloud.GetBoundingRectangle(cloud, out minXY, out maxXY);
            // get cloud's size
            var cloudSize = maxXY - minXY;
            // calculate center point
            var center = minXY + cloudSize / 2;
            // acceptable deviation limit
            var distortionLimit = quadrilateralRelativeDistortionLimit * (cloudSize.X + cloudSize.Y) / 2;

            // get the furthest point from (0,0)
            var point1 = PointsCloud.GetFurthestPoint(cloud, center);
            // get the furthest point from the first point
            var point2 = PointsCloud.GetFurthestPoint(cloud, point1);

            corners.Add(point1);
            corners.Add(point2);

            // get two furthest points from line
            IntPoint point3, point4;
            float    distance3, distance4;

            PointsCloud.GetFurthestPointsFromLine(cloud, point1, point2,
                                                  out point3, out distance3, out point4, out distance4);

            // ideally points 1 and 2 form a diagonal of the
            // quadrilateral area, and points 3 and 4 form another diagonal

            // but if one of the points (3 or 4) is very close to the line
            // connecting points 1 and 2, then it is one the same line ...
            // which means corner was not found.
            // in this case we deal with a trapezoid or triangle, where
            // (1-2) line is one of it sides.

            // another interesting case is when both points (3) and (4) are
            // very close the (1-2) line. in this case we may have just a flat
            // quadrilateral.

            if (
                ((distance3 >= distortionLimit) && (distance4 >= distortionLimit)) ||

                ((distance3 < distortionLimit) && (distance3 != 0) &&
                 (distance4 < distortionLimit) && (distance4 != 0)))
            {
                // don't add one of the corners, if the point is already in the corners list
                // (this may happen when both #3 and #4 points are very close to the line
                // connecting #1 and #2)
                if (!corners.Contains(point3))
                {
                    corners.Add(point3);
                }
                if (!corners.Contains(point4))
                {
                    corners.Add(point4);
                }
            }
            else
            {
                // it seems that we deal with kind of trapezoid,
                // where point 1 and 2 are on the same edge

                var tempPoint = (distance3 > distance4) ? point3 : point4;

                // try to find 3rd point
                PointsCloud.GetFurthestPointsFromLine(cloud, point1, tempPoint,
                                                      out point3, out distance3, out point4, out distance4);

                var thirdPointIsFound = false;

                if ((distance3 >= distortionLimit) && (distance4 >= distortionLimit))
                {
                    if (point4.DistanceTo(point2) > point3.DistanceTo(point2))
                    {
                        point3 = point4;
                    }

                    thirdPointIsFound = true;
                }
                else
                {
                    PointsCloud.GetFurthestPointsFromLine(cloud, point2, tempPoint,
                                                          out point3, out distance3, out point4, out distance4);

                    if ((distance3 >= distortionLimit) && (distance4 >= distortionLimit))
                    {
                        if (point4.DistanceTo(point1) > point3.DistanceTo(point1))
                        {
                            point3 = point4;
                        }

                        thirdPointIsFound = true;
                    }
                }

                if (!thirdPointIsFound)
                {
                    // failed to find 3rd edge point, which is away enough from the temp point.
                    // this means that the clound looks more like triangle
                    corners.Add(tempPoint);
                }
                else
                {
                    corners.Add(point3);

                    // try to find 4th point
                    float tempDistance;

                    PointsCloud.GetFurthestPointsFromLine(cloud, point1, point3,
                                                          out tempPoint, out tempDistance, out point4, out distance4);

                    if ((distance4 >= distortionLimit) && (tempDistance >= distortionLimit))
                    {
                        if (tempPoint.DistanceTo(point2) > point4.DistanceTo(point2))
                        {
                            point4 = tempPoint;
                        }
                    }
                    else
                    {
                        PointsCloud.GetFurthestPointsFromLine(cloud, point2, point3,
                                                              out tempPoint, out tempDistance, out point4, out distance4);

                        if ((tempPoint.DistanceTo(point1) > point4.DistanceTo(point1)) &&
                            (tempPoint != point2) && (tempPoint != point3))
                        {
                            point4 = tempPoint;
                        }
                    }

                    if ((point4 != point1) && (point4 != point2) && (point4 != point3))
                    {
                        corners.Add(point4);
                    }
                }
            }

            // put the point with lowest X as the first
            for (int i = 1, n = corners.Count; i < n; i++)
            {
                if ((corners[i].X < corners[0].X) ||
                    ((corners[i].X == corners[0].X) && (corners[i].Y < corners[0].Y)))
                {
                    var temp = corners[i];
                    corners[i] = corners[0];
                    corners[0] = temp;
                }
            }


            // sort other points in counter clockwise order
            var k1 = (corners[1].X != corners[0].X) ?
                     ((float)(corners[1].Y - corners[0].Y) / (corners[1].X - corners[0].X)) :
                     ((corners[1].Y > corners[0].Y) ? float.PositiveInfinity : float.NegativeInfinity);

            var k2 = (corners[2].X != corners[0].X) ?
                     ((float)(corners[2].Y - corners[0].Y) / (corners[2].X - corners[0].X)) :
                     ((corners[2].Y > corners[0].Y) ? float.PositiveInfinity : float.NegativeInfinity);

            if (k2 < k1)
            {
                var temp = corners[1];
                corners[1] = corners[2];
                corners[2] = temp;

                var tk = k1;
                k1 = k2;
                k2 = tk;
            }

            if (corners.Count == 4)
            {
                var k3 = (corners[3].X != corners[0].X) ?
                         ((float)(corners[3].Y - corners[0].Y) / (corners[3].X - corners[0].X)) :
                         ((corners[3].Y > corners[0].Y) ? float.PositiveInfinity : float.NegativeInfinity);

                if (k3 < k1)
                {
                    var temp = corners[1];
                    corners[1] = corners[3];
                    corners[3] = temp;

                    var tk = k1;
                    k1 = k3;
                    k3 = tk;
                }
                if (k3 < k2)
                {
                    var temp = corners[2];
                    corners[2] = corners[3];
                    corners[3] = temp;

                    var tk = k2;
                    k2 = k3;
                    k3 = tk;
                }
            }

            return(corners);
        }