diff --git a/bindings/python/src/geometry/CMakeLists.txt b/bindings/python/src/geometry/CMakeLists.txt index 2fe7b2010..0dfbc753a 100644 --- a/bindings/python/src/geometry/CMakeLists.txt +++ b/bindings/python/src/geometry/CMakeLists.txt @@ -24,8 +24,8 @@ add_geode_python_binding( "geometry.cpp" "angle.cpp" "barycentric_coordinates.cpp" - "basic_objects.cpp" "bounding_box.cpp" + "basic_objects.cpp" "coordinate_system.cpp" "distance.cpp" "frame.cpp" diff --git a/bindings/python/src/geometry/basic_objects.cpp b/bindings/python/src/geometry/basic_objects.cpp index 591f579af..b600f0497 100644 --- a/bindings/python/src/geometry/basic_objects.cpp +++ b/bindings/python/src/geometry/basic_objects.cpp @@ -97,6 +97,25 @@ .def( "origin", &Ray##dimension##D::origin ) \ .def( "direction", &Ray##dimension##D::direction ) +#define PYTHON_BOUNDING_BOX_AND_BASIC_OBJECTS( dimension ) \ + const auto bbox##dimension = \ + "BoundingBox" + std::to_string( dimension ) + "D"; \ + auto pybbox##dimension = \ + module.attr( bbox##dimension.c_str() ) \ + .cast< pybind11::class_< BoundingBox##dimension##D > >(); \ + pybbox##dimension.def( \ + "intersects_ray", static_cast< bool ( BoundingBox##dimension##D::* )( \ + const Ray< dimension >& ) const >( \ + &BoundingBox##dimension##D::intersects ) ); \ + pybbox##dimension.def( "intersects_infinite_line", \ + static_cast< bool ( BoundingBox##dimension##D::* )( \ + const InfiniteLine< dimension >& ) const >( \ + &BoundingBox##dimension##D::intersects ) ); \ + pybbox##dimension.def( "intersects_segment", \ + static_cast< bool ( BoundingBox##dimension##D::* )( \ + const Segment< dimension >& ) const >( \ + &BoundingBox##dimension##D::intersects ) ) + namespace geode { void define_basic_objects( pybind11::module& module ) @@ -169,5 +188,7 @@ namespace geode .def( pybind11::init< Segment3D, double >() ) .def( "axis", &Cylinder::axis ) .def( "radius", &Cylinder::radius ); + PYTHON_BOUNDING_BOX_AND_BASIC_OBJECTS( 2 ); + PYTHON_BOUNDING_BOX_AND_BASIC_OBJECTS( 3 ); } } // namespace geode diff --git a/bindings/python/src/geometry/bounding_box.cpp b/bindings/python/src/geometry/bounding_box.cpp index c85225d00..95b672277 100644 --- a/bindings/python/src/geometry/bounding_box.cpp +++ b/bindings/python/src/geometry/bounding_box.cpp @@ -24,6 +24,7 @@ #include "../common.hpp" #include +#include #include #include @@ -35,6 +36,7 @@ .def( pybind11::init<>() ) \ .def( "add_box", &BoundingBox##dimension##D::add_box ) \ .def( "add_point", &BoundingBox##dimension##D::add_point ) \ + .def( "extends", &BoundingBox##dimension##D::extends ) \ .def( "contains_point", \ static_cast< bool ( BoundingBox##dimension##D::* )( \ const Point< dimension >& ) const >( \ @@ -43,16 +45,19 @@ static_cast< bool ( BoundingBox##dimension##D::* )( \ const BoundingBox< dimension >& ) const >( \ &BoundingBox##dimension##D::contains ) ) \ - .def( "intersects_bbox", \ + .def( "intersects_bounding_box", \ static_cast< bool ( BoundingBox##dimension##D::* )( \ const BoundingBox< dimension >& ) const >( \ &BoundingBox##dimension##D::intersects ) ) \ + .def( "signed_distance", &BoundingBox##dimension##D::signed_distance ) \ .def( "min", &BoundingBox##dimension##D::min ) \ .def( "max", &BoundingBox##dimension##D::max ) \ .def( "center", &BoundingBox##dimension##D::center ) \ .def( "diagonal", &BoundingBox##dimension##D::diagonal ) \ .def( "smallest_length", &BoundingBox##dimension##D::smallest_length ) \ - .def( "largest_length", &BoundingBox##dimension##D::largest_length ) + .def( "largest_length", &BoundingBox##dimension##D::largest_length ) \ + .def( "n_volume", &BoundingBox##dimension##D::n_volume ) \ + .def( "string", &BoundingBox##dimension##D::string ) namespace geode { diff --git a/bindings/python/tests/geometry/test-py-bounding-box.py b/bindings/python/tests/geometry/test-py-bounding-box.py index 74e6325fc..fd92bb695 100644 --- a/bindings/python/tests/geometry/test-py-bounding-box.py +++ b/bindings/python/tests/geometry/test-py-bounding-box.py @@ -47,3 +47,34 @@ raise ValueError("[Test] BBox should contain this point") if box2.contains_point(geom.Point2D([10, 0])): raise ValueError("[Test] BBox should not contain this point") + + # --- 3D Bounding Box and Ray/Line intersections --- + bbox3 = geom.BoundingBox3D() + bbox3.add_point(geom.Point3D([-1, -1, -1])) + bbox3.add_point(geom.Point3D([1, 1, 1])) + + # Rays + ray_inside = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 0])) + if not bbox3.intersects_ray(ray_inside): + raise ValueError("[Test] Wrong result with ray_inside") + + ray_up = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 2])) + if bbox3.intersects_ray(ray_up): + raise ValueError("[Test] Wrong result with ray_up") + + ray_down = geom.Ray3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, -2])) + if not bbox3.intersects_ray(ray_down): + raise ValueError("[Test] Wrong result with ray_down") + + # Infinite lines + line_inside = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 0])) + if not bbox3.intersects_infinite_line(line_inside): + raise ValueError("[Test] Wrong result with line_inside") + + line_up = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, 2])) + if not bbox3.intersects_infinite_line(line_up): + raise ValueError("[Test] Wrong result with line_up") + + line_down = geom.InfiniteLine3D( geom.Vector3D([0, 0, 1]),geom.Point3D([0, 0, -2])) + if not bbox3.intersects_infinite_line(line_down): + raise ValueError("[Test] Wrong result with line_down") \ No newline at end of file