예제 #1
0
            public int CompareTo(object obj)
            {
                PointToProcess another = (PointToProcess)obj;

                return((K < another.K) ? -1 : (K > another.K) ? 1 :
                       ((Distance > another.Distance) ? -1 : (Distance < another.Distance) ? 1 : 0));
            }
예제 #2
0
            public int CompareTo(object obj)
            {
                PointToProcess pointToProcess = (PointToProcess)obj;

                if (!(K < pointToProcess.K))
                {
                    if (!(K > pointToProcess.K))
                    {
                        if (!(Distance > pointToProcess.Distance))
                        {
                            if (!(Distance < pointToProcess.Distance))
                            {
                                return(0);
                            }
                            return(1);
                        }
                        return(-1);
                    }
                    return(1);
                }
                return(-1);
            }
예제 #3
0
        /// <summary>
        /// Find convex hull for the given set of points.
        /// </summary>
        ///
        /// <param name="points">Set of points to search convex hull for.</param>
        ///
        /// <returns>Returns set of points, which form a convex hull for the given <paramref name="points"/>.
        /// 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). Points are provided in counter clockwise order
        /// (<a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian
        /// coordinate system</a>).</returns>
        ///
        public IEnumerable <Point> FindHull(IEnumerable <Point> points)
        {
            var            pointsToProcess  = new List <PointToProcess>();
            int            firstCornerIndex = 0;
            PointToProcess firstCorner      = null;
            int            fi           = 0;
            var            firstPoint   = new Point();
            bool           newPoly      = true;
            int            polygonCount = 0;

            foreach (var point in points)
            {
                // convert input points to points
                var pp = new PointToProcess(point);
                pointsToProcess.Add(pp);

                if (newPoly)
                {
                    firstPoint = point;
                    newPoly    = false;
                }
                else
                {
                    if (point == firstPoint)
                    {
                        polygonCount++;
                        newPoly = true;
                    }
                }
                // find a point, with lowest X and lowest Y
                if ((firstCorner == null) ||
                    (pp.X < firstCorner.X) ||
                    ((pp.X == firstCorner.X) && (pp.Y < firstCorner.Y)))
                {
                    firstCorner      = pp;
                    firstCornerIndex = fi;
                }
                fi++;
            }

            if (pointsToProcess.Count == 0)
            {
                return(points);
            }

            // thats not true! a convexhull can be different from the polyon!
            //if (polygonCount <= 0)
            //    return points;

            // remove the just found point
            pointsToProcess.RemoveAt(firstCornerIndex);

            // find K (tangent of line's angle) and distance to the first corner
            foreach (var point in pointsToProcess)
            {
                var dx = point.X - firstCorner.X;
                var dy = point.Y - firstCorner.Y;

                // don't need square root, since it is not important in our case
                point.Distance = dx * dx + dy * dy;
                // tangent of lines angle
                point.K = (dx == 0) ? double.PositiveInfinity : (double)dy / dx;
            }

            // sort point by angle and distance
            pointsToProcess.Sort();

            var convexHullTemp = new List <PointToProcess>();

            // add first corner, which is always on the hull
            convexHullTemp.Add(firstCorner);
            // add another point, which forms a line with lowest slope
            convexHullTemp.Add(pointsToProcess[0]);
            pointsToProcess.RemoveAt(0); //Lytico: error here: was: points.removeat(0);

            var lastPoint = convexHullTemp[1];
            var prevPoint = convexHullTemp[0];

            while (pointsToProcess.Count != 0)
            {
                PointToProcess newPoint = pointsToProcess[0];

                // skip any point, which has the same slope as the last one
                if (newPoint.K == lastPoint.K)
                {
                    pointsToProcess.RemoveAt(0);
                    continue;
                }

                // check if current point is on the left side from two last points
                if ((newPoint.X - prevPoint.X) * (lastPoint.Y - newPoint.Y) - (lastPoint.X - newPoint.X) * (newPoint.Y - prevPoint.Y) < 0)
                {
                    // add the point to the hull
                    convexHullTemp.Add(newPoint);
                    // and remove it from the list of points to process
                    pointsToProcess.RemoveAt(0);

                    prevPoint = lastPoint;
                    lastPoint = newPoint;
                }
                else
                {
                    // remove the last point from the hull
                    convexHullTemp.RemoveAt(convexHullTemp.Count - 1);

                    lastPoint = prevPoint;
                    prevPoint = convexHullTemp[convexHullTemp.Count - 2];
                }
            }

            // convert points back
            var convexHull = new List <Point>(convexHullTemp.Count);

            foreach (PointToProcess pt in convexHullTemp)
            {
                convexHull.Add(new Point(pt.X, pt.Y));
            }

            return(convexHull);
            //convexHullTemp.Select<PointToProcess,PointD>(pt=>pt.ToPoint());
        }
        public static List <Point> FindHull(List <Point> points)
        {
            List <PointToProcess> pointsToProcess = new List <PointToProcess>();

            // convert input points to points we can process
            foreach (Point point in points)
            {
                pointsToProcess.Add(new PointToProcess(point));
            }

            // find a point, with lowest X and lowest Y
            int            firstCornerIndex = 0;
            PointToProcess firstCorner      = pointsToProcess[0];

            for (int i = 1, n = pointsToProcess.Count; i < n; i++)
            {
                if ((pointsToProcess[i].X < firstCorner.X) ||
                    ((pointsToProcess[i].X == firstCorner.X) && (pointsToProcess[i].Y < firstCorner.Y)))
                {
                    firstCorner      = pointsToProcess[i];
                    firstCornerIndex = i;
                }
            }

            // remove the just found point
            pointsToProcess.RemoveAt(firstCornerIndex);

            // find K (tangent of line's angle) and distance to the first corner
            for (int i = 0, n = pointsToProcess.Count; i < n; i++)
            {
                double dx = pointsToProcess[i].X - firstCorner.X;
                double dy = pointsToProcess[i].Y - firstCorner.Y;

                // don't need square root, since it is not important in our case
                pointsToProcess[i].Distance = dx * dx + dy * dy;
                // tangent of lines angle
                pointsToProcess[i].K = (dx == 0) ? float.PositiveInfinity : (float)dy / dx;
            }

            // sort points by angle and distance
            pointsToProcess.Sort();

            List <PointToProcess> convexHullTemp = new List <PointToProcess>();

            // add first corner, which is always on the hull
            convexHullTemp.Add(firstCorner);
            // add another point, which forms a line with lowest slope
            convexHullTemp.Add(pointsToProcess[0]);
            points.RemoveAt(0);

            PointToProcess lastPoint = convexHullTemp[1];
            PointToProcess prevPoint = convexHullTemp[0];

            while (pointsToProcess.Count != 0)
            {
                PointToProcess newPoint = pointsToProcess[0];

                // skip any point, which has the same slope as the last one or
                // has 0 distance to the first point
                if ((newPoint.K == lastPoint.K) || (newPoint.Distance == 0))
                {
                    pointsToProcess.RemoveAt(0);
                    continue;
                }

                // check if current point is on the left side from two last points
                if ((newPoint.X - prevPoint.X) * (lastPoint.Y - newPoint.Y) - (lastPoint.X - newPoint.X) * (newPoint.Y - prevPoint.Y) < 0)
                {
                    // add the point to the hull
                    convexHullTemp.Add(newPoint);
                    // and remove it from the list of points to process
                    pointsToProcess.RemoveAt(0);

                    prevPoint = lastPoint;
                    lastPoint = newPoint;
                }
                else
                {
                    // remove the last point from the hull
                    convexHullTemp.RemoveAt(convexHullTemp.Count - 1);

                    lastPoint = prevPoint;
                    prevPoint = convexHullTemp[convexHullTemp.Count - 2];
                }
            }

            // convert points back
            List <Point> convexHull = new List <Point>();

            foreach (PointToProcess pt in convexHullTemp)
            {
                convexHull.Add(pt.ToPoint());
            }

            return(convexHull);
        }
예제 #5
0
        public List <IntPoint> FindHull(List <IntPoint> points)
        {
            if (points.Count <= 3)
            {
                return(new List <IntPoint>(points));
            }
            List <PointToProcess> list = new List <PointToProcess>();

            foreach (IntPoint point in points)
            {
                list.Add(new PointToProcess(point));
            }
            int            index          = 0;
            PointToProcess pointToProcess = list[0];
            int            i = 1;

            for (int count = list.Count; i < count; i++)
            {
                if (list[i].X < pointToProcess.X || (list[i].X == pointToProcess.X && list[i].Y < pointToProcess.Y))
                {
                    pointToProcess = list[i];
                    index          = i;
                }
            }
            list.RemoveAt(index);
            int j = 0;

            for (int count2 = list.Count; j < count2; j++)
            {
                int num  = list[j].X - pointToProcess.X;
                int num2 = list[j].Y - pointToProcess.Y;
                list[j].Distance = num * num + num2 * num2;
                list[j].K        = ((num == 0) ? float.PositiveInfinity : ((float)num2 / (float)num));
            }
            list.Sort();
            List <PointToProcess> list2 = new List <PointToProcess>();

            list2.Add(pointToProcess);
            list2.Add(list[0]);
            list.RemoveAt(0);
            PointToProcess pointToProcess2 = list2[1];
            PointToProcess pointToProcess3 = list2[0];

            while (list.Count != 0)
            {
                PointToProcess pointToProcess4 = list[0];
                if (pointToProcess4.K == pointToProcess2.K || pointToProcess4.Distance == 0f)
                {
                    list.RemoveAt(0);
                }
                else if ((pointToProcess4.X - pointToProcess3.X) * (pointToProcess2.Y - pointToProcess4.Y) - (pointToProcess2.X - pointToProcess4.X) * (pointToProcess4.Y - pointToProcess3.Y) < 0)
                {
                    list2.Add(pointToProcess4);
                    list.RemoveAt(0);
                    pointToProcess3 = pointToProcess2;
                    pointToProcess2 = pointToProcess4;
                }
                else
                {
                    list2.RemoveAt(list2.Count - 1);
                    pointToProcess2 = pointToProcess3;
                    pointToProcess3 = list2[list2.Count - 2];
                }
            }
            List <IntPoint> list3 = new List <IntPoint>();

            foreach (PointToProcess item in list2)
            {
                list3.Add(item.ToPoint());
            }
            return(list3);
        }
예제 #6
0
        /// <summary>
        /// Find convex hull for the given set of points.
        /// </summary>
        ///
        /// <param name="points">Set of points to search convex hull for.</param>
        ///
        /// <returns>Returns set of points, which form a convex hull for the given <paramref name="points"/>.
        /// 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). Points are provided in counter clockwise order
        /// (<a href="http://en.wikipedia.org/wiki/Cartesian_coordinate_system">Cartesian
        /// coordinate system</a>).</returns>
        ///
        public List <IntPoint> FindHull(List <IntPoint> points)
        {
            // do nothing if there 3 points or less
            if (points.Count <= 3)
            {
                return(new List <IntPoint>(points));
            }

            // find a point, with lowest X and lowest Y
            int      firstCornerIndex = 0;
            IntPoint pointFirstCorner = points[0];

            for (int i = 1, n = points.Count; i < n; i++)
            {
                if ((points[i].X < pointFirstCorner.X) ||
                    ((points[i].X == pointFirstCorner.X) && (points[i].Y < pointFirstCorner.Y)))
                {
                    pointFirstCorner = points[i];
                    firstCornerIndex = i;
                }
            }

            // convert input points to points we can process
            PointToProcess firstCorner = new PointToProcess(pointFirstCorner);

            // Points to process must exclude the first corner that we've already found
            PointToProcess[] arrPointsToProcess = new PointToProcess[points.Count - 1];
            for (int i = 0; i < points.Count - 1; i++)
            {
                IntPoint point = points[i >= firstCornerIndex ? i + 1 : i];
                arrPointsToProcess[i] = new PointToProcess(point);
            }

            // find K (tangent of line's angle) and distance to the first corner
            for (int i = 0, n = arrPointsToProcess.Length; i < n; i++)
            {
                int dx = arrPointsToProcess[i].X - firstCorner.X;
                int dy = arrPointsToProcess[i].Y - firstCorner.Y;

                // don't need square root, since it is not important in our case
                arrPointsToProcess[i].Distance = dx * dx + dy * dy;
                // tangent of lines angle
                arrPointsToProcess[i].K = (dx == 0) ? float.PositiveInfinity : (float)dy / dx;
            }

            // sort points by angle and distance
            Array.Sort(arrPointsToProcess);

            // Convert points to process to a queue. Continually removing the first item of an array list
            //  is highly inefficient
            Queue <PointToProcess> queuePointsToProcess = new Queue <PointToProcess>(arrPointsToProcess);

            LinkedList <PointToProcess> convexHullTemp = new LinkedList <PointToProcess>();

            // add first corner, which is always on the hull
            PointToProcess prevPoint = convexHullTemp.AddLast(firstCorner).Value;
            // add another point, which forms a line with lowest slope
            PointToProcess lastPoint = convexHullTemp.AddLast(queuePointsToProcess.Dequeue()).Value;

            while (queuePointsToProcess.Count != 0)
            {
                PointToProcess newPoint = queuePointsToProcess.Peek();

                // skip any point, which has the same slope as the last one or
                // has 0 distance to the first point
                if ((newPoint.K == lastPoint.K) || (newPoint.Distance == 0))
                {
                    queuePointsToProcess.Dequeue();
                    continue;
                }

                // check if current point is on the left side from two last points
                if ((newPoint.X - prevPoint.X) * (lastPoint.Y - newPoint.Y) - (lastPoint.X - newPoint.X) * (newPoint.Y - prevPoint.Y) < 0)
                {
                    // add the point to the hull
                    convexHullTemp.AddLast(newPoint);
                    // and remove it from the list of points to process
                    queuePointsToProcess.Dequeue();

                    prevPoint = lastPoint;
                    lastPoint = newPoint;
                }
                else
                {
                    // remove the last point from the hull
                    convexHullTemp.RemoveLast();

                    lastPoint = prevPoint;
                    prevPoint = convexHullTemp.Last.Previous.Value;
                }
            }

            // convert points back
            List <IntPoint> convexHull = new List <IntPoint>();

            foreach (PointToProcess pt in convexHullTemp)
            {
                convexHull.Add(pt.ToPoint());
            }

            return(convexHull);
        }