1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 // clang-format off
7 
8 #ifndef _PyImathVec3Impl_h_
9 #define _PyImathVec3Impl_h_
10 
11 //
12 // This .C file was turned into a header file so that instantiations
13 // of the various V3* types can be spread across multiple files in
14 // order to work around MSVC limitations.
15 //
16 
17 #include <Python.h>
18 #include <boost/python.hpp>
19 #include <boost/python/make_constructor.hpp>
20 #include <boost/format.hpp>
21 #include <ImathVec.h>
22 #include <ImathVecAlgo.h>
23 #include "PyImath.h"
24 #include "PyImathMathExc.h"
25 #include "PyImathVec.h"
26 #include "PyImathDecorators.h"
27 
28 namespace PyImath {
29 using namespace boost::python;
30 using namespace IMATH_NAMESPACE;
31 
32 template <class T> struct Vec3Name      { static const char *value(); };
33 
34 // create a new default constructor that initializes Vec3<T> to zero.
35 template <class T>
Vec3_construct_default()36 static Vec3<T> * Vec3_construct_default()
37 {
38     return new Vec3<T>(T(0),T(0),T(0));
39 }
40 
41 template <class T>
Vec3_object_constructor1(const object & obj)42 static Vec3<T> * Vec3_object_constructor1(const object &obj)
43 {
44     Vec3<T> w;
45     extract<Vec3<int> >     e1(obj);
46     extract<Vec3<float> >   e2(obj);
47     extract<Vec3<double> >  e3(obj);
48     extract<tuple>          e4(obj);
49     extract<double>         e5(obj);
50     extract<list>           e6(obj);
51 
52     if(e1.check())      { w = e1(); }
53     else if(e2.check()) { w = e2(); }
54     else if(e3.check()) { w = e3(); }
55     else if(e4.check())
56     {
57         tuple t = e4();
58         if(t.attr("__len__")() == 3)
59         {
60             w.x = extract<T>(t[0]);
61             w.y = extract<T>(t[1]);
62             w.z = extract<T>(t[2]);
63         }
64         else
65             throw std::invalid_argument ("tuple must have length of 3");
66 
67     }
68     else if(e5.check()) { T a = e5(); w.setValue(a, a, a); }
69     else if(e6.check())
70     {
71         list l = e6();
72         if(l.attr("__len__")() == 3)
73         {
74             w.x = extract<T>(l[0]);
75             w.y = extract<T>(l[1]);
76             w.z = extract<T>(l[2]);
77         }
78         else
79             throw std::invalid_argument ("list must have length of 3");
80     }
81     else
82         throw std::invalid_argument ("invalid parameters passed to Vec3 constructor");
83 
84     Vec3<T> *v = new Vec3<T>;
85     *v = w;
86 
87     return v;
88 
89 }
90 
91 template <class T>
Vec3_object_constructor2(const object & obj1,const object & obj2,const object & obj3)92 static Vec3<T> * Vec3_object_constructor2(const object &obj1, const object &obj2, const object &obj3)
93 {
94     extract<double>    e1(obj1);
95     extract<double>    e2(obj2);
96     extract<double>    e3(obj3);
97     Vec3<T> *v = new Vec3<T>;
98 
99     if(e1.check()) { v->x = e1();}
100     else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); }
101 
102     if(e2.check()) { v->y = e2();}
103     else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); }
104 
105     if(e3.check()) { v->z = e3();}
106     else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); }
107 
108     return v;
109 }
110 
111 
112 
113 // Implementations of str and repr are same here,
114 // but we'll specialize repr for float and double to make them exact.
115 template <class T>
Vec3_str(const Vec3<T> & v)116 static std::string Vec3_str(const Vec3<T> &v)
117 {
118     std::stringstream stream;
119     stream << Vec3Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ")";
120     return stream.str();
121 }
122 template <class T>
Vec3_repr(const Vec3<T> & v)123 static std::string Vec3_repr(const Vec3<T> &v)
124 {
125     std::stringstream stream;
126     stream << Vec3Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ")";
127     return stream.str();
128 }
129 
130 template <class T>
131 static IMATH_NAMESPACE::Vec3<T>
Vec3_cross(const IMATH_NAMESPACE::Vec3<T> & v,const IMATH_NAMESPACE::Vec3<T> & other)132 Vec3_cross(const IMATH_NAMESPACE::Vec3<T> &v, const IMATH_NAMESPACE::Vec3<T> &other)
133 {
134     MATH_EXC_ON;
135     return v.cross(other);
136 }
137 
138 template <class T>
139 static FixedArray<IMATH_NAMESPACE::Vec3<T> >
Vec3_cross_Vec3Array(const IMATH_NAMESPACE::Vec3<T> & va,const FixedArray<IMATH_NAMESPACE::Vec3<T>> & vb)140 Vec3_cross_Vec3Array(const IMATH_NAMESPACE::Vec3<T> &va, const FixedArray<IMATH_NAMESPACE::Vec3<T> > &vb)
141 {
142     MATH_EXC_ON;
143     size_t len = vb.len();
144     FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len);
145     for (size_t i = 0; i < len; ++i)
146         f[i] = va.cross(vb[i]);
147     return f;
148 }
149 
150 template <class T>
151 static T
Vec3_dot(const IMATH_NAMESPACE::Vec3<T> & v,const IMATH_NAMESPACE::Vec3<T> & other)152 Vec3_dot(const IMATH_NAMESPACE::Vec3<T> &v, const IMATH_NAMESPACE::Vec3<T> &other)
153 {
154     MATH_EXC_ON;
155     return v.dot(other);
156 }
157 
158 template <class T>
159 static FixedArray<T>
Vec3_dot_Vec3Array(const IMATH_NAMESPACE::Vec3<T> & va,const FixedArray<IMATH_NAMESPACE::Vec3<T>> & vb)160 Vec3_dot_Vec3Array(const IMATH_NAMESPACE::Vec3<T> &va, const FixedArray<IMATH_NAMESPACE::Vec3<T> > &vb)
161 {
162     MATH_EXC_ON;
163     size_t len = vb.len();
164     FixedArray<T> f(len);
165     for (size_t i = 0; i < len; ++i)
166         f[i] = va.dot(vb[i]);
167     return f;
168 }
169 
170 template <class T>
171 static T
Vec3_length(const IMATH_NAMESPACE::Vec3<T> & v)172 Vec3_length(const IMATH_NAMESPACE::Vec3<T> &v)
173 {
174     MATH_EXC_ON;
175     return v.length();
176 }
177 
178 template <class T>
179 static T
Vec3_length2(const IMATH_NAMESPACE::Vec3<T> & v)180 Vec3_length2(const IMATH_NAMESPACE::Vec3<T> &v)
181 {
182     MATH_EXC_ON;
183     return v.length2();
184 }
185 
186 template <class T>
187 static const Vec3<T> &
Vec3_normalize(IMATH_NAMESPACE::Vec3<T> & v)188 Vec3_normalize(IMATH_NAMESPACE::Vec3<T> &v)
189 {
190     MATH_EXC_ON;
191     return v.normalize();
192 }
193 
194 template <class T>
195 static const Vec3<T> &
Vec3_normalizeExc(IMATH_NAMESPACE::Vec3<T> & v)196 Vec3_normalizeExc(IMATH_NAMESPACE::Vec3<T> &v)
197 {
198     MATH_EXC_ON;
199     return v.normalizeExc();
200 }
201 
202 template <class T>
203 static const Vec3<T> &
Vec3_normalizeNonNull(IMATH_NAMESPACE::Vec3<T> & v)204 Vec3_normalizeNonNull(IMATH_NAMESPACE::Vec3<T> &v)
205 {
206     MATH_EXC_ON;
207     return v.normalizeNonNull();
208 }
209 
210 template <class T>
211 static Vec3<T>
Vec3_normalized(const IMATH_NAMESPACE::Vec3<T> & v)212 Vec3_normalized(const IMATH_NAMESPACE::Vec3<T> &v)
213 {
214     MATH_EXC_ON;
215     return v.normalized();
216 }
217 
218 template <class T>
219 static Vec3<T>
Vec3_normalizedExc(const IMATH_NAMESPACE::Vec3<T> & v)220 Vec3_normalizedExc(const IMATH_NAMESPACE::Vec3<T> &v)
221 {
222     MATH_EXC_ON;
223     return v.normalizedExc();
224 }
225 
226 template <class T>
227 static Vec3<T>
Vec3_normalizedNonNull(const IMATH_NAMESPACE::Vec3<T> & v)228 Vec3_normalizedNonNull(const IMATH_NAMESPACE::Vec3<T> &v)
229 {
230     MATH_EXC_ON;
231     return v.normalizedNonNull();
232 }
233 
234 template <class T>
235 static Vec3<T>
closestVertex(Vec3<T> & p,const Vec3<T> & v0,const Vec3<T> & v1,const Vec3<T> & v2)236 closestVertex(Vec3<T> &p, const Vec3<T> &v0, const Vec3<T> &v1, const Vec3<T> &v2)
237 {
238     MATH_EXC_ON;
239     return IMATH_NAMESPACE::closestVertex(v0, v1, v2, p);
240 }
241 
242 template <class T>
243 static const Vec3<T> &
Vec3_negate(IMATH_NAMESPACE::Vec3<T> & v)244 Vec3_negate(IMATH_NAMESPACE::Vec3<T> &v)
245 {
246     MATH_EXC_ON;
247     return v.negate();
248 }
249 
250 template <class T>
251 static Vec3<T>
orthogonal(const Vec3<T> & v,const Vec3<T> & v0)252 orthogonal(const Vec3<T> &v, const Vec3<T> &v0)
253 {
254     MATH_EXC_ON;
255     return IMATH_NAMESPACE::orthogonal(v, v0);
256 }
257 
258 template <class T>
259 static Vec3<T>
project(const Vec3<T> & v,const Vec3<T> & v0)260 project(const Vec3<T> &v, const Vec3<T> &v0)
261 {
262     MATH_EXC_ON;
263     return IMATH_NAMESPACE::project(v0, v);
264 }
265 
266 template <class T>
267 static Vec3<T>
reflect(const Vec3<T> & v,const Vec3<T> & v0)268 reflect(const Vec3<T> &v, const Vec3<T> &v0)
269 {
270     MATH_EXC_ON;
271     return IMATH_NAMESPACE::reflect(v, v0);
272 }
273 
274 template <class T>
275 static void
setValue(Vec3<T> & v,T a,T b,T c)276 setValue(Vec3<T> &v, T a, T b, T c)
277 {
278     v.x = a;
279     v.y = b;
280     v.z = c;
281 }
282 
283 template <class T>
284 static Vec3<T>
Vec3_add(const Vec3<T> & v,const Vec3<T> & w)285 Vec3_add (const Vec3<T> &v, const Vec3<T> &w)
286 {
287     MATH_EXC_ON;
288     return v + w;
289 }
290 
291 template <class T>
292 static Vec3<T>
Vec3_sub(const Vec3<T> & v,const Vec3<T> & w)293 Vec3_sub (const Vec3<T> &v, const Vec3<T> &w)
294 {
295     MATH_EXC_ON;
296     return v - w;
297 }
298 
299 template <class T>
300 static Vec3<T>
Vec3_neg(const Vec3<T> & v)301 Vec3_neg (const Vec3<T> &v)
302 {
303     MATH_EXC_ON;
304     return -v;
305 }
306 
307 template <class T, class U>
308 static Vec3<T>
Vec3_mul(const Vec3<T> & v,Vec3<U> & w)309 Vec3_mul (const Vec3<T> &v, Vec3<U> &w)
310 {
311     MATH_EXC_ON;
312     Vec3<T> w2 (w);
313     return v * w2;
314 }
315 
316 template <class T>
317 static Vec3<T>
Vec3_mulT(const Vec3<T> & v,T t)318 Vec3_mulT (const Vec3<T> &v, T t)
319 {
320     MATH_EXC_ON;
321     return v * t;
322 }
323 
324 template <class T>
325 static FixedArray<IMATH_NAMESPACE::Vec3<T> >
Vec3_mulTArray(const Vec3<T> & v,const FixedArray<T> & t)326 Vec3_mulTArray (const Vec3<T> &v, const FixedArray<T> &t)
327 {
328     MATH_EXC_ON;
329     size_t len = t.len();
330     FixedArray<IMATH_NAMESPACE::Vec3<T> > retval(len);
331     for (size_t i=0; i<len; ++i) retval[i] = v*t[i];
332     return retval;
333 }
334 
335 template <class T>
336 static FixedArray<IMATH_NAMESPACE::Vec3<T> >
Vec3_rmulTArray(const Vec3<T> & v,const FixedArray<T> & t)337 Vec3_rmulTArray (const Vec3<T> &v, const FixedArray<T> &t)
338 {
339     return Vec3_mulTArray(v,t);
340 }
341 
342 template <class T,class S>
343 static Vec3<T>
Vec3_div(Vec3<T> & v,Vec3<S> & w)344 Vec3_div (Vec3<T> &v, Vec3<S> &w)
345 {
346     MATH_EXC_ON;
347     return v / w;
348 }
349 
350 template <class T>
351 static Vec3<T>
Vec3_rmulT(Vec3<T> & v,T t)352 Vec3_rmulT (Vec3<T> &v, T t)
353 {
354     MATH_EXC_ON;
355     return t * v;
356 }
357 
358 template <class T, class U>
359 static const Vec3<T> &
Vec3_imulV(Vec3<T> & v,const Vec3<U> & w)360 Vec3_imulV(Vec3<T> &v, const Vec3<U> &w)
361 {
362     MATH_EXC_ON;
363     return v *= w;
364 }
365 
366 template <class T>
367 static const Vec3<T> &
Vec3_imulT(IMATH_NAMESPACE::Vec3<T> & v,T t)368 Vec3_imulT(IMATH_NAMESPACE::Vec3<T> &v, T t)
369 {
370     MATH_EXC_ON;
371     return v *= t;
372 }
373 
374 template <class T, class U>
375 static Vec3<T>
Vec3_mulM33(Vec3<T> & v,const Matrix33<U> & m)376 Vec3_mulM33 (Vec3<T> &v, const Matrix33<U> &m)
377 {
378     MATH_EXC_ON;
379     return v * m;
380 }
381 
382 template <class T, class U>
383 static Vec3<T>
Vec3_mulM44(Vec3<T> & v,const Matrix44<U> & m)384 Vec3_mulM44 (Vec3<T> &v, const Matrix44<U> &m)
385 {
386     MATH_EXC_ON;
387     return v * m;
388 }
389 
390 template <class T>
391 static const Vec3<T> &
Vec3_idivObj(IMATH_NAMESPACE::Vec3<T> & v,const object & o)392 Vec3_idivObj(IMATH_NAMESPACE::Vec3<T> &v, const object &o)
393 {
394     MATH_EXC_ON;
395     Vec3<T> v2;
396     if (PyImath::V3<T>::convert (o.ptr(), &v2))
397     {
398         return v /= v2;
399     }
400     else
401     {
402         extract<double> e(o);
403         if (e.check())
404             return v /= e();
405         else
406           throw std::invalid_argument ("V3 division expects an argument"
407                    "convertible to a V3");
408     }
409 }
410 
411 template <class T>
412 static Vec3<T>
Vec3_subT(const Vec3<T> & v,T a)413 Vec3_subT(const Vec3<T> &v, T a)
414 {
415     MATH_EXC_ON;
416     Vec3<T> w;
417     w.setValue(v.x - a, v.y - a, v.z - a);
418     return w;
419 }
420 
421 template <class T,class BoostPyType>
422 static Vec3<T>
Vec3_subTuple(const Vec3<T> & v,const BoostPyType & t)423 Vec3_subTuple(const Vec3<T> &v, const BoostPyType &t)
424 {
425     MATH_EXC_ON;
426     Vec3<T> w;
427 
428     if(t.attr("__len__")() == 3)
429     {
430         w.x = v.x - extract<T>(t[0]);
431         w.y = v.y - extract<T>(t[1]);
432         w.z = v.z - extract<T>(t[2]);
433     }
434     else
435         throw std::invalid_argument ("tuple must have length of 3");
436 
437     return w;
438 }
439 
440 template <class T>
441 static Vec3<T>
Vec3_rsubT(const Vec3<T> & v,T a)442 Vec3_rsubT(const Vec3<T> &v, T a)
443 {
444     MATH_EXC_ON;
445     Vec3<T> w;
446     w.setValue(a - v.x, a - v.y, a - v.z);
447     return w;
448 }
449 
450 template <class T, class BoostPyType>
451 static Vec3<T>
Vec3_rsubTuple(const Vec3<T> & v,const BoostPyType & t)452 Vec3_rsubTuple(const Vec3<T> &v, const BoostPyType &t)
453 {
454     MATH_EXC_ON;
455     Vec3<T> w;
456 
457     if(t.attr("__len__")() == 3)
458     {
459         w.x = extract<T>(t[0]) - v.x;
460         w.y = extract<T>(t[1]) - v.y;
461         w.z = extract<T>(t[2]) - v.z;
462     }
463     else
464         throw std::invalid_argument ("tuple must have length of 3");
465 
466     return w;
467 }
468 
469 template <class T, class BoostPyType>
470 static Vec3<T>
Vec3_addTuple(const Vec3<T> & v,const BoostPyType & t)471 Vec3_addTuple(const Vec3<T> &v, const BoostPyType &t)
472 {
473     MATH_EXC_ON;
474     Vec3<T> w;
475 
476     if(t.attr("__len__")() == 3)
477     {
478         w.x = v.x + extract<T>(t[0]);
479         w.y = v.y + extract<T>(t[1]);
480         w.z = v.z + extract<T>(t[2]);
481     }
482     else
483         throw std::invalid_argument ("tuple must have length of 3");
484 
485     return w;
486 }
487 
488 template <class T>
489 static Vec3<T>
Vec3_addT(const Vec3<T> & v,T a)490 Vec3_addT(const Vec3<T> &v, T a)
491 {
492     MATH_EXC_ON;
493     Vec3<T> w;
494     w.setValue(v.x + a, v.y + a, v.z + a);
495     return w;
496 }
497 
498 template <class T, class U>
499 static Vec3<T>
Vec3_addV(const Vec3<T> & v,const Vec3<U> & w)500 Vec3_addV(const Vec3<T> &v, const Vec3<U> &w)
501 {
502     MATH_EXC_ON;
503     return v + w;
504 }
505 
506 template <class T, class U>
507 static const Vec3<T> &
Vec3_iaddV(Vec3<T> & v,const Vec3<U> & w)508 Vec3_iaddV(Vec3<T> &v, const Vec3<U> &w)
509 {
510     MATH_EXC_ON;
511     return v += w;
512 }
513 
514 template <class T, class U>
515 static Vec3<T>
Vec3_subV(const Vec3<T> & v,const Vec3<U> & w)516 Vec3_subV(const Vec3<T> &v, const Vec3<U> &w)
517 {
518     MATH_EXC_ON;
519     return v - w;
520 }
521 
522 template <class T, class U>
523 static const Vec3<T> &
Vec3_isubV(Vec3<T> & v,const Vec3<U> & w)524 Vec3_isubV(Vec3<T> &v, const Vec3<U> &w)
525 {
526     MATH_EXC_ON;
527     return v -= w;
528 }
529 
530 template <class T>
531 static Vec3<T>
mult(const Vec3<T> & v,tuple t)532 mult(const Vec3<T> &v, tuple t)
533 {
534     MATH_EXC_ON;
535     Vec3<T> w;
536 
537     if(t.attr("__len__")() == 1){
538         w.x = v.x*extract<T>(t[0]);
539         w.y = v.y*extract<T>(t[0]);
540         w.z = v.z*extract<T>(t[0]);
541     }
542     else if(t.attr("__len__")() == 3){
543         w.x = v.x*extract<T>(t[0]);
544         w.y = v.y*extract<T>(t[1]);
545         w.z = v.z*extract<T>(t[2]);
546     }
547     else
548         throw std::invalid_argument ("tuple must have length of 1 or 3");
549 
550     return w;
551 }
552 
553 template <class T, class U>
554 static const Vec3<T> &
Vec3_imulM44(Vec3<T> & v,const Matrix44<U> & m)555 Vec3_imulM44 (Vec3<T> &v, const Matrix44<U> &m)
556 {
557     MATH_EXC_ON;
558     return v *= m;
559 }
560 
561 template <class T, class BoostPyType>
562 static Vec3<T>
Vec3_divTuple(const Vec3<T> & v,const BoostPyType & t)563 Vec3_divTuple(const Vec3<T> &v, const BoostPyType &t)
564 {
565     if(t.attr("__len__")() == 3)
566     {
567         T x = extract<T>(t[0]);
568         T y = extract<T>(t[1]);
569         T z = extract<T>(t[2]);
570         if(x != T(0) && y != T(0) && z != T(0))
571             return Vec3<T>(v.x / x, v.y / y, v.z / z);
572         else
573           throw std::domain_error ("Division by zero");
574     }
575     else
576         throw std::invalid_argument ("Vec3 expects tuple of length 3");
577 }
578 
579 template <class T, class BoostPyType>
580 static Vec3<T>
Vec3_rdivTuple(const Vec3<T> & v,const BoostPyType & t)581 Vec3_rdivTuple(const Vec3<T> &v, const BoostPyType &t)
582 {
583     MATH_EXC_ON;
584     Vec3<T> w;
585     if(t.attr("__len__")() == 3)
586     {
587         T x = extract<T>(t[0]);
588         T y = extract<T>(t[1]);
589         T z = extract<T>(t[2]);
590 
591         if(v.x != T(0) && v.y != T(0) && v.z != T(0)){
592             w.setValue(x / v.x, y / v.y, z / v.z);
593         }
594         else
595           throw std::domain_error ("Division by zero");
596     }
597     else
598         throw std::invalid_argument ("tuple must have length of 3");
599 
600     return w;
601 }
602 
603 template <class T>
604 static Vec3<T>
Vec3_divT(const Vec3<T> & v,T a)605 Vec3_divT(const Vec3<T> &v, T a)
606 {
607     MATH_EXC_ON;
608     Vec3<T> w;
609     if(a != T(0)){
610         w.setValue(v.x / a, v.y / a, v.z / a);
611     }
612     else
613       throw std::domain_error ("Division by zero");
614 
615     return w;
616 }
617 
618 template <class T>
619 static Vec3<T>
Vec3_rdivT(const Vec3<T> & v,T a)620 Vec3_rdivT(const Vec3<T> &v, T a)
621 {
622     MATH_EXC_ON;
623     Vec3<T> w;
624     if(v.x != T(0) && v.y != T(0) && v.z != T(0)){
625         w.setValue(a / v.x, a / v.y, a / v.z);
626     }
627     else
628       throw std::domain_error ("Division by zero");
629 
630     return w;
631 }
632 
633 template <class T>
634 static Vec3<T>
Vec3_Vec3_mulT(const Vec3<T> & v,const Vec3<T> & w)635 Vec3_Vec3_mulT(const Vec3<T>& v, const Vec3<T>& w)
636 {
637     MATH_EXC_ON;
638     return v*w;
639 }
640 
641 template <class T>
642 static Vec3<T>
Vec3_Vec3_divT(const Vec3<T> & v,const Vec3<T> & w)643 Vec3_Vec3_divT(const Vec3<T>& v, const Vec3<T>& w)
644 {
645     MATH_EXC_ON;
646     return v/w;
647 }
648 
649 template <class T>
650 static bool
lessThan(const Vec3<T> & v,const object & obj)651 lessThan(const Vec3<T> &v, const object &obj)
652 {
653     extract<Vec3<T> > e1(obj);
654     extract<tuple> e2(obj);
655 
656     Vec3<T> w;
657     if(e1.check())
658     {
659         w = e1();
660     }
661     else if(e2.check())
662     {
663         tuple t = e2();
664         T x = extract<T>(t[0]);
665         T y = extract<T>(t[1]);
666         T z = extract<T>(t[2]);
667         w.setValue(x,y,z);
668     }
669     else
670         throw std::invalid_argument ("invalid parameters passed to operator <");
671 
672     bool isLessThan = (v.x <= w.x && v.y <= w.y && v.z <= w.z)
673                     && v != w;
674 
675     return isLessThan;
676 }
677 
678 template <class T>
679 static bool
greaterThan(const Vec3<T> & v,const object & obj)680 greaterThan(const Vec3<T> &v, const object &obj)
681 {
682     extract<Vec3<T> > e1(obj);
683     extract<tuple> e2(obj);
684 
685     Vec3<T> w;
686     if(e1.check())
687     {
688         w = e1();
689     }
690     else if(e2.check())
691     {
692         tuple t = e2();
693         T x = extract<T>(t[0]);
694         T y = extract<T>(t[1]);
695         T z = extract<T>(t[2]);
696         w.setValue(x,y,z);
697     }
698     else
699         throw std::invalid_argument ("invalid parameters passed to operator >");
700 
701     bool isGreaterThan = (v.x >= w.x && v.y >= w.y && v.z >= w.z)
702                        && v != w;
703 
704     return isGreaterThan;
705 }
706 
707 template <class T>
708 static bool
lessThanEqual(const Vec3<T> & v,const object & obj)709 lessThanEqual(const Vec3<T> &v, const object &obj)
710 {
711     extract<Vec3<T> > e1(obj);
712     extract<tuple> e2(obj);
713 
714     Vec3<T> w;
715     if(e1.check())
716     {
717         w = e1();
718     }
719     else if(e2.check())
720     {
721         tuple t = e2();
722         T x = extract<T>(t[0]);
723         T y = extract<T>(t[1]);
724         T z = extract<T>(t[2]);
725         w.setValue(x,y,z);
726     }
727     else
728         throw std::invalid_argument ("invalid parameters passed to operator <=");
729 
730     bool isLessThanEqual = (v.x <= w.x && v.y <= w.y && v.z <= w.z);
731 
732     return isLessThanEqual;
733 }
734 
735 template <class T>
736 static bool
greaterThanEqual(const Vec3<T> & v,const object & obj)737 greaterThanEqual(const Vec3<T> &v, const object &obj)
738 {
739     extract<Vec3<T> > e1(obj);
740     extract<tuple> e2(obj);
741 
742     Vec3<T> w;
743     if(e1.check())
744     {
745         w = e1();
746     }
747     else if(e2.check())
748     {
749         tuple t = e2();
750         T x = extract<T>(t[0]);
751         T y = extract<T>(t[1]);
752         T z = extract<T>(t[2]);
753         w.setValue(x,y,z);
754     }
755     else
756         throw std::invalid_argument ("invalid parameters passed to operator >=");
757 
758     bool isGreaterThanEqual = (v.x >= w.x && v.y >= w.y && v.z >= w.z);
759 
760     return isGreaterThanEqual;
761 }
762 
763 
764 template <class T>
765 static bool
equalWithAbsErrorObj(const Vec3<T> & v,const object & obj1,const object & obj2)766 equalWithAbsErrorObj(const Vec3<T> &v, const object &obj1, const object &obj2)
767 {
768     extract<Vec3<int> >    e1(obj1);
769     extract<Vec3<float> >  e2(obj1);
770     extract<Vec3<double> > e3(obj1);
771 
772     extract<tuple>         e4(obj1);
773     extract<double>        e5(obj2);
774 
775     Vec3<T> w;
776     if(e1.check())      { w = e1(); }
777     else if(e2.check()) { w = e2(); }
778     else if(e3.check()) { w = e3(); }
779     else if(e4.check())
780     {
781         tuple t = e4();
782         if(t.attr("__len__")() == 3)
783         {
784             w.x = extract<T>(t[0]);
785             w.y = extract<T>(t[1]);
786             w.z = extract<T>(t[2]);
787         }
788         else
789             throw std::invalid_argument ("tuple of length 3 expected");
790     }
791     else
792         throw std::invalid_argument ("invalid parameters passed to equalWithAbsError");
793 
794     if(e5.check())      { return v.equalWithAbsError(w, e5()); }
795     else
796         throw std::invalid_argument ("invalid parameters passed to equalWithAbsError");
797 }
798 
799 template <class T>
800 static bool
equalWithRelErrorObj(const Vec3<T> & v,const object & obj1,const object & obj2)801 equalWithRelErrorObj(const Vec3<T> &v, const object &obj1, const object &obj2)
802 {
803     extract<Vec3<int> >    e1(obj1);
804     extract<Vec3<float> >  e2(obj1);
805     extract<Vec3<double> > e3(obj1);
806 
807     extract<tuple>         e4(obj1);
808     extract<double>        e5(obj2);
809 
810     Vec3<T> w;
811     if(e1.check())      { w = e1(); }
812     else if(e2.check()) { w = e2(); }
813     else if(e3.check()) { w = e3(); }
814     else if(e4.check())
815     {
816         tuple t = e4();
817         if(t.attr("__len__")() == 3)
818         {
819             w.x = extract<T>(t[0]);
820             w.y = extract<T>(t[1]);
821             w.z = extract<T>(t[2]);
822         }
823         else
824             throw std::invalid_argument ("tuple of length 3 expected");
825     }
826     else
827         throw std::invalid_argument ("invalid parameters passed to equalWithRelError");
828 
829     if(e5.check())      { return v.equalWithRelError(w, e5()); }
830     else
831         throw std::invalid_argument ("invalid parameters passed to equalWithRelError");
832 
833 }
834 
835 
836 template <class T>
837 static bool
equal(const Vec3<T> & v,const tuple & t)838 equal(const Vec3<T> &v, const tuple &t)
839 {
840     Vec3<T> w;
841     if(t.attr("__len__")() == 3)
842     {
843         w.x = extract<T>(t[0]);
844         w.y = extract<T>(t[1]);
845         w.z = extract<T>(t[2]);
846 
847         return (v == w);
848     }
849     else
850         throw std::invalid_argument ("tuple of length 3 expected");
851 }
852 
853 template <class T>
854 static bool
notequal(const Vec3<T> & v,const tuple & t)855 notequal(const Vec3<T> &v, const tuple &t)
856 {
857     Vec3<T> w;
858     if(t.attr("__len__")() == 3)
859     {
860         w.x = extract<T>(t[0]);
861         w.y = extract<T>(t[1]);
862         w.z = extract<T>(t[2]);
863 
864         return (v != w);
865     }
866     else
867         throw std::invalid_argument ("tuple of length 3 expected");
868 }
869 
870 
871 
872 // Trick to register methods for float-only-based vectors
873 template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)>
register_Vec3_floatonly(class_<Vec3<T>> & vec3_class)874 void register_Vec3_floatonly(class_<Vec3<T>>& vec3_class)
875 {
876    vec3_class
877         .def("length", &Vec3_length<T>,"length() magnitude of the vector")
878         .def("normalize", &Vec3_normalize<T>,return_internal_reference<>(),
879              "v.normalize() destructively normalizes v and returns a reference to it")
880         .def("normalizeExc", &Vec3_normalizeExc<T>,return_internal_reference<>(),
881              "v.normalizeExc() destructively normalizes V and returns a reference to it, throwing an exception if length() == 0")
882         .def("normalizeNonNull", &Vec3_normalizeNonNull<T>,return_internal_reference<>(),
883              "v.normalizeNonNull() destructively normalizes V and returns a reference to it, faster if lngth() != 0")
884         .def("normalized", &Vec3_normalized<T>, "v.normalized() returns a normalized copy of v")
885         .def("normalizedExc", &Vec3_normalizedExc<T>, "v.normalizedExc() returns a normalized copy of v, throwing an exception if length() == 0")
886         .def("normalizedNonNull", &Vec3_normalizedNonNull<T>, "v.normalizedNonNull() returns a normalized copy of v, faster if lngth() != 0")
887         .def("orthogonal", &orthogonal<T>)
888         .def("project", &project<T>)
889         .def("reflect", &reflect<T>)
890         ;
891 }
892 
893 template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)>
register_Vec3_floatonly(class_<Vec3<T>> & vec2_class)894 void register_Vec3_floatonly(class_<Vec3<T>>& vec2_class)
895 {
896 }
897 
898 
899 
900 template <class T>
901 class_<Vec3<T> >
register_Vec3()902 register_Vec3()
903 {
904     typedef PyImath::StaticFixedArray<Vec3<T>,T,3> Vec3_helper;
905 
906     class_<Vec3<T> > vec3_class(Vec3Name<T>::value(), Vec3Name<T>::value(),init<Vec3<T> >("copy construction"));
907     vec3_class
908         .def("__init__",make_constructor(Vec3_construct_default<T>),"initialize to (0,0,0)")
909         .def("__init__",make_constructor(Vec3_object_constructor1<T>))
910         .def("__init__",make_constructor(Vec3_object_constructor2<T>))
911         .def_readwrite("x", &Vec3<T>::x)
912         .def_readwrite("y", &Vec3<T>::y)
913         .def_readwrite("z", &Vec3<T>::z)
914 	.def("baseTypeEpsilon", &Vec3<T>::baseTypeEpsilon,"baseTypeEpsilon() epsilon value of the base type of the vector")
915         .staticmethod("baseTypeEpsilon")
916 	.def("baseTypeMax", &Vec3<T>::baseTypeMax,"baseTypeMax() max value of the base type of the vector")
917         .staticmethod("baseTypeMax")
918 	.def("baseTypeLowest", &Vec3<T>::baseTypeLowest,"baseTypeLowest() largest negative value of the base type of the vector")
919         .staticmethod("baseTypeLowest")
920 	.def("baseTypeSmallest", &Vec3<T>::baseTypeSmallest,"baseTypeSmallest() smallest value of the base type of the vector")
921         .staticmethod("baseTypeSmallest")
922 	.def("cross", &Vec3_cross<T>,"v1.cross(v2) right handed cross product")
923 	.def("cross", &Vec3_cross_Vec3Array<T>,"v1.cross(v2) right handed array cross product")
924 	.def("dimensions", &Vec3<T>::dimensions,"dimensions() number of dimensions in the vector")
925         .staticmethod("dimensions")
926 	.def("dot", &Vec3_dot<T>,"v1.dot(v2) inner product of the two vectors")
927 	.def("dot", &Vec3_dot_Vec3Array<T>,"v1.dot(v2) array inner product")
928 
929 	.def("equalWithAbsError", &Vec3<T>::equalWithAbsError,
930          "v1.equalWithAbsError(v2) true if the elements "
931          "of v1 and v2 are the same with an absolute error of no more than e, "
932          "i.e., abs(v1[i] - v2[i]) <= e")
933         .def("equalWithAbsError", &equalWithAbsErrorObj<T>)
934 
935 	.def("equalWithRelError", &Vec3<T>::equalWithRelError,
936          "v1.equalWithAbsError(v2) true if the elements "
937          "of v1 and v2 are the same with an absolute error of no more than e, "
938          "i.e., abs(v1[i] - v2[i]) <= e * abs(v1[i])")
939         .def("equalWithRelError", &equalWithRelErrorObj<T>)
940 
941 	.def("length2", &Vec3_length2<T>,"length2() square magnitude of the vector")
942 	.def("__len__", Vec3_helper::len)
943 	.def("__getitem__", Vec3_helper::getitem,return_value_policy<copy_non_const_reference>())
944 	.def("__setitem__", Vec3_helper::setitem)
945         .def("closestVertex", &closestVertex<T>)
946         .def("negate", &Vec3_negate<T>, return_internal_reference<>())
947         .def("setValue", &setValue<T>)
948         .def("__neg__", &Vec3_neg<T>)
949         .def("__mul__", &Vec3_mul<T, int>)
950         .def("__mul__", &Vec3_mul<T, float>)
951         .def("__mul__", &Vec3_mul<T, double>)
952         .def("__mul__", &Vec3_mulT<T>)
953         .def("__mul__", &Vec3_mulTArray<T>)
954         .def("__rmul__", &Vec3_rmulT<T>)
955         .def("__rmul__", &Vec3_rmulTArray<T>)
956         .def("__imul__", &Vec3_imulV<T, int>,return_internal_reference<>())
957         .def("__imul__", &Vec3_imulV<T, float>,return_internal_reference<>())
958         .def("__imul__", &Vec3_imulV<T, double>,return_internal_reference<>())
959         .def("__imul__", &Vec3_imulT<T>,return_internal_reference<>())
960         .def("__div__", &Vec3_Vec3_divT<T>)
961         .def("__truediv__", &Vec3_Vec3_divT<T>)
962         .def("__mul__", &Vec3_mulM33<T, float>)
963         .def("__mul__", &Vec3_mulM33<T, double>)
964         .def("__mul__", &Vec3_mulM44<T, float>)
965         .def("__mul__", &Vec3_mulM44<T, double>)
966         .def("__mul__", &Vec3_Vec3_mulT<T>)
967         .def("__div__", &Vec3_div<T,int>)
968         .def("__div__", &Vec3_div<T,float>)
969         .def("__div__", &Vec3_div<T,double>)
970         .def("__div__", &Vec3_divTuple<T,tuple>)
971         .def("__div__", &Vec3_divTuple<T,list>)
972         .def("__div__", &Vec3_divT<T>)
973         .def("__truediv__", &Vec3_div<T,int>)
974         .def("__truediv__", &Vec3_div<T,float>)
975         .def("__truediv__", &Vec3_div<T,double>)
976         .def("__truediv__", &Vec3_divTuple<T,tuple>)
977         .def("__truediv__", &Vec3_divTuple<T,list>)
978         .def("__truediv__", &Vec3_divT<T>)
979         .def("__rdiv__", &Vec3_rdivTuple<T,tuple>)
980         .def("__rdiv__", &Vec3_rdivTuple<T,list>)
981         .def("__rdiv__", &Vec3_rdivT<T>)
982         .def("__rtruediv__", &Vec3_rdivTuple<T,tuple>)
983         .def("__rtruediv__", &Vec3_rdivTuple<T,list>)
984         .def("__rtruediv__", &Vec3_rdivT<T>)
985         .def("__idiv__", &Vec3_idivObj<T>,return_internal_reference<>())
986         .def("__itruediv__", &Vec3_idivObj<T>,return_internal_reference<>())
987         .def("__xor__", &Vec3_dot<T>)
988         .def("__mod__", &Vec3_cross<T>)
989         .def(self == self) // NOSONAR - suppress SonarCloud bug report.
990         .def(self != self) // NOSONAR - suppress SonarCloud bug report.
991         .def("__add__", &Vec3_add<T>)
992         .def("__add__", &Vec3_addV<T, int>)
993         .def("__add__", &Vec3_addV<T, float>)
994         .def("__add__", &Vec3_addV<T, double>)
995         .def("__add__", &Vec3_addT<T>)
996         .def("__add__", &Vec3_addTuple<T,tuple>)
997         .def("__add__", &Vec3_addTuple<T,list>)
998         .def("__radd__", &Vec3_addT<T>)
999         .def("__radd__", &Vec3_addTuple<T,tuple>)
1000         .def("__radd__", &Vec3_addTuple<T,list>)
1001         .def("__radd__", &Vec3_add<T>)
1002         .def("__iadd__", &Vec3_iaddV<T, int>, return_internal_reference<>())
1003         .def("__iadd__", &Vec3_iaddV<T, float>, return_internal_reference<>())
1004         .def("__iadd__", &Vec3_iaddV<T, double>, return_internal_reference<>())
1005         .def("__sub__", &Vec3_sub<T>)
1006         .def("__sub__", &Vec3_subV<T, int>)
1007         .def("__sub__", &Vec3_subV<T, float>)
1008         .def("__sub__", &Vec3_subV<T, double>)
1009         .def("__sub__", &Vec3_subT<T>)
1010         .def("__sub__", &Vec3_subTuple<T,tuple>)
1011         .def("__sub__", &Vec3_subTuple<T,list>)
1012         .def("__rsub__", &Vec3_rsubT<T>)
1013         .def("__rsub__", &Vec3_rsubTuple<T,tuple>)
1014         .def("__rsub__", &Vec3_rsubTuple<T,list>)
1015         .def("__isub__", &Vec3_isubV<T, int>, return_internal_reference<>())
1016         .def("__isub__", &Vec3_isubV<T, float>, return_internal_reference<>())
1017         .def("__isub__", &Vec3_isubV<T, double>, return_internal_reference<>())
1018         .def("__mul__", &mult<T>)
1019         .def("__rmul__", &mult<T>)
1020         .def("__imul__", &Vec3_imulM44<T, float>, return_internal_reference<>())
1021         .def("__imul__", &Vec3_imulM44<T, double>, return_internal_reference<>())
1022         .def("__lt__", &lessThan<T>)
1023         .def("__gt__", &greaterThan<T>)
1024         .def("__le__", &lessThanEqual<T>)
1025         .def("__ge__", &greaterThanEqual<T>)
1026         .def("__eq__", &equal<T>)
1027         .def("__ne__", &notequal<T>)
1028 	//.def(self_ns::str(self))
1029 	.def("__str__",&Vec3_str<T>)
1030 	.def("__repr__",&Vec3_repr<T>)
1031         ;
1032 
1033     register_Vec3_floatonly<T>(vec3_class);
1034 
1035     decoratecopy(vec3_class);
1036 
1037     //add_swizzle3_operators(v3f_class);
1038     return vec3_class;
1039 }
1040 
1041 
1042 
1043 }  // namespace PyImath
1044 
1045 #endif    // _PyImathVec3Impl_h_
1046