Fix for issues #9419/9390 + some minor changes

git-svn-id: https://triangle.svn.codeplex.com/svn@67675 0e2699bc-83d4-4a8f-98e7-55e24ab8c7a5
This commit is contained in:
SND\wo80_cp
2012-05-28 14:35:16 +00:00
parent 5bebd21141
commit c9dac5d6d1
5 changed files with 54 additions and 79 deletions
+12 -1
View File
@@ -93,6 +93,7 @@ namespace TestApp
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
meshRenderer1.SetData(mesh, false);
@@ -180,7 +181,16 @@ namespace TestApp
else
{
dlgFilterIndex = 1;
input = FileReader.ReadFile(file);
try
{
input = FileReader.ReadFile(file);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
input = null;
return;
}
}
meshRenderer1.SetData(input, true);
@@ -212,6 +222,7 @@ namespace TestApp
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
meshRenderer1.SetData(mesh, false);
+36 -33
View File
@@ -47,6 +47,9 @@ namespace TriangleNet.Algorithm
static Random rand = new Random(DateTime.Now.Millisecond);
bool useDwyer = true;
Vertex[] sortarray;
Mesh mesh;
/// <summary>
/// Sort an array of vertices by x-coordinate, using the y-coordinate as a secondary key.
/// </summary>
@@ -57,7 +60,7 @@ namespace TriangleNet.Algorithm
/// Uses quicksort. Randomized O(n log n) time. No, I did not make any of
/// the usual quicksort mistakes.
/// </remarks>
static void VertexSort(Vertex[] sortarray, int left, int right)
void VertexSort(int left, int right)
{
int oleft = left;
int oright = right;
@@ -121,12 +124,12 @@ namespace TriangleNet.Algorithm
if (left > oleft)
{
// Recursively sort the left subset.
VertexSort(sortarray, oleft, left);
VertexSort(oleft, left);
}
if (oright > right + 1)
{
// Recursively sort the right subset.
VertexSort(sortarray, right + 1, oright);
VertexSort(right + 1, oright);
}
}
@@ -144,7 +147,7 @@ namespace TriangleNet.Algorithm
/// if axis == 1. Very similar to the vertexsort() procedure, but runs in
/// randomized linear time.
/// </remarks>
void VertexMedian(Vertex[] sortarray, int left, int right, int median, int axis)
void VertexMedian(int left, int right, int median, int axis)
{
int arraysize = right - left + 1;
int oleft = left, oright = right;
@@ -203,12 +206,12 @@ namespace TriangleNet.Algorithm
if (left > median)
{
// Recursively shuffle the left subset.
VertexMedian(sortarray, oleft, left - 1, median, axis);
VertexMedian(oleft, left - 1, median, axis);
}
if (right < median - 1)
{
// Recursively shuffle the right subset.
VertexMedian(sortarray, right + 1, oright, median, axis);
VertexMedian(right + 1, oright, median, axis);
}
}
@@ -225,7 +228,7 @@ namespace TriangleNet.Algorithm
/// For the base case, subsets containing only two or three vertices are
/// always sorted by x-coordinate.
/// </remarks>
void AlternateAxes(Vertex[] sortarray, int left, int right, int axis)
void AlternateAxes(int left, int right, int axis)
{
int arraysize = right - left + 1;
int divider;
@@ -239,15 +242,15 @@ namespace TriangleNet.Algorithm
axis = 0;
}
// Partition with a horizontal or vertical cut.
VertexMedian(sortarray, left, right, left + divider, axis);
VertexMedian(left, right, left + divider, axis);
// Recursively partition the subsets with a cross cut.
if (arraysize - divider >= 2)
{
if (divider >= 2)
{
AlternateAxes(sortarray, left, left + divider - 1, 1 - axis);
AlternateAxes(left, left + divider - 1, 1 - axis);
}
AlternateAxes(sortarray, left + divider, right, 1 - axis);
AlternateAxes(left + divider, right, 1 - axis);
}
}
@@ -288,8 +291,7 @@ namespace TriangleNet.Algorithm
/// merged triangulation, and the destination of 'farright' is the rightmost
/// vertex.
/// </remarks>
void MergeHulls(Mesh m, ref Otri farleft,
ref Otri innerleft, ref Otri innerright,
void MergeHulls(ref Otri farleft, ref Otri innerleft, ref Otri innerright,
ref Otri farright, int axis)
{
Otri leftcand = default(Otri), rightcand = default(Otri);
@@ -386,7 +388,7 @@ namespace TriangleNet.Algorithm
innerleft.Sym(ref leftcand);
innerright.Sym(ref rightcand);
// Create the bottom new bounding triangle.
m.MakeTriangle(ref baseedge);
mesh.MakeTriangle(ref baseedge);
// Connect it to the bounding boxes of the left and right triangulations.
baseedge.Bond(ref innerleft);
baseedge.LnextSelf();
@@ -425,7 +427,7 @@ namespace TriangleNet.Algorithm
if (leftfinished && rightfinished)
{
// Create the top new bounding triangle.
m.MakeTriangle(ref nextedge);
mesh.MakeTriangle(ref nextedge);
nextedge.SetOrg(lowerleft);
nextedge.SetDest(lowerright);
// Apex is intentionally left NULL.
@@ -616,7 +618,7 @@ namespace TriangleNet.Algorithm
/// 'farright' is the rightmost vertex (breaking ties by choosing the
/// lowest rightmost vertex).
/// </remarks>
void DivconqRecurse(Mesh m, Vertex[] sortarray, int left, int right, int axis,
void DivconqRecurse(int left, int right, int axis,
ref Otri farleft, ref Otri farright)
{
Otri midtri = default(Otri);
@@ -632,11 +634,11 @@ namespace TriangleNet.Algorithm
{
// The triangulation of two vertices is an edge. An edge is
// represented by two bounding triangles.
m.MakeTriangle(ref farleft);
mesh.MakeTriangle(ref farleft);
farleft.SetOrg(sortarray[left]);
farleft.SetDest(sortarray[left + 1]);
// The apex is intentionally left NULL.
m.MakeTriangle(ref farright);
mesh.MakeTriangle(ref farright);
farright.SetOrg(sortarray[left + 1]);
farright.SetDest(sortarray[left]);
// The apex is intentionally left NULL.
@@ -657,10 +659,10 @@ namespace TriangleNet.Algorithm
// The triangulation of three vertices is either a triangle (with
// three bounding triangles) or two edges (with four bounding
// triangles). In either case, four triangles are created.
m.MakeTriangle(ref midtri);
m.MakeTriangle(ref tri1);
m.MakeTriangle(ref tri2);
m.MakeTriangle(ref tri3);
mesh.MakeTriangle(ref midtri);
mesh.MakeTriangle(ref tri1);
mesh.MakeTriangle(ref tri2);
mesh.MakeTriangle(ref tri3);
area = Primitives.CounterClockwise(sortarray[left].pt, sortarray[left + 1].pt, sortarray[left + 2].pt);
if (area == 0.0)
{
@@ -756,11 +758,11 @@ namespace TriangleNet.Algorithm
// Split the vertices in half.
divider = vertices >> 1;
// Recursively triangulate each half.
DivconqRecurse(m, sortarray, left, left + divider - 1, 1 - axis, ref farleft, ref innerleft);
DivconqRecurse(m, sortarray, left + divider, right, 1 - axis, ref innerright, ref farright);
DivconqRecurse(left, left + divider - 1, 1 - axis, ref farleft, ref innerleft);
DivconqRecurse(left + divider, right, 1 - axis, ref innerright, ref farright);
// Merge the two triangulations into one.
MergeHulls(m, ref farleft, ref innerleft, ref innerright, ref farright, axis);
MergeHulls(ref farleft, ref innerleft, ref innerright, ref farright, axis);
}
}
@@ -769,7 +771,7 @@ namespace TriangleNet.Algorithm
/// </summary>
/// <param name="startghost"></param>
/// <returns>Number of vertices on the hull.</returns>
int RemoveGhosts(Mesh m, ref Otri startghost)
int RemoveGhosts(ref Otri startghost)
{
Otri searchedge = default(Otri);
Otri dissolveedge = default(Otri);
@@ -809,7 +811,7 @@ namespace TriangleNet.Algorithm
// Find the next bounding triangle.
deadtriangle.Sym(ref dissolveedge);
// Delete the bounding triangle.
m.TriangleDealloc(deadtriangle.triangle);
mesh.TriangleDealloc(deadtriangle.triangle);
} while (!dissolveedge.Equal(startghost));
return hullsize;
@@ -825,13 +827,14 @@ namespace TriangleNet.Algorithm
/// </remarks>
public int Triangulate(Mesh m)
{
Vertex[] sortarray;
Otri hullleft = default(Otri), hullright = default(Otri);
int divider;
int i, j;
this.mesh = m;
// Allocate an array of pointers to vertices for sorting.
sortarray = new Vertex[m.invertices];
this.sortarray = new Vertex[m.invertices];
i = 0;
foreach (var v in m.vertices.Values)
{
@@ -839,7 +842,7 @@ namespace TriangleNet.Algorithm
}
// Sort the vertices.
//Array.Sort(sortarray);
VertexSort(sortarray, 0, m.invertices - 1);
VertexSort(0, m.invertices - 1);
// Discard duplicate vertices, which can really mess up the algorithm.
i = 0;
for (j = 1; j < m.invertices; j++)
@@ -871,17 +874,17 @@ namespace TriangleNet.Algorithm
{
if (divider >= 2)
{
AlternateAxes(sortarray, 0, divider - 1, 1);
AlternateAxes(0, divider - 1, 1);
}
AlternateAxes(sortarray, divider, i - 1, 1);
AlternateAxes(divider, i - 1, 1);
}
}
// Form the Delaunay triangulation.
DivconqRecurse(m, sortarray, 0, i-1, 0, ref hullleft, ref hullright);
DivconqRecurse(0, i-1, 0, ref hullleft, ref hullright);
//trifree((VOID*)sortarray);
return RemoveGhosts(m, ref hullleft);
return RemoveGhosts(ref hullleft);
}
}
}
+3 -3
View File
@@ -485,7 +485,7 @@ namespace TriangleNet.Algorithm
/// </summary>
/// <param name="startghost"></param>
/// <returns>Number of vertices on the hull.</returns>
int RemoveGhosts(Mesh m, ref Otri startghost)
int RemoveGhosts(ref Otri startghost)
{
Otri searchedge = default(Otri);
Otri dissolveedge = default(Otri);
@@ -525,7 +525,7 @@ namespace TriangleNet.Algorithm
// Find the next bounding triangle.
deadtriangle.Sym(ref dissolveedge);
// Delete the bounding triangle.
m.TriangleDealloc(deadtriangle.triangle);
mesh.TriangleDealloc(deadtriangle.triangle);
} while (!dissolveedge.Equal(startghost));
return hullsize;
@@ -746,7 +746,7 @@ namespace TriangleNet.Algorithm
splaynodes.Clear();
bottommost.LprevSelf();
return RemoveGhosts(mesh, ref bottommost);
return RemoveGhosts(ref bottommost);
}
}
}
+2 -42
View File
@@ -28,7 +28,7 @@ namespace TriangleNet
/// protected by subsegments. Where there are subsegments, set boundary
/// markers as appropriate.
/// </summary>
bool InfectHull()
void InfectHull()
{
Otri hulltri = default(Otri);
Otri nexttri = default(Otri);
@@ -36,8 +36,6 @@ namespace TriangleNet
Osub hullsubseg = default(Osub);
Vertex horg, hdest;
int workaround, nseg= mesh.subsegs.Count;
// Find a triangle handle on the hull.
hulltri.triangle = Mesh.dummytri;
hulltri.orient = 0;
@@ -47,8 +45,6 @@ namespace TriangleNet
// Go once counterclockwise around the convex hull.
do
{
workaround = 0;
// Ignore triangles that are already infected.
if (!hulltri.IsInfected())
{
@@ -89,22 +85,8 @@ namespace TriangleNet
{
nexttri.Copy(ref hulltri);
hulltri.Oprev(ref nexttri);
if (++workaround > nseg)
{
// Reverse infection
foreach (var item in mesh.viri)
{
item.infected = false;
}
mesh.viri.Clear();
return false;
}
}
} while (!hulltri.Equal(starttri));
return true;
}
/// <summary>
@@ -404,29 +386,7 @@ namespace TriangleNet
{
// Mark as infected any unprotected triangles on the boundary.
// This is one way by which concavities are created.
if (!InfectHull())
{
// THIS IS A WORKAROUND FOR
// http://triangle.codeplex.com/workitem/9390
// Problem seems to be Otri being a value type. Assigning and getting
// dummytri.neighbors[0] (the triangulation algorithms use this to
// store a pointer to a boundary triangle) always produces an otri copy,
// so changes made to the orientation aren't persisted. The problem occurs
// when InsertSegment -> ConstrainedEdge -> Flip is called and InsertSegment
// has Mesh.dummytri.neighbors[0] as searchtri1.
Mesh.dummytri.neighbors[0].LprevSelf();
if (!InfectHull())
{
Mesh.dummytri.neighbors[0].LprevSelf();
if (!InfectHull())
{
throw new Exception("Inconsistent topology.");
}
}
}
InfectHull();
}
if (!Behavior.NoHoles)
+1
View File
@@ -386,6 +386,7 @@ namespace TriangleNet.Data
public void Dissolve()
{
triangle.neighbors[orient].triangle = Mesh.dummytri;
triangle.neighbors[orient].orient = 0;
}
/// <summary>