diff --git a/Triangle.NET/TestApp/FormMain.cs b/Triangle.NET/TestApp/FormMain.cs index 557f6bd..5d1d220 100644 --- a/Triangle.NET/TestApp/FormMain.cs +++ b/Triangle.NET/TestApp/FormMain.cs @@ -616,7 +616,7 @@ namespace MeshExplorer } else { - this.voronoi = new Voronoi(mesh); + this.voronoi = new SimpleVoronoi(mesh); } renderManager.Set(voronoi, false); diff --git a/Triangle.NET/Triangle/Data/Osub.cs b/Triangle.NET/Triangle/Data/Osub.cs index e66720d..ebef407 100644 --- a/Triangle.NET/Triangle/Data/Osub.cs +++ b/Triangle.NET/Triangle/Data/Osub.cs @@ -193,7 +193,7 @@ namespace TriangleNet.Data /// connected to this subsegment. public void Dissolve() { - seg.subsegs[orient].seg = Mesh.dummysub; + seg.subsegs[orient].seg = Segment.Empty; } /// @@ -244,7 +244,7 @@ namespace TriangleNet.Data /// public void TriDissolve() { - seg.triangles[orient].triangle = Mesh.dummytri; + seg.triangles[orient].triangle = Triangle.Empty; } #endregion diff --git a/Triangle.NET/Triangle/Data/Otri.cs b/Triangle.NET/Triangle/Data/Otri.cs index e4d9515..335c0c5 100644 --- a/Triangle.NET/Triangle/Data/Otri.cs +++ b/Triangle.NET/Triangle/Data/Otri.cs @@ -388,7 +388,7 @@ namespace TriangleNet.Data /// public void Dissolve() { - triangle.neighbors[orient].triangle = Mesh.dummytri; + triangle.neighbors[orient].triangle = Triangle.Empty; triangle.neighbors[orient].orient = 0; } @@ -473,7 +473,7 @@ namespace TriangleNet.Data /// public void SegDissolve() { - triangle.subsegs[orient].seg = Mesh.dummysub; + triangle.subsegs[orient].seg = Segment.Empty; } #endregion diff --git a/Triangle.NET/Triangle/Data/Segment.cs b/Triangle.NET/Triangle/Data/Segment.cs index 80b3e77..85f8155 100644 --- a/Triangle.NET/Triangle/Data/Segment.cs +++ b/Triangle.NET/Triangle/Data/Segment.cs @@ -15,6 +15,31 @@ namespace TriangleNet.Data /// public class Segment : ISegment { + #region Static initialization of "omnipresent" subsegment + + // Set up 'dummysub', the omnipresent subsegment pointed to by any + // triangle side or subsegment end that isn't attached to a real + // subsegment. + + internal static Segment Empty; + + static Segment() + { + Empty = new Segment(); + Empty.hash = -1; + + // Initialize the two adjoining subsegments to be the omnipresent + // subsegment. These will eventually be changed by various bonding + // operations, but their values don't really matter, as long as they + // can legally be dereferenced. + Empty.subsegs[0].seg = Empty; + Empty.subsegs[1].seg = Empty; + + Triangle.Initialize(); + } + + #endregion + // Hash for dictionary. Will be set by mesh instance. internal int hash; @@ -28,16 +53,16 @@ namespace TriangleNet.Data // Initialize the two adjoining subsegments to be the omnipresent // subsegment. subsegs = new Osub[2]; - subsegs[0].seg = Mesh.dummysub; - subsegs[1].seg = Mesh.dummysub; + subsegs[0].seg = Empty; + subsegs[1].seg = Empty; // Four NULL vertices. vertices = new Vertex[4]; // Initialize the two adjoining triangles to be "outer space." triangles = new Otri[2]; - triangles[0].triangle = Mesh.dummytri; - triangles[1].triangle = Mesh.dummytri; + triangles[0].triangle = Triangle.Empty; + triangles[1].triangle = Triangle.Empty; // Set the boundary marker to zero. boundary = 0; @@ -84,7 +109,7 @@ namespace TriangleNet.Data /// public ITriangle GetTriangle(int index) { - return triangles[index].triangle == Mesh.dummytri ? null : triangles[index].triangle; + return triangles[index].triangle.id == Triangle.EmptyID ? null : triangles[index].triangle; } public override int GetHashCode() diff --git a/Triangle.NET/Triangle/Data/Triangle.cs b/Triangle.NET/Triangle/Data/Triangle.cs index 272a6e5..ca676a6 100644 --- a/Triangle.NET/Triangle/Data/Triangle.cs +++ b/Triangle.NET/Triangle/Data/Triangle.cs @@ -15,6 +15,57 @@ namespace TriangleNet.Data /// public class Triangle : ITriangle { + #region Static initialization of "Outer Space" triangle + + // The triangle that fills "outer space," called 'dummytri', is pointed to + // by every triangle and subsegment on a boundary (be it outer or inner) of + // the triangulation. Also, 'dummytri' points to one of the triangles on + // the convex hull (until the holes and concavities are carved), making it + // possible to find a starting triangle for point location. + + // 'dummytri' and 'dummysub' are generally required to fulfill only a few + // invariants: their vertices must remain NULL and 'dummytri' must always + // be bonded (at offset zero) to some triangle on the convex hull of the + // mesh, via a boundary edge. Otherwise, the connections of 'dummytri' and + // 'dummysub' may change willy-nilly. This makes it possible to avoid + // writing a good deal of special-case code (in the edge flip, for example) + // for dealing with the boundary of the mesh, places where no subsegment is + // present, and so forth. Other entities are frequently bonded to + // 'dummytri' and 'dummysub' as if they were real mesh entities, with no + // harm done. + + internal const int EmptyID = -1; + + internal static Triangle Empty; + + /// + /// Initializes the dummytri (Triangle.Empty). The method is called by the static Segment + /// constructor (which ensures that dummysub (Segment.Empty) will not be null). + /// + internal static void Initialize() + { + // Set up 'dummytri', the 'triangle' that occupies "outer space." + Empty = new Triangle(); + Empty.hash = EmptyID; + Empty.id = EmptyID; + + // Initialize the three adjoining triangles to be "outer space." These + // will eventually be changed by various bonding operations, but their + // values don't really matter, as long as they can legally be + // dereferenced. + Empty.neighbors[0].triangle = Empty; + Empty.neighbors[1].triangle = Empty; + Empty.neighbors[2].triangle = Empty; + + // Initialize the three adjoining subsegments of 'dummytri' to be + // the omnipresent subsegment. + Empty.subsegs[0].seg = Segment.Empty; + Empty.subsegs[1].seg = Segment.Empty; + Empty.subsegs[2].seg = Segment.Empty; + } + + #endregion + // Hash for dictionary. Will be set by mesh instance. internal int hash; @@ -32,9 +83,9 @@ namespace TriangleNet.Data { // Initialize the three adjoining triangles to be "outer space". neighbors = new Otri[3]; - neighbors[0].triangle = Mesh.dummytri; - neighbors[1].triangle = Mesh.dummytri; - neighbors[2].triangle = Mesh.dummytri; + neighbors[0].triangle = Empty; + neighbors[1].triangle = Empty; + neighbors[2].triangle = Empty; // Three NULL vertices. vertices = new Vertex[3]; @@ -44,9 +95,9 @@ namespace TriangleNet.Data // Initialize the three adjoining subsegments to be the // omnipresent subsegment. subsegs = new Osub[3]; - subsegs[0].seg = Mesh.dummysub; - subsegs[1].seg = Mesh.dummysub; - subsegs[2].seg = Mesh.dummysub; + subsegs[0].seg = Segment.Empty; + subsegs[1].seg = Segment.Empty; + subsegs[2].seg = Segment.Empty; } // TODO: @@ -134,7 +185,7 @@ namespace TriangleNet.Data /// The neigbbor opposite of vertex with given index. public ITriangle GetNeighbor(int index) { - return neighbors[index].triangle == Mesh.dummytri ? null : neighbors[index].triangle; + return neighbors[index].triangle.id == EmptyID ? null : neighbors[index].triangle; } /// @@ -144,7 +195,7 @@ namespace TriangleNet.Data /// The segment opposite of vertex with given index. public ISegment GetSegment(int index) { - return subsegs[index].seg == Mesh.dummysub ? null : subsegs[index].seg; + return subsegs[index].seg == Segment.Empty ? null : subsegs[index].seg; } /// diff --git a/Triangle.NET/Triangle/Geometry/Point.cs b/Triangle.NET/Triangle/Geometry/Point.cs index 21a2332..7f70192 100644 --- a/Triangle.NET/Triangle/Geometry/Point.cs +++ b/Triangle.NET/Triangle/Geometry/Point.cs @@ -20,7 +20,6 @@ namespace TriangleNet.Geometry internal double x; internal double y; internal int mark; - internal double[] attributes; public Point() : this(0, 0, 0) @@ -73,14 +72,6 @@ namespace TriangleNet.Geometry get { return this.mark; } } - /// - /// Gets the vertex attributes (may be null). - /// - public double[] Attributes - { - get { return this.attributes; } - } - #endregion #region Operator overloading / overriding Equals @@ -154,7 +145,11 @@ namespace TriangleNet.Geometry public override int GetHashCode() { - return x.GetHashCode() ^ y.GetHashCode(); + int hash = 19; + hash = hash * 31 + x.GetHashCode(); + hash = hash * 31 + y.GetHashCode(); + + return hash; } public override string ToString() diff --git a/Triangle.NET/Triangle/Geometry/Vertex.cs b/Triangle.NET/Triangle/Geometry/Vertex.cs index d5b46a4..ca5dc8d 100644 --- a/Triangle.NET/Triangle/Geometry/Vertex.cs +++ b/Triangle.NET/Triangle/Geometry/Vertex.cs @@ -18,6 +18,8 @@ namespace TriangleNet.Geometry // Hash for dictionary. Will be set by mesh instance. internal int hash; + internal double[] attributes; + internal VertexType type; internal Otri tri; @@ -70,6 +72,14 @@ namespace TriangleNet.Geometry #region Public properties + /// + /// Gets the vertex attributes (may be null). + /// + public double[] Attributes + { + get { return this.attributes; } + } + /// /// Gets the vertex type. /// diff --git a/Triangle.NET/Triangle/IO/TriangleWriter.cs b/Triangle.NET/Triangle/IO/TriangleWriter.cs index b3c9ab8..c5c8280 100644 --- a/Triangle.NET/Triangle/IO/TriangleWriter.cs +++ b/Triangle.NET/Triangle/IO/TriangleWriter.cs @@ -365,7 +365,7 @@ namespace TriangleNet.IO for (tri.orient = 0; tri.orient < 3; tri.orient++) { tri.Sym(ref trisym); - if ((tri.triangle.id < trisym.triangle.id) || (trisym.triangle == Mesh.dummytri)) + if ((tri.triangle.id < trisym.triangle.id) || (trisym.triangle.id == Triangle.EmptyID)) { p1 = tri.Org(); p2 = tri.Dest(); @@ -378,7 +378,7 @@ namespace TriangleNet.IO { tri.SegPivot(ref checkmark); - if (checkmark.seg == Mesh.dummysub) + if (checkmark.seg == Segment.Empty) { writer.WriteLine("{0} {1} {2} {3}", index, p1.id, p2.id, 0); } @@ -391,7 +391,7 @@ namespace TriangleNet.IO else { writer.WriteLine("{0} {1} {2} {3}", index, p1.id, p2.id, - trisym.triangle == Mesh.dummytri ? "1" : "0"); + trisym.triangle.id == Triangle.EmptyID ? "1" : "0"); } } else @@ -425,8 +425,6 @@ namespace TriangleNet.IO // Number of triangles, three neighbors per triangle. writer.WriteLine("{0} 3", mesh.triangles.Count); - Mesh.dummytri.id = -1; - foreach (var item in mesh.triangles.Values) { tri.triangle = item; @@ -522,12 +520,12 @@ namespace TriangleNet.IO for (tri.orient = 0; tri.orient < 3; tri.orient++) { tri.Sym(ref trisym); - if ((tri.triangle.id < trisym.triangle.id) || (trisym.triangle == Mesh.dummytri)) + if ((tri.triangle.id < trisym.triangle.id) || (trisym.triangle.id == Triangle.EmptyID)) { // Find the number of this triangle (and Voronoi vertex). p1 = tri.triangle.id; - if (trisym.triangle == Mesh.dummytri) + if (trisym.triangle.id == Triangle.EmptyID) { torg = tri.Org(); tdest = tri.Dest(); diff --git a/Triangle.NET/Triangle/Mesh.cs b/Triangle.NET/Triangle/Mesh.cs index 6b6c689..e1c31a7 100644 --- a/Triangle.NET/Triangle/Mesh.cs +++ b/Triangle.NET/Triangle/Mesh.cs @@ -63,13 +63,6 @@ namespace TriangleNet // Triangular bounding box vertices. internal Vertex infvertex1, infvertex2, infvertex3; - // The 'triangle' that occupies all of 'outer space'. - internal static Triangle dummytri; - - // The omnipresent subsegment. Referenced by any triangle or subsegment - // that isn't really connected to a subsegment at that location. - internal static Segment dummysub; - internal TriangleLocator locator; // Controls the behavior of the mesh instance. @@ -185,12 +178,6 @@ namespace TriangleNet locator = new TriangleLocator(this); RobustPredicates.ExactInit(); - - if (dummytri == null) - { - // Initialize static dummy triangle and subseg. - DummyInit(); - } } public void Refine(QualityOptions quality) @@ -528,69 +515,6 @@ namespace TriangleNet Statistic.CircumcenterCount = 0; } - /// - /// Initialize the triangle that fills "outer space" and the omnipresent subsegment. - /// - /// - /// The triangle that fills "outer space," called 'dummytri', is pointed to - /// by every triangle and subsegment on a boundary (be it outer or inner) of - /// the triangulation. Also, 'dummytri' points to one of the triangles on - /// the convex hull (until the holes and concavities are carved), making it - /// possible to find a starting triangle for point location. - // - /// The omnipresent subsegment, 'dummysub', is pointed to by every triangle - /// or subsegment that doesn't have a full complement of real subsegments - /// to point to. - // - /// 'dummytri' and 'dummysub' are generally required to fulfill only a few - /// invariants: their vertices must remain NULL and 'dummytri' must always - /// be bonded (at offset zero) to some triangle on the convex hull of the - /// mesh, via a boundary edge. Otherwise, the connections of 'dummytri' and - /// 'dummysub' may change willy-nilly. This makes it possible to avoid - /// writing a good deal of special-case code (in the edge flip, for example) - /// for dealing with the boundary of the mesh, places where no subsegment is - /// present, and so forth. Other entities are frequently bonded to - /// 'dummytri' and 'dummysub' as if they were real mesh entities, with no - /// harm done. - /// - private void DummyInit() - { - // Set up 'dummytri', the 'triangle' that occupies "outer space." - dummytri = new Triangle(); - dummytri.hash = -1; - dummytri.id = -1; - - // Initialize the three adjoining triangles to be "outer space." These - // will eventually be changed by various bonding operations, but their - // values don't really matter, as long as they can legally be - // dereferenced. - dummytri.neighbors[0].triangle = dummytri; - dummytri.neighbors[1].triangle = dummytri; - dummytri.neighbors[2].triangle = dummytri; - - if (behavior.useSegments) - { - // Set up 'dummysub', the omnipresent subsegment pointed to by any - // triangle side or subsegment end that isn't attached to a real - // subsegment. - dummysub = new Segment(); - dummysub.hash = -1; - - // Initialize the two adjoining subsegments to be the omnipresent - // subsegment. These will eventually be changed by various bonding - // operations, but their values don't really matter, as long as they - // can legally be dereferenced. - dummysub.subsegs[0].seg = dummysub; - dummysub.subsegs[1].seg = dummysub; - - // Initialize the three adjoining subsegments of 'dummytri' to be - // the omnipresent subsegment. - dummytri.subsegs[0].seg = dummysub; - dummytri.subsegs[1].seg = dummysub; - dummytri.subsegs[2].seg = dummysub; - } - } - /// /// Read the vertices from memory. /// @@ -775,10 +699,10 @@ namespace TriangleNet { // Find the location of the vertex to be inserted. Check if a good // starting triangle has already been provided by the caller. - if (searchtri.triangle == dummytri) + if (searchtri.triangle.id == Triangle.EmptyID) { // Find a boundary triangle. - horiz.triangle = dummytri; + horiz.triangle = Triangle.Empty; horiz.orient = 0; horiz.SymSelf(); // Search for a triangle containing 'newvertex'. @@ -814,7 +738,7 @@ namespace TriangleNet { // Check whether the vertex falls on a subsegment. horiz.SegPivot(ref brokensubseg); - if (brokensubseg.seg != dummysub) + if (brokensubseg.seg != Segment.Empty) { // The vertex falls on a subsegment, and hence will not be inserted. if (segmentflaws) @@ -825,7 +749,7 @@ namespace TriangleNet // This subsegment may be split only if it is an // internal boundary. horiz.Sym(ref testtri); - enq = testtri.triangle != dummytri; + enq = testtri.triangle.id != Triangle.EmptyID; } if (enq) { @@ -852,7 +776,7 @@ namespace TriangleNet botright.Sym(ref botrcasing); horiz.Sym(ref topright); // Is there a second triangle? (Or does this edge lie on a boundary?) - mirrorflag = topright.triangle != dummytri; + mirrorflag = topright.triangle.id != Triangle.EmptyID; if (mirrorflag) { topright.LnextSelf(); @@ -908,7 +832,7 @@ namespace TriangleNet { botright.SegPivot(ref botrsubseg); - if (botrsubseg.seg != dummysub) + if (botrsubseg.seg != Segment.Empty) { botright.SegDissolve(); newbotright.SegBond(ref botrsubseg); @@ -917,7 +841,7 @@ namespace TriangleNet if (mirrorflag) { topright.SegPivot(ref toprsubseg); - if (toprsubseg.seg != dummysub) + if (toprsubseg.seg != Segment.Empty) { topright.SegDissolve(); newtopright.SegBond(ref toprsubseg); @@ -1015,13 +939,13 @@ namespace TriangleNet if (checksegments) { botleft.SegPivot(ref botlsubseg); - if (botlsubseg.seg != dummysub) + if (botlsubseg.seg != Segment.Empty) { botleft.SegDissolve(); newbotleft.SegBond(ref botlsubseg); } botright.SegPivot(ref botrsubseg); - if (botrsubseg.seg != dummysub) + if (botrsubseg.seg != Segment.Empty) { botright.SegDissolve(); newbotright.SegBond(ref botrsubseg); @@ -1065,7 +989,7 @@ namespace TriangleNet { // Check for a subsegment, which cannot be flipped. horiz.SegPivot(ref checksubseg); - if (checksubseg.seg != dummysub) + if (checksubseg.seg != Segment.Empty) { // The edge is a subsegment and cannot be flipped. doflip = false; @@ -1085,7 +1009,7 @@ namespace TriangleNet { // Check if the edge is a boundary edge. horiz.Sym(ref top); - if (top.triangle == dummytri) + if (top.triangle.id == Triangle.EmptyID) { // The edge is a boundary edge and cannot be flipped. doflip = false; @@ -1156,7 +1080,7 @@ namespace TriangleNet botleft.SegPivot(ref botlsubseg); botright.SegPivot(ref botrsubseg); topright.SegPivot(ref toprsubseg); - if (toplsubseg.seg == dummysub) + if (toplsubseg.seg == Segment.Empty) { topright.SegDissolve(); } @@ -1164,7 +1088,7 @@ namespace TriangleNet { topright.SegBond(ref toplsubseg); } - if (botlsubseg.seg == dummysub) + if (botlsubseg.seg == Segment.Empty) { topleft.SegDissolve(); } @@ -1172,7 +1096,7 @@ namespace TriangleNet { topleft.SegBond(ref botlsubseg); } - if (botrsubseg.seg == dummysub) + if (botrsubseg.seg == Segment.Empty) { botleft.SegDissolve(); } @@ -1180,7 +1104,7 @@ namespace TriangleNet { botleft.SegBond(ref botrsubseg); } - if (toprsubseg.seg == dummysub) + if (toprsubseg.seg == Segment.Empty) { botright.SegDissolve(); } @@ -1248,7 +1172,7 @@ namespace TriangleNet // Check for finishing a complete revolution about the new vertex, or // falling outside of the triangulation. The latter will happen when // a vertex is inserted at a boundary. - if ((leftvertex == first) || (testtri.triangle == dummytri)) + if ((leftvertex == first) || (testtri.triangle.id == Triangle.EmptyID)) { // We're done. Return a triangle whose origin is the new vertex. horiz.Lnext(ref searchtri); @@ -1294,7 +1218,7 @@ namespace TriangleNet } // Check if there's already a subsegment here. tri.SegPivot(ref newsubseg); - if (newsubseg.seg == dummysub) + if (newsubseg.seg == Segment.Empty) { // Make new subsegment and initialize its vertices. MakeSegment(ref newsubseg); @@ -1379,7 +1303,7 @@ namespace TriangleNet // SELF CHECK - //if (top.triangle == dummytri) + //if (top.triangle.id == Triangle.EmptyID) //{ // logger.Error("Attempt to flip on boundary.", "Mesh.Flip()"); // flipedge.LnextSelf(); @@ -1389,7 +1313,7 @@ namespace TriangleNet //if (checksegments) //{ // flipedge.SegPivot(ref toplsubseg); - // if (toplsubseg.ss != dummysub) + // if (toplsubseg.ss != Segment.Empty) // { // logger.Error("Attempt to flip a segment.", "Mesh.Flip()"); // flipedge.LnextSelf(); @@ -1422,7 +1346,7 @@ namespace TriangleNet botright.SegPivot(ref botrsubseg); topright.SegPivot(ref toprsubseg); - if (toplsubseg.seg == Mesh.dummysub) + if (toplsubseg.seg == Segment.Empty) { topright.SegDissolve(); } @@ -1431,7 +1355,7 @@ namespace TriangleNet topright.SegBond(ref toplsubseg); } - if (botlsubseg.seg == Mesh.dummysub) + if (botlsubseg.seg == Segment.Empty) { topleft.SegDissolve(); } @@ -1440,7 +1364,7 @@ namespace TriangleNet topleft.SegBond(ref botlsubseg); } - if (botrsubseg.seg == Mesh.dummysub) + if (botrsubseg.seg == Segment.Empty) { botleft.SegDissolve(); } @@ -1449,7 +1373,7 @@ namespace TriangleNet botleft.SegBond(ref botrsubseg); } - if (toprsubseg.seg == Mesh.dummysub) + if (toprsubseg.seg == Segment.Empty) { botright.SegDissolve(); } @@ -1524,7 +1448,7 @@ namespace TriangleNet botleft.SegPivot(ref botlsubseg); botright.SegPivot(ref botrsubseg); topright.SegPivot(ref toprsubseg); - if (toplsubseg.seg == Mesh.dummysub) + if (toplsubseg.seg == Segment.Empty) { botleft.SegDissolve(); } @@ -1532,7 +1456,7 @@ namespace TriangleNet { botleft.SegBond(ref toplsubseg); } - if (botlsubseg.seg == Mesh.dummysub) + if (botlsubseg.seg == Segment.Empty) { botright.SegDissolve(); } @@ -1540,7 +1464,7 @@ namespace TriangleNet { botright.SegBond(ref botlsubseg); } - if (botrsubseg.seg == Mesh.dummysub) + if (botrsubseg.seg == Segment.Empty) { topright.SegDissolve(); } @@ -1548,7 +1472,7 @@ namespace TriangleNet { topright.SegBond(ref botrsubseg); } - if (toprsubseg.seg == Mesh.dummysub) + if (toprsubseg.seg == Segment.Empty) { topleft.SegDissolve(); } @@ -1750,12 +1674,12 @@ namespace TriangleNet deltri.Bond(ref leftcasing); deltriright.Bond(ref rightcasing); lefttri.SegPivot(ref leftsubseg); - if (leftsubseg.seg != Mesh.dummysub) + if (leftsubseg.seg != Segment.Empty) { deltri.SegBond(ref leftsubseg); } righttri.SegPivot(ref rightsubseg); - if (rightsubseg.seg != Mesh.dummysub) + if (rightsubseg.seg != Segment.Empty) { deltriright.SegBond(ref rightsubseg); } @@ -1848,7 +1772,7 @@ namespace TriangleNet TriangleDealloc(botright.triangle); fliptri.Sym(ref gluetri); - if (gluetri.triangle != Mesh.dummytri) + if (gluetri.triangle.id != Triangle.EmptyID) { gluetri.LnextSelf(); gluetri.Dnext(ref topright); diff --git a/Triangle.NET/Triangle/MeshValidator.cs b/Triangle.NET/Triangle/MeshValidator.cs index e1a7903..9bb56f3 100644 --- a/Triangle.NET/Triangle/MeshValidator.cs +++ b/Triangle.NET/Triangle/MeshValidator.cs @@ -60,7 +60,7 @@ namespace TriangleNet // Find the neighboring triangle on this edge. tri.Sym(ref oppotri); - if (oppotri.triangle != Mesh.dummytri) + if (oppotri.triangle.id != Triangle.EmptyID) { // Check that the triangle's neighbor knows it's a neighbor. oppotri.Sym(ref oppooppotri); @@ -170,7 +170,7 @@ namespace TriangleNet // adjoining triangle whose pointer is larger (to ensure that // each pair isn't tested twice). shouldbedelaunay = (loop.triangle.id < oppotri.triangle.id) && - !Otri.IsDead(oppotri.triangle) && (oppotri.triangle != Mesh.dummytri) && + !Otri.IsDead(oppotri.triangle) && (oppotri.triangle.id != Triangle.EmptyID) && (org != inf1) && (org != inf2) && (org != inf3) && (dest != inf1) && (dest != inf2) && (dest != inf3) && (apex != inf1) && (apex != inf2) && (apex != inf3) && @@ -182,7 +182,7 @@ namespace TriangleNet // constrained, so no local Delaunay test should be done. loop.SegPivot(ref opposubseg); - if (opposubseg.seg != Mesh.dummysub) + if (opposubseg.seg != Segment.Empty) { shouldbedelaunay = false; } diff --git a/Triangle.NET/Triangle/Meshing/Algorithm/Dwyer.cs b/Triangle.NET/Triangle/Meshing/Algorithm/Dwyer.cs index 424e6ce..d9091dc 100644 --- a/Triangle.NET/Triangle/Meshing/Algorithm/Dwyer.cs +++ b/Triangle.NET/Triangle/Meshing/Algorithm/Dwyer.cs @@ -860,7 +860,7 @@ namespace TriangleNet.Meshing.Algorithm // Find an edge on the convex hull to start point location from. startghost.Lprev(ref searchedge); searchedge.SymSelf(); - Mesh.dummytri.neighbors[0] = searchedge; + Triangle.Empty.neighbors[0] = searchedge; // Remove the bounding box and count the convex hull edges. startghost.Copy(ref dissolveedge); hullsize = 0; @@ -876,7 +876,7 @@ namespace TriangleNet.Meshing.Algorithm if (noPoly) { // Watch out for the case where all the input vertices are collinear. - if (dissolveedge.triangle != Mesh.dummytri) + if (dissolveedge.triangle.id != Triangle.EmptyID) { markorg = dissolveedge.Org(); if (markorg.mark == 0) diff --git a/Triangle.NET/Triangle/Meshing/Algorithm/Incremental.cs b/Triangle.NET/Triangle/Meshing/Algorithm/Incremental.cs index 0d4c716..0a3c5e1 100644 --- a/Triangle.NET/Triangle/Meshing/Algorithm/Incremental.cs +++ b/Triangle.NET/Triangle/Meshing/Algorithm/Incremental.cs @@ -35,7 +35,7 @@ namespace TriangleNet.Meshing.Algorithm foreach (var v in mesh.vertices.Values) { - starttri.triangle = Mesh.dummytri; + starttri.triangle = Triangle.Empty; Osub tmp = default(Osub); if (mesh.InsertVertex(v, ref starttri, ref tmp, false, false) == InsertVertexResult.Duplicate) { @@ -90,7 +90,7 @@ namespace TriangleNet.Meshing.Algorithm inftri.SetApex(mesh.infvertex3); // Link dummytri to the bounding box so we can always find an // edge to begin searching (point location) from. - Mesh.dummytri.neighbors[0] = inftri; + Triangle.Empty.neighbors[0] = inftri; } /// @@ -115,7 +115,7 @@ namespace TriangleNet.Meshing.Algorithm bool noPoly = !mesh.behavior.Poly; // Find a boundary triangle. - nextedge.triangle = Mesh.dummytri; + nextedge.triangle = Triangle.Empty; nextedge.orient = 0; nextedge.SymSelf(); // Mark a place to stop. @@ -130,7 +130,7 @@ namespace TriangleNet.Meshing.Algorithm // adjacent to the first one. nextedge.Lnext(ref checkedge); checkedge.SymSelf(); - if (checkedge.triangle == Mesh.dummytri) + if (checkedge.triangle.id == Triangle.EmptyID) { // Go on to the next triangle. There are only three boundary // triangles, and this next triangle cannot be the third one, @@ -140,7 +140,7 @@ namespace TriangleNet.Meshing.Algorithm } // Find a new boundary edge to search from, as the current search // edge lies on a bounding box triangle and will be deleted. - Mesh.dummytri.neighbors[0] = searchedge; + Triangle.Empty.neighbors[0] = searchedge; hullsize = -2; while (!nextedge.Equal(finaledge)) { @@ -155,7 +155,7 @@ namespace TriangleNet.Meshing.Algorithm // vertices are collinear, and thus all the triangles are part of // the bounding box. Otherwise, the setvertexmark() call below // will cause a bad pointer reference. - if (dissolveedge.triangle != Mesh.dummytri) + if (dissolveedge.triangle.id != Triangle.EmptyID) { markorg = dissolveedge.Org(); if (markorg.mark == 0) @@ -171,7 +171,7 @@ namespace TriangleNet.Meshing.Algorithm // Get rid of the bounding box triangle. mesh.TriangleDealloc(deadtriangle.triangle); // Do we need to turn the corner? - if (nextedge.triangle == Mesh.dummytri) + if (nextedge.triangle.id == Triangle.EmptyID) { // Turn the corner. dissolveedge.Copy(ref nextedge); diff --git a/Triangle.NET/Triangle/Meshing/Algorithm/SweepLine.cs b/Triangle.NET/Triangle/Meshing/Algorithm/SweepLine.cs index 59529bb..00fd07d 100644 --- a/Triangle.NET/Triangle/Meshing/Algorithm/SweepLine.cs +++ b/Triangle.NET/Triangle/Meshing/Algorithm/SweepLine.cs @@ -701,7 +701,7 @@ namespace TriangleNet.Meshing.Algorithm // Find an edge on the convex hull to start point location from. startghost.Lprev(ref searchedge); searchedge.SymSelf(); - Mesh.dummytri.neighbors[0] = searchedge; + Triangle.Empty.neighbors[0] = searchedge; // Remove the bounding box and count the convex hull edges. startghost.Copy(ref dissolveedge); hullsize = 0; @@ -717,7 +717,7 @@ namespace TriangleNet.Meshing.Algorithm if (noPoly) { // Watch out for the case where all the input vertices are collinear. - if (dissolveedge.triangle != Mesh.dummytri) + if (dissolveedge.triangle.id != Triangle.EmptyID) { markorg = dissolveedge.Org(); if (markorg.mark == 0) diff --git a/Triangle.NET/Triangle/Meshing/ConstraintMesher.cs b/Triangle.NET/Triangle/Meshing/ConstraintMesher.cs index 643993f..4a738da 100644 --- a/Triangle.NET/Triangle/Meshing/ConstraintMesher.cs +++ b/Triangle.NET/Triangle/Meshing/ConstraintMesher.cs @@ -64,7 +64,7 @@ namespace TriangleNet.Meshing if (mesh.bounds.Contains(hole)) { // Start searching from some triangle on the outer boundary. - searchtri.triangle = Mesh.dummytri; + searchtri.triangle = Triangle.Empty; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the hole is to the left of this boundary edge; @@ -101,12 +101,12 @@ namespace TriangleNet.Meshing // Find the starting triangle for each region. foreach (var region in mesh.regions) { - regionTris[i] = Mesh.dummytri; + regionTris[i] = Triangle.Empty; // 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.triangle = Triangle.Empty; searchtri.orient = 0; searchtri.SymSelf(); // Ensure that the region point is to the left of this boundary @@ -144,7 +144,7 @@ namespace TriangleNet.Meshing for (int i = 0; i < regionTris.Length; i++) { - if (regionTris[i] != Mesh.dummytri) + if (regionTris[i].id != Triangle.EmptyID) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. @@ -261,7 +261,7 @@ namespace TriangleNet.Meshing Vertex horg, hdest; // Find a triangle handle on the hull. - hulltri.triangle = Mesh.dummytri; + hulltri.triangle = Triangle.Empty; hulltri.orient = 0; hulltri.SymSelf(); // Remember where we started so we know when to stop. @@ -274,7 +274,7 @@ namespace TriangleNet.Meshing { // Is the triangle protected by a subsegment? hulltri.SegPivot(ref hullsubseg); - if (hullsubseg.seg == Mesh.dummysub) + if (hullsubseg.seg == Segment.Empty) { // The triangle is not protected; infect it. if (!hulltri.IsInfected()) @@ -305,7 +305,7 @@ namespace TriangleNet.Meshing // To find the next hull edge, go clockwise around the next vertex. hulltri.LnextSelf(); hulltri.Oprev(ref nexttri); - while (nexttri.triangle != Mesh.dummytri) + while (nexttri.triangle.id != Triangle.EmptyID) { nexttri.Copy(ref hulltri); hulltri.Oprev(ref nexttri); @@ -361,15 +361,15 @@ namespace TriangleNet.Meshing // 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 ((neighbor.triangle.id == Triangle.EmptyID) || neighbor.IsInfected()) { - if (neighborsubseg.seg != Mesh.dummysub) + if (neighborsubseg.seg != Segment.Empty) { // 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) + if (neighbor.triangle.id != Triangle.EmptyID) { // Make sure the subsegment doesn't get deallocated again // later when the infected neighbor is visited. @@ -381,7 +381,7 @@ namespace TriangleNet.Meshing } else { // The neighbor exists and is not infected. - if (neighborsubseg.seg == Mesh.dummysub) + if (neighborsubseg.seg == Segment.Empty) { // There is no subsegment protecting the neighbor, so // the neighbor becomes infected. @@ -436,7 +436,7 @@ namespace TriangleNet.Meshing // Walk counterclockwise about the vertex. testtri.Onext(ref neighbor); // Stop upon reaching a boundary or the starting triangle. - while ((neighbor.triangle != Mesh.dummytri) && + while ((neighbor.triangle.id != Triangle.EmptyID) && (!neighbor.Equal(testtri))) { if (neighbor.IsInfected()) @@ -453,12 +453,12 @@ namespace TriangleNet.Meshing neighbor.OnextSelf(); } // If we reached a boundary, we must walk clockwise as well. - if (neighbor.triangle == Mesh.dummytri) + if (neighbor.triangle.id == Triangle.EmptyID) { // Walk clockwise about the vertex. testtri.Oprev(ref neighbor); // Stop upon reaching a boundary. - while (neighbor.triangle != Mesh.dummytri) + while (neighbor.triangle.id != Triangle.EmptyID) { if (neighbor.IsInfected()) { @@ -488,7 +488,7 @@ namespace TriangleNet.Meshing for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) { testtri.Sym(ref neighbor); - if (neighbor.triangle == Mesh.dummytri) + if (neighbor.triangle.id == Triangle.EmptyID) { // There is no neighboring triangle on this edge, so this edge // is a boundary edge. This triangle is being deleted, so this @@ -554,7 +554,7 @@ namespace TriangleNet.Meshing // 'searchtri' faces directly away from 'searchpoint'. We could go left // or right. Ask whether it's a triangle or a boundary on the left. searchtri.Onext(ref checktri); - if (checktri.triangle == Mesh.dummytri) + if (checktri.triangle.id == Triangle.EmptyID) { leftflag = false; } @@ -567,7 +567,7 @@ namespace TriangleNet.Meshing { // Turn left until satisfied. searchtri.OnextSelf(); - if (searchtri.triangle == Mesh.dummytri) + if (searchtri.triangle.id == Triangle.EmptyID) { logger.Error("Unable to find a triangle on path.", "Mesh.FindDirection().1"); throw new Exception("Unable to find a triangle on path."); @@ -581,7 +581,7 @@ namespace TriangleNet.Meshing { // Turn right until satisfied. searchtri.OprevSelf(); - if (searchtri.triangle == Mesh.dummytri) + if (searchtri.triangle.id == Triangle.EmptyID) { logger.Error("Unable to find a triangle on path.", "Mesh.FindDirection().2"); throw new Exception("Unable to find a triangle on path."); @@ -696,12 +696,12 @@ namespace TriangleNet.Meshing { splitsubseg.SetSegOrg(newvertex); splitsubseg.NextSelf(); - } while (splitsubseg.seg != Mesh.dummysub); + } while (splitsubseg.seg != Segment.Empty); do { opposubseg.SetSegOrg(newvertex); opposubseg.NextSelf(); - } while (opposubseg.seg != Mesh.dummysub); + } while (opposubseg.seg != Segment.Empty); // Inserting the vertex may have caused edge flips. We wish to rediscover // the edge connecting endpoint1 to the new intersection vertex. @@ -789,7 +789,7 @@ namespace TriangleNet.Meshing searchtri.Lnext(ref crosstri); crosstri.SegPivot(ref crosssubseg); // Check for a crossing segment. - if (crosssubseg.seg == Mesh.dummysub) + if (crosssubseg.seg == Segment.Empty) { return false; } @@ -850,12 +850,12 @@ namespace TriangleNet.Meshing fixuptri.Lnext(ref neartri); neartri.Sym(ref fartri); // Check if the edge opposite the origin of fixuptri can be flipped. - if (fartri.triangle == Mesh.dummytri) + if (fartri.triangle.id == Triangle.EmptyID) { return; } neartri.SegPivot(ref faredge); - if (faredge.seg != Mesh.dummysub) + if (faredge.seg != Segment.Empty) { return; } @@ -1027,7 +1027,7 @@ namespace TriangleNet.Meshing } // Check for two intersecting segments. fixuptri.SegPivot(ref crosssubseg); - if (crosssubseg.seg == Mesh.dummysub) + if (crosssubseg.seg == Segment.Empty) { mesh.Flip(ref fixuptri); // May create inverted triangle at left. } @@ -1077,7 +1077,7 @@ namespace TriangleNet.Meshing if (checkvertex != endpoint1) { // Find a boundary triangle to search from. - searchtri1.triangle = Mesh.dummytri; + searchtri1.triangle = Triangle.Empty; searchtri1.orient = 0; searchtri1.SymSelf(); // Search for the segment's first endpoint by point location. @@ -1111,7 +1111,7 @@ namespace TriangleNet.Meshing if (checkvertex != endpoint2) { // Find a boundary triangle to search from. - searchtri2.triangle = Mesh.dummytri; + searchtri2.triangle = Triangle.Empty; searchtri2.orient = 0; searchtri2.SymSelf(); // Search for the segment's second endpoint by point location. @@ -1148,7 +1148,7 @@ namespace TriangleNet.Meshing Otri starttri = default(Otri); // Find a triangle handle on the hull. - hulltri.triangle = Mesh.dummytri; + hulltri.triangle = Triangle.Empty; hulltri.orient = 0; hulltri.SymSelf(); // Remember where we started so we know when to stop. @@ -1161,7 +1161,7 @@ namespace TriangleNet.Meshing // To find the next hull edge, go clockwise around the next vertex. hulltri.LnextSelf(); hulltri.Oprev(ref nexttri); - while (nexttri.triangle != Mesh.dummytri) + while (nexttri.triangle.id != Triangle.EmptyID) { nexttri.Copy(ref hulltri); hulltri.Oprev(ref nexttri); diff --git a/Triangle.NET/Triangle/Meshing/Converter.cs b/Triangle.NET/Triangle/Meshing/Converter.cs index ca2154f..946523c 100644 --- a/Triangle.NET/Triangle/Meshing/Converter.cs +++ b/Triangle.NET/Triangle/Meshing/Converter.cs @@ -100,7 +100,7 @@ namespace TriangleNet.Meshing for (i = 0; i < mesh.vertices.Count; i++) { Otri tmp = default(Otri); - tmp.triangle = Mesh.dummytri; + tmp.triangle = Triangle.Empty; vertexarray[i] = new List(3); vertexarray[i].Add(tmp); } @@ -158,7 +158,7 @@ namespace TriangleNet.Meshing checktri = nexttri; - if (checktri.triangle != Mesh.dummytri) + if (checktri.triangle.id != Triangle.EmptyID) { tdest = tri.Dest(); tapex = tri.Apex(); @@ -186,7 +186,7 @@ namespace TriangleNet.Meshing nexttri = vertexarray[aroundvertex][index]; checktri = nexttri; - } while (checktri.triangle != Mesh.dummytri); + } while (checktri.triangle.id != Triangle.EmptyID); } } @@ -270,7 +270,7 @@ namespace TriangleNet.Meshing // occurrence of a triangle on a list can (and does) represent // an edge. In this way, most edges are represented twice, and // every triangle-subsegment bond is represented once. - while (notfound && (checktri.triangle != Mesh.dummytri)) + while (notfound && (checktri.triangle.id != Triangle.EmptyID)) { checkdest = checktri.Dest(); @@ -283,7 +283,7 @@ namespace TriangleNet.Meshing checktri.SegBond(ref subseg); // Check if this is a boundary edge. checktri.Sym(ref checkneighbor); - if (checkneighbor.triangle == Mesh.dummytri) + if (checkneighbor.triangle.id == Triangle.EmptyID) { // The next line doesn't insert a subsegment (because there's // already one there), but it sets the boundary markers of @@ -315,7 +315,7 @@ namespace TriangleNet.Meshing nexttri = vertexarray[i][index]; checktri = nexttri; - while (checktri.triangle != Mesh.dummytri) + while (checktri.triangle.id != Triangle.EmptyID) { // Find the next triangle in the stack before this // information gets overwritten. @@ -324,7 +324,7 @@ namespace TriangleNet.Meshing // No adjacent subsegment. (This overwrites the stack info.) checktri.SegDissolve(); checktri.Sym(ref checkneighbor); - if (checkneighbor.triangle == Mesh.dummytri) + if (checkneighbor.triangle.id == Triangle.EmptyID) { mesh.InsertSubseg(ref checktri, 1); hullsize++; diff --git a/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs b/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs index 28d42cc..3fd4f95 100644 --- a/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs +++ b/Triangle.NET/Triangle/Meshing/Iterators/EdgeIterator.cs @@ -76,7 +76,7 @@ namespace TriangleNet.Meshing.Iterators tri.Sym(ref neighbor); - if ((tri.triangle.id < neighbor.triangle.id) || (neighbor.triangle == Mesh.dummytri)) + if ((tri.triangle.id < neighbor.triangle.id) || (neighbor.triangle.id == Triangle.EmptyID)) { p1 = tri.Org(); p2 = tri.Dest(); diff --git a/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs b/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs index 02e1be5..2dda7f3 100644 --- a/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs +++ b/Triangle.NET/Triangle/Meshing/Iterators/RegionIterator.cs @@ -66,8 +66,8 @@ namespace TriangleNet.Meshing.Iterators testtri.SegPivot(ref neighborsubseg); // Make sure the neighbor exists, is not already infected, and // isn't protected by a subsegment. - if ((neighbor.triangle != Mesh.dummytri) && !neighbor.IsInfected() - && (neighborsubseg.seg == Mesh.dummysub)) + if ((neighbor.triangle.id != Triangle.EmptyID) && !neighbor.IsInfected() + && (neighborsubseg.seg == Segment.Empty)) { // Infect the neighbor. neighbor.Infect(); @@ -104,7 +104,7 @@ namespace TriangleNet.Meshing.Iterators /// public void Process(Triangle triangle, Action func) { - if (triangle != Mesh.dummytri) + if (triangle.id != Triangle.EmptyID) { // Make sure the triangle under consideration still exists. // It may have been eaten by the virus. diff --git a/Triangle.NET/Triangle/Meshing/QualityMesher.cs b/Triangle.NET/Triangle/Meshing/QualityMesher.cs index 2eca40d..4fc0a11 100644 --- a/Triangle.NET/Triangle/Meshing/QualityMesher.cs +++ b/Triangle.NET/Triangle/Meshing/QualityMesher.cs @@ -89,7 +89,7 @@ namespace TriangleNet.Meshing // Check one neighbor of the subsegment. testsubseg.TriPivot(ref neighbortri); // Does the neighbor exist, or is this a boundary edge? - if (neighbortri.triangle != Mesh.dummytri) + if (neighbortri.triangle.id != Triangle.EmptyID) { sides++; // Find a vertex opposite this subsegment. @@ -119,7 +119,7 @@ namespace TriangleNet.Meshing testsubseg.Sym(ref testsym); testsym.TriPivot(ref neighbortri); // Does the neighbor exist, or is this a boundary edge? - if (neighbortri.triangle != Mesh.dummytri) + if (neighbortri.triangle.id != Triangle.EmptyID) { sides++; // Find the other vertex opposite this subsegment. @@ -318,7 +318,7 @@ namespace TriangleNet.Meshing // Check if both points lie in a common segment. If they do, the // skinny triangle is enqueued to be split as usual. tri1.SegPivot(ref testsub); - if (testsub.seg == Mesh.dummysub) + if (testsub.seg == Segment.Empty) { // No common segment. Find a subsegment that contains 'torg'. tri1.Copy(ref tri2); @@ -326,7 +326,7 @@ namespace TriangleNet.Meshing { tri1.OprevSelf(); tri1.SegPivot(ref testsub); - } while (testsub.seg == Mesh.dummysub); + } while (testsub.seg == Segment.Empty); // Find the endpoints of the containing segment. org1 = testsub.SegOrg(); dest1 = testsub.SegDest(); @@ -335,7 +335,7 @@ namespace TriangleNet.Meshing { tri2.DnextSelf(); tri2.SegPivot(ref testsub); - } while (testsub.seg == Mesh.dummysub); + } while (testsub.seg == Segment.Empty); // Find the endpoints of the containing segment. org2 = testsub.SegOrg(); dest2 = testsub.SegDest(); @@ -458,11 +458,11 @@ namespace TriangleNet.Meshing currentenc.TriPivot(ref enctri); enctri.Lnext(ref testtri); testtri.SegPivot(ref testsh); - acuteorg = testsh.seg != Mesh.dummysub; + acuteorg = testsh.seg != Segment.Empty; // Is the destination shared with another segment? testtri.LnextSelf(); testtri.SegPivot(ref testsh); - acutedest = testsh.seg != Mesh.dummysub; + acutedest = testsh.seg != Segment.Empty; // If we're using Chew's algorithm (rather than Ruppert's) // to define encroachment, delete free vertices from the @@ -483,17 +483,17 @@ namespace TriangleNet.Meshing // Now, check the other side of the segment, if there's a triangle there. enctri.Sym(ref testtri); - if (testtri.triangle != Mesh.dummytri) + if (testtri.triangle.id != Triangle.EmptyID) { // Is the destination shared with another segment? testtri.LnextSelf(); testtri.SegPivot(ref testsh); - acutedest2 = testsh.seg != Mesh.dummysub; + acutedest2 = testsh.seg != Segment.Empty; acutedest = acutedest || acutedest2; // Is the origin shared with another segment? testtri.LnextSelf(); testtri.SegPivot(ref testsh); - acuteorg2 = testsh.seg != Mesh.dummysub; + acuteorg2 = testsh.seg != Segment.Empty; acuteorg = acuteorg || acuteorg2; // Delete free vertices from the subsegment's diametral circle. diff --git a/Triangle.NET/Triangle/NewLocation.cs b/Triangle.NET/Triangle/NewLocation.cs index 8ee4e68..55686eb 100644 --- a/Triangle.NET/Triangle/NewLocation.cs +++ b/Triangle.NET/Triangle/NewLocation.cs @@ -13,7 +13,7 @@ namespace TriangleNet using TriangleNet.Tools; /// - /// Find new Steiner Point locations. + /// Find new Steiner point locations. /// /// /// http://www.cise.ufl.edu/~ungor/aCute/index.html @@ -51,25 +51,25 @@ namespace TriangleNet /// /// Find a new location for a Steiner point. /// - /// - /// - /// + /// + /// + /// /// /// /// /// /// - public Point FindLocation(Vertex torg, Vertex tdest, Vertex tapex, + public Point FindLocation(Vertex org, Vertex dest, Vertex apex, ref double xi, ref double eta, bool offcenter, Otri badotri) { // Based on using -U switch, call the corresponding function if (behavior.MaxAngle == 0.0) { - return FindNewLocationWithoutMaxAngle(torg, tdest, tapex, ref xi, ref eta, true, badotri); + return FindNewLocationWithoutMaxAngle(org, dest, apex, ref xi, ref eta, true, badotri); } // With max angle - return FindNewLocation(torg, tdest, tapex, ref xi, ref eta, true, badotri); + return FindNewLocation(org, dest, apex, ref xi, ref eta, true, badotri); } /// @@ -2364,7 +2364,7 @@ namespace TriangleNet badotri.Sym(ref neighbor); // check if it is the one we are looking for by checking the corners // first check if the neighbor is nonexistent, since it can be on the border - if ((neighbor.triangle != Mesh.dummytri)) + if (neighbor.triangle.id != Triangle.EmptyID) { // then check if two wanted corners are also in this triangle // take the vertices of the candidate neighbor diff --git a/Triangle.NET/Triangle/Tools/PointSorter.cs b/Triangle.NET/Triangle/Tools/PointSorter.cs new file mode 100644 index 0000000..374741e --- /dev/null +++ b/Triangle.NET/Triangle/Tools/PointSorter.cs @@ -0,0 +1,111 @@ +// ----------------------------------------------------------------------- +// +// 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.Tools +{ + using System; + using TriangleNet.Geometry; + + /// + /// Sort an array of points using quicksort. + /// + public class PointSorter + { + static Random rand = new Random(57113); + + Point[] points; + + public void Sort(Point[] array) + { + this.points = array; + + VertexSort(0, array.Length - 1); + } + + /// + /// Sort an array of vertices by x-coordinate, using the y-coordinate as a secondary key. + /// + /// + /// + /// + /// Uses quicksort. Randomized O(n log n) time. No, I did not make any of + /// the usual quicksort mistakes. + /// + void VertexSort(int left, int right) + { + int oleft = left; + int oright = right; + int arraysize = right - left + 1; + int pivot; + double pivotx, pivoty; + Point temp; + + var array = this.points; + + if (arraysize < 32) + { + // Insertion sort + for (int i = left + 1; i <= right; i++) + { + var a = array[i]; + int j = i - 1; + while (j >= left && (array[j].X > a.X || (array[j].X == a.X && array[j].Y > a.Y))) + { + array[j + 1] = array[j]; + j--; + } + array[j + 1] = a; + } + + return; + } + + // Choose a random pivot to split the array. + pivot = rand.Next(left, right); + pivotx = array[pivot].X; + pivoty = array[pivot].Y; + // Split the array. + left--; + right++; + while (left < right) + { + // Search for a vertex whose x-coordinate is too large for the left. + do + { + left++; + } + while ((left <= right) && ((array[left].X < pivotx) || + ((array[left].X == pivotx) && (array[left].Y < pivoty)))); + // Search for a vertex whose x-coordinate is too small for the right. + do + { + right--; + } + while ((left <= right) && ((array[right].X > pivotx) || + ((array[right].X == pivotx) && (array[right].Y > pivoty)))); + + if (left < right) + { + // Swap the left and right vertices. + temp = array[left]; + array[left] = array[right]; + array[right] = temp; + } + } + if (left > oleft) + { + // Recursively sort the left subset. + VertexSort(oleft, left); + } + if (oright > right + 1) + { + // Recursively sort the right subset. + VertexSort(right + 1, oright); + } + } + } +} diff --git a/Triangle.NET/Triangle/Triangle.csproj b/Triangle.NET/Triangle/Triangle.csproj index 7be2058..66f05a3 100644 --- a/Triangle.NET/Triangle/Triangle.csproj +++ b/Triangle.NET/Triangle/Triangle.csproj @@ -96,6 +96,7 @@ + @@ -104,7 +105,7 @@ - + diff --git a/Triangle.NET/Triangle/TriangleLocator.cs b/Triangle.NET/Triangle/TriangleLocator.cs index 429ffea..cafb6df 100644 --- a/Triangle.NET/Triangle/TriangleLocator.cs +++ b/Triangle.NET/Triangle/TriangleLocator.cs @@ -196,7 +196,7 @@ namespace TriangleNet { // Check for walking through a subsegment. backtracktri.SegPivot(ref checkedge); - if (checkedge.seg != Mesh.dummysub) + if (checkedge.seg != Segment.Empty) { // Go back to the last triangle. backtracktri.Copy(ref searchtri); @@ -204,7 +204,7 @@ namespace TriangleNet } } // Check for walking right out of the triangulation. - if (searchtri.triangle == Mesh.dummytri) + if (searchtri.triangle.id == Triangle.EmptyID) { // Go back to the last triangle. backtracktri.Copy(ref searchtri); diff --git a/Triangle.NET/Triangle/Voronoi/Legacy/BoundedVoronoiLegacy.cs b/Triangle.NET/Triangle/Voronoi/Legacy/BoundedVoronoiLegacy.cs index 2cdf1f9..537d6fa 100644 --- a/Triangle.NET/Triangle/Voronoi/Legacy/BoundedVoronoiLegacy.cs +++ b/Triangle.NET/Triangle/Voronoi/Legacy/BoundedVoronoiLegacy.cs @@ -176,7 +176,7 @@ namespace TriangleNet.Voronoi.Legacy e.orient = 0; e.TriPivot(ref f); - if (f.triangle != Mesh.dummytri && !f.triangle.infected) + if (f.triangle.id != Triangle.EmptyID && !f.triangle.infected) { triangles.Push(f.triangle); } @@ -184,7 +184,7 @@ namespace TriangleNet.Voronoi.Legacy e.SymSelf(); e.TriPivot(ref f); - if (f.triangle != Mesh.dummytri && !f.triangle.infected) + if (f.triangle.id != Triangle.EmptyID && !f.triangle.infected) { triangles.Push(f.triangle); } @@ -215,7 +215,7 @@ namespace TriangleNet.Voronoi.Legacy // if f0 is finite and tagged non-blind & the common edge // between f and f0 is unconstrained then - if (f0.triangle != Mesh.dummytri && !f0.triangle.infected && sub1.seg == Mesh.dummysub) + if (f0.triangle.id != Triangle.EmptyID && !f0.triangle.infected && sub1.seg == Segment.Empty) { // Push f0 into triangles. triangles.Push(f0.triangle); @@ -412,10 +412,10 @@ namespace TriangleNet.Voronoi.Legacy f_init.Oprev(ref f_prev); // Is the border to the left? - if (f_prev.triangle != Mesh.dummytri) + if (f_prev.triangle.id != Triangle.EmptyID) { // Go clockwise until we reach the border (or the initial triangle) - while (f_prev.triangle != Mesh.dummytri && !f_prev.Equal(f_init)) + while (f_prev.triangle.id != Triangle.EmptyID && !f_prev.Equal(f_init)) { f_prev.Copy(ref f); f_prev.OprevSelf(); @@ -425,7 +425,7 @@ namespace TriangleNet.Voronoi.Legacy f.Onext(ref f_next); } - if (f_prev.triangle == Mesh.dummytri) + if (f_prev.triangle.id == Triangle.EmptyID) { // For vertices on the domain boundaray, add the vertex. For // internal boundaries don't add it. @@ -451,7 +451,7 @@ namespace TriangleNet.Voronoi.Legacy // Call Lffnext the line going through the circumcenters of f and f_next cc_f = this.points[f.triangle.id]; - if (f_next.triangle == Mesh.dummytri) + if (f_next.triangle.id == Triangle.EmptyID) { if (!f.triangle.infected) { diff --git a/Triangle.NET/Triangle/Voronoi/Legacy/Voronoi.cs b/Triangle.NET/Triangle/Voronoi/Legacy/SimpleVoronoi.cs similarity index 93% rename from Triangle.NET/Triangle/Voronoi/Legacy/Voronoi.cs rename to Triangle.NET/Triangle/Voronoi/Legacy/SimpleVoronoi.cs index 155406a..db44144 100644 --- a/Triangle.NET/Triangle/Voronoi/Legacy/Voronoi.cs +++ b/Triangle.NET/Triangle/Voronoi/Legacy/SimpleVoronoi.cs @@ -15,7 +15,7 @@ namespace TriangleNet.Voronoi.Legacy /// /// The Voronoi Diagram is the dual of a pointset triangulation. /// - public class Voronoi : IVoronoi + public class SimpleVoronoi : IVoronoi { Mesh mesh; @@ -30,13 +30,13 @@ namespace TriangleNet.Voronoi.Legacy Rectangle bounds; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// /// Be sure MakeVertexMap has been called (should always be the case). /// - public Voronoi(Mesh mesh) + public SimpleVoronoi(Mesh mesh) { this.mesh = mesh; @@ -155,11 +155,11 @@ namespace TriangleNet.Voronoi.Legacy f_init.Onext(ref f_next); // Check if f_init lies on the boundary of the triangulation. - if (f_next.triangle == Mesh.dummytri) + if (f_next.triangle.id == Triangle.EmptyID) { f_init.Oprev(ref f_prev); - if (f_prev.triangle != Mesh.dummytri) + if (f_prev.triangle.id != Triangle.EmptyID) { f_init.Copy(ref f_next); // Move one triangle clockwise @@ -169,7 +169,7 @@ namespace TriangleNet.Voronoi.Legacy } // Go counterclockwise until we reach the border or the initial triangle. - while (f_next.triangle != Mesh.dummytri) + while (f_next.triangle.id != Triangle.EmptyID) { // Add circumcenter of current triangle vpoints.Add(points[f.triangle.id]); @@ -227,7 +227,7 @@ namespace TriangleNet.Voronoi.Legacy f_init.Copy(ref f); f.Oprev(ref f_prev); - while (f_prev.triangle != Mesh.dummytri) + while (f_prev.triangle.id != Triangle.EmptyID) { vpoints.Add(points[f_prev.triangle.id]); region.AddNeighbor(f_prev.triangle.id, regions[f_prev.Apex().id]);