private void FillBasinReq(SweepContext tcx, Node node) { // if shallow stop filling if (IsShallow(tcx, node)) { return; } Fill(tcx, node); if (node.Prev == tcx.Basin.LeftNode && node.Next == tcx.Basin.RightNode) { return; } else if (node.Prev == tcx.Basin.LeftNode) { Winding o = TriUtil.Orient2d(node.Point, node.Next.Point, node.Next.Next.Point); if (o == Winding.CW) { return; } node = node.Next; } else if (node.Next == tcx.Basin.RightNode) { Winding o = TriUtil.Orient2d(node.Point, node.Prev.Point, node.Prev.Prev.Point); if (o == Winding.CCW) { return; } node = node.Prev; } else { // Continue with the neighbor node with lowest Y value if (node.Prev.Point.Y < node.Next.Point.Y) { node = node.Prev; } else { node = node.Next; } } FillBasinReq(tcx, node); }
private void FillLeftAboveEdgeEvent(SweepContext tcx, Edge edge, Node node) { while (node.Prev.Point.X > edge.P.X) { // Check if next node is below the edge if (TriUtil.Orient2d(edge.Q, node.Prev.Point, edge.P) == Winding.CW) { FillLeftBelowEdgeEvent(tcx, edge, node); } else { node = node.Prev; } } }
private TriPoint NextFlipPoint(TriPoint ep, TriPoint eq, Triangle ot, TriPoint op) { Winding o2d = TriUtil.Orient2d(eq, op, ep); if (o2d == Winding.CW) { // Right return(ot.PointCCW(op)); } else if (o2d == Winding.CCW) { // Left return(ot.PointCW(op)); } throw new NotSupportedException("[Unsupported] Opposing point on constrained edge"); }
private void FillLeftBelowEdgeEvent(SweepContext tcx, Edge edge, Node node) { if (node.Point.X > edge.P.X) { if (TriUtil.Orient2d(node.Point, node.Prev.Point, node.Prev.Prev.Point) == Winding.CW) { // Concave FillLeftConcaveEdgeEvent(tcx, edge, node); } else { // Convex FillLeftConvexEdgeEvent(tcx, edge, node); // Retry this one FillLeftBelowEdgeEvent(tcx, edge, node); } } }
private void FillBasin(SweepContext tcx, Node node) { if (TriUtil.Orient2d(node.Point, node.Next.Point, node.Next.Next.Point) == Winding.CCW) { tcx.Basin.LeftNode = node.Next.Next; } else { tcx.Basin.LeftNode = node.Next; } // Find the bottom and right node tcx.Basin.BottomNode = tcx.Basin.LeftNode; while (tcx.Basin.BottomNode.Next != null && tcx.Basin.BottomNode.Point.Y >= tcx.Basin.BottomNode.Next.Point.Y) { tcx.Basin.BottomNode = tcx.Basin.BottomNode.Next; } if (tcx.Basin.BottomNode == tcx.Basin.LeftNode) { // No valid basin return; } tcx.Basin.RightNode = tcx.Basin.BottomNode; while (tcx.Basin.RightNode.Next != null && tcx.Basin.RightNode.Point.Y < tcx.Basin.RightNode.Next.Point.Y) { tcx.Basin.RightNode = tcx.Basin.RightNode.Next; } if (tcx.Basin.RightNode == tcx.Basin.BottomNode) { // No valid basins return; } tcx.Basin.Width = tcx.Basin.RightNode.Point.X - tcx.Basin.LeftNode.Point.X; tcx.Basin.LeftHighest = tcx.Basin.LeftNode.Point.Y > tcx.Basin.RightNode.Point.Y; FillBasinReq(tcx, tcx.Basin.BottomNode); }
private void FillLeftConcaveEdgeEvent(SweepContext tcx, Edge edge, Node node) { Fill(tcx, node.Prev); if (node.Prev.Point != edge.P) { // Next above or below edge? if (TriUtil.Orient2d(edge.Q, node.Prev.Point, edge.P) == Winding.CW) { // Below if (TriUtil.Orient2d(node.Point, node.Prev.Point, node.Prev.Prev.Point) == Winding.CW) { // Next is concave FillLeftConcaveEdgeEvent(tcx, edge, node); } else { // Next is convex } } } }
private void FlipEdgeEvent(SweepContext tcx, TriPoint ep, TriPoint eq, Triangle t, TriPoint p) { Triangle ot = t.NeighborAcross(p); TriPoint op = ot.OppositePoint(t, p); if (TriUtil.InScanArea(p, t.PointCCW(p), t.PointCW(p), op)) { // 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) { t.MarkConstrainedEdge(ep, eq); ot.MarkConstrainedEdge(ep, eq); Legalize(tcx, t); Legalize(tcx, ot); } else { // XXX: I think one of the triangles should be legalized here? } } else { Winding o = TriUtil.Orient2d(eq, op, ep); t = NextFlipTriangle(tcx, o, t, ot, p, op); FlipEdgeEvent(tcx, ep, eq, t, p); } } else { TriPoint newP = NextFlipPoint(ep, eq, ot, op); FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP); EdgeEvent(tcx, ep, eq, t, p); } }
private void FillRightConvexEdgeEvent(SweepContext tcx, Edge edge, Node node) { // Next concave or convex? if (TriUtil.Orient2d(node.Next.Point, node.Next.Next.Point, node.Next.Next.Next.Point) == Winding.CCW) { // Concave FillRightConcaveEdgeEvent(tcx, edge, node.Next); } else { // Convex // Next above or below edge? if (TriUtil.Orient2d(edge.Q, node.Next.Next.Point, edge.P) == Winding.CCW) { // Below FillRightConvexEdgeEvent(tcx, edge, node.Next); } else { // Above } } }
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); } }