Skip to content

Commit b69b141

Browse files
cary-ilmazmine-1
andauthored
Added python bindings for Box2 and Box3 classes (#495)
* Added python bindings for Box2 and Box3 classes Signed-off-by: azmine-1 <[email protected]> * fixed box setMin/setMax bindings to use direct member access * Resolve issues with Box classes Signed-off-by: Cary Phillips <[email protected]> --------- Signed-off-by: azmine-1 <[email protected]> Signed-off-by: Cary Phillips <[email protected]> Co-authored-by: azmine-1 <[email protected]>
1 parent 4810773 commit b69b141

File tree

2 files changed

+92
-39
lines changed

2 files changed

+92
-39
lines changed

src/pybind11/PyBindImath/PyBindImathBox.cpp

Lines changed: 86 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,113 @@
44
//
55

66
#include "PyBindImath.h"
7+
#include "PyBindImathVec.h"
78
#include <ImathBox.h>
9+
#include <ImathBoxAlgo.h>
10+
#include <ImathMatrix.h>
11+
12+
namespace py = pybind11;
813

914
namespace {
1015

11-
template <class T, class V>
12-
void register_box(pybind11::class_<T>& c)
16+
template <class Box, class Vec>
17+
py::class_<Box>
18+
register_box(const char* name, py::class_<Box>& c)
1319
{
14-
c.def(pybind11::init<>())
15-
.def(pybind11::init<const V &>())
16-
.def(pybind11::init<const V &, const V &>())
17-
.def(pybind11::self == pybind11::self)
18-
.def(pybind11::self != pybind11::self)
19-
.def("makeEmpty", &T::makeEmpty, "makeEmpty() make the box empty")
20-
.def("makeInfinite", &T::makeInfinite, "makeInfinite() make the box cover all space")
21-
.def_readwrite("min", &T::min)
22-
.def_readwrite("max", &T::max)
23-
.def("extendBy", pybind11::overload_cast<const T &>(&T::extendBy), "extendBy(point) extend the box by a box")
24-
.def("extendBy", pybind11::overload_cast<const V &>(&T::extendBy), "extendBy(point) extend the box by a point")
25-
.def("size", &T::size, "size() size of the box")
26-
.def("center", &T::center, "center() center of the box")
27-
.def("intersects",pybind11::overload_cast<const V &>(&T::extendBy), "intersects(point) returns true if the box intersects the given point")
28-
.def("intersects",pybind11::overload_cast<const T &>(&T::extendBy), "intersects(box) returns true if the box intersects the given box")
29-
.def("majorAxis",&T::majorAxis, "majorAxis() major axis of the box")
30-
.def("isEmpty",&T::isEmpty, "isEmpty() returns true if the box is empty")
31-
.def("isInfinite",&T::isInfinite, "isInfinite() returns true if the box covers all space")
32-
.def("hasVolume",&T::hasVolume, "hasVolume() returns true if the box has volume")
33-
;
20+
c
21+
.def(py::init<>())
22+
.def(py::init<const Vec &>())
23+
.def(py::init<const Vec &, const Vec &>())
24+
.def(py::init<const Box &>()) // Copy constructor
25+
.def(py::init([](py::tuple t)
26+
{
27+
if (t.size() != 2)
28+
throw std::runtime_error("Box constructor requires two arguments");
29+
return Box(vecFromObject<Vec>(t[0]), vecFromObject<Vec>(t[1]));
30+
}))
31+
.def("__repr__", [name](const Box& b) {
32+
py::object min_obj = py::cast(b.min);
33+
py::object max_obj = py::cast(b.max);
34+
return py::str("{}({}, {})").format(name, py::repr(min_obj), py::repr(max_obj));
35+
})
36+
.def(py::self == py::self)
37+
.def(py::self != py::self)
38+
.def("makeEmpty", &Box::makeEmpty, "makeEmpty() make the box empty")
39+
.def("makeInfinite", &Box::makeInfinite, "makeInfinite() make the box cover all space")
40+
.def("min", [](const Box& self) { return self.min; }, "min() returns the minimum point of the box")
41+
.def("max", [](const Box& self) { return self.max; }, "max() returns the maximum point of the box")
42+
.def("setMin", [](Box& self, const Vec& v) { self.min = v; }, "setMin(point) sets the minimum point of the box")
43+
.def("setMax", [](Box& self, const Vec& v) { self.max = v; }, "setMax(point) sets the maximum point of the box")
44+
.def("size", &Box::size, "size() size of the box")
45+
.def("center", &Box::center, "center() center of the box")
46+
.def("extendBy", py::overload_cast<const Box &>(&Box::extendBy), "extendBy(box) extend the box by a box")
47+
.def("extendBy", py::overload_cast<const Vec &>(&Box::extendBy), "extendBy(point) extend the box by a point")
48+
.def("intersects", py::overload_cast<const Vec &>(&Box::intersects, py::const_), "intersects(point) returns true if the box intersects the given point")
49+
.def("intersects", py::overload_cast<const Box &>(&Box::intersects, py::const_), "intersects(box) returns true if the box intersects the given box")
50+
.def("majorAxis", &Box::majorAxis, "majorAxis() major axis of the box")
51+
.def("isEmpty", &Box::isEmpty, "isEmpty() returns true if the box is empty")
52+
.def("isInfinite", &Box::isInfinite, "isInfinite() returns true if the box covers all space")
53+
.def("hasVolume", &Box::hasVolume, "hasVolume() returns true if the box has volume");
54+
55+
return c;
56+
}
57+
3458

59+
template <class Box, class Matrix>
60+
py::class_<Box>
61+
register_box_mul(py::class_<Box>& c)
62+
{
63+
auto ri = py::return_value_policy::reference_internal;
64+
65+
c.def("__mul__", [](const Box& self, const Matrix& M) { return IMATH_NAMESPACE::transform(self, M); });
66+
c.def("__imul__", [](Box& self, const Matrix& M) -> const Box& { self = IMATH_NAMESPACE::transform(self, M); return self; }, ri);
67+
return c;
3568
}
3669

37-
template <class T, class V>
38-
void register_box2(pybind11::module& m, const char * name)
70+
template <class Box, class Vec>
71+
py::class_<Box>
72+
register_box2(py::module& m, const char * name)
3973
{
40-
pybind11::class_<T> c(m, name);
41-
register_box<T, V>(c);
74+
py::class_<Box> c(m, name);
75+
return register_box<Box, Vec>(name, c);
4276
}
4377

44-
template <class T, class V>
45-
void register_box3(pybind11::module& m, const char * name)
78+
template <class Box, class Vec>
79+
py::class_<Box>
80+
register_box3(py::module& m, const char * name)
4681
{
47-
pybind11::class_<T> c(m, name);
48-
register_box<T, V>(c);
82+
py::class_<Box> c(m, name);
83+
return register_box<Box, Vec>(name, c);
4984
}
5085

5186
} // namespace
5287

5388
namespace PyBindImath {
5489

55-
void register_imath_box(pybind11::module& m)
90+
void register_imath_box(py::module& m)
5691
{
57-
register_box2<IMATH_NAMESPACE::Box2d, IMATH_NAMESPACE::V2d>(m, "Box2d");
92+
// Register 2D boxes
93+
register_box2<IMATH_NAMESPACE::Box2i, IMATH_NAMESPACE::V2i>(m, "Box2i");
94+
register_box2<IMATH_NAMESPACE::Box2i64, IMATH_NAMESPACE::V2i64>(m, "Box2i64");
5895
register_box2<IMATH_NAMESPACE::Box2f, IMATH_NAMESPACE::V2f>(m, "Box2f");
96+
register_box2<IMATH_NAMESPACE::Box2d, IMATH_NAMESPACE::V2d>(m, "Box2d");
97+
98+
// Register 3D boxes
99+
auto box3i = register_box3<IMATH_NAMESPACE::Box3i, IMATH_NAMESPACE::V3i>(m, "Box3i");
100+
register_box_mul<IMATH_NAMESPACE::Box3i,IMATH_NAMESPACE::M44f>(box3i);
101+
register_box_mul<IMATH_NAMESPACE::Box3i,IMATH_NAMESPACE::M44d>(box3i);
102+
103+
auto box3i64 = register_box3<IMATH_NAMESPACE::Box3i64, IMATH_NAMESPACE::V3i64>(m, "Box3i64");
104+
register_box_mul<IMATH_NAMESPACE::Box3i64,IMATH_NAMESPACE::M44f>(box3i64);
105+
register_box_mul<IMATH_NAMESPACE::Box3i64,IMATH_NAMESPACE::M44d>(box3i64);
59106

60-
register_box3<IMATH_NAMESPACE::Box3d, IMATH_NAMESPACE::V3d>(m, "Box3d");
61-
register_box3<IMATH_NAMESPACE::Box3f, IMATH_NAMESPACE::V3f>(m, "Box3f");
107+
auto box3f = register_box3<IMATH_NAMESPACE::Box3f, IMATH_NAMESPACE::V3f>(m, "Box3f");
108+
register_box_mul<IMATH_NAMESPACE::Box3f,IMATH_NAMESPACE::M44f>(box3f);
109+
register_box_mul<IMATH_NAMESPACE::Box3f,IMATH_NAMESPACE::M44d>(box3f);
110+
111+
auto box3d = register_box3<IMATH_NAMESPACE::Box3d, IMATH_NAMESPACE::V3d>(m, "Box3d");
112+
register_box_mul<IMATH_NAMESPACE::Box3d,IMATH_NAMESPACE::M44f>(box3d);
113+
register_box_mul<IMATH_NAMESPACE::Box3d,IMATH_NAMESPACE::M44d>(box3d);
62114
}
63115

64116
} // namespace PyBindImath

src/pybind11/PyBindImathTest/pyBindImathTest.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6758,6 +6758,7 @@ def testBox2x (Box, Vec):
67586758
# repr
67596759

67606760
b = Box (Vec (1/9., 2/9.), Vec (4/9., 5/9.))
6761+
print(f"repr: {repr(b)}")
67616762
assert b == eval (repr (b))
67626763

67636764
print ("ok")
@@ -6776,7 +6777,7 @@ def testBox2():
67766777
testBox2x (Box2d, V2d)
67776778

67786779

6779-
#testList.append (('testBox2',testBox2))
6780+
testList.append (('testBox2',testBox2))
67806781

67816782

67826783
# -------------------------------------------------------------------------
@@ -6852,7 +6853,7 @@ def testBox3x (Box, Vec):
68526853
b = Box (Vec (1, 1, 1), Vec (2, 2, 2))
68536854

68546855
mf = M44f ()
6855-
mf.setTranslation (Vec (10, 11, 12))
6856+
mf.setTranslation (V3f (10, 11, 12))
68566857

68576858
b2 = b * mf
68586859
assert b2.min() == Vec (11, 12, 13)
@@ -6865,7 +6866,7 @@ def testBox3x (Box, Vec):
68656866
b = Box (Vec (1, 1, 1), Vec (2, 2, 2))
68666867

68676868
md = M44d ()
6868-
md.setTranslation (Vec (10, 11, 12))
6869+
md.setTranslation (V3d (10, 11, 12))
68696870

68706871
b2 = b * md
68716872
assert b2.min() == Vec (11, 12, 13)
@@ -6891,7 +6892,7 @@ def testBox3():
68916892
testBox3x (Box3d, V3d)
68926893

68936894

6894-
#testList.append (('testBox3',testBox3))
6895+
testList.append (('testBox3',testBox3))
68956896

68966897

68976898
# -------------------------------------------------------------------------
@@ -9051,7 +9052,6 @@ def checkSVD33(m):
90519052
scaleMatrix = M33d (-3, 0, 0, 0, 2, 0, 0, 0, 3)
90529053
m = m * e.toMatrix33()
90539054
checkSVD33(m)
9054-
90559055
#testList.append (('testSVD',testSVD))
90569056

90579057
def testSymmetricEigensolve():
@@ -10801,3 +10801,4 @@ def testColor4Array2D():
1080110801
# Local Variables:
1080210802
# mode:python
1080310803
# End:
10804+

0 commit comments

Comments
 (0)