Fix Bounded Voronoi exception;

More code reorganization;

git-svn-id: https://triangle.svn.codeplex.com/svn@74907 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2014-04-24 12:24:42 +00:00
parent 616f86c52b
commit c5c0b3363a
7 changed files with 455 additions and 483 deletions
-421
View File
@@ -1,421 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="Carver.cs">
// 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/
// </copyright>
// -----------------------------------------------------------------------
namespace TriangleNet
{
using TriangleNet.Data;
using System;
using TriangleNet.Geometry;
using System.Collections.Generic;
using TriangleNet.Tools;
/// <summary>
/// Carves holes into the triangulation.
/// </summary>
class Carver
{
Mesh mesh;
List<Triangle> viri;
public Carver(Mesh mesh)
{
this.mesh = mesh;
this.viri = new List<Triangle>();
}
/// <summary>
/// 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.
/// </summary>
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));
}
/// <summary>
/// Spread the virus from all infected triangles to any neighbors not
/// protected by subsegments. Delete all infected triangles.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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();
}
/// <summary>
/// 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.
/// </summary>
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();
}
}
}
+401 -3
View File
@@ -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<Triangle> viri;
ILog<SimpleLogItem> logger;
public ConstraintMesher(Mesh mesh)
@@ -26,16 +30,141 @@ namespace TriangleNet
this.behavior = mesh.behavior;
this.locator = mesh.locator;
this.viri = new List<Triangle>();
logger = SimpleLog.Instance;
}
/// <summary>
/// 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.
/// </summary>
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();
}
/// <summary>
/// Create the segments of a triangulation, including PSLG segments and edges
/// on the convex hull.
/// </summary>
/// <param name="segmentlist"></param>
/// <param name="segmentmarkerlist"></param>
/// <param name="numberofsegments"></param>
public void FormSkeleton(InputGeometry input)
{
Vertex endpoint1, endpoint2;
@@ -116,6 +245,275 @@ namespace TriangleNet
}
}
#region Carving holes
/// <summary>
/// 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.
/// </summary>
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));
}
/// <summary>
/// Spread the virus from all infected triangles to any neighbors not
/// protected by subsegments. Delete all infected triangles.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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
/// <summary>
+6 -6
View File
@@ -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;
+2
View File
@@ -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);
}
+44 -50
View File
@@ -27,6 +27,8 @@ namespace TriangleNet.Tools
Point[] points;
List<VoronoiRegion> regions;
// Used for new points on segments.
List<Point> segPoints;
int segIndex;
Dictionary<int, Segment> 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<VoronoiRegion>(mesh.vertices.Count);
this.points = new Point[mesh.triangles.Count];
this.segPoints = new List<Point>(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<Point>(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);
}
}
+2 -2
View File
@@ -23,13 +23,13 @@ namespace TriangleNet.Tools
/// Number of incircle tests performed.
/// </summary>
public static long InCircleCount = 0;
public static long InCircleCountDecimal = 0;
public static long InCircleAdaptCount = 0;
/// <summary>
/// Number of counterclockwise tests performed.
/// </summary>
public static long CounterClockwiseCount = 0;
public static long CounterClockwiseCountDecimal = 0;
public static long CounterClockwiseAdaptCount = 0;
/// <summary>
/// Number of 3D orientation tests performed.
-1
View File
@@ -44,7 +44,6 @@
<Compile Include="Algorithm\ITriangulator.cs" />
<Compile Include="BadTriQueue.cs" />
<Compile Include="Behavior.cs" />
<Compile Include="Carver.cs" />
<Compile Include="ConstraintMesher.cs" />
<Compile Include="Data\BadSubseg.cs" />
<Compile Include="Data\BadTriangle.cs" />