22 #include "pybind11/pybind11.h" 23 #include "pybind11/eigen.h" 24 #include "ndarray/pybind11.h" 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 {
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) {
76 static std::string const name =
"CoordinateExpr" + 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) {
93 static std::string const name =
"ExtentBase" + 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));
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 cls.def(
"getX", [](Extent<T, 2>
const &
self) {
return self[0]; });
191 cls.def(
"getY", [](Extent<T, 2>
const &
self) {
return self[1]; });
192 cls.def(
"setX", [](Extent<T, 2> &
self, T other) {
self[0] =
other; });
193 cls.def(
"setY", [](Extent<T, 2> &
self, T other) {
self[1] =
other; });
199 template <
typename T>
200 PyExtent<T, 3> declareExtent3(utils::python::WrapperCollection & wrappers,
const std::string &suffix) {
201 return wrappers.wrapType(
202 declareExtent<T, 3>(wrappers,
std::string(
"3") + suffix),
203 [](
auto & mod,
auto &
cls)
mutable {
205 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 3; });
207 cls.def(py::init<int, int, int>(),
"x"_a,
"y"_a,
"z"_a);
208 cls.def(py::init<double, double, double>(),
"x"_a,
"y"_a,
"z"_a);
210 cls.def(
"getX", [](Extent<T, 3>
const &
self) {
return self[0]; });
211 cls.def(
"getY", [](Extent<T, 3>
const &
self) {
return self[1]; });
212 cls.def(
"getZ", [](Extent<T, 3>
const &
self) {
return self[2]; });
213 cls.def(
"setX", [](Extent<T, 3> &
self, T other) {
self[0] =
other; });
214 cls.def(
"setY", [](Extent<T, 3> &
self, T other) {
self[1] =
other; });
215 cls.def(
"setZ", [](Extent<T, 3> &
self, T other) {
self[2] =
other; });
226 void declareExtentOperators(utils::python::WrapperCollection & wrapper,
227 PyExtent<int, N> &clsI, PyExtent<double, N> &clsD) {
229 [clsI, clsD](
auto & mod)
mutable {
233 clsI.def(
"__floordiv__",
234 [](Extent<int, N>
const &
self,
int other) -> Extent<int, N> {
235 return floor(
self / static_cast<double>(other));
239 clsI.def(
"__truediv__", [](Extent<int, N>
const &
self,
double other) {
return self /
other; },
241 clsD.def(
"__truediv__", [](Extent<double, N>
const &
self,
double other) {
return self /
other; },
244 clsI.def(
"__ifloordiv__", [](Extent<int, N> &
self,
int other) -> Extent<int, N> & {
245 self =
floor(
self / static_cast<double>(other));
249 clsI.def(
"__itruediv__", [](Extent<int, N> &
self,
double other) {
250 PyErr_SetString(PyExc_TypeError,
"In-place true division not supported for Extent<int,N>.");
251 throw py::error_already_set();
253 clsD.def(
"__itruediv__", [](Extent<double, N> &
self,
double other) -> Extent<double, N> & {
258 clsI.def(
"__iadd__", [](Extent<int, N> &
self, Extent<int, N>
const &other) -> Extent<int, N> & {
264 [](Extent<double, N> &
self, Extent<double, N>
const &other) -> Extent<double, N> & {
271 [](Extent<double, N> &
self, Extent<int, N>
const &other) -> Extent<double, N> & {
277 clsI.def(
"__isub__", [](Extent<int, N> &
self, Extent<int, N>
const &other) -> Extent<int, N> & {
281 clsD.def(
"__isub__", [](Extent<double, N> &
self, Extent<double, N>
const &other) -> Extent<double, N> & {
285 clsD.def(
"__isub__", [](Extent<double, N> &
self, Extent<int, N>
const &other) -> Extent<double, N> & {
290 clsI.def(
"__imul__", [](Extent<int, N> &
self,
int other) -> Extent<int, N> & {
294 clsD.def(
"__imul__", [](Extent<double, N> &
self,
int other) -> Extent<double, N> & {
298 clsD.def(
"__imul__", [](Extent<double, N> &
self,
double other) -> Extent<double, N> & {
304 mod.def(
"truncate", truncate<N>);
305 mod.def(
"floor", floor<N>);
306 mod.def(
"ceil", ceil<N>);
308 clsD.def(
"truncate", truncate<N>);
309 clsD.def(
"floor", floor<N>);
310 clsD.def(
"ceil", ceil<N>);
315 template <
typename T,
int N>
316 void declarePointBase(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
317 static std::string const name =
"PointBase" + suffix;
318 declareCoordinateBase<Point<T, N>, T, N>(wrappers,
"Point" + suffix);
320 PyPointBase<T, N>(wrappers.module, name.
c_str()),
321 [](
auto & mod,
auto &
cls) {
325 cls.def(
"eq", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.eq(rhs); });
326 cls.def(
"ne", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.ne(rhs); });
327 cls.def(
"lt", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.lt(rhs); });
328 cls.def(
"le", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.le(rhs); });
329 cls.def(
"gt", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.gt(rhs); });
330 cls.def(
"ge", [](PointBase<T, N>
const &
self, Point<T, N>
const &rhs) {
return self.ge(rhs); });
331 cls.def(
"eq", [](PointBase<T, N>
const &
self, T rhs) {
return self.eq(rhs); });
332 cls.def(
"ne", [](PointBase<T, N>
const &
self, T rhs) {
return self.ne(rhs); });
333 cls.def(
"lt", [](PointBase<T, N>
const &
self, T rhs) {
return self.lt(rhs); });
334 cls.def(
"le", [](PointBase<T, N>
const &
self, T rhs) {
return self.le(rhs); });
335 cls.def(
"gt", [](PointBase<T, N>
const &
self, T rhs) {
return self.gt(rhs); });
336 cls.def(
"ge", [](PointBase<T, N>
const &
self, T rhs) {
return self.ge(rhs); });
338 cls.def(
"asExtent", &PointBase<T, N>::asExtent);
339 cls.def(
"shift", &PointBase<T, N>::shift);
341 cls.def(
"distanceSquared", &PointBase<T, N>::distanceSquared);
342 cls.def(
"toString", &PointBase<T, N>::toString);
348 template <
typename T,
int N>
349 PyPoint<T, N> declarePoint(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
351 declarePointBase<T, N>(wrappers, suffix);
352 return wrappers.wrapType(
353 PyPoint<T, N>(wrappers.module, name.
c_str()),
354 [](
auto & mod,
auto &
cls) {
356 cls.def(py::init<T>(),
"value"_a = static_cast<T>(0));
361 cls.def(
py::init<
typename Point<T, N>::EigenVector>());
363 cls.def(
"__add__", [](Point<T, N>
const &
self, Extent<double, N> &other) {
return self +
other; },
365 cls.def(
"__add__", [](Point<T, N>
const &
self, Extent<int, N> &other) {
return self +
other; },
367 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<T, N> &other) {
return self -
other; },
369 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<T, N> &other) {
return self -
other; },
371 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<double, N> &other) {
return self -
other; },
373 cls.def(
"__sub__", [](Point<T, N>
const &
self, Point<int, N> &other) {
return self -
other; },
375 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<double, N> &other) {
return self -
other; },
377 cls.def(
"__sub__", [](Point<T, N>
const &
self, Extent<int, N> &other) {
return self -
other; },
379 cls.def(
"__eq__", [](Point<T, N>
const &
self, Point<T, N>
const &other) {
return self ==
other; },
381 cls.def(
"__ne__", [](Point<T, N>
const &
self, Point<T, N>
const &other) {
return self !=
other; },
384 cls.def(
"clone", [](Point<T, N>
const &
self) {
return Point<T, N>{
self}; });
390 template <
typename T>
391 PyPoint<T, 2> declarePoint2(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
392 return wrappers.wrapType(
393 declarePoint<T, 2>(wrappers,
std::string(
"2") + suffix),
394 [](
auto & mod,
auto &
cls) {
396 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 2; });
398 cls.def(py::init<int, int>(),
"x"_a,
"y"_a);
399 cls.def(py::init<double, double>(),
"x"_a,
"y"_a);
401 cls.def(
"getX", [](Point<T, 2>
const &
self) {
return self[0]; });
402 cls.def(
"getY", [](Point<T, 2>
const &
self) {
return self[1]; });
403 cls.def(
"setX", [](Point<T, 2> &
self, T other) {
self[0] =
other; });
404 cls.def(
"setY", [](Point<T, 2> &
self, T other) {
self[1] =
other; });
410 template <
typename T>
411 PyPoint<T, 3> declarePoint3(utils::python::WrapperCollection & wrappers,
std::string const &suffix) {
412 return wrappers.wrapType(
413 declarePoint<T, 3>(wrappers,
std::string(
"3") + suffix),
414 [](
auto & mod,
auto &
cls) {
416 cls.def_property_readonly_static(
"dimensions", [](py::object ) {
return 3; });
418 cls.def(py::init<int, int, int>(),
"x"_a,
"y"_a,
"z"_a);
419 cls.def(py::init<double, double, double>(),
"x"_a,
"y"_a,
"z"_a);
421 cls.def(
"getX", [](Point<T, 3>
const &
self) {
return self[0]; });
422 cls.def(
"getY", [](Point<T, 3>
const &
self) {
return self[1]; });
423 cls.def(
"getZ", [](Point<T, 3>
const &
self) {
return self[2]; });
424 cls.def(
"setX", [](Point<T, 3> &
self, T other) {
self[0] =
other; });
425 cls.def(
"setY", [](Point<T, 3> &
self, T other) {
self[1] =
other; });
426 cls.def(
"setZ", [](Point<T, 3> &
self, T other) {
self[2] =
other; });
437 void declarePointOperators(utils::python::WrapperCollection & wrappers,
438 PyPoint<int, N> &clsI, PyPoint<double, N> &clsD) {
440 [clsI, clsD](
auto & mod)
mutable {
441 clsI.def(
"__iadd__", [](Point<int, N> &
self, Extent<int, N>
const &other) {
445 clsD.def(
"__iadd__", [](Point<double, N> &
self, Extent<int, N>
const &other) {
449 clsD.def(
"__iadd__", [](Point<double, N> &
self, Extent<double, N>
const &other) {
453 clsI.def(
"__isub__", [](Point<int, N> &
self, Extent<int, N>
const &other) {
457 clsD.def(
"__isub__", [](Point<double, N> &
self, Extent<int, N>
const &other) {
461 clsD.def(
"__isub__", [](Point<double, N> &
self, Extent<double, N>
const &other) {
475 declareCoordinateExpr<2>(wrappers,
"2");
476 declareCoordinateExpr<3>(wrappers,
"3");
478 auto clsExtent2I = declareExtent2<int>(wrappers,
"I");
479 auto clsExtent2D = declareExtent2<double>(wrappers,
"D");
481 auto clsExtent3I = declareExtent3<int>(wrappers,
"I");
482 auto clsExtent3D = declareExtent3<double>(wrappers,
"D");
484 auto clsPoint2I = declarePoint2<int>(wrappers,
"I");
485 auto clsPoint2D = declarePoint2<double>(wrappers,
"D");
487 auto clsPoint3I = declarePoint3<int>(wrappers,
"I");
488 auto clsPoint3D = declarePoint3<double>(wrappers,
"D");
490 declareExtentOperators(wrappers, clsExtent2I, clsExtent2D);
491 declareExtentOperators(wrappers, clsExtent3I, clsExtent3D);
492 declarePointOperators(wrappers, clsPoint2I, clsPoint2D);
493 declarePointOperators(wrappers, clsPoint3I, clsPoint3D);
std::size_t cppIndex(std::ptrdiff_t size, std::ptrdiff_t i)
Compute a C++ index from a Python index (negative values count from the end) and range-check.
def scale(algorithm, min, max=None, frame=None)
void wrapCoordinates(utils::python::WrapperCollection &wrappers)
A base class for image defects.
Extent< int, N > floor(Extent< double, N > const &input) noexcept
Return the component-wise floor (round towards more negative).
ItemVariant const * other
A helper class for subdividing pybind11 module across multiple translation units (i.e.