77namespace UniversalNumerics . Geometrics {
88 public static class Triangulation {
99
10- public static IEnumerable < Triangle2D > BowyerWatsonTriangulation ( IEnumerable < Vector2 > PointCloud ) {
10+ public static IEnumerable < Triangle2D > Triangulate ( IEnumerable < Vector2 > PointCloud ) {
1111 List < Triangle2D > Triangulation = new List < Triangle2D > ( ) ;
1212
1313 Triangle2D SuperTriangle = new Triangle2D (
@@ -77,17 +77,7 @@ private static bool PointInList(Vector2 Point, List<Vector2> Points, float Toler
7777 return Points . Any ( OtherPoint => Vector2 . DistanceSquared ( OtherPoint , Point ) < SqrTol ) ;
7878 }
7979
80- [ Pure ] private static IEnumerable < Vector2 > CleanPoints ( IEnumerable < Vector2 > UncleanPoints ) {
81- List < Vector2 > CleanedPoints = new List < Vector2 > ( ) ;
82- foreach ( Vector2 Point in UncleanPoints ) {
83- if ( ! PointInList ( Point , CleanedPoints ) ) {
84- CleanedPoints . Add ( Point ) ;
85- }
86- }
87- return CleanedPoints ;
88- }
89-
90- [ Pure ] public static IEnumerable < Triangle2D > BowyerWatsonTriangulation ( IEnumerable < Edge2D > PSG ) {
80+ [ Pure ] public static IEnumerable < Triangle2D > Triangulate ( IEnumerable < Edge2D > PSG ) {
9181 List < Vector2 > PointCloud = new List < Vector2 > ( ) ;
9282 foreach ( Edge2D Edge in PSG ) {
9383 if ( ! PointInList ( Edge . A , PointCloud ) ) {
@@ -97,7 +87,7 @@ [Pure] public static IEnumerable<Triangle2D> BowyerWatsonTriangulation(IEnumerab
9787 PointCloud . Add ( Edge . B ) ;
9888 }
9989 }
100- return BowyerWatsonTriangulation ( PointCloud ) ;
90+ return Triangulate ( PointCloud ) ;
10191 }
10292
10393 [ Pure ] public static IEnumerable < Edge2D > VoronoiFromTriangulation ( IEnumerable < Triangle2D > Triangulation ) {
@@ -123,110 +113,95 @@ [Pure] private static bool IsPoorTriangle(Triangle2D Triangle, float Threshold)
123113 return ( Angle1 < Threshold || Angle2 < Threshold || Angle3 < Threshold ) ;
124114 }
125115
126- [ Pure ] private static IEnumerable < Edge2D > GetEncroachedSegments ( IEnumerable < Edge2D > Segments , IEnumerable < Vector2 > PointCloud ) {
127- List < Edge2D > EncroachedEdges = new List < Edge2D > ( ) ;
128- foreach ( Edge2D Segment in Segments ) {
129- bool Encroached = false ;
130- foreach ( Vector2 Point in PointCloud ) {
131- Encroached = Segment . EncroachedByPoint ( Point ) ;
132- if ( Encroached ) {
133- break ;
116+ [ Pure ] private static Edge2D GetIntersectingEdge ( List < Triangle2D > Triangulation ) {
117+ foreach ( Triangle2D Tri in Triangulation ) {
118+ foreach ( Triangle2D OtherTri in Triangulation ) {
119+ if ( Tri . Equals ( OtherTri ) ) continue ;
120+ foreach ( Edge2D Edge in Tri . Edges ) {
121+ foreach ( Edge2D OtherEdge in OtherTri . Edges ) {
122+ if ( Intersection . AreSegmentsIntersecting ( Edge . A , Edge . B , OtherEdge . A , OtherEdge . B ) ) {
123+ return Edge ;
124+ }
125+ }
134126 }
135127 }
136- if ( Encroached ) {
137- EncroachedEdges . Add ( Segment ) ;
138- }
139128 }
140- return EncroachedEdges ;
129+ return null ;
141130 }
142-
143- [ Pure ] public static IEnumerable < Triangle2D > ConstrainedBowyerWatsonTriangulation ( IEnumerable < Vector2 > PointCloud , IEnumerable < Edge2D > ConstraintEdges , float Threshold = 26 ) {
144- List < Vector2 > PointCloudList = CleanPoints ( PointCloud ) . ToList ( ) ;
145- List < Edge2D > ConstraintEdgeList = ConstraintEdges . ToList ( ) ;
146- List < Triangle2D > Triangulation = BowyerWatsonTriangulation ( PointCloudList ) . ToList ( ) ;
147- List < Edge2D > EncroachedSegments = new List < Edge2D > ( ) ;
148- List < Triangle2D > PoorTriangles = new List < Triangle2D > ( ) ;
149-
150- foreach ( Edge2D ConstraintEdge in ConstraintEdgeList ) {
151-
152- if ( ! PointInList ( ConstraintEdge . A , PointCloudList ) ) {
153- PointCloudList . Add ( ConstraintEdge . A ) ;
154- }
155- if ( ! PointInList ( ConstraintEdge . B , PointCloudList ) ) {
156- PointCloudList . Add ( ConstraintEdge . B ) ;
157- }
158-
159- foreach ( Vector2 Point in PointCloudList ) {
160- if ( ConstraintEdge . EncroachedByPoint ( Point ) ) {
161- EncroachedSegments . Add ( ConstraintEdge ) ;
162- break ;
131+
132+ [ Pure ] private static bool HasIntersectingEdges ( List < Edge2D > Edges ) {
133+ foreach ( Edge2D Edge in Edges ) {
134+ foreach ( Edge2D OtherEdge in Edges ) {
135+ if ( Edge . Equals ( OtherEdge ) ) continue ;
136+ if ( Intersection . AreSegmentsIntersecting ( Edge . A , Edge . B , OtherEdge . A , OtherEdge . B ) ) {
137+ return true ;
163138 }
164139 }
165140 }
141+ return false ;
142+ }
143+
144+ [ Pure ] private static Triangle2D [ ] GetEdgeSharedTriangles ( IEnumerable < Triangle2D > Triangles , Edge2D Edge ) {
145+ IEnumerable < Triangle2D > OtherTriangles = Triangles . ToList ( ) ;
166146
167- foreach ( Triangle2D Triangle in Triangulation ) {
168- if ( IsPoorTriangle ( Triangle , Threshold ) ) {
169- PoorTriangles . Add ( Triangle ) ;
147+ foreach ( Triangle2D Triangle in OtherTriangles ) {
148+ foreach ( Triangle2D OtherTriangle in OtherTriangles ) {
149+ if ( Triangle . Equals ( OtherTriangle ) ) continue ;
150+ if ( Triangle . SharedEdgeWith ( OtherTriangle ) . Equals ( Edge ) ) {
151+ return new [ ] { Triangle , OtherTriangle } ;
152+ }
170153 }
171154 }
172155
173- while ( EncroachedSegments . Count > 0 || PoorTriangles . Count > 0 ) {
174- List < Edge2D > EdgesToRemove = new List < Edge2D > ( ) ;
175- List < Triangle2D > TrianglesToRemove = new List < Triangle2D > ( ) ;
176-
177- foreach ( Edge2D EncroachedSegment in EncroachedSegments ) {
178- Vector2 Midpoint = EncroachedSegment . GetMidpoint ( ) ;
179- PointCloudList . Add ( Midpoint ) ;
180- EdgesToRemove . Add ( EncroachedSegment ) ;
181- ConstraintEdgeList . Remove ( EncroachedSegment ) ;
182- ConstraintEdgeList . Add ( new Edge2D ( Midpoint , EncroachedSegment . A ) ) ;
183- ConstraintEdgeList . Add ( new Edge2D ( Midpoint , EncroachedSegment . B ) ) ;
184- }
185-
186- foreach ( Edge2D EdgeToRemove in EdgesToRemove ) {
187- EncroachedSegments . Remove ( EdgeToRemove ) ;
188- }
189-
190- foreach ( Triangle2D Triangle in PoorTriangles ) {
191- Vector2 Midpoint = Triangle . Circumcenter ;
192- List < Edge2D > SegmentsEncroachedByMidpoint = new List < Edge2D > ( ) ;
193- foreach ( Edge2D Segment in ConstraintEdgeList ) {
194- if ( Segment . EncroachedByPoint ( Midpoint ) ) {
195- SegmentsEncroachedByMidpoint . Add ( Segment ) ;
196- }
197- }
156+ return null ;
157+ }
198158
199- if ( SegmentsEncroachedByMidpoint . Count > 0 ) {
200- EncroachedSegments . AddRange ( SegmentsEncroachedByMidpoint ) ;
201- }
202- else {
203- PointCloudList . Add ( Midpoint ) ;
204- }
205- TrianglesToRemove . Add ( Triangle ) ;
206- }
207-
208- foreach ( Triangle2D TriangleToRemove in TrianglesToRemove ) {
209- PoorTriangles . Remove ( TriangleToRemove ) ;
210- }
159+ [ Pure ] private static List < Triangle2D > ToTriangles ( List < Edge2D > Edges ) {
160+ List < Triangle2D > outputTriangles = new List < Triangle2D > ( ) ;
161+ for ( int i = 0 ; i < Edges . Count ; i += 3 ) {
162+ outputTriangles . Add ( new Triangle2D ( Edges [ i ] . A , Edges [ i + 1 ] . A , Edges [ i + 2 ] . A ) ) ;
163+ }
164+ return outputTriangles ;
165+ }
211166
212- Triangulation = BowyerWatsonTriangulation ( PointCloudList ) . ToList ( ) ;
213-
214- foreach ( Edge2D ConstraintEdge in ConstraintEdgeList ) {
215- foreach ( Vector2 Point in PointCloudList ) {
216- if ( ConstraintEdge . EncroachedByPoint ( Point ) ) {
217- EncroachedSegments . Add ( ConstraintEdge ) ;
218- break ;
219- }
220- }
221- }
222-
223- foreach ( Triangle2D Triangle in Triangulation ) {
224- if ( IsPoorTriangle ( Triangle , Threshold ) ) {
225- PoorTriangles . Add ( Triangle ) ;
226- }
227- }
167+ [ Pure ] public static IEnumerable < Triangle2D > ConstrainedTriangulation ( IEnumerable < Vector2 > PointCloud , IEnumerable < Edge2D > ConstraintEdges , float Threshold = 26 ) {
168+ List < Triangle2D > Triangulation = Triangulate ( PointCloud ) . ToList ( ) ;
169+ foreach ( Edge2D ConstraintEdge in ConstraintEdges ) {
170+ Triangulation . Add ( new Triangle2D ( ConstraintEdge ) ) ;
228171 }
229172
173+ Edge2D NextIntersectingEdge = GetIntersectingEdge ( Triangulation ) ;
174+
175+ while ( NextIntersectingEdge != null ) {
176+ foreach ( Triangle2D Triangle in GetEdgeSharedTriangles ( Triangulation , NextIntersectingEdge ) ) {
177+ Vector2 v1 = Triangle . A ;
178+ Vector2 v2 = Triangle . B ;
179+ Vector2 v3 = Triangle . C ;
180+
181+ Triangulation . Remove ( Triangle ) ;
182+
183+ Triangle2D t1 = new ( NextIntersectingEdge . A , v1 , v2 ) ;
184+ Triangle2D t2 = new ( NextIntersectingEdge . B , v1 , v2 ) ;
185+ Triangle2D t3 = new ( NextIntersectingEdge . A , v2 , v3 ) ;
186+ Triangle2D t4 = new ( NextIntersectingEdge . B , v2 , v3 ) ;
187+ Triangle2D t5 = new ( NextIntersectingEdge . A , v3 , v1 ) ;
188+ Triangle2D t6 = new ( NextIntersectingEdge . B , v3 , v1 ) ;
189+
190+ t1 . Vertices [ 2 ] = t2 . Vertices [ 2 ] = v2 ;
191+ t3 . Vertices [ 2 ] = t4 . Vertices [ 2 ] = v3 ;
192+ t5 . Vertices [ 2 ] = t6 . Vertices [ 2 ] = v1 ;
193+
194+ Triangulation . Add ( t1 ) ;
195+ Triangulation . Add ( t2 ) ;
196+ Triangulation . Add ( t3 ) ;
197+ Triangulation . Add ( t4 ) ;
198+ Triangulation . Add ( t5 ) ;
199+ Triangulation . Add ( t6 ) ;
200+ }
201+
202+ NextIntersectingEdge = GetIntersectingEdge ( Triangulation ) ;
203+ }
204+
230205 return Triangulation ;
231206 }
232207
0 commit comments