3535#include < geode/geometry/intersection_detection.hpp>
3636#include < geode/geometry/position.hpp>
3737
38+ #include < geode/mesh/core/edged_curve.hpp>
3839#include < geode/mesh/core/triangulated_surface.hpp>
3940#include < geode/mesh/helpers/aabb_surface_helpers.hpp>
4041
4142#include < geode/model/helpers/aabb_model_helpers.hpp>
43+ #include < geode/model/mixin/core/line.hpp>
4244#include < geode/model/mixin/core/surface.hpp>
4345#include < geode/model/representation/core/brep.hpp>
4446#include < geode/model/representation/core/section.hpp>
@@ -75,6 +77,88 @@ namespace
7577 return triangles;
7678 }
7779
80+ class BRepLineSurfacesIntersection
81+ {
82+ public:
83+ BRepLineSurfacesIntersection ( const geode::BRep& model,
84+ const geode::uuid& surface_id,
85+ const geode::uuid& line_id )
86+ : surface_( model.surface( surface_id ) ),
87+ line_ ( model.line( line_id ) ),
88+ surface_mesh_( surface_.mesh() ),
89+ line_mesh_( line_.mesh() )
90+ {
91+ }
92+
93+ bool operator ()( geode::index_t polygon_id, geode::index_t edge_id )
94+ {
95+ if ( polygon_edge_intersect ( polygon_id, edge_id ) )
96+ {
97+ emplace ( polygon_id, edge_id );
98+ }
99+ return false ;
100+ }
101+
102+ std::vector< std::pair< geode::index_t , geode::index_t > >
103+ intersecting_elements ()
104+ {
105+ return std::move ( intersecting_surface_polygon_line_edge_ );
106+ }
107+
108+ private:
109+ bool polygon_edge_intersect ( geode::index_t p_id, geode::index_t e_id )
110+ {
111+ const auto polygon_vertices =
112+ surface_mesh_.polygon_vertices ( p_id );
113+ const auto fan_triangles =
114+ polygon_fan_triangles ( polygon_vertices, 0 );
115+ const auto line_segment = line_mesh_.segment ( e_id );
116+ for ( const auto & triangle_vertices : fan_triangles )
117+ {
118+ geode::Triangle3D triangle{ surface_mesh_.point (
119+ triangle_vertices[0 ] ),
120+ surface_mesh_.point ( triangle_vertices[1 ] ),
121+ surface_mesh_.point ( triangle_vertices[2 ] ) };
122+ const auto segment_triangle_intersection =
123+ geode::segment_triangle_intersection_detection (
124+ line_segment, triangle );
125+ if ( segment_triangle_intersection.first
126+ == geode::POSITION ::inside
127+ || segment_triangle_intersection.second
128+ == geode::POSITION ::inside
129+ || segment_triangle_intersection.first
130+ == geode::POSITION ::edge0
131+ || segment_triangle_intersection.first
132+ == geode::POSITION ::edge1
133+ || segment_triangle_intersection.second
134+ == geode::POSITION ::edge0
135+ || segment_triangle_intersection.second
136+ == geode::POSITION ::edge1
137+ || segment_triangle_intersection.second
138+ == geode::POSITION ::edge2
139+ || segment_triangle_intersection.first
140+ == geode::POSITION ::edge2 )
141+ {
142+ return true ;
143+ }
144+ }
145+ return false ;
146+ }
147+ void emplace ( geode::index_t p_id, geode::index_t e_id )
148+ {
149+ intersecting_surface_polygon_line_edge_.emplace_back ( p_id, e_id );
150+ }
151+
152+ private:
153+ const geode::Surface3D& surface_;
154+ const geode::Line3D& line_;
155+ const geode::SurfaceMesh3D& surface_mesh_;
156+ const geode::EdgedCurve3D& line_mesh_;
157+ std::vector< std::pair< geode::index_t , geode::index_t > >
158+ intersecting_surface_polygon_line_edge_;
159+ std::mutex mutex_;
160+ };
161+
78162 template < typename Model >
79163 class ModelSurfacesIntersectionBase
80164 {
@@ -171,7 +255,6 @@ namespace
171255
172256 void emplace ( geode::index_t p1_id, geode::index_t p2_id )
173257 {
174- std::lock_guard< std::mutex > lock ( mutex_ );
175258 intersecting_polygons_.emplace_back ( p1_id, p2_id );
176259 }
177260
@@ -554,6 +637,34 @@ namespace geode
554637 }
555638 }
556639
640+ void add_intersecting_lines_surfaces_elements (
641+ InspectionIssues< std::pair< ComponentMeshElement,
642+ ComponentMeshElement > >& intersection_issues ) const
643+ {
644+ if constexpr ( Model::dim == 3 )
645+ {
646+ const auto intersections =
647+ intersecting_lines_surfaces ( model_ );
648+ for ( const auto & element_pair : intersections )
649+ {
650+ const auto & surface =
651+ model_.surface ( element_pair.first .component_id .id () );
652+ const auto & line =
653+ model_.line ( element_pair.second .component_id .id () );
654+ intersection_issues.add_issue ( element_pair,
655+ absl::StrCat ( " Surface " ,
656+ surface.name ().value_or ( surface.id ().string () ),
657+ " (" , element_pair.first .component_id .id ().string (),
658+ " ) and Line " ,
659+ line.name ().value_or ( line.id ().string () ), " (" ,
660+ element_pair.second .component_id .id ().string (),
661+ " ) intersect on polygon " ,
662+ element_pair.first .element_id , " and edge " ,
663+ element_pair.second .element_id ) );
664+ }
665+ }
666+ }
667+
557668 private:
558669 template < typename Action >
559670 std::vector< std::pair< ComponentMeshElement, ComponentMeshElement > >
@@ -569,7 +680,8 @@ namespace geode
569680 geode::Logger::warn (
570681 " One of the surface meshes has an empty mesh, cannot "
571682 " compute the AABBTree used for detecting the mesh "
572- " intersections, no intersections will be computed." );
683+ " intersections, no intersections will be "
684+ " computed." );
573685 return component_intersections;
574686 }
575687 }
@@ -622,6 +734,69 @@ namespace geode
622734 return component_intersections;
623735 }
624736
737+ std::vector< std::pair< ComponentMeshElement, ComponentMeshElement > >
738+ intersecting_lines_surfaces ( const BRep& brep ) const
739+ {
740+ std::vector<
741+ std::pair< ComponentMeshElement, ComponentMeshElement > >
742+ component_intersections;
743+ for ( const auto & surface : brep.active_surfaces () )
744+ {
745+ if ( surface.mesh ().nb_polygons () == 0 )
746+ {
747+ geode::Logger::warn (
748+ " One of the surface meshes has an empty mesh, "
749+ " skipping "
750+ " line-surface intersection detection." );
751+ return component_intersections;
752+ }
753+ }
754+ for ( const auto & line : brep.active_lines () )
755+ {
756+ if ( line.mesh ().nb_edges () == 0 )
757+ {
758+ geode::Logger::warn (
759+ " One of the line meshes has an empty mesh, "
760+ " skipping "
761+ " line-surface intersection detection." );
762+ return component_intersections;
763+ }
764+ }
765+ const auto surfaces_model_tree =
766+ create_surface_meshes_aabb_trees ( brep );
767+ const auto lines_model_tree = create_line_meshes_aabb_trees ( brep );
768+ for ( const auto & surface : brep.active_surfaces () )
769+ {
770+ const auto & surface_tree =
771+ surfaces_model_tree.mesh_trees_ [surfaces_model_tree
772+ .mesh_tree_ids_ .at ( surface.id () )];
773+ for ( const auto & line : brep.active_lines () )
774+ {
775+ if ( brep.nb_embedding_blocks ( line ) == 0 )
776+ {
777+ continue ;
778+ }
779+ BRepLineSurfacesIntersection action{ brep, surface.id (),
780+ line.id () };
781+ const auto & line_tree =
782+ lines_model_tree.mesh_trees_ [lines_model_tree
783+ .mesh_tree_ids_ .at ( line.id () )];
784+ surface_tree.compute_other_element_bbox_intersections (
785+ line_tree, action );
786+ for ( const auto & element_pair :
787+ action.intersecting_elements () )
788+ {
789+ component_intersections.emplace_back (
790+ ComponentMeshElement{
791+ surface.component_id (), element_pair.first },
792+ ComponentMeshElement{
793+ line.component_id (), element_pair.second } );
794+ }
795+ }
796+ }
797+ return component_intersections;
798+ }
799+
625800 private:
626801 const Model& model_;
627802 };
@@ -650,6 +825,8 @@ namespace geode
650825 ElementsIntersectionsInspectionResult results;
651826 impl_->add_intersecting_surfaces_elements (
652827 results.elements_intersections );
828+ impl_->add_intersecting_lines_surfaces_elements (
829+ results.elements_intersections );
653830 return results;
654831 }
655832
0 commit comments