/// <summary>
        /// Scans the vertices on the polygon until either an advance or retard step can be made.
        /// Used when iterating over a section of the polygon not visible from z.
        /// </summary>
        /// <param name="v"></param>
        /// <param name="s"></param>
        /// <param name="iprev"></param>
        /// <param name="windowEnd"></param>
        /// <param name="ccw"></param>
        /// <returns> </returns>
        public static NextCall Scan(ref VsRep v, ref Stack <VertDispl> s, ref int i, ref VertDispl windowEnd, ref bool ccw)
        {
            while (i < v.n)
            {
                i++;

                if (ccw &&        // CounterClockWise
                    MathUtil.GreaterEps(v.Get(i + 1).alpha, s.Peek().alpha) &&
                    MathUtil.GEQEps(s.Peek().alpha, v.Get(i).alpha))
                {
                    VertDispl intersec = IntersectWithWindow(v.Get(i), v.Get(i + 1), s.Peek(), windowEnd);

                    if (intersec != null && !(windowEnd != null && MathUtil.EqualsEps(intersec.p.Cartesian, windowEnd.p.Cartesian)))
                    {
                        s.Push(intersec);
                        return(NextCall.ADVANCE);
                    }
                }
                else if (!ccw &&        // ClockWise
                         MathUtil.LEQEps(v.Get(i + 1).alpha, s.Peek().alpha) &&
                         s.Peek().alpha < v.Get(i).alpha)
                {
                    if (IntersectWithWindow(v.Get(i), v.Get(i + 1), s.Peek(), windowEnd) != null)
                    {
                        return(NextCall.RETARD);
                    }
                }
            }

            return(NextCall.STOP);
        }
        /// <summary>
        /// Pushes a new vertex on the stack and calls the appropriated function
        /// (advance, retard, scan) depending on the next vertex on the polygon.
        /// </summary>
        /// <param name="v"></param>
        /// <param name="s"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        public static NextCall Advance(ref VsRep v, ref Stack <VertDispl> s, ref int i, ref VertDispl w, ref bool ccw)
        {
            var n = v.n - 1;

            Debug.Assert(i + 1 <= n);

            if (MathUtil.LEQEps(v.Get(i + 1).alpha, MathUtil.PI2))
            {
                i++;
                s.Push(v.Get(i));

                // TODO check order of returned list
                if (i == n)
                {
                    return(NextCall.STOP);
                }

                if (MathUtil.LessEps(v.Get(i + 1).alpha, v.Get(i).alpha) &&
                    MathUtil.Orient2D(v.Get(i - 1).p.Cartesian, v.Get(i).p.Cartesian,
                                      v.Get(i + 1).p.Cartesian) < 0)
                { // -1 is RightTurn
                    w   = null;
                    ccw = true;
                    return(NextCall.SCAN);
                }
                else if (MathUtil.LessEps(v.Get(i + 1).alpha, v.Get(i).alpha) &&
                         MathUtil.Orient2D(v.Get(i - 1).p.Cartesian, v.Get(i).p.Cartesian,
                                           v.Get(i + 1).p.Cartesian) > 0)
                { // 1 is LeftTurn
                    return(NextCall.RETARD);
                }
                else
                {
                    return(NextCall.ADVANCE);
                }
            }
            else
            {
                var v0 = v.Get(0);

                if (MathUtil.LEQEps(s.Peek().alpha, MathUtil.PI2))
                {
                    var isect = (new LineSegment(v.Get(i).p.Cartesian, v.Get(i + 1).p.Cartesian)).Intersect(v0.p.Ray);

                    Debug.Assert(isect != null);

                    var st = DisplacementInBetween(new PolarPoint2D(isect.Value), v.Get(i), v.Get(i + 1));
                    s.Push(st);
                }

                w   = v0;
                ccw = false;
                return(NextCall.SCAN);
            }
        }
        /// <summary>
        /// Transforms the vertices on the stack to the final visibility polygon.
        /// Reverses the pre-process steps, namely the translation and rotation.
        /// Also removes one of endpoints if duplicate
        /// </summary>
        /// <param name="pre_s"></param>
        /// <param name="vs"></param>
        /// <param name="z"></param>
        /// <param name="initAngle"></param>
        /// <returns> Final visibility polygon. </returns>
        private static Polygon2D Postprocess(List <VertDispl> pre_s, VsRep vs, Vector2 z, double initAngle)
        {
            // reverse order of stack to establish CCW order of final visibility polygon
            pre_s.Reverse();

            if (vs.zIsVertex)
            {
                pre_s.Add(new VertDispl(new PolarPoint2D(Vector2.zero), 0));
            }

            // convert VertDispl to PolarPoint2D
            var rotatedPol = pre_s.Select(v => v.p).ToList();

            // rotates points back to original position before the rotation in preprocess()
            foreach (var curr in rotatedPol)
            {
                curr.RotateClockWise(-initAngle);
            }

            // convert PolarPoint2D to Vector2
            // shifts points back to their position before the shift in preprocess()
            var shiftedPol = rotatedPol.Select(v => v.Cartesian + z).ToList();

            Debug.Assert(shiftedPol.Count > 0);

            // check if first and last vertex are the same
            if (shiftedPol.Count > 1 &&
                MathUtil.EqualsEps(shiftedPol.FirstOrDefault(), shiftedPol.LastOrDefault(), MathUtil.EPS * 10))
            {
                shiftedPol.RemoveAt(shiftedPol.Count - 1);
            }

            // check if first point is colinear with last and second
            if (shiftedPol.Count > 2 &&
                Line.Colinear(shiftedPol.LastOrDefault(), shiftedPol.FirstOrDefault(), shiftedPol.ElementAt(1)))
            {
                shiftedPol.RemoveAt(0);
            }

            // make polygon clockwise
            // to conform to clockwise standard in project
            shiftedPol.Reverse();

            return(new Polygon2D(shiftedPol));
        }
        /// <summary>
        /// Pops all vertices from the stack that have become invisible after the addition
        /// of a new vertex.
        /// Calls appropriate method (advance, scan, retard) after being done based on next vertex.
        /// </summary>
        /// <param name="v"></param>
        /// <param name="sOld"></param>
        /// <param name="iprev"></param>
        /// <returns></returns>
        public static NextCall Retard(ref VsRep v, ref Stack <VertDispl> s, ref int i, ref VertDispl w, ref bool ccw)
        {
            // LocateSj will pop vertices from the stack
            // until appropriated s_j is found
            // see paper
            var sjNext = LocateSj(v.Get(i), v.Get(i + 1), s);

            if (s.Count == 0)
            {
                return(NextCall.STOP);
            }

            var sj = s.Peek();

            if (sj.alpha < v.Get(i + 1).alpha)
            {
                i++;

                var vi = v.Get(i);
                var p  = (new LineSegment(sj.p.Cartesian, sjNext.p.Cartesian)).Intersect(vi.p.Ray);

                // fallback method, return point closest to intersection with segment line
                if (p == null)
                {
                    var line = new Line(vi.p.Ray.origin, vi.p.Ray.origin + vi.p.Ray.direction);
                    p = (new LineSegment(sj.p.Cartesian, sjNext.p.Cartesian)).Line.Intersect(line);
                    p = Vector2.Distance(p.Value, sj.p.Cartesian) < Vector2.Distance(p.Value, sjNext.p.Cartesian)
                        ? sj.p.Cartesian : sjNext.p.Cartesian;
                }

                var st1 = DisplacementInBetween(new PolarPoint2D(p.Value), sj, sjNext);

                if (st1 != null)
                {
                    s.Push(st1);
                }

                s.Push(vi);

                // paper does i == v.n
                if (i == v.n - 1)
                {
                    // TODO order of returned list correct? (check stack to list conversion)
                    return(NextCall.STOP);
                }
                else if (MathUtil.GEQEps(v.Get(i + 1).alpha, vi.alpha) &&
                         MathUtil.Orient2D(v.Get(i - 1).p.Cartesian, vi.p.Cartesian, v.Get(i + 1).p.Cartesian) <= 0)
                { // -1 is RighTurn
                    return(NextCall.ADVANCE);
                }
                else if (MathUtil.GreaterEps(v.Get(i + 1).alpha, vi.alpha) &&
                         MathUtil.Orient2D(v.Get(i - 1).p.Cartesian, vi.p.Cartesian, v.Get(i + 1).p.Cartesian) > 0)
                {  // 1 is LeftTurn
                    s.Pop();
                    w   = vi;
                    ccw = false;
                    return(NextCall.SCAN);
                }
                else
                {
                    s.Pop();
                    return(NextCall.RETARD);
                }
            }
            else
            {
                if (MathUtil.EqualsEps(v.Get(i + 1).alpha, sj.alpha) &&
                    MathUtil.GreaterEps(v.Get(i + 2).alpha, v.Get(i + 1).alpha) &&
                    MathUtil.Orient2D(v.Get(i).p.Cartesian, v.Get(i + 1).p.Cartesian, v.Get(i + 2).p.Cartesian) <= 0)
                {  // -1 is RightTurn
                    s.Push(v.Get(i + 1));
                    return(NextCall.ADVANCE);
                }
                else
                {
                    w   = IntersectWithWindow(v.Get(i), v.Get(i + 1), sj, sjNext);
                    ccw = true;

                    if (w == null)
                    {
                        var seg = new LineSegment(v.Get(i).p, v.Get(i + 1).p);
                        var res = seg.ClosestPoint(sj.p.Cartesian);
                        w = DisplacementInBetween(new PolarPoint2D(res), v.Get(i), v.Get(i + 1));
                    }

                    return(NextCall.SCAN);
                }
            }
        }