Пример #1
0
        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);
        }
Пример #2
0
 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;
         }
     }
 }
Пример #3
0
        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");
        }
Пример #4
0
 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);
         }
     }
 }
Пример #5
0
        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);
        }
Пример #6
0
 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
             }
         }
     }
 }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
            }
        }
Пример #9
0
 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
         }
     }
 }
Пример #10
0
        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);
            }
        }