C#計算凸包的點的方法
阿新 • • 發佈:2018-11-06
參考資料:
https://download.csdn.net/download/u010991835/10223982
http://www.cnblogs.com/HolyChen/p/5982184.html
傳進來點集,輸出凸包的點集:
#region 計算點的凸包,並返回凸包的點集 public static List<XYZ> GetConvexHullPoints(List<XYZ> points) { List<Segment> segments = new List<Segment>(); segments = GetAllSegments(points); List<XYZ> ProcessingPoints = new List<XYZ>(); int i = 0; int j = 0; for (i = 0; i < segments.Count; ) { //ProcessingPoints will be the points that are not in the current segment ProcessingPoints = new List<XYZ>(points); for (j = 0; j < ProcessingPoints.Count; ) { if (segments[i].contains(ProcessingPoints[j])) { ProcessingPoints.Remove(ProcessingPoints[j]); j = 0; continue; } j++; } if (!isEdge(ProcessingPoints, segments[i])) { segments.Remove(segments[i]); i = 0; continue; } else { i++; } } return segments.Select(x => x.p).ToList(); } private static bool isEdge(List<XYZ> processingPoints, Segment edge) { for (int k = 0; k < processingPoints.Count; k++) { if (IsLeft(edge, processingPoints[k])) { return false; } } return true; } private static bool IsLeft(Segment segment, XYZ r) { double D = 0; double px, py, qx, qy, rx, ry = 0; //The determinant // | 1 px py | // | 1 qx qy | // | 1 rx ry | //if the determinant result is positive then the point is left of the segment px = segment.p.X; py = segment.p.Y; qx = segment.q.X; qy = segment.q.Y; rx = r.X; ry = r.Y; D = ((qx * ry) - (qy * rx)) - (px * (ry - qy)) + (py * (rx - qx)); if (D <= 0) return false; return true; } private static List<Segment> GetAllSegments(List<XYZ> points) { List<Segment> segments = new List<Segment>(); //Initialize all possible segments from the picked points for (int i = 0; i < points.Count; i++) { for (int j = 0; j < points.Count; j++) { if (i != j) { Segment op = new Segment(); XYZ p1 = points[i]; XYZ p2 = points[j]; op.p = p1; op.q = p2; segments.Add(op); } } } return segments; } public struct Segment { public XYZ p; public XYZ q; public bool contains(XYZ point) { if (p.IsAlmostEqualTo(point) || q.IsAlmostEqualTo(point)) return true; return false; } } #endregion
進一步改進演算法,這裡的segement點不是按照順序連起來的,那麼需要讓點按照順序串聯起來需要進一步判斷。
public static List<XYZ> GetConvexHullPoints(List<XYZ> points) { List<Segment> segments = new List<Segment>(); segments = GetAllSegments(points); List<XYZ> ProcessingPoints = new List<XYZ>(); int i = 0; int j = 0; for (i = 0; i < segments.Count; ) { //ProcessingPoints will be the points that are not in the current segment ProcessingPoints = new List<XYZ>(points); for (j = 0; j < ProcessingPoints.Count; ) { if (segments[i].contains(ProcessingPoints[j])) { ProcessingPoints.Remove(ProcessingPoints[j]); j = 0; continue; } j++; } if (!isEdge(ProcessingPoints, segments[i])) { segments.Remove(segments[i]); i = 0; continue; } else { i++; } } List<XYZ> xyzList = new List<XYZ>(); xyzList.Add(segments[0].StartPoint); xyzList.Add(segments[0].EndPoint); segments.RemoveAt(0); while(segments.Count!=0) { bool hasContinuePoint = false; for (int ii=0;ii<segments.Count;ii++) { if (xyzList.Last().IsAlmostEqualTo(segments[ii].StartPoint)) { xyzList.Add(segments[ii].EndPoint); hasContinuePoint = true; segments.RemoveAt(ii); break; } if (hasContinuePoint == false && xyzList.Last().IsAlmostEqualTo(segments[ii].EndPoint)) { xyzList.Add(segments[ii].StartPoint); segments.RemoveAt(ii); break; } } } return xyzList; }