private static bool EdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point) { TriangulationPoint p1, p2; if (tcx.IsDebugEnabled) { tcx.DTDebugContext.PrimaryTriangle = triangle; } if (IsEdgeSideOfTriangle(triangle, ep, eq)) { return(true); } if (triangle == null) { return(false); } p1 = triangle.PointCCWFrom(point); Orientation o1 = TriangulationUtil.Orient2d(eq, p1, ep); if (o1 == Orientation.Collinear) { // TODO: Split edge in two //SplitEdge(ep, eq, p1); //EdgeEvent(tcx, p1, eq, triangle, point); //EdgeEvent(tcx, ep, p1, triangle, p1); //return; //throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet",eq,p1,ep); return(false); } p2 = triangle.PointCWFrom(point); Orientation o2 = TriangulationUtil.Orient2d(eq, p2, ep); if (o2 == Orientation.Collinear) { // TODO: Split edge in two //SplitEdge(ep, eq, p2); //EdgeEvent(tcx, p2, eq, triangle, point); //EdgeEvent(tcx, ep, p2, triangle, p2); //return; //throw new PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet",eq,p2,ep); return(false); } if (o1 == o2) { // Need to decide if we are rotating CW or CCW to get to a triangle // that will cross edge if (o1 == Orientation.CW) { triangle = triangle.NeighborCCWFrom(point); } else { triangle = triangle.NeighborCWFrom(point); } return(EdgeEvent(tcx, ep, eq, triangle, point)); } else { // This triangle crosses constraint so lets flippin start! return(FlipEdgeEvent(tcx, ep, eq, triangle, point)); } }
private static bool FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p) { DelaunayTriangle ot = t.NeighborAcrossFrom(p); TriangulationPoint op = ot != null?ot.OppositePoint(t, p) : null; if (ot == null) { // If we want to integrate the fillEdgeEvent do it here // With current implementation we should never get here //throw new InvalidOperationException("[BUG:FIXME] FLIP failed due to missing triangle"); return(false); } if (tcx.IsDebugEnabled) { tcx.DTDebugContext.PrimaryTriangle = t; tcx.DTDebugContext.SecondaryTriangle = ot; } // TODO: remove bool inScanArea = TriangulationUtil.InScanArea(p, t.PointCCWFrom(p), t.PointCWFrom(p), op); if (inScanArea) { // Lets rotate shared edge one vertex CW RotateTrianglePair(t, p, ot, op); tcx.MapTriangleToNodes(t); tcx.MapTriangleToNodes(ot); if (p == eq && op == ep) { if (eq == tcx.EdgeEvent.ConstrainedEdge.Q && ep == tcx.EdgeEvent.ConstrainedEdge.P) { if (tcx.IsDebugEnabled) { Console.WriteLine("[FLIP] - constrained edge done"); // TODO: remove } t.MarkConstrainedEdge(ep, eq); ot.MarkConstrainedEdge(ep, eq); Legalize(tcx, t); Legalize(tcx, ot); } else { if (tcx.IsDebugEnabled) { Console.WriteLine("[FLIP] - subedge done"); // TODO: remove } // XXX: I think one of the triangles should be legalized here? } } else { if (tcx.IsDebugEnabled) { Console.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge"); // TODO: remove } Orientation o = TriangulationUtil.Orient2d(eq, op, ep); t = NextFlipTriangle(tcx, o, t, ot, p, op); return(FlipEdgeEvent(tcx, ep, eq, t, p)); } } else { TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op); var v_sucess = FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP); if (v_sucess) { v_sucess = EdgeEvent(tcx, ep, eq, t, p); } return(v_sucess); } return(true); }
/// <summary> /// Returns true if triangle was legalized /// </summary> private static bool Legalize(DTSweepContext tcx, DelaunayTriangle t) { // To legalize a triangle we start by finding if any of the three edges // violate the Delaunay condition for (int i = 0; i < 3; i++) { // TODO: fix so that cEdge is always valid when creating new triangles then we can check it here // instead of below with ot if (t.EdgeIsDelaunay[i]) { continue; } DelaunayTriangle ot = t.Neighbors[i]; if (ot == null) { continue; } TriangulationPoint p = t.Points[i]; TriangulationPoint op = ot.OppositePoint(t, p); int oi = ot.IndexOf(op); // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) // then we should not try to legalize if (ot.EdgeIsConstrained[oi] || ot.EdgeIsDelaunay[oi]) { t.EdgeIsConstrained[i] = ot.EdgeIsConstrained[oi]; // XXX: have no good way of setting this property when creating new triangles so lets set it here continue; } if (!TriangulationUtil.SmartIncircle(p, t.PointCCWFrom(p), t.PointCWFrom(p), op)) { continue; } // Lets mark this shared edge as Delaunay t.EdgeIsDelaunay[i] = true; ot.EdgeIsDelaunay[oi] = true; // Lets rotate shared edge one vertex CW to legalize it RotateTrianglePair(t, p, ot, op); // We now got one valid Delaunay Edge shared by two triangles // This gives us 4 new edges to check for Delaunay // Make sure that triangle to node mapping is done only one time for a specific triangle if (!Legalize(tcx, t)) { tcx.MapTriangleToNodes(t); } if (!Legalize(tcx, ot)) { tcx.MapTriangleToNodes(ot); } // Reset the Delaunay edges, since they only are valid Delaunay edges // until we add a new triangle or point. // XXX: need to think about this. Can these edges be tried after we // return to previous recursive level? t.EdgeIsDelaunay[i] = false; ot.EdgeIsDelaunay[oi] = false; // If triangle have been legalized no need to check the other edges since // the recursive legalization will handles those so we can end here. return(true); } return(false); }