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