private void EdgeEvent(SweepContext tcx, TriPoint ep, TriPoint eq, Triangle triangle, TriPoint point) { if (IsEdgeSideOfTriangle(triangle, ep, eq)) { return; } TriPoint p1 = triangle.PointCCW(point); Winding o1 = TriUtil.Orient2d(eq, p1, ep); if (o1 == Winding.Collinear) { if (triangle.Contains(eq, p1)) { triangle.MarkConstrainedEdge(eq, p1); // We are modifying the constraint maybe it would be better to // not change the given constraint and just keep a variable for the new constraint tcx.EdgeEvent.ConstrainedEdge.Q = p1; triangle = triangle.NeighborAcross(point); EdgeEvent(tcx, ep, p1, triangle, p1); } else { throw new NotSupportedException("EdgeEvent - collinear points not supported"); } return; } TriPoint p2 = triangle.PointCW(point); Winding o2 = TriUtil.Orient2d(eq, p2, ep); if (o2 == Winding.Collinear) { if (triangle.Contains(eq, p2)) { triangle.MarkConstrainedEdge(eq, p2); // We are modifying the constraint maybe it would be better to // not change the given constraint and just keep a variable for the new constraint tcx.EdgeEvent.ConstrainedEdge.Q = p2; triangle = triangle.NeighborAcross(point); EdgeEvent(tcx, ep, p2, triangle, p2); } else { throw new NotSupportedException("EdgeEvent - collinear points not supported"); } return; } if (o1 == o2) { // Need to decide if we are rotating CW or CCW to get to a triangle // that will cross edge if (o1 == Winding.CW) { triangle = triangle.NeighborCCW(point); } else { triangle = triangle.NeighborCW(point); } EdgeEvent(tcx, ep, eq, triangle, point); } else { // This triangle crosses constraint so lets flippin start! FlipEdgeEvent(tcx, ep, eq, triangle, point); } }
/** * Rotates a triangle pair one vertex CW *<pre> * n2 n2 * P +-----+ P +-----+ * | t /| |\ t | * | / | | \ | * n1| / |n3 n1| \ |n3 * | / | after CW | \ | * |/ oT | | oT \| * +-----+ oP +-----+ * n4 n4 * </pre> */ private void RotateTrianglePair(Triangle t, TriPoint p, Triangle ot, TriPoint op) { Triangle n1, n2, n3, n4; n1 = t.NeighborCCW(p); n2 = t.NeighborCW(p); n3 = ot.NeighborCCW(op); n4 = ot.NeighborCW(op); bool ce1, ce2, ce3, ce4; ce1 = t.GetConstrainedEdgeCCW(p); ce2 = t.GetConstrainedEdgeCW(p); ce3 = ot.GetConstrainedEdgeCCW(op); ce4 = ot.GetConstrainedEdgeCW(op); bool de1, de2, de3, de4; de1 = t.GetDelaunayEdgeCCW(p); de2 = t.GetDelaunayEdgeCW(p); de3 = ot.GetDelaunayEdgeCCW(op); de4 = ot.GetDelaunayEdgeCW(op); t.Legalize(p, op); ot.Legalize(op, p); // Remap delaunay_edge ot.SetDelunayEdgeCCW(p, de1); t.SetDelunayEdgeCW(p, de2); t.SetDelunayEdgeCCW(op, de3); ot.SetDelunayEdgeCW(op, de4); // Remap constrained_edge ot.SetConstrainedEdgeCCW(p, ce1); t.SetConstrainedEdgeCW(p, ce2); t.SetConstrainedEdgeCCW(op, ce3); ot.SetConstrainedEdgeCW(op, ce4); // Remap neighbors // XXX: might optimize the markNeighbor by keeping track of // what side should be assigned to what neighbor after the // rotation. Now mark neighbor does lots of testing to find // the right side. t.ClearNeighbors(); ot.ClearNeighbors(); if (n1 != null) { ot.MarkNeighbor(n1); } if (n2 != null) { t.MarkNeighbor(n2); } if (n3 != null) { t.MarkNeighbor(n3); } if (n4 != null) { ot.MarkNeighbor(n4); } t.MarkNeighbor(ot); }
private void FlipScanEdgeEvent(SweepContext tcx, TriPoint ep, TriPoint eq, Triangle flip_triangle, Triangle t, TriPoint p) { Triangle ot = t.NeighborAcross(p); TriPoint op = ot.OppositePoint(t, p); if (TriUtil.InScanArea(eq, flip_triangle.PointCCW(eq), flip_triangle.PointCW(eq), op)) { // flip with new edge op->eq FlipEdgeEvent(tcx, eq, op, ot, op); // TODO: Actually I just figured out that it should be possible to // improve this by getting the next ot and op before the the above // flip and continue the flipScanEdgeEvent here // set new ot and op here and loop back to inScanArea test // also need to set a new flip_triangle first // Turns out at first glance that this is somewhat complicated // so it will have to wait. } else { TriPoint newP = NextFlipPoint(ep, eq, ot, op); FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); } }
private bool Legalize(SweepContext tcx, Triangle 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++) { if (t.DelaunayEdge[i]) { continue; } Triangle ot = t.GetNeighbor(i); if (ot != null) { TriPoint p = t.Points[i]; TriPoint op = ot.OppositePoint(t, p); int oi = ot.Index(op); // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) // then we should not try to legalize if (ot.ConstrainedEdge[oi] || ot.DelaunayEdge[oi]) { t.ConstrainedEdge[i] = ot.ConstrainedEdge[oi]; continue; } bool inside = Incircle(p, t.PointCCW(p), t.PointCW(p), op); if (inside) { // Lets mark this shared edge as Delaunay t.DelaunayEdge[i] = true; ot.DelaunayEdge[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 bool not_legalized = !Legalize(tcx, t); if (not_legalized) { tcx.MapTriangleToNodes(t); } not_legalized = !Legalize(tcx, ot); if (not_legalized) { 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.DelaunayEdge[i] = false; ot.DelaunayEdge[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); }