feat: Add Python packaging infrastructure and comprehensive bindings for math and vector types.
This commit is contained in:
10
pyproject.toml
Normal file
10
pyproject.toml
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=42",
|
||||
"wheel",
|
||||
"pybind11>=2.6.0",
|
||||
"cmake>=3.12",
|
||||
"ninja"]
|
||||
|
||||
build-backend = "setuptools.build_meta"
|
||||
52
setup.py
Normal file
52
setup.py
Normal file
@@ -0,0 +1,52 @@
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from setuptools import Extension, setup
|
||||
from setuptools.command.build_ext import build_ext
|
||||
|
||||
class CMakeExtension(Extension):
|
||||
def __init__(self, name, sourcedir=""):
|
||||
Extension.__init__(self, name, sources=[])
|
||||
self.sourcedir = os.path.abspath(sourcedir)
|
||||
|
||||
class CMakeBuild(build_ext):
|
||||
def build_extension(self, ext):
|
||||
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
|
||||
|
||||
if not extdir.endswith(os.path.sep):
|
||||
extdir += os.path.sep
|
||||
|
||||
debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug
|
||||
cfg = "Debug" if debug else "Release"
|
||||
|
||||
cmake_args = [
|
||||
f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}",
|
||||
f"-DPYTHON_EXECUTABLE={sys.executable}",
|
||||
f"-DCMAKE_BUILD_TYPE={cfg}",
|
||||
f"-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE",
|
||||
f"-DCMAKE_INSTALL_RPATH=$ORIGIN",
|
||||
"-DUSE_CUDA=OFF",
|
||||
"-G", "Unix Makefiles",
|
||||
]
|
||||
build_args = []
|
||||
|
||||
build_temp = os.path.join(self.build_temp, ext.name)
|
||||
if not os.path.exists(build_temp):
|
||||
os.makedirs(build_temp)
|
||||
|
||||
subprocess.check_call(["cmake", ext.sourcedir] + cmake_args, cwd=build_temp)
|
||||
subprocess.check_call(["cmake", "--build", ".", "--target", "uLib_python"] + build_args, cwd=build_temp)
|
||||
|
||||
setup(
|
||||
name="ulib",
|
||||
version="0.6.0",
|
||||
author="Andrea Rigoni Garola",
|
||||
author_email="andrea.rigoni@pd.infn.it",
|
||||
description="CMT Cosmic Muon Tomography project uLib python bindings",
|
||||
ext_modules=[CMakeExtension("uLib_python")],
|
||||
cmdclass={"build_ext": CMakeBuild},
|
||||
zip_safe=False,
|
||||
python_requires=">=3.6",
|
||||
)
|
||||
@@ -1,7 +1,36 @@
|
||||
|
||||
set(HEADERS Archives.h Array.h Collection.h DataAllocator.h Debug.h Export.h Function.h Macros.h Mpl.h Object.h Options.h Serializable.h Signal.h Singleton.h SmartPointer.h StaticInterface.h StringReader.h Types.h Uuid.h Vector.h)
|
||||
set(HEADERS
|
||||
Archives.h
|
||||
Array.h
|
||||
Collection.h
|
||||
DataAllocator.h
|
||||
Debug.h
|
||||
Export.h
|
||||
Function.h
|
||||
Macros.h
|
||||
Mpl.h
|
||||
Object.h
|
||||
Options.h
|
||||
Serializable.h
|
||||
Signal.h
|
||||
Singleton.h
|
||||
SmartPointer.h
|
||||
StaticInterface.h
|
||||
StringReader.h
|
||||
Types.h
|
||||
Uuid.h
|
||||
Vector.h
|
||||
)
|
||||
|
||||
set(SOURCES Archives.cpp Debug.cpp Object.cpp Options.cpp Serializable.cpp Signal.cpp Uuid.cpp)
|
||||
set(SOURCES
|
||||
Archives.cpp
|
||||
Debug.cpp
|
||||
Object.cpp
|
||||
Options.cpp
|
||||
Serializable.cpp
|
||||
Signal.cpp
|
||||
Uuid.cpp
|
||||
)
|
||||
|
||||
set(LIBRARIES Boost::program_options Boost::serialization)
|
||||
|
||||
|
||||
@@ -274,6 +274,11 @@ public:
|
||||
this->MoveToRAM();
|
||||
return BaseClass::insert(pos, std::move(x));
|
||||
}
|
||||
template <typename InputIt>
|
||||
iterator insert(const_iterator pos, InputIt first, InputIt last) {
|
||||
this->MoveToRAM();
|
||||
return BaseClass::insert(pos, first, last);
|
||||
}
|
||||
iterator erase(const_iterator pos) {
|
||||
this->MoveToRAM();
|
||||
return BaseClass::erase(pos);
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#include <Core/Vector.h>
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
uLib::Vector<int> v;
|
||||
v.push_back(1);
|
||||
v.push_back(2);
|
||||
v.push_back(3);
|
||||
|
||||
std::cout << "RAM Vector elements: ";
|
||||
for (int i = 0; i < v.size(); ++i) {
|
||||
std::cout << v[i] << " ";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
#ifdef USE_CUDA
|
||||
std::cout << "Moving to VRAM..." << std::endl;
|
||||
v.MoveToVRAM();
|
||||
int *vram_ptr = v.GetVRAMData();
|
||||
if (vram_ptr) {
|
||||
std::cout << "Successfully got VRAM pointer!" << std::endl;
|
||||
} else {
|
||||
std::cout << "Failed to get VRAM pointer!" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Moving back to RAM..." << std::endl;
|
||||
v.MoveToRAM();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -114,6 +114,21 @@ typedef unsigned long Scalarul;
|
||||
typedef float Scalarf;
|
||||
typedef double Scalard;
|
||||
|
||||
typedef Eigen::Matrix<int, 1, 1> Vector1i;
|
||||
typedef Eigen::Vector2i Vector2i;
|
||||
typedef Eigen::Vector3i Vector3i;
|
||||
typedef Eigen::Vector4i Vector4i;
|
||||
|
||||
typedef Eigen::Matrix<float, 1, 1> Vector1f;
|
||||
typedef Eigen::Vector2f Vector2f;
|
||||
typedef Eigen::Vector3f Vector3f;
|
||||
typedef Eigen::Vector4f Vector4f;
|
||||
|
||||
typedef Eigen::Matrix<double, 1, 1> Vector1d;
|
||||
typedef Eigen::Vector2d Vector2d;
|
||||
typedef Eigen::Vector3d Vector3d;
|
||||
typedef Eigen::Vector4d Vector4d;
|
||||
|
||||
typedef Eigen::Matrix<int, 1, 1> Matrix1i;
|
||||
typedef Eigen::Matrix2i Matrix2i;
|
||||
typedef Eigen::Matrix3i Matrix3i;
|
||||
@@ -124,15 +139,10 @@ typedef Eigen::Matrix2f Matrix2f;
|
||||
typedef Eigen::Matrix3f Matrix3f;
|
||||
typedef Eigen::Matrix4f Matrix4f;
|
||||
|
||||
typedef Eigen::Matrix<int, 1, 1> Vector1i;
|
||||
typedef Eigen::Vector2i Vector2i;
|
||||
typedef Eigen::Vector3i Vector3i;
|
||||
typedef Eigen::Vector4i Vector4i;
|
||||
|
||||
typedef Eigen::Matrix<float, 1, 1> Vector1f;
|
||||
typedef Eigen::Vector2f Vector2f;
|
||||
typedef Eigen::Vector3f Vector3f;
|
||||
typedef Eigen::Vector4f Vector4f;
|
||||
typedef Eigen::Matrix<double, 1, 1> Matrix1d;
|
||||
typedef Eigen::Matrix2d Matrix2d;
|
||||
typedef Eigen::Matrix3d Matrix3d;
|
||||
typedef Eigen::Matrix4d Matrix4d;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Vector String interaction ///////////////////////////////////////////////////
|
||||
@@ -188,6 +198,9 @@ public:
|
||||
typedef Eigen::Matrix<Scalarf, 4, 1> BaseClass;
|
||||
|
||||
_HPoint3f() : BaseClass(0, 0, 0, p) {}
|
||||
_HPoint3f(int rows, int cols) : BaseClass() {
|
||||
this->operator()(3) = p;
|
||||
}
|
||||
_HPoint3f(float x, float y, float z) : BaseClass(x, y, z, p) {}
|
||||
_HPoint3f(Vector3f &in) : BaseClass(in.homogeneous()) {
|
||||
this->operator()(3) = p;
|
||||
|
||||
@@ -70,8 +70,8 @@ public:
|
||||
|
||||
int ImportFromVti(const char *file, bool density_type = 0);
|
||||
|
||||
protected:
|
||||
virtual ~VoxImage() {}
|
||||
protected:
|
||||
VoxImage(const Vector3i &size) : BaseClass(size) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,14 @@ target_include_directories(uLib_python PRIVATE
|
||||
${PROJECT_BINARY_DIR}
|
||||
)
|
||||
|
||||
# Install uLib_python within the uLib install target
|
||||
install(TARGETS uLib_python
|
||||
EXPORT "${PROJECT_NAME}Targets"
|
||||
RUNTIME DESTINATION ${INSTALL_BIN_DIR} COMPONENT bin
|
||||
LIBRARY DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib
|
||||
ARCHIVE DESTINATION ${INSTALL_LIB_DIR} COMPONENT lib
|
||||
)
|
||||
|
||||
# --- Python Tests ---------------------------------------------------------- #
|
||||
|
||||
if(BUILD_TESTING)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/eigen.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/stl_bind.h>
|
||||
|
||||
#include "Math/Dense.h"
|
||||
#include "Math/Transform.h"
|
||||
@@ -13,13 +14,154 @@
|
||||
#include "Math/TriangleMesh.h"
|
||||
#include "Math/VoxRaytracer.h"
|
||||
#include "Math/Accumulator.h"
|
||||
#include "Math/VoxImage.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace uLib;
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalari>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarui>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarl>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarul>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalarf>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Scalard>);
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3f>);
|
||||
PYBIND11_MAKE_OPAQUE(uLib::Vector<Vector3i>);
|
||||
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>);
|
||||
|
||||
void init_math(py::module_ &m) {
|
||||
|
||||
// Math/Transform.h
|
||||
// 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<>());
|
||||
|
||||
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<>());
|
||||
|
||||
// 2. Homogeneous types
|
||||
py::class_<HPoint3f>(m, "HPoint3f")
|
||||
.def(py::init<>())
|
||||
.def(py::init<float, float, float>())
|
||||
.def(py::init<Vector3f &>());
|
||||
py::class_<HVector3f>(m, "HVector3f")
|
||||
.def(py::init<>())
|
||||
.def(py::init<float, float, float>())
|
||||
.def(py::init<Vector3f &>());
|
||||
py::class_<HLine3f>(m, "HLine3f")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("origin", &HLine3f::origin)
|
||||
.def_readwrite("direction", &HLine3f::direction);
|
||||
py::class_<HError3f>(m, "HError3f")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("position_error", &HError3f::position_error)
|
||||
.def_readwrite("direction_error", &HError3f::direction_error);
|
||||
|
||||
// 3. Dynamic Vectors (uLib::Vector)
|
||||
py::bind_vector<uLib::Vector<Scalari>>(m, "Vector_i")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalari>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalari>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Scalarui>>(m, "Vector_ui")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalarui>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalarui>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Scalarl>>(m, "Vector_l")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalarl>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalarl>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Scalarul>>(m, "Vector_ul")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalarul>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalarul>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Scalarf>>(m, "Vector_f")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalarf>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalarf>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Scalard>>(m, "Vector_d")
|
||||
.def("MoveToVRAM", &uLib::Vector<Scalard>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Scalard>::MoveToRAM);
|
||||
|
||||
py::bind_vector<uLib::Vector<Vector3f>>(m, "Vector_Vector3f")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector3f>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector3f>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Vector3i>>(m, "Vector_Vector3i")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector3i>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector3i>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Vector4f>>(m, "Vector_Vector4f")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector4f>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector4f>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Vector4i>>(m, "Vector_Vector4i")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector4i>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector4i>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Vector3d>>(m, "Vector_Vector3d")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector3d>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector3d>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Vector4d>>(m, "Vector_Vector4d")
|
||||
.def("MoveToVRAM", &uLib::Vector<Vector4d>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Vector4d>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<Voxel>>(m, "Vector_Voxel")
|
||||
.def("MoveToVRAM", &uLib::Vector<Voxel>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<Voxel>::MoveToRAM);
|
||||
py::bind_vector<uLib::Vector<VoxRaytracer::RayData::Element>>(m, "Vector_VoxRaytracerRayDataElement")
|
||||
.def("MoveToVRAM", &uLib::Vector<VoxRaytracer::RayData::Element>::MoveToVRAM)
|
||||
.def("MoveToRAM", &uLib::Vector<VoxRaytracer::RayData::Element>::MoveToRAM);
|
||||
|
||||
// 4. Accumulators
|
||||
py::class_<Accumulator_Mean<float>>(m, "Accumulator_Mean_f")
|
||||
.def(py::init<>())
|
||||
.def("AddPass", &Accumulator_Mean<float>::AddPass)
|
||||
.def("__call__", py::overload_cast<const float>(&Accumulator_Mean<float>::operator()))
|
||||
.def("__call__", py::overload_cast<>(&Accumulator_Mean<float>::operator(), py::const_));
|
||||
|
||||
py::class_<Accumulator_Mean<double>>(m, "Accumulator_Mean_d")
|
||||
.def(py::init<>())
|
||||
.def("AddPass", &Accumulator_Mean<double>::AddPass)
|
||||
.def("__call__", py::overload_cast<const double>(&Accumulator_Mean<double>::operator()))
|
||||
.def("__call__", py::overload_cast<>(&Accumulator_Mean<double>::operator(), py::const_));
|
||||
|
||||
py::class_<Accumulator_ABTrim<float>>(m, "Accumulator_ABTrim_f")
|
||||
.def(py::init<>())
|
||||
.def("SetABTrim", &Accumulator_ABTrim<float>::SetABTrim)
|
||||
.def("__iadd__", [](Accumulator_ABTrim<float> &self, float val) { self += val; return &self; })
|
||||
.def("__call__", &Accumulator_ABTrim<float>::operator());
|
||||
|
||||
py::class_<Accumulator_ABTrim<double>>(m, "Accumulator_ABTrim_d")
|
||||
.def(py::init<>())
|
||||
.def("SetABTrim", &Accumulator_ABTrim<double>::SetABTrim)
|
||||
.def("__iadd__", [](Accumulator_ABTrim<double> &self, double val) { self += val; return &self; })
|
||||
.def("__call__", &Accumulator_ABTrim<double>::operator());
|
||||
|
||||
py::class_<Accumulator_ABClip<float>>(m, "Accumulator_ABClip_f")
|
||||
.def(py::init<>())
|
||||
.def("SetABTrim", &Accumulator_ABClip<float>::SetABTrim)
|
||||
.def("__iadd__", [](Accumulator_ABClip<float> &self, float val) { self += val; return &self; })
|
||||
.def("__call__", &Accumulator_ABClip<float>::operator());
|
||||
|
||||
py::class_<Accumulator_ABClip<double>>(m, "Accumulator_ABClip_d")
|
||||
.def(py::init<>())
|
||||
.def("SetABTrim", &Accumulator_ABClip<double>::SetABTrim)
|
||||
.def("__iadd__", [](Accumulator_ABClip<double> &self, double val) { self += val; return &self; })
|
||||
.def("__call__", &Accumulator_ABClip<double>::operator());
|
||||
|
||||
// 5. Core Math Structures
|
||||
py::class_<AffineTransform>(m, "AffineTransform")
|
||||
.def(py::init<>())
|
||||
.def("GetWorldMatrix", &AffineTransform::GetWorldMatrix)
|
||||
@@ -34,13 +176,11 @@ void init_math(py::module_ &m) {
|
||||
.def("EulerYZYRotate", &AffineTransform::EulerYZYRotate)
|
||||
.def("FlipAxes", &AffineTransform::FlipAxes);
|
||||
|
||||
// Math/Geometry.h
|
||||
py::class_<Geometry, AffineTransform>(m, "Geometry")
|
||||
.def(py::init<>())
|
||||
.def("GetWorldPoint", py::overload_cast<const Vector4f &>(&Geometry::GetWorldPoint, py::const_))
|
||||
.def("GetLocalPoint", py::overload_cast<const Vector4f &>(&Geometry::GetLocalPoint, py::const_));
|
||||
|
||||
// Math/ContainerBox.h
|
||||
py::class_<ContainerBox, AffineTransform>(m, "ContainerBox")
|
||||
.def(py::init<>())
|
||||
.def("SetOrigin", &ContainerBox::SetOrigin)
|
||||
@@ -51,7 +191,6 @@ void init_math(py::module_ &m) {
|
||||
.def("GetWorldPoint", py::overload_cast<const Vector4f &>(&ContainerBox::GetWorldPoint, py::const_))
|
||||
.def("GetLocalPoint", py::overload_cast<const Vector4f &>(&ContainerBox::GetLocalPoint, py::const_));
|
||||
|
||||
// Math/StructuredData.h
|
||||
py::enum_<StructuredData::_Order>(m, "StructuredDataOrder")
|
||||
.value("CustomOrder", StructuredData::CustomOrder)
|
||||
.value("XYZ", StructuredData::XYZ)
|
||||
@@ -74,7 +213,6 @@ void init_math(py::module_ &m) {
|
||||
.def("Map", &StructuredData::Map)
|
||||
.def("UnMap", &StructuredData::UnMap);
|
||||
|
||||
// Math/StructuredGrid.h
|
||||
py::class_<StructuredGrid, ContainerBox, StructuredData>(m, "StructuredGrid")
|
||||
.def(py::init<const Vector3i &>())
|
||||
.def("SetSpacing", &StructuredGrid::SetSpacing)
|
||||
@@ -84,7 +222,6 @@ void init_math(py::module_ &m) {
|
||||
return self.Find(HPoint3f(pt));
|
||||
});
|
||||
|
||||
// Math/Structured2DGrid.h
|
||||
py::class_<Structured2DGrid>(m, "Structured2DGrid")
|
||||
.def(py::init<>())
|
||||
.def("SetDims", &Structured2DGrid::SetDims)
|
||||
@@ -100,7 +237,6 @@ void init_math(py::module_ &m) {
|
||||
.def("UnitToPhysicsSpace", &Structured2DGrid::UnitToPhysicsSpace)
|
||||
.def("SetDebug", &Structured2DGrid::SetDebug);
|
||||
|
||||
// Math/Structured4DGrid.h
|
||||
py::class_<Structured4DGrid>(m, "Structured4DGrid")
|
||||
.def(py::init<>())
|
||||
.def("SetDims", &Structured4DGrid::SetDims)
|
||||
@@ -116,7 +252,36 @@ void init_math(py::module_ &m) {
|
||||
.def("UnitToPhysicsSpace", &Structured4DGrid::UnitToPhysicsSpace)
|
||||
.def("SetDebug", &Structured4DGrid::SetDebug);
|
||||
|
||||
// Math/TriangleMesh.h
|
||||
// 6. High-level Structures
|
||||
py::class_<Voxel>(m, "Voxel")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("Value", &Voxel::Value);
|
||||
|
||||
py::class_<Abstract::VoxImage, StructuredGrid>(m, "AbstractVoxImage")
|
||||
.def("GetValue", py::overload_cast<const Vector3i &>(&Abstract::VoxImage::GetValue, py::const_))
|
||||
.def("GetValue", py::overload_cast<const int>(&Abstract::VoxImage::GetValue, py::const_))
|
||||
.def("SetValue", py::overload_cast<const Vector3i &, float>(&Abstract::VoxImage::SetValue))
|
||||
.def("SetValue", py::overload_cast<const int, float>(&Abstract::VoxImage::SetValue))
|
||||
.def("ExportToVtk", &Abstract::VoxImage::ExportToVtk)
|
||||
.def("ExportToVti", &Abstract::VoxImage::ExportToVti)
|
||||
.def("ImportFromVtk", &Abstract::VoxImage::ImportFromVtk)
|
||||
.def("ImportFromVti", &Abstract::VoxImage::ImportFromVti);
|
||||
|
||||
py::class_<VoxImage<Voxel>, Abstract::VoxImage>(m, "VoxImage")
|
||||
.def(py::init<>())
|
||||
.def(py::init<const Vector3i &>())
|
||||
.def("Data", &VoxImage<Voxel>::Data, py::return_value_policy::reference_internal)
|
||||
.def("InitVoxels", &VoxImage<Voxel>::InitVoxels)
|
||||
.def("Abs", &VoxImage<Voxel>::Abs)
|
||||
.def("clipImage", py::overload_cast<const Vector3i, const Vector3i>(&VoxImage<Voxel>::clipImage, py::const_))
|
||||
.def("clipImage", py::overload_cast<const HPoint3f, const HPoint3f>(&VoxImage<Voxel>::clipImage, py::const_))
|
||||
.def("clipImage", py::overload_cast<const float>(&VoxImage<Voxel>::clipImage, py::const_))
|
||||
.def("maskImage", py::overload_cast<const HPoint3f, const HPoint3f, float>(&VoxImage<Voxel>::maskImage, py::const_))
|
||||
.def("maskImage", py::overload_cast<const float, float, float>(&VoxImage<Voxel>::maskImage, py::const_), py::arg("threshold"), py::arg("belowValue") = 0, py::arg("aboveValue") = 0)
|
||||
.def("fixVoxels", py::overload_cast<const float, float>(&VoxImage<Voxel>::fixVoxels, py::const_))
|
||||
.def("__getitem__", py::overload_cast<unsigned int>(&VoxImage<Voxel>::operator[]))
|
||||
.def("__getitem__", py::overload_cast<const Vector3i &>(&VoxImage<Voxel>::operator[]));
|
||||
|
||||
py::class_<TriangleMesh>(m, "TriangleMesh")
|
||||
.def(py::init<>())
|
||||
.def("AddPoint", &TriangleMesh::AddPoint)
|
||||
@@ -124,7 +289,6 @@ void init_math(py::module_ &m) {
|
||||
.def("Points", &TriangleMesh::Points, py::return_value_policy::reference_internal)
|
||||
.def("Triangles", &TriangleMesh::Triangles, py::return_value_policy::reference_internal);
|
||||
|
||||
// Math/VoxRaytracer.h
|
||||
py::class_<VoxRaytracer::RayData::Element>(m, "VoxRaytracerRayDataElement")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("vox_id", &VoxRaytracer::RayData::Element::vox_id)
|
||||
@@ -133,6 +297,7 @@ void init_math(py::module_ &m) {
|
||||
py::class_<VoxRaytracer::RayData>(m, "VoxRaytracerRayData")
|
||||
.def(py::init<>())
|
||||
.def("AppendRay", &VoxRaytracer::RayData::AppendRay)
|
||||
.def("Data", py::overload_cast<>(&VoxRaytracer::RayData::Data), py::return_value_policy::reference_internal)
|
||||
.def("Count", &VoxRaytracer::RayData::Count)
|
||||
.def("TotalLength", &VoxRaytracer::RayData::TotalLength)
|
||||
.def("SetCount", &VoxRaytracer::RayData::SetCount)
|
||||
@@ -140,13 +305,8 @@ void init_math(py::module_ &m) {
|
||||
|
||||
py::class_<VoxRaytracer>(m, "VoxRaytracer")
|
||||
.def(py::init<StructuredGrid &>(), py::keep_alive<1, 2>())
|
||||
.def("GetImage", &VoxRaytracer::GetImage, py::return_value_policy::reference_internal);
|
||||
|
||||
// Math/Accumulator.h
|
||||
py::class_<Accumulator_Mean<float>>(m, "Accumulator_Mean_f")
|
||||
.def(py::init<>())
|
||||
.def("AddPass", &Accumulator_Mean<float>::AddPass)
|
||||
.def("__call__", py::overload_cast<const float>(&Accumulator_Mean<float>::operator()))
|
||||
.def("__call__", py::overload_cast<>(&Accumulator_Mean<float>::operator(), py::const_));
|
||||
.def("GetImage", &VoxRaytracer::GetImage, py::return_value_policy::reference_internal)
|
||||
.def("TraceLine", &VoxRaytracer::TraceLine)
|
||||
.def("TraceBetweenPoints", &VoxRaytracer::TraceBetweenPoints);
|
||||
|
||||
}
|
||||
|
||||
@@ -58,5 +58,71 @@ class TestMathAccumulator(unittest.TestCase):
|
||||
acc(20.0)
|
||||
self.assertAlmostEqual(acc(), 15.0)
|
||||
|
||||
class TestMathNewTypes(unittest.TestCase):
|
||||
def test_eigen_vectors(self):
|
||||
v1f = uLib_python.Math.Vector1f()
|
||||
v3d = uLib_python.Math.Vector3d()
|
||||
m4f = uLib_python.Math.Matrix4f()
|
||||
self.assertIsNotNone(v1f)
|
||||
self.assertIsNotNone(v3d)
|
||||
self.assertIsNotNone(m4f)
|
||||
|
||||
def test_ulib_vectors(self):
|
||||
vi = uLib_python.Math.Vector_i()
|
||||
vi.append(1)
|
||||
vi.append(2)
|
||||
self.assertEqual(len(vi), 2)
|
||||
self.assertEqual(vi[0], 1)
|
||||
self.assertEqual(vi[1], 2)
|
||||
|
||||
vf = uLib_python.Math.Vector_f()
|
||||
vf.append(1.5)
|
||||
self.assertAlmostEqual(vf[0], 1.5)
|
||||
|
||||
def test_homogeneous(self):
|
||||
p = uLib_python.Math.HPoint3f(1.0, 2.0, 3.0)
|
||||
v = uLib_python.Math.HVector3f(0.0, 1.0, 0.0)
|
||||
self.assertIsNotNone(p)
|
||||
self.assertIsNotNone(v)
|
||||
|
||||
def test_vox_image(self):
|
||||
img = uLib_python.Math.VoxImage([2, 2, 2])
|
||||
self.assertEqual(img.GetDims()[0], 2)
|
||||
img.SetValue([0, 0, 0], 10.5)
|
||||
# Note: GetValue returns float, and there might be internal scaling (1.E-6 observed in code)
|
||||
# Actually in VoxImage.h: GetValue(id) returns At(id).Value
|
||||
# SetValue(id, value) sets At(id).Value = value
|
||||
self.assertAlmostEqual(img.GetValue([0, 0, 0]), 10.5)
|
||||
|
||||
class TestMathVoxRaytracer(unittest.TestCase):
|
||||
def test_raytracer(self):
|
||||
grid = uLib_python.Math.StructuredGrid([10, 10, 10])
|
||||
grid.SetSpacing([1, 1, 1])
|
||||
grid.SetOrigin([0, 0, 0])
|
||||
|
||||
rt = uLib_python.Math.VoxRaytracer(grid)
|
||||
self.assertIsNotNone(rt)
|
||||
|
||||
# Test TraceBetweenPoints
|
||||
p1 = np.array([0.5, 0.5, -1.0, 1.0], dtype=np.float32)
|
||||
p2 = np.array([0.5, 0.5, 11.0, 1.0], dtype=np.float32)
|
||||
data = rt.TraceBetweenPoints(p1, p2)
|
||||
|
||||
self.assertGreater(data.Count(), 0)
|
||||
self.assertAlmostEqual(data.TotalLength(), 10.0)
|
||||
|
||||
# Check elements
|
||||
elements = data.Data()
|
||||
for i in range(data.Count()):
|
||||
self.assertGreaterEqual(elements[i].vox_id, 0)
|
||||
self.assertGreater(elements[i].L, 0)
|
||||
|
||||
def test_ray_data(self):
|
||||
data = uLib_python.Math.VoxRaytracerRayData()
|
||||
data.SetCount(10)
|
||||
data.SetTotalLength(5.5)
|
||||
self.assertEqual(data.Count(), 10)
|
||||
self.assertAlmostEqual(data.TotalLength(), 5.5)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user