22 #include "pybind11/pybind11.h"
23 #include "pybind11/eigen.h"
24 #include "ndarray/pybind11.h"
33 using namespace pybind11::literals;
39 template <
typename Derived,
typename T,
int N>
40 using PyCoordinateBase = py::class_<CoordinateBase<Derived, T, N>>;
43 using PyCoordinateExpr = py::class_<CoordinateExpr<N>, CoordinateBase<CoordinateExpr<N>, bool, N>>;
45 template <
typename T,
int N>
46 using PyExtentBase = py::class_<ExtentBase<T, N>, CoordinateBase<Extent<T, N>, T, N>>;
48 template <
typename T,
int N>
49 using PyExtent = py::class_<Extent<T, N>, ExtentBase<T, N>>;
51 template <
typename T,
int N>
52 using PyPointBase = py::class_<PointBase<T, N>, CoordinateBase<Point<T, N>, T, N>>;
54 template <
typename T,
int N>
55 using PyPoint = py::class_<Point<T, N>, PointBase<T, N>>;
57 template <
typename Derived,
typename T,
int N>
58 void declareCoordinateBase(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
61 PyCoordinateBase<Derived, T, N>(wrappers.module,
name.c_str()),
62 [](
auto & mod,
auto &
cls) {
63 cls.def(
"__getitem__", [](CoordinateBase<Derived, T, N> &self, int i) -> T {
64 return self[utils::python::cppIndex(N, i)];
66 cls.def(
"__setitem__", [](CoordinateBase<Derived, T, N> &
self,
int i, T value) {
69 cls.def(
"__len__", [](CoordinateBase<Derived, T, N> &c) ->
int {
return N; });
75 void declareCoordinateExpr(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
77 declareCoordinateBase<CoordinateExpr<N>, bool, N>(wrappers,
name);
79 PyCoordinateExpr<N>(wrappers.module,
name.c_str()),
80 [](
auto & mod,
auto &
cls) {
81 cls.def(py::init<bool>(),
"val"_a =
false);
82 cls.def(
"and_", &CoordinateExpr<N>::and_);
83 cls.def(
"or_", &CoordinateExpr<N>::or_);
84 cls.def(
"not_", &CoordinateExpr<N>::not_);
85 mod.def(
"all", all<N>);
86 mod.def(
"any", any<N>);
91 template <
typename T,
int N>
92 void declareExtentBase(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
94 declareCoordinateBase<Extent<T, N>, T, N>(wrappers,
"Extent" + suffix);
96 PyExtentBase<T, N>(wrappers.module,
name.c_str()),
97 [](
auto & mod,
auto &
cls) {
101 cls.def(
"eq", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.eq(
other); });
102 cls.def(
"ne", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.ne(
other); });
103 cls.def(
"lt", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.lt(
other); });
104 cls.def(
"le", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.le(
other); });
105 cls.def(
"gt", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.gt(
other); });
106 cls.def(
"ge", [](ExtentBase<T, N>
const &
self, Extent<T, N>
other) {
return self.ge(
other); });
107 cls.def(
"eq", [](ExtentBase<T, N>
const &
self, T
other) {
return self.eq(
other); });
108 cls.def(
"ne", [](ExtentBase<T, N>
const &
self, T
other) {
return self.ne(
other); });
109 cls.def(
"lt", [](ExtentBase<T, N>
const &
self, T
other) {
return self.lt(
other); });
110 cls.def(
"le", [](ExtentBase<T, N>
const &
self, T
other) {
return self.le(
other); });
111 cls.def(
"gt", [](ExtentBase<T, N>
const &
self, T
other) {
return self.gt(
other); });
112 cls.def(
"ge", [](ExtentBase<T, N>
const &
self, T
other) {
return self.ge(
other); });
114 cls.def(
"asPoint", &ExtentBase<T, N>::asPoint);
115 cls.def(
"computeNorm", &ExtentBase<T, N>::computeNorm);
116 cls.def(
"computeSquaredNorm", &ExtentBase<T, N>::computeSquaredNorm);
122 template <
typename T,
int N>
123 PyExtent<T, N> declareExtent(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
125 declareExtentBase<T, N>(wrappers, suffix);
126 return wrappers.wrapType(
127 PyExtent<T, N>(wrappers.module,
name.c_str()),
128 [](
auto & mod,
auto &
cls) {
129 cls.def(py::init<T>(),
"value"_a = static_cast<T>(0));
130 cls.def(py::init<Point<int, N> const &>());
131 cls.def(py::init<Point<T, N> const &>());
132 cls.def(py::init<Extent<int, N> const &>());
133 cls.def(py::init<Extent<T, N> const &>());
134 cls.def(py::init<typename Extent<T, N>::EigenVector>());
135 cls.def(
"__neg__", [](Extent<T, N> const &self) { return -self; });
136 cls.def(
"__pos__", [](Extent<T, N>
const &
self) {
return self; });
137 cls.def(
"__mul__", [](Extent<T, N>
const &
self,
int other) {
return self *
other; },
139 cls.def(
"__mul__", [](Extent<T, N>
const &
self,
double other) {
return self *
other; },
141 cls.def(
"__rmul__", [](Extent<T, N>
const &
self,
int other) {
return self *
other; },
143 cls.def(
"__rmul__", [](Extent<T, N>
const &
self,
double other) {
return self *
other; },
146 [](Extent<T, N>
const &
self, Extent<int, N>
const &
other) {
return self +
other; },
149 [](Extent<T, N>
const &
self, Extent<double, N>
const &
other) {
return self +
other; },
152 [](Extent<T, N>
const &
self, Point<int, N>
const &
other) {
153 return self + Point<T, N>(
other);
157 [](Extent<T, N>
const &
self, Point<double, N>
const &
other) {
return self +
other; },
160 [](Extent<T, N>
const &
self, Extent<int, N>
const &
other) {
161 return self - Extent<T, N>(
other);
165 [](Extent<T, N>
const &
self, Extent<double, N>
const &
other) {
return self -
other; },
168 [](Extent<T, N>
const &
self, Extent<T, N>
const &
other) {
return self ==
other; },
171 [](Extent<T, N>
const &
self, Extent<T, N>
const &
other) {
return self !=
other; },
173 cls.def(
"clone", [](Extent<T, N>
const &
self) {
return Extent<T, N>{
self}; });
179 template <
typename T>
180 PyExtent<T, 2> declareExtent2(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
181 return wrappers.wrapType(
182 declareExtent<T, 2>(wrappers,
std::string(
"2") + suffix),
183 [](
auto & mod,
auto &
cls) {
185 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 2; });
187 cls.def(py::init<int, int>(),
"x"_a,
"y"_a);
188 cls.def(py::init<double, double>(),
"x"_a,
"y"_a);
190 auto getX = py::overload_cast<>(&Extent<T, 2>::getX, py::const_);
191 auto getY = py::overload_cast<>(&Extent<T, 2>::getY, py::const_);
192 cls.def(
"getX", getX);
193 cls.def(
"getY", getY);
194 cls.def(
"setX", &Extent<T, 2>::setX);
195 cls.def(
"setY", &Extent<T, 2>::setY);
196 cls.def_property(
"x", getX, &Extent<T, 2>::setX);
197 cls.def_property(
"y", getY, &Extent<T, 2>::setY);
203 template <
typename T>
204 PyExtent<T, 3> declareExtent3(utils::python::WrapperCollection & wrappers,
const std::string &suffix) {
205 return wrappers.wrapType(
206 declareExtent<T, 3>(wrappers,
std::string(
"3") + suffix),
207 [](
auto & mod,
auto &
cls)
mutable {
209 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 3; });
211 cls.def(py::init<int, int, int>(),
"x"_a,
"y"_a,
"z"_a);
212 cls.def(py::init<double, double, double>(),
"x"_a,
"y"_a,
"z"_a);
214 auto getX = py::overload_cast<>(&Extent<T, 3>::getX, py::const_);
215 auto getY = py::overload_cast<>(&Extent<T, 3>::getY, py::const_);
216 auto getZ = py::overload_cast<>(&Extent<T, 3>::getZ, py::const_);
217 cls.def(
"getX", getX);
218 cls.def(
"getY", getY);
219 cls.def(
"getZ", getZ);
220 cls.def(
"setX", &Extent<T, 3>::setX);
221 cls.def(
"setY", &Extent<T, 3>::setY);
222 cls.def(
"setZ", &Extent<T, 3>::setZ);
223 cls.def_property(
"x", getX, &Extent<T, 3>::setX);
224 cls.def_property(
"y", getY, &Extent<T, 3>::setY);
225 cls.def_property(
"z", getZ, &Extent<T, 3>::setZ);
236 void declareExtentOperators(utils::python::WrapperCollection & wrapper,
237 PyExtent<int, N> &clsI, PyExtent<double, N> &clsD) {
239 [clsI, clsD](
auto & mod)
mutable {
243 clsI.def(
"__floordiv__",
244 [](Extent<int, N>
const &
self,
int other) -> Extent<int, N> {
245 return floor(
self /
static_cast<double>(
other));
249 clsI.def(
"__truediv__", [](Extent<int, N>
const &
self,
double other) {
return self /
other; },
251 clsD.def(
"__truediv__", [](Extent<double, N>
const &
self,
double other) {
return self /
other; },
254 clsI.def(
"__ifloordiv__", [](Extent<int, N> &
self,
int other) -> Extent<int, N> & {
255 self =
floor(
self /
static_cast<double>(
other));
259 clsI.def(
"__itruediv__", [](Extent<int, N> &
self,
double other) {
260 PyErr_SetString(PyExc_TypeError,
"In-place true division not supported for Extent<int,N>.");
261 throw py::error_already_set();
263 clsD.def(
"__itruediv__", [](Extent<double, N> &
self,
double other) -> Extent<double, N> & {
268 clsI.def(
"__iadd__", [](Extent<int, N> &
self, Extent<int, N>
const &
other) -> Extent<int, N> & {
274 [](Extent<double, N> &
self, Extent<double, N>
const &
other) -> Extent<double, N> & {
281 [](Extent<double, N> &
self, Extent<int, N>
const &
other) -> Extent<double, N> & {
287 clsI.def(
"__isub__", [](Extent<int, N> &
self, Extent<int, N>
const &
other) -> Extent<int, N> & {
291 clsD.def(
"__isub__", [](Extent<double, N> &
self, Extent<double, N>
const &
other) -> Extent<double, N> & {
295 clsD.def(
"__isub__", [](Extent<double, N> &
self, Extent<int, N>
const &
other) -> Extent<double, N> & {
300 clsI.def(
"__imul__", [](Extent<int, N> &
self,
int other) -> Extent<int, N> & {
304 clsD.def(
"__imul__", [](Extent<double, N> &
self,
int other) -> Extent<double, N> & {
308 clsD.def(
"__imul__", [](Extent<double, N> &
self,
double other) -> Extent<double, N> & {
314 mod.def(
"truncate", truncate<N>);
315 mod.def(
"floor", floor<N>);
316 mod.def(
"ceil", ceil<N>);
318 clsD.def(
"truncate", truncate<N>);
319 clsD.def(
"floor", floor<N>);
320 clsD.def(
"ceil", ceil<N>);
325 template <
typename T,
int N>
326 void declarePointBase(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
328 declareCoordinateBase<Point<T, N>, T, N>(wrappers,
"Point" + suffix);
330 PyPointBase<T, N>(wrappers.module,
name.c_str()),
331 [](
auto & mod,
auto &
cls) {
335 cls.def(
"eq", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.eq(rhs); });
336 cls.def(
"ne", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.ne(rhs); });
337 cls.def(
"lt", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.lt(rhs); });
338 cls.def(
"le", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.le(rhs); });
339 cls.def(
"gt", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.gt(rhs); });
340 cls.def(
"ge", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.ge(rhs); });
341 cls.def(
"eq", [](PointBase<T, N>
const &
self, T rhs) {
return self.eq(rhs); });
342 cls.def(
"ne", [](PointBase<T, N>
const &
self, T rhs) {
return self.ne(rhs); });
343 cls.def(
"lt", [](PointBase<T, N>
const &
self, T rhs) {
return self.lt(rhs); });
344 cls.def(
"le", [](PointBase<T, N>
const &
self, T rhs) {
return self.le(rhs); });
345 cls.def(
"gt", [](PointBase<T, N>
const &
self, T rhs) {
return self.gt(rhs); });
346 cls.def(
"ge", [](PointBase<T, N>
const &
self, T rhs) {
return self.ge(rhs); });
348 cls.def(
"asExtent", &PointBase<T, N>::asExtent);
349 cls.def(
"shift", &PointBase<T, N>::shift);
351 cls.def(
"distanceSquared", &PointBase<T, N>::distanceSquared);
352 cls.def(
"toString", &PointBase<T, N>::toString);
358 template <
typename T,
int N>
359 PyPoint<T, N> declarePoint(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
361 declarePointBase<T, N>(wrappers, suffix);
362 return wrappers.wrapType(
363 PyPoint<T, N>(wrappers.module,
name.c_str()),
364 [](
auto & mod,
auto &
cls) {
366 cls.def(py::init<T>(),
"value"_a = static_cast<T>(0));
368 cls.def(py::init<Point<double, N> const &>());
369 cls.def(py::init<Point<int, N> const &>());
370 cls.def(py::init<Extent<T, N> const &>());
371 cls.def(py::init<typename Point<T, N>::EigenVector>());
373 cls.def(
"__add__", [](Point<T, N> const &self, Extent<double, N> &other) { return self + other; },
375 cls.def(
"__add__", [](Point<T, N>
const &
self, Extent<int, N> &
other) {
return self +
other; },
377 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<T, N> &
other) {
return self -
other; },
379 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<T, N> &
other) {
return self -
other; },
381 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<double, N> &
other) {
return self -
other; },
383 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<int, N> &
other) {
return self -
other; },
385 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<double, N> &
other) {
return self -
other; },
387 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<int, N> &
other) {
return self -
other; },
389 cls.def(
"__eq__", [](Point<T, N>
const &
self, Point<T, N>
const &
other) {
return self ==
other; },
391 cls.def(
"__ne__", [](Point<T, N>
const &
self, Point<T, N>
const &
other) {
return self !=
other; },
394 cls.def(
"clone", [](Point<T, N>
const &
self) {
return Point<T, N>{
self}; });
400 template <
typename T>
401 PyPoint<T, 2> declarePoint2(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
402 return wrappers.wrapType(
403 declarePoint<T, 2>(wrappers,
std::string(
"2") + suffix),
404 [](
auto & mod,
auto &
cls) {
406 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 2; });
408 cls.def(py::init<int, int>(),
"x"_a,
"y"_a);
409 cls.def(py::init<double, double>(),
"x"_a,
"y"_a);
411 auto getX = py::overload_cast<>(&Point<T, 2>::getX, py::const_);
412 auto getY = py::overload_cast<>(&Point<T, 2>::getY, py::const_);
413 cls.def(
"getX", getX);
414 cls.def(
"getY", getY);
415 cls.def(
"setX", &Point<T, 2>::setX);
416 cls.def(
"setY", &Point<T, 2>::setY);
417 cls.def_property(
"x", getX, &Point<T, 2>::setX);
418 cls.def_property(
"y", getY, &Point<T, 2>::setY);
424 template <
typename T>
425 PyPoint<T, 3> declarePoint3(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
426 return wrappers.wrapType(
427 declarePoint<T, 3>(wrappers,
std::string(
"3") + suffix),
428 [](
auto & mod,
auto &
cls) {
430 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 3; });
432 cls.def(py::init<int, int, int>(),
"x"_a,
"y"_a,
"z"_a);
433 cls.def(py::init<double, double, double>(),
"x"_a,
"y"_a,
"z"_a);
435 auto getX = py::overload_cast<>(&Point<T, 3>::getX, py::const_);
436 auto getY = py::overload_cast<>(&Point<T, 3>::getY, py::const_);
437 auto getZ = py::overload_cast<>(&Point<T, 3>::getZ, py::const_);
438 cls.def(
"getX", getX);
439 cls.def(
"getY", getY);
440 cls.def(
"getZ", getZ);
441 cls.def(
"setX", &Point<T, 3>::setX);
442 cls.def(
"setY", &Point<T, 3>::setY);
443 cls.def(
"setZ", &Point<T, 3>::setZ);
444 cls.def_property(
"x", getX, &Point<T, 3>::setX);
445 cls.def_property(
"y", getY, &Point<T, 3>::setY);
446 cls.def_property(
"z", getZ, &Point<T, 3>::setZ);
457 void declarePointOperators(utils::python::WrapperCollection & wrappers,
458 PyPoint<int, N> &clsI, PyPoint<double, N> &clsD) {
460 [clsI, clsD](
auto & mod)
mutable {
461 clsI.def(
"__iadd__", [](Point<int, N> &
self, Extent<int, N>
const &
other) {
465 clsD.def(
"__iadd__", [](Point<double, N> &
self, Extent<int, N>
const &
other) {
469 clsD.def(
"__iadd__", [](Point<double, N> &
self, Extent<double, N>
const &
other) {
473 clsI.def(
"__isub__", [](Point<int, N> &
self, Extent<int, N>
const &
other) {
477 clsD.def(
"__isub__", [](Point<double, N> &
self, Extent<int, N>
const &
other) {
481 clsD.def(
"__isub__", [](Point<double, N> &
self, Extent<double, N>
const &
other) {
495 declareCoordinateExpr<2>(wrappers,
"2");
496 declareCoordinateExpr<3>(wrappers,
"3");
498 auto clsExtent2I = declareExtent2<int>(wrappers,
"I");
499 auto clsExtent2D = declareExtent2<double>(wrappers,
"D");
501 auto clsExtent3I = declareExtent3<int>(wrappers,
"I");
502 auto clsExtent3D = declareExtent3<double>(wrappers,
"D");
504 auto clsPoint2I = declarePoint2<int>(wrappers,
"I");
505 auto clsPoint2D = declarePoint2<double>(wrappers,
"D");
507 auto clsPoint3I = declarePoint3<int>(wrappers,
"I");
508 auto clsPoint3D = declarePoint3<double>(wrappers,
"D");
510 declareExtentOperators(wrappers, clsExtent2I, clsExtent2D);
511 declareExtentOperators(wrappers, clsExtent3I, clsExtent3D);
512 declarePointOperators(wrappers, clsPoint2I, clsPoint2D);
513 declarePointOperators(wrappers, clsPoint3I, clsPoint3D);