/////////////////////////////////////////////////////////////////////////// // // 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 #include "PyImathDecorators.h" #include "PyImathExport.h" #include #include #include #include #include #include #include #include #include // XXX incomplete array wrapping, docstrings missing namespace PyImath { template<> const char *PyImath::EulerfArray::name() { return "EulerfArray"; } template<> const char *PyImath::EulerdArray::name() { return "EulerdArray"; } } namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template struct EulerName { static const char *value; }; template<> const char *EulerName::value = "Eulerf"; template<> const char *EulerName::value = "Eulerd"; template static std::string nameOfOrder(typename IMATH_NAMESPACE::Euler::Order order) { switch(order) { case IMATH_NAMESPACE::Euler::XYZ: return "EULER_XYZ"; case IMATH_NAMESPACE::Euler::XZY: return "EULER_XZY"; case IMATH_NAMESPACE::Euler::YZX: return "EULER_YZX"; case IMATH_NAMESPACE::Euler::YXZ: return "EULER_YXZ"; case IMATH_NAMESPACE::Euler::ZXY: return "EULER_ZXY"; case IMATH_NAMESPACE::Euler::ZYX: return "EULER_ZYX"; case IMATH_NAMESPACE::Euler::XZX: return "EULER_XZX"; case IMATH_NAMESPACE::Euler::XYX: return "EULER_XYX"; case IMATH_NAMESPACE::Euler::YXY: return "EULER_YXY"; case IMATH_NAMESPACE::Euler::YZY: return "EULER_YZY"; case IMATH_NAMESPACE::Euler::ZYZ: return "EULER_ZYZ"; case IMATH_NAMESPACE::Euler::ZXZ: return "EULER_ZXZ"; case IMATH_NAMESPACE::Euler::XYZr: return "EULER_XYZr"; case IMATH_NAMESPACE::Euler::XZYr: return "EULER_XZYr"; case IMATH_NAMESPACE::Euler::YZXr: return "EULER_YZXr"; case IMATH_NAMESPACE::Euler::YXZr: return "EULER_YXZr"; case IMATH_NAMESPACE::Euler::ZXYr: return "EULER_ZXYr"; case IMATH_NAMESPACE::Euler::ZYXr: return "EULER_ZYXr"; case IMATH_NAMESPACE::Euler::XZXr: return "EULER_XZXr"; case IMATH_NAMESPACE::Euler::XYXr: return "EULER_XYXr"; case IMATH_NAMESPACE::Euler::YXYr: return "EULER_YXYr"; case IMATH_NAMESPACE::Euler::YZYr: return "EULER_YZYr"; case IMATH_NAMESPACE::Euler::ZYZr: return "EULER_ZYZr"; case IMATH_NAMESPACE::Euler::ZXZr: return "EULER_ZXZr"; } return ""; } template static std::string Euler_str(const Euler &e) { std::stringstream stream; stream << EulerName::value << "(" << e.x << ", " << e.y << ", " << e.z << ", " << nameOfOrder (e.order()) << ")"; return stream.str(); } // Non-specialized repr is same as str template static std::string Euler_repr(const Euler &e) { return Euler_str(e); } // Specialization for float to full precision template <> std::string Euler_repr(const Euler &e) { return (boost::format("%s(%.9g, %.9g, %.9g, %s)") % EulerName::value % e.x % e.y % e.z % nameOfOrder(e.order()).c_str()).str(); } // Specialization for double to full precision template <> std::string Euler_repr(const Euler &e) { return (boost::format("%s(%.17g, %.17g, %.17g, %s)") % EulerName::value % e.x % e.y % e.z % nameOfOrder(e.order()).c_str()).str(); } template static bool equal(const Euler &e0, const Euler &e1) { if(e0.x == e1.x && e0.y == e1.y && e0.z == e1.z && (e0.order())==(e1.order())) return true; else return false; } template static bool notequal(const Euler &e0, const Euler &e1) { if(e0.x != e1.x || e0.y != e1.y || e0.z != e1.z || (e0.order()) != (e1.order())) { return true; } else return false; } template static IMATH_NAMESPACE::Vec3 getAngleOrder(Euler &euler) { int i, j, k; euler.angleOrder(i, j, k); return IMATH_NAMESPACE::Vec3 (i, j, k); } template static void setXYZTuple(Euler &euler, const tuple &t) { MATH_EXC_ON; Vec3 v; if(t.attr("__len__")() == 3) { v.x = extract(t[0]); v.y = extract(t[1]); v.z = extract(t[2]); euler.setXYZVector(v); } else THROW(IEX_NAMESPACE::LogicExc, "Color3 expects tuple of length 3"); } // needed to convert Eulerf::Order to Euler::Order template static typename Euler::Order interpretOrder(typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = Euler::XYZ; switch(order) { case IMATH_NAMESPACE::Eulerf::XYZ: { o = Euler::XYZ; }break; case IMATH_NAMESPACE::Eulerf::XZY: { o = Euler::XZY; }break; case IMATH_NAMESPACE::Eulerf::YZX: { o = Euler::YZX; }break; case IMATH_NAMESPACE::Eulerf::YXZ: { o = Euler::YXZ; }break; case IMATH_NAMESPACE::Eulerf::ZXY: { o = Euler::ZXY; }break; case IMATH_NAMESPACE::Eulerf::ZYX: { o = Euler::ZYX; }break; case IMATH_NAMESPACE::Eulerf::XZX: { o = Euler::XZX; }break; case IMATH_NAMESPACE::Eulerf::XYX: { o = Euler::XYX; }break; case IMATH_NAMESPACE::Eulerf::YXY: { o = Euler::YXY; }break; case IMATH_NAMESPACE::Eulerf::YZY: { o = Euler::YZY; }break; case IMATH_NAMESPACE::Eulerf::ZYZ: { o = Euler::ZYZ; }break; case IMATH_NAMESPACE::Eulerf::ZXZ: { o = Euler::ZXZ; }break; case IMATH_NAMESPACE::Eulerf::XYZr: { o = Euler::XYZr; }break; case IMATH_NAMESPACE::Eulerf::XZYr: { o = Euler::XZYr; }break; case IMATH_NAMESPACE::Eulerf::YZXr: { o = Euler::YZXr; }break; case IMATH_NAMESPACE::Eulerf::YXZr: { o = Euler::YXZr; }break; case IMATH_NAMESPACE::Eulerf::ZXYr: { o = Euler::ZXYr; }break; case IMATH_NAMESPACE::Eulerf::ZYXr: { o = Euler::ZYXr; }break; case IMATH_NAMESPACE::Eulerf::XZXr: { o = Euler::XZXr; }break; case IMATH_NAMESPACE::Eulerf::XYXr: { o = Euler::XYXr; }break; case IMATH_NAMESPACE::Eulerf::YXYr: { o = Euler::YXYr; }break; case IMATH_NAMESPACE::Eulerf::YZYr: { o = Euler::YZYr; }break; case IMATH_NAMESPACE::Eulerf::ZYZr: { o = Euler::ZYZr; }break; case IMATH_NAMESPACE::Eulerf::ZXZr: { o = Euler::ZXZr; }break; } return o; } // needed to convert Eulerf::Axis to Euler::Axis template static typename Euler::Axis interpretAxis(typename IMATH_NAMESPACE::Eulerf::Axis axis) { if (axis == IMATH_NAMESPACE::Eulerf::X) return Euler::X; else if (axis == IMATH_NAMESPACE::Eulerf::Y) return Euler::Y; else return Euler::Z; } template static Euler * eulerConstructor1(const Vec3 &v, typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); return new Euler(v, o); } template static Euler * eulerConstructor1a(const Vec3 &v) { return eulerConstructor1 (v, IMATH_NAMESPACE::Eulerf::Default); } template static Euler * eulerConstructor1b(const Vec3 &v, int iorder) { typename Euler::Order o = typename Euler::Order (iorder); return new Euler(v, o); } template static Euler * eulerConstructor2(T i, T j, T k, typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); return new Euler(i, j, k, o); } template static Euler * eulerConstructor2a(T i, T j, T k) { return eulerConstructor2 (i, j, k, IMATH_NAMESPACE::Eulerf::Default); } template static Euler * eulerConstructor2b(T i, T j, T k, int iorder) { typename Euler::Order o = typename Euler::Order (iorder); return new Euler(i, j, k, o); } template static Euler * eulerConstructor3(const Matrix33 &mat, typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); return new Euler(mat, o); } template static Euler * eulerConstructor3a(const Matrix33 &mat) { return eulerConstructor3 (mat, IMATH_NAMESPACE::Eulerf::Default); } template static Euler * eulerConstructor3b(const Matrix33 &mat, int iorder) { typename Euler::Order o = typename Euler::Order (iorder); return new Euler(mat, o); } template static Euler * eulerConstructor4(const Matrix44 &mat, typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); return new Euler(mat, o); } template static Euler * eulerConstructor4a(const Matrix44 &mat) { return eulerConstructor4 (mat, IMATH_NAMESPACE::Eulerf::Default); } template static Euler * eulerConstructor4b(const Matrix44 &mat, int iorder) { typename Euler::Order o = typename Euler::Order (iorder); return new Euler(mat, o); } template static Euler * eulerConstructor5(typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); return new Euler(o); } template static Euler * eulerConstructor5a() { typename Euler::Order o = interpretOrder(IMATH_NAMESPACE::Eulerf::Default); return new Euler(o); } template static Euler * eulerConstructor5b(int iorder) { typename Euler::Order o = typename Euler::Order (iorder); return new Euler(o); } template static Euler * eulerConstructor6(T x, T y, T z) { return new Euler(Vec3(x,y,z)); } template static Euler * eulerConstructor7(const Quat &quat, typename IMATH_NAMESPACE::Eulerf::Order order) { Euler *e = eulerConstructor5(order); e->extract(quat); return e; } template static Euler * eulerConstructor7a(const Quat &quat) { return eulerConstructor7(quat, IMATH_NAMESPACE::Eulerf::Default); } template static Euler * eulerConstructor7b(const Quat &quat, int iorder) { Euler *e = eulerConstructor5b(iorder); e->extract(quat); return e; } template static Euler * eulerConversionConstructor(const Euler &euler) { MATH_EXC_ON; Euler *e = new Euler; *e = euler; return e; } template static void eulerMakeNear(Euler &euler, Euler &target) { MATH_EXC_ON; euler.makeNear (target); } template static void eulerSetOrder(Euler &euler, typename IMATH_NAMESPACE::Eulerf::Order order) { typename Euler::Order o = interpretOrder(order); euler.setOrder (o); } template static void eulerSet(Euler &euler, IMATH_NAMESPACE::Eulerf::Axis axis, int relative, int parityEven, int firstRepeats) { MATH_EXC_ON; typename Euler::Axis a = interpretAxis(axis); euler.set (a, relative, parityEven, firstRepeats); } template static void extract1(Euler &euler, const Matrix33 &m) { MATH_EXC_ON; euler.extract(m); } template static void extract2(Euler &euler, const Matrix44 &m) { MATH_EXC_ON; euler.extract(m); } template static void extract3(Euler &euler, const Quat &q) { MATH_EXC_ON; euler.extract(q); } template static Matrix33 toMatrix33(Euler &euler) { MATH_EXC_ON; return euler.toMatrix33(); } template static Matrix44 toMatrix44(Euler &euler) { MATH_EXC_ON; return euler.toMatrix44(); } template static Quat toQuat(Euler &euler) { MATH_EXC_ON; return euler.toQuat(); } template static Vec3 toXYZVector(Euler &euler) { MATH_EXC_ON; return euler.toXYZVector(); } template class_,bases > > register_Euler() { class_,bases > > euler_class(EulerName::value,EulerName::value,init >("copy construction")); euler_class .def(init<>("imath Euler default construction")) .def("__init__", make_constructor(eulerConstructor1)) .def("__init__", make_constructor(eulerConstructor1a)) .def("__init__", make_constructor(eulerConstructor1b)) .def("__init__", make_constructor(eulerConstructor2)) .def("__init__", make_constructor(eulerConstructor2a)) .def("__init__", make_constructor(eulerConstructor2b)) .def("__init__", make_constructor(eulerConstructor3), "Euler-from-matrix construction assumes, but does\n" "not verify, that the matrix includes no shear or\n" "non-uniform scaling. If necessary, you can fix\n" "the matrix by calling the removeScalingAndShear()\n" "function.\n") .def("__init__", make_constructor(eulerConstructor3a)) .def("__init__", make_constructor(eulerConstructor3b)) .def("__init__", make_constructor(eulerConstructor4)) .def("__init__", make_constructor(eulerConstructor4a)) .def("__init__", make_constructor(eulerConstructor4b)) .def("__init__", make_constructor(eulerConstructor5)) .def("__init__", make_constructor(eulerConstructor5a)) .def("__init__", make_constructor(eulerConstructor5b)) .def("__init__", make_constructor(eulerConstructor6)) .def("__init__", make_constructor(eulerConstructor7)) .def("__init__", make_constructor(eulerConstructor7a)) .def("__init__", make_constructor(eulerConstructor7b)) .def("__init__", make_constructor(eulerConversionConstructor)) .def("__init__", make_constructor(eulerConversionConstructor)) .def("angleOrder", &getAngleOrder, "angleOrder() set the angle order") .def("frameStatic", &Euler::frameStatic, "e.frameStatic() -- returns true if the angles of e\n" "are measured relative to a set of fixed axes,\n" "or false if the angles of e are measured relative to\n" "each other\n") .def("initialAxis", &Euler::initialAxis, "e.initialAxis() -- returns the initial rotation\n" "axis of e (EULER_X_AXIS, EULER_Y_AXIS, EULER_Z_AXIS)") .def("initialRepeated", &Euler::initialRepeated, "e.initialRepeated() -- returns 1 if the initial\n" "rotation axis of e is repeated (for example,\n" "e.order() == EULER_XYX); returns 0 if the initial\n" "rotation axis is not repeated.\n") .def("makeNear", &eulerMakeNear, "e.makeNear(t) -- adjusts Euler e so that it\n" "represents the same rotation as before, but the\n" "individual angles of e differ from the angles of\n" "t by as little as possible.\n" "This method might not make sense if e.order()\n" "and t.order() are different\n") .def("order", &Euler::order, "e.order() -- returns the rotation order in e\n" "(EULER_XYZ, EULER_XZY, ...)") .def("parityEven", &Euler::parityEven, "e.parityEven() -- returns the parity of the\n" "axis permutation of e\n") .def("set", &eulerSet, "e.set(i,r,p,f) -- sets the rotation order in e\n" "according to the following flags:\n" "\n" " i initial axis (EULER_X_AXIS,\n" " EULER_Y_AXIS or EULER_Z_AXIS)\n" "\n" " r rotation angles are measured relative\n" " to each other (r == 1), or relative to a\n" " set of fixed axes (r == 0)\n" "\n" " p parity of axis permutation is even (r == 1)\n" " or odd (r == 0)\n" "\n" " f first rotation axis is repeated (f == 1)\n" " or not repeated (f == 0)\n") .def("setOrder", &eulerSetOrder, "e.setOrder(o) -- sets the rotation order in e\n" "to o (EULER_XYZ, EULER_XZY, ...)") .def("setXYZVector", &Euler::setXYZVector, "e.setXYZVector(v) -- sets the three rotation\n" "angles in e to v[0], v[1], v[2]") .def("setXYZVector", &setXYZTuple) .def("extract", &extract1, "e.extract(m) -- extracts the rotation component\n" "from 3x3 matrix m and stores the result in e.\n" "Assumes that m does not contain shear or non-\n" "uniform scaling. If necessary, you can fix m\n" "by calling m.removeScalingAndShear().") .def("extract", &extract2, "e.extract(m) -- extracts the rotation component\n" "from 4x4 matrix m and stores the result in e.\n" "Assumes that m does not contain shear or non-\n" "uniform scaling. If necessary, you can fix m\n" "by calling m.removeScalingAndShear().") .def("extract", &extract3, "e.extract(q) -- extracts the rotation component\n" "from quaternion q and stores the result in e") .def("toMatrix33", &toMatrix33, "e.toMatrix33() -- converts e into a 3x3 matrix\n") .def("toMatrix44", &toMatrix44, "e.toMatrix44() -- converts e into a 4x4 matrix\n") .def("toQuat", &toQuat, "e.toQuat() -- converts e into a quaternion\n") .def("toXYZVector", &toXYZVector, "e.toXYZVector() -- converts e into an XYZ\n" "rotation vector") .def("__str__", &Euler_str) .def("__repr__", &Euler_repr) .def("__eq__", &equal) .def("__ne__", ¬equal) ; // fill in the Euler scope { scope euler_scope(euler_class); enum_::Order> euler_order("Order"); euler_order .value("XYZ",Euler::XYZ) .value("XZY",Euler::XZY) .value("YZX",Euler::YZX) .value("YXZ",Euler::YXZ) .value("ZXY",Euler::ZXY) .value("ZYX",Euler::ZYX) .value("XZX",Euler::XZX) .value("XYX",Euler::XYX) .value("YXY",Euler::YXY) .value("YZY",Euler::YZY) .value("ZYZ",Euler::ZYZ) .value("ZXZ",Euler::ZXZ) .value("XYZr",Euler::XYZr) .value("XZYr",Euler::XZYr) .value("YZXr",Euler::YZXr) .value("YXZr",Euler::YXZr) .value("ZXYr",Euler::ZXYr) .value("ZYXr",Euler::ZYXr) .value("XZXr",Euler::XZXr) .value("XYXr",Euler::XYXr) .value("YXYr",Euler::YXYr) .value("YZYr",Euler::YZYr) .value("ZYZr",Euler::ZYZr) .value("ZXZr",Euler::ZXZr) // don't export these, they're not really part of the public interface //.value("Legal",Euler::Legal) //.value("Min",Euler::Min) //.value("Max",Euler::Max) // handle Default seperately since boost sets up a 1-1 mapping for enum values //.value("Default",Euler::Default) .export_values() ; // just set it to the XYZ value manually euler_scope.attr("Default") = euler_scope.attr("XYZ"); enum_::Axis>("Axis") .value("X",Euler::X) .value("Y",Euler::Y) .value("Z",Euler::Z) .export_values() ; enum_::InputLayout>("InputLayout") .value("XYZLayout",Euler::XYZLayout) .value("IJKLayout",Euler::IJKLayout) .export_values() ; } decoratecopy(euler_class); return euler_class; } // XXX fixme - template this // really this should get generated automatically... /* template static FixedArray EulerArray_get(FixedArray > &qa) { return FixedArray( &(qa[0].r)+index, qa.len(), 4*qa.stride()); } */ template static FixedArray > * EulerArray_eulerConstructor7a(const FixedArray > &q) { MATH_EXC_ON; size_t len = q.len(); FixedArray >* result = new FixedArray >(len); for (size_t i = 0; i < len; ++i) { (*result)[i].extract(q[i]); } return result; } template class_ > > register_EulerArray() { class_ > > eulerArray_class = FixedArray >::register_("Fixed length array of IMATH_NAMESPACE::Euler"); eulerArray_class //.add_property("x",&EulerArray_get) //.add_property("y",&EulerArray_get) //.add_property("z",&EulerArray_get) .def("__init__", make_constructor(EulerArray_eulerConstructor7a)) ; add_comparison_functions(eulerArray_class); PyImath::add_explicit_construction_from_type >(eulerArray_class); PyImath::add_explicit_construction_from_type >(eulerArray_class); return eulerArray_class; } template PYIMATH_EXPORT class_,bases > > register_Euler(); template PYIMATH_EXPORT class_,bases > > register_Euler(); template PYIMATH_EXPORT class_ > > register_EulerArray(); template PYIMATH_EXPORT class_ > > register_EulerArray(); } namespace PyImath { template<> PYIMATH_EXPORT IMATH_NAMESPACE::Euler FixedArrayDefaultValue >::value() { return IMATH_NAMESPACE::Euler(); } template<> PYIMATH_EXPORT IMATH_NAMESPACE::Euler FixedArrayDefaultValue >::value() { return IMATH_NAMESPACE::Euler(); } }