/////////////////////////////////////////////////////////////////////////// // // 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 namespace PyImath{ using namespace boost::python; using namespace IMATH_NAMESPACE; template struct PlaneName {static const char *value;}; template <> const char *PlaneName::value = "Plane3f"; template <> const char *PlaneName::value = "Plane3d"; template static Plane3 *Plane3_construct_default() { Vec3 normal(T (1), T (0), T (0)); return new Plane3(normal, T (0)); } template static Plane3 *Plane3_plane_construct(const object &planeObj) { MATH_EXC_ON; extract < Plane3 > ef (planeObj); extract < Plane3 > ed (planeObj); Plane3 *p = 0; if (ef.check()) { Plane3 efp = ef(); p = new Plane3; p->normal = efp.normal; p->distance = efp.distance; } else if (ed.check()) { Plane3 edp = ed(); p = new Plane3; p->normal = edp.normal; p->distance = edp.distance; } else { THROW(IEX_NAMESPACE::LogicExc, "invalid parameter passed to Plane constructor"); } return p; } template static Plane3 *Plane3_tuple_constructor1(const tuple &t, T distance) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 normal; normal.x = extract(t[0]); normal.y = extract(t[1]); normal.z = extract(t[2]); return new Plane3(normal, distance); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static Plane3 *Plane3_tuple_constructor2(const tuple &t0, const tuple &t1) { MATH_EXC_ON; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3) { Vec3 point, normal; point.x = extract(t0[0]); point.y = extract(t0[1]); point.z = extract(t0[2]); normal.x = extract(t1[0]); normal.y = extract(t1[1]); normal.z = extract(t1[2]); return new Plane3(point, normal); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuples of length 3"); } template static Plane3 *Plane3_tuple_constructor3(const tuple &t0, const tuple &t1, const tuple &t2) { MATH_EXC_ON; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3 && t2.attr("__len__")() == 3) { Vec3 point0, point1, point2; 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]); point2.x = extract(t2[0]); point2.y = extract(t2[1]); point2.z = extract(t2[2]); return new Plane3(point0, point1, point2); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static Plane3 mul (const Plane3 &plane, const Matrix44 &M) { MATH_EXC_ON; return plane * M; } template static void set1 (Plane3 &plane, const Vec3 &v, T t) { MATH_EXC_ON; plane.set (v, t); } template static void set2 (Plane3 &plane, const Vec3 &v1, const Vec3 &v2) { MATH_EXC_ON; plane.set (v1, v2); } template static void set3 (Plane3 &plane, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3) { MATH_EXC_ON; plane.set (v1, v2, v3); } template static std::string Plane3_str(const Plane3 &plane) { std::stringstream stream; PyObject *normalObj = V3::wrap (plane.normal); PyObject *normalReprObj = PyObject_Repr (normalObj); std::string normalReprStr = PyString_AsString (normalReprObj); Py_DECREF (normalReprObj); Py_DECREF (normalObj); stream << PlaneName::value << "(" << normalReprStr << ", " << plane.distance << ")"; return stream.str(); } // Non-specialized repr is same as str template static std::string Plane3_repr(const Plane3 &plane) { return Plane3_str(plane); } // Specialization for float to full precision template <> std::string Plane3_repr(const Plane3 &plane) { PyObject *normalObj = V3::wrap (plane.normal); PyObject *normalReprObj = PyObject_Repr (normalObj); std::string normalReprStr = PyString_AsString (normalReprObj); Py_DECREF (normalReprObj); Py_DECREF (normalObj); return (boost::format("%s(%s, %.9g)") % PlaneName::value % normalReprStr.c_str() % plane.distance).str(); } // Specialization for double to full precision template <> std::string Plane3_repr(const Plane3 &plane) { PyObject *normalObj = V3::wrap (plane.normal); PyObject *normalReprObj = PyObject_Repr (normalObj); std::string normalReprStr = PyString_AsString (normalReprObj); Py_DECREF (normalReprObj); Py_DECREF (normalObj); return (boost::format("%s(%s, %.17g)") % PlaneName::value % normalReprStr.c_str() % plane.distance).str(); } template static T distance(Plane3 &plane) { return plane.distance; } template static Vec3 normal(Plane3 &plane) { return plane.normal; } template static void setNormal(Plane3 &plane, const Vec3 &normal) { MATH_EXC_ON; plane.normal = normal.normalized(); } template static void setDistance(Plane3 &plane, const T &distance) { plane.distance = distance; } template static object intersectT(const Plane3 &plane, const Line3 &line) { MATH_EXC_ON; T param; Line3 l; l.pos = line.pos; l.dir = line.dir; if(plane.intersectT(l, param)) return object(param); return object(); } template static bool intersect2(const Plane3 &plane, const Line3 &line, Vec3 &intersection) { MATH_EXC_ON; return plane.intersect(line, intersection); } template static object intersect1(const Plane3 &plane, const Line3 &line) { MATH_EXC_ON; Vec3 intersection; Line3 l; l.pos = line.pos; l.dir = line.dir; if(plane.intersect(l, intersection)) return object(intersection); return object(); } template static void setTuple1(Plane3 &plane, const tuple &t, T distance) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 normal; normal.x = extract(t[0]); normal.y = extract(t[1]); normal.z = extract(t[2]); plane.set(normal, distance); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static void setTuple2(Plane3 &plane, const tuple &t0, const tuple &t1) { MATH_EXC_ON; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3) { Vec3 point, normal; point.x = extract(t0[0]); point.y = extract(t0[1]); point.z = extract(t0[2]); normal.x = extract(t1[0]); normal.y = extract(t1[1]); normal.z = extract(t1[2]); plane.set(point, normal); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuples of length 3"); } template static void setTuple3(Plane3 &plane, const tuple &t0, const tuple &t1, const tuple &t2) { MATH_EXC_ON; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3 && t2.attr("__len__")() == 3) { Vec3 point0, point1, point2; 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]); point2.x = extract(t2[0]); point2.y = extract(t2[1]); point2.z = extract(t2[2]); plane.set(point0, point1, point2); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static Vec3 reflectPoint(Plane3 &plane, const Vec3 &p) { MATH_EXC_ON; return plane.reflectPoint(p); } template static Vec3 reflectPointTuple(Plane3 &plane, const tuple &t) { MATH_EXC_ON; Vec3 point; if(t.attr("__len__")() == 3) { point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return plane.reflectPoint(point); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static T distanceTo(Plane3 &plane, const Vec3 &v) { MATH_EXC_ON; return plane.distanceTo(v); } template static T distanceToTuple(Plane3 &plane, const tuple &t) { MATH_EXC_ON; Vec3 point; if(t.attr("__len__")() == 3) { point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return plane.distanceTo(point); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static Vec3 reflectVector(Plane3 &plane, const Vec3 &v) { MATH_EXC_ON; return plane.reflectVector(v); } template static Vec3 reflectVectorTuple(Plane3 &plane, const tuple &t) { MATH_EXC_ON; Vec3 point; if(t.attr("__len__")() == 3) { point.x = extract(t[0]); point.y = extract(t[1]); point.z = extract(t[2]); return plane.reflectVector(point); } else THROW(IEX_NAMESPACE::LogicExc, "Plane3 expects tuple of length 3"); } template static bool equal(const Plane3 &p1, const Plane3 &p2) { if(p1.normal == p2.normal && p1.distance == p2.distance) return true; else return false; } template static bool notequal(const Plane3 &p1, const Plane3 &p2) { if(p1.normal != p2.normal || p1.distance != p2.distance) return true; else return false; } template static Plane3 negate(const Plane3 &plane) { MATH_EXC_ON; Plane3 p; p.set(-plane.normal, -plane.distance); return p; } template class_ > register_Plane() { const char *name = PlaneName::value; class_< Plane3 > plane_class(name); plane_class .def("__init__",make_constructor(Plane3_construct_default),"initialize normal to (1,0,0), distance to 0") .def("__init__",make_constructor(Plane3_tuple_constructor1)) .def("__init__",make_constructor(Plane3_tuple_constructor2)) .def("__init__",make_constructor(Plane3_tuple_constructor3)) .def("__init__",make_constructor(Plane3_plane_construct)) .def(init &, T>("Plane3(normal, distance) construction")) .def(init &, const Vec3 &>("Plane3(point, normal) construction")) .def(init &, const Vec3 &, const Vec3 &>("Plane3(point1, point2, point3) construction")) .def("__eq__", &equal) .def("__ne__", ¬equal) .def("__mul__", &mul) .def("__neg__", &negate) .def("__str__", &Plane3_str) .def("__repr__", &Plane3_repr) .def_readwrite("normal", &Plane3::normal) .def_readwrite("distance", &Plane3::distance) .def("normal", &normal, "normal()", "pl.normal() -- returns the normal of plane pl") .def("distance", &distance, "distance()", "pl.distance() -- returns the signed distance\n" "of plane pl from the coordinate origin") .def("setNormal", &setNormal, "setNormal()", "pl.setNormal(n) -- sets the normal of plane\n" "pl to n.normalized()") .def("setDistance", &setDistance, "setDistance()", "pl.setDistance(d) -- sets the signed distance\n" "of plane pl from the coordinate origin to d") .def("set", &set1, "set()", "pl.set(n,d) -- sets the normal and the signed\n" " distance of plane pl to n and d\n" "\n" "pl.set(p,n) -- sets the normal of plane pl to\n" " n.normalized() and adjusts the distance of\n" " pl from the coordinate origin so that pl\n" " passes through point p\n" "\n" "pl.set(p1,p2,p3) -- sets the normal of plane pl\n" " to (p2-p1)%(p3-p1)).normalized(), and adjusts\n" " the distance of pl from the coordinate origin\n" " so that pl passes through points p1, p2 and p3") .def("set", &set2, "set()") .def("set", &set3, "set()") .def("set", &setTuple1, "set()") .def("set", &setTuple2, "set()") .def("set", &setTuple3, "set()") .def("intersect", &intersect2, "pl.intersect(ln, pt) -- returns true if the line intersects\n" "the plane, false if it doesn't. The point where plane\n" "pl and line ln intersect is stored in pt") .def("intersect", &intersect1, "pl.intersect(ln) -- returns the point where plane\n" "pl and line ln intersect, or None if pl and ln do\n" "not intersect") .def("intersect", &intersect1, "pl.intersect(ln) -- returns the point where plane\n" "pl and line ln intersect, or None if pl and ln do\n" "not intersect") .def("intersectT", &intersectT, "pl.intersectT(ln) -- computes the intersection,\n" "i, of plane pl and line ln, and returns t, so that\n" "ln.pos() + t * ln.dir() == i.\n" "If pl and ln do not intersect, pl.intersectT(ln)\n" "returns None.\n") .def("intersectT", &intersectT) .def("distanceTo", &distanceTo, "distanceTo()", "pl.distanceTo(p) -- returns the signed distance\n" "between plane pl and point p (positive if p is\n" "on the side of pl where the pl's normal points)\n") .def("distanceTo", &distanceToTuple) .def("reflectPoint", &reflectPoint, "reflectPoint()", "pl.reflectPoint(p) -- returns the image,\n" "q, of point p after reflection on plane pl:\n" "the distance between p and q is twice the\n" "distance between p and pl, and the line from\n" "p to q is parallel to pl's normal.") .def("reflectPoint", &reflectPointTuple) .def("reflectVector", &reflectVector, "reflectVector()", "pl.reflectVector(v) -- returns the direction\n" "of a ray with direction v after reflection on\n" "plane pl") .def("reflectVector", &reflectVectorTuple) ; decoratecopy(plane_class); return plane_class; } template PYIMATH_EXPORT class_ > register_Plane(); template PYIMATH_EXPORT class_ > register_Plane(); } //namespace PyIMath