Beispiel #1
0
		public static bool InScanArea(
			TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd)
		{
			double pdx = pd.X;
			double pdy = pd.Y;
			double adx = pa.X - pdx;
			double ady = pa.Y - pdy;
			double bdx = pb.X - pdx;
			double bdy = pb.Y - pdy;

			double adxbdy = adx * bdy;
			double bdxady = bdx * ady;
			double oabd = adxbdy - bdxady;
			//        oabd = orient2d(pa,pb,pd);
			if (oabd <= 0)
			{
				return false;
			}

			double cdx = pc.X - pdx;
			double cdy = pc.Y - pdy;

			double cdxady = cdx * ady;
			double adxcdy = adx * cdy;
			double ocad = cdxady - adxcdy;
			//      ocad = orient2d(pc,pa,pd);
			if (ocad <= 0)
			{
				return false;
			}
			return true;
		}
		public PointOnEdgeException(string message, TriangulationPoint a, TriangulationPoint b, TriangulationPoint c)
			: base(message)
		{
			this.A = a;
			this.B = b;
			this.C = c;
		}
		/// <summary>
		///   Requirements:
		/// 1. a,b and c form a triangle.
		/// 2. a and d is know to be on opposite side of bc
		/// <code>
		///                a
		///                +
		///               / \
		///              /   \
		///            b/     \c
		///            +-------+ 
		///           /    B    \  
		///          /           \ 
		/// </code>
		///    Facts:
		///  d has to be in area B to have a chance to be inside the circle formed by a,b and c
		///  d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW
		///  This preknowledge gives us a way to optimize the incircle test
		/// </summary>
		/// <param name="pa">triangle point, opposite d</param>
		/// <param name="pb">triangle point</param>
		/// <param name="pc">triangle point</param>
		/// <param name="pd">point opposite a</param>
		/// <returns>true if d is inside circle, false if on circle edge</returns>
		public static bool SmartIncircle( TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd ) {
			double pdx = pd.X;
			double pdy = pd.Y;
			double adx = pa.X - pdx;
			double ady = pa.Y - pdy;
			double bdx = pb.X - pdx;
			double bdy = pb.Y - pdy;

			double adxbdy = adx * bdy;
			double bdxady = bdx * ady;
			double oabd = adxbdy - bdxady;
			//        oabd = orient2d(pa,pb,pd);
			if (oabd <= 0) return false;

			double cdx = pc.X - pdx;
			double cdy = pc.Y - pdy;

			double cdxady = cdx * ady;
			double adxcdy = adx * cdy;
			double ocad = cdxady - adxcdy;
			//      ocad = orient2d(pc,pa,pd);
			if (ocad <= 0) return false;

			double bdxcdy = bdx * cdy;
			double cdxbdy = cdx * bdy;

			double alift = adx * adx + ady * ady;
			double blift = bdx * bdx + bdy * bdy;
			double clift = cdx * cdx + cdy * cdy;

			double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;

			return det > 0;
		}
Beispiel #4
0
		/// <summary>
		/// Give two points in any order. Will always be ordered so
		/// that q.y > p.y and q.x > p.x if same y value 
		/// </summary>
		public DTSweepConstraint(TriangulationPoint p1, TriangulationPoint p2)
		{
			this.P = p1;
			this.Q = p2;
			if (p1.Y > p2.Y)
			{
				this.Q = p1;
				this.P = p2;
			}
			else if (p1.Y == p2.Y)
			{
				if (p1.X > p2.X)
				{
					this.Q = p1;
					this.P = p2;
				}
				else if (p1.X == p2.X)
				{
					//                logger.info( "Failed to create constraint {}={}", p1, p2 );
					//                throw new DuplicatePointException( p1 + "=" + p2 );
					//                return;
				}
			}
			this.Q.AddEdge(this);
		}
 /// <summary>
 /// Give two points in any order. Will always be ordered so
 /// that q.y > p.y and q.x > p.x if same y value 
 /// </summary>
 public DTSweepConstraint(TriangulationPoint p1, TriangulationPoint p2)
 {
     P = p1;
     Q = p2;
     if (p1.y > p2.y)
     {
         Q = p1;
         P = p2;
     }
     else if (p1.y == p2.y)
     {
         if (p1.x > p2.x)
         {
             Q = p1;
             P = p2;
         }
         else if (p1.x == p2.x)
         {
             //                logger.info( "Failed to create constraint {}={}", p1, p2 );
             //                throw new DuplicatePointException( p1 + "=" + p2 );
             //                return;
         }
     }
     Q.AddEdge(this);
 }
 public PointOnEdgeException( string message, TriangulationPoint a, TriangulationPoint b, TriangulationPoint c )
     : base(message)
 {
     A=a;
     B=b;
     C=c;
 }
 /// Forumla to calculate signed area
 /// Positive if CCW
 /// Negative if CW
 /// 0 if collinear
 /// A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
 ///              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
 public static Orientation Orient2d( TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc )
 {
     double detleft = (pa.X - pc.X) * (pb.Y - pc.Y);
     double detright = (pa.Y - pc.Y) * (pb.X - pc.X);
     double val = detleft - detright;
     if (val > -EPSILON && val < EPSILON) {
         return Orientation.Collinear;
     } else if (val > 0) {
         return Orientation.CCW;
     }
     return Orientation.CW;
 }
 //TODO: Port note - different implementation
 public int IndexCW(TriangulationPoint p)
 {
     int index = IndexOf(p);
     switch (index)
     {
         case 0:
             return 2;
         case 1:
             return 0;
         default:
             return 1;
     }
 }
        /*
        public static bool InScanArea(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc,
                                      TriangulationPoint pd)
        {
            double pdx = pd.X;
            double pdy = pd.Y;
            double adx = pa.X - pdx;
            double ady = pa.Y - pdy;
            double bdx = pb.X - pdx;
            double bdy = pb.Y - pdy;

            double adxbdy = adx*bdy;
            double bdxady = bdx*ady;
            double oabd = adxbdy - bdxady;
            //        oabd = orient2d(pa,pb,pd);
            if (oabd <= 0)
            {
                return false;
            }

            double cdx = pc.X - pdx;
            double cdy = pc.Y - pdy;

            double cdxady = cdx*ady;
            double adxcdy = adx*cdy;
            double ocad = cdxady - adxcdy;
            //      ocad = orient2d(pc,pa,pd);
            if (ocad <= 0)
            {
                return false;
            }
            return true;
        }
        */
        public static bool InScanArea(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd)
        {
            double oadb = (pa.X - pb.X) * (pd.Y - pb.Y) - (pd.X - pb.X) * (pa.Y - pb.Y);
            if (oadb >= -EPSILON)
            {
                return false;
            }

            double oadc = (pa.X - pc.X) * (pd.Y - pc.Y) - (pd.X - pc.X) * (pa.Y - pc.Y);
            if (oadc <= EPSILON)
            {
                return false;
            }
            return true;
        }
Beispiel #10
0
		/// <summary>
		/// We use a balancing tree to locate a node smaller or equal to given key value (in theory)
		/// </summary>
		public AdvancingFrontNode LocateNode(TriangulationPoint point)
		{
			return LocateNode(point.X);
		}
Beispiel #11
0
        /// <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>
        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);
        }
Beispiel #12
0
        static void FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle   ot = t.NeighborAcross(p);
            TriangulationPoint 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");
            }

            if (t.GetConstrainedEdgeAcross(p))
            {
                throw new Exception("Intersecting Constraints");
            }

            bool inScanArea = TriangulationUtil.InScanArea(p, t.PointCCW(p), t.PointCW(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)
                    {
                        //if (tcx.IsDebugEnabled) Console.WriteLine("[FLIP] - constrained edge done"); // TODO: remove
                        t.MarkConstrainedEdge(ep, eq);
                        ot.MarkConstrainedEdge(ep, eq);
                        Legalize(tcx, t);
                        Legalize(tcx, ot);
                    }
                    else
                    {
                        //if (tcx.IsDebugEnabled) Console.WriteLine("[FLIP] - subedge done"); // TODO: remove
                        // XXX: I think one of the triangles should be legalized here?
                    }
                }
                else
                {
                    //if (tcx.IsDebugEnabled)
                    //    Console.WriteLine("[FLIP] - flipping and continuing with triangle still crossing edge");
                    // TODO: remove
                    Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
        /// Forumla to calculate signed area
        /// Positive if CCW
        /// Negative if CW
        /// 0 if collinear
        /// A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
        ///              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
        public static Orientation Orient2d(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc)
        {
            double detleft  = (pa.X - pc.X) * (pb.Y - pc.Y);
            double detright = (pa.Y - pc.Y) * (pb.X - pc.X);
            double val      = detleft - detright;

            if (val > -EPSILON && val < EPSILON)
            {
                return(Orientation.Collinear);
            }
            else if (val > 0)
            {
                return(Orientation.CCW);
            }
            return(Orientation.CW);
        }
Beispiel #14
0
        /// <summary>
        /// Creates a new front triangle and legalize it
        /// </summary>
        private static AdvancingFrontNode NewFrontTriangle(DTSweepContext tcx, TriangulationPoint point, AdvancingFrontNode node)
        {
            DelaunayTriangle triangle = new DelaunayTriangle(point, node.Point, node.Next.Point);
            triangle.MarkNeighbor(node.Triangle);
            tcx.Triangles.Add(triangle);

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

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

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

            return newNode;
        }
Beispiel #15
0
        static void EdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point)
        {
            if (IsEdgeSideOfTriangle(triangle, ep, eq))
            {
                return;
            }

            TriangulationPoint p1 = triangle.PointCCW(point);
            Orientation        o1 = TriangulationUtil.Orient2d(eq, p1, ep);

            if (o1 == Orientation.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 PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                if (tcx.IsDebugEnabled)
                {
                    Debug.WriteLine("EdgeEvent - Point on constrained edge");
                }
                return;
            }

            TriangulationPoint p2 = triangle.PointCW(point);
            Orientation        o2 = TriangulationUtil.Orient2d(eq, p2, ep);

            if (o2 == Orientation.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 PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                if (tcx.IsDebugEnabled)
                {
                    Debug.WriteLine("EdgeEvent - Point on constrained edge");
                }
                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 == Orientation.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);
            }
        }
Beispiel #16
0
 public bool Contains(TriangulationPoint p, TriangulationPoint q)
 {
     return(Contains(p) && Contains(q));
 }
Beispiel #17
0
        private static void FlipEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle ot = t.NeighborAcross(p);
            TriangulationPoint 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");
            }

            if (t.GetConstrainedEdgeAcross(p))
            {
                throw new Exception("Intersecting Constraints");
            }

            bool inScanArea = TriangulationUtil.InScanArea(p, t.PointCCW(p), t.PointCW(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
                {
                    // TODO: remove
                    Orientation o = TriangulationUtil.Orient2d(eq, op, ep);
                    t = NextFlipTriangle(tcx, o, t, ot, p, op);
                    FlipEdgeEvent(tcx, ep, eq, t, p);
                }
            }
            else
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, t, ot, newP);
                EdgeEvent(tcx, ep, eq, t, p);
            }
        }
 /// <summary>
 /// Give two points in any order. Will always be ordered so
 /// that q.y > p.y and q.x > p.x if same y value
 /// </summary>
 public DTSweepConstraint(TriangulationPoint p1, TriangulationPoint p2)
     : base(p1, p2)
 {
     Q.AddEdge(this);
 }
Beispiel #19
0
 public bool Contains(TriangulationPoint p)
 {
     return(p == Points[0] || p == Points[1] || p == Points[2]);
 }
 /// <summary>
 /// We use a balancing tree to locate a node smaller or equal to given key value
 /// </summary>
 public AdvancingFrontNode LocateNode(TriangulationPoint point)
 {
     return(LocateNode(point.X));
 }
Beispiel #21
0
 public AdvancingFrontNode(TriangulationPoint point)
 {
     Point = point;
     Value = point.X;
 }
        /// <summary>
        ///   Requirements:
        /// 1. a,b and c form a triangle.
        /// 2. a and d is know to be on opposite side of bc
        /// <code>
        ///                a
        ///                +
        ///               / \
        ///              /   \
        ///            b/     \c
        ///            +-------+
        ///           /    B    \ 
        ///          /           \ 
        /// </code>
        ///    Facts:
        ///  d has to be in area B to have a chance to be inside the circle formed by a,b and c
        ///  d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW
        ///  This preknowledge gives us a way to optimize the incircle test
        /// </summary>
        /// <param name="pa">triangle point, opposite d</param>
        /// <param name="pb">triangle point</param>
        /// <param name="pc">triangle point</param>
        /// <param name="pd">point opposite a</param>
        /// <returns>true if d is inside circle, false if on circle edge</returns>
        public static bool SmartIncircle(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc,
                                         TriangulationPoint pd)
        {
            double pdx = pd.X;
            double pdy = pd.Y;
            double adx = pa.X - pdx;
            double ady = pa.Y - pdy;
            double bdx = pb.X - pdx;
            double bdy = pb.Y - pdy;

            double adxbdy = adx * bdy;
            double bdxady = bdx * ady;
            double oabd   = adxbdy - bdxady;

            //        oabd = orient2d(pa,pb,pd);
            if (oabd <= 0)
            {
                return(false);
            }

            double cdx = pc.X - pdx;
            double cdy = pc.Y - pdy;

            double cdxady = cdx * ady;
            double adxcdy = adx * cdy;
            double ocad   = cdxady - adxcdy;

            //      ocad = orient2d(pc,pa,pd);
            if (ocad <= 0)
            {
                return(false);
            }

            double bdxcdy = bdx * cdy;
            double cdxbdy = cdx * bdy;

            double alift = adx * adx + ady * ady;
            double blift = bdx * bdx + bdy * bdy;
            double clift = cdx * cdx + cdy * cdy;

            double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;

            return(det > 0);
        }
Beispiel #23
0
        /// <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 = t.NeighborCCW(p);
            DelaunayTriangle n2 = t.NeighborCW(p);
            DelaunayTriangle n3 = ot.NeighborCCW(op);
            DelaunayTriangle n4 = ot.NeighborCW(op);

            bool ce1 = t.GetConstrainedEdgeCCW(p);
            bool ce2 = t.GetConstrainedEdgeCW(p);
            bool ce3 = ot.GetConstrainedEdgeCCW(op);
            bool ce4 = ot.GetConstrainedEdgeCW(op);

            bool de1 = t.GetDelaunayEdgeCCW(p);
            bool de2 = t.GetDelaunayEdgeCW(p);
            bool de3 = ot.GetDelaunayEdgeCCW(op);
            bool 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);
        }
Beispiel #24
0
        static bool AngleExceedsPlus90DegreesOrIsNegative(TriangulationPoint origin, TriangulationPoint pa, TriangulationPoint pb)
        {
            double angle = Angle(origin, pa, pb);
            bool   exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0);

            return(exceedsPlus90DegreesOrIsNegative);
        }
Beispiel #25
0
 private static bool AngleExceedsPlus90DegreesOrIsNegative(TriangulationPoint origin, TriangulationPoint pa, TriangulationPoint pb)
 {
     double angle = Angle(origin, pa, pb);
     bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0);
     return exceedsPlus90DegreesOrIsNegative;
 }
Beispiel #26
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;
		}
Beispiel #27
0
 private static bool IsEdgeSideOfTriangle(DelaunayTriangle triangle, TriangulationPoint ep, TriangulationPoint eq)
 {
     int index = triangle.EdgeIndex(ep, eq);
     if (index != -1)
     {
         triangle.MarkConstrainedEdge(index);
         triangle = triangle.Neighbors[index];
         if (triangle != null)
         {
             triangle.MarkConstrainedEdge(ep, eq);
         }
         return true;
     }
     return false;
 }
Beispiel #28
0
        static bool AngleExceeds90Degrees(TriangulationPoint origin, TriangulationPoint pa, TriangulationPoint pb)
        {
            double angle            = Angle(origin, pa, pb);
            bool   exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2));

            return(exceeds90Degrees);
        }
Beispiel #29
0
 /// <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;
 }
Beispiel #30
0
        /// <summary>
        /// Scan part of the FlipScan algorithm
        /// 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>
        static void FlipScanEdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle flipTriangle, DelaunayTriangle t, TriangulationPoint p)
        {
            DelaunayTriangle   ot = t.NeighborAcross(p);
            TriangulationPoint 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");
            }

            bool inScanArea = TriangulationUtil.InScanArea(eq, flipTriangle.PointCCW(eq), flipTriangle.PointCW(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
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flipTriangle, ot, newP);
            }
        }
Beispiel #31
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>
        static TriangulationPoint NextFlipPoint(TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op)
        {
            Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);

            if (o2d == Orientation.CW)
            {
                // Right
                return(ot.PointCCW(op));
            }
            else if (o2d == Orientation.CCW)
            {
                // Left
                return(ot.PointCW(op));
            }
            else
            {
                // TODO: implement support for point on constraint edge
                throw new PointOnEdgeException("Point on constrained edge not supported yet");
            }
        }
 public override TriangulationConstraint NewConstraint(TriangulationPoint a, TriangulationPoint b)
 {
     return new DTSweepConstraint(a, b);
 }
Beispiel #33
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(PointCW(t.PointCW(p)));
 }
        /*
         * public static bool InScanArea(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc,
         *                            TriangulationPoint pd)
         * {
         *  double pdx = pd.X;
         *  double pdy = pd.Y;
         *  double adx = pa.X - pdx;
         *  double ady = pa.Y - pdy;
         *  double bdx = pb.X - pdx;
         *  double bdy = pb.Y - pdy;
         *
         *  double adxbdy = adx*bdy;
         *  double bdxady = bdx*ady;
         *  double oabd = adxbdy - bdxady;
         *  //        oabd = orient2d(pa,pb,pd);
         *  if (oabd <= 0)
         *  {
         *      return false;
         *  }
         *
         *  double cdx = pc.X - pdx;
         *  double cdy = pc.Y - pdy;
         *
         *  double cdxady = cdx*ady;
         *  double adxcdy = adx*cdy;
         *  double ocad = cdxady - adxcdy;
         *  //      ocad = orient2d(pc,pa,pd);
         *  if (ocad <= 0)
         *  {
         *      return false;
         *  }
         *  return true;
         * }
         */

        public static bool InScanArea(TriangulationPoint pa, TriangulationPoint pb, TriangulationPoint pc, TriangulationPoint pd)
        {
            double oadb = (pa.X - pb.X) * (pd.Y - pb.Y) - (pd.X - pb.X) * (pa.Y - pb.Y);

            if (oadb >= -EPSILON)
            {
                return(false);
            }

            double oadc = (pa.X - pc.X) * (pd.Y - pc.Y) - (pd.X - pc.X) * (pa.Y - pc.Y);

            if (oadc <= EPSILON)
            {
                return(false);
            }
            return(true);
        }
Beispiel #35
0
		public DelaunayTriangle( TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3 )
		{
			points[0] = p1;
			points[1] = p2;
			points[2] = p3;
		}
Beispiel #36
0
 public DelaunayTriangle NeighborCCW(TriangulationPoint point)
 {
     return(Neighbors[(Points.IndexOf(point) + 2) % 3]);
 }
Beispiel #37
0
 public DelaunayTriangle NeighborAcross(TriangulationPoint point)
 {
     return(Neighbors[Points.IndexOf(point)]);
 }
Beispiel #38
0
 public TriangulationPoint PointCW(TriangulationPoint point)
 {
     return(Points[(IndexOf(point) + 2) % 3]);
 }
Beispiel #39
0
 public void AddSteinerPoint(TriangulationPoint point)
 {
     if (_steinerPoints == null)
     {
         _steinerPoints = new List<TriangulationPoint>();
     }
     _steinerPoints.Add(point);
 }
Beispiel #40
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[IndexCCW(oPoint)] = nPoint;
 }
        private static Vector3 ConvertToVertexPosition(TriangulationPoint point, Vector3 normal, float normalComponent)
        {
            if (normal.X != 0 && normal.Y == 0 && normal.Z == 0)
            {
                return new Vector3(normalComponent, point.Yf, point.Xf);
            }
            if (normal.X == 0 && normal.Y != 0 && normal.Z == 0)
            {
                return new Vector3(point.Xf, normalComponent, point.Yf);
            }
            if (normal.X == 0 && normal.Y == 0 && normal.Z != 0)
            {
                return new Vector3(point.Xf, point.Yf, normalComponent);
            }

            return new Vector3(0, 0, 0);
        }
Beispiel #42
0
 public bool GetConstrainedEdgeCW(TriangulationPoint p)
 {
     return(EdgeIsConstrained[(IndexOf(p) + 1) % 3]);
 }
        public override void PrepareTriangulation(Triangulatable t)
        {
            base.PrepareTriangulation(t);

            double xmax, xmin;
            double ymax, ymin;

            xmax = xmin = Points[0].x;
            ymax = ymin = Points[0].y;

            // Calculate bounds. Should be combined with the sorting
            foreach (TriangulationPoint p in Points)
            {
                if (p.x > xmax)
                    xmax = p.x;
                if (p.x < xmin)
                    xmin = p.x;
                if (p.y > ymax)
                    ymax = p.y;
                if (p.y < ymin)
                    ymin = p.y;
            }

            double deltaX = ALPHA*(xmax - xmin);
            double deltaY = ALPHA*(ymax - ymin);
            TriangulationPoint p1 = new TriangulationPoint(xmax + deltaX, ymin - deltaY);
            TriangulationPoint p2 = new TriangulationPoint(xmin - deltaX, ymin - deltaY);

            Head = p1;
            Tail = p2;

            //        long time = System.nanoTime();
            // Sort the points along y-axis
            Points.Sort(_comparator);
            //        logger.info( "Triangulation setup [{}ms]", ( System.nanoTime() - time ) / 1e6 );
        }
Beispiel #44
0
 public bool GetConstrainedEdgeAcross(TriangulationPoint p)
 {
     return(EdgeIsConstrained[IndexOf(p)]);
 }
Beispiel #45
0
		/// <summary>
		/// This implementation will use simple node traversal algorithm to find a point on the front
		/// </summary>
		public AdvancingFrontNode LocatePoint(TriangulationPoint point)
		{
			double px = point.X;
			AdvancingFrontNode node = this.FindSearchNode(px);
			double nx = node.Point.X;

			if (px == nx)
			{
				if (point != node.Point)
				{
					// We might have two nodes with same x value for a short time
					if (point == node.Prev.Point)
					{
						node = node.Prev;
					}
					else if (point == node.Next.Point)
					{
						node = node.Next;
					}
					else
					{
						throw new Exception("Failed to find Node for given afront point");
					}
				}
			}
			else if (px < nx)
			{
				while ((node = node.Prev) != null)
				{
					if (point == node.Point)
					{
						break;
					}
				}
			}
			else
			{
				while ((node = node.Next) != null)
				{
					if (point == node.Point)
					{
						break;
					}
				}
			}
			this.Search = node;
			return node;
		}
Beispiel #46
0
 public void SetConstrainedEdgeCW(TriangulationPoint p, bool ce)
 {
     EdgeIsConstrained[(IndexOf(p) + 1) % 3] = ce;
 }
Beispiel #47
0
        /// <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 = tcx.LocateNode(point);
            AdvancingFrontNode 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;
        }
Beispiel #48
0
 public void SetConstrainedEdgeAcross(TriangulationPoint p, bool ce)
 {
     EdgeIsConstrained[IndexOf(p)] = ce;
 }
Beispiel #49
0
 private static bool AngleExceeds90Degrees(TriangulationPoint origin, TriangulationPoint pa, TriangulationPoint pb)
 {
     double angle = Angle(origin, pa, pb);
     bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2));
     return exceeds90Degrees;
 }
Beispiel #50
0
 public bool GetDelaunayEdgeCW(TriangulationPoint p)
 {
     return(EdgeIsDelaunay[(IndexOf(p) + 1) % 3]);
 }
Beispiel #51
0
        private static void EdgeEvent(DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle triangle, TriangulationPoint point)
        {
            if (IsEdgeSideOfTriangle(triangle, ep, eq))
                return;

            TriangulationPoint p1 = triangle.PointCCW(point);
            Orientation o1 = TriangulationUtil.Orient2d(eq, p1, ep);
            if (o1 == Orientation.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 PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                return;
            }

            TriangulationPoint p2 = triangle.PointCW(point);
            Orientation o2 = TriangulationUtil.Orient2d(eq, p2, ep);
            if (o2 == Orientation.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 PointOnEdgeException("EdgeEvent - Point on constrained edge not supported yet");
                }
                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 == Orientation.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);
            }
        }
Beispiel #52
0
 public bool GetDelaunayEdgeAcross(TriangulationPoint p)
 {
     return(EdgeIsDelaunay[IndexOf(p)]);
 }
Beispiel #53
0
        /// <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 = t.NeighborAcross(p);
            TriangulationPoint 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");
            }

            bool inScanArea = TriangulationUtil.InScanArea(eq, flipTriangle.PointCCW(eq), flipTriangle.PointCW(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
            {
                TriangulationPoint newP = NextFlipPoint(ep, eq, ot, op);
                FlipScanEdgeEvent(tcx, ep, eq, flipTriangle, ot, newP);
            }
        }
Beispiel #54
0
 public void SetDelaunayEdgeCW(TriangulationPoint p, bool ce)
 {
     EdgeIsDelaunay[(IndexOf(p) + 1) % 3] = ce;
 }
Beispiel #55
0
 private static double Angle(TriangulationPoint origin, TriangulationPoint pa, TriangulationPoint pb)
 {
     /* Complex plane
     * ab = cosA +i*sinA
     * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
     * atan2(y,x) computes the principal value of the argument function
     * applied to the complex number x+iy
     * Where x = ax*bx + ay*by
     * y = ax*by - ay*bx
     */
     double px = origin.X;
     double py = origin.Y;
     double ax = pa.X - px;
     double ay = pa.Y - py;
     double bx = pb.X - px;
     double by = pb.Y - py;
     double x = ax * by - ay * bx;
     double y = ax * bx + ay * by;
     double angle = Math.Atan2(x, y);
     return angle;
 }
Beispiel #56
0
 public void SetDelaunayEdgeAcross(TriangulationPoint p, bool ce)
 {
     EdgeIsDelaunay[IndexOf(p)] = ce;
 }
Beispiel #57
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 TriangulationPoint NextFlipPoint(TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle ot, TriangulationPoint op)
 {
     Orientation o2d = TriangulationUtil.Orient2d(eq, op, ep);
     if (o2d == Orientation.CW)
     {
         // Right
         return ot.PointCCW(op);
     }
     else if (o2d == Orientation.CCW)
     {
         // Left
         return ot.PointCW(op);
     }
     else
     {
         // TODO: implement support for point on constraint edge
         throw new PointOnEdgeException("Point on constrained edge not supported yet");
     }
 }
Beispiel #58
0
 public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
 {
     Points[0] = p1;
     Points[1] = p2;
     Points[2] = p3;
 }
 public AdvancingFrontNode(TriangulationPoint point)
 {
     this.Point = point;
     Value = point.X;
 }
Beispiel #60
0
        static bool IsEdgeSideOfTriangle(DelaunayTriangle triangle, TriangulationPoint ep, TriangulationPoint eq)
        {
            int index = triangle.EdgeIndex(ep, eq);

            if (index != -1)
            {
                triangle.MarkConstrainedEdge(index);
                triangle = triangle.Neighbors[index];
                if (triangle != null)
                {
                    triangle.MarkConstrainedEdge(ep, eq);
                }
                return(true);
            }
            return(false);
        }