From 53ec73dd1a33657e909ddbeac721657c1a6a7aed Mon Sep 17 00:00:00 2001 From: Samuel Felton Date: Thu, 30 Nov 2023 15:35:31 +0100 Subject: [PATCH] Add 1D indexing for col/row/translation vector, correct np representation for translationVector --- .../python/bindings/include/core/arrays.hpp | 145 +++++++++++++----- modules/python/config/core.json | 1 + 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/modules/python/bindings/include/core/arrays.hpp b/modules/python/bindings/include/core/arrays.hpp index 52dd774144..20274f2e22 100644 --- a/modules/python/bindings/include/core/arrays.hpp +++ b/modules/python/bindings/include/core/arrays.hpp @@ -77,6 +77,11 @@ py::buffer_info get_buffer_info(vpRowVector &array) return make_array_buffer(array.data, { array.getCols() }, false); } template<> +py::buffer_info get_buffer_info(vpTranslationVector &array) +{ + return make_array_buffer(array.data, { 3 }, false); +} +template<> py::buffer_info get_buffer_info(vpRotationMatrix &array) { return make_array_buffer(array.data, { array.getRows(), array.getCols() }, true); @@ -123,7 +128,7 @@ void define_get_item_2d_array(PyClass &pyClass) } return (py::cast(self).template cast >())[py::cast(i)].template cast>(); }); - pyClass.def("__getitem__", [](const Class &self, py::slice slice) -> np_array_cf { + pyClass.def("__getitem__", [](const Class &self, py::slice slice) -> py::array_t { return (py::cast(self).template cast >())[slice].template cast>(); }); pyClass.def("__getitem__", [](const Class &self, py::tuple tuple) { @@ -131,6 +136,31 @@ void define_get_item_2d_array(PyClass &pyClass) }); } +/* + * Array 2D indexing + */ +template +void define_get_item_1d_array(PyClass &pyClass) +{ + pyClass.def("__getitem__", [](const Class &self, int i) -> Item { + + const int elems = (int)self.getRows() * (int)self.getCols(); + if (i >= elems || i < -elems) { + std::stringstream ss; + ss << "Invalid indexing into a 1D array: got indices " << shape_to_string({ i }) + << " but array has dimensions " << shape_to_string({ elems }); + throw std::runtime_error(ss.str()); + } + if (i < 0) { + i = elems + i; + } + return self[i]; + }); + pyClass.def("__getitem__", [](const Class &self, py::slice slice) -> py::array_t { + return (py::cast(self).template cast >())[slice].template cast>(); + }); +} + const char *numpy_fn_doc_writable = R"doc( Numpy view of the underlying array data. This numpy view can be used to directly modify the array. @@ -191,47 +221,6 @@ Construct a matrix by **copying** a 2D numpy array. define_get_item_2d_array>, vpMatrix, double>(pyMatrix); } -void bindings_vpColVector(py::class_> &pyColVector) -{ - pyColVector.def_buffer(&get_buffer_info); - - pyColVector.def("numpy", [](vpColVector &self) -> np_array_cf { - return py::cast(self).cast>(); - }, numpy_fn_doc_writable); - - pyColVector.def(py::init([](np_array_cf np_array) { - verify_array_shape_and_dims(np_array, 1, "ViSP column vector"); - const std::vector shape = np_array.request().shape; - vpColVector result(shape[0]); - copy_data_from_np(np_array, result.data); - return result; - }), R"doc( -Construct a column vector by **copying** a 1D numpy array. - -:param np_array: The numpy 1D array to copy. - -)doc", py::arg("np_array")); -} - -void bindings_vpRowVector(py::class_> &pyRowVector) -{ - pyRowVector.def_buffer(&get_buffer_info); - pyRowVector.def("numpy", [](vpRowVector &self) -> np_array_cf { - return np_array_cf(get_buffer_info(self), py::cast(self)); - }, numpy_fn_doc_writable); - pyRowVector.def(py::init([](np_array_cf np_array) { - verify_array_shape_and_dims(np_array, 1, "ViSP row vector"); - const std::vector shape = np_array.request().shape; - vpRowVector result(shape[0]); - copy_data_from_np(np_array, result.data); - return result; - }), R"doc( -Construct a row vector by **copying** a 1D numpy array. - -:param np_array: The numpy 1D array to copy. - -)doc", py::arg("np_array")); -} void bindings_vpRotationMatrix(py::class_> &pyRotationMatrix) { @@ -287,4 +276,76 @@ If it is not a homogeneous matrix, an exception will be raised. define_get_item_2d_array>, vpHomogeneousMatrix, double>(pyHomogeneousMatrix); } + + +void bindings_vpTranslationVector(py::class_> &pyTranslationVector) +{ + pyTranslationVector.def_buffer(&get_buffer_info); + + pyTranslationVector.def("numpy", [](vpTranslationVector &self) -> np_array_cf { + return py::cast(self).cast>(); + }, numpy_fn_doc_writable); + + pyTranslationVector.def(py::init([](np_array_cf np_array) { + verify_array_shape_and_dims(np_array, { 3 }, "ViSP translation vector"); + const std::vector shape = np_array.request().shape; + vpTranslationVector result; + copy_data_from_np(np_array, result.data); + return result; + }), R"doc( +Construct a Translation vector by **copying** a 1D numpy array of size 3. + +:param np_array: The numpy 1D array to copy. + +)doc", py::arg("np_array")); + define_get_item_1d_array>, vpTranslationVector, double>(pyTranslationVector); +} + + +void bindings_vpColVector(py::class_> &pyColVector) +{ + pyColVector.def_buffer(&get_buffer_info); + + pyColVector.def("numpy", [](vpColVector &self) -> np_array_cf { + return py::cast(self).cast>(); + }, numpy_fn_doc_writable); + + pyColVector.def(py::init([](np_array_cf np_array) { + verify_array_shape_and_dims(np_array, 1, "ViSP column vector"); + const std::vector shape = np_array.request().shape; + vpColVector result(shape[0]); + copy_data_from_np(np_array, result.data); + return result; + }), R"doc( +Construct a column vector by **copying** a 1D numpy array. + +:param np_array: The numpy 1D array to copy. + +)doc", py::arg("np_array")); + define_get_item_1d_array>, vpColVector, double>(pyColVector); + +} + +void bindings_vpRowVector(py::class_> &pyRowVector) +{ + pyRowVector.def_buffer(&get_buffer_info); + pyRowVector.def("numpy", [](vpRowVector &self) -> np_array_cf { + return np_array_cf(get_buffer_info(self), py::cast(self)); + }, numpy_fn_doc_writable); + pyRowVector.def(py::init([](np_array_cf np_array) { + verify_array_shape_and_dims(np_array, 1, "ViSP row vector"); + const std::vector shape = np_array.request().shape; + vpRowVector result(shape[0]); + copy_data_from_np(np_array, result.data); + return result; + }), R"doc( +Construct a row vector by **copying** a 1D numpy array. + +:param np_array: The numpy 1D array to copy. + +)doc", py::arg("np_array")); + define_get_item_1d_array>, vpRowVector, double>(pyRowVector); +} + + #endif diff --git a/modules/python/config/core.json b/modules/python/config/core.json index 2b781d25b3..62059157bc 100644 --- a/modules/python/config/core.json +++ b/modules/python/config/core.json @@ -94,6 +94,7 @@ ] }, "vpTranslationVector": { + "additional_bindings": "bindings_vpTranslationVector", "methods": [ {