3737
3838#include < geode/mesh/core/triangulated_surface.hpp>
3939#include < geode/mesh/helpers/aabb_surface_helpers.hpp>
40+ #include < geode/mesh/helpers/detail/mesh_intersection_detection.hpp>
4041
4142namespace
4243{
43- geode::local_index_t surface_vertex_position_to_index (
44- geode::POSITION position )
45- {
46- if ( position == geode::POSITION::vertex0 )
47- {
48- return 0 ;
49- }
50- if ( position == geode::POSITION::vertex1 )
51- {
52- return 1 ;
53- }
54- if ( position == geode::POSITION::vertex2 )
55- {
56- return 2 ;
57- }
58- return geode::NO_LID;
59- }
60-
6144 template < geode::index_t dimension >
62- class TriangleTriangleIntersectionBase
45+ class TriangleTriangleIntersection
6346 {
6447 public:
65- TriangleTriangleIntersectionBase (
66- const geode::TriangulatedSurface< dimension >& mesh )
67- : mesh_( mesh )
48+ TriangleTriangleIntersection (
49+ const geode::TriangulatedSurface< dimension >& mesh,
50+ bool stop_at_first_intersection )
51+ : mesh_( mesh ),
52+ stop_at_first_intersection_{ stop_at_first_intersection }
6853 {
6954 }
7055
@@ -74,56 +59,6 @@ namespace
7459 return std::move ( intersecting_triangles_ );
7560 }
7661
77- protected:
78- void emplace ( geode::index_t t1_id, geode::index_t t2_id )
79- {
80- intersecting_triangles_.emplace_back ( t1_id, t2_id );
81- }
82-
83- const geode::TriangulatedSurface< dimension >& mesh () const
84- {
85- return mesh_;
86- }
87-
88- geode::PolygonVertices triangles_common_points (
89- const geode::PolygonVertices& t1_vertices,
90- const geode::PolygonVertices& t2_vertices ) const
91- {
92- geode::PolygonVertices common_points;
93- for ( const auto vertex_id : t1_vertices )
94- {
95- if ( absl::c_find ( t2_vertices, vertex_id )
96- != t2_vertices.end () )
97- {
98- common_points.push_back ( vertex_id );
99- }
100- }
101- return common_points;
102- }
103-
104- bool triangles_intersect ( geode::index_t t1_id,
105- geode::index_t t2_id,
106- const geode::PolygonVertices& t1_vertices,
107- const geode::PolygonVertices& t2_vertices,
108- const geode::PolygonVertices& common_points ) const ;
109-
110- private:
111- const geode::TriangulatedSurface< dimension >& mesh_;
112- std::vector< std::pair< geode::index_t , geode::index_t > >
113- intersecting_triangles_;
114- };
115-
116- template < geode::index_t dimension >
117- class OneTriangleTriangleIntersection
118- : public TriangleTriangleIntersectionBase< dimension >
119- {
120- public:
121- OneTriangleTriangleIntersection (
122- const geode::TriangulatedSurface< dimension >& surface )
123- : TriangleTriangleIntersectionBase< dimension >( surface )
124- {
125- }
126-
12762 bool operator ()( geode::index_t t1_id, geode::index_t t2_id )
12863 {
12964 if ( t1_id == t2_id )
@@ -132,225 +67,33 @@ namespace
13267 }
13368 const auto t1_vertices = this ->mesh ().polygon_vertices ( t1_id );
13469 const auto t2_vertices = this ->mesh ().polygon_vertices ( t2_id );
135- const auto common_points =
136- this ->triangles_common_points ( t1_vertices, t2_vertices );
137- if ( common_points.size () == 3
138- || this ->triangles_intersect (
139- t1_id, t2_id, t1_vertices, t2_vertices, common_points ) )
70+ if ( geode::detail::polygons_intersection_detection<
71+ geode::SurfaceMesh< dimension > >(
72+ mesh_, t1_vertices, t2_vertices ) )
14073 {
14174 this ->emplace ( t1_id, t2_id );
142- return true ;
75+ return stop_at_first_intersection_ ;
14376 }
14477 return false ;
14578 }
146- };
147-
148- template < geode::index_t dimension >
149- class AllTriangleTriangleIntersection
150- : public TriangleTriangleIntersectionBase< dimension >
151- {
152- public:
153- AllTriangleTriangleIntersection (
154- const geode::TriangulatedSurface< dimension >& surface )
155- : TriangleTriangleIntersectionBase< dimension >( surface )
156- {
157- }
15879
159- bool operator ()( geode::index_t t1_id, geode::index_t t2_id )
160- {
161- if ( t1_id == t2_id )
162- {
163- return false ;
164- }
165- const auto t1_vertices = this ->mesh ().polygon_vertices ( t1_id );
166- const auto t2_vertices = this ->mesh ().polygon_vertices ( t2_id );
167- const auto common_points =
168- this ->triangles_common_points ( t1_vertices, t2_vertices );
169- if ( common_points.size () == 3
170- || this ->triangles_intersect (
171- t1_id, t2_id, t1_vertices, t2_vertices, common_points ) )
172- {
173- this ->emplace ( t1_id, t2_id );
174- }
175- return false ;
176- }
177- };
178-
179- geode::index_t third_point_index ( const geode::PolygonVertices& vertices,
180- const geode::PolygonVertices& vertices_to_avoid )
181- {
182- for ( const auto vertex_id : vertices )
183- {
184- if ( vertex_id == vertices_to_avoid[0 ]
185- || vertex_id == vertices_to_avoid[1 ] )
186- {
187- continue ;
188- }
189- return vertex_id;
190- }
191- OPENGEODE_ASSERT_NOT_REACHED ( " Should have found a third point index" );
192- return geode::NO_ID;
193- }
194-
195- template <>
196- bool TriangleTriangleIntersectionBase< 2 >::triangles_intersect(
197- geode::index_t t1_id,
198- geode::index_t t2_id,
199- const geode::PolygonVertices& t1_vertices,
200- const geode::PolygonVertices& t2_vertices,
201- const geode::PolygonVertices& common_points ) const
202- {
203- if ( common_points.size () == 2 )
204- {
205- const auto & common_pt0 = mesh_.point ( common_points[0 ] );
206- const auto & common_pt1 = mesh_.point ( common_points[1 ] );
207- const auto & t1_third_pt =
208- mesh_.point ( third_point_index ( t1_vertices, common_points ) );
209- const auto & t2_third_pt =
210- mesh_.point ( third_point_index ( t2_vertices, common_points ) );
211- if ( geode::segment_segment_intersection_detection (
212- { common_pt0, t1_third_pt }, { common_pt1, t2_third_pt } )
213- .first
214- != geode::POSITION::outside
215- || geode::segment_segment_intersection_detection (
216- { common_pt1, t1_third_pt },
217- { common_pt0, t2_third_pt } )
218- .first
219- != geode::POSITION::outside )
220- {
221- return true ;
222- }
223- const auto t1 = mesh_.triangle ( t1_id );
224- const auto t2 = mesh_.triangle ( t2_id );
225- if ( geode::point_triangle_position ( t1_third_pt, t2 )
226- != geode::POSITION::outside
227- || geode::point_triangle_position ( t2_third_pt, t1 )
228- != geode::POSITION::outside )
229- {
230- return true ;
231- }
232- return false ;
233- }
234- for ( const auto t1_edge_v : geode::LRange{ 3 } )
80+ protected:
81+ void emplace ( geode::index_t t1_id, geode::index_t t2_id )
23582 {
236- const std::array< geode::index_t , 2 > edge1_vertices{
237- t1_vertices[t1_edge_v],
238- t1_vertices[t1_edge_v == 2 ? 0 : t1_edge_v + 1 ]
239- };
240- const geode::Segment2D t1_edge{ mesh_.point ( edge1_vertices[0 ] ),
241- mesh_.point ( edge1_vertices[1 ] ) };
242- for ( const auto t2_edge_v : geode::LRange{ 3 } )
243- {
244- const std::array< geode::index_t , 2 > edge2_vertices{
245- t2_vertices[t2_edge_v],
246- t2_vertices[t2_edge_v == 2 ? 0 : t2_edge_v + 1 ]
247- };
248- const auto edge_edge_inter =
249- geode::segment_segment_intersection_detection (
250- t1_edge, { mesh_.point ( edge2_vertices[0 ] ),
251- mesh_.point ( edge2_vertices[1 ] ) } );
252- if ( edge_edge_inter.first == geode::POSITION::outside
253- || edge_edge_inter.first == geode::POSITION::parallel )
254- {
255- continue ;
256- }
257- if ( common_points.size () != 1 )
258- {
259- return true ;
260- }
261- const auto t1_edge_inter_pt_id =
262- surface_vertex_position_to_index ( edge_edge_inter.first );
263- const auto t2_edge_inter_pt_id =
264- surface_vertex_position_to_index ( edge_edge_inter.second );
265- if ( t1_edge_inter_pt_id == geode::NO_LID
266- || t2_edge_inter_pt_id == geode::NO_LID )
267- {
268- return true ;
269- }
270- if ( edge1_vertices[t1_edge_inter_pt_id]
271- != edge2_vertices[t2_edge_inter_pt_id]
272- || edge1_vertices[t1_edge_inter_pt_id] != common_points[0 ] )
273- {
274- return true ;
275- }
276- }
83+ intersecting_triangles_.emplace_back ( t1_id, t2_id );
27784 }
278- return false ;
279- }
28085
281- bool triangle_intersects_other ( const geode::Triangle3D& t1,
282- const geode::Triangle3D& t2,
283- const geode::PolygonVertices& t1_vertices,
284- const geode::PolygonVertices& t2_vertices,
285- const geode::PolygonVertices& common_points )
286- {
287- for ( const auto v_id : geode::LRange{ 3 } )
86+ const geode::TriangulatedSurface< dimension >& mesh () const
28887 {
289- const auto v2_id = v_id == 2 ? 0 : v_id + 1 ;
290- const auto intersection = segment_triangle_intersection_detection (
291- { t1.vertices ()[v_id], t1.vertices ()[v2_id] }, t2 );
292- if ( intersection.first != geode::POSITION::outside )
293- {
294- if ( common_points.size () != 1 )
295- {
296- return true ;
297- }
298- const auto edge_inter_pt_id =
299- surface_vertex_position_to_index ( intersection.first );
300- const auto t2_inter_pt_id =
301- surface_vertex_position_to_index ( intersection.second );
302- if ( edge_inter_pt_id == geode::NO_LID
303- || t2_inter_pt_id == geode::NO_LID )
304- {
305- return true ;
306- }
307- if ( t1_vertices[edge_inter_pt_id == 0 ? v_id : v2_id]
308- != t2_vertices[t2_inter_pt_id]
309- || t2_vertices[t2_inter_pt_id] != common_points[0 ] )
310- {
311- return true ;
312- }
313- }
88+ return mesh_;
31489 }
315- return false ;
316- }
31790
318- template <>
319- bool TriangleTriangleIntersectionBase< 3 >::triangles_intersect(
320- geode::index_t t1_id,
321- geode::index_t t2_id,
322- const geode::PolygonVertices& t1_vertices,
323- const geode::PolygonVertices& t2_vertices,
324- const geode::PolygonVertices& common_points ) const
325- {
326- const auto t2 = mesh_.triangle ( t2_id );
327- if ( common_points.size () == 2 )
328- {
329- const auto & t1_third_pt =
330- mesh_.point ( third_point_index ( t1_vertices, common_points ) );
331- if ( geode::segment_triangle_intersection_detection (
332- { mesh_.point ( common_points[0 ] ), t1_third_pt }, t2 )
333- .first
334- == geode::POSITION::parallel
335- || geode::segment_triangle_intersection_detection (
336- { mesh_.point ( common_points[1 ] ), t1_third_pt }, t2 )
337- .first
338- == geode::POSITION::parallel )
339- {
340- return true ;
341- }
342- return false ;
343- }
344- const auto t1 = mesh_.triangle ( t1_id );
345- if ( triangle_intersects_other (
346- t1, t2, t1_vertices, t2_vertices, common_points )
347- || triangle_intersects_other (
348- t2, t1, t2_vertices, t1_vertices, common_points ) )
349- {
350- return true ;
351- }
352- return false ;
353- }
91+ private:
92+ const geode::TriangulatedSurface< dimension >& mesh_;
93+ bool stop_at_first_intersection_;
94+ std::vector< std::pair< geode::index_t , geode::index_t > >
95+ intersecting_triangles_;
96+ };
35497} // namespace
35598
35699namespace geode
@@ -366,8 +109,7 @@ namespace geode
366109
367110 bool mesh_has_self_intersections () const
368111 {
369- const auto intersections = intersecting_triangles<
370- OneTriangleTriangleIntersection< dimension > >();
112+ const auto intersections = intersecting_triangles ( true );
371113 if ( intersections.empty () )
372114 {
373115 return false ;
@@ -378,8 +120,7 @@ namespace geode
378120 InspectionIssues< std::pair< index_t , index_t > >
379121 intersecting_elements () const
380122 {
381- const auto intersections = intersecting_triangles<
382- AllTriangleTriangleIntersection< dimension > >();
123+ const auto intersections = intersecting_triangles ( false );
383124 InspectionIssues< std::pair< index_t , index_t > > issues{
384125 " Triangle - triangle intersections."
385126 };
@@ -394,12 +135,12 @@ namespace geode
394135 }
395136
396137 private:
397- template < typename Action >
398- std::vector< std::pair< index_t , index_t > >
399- intersecting_triangles () const
138+ std::vector< std::pair< index_t , index_t > > intersecting_triangles (
139+ bool stop_at_first_intersection ) const
400140 {
401141 const auto surface_aabb = create_aabb_tree ( mesh_ );
402- Action action{ mesh_ };
142+ TriangleTriangleIntersection< dimension > action{ mesh_,
143+ stop_at_first_intersection };
403144 surface_aabb.compute_self_element_bbox_intersections ( action );
404145 return action.intersecting_triangles ();
405146 }
0 commit comments