Example #1
0
 public EdgeInserter(CdtEdge edge, Set <CdtTriangle> triangles, RbTree <CdtFrontElement> front, Func <CdtSite, CdtSite, CdtEdge> createEdgeDelegate)
 {
     this.edge               = edge;
     this.triangles          = triangles;
     this.front              = front;
     this.createEdgeDelegate = createEdgeDelegate;
 }
Example #2
0
        PerimeterEdge CreateDoubleLinkedListOfPerimeter()
        {
            CdtEdge       firstEdge = this.triangles.SelectMany(t => t.Edges).FirstOrDefault(e => e.CwTriangle == null || e.CcwTriangle == null);
            var           edge = firstEdge;
            PerimeterEdge pe, prevPe = null, listStart = null;

            do
            {
                pe   = CreatePerimeterElementFromEdge(edge);
                edge = FindNextEdgeOnPerimeter(edge);
                if (prevPe != null)
                {
                    pe.Prev     = prevPe;
                    prevPe.Next = pe;
                }
                else
                {
                    listStart = pe;
                }

                prevPe = pe;
            } while (edge != firstEdge);
            listStart.Prev = pe;
            pe.Next        = listStart;
            return(listStart);
        }
        void StepFromEdgeInteriorPoint(CdtEdge edge)
        {
            var triangle = GetTriangleOnThePointSide(edge, segEnd.Point);

            if (triangle == null)
            {
                lastCrossedFeature = OutsideOfTriangulation;
                return;
            }
            if (PointBelongsToInteriorOfTriangle(segEnd.Point, triangle))
            {
                lastCrossedFeature = triangle;
                return;
            }

            //we cross an edge
            for (int i = 0; i < 3; i++)
            {
                if (triangle.Edges[i] == edge)
                {
                    continue;
                }
                if (PointIsInsideCone(segEnd.Point, segStart.Point, triangle.Sites[i + 1].Point,
                                      triangle.Sites[i].Point))
                {
                    CrossTriangleEdge(triangle.Edges[i]);
                    return;
                }
            }
        }
 static CdtTriangle GetTriangleOnThePointSide(CdtEdge edge, Point p)
 {
     return(Point.GetTriangleOrientation(edge.upperSite.Point, edge.lowerSite.Point, p) ==
            TriangleOrientation.Counterclockwise
              ? edge.CcwTriangle
              : edge.CwTriangle);
 }
        internal static bool EdgeIsPierced(CdtEdge e, Point source, Point target, CdtTriangle cdtTriangle)
        {
            var area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, source, target);
            var area1 = Point.SignedDoubledTriangleArea(e.lowerSite.Point, source, target);

            if (ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) > 0)
            {
                return(false);
            }
            area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, source);
            area1 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, target);
            if (ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) > 0)
            {
                return(false);
            }
            var otherT = e.GetOtherTriangle(cdtTriangle);

            if (otherT == null)
            {
                return(true);
            }
            var otherSite = otherT.OppositeSite(e);

            area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, otherSite.Point);
            return(ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) >= 0);
        }
Example #6
0
        void LegalizeEdgeForOtherCwTriangle(CdtSite pi, CdtEdge edge)
        {
            var i = edge.CwTriangle.Edges.Index(edge);

//            if (i == -1)
//            {
//                List<DebugCurve> ls = new List<DebugCurve>();
//                ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
//                for (int j = 0; j < 3; j++)
//                {
//                    var ee = edge.CwTriangle.Edges[j];
//                    ls.Add(new DebugCurve(100,1, j == i ? "red" : "blue", new LineSegment(ee.upperSite.Point, ee.lowerSite.Point)));
//                }
//                ls.Add(new DebugCurve("purple", new LineSegment(edge.upperSite.Point, edge.lowerSite.Point)));
//
//                LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
//            }
            Debug.Assert(i >= 0);
            if (IsIllegal(pi, edge.upperSite, edge.CwTriangle.Sites[i + 2], edge.lowerSite))
            {
                //ShowIllegalEdge(edge, i, pi);

                CdtEdge e = Flip(pi, edge);
                LegalizeEdge(pi, e.CwTriangle.OppositeEdge(pi));
                LegalizeEdge(pi, e.CcwTriangle.OppositeEdge(pi));
            }
        }
Example #7
0
        bool EdgeSeparationIsOk(CdtEdge edge, Set <EdgeGeometry> paths, double separation)
        {
            double requiredWidth  = paths.Select(v => v.LineWidth).Sum() + (paths.Count - 1) * separation;
            double availableWidth = edge.Capacity;

            return(requiredWidth <= availableWidth);
        }
 internal CdtFrontElement(CdtSite leftSite, CdtEdge edge) {
     Debug.Assert(edge.upperSite.Point.X != edge.lowerSite.Point.X &&
                  edge.upperSite.Point.X < edge.lowerSite.Point.X && leftSite == edge.upperSite ||
                  edge.upperSite.Point.X > edge.lowerSite.Point.X && leftSite == edge.lowerSite);
     RightSite = edge.upperSite == leftSite ? edge.lowerSite : edge.upperSite;
     LeftSite = leftSite;
     Edge = edge;
 }
Example #9
0
 static DebugCurve GetDebugCurveOfCdtEdge(CdtEdge e)
 {
     if (e.CcwTriangle == null || e.CwTriangle == null)
     {
         return(new DebugCurve(255, 4, e.Constrained ? "brown" : "blue", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
     }
     return(new DebugCurve(100, e.Constrained?0.002:0.001, e.Constrained?"pink":"navy", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
 }
Example #10
0
 static DebugCurve GetDebugCurveOfCdtEdge(CdtEdge e)
 {
     if (e.CcwTriangle == null || e.CwTriangle == null)
     {
         return(new DebugCurve(100, 0.5, e.Constrained ? "pink" : "rose", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
     }
     return(new DebugCurve(100, e.Constrained?0.002:0.001, e.Constrained?"violet":"yellow", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
 }
Example #11
0
        bool RealCrossing(CdtEdge cdtEdge)
        {
            var segEndOrientation   = Point.GetTriangleOrientation(segEnd.Point, cdtEdge.upperSite.Point, cdtEdge.lowerSite.Point);
            var segStartOrientation = Point.GetTriangleOrientation(segStart.Point, cdtEdge.upperSite.Point,
                                                                   cdtEdge.lowerSite.Point);

            return(segStartOrientation != TriangleOrientation.Collinear && segStartOrientation != segEndOrientation ||
                   SomePreviousPointIsOnOtherSiteOfEdge(cdtEdge, segEndOrientation));
        }
 public EdgeTracer(CdtEdge edge, Set<CdtTriangle> triangles, RbTree<CdtFrontElement> front, List<CdtSite> leftPolygon, List<CdtSite> rightPolygon) {
     this.edge = edge;
     this.triangles = triangles;
     this.front = front;
     this.leftPolygon = leftPolygon;
     this.rightPolygon = rightPolygon;
     a = edge.upperSite;
     b = edge.lowerSite;
 }
Example #13
0
 internal CdtFrontElement(CdtSite leftSite, CdtEdge edge)
 {
     Debug.Assert(edge.upperSite.Point.X != edge.lowerSite.Point.X &&
                  edge.upperSite.Point.X <edge.lowerSite.Point.X && leftSite == edge.upperSite ||
                                          edge.upperSite.Point.X> edge.lowerSite.Point.X && leftSite == edge.lowerSite);
     RightSite = edge.upperSite == leftSite ? edge.lowerSite : edge.upperSite;
     LeftSite  = leftSite;
     Edge      = edge;
 }
        bool RealCrossing(CdtEdge cdtEdge) {
            var segEndOrientation = Point.GetTriangleOrientation(segEnd.Point, cdtEdge.upperSite.Point, cdtEdge.lowerSite.Point);
            var segStartOrientation = Point.GetTriangleOrientation(segStart.Point, cdtEdge.upperSite.Point,
                                                          cdtEdge.lowerSite.Point);

            return segStartOrientation != TriangleOrientation.Collinear && segStartOrientation != segEndOrientation ||
                    SomePreviousPointIsOnOtherSiteOfEdge(cdtEdge, segEndOrientation);

        }
 bool SomePreviousPointIsOnOtherSiteOfEdge(CdtEdge cdtEdge, TriangleOrientation segEndOrientation) {
     foreach (PolylinePoint polylinePoint in polylineHead) {
         var orientation = Point.GetTriangleOrientation(polylinePoint.Point, cdtEdge.upperSite.Point,
                                                        cdtEdge.lowerSite.Point);
         if (orientation != TriangleOrientation.Collinear)
             return orientation != segEndOrientation;
     }
     return false;
 }
 public EdgeTracer(CdtEdge edge, Set <CdtTriangle> triangles, RbTree <CdtFrontElement> front, List <CdtSite> leftPolygon, List <CdtSite> rightPolygon)
 {
     this.edge         = edge;
     this.triangles    = triangles;
     this.front        = front;
     this.leftPolygon  = leftPolygon;
     this.rightPolygon = rightPolygon;
     a = edge.upperSite;
     b = edge.lowerSite;
 }
 /// <summary>
 /// in the trianlge, which is always oriented counterclockwise, the edge starts at site
 /// </summary>
 /// <param name="site"></param>
 /// <param name="edge"></param>
 void BindEdgeToTriangle(CdtSite site, CdtEdge edge)
 {
     if (site == edge.upperSite)
     {
         edge.CcwTriangle = this;
     }
     else
     {
         edge.CwTriangle = this;
     }
 }
Example #18
0
        void LegalizeEdgeForOtherCcwTriangle(CdtSite pi, CdtEdge edge)
        {
            var i = edge.CcwTriangle.Edges.Index(edge);

            if (IsIllegal(pi, edge.lowerSite, edge.CcwTriangle.Sites[i + 2], edge.upperSite))
            {
                CdtEdge e = Flip(pi, edge);
                LegalizeEdge(pi, e.CwTriangle.OppositeEdge(pi));
                LegalizeEdge(pi, e.CcwTriangle.OppositeEdge(pi));
            }
        }
 //
 internal CdtTriangle(CdtSite aLeft, CdtSite aRight, CdtSite bRight, CdtEdge a, CdtEdge b, Func<CdtSite, CdtSite, CdtEdge> createEdgeDelegate) {
    // Debug.Assert(Point.GetTriangleOrientation(aLeft.Point, aRight.Point, bRight.Point) == TriangleOrientation.Counterclockwise);
     Sites[0] = aLeft;
     Sites[1] = aRight;
     Sites[2] = bRight;
     Edges[0] = a;
     Edges[1] = b;
     BindEdgeToTriangle(aLeft, a);
     BindEdgeToTriangle(aRight, b);
     CreateEdge(2, createEdgeDelegate);
 }
Example #20
0
 void TryInsertEdge(CdtEdge e)
 {
     if (crossedEdges.Contains(e))
     {
         return;
     }
     if (e.upperSite.Owner != e.lowerSite.Owner && RealCrossing(e))
     {
         crossedEdges.Insert(e);
     }
 }
Example #21
0
        void EdgeEvent(CdtEdge edge)
        {
            Debug.Assert(edge.Constrained);
            if (EdgeIsProcessed(edge))
            {
                return;
            }
            var edgeInserter = new EdgeInserter(edge, Triangles, front, createEdgeDelegate);

            edgeInserter.Run();
        }
Example #22
0
        static CdtEdge FindNextEdgeOnPerimeter(CdtEdge e)
        {
            var t = e.CwTriangle ?? e.CcwTriangle;

            e = t.Edges[t.Edges.Index(e) + 2];
            while (e.CwTriangle != null && e.CcwTriangle != null)
            {
                t = e.GetOtherTriangle(t);
                e = t.Edges[t.Edges.Index(e) + 2];
            }
            return(e);
        }
 //
 internal CdtTriangle(CdtSite aLeft, CdtSite aRight, CdtSite bRight, CdtEdge a, CdtEdge b, Func <CdtSite, CdtSite, CdtEdge> createEdgeDelegate)
 {
     // Debug.Assert(Point.GetTriangleOrientation(aLeft.Point, aRight.Point, bRight.Point) == TriangleOrientation.Counterclockwise);
     Sites[0] = aLeft;
     Sites[1] = aRight;
     Sites[2] = bRight;
     Edges[0] = a;
     Edges[1] = b;
     BindEdgeToTriangle(aLeft, a);
     BindEdgeToTriangle(aRight, b);
     CreateEdge(2, createEdgeDelegate);
 }
Example #24
0
        void ShowIllegalEdge(CdtEdge edge, int i, CdtSite pi)
        {
            List <DebugCurve> ls = new List <DebugCurve>();

            ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
            for (int j = 0; j < 3; j++)
            {
                var ee = edge.CwTriangle.Edges[j];
                ls.Add(new DebugCurve(j == i?"red":"blue", new LineSegment(ee.upperSite.Point, ee.lowerSite.Point)));
            }
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
        }
 internal bool MoveNext()
 {
     if (currentPiercedEdge == null)
     {
         currentPiercedEdge = FindFirstPiercedEdge();
     }
     else
     {
         FindNextPierced();
     }
     return(currentPiercedEdge != null);
 }
Example #26
0
 bool SomePreviousPointIsOnOtherSiteOfEdge(CdtEdge cdtEdge, TriangleOrientation segEndOrientation)
 {
     foreach (PolylinePoint polylinePoint in polylineHead)
     {
         var orientation = Point.GetTriangleOrientation(polylinePoint.Point, cdtEdge.upperSite.Point,
                                                        cdtEdge.lowerSite.Point);
         if (orientation != TriangleOrientation.Collinear)
         {
             return(orientation != segEndOrientation);
         }
     }
     return(false);
 }
Example #27
0
        List <DebugCurve> ShowIllegalEdge(CdtEdge edge, CdtSite pi, int i)
        {
            List <DebugCurve> ls = new List <DebugCurve>();

            ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
            for (int j = 0; j < 3; j++)
            {
                var ee = edge.CcwTriangle.Edges[j];
                ls.Add(new DebugCurve(j == i ? "red" : "blue", new LineSegment(ee.upperSite.Point, ee.lowerSite.Point)));
            }
            ls.Add(new DebugCurve(100, 1, "black", Circumcircle(edge.CcwTriangle.Sites[0].Point, edge.CcwTriangle.Sites[1].Point, edge.CcwTriangle.Sites[2].Point)));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
            return(ls);
        }
Example #28
0
        static PerimeterEdge CreatePerimeterElementFromEdge(CdtEdge edge)
        {
            var pe = new PerimeterEdge(edge);

            if (edge.CwTriangle != null)
            {
                pe.Start = edge.upperSite;
                pe.End   = edge.lowerSite;
            }
            else
            {
                pe.End   = edge.upperSite;
                pe.Start = edge.lowerSite;
            }
            return(pe);
        }
Example #29
0
 void LegalizeEdge(CdtSite pi, CdtEdge edge)
 {
     Debug.Assert(pi != edge.upperSite && pi != edge.lowerSite);
     if (edge.Constrained || edge.CcwTriangle == null || edge.CwTriangle == null)
     {
         return;
     }
     if (edge.CcwTriangle.Contains(pi))
     {
         LegalizeEdgeForOtherCwTriangle(pi, edge);
     }
     else
     {
         LegalizeEdgeForOtherCcwTriangle(pi, edge);
     }
 }
        void FindPiercedTriangle(RBNode <CdtFrontElement> v)
        {
            var e      = v.Item.Edge;
            var t      = e.CcwTriangle ?? e.CwTriangle;
            var eIndex = t.Edges.Index(e);

            for (int i = 1; i <= 2; i++)
            {
                var ei          = t.Edges[i + eIndex];
                var signedArea0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(ei.lowerSite.Point, a.Point, b.Point));
                var signedArea1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(ei.upperSite.Point, a.Point, b.Point));
                if (signedArea1 * signedArea0 <= 0)
                {
                    piercedTriangle = t;
                    piercedEdge     = ei;
                    break;
                }
            }
        }
        static void CalculateCdtEdgeCapacityForEdge(CdtEdge e)
        {
            if (e.Constrained || e.CwTriangle == null || e.CcwTriangle == null)
            {
                return; //this is a convex hull edge or an obstacle edge
            }
            var startPoly = e.upperSite.Owner as Polyline;
            var endPoly   = e.lowerSite.Owner as Polyline;

            if (startPoly != endPoly)
            {
                //e.Capacity = Polygon.Distance(new Polygon(startPoly), new Polygon(endPoly)); //todo: cache this
                //e.Capacity = (e.upperSite.Point - e.lowerSite.Point).Length;
                double distA = Polygon.Distance(new Polygon(startPoly), e.lowerSite.Point);
                double distB = Polygon.Distance(new Polygon(endPoly), e.upperSite.Point);
                e.Capacity = (distA + distB) / 2;
            }
            //else - it is a diagonal of an obstacle, do not care
        }
        void Init()
        {
//            if (CdtSweeper.D)
//                CdtSweeper.ShowFront(triangles, front, new[] {new LineSegment(a.Point, b.Point)},null);
            //new[] {new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point)});
            var frontElemNodeRightOfA = CdtSweeper.FindNodeInFrontBySite(front, a);
            var frontElemNodeLeftOfA  = front.Previous(frontElemNodeRightOfA);

            if (Point.PointToTheLeftOfLine(b.Point, frontElemNodeLeftOfA.Item.LeftSite.Point, frontElemNodeLeftOfA.Item.RightSite.Point))
            {
                piercedToTheLeftFrontElemNode = frontElemNodeLeftOfA;
            }
            else if (Point.PointToTheRightOfLine(b.Point, frontElemNodeRightOfA.Item.RightSite.Point, frontElemNodeRightOfA.Item.LeftSite.Point))
            {
                piercedToTheRightFrontElemNode = frontElemNodeRightOfA;
            }
            else
            {
                foreach (var e in a.Edges)
                {
                    var t = e.CcwTriangle;
                    if (t == null)
                    {
                        continue;
                    }
                    if (Point.PointToTheLeftOfLine(b.Point, e.lowerSite.Point, e.upperSite.Point))
                    {
                        continue;
                    }
                    var eIndex = t.Edges.Index(e);
                    var site   = t.Sites[eIndex + 2];
                    if (Point.PointToTheLeftOfLineOrOnLine(b.Point, site.Point, e.upperSite.Point))
                    {
                        piercedEdge     = t.Edges[eIndex + 1];
                        piercedTriangle = t;
//                                                CdtSweeper.ShowFront(triangles, front, new[] { new LineSegment(e.upperSite.Point, e.lowerSite.Point) },
//                                                    new[] { new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point) });
                        break;
                    }
                }
            }
        }
        CdtTriangle FindFirstPiercedTriangle(CdtSite startSite, Point target, out CdtEdge piercedEdge)
        {
            if (startSite != null)
            {
                foreach (var t in startSite.Triangles)
                {
                    piercedEdge = GetPiercedEdgeInSiteTriangle(t, startSite, target);
                    if (piercedEdge != null)
                    {
                        if (!PointIsInsideOfTriangle(target, t))
                        {
                            return(t);
                        }
                    }
                }
            }

            piercedEdge = null;
            return(null);
        }
 internal CdtTriangle(CdtSite pi, CdtEdge edge, Func<CdtSite, CdtSite, CdtEdge> createEdgeDelegate) {
     switch (Point.GetTriangleOrientationWithNoEpsilon(edge.upperSite.Point, edge.lowerSite.Point, pi.Point)) {
         case TriangleOrientation.Counterclockwise:
             edge.CcwTriangle = this;
             Sites[0] = edge.upperSite;
             Sites[1] = edge.lowerSite;
             break;
         case TriangleOrientation.Clockwise:
             edge.CwTriangle = this;
             Sites[0] = edge.lowerSite;
             Sites[1] = edge.upperSite;
             break;
         default:
             throw new InvalidOperationException();
     }
     Edges[0] = edge;
     Sites[2] = pi;
     CreateEdge(1, createEdgeDelegate);
     CreateEdge(2, createEdgeDelegate);
 }
Example #35
0
 void CrossTriangleEdge(CdtEdge e)
 {
     TryInsertEdge(e);
     if (Point.GetTriangleOrientation(segStart.Point, e.upperSite.Point, segEnd.Point) ==
         TriangleOrientation.Collinear)
     {
         lastCrossedFeature = e.upperSite;
         //    PickupEdgesOfSite(e.upperSite);
     }
     else if (Point.GetTriangleOrientation(segStart.Point, e.lowerSite.Point, segEnd.Point) ==
              TriangleOrientation.Collinear)
     {
         lastCrossedFeature = e.lowerSite;
         //  PickupEdgesOfSite(e.lowerSite);
     }
     else
     {
         lastCrossedFeature = e;
     }
 }
        Set <CdtEdge> ThreadBoneEdgeThroughCdt(SdBoneEdge boneEdge)
        {
            var start           = boneEdge.SourcePoint;
            var currentTriangle = boneEdge.Source.Triangle;

            Debug.Assert(Cdt.PointIsInsideOfTriangle(start, currentTriangle));
            var crossedEdges = new Set <CdtEdge>();
            var end          = boneEdge.TargetPoint;

            if (Cdt.PointIsInsideOfTriangle(end, currentTriangle))
            {
                return(crossedEdges);
            }

            var threader = new CdtThreader(currentTriangle, start, end);

            while (threader.MoveNext())
            {
                CdtEdge piercedEdge = threader.CurrentPiercedEdge;
                Debug.Assert(piercedEdge != null);
                if (Gates.Contains(piercedEdge))
                {
                    crossedEdges.Insert(piercedEdge);
                }
            }

            /*
             * CdtEdge piercedEdge = CdtIntersections.FindFirstPiercedEdge(currentTriangle, start, end, out negativeSign, out positiveSign, this.Cdt );
             * Debug.Assert(piercedEdge != null);
             *
             * do {
             *  if (Gates.Contains(piercedEdge))
             *      crossedEdges.Insert(piercedEdge);
             * }
             * while (CdtIntersections.FindNextPierced(start, end, ref currentTriangle, ref piercedEdge, ref negativeSign, ref positiveSign));
             */
            //if(ddd(boneEdge))
            //CdtSweeper.ShowFront(Cdt.GetTriangles(),null,new []{new LineSegment(boneEdge.SourcePoint,boneEdge.TargetPoint)}, crossedEdges.Select(e=>new LineSegment(e.upperSite.Point,e.lowerSite.Point)));

            return(crossedEdges);
        }
        bool EdgeSeparationIsOk(CdtEdge edge, Set<EdgeGeometry> paths, double separation) {
            double requiredWidth = paths.Select(v => v.LineWidth).Sum() + (paths.Count - 1) * separation;
            double availableWidth = edge.Capacity;

            return (requiredWidth <= availableWidth);
        }
 static CdtEdge FindNextEdgeOnPerimeter(CdtEdge e) {
     var t = e.CwTriangle ?? e.CcwTriangle;
     e = t.Edges[t.Edges.Index(e) + 2];
     while(e.CwTriangle != null && e.CcwTriangle != null) {
         t = e.GetOtherTriangle(t);
         e = t.Edges[t.Edges.Index(e) + 2];
     }
     return e;
 }
 void LegalizeEdge(CdtSite pi, CdtEdge edge) {
     Debug.Assert(pi!=edge.upperSite && pi!=edge.lowerSite);
     if (edge.Constrained || edge.CcwTriangle == null || edge.CwTriangle == null) return;
     if (edge.CcwTriangle.Contains(pi))
         LegalizeEdgeForOtherCwTriangle(pi, edge);
     else
         LegalizeEdgeForOtherCcwTriangle(pi, edge);
 }
        double SavedCapacityPenaltyOnCdtEdge(CdtEdge cdtEdge, EdgeGeometry edgeGeometry) {
            if (cdtEdge.ResidualCapacity > 0) return 0;

            double savedDelta;
            double width = edgeGeometry.LineWidth;
            if (cdtEdge.ResidualCapacity == cdtEdge.Capacity - width)
                savedDelta = width;
            else
                savedDelta = width + bundlingSettings.EdgeSeparation;
            if (savedDelta > -cdtEdge.ResidualCapacity)
                savedDelta = -cdtEdge.ResidualCapacity;
            return savedDelta * SdShortestPath.CapacityOverflowPenaltyMultiplier(bundlingSettings);
        }
 /// <summary>
 /// in the trianlge, which is always oriented counterclockwise, the edge starts at site 
 /// </summary>
 /// <param name="site"></param>
 /// <param name="edge"></param>
 void BindEdgeToTriangle(CdtSite site, CdtEdge edge) {
     if (site == edge.upperSite)
         edge.CcwTriangle = this;
     else
         edge.CwTriangle = this;
 }
 public EdgeInserter(CdtEdge edge, Set<CdtTriangle> triangles, RbTree<CdtFrontElement> front, Func<CdtSite, CdtSite, CdtEdge> createEdgeDelegate) {
     this.edge = edge;
     this.triangles = triangles;
     this.front = front;
     this.createEdgeDelegate = createEdgeDelegate;
 }
 IEnumerable<CdtEdge> ThreadThroughTriangles(Point start, Point end, CdtTriangle triangle, CdtEdge piercedEdge) {
     var ret = new List<CdtEdge>();
     do {
         if (piercedEdge.upperSite.Owner != piercedEdge.lowerSite.Owner)
             ret.Add(piercedEdge);
     }
     while (FindNextPierced(start, end, ref triangle, ref piercedEdge));
     return ret;
 }
 void EdgeEvent(CdtEdge edge) {
       Debug.Assert(edge.Constrained);
       if(EdgeIsProcessed(edge))
           return;
       var edgeInserter = new EdgeInserter(edge, Triangles, front, createEdgeDelegate);
       edgeInserter.Run();
       
   }
        void LegalizeEdgeForOtherCwTriangle(CdtSite pi, CdtEdge edge) {
            var i=edge.CwTriangle.Edges.Index(edge);
//            if (i == -1)
//            {
//                List<DebugCurve> ls = new List<DebugCurve>();
//                ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
//                for (int j = 0; j < 3; j++)
//                {
//                    var ee = edge.CwTriangle.Edges[j];
//                    ls.Add(new DebugCurve(100,1, j == i ? "red" : "blue", new LineSegment(ee.upperSite.Point, ee.lowerSite.Point)));
//                }
//                ls.Add(new DebugCurve("purple", new LineSegment(edge.upperSite.Point, edge.lowerSite.Point)));
//                
//                LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
//            }
            Debug.Assert(i>=0);
            if (IsIllegal(pi, edge.upperSite, edge.CwTriangle.Sites[i + 2], edge.lowerSite)) {
                //ShowIllegalEdge(edge, i, pi);

                CdtEdge e = Flip(pi, edge);
                LegalizeEdge(pi, e.CwTriangle.OppositeEdge(pi) );
                LegalizeEdge(pi, e.CcwTriangle.OppositeEdge(pi));
            }
        }
 List<DebugCurve> ShowIllegalEdge(CdtEdge edge, CdtSite pi, int i) {
     List<DebugCurve> ls = new List<DebugCurve>();
     ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
     for (int j = 0; j < 3; j++) {
         var ee = edge.CcwTriangle.Edges[j];
         ls.Add(new DebugCurve(j == i ? "red" : "blue", new LineSegment(ee.upperSite.Point, ee.lowerSite.Point)));
     }
     ls.Add(new DebugCurve(100,1, "black", Circumcircle(edge.CcwTriangle.Sites[0].Point,edge.CcwTriangle.Sites[1].Point,edge.CcwTriangle.Sites[2].Point)));
     LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
     return ls;
 }
 static bool EdgeIsProcessed(CdtEdge edge) {
     return edge.CwTriangle != null || edge.CcwTriangle != null;
 }
 static DebugCurve GetDebugCurveOfCdtEdge(CdtEdge e) {
     if(e.CcwTriangle==null || e.CwTriangle==null)
         return new DebugCurve(255, 4, e.Constrained ? "brown" : "blue", new LineSegment(e.upperSite.Point, e.lowerSite.Point));
     return new DebugCurve(100, e.Constrained?0.002:0.001, e.Constrained?"pink":"navy", new LineSegment(e.upperSite.Point, e.lowerSite.Point));
 }
 void AddEdgeToFront(CdtEdge e) {
     var leftSite=e.upperSite.Point.X<e.lowerSite.Point.X?e.upperSite:e.lowerSite;
     front.Insert(new CdtFrontElement(leftSite, e));
 }
 bool FindNextPierced(Point start, Point end, ref CdtTriangle t, ref CdtEdge piercedEdge) {
     t = piercedEdge.GetOtherTriangle(t);
     if (t == null)
         return false;
     var i = t.Edges.Index(piercedEdge);
     for (int j = i + 1; j <= i + 2; j++) {
         var pe = t.Edges[j];
         piercedEdge = PiercedEdgeQuery(pe, start, end, t);
         if (piercedEdge != null) {
             //                    CdtSweeper.ShowFront(trs, null, 
             //                        new []{new LineSegment(e.SourcePoint,e.TargetPoint)}, new []{new LineSegment(pe.upperSite.Point,pe.lowerSite.Point)});
             break;
         }
     }
     return !PointIsInsideOfTriangle(end, t);
 }
 internal CdtSite OppositeSite(CdtEdge cdtEdge) {
     var i = Edges.Index(cdtEdge);
     return Sites[i + 2];
 }
        CdtTriangle FindFirstPiercedTriangle(CdtSite startSite, Point target, out CdtEdge piercedEdge) {
            if (startSite != null) {
                foreach (var t in startSite.Triangles) {
                    piercedEdge = GetPiercedEdgeInSiteTriangle(t, startSite, target);
                    if (piercedEdge != null)
                        if (!PointIsInsideOfTriangle(target, t))
                            return t;
                }
            }

            piercedEdge = null;
            return null;
        }
 double AddedCapacityPenaltyForCdtEdge(CdtEdge cdtEdge, EdgeGeometry edgeGeometry) {
     double capacityOverflowMultiplier = SdShortestPath.CapacityOverflowPenaltyMultiplier(bundlingSettings);
     return SdShortestPath.CostOfCrossingCdtEdge(capacityOverflowMultiplier,   bundlingSettings, edgeGeometry, cdtEdge);
 }
 void ShowIllegalEdge(CdtEdge edge, int i, CdtSite pi) {
     List<DebugCurve> ls=new List<DebugCurve>();
     ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
     for(int j=0;j<3;j++) {
         var ee=edge.CwTriangle.Edges[j];
         ls.Add(new DebugCurve(j==i?"red":"blue", new LineSegment(ee.upperSite.Point,ee.lowerSite.Point)));
     }
     LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
 }
 internal bool EdgeIsReversed(CdtEdge edge) {
     return edge.CwTriangle == this;
 }
 static PerimeterEdge CreatePerimeterElementFromEdge(CdtEdge edge) {
     var pe = new PerimeterEdge(edge);
     if (edge.CwTriangle != null) {
         pe.Start=edge.upperSite;
         pe.End = edge.lowerSite;
     } else {
         pe.End = edge.upperSite;
         pe.Start = edge.lowerSite;
     }
     return pe;
 }
 internal static bool EdgeIsPierced(CdtEdge e, Point source, Point target, CdtTriangle cdtTriangle) {
     var area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, source, target);
     var area1 = Point.SignedDoubledTriangleArea(e.lowerSite.Point, source, target);
     if (ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) > 0)
         return false;
     area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, source);
     area1 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, target);
     if (ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) > 0)
         return false;
     var otherT = e.GetOtherTriangle(cdtTriangle);
     if (otherT == null)
         return true;
     var otherSite = otherT.OppositeSite(e);
     area0 = Point.SignedDoubledTriangleArea(e.upperSite.Point, e.lowerSite.Point, otherSite.Point);
     return (ApproximateComparer.Sign(area0) * ApproximateComparer.Sign(area1) >= 0);
 }
 void LegalizeEdgeForOtherCcwTriangle(CdtSite pi, CdtEdge edge) {
     var i = edge.CcwTriangle.Edges.Index(edge);
     if (IsIllegal(pi, edge.lowerSite, edge.CcwTriangle.Sites[i + 2], edge.upperSite)) {
         CdtEdge e = Flip(pi, edge);                
         LegalizeEdge(pi, e.CwTriangle.OppositeEdge(pi));
         LegalizeEdge(pi, e.CcwTriangle.OppositeEdge(pi));
     }
 }
 CdtEdge PiercedEdgeQuery(CdtEdge e, Point source, Point target, CdtTriangle cdtTriangle) {
     return EdgeIsPierced(e, source, target, cdtTriangle) ? e : null;
 }
        static CdtEdge Flip(CdtSite pi, CdtEdge edge) {
            Debug.Assert(!edge.IsAdjacent(pi));
            Debug.Assert(edge.CcwTriangle.Contains(pi) || edge.CwTriangle.Contains(pi));
            //get surrounding data
            CdtTriangle t, ot;
            if (edge.CcwTriangle.Contains(pi)) {
                t = edge.CcwTriangle;
                ot = edge.CwTriangle;
            } else {
                t = edge.CwTriangle;
                ot = edge.CcwTriangle;
            }
            Debug.Assert(t.Contains(pi));
            var eIndex = t.Edges.Index(edge);
            var eOtherIndex = ot.Edges.Index(edge);
            Debug.Assert(eIndex > -1 && eOtherIndex > -1);
            var pl = ot.Sites[eOtherIndex + 2];
            var edgeBeforPi = t.Edges[eIndex + 1];
            var edgeBeforPl = ot.Edges[eOtherIndex + 1];

            //changing t 
            var newEdge = Cdt.GetOrCreateEdge(pi, pl);
            t.Sites[eIndex + 1] = pl;
            t.Edges[eIndex] = edgeBeforPl;
            t.Edges[eIndex + 1] = newEdge;
            //changing ot
            ot.Sites[eOtherIndex + 1] = pi;
            ot.Edges[eOtherIndex] = edgeBeforPi;
            ot.Edges[eOtherIndex + 1] = newEdge;
            //orient the new edge and the two edges that move from one triangle to another
            if (edgeBeforPl.lowerSite == pl)
                edgeBeforPl.CcwTriangle = t;
            else
                edgeBeforPl.CwTriangle = t;

            if (edgeBeforPi.lowerSite == pi)
                edgeBeforPi.CcwTriangle = ot;
            else
                edgeBeforPi.CwTriangle = ot;

            if (newEdge.upperSite == pi) {
                newEdge.CcwTriangle = ot;
                newEdge.CwTriangle = t;
            } else {
                newEdge.CcwTriangle = t;
                newEdge.CwTriangle = ot;
            }
            Debug.Assert(CheckTriangle(t));
            Debug.Assert(CheckTriangle(t));
            //ShowFlip(pi, t, ot);
            edge.upperSite.Edges.Remove(edge); //forget the edge 
            return newEdge;
        }