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)); }
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); }
/// <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); }
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); }
/// <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); }