3232#include < geode/model/mixin/core/surface.h>
3333#include < geode/model/representation/core/brep.h>
3434
35+ namespace
36+ {
37+ geode::BoundarySurfaceIntersections find_intersections_with_boundaries (
38+ const geode::Ray3D& ray,
39+ const geode::BRep& brep,
40+ const geode::Block3D& block )
41+ {
42+ geode::BoundarySurfaceIntersections result;
43+ for ( const auto & surface : brep.boundaries ( block ) )
44+ {
45+ const auto aabb = geode::create_aabb_tree ( surface.mesh () );
46+ geode::RayTracing3D ray_tracing{ surface.mesh (), ray };
47+ aabb.compute_ray_element_bbox_intersections ( ray, ray_tracing );
48+ result[surface.id ()] = ray_tracing.all_intersections ();
49+ }
50+ return result;
51+ }
52+
53+ absl::optional< geode::index_t > count_real_intersections_with_boudaries (
54+ const geode::Ray3D& ray,
55+ const geode::BRep& brep,
56+ const geode::Block3D& block )
57+ {
58+ geode::index_t nb_intersections{ 0 };
59+ const auto tracing =
60+ find_intersections_with_boundaries ( ray, brep, block );
61+ for ( const auto & intersections : tracing )
62+ {
63+ for ( const auto & intersection : intersections.second )
64+ {
65+ if ( intersection.position != geode::Position::inside )
66+ {
67+ return absl::nullopt ;
68+ }
69+ if ( std::fabs ( intersection.distance )
70+ <= geode::global_epsilon )
71+ {
72+ continue ;
73+ }
74+ else
75+ {
76+ nb_intersections += 1 ;
77+ }
78+ }
79+ }
80+ return nb_intersections;
81+ }
82+ } // namespace
83+
3584namespace geode
3685{
3786 BoundarySurfaceIntersections find_intersections_with_boundaries (
@@ -51,4 +100,43 @@ namespace geode
51100 return result;
52101 }
53102
103+ bool is_point_inside_block (
104+ const BRep& brep, const Block3D& block, const Point3D& point )
105+ {
106+ std::array< Vector3D, 12 > directions = { { { { 0 ., 0 ., 1 . } },
107+ { { 0.1 , 0 ., 1 . } }, { { 0.3 , 0 ., 1 . } }, { { 0.5 , 0 ., 1 . } },
108+ { { 0 ., 1 ., 0 . } }, { { 0.1 , 1 ., 0 . } }, { { 0.3 , 1 ., 0 . } },
109+ { { 0.5 , 1 ., 0 . } }, { { 1 ., 0 ., 0 . } }, { { 1 ., 0 ., 0.1 } },
110+ { { 1 ., 0 ., 0.3 } }, { { 1 ., 0 ., 0.5 } } } };
111+
112+ for ( const auto & direction : directions )
113+ {
114+ const Ray3D ray{ direction, point };
115+ auto nb_intersections =
116+ count_real_intersections_with_boudaries ( ray, brep, block );
117+
118+ if ( nb_intersections.has_value () )
119+ {
120+ return ( nb_intersections.value () % 2 == 1 );
121+ }
122+ }
123+ throw OpenGeodeException{
124+ " Cannot determine the point is inside the block or not "
125+ " (ambigous intersection with rays)."
126+ };
127+ }
128+
129+ absl::optional< uuid > block_containing_point (
130+ const BRep& brep, const Point3D& point )
131+ {
132+ for ( const auto & block : brep.blocks () )
133+ {
134+ if ( is_point_inside_block ( brep, block, point ) )
135+ {
136+ return block.id ();
137+ }
138+ }
139+ return absl::nullopt ;
140+ }
141+
54142} // namespace geode
0 commit comments