fix py dense
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -9,3 +9,6 @@ compile_commands.json
|
||||
dist/
|
||||
build_python/
|
||||
src/Python/uLib/*.so*
|
||||
src/Python/uLib/*.pyd
|
||||
src/Python/uLib/*.pyc
|
||||
src/Python/uLib/__pycache__
|
||||
|
||||
@@ -117,6 +117,10 @@ bool operator!=(const MetaAllocator<T> &, const MetaAllocator<U> &) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Vector Implemetation ... wraps std::vector
|
||||
template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> {
|
||||
typedef std::vector<T, MetaAllocator<T>> BaseClass;
|
||||
@@ -136,6 +140,7 @@ public:
|
||||
Vector(unsigned int size) : BaseClass(size) {}
|
||||
Vector(unsigned int size, T &value) : BaseClass(size, value) {}
|
||||
Vector() : BaseClass(0) {}
|
||||
Vector(std::initializer_list<T> init) : BaseClass(init) {}
|
||||
|
||||
inline VectorCommaInit operator<<(T scalar) {
|
||||
return VectorCommaInit(this, scalar);
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#ifndef ULIB_DENSEMATRIX_H
|
||||
#define ULIB_DENSEMATRIX_H
|
||||
|
||||
// #include <Eigen/src/Core/Matrix.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Eigen/Dense>
|
||||
@@ -144,6 +145,11 @@ typedef Eigen::Matrix2d Matrix2d;
|
||||
typedef Eigen::Matrix3d Matrix3d;
|
||||
typedef Eigen::Matrix4d Matrix4d;
|
||||
|
||||
typedef Eigen::MatrixXi MatrixXi;
|
||||
typedef Eigen::MatrixXf MatrixXf;
|
||||
typedef Eigen::MatrixXd MatrixXd;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector String interaction ///////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -38,15 +38,15 @@ if(BUILD_TESTING)
|
||||
add_test(NAME pybind_general
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/pybind_test.py)
|
||||
set_tests_properties(pybind_general PROPERTIES
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>")
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
|
||||
|
||||
add_test(NAME pybind_core
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/core_pybind_test.py)
|
||||
set_tests_properties(pybind_core PROPERTIES
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>")
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
|
||||
|
||||
add_test(NAME pybind_math
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/math_pybind_test.py)
|
||||
set_tests_properties(pybind_math PROPERTIES
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>")
|
||||
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:uLib_python>:${PROJECT_SOURCE_DIR}/src/Python")
|
||||
endif()
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
|
||||
#include <pybind11/numpy.h>
|
||||
|
||||
#include "Math/Dense.h"
|
||||
#include "Math/Transform.h"
|
||||
#include "Math/Geometry.h"
|
||||
@@ -32,34 +34,104 @@ PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4f>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4i>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3d>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4d>);
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Voxel>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<VoxRaytracer::RayData::Element>);
|
||||
|
||||
template <typename MatrixType>
|
||||
void bind_eigen_type(py::module_ &m, const char *name) {
|
||||
using Scalar = typename MatrixType::Scalar;
|
||||
constexpr bool is_vector = MatrixType::IsVectorAtCompileTime;
|
||||
|
||||
// Default constructor (zeros)
|
||||
m.def(name, []() -> MatrixType {
|
||||
if constexpr (MatrixType::RowsAtCompileTime == Eigen::Dynamic || MatrixType::ColsAtCompileTime == Eigen::Dynamic) {
|
||||
return MatrixType(); // Empty dynamic matrix
|
||||
} else {
|
||||
return MatrixType::Zero(); // Zero static matrix
|
||||
}
|
||||
});
|
||||
|
||||
// Specialized constructor for dynamic matrices
|
||||
if constexpr (MatrixType::RowsAtCompileTime == Eigen::Dynamic || MatrixType::ColsAtCompileTime == Eigen::Dynamic) {
|
||||
m.def(name, [](int rows, int cols) -> MatrixType {
|
||||
MatrixType mat;
|
||||
mat.setZero(rows, cols);
|
||||
return mat;
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize from list
|
||||
m.def(name, [](py::list l) -> MatrixType {
|
||||
MatrixType mat;
|
||||
if constexpr (is_vector) {
|
||||
mat.setZero(l.size());
|
||||
for (size_t i = 0; i < l.size(); ++i) {
|
||||
mat(i) = l[i].cast<Scalar>();
|
||||
}
|
||||
} else {
|
||||
int rows = MatrixType::RowsAtCompileTime == Eigen::Dynamic ? (int)std::sqrt(l.size()) : MatrixType::RowsAtCompileTime;
|
||||
int cols = MatrixType::ColsAtCompileTime == Eigen::Dynamic ? (int)std::sqrt(l.size()) : MatrixType::ColsAtCompileTime;
|
||||
mat.setZero(rows, cols);
|
||||
for (size_t i = 0; i < (size_t)l.size(); ++i) {
|
||||
mat(i / cols, i % cols) = l[i].cast<Scalar>();
|
||||
}
|
||||
}
|
||||
return mat;
|
||||
});
|
||||
|
||||
// Initialize from py::array
|
||||
m.def(name, [](py::array_t<Scalar, py::array::c_style | py::array::forcecast> arr) -> MatrixType {
|
||||
auto buf = arr.request();
|
||||
MatrixType mat;
|
||||
if constexpr (is_vector) {
|
||||
mat.setZero(buf.size);
|
||||
Scalar* ptr = static_cast<Scalar*>(buf.ptr);
|
||||
for (ssize_t i = 0; i < buf.size; ++i) mat(i) = ptr[i];
|
||||
} else {
|
||||
int rows = buf.shape.size() > 0 ? (int)buf.shape[0] : 1;
|
||||
int cols = buf.shape.size() > 1 ? (int)buf.shape[1] : 1;
|
||||
mat.setZero(rows, cols);
|
||||
Scalar* ptr = static_cast<Scalar*>(buf.ptr);
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
for (int j = 0; j < cols; ++j) {
|
||||
mat(i, j) = ptr[i * cols + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return mat;
|
||||
});
|
||||
}
|
||||
|
||||
void init_math(py::module_ &m) {
|
||||
|
||||
// 1. Basic Eigen Types (Vectors and Matrices)
|
||||
py::class_<Vector1f>(m, "Vector1f").def(py::init<>());
|
||||
py::class_<Vector2f>(m, "Vector2f").def(py::init<>());
|
||||
py::class_<Vector3f>(m, "Vector3f").def(py::init<>());
|
||||
py::class_<Vector4f>(m, "Vector4f").def(py::init<>());
|
||||
py::class_<Vector1i>(m, "Vector1i").def(py::init<>());
|
||||
py::class_<Vector2i>(m, "Vector2i").def(py::init<>());
|
||||
py::class_<Vector3i>(m, "Vector3i").def(py::init<>());
|
||||
py::class_<Vector4i>(m, "Vector4i").def(py::init<>());
|
||||
py::class_<Vector1d>(m, "Vector1d").def(py::init<>());
|
||||
py::class_<Vector2d>(m, "Vector2d").def(py::init<>());
|
||||
py::class_<Vector3d>(m, "Vector3d").def(py::init<>());
|
||||
py::class_<Vector4d>(m, "Vector4d").def(py::init<>());
|
||||
bind_eigen_type<Vector1f>(m, "Vector1f");
|
||||
bind_eigen_type<Vector2f>(m, "Vector2f");
|
||||
bind_eigen_type<Vector3f>(m, "Vector3f");
|
||||
bind_eigen_type<Vector4f>(m, "Vector4f");
|
||||
bind_eigen_type<Vector1i>(m, "Vector1i");
|
||||
bind_eigen_type<Vector2i>(m, "Vector2i");
|
||||
bind_eigen_type<Vector3i>(m, "Vector3i");
|
||||
bind_eigen_type<Vector4i>(m, "Vector4i");
|
||||
bind_eigen_type<Vector1d>(m, "Vector1d");
|
||||
bind_eigen_type<Vector2d>(m, "Vector2d");
|
||||
bind_eigen_type<Vector3d>(m, "Vector3d");
|
||||
bind_eigen_type<Vector4d>(m, "Vector4d");
|
||||
|
||||
py::class_<Matrix2f>(m, "Matrix2f").def(py::init<>());
|
||||
py::class_<Matrix3f>(m, "Matrix3f").def(py::init<>());
|
||||
py::class_<Matrix4f>(m, "Matrix4f").def(py::init<>());
|
||||
py::class_<Matrix2i>(m, "Matrix2i").def(py::init<>());
|
||||
py::class_<Matrix3i>(m, "Matrix3i").def(py::init<>());
|
||||
py::class_<Matrix4i>(m, "Matrix4i").def(py::init<>());
|
||||
py::class_<Matrix2d>(m, "Matrix2d").def(py::init<>());
|
||||
py::class_<Matrix3d>(m, "Matrix3d").def(py::init<>());
|
||||
py::class_<Matrix4d>(m, "Matrix4d").def(py::init<>());
|
||||
bind_eigen_type<Matrix2f>(m, "Matrix2f");
|
||||
bind_eigen_type<Matrix3f>(m, "Matrix3f");
|
||||
bind_eigen_type<Matrix4f>(m, "Matrix4f");
|
||||
bind_eigen_type<Matrix2i>(m, "Matrix2i");
|
||||
bind_eigen_type<Matrix3i>(m, "Matrix3i");
|
||||
bind_eigen_type<Matrix4i>(m, "Matrix4i");
|
||||
bind_eigen_type<Matrix2d>(m, "Matrix2d");
|
||||
bind_eigen_type<Matrix3d>(m, "Matrix3d");
|
||||
bind_eigen_type<Matrix4d>(m, "Matrix4d");
|
||||
|
||||
bind_eigen_type<MatrixXi>(m, "MatrixXi");
|
||||
bind_eigen_type<MatrixXf>(m, "MatrixXf");
|
||||
bind_eigen_type<MatrixXd>(m, "MatrixXd");
|
||||
|
||||
// 2. Homogeneous types
|
||||
py::class_<HPoint3f>(m, "HPoint3f")
|
||||
|
||||
@@ -10,6 +10,67 @@ def vector4f0(v, target):
|
||||
diff[3] = 0 # ignoring w
|
||||
return np.all(np.abs(diff) < 0.001)
|
||||
|
||||
|
||||
class TestMathMatrix(unittest.TestCase):
|
||||
|
||||
def test_matrix(self):
|
||||
def check_1234(m2f):
|
||||
self.assertEqual(m2f[0, 0], 1)
|
||||
self.assertEqual(m2f[0, 1], 2)
|
||||
self.assertEqual(m2f[1, 0], 3)
|
||||
self.assertEqual(m2f[1, 1], 4)
|
||||
|
||||
m2f = uLib.Math.Matrix2f()
|
||||
m2f[0, 0] = 1
|
||||
m2f[0, 1] = 2
|
||||
m2f[1, 0] = 3
|
||||
m2f[1, 1] = 4
|
||||
check_1234(m2f)
|
||||
|
||||
m2f = uLib.Math.Matrix2f([1, 2, 3, 4])
|
||||
check_1234(m2f)
|
||||
|
||||
# m2f = uLib.Math.Matrix2f([[1, 2], [3, 4]])
|
||||
# check_1234(m2f)
|
||||
|
||||
m2f = uLib.Math.Matrix2f(np.array([[1, 2], [3, 4]]))
|
||||
check_1234(m2f)
|
||||
|
||||
def test_vector2(self):
|
||||
v2f = uLib.Math.Vector2f()
|
||||
v2f[0] = 1
|
||||
v2f[1] = 2
|
||||
self.assertEqual(v2f[0], 1)
|
||||
self.assertEqual(v2f[1], 2)
|
||||
|
||||
v2f = uLib.Math.Vector2f([1, 2])
|
||||
self.assertEqual(v2f[0], 1)
|
||||
self.assertEqual(v2f[1], 2)
|
||||
|
||||
v2f = uLib.Math.Vector2f(np.array([1, 2]))
|
||||
self.assertEqual(v2f[0], 1)
|
||||
self.assertEqual(v2f[1], 2)
|
||||
|
||||
def test_vector3(self):
|
||||
v3f = uLib.Math.Vector3f()
|
||||
v3f[0] = 1
|
||||
v3f[1] = 2
|
||||
v3f[2] = 3
|
||||
self.assertEqual(v3f[0], 1)
|
||||
self.assertEqual(v3f[1], 2)
|
||||
self.assertEqual(v3f[2], 3)
|
||||
|
||||
v3f = uLib.Math.Vector3f([1, 2, 3])
|
||||
self.assertEqual(v3f[0], 1)
|
||||
self.assertEqual(v3f[1], 2)
|
||||
self.assertEqual(v3f[2], 3)
|
||||
|
||||
v3f = uLib.Math.Vector3f(np.array([1, 2, 3]))
|
||||
self.assertEqual(v3f[0], 1)
|
||||
self.assertEqual(v3f[1], 2)
|
||||
self.assertEqual(v3f[2], 3)
|
||||
|
||||
|
||||
class TestMathGeometry(unittest.TestCase):
|
||||
def test_geometry(self):
|
||||
Geo = uLib.Math.Geometry()
|
||||
|
||||
Reference in New Issue
Block a user