Commit 7bdcaf57 authored by Jan Möbius's avatar Jan Möbius

Implemetnation of Matrix4x4 python type caster

parent 0c5cd310
......@@ -168,7 +168,7 @@ namespace pybind11 { namespace detail {
return true;
} else {
PyErr_SetString(PyExc_RuntimeError, "Vector Conversion: Not a list or a tuple.");
PyErr_SetString(PyExc_RuntimeError, "Vector Conversion: Not a list or a tuple or a numpy array.");
throw py::error_already_set();
return false;
}
......@@ -186,12 +186,141 @@ namespace pybind11 { namespace detail {
*/
static handle cast(Vector src, return_value_policy /* policy */, handle parent ) {
// Create numpy array
// py::array a({3,1}, src.data());
py::array a(3, src.data());
return a.release();
// return PyTuple_Pack(3, PyFloat_FromDouble(src[0]),PyFloat_FromDouble(src[1]),PyFloat_FromDouble(src[2]));
}
};
}} // namespace pybind11::detail
namespace pybind11 { namespace detail {
template <> struct type_caster<Matrix4x4> {
public:
/**
* This macro establishes the name 'str' in
* function signatures and declares a local variable
* 'value' of type Matrix4x4
*/
PYBIND11_TYPE_CASTER(Matrix4x4, _("Matrix4x4"));
/**
* Conversion part 1 (Python->C++): convert a PyObject into a Matrix4x4
* instance or return false upon failure. The second argument
* indicates whether implicit conversions should be applied.
*/
bool load(handle src, bool convert ) {
/* Extract PyObject from handle */
PyObject* source = src.ptr();
if ( PyList_Check(source) ) {
if ( PyList_Size(source) != 16) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: List size should be 16!");
throw py::error_already_set();
return false;
}
double convert[16] = { PyFloat_AsDouble(PyList_GetItem(source,0)),
PyFloat_AsDouble(PyList_GetItem(source,1)),
PyFloat_AsDouble(PyList_GetItem(source,2)),
PyFloat_AsDouble(PyList_GetItem(source,3)),
PyFloat_AsDouble(PyList_GetItem(source,4)),
PyFloat_AsDouble(PyList_GetItem(source,5)),
PyFloat_AsDouble(PyList_GetItem(source,6)),
PyFloat_AsDouble(PyList_GetItem(source,7)),
PyFloat_AsDouble(PyList_GetItem(source,8)),
PyFloat_AsDouble(PyList_GetItem(source,9)),
PyFloat_AsDouble(PyList_GetItem(source,0)),
PyFloat_AsDouble(PyList_GetItem(source,11)),
PyFloat_AsDouble(PyList_GetItem(source,12)),
PyFloat_AsDouble(PyList_GetItem(source,13)),
PyFloat_AsDouble(PyList_GetItem(source,14))};
/* Now convert into a C++ Matrix4x4 */
value = Matrix4x4(convert);
} else if ( PyTuple_Check(source) ) {
if ( PyTuple_Size(source) != 16) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Tuple size should be 3!");
throw py::error_already_set();
return false;
}
double convert[16] = { PyFloat_AsDouble(PyTuple_GetItem(source,0)),
PyFloat_AsDouble(PyTuple_GetItem(source,1)),
PyFloat_AsDouble(PyTuple_GetItem(source,2)),
PyFloat_AsDouble(PyTuple_GetItem(source,3)),
PyFloat_AsDouble(PyTuple_GetItem(source,4)),
PyFloat_AsDouble(PyTuple_GetItem(source,5)),
PyFloat_AsDouble(PyTuple_GetItem(source,6)),
PyFloat_AsDouble(PyTuple_GetItem(source,7)),
PyFloat_AsDouble(PyTuple_GetItem(source,8)),
PyFloat_AsDouble(PyTuple_GetItem(source,9)),
PyFloat_AsDouble(PyTuple_GetItem(source,0)),
PyFloat_AsDouble(PyTuple_GetItem(source,11)),
PyFloat_AsDouble(PyTuple_GetItem(source,12)),
PyFloat_AsDouble(PyTuple_GetItem(source,13)),
PyFloat_AsDouble(PyTuple_GetItem(source,14)) };
/* Now convert into a C++ Matrix4x4 */
value = Matrix4x4(convert);
} else if ( py::cast<py::array>(source) ) {
py::array array = py::cast<py::array>(source);
if ( array.size() != 16) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Numpy Array size should be 16!");
throw py::error_already_set();
return false;
}
if (!convert && !py::array_t<double>::check_(src)) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Numpy Array, wrong dtype, conversion disabled");
return false;
}
auto buf = py::array_t<double, py::array::c_style | py::array::forcecast>::ensure(src);
if (!buf) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Numpy Array, conversion failed.");
return false;
}
// Check Dimension : Matrix has 2 dimensions
// Check buffer size : 4x4 -> 16 entries
// Check shape : 2 dimensions, each has size 4
if (buf.ndim() != 2 || buf.size() != 16 || buf.shape()[0] !=4 || buf.shape()[1] !=4) {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Numpy Array dimension or size error. Dimension should be four, size 16, and shape 4x4!");
return false;
}
value = Matrix4x4(buf.data());
return true;
} else {
PyErr_SetString(PyExc_RuntimeError, "Matrix4x4 Conversion: Not a list or a tuple or a numpy array.");
throw py::error_already_set();
return false;
}
/* Ensure return code was OK (to avoid out-of-range errors etc) */
return ( !PyErr_Occurred() );
}
/**
* Conversion part 2 (C++ -> Python): convert an Matrix4x4 instance into
* a Python object. The second and third arguments are used to
* indicate the return value policy and parent object (for
* ``return_value_policy::reference_internal``) and are generally
* ignored by implicit casters.
*/
static handle cast(Matrix4x4 src, return_value_policy /* policy */, handle parent ) {
// Create numpy array
py::array a({4,4}, src.data());
return a.release();
}
};
}} // namespace pybind11::detail
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment