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