diff --git a/Triangle.NET/Triangle/Carver.cs b/Triangle.NET/Triangle/Carver.cs
deleted file mode 100644
index 12e20f7..0000000
--- a/Triangle.NET/Triangle/Carver.cs
+++ /dev/null
@@ -1,421 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Original Triangle code by Jonathan Richard Shewchuk, http://www.cs.cmu.edu/~quake/triangle.html
-// Triangle.NET code by Christian Woltering, http://triangle.codeplex.com/
-//
-// -----------------------------------------------------------------------
-
-namespace TriangleNet
-{
- using TriangleNet.Data;
- using System;
- using TriangleNet.Geometry;
- using System.Collections.Generic;
- using TriangleNet.Tools;
-
- ///
- /// Carves holes into the triangulation.
- ///
- class Carver
- {
- Mesh mesh;
- List viri;
-
- public Carver(Mesh mesh)
- {
- this.mesh = mesh;
- this.viri = new List();
- }
-
- ///
- /// Virally infect all of the triangles of the convex hull that are not
- /// protected by subsegments. Where there are subsegments, set boundary
- /// markers as appropriate.
- ///
- private void InfectHull()
- {
- Otri hulltri = default(Otri);
- Otri nexttri = default(Otri);
- Otri starttri = default(Otri);
- Osub hullsubseg = default(Osub);
- Vertex horg, hdest;
-
- // Find a triangle handle on the hull.
- hulltri.triangle = Mesh.dummytri;
- hulltri.orient = 0;
- hulltri.SymSelf();
- // Remember where we started so we know when to stop.
- hulltri.Copy(ref starttri);
- // Go once counterclockwise around the convex hull.
- do
- {
- // Ignore triangles that are already infected.
- if (!hulltri.IsInfected())
- {
- // Is the triangle protected by a subsegment?
- hulltri.SegPivot(ref hullsubseg);
- if (hullsubseg.seg == Mesh.dummysub)
- {
- // The triangle is not protected; infect it.
- if (!hulltri.IsInfected())
- {
- hulltri.Infect();
- viri.Add(hulltri.triangle);
- }
- }
- else
- {
- // The triangle is protected; set boundary markers if appropriate.
- if (hullsubseg.seg.boundary == 0)
- {
- hullsubseg.seg.boundary = 1;
- horg = hulltri.Org();
- hdest = hulltri.Dest();
- if (horg.mark == 0)
- {
- horg.mark = 1;
- }
- if (hdest.mark == 0)
- {
- hdest.mark = 1;
- }
- }
- }
- }
- // To find the next hull edge, go clockwise around the next vertex.
- hulltri.LnextSelf();
- hulltri.Oprev(ref nexttri);
- while (nexttri.triangle != Mesh.dummytri)
- {
- nexttri.Copy(ref hulltri);
- hulltri.Oprev(ref nexttri);
- }
-
- } while (!hulltri.Equal(starttri));
- }
-
- ///
- /// Spread the virus from all infected triangles to any neighbors not
- /// protected by subsegments. Delete all infected triangles.
- ///
- ///
- /// This is the procedure that actually creates holes and concavities.
- ///
- /// This procedure operates in two phases. The first phase identifies all
- /// the triangles that will die, and marks them as infected. They are
- /// marked to ensure that each triangle is added to the virus pool only
- /// once, so the procedure will terminate.
- ///
- /// The second phase actually eliminates the infected triangles. It also
- /// eliminates orphaned vertices.
- ///
- void Plague()
- {
- Otri testtri = default(Otri);
- Otri neighbor = default(Otri);
- Osub neighborsubseg = default(Osub);
- Vertex testvertex;
- Vertex norg, ndest;
-
- bool killorg;
-
- // Loop through all the infected triangles, spreading the virus to
- // their neighbors, then to their neighbors' neighbors.
- for (int i = 0; i < viri.Count; i++)
- {
- // WARNING: Don't use foreach, mesh.viri list may get modified.
-
- testtri.triangle = viri[i];
- // A triangle is marked as infected by messing with one of its pointers
- // to subsegments, setting it to an illegal value. Hence, we have to
- // temporarily uninfect this triangle so that we can examine its
- // adjacent subsegments.
- // TODO: Not true in the C# version (so we could skip this).
- testtri.Uninfect();
-
- // Check each of the triangle's three neighbors.
- for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
- {
- // Find the neighbor.
- testtri.Sym(ref neighbor);
- // Check for a subsegment between the triangle and its neighbor.
- testtri.SegPivot(ref neighborsubseg);
- // Check if the neighbor is nonexistent or already infected.
- if ((neighbor.triangle == Mesh.dummytri) || neighbor.IsInfected())
- {
- if (neighborsubseg.seg != Mesh.dummysub)
- {
- // There is a subsegment separating the triangle from its
- // neighbor, but both triangles are dying, so the subsegment
- // dies too.
- mesh.SubsegDealloc(neighborsubseg.seg);
- if (neighbor.triangle != Mesh.dummytri)
- {
- // Make sure the subsegment doesn't get deallocated again
- // later when the infected neighbor is visited.
- neighbor.Uninfect();
- neighbor.SegDissolve();
- neighbor.Infect();
- }
- }
- }
- else
- { // The neighbor exists and is not infected.
- if (neighborsubseg.seg == Mesh.dummysub)
- {
- // There is no subsegment protecting the neighbor, so
- // the neighbor becomes infected.
- neighbor.Infect();
- // Ensure that the neighbor's neighbors will be infected.
- viri.Add(neighbor.triangle);
- }
- else
- {
- // The neighbor is protected by a subsegment.
- // Remove this triangle from the subsegment.
- neighborsubseg.TriDissolve();
- // The subsegment becomes a boundary. Set markers accordingly.
- if (neighborsubseg.seg.boundary == 0)
- {
- neighborsubseg.seg.boundary = 1;
- }
- norg = neighbor.Org();
- ndest = neighbor.Dest();
- if (norg.mark == 0)
- {
- norg.mark = 1;
- }
- if (ndest.mark == 0)
- {
- ndest.mark = 1;
- }
- }
- }
- }
- // Remark the triangle as infected, so it doesn't get added to the
- // virus pool again.
- testtri.Infect();
- }
-
- foreach (var virus in viri)
- {
- testtri.triangle = virus;
-
- // Check each of the three corners of the triangle for elimination.
- // This is done by walking around each vertex, checking if it is
- // still connected to at least one live triangle.
- for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
- {
- testvertex = testtri.Org();
- // Check if the vertex has already been tested.
- if (testvertex != null)
- {
- killorg = true;
- // Mark the corner of the triangle as having been tested.
- testtri.SetOrg(null);
- // Walk counterclockwise about the vertex.
- testtri.Onext(ref neighbor);
- // Stop upon reaching a boundary or the starting triangle.
- while ((neighbor.triangle != Mesh.dummytri) &&
- (!neighbor.Equal(testtri)))
- {
- if (neighbor.IsInfected())
- {
- // Mark the corner of this triangle as having been tested.
- neighbor.SetOrg(null);
- }
- else
- {
- // A live triangle. The vertex survives.
- killorg = false;
- }
- // Walk counterclockwise about the vertex.
- neighbor.OnextSelf();
- }
- // If we reached a boundary, we must walk clockwise as well.
- if (neighbor.triangle == Mesh.dummytri)
- {
- // Walk clockwise about the vertex.
- testtri.Oprev(ref neighbor);
- // Stop upon reaching a boundary.
- while (neighbor.triangle != Mesh.dummytri)
- {
- if (neighbor.IsInfected())
- {
- // Mark the corner of this triangle as having been tested.
- neighbor.SetOrg(null);
- }
- else
- {
- // A live triangle. The vertex survives.
- killorg = false;
- }
- // Walk clockwise about the vertex.
- neighbor.OprevSelf();
- }
- }
- if (killorg)
- {
- // Deleting vertex
- testvertex.type = VertexType.UndeadVertex;
- mesh.undeads++;
- }
- }
- }
-
- // Record changes in the number of boundary edges, and disconnect
- // dead triangles from their neighbors.
- for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
- {
- testtri.Sym(ref neighbor);
- if (neighbor.triangle == Mesh.dummytri)
- {
- // There is no neighboring triangle on this edge, so this edge
- // is a boundary edge. This triangle is being deleted, so this
- // boundary edge is deleted.
- mesh.hullsize--;
- }
- else
- {
- // Disconnect the triangle from its neighbor.
- neighbor.Dissolve();
- // There is a neighboring triangle on this edge, so this edge
- // becomes a boundary edge when this triangle is deleted.
- mesh.hullsize++;
- }
- }
- // Return the dead triangle to the pool of triangles.
- mesh.TriangleDealloc(testtri.triangle);
- }
-
- // Empty the virus pool.
- viri.Clear();
- }
-
- ///
- /// Find the holes and infect them. Find the area constraints and infect
- /// them. Infect the convex hull. Spread the infection and kill triangles.
- /// Spread the area constraints.
- ///
- public void CarveHoles()
- {
- Otri searchtri = default(Otri);
- Vertex searchorg, searchdest;
- LocateResult intersect;
-
- Triangle[] regionTris = null;
-
- if (!mesh.behavior.Convex)
- {
- // Mark as infected any unprotected triangles on the boundary.
- // This is one way by which concavities are created.
- InfectHull();
- }
-
- if (!mesh.behavior.NoHoles)
- {
- // Infect each triangle in which a hole lies.
- foreach (var hole in mesh.holes)
- {
- // Ignore holes that aren't within the bounds of the mesh.
- if (mesh.bounds.Contains(hole))
- {
- // Start searching from some triangle on the outer boundary.
- searchtri.triangle = Mesh.dummytri;
- searchtri.orient = 0;
- searchtri.SymSelf();
- // Ensure that the hole is to the left of this boundary edge;
- // otherwise, locate() will falsely report that the hole
- // falls within the starting triangle.
- searchorg = searchtri.Org();
- searchdest = searchtri.Dest();
- if (Primitives.CounterClockwise(searchorg, searchdest, hole) > 0.0)
- {
- // Find a triangle that contains the hole.
- intersect = mesh.locator.Locate(hole, ref searchtri);
- if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected()))
- {
- // Infect the triangle. This is done by marking the triangle
- // as infected and including the triangle in the virus pool.
- searchtri.Infect();
- viri.Add(searchtri.triangle);
- }
- }
- }
- }
- }
-
- // Now, we have to find all the regions BEFORE we carve the holes, because locate() won't
- // work when the triangulation is no longer convex. (Incidentally, this is the reason why
- // regional attributes and area constraints can't be used when refining a preexisting mesh,
- // which might not be convex; they can only be used with a freshly triangulated PSLG.)
- if (mesh.regions.Count > 0)
- {
- int i = 0;
-
- regionTris = new Triangle[mesh.regions.Count];
-
- // Find the starting triangle for each region.
- foreach (var region in mesh.regions)
- {
- regionTris[i] = Mesh.dummytri;
- // Ignore region points that aren't within the bounds of the mesh.
- if (mesh.bounds.Contains(region.point))
- {
- // Start searching from some triangle on the outer boundary.
- searchtri.triangle = Mesh.dummytri;
- searchtri.orient = 0;
- searchtri.SymSelf();
- // Ensure that the region point is to the left of this boundary
- // edge; otherwise, locate() will falsely report that the
- // region point falls within the starting triangle.
- searchorg = searchtri.Org();
- searchdest = searchtri.Dest();
- if (Primitives.CounterClockwise(searchorg, searchdest, region.point) > 0.0)
- {
- // Find a triangle that contains the region point.
- intersect = mesh.locator.Locate(region.point, ref searchtri);
- if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected()))
- {
- // Record the triangle for processing after the
- // holes have been carved.
- regionTris[i] = searchtri.triangle;
- regionTris[i].region = region.id;
- }
- }
- }
-
- i++;
- }
- }
-
- if (viri.Count > 0)
- {
- // Carve the holes and concavities.
- Plague();
- }
-
- if (regionTris != null)
- {
- var iterator = new RegionIterator(mesh);
-
- for (int i = 0; i < regionTris.Length; i++)
- {
- if (regionTris[i] != Mesh.dummytri)
- {
- // Make sure the triangle under consideration still exists.
- // It may have been eaten by the virus.
- if (!Otri.IsDead(regionTris[i]))
- {
- // Apply one region's attribute and/or area constraint.
- iterator.Process(regionTris[i]);
- }
- }
- }
- }
-
- // Free up memory (virus pool should be empty anyway).
- viri.Clear();
- }
- }
-}
diff --git a/Triangle.NET/Triangle/ConstraintMesher.cs b/Triangle.NET/Triangle/ConstraintMesher.cs
index 13ec654..db3809d 100644
--- a/Triangle.NET/Triangle/ConstraintMesher.cs
+++ b/Triangle.NET/Triangle/ConstraintMesher.cs
@@ -8,9 +8,11 @@
namespace TriangleNet
{
using System;
+ using System.Collections.Generic;
using TriangleNet.Data;
using TriangleNet.Geometry;
using TriangleNet.Log;
+ using TriangleNet.Tools;
internal class ConstraintMesher
{
@@ -18,6 +20,8 @@ namespace TriangleNet
Behavior behavior;
TriangleLocator locator;
+ List viri;
+
ILog logger;
public ConstraintMesher(Mesh mesh)
@@ -26,16 +30,141 @@ namespace TriangleNet
this.behavior = mesh.behavior;
this.locator = mesh.locator;
+ this.viri = new List();
+
logger = SimpleLog.Instance;
}
+ ///
+ /// Find the holes and infect them. Find the area constraints and infect
+ /// them. Infect the convex hull. Spread the infection and kill triangles.
+ /// Spread the area constraints.
+ ///
+ public void CarveHoles()
+ {
+ Otri searchtri = default(Otri);
+ Vertex searchorg, searchdest;
+ LocateResult intersect;
+
+ Triangle[] regionTris = null;
+
+ if (!mesh.behavior.Convex)
+ {
+ // Mark as infected any unprotected triangles on the boundary.
+ // This is one way by which concavities are created.
+ InfectHull();
+ }
+
+ if (!mesh.behavior.NoHoles)
+ {
+ // Infect each triangle in which a hole lies.
+ foreach (var hole in mesh.holes)
+ {
+ // Ignore holes that aren't within the bounds of the mesh.
+ if (mesh.bounds.Contains(hole))
+ {
+ // Start searching from some triangle on the outer boundary.
+ searchtri.triangle = Mesh.dummytri;
+ searchtri.orient = 0;
+ searchtri.SymSelf();
+ // Ensure that the hole is to the left of this boundary edge;
+ // otherwise, locate() will falsely report that the hole
+ // falls within the starting triangle.
+ searchorg = searchtri.Org();
+ searchdest = searchtri.Dest();
+ if (Primitives.CounterClockwise(searchorg, searchdest, hole) > 0.0)
+ {
+ // Find a triangle that contains the hole.
+ intersect = mesh.locator.Locate(hole, ref searchtri);
+ if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected()))
+ {
+ // Infect the triangle. This is done by marking the triangle
+ // as infected and including the triangle in the virus pool.
+ searchtri.Infect();
+ viri.Add(searchtri.triangle);
+ }
+ }
+ }
+ }
+ }
+
+ // Now, we have to find all the regions BEFORE we carve the holes, because locate() won't
+ // work when the triangulation is no longer convex. (Incidentally, this is the reason why
+ // regional attributes and area constraints can't be used when refining a preexisting mesh,
+ // which might not be convex; they can only be used with a freshly triangulated PSLG.)
+ if (mesh.regions.Count > 0)
+ {
+ int i = 0;
+
+ regionTris = new Triangle[mesh.regions.Count];
+
+ // Find the starting triangle for each region.
+ foreach (var region in mesh.regions)
+ {
+ regionTris[i] = Mesh.dummytri;
+ // Ignore region points that aren't within the bounds of the mesh.
+ if (mesh.bounds.Contains(region.point))
+ {
+ // Start searching from some triangle on the outer boundary.
+ searchtri.triangle = Mesh.dummytri;
+ searchtri.orient = 0;
+ searchtri.SymSelf();
+ // Ensure that the region point is to the left of this boundary
+ // edge; otherwise, locate() will falsely report that the
+ // region point falls within the starting triangle.
+ searchorg = searchtri.Org();
+ searchdest = searchtri.Dest();
+ if (Primitives.CounterClockwise(searchorg, searchdest, region.point) > 0.0)
+ {
+ // Find a triangle that contains the region point.
+ intersect = mesh.locator.Locate(region.point, ref searchtri);
+ if ((intersect != LocateResult.Outside) && (!searchtri.IsInfected()))
+ {
+ // Record the triangle for processing after the
+ // holes have been carved.
+ regionTris[i] = searchtri.triangle;
+ regionTris[i].region = region.id;
+ }
+ }
+ }
+
+ i++;
+ }
+ }
+
+ if (viri.Count > 0)
+ {
+ // Carve the holes and concavities.
+ Plague();
+ }
+
+ if (regionTris != null)
+ {
+ var iterator = new RegionIterator(mesh);
+
+ for (int i = 0; i < regionTris.Length; i++)
+ {
+ if (regionTris[i] != Mesh.dummytri)
+ {
+ // Make sure the triangle under consideration still exists.
+ // It may have been eaten by the virus.
+ if (!Otri.IsDead(regionTris[i]))
+ {
+ // Apply one region's attribute and/or area constraint.
+ iterator.Process(regionTris[i]);
+ }
+ }
+ }
+ }
+
+ // Free up memory (virus pool should be empty anyway).
+ viri.Clear();
+ }
+
///
/// Create the segments of a triangulation, including PSLG segments and edges
/// on the convex hull.
///
- ///
- ///
- ///
public void FormSkeleton(InputGeometry input)
{
Vertex endpoint1, endpoint2;
@@ -116,6 +245,275 @@ namespace TriangleNet
}
}
+ #region Carving holes
+
+ ///
+ /// Virally infect all of the triangles of the convex hull that are not
+ /// protected by subsegments. Where there are subsegments, set boundary
+ /// markers as appropriate.
+ ///
+ private void InfectHull()
+ {
+ Otri hulltri = default(Otri);
+ Otri nexttri = default(Otri);
+ Otri starttri = default(Otri);
+ Osub hullsubseg = default(Osub);
+ Vertex horg, hdest;
+
+ // Find a triangle handle on the hull.
+ hulltri.triangle = Mesh.dummytri;
+ hulltri.orient = 0;
+ hulltri.SymSelf();
+ // Remember where we started so we know when to stop.
+ hulltri.Copy(ref starttri);
+ // Go once counterclockwise around the convex hull.
+ do
+ {
+ // Ignore triangles that are already infected.
+ if (!hulltri.IsInfected())
+ {
+ // Is the triangle protected by a subsegment?
+ hulltri.SegPivot(ref hullsubseg);
+ if (hullsubseg.seg == Mesh.dummysub)
+ {
+ // The triangle is not protected; infect it.
+ if (!hulltri.IsInfected())
+ {
+ hulltri.Infect();
+ viri.Add(hulltri.triangle);
+ }
+ }
+ else
+ {
+ // The triangle is protected; set boundary markers if appropriate.
+ if (hullsubseg.seg.boundary == 0)
+ {
+ hullsubseg.seg.boundary = 1;
+ horg = hulltri.Org();
+ hdest = hulltri.Dest();
+ if (horg.mark == 0)
+ {
+ horg.mark = 1;
+ }
+ if (hdest.mark == 0)
+ {
+ hdest.mark = 1;
+ }
+ }
+ }
+ }
+ // To find the next hull edge, go clockwise around the next vertex.
+ hulltri.LnextSelf();
+ hulltri.Oprev(ref nexttri);
+ while (nexttri.triangle != Mesh.dummytri)
+ {
+ nexttri.Copy(ref hulltri);
+ hulltri.Oprev(ref nexttri);
+ }
+
+ } while (!hulltri.Equal(starttri));
+ }
+
+ ///
+ /// Spread the virus from all infected triangles to any neighbors not
+ /// protected by subsegments. Delete all infected triangles.
+ ///
+ ///
+ /// This is the procedure that actually creates holes and concavities.
+ ///
+ /// This procedure operates in two phases. The first phase identifies all
+ /// the triangles that will die, and marks them as infected. They are
+ /// marked to ensure that each triangle is added to the virus pool only
+ /// once, so the procedure will terminate.
+ ///
+ /// The second phase actually eliminates the infected triangles. It also
+ /// eliminates orphaned vertices.
+ ///
+ void Plague()
+ {
+ Otri testtri = default(Otri);
+ Otri neighbor = default(Otri);
+ Osub neighborsubseg = default(Osub);
+ Vertex testvertex;
+ Vertex norg, ndest;
+
+ bool killorg;
+
+ // Loop through all the infected triangles, spreading the virus to
+ // their neighbors, then to their neighbors' neighbors.
+ for (int i = 0; i < viri.Count; i++)
+ {
+ // WARNING: Don't use foreach, mesh.viri list may get modified.
+
+ testtri.triangle = viri[i];
+ // A triangle is marked as infected by messing with one of its pointers
+ // to subsegments, setting it to an illegal value. Hence, we have to
+ // temporarily uninfect this triangle so that we can examine its
+ // adjacent subsegments.
+ // TODO: Not true in the C# version (so we could skip this).
+ testtri.Uninfect();
+
+ // Check each of the triangle's three neighbors.
+ for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
+ {
+ // Find the neighbor.
+ testtri.Sym(ref neighbor);
+ // Check for a subsegment between the triangle and its neighbor.
+ testtri.SegPivot(ref neighborsubseg);
+ // Check if the neighbor is nonexistent or already infected.
+ if ((neighbor.triangle == Mesh.dummytri) || neighbor.IsInfected())
+ {
+ if (neighborsubseg.seg != Mesh.dummysub)
+ {
+ // There is a subsegment separating the triangle from its
+ // neighbor, but both triangles are dying, so the subsegment
+ // dies too.
+ mesh.SubsegDealloc(neighborsubseg.seg);
+ if (neighbor.triangle != Mesh.dummytri)
+ {
+ // Make sure the subsegment doesn't get deallocated again
+ // later when the infected neighbor is visited.
+ neighbor.Uninfect();
+ neighbor.SegDissolve();
+ neighbor.Infect();
+ }
+ }
+ }
+ else
+ { // The neighbor exists and is not infected.
+ if (neighborsubseg.seg == Mesh.dummysub)
+ {
+ // There is no subsegment protecting the neighbor, so
+ // the neighbor becomes infected.
+ neighbor.Infect();
+ // Ensure that the neighbor's neighbors will be infected.
+ viri.Add(neighbor.triangle);
+ }
+ else
+ {
+ // The neighbor is protected by a subsegment.
+ // Remove this triangle from the subsegment.
+ neighborsubseg.TriDissolve();
+ // The subsegment becomes a boundary. Set markers accordingly.
+ if (neighborsubseg.seg.boundary == 0)
+ {
+ neighborsubseg.seg.boundary = 1;
+ }
+ norg = neighbor.Org();
+ ndest = neighbor.Dest();
+ if (norg.mark == 0)
+ {
+ norg.mark = 1;
+ }
+ if (ndest.mark == 0)
+ {
+ ndest.mark = 1;
+ }
+ }
+ }
+ }
+ // Remark the triangle as infected, so it doesn't get added to the
+ // virus pool again.
+ testtri.Infect();
+ }
+
+ foreach (var virus in viri)
+ {
+ testtri.triangle = virus;
+
+ // Check each of the three corners of the triangle for elimination.
+ // This is done by walking around each vertex, checking if it is
+ // still connected to at least one live triangle.
+ for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
+ {
+ testvertex = testtri.Org();
+ // Check if the vertex has already been tested.
+ if (testvertex != null)
+ {
+ killorg = true;
+ // Mark the corner of the triangle as having been tested.
+ testtri.SetOrg(null);
+ // Walk counterclockwise about the vertex.
+ testtri.Onext(ref neighbor);
+ // Stop upon reaching a boundary or the starting triangle.
+ while ((neighbor.triangle != Mesh.dummytri) &&
+ (!neighbor.Equal(testtri)))
+ {
+ if (neighbor.IsInfected())
+ {
+ // Mark the corner of this triangle as having been tested.
+ neighbor.SetOrg(null);
+ }
+ else
+ {
+ // A live triangle. The vertex survives.
+ killorg = false;
+ }
+ // Walk counterclockwise about the vertex.
+ neighbor.OnextSelf();
+ }
+ // If we reached a boundary, we must walk clockwise as well.
+ if (neighbor.triangle == Mesh.dummytri)
+ {
+ // Walk clockwise about the vertex.
+ testtri.Oprev(ref neighbor);
+ // Stop upon reaching a boundary.
+ while (neighbor.triangle != Mesh.dummytri)
+ {
+ if (neighbor.IsInfected())
+ {
+ // Mark the corner of this triangle as having been tested.
+ neighbor.SetOrg(null);
+ }
+ else
+ {
+ // A live triangle. The vertex survives.
+ killorg = false;
+ }
+ // Walk clockwise about the vertex.
+ neighbor.OprevSelf();
+ }
+ }
+ if (killorg)
+ {
+ // Deleting vertex
+ testvertex.type = VertexType.UndeadVertex;
+ mesh.undeads++;
+ }
+ }
+ }
+
+ // Record changes in the number of boundary edges, and disconnect
+ // dead triangles from their neighbors.
+ for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
+ {
+ testtri.Sym(ref neighbor);
+ if (neighbor.triangle == Mesh.dummytri)
+ {
+ // There is no neighboring triangle on this edge, so this edge
+ // is a boundary edge. This triangle is being deleted, so this
+ // boundary edge is deleted.
+ mesh.hullsize--;
+ }
+ else
+ {
+ // Disconnect the triangle from its neighbor.
+ neighbor.Dissolve();
+ // There is a neighboring triangle on this edge, so this edge
+ // becomes a boundary edge when this triangle is deleted.
+ mesh.hullsize++;
+ }
+ }
+ // Return the dead triangle to the pool of triangles.
+ mesh.TriangleDealloc(testtri.triangle);
+ }
+
+ // Empty the virus pool.
+ viri.Clear();
+ }
+
+ #endregion
+
#region Segment insertion
///
diff --git a/Triangle.NET/Triangle/Mesh.cs b/Triangle.NET/Triangle/Mesh.cs
index c0eaa7f..2255a46 100644
--- a/Triangle.NET/Triangle/Mesh.cs
+++ b/Triangle.NET/Triangle/Mesh.cs
@@ -335,13 +335,14 @@ namespace TriangleNet
infvertex2 = null;
infvertex3 = null;
+ // Insert segments, carving holes.
+ var mesher = new ConstraintMesher(this);
+
if (behavior.useSegments)
{
// Segments will be introduced next.
checksegments = true;
- var mesher = new ConstraintMesher(this);
-
// Insert PSLG segments and/or convex hull segments.
mesher.FormSkeleton(input);
}
@@ -363,8 +364,7 @@ namespace TriangleNet
//dummytri.neighbors[2].triangle = dummytri;
// Carve out holes and concavities.
- Carver c = new Carver(this);
- c.CarveHoles();
+ mesher.CarveHoles();
}
else
{
@@ -618,8 +618,8 @@ namespace TriangleNet
Statistic.InCircleCount = 0;
Statistic.CounterClockwiseCount = 0;
- Statistic.InCircleCountDecimal = 0;
- Statistic.CounterClockwiseCountDecimal = 0;
+ Statistic.InCircleAdaptCount = 0;
+ Statistic.CounterClockwiseAdaptCount = 0;
Statistic.Orient3dCount = 0;
Statistic.HyperbolaCount = 0;
Statistic.CircleTopCount = 0;
diff --git a/Triangle.NET/Triangle/Primitives.cs b/Triangle.NET/Triangle/Primitives.cs
index 6433046..793de81 100644
--- a/Triangle.NET/Triangle/Primitives.cs
+++ b/Triangle.NET/Triangle/Primitives.cs
@@ -147,6 +147,7 @@ namespace TriangleNet
return det;
}
+ Statistic.CounterClockwiseAdaptCount++;
return CounterClockwiseAdapt(pa, pb, pc, detsum);
}
@@ -209,6 +210,7 @@ namespace TriangleNet
return det;
}
+ Statistic.InCircleAdaptCount++;
return InCircleAdapt(pa, pb, pc, pd, permanent);
}
diff --git a/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs b/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs
index 91c0156..8ffd857 100644
--- a/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs
+++ b/Triangle.NET/Triangle/Tools/BoundedVoronoi.cs
@@ -27,6 +27,8 @@ namespace TriangleNet.Tools
Point[] points;
List regions;
+ // Used for new points on segments.
+ List segPoints;
int segIndex;
Dictionary subsegMap;
@@ -79,9 +81,11 @@ namespace TriangleNet.Tools
mesh.MakeVertexMap();
// Allocate space for voronoi diagram
- this.points = new Point[mesh.triangles.Count + mesh.subsegs.Count * 5]; // This is an upper bound.
this.regions = new List(mesh.vertices.Count);
+ this.points = new Point[mesh.triangles.Count];
+ this.segPoints = new List(mesh.subsegs.Count * 4);
+
ComputeCircumCenters();
TagBlindTriangles();
@@ -98,6 +102,19 @@ namespace TriangleNet.Tools
ConstructBoundaryBvdCell(v);
}
}
+
+ // Add the new points on segments to the point array.
+ int length = points.Length;
+
+ Array.Resize(ref points, length + segPoints.Count);
+
+ for (int i = 0; i < segPoints.Count; i++)
+ {
+ points[length + i] = segPoints[i];
+ }
+
+ this.segPoints.Clear();
+ this.segPoints = null;
}
private void ComputeCircumCenters()
@@ -297,10 +314,8 @@ namespace TriangleNet.Tools
// Insert point Lf,f_next /\ Sf_next into P
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -316,10 +331,8 @@ namespace TriangleNet.Tools
// Insert point Lf,f_next /\ Sf into P
if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -334,19 +347,15 @@ namespace TriangleNet.Tools
// Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
if (SegmentsIntersect(sf.SegOrg(), sf.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -418,10 +427,9 @@ namespace TriangleNet.Tools
// For vertices on the domain boundaray, add the vertex. For
// internal boundaries don't add it.
p = new Point(vertex.x, vertex.y);
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
@@ -429,10 +437,9 @@ namespace TriangleNet.Tools
torg = f.Org();
tdest = f.Dest();
p = new Point((torg.X + tdest.X) / 2, (torg.Y + tdest.Y) / 2);
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
// repeat ... until f = f_init
@@ -454,10 +461,9 @@ namespace TriangleNet.Tools
torg = f.Org();
tapex = f.Apex();
p = new Point((torg.X + tapex.X) / 2, (torg.Y + tapex.Y) / 2);
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
break;
@@ -479,10 +485,8 @@ namespace TriangleNet.Tools
// Insert point Lf,f_next /\ Sf_next into P
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -510,20 +514,16 @@ namespace TriangleNet.Tools
// Find intersection of seg with line through f's bisector and circumcenter
if (SegmentsIntersect(sorg, sdest, bisec, cc_f, out p, false))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
// Insert point Lf,f_next /\ Sf into P
if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -538,19 +538,15 @@ namespace TriangleNet.Tools
// Insert Lf,fnext /\ Sf and Lf,fnext /\ Sfnext into P
if (SegmentsIntersect(sorg, sdest, cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
if (SegmentsIntersect(sfn.SegOrg(), sfn.SegDest(), cc_f, cc_f_next, out p, true))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
@@ -565,10 +561,8 @@ namespace TriangleNet.Tools
// Find intersection of seg with line through f_next's bisector and circumcenter
if (SegmentsIntersect(sorg, sdest, bisec, cc_f_next, out p, false))
{
- p.id = n + segIndex;
- points[n + segIndex] = p;
- segIndex++;
-
+ p.id = n + segIndex++;
+ segPoints.Add(p);
vpoints.Add(p);
}
}
diff --git a/Triangle.NET/Triangle/Tools/Statistic.cs b/Triangle.NET/Triangle/Tools/Statistic.cs
index 002d7bb..a22b17b 100644
--- a/Triangle.NET/Triangle/Tools/Statistic.cs
+++ b/Triangle.NET/Triangle/Tools/Statistic.cs
@@ -23,13 +23,13 @@ namespace TriangleNet.Tools
/// Number of incircle tests performed.
///
public static long InCircleCount = 0;
- public static long InCircleCountDecimal = 0;
+ public static long InCircleAdaptCount = 0;
///
/// Number of counterclockwise tests performed.
///
public static long CounterClockwiseCount = 0;
- public static long CounterClockwiseCountDecimal = 0;
+ public static long CounterClockwiseAdaptCount = 0;
///
/// Number of 3D orientation tests performed.
diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj
index 488da34..7fbd442 100644
--- a/Triangle.NET/Triangle/Triangle.csproj
+++ b/Triangle.NET/Triangle/Triangle.csproj
@@ -44,7 +44,6 @@
-