コード例 #1
0
 public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
 {
     Points[0] = p1;
     Points[1] = p2;
     Points[2] = p3;
 }
コード例 #2
0
 public void SetConstrainedEdgeCW( TriangulationPoint p, bool ce )
 {
     EdgeIsConstrained[(IndexOf(p)+1)%3] = ce;
 }
コード例 #3
0
 public void SetDelaunayEdgeCW( TriangulationPoint p, bool ce )
 {
     EdgeIsDelaunay[(IndexOf(p)+1)%3] = ce;
 }
コード例 #4
0
 public DelaunayTriangle NeighborCWFrom(TriangulationPoint point)
 {
     return Neighbors[(Points.IndexOf(point)+1)%3];
 }
コード例 #5
0
 public TriangulationPoint PointCWFrom(TriangulationPoint point)
 {
     return Points[(IndexOf(point)+2)%3];
 }
コード例 #6
0
 public int IndexOf(TriangulationPoint p)
 {
     int i = Points.IndexOf(p);
     if (i==-1) throw new Exception("Calling index with a point that doesn't exist in triangle");
     return i;
 }
コード例 #7
0
 /// <summary>
 /// Mark edge as constrained
 /// </summary>
 public void MarkConstrainedEdge(TriangulationPoint p, TriangulationPoint q)
 {
     int i = EdgeIndex(p,q);
     if ( i != -1 ) EdgeIsConstrained[i] = true;
 }
コード例 #8
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
        /// <summary>
        /// Find closes node to the left of the new point and
        /// create a new triangle. If needed new holes and basins
        /// will be filled to.
        /// </summary>
        private static AdvancingFrontNode PointEvent( DTSweepContext tcx, TriangulationPoint point )
        {
            AdvancingFrontNode node, newNode;

            node = tcx.LocateNode(point);
            if (tcx.IsDebugEnabled) tcx.DTDebugContext.ActiveNode = node;
            newNode = NewFrontTriangle(tcx, point, node);

            // Only need to check +epsilon since point never have smaller
            // x value than node due to how we fetch nodes from the front
            if (point.X <= node.Point.X + TriangulationUtil.EPSILON) Fill(tcx, node);

            tcx.AddNode(newNode);

            FillAdvancingFront(tcx, newNode);
            return newNode;
        }
コード例 #9
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
        /// <summary>
        /// Rotates a triangle pair one vertex CW
        ///       n2                    n2
        ///  P +-----+             P +-----+
        ///    | t  /|               |\  t |  
        ///    |   / |               | \   |
        ///  n1|  /  |n3           n1|  \  |n3
        ///    | /   |    after CW   |   \ |
        ///    |/ oT |               | oT \|
        ///    +-----+ oP            +-----+
        ///       n4                    n4
        /// </summary>
        private static void RotateTrianglePair( DelaunayTriangle t, TriangulationPoint p, DelaunayTriangle ot, TriangulationPoint op )
        {
            DelaunayTriangle n1, n2, n3, n4;
            n1 = t.NeighborCCWFrom(p);
            n2 = t.NeighborCWFrom(p);
            n3 = ot.NeighborCCWFrom(op);
            n4 = ot.NeighborCWFrom(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 dEdge
            ot.SetDelaunayEdgeCCW(p, de1);
            t.SetDelaunayEdgeCW(p, de2);
            t.SetDelaunayEdgeCCW(op, de3);
            ot.SetDelaunayEdgeCW(op, de4);

            // Remap cEdge
            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.Neighbors.Clear();
            ot.Neighbors.Clear();
            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);
        }
コード例 #10
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
 /// <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 TriangulationPoint NextFlipPoint( TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint 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");
     }
 }
コード例 #11
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
 /// <summary>
 /// After a flip we have two triangles and know that only one will still be
 /// intersecting the edge. So decide which to contiune with and legalize the other
 /// </summary>
 /// <param name="tcx"></param>
 /// <param name="o">should be the result of an TriangulationUtil.orient2d( eq, op, ep )</param>
 /// <param name="t">triangle 1</param>
 /// <param name="ot">triangle 2</param>
 /// <param name="p">a point shared by both triangles</param>
 /// <param name="op">another point shared by both triangles</param>
 /// <returns>returns the triangle still intersecting the edge</returns>
 private static DelaunayTriangle NextFlipTriangle( DTSweepContext tcx, Orientation o, DelaunayTriangle t, DelaunayTriangle ot, TriangulationPoint p, TriangulationPoint op )
 {
     int edgeIndex;
     if (o == Orientation.CCW) {
         // ot is not crossing edge after flip
         edgeIndex = ot.EdgeIndex(p, op);
         ot.EdgeIsDelaunay[edgeIndex] = true;
         Legalize(tcx, ot);
         ot.EdgeIsDelaunay.Clear();
         return t;
     }
     // t is not crossing edge after flip
     edgeIndex = t.EdgeIndex(p, op);
     t.EdgeIsDelaunay[edgeIndex] = true;
     Legalize(tcx, t);
     t.EdgeIsDelaunay.Clear();
     return ot;
 }
コード例 #12
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
        /// <summary>
        /// Creates a new front triangle and legalize it
        /// </summary>
        private static AdvancingFrontNode NewFrontTriangle( DTSweepContext tcx, TriangulationPoint point, AdvancingFrontNode node )
        {
            AdvancingFrontNode newNode;
            DelaunayTriangle triangle;

            triangle = new DelaunayTriangle(point, node.Point, node.Next.Point);
            triangle.MarkNeighbor(node.Triangle);
            tcx.Triangles.Add(triangle);

            newNode = new AdvancingFrontNode(point);
            newNode.Next = node.Next;
            newNode.Prev = node;
            node.Next.Prev = newNode;
            node.Next = newNode;

            tcx.AddNode(newNode); // XXX: BST

            if (tcx.IsDebugEnabled) tcx.DTDebugContext.ActiveNode = newNode;

            if (!Legalize(tcx, triangle)) tcx.MapTriangleToNodes(triangle);

            return newNode;
        }
コード例 #13
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
 private static bool IsEdgeSideOfTriangle( DelaunayTriangle triangle, TriangulationPoint ep, TriangulationPoint eq )
 {
     int index = triangle.EdgeIndex(ep, eq);
     if ( index == -1 ) return false;
     triangle.MarkConstrainedEdge(index);
     triangle = triangle.Neighbors[index];
     if (triangle != null) triangle.MarkConstrainedEdge(ep, eq);
     return true;
 }
コード例 #14
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
        /// <summary>
        /// Scan part of the FlipScan algorithm<br>
        /// When a triangle pair isn't flippable we will scan for the next 
        /// point that is inside the flip triangle scan area. When found 
        /// we generate a new flipEdgeEvent
        /// </summary>
        /// <param name="tcx"></param>
        /// <param name="ep">last point on the edge we are traversing</param>
        /// <param name="eq">first point on the edge we are traversing</param>
        /// <param name="flipTriangle">the current triangle sharing the point eq with edge</param>
        /// <param name="t"></param>
        /// <param name="p"></param>
        private static void FlipScanEdgeEvent( DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle flipTriangle, DelaunayTriangle t, TriangulationPoint p )
        {
            DelaunayTriangle ot;
            TriangulationPoint op, newP;
            bool inScanArea;

            ot = t.NeighborAcrossFrom(p);
            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 Exception("[BUG:FIXME] FLIP failed due to missing triangle");
            }

            if (tcx.IsDebugEnabled) {
                Console.WriteLine("[FLIP:SCAN] - scan next point"); // TODO: remove
                tcx.DTDebugContext.PrimaryTriangle = t;
                tcx.DTDebugContext.SecondaryTriangle = ot;
            }

            inScanArea = TriangulationUtil.InScanArea(eq, flipTriangle.PointCCWFrom(eq), flipTriangle.PointCWFrom(eq), op);
            if (inScanArea) {
                // 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 flipTriangle first
                // Turns out at first glance that this is somewhat complicated
                // so it will have to wait.
            } else {
                newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flipTriangle, ot, newP);
            }
        }
コード例 #15
0
 public AdvancingFrontNode(TriangulationPoint point)
 {
     this.Point = point;
     this.Value = point.X;
 }
コード例 #16
0
ファイル: DTSweep.cs プロジェクト: doctorpangloss/Cordon2
        /// <summary>
        /// In the case of a pointset with some constraint edges. If a triangle side is collinear
        /// with a part of the constraint we split the constraint into two constraints. This could
        /// happen when the given constraint migth intersect a point in the set.<br>
        /// This can never happen in the case when we are working with a polygon.
        /// 
        /// Think of two triangles that have non shared sides that are collinear and the constraint
        /// is set from a point in triangle A to a point in triangle B so that the constraint is
        /// the union of both those sides. We then have to split the constraint into two so we get
        /// one constraint for each triangle.  
        /// </summary>
        /// <param name="ep"></param>
        /// <param name="eq"></param>
        /// <param name="p">point on the edge between ep->eq</param>
        private static void SplitEdge( TriangulationPoint ep, TriangulationPoint eq, TriangulationPoint p )
        {
            #if !DOTNET2
            DTSweepConstraint edge = eq.Edges.First( e => e.Q==ep || e.P==ep );
            #else
            DTSweepConstraint edge = null;
            for ( int i=0;i<eq.Edges.Count;i++) if (eq.Edges[i].Q == ep || eq.Edges[i].P == ep) { edge = eq.Edges[i]; break; }
            #endif
            edge.P = p;
            new DTSweepConstraint(ep, p); // Et tu, Brute? --MM

            //        // Redo this edge now that we have split the constraint
            //          newEdgeEvent( tcx, edge, triangle, point );
            //          // Continue with new edge
            //          newEdgeEvent( tcx, edge, triangle, p2 );
        }
コード例 #17
0
 public int IndexCWFrom(TriangulationPoint p)
 {
     return (IndexOf(p)+2)%3;
 }
コード例 #18
0
ファイル: Polygon.cs プロジェクト: doctorpangloss/Cordon2
 public void AddSteinerPoint( TriangulationPoint point )
 {
     if (_steinerPoints == null) _steinerPoints = new List<TriangulationPoint>();
     _steinerPoints.Add(point);
 }
コード例 #19
0
 /// <summary>
 /// Legalize triangle by rotating clockwise around oPoint
 /// </summary>
 /// <param name="oPoint">The origin point to rotate around</param>
 /// <param name="nPoint">???</param>
 public void Legalize(TriangulationPoint oPoint, TriangulationPoint nPoint)
 {
     RotateCW();
     Points[IndexCCWFrom(oPoint)] = nPoint;
 }
コード例 #20
0
 public abstract TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);
コード例 #21
0
 public DelaunayTriangle NeighborAcrossFrom(TriangulationPoint point)
 {
     return Neighbors[ Points.IndexOf(point)     ];
 }
コード例 #22
0
        /// <summary>
        /// Get the index of the neighbor that shares this edge (or -1 if it isn't shared)
        /// </summary>
        /// <returns>index of the shared edge or -1 if edge isn't shared</returns>
        public int EdgeIndex(TriangulationPoint p1, TriangulationPoint p2)
        {
            int i1 = Points.IndexOf(p1);
            int i2 = Points.IndexOf(p2);

            // Points of this triangle in the edge p1-p2
            bool a = (i1==0 || i2==0);
            bool b = (i1==1 || i2==1);
            bool c = (i1==2 || i2==2);

            if (b&&c) return 0;
            if (a&&c) return 1;
            if (a&&b) return 2;
            return -1;
        }
コード例 #23
0
 /// <param name="t">Opposite triangle</param>
 /// <param name="p">The point in t that isn't shared between the triangles</param>
 public TriangulationPoint OppositePoint(DelaunayTriangle t, TriangulationPoint p)
 {
     Debug.Assert(t != this, "self-pointer error");
     return PointCWFrom(t.PointCWFrom(p));
 }
コード例 #24
0
 public bool GetConstrainedEdgeAcross( TriangulationPoint p )
 {
     return EdgeIsConstrained[ IndexOf(p)     ];
 }
コード例 #25
0
 public void SetConstrainedEdgeAcross( TriangulationPoint p, bool ce )
 {
     EdgeIsConstrained[ IndexOf(p)     ] = ce;
 }
コード例 #26
0
 public bool GetConstrainedEdgeCW( TriangulationPoint p )
 {
     return EdgeIsConstrained[(IndexOf(p)+1)%3];
 }
コード例 #27
0
 public void SetDelaunayEdgeAcross( TriangulationPoint p, bool ce )
 {
     EdgeIsDelaunay[ IndexOf(p)     ] = ce;
 }
コード例 #28
0
 public bool GetDelaunayEdgeAcross( TriangulationPoint p )
 {
     return EdgeIsDelaunay[ IndexOf(p)     ];
 }
コード例 #29
0
 /// <summary>
 /// Update neighbor pointers
 /// </summary>
 /// <param name="p1">Point 1 of the shared edge</param>
 /// <param name="p2">Point 2 of the shared edge</param>
 /// <param name="t">This triangle's new neighbor</param>
 private void MarkNeighbor( TriangulationPoint p1, TriangulationPoint p2, DelaunayTriangle t )
 {
     int i = EdgeIndex(p1,p2);
     if ( i==-1 ) throw new Exception( "Error marking neighbors -- t doesn't contain edge p1-p2!" );
     Neighbors[i] = t;
 }
コード例 #30
0
 public bool GetDelaunayEdgeCW( TriangulationPoint p )
 {
     return EdgeIsDelaunay[(IndexOf(p)+1)%3];
 }
コード例 #31
0
 public bool Contains(TriangulationPoint p)
 {
     return Points.Contains(p);
 }
コード例 #32
0
 public abstract TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b);