Skip to content

Commit a8b4e64

Browse files
committed
02: TriangulationPoint's edges
1 parent b9d85e4 commit a8b4e64

File tree

5 files changed

+401
-319
lines changed

5 files changed

+401
-319
lines changed

Triangulation/Delaunay/DelaunayTriangle.cs

Lines changed: 204 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -27,189 +27,207 @@
2727
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2828
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2929
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30-
*/
31-
32-
/// Changes from the Java version
33-
/// attributification
34-
/// Future possibilities
35-
/// Flattening out the number of indirections
36-
/// Replacing arrays of 3 with fixed-length arrays?
37-
/// Replacing bool[3] with a bit array of some sort?
38-
/// Bundling everything into an AoS mess?
39-
/// Hardcode them all as ABC ?
40-
41-
using System;
42-
using System.Diagnostics;
43-
using System.Collections.Generic;
44-
45-
namespace Poly2Tri {
46-
public class DelaunayTriangle {
47-
public FixedArray3<TriangulationPoint> Points;
48-
public FixedArray3<DelaunayTriangle > Neighbors;
49-
public FixedBitArray3 EdgeIsConstrained, EdgeIsDelaunay;
50-
public bool IsInterior { get; set; }
51-
52-
public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3) {
53-
Points[0] = p1;
54-
Points[1] = p2;
55-
Points[2] = p3;
56-
}
57-
58-
public int IndexOf(TriangulationPoint p) {
59-
int i = Points.IndexOf(p);
60-
if (i==-1) throw new Exception("Calling index with a point that doesn't exist in triangle");
61-
return i;
62-
}
63-
64-
public int IndexCWFrom (TriangulationPoint p) { return (IndexOf(p)+2)%3; }
65-
public int IndexCCWFrom(TriangulationPoint p) { return (IndexOf(p)+1)%3; }
66-
67-
public bool Contains(TriangulationPoint p) { return Points.Contains(p); }
68-
69-
/// <summary>
70-
/// Update neighbor pointers
71-
/// </summary>
72-
/// <param name="p1">Point 1 of the shared edge</param>
73-
/// <param name="p2">Point 2 of the shared edge</param>
74-
/// <param name="t">This triangle's new neighbor</param>
75-
private void MarkNeighbor( TriangulationPoint p1, TriangulationPoint p2, DelaunayTriangle t ) {
76-
int i = EdgeIndex(p1,p2);
77-
if ( i==-1 ) throw new Exception( "Error marking neighbors -- t doesn't contain edge p1-p2!" );
78-
Neighbors[i] = t;
79-
}
80-
81-
/// <summary>
82-
/// Exhaustive search to update neighbor pointers
83-
/// </summary>
84-
public void MarkNeighbor( DelaunayTriangle t ) {
85-
// Points of this triangle also belonging to t
86-
bool a = t.Contains(Points[0]);
87-
bool b = t.Contains(Points[1]);
88-
bool c = t.Contains(Points[2]);
89-
90-
if (b&&c) { Neighbors[0]=t; t.MarkNeighbor(Points[1],Points[2],this); }
91-
else if (a&&c) { Neighbors[1]=t; t.MarkNeighbor(Points[0],Points[2],this); }
92-
else if (a&&b) { Neighbors[2]=t; t.MarkNeighbor(Points[0],Points[1],this); }
93-
else throw new Exception( "Failed to mark neighbor, doesn't share an edge!");
94-
}
95-
96-
/// <param name="t">Opposite triangle</param>
97-
/// <param name="p">The point in t that isn't shared between the triangles</param>
98-
public TriangulationPoint OppositePoint(DelaunayTriangle t, TriangulationPoint p) {
99-
Debug.Assert(t != this, "self-pointer error");
100-
return PointCWFrom(t.PointCWFrom(p));
101-
}
102-
103-
public DelaunayTriangle NeighborCWFrom (TriangulationPoint point) { return Neighbors[(Points.IndexOf(point)+1)%3]; }
104-
public DelaunayTriangle NeighborCCWFrom (TriangulationPoint point) { return Neighbors[(Points.IndexOf(point)+2)%3]; }
105-
public DelaunayTriangle NeighborAcrossFrom(TriangulationPoint point) { return Neighbors[ Points.IndexOf(point) ]; }
106-
107-
public TriangulationPoint PointCCWFrom(TriangulationPoint point) { return Points[(IndexOf(point)+1)%3]; }
108-
public TriangulationPoint PointCWFrom (TriangulationPoint point) { return Points[(IndexOf(point)+2)%3]; }
109-
110-
private void RotateCW() {
111-
var t = Points[2];
112-
Points[2] = Points[1];
113-
Points[1] = Points[0];
114-
Points[0] = t;
115-
}
116-
117-
/// <summary>
118-
/// Legalize triangle by rotating clockwise around oPoint
119-
/// </summary>
120-
/// <param name="oPoint">The origin point to rotate around</param>
121-
/// <param name="nPoint">???</param>
122-
public void Legalize(TriangulationPoint oPoint, TriangulationPoint nPoint) {
123-
RotateCW();
124-
Points[IndexCCWFrom(oPoint)] = nPoint;
125-
}
126-
127-
public override string ToString() { return Points[0] + "," + Points[1] + "," + Points[2]; }
128-
129-
/// <summary>
130-
/// Finalize edge marking
131-
/// </summary>
132-
public void MarkNeighborEdges() {
133-
for (int i = 0; i < 3; i++) if ( EdgeIsConstrained[i] && Neighbors[i] != null ) {
134-
Neighbors[i].MarkConstrainedEdge(Points[(i+1)%3], Points[(i+2)%3]);
135-
}
136-
}
137-
138-
public void MarkEdge(DelaunayTriangle triangle) {
139-
for (int i = 0; i < 3; i++) if ( EdgeIsConstrained[i] ) {
140-
triangle.MarkConstrainedEdge(Points[(i+1)%3], Points[(i+2)%3]);
141-
}
142-
}
143-
144-
public void MarkEdge(List<DelaunayTriangle> tList) {
145-
foreach ( DelaunayTriangle t in tList )
146-
for ( int i = 0; i < 3; i++ )
147-
if ( t.EdgeIsConstrained[i] )
148-
{
149-
MarkConstrainedEdge( t.Points[(i+1)%3], t.Points[(i+2)%3] );
150-
}
151-
}
152-
153-
public void MarkConstrainedEdge(int index) {
154-
EdgeIsConstrained[index] = true;
155-
}
156-
157-
public void MarkConstrainedEdge(DTSweepConstraint edge) {
158-
MarkConstrainedEdge(edge.P, edge.Q);
159-
}
160-
161-
/// <summary>
162-
/// Mark edge as constrained
163-
/// </summary>
164-
public void MarkConstrainedEdge(TriangulationPoint p, TriangulationPoint q) {
165-
int i = EdgeIndex(p,q);
166-
if ( i != -1 ) EdgeIsConstrained[i] = true;
167-
}
168-
169-
public double Area() {
170-
double b = Points[0].X - Points[1].X;
171-
double h = Points[2].Y - Points[1].Y;
172-
173-
return Math.Abs((b * h * 0.5f));
174-
}
175-
176-
public TriangulationPoint Centroid() {
177-
double cx = (Points[0].X + Points[1].X + Points[2].X) / 3f;
178-
double cy = (Points[0].Y + Points[1].Y + Points[2].Y) / 3f;
179-
return new TriangulationPoint(cx, cy);
180-
}
181-
182-
/// <summary>
183-
/// Get the index of the neighbor that shares this edge (or -1 if it isn't shared)
184-
/// </summary>
185-
/// <returns>index of the shared edge or -1 if edge isn't shared</returns>
186-
public int EdgeIndex(TriangulationPoint p1, TriangulationPoint p2) {
187-
int i1 = Points.IndexOf(p1);
188-
int i2 = Points.IndexOf(p2);
189-
190-
// Points of this triangle in the edge p1-p2
191-
bool a = (i1==0 || i2==0);
192-
bool b = (i1==1 || i2==1);
193-
bool c = (i1==2 || i2==2);
194-
195-
if (b&&c) return 0;
196-
if (a&&c) return 1;
197-
if (a&&b) return 2;
198-
return -1;
199-
}
200-
201-
public bool GetConstrainedEdgeCCW ( TriangulationPoint p ) { return EdgeIsConstrained[(IndexOf(p)+2)%3]; }
202-
public bool GetConstrainedEdgeCW ( TriangulationPoint p ) { return EdgeIsConstrained[(IndexOf(p)+1)%3]; }
203-
public bool GetConstrainedEdgeAcross( TriangulationPoint p ) { return EdgeIsConstrained[ IndexOf(p) ]; }
204-
public void SetConstrainedEdgeCCW ( TriangulationPoint p, bool ce ) { EdgeIsConstrained[(IndexOf(p)+2)%3] = ce; }
205-
public void SetConstrainedEdgeCW ( TriangulationPoint p, bool ce ) { EdgeIsConstrained[(IndexOf(p)+1)%3] = ce; }
206-
public void SetConstrainedEdgeAcross( TriangulationPoint p, bool ce ) { EdgeIsConstrained[ IndexOf(p) ] = ce; }
207-
208-
public bool GetDelaunayEdgeCCW ( TriangulationPoint p ) { return EdgeIsDelaunay[(IndexOf(p)+2)%3]; }
209-
public bool GetDelaunayEdgeCW ( TriangulationPoint p ) { return EdgeIsDelaunay[(IndexOf(p)+1)%3]; }
210-
public bool GetDelaunayEdgeAcross( TriangulationPoint p ) { return EdgeIsDelaunay[ IndexOf(p) ]; }
211-
public void SetDelaunayEdgeCCW ( TriangulationPoint p, bool ce ) { EdgeIsDelaunay[(IndexOf(p)+2)%3] = ce; }
212-
public void SetDelaunayEdgeCW ( TriangulationPoint p, bool ce ) { EdgeIsDelaunay[(IndexOf(p)+1)%3] = ce; }
213-
public void SetDelaunayEdgeAcross( TriangulationPoint p, bool ce ) { EdgeIsDelaunay[ IndexOf(p) ] = ce; }
214-
}
215-
}
30+
*/
31+
32+
/// Changes from the Java version
33+
/// attributification
34+
/// Future possibilities
35+
/// Flattening out the number of indirections
36+
/// Replacing arrays of 3 with fixed-length arrays?
37+
/// Replacing bool[3] with a bit array of some sort?
38+
/// Bundling everything into an AoS mess?
39+
/// Hardcode them all as ABC ?
40+
41+
using System;
42+
using System.Diagnostics;
43+
using System.Collections.Generic;
44+
45+
namespace Poly2Tri
46+
{
47+
public class DelaunayTriangle
48+
{
49+
public FixedArray3<TriangulationPoint> Points;
50+
public FixedArray3<DelaunayTriangle> Neighbors;
51+
public FixedBitArray3 EdgeIsConstrained, EdgeIsDelaunay;
52+
public bool IsInterior { get; set; }
53+
public DelaunayTriangle(TriangulationPoint p1, TriangulationPoint p2, TriangulationPoint p3)
54+
{
55+
Points[0] = p1;
56+
Points[1] = p2;
57+
Points[2] = p3;
58+
}
59+
public int IndexOf(TriangulationPoint p)
60+
{
61+
int i = Points.IndexOf(p);
62+
if (i == -1) throw new Exception("Calling index with a point that doesn't exist in triangle");
63+
return i;
64+
}
65+
66+
public int IndexCWFrom(TriangulationPoint p) { return (IndexOf(p) + 2) % 3; }
67+
public int IndexCCWFrom(TriangulationPoint p) { return (IndexOf(p) + 1) % 3; }
68+
69+
public bool Contains(TriangulationPoint p) { return Points.Contains(p); }
70+
71+
/// <summary>
72+
/// Update neighbor pointers
73+
/// </summary>
74+
/// <param name="p1">Point 1 of the shared edge</param>
75+
/// <param name="p2">Point 2 of the shared edge</param>
76+
/// <param name="t">This triangle's new neighbor</param>
77+
private void MarkNeighbor(TriangulationPoint p1, TriangulationPoint p2, DelaunayTriangle t)
78+
{
79+
int i = EdgeIndex(p1, p2);
80+
if (i == -1) throw new Exception("Error marking neighbors -- t doesn't contain edge p1-p2!");
81+
Neighbors[i] = t;
82+
}
83+
84+
/// <summary>
85+
/// Exhaustive search to update neighbor pointers
86+
/// </summary>
87+
public void MarkNeighbor(DelaunayTriangle t)
88+
{
89+
// Points of this triangle also belonging to t
90+
bool a = t.Contains(Points[0]);
91+
bool b = t.Contains(Points[1]);
92+
bool c = t.Contains(Points[2]);
93+
94+
if (b && c) { Neighbors[0] = t; t.MarkNeighbor(Points[1], Points[2], this); }
95+
else if (a && c) { Neighbors[1] = t; t.MarkNeighbor(Points[0], Points[2], this); }
96+
else if (a && b) { Neighbors[2] = t; t.MarkNeighbor(Points[0], Points[1], this); }
97+
else throw new Exception("Failed to mark neighbor, doesn't share an edge!");
98+
}
99+
100+
/// <param name="t">Opposite triangle</param>
101+
/// <param name="p">The point in t that isn't shared between the triangles</param>
102+
public TriangulationPoint OppositePoint(DelaunayTriangle t, TriangulationPoint p)
103+
{
104+
Debug.Assert(t != this, "self-pointer error");
105+
return PointCWFrom(t.PointCWFrom(p));
106+
}
107+
108+
public DelaunayTriangle NeighborCWFrom(TriangulationPoint point) { return Neighbors[(Points.IndexOf(point) + 1) % 3]; }
109+
public DelaunayTriangle NeighborCCWFrom(TriangulationPoint point) { return Neighbors[(Points.IndexOf(point) + 2) % 3]; }
110+
public DelaunayTriangle NeighborAcrossFrom(TriangulationPoint point) { return Neighbors[Points.IndexOf(point)]; }
111+
112+
public TriangulationPoint PointCCWFrom(TriangulationPoint point) { return Points[(IndexOf(point) + 1) % 3]; }
113+
public TriangulationPoint PointCWFrom(TriangulationPoint point) { return Points[(IndexOf(point) + 2) % 3]; }
114+
115+
private void RotateCW()
116+
{
117+
var t = Points[2];
118+
Points[2] = Points[1];
119+
Points[1] = Points[0];
120+
Points[0] = t;
121+
}
122+
123+
/// <summary>
124+
/// Legalize triangle by rotating clockwise around oPoint
125+
/// </summary>
126+
/// <param name="oPoint">The origin point to rotate around</param>
127+
/// <param name="nPoint">???</param>
128+
public void Legalize(TriangulationPoint oPoint, TriangulationPoint nPoint)
129+
{
130+
RotateCW();
131+
Points[IndexCCWFrom(oPoint)] = nPoint;
132+
}
133+
134+
public override string ToString() { return Points[0] + "," + Points[1] + "," + Points[2]; }
135+
136+
/// <summary>
137+
/// Finalize edge marking
138+
/// </summary>
139+
public void MarkNeighborEdges()
140+
{
141+
for (int i = 0; i < 3; i++) if (EdgeIsConstrained[i] && Neighbors[i] != null)
142+
{
143+
Neighbors[i].MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
144+
}
145+
}
146+
147+
public void MarkEdge(DelaunayTriangle triangle)
148+
{
149+
for (int i = 0; i < 3; i++) if (EdgeIsConstrained[i])
150+
{
151+
triangle.MarkConstrainedEdge(Points[(i + 1) % 3], Points[(i + 2) % 3]);
152+
}
153+
}
154+
155+
public void MarkEdge(List<DelaunayTriangle> tList)
156+
{
157+
foreach (DelaunayTriangle t in tList)
158+
for (int i = 0; i < 3; i++)
159+
if (t.EdgeIsConstrained[i])
160+
{
161+
MarkConstrainedEdge(t.Points[(i + 1) % 3], t.Points[(i + 2) % 3]);
162+
}
163+
}
164+
165+
public void MarkConstrainedEdge(int index)
166+
{
167+
EdgeIsConstrained[index] = true;
168+
}
169+
170+
public void MarkConstrainedEdge(DTSweepConstraint edge)
171+
{
172+
MarkConstrainedEdge(edge.P, edge.Q);
173+
}
174+
175+
/// <summary>
176+
/// Mark edge as constrained
177+
/// </summary>
178+
public void MarkConstrainedEdge(TriangulationPoint p, TriangulationPoint q)
179+
{
180+
int i = EdgeIndex(p, q);
181+
if (i != -1) EdgeIsConstrained[i] = true;
182+
}
183+
184+
public double Area()
185+
{
186+
double b = Points[0].X - Points[1].X;
187+
double h = Points[2].Y - Points[1].Y;
188+
189+
return Math.Abs((b * h * 0.5f));
190+
}
191+
192+
public TriangulationPoint Centroid()
193+
{
194+
double cx = (Points[0].X + Points[1].X + Points[2].X) / 3f;
195+
double cy = (Points[0].Y + Points[1].Y + Points[2].Y) / 3f;
196+
return new TriangulationPoint(cx, cy);
197+
}
198+
199+
/// <summary>
200+
/// Get the index of the neighbor that shares this edge (or -1 if it isn't shared)
201+
/// </summary>
202+
/// <returns>index of the shared edge or -1 if edge isn't shared</returns>
203+
public int EdgeIndex(TriangulationPoint p1, TriangulationPoint p2)
204+
{
205+
int i1 = Points.IndexOf(p1);
206+
int i2 = Points.IndexOf(p2);
207+
208+
// Points of this triangle in the edge p1-p2
209+
bool a = (i1 == 0 || i2 == 0);
210+
bool b = (i1 == 1 || i2 == 1);
211+
bool c = (i1 == 2 || i2 == 2);
212+
213+
if (b && c) return 0;
214+
if (a && c) return 1;
215+
if (a && b) return 2;
216+
return -1;
217+
}
218+
219+
public bool GetConstrainedEdgeCCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 2) % 3]; }
220+
public bool GetConstrainedEdgeCW(TriangulationPoint p) { return EdgeIsConstrained[(IndexOf(p) + 1) % 3]; }
221+
public bool GetConstrainedEdgeAcross(TriangulationPoint p) { return EdgeIsConstrained[IndexOf(p)]; }
222+
public void SetConstrainedEdgeCCW(TriangulationPoint p, bool ce) { EdgeIsConstrained[(IndexOf(p) + 2) % 3] = ce; }
223+
public void SetConstrainedEdgeCW(TriangulationPoint p, bool ce) { EdgeIsConstrained[(IndexOf(p) + 1) % 3] = ce; }
224+
public void SetConstrainedEdgeAcross(TriangulationPoint p, bool ce) { EdgeIsConstrained[IndexOf(p)] = ce; }
225+
226+
public bool GetDelaunayEdgeCCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 2) % 3]; }
227+
public bool GetDelaunayEdgeCW(TriangulationPoint p) { return EdgeIsDelaunay[(IndexOf(p) + 1) % 3]; }
228+
public bool GetDelaunayEdgeAcross(TriangulationPoint p) { return EdgeIsDelaunay[IndexOf(p)]; }
229+
public void SetDelaunayEdgeCCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 2) % 3] = ce; }
230+
public void SetDelaunayEdgeCW(TriangulationPoint p, bool ce) { EdgeIsDelaunay[(IndexOf(p) + 1) % 3] = ce; }
231+
public void SetDelaunayEdgeAcross(TriangulationPoint p, bool ce) { EdgeIsDelaunay[IndexOf(p)] = ce; }
232+
}
233+
}

0 commit comments

Comments
 (0)