pybind11Utils.hpp
Go to the documentation of this file.
1 // This code is based on Jet framework.
2 // Copyright (c) 2018 Doyub Kim
3 // CubbyFlow is voxel-based fluid simulation engine for computer games.
4 // Copyright (c) 2020 CubbyFlow Team
5 // Core Part: Chris Ohk, Junwoo Hwang, Jihong Sin, Seungwoo Yoo
6 // AI Part: Dongheon Cho, Minseo Kim
7 // We are making my contributions/submissions to this project solely in our
8 // personal capacity and are not conveying any rights to any intellectual
9 // property of any third parties.
10 
11 #ifndef CUBBYFLOW_PYTHON_PYBIND11_UTILS_HPP
12 #define CUBBYFLOW_PYTHON_PYBIND11_UTILS_HPP
13 
14 #include <Core/Math/Quaternion.hpp>
15 #include <Core/Matrix/Matrix.hpp>
16 
17 #include <pybind11/pybind11.h>
18 #include <pybind11/stl.h>
19 
20 namespace CubbyFlow
21 {
22 inline Vector2UZ TupleToVector2UZ(pybind11::tuple tuple)
23 {
24  Vector2UZ ret;
25 
26  if (tuple.size() == 2)
27  {
28  for (size_t i = 0; i < 2; ++i)
29  {
30  ret[i] = tuple[i].cast<size_t>();
31  }
32  }
33  else
34  {
35  throw std::invalid_argument("Invalid size.");
36  }
37 
38  return ret;
39 }
40 
41 inline Vector2UZ TupleToVector2UZ(pybind11::list list)
42 {
43  Vector2UZ ret;
44 
45  if (list.size() == 2)
46  {
47  for (size_t i = 0; i < 2; ++i)
48  {
49  ret[i] = list[i].cast<size_t>();
50  }
51  }
52  else
53  {
54  throw std::invalid_argument("Invalid size.");
55  }
56 
57  return ret;
58 }
59 
60 inline Vector3UZ TupleToVector3UZ(pybind11::tuple tuple)
61 {
62  Vector3UZ ret;
63 
64  if (tuple.size() == 3)
65  {
66  for (size_t i = 0; i < 3; ++i)
67  {
68  ret[i] = tuple[i].cast<size_t>();
69  }
70  }
71  else
72  {
73  throw std::invalid_argument("Invalid size.");
74  }
75 
76  return ret;
77 }
78 
79 inline Vector3UZ TupleToVector3UZ(pybind11::list list)
80 {
81  Vector3UZ ret;
82 
83  if (list.size() == 3)
84  {
85  for (size_t i = 0; i < 3; ++i)
86  {
87  ret[i] = list[i].cast<size_t>();
88  }
89  }
90  else
91  {
92  throw std::invalid_argument("Invalid size.");
93  }
94 
95  return ret;
96 }
97 
98 inline pybind11::tuple Vector2UZToTuple(const Vector2UZ& size)
99 {
100  return pybind11::make_tuple(size.x, size.y);
101 }
102 
103 inline pybind11::tuple Vector3UZToTuple(const Vector3UZ& size)
104 {
105  return pybind11::make_tuple(size.x, size.y, size.z);
106 }
107 
108 template <typename T, size_t N>
109 inline Vector<T, N> TupleToVector(pybind11::tuple tuple)
110 {
111  Vector<T, N> ret;
112 
113  if (tuple.size() == N)
114  {
115  for (size_t i = 0; i < N; ++i)
116  {
117  ret[i] = tuple[i].cast<T>();
118  }
119  }
120  else
121  {
122  throw std::invalid_argument("Invalid size.");
123  }
124 
125  return ret;
126 }
127 
128 template <typename T, size_t N>
129 inline Vector<T, N> TupleToVector(pybind11::list list)
130 {
131  Vector<T, N> ret;
132 
133  if (list.size() == N)
134  {
135  for (size_t i = 0; i < N; ++i)
136  {
137  ret[i] = list[i].cast<T>();
138  }
139  }
140  else
141  {
142  throw std::invalid_argument("Invalid size.");
143  }
144 
145  return ret;
146 }
147 
148 template <typename T>
149 inline Quaternion<T> TupleToQuaternion(pybind11::tuple tuple)
150 {
151  Quaternion<T> ret;
152 
153  for (size_t i = 0; i < 4; ++i)
154  {
155  ret[i] = tuple[i].cast<T>();
156  }
157 
158  return ret;
159 }
160 
161 template <typename T>
162 inline Quaternion<T> TupleToQuaternion(pybind11::list list)
163 {
164  Quaternion<T> ret;
165 
166  for (size_t i = 0; i < 4; ++i)
167  {
168  ret[i] = list[i].cast<T>();
169  }
170 
171  return ret;
172 }
173 
174 inline Vector2F TupleToVector2F(pybind11::tuple tuple)
175 {
176  return TupleToVector<float, 2>(tuple);
177 }
178 
179 inline Vector2F TupleToVector2F(pybind11::list list)
180 {
181  return TupleToVector<float, 2>(list);
182 }
183 
184 inline Vector3F TupleToVector3F(pybind11::tuple tuple)
185 {
186  return TupleToVector<float, 3>(tuple);
187 }
188 
189 inline Vector3F TupleToVector3F(pybind11::list list)
190 {
191  return TupleToVector<float, 3>(list);
192 }
193 
194 inline Vector4F TupleToVector4F(pybind11::tuple tuple)
195 {
196  return TupleToVector<float, 4>(tuple);
197 }
198 
199 inline Vector4F TupleToVector4F(pybind11::list list)
200 {
201  return TupleToVector<float, 4>(list);
202 }
203 
204 inline QuaternionF TupleToQuaternionF(pybind11::tuple tuple)
205 {
206  return TupleToQuaternion<float>(tuple);
207 }
208 
209 inline QuaternionF TupleToQuaternionF(pybind11::list list)
210 {
211  return TupleToQuaternion<float>(list);
212 }
213 
214 inline Vector2D TupleToVector2D(pybind11::tuple tuple)
215 {
216  return TupleToVector<double, 2>(tuple);
217 }
218 
219 inline Vector2D TupleToVector2D(pybind11::list list)
220 {
221  return TupleToVector<double, 2>(list);
222 }
223 
224 inline Vector3D TupleToVector3D(pybind11::tuple tuple)
225 {
226  return TupleToVector<double, 3>(tuple);
227 }
228 
229 inline Vector3D TupleToVector3D(pybind11::list list)
230 {
231  return TupleToVector<double, 3>(list);
232 }
233 
234 inline Vector4D TupleToVector4D(pybind11::tuple tuple)
235 {
236  return TupleToVector<double, 4>(tuple);
237 }
238 
239 inline Vector4D TupleToVector4D(pybind11::list list)
240 {
241  return TupleToVector<double, 4>(list);
242 }
243 
244 template <typename T>
245 inline pybind11::tuple Vector2ToTuple(const Vector<T, 2>& vec)
246 {
247  return pybind11::make_tuple(vec.x, vec.y);
248 }
249 
250 template <typename T>
251 inline pybind11::tuple Vector3ToTuple(const Vector<T, 3>& vec)
252 {
253  return pybind11::make_tuple(vec.x, vec.y, vec.z);
254 }
255 
256 template <typename T>
257 inline pybind11::tuple Vector4ToTuple(const Vector<T, 4>& vec)
258 {
259  return pybind11::make_tuple(vec.x, vec.y, vec.z, vec.w);
260 }
261 
262 inline QuaternionD TupleToQuaternionD(pybind11::tuple tuple)
263 {
264  return TupleToQuaternion<double>(tuple);
265 }
266 
267 inline QuaternionD TupleToQuaternionD(pybind11::list list)
268 {
269  return TupleToQuaternion<double>(list);
270 }
271 
272 inline Vector2UZ ObjectToVector2UZ(const pybind11::object& obj)
273 {
274  if (pybind11::isinstance<Vector2UZ>(static_cast<pybind11::handle>(obj)))
275  {
276  return obj.cast<Vector2UZ>();
277  }
278 
279  if (pybind11::isinstance<pybind11::tuple>(
280  static_cast<pybind11::handle>(obj)))
281  {
282  return TupleToVector2UZ(pybind11::tuple(obj));
283  }
284 
285  if (pybind11::isinstance<pybind11::list>(
286  static_cast<pybind11::handle>(obj)))
287  {
288  return TupleToVector2UZ(pybind11::list(obj));
289  }
290 
291  throw std::invalid_argument("Cannot convert to Vector2UZ.");
292 }
293 
294 inline Vector3UZ ObjectToVector3UZ(const pybind11::object& obj)
295 {
296  if (pybind11::isinstance<Vector3UZ>(static_cast<pybind11::handle>(obj)))
297  {
298  return obj.cast<Vector3UZ>();
299  }
300 
301  if (pybind11::isinstance<pybind11::tuple>(
302  static_cast<pybind11::handle>(obj)))
303  {
304  return TupleToVector3UZ(pybind11::tuple(obj));
305  }
306 
307  if (pybind11::isinstance<pybind11::list>(
308  static_cast<pybind11::handle>(obj)))
309  {
310  return TupleToVector3UZ(pybind11::list(obj));
311  }
312 
313  throw std::invalid_argument("Cannot convert to Vector3UZ.");
314 }
315 
316 inline Vector2F ObjectToVector2F(const pybind11::object& obj)
317 {
318  if (pybind11::isinstance<Vector2F>(static_cast<pybind11::handle>(obj)))
319  {
320  return obj.cast<Vector2F>();
321  }
322 
323  if (pybind11::isinstance<pybind11::tuple>(
324  static_cast<pybind11::handle>(obj)))
325  {
326  return TupleToVector2F(pybind11::tuple(obj));
327  }
328 
329  if (pybind11::isinstance<pybind11::list>(
330  static_cast<pybind11::handle>(obj)))
331  {
332  return TupleToVector2F(pybind11::list(obj));
333  }
334 
335  throw std::invalid_argument("Cannot convert to Vector2F.");
336 }
337 
338 inline Vector2D ObjectToVector2D(const pybind11::object& obj)
339 {
340  if (pybind11::isinstance<Vector2D>(static_cast<pybind11::handle>(obj)))
341  {
342  return obj.cast<Vector2D>();
343  }
344 
345  if (pybind11::isinstance<pybind11::tuple>(
346  static_cast<pybind11::handle>(obj)))
347  {
348  return TupleToVector2D(pybind11::tuple(obj));
349  }
350 
351  if (pybind11::isinstance<pybind11::list>(
352  static_cast<pybind11::handle>(obj)))
353  {
354  return TupleToVector2D(pybind11::list(obj));
355  }
356 
357  throw std::invalid_argument("Cannot convert to Vector2D.");
358 }
359 
360 inline Vector3F ObjectToVector3F(const pybind11::object& obj)
361 {
362  if (pybind11::isinstance<Vector3F>(static_cast<pybind11::handle>(obj)))
363  {
364  return obj.cast<Vector3F>();
365  }
366 
367  if (pybind11::isinstance<pybind11::tuple>(
368  static_cast<pybind11::handle>(obj)))
369  {
370  return TupleToVector3F(pybind11::tuple(obj));
371  }
372 
373  if (pybind11::isinstance<pybind11::list>(
374  static_cast<pybind11::handle>(obj)))
375  {
376  return TupleToVector3F(pybind11::list(obj));
377  }
378 
379  throw std::invalid_argument("Cannot convert to Vector3F.");
380 }
381 
382 inline Vector3D ObjectToVector3D(const pybind11::object& obj)
383 {
384  if (pybind11::isinstance<Vector3D>(static_cast<pybind11::handle>(obj)))
385  {
386  return obj.cast<Vector3D>();
387  }
388 
389  if (pybind11::isinstance<pybind11::tuple>(
390  static_cast<pybind11::handle>(obj)))
391  {
392  return TupleToVector3D(pybind11::tuple(obj));
393  }
394 
395  if (pybind11::isinstance<pybind11::list>(
396  static_cast<pybind11::handle>(obj)))
397  {
398  return TupleToVector3D(pybind11::list(obj));
399  }
400 
401  throw std::invalid_argument("Cannot convert to Vector3D.");
402 }
403 
404 inline Vector4F ObjectToVector4F(const pybind11::object& obj)
405 {
406  if (pybind11::isinstance<Vector4F>(static_cast<pybind11::handle>(obj)))
407  {
408  return obj.cast<Vector4F>();
409  }
410 
411  if (pybind11::isinstance<pybind11::tuple>(
412  static_cast<pybind11::handle>(obj)))
413  {
414  return TupleToVector4F(pybind11::tuple(obj));
415  }
416 
417  if (pybind11::isinstance<pybind11::list>(
418  static_cast<pybind11::handle>(obj)))
419  {
420  return TupleToVector4F(pybind11::list(obj));
421  }
422 
423  throw std::invalid_argument("Cannot convert to Vector4F.");
424 }
425 
426 inline Vector4D ObjectToVector4D(const pybind11::object& obj)
427 {
428  if (pybind11::isinstance<Vector4D>(static_cast<pybind11::handle>(obj)))
429  {
430  return obj.cast<Vector4D>();
431  }
432 
433  if (pybind11::isinstance<pybind11::tuple>(
434  static_cast<pybind11::handle>(obj)))
435  {
436  return TupleToVector4D(pybind11::tuple(obj));
437  }
438 
439  if (pybind11::isinstance<pybind11::list>(
440  static_cast<pybind11::handle>(obj)))
441  {
442  return TupleToVector4D(pybind11::list(obj));
443  }
444 
445  throw std::invalid_argument("Cannot convert to Vector4D.");
446 }
447 
448 inline QuaternionF ObjectToQuaternionF(const pybind11::object& obj)
449 {
450  if (pybind11::isinstance<QuaternionF>(static_cast<pybind11::handle>(obj)))
451  {
452  return obj.cast<QuaternionF>();
453  }
454 
455  if (pybind11::isinstance<pybind11::tuple>(
456  static_cast<pybind11::handle>(obj)))
457  {
458  return TupleToQuaternionF(pybind11::tuple(obj));
459  }
460 
461  if (pybind11::isinstance<pybind11::list>(
462  static_cast<pybind11::handle>(obj)))
463  {
464  return TupleToQuaternionF(pybind11::list(obj));
465  }
466 
467  throw std::invalid_argument("Cannot convert to QuaternionF.");
468 }
469 
470 inline QuaternionD ObjectToQuaternionD(const pybind11::object& obj)
471 {
472  if (pybind11::isinstance<QuaternionD>(static_cast<pybind11::handle>(obj)))
473  {
474  return obj.cast<QuaternionD>();
475  }
476 
477  if (pybind11::isinstance<pybind11::tuple>(
478  static_cast<pybind11::handle>(obj)))
479  {
480  return TupleToQuaternionD(pybind11::tuple(obj));
481  }
482 
483  if (pybind11::isinstance<pybind11::list>(
484  static_cast<pybind11::handle>(obj)))
485  {
486  return TupleToQuaternionD(pybind11::list(obj));
487  }
488 
489  throw std::invalid_argument("Cannot convert to QuaternionD.");
490 }
491 
492 inline void ParseGridResizeParams(pybind11::args args, pybind11::kwargs kwargs,
493  Vector2UZ& resolution, Vector2D& gridSpacing,
494  Vector2D& gridOrigin)
495 {
496  // See if we have list of parameters
497  if (args.size() <= 3)
498  {
499  if (args.size() > 0)
500  {
501  resolution = ObjectToVector2UZ(pybind11::object(args[0]));
502  }
503  if (args.size() > 1)
504  {
505  gridSpacing = ObjectToVector2D(pybind11::object(args[1]));
506  }
507  if (args.size() > 2)
508  {
509  gridOrigin = ObjectToVector2D(pybind11::object(args[2]));
510  }
511  }
512  else
513  {
514  throw std::invalid_argument("Too many arguments.");
515  }
516 
517  // Parse out keyword args
518  if (kwargs.contains("resolution"))
519  {
520  resolution = ObjectToVector2UZ(pybind11::object(kwargs["resolution"]));
521  }
522  if (kwargs.contains("gridSpacing"))
523  {
524  gridSpacing = ObjectToVector2D(pybind11::object(kwargs["gridSpacing"]));
525  }
526  if (kwargs.contains("gridOrigin"))
527  {
528  gridOrigin = ObjectToVector2D(pybind11::object(kwargs["gridOrigin"]));
529  }
530  if (kwargs.contains("domainSizeX"))
531  {
532  double domainSizeX = kwargs["domainSizeX"].cast<double>();
533  gridSpacing.Fill(domainSizeX / static_cast<double>(resolution.x));
534  }
535 }
536 
537 inline void ParseGridResizeParams(pybind11::args args, pybind11::kwargs kwargs,
538  Vector3UZ& resolution, Vector3D& gridSpacing,
539  Vector3D& gridOrigin)
540 {
541  // See if we have list of parameters
542  if (args.size() <= 3)
543  {
544  if (args.size() > 0)
545  {
546  resolution = ObjectToVector3UZ(pybind11::object(args[0]));
547  }
548  if (args.size() > 1)
549  {
550  gridSpacing = ObjectToVector3D(pybind11::object(args[1]));
551  }
552  if (args.size() > 2)
553  {
554  gridOrigin = ObjectToVector3D(pybind11::object(args[2]));
555  }
556  }
557  else
558  {
559  throw std::invalid_argument("Too many arguments.");
560  }
561 
562  // Parse out keyword args
563  if (kwargs.contains("resolution"))
564  {
565  resolution = ObjectToVector3UZ(pybind11::object(kwargs["resolution"]));
566  }
567  if (kwargs.contains("gridSpacing"))
568  {
569  gridSpacing = ObjectToVector3D(pybind11::object(kwargs["gridSpacing"]));
570  }
571  if (kwargs.contains("gridOrigin"))
572  {
573  gridOrigin = ObjectToVector3D(pybind11::object(kwargs["gridOrigin"]));
574  }
575  if (kwargs.contains("domainSizeX"))
576  {
577  double domainSizeX = kwargs["domainSizeX"].cast<double>();
578  gridSpacing.Fill(domainSizeX / static_cast<double>(resolution.x));
579  }
580 }
581 } // namespace CubbyFlow
582 
583 #define CUBBYFLOW_PYTHON_MAKE_INDEX_FUNCTION2(Class, Func) \
584  [](const Class& instance, pybind11::args args) { \
585  if (args.size() == 1) \
586  { \
587  return instance.Func(ObjectToVector2UZ(args[0])); \
588  } \
589  else \
590  { \
591  throw std::invalid_argument("Invalid number of arguments."); \
592  } \
593  }
594 
595 #define CUBBYFLOW_PYTHON_MAKE_INDEX_FUNCTION3(Class, Func) \
596  [](const Class& instance, pybind11::args args) { \
597  if (args.size() == 1) \
598  { \
599  return instance.Func(ObjectToVector3UZ(args[0])); \
600  } \
601  else \
602  { \
603  throw std::invalid_argument("Invalid number of arguments."); \
604  } \
605  }
606 
607 #endif
Quaternion< T > TupleToQuaternion(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:149
Vector2UZ ObjectToVector2UZ(const pybind11::object &obj)
Definition: pybind11Utils.hpp:272
pybind11::tuple Vector2UZToTuple(const Vector2UZ &size)
Definition: pybind11Utils.hpp:98
Vector2UZ TupleToVector2UZ(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:22
QuaternionD ObjectToQuaternionD(const pybind11::object &obj)
Definition: pybind11Utils.hpp:470
pybind11::tuple Vector3UZToTuple(const Vector3UZ &size)
Definition: pybind11Utils.hpp:103
Vector4D ObjectToVector4D(const pybind11::object &obj)
Definition: pybind11Utils.hpp:426
pybind11::tuple Vector4ToTuple(const Vector< T, 4 > &vec)
Definition: pybind11Utils.hpp:257
void ParseGridResizeParams(pybind11::args args, pybind11::kwargs kwargs, Vector2UZ &resolution, Vector2D &gridSpacing, Vector2D &gridOrigin)
Definition: pybind11Utils.hpp:492
QuaternionD TupleToQuaternionD(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:262
Vector4F ObjectToVector4F(const pybind11::object &obj)
Definition: pybind11Utils.hpp:404
Vector3UZ TupleToVector3UZ(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:60
pybind11::tuple Vector3ToTuple(const Vector< T, 3 > &vec)
Definition: pybind11Utils.hpp:251
void Fill(const T &val)
Definition: Matrix-Impl.hpp:226
Vector2D ObjectToVector2D(const pybind11::object &obj)
Definition: pybind11Utils.hpp:338
Vector3F ObjectToVector3F(const pybind11::object &obj)
Definition: pybind11Utils.hpp:360
Definition: Matrix.hpp:27
Definition: pybind11Utils.hpp:20
Vector3D TupleToVector3D(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:224
Vector3UZ ObjectToVector3UZ(const pybind11::object &obj)
Definition: pybind11Utils.hpp:294
QuaternionF TupleToQuaternionF(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:204
Vector3D ObjectToVector3D(const pybind11::object &obj)
Definition: pybind11Utils.hpp:382
Vector2F TupleToVector2F(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:174
Vector2D TupleToVector2D(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:214
Vector4F TupleToVector4F(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:194
Vector3F TupleToVector3F(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:184
Vector2F ObjectToVector2F(const pybind11::object &obj)
Definition: pybind11Utils.hpp:316
Vector4D TupleToVector4D(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:234
QuaternionF ObjectToQuaternionF(const pybind11::object &obj)
Definition: pybind11Utils.hpp:448
Quaternion class defined as q = w + xi + yj + zk.
Definition: Quaternion.hpp:22
pybind11::tuple Vector2ToTuple(const Vector< T, 2 > &vec)
Definition: pybind11Utils.hpp:245
Vector< T, N > TupleToVector(pybind11::tuple tuple)
Definition: pybind11Utils.hpp:109