Skip to content

Commit ed36887

Browse files
authored
Merge pull request #933 from Geode-solutions/brep_helper_ray_tracing
feat(BRepHelper): add ray tracing based test for point in block.
2 parents 8b75e37 + e692519 commit ed36887

File tree

8 files changed

+205
-0
lines changed

8 files changed

+205
-0
lines changed

bindings/python/src/model/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ add_geode_python_binding(
2929
"helpers/model_component_filter.cpp"
3030
"helpers/model_concatener.cpp"
3131
"helpers/model_crs.cpp"
32+
"helpers/ray_tracing.cpp"
3233
"mixin/builder/blocks_builder.cpp"
3334
"mixin/builder/block_collections_builder.cpp"
3435
"mixin/builder/corners_builder.cpp"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2019 - 2024 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#include "../../common.h"
25+
26+
#include <geode/model/mixin/core/block.h>
27+
#include <geode/model/representation/core/brep.h>
28+
29+
#include <geode/model/helpers/ray_tracing.h>
30+
31+
namespace geode
32+
{
33+
void define_model_ray_tracing( pybind11::module& module )
34+
{
35+
module
36+
.def( "find_intersections_with_boundaries",
37+
&find_intersections_with_boundaries )
38+
.def( "is_point_inside_block", &is_point_inside_block )
39+
.def( "block_containing_point", &block_containing_point );
40+
}
41+
} // namespace geode

bindings/python/src/model/model.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ namespace geode
8383
void define_model_component_filter( pybind11::module& );
8484
void define_model_concatener( pybind11::module& );
8585
void define_model_coordinate_reference_system( pybind11::module& );
86+
void define_model_ray_tracing( pybind11::module& );
8687
} // namespace geode
8788

8889
PYBIND11_MODULE( opengeode_py_model, module )

include/geode/model/helpers/ray_tracing.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,10 @@ namespace geode
4747
const BRep& brep,
4848
const Block3D& block );
4949

50+
bool opengeode_model_api is_point_inside_block(
51+
const BRep& brep, const Block3D& block, const Point3D& point );
52+
53+
absl::optional< uuid > opengeode_model_api block_containing_point(
54+
const BRep& brep, const Point3D& point );
55+
5056
} // namespace geode

src/geode/model/helpers/ray_tracing.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,55 @@
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+
3584
namespace 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

tests/data/box_brep.og_brep

35.1 KB
Binary file not shown.

tests/model/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,13 @@ add_geode_test(
101101
${PROJECT_NAME}::geometry
102102
${PROJECT_NAME}::model
103103
)
104+
add_geode_test(
105+
SOURCE "test-ray-tracing-helpers.cpp"
106+
DEPENDENCIES
107+
${PROJECT_NAME}::basic
108+
${PROJECT_NAME}::geometry
109+
${PROJECT_NAME}::model
110+
)
104111
add_geode_test(
105112
SOURCE "test-relationships.cpp"
106113
DEPENDENCIES
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2019 - 2024 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#include <geode/basic/assert.h>
25+
#include <geode/basic/logger.h>
26+
27+
#include <geode/model/helpers/ray_tracing.h>
28+
29+
#include <geode/geometry/bounding_box.h>
30+
#include <geode/model/representation/core/brep.h>
31+
#include <geode/model/representation/io/brep_input.h>
32+
33+
#include <geode/tests/common.h>
34+
35+
void test()
36+
{
37+
geode::OpenGeodeModelLibrary::initialize();
38+
39+
// load a 40x40x40 aligned cubic box brep
40+
auto brep = geode::load_brep(
41+
absl::StrCat( geode::data_path, "box_brep.og_brep" ) );
42+
geode::Point3D center( { 20., 20., 20. } );
43+
44+
// get the block
45+
const auto block_id = geode::block_containing_point( brep, center );
46+
OPENGEODE_EXCEPTION( block_id.has_value(),
47+
"[Test] fail to recover block_containing_point." );
48+
49+
// test point iside the block
50+
geode::Point3D inside( { 0.00001, 0.00001, 0.00001 } );
51+
geode::Point3D outside( { -0.00001, 0.00001, 0.00001 } );
52+
OPENGEODE_EXCEPTION( geode::is_point_inside_block(
53+
brep, brep.block( block_id.value() ), inside ),
54+
"[Test] the point named inside should be inside the block." );
55+
56+
OPENGEODE_EXCEPTION( !geode::is_point_inside_block(
57+
brep, brep.block( block_id.value() ), outside ),
58+
"[Test] the point named outside should be outside the block." );
59+
}
60+
61+
OPENGEODE_TEST( "ray-tracing-helpers" )

0 commit comments

Comments
 (0)