Skip to content

Commit 7247c69

Browse files
authored
Merge pull request #1190 from Geode-solutions/09_2025_120250
fix(BoundingBox): avoid to return invalid BoundingBox
2 parents 908ee60 + bce3ab7 commit 7247c69

File tree

7 files changed

+105
-32
lines changed

7 files changed

+105
-32
lines changed

include/geode/model/representation/core/internal/helpers.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,20 @@ namespace geode
5757
}
5858

5959
template < index_t dimension, typename MeshComponentRange >
60-
[[nodiscard]] BoundingBox< dimension > meshes_bounding_box(
61-
MeshComponentRange range )
60+
[[nodiscard]] std::optional< BoundingBox< dimension > >
61+
meshes_bounding_box( MeshComponentRange range )
6262
{
6363
BoundingBox< dimension > box;
64+
bool computed{ false };
6465
for( const auto& component : range )
6566
{
67+
computed = true;
6668
box.add_box( component.mesh().bounding_box() );
6769
}
70+
if( !computed )
71+
{
72+
return std::nullopt;
73+
}
6874
return box;
6975
}
7076
} // namespace internal

src/geode/mesh/core/edged_curve.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ namespace geode
158158
template < index_t dimension >
159159
BoundingBox< dimension > EdgedCurve< dimension >::bounding_box() const
160160
{
161+
OPENGEODE_EXCEPTION( nb_vertices() != 0,
162+
"[EdgedCurve::bounding_box] Cannot return "
163+
"the bounding_box of an empty edged curve." );
161164
BoundingBox< dimension > box;
162165
for( const auto p : Range{ nb_vertices() } )
163166
{

src/geode/mesh/core/point_set.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ namespace geode
8686
template < index_t dimension >
8787
BoundingBox< dimension > PointSet< dimension >::bounding_box() const
8888
{
89+
OPENGEODE_EXCEPTION( nb_vertices() != 0,
90+
"[PointSet::bounding_box] Cannot return "
91+
"the bounding_box of an empty point set." );
8992
BoundingBox< dimension > box;
9093
for( const auto p : Range{ nb_vertices() } )
9194
{

src/geode/mesh/core/solid_mesh.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,9 @@ namespace geode
17311731
template < index_t dimension >
17321732
BoundingBox< dimension > SolidMesh< dimension >::bounding_box() const
17331733
{
1734+
OPENGEODE_EXCEPTION( nb_vertices() != 0,
1735+
"[SolidMesh::bounding_box] Cannot return "
1736+
"the bounding_box of an empty solid mesh." );
17341737
BoundingBox< dimension > box;
17351738
for( const auto p : Range{ nb_vertices() } )
17361739
{

src/geode/mesh/core/surface_mesh.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,9 @@ namespace geode
10641064
template < index_t dimension >
10651065
BoundingBox< dimension > SurfaceMesh< dimension >::bounding_box() const
10661066
{
1067+
OPENGEODE_EXCEPTION( nb_vertices() != 0,
1068+
"[SurfaceMesh::bounding_box] Cannot return "
1069+
"the bounding_box of an empty surface mesh." );
10671070
BoundingBox< dimension > box;
10681071
for( const auto p : Range{ nb_vertices() } )
10691072
{

src/geode/model/representation/core/brep.cpp

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -890,41 +890,82 @@ namespace geode
890890

891891
BoundingBox3D BRep::bounding_box() const
892892
{
893-
if( nb_surfaces() > 0 )
893+
geode::BoundingBox3D bbox;
894+
if( const auto box = internal::meshes_bounding_box< 3 >( surfaces() ) )
894895
{
895-
return internal::meshes_bounding_box< 3 >( surfaces() );
896+
bbox.add_box( box.value() );
896897
}
897-
if( nb_blocks() > 0 )
898+
if( const auto box = internal::meshes_bounding_box< 3 >( lines() ) )
898899
{
899-
return internal::meshes_bounding_box< 3 >( blocks() );
900+
bbox.add_box( box.value() );
900901
}
901-
if( nb_lines() > 0 )
902+
if( const auto box = internal::meshes_bounding_box< 3 >( corners() ) )
902903
{
903-
return internal::meshes_bounding_box< 3 >( lines() );
904+
bbox.add_box( box.value() );
904905
}
905-
return internal::meshes_bounding_box< 3 >( corners() );
906+
try
907+
{
908+
if( const auto box =
909+
internal::meshes_bounding_box< 3 >( blocks() ) )
910+
{
911+
bbox.add_box( box.value() );
912+
}
913+
}
914+
catch( const OpenGeodeException& )
915+
{
916+
OPENGEODE_EXCEPTION(
917+
nb_corners() > 0 || nb_lines() > 0 || nb_surfaces() > 0,
918+
"[BRep::bounding_box] Cannot return the bounding_box of a BRep "
919+
"with not meshes Blocks and no Corners, no Lines and no "
920+
"Surfaces." );
921+
}
922+
OPENGEODE_EXCEPTION( bbox.min() <= bbox.max(),
923+
"[BRep::bounding_box] Cannot return the "
924+
"bounding_box of an empty BRep." );
925+
return bbox;
906926
}
907927

908928
BoundingBox3D BRep::active_components_bounding_box() const
909929
{
910-
geode::BoundingBox3D box;
911-
for( const auto& corner : active_corners() )
930+
geode::BoundingBox3D bbox;
931+
if( const auto box =
932+
internal::meshes_bounding_box< 3 >( active_surfaces() ) )
933+
{
934+
bbox.add_box( box.value() );
935+
}
936+
if( const auto box =
937+
internal::meshes_bounding_box< 3 >( active_lines() ) )
912938
{
913-
box.add_box( corner.mesh().bounding_box() );
939+
bbox.add_box( box.value() );
914940
}
915-
for( const auto& line : active_lines() )
941+
if( const auto box =
942+
internal::meshes_bounding_box< 3 >( active_corners() ) )
916943
{
917-
box.add_box( line.mesh().bounding_box() );
944+
bbox.add_box( box.value() );
918945
}
919-
for( const auto& surface : active_surfaces() )
946+
try
920947
{
921-
box.add_box( surface.mesh().bounding_box() );
948+
if( const auto box =
949+
internal::meshes_bounding_box< 3 >( active_blocks() ) )
950+
{
951+
bbox.add_box( box.value() );
952+
}
922953
}
923-
for( const auto& block : active_blocks() )
954+
catch( const OpenGeodeException& )
924955
{
925-
box.add_box( block.mesh().bounding_box() );
956+
for( const auto& block : active_blocks() )
957+
{
958+
if( const auto box = internal::meshes_bounding_box< 3 >(
959+
boundaries( block ) ) )
960+
{
961+
bbox.add_box( box.value() );
962+
}
963+
}
926964
}
927-
return box;
965+
OPENGEODE_EXCEPTION( bbox.min() <= bbox.max(),
966+
"[BRep::bounding_box] Cannot return the "
967+
"bounding_box of a full inactive BRep." );
968+
return bbox;
928969
}
929970

930971
} // namespace geode

src/geode/model/representation/core/section.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -590,32 +590,46 @@ namespace geode
590590

591591
BoundingBox2D Section::bounding_box() const
592592
{
593-
if( nb_lines() > 0 )
593+
geode::BoundingBox2D bbox;
594+
if( const auto box = internal::meshes_bounding_box< 2 >( surfaces() ) )
594595
{
595-
return internal::meshes_bounding_box< 2 >( lines() );
596+
bbox.add_box( box.value() );
596597
}
597-
if( nb_surfaces() > 0 )
598+
if( const auto box = internal::meshes_bounding_box< 2 >( lines() ) )
598599
{
599-
return internal::meshes_bounding_box< 2 >( surfaces() );
600+
bbox.add_box( box.value() );
600601
}
601-
return internal::meshes_bounding_box< 2 >( corners() );
602+
if( const auto box = internal::meshes_bounding_box< 2 >( corners() ) )
603+
{
604+
bbox.add_box( box.value() );
605+
}
606+
OPENGEODE_EXCEPTION( bbox.min() <= bbox.max(),
607+
"[Section::bounding_box] Cannot return the "
608+
"bounding_box of an empty Section." );
609+
return bbox;
602610
}
603611

604612
BoundingBox2D Section::active_components_bounding_box() const
605613
{
606-
geode::BoundingBox2D box;
607-
for( const auto& corner : active_corners() )
614+
geode::BoundingBox2D bbox;
615+
if( const auto box =
616+
internal::meshes_bounding_box< 2 >( active_surfaces() ) )
608617
{
609-
box.add_box( corner.mesh().bounding_box() );
618+
bbox.add_box( box.value() );
610619
}
611-
for( const auto& line : active_lines() )
620+
if( const auto box =
621+
internal::meshes_bounding_box< 2 >( active_lines() ) )
612622
{
613-
box.add_box( line.mesh().bounding_box() );
623+
bbox.add_box( box.value() );
614624
}
615-
for( const auto& surface : active_surfaces() )
625+
if( const auto box =
626+
internal::meshes_bounding_box< 2 >( active_corners() ) )
616627
{
617-
box.add_box( surface.mesh().bounding_box() );
628+
bbox.add_box( box.value() );
618629
}
619-
return box;
630+
OPENGEODE_EXCEPTION( bbox.min() <= bbox.max(),
631+
"[Section::bounding_box] Cannot return the "
632+
"bounding_box of a full inactive Section." );
633+
return bbox;
620634
}
621635
} // namespace geode

0 commit comments

Comments
 (0)