示例#1
0
		/// <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;
		}
示例#2
0
		/// <summary>
		/// Returns true if triangle was legalized
		/// </summary>
		private static bool Legalize(DTSweepContext tcx, DelaunayTriangle t)
		{
			// To legalize a triangle we start by finding if any of the three edges
			// violate the Delaunay condition
			for (int i = 0; i < 3; i++)
			{
				// TODO: fix so that cEdge is always valid when creating new triangles then we can check it here
				//       instead of below with ot
				if (t.EdgeIsDelaunay[i])
				{
					continue;
				}

				DelaunayTriangle ot = t.Neighbors[i];
				if (ot == null)
				{
					continue;
				}

				TriangulationPoint p = t.Points[i];
				TriangulationPoint op = ot.OppositePoint(t, p);
				int oi = ot.IndexOf(op);
				// If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
				// then we should not try to legalize
				if (ot.EdgeIsConstrained[oi] || ot.EdgeIsDelaunay[oi])
				{
					t.EdgeIsConstrained[i] = ot.EdgeIsConstrained[oi];
					// XXX: have no good way of setting this property when creating new triangles so lets set it here
					continue;
				}

				if (!TriangulationUtil.SmartIncircle(p, t.PointCCWFrom(p), t.PointCWFrom(p), op))
				{
					continue;
				}

				// Lets mark this shared edge as Delaunay 
				t.EdgeIsDelaunay[i] = true;
				ot.EdgeIsDelaunay[oi] = true;

				// Lets rotate shared edge one vertex CW to legalize it
				RotateTrianglePair(t, p, ot, op);

				// We now got one valid Delaunay Edge shared by two triangles
				// This gives us 4 new edges to check for Delaunay

				// Make sure that triangle to node mapping is done only one time for a specific triangle
				if (!Legalize(tcx, t))
				{
					tcx.MapTriangleToNodes(t);
				}
				if (!Legalize(tcx, ot))
				{
					tcx.MapTriangleToNodes(ot);
				}

				// Reset the Delaunay edges, since they only are valid Delaunay edges
				// until we add a new triangle or point.
				// XXX: need to think about this. Can these edges be tried after we 
				//      return to previous recursive level?
				t.EdgeIsDelaunay[i] = false;
				ot.EdgeIsDelaunay[oi] = false;

				// If triangle have been legalized no need to check the other edges since
				// the recursive legalization will handles those so we can end here.
				return true;
			}
			return false;
		}
示例#3
0
		/// <summary>
		/// If this is a Delaunay Triangulation of a pointset we need to fill so the triangle mesh gets a ConvexHull 
		/// </summary>
		private static void FinalizationConvexHull(DTSweepContext tcx)
		{
			AdvancingFrontNode n1, n2, n3;
			DelaunayTriangle t1;
			TriangulationPoint first, p1;

			n1 = tcx.Front.Head.Next;
			n2 = n1.Next;
			n3 = n2.Next;
			first = n1.Point;

			TurnAdvancingFrontConvex(tcx, n1, n2);

			n1 = tcx.Front.Tail.Prev;
			if (n1.Triangle.Contains(n1.Next.Point) && n1.Triangle.Contains(n1.Prev.Point))
			{
				t1 = n1.Triangle.NeighborAcrossFrom(n1.Point);
				RotateTrianglePair(n1.Triangle, n1.Point, t1, t1.OppositePoint(n1.Triangle, n1.Point));
				tcx.MapTriangleToNodes(n1.Triangle);
				tcx.MapTriangleToNodes(t1);
			}
			n1 = tcx.Front.Head.Next;
			if (n1.Triangle.Contains(n1.Prev.Point) && n1.Triangle.Contains(n1.Next.Point))
			{
				t1 = n1.Triangle.NeighborAcrossFrom(n1.Point);
				RotateTrianglePair(n1.Triangle, n1.Point, t1, t1.OppositePoint(n1.Triangle, n1.Point));
				tcx.MapTriangleToNodes(n1.Triangle);
				tcx.MapTriangleToNodes(t1);
			}

			// TODO: implement ConvexHull for lower right and left boundary
			// Lower right boundary 
			first = tcx.Front.Head.Point;
			n2 = tcx.Front.Tail.Prev;
			t1 = n2.Triangle;
			p1 = n2.Point;
			do
			{
				tcx.RemoveFromList(t1);
				p1 = t1.PointCCWFrom(p1);
				if (p1 == first)
				{
					break;
				}
				t1 = t1.NeighborCCWFrom(p1);
			}
			while (true);

			// Lower left boundary
			first = tcx.Front.Head.Next.Point;
			p1 = t1.PointCWFrom(tcx.Front.Head.Point);
			t1 = t1.NeighborCWFrom(tcx.Front.Head.Point);
			do
			{
				tcx.RemoveFromList(t1);
				p1 = t1.PointCCWFrom(p1);
				t1 = t1.NeighborCCWFrom(p1);
			}
			while (p1 != first);

			tcx.FinalizeTriangulation();
		}
示例#4
0
		private static void FlipEdgeEvent(
			DTSweepContext tcx, TriangulationPoint ep, TriangulationPoint eq, DelaunayTriangle t, TriangulationPoint p)
		{
			DelaunayTriangle ot = t.NeighborAcrossFrom(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 (tcx.IsDebugEnabled)
			{
				tcx.DTDebugContext.PrimaryTriangle = t;
				tcx.DTDebugContext.SecondaryTriangle = ot;
			} // TODO: remove

			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)
					{
						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);
			}
		}
示例#5
0
		/// <summary>
		/// Adds a triangle to the advancing front to fill a hole.
		/// </summary>
		/// <param name="tcx"></param>
		/// <param name="node">middle node, that is the bottom of the hole</param>
		private static void Fill(DTSweepContext tcx, AdvancingFrontNode node)
		{
			DelaunayTriangle triangle = new DelaunayTriangle(node.Prev.Point, node.Point, node.Next.Point);
			// TODO: should copy the cEdge value from neighbor triangles
			//       for now cEdge values are copied during the legalize 
			triangle.MarkNeighbor(node.Prev.Triangle);
			triangle.MarkNeighbor(node.Triangle);
			tcx.Triangles.Add(triangle);

			// Update the advancing front
			node.Prev.Next = node.Next;
			node.Next.Prev = node.Prev;
			tcx.RemoveNode(node);

			// If it was legalized the triangle has already been mapped
			if (!Legalize(tcx, triangle))
			{
				tcx.MapTriangleToNodes(triangle);
			}
		}