2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
9 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
10 #include <boost/python.hpp>
11 #include <boost/python/make_constructor.hpp>
12 #include <boost/format.hpp>
14 #include "PyImathVec.h"
15 #include "PyImathMathExc.h"
16 #include "PyImathPlane.h"
17 #include "PyImathDecorators.h"
18 #include "PyImathExport.h"
21 using namespace boost::python;
22 using namespace IMATH_NAMESPACE;
24 template <class T> struct PlaneName {static const char *value;};
25 template <> const char *PlaneName<float>::value = "Plane3f";
26 template <> const char *PlaneName<double>::value = "Plane3d";
29 static Plane3<T> *Plane3_construct_default()
31 Vec3<T> normal(T (1), T (0), T (0));
32 return new Plane3<T>(normal, T (0));
36 static Plane3<T> *Plane3_plane_construct(const object &planeObj)
39 extract < Plane3<float> > ef (planeObj);
40 extract < Plane3<double> > ed (planeObj);
46 Plane3<float> efp = ef();
48 p->normal = efp.normal;
49 p->distance = efp.distance;
54 Plane3<double> edp = ed();
56 p->normal = edp.normal;
57 p->distance = edp.distance;
62 throw std::invalid_argument ("invalid parameter passed to Plane constructor");
69 static Plane3<T> *Plane3_tuple_constructor1(const tuple &t, T distance)
72 if(t.attr("__len__")() == 3)
75 normal.x = extract<T>(t[0]);
76 normal.y = extract<T>(t[1]);
77 normal.z = extract<T>(t[2]);
79 return new Plane3<T>(normal, distance);
82 throw std::domain_error ("Plane3 expects tuple of length 3");
86 static Plane3<T> *Plane3_tuple_constructor2(const tuple &t0, const tuple &t1)
89 if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3)
91 Vec3<T> point, normal;
92 point.x = extract<T>(t0[0]);
93 point.y = extract<T>(t0[1]);
94 point.z = extract<T>(t0[2]);
96 normal.x = extract<T>(t1[0]);
97 normal.y = extract<T>(t1[1]);
98 normal.z = extract<T>(t1[2]);
100 return new Plane3<T>(point, normal);
103 throw std::domain_error ("Plane3 expects tuples of length 3");
107 static Plane3<T> *Plane3_tuple_constructor3(const tuple &t0, const tuple &t1, const tuple &t2)
110 if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3 && t2.attr("__len__")() == 3)
112 Vec3<T> point0, point1, point2;
113 point0.x = extract<T>(t0[0]);
114 point0.y = extract<T>(t0[1]);
115 point0.z = extract<T>(t0[2]);
117 point1.x = extract<T>(t1[0]);
118 point1.y = extract<T>(t1[1]);
119 point1.z = extract<T>(t1[2]);
121 point2.x = extract<T>(t2[0]);
122 point2.y = extract<T>(t2[1]);
123 point2.z = extract<T>(t2[2]);
125 return new Plane3<T>(point0, point1, point2);
128 throw std::domain_error ("Plane3 expects tuple of length 3");
133 mul (const Plane3<T> &plane, const Matrix44<T> &M)
141 set1 (Plane3<T> &plane, const Vec3<T> &v, T t)
149 set2 (Plane3<T> &plane, const Vec3<T> &v1, const Vec3<T> &v2)
157 set3 (Plane3<T> &plane, const Vec3<T> &v1, const Vec3<T> &v2, const Vec3<T> &v3)
160 plane.set (v1, v2, v3);
164 static std::string Plane3_str(const Plane3<T> &plane)
166 std::stringstream stream;
168 typename return_by_value::apply <Vec3<float> >::type converter;
169 handle<> normH (converter (plane.normal));
170 handle<> normRepr (PYUTIL_OBJECT_REPR (normH.get()));
171 std::string normalReprStr = extract<std::string> (normRepr.get());
173 stream << PlaneName<T>::value << "(" << normalReprStr << ", "
174 << plane.distance << ")";
178 // Non-specialized repr is same as str
180 static std::string Plane3_repr(const Plane3<T> &plane)
182 return Plane3_str(plane);
185 // Specialization for float to full precision
187 std::string Plane3_repr(const Plane3<float> &plane)
189 typename return_by_value::apply <Vec3<float> >::type converter;
191 handle<> normH (converter (plane.normal));
192 handle<> normRepr (PYUTIL_OBJECT_REPR (normH.get()));
193 std::string normalReprStr = extract<std::string> (normRepr.get());
195 return (boost::format("%s(%s, %.9g)")
196 % PlaneName<float>::value
197 % normalReprStr.c_str()
198 % plane.distance).str();
201 // Specialization for double to full precision
203 std::string Plane3_repr(const Plane3<double> &plane)
205 typename return_by_value::apply <Vec3<double> >::type converter;
207 handle<> normH (converter (plane.normal));
208 handle<> normRepr (PYUTIL_OBJECT_REPR (normH.get()));
209 std::string normalReprStr = extract<std::string> (normRepr.get());
211 return (boost::format("%s(%s, %.17g)")
212 % PlaneName<double>::value
213 % normalReprStr.c_str()
214 % plane.distance).str();
220 distance(Plane3<T> &plane)
222 return plane.distance;
227 normal(Plane3<T> &plane)
234 setNormal(Plane3<T> &plane, const Vec3<T> &normal)
237 plane.normal = normal.normalized();
242 setDistance(Plane3<T> &plane, const T &distance)
244 plane.distance = distance;
247 template <class T, class S>
248 static object intersectT(const Plane3<T> &plane, const Line3<S> &line)
256 if(plane.intersectT(l, param))
257 return object(param);
264 intersect2(const Plane3<T> &plane, const Line3<T> &line, Vec3<T> &intersection)
267 return plane.intersect(line, intersection);
270 template <class T, class S>
272 intersect1(const Plane3<T> &plane, const Line3<S> &line)
275 Vec3<T> intersection;
279 if(plane.intersect(l, intersection))
280 return object(intersection);
288 setTuple1(Plane3<T> &plane, const tuple &t, T distance)
291 if(t.attr("__len__")() == 3)
294 normal.x = extract<T>(t[0]);
295 normal.y = extract<T>(t[1]);
296 normal.z = extract<T>(t[2]);
298 plane.set(normal, distance);
301 throw std::domain_error ("Plane3 expects tuple of length 3");
306 setTuple2(Plane3<T> &plane, const tuple &t0, const tuple &t1)
309 if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3)
311 Vec3<T> point, normal;
312 point.x = extract<T>(t0[0]);
313 point.y = extract<T>(t0[1]);
314 point.z = extract<T>(t0[2]);
316 normal.x = extract<T>(t1[0]);
317 normal.y = extract<T>(t1[1]);
318 normal.z = extract<T>(t1[2]);
320 plane.set(point, normal);
323 throw std::domain_error ("Plane3 expects tuples of length 3");
328 setTuple3(Plane3<T> &plane, const tuple &t0, const tuple &t1, const tuple &t2)
331 if(t0.attr("__len__")() == 3 && t1.attr("__len__")() == 3 && t2.attr("__len__")() == 3)
333 Vec3<T> point0, point1, point2;
334 point0.x = extract<T>(t0[0]);
335 point0.y = extract<T>(t0[1]);
336 point0.z = extract<T>(t0[2]);
338 point1.x = extract<T>(t1[0]);
339 point1.y = extract<T>(t1[1]);
340 point1.z = extract<T>(t1[2]);
342 point2.x = extract<T>(t2[0]);
343 point2.y = extract<T>(t2[1]);
344 point2.z = extract<T>(t2[2]);
346 plane.set(point0, point1, point2);
349 throw std::domain_error ("Plane3 expects tuple of length 3");
354 reflectPoint(Plane3<T> &plane, const Vec3<T> &p)
357 return plane.reflectPoint(p);
362 reflectPointTuple(Plane3<T> &plane, const tuple &t)
366 if(t.attr("__len__")() == 3)
368 point.x = extract<T>(t[0]);
369 point.y = extract<T>(t[1]);
370 point.z = extract<T>(t[2]);
372 return plane.reflectPoint(point);
375 throw std::domain_error ("Plane3 expects tuple of length 3");
380 distanceTo(Plane3<T> &plane, const Vec3<T> &v)
383 return plane.distanceTo(v);
388 distanceToTuple(Plane3<T> &plane, const tuple &t)
392 if(t.attr("__len__")() == 3)
394 point.x = extract<T>(t[0]);
395 point.y = extract<T>(t[1]);
396 point.z = extract<T>(t[2]);
398 return plane.distanceTo(point);
401 throw std::domain_error ("Plane3 expects tuple of length 3");
406 reflectVector(Plane3<T> &plane, const Vec3<T> &v)
409 return plane.reflectVector(v);
414 reflectVectorTuple(Plane3<T> &plane, const tuple &t)
418 if(t.attr("__len__")() == 3)
420 point.x = extract<T>(t[0]);
421 point.y = extract<T>(t[1]);
422 point.z = extract<T>(t[2]);
424 return plane.reflectVector(point);
427 throw std::domain_error ("Plane3 expects tuple of length 3");
432 equal(const Plane3<T> &p1, const Plane3<T> &p2)
434 if(p1.normal == p2.normal && p1.distance == p2.distance)
442 notequal(const Plane3<T> &p1, const Plane3<T> &p2)
444 if(p1.normal != p2.normal || p1.distance != p2.distance)
452 negate(const Plane3<T> &plane)
456 p.set(-plane.normal, -plane.distance);
467 const char *name = PlaneName<T>::value;
469 class_< Plane3<T> > plane_class(name);
471 .def("__init__",make_constructor(Plane3_construct_default<T>),"initialize normal to (1,0,0), distance to 0")
472 .def("__init__",make_constructor(Plane3_tuple_constructor1<T>))
473 .def("__init__",make_constructor(Plane3_tuple_constructor2<T>))
474 .def("__init__",make_constructor(Plane3_tuple_constructor3<T>))
475 .def("__init__",make_constructor(Plane3_plane_construct<T>))
476 .def(init<const Vec3<T> &, T>("Plane3(normal, distance) construction"))
477 .def(init<const Vec3<T> &, const Vec3<T> &>("Plane3(point, normal) construction"))
478 .def(init<const Vec3<T> &, const Vec3<T> &, const Vec3<T> &>("Plane3(point1, point2, point3) construction"))
479 .def("__eq__", &equal<T>)
480 .def("__ne__", ¬equal<T>)
481 .def("__mul__", &mul<T>)
482 .def("__neg__", &negate<T>)
483 .def("__str__", &Plane3_str<T>)
484 .def("__repr__", &Plane3_repr<T>)
486 .def_readwrite("normal", &Plane3<T>::normal)
487 .def_readwrite("distance", &Plane3<T>::distance)
489 .def("normal", &normal<T>, "normal()",
490 "pl.normal() -- returns the normal of plane pl")
492 .def("distance", &distance<T>, "distance()",
493 "pl.distance() -- returns the signed distance\n"
494 "of plane pl from the coordinate origin")
496 .def("setNormal", &setNormal<T>, "setNormal()",
497 "pl.setNormal(n) -- sets the normal of plane\n"
498 "pl to n.normalized()")
500 .def("setDistance", &setDistance<T>, "setDistance()",
501 "pl.setDistance(d) -- sets the signed distance\n"
502 "of plane pl from the coordinate origin to d")
504 .def("set", &set1<T>, "set()",
505 "pl.set(n,d) -- sets the normal and the signed\n"
506 " distance of plane pl to n and d\n"
508 "pl.set(p,n) -- sets the normal of plane pl to\n"
509 " n.normalized() and adjusts the distance of\n"
510 " pl from the coordinate origin so that pl\n"
511 " passes through point p\n"
513 "pl.set(p1,p2,p3) -- sets the normal of plane pl\n"
514 " to (p2-p1)%(p3-p1)).normalized(), and adjusts\n"
515 " the distance of pl from the coordinate origin\n"
516 " so that pl passes through points p1, p2 and p3")
518 .def("set", &set2<T>, "set()")
519 .def("set", &set3<T>, "set()")
521 .def("set", &setTuple1<T>, "set()")
522 .def("set", &setTuple2<T>, "set()")
523 .def("set", &setTuple3<T>, "set()")
525 .def("intersect", &intersect2<T>,
526 "pl.intersect(ln, pt) -- returns true if the line intersects\n"
527 "the plane, false if it doesn't. The point where plane\n"
528 "pl and line ln intersect is stored in pt")
530 .def("intersect", &intersect1<T,float>,
531 "pl.intersect(ln) -- returns the point where plane\n"
532 "pl and line ln intersect, or None if pl and ln do\n"
534 .def("intersect", &intersect1<T,double>,
535 "pl.intersect(ln) -- returns the point where plane\n"
536 "pl and line ln intersect, or None if pl and ln do\n"
539 .def("intersectT", &intersectT<T, float>,
540 "pl.intersectT(ln) -- computes the intersection,\n"
541 "i, of plane pl and line ln, and returns t, so that\n"
542 "ln.pos() + t * ln.dir() == i.\n"
543 "If pl and ln do not intersect, pl.intersectT(ln)\n"
546 .def("intersectT", &intersectT<T,double>)
548 .def("distanceTo", &distanceTo<T>, "distanceTo()",
549 "pl.distanceTo(p) -- returns the signed distance\n"
550 "between plane pl and point p (positive if p is\n"
551 "on the side of pl where the pl's normal points)\n")
553 .def("distanceTo", &distanceToTuple<T>)
555 .def("reflectPoint", &reflectPoint<T>, "reflectPoint()",
556 "pl.reflectPoint(p) -- returns the image,\n"
557 "q, of point p after reflection on plane pl:\n"
558 "the distance between p and q is twice the\n"
559 "distance between p and pl, and the line from\n"
560 "p to q is parallel to pl's normal.")
562 .def("reflectPoint", &reflectPointTuple<T>)
564 .def("reflectVector", &reflectVector<T>, "reflectVector()",
565 "pl.reflectVector(v) -- returns the direction\n"
566 "of a ray with direction v after reflection on\n"
568 .def("reflectVector", &reflectVectorTuple<T>)
572 decoratecopy(plane_class);
577 template PYIMATH_EXPORT class_<Plane3<float> > register_Plane<float>();
578 template PYIMATH_EXPORT class_<Plane3<double> > register_Plane<double>();
580 } //namespace PyIMath