/////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1998-2011, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////// #include "PyImathBox.h" #include "PyImathVec.h" #include "PyImathMathExc.h" #include "PyImathDecorators.h" #include "PyImathExport.h" #include #include #include #include #include #include "PyImathBoxArrayImpl.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; using namespace PyImath; template struct BoxName { static const char *value; }; template <> const char *BoxName::value = "Box2s"; template <> const char *BoxName::value = "Box2i"; template <> const char *BoxName::value = "Box2f"; template <> const char *BoxName::value = "Box2d"; template <> const char *BoxName::value = "Box3s"; template <> const char *BoxName::value = "Box3i"; template <> const char *BoxName::value = "Box3f"; template <> const char *BoxName::value = "Box3d"; template <> PYIMATH_EXPORT const char *PyImath::Box2sArray::name() { return "Box2sArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box2iArray::name() { return "Box2iArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box2fArray::name() { return "Box2fArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box2dArray::name() { return "Box2dArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box3sArray::name() { return "Box3sArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box3iArray::name() { return "Box3iArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box3fArray::name() { return "Box3fArray"; } template <> PYIMATH_EXPORT const char *PyImath::Box3dArray::name() { return "Box3dArray"; } template static Box * box2TupleConstructor1(const tuple &t) { if(t.attr("__len__")() == 2) { // The constructor was called like this: // Box2f ((V2f(1,2), V2f(3,4))) or // Box2f (((1,2), (3,4))) PyObject *t0Obj = extract (t[0])().ptr(); PyObject *t1Obj = extract (t[1])().ptr(); T t0, t1; if (V2::convert (t0Obj, &t0) && V2::convert (t1Obj, &t1)) { return new Box (t0, t1); } // The constructor was called like this: // Box2f ((1,2)) else { T point; point.x = extract(t[0]); point.y = extract(t[1]); return new Box(point); } } else THROW(IEX_NAMESPACE::LogicExc, "Invalid input to Box tuple constructor"); } template static Box * box2TupleConstructor2(const tuple &t0, const tuple &t1) { if(t0.attr("__len__")() == 2 && t1.attr("__len__")() == 2) { T point0, point1; point0.x = extract(t0[0]); point0.y = extract(t0[1]); point1.x = extract(t1[0]); point1.y = extract(t1[1]); return new Box(point0, point1); } else THROW(IEX_NAMESPACE::LogicExc, "Invalid input to Box tuple constructor"); } template static Box *boxConstructor(const Box &box) { Box *newBox = new Box; newBox->min = box.min; newBox->max = box.max; return newBox; } template static Box * box3TupleConstructor1(const tuple &t) { if(t.attr("__len__")() == 3) { // The constructor was called like this: // Box3f ((1,2,3)) T point; point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return new Box(point); } else if (t.attr("__len__")() == 2) { // The constructor was called like this: // Box3f ((V3f(1,2,3), V3f(4,5,6))) or // Box3f (((1,2,3), (4,5,6))) PyObject *t0Obj = extract (t[0])().ptr(); PyObject *t1Obj = extract (t[1])().ptr(); T t0, t1; if (V3::convert (t0Obj, &t0) && V3::convert (t1Obj, &t1)) { return new Box (t0, t1); } else THROW(IEX_NAMESPACE::LogicExc, "Invalid input to Box tuple constructor"); } else THROW(IEX_NAMESPACE::LogicExc, "Invalid input to Box tuple constructor"); } template static Box * box3TupleConstructor2(const tuple &t0, const tuple &t1) { if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3) { T point0, point1; point0.x = extract(t0[0]); point0.y = extract(t0[1]); point0.z = extract(t0[2]); point1.x = extract(t1[0]); point1.y = extract(t1[1]); point1.z = extract(t1[2]); return new Box(point0, point1); } else THROW(IEX_NAMESPACE::LogicExc, "Invalid input to Box tuple constructor"); } template static std::string Box2_repr(const Box &box) { std::stringstream stream; typename boost::python::return_by_value::apply ::type converter; PyObject *minObj = converter (box.min); PyObject *minReprObj = PyObject_Repr (minObj); std::string minReprStr = PyString_AsString (minReprObj); Py_DECREF (minReprObj); Py_DECREF (minObj); PyObject *maxObj = converter (box.max); PyObject *maxReprObj = PyObject_Repr (maxObj); std::string maxReprStr = PyString_AsString (maxReprObj); Py_DECREF (maxReprObj); Py_DECREF (maxObj); stream << BoxName::value << "(" << minReprStr << ", " << maxReprStr << ")"; return stream.str(); } template static std::string Box3_repr(const Box &box) { std::stringstream stream; typename boost::python::return_by_value::apply ::type converter; PyObject *minObj = converter (box.min); PyObject *minReprObj = PyObject_Repr (minObj); std::string minReprStr = PyString_AsString (minReprObj); Py_DECREF (minReprObj); Py_DECREF (minObj); PyObject *maxObj = converter (box.max); PyObject *maxReprObj = PyObject_Repr (maxObj); std::string maxReprStr = PyString_AsString (maxReprObj); Py_DECREF (maxReprObj); Py_DECREF (maxObj); stream << BoxName::value << "(" << minReprStr << ", " << maxReprStr << ")"; return stream.str(); } template static void boxSetMin(IMATH_NAMESPACE::Box &box, const T &m) { box.min = m; } template static void boxSetMax(IMATH_NAMESPACE::Box &box, const T &m) { box.max = m; } template static T boxMin(IMATH_NAMESPACE::Box &box) { return box.min; } template static T boxMax(IMATH_NAMESPACE::Box &box) { return box.max; } template struct IntersectsTask : public Task { const IMATH_NAMESPACE::Box& box; const PyImath::FixedArray& points; PyImath::FixedArray& results; IntersectsTask(IMATH_NAMESPACE::Box& b, const PyImath::FixedArray &p, PyImath::FixedArray &r) : box(b), points(p), results(r) {} void execute(size_t start, size_t end) { for(size_t p = start; p < end; ++p) results[p] = box.intersects(points[p]); } }; template struct ExtendByTask : public Task { std::vector >& boxes; const PyImath::FixedArray& points; ExtendByTask(std::vector >& b, const PyImath::FixedArray &p) : boxes(b), points(p) {} void execute(size_t start, size_t end, int tid) { for(size_t p = start; p < end; ++p) boxes[tid].extendBy(points[p]); } void execute(size_t start, size_t end) { ASSERT(false, IEX_NAMESPACE::NoImplExc, "Box::ExtendBy execute requires a thread id"); } }; template static void box_extendBy(IMATH_NAMESPACE::Box &box, const PyImath::FixedArray &points) { size_t numBoxes = workers(); std::vector > boxes(numBoxes); ExtendByTask task(boxes,points); dispatchTask(task,points.len()); for (int i=0; i PyImath::FixedArray box_intersects(IMATH_NAMESPACE::Box& box, const PyImath::FixedArray& points) { size_t numPoints = points.len(); PyImath::FixedArray mask(numPoints); IntersectsTask task(box,points,mask); dispatchTask(task,numPoints); return mask; } template class_ > register_Box2() { void (IMATH_NAMESPACE::Box::*extendBy1)(const T&) = &IMATH_NAMESPACE::Box::extendBy; void (IMATH_NAMESPACE::Box::*extendBy2)(const IMATH_NAMESPACE::Box&) = &IMATH_NAMESPACE::Box::extendBy; bool (IMATH_NAMESPACE::Box::*intersects1)(const T&) const = &IMATH_NAMESPACE::Box::intersects; bool (IMATH_NAMESPACE::Box::*intersects2)(const IMATH_NAMESPACE::Box&) const = &IMATH_NAMESPACE::Box::intersects; const char *name = BoxName::value; class_ > box_class(name); box_class .def(init<>("Box() create empty box") ) .def(init("Box(point)create box containing the given point") ) .def(init("Box(point,point) create box continaing min and max") ) .def("__init__", make_constructor(box2TupleConstructor1), "Box(point) where point is a python tuple") .def("__init__", make_constructor(box2TupleConstructor2), "Box(point,point) where point is a python tuple") .def("__init__", make_constructor(boxConstructor)) .def("__init__", make_constructor(boxConstructor)) .def("__init__", make_constructor(boxConstructor)) .def_readwrite("min",&Box::min) .def_readwrite("max",&Box::max) .def("min", &boxMin) .def("max", &boxMax) .def(self == self) .def(self != self) .def("__repr__", &Box2_repr) .def("makeEmpty",&Box::makeEmpty,"makeEmpty() make the box empty") .def("makeInfinite",&Box::makeInfinite,"makeInfinite() make the box cover all space") .def("extendBy",extendBy1,"extendBy(point) extend the box by a point") .def("extendBy",box_extendBy,"extendBy(array) extend the box the values in the array") .def("extendBy",extendBy2,"extendBy(box) extend the box by a box") .def("size",&Box::size,"size() size of the box") .def("center",&Box::center,"center() center of the box") .def("intersects",intersects1,"intersects(point) returns true if the box intersects the given point") .def("intersects",intersects2,"intersects(box) returns true if the box intersects the given box") .def("majorAxis",&Box::majorAxis,"majorAxis() major axis of the box") .def("isEmpty",&Box::isEmpty,"isEmpty() returns true if the box is empty") .def("isInfinite",&Box::isInfinite,"isInfinite() returns true if the box covers all space") .def("hasVolume",&Box::hasVolume,"hasVolume() returns true if the box has volume") .def("setMin",&boxSetMin,"setMin() sets the min value of the box") .def("setMax",&boxSetMax,"setMax() sets the max value of the box") ; return box_class; } template static IMATH_NAMESPACE::Box mulM44 (const IMATH_NAMESPACE::Box &b, const Matrix44 &m) { MATH_EXC_ON; return IMATH_NAMESPACE::transform (b, m); } template static const IMATH_NAMESPACE::Box & imulM44 (IMATH_NAMESPACE::Box &b, const Matrix44 &m) { MATH_EXC_ON; b = IMATH_NAMESPACE::transform (b, m); return b; } template class_ > register_Box3() { void (IMATH_NAMESPACE::Box::*extendBy1)(const T&) = &IMATH_NAMESPACE::Box::extendBy; void (IMATH_NAMESPACE::Box::*extendBy2)(const IMATH_NAMESPACE::Box&) = &IMATH_NAMESPACE::Box::extendBy; bool (IMATH_NAMESPACE::Box::*intersects1)(const T&) const = &IMATH_NAMESPACE::Box::intersects; bool (IMATH_NAMESPACE::Box::*intersects2)(const IMATH_NAMESPACE::Box&) const = &IMATH_NAMESPACE::Box::intersects; const char *name = BoxName::value; class_ > box_class(name); box_class .def(init<>("Box() create empty box") ) .def(init("Box(point)create box containing the given point") ) .def(init("Box(point,point) create box continaing min and max") ) .def("__init__", make_constructor(box3TupleConstructor1), "Box(point) where point is a python tuple") .def("__init__", make_constructor(box3TupleConstructor2), "Box(point,point) where point is a python tuple") .def("__init__", make_constructor(boxConstructor)) .def("__init__", make_constructor(boxConstructor)) .def("__init__", make_constructor(boxConstructor)) .def_readwrite("min",&Box::min) .def_readwrite("max",&Box::max) .def(self == self) .def(self != self) .def("__mul__", &mulM44) .def("__mul__", &mulM44) .def("__imul__", &imulM44,return_internal_reference<>()) .def("__imul__", &imulM44,return_internal_reference<>()) .def("min", &boxMin) .def("max", &boxMax) .def("__repr__", &Box3_repr) .def("makeEmpty",&Box::makeEmpty,"makeEmpty() make the box empty") .def("makeInfinite",&Box::makeInfinite,"makeInfinite() make the box cover all space") .def("extendBy",extendBy1,"extendBy(point) extend the box by a point") .def("extendBy",box_extendBy,"extendBy(array) extend the box the values in the array") .def("extendBy",extendBy2,"extendBy(box) extend the box by a box") .def("size",&Box::size,"size() size of the box") .def("center",&Box::center,"center() center of the box") .def("intersects",intersects1,"intersects(point) returns true if the box intersects the given point") .def("intersects",intersects2,"intersects(box) returns true if the box intersects the given box") .def("intersects",box_intersects, "intersects(array) returns an int array where 0 indicates the point is not in the box and 1 indicates that it is") .def("majorAxis",&Box::majorAxis,"majorAxis() major axis of the box") .def("isEmpty",&Box::isEmpty,"isEmpty() returns true if the box is empty") .def("isInfinite",&Box::isInfinite,"isInfinite() returns true if the box covers all space") .def("hasVolume",&Box::hasVolume,"hasVolume() returns true if the box has volume") .def("setMin",&boxSetMin,"setMin() sets the min value of the box") .def("setMax",&boxSetMax,"setMax() sets the max value of the box") ; decoratecopy(box_class); return box_class; } template PYIMATH_EXPORT class_ > register_Box2(); template PYIMATH_EXPORT class_ > register_Box2(); template PYIMATH_EXPORT class_ > register_Box2(); template PYIMATH_EXPORT class_ > register_Box2(); template PYIMATH_EXPORT class_ > register_Box3(); template PYIMATH_EXPORT class_ > register_Box3(); template PYIMATH_EXPORT class_ > register_Box3(); template PYIMATH_EXPORT class_ > register_Box3(); }