andrea-dev #1

Merged
andrea merged 19 commits from andrea-dev into main 2026-03-06 17:17:52 +01:00
8 changed files with 174 additions and 37 deletions
Showing only changes of commit 42db99759f - Show all commits

3
.gitignore vendored
View File

@@ -9,3 +9,6 @@ compile_commands.json
dist/ dist/
build_python/ build_python/
src/Python/uLib/*.so* src/Python/uLib/*.so*
src/Python/uLib/*.pyd
src/Python/uLib/*.pyc
src/Python/uLib/__pycache__

View File

@@ -117,6 +117,10 @@ bool operator!=(const MetaAllocator<T> &, const MetaAllocator<U> &) {
return false; return false;
} }
// Vector Implemetation ... wraps std::vector // Vector Implemetation ... wraps std::vector
template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> { template <typename T> class Vector : public std::vector<T, MetaAllocator<T>> {
typedef std::vector<T, MetaAllocator<T>> BaseClass; typedef std::vector<T, MetaAllocator<T>> BaseClass;
@@ -136,6 +140,7 @@ public:
Vector(unsigned int size) : BaseClass(size) {} Vector(unsigned int size) : BaseClass(size) {}
Vector(unsigned int size, T &value) : BaseClass(size, value) {} Vector(unsigned int size, T &value) : BaseClass(size, value) {}
Vector() : BaseClass(0) {} Vector() : BaseClass(0) {}
Vector(std::initializer_list<T> init) : BaseClass(init) {}
inline VectorCommaInit operator<<(T scalar) { inline VectorCommaInit operator<<(T scalar) {
return VectorCommaInit(this, scalar); return VectorCommaInit(this, scalar);

View File

@@ -47,6 +47,7 @@
#ifndef ULIB_DENSEMATRIX_H #ifndef ULIB_DENSEMATRIX_H
#define ULIB_DENSEMATRIX_H #define ULIB_DENSEMATRIX_H
// #include <Eigen/src/Core/Matrix.h>
#include <stdlib.h> #include <stdlib.h>
#include <Eigen/Dense> #include <Eigen/Dense>
@@ -144,6 +145,11 @@ typedef Eigen::Matrix2d Matrix2d;
typedef Eigen::Matrix3d Matrix3d; typedef Eigen::Matrix3d Matrix3d;
typedef Eigen::Matrix4d Matrix4d; typedef Eigen::Matrix4d Matrix4d;
typedef Eigen::MatrixXi MatrixXi;
typedef Eigen::MatrixXf MatrixXf;
typedef Eigen::MatrixXd MatrixXd;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Vector String interaction /////////////////////////////////////////////////// // Vector String interaction ///////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@@ -185,7 +191,7 @@ std::string VectorxT_ToString(const Eigen::Matrix<T, size, 1> &vec) {
// } // }
template <typename T, int size> template <typename T, int size>
void operator>>(std::string &str, Eigen::Matrix<T, size, 1> &vec) { void operator >> (std::string &str, Eigen::Matrix<T, size, 1> &vec) {
VectorxT_StringTo(vec, str); VectorxT_StringTo(vec, str);
} }

View File

@@ -38,15 +38,15 @@ if(BUILD_TESTING)
add_test(NAME pybind_general add_test(NAME pybind_general
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/pybind_test.py) COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/pybind_test.py)
set_tests_properties(pybind_general PROPERTIES 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 add_test(NAME pybind_core
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/core_pybind_test.py) COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/core_pybind_test.py)
set_tests_properties(pybind_core PROPERTIES 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 add_test(NAME pybind_math
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/math_pybind_test.py) COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/testing/math_pybind_test.py)
set_tests_properties(pybind_math PROPERTIES 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() endif()

View File

@@ -3,6 +3,8 @@
#include <pybind11/stl.h> #include <pybind11/stl.h>
#include <pybind11/stl_bind.h> #include <pybind11/stl_bind.h>
#include <pybind11/numpy.h>
#include "Math/Dense.h" #include "Math/Dense.h"
#include "Math/Transform.h" #include "Math/Transform.h"
#include "Math/Geometry.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<Vector4i>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3d>); PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3d>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4d>); PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector4d>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<Voxel>); PYBIND11_MAKE_OPAQUE(uLib::Vector<Voxel>);
PYBIND11_MAKE_OPAQUE(uLib::Vector<VoxRaytracer::RayData::Element>); 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) { void init_math(py::module_ &m) {
// 1. Basic Eigen Types (Vectors and Matrices) // 1. Basic Eigen Types (Vectors and Matrices)
py::class_<Vector1f>(m, "Vector1f").def(py::init<>()); bind_eigen_type<Vector1f>(m, "Vector1f");
py::class_<Vector2f>(m, "Vector2f").def(py::init<>()); bind_eigen_type<Vector2f>(m, "Vector2f");
py::class_<Vector3f>(m, "Vector3f").def(py::init<>()); bind_eigen_type<Vector3f>(m, "Vector3f");
py::class_<Vector4f>(m, "Vector4f").def(py::init<>()); bind_eigen_type<Vector4f>(m, "Vector4f");
py::class_<Vector1i>(m, "Vector1i").def(py::init<>()); bind_eigen_type<Vector1i>(m, "Vector1i");
py::class_<Vector2i>(m, "Vector2i").def(py::init<>()); bind_eigen_type<Vector2i>(m, "Vector2i");
py::class_<Vector3i>(m, "Vector3i").def(py::init<>()); bind_eigen_type<Vector3i>(m, "Vector3i");
py::class_<Vector4i>(m, "Vector4i").def(py::init<>()); bind_eigen_type<Vector4i>(m, "Vector4i");
py::class_<Vector1d>(m, "Vector1d").def(py::init<>()); bind_eigen_type<Vector1d>(m, "Vector1d");
py::class_<Vector2d>(m, "Vector2d").def(py::init<>()); bind_eigen_type<Vector2d>(m, "Vector2d");
py::class_<Vector3d>(m, "Vector3d").def(py::init<>()); bind_eigen_type<Vector3d>(m, "Vector3d");
py::class_<Vector4d>(m, "Vector4d").def(py::init<>()); bind_eigen_type<Vector4d>(m, "Vector4d");
py::class_<Matrix2f>(m, "Matrix2f").def(py::init<>()); bind_eigen_type<Matrix2f>(m, "Matrix2f");
py::class_<Matrix3f>(m, "Matrix3f").def(py::init<>()); bind_eigen_type<Matrix3f>(m, "Matrix3f");
py::class_<Matrix4f>(m, "Matrix4f").def(py::init<>()); bind_eigen_type<Matrix4f>(m, "Matrix4f");
py::class_<Matrix2i>(m, "Matrix2i").def(py::init<>()); bind_eigen_type<Matrix2i>(m, "Matrix2i");
py::class_<Matrix3i>(m, "Matrix3i").def(py::init<>()); bind_eigen_type<Matrix3i>(m, "Matrix3i");
py::class_<Matrix4i>(m, "Matrix4i").def(py::init<>()); bind_eigen_type<Matrix4i>(m, "Matrix4i");
py::class_<Matrix2d>(m, "Matrix2d").def(py::init<>()); bind_eigen_type<Matrix2d>(m, "Matrix2d");
py::class_<Matrix3d>(m, "Matrix3d").def(py::init<>()); bind_eigen_type<Matrix3d>(m, "Matrix3d");
py::class_<Matrix4d>(m, "Matrix4d").def(py::init<>()); 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 // 2. Homogeneous types
py::class_<HPoint3f>(m, "HPoint3f") py::class_<HPoint3f>(m, "HPoint3f")

View File

@@ -19,7 +19,7 @@ class TestCoreOptions(unittest.TestCase):
class TestCoreObject(unittest.TestCase): class TestCoreObject(unittest.TestCase):
def test_object(self): def test_object(self):
obj = uLib.Core.Object() obj = uLib.Core.Object()
self.assertIsNotN one(obj) self.assertIsNotNone(obj)
class TestCoreTimer(unittest.TestCase): class TestCoreTimer(unittest.TestCase):
def test_timer(self): def test_timer(self):

View File

@@ -10,6 +10,67 @@ def vector4f0(v, target):
diff[3] = 0 # ignoring w diff[3] = 0 # ignoring w
return np.all(np.abs(diff) < 0.001) 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): class TestMathGeometry(unittest.TestCase):
def test_geometry(self): def test_geometry(self):
Geo = uLib.Math.Geometry() Geo = uLib.Math.Geometry()

View File

@@ -1,10 +0,0 @@
#include "Core/Object.h"
int main()
{
uLib::Object obj;
return 0;
}