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); } } } } }
public void CdtTriangleCreationTest() { var a = new CdtSite(new Point()); var b = new CdtSite(new Point(2, 0)); var c = new CdtSite(new Point(1, 2)); var tri = new CdtTriangle(a, b, c, Cdt.GetOrCreateEdge); var e = tri.Edges[0]; Assert.IsTrue(e.upperSite == a); Assert.IsTrue(e.lowerSite == b); Assert.IsTrue(e.CcwTriangle == tri && e.CwTriangle == null); e = tri.Edges[1]; Assert.IsTrue(e.upperSite == c); Assert.IsTrue(e.lowerSite == b); Assert.IsTrue(e.CwTriangle == tri && e.CcwTriangle == null); e = tri.Edges[2]; Assert.IsTrue(e.upperSite == c); Assert.IsTrue(e.lowerSite == a); Assert.IsTrue(e.CcwTriangle == tri && e.CwTriangle == null); var tri0 = new CdtTriangle(new CdtSite(new Point(2, 2)), tri.Edges[1], Cdt.GetOrCreateEdge); Assert.IsTrue(tri0.Edges[0] == tri.Edges[1]); Assert.IsTrue(tri.Edges[1].CcwTriangle != null && tri.Edges[1].CwTriangle != null); }
internal CdtThreader(CdtTriangle startTriangle, Point start, Point end) { Debug.Assert(PointLocationForTriangle(start, startTriangle) != PointLocation.Outside); currentTriangle = startTriangle; this.start = start; this.end = end; }
/// <summary> /// checks if an edge intersects obstacles /// otherwise it calulates distances to the closest obstacles /// </summary> internal bool EdgeIsLegal(Station v, Station u, Point vPosition, Point uPosition, Set <Polyline> obstaclesToIgnore) { var start = v.Position; CdtTriangle currentTriangle = v.CdtTriangle; Debug.Assert(Cdt.PointIsInsideOfTriangle(start, currentTriangle)); Point end = u.Position; if (Cdt.PointIsInsideOfTriangle(end, currentTriangle)) { return(true); } var threader = new CdtThreader(currentTriangle, start, end); while (threader.MoveNext()) { var piercedEdge = threader.CurrentPiercedEdge; if (piercedEdge.Constrained) { Debug.Assert(piercedEdge.lowerSite.Owner == piercedEdge.upperSite.Owner); var poly = (Polyline)piercedEdge.lowerSite.Owner; if (!obstaclesToIgnore.Contains(poly)) { return(false); } } } return(true); }
Dictionary <Polyline, double> FindCloseObstaclesForHub(CdtTriangle startTriangle, Point start, Point end, Set <Polyline> obstaclesToIgnore, double upperBound) { var obstacles = new Dictionary <Polyline, double>(); List <CdtTriangle> nearestTriangles; if (!ThreadLineSegmentThroughTriangles(startTriangle, start, end, obstaclesToIgnore, out nearestTriangles)) { return(null); } var checkedSites = new HashSet <CdtSite>(); foreach (var t in nearestTriangles) { foreach (var s in t.Sites) { CheckSite(end, obstaclesToIgnore, checkedSites, s, upperBound, obstacles); var edge = t.OppositeEdge(s); var ot = edge.GetOtherTriangle(t); if (ot != null) { CheckSite(end, obstaclesToIgnore, checkedSites, ot.OppositeSite(edge), upperBound, obstacles); } } } return(obstacles); }
private static void ThreadOnTriangle(Point start, Point end, CdtTriangle t) { var threader = new CdtThreader(t, start, end); while (threader.MoveNext()) { } }
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 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))); } }
/// <summary> /// returns false iff the edge overlap an obstacle /// </summary> bool ThreadLineSegmentThroughTriangles(CdtTriangle currentTriangle, Point start, Point end, Set <Polyline> obstaclesToIgnore, out List <CdtTriangle> triangles) { Debug.Assert(Cdt.PointIsInsideOfTriangle(start, currentTriangle)); triangles = new List <CdtTriangle>(); if (Cdt.PointIsInsideOfTriangle(end, currentTriangle)) { triangles.Add(currentTriangle); return(true); } var threader = new CdtThreader(currentTriangle, start, end); triangles.Add(currentTriangle); while (threader.MoveNext()) { triangles.Add(threader.CurrentTriangle); var piercedEdge = threader.CurrentPiercedEdge; if (piercedEdge.Constrained) { Debug.Assert(piercedEdge.lowerSite.Owner == piercedEdge.upperSite.Owner); var poly = (Polyline)piercedEdge.lowerSite.Owner; if (!obstaclesToIgnore.Contains(poly)) { return(false); } } } if (threader.CurrentTriangle != null) { triangles.Add(threader.CurrentTriangle); } // // int positiveSign, negativeSign; // CdtEdge piercedEdge = FindFirstPiercedEdge(currentTriangle, start, end, out negativeSign, out positiveSign, null); // // Debug.Assert(positiveSign > negativeSign); // // Debug.Assert(piercedEdge != null); // // do { // triangles.Add(currentTriangle); // if (piercedEdge.Constrained) { // Debug.Assert(piercedEdge.lowerSite.Owner == piercedEdge.upperSite.Owner); // Polyline poly = (Polyline)piercedEdge.lowerSite.Owner; // if (!obstaclesToIgnore.Contains(poly)) return false; // } // } // while (FindNextPierced(start, end, ref currentTriangle, ref piercedEdge, ref negativeSign, ref positiveSign)); // if (currentTriangle != null) // triangles.Add(currentTriangle); return(true); }
static bool SeparatedByConstrainedEdge(CdtTriangle triangle, CdtSite site) { for (int i = 0; i < 3; i++) { if (SeparatedByEdge(triangle, i, site)) { return(true); } } return(false); }
void TryToAssigenTriangleToVertex(CdtTriangle triangle, SdVertex vertex) { if (vertex.Triangle != null) { return; } if (Cdt.PointIsInsideOfTriangle(vertex.Point, triangle)) { vertex.Triangle = triangle; } }
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); }
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); }
void StepFromTriangleInteriorPoint(CdtTriangle triangle) { if (PointBelongsToInteriorOfTriangle(segEnd.Point, triangle)) { lastCrossedFeature = triangle; return; } //we cross an edge for (int i = 0; i < 3; i++) { if (PointIsInsideCone(segEnd.Point, segStart.Point, triangle.Sites[i + 1].Point, triangle.Sites[i].Point)) { CrossTriangleEdge(triangle.Edges[i]); return; } } }
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); }
void TestTriangle(CdtTriangle triangle, Set <CdtSite> usedSites) { var tsites = triangle.Sites; foreach (var site in usedSites) { if (!tsites.Contains(site)) { Assert.IsTrue(SeparatedByConstrainedEdge(triangle, site) || !CdtSweeper.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); // } } } }
static object TryCreateFeatureWhichIsNotSite(PolylinePoint pp, CdtTriangle triangle) { Debug.Assert(!triangle.Sites.Any(s => ApproximateComparer.Close(pp.Point, s.Point))); var a0 = Point.GetTriangleOrientation(pp.Point, triangle.Sites[0].Point, triangle.Sites[1].Point); if (a0 == TriangleOrientation.Clockwise) { return(null); } var a1 = Point.GetTriangleOrientation(pp.Point, triangle.Sites[1].Point, triangle.Sites[2].Point); if (a1 == TriangleOrientation.Clockwise) { return(null); } var a2 = Point.GetTriangleOrientation(pp.Point, triangle.Sites[2].Point, triangle.Sites[3].Point); if (a2 == TriangleOrientation.Clockwise) { return(null); } if (a0 == TriangleOrientation.Counterclockwise && a1 == TriangleOrientation.Counterclockwise && a2 == TriangleOrientation.Counterclockwise) { return(triangle); } if (a0 == TriangleOrientation.Collinear) { return(triangle.Edges[0]); } if (a1 == TriangleOrientation.Collinear) { return(triangle.Edges[1]); } Debug.Assert(a2 == TriangleOrientation.Collinear); return(triangle.Edges[2]); }
void RegularStepFromSite(CdtSite site) { CdtTriangle triangle = null; foreach (var t in site.Triangles) { int index = t.Sites.Index(site); if (PointIsInsideCone(segEnd.Point, site.Point, t.Sites[index + 2].Point, t.Sites[index + 1].Point)) { triangle = t; var segEndOrientation = Point.GetTriangleOrientation(segEnd.Point, t.Sites[index + 1].Point, t.Sites[index + 2].Point); if (segEndOrientation != TriangleOrientation.Counterclockwise) { CrossTriangleEdge(t.OppositeEdge(site)); return; } } } if (triangle == null) { lastCrossedFeature = OutsideOfTriangulation; return; } if (PointBelongsToInteriorOfTriangle(segEnd.Point, triangle)) { lastCrossedFeature = triangle; } else { foreach (var e in triangle.Edges.Where(e => e.IsAdjacent(site))) { if (Point.GetTriangleOrientation(e.upperSite.Point, e.lowerSite.Point, segEnd.Point) == TriangleOrientation.Collinear) { lastCrossedFeature = e; return; } } } }
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); }
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); }
/// <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 = Point.MinDistBetweenLineSegments(pp.Point, pp.NextOnPolyline.Point, start, end, out par11, out par12); double d22 = Point.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); }
///<summary> ///</summary> ///<param name="triangle"></param> ///<returns></returns> public CdtTriangle GetOtherTriangle(CdtTriangle triangle) { return(ccwTriangle == triangle ? cwTriangle : ccwTriangle); }
internal void FindNextPierced() { Debug.Assert(negativeSign < positiveSign); /*List<DebugCurve> l = null; * if (db) { * l = new List<DebugCurve>(); * l.Add(new DebugCurve(0.05, "red", new LineSegment(start, end))); * l.Add(new DebugCurve(0.05, "blue", new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point))); * l.Add(new DebugCurve(new Ellipse(3, 3, end))); * * var ii = currentTriangle.Edges.Index(piercedEdge); * for (int j = ii + 1; j <= ii + 2; j++) * l.Add(new DebugCurve(0.05, "brown", new LineSegment(currentTriangle.Edges[j].upperSite.Point, currentTriangle.Edges[j].lowerSite.Point))); * }*/ currentTriangle = currentPiercedEdge.GetOtherTriangle(currentTriangle); // ShowDebug(null,currentPiercedEdge,currentTriangle); /* if (db) { * for (int j = 0; j <= 2; j++) { * var piercedEdge = currentTriangle.Edges[j]; * if (piercedEdge == piercedEdge) continue; * l.Add(new DebugCurve(0.05, new LineSegment(piercedEdge.upperSite.Point, piercedEdge.lowerSite.Point))); * } * * LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(l.ToArray()); * }*/ if (currentTriangle == null) { currentPiercedEdge = null; return; } var i = currentTriangle.Edges.Index(currentPiercedEdge); int j; //pierced index var oppositeSite = currentTriangle.Sites[i + 2]; var oppositeSiteSign = GetHyperplaneSign(oppositeSite); if (negativeSign == 0) { Debug.Assert(positiveSign == 1); if (oppositeSiteSign == -1 || oppositeSiteSign == 0) { negativeSign = oppositeSiteSign; j = i + 1; } else { j = i + 2; } } else if (positiveSign == 0) { Debug.Assert(negativeSign == -1); if (oppositeSiteSign == 1 || oppositeSiteSign == 0) { positiveSign = oppositeSiteSign; j = i + 2; } else { j = i + 1; } } else if (oppositeSiteSign != positiveSign) { negativeSign = oppositeSiteSign; j = i + 1; } else { Debug.Assert(negativeSign != oppositeSiteSign); positiveSign = oppositeSiteSign; j = i + 2; } currentPiercedEdge = Point.SignedDoubledTriangleArea(end, currentTriangle.Sites[j].Point, currentTriangle.Sites[j + 1].Point) < -ApproximateComparer.DistanceEpsilon ? currentTriangle.Edges[j] : null; // ShowDebug(null,currentPiercedEdge, currentTriangle); }
static internal HitTestBehavior Test(Point pnt, CdtTriangle t) { return(Cdt.PointIsInsideOfTriangle(pnt, t) ? HitTestBehavior.Stop : HitTestBehavior.Continue); }