/////////////////////////////////////////////////////////////////////////// // // 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 #include namespace PyImath{ using namespace boost::python; using namespace IMATH_NAMESPACE; template struct LineName {static const char *value;}; template <> const char *LineName::value = "Line3f"; template <> const char *LineName::value = "Line3d"; template static Line3 * Line3_construct_default() { Vec3 point1(T (0), T(0), T(0)); Vec3 point2(T (1), T(0), T(0)); return new Line3(point1, point2); } template static Line3 * Line3_tuple_construct(const tuple &t0, const tuple &t1) { Vec3 v0, v1; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3) { v0.x = extract(t0[0]); v0.y = extract(t0[1]); v0.z = extract(t0[2]); v1.x = extract(t1[0]); v1.y = extract(t1[1]); v1.z = extract(t1[2]); return new Line3(v0, v1); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Line3 * Line3_line_construct(const Line3 &line) { Line3 *l = new Line3; l->pos = line.pos; l->dir = line.dir; return l; } template static void set1(Line3 &line, const Vec3 &p0, const Vec3 &p1) { MATH_EXC_ON; line.set (p0, p1); } template static void setTuple(Line3 &line, const tuple &t0, const tuple &t1) { MATH_EXC_ON; Vec3 v0, v1; if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3) { v0.x = extract(t0[0]); v0.y = extract(t0[1]); v0.z = extract(t0[2]); v1.x = extract(t1[0]); v1.y = extract(t1[1]); v1.z = extract(t1[2]); line.set(v0, v1); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Vec3 pointAt(Line3 &line, T t) { MATH_EXC_ON; return line.operator()(t); } template static T distanceTo1(Line3 &line, Vec3 &p) { MATH_EXC_ON; return line.distanceTo(p); } template static T distanceTo2(Line3 &line, Line3 &other) { MATH_EXC_ON; return line.distanceTo(other); } template static T distanceToTuple(Line3 line, const tuple &t) { Vec3 v; if(t.attr("__len__")() == 3) { v.x = extract(t[0]); v.y = extract(t[1]); v.z = extract(t[2]); return line.distanceTo(v); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Vec3 closestPointTo1(Line3 line, const Vec3 &p) { MATH_EXC_ON; return line.closestPointTo(p); } template static Vec3 closestPointTo2(Line3 line, const Line3 &other) { MATH_EXC_ON; return line.closestPointTo(other); } template static Vec3 closestPointToTuple(Line3 line, 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]); return line.closestPointTo(v); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Vec3 getPosition(Line3 &line) { return line.pos; } template static void setPosition(Line3 &line, const Vec3 &pos) { line.pos = pos; } template static void setPositionTuple(Line3 &line, const tuple &t) { Vec3 pos; if(t.attr("__len__")() == 3) { pos.x = extract(t[0]); pos.y = extract(t[1]); pos.z = extract(t[2]); line.pos = pos; } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Vec3 getDirection(Line3 &line) { return line.dir; } template static void setDirection(Line3 &line, const Vec3 &dir) { MATH_EXC_ON; line.dir = dir.normalized(); } template static void setDirectionTuple(Line3 &line, const tuple &t) { MATH_EXC_ON; Vec3 dir; if(t.attr("__len__")() == 3) { dir.x = extract(t[0]); dir.y = extract(t[1]); dir.z = extract(t[2]); line.dir = dir.normalized(); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static void closestPoints1(Line3 &line1, const Line3 &line2, Vec3 &p0, Vec3 &p1) { MATH_EXC_ON; IMATH_NAMESPACE::closestPoints(line1, line2, p0, p1); } template static tuple closestPoints2(Line3 &line1, const Line3 &line2) { MATH_EXC_ON; Vec3 p0, p1; IMATH_NAMESPACE::closestPoints(line1, line2, p0, p1); tuple p0Tuple = make_tuple(p0.x,p0.y,p0.z); tuple p1Tuple = make_tuple(p1.x,p1.y,p1.z); #if !defined(_MSC_VER) || (_MSC_VER <= 1200) tuple t = make_tuple(p0Tuple, p1Tuple); return t; #else list v3; v3.append(p0Tuple); v3.append(p1Tuple); return tuple(v3); #endif } template static Vec3 closestVertex(Line3 &line, const Vec3 &v0, const Vec3 &v1, const Vec3 &v2) { MATH_EXC_ON; return IMATH_NAMESPACE::closestVertex(v0, v1, v2, line); } template static Vec3 closestVertexTuple(Line3 &line, 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 v0, v1, v2; v0.x = extract(t0[0]); v0.y = extract(t0[1]); v0.z = extract(t0[2]); v1.x = extract(t1[0]); v1.y = extract(t1[1]); v1.z = extract(t1[2]); v2.x = extract(t2[0]); v2.y = extract(t2[1]); v2.z = extract(t2[2]); return IMATH_NAMESPACE::closestVertex(v0, v1, v2, line); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static bool intersect1(Line3 &line, const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, Vec3 &pt, Vec3 &barycentric, bool &front) { MATH_EXC_ON; return IMATH_NAMESPACE::intersect(line, v0, v1, v2, pt, barycentric, front); } template static object intersect2(Line3 &line, const Vec3 &v0, const Vec3 &v1, const Vec3 &v2) { MATH_EXC_ON; Vec3 pt, bar; bool front; if(IMATH_NAMESPACE::intersect(line, v0, v1, v2, pt, bar, front)) { tuple t = make_tuple(pt, bar, front); return t; } else { return object(); } } template static tuple intersectTuple(Line3 &line, const tuple &t0, const tuple &t1, const tuple &t2) { if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3 && t2.attr("__len__")() == 3) { Vec3 v0, v1, v2, pt, bar; bool front; v0.x = extract(t0[0]); v0.y = extract(t0[1]); v0.z = extract(t0[2]); v1.x = extract(t1[0]); v1.y = extract(t1[1]); v1.z = extract(t1[2]); v2.x = extract(t2[0]); v2.y = extract(t2[1]); v2.z = extract(t2[2]); if(IMATH_NAMESPACE::intersect(line, v0, v1, v2, pt, bar, front)) { tuple t = make_tuple(pt, bar, front); return t; } else { tuple t; return t; } } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static Vec3 rotatePoint(Line3 &line, const Vec3 &p, const T &r) { MATH_EXC_ON; return IMATH_NAMESPACE::rotatePoint(p, line, r); } template static Vec3 rotatePointTuple(Line3 &line, const tuple &t, const T &r) { MATH_EXC_ON; if(t.attr("__len__")() == 3) { Vec3 p; p.x = extract(t[0]); p.y = extract(t[1]); p.z = extract(t[2]); return IMATH_NAMESPACE::rotatePoint(p, line, r); } else THROW(IEX_NAMESPACE::LogicExc, "Line3 expects tuple of length 3"); } template static std::string Line3_repr(const Line3 &v) { Vec3 v1 = v.pos; Vec3 v2 = v.pos + v.dir; PyObject *v1Obj = V3::wrap (v1); PyObject *v1ReprObj = PyObject_Repr (v1Obj); std::string v1ReprStr = PyString_AsString (v1ReprObj); Py_DECREF (v1ReprObj); Py_DECREF (v1Obj); PyObject *v2Obj = V3::wrap (v2); PyObject *v2ReprObj = PyObject_Repr (v2Obj); std::string v2ReprStr = PyString_AsString (v2ReprObj); Py_DECREF (v2ReprObj); Py_DECREF (v2Obj); std::stringstream stream; stream << LineName::value << "(" << v1ReprStr << ", " << v2ReprStr << ")"; return stream.str(); } template static bool equal(const Line3 &l1, const Line3 &l2) { if(l1.pos == l2.pos && l1.dir == l2.dir) return true; else return false; } template static bool notequal(const Line3 &l1, const Line3 &l2) { if(l1.pos != l2.pos || l1.dir != l2.dir) return true; else return false; } template class_ > register_Line() { const char *name = LineName::value; class_ > line_class(name); line_class .def("__init__", make_constructor(Line3_construct_default), "initialize point to (0,0,0) and direction to (1,0,0)") .def("__init__", make_constructor(Line3_tuple_construct)) .def("__init__", make_constructor(Line3_line_construct)) .def("__init__", make_constructor(Line3_line_construct)) .def(init &, const Vec3 &>("Line3(point1, point2) construction")) .def(init &, const Vec3 &>("Line3(point1, point2) construction")) .def(self * Matrix44()) .def("__eq__", &equal) .def("__ne__", ¬equal) .def_readwrite("pos", &Line3::pos) .def_readwrite("dir", &Line3::dir) .def("pos", &getPosition, "l.pos() -- returns the start point of line l") .def("dir", &getDirection, "l.dir() -- returns the direction of line l\n") .def("setPos", &setPosition, "l.setPos(p) -- sets the start point of line l to p") .def("setPos", &setPositionTuple) .def("setDir", &setDirection, "l.setDir(d) -- sets the direction of line l\n" "to d.normalized().\n") .def("setDir", &setDirectionTuple) .def("set", &set1, "l.set(p1, p2) -- sets the start point\n" "and direction of line l by calling\n" " l.setPos (p1)\n" " l.setDir (p2 - p1)\n") .def("set", &setTuple) .def("pointAt", &pointAt, "l.pointAt(t) -- returns l.pos() + t * l.dir()") .def("distanceTo", &distanceTo1, "l.distanceTo(p) -- returns the distance from\n" " line l to point p\n") .def("distanceTo", &distanceTo2, "l1.distanceTo(l2) -- returns the distance from\n" " line l1 to line l2\n") .def("distanceTo", &distanceToTuple) .def("closestPointTo", &closestPointTo1, "l.closestPointTo(p) -- returns the point on\n" " line l that is closest to point p\n" "\n") .def("closestPointTo", &closestPointToTuple) .def("closestPointTo", &closestPointTo2, "l1.closestPointTo(l2) -- returns the point on\n" " line l1 that is closest to line l2\n") .def("closestPoints", &closestPoints1, "l1.closestPoints(l2,p0,p1)") .def("closestPoints", &closestPoints2, "l1.closestPoints(l2) -- returns a tuple with\n" "two points:\n" " (l1.closestPoint(l2), l2.closestPoint(l1)\n") .def("closestTriangleVertex", &closestVertex, "l.closestTriangleVertex(v0, v1, v2) -- returns\n" "a copy of v0, v1, or v2, depending on which is\n" "closest to line l.\n") .def("closestTriangleVertex", &closestVertexTuple) .def("intersectWithTriangle", &intersect2) .def("intersectWithTriangle", &intersect1, "l.intersectWithTriangle(v0, v1, v2) -- computes the\n" "intersection of line l and triangle (v0, v1, v2).\n" "\n" "If the line and the triangle do not intersect,\n" "None is returned.\n" "" "If the line and the triangle intersect, a tuple\n" "(p, b, f) is returned:\n" "\n" " p intersection point in 3D space\n" "\n" " b intersection point in barycentric coordinates\n" "\n" " f 1 if the line hits the triangle from the\n" " front (((v2-v1) % (v1-v2)) ^ l.dir() < 0),\n" " 0 if the line hits the trianble from the\n" " back\n" "\n") .def("intersectWithTriangle", &intersectTuple) .def("rotatePoint", &rotatePoint, "l.rotatePoint(p,r) -- rotates point p around\n" "line by angle r (in radians), and returns the\n" "result (p is not modified)\n") .def("rotatePoint", &rotatePointTuple) .def("__repr__",&Line3_repr) ; decoratecopy(line_class); return line_class; } template PYIMATH_EXPORT class_ > register_Line(); template PYIMATH_EXPORT class_ > register_Line(); } // namespace PyImath