Beispiel #1
0
        PerimeterEdge ShortcutTwoListElements(PerimeterEdge a)
        {
            var b = a.Next;

            Debug.Assert(a.End == b.Start);
            var t = new CdtTriangle(a.Start, a.End, b.End, a.Edge, b.Edge,
                                    createEdgeDelegate);

            Triangles.Insert(t);
            var newEdge = t.Edges[2];

            Debug.Assert(newEdge.IsAdjacent(a.Start) && newEdge.IsAdjacent(b.End));
            LegalizeEdge(a.Start, t.OppositeEdge(a.Start));
            t = newEdge.CcwTriangle ?? newEdge.CwTriangle;
            LegalizeEdge(b.End, t.OppositeEdge(b.End));
            var c = new PerimeterEdge(newEdge)
            {
                Start = a.Start, End = b.End
            };

            a.Prev.Next = c;
            c.Prev      = a.Prev;
            c.Next      = b.Next;
            b.Next.Prev = c;
            return(c);
        }
Beispiel #2
0
        static bool CheckTriangle(CdtTriangle t)
        {
            if (Point.GetTriangleOrientationWithNoEpsilon(t.Sites[0].Point, t.Sites[1].Point, t.Sites[2].Point) != TriangleOrientation.Counterclockwise)
            {
                return(false);
            }

            for (int i = 0; i < 3; i++)
            {
                var e = t.Edges[i];
                var a = t.Sites[i];
                var b = t.Sites[i + 1];
                if (!e.IsAdjacent(a) || !e.IsAdjacent(b))
                {
                    return(false);
                }
                if (e.upperSite == a)
                {
                    if (e.CcwTriangle != t)
                    {
                        return(false);
                    }
                }
                else if (e.CwTriangle != t)
                {
                    return(false);
                }
            }
            return(true);
        }
        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);
        }
Beispiel #4
0
        void TriangulatePolygon(int start, int end, List <CdtSite> polygon, CdtSite a, CdtSite b, bool reverseTrangleWhenCompare)
        {
//            if(CdtSweeper.db)
//               CdtSweeper.ShowFront(triangles,front, Enumerable.Range(start, end-start+1).Select(i=> new Ellipse(10,10,polygon[i].Point)).ToArray(), new[]{new LineSegment(a.Point,b.Point)});
            var c      = polygon[start];
            int cIndex = start;

            for (int i = start + 1; i <= end; i++)
            {
                var v = polygon[i];
                if (LocalInCircle(v, a, b, c, reverseTrangleWhenCompare))
                {
                    cIndex = i;
                    c      = v;
                }
            }
            var t = new CdtTriangle(a, b, c, createEdgeDelegate);

            triangles.Insert(t);
            addedTriangles.Add(t);
            if (start < cIndex)
            {
                TriangulatePolygon(start, cIndex - 1, polygon, a, c, reverseTrangleWhenCompare);
            }
            if (cIndex < end)
            {
                TriangulatePolygon(cIndex + 1, end, polygon, c, b, reverseTrangleWhenCompare);
            }
        }
        static bool PointBelongsToInteriorOfTriangle(Point point, CdtTriangle cdtTriangle) {
            for (int i = 0; i < 3; i++)
                if (Point.GetTriangleOrientation(cdtTriangle.Sites[i].Point, cdtTriangle.Sites[i + 1].Point,
                                                 point) != TriangleOrientation.Counterclockwise)
                    return false;

            return true;
        }
 private bool GetCenterOfDescribedCircle(CdtTriangle triangle, out Point x)
 {
     var p0 = (triangle.Sites[0].Point + triangle.Sites[1].Point) / 2;
     var p1 = p0 + (triangle.Sites[0].Point - triangle.Sites[1].Point).Rotate(-Math.PI/2);
     var p2 = (triangle.Sites[1].Point + triangle.Sites[2].Point) / 2;
     var p3 = p0 + (triangle.Sites[1].Point - triangle.Sites[2].Point).Rotate(-Math.PI/2);
     return Point.LineLineIntersection(p0, p1, p2, p3, out x);
 }
Beispiel #7
0
        static bool SeparatedByEdge(CdtTriangle triangle, int i, CdtSite site)
        {
            var e  = triangle.Edges[i];
            var s  = triangle.Sites[i + 2];
            var a0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(s.Point, e.upperSite.Point, e.lowerSite.Point));
            var a1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(site.Point, e.upperSite.Point, e.lowerSite.Point));

            return(a0 * a1 <= 0);
        }
Beispiel #8
0
 static bool SeparatedByConstrainedEdge(CdtTriangle triangle, CdtSite site)
 {
     for (int i = 0; i < 3; i++)
     {
         if (SeparatedByEdge(triangle, i, site))
         {
             return(true);
         }
     }
     return(false);
 }
 internal CdtSweeper(List<CdtSite> listOfSites, CdtSite p_1, CdtSite p_2, 
     Func<CdtSite, CdtSite, CdtEdge> createEdgeDelegate) {
     this.listOfSites=listOfSites;
     var firstTriangle=new CdtTriangle(p_1, p_2, listOfSites[0], createEdgeDelegate);
     Triangles.Insert( firstTriangle );
     front.Insert(new CdtFrontElement(p_1, firstTriangle.Edges[2] ));
     front.Insert(new CdtFrontElement(listOfSites[0], firstTriangle.Edges[1]));
     this.p_1 = p_1;
     this.p_2 = p_2;
     this.createEdgeDelegate = createEdgeDelegate;
     //ShowFront();
 }
        internal static PointLocation PointLocationForTriangle(Point p, CdtTriangle triangle) {
            bool seenBoundary = false;
            for (int i = 0; i < 3; i++) {
                var area = Point.SignedDoubledTriangleArea(p, triangle.Sites[i].Point, triangle.Sites[i + 1].Point);
                if (area < -ApproximateComparer.DistanceEpsilon)
                    return PointLocation.Outside;
                if (area < ApproximateComparer.DistanceEpsilon)
                    seenBoundary = true;
            }

            return seenBoundary ? PointLocation.Boundary : PointLocation.Inside;
        }
        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);
        }
Beispiel #12
0
        //        /// <summary>
        //        /// returns CdtEdges crossed by the segment a.Point, b.Point
        //        /// </summary>
        //        /// <param name="prevA">if prevA is not a null, that means the path is passing through prevA and might need to include
        //        /// the edge containing a.Point if such exists</param>
        //        /// <param name="a"></param>
        //        /// <param name="b"></param>
        //        /// <returns></returns>
        //        internal IEnumerable<CdtEdge> GetCdtEdgesCrossedBySegment(PolylinePoint prevA, PolylinePoint a, PolylinePoint b) {
        //            count++;
        //            if (dd) {
        //                var l = new List<DebugCurve> {
        //                                                 new DebugCurve("red", new Ellipse(5, 5, a.Point)),
        //                                                 new DebugCurve("blue", new Ellipse(5, 5, b.Point)),
        //                                                 new DebugCurve("blue", new LineSegment(a.Point, b.Point))
        //                                             };
        //
        //                l.AddRange(
        //                    GetTriangles().Select(
        //                        tr => new DebugCurve(100, 1, "green", new Polyline(tr.Sites.Select(v => v.Point)) {Closed = true})));
        //                LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(l);
        //
        //            }
        //            var ret = new List<CdtEdge>();
        //            CdtEdge piercedEdge;
        //            CdtTriangle t = GetFirstTriangleAndPiercedEdge(a, b, out piercedEdge);
        //            if (ProperCrossing(a, b, piercedEdge))
        //                ret.Add(piercedEdge);
        //
        //            ret.AddRange(ContinueThreadingThroughTriangles(a,b,t, piercedEdge));
        //
        //            return ret;
        //        }

        /*
         *      static bool ProperCrossing(Point a, Point b, CdtEdge cdtEdge) {
         *          return cdtEdge != null && cdtEdge.upperSite.Owner != cdtEdge.lowerSite.Owner &&
         *                 CrossEdgeInterior(cdtEdge, a, b);
         *      }
         */
        //        static int count;
        //        static bool db { get { return count == 125; }}

        /*
         *      static CdtEdge GetPiercedEdge(Point a, Point b, CdtTriangle triangle) {
         *          Debug.Assert(!triangle.Sites.Any(s=>ApproximateComparer.Close(a, s.Point)));
         *          var a0 = Point.GetTriangleOrientation(a, triangle.Sites[0].Point, triangle.Sites[1].Point);
         *          if (a0 == TriangleOrientation.Clockwise)return null;
         *
         *          var a1 = Point.GetTriangleOrientation(a,triangle.Sites[1].Point, triangle.Sites[2].Point);
         *          if (a1 == TriangleOrientation.Clockwise)return null;
         *
         *          var a2 = Point.GetTriangleOrientation(a,triangle.Sites[2].Point, triangle.Sites[3].Point);
         *          if (a2 == TriangleOrientation.Clockwise)return null;
         *
         *          if (a0 == TriangleOrientation.Counterclockwise &&
         *              Point.GetTriangleOrientation(b, triangle.Sites[0].Point, triangle.Sites[1].Point) == TriangleOrientation.Clockwise)
         *              return triangle.Edges[0];
         *          if (a1 == TriangleOrientation.Counterclockwise &&
         *              Point.GetTriangleOrientation(b, triangle.Sites[1].Point, triangle.Sites[2].Point) == TriangleOrientation.Clockwise)
         *              return triangle.Edges[1];
         *          if (a2 == TriangleOrientation.Counterclockwise &&
         *              Point.GetTriangleOrientation(b, triangle.Sites[2].Point, triangle.Sites[3].Point) == TriangleOrientation.Clockwise)
         *              return triangle.Edges[2];
         *
         *          return null;
         *      }
         */

        /*
         *      static bool CheckIntersectionStartingFromSide(int i, CdtTriangle triangle, Point a, Point b) {
         *          var edgeDir = triangle.Sites[i + 1].Point - triangle.Sites[i].Point;
         *          var edgePerp = edgeDir.Rotate90Ccw();
         *          return ((b - a)*edgePerp)*((triangle.Sites[i + 2].Point - a)*edgePerp) > 0;
         *      }
         */

        internal static bool PointIsInsideOfTriangle(Point point, CdtTriangle t)
        {
            for (int i = 0; i < 3; i++)
            {
                var a = t.Sites[i].Point;
                var b = t.Sites[i + 1].Point;
                if (Point.SignedDoubledTriangleArea(point, a, b) < -ApproximateComparer.DistanceEpsilon)
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// returns null iff the edge overlap an obstacle
        /// </summary>
        Dictionary<Polyline, Tuple<Point, Point>> FindCloseObstaclesForBundle(CdtTriangle startTriangle, Point start,
                                                                              Point end, Set<Polyline> obstaclesToIgnore,
                                                                              double upperBound) {
            var obstacles = new Dictionary<Polyline, Tuple<Point, Point>>();
            List<CdtTriangle> list;
            if (!ThreadLineSegmentThroughTriangles(startTriangle, start, end, obstaclesToIgnore, out list))
                return null;

            if (!ComputeForcesForBundles && !bundlingSettings.HighestQuality)
                return obstacles;

            var checkedSites = new HashSet<CdtSite>();

            foreach (var t in list) {
                foreach (var s in t.Sites) {
                    if (!checkedSites.Add(s)) continue;

                    var poly = (Polyline) s.Owner;
                    if (obstaclesToIgnore.Contains(poly)) continue;

                    PolylinePoint pp = FindPolylinePoint(poly, s.Point);
                    double par11, par12, par21, par22;
                    double d12 = LineSegment.MinDistBetweenLineSegments(pp.Point, pp.NextOnPolyline.Point, start, end,
                                                                  out par11, out par12);
                    double d22 = LineSegment.MinDistBetweenLineSegments(pp.Point, pp.PrevOnPolyline.Point, start, end,
                                                                  out par21, out par22);
                    Point r1, r2;
                    double dist;
                    if (d12 < d22) {
                        dist = d12;
                        if (dist > upperBound) continue;
                        r1 = pp.Point + (pp.NextOnPolyline.Point - pp.Point)*par11;
                        r2 = start + (end - start)*par12;
                    }
                    else {
                        dist = d22;
                        if (dist > upperBound) continue;
                        r1 = pp.Point + (pp.PrevOnPolyline.Point - pp.Point)*par21;
                        r2 = start + (end - start)*par22;
                    }
                    //if (dist > upperBound) continue;

                    Tuple<Point, Point> currentValue;
                    if (!obstacles.TryGetValue(poly, out currentValue))
                        obstacles.Add(poly, new Tuple<Point, Point>(r1, r2));
                }
            }

            return obstacles;
        }
        internal CdtSweeper(List <CdtSite> listOfSites, CdtSite p_1, CdtSite p_2,
                            Func <CdtSite, CdtSite, CdtEdge> createEdgeDelegate)
        {
            this.listOfSites = listOfSites;
            var firstTriangle = new CdtTriangle(p_1, p_2, listOfSites[0], createEdgeDelegate);

            Triangles.Insert(firstTriangle);
            front.Insert(new CdtFrontElement(p_1, firstTriangle.Edges[2]));
            front.Insert(new CdtFrontElement(listOfSites[0], firstTriangle.Edges[1]));
            this.p_1 = p_1;
            this.p_2 = p_2;
            this.createEdgeDelegate = createEdgeDelegate;
            //ShowFront();
        }
        void AddVoronoiCite(CdtTriangle triangle)
        {
            Point p;
            var goodTriangle = GetCenterOfDescribedCircle(triangle, out p);
            if (!goodTriangle)
                return;
            if (!BoundingBox.Contains(p))
                return;
            var rect=new Rectangle(p);
            rect.Pad(eps);
            if (voronoiSiteTree.GetAllIntersecting(rect).Count() > 0)
                return;

            voronoiSiteTree.Add(rect, p);
        }
 void RemovePiercedTriangle(CdtTriangle t)
 {
     triangles.Remove(t);
     foreach (var e in t.Edges)
     {
         if (e.CwTriangle == t)
         {
             e.CwTriangle = null;
         }
         else
         {
             e.CcwTriangle = null;
         }
     }
     removedTriangles.Add(t);
 }
Beispiel #17
0
        static void ShowFlip(CdtSite pi, CdtTriangle t, CdtTriangle ot)
        {
            List <DebugCurve> ls = new List <DebugCurve>();

            ls.Add(new DebugCurve(new Ellipse(2, 2, pi.Point)));
            for (int i = 0; i < 3; i++)
            {
                var e = t.Edges[i];
                ls.Add(new DebugCurve(100, 1, "red", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
            }
            for (int i = 0; i < 3; i++)
            {
                var e = ot.Edges[i];
                ls.Add(new DebugCurve(100, 1, "blue", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
            }
            ls.Add(new DebugCurve(Circumcircle(t.Sites[0].Point, t.Sites[1].Point, t.Sites[2].Point)));
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
        }
Beispiel #18
0
 internal static void RemoveTriangleWithEdges(Set <CdtTriangle> cdtTriangles, CdtTriangle t)
 {
     cdtTriangles.Remove(t);
     foreach (var e in t.Edges)
     {
         if (e.CwTriangle == t)
         {
             e.CwTriangle = null;
         }
         else
         {
             e.CcwTriangle = null;
         }
         if (e.CwTriangle == null && e.CcwTriangle == null)
         {
             e.upperSite.Edges.Remove(e);
         }
     }
 }
Beispiel #19
0
        void TestTriangle(CdtTriangle triangle, Set <CdtSite> usedSites)
        {
            var tsites = triangle.Sites;

            foreach (var site in usedSites)
            {
                if (!tsites.Contains(site))
                {
                    if (!SeparatedByConstrainedEdge(triangle, site) && InCircle(site, tsites[0], tsites[1], tsites[2]))
                    {
                        List <ICurve> redCurves = new List <ICurve>();
                        redCurves.Add(new Ellipse(2, 2, site.Point));
                        List <ICurve> blueCurves = new List <ICurve>();
                        blueCurves.Add(Circumcircle(tsites[0].Point, tsites[1].Point, tsites[2].Point));
                        ShowFront(Triangles, front, redCurves, blueCurves);
                    }
                }
            }
        }
        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;
                }
            }
        }
        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;
                    }
                }
            }
        }
        void TriangulatePolygon(int start, int end, List<CdtSite> polygon, CdtSite a, CdtSite b, bool reverseTrangleWhenCompare) {
//            if(CdtSweeper.db)
//               CdtSweeper.ShowFront(triangles,front, Enumerable.Range(start, end-start+1).Select(i=> new Ellipse(10,10,polygon[i].Point)).ToArray(), new[]{new LineSegment(a.Point,b.Point)});
            var c = polygon[start];
            int cIndex = start;
            for (int i = start + 1; i <= end; i++) {
                var v = polygon[i];
                if (LocalInCircle(v, a, b, c, reverseTrangleWhenCompare)) {
                    cIndex = i;
                    c = v;
                }
            }
            var t = new CdtTriangle(a, b, c, createEdgeDelegate);
            triangles.Insert(t);
            addedTriangles.Add(t);
            if (start < cIndex)
                TriangulatePolygon(start, cIndex - 1, polygon, a, c, reverseTrangleWhenCompare);
            if (cIndex < end)
                TriangulatePolygon(cIndex + 1, end, polygon, c, b, reverseTrangleWhenCompare);
        }
Beispiel #23
0
        /// <summary>
        /// aNode is to the left of bNode, and they are consecutive
        /// </summary>
        /// <param name="aNode"></param>
        /// <param name="bNode"></param>
        RBNode <CdtFrontElement> ShortcutTwoFrontElements(RBNode <CdtFrontElement> aNode, RBNode <CdtFrontElement> bNode)
        {
            var aElem = aNode.Item;
            var bElem = bNode.Item;

            Debug.Assert(aElem.RightSite == bElem.LeftSite);
            CdtTriangle t = new CdtTriangle(aElem.LeftSite, aElem.RightSite, bElem.RightSite, aElem.Edge, bElem.Edge,
                                            createEdgeDelegate);

            Triangles.Insert(t);
            front.DeleteNodeInternal(aNode);
            //now bNode might b not valid anymore
            front.Remove(bElem);
            var newEdge = t.Edges[2];

            Debug.Assert(newEdge.IsAdjacent(aElem.LeftSite) && newEdge.IsAdjacent(bElem.RightSite));
            LegalizeEdge(aElem.LeftSite, t.OppositeEdge(aElem.LeftSite));
            t = newEdge.CcwTriangle ?? newEdge.CwTriangle;
            LegalizeEdge(bElem.RightSite, t.OppositeEdge(bElem.RightSite));
            return(front.Insert(new CdtFrontElement(aElem.LeftSite, newEdge)));
        }
        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));
        }
        void PrepareNextStateAfterPiercedEdge()
        {
            var t      = piercedEdge.CwTriangle ?? piercedEdge.CcwTriangle;
            var eIndex = t.Edges.Index(piercedEdge);

            for (int i = 1; i <= 2; i++)
            {
                var e           = t.Edges[i + eIndex];
                var signedArea0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(e.lowerSite.Point, a.Point, b.Point));
                var signedArea1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(e.upperSite.Point, a.Point, b.Point));
                if (signedArea1 * signedArea0 <= 0)
                {
                    if (e.CwTriangle != null && e.CcwTriangle != null)
                    {
                        piercedTriangle = t;
                        piercedEdge     = e;
                        break;
                    }
                    //e has to belong to the front, and its triangle has to be removed
                    piercedTriangle = null;
                    piercedEdge     = null;
                    var leftSite  = e.upperSite.Point.X < e.lowerSite.Point.X ? e.upperSite : e.lowerSite;
                    var frontElem = CdtSweeper.FindNodeInFrontBySite(front, leftSite);
                    Debug.Assert(frontElem != null);
                    if (leftSite.Point.X < a.Point.X)
                    {
                        piercedToTheLeftFrontElemNode = frontElem;
                    }
                    else
                    {
                        piercedToTheRightFrontElemNode = frontElem;
                    }

                    RemovePiercedTriangle(e.CwTriangle ?? e.CcwTriangle);
                    break;
                }
            }
        }
Beispiel #26
0
 void InsertAndLegalizeTriangle(CdtSite pi, CdtFrontElement frontElement)
 {
     if (Point.GetTriangleOrientationWithNoEpsilon(pi.Point, frontElement.LeftSite.Point, frontElement.RightSite.Point) != TriangleOrientation.Collinear)
     {
         var tr = new CdtTriangle(pi, frontElement.Edge, createEdgeDelegate);
         Triangles.Insert(tr);
         LegalizeEdge(pi, tr.Edges[0]);
     }
     else     //we need to split the triangle below the element in to two triangles and legalize the old edges
     //we also delete, that is forget, the frontElement.Edge
     {
         var e = frontElement.Edge;
         e.upperSite.Edges.Remove(e);
         var t            = e.CcwTriangle ?? e.CwTriangle;
         var oppositeSite = t.OppositeSite(e);
         RemoveTriangleButLeaveEdges(triangles, t);
         t = new CdtTriangle(frontElement.LeftSite, oppositeSite, pi, createEdgeDelegate);
         var t1 = new CdtTriangle(frontElement.RightSite, oppositeSite, pi, createEdgeDelegate);
         triangles.Insert(t);
         triangles.Insert(t1);
         LegalizeEdge(pi, t.OppositeEdge(pi));
         LegalizeEdge(pi, t1.OppositeEdge(pi));
     }
 }
        static bool CheckTriangle(CdtTriangle t) {
            if (Point.GetTriangleOrientationWithNoEpsilon(t.Sites[0].Point, t.Sites[1].Point, t.Sites[2].Point) != TriangleOrientation.Counterclockwise) {
                return false;
            }
            for (int i = 0; i < 3; i++) {
                var e = t.Edges[i];
                var a = t.Sites[i];
                var b = t.Sites[i+1];
                if (!e.IsAdjacent(a) || !e.IsAdjacent(b)) return false;
                if (e.upperSite == a) {
                    if (e.CcwTriangle != t)
                        return false;
                }
                else if (e.CwTriangle != t)
                    return false;

            }
            return true;
        }
        CdtEdge GetPiercedEdgeInSiteTriangle(CdtTriangle t, CdtSite site, Point target)
        {
            var e = t.OppositeEdge(site);

            return(PiercedEdgeQuery(e, site.Point, target, t));
        }
 void TestTriangle(CdtTriangle triangle, Set<CdtSite> usedSites) {
     var tsites=triangle.Sites;
     foreach (var site in usedSites) {
         if (!tsites.Contains(site)) {
             if (!SeparatedByConstrainedEdge(triangle, site) && InCircle(site, tsites[0], tsites[1], tsites[2])) {
                 List<ICurve> redCurves=new List<ICurve>();
                 redCurves.Add(new Ellipse(2, 2, site.Point));
                 List<ICurve> blueCurves = new List<ICurve>();
                 blueCurves.Add(Circumcircle(tsites[0].Point,tsites[1].Point,tsites[2].Point));
                 ShowFront(Triangles, front, redCurves, blueCurves);
             }
         }
     }
 }
 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);
 }
 static bool SeparatedByConstrainedEdge(CdtTriangle triangle, CdtSite site) {
     for (int i = 0; i < 3; i++)
         if (SeparatedByEdge(triangle, i, site))
             return true;
     return false;
 }
 static internal HitTestBehavior Test(Point pnt, CdtTriangle t) {
     return Cdt.PointIsInsideOfTriangle(pnt, t) ? HitTestBehavior.Stop : HitTestBehavior.Continue;
 }
 static bool SeparatedByEdge(CdtTriangle triangle, int i, CdtSite site) {
     var e = triangle.Edges[i];
     var s = triangle.Sites[i+2];
     var a0 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(s.Point, e.upperSite.Point, e.lowerSite.Point));
     var a1 = ApproximateComparer.Sign(Point.SignedDoubledTriangleArea(site.Point, e.upperSite.Point, e.lowerSite.Point));
     return a0 * a1 <= 0;
 }
        void InsertAndLegalizeTriangle(CdtSite pi, CdtFrontElement frontElement) {
            if (Point.GetTriangleOrientationWithNoEpsilon(pi.Point, frontElement.LeftSite.Point, frontElement.RightSite.Point) != TriangleOrientation.Collinear) {
                var tr = new CdtTriangle(pi, frontElement.Edge, createEdgeDelegate);
                Triangles.Insert(tr);
                LegalizeEdge(pi, tr.Edges[0]);
            } else { //we need to split the triangle below the element in to two triangles and legalize the old edges 
                //we also delete, that is forget, the frontElement.Edge
                var e = frontElement.Edge;
                e.upperSite.Edges.Remove(e);
                var t=e.CcwTriangle??e.CwTriangle;
                var oppositeSite = t.OppositeSite(e);
                RemoveTriangleButLeaveEdges(triangles, t);
                t=new CdtTriangle(frontElement.LeftSite, oppositeSite, pi, createEdgeDelegate);
                var t1 = new CdtTriangle(frontElement.RightSite, oppositeSite, pi, createEdgeDelegate);
                triangles.Insert(t);
                triangles.Insert(t1);
                LegalizeEdge(pi, t.OppositeEdge(pi));
                LegalizeEdge(pi,t1.OppositeEdge(pi));
            }

        }
 /// <summary>
 /// aNode is to the left of bNode, and they are consecutive
 /// </summary>
 /// <param name="aNode"></param>
 /// <param name="bNode"></param>
 RBNode<CdtFrontElement> ShortcutTwoFrontElements(RBNode<CdtFrontElement> aNode, RBNode<CdtFrontElement> bNode) {
     var aElem = aNode.Item;
     var bElem = bNode.Item;
     Debug.Assert(aElem.RightSite == bElem.LeftSite);
     CdtTriangle t = new CdtTriangle(aElem.LeftSite, aElem.RightSite, bElem.RightSite, aElem.Edge, bElem.Edge,
                                     createEdgeDelegate);
     Triangles.Insert(t);
     front.DeleteNodeInternal(aNode); 
     //now bNode might b not valid anymore
     front.Remove(bElem);
     var newEdge = t.Edges[2];
     Debug.Assert(newEdge.IsAdjacent( aElem.LeftSite) && newEdge.IsAdjacent(bElem.RightSite));
     LegalizeEdge(aElem.LeftSite, t.OppositeEdge(aElem.LeftSite));
     t=newEdge.CcwTriangle ?? newEdge.CwTriangle;
     LegalizeEdge(bElem.RightSite, t.OppositeEdge(bElem.RightSite));
     return front.Insert(new CdtFrontElement(aElem.LeftSite, newEdge));          
 }
 PerimeterEdge ShortcutTwoListElements(PerimeterEdge a) {
     var b = a.Next;
     Debug.Assert(a.End == b.Start);
     var t = new CdtTriangle(a.Start, a.End, b.End, a.Edge, b.Edge,
                                     createEdgeDelegate);
     Triangles.Insert(t);
     var newEdge = t.Edges[2];
     Debug.Assert(newEdge.IsAdjacent(a.Start) && newEdge.IsAdjacent(b.End));
     LegalizeEdge(a.Start, t.OppositeEdge(a.Start));
     t = newEdge.CcwTriangle ?? newEdge.CwTriangle;
     LegalizeEdge(b.End, t.OppositeEdge(b.End));
     var c = new PerimeterEdge(newEdge) { Start = a.Start, End = b.End };
     a.Prev.Next = c;
     c.Prev = a.Prev;
     c.Next = b.Next;
     b.Next.Prev = c;
     return c;
 }
        private void AddTriangleToCanvas(CdtTriangle t) {
            var color = new System.Windows.Media.Color();
            color.A = 100;
            color.B = 255;
            var wpfTriangle = new Polygon {
                Stroke = new SolidColorBrush(color),
                StrokeEndLineCap = PenLineCap.Round,
                StrokeStartLineCap = PenLineCap.Round,
                StrokeLineJoin = PenLineJoin.Round,
                StrokeThickness = scroller.GetScale()
            };

            

            
            PointCollection trianglePoints = new PointCollection();
            trianglePoints.Add(ToWpfPoint( t.Sites[0].Point));
            trianglePoints.Add(ToWpfPoint(t.Sites[1].Point));
            trianglePoints.Add(ToWpfPoint(t.Sites[2].Point));
            wpfTriangle.Points = trianglePoints;
            diagram.Canvas.Children.Add(wpfTriangle);

           
        }
  internal static void RemoveTriangleButLeaveEdges(Set<CdtTriangle> cdtTriangles, CdtTriangle t) {
     cdtTriangles.Remove(t);
     foreach (var e in t.Edges) 
         if (e.CwTriangle == t)
             e.CwTriangle = null;
         else 
             e.CcwTriangle = null;                          
 }
 ///<summary>
 ///</summary>
 ///<param name="triangle"></param>
 ///<returns></returns>
 public CdtTriangle GetOtherTriangle(CdtTriangle triangle) {
     return ccwTriangle == triangle ? cwTriangle : ccwTriangle;
 }
 internal static void RemoveTriangleWithEdges(Set<CdtTriangle> cdtTriangles, CdtTriangle t) {
      cdtTriangles.Remove(t);
      foreach (var e in t.Edges) {
          if (e.CwTriangle == t)
              e.CwTriangle = null;
          else e.CcwTriangle = null;
          if (e.CwTriangle == null && e.CcwTriangle == null)
              e.upperSite.Edges.Remove(e);
      }
  }
 CdtEdge GetPiercedEdgeInSiteTriangle(CdtTriangle t, CdtSite site, Point target) {
     var e = t.OppositeEdge(site);
     return PiercedEdgeQuery(e, site.Point, target, t);
 }
 CdtEdge PiercedEdgeQuery(CdtEdge e, Point source, Point target, CdtTriangle cdtTriangle) {
     return EdgeIsPierced(e, source, target, cdtTriangle) ? e : null;
 }
 static IEnumerable<CdtTriangle> FindStartTriangle(CdtTriangle[] trs, Point p) {
     foreach (CdtTriangle t in trs) {
         PointLocation loc = CdtIntersections.PointLocationInsideTriangle(p, t);
         if (loc != PointLocation.Outside)
             yield return t;
     }
 }
 static void AddTriangleToListOfDebugCurves(List<DebugCurve> debugCurves, CdtTriangle triangle, byte transparency,
                                            double width, string color) {
     foreach (CdtEdge cdtEdge in triangle.Edges) {
         debugCurves.Add(new DebugCurve(transparency, width, color,
                                        new LineSegment(cdtEdge.upperSite.Point, cdtEdge.lowerSite.Point)));
     }
 }
 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;
 }
 CdtEdge PiercedEdgeQuery(CdtEdge e, Point source, Point target, CdtTriangle cdtTriangle)
 {
     return(EdgeIsPierced(e, source, target, cdtTriangle) ? e : null);
 }
        /*
                static CdtEdge GetPiercedEdge(Point a, Point b, CdtTriangle triangle) {
                    Debug.Assert(!triangle.Sites.Any(s=>ApproximateComparer.Close(a, s.Point)));
                    var a0 = Point.GetTriangleOrientation(a, triangle.Sites[0].Point, triangle.Sites[1].Point);
                    if (a0 == TriangleOrientation.Clockwise)return null;

                    var a1 = Point.GetTriangleOrientation(a,triangle.Sites[1].Point, triangle.Sites[2].Point);
                    if (a1 == TriangleOrientation.Clockwise)return null;

                    var a2 = Point.GetTriangleOrientation(a,triangle.Sites[2].Point, triangle.Sites[3].Point);
                    if (a2 == TriangleOrientation.Clockwise)return null;
      
                    if (a0 == TriangleOrientation.Counterclockwise &&
                        Point.GetTriangleOrientation(b, triangle.Sites[0].Point, triangle.Sites[1].Point) == TriangleOrientation.Clockwise)
                        return triangle.Edges[0];
                    if (a1 == TriangleOrientation.Counterclockwise &&
                        Point.GetTriangleOrientation(b, triangle.Sites[1].Point, triangle.Sites[2].Point) == TriangleOrientation.Clockwise)
                        return triangle.Edges[1];
                    if (a2 == TriangleOrientation.Counterclockwise &&
                        Point.GetTriangleOrientation(b, triangle.Sites[2].Point, triangle.Sites[3].Point) == TriangleOrientation.Clockwise)
                        return triangle.Edges[2];

                    return null;
                }
        */

        /*
                static bool CheckIntersectionStartingFromSide(int i, CdtTriangle triangle, Point a, Point b) {
                    var edgeDir = triangle.Sites[i + 1].Point - triangle.Sites[i].Point;
                    var edgePerp = edgeDir.Rotate90Ccw();
                    return ((b - a)*edgePerp)*((triangle.Sites[i + 2].Point - a)*edgePerp) > 0;
                }
        */

        internal static bool PointIsInsideOfTriangle(Point point, CdtTriangle t) {
            for (int i = 0; i < 3; i++) {
                var a = t.Sites[i].Point;
                var b = t.Sites[i + 1].Point;
                if (Point.SignedDoubledTriangleArea(point, a, b) < -ApproximateComparer.DistanceEpsilon)
                    return false;
            }
            return true;
        }
 private void FillRemovedConnectedRegion(CdtTriangle t, Set<CdtTriangle> removedTriangles) {
     if (removedTriangles.Contains(t))
         return;
     var q = new Queue<CdtTriangle>();
     q.Enqueue(t);
     while (q.Count > 0) {
         t = q.Dequeue();
         removedTriangles.Insert(t);
         foreach(var e in t.Edges)
             if (!e.Constrained) {
                 var tr = e.GetOtherTriangle(t);
                 if (tr!=null && !removedTriangles.Contains(tr))
                     q.Enqueue(tr);
             }
     }
 }
 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);
 }
Beispiel #50
0
 internal static void RemoveTriangleButLeaveEdges(Set <CdtTriangle> cdtTriangles, CdtTriangle t)
 {
     cdtTriangles.Remove(t);
     foreach (var e in t.Edges)
     {
         if (e.CwTriangle == t)
         {
             e.CwTriangle = null;
         }
         else
         {
             e.CcwTriangle = null;
         }
     }
 }
 static void ShowFlip(CdtSite pi, CdtTriangle t, CdtTriangle ot) {
     List<DebugCurve> ls=new List<DebugCurve>();
     ls.Add(new DebugCurve(new Ellipse(2,2, pi.Point)));
     for(int i=0;i<3;i++) {
         var e=t.Edges[i];
         ls.Add(new DebugCurve(100, 1, "red", new LineSegment(e.upperSite.Point,e.lowerSite.Point)));
     }
     for (int i = 0; i < 3; i++)
     {
         var e = ot.Edges[i];
         ls.Add(new DebugCurve(100, 1, "blue", new LineSegment(e.upperSite.Point, e.lowerSite.Point)));
     }
     ls.Add(new DebugCurve(Circumcircle(t.Sites[0].Point, t.Sites[1].Point, t.Sites[2].Point)));
     LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(ls);
 }
        static List<DebugCurve> ThreadOnTriangle(Point start, Point end, CdtTriangle t) {
            var l = new List<DebugCurve> {new DebugCurve(10, "red", new LineSegment(start, end))};
            AddTriangleToListOfDebugCurves(l, t, 100, 3, "brown");
            var threader = new CdtThreader(t, start, end);
            foreach (var triangle in threader.Triangles()) {
                AddTriangleToListOfDebugCurves(l, triangle, 100, 3, "black");
//                CdtSweeper.ShowFront(trs, null, new ICurve[] { new LineSegment(start, end), new Polyline(triangle.Sites.Select(s => s.Point)) { Closed = true } }, new []{new LineSegment(threader.CurrentPiercedEdge.lowerSite.Point,threader.CurrentPiercedEdge.upperSite.Point) });
            }
            return l;
        }