Beispiel #1
0
        private static void EdgeEvent(DTSweepContext tcx, PolygonPoint ep, PolygonPoint eq,
                                      DelaunayTriangle triangle, PolygonPoint point)
        {
            PolygonPoint p1, p2;

            if (IsEdgeSideOfTriangle(triangle, ep, eq))
            {
                return;
            }

            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);
            }

            p2 = triangle.PointCWFrom(point);
            Orientation o2 = TriangulationUtil.Orient2D(eq, p2, ep);

            if (o2 == Orientation.Collinear)
            {
                // TODO: Split edge in two
                //            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);
            }

            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);
                }
                EdgeEvent(tcx, ep, eq, triangle, point);
            }
            else
            {
                // This triangle crosses constraint so lets flippin start!
                FlipEdgeEvent(tcx, ep, eq, triangle, point);
            }
        }
Beispiel #2
0
        private static void FlipEdgeEvent(DTSweepContext tcx, PolygonPoint ep, PolygonPoint eq,
                                          DelaunayTriangle t, PolygonPoint p)
        {
            DelaunayTriangle ot = t.NeighborAcrossFrom(p);
            PolygonPoint     op = ot.OppositePoint(t, p);

            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");
            }

            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)
                    {
                        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
                {
                    Orientation o = TriangulationUtil.Orient2D(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                PolygonPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
Beispiel #3
0
 private static void FillLeftAboveEdgeEvent(DTSweepContext tcx, DTSweepConstraint edge, AdvancingFrontNode node)
 {
     while (node.Prev.Point.X > edge.P.X)
     {
         // Check if next node is below the edge
         Orientation o1 = TriangulationUtil.Orient2D(edge.Q, node.Prev.Point, edge.P);
         if (o1 == Orientation.CW)
         {
             FillLeftBelowEdgeEvent(tcx, edge, node);
         }
         else
         {
             node = node.Prev;
         }
     }
 }
Beispiel #4
0
 private static void FillLeftBelowEdgeEvent(DTSweepContext tcx, DTSweepConstraint edge, AdvancingFrontNode node)
 {
     if (node.Point.X > edge.P.X)
     {
         if (TriangulationUtil.Orient2D(node.Point, node.Prev.Point, node.Prev.Prev.Point) == Orientation.CW)
         {
             // Concave
             FillLeftConcaveEdgeEvent(tcx, edge, node);
         }
         else
         {
             // Convex
             FillLeftConvexEdgeEvent(tcx, edge, node);
             // Retry this one
             FillLeftBelowEdgeEvent(tcx, edge, node);
         }
     }
 }
Beispiel #5
0
 /// <summary>
 /// Recursive algorithm to fill a Basin with triangles
 /// </summary>
 private static void FillBasinReq(DTSweepContext tcx, AdvancingFrontNode node)
 {
     if (IsShallow(tcx, node))
     {
         return;                       // if shallow stop filling
     }
     Fill(tcx, node);
     if (node.Prev == tcx.Basin.LeftNode && node.Next == tcx.Basin.RightNode)
     {
         return;
     }
     else if (node.Prev == tcx.Basin.LeftNode)
     {
         Orientation o = TriangulationUtil.Orient2D(node.Point, node.Next.Point, node.Next.Next.Point);
         if (o == Orientation.CW)
         {
             return;
         }
         node = node.Next;
     }
     else if (node.Next == tcx.Basin.RightNode)
     {
         Orientation o = TriangulationUtil.Orient2D(node.Point, node.Prev.Point, node.Prev.Prev.Point);
         if (o == Orientation.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);
 }
Beispiel #6
0
        /// <summary>
        /// When we need to traverse from one triangle to the next we need
        /// the point in current triangle that is the opposite point to the next
        /// triangle.
        /// </summary>
        private static PolygonPoint NextFlipPoint(PolygonPoint ep, PolygonPoint eq,
                                                  DelaunayTriangle ot, PolygonPoint op)
        {
            Orientation o2d = TriangulationUtil.Orient2D(eq, op, ep);

            switch (o2d)
            {
            case Orientation.CW:
                return(ot.PointCCWFrom(op));

            case Orientation.CCW:
                return(ot.PointCWFrom(op));

            case Orientation.Collinear:
                // TODO: implement support for point on constraint edge
                throw new PointOnEdgeException("Point on constrained edge not supported yet", eq, op, ep);

            default:
                throw new NotImplementedException("Orientation not handled");
            }
        }
Beispiel #7
0
 private static void FillLeftConcaveEdgeEvent(DTSweepContext tcx, DTSweepConstraint edge, AdvancingFrontNode node)
 {
     Fill(tcx, node.Prev);
     if (node.Prev.Point != edge.P)
     {
         // Next above or below edge?
         if (TriangulationUtil.Orient2D(edge.Q, node.Prev.Point, edge.P) == Orientation.CW)
         {
             // Below
             if (TriangulationUtil.Orient2D(node.Point, node.Prev.Point, node.Prev.Prev.Point) == Orientation.CW)
             {
                 // Next is concave
                 FillLeftConcaveEdgeEvent(tcx, edge, node);
             }
             else
             {
                 // Next is convex
             }
         }
     }
 }
Beispiel #8
0
        /// <summary>
        /// Fills a basin that has formed on the Advancing Front to the right
        /// of given node.<br>
        /// First we decide a left,bottom and right node that forms the
        /// boundaries of the basin. Then we do a reqursive fill.
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="node">starting node, this or next node will be left node</param>
        private static void FillBasin(DTSweepContext tcx, AdvancingFrontNode node)
        {
            if (TriangulationUtil.Orient2D(node.Point, node.Next.Point, node.Next.Next.Point) == Orientation.CCW)
            {
                // tcx.basin.leftNode = node.next.next;
                tcx.Basin.LeftNode = node;
            }
            else
            {
                tcx.Basin.LeftNode = node.Next;
            }

            // Find the bottom and right node
            tcx.Basin.BottomNode = tcx.Basin.LeftNode;
            while (tcx.Basin.BottomNode.HasNext && 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)
            {
                return;                                             // No valid basin
            }
            tcx.Basin.RightNode = tcx.Basin.BottomNode;
            while (tcx.Basin.RightNode.HasNext && 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)
            {
                return;                                              // No valid basins
            }
            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);
        }
Beispiel #9
0
 private static void FillRightConvexEdgeEvent(DTSweepContext tcx, DTSweepConstraint edge, AdvancingFrontNode node)
 {
     // Next concave or convex?
     if (TriangulationUtil.Orient2D(node.Next.Point, node.Next.Next.Point, node.Next.Next.Next.Point) ==
         Orientation.CCW)
     {
         // Concave
         FillRightConcaveEdgeEvent(tcx, edge, node.Next);
     }
     else
     {
         // Convex
         // Next above or below edge?
         if (TriangulationUtil.Orient2D(edge.Q, node.Next.Next.Point, edge.P) == Orientation.CCW)
         {
             // Below
             FillRightConvexEdgeEvent(tcx, edge, node.Next);
         }
         else
         {
             // Above
         }
     }
 }