public static Polygon Create(IPointCloud pointCloud, double searchRange, int kNearestCount) { var result = new Polygon(); var currPoint = pointCloud.QuadTree.GetLowestYPoint(); result.Points.Add(currPoint); //Uno a sinistra così può calcolare l'angolo in modo uniforme var prevPoint = new DblPoint2(currPoint.x - 1, currPoint.y); while (true) { var nextPoint = GetNextPoint(pointCloud, result, prevPoint, currPoint, result.Points.Count < 3 ? result.Points : result.Points.Skip(1), searchRange, kNearestCount); if (nextPoint == result.Points[0]) break; result.Points.Add(nextPoint); prevPoint = currPoint; currPoint = nextPoint; } return result; }
private static DblPoint2 GetNextPoint(IPointCloud pointCloud, Polygon partialResult, DblPoint2 prevPoint, DblPoint2 currPoint, IEnumerable<DblPoint2> excludedPoints, double searchRange, int kNearestCount) { while (true) { var kNearest = new List<DblPoint2>(); var actualkNearestCount = kNearestCount; while (true) { pointCloud.QuadTree.GetPointsInsideCircle(currPoint, 1000000.0, kNearest); kNearest.RemoveAll((x) => excludedPoints.Contains(x)); if (kNearest.Count < actualkNearestCount && kNearest.Count != (pointCloud.Points.Count() - excludedPoints.Count())) { actualkNearestCount++; kNearest.Clear(); } else if (kNearest.Count > 3) { kNearest = (from k in kNearest orderby (k - currPoint).Length2 ascending select k).Take(actualkNearestCount).ToList(); break; } else break; } var kNearestOrderedByAngle = (from k in kNearest orderby (prevPoint - currPoint).CWAngleTo(k - currPoint) descending select k).ToList(); //Rimuovi tutti quelli che intersecano il poligono corrente var kNearestOrderedByAngleNotIntersecting = (from k in kNearestOrderedByAngle where !IntersectAnyPolygonEdgeExceptLast(partialResult, currPoint, k) select k).ToList(); if (kNearestOrderedByAngleNotIntersecting.Count > 0) return kNearestOrderedByAngleNotIntersecting.First(); } }
private static Boolean IntersectAnyPolygonEdgeExceptLast(Polygon polygon, DblPoint2 p1, DblPoint2 p2) { var s12 = new Segment(p1, p2); for (var i = 0; i < polygon.Points.Count - 1; i++) { var result = new Segment(polygon.Points[i], polygon.Points[i + 1]).Intersect(s12); if (result.IsIntersection) return true; } return false; }