IEnumerable <Point> Calculate() { if (pivot.Y == Double.MaxValue) { return(new Point[0]); } if (hullPoints.Length == 0) { return new[] { pivot } } ; SortAllPointsWithoutPivot(); Scan(); return(EnumerateStack()); } IEnumerable <Point> EnumerateStack() { HullStack stackCell = stack; while (stackCell != null) { yield return(stackCell.Point); stackCell = stackCell.Next; } } void Scan() { int i = 0; while (hullPoints[i].Deleted) { i++; } stack = new HullStack(pivot); Push(i++); if (i < hullPoints.Length) { if (!hullPoints[i].Deleted) { Push(i++); } else { i++; } } while (i < hullPoints.Length) { if (!hullPoints[i].Deleted) { if (LeftTurn(i)) { Push(i++); } else { Pop(); } } else { i++; } } //cleanup the end while (StackHasMoreThanTwoPoints() && !LeftTurnToPivot()) { Pop(); } } bool LeftTurnToPivot() { return(Point.GetTriangleOrientation(StackSecondPoint, StackTopPoint, pivot) == TriangleOrientation.Counterclockwise); } bool StackHasMoreThanTwoPoints() { return(stack.Next != null && stack.Next.Next != null); } void Pop() { stack = stack.Next; } bool LeftTurn(int i) { if (stack.Next == null) { return(true); //there is only one point in the stack } var orientation = Point.GetTriangleOrientationWithIntersectionEpsilon(StackSecondPoint, StackTopPoint, hullPoints[i].Point); if (orientation == TriangleOrientation.Counterclockwise) { return(true); } if (orientation == TriangleOrientation.Clockwise) { return(false); } return(BackSwitchOverPivot(hullPoints[i].Point)); } bool BackSwitchOverPivot(Point point) { //we know here that there at least two points in the stack but it has to be exaclty two if (stack.Next.Next != null) { return(false); } Debug.Assert(StackSecondPoint == pivot); return(StackTopPoint.X > pivot.X + ApproximateComparer.DistanceEpsilon && point.X < pivot.X - ApproximateComparer.DistanceEpsilon); } void Push(int p) { var t = new HullStack(hullPoints[p].Point) { Next = stack }; stack = t; } void SortAllPointsWithoutPivot() { comparer = new HullPointComparer(pivot); Array.Sort(hullPoints, comparer); // if (true) { // var list = new List<DebugCurve>(); // var d = 3.0; // list.Add(new DebugCurve(100, 0.001, "magenta", El(ref d, pivot))); // foreach (var hullPoint in hullPoints) { // list.Add(new DebugCurve(100,0.001, hullPoint.Deleted ? "blue" : "green", El(ref d, hullPoint.Point))); // } // LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(list); // } }
void Push(int p) { var t = new HullStack(hullPoints[p].Point) {Next = stack}; stack = t; }
void Scan() { int i = 0; while (hullPoints[i].Deleted) i++; stack = new HullStack(pivot); Push(i++); if (i < hullPoints.Length) { if (!hullPoints[i].Deleted) Push(i++); else i++; } while (i < hullPoints.Length) { if (!hullPoints[i].Deleted) { if (LeftTurn(i)) Push(i++); else Pop(); } else i++; } //cleanup the end while (StackHasMoreThanTwoPoints() && !LeftTurnToPivot()) Pop(); }
void Pop() { stack = stack.Next; }