void CloseConesAtRightVertex(VertexEvent rightVertexEvent,
                                     PolylinePoint nextVertex)
        {
            Point  prevSite = rightVertexEvent.Vertex.NextOnPolyline.Point;
            double prevZ    = prevSite * SweepDirection;

            if (prevZ <= Z && Z - prevZ < ApproximateComparer.DistanceEpsilon)
            {
                RemoveConesClosedBySegment(prevSite, rightVertexEvent.Vertex.Point);
            }

            Point site     = rightVertexEvent.Site;
            Point coneLp   = site + ConeLeftSideDirection;
            Point coneRp   = site + ConeRightSideDirection;
            Point nextSite = nextVertex.Point;

            //SugiyamaLayoutSettings.Show(new LineSegment(site, coneLP), new LineSegment(site, coneRP), new LineSegment(site, nextSite));
            //try to remove the right side
            if ((site - prevSite) * SweepDirection > ApproximateComparer.DistanceEpsilon)
            {
                RemoveRightSide(new RightObstacleSide(rightVertexEvent.Vertex.NextOnPolyline));
            }
            if (GetZ(nextSite) + ApproximateComparer.DistanceEpsilon < GetZ(rightVertexEvent))
            {
                return;
            }
            if (!Point.PointToTheRightOfLineOrOnLine(nextSite, site, coneLp))
            {
                //if (angle <= -coneAngle / 2) {
                //   CreateConeOnVertex(rightVertexEvent);
                if (Point.PointToTheLeftOfLineOrOnLine(nextSite + DirectionPerp, nextSite, site))
                {
                    EnqueueEvent(new RightVertexEvent(nextVertex));
                }
                //  TryEnqueueRighVertexEvent(nextVertex);
            }
            else if (Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneRp))
            {
                //if (angle < coneAngle / 2) {
                CaseToTheLeftOfLineOrOnLineConeRp(rightVertexEvent, nextVertex);
            }
            else
            {
                if ((nextSite - site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                {
                    LookForIntersectionOfObstacleSideAndLeftConeSide(rightVertexEvent.Site, nextVertex);
                    InsertRightSide(new RightObstacleSide(rightVertexEvent.Vertex));
                }
                EnqueueEvent(new RightVertexEvent(nextVertex));
            }
        }
        void CaseToTheLeftOfLineOrOnLineConeRp(VertexEvent rightVertexEvent, PolylinePoint nextVertex)
        {
            EnqueueEvent(new RightVertexEvent(nextVertex));
            //the obstacle side is inside of the cone
            //we need to create an obstacle left side segment instead of the left cone side
            //                var cone = new Cone(rightVertexEvent.Vertex.Point, this);
            //                var obstacleSideSeg = new BrokenConeSide(cone.Apex, nextVertex, new ConeLeftSide(cone));
            //                cone.LeftSide = obstacleSideSeg;
            //                cone.RightSide = new ConeRightSide(cone);
            //                var rnode = InsertToTree(rightConeSides, cone.RightSide);
            //                LookForIntersectionWithConeRightSide(rnode);
            RBNode <ConeSide> lnode =
                leftConeSides.FindFirst(side => PointIsToTheLeftOfSegment(rightVertexEvent.Site, side));

            FixConeLeftSideIntersections(rightVertexEvent.Vertex, nextVertex, lnode);
            if ((nextVertex.Point - rightVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
            {
                InsertRightSide(new RightObstacleSide(rightVertexEvent.Vertex));
            }
        }
        void AddConeAndEnqueueEvents(VertexEvent vertexEvent)
        {
            var leftVertexEvent = vertexEvent as LeftVertexEvent;

            if (leftVertexEvent != null)
            {
                PolylinePoint nextPoint = vertexEvent.Vertex.NextOnPolyline;
                CloseConesAtLeftVertex(leftVertexEvent, nextPoint);
            }
            else
            {
                var rightVertexEvent = vertexEvent as RightVertexEvent;
                if (rightVertexEvent != null)
                {
                    PolylinePoint nextPoint = vertexEvent.Vertex.PrevOnPolyline;
                    CloseConesAtRightVertex(rightVertexEvent, nextPoint);
                }
                else
                {
                    CloseConesAtLeftVertex(vertexEvent, vertexEvent.Vertex.NextOnPolyline);
                    CloseConesAtRightVertex(vertexEvent, vertexEvent.Vertex.PrevOnPolyline);
                }
            }
        }
        void CloseConesAtLeftVertex(VertexEvent leftVertexEvent, PolylinePoint nextVertex)
        {
            //close segments first
            Point  prevSite = leftVertexEvent.Vertex.PrevOnPolyline.Point;
            double prevZ    = prevSite * SweepDirection;

            if (prevZ <= Z && Z - prevZ < ApproximateComparer.DistanceEpsilon)
            {
                //Show(
                //    new Ellipse(1, 1, prevSite),
                //    CurveFactory.CreateBox(2, 2, leftVertexEvent.Vertex.Point));

                RemoveConesClosedBySegment(leftVertexEvent.Vertex.Point, prevSite);
            }

            Point site     = leftVertexEvent.Site;
            Point coneLp   = site + ConeLeftSideDirection;
            Point coneRp   = site + ConeRightSideDirection;
            Point nextSite = nextVertex.Point;

            // SugiyamaLayoutSettings.Show(new LineSegment(site, coneLP), new LineSegment(site, coneRP), new LineSegment(site, nextSite));

            if ((site - prevSite) * SweepDirection > ApproximateComparer.DistanceEpsilon)
            {
                RemoveLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex.PrevOnPolyline));
            }


            if (Point.PointToTheRightOfLineOrOnLine(nextSite, site, site + DirectionPerp))
            {
                //if (angle > Math.PI / 2)
                //   CreateConeOnVertex(leftVertexEvent); //it is the last left vertex on this obstacle
            }
            else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneRp))
            {
                //if (angle >= coneAngle / 2) {
                // CreateConeOnVertex(leftVertexEvent);
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                //we schedule LeftVertexEvent for a vertex with horizontal segment to the left on the top of the obstace
            }
            else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneLp))
            {
                //if (angle >= -coneAngle / 2) {
                //we cannot completely obscure the cone here
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                //the obstacle side is inside of the cone
                //we need to create an obstacle right side segment instead of the cone side
                //                var cone = new Cone(leftVertexEvent.Vertex.Point, this);
                //                var rightSide = new BrokenConeSide(leftVertexEvent.Vertex.Point, nextVertex,
                //                                                        new ConeRightSide(cone));
                //                cone.RightSide = rightSide;
                //                cone.LeftSide = new ConeLeftSide(cone);
                //                LookForIntersectionWithConeLeftSide(InsertToTree(leftConeSides, cone.LeftSide));
                RBNode <ConeSide> rbNode = rightConeSides.FindLast(s => PointIsToTheRightOfSegment(site, s));
                FixConeRightSideIntersections(leftVertexEvent.Vertex, nextVertex, rbNode);
                if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                {
                    InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex));
                }
            }
            else
            {
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                {
                    //if( angle >- Pi/2
                    // Debug.Assert(angle > -Math.PI / 2);
                    LookForIntersectionOfObstacleSideAndRightConeSide(leftVertexEvent.Site, nextVertex);
                    InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex));
                }
            }
        }
        void CloseConesAddConeAtLeftVertex(VertexEvent leftVertexEvent, PolylinePoint nextVertex) {
            //close segments first
            Point prevSite = leftVertexEvent.Vertex.PrevOnPolyline.Point;
            double prevZ = prevSite * SweepDirection;
            if (ApproximateComparer.Close(prevZ, Z) && (prevSite - leftVertexEvent.Site) * DirectionPerp > 0) {
                //Show(
                //    new Ellipse(1, 1, prevSite),
                //    CurveFactory.CreateBox(2, 2, leftVertexEvent.Vertex.Point));
                RemoveConesClosedBySegment(leftVertexEvent.Vertex.Point, prevSite);
            }

            var site = leftVertexEvent.Site;
            var coneLp = site + ConeLeftSideDirection;
            var coneRp = site + ConeRightSideDirection;
            var nextSite = nextVertex.Point;
            // SugiyamaLayoutSettings.Show(new LineSegment(site, coneLP), new LineSegment(site, coneRP), new LineSegment(site, nextSite));

            if ((site - prevSite) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                RemoveLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex.PrevOnPolyline));
           

            var nextDelZ = GetZ(nextSite) - Z;
            if(nextDelZ<-ApproximateComparer.DistanceEpsilon)
                RemoveRightSide(new RightObstacleSide(nextVertex));

            if (nextDelZ < -ApproximateComparer.DistanceEpsilon ||
                ApproximateComparer.Close(nextDelZ, 0) && (nextSite - leftVertexEvent.Site) * DirectionPerp > 0) {
                //if (angle > Math.PI / 2)
                CreateConeOnVertex(leftVertexEvent); //it is the last left vertex on this obstacle
                
            } else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneRp)) {
                //if (angle >= coneAngle / 2) {
                CreateConeOnVertex(leftVertexEvent);
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                //we schedule LeftVertexEvent for a vertex with horizontal segment to the left on the top of the obstace
            } else if (!Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneLp)) {
                //if (angle >= -coneAngle / 2) {
                //we cannot completely obscure the cone here
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                //the obstacle side is inside of the cone
                //we need to create an obstacle right side segment instead of the cone side
                var cone = new Cone(leftVertexEvent.Vertex.Point, this);
                var rightSide = new BrokenConeSide(leftVertexEvent.Vertex.Point, nextVertex,
                                                   new ConeRightSide(cone));
                cone.RightSide = rightSide;
                cone.LeftSide = new ConeLeftSide(cone);
                LookForIntersectionWithConeLeftSide(InsertToTree(leftConeSides, cone.LeftSide));
                var rbNode = InsertToTree(rightConeSides, rightSide);
                FixConeRightSideIntersections(rightSide, rbNode);
                if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                    InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex));
            } else {
                EnqueueEvent(new LeftVertexEvent(nextVertex));
                if ((nextVertex.Point - leftVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon) {
                    //if( angle >- Pi/2
                    // Debug.Assert(angle > -Math.PI / 2);
                    LookForIntersectionOfObstacleSideAndRightConeSide(leftVertexEvent.Site, nextVertex);
                    InsertLeftSide(new LeftObstacleSide(leftVertexEvent.Vertex));
                }
            }
        }
 void ProcessVertexEvent(VertexEvent vertexEvent)
 {
     Z = GetZ(vertexEvent);
     GoOverConesSeeingVertexEvent(vertexEvent);
     AddConeAndEnqueueEvents(vertexEvent);
 }
 void CaseToTheLeftOfLineOrOnLineConeRp(VertexEvent rightVertexEvent, PolylinePoint nextVertex) {
     EnqueueEvent(new RightVertexEvent(nextVertex));
     //the obstacle side is inside of the cone
     //we need to create an obstacle left side segment instead of the left cone side
     var cone = new Cone(rightVertexEvent.Vertex.Point, this);
     var obstacleSideSeg = new BrokenConeSide(cone.Apex, nextVertex, new ConeLeftSide(cone));
     cone.LeftSide = obstacleSideSeg;
     cone.RightSide = new ConeRightSide(cone);
     var rnode = InsertToTree(rightConeSides, cone.RightSide);
     LookForIntersectionWithConeRightSide(rnode);
     var lnode = InsertToTree(leftConeSides, cone.LeftSide);
     FixConeLeftSideIntersections(obstacleSideSeg, lnode);
     if ((nextVertex.Point - rightVertexEvent.Site) * SweepDirection > ApproximateComparer.DistanceEpsilon)
         InsertRightSide(new RightObstacleSide(rightVertexEvent.Vertex));
 }
        void CloseConesAddConeAtRightVertex(VertexEvent rightVertexEvent,
                                            PolylinePoint nextVertex) {
            var prevSite = rightVertexEvent.Vertex.NextOnPolyline.Point;
            var prevZ = prevSite*SweepDirection;
            if (ApproximateComparer.Close(prevZ, Z))
                RemoveConesClosedBySegment(prevSite, rightVertexEvent.Vertex.Point);

            var site = rightVertexEvent.Site;
            var coneLp = site + ConeLeftSideDirection;
            var coneRp = site + ConeRightSideDirection;
            var nextSite = nextVertex.Point;
            //SugiyamaLayoutSettings.Show(new LineSegment(site, coneLP), new LineSegment(site, coneRP), new LineSegment(site, nextSite));
            //try to remove the right side
            if ((site - prevSite)*SweepDirection > ApproximateComparer.DistanceEpsilon)
                RemoveRightSide(new RightObstacleSide(rightVertexEvent.Vertex.NextOnPolyline));
            if ((site - nextVertex.Point) * SweepDirection > ApproximateComparer.DistanceEpsilon)
                RemoveLeftSide(new LeftObstacleSide(nextVertex));

            if (GetZ(nextSite) + ApproximateComparer.DistanceEpsilon < GetZ(rightVertexEvent))
                  CreateConeOnVertex(rightVertexEvent);   
            if (!Point.PointToTheRightOfLineOrOnLine(nextSite, site, coneLp)) {
                //if (angle <= -coneAngle / 2) {
                CreateConeOnVertex(rightVertexEvent);
                if (Point.PointToTheLeftOfLineOrOnLine(nextSite + DirectionPerp, nextSite, site))
                    EnqueueEvent(new RightVertexEvent(nextVertex));
                //  TryEnqueueRighVertexEvent(nextVertex);
            } else if (Point.PointToTheLeftOfLineOrOnLine(nextSite, site, coneRp))
                //if (angle < coneAngle / 2) {
                CaseToTheLeftOfLineOrOnLineConeRp(rightVertexEvent, nextVertex);
            else {
                if ((nextSite - site)*SweepDirection > ApproximateComparer.DistanceEpsilon) {
                    LookForIntersectionOfObstacleSideAndLeftConeSide(rightVertexEvent.Site, nextVertex);
                    InsertRightSide(new RightObstacleSide(rightVertexEvent.Vertex));
                }
                EnqueueEvent(new RightVertexEvent(nextVertex));
            }
        }
 void AddConeAndEnqueueEvents(VertexEvent vertexEvent) {
     var leftVertexEvent = vertexEvent as LeftVertexEvent;
     if (leftVertexEvent != null) {
         PolylinePoint nextPoint = vertexEvent.Vertex.NextOnPolyline;
         CloseConesAddConeAtLeftVertex(leftVertexEvent, nextPoint);
     } else {
         var rightVertexEvent = vertexEvent as RightVertexEvent;
         if (rightVertexEvent != null) {
             PolylinePoint nextPoint = vertexEvent.Vertex.PrevOnPolyline;
             CloseConesAddConeAtRightVertex(rightVertexEvent, nextPoint);
         } else {
             CloseConesAddConeAtLeftVertex(vertexEvent, vertexEvent.Vertex.NextOnPolyline);
             CloseConesAddConeAtRightVertex(vertexEvent, vertexEvent.Vertex.PrevOnPolyline);
         }
     }
 }
        void ProcessVertexEvent(VertexEvent vertexEvent) {
//            if (count == 872 && (vertexEvent.Site - new Point(-130.7368, -305.908)).Length < 1)
//                Show(EllipseOnVert(vertexEvent));

            Z = GetZ(vertexEvent);
            //PrintOutLeftSegTree();
            //PrintOutRightSegTree();
            GoOverConesSeeingVertexEvent(vertexEvent);
            AddConeAndEnqueueEvents(vertexEvent);
        }
 void ProcessVertexEvent(VertexEvent vertexEvent) {
     Z = GetZ(vertexEvent);
     GoOverConesSeeingVertexEvent(vertexEvent);
     AddConeAndEnqueueEvents(vertexEvent);
 }