Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions bindings/SofaTypes/src/SofaPython3/SofaTypes/Binding_Mat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ template <sofa::Size S> static void bindSquaredMat(py::class_<Mat<S, S, double>>
p.def("transpose", (void (MatClass::*)()) & MatClass::transpose);
p.def("inverted", [](MatClass &mat){ return mat.inverted(); });
p.def("invert", [](MatClass &dest, MatClass &from){ return dest.invert(from); });
p.def("trace", [](const MatClass& mat){ return sofa::type::trace(mat); });
}

template <sofa::Size R, sofa::Size C>
Expand Down Expand Up @@ -150,8 +151,14 @@ static void addMat(py::module & /*m*/, py::class_<Mat<R, C, double>> &p) {
p.def(py::self * double());
p.def(double() * py::self);
p.def(py::self / double());
p.def(py::self *= double());
p.def(py::self /= double());
p.def("__imul__", [](MatClass& self, double value) -> MatClass& {
self *= value;
return self;
}, py::return_value_policy::reference_internal);
p.def("__itruediv__", [](MatClass& self, double value) -> MatClass& {
self /= value;
return self;
}, py::return_value_policy::reference_internal);

p.def(py::self += py::self);
p.def(py::self -= py::self);
Expand All @@ -163,6 +170,16 @@ static void addMat(py::module & /*m*/, py::class_<Mat<R, C, double>> &p) {
p.def("__repr__", [](MatClass &self) { return pyMat::__str__(self, true); });
}

template <sofa::Size R_1, sofa::Size C_1, sofa::Size R_2, sofa::Size C_2>
static void addMatProduct(py::module & /*m*/, py::class_<Mat<R_1, C_1, double>> &p)
{
using LHS = Mat<R_1, C_1, double>;
using RHS = Mat<R_2, C_2, double>;
p.def("__mul__", [](const LHS &self, const RHS &m) {
return self * m;
});
}

// Generic bindings for Matrices
template <sofa::Size R, sofa::Size C> struct MATRIX {
static void addMat(py::module &m) {
Expand Down Expand Up @@ -205,6 +222,8 @@ template <> struct MATRIX<1, 1> {
return std::unique_ptr<MatClass>(mat);
}));
::addMat(m, p);

addMatProduct<1,1, 1,1>(m, p);
}
};

Expand Down Expand Up @@ -234,6 +253,8 @@ template <> struct MATRIX<2, 2> {
return std::unique_ptr<MatClass>(mat);
}));
::addMat(m, p);

addMatProduct<2,2, 2,2>(m, p);
}
};

Expand Down Expand Up @@ -263,6 +284,8 @@ template <> struct MATRIX<3, 3> {
return std::unique_ptr<MatClass>(mat);
}));
::addMat(m, p);

addMatProduct<3,3, 3,3>(m, p);
}
};

Expand Down Expand Up @@ -292,6 +315,8 @@ template <> struct MATRIX<4, 4> {
return std::unique_ptr<MatClass>(mat);
}));
::addMat(m, p);

addMatProduct<4,4, 4,4>(m, p);
}
};

Expand Down
44 changes: 24 additions & 20 deletions bindings/SofaTypes/src/SofaPython3/SofaTypes/Binding_Vec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ void setFromPartialSequence(const VecClass& s, py::list t)
for(unsigned int i=0;i<N;i++) { t[i] = s[i]; }
}

template <sofa::Size N, class T>
py::class_<Vec<N,T>> addVec(py::module &m)
template <sofa::Size N, class T, template<sofa::Size, class> class V = sofa::type::Vec>
py::class_<V<N,T>> addVec(py::module &m)
{
typedef Vec<N, T> VecClass;
py::class_<Vec<N, T>> p(m, sofa::defaulttype::DataTypeInfo< Vec<N, T> >::name().c_str());
typedef V<N, T> VecClass;
py::class_<V<N, T>> p(m, sofa::defaulttype::DataTypeInfo< V<N, T> >::name().c_str());

p.def(py::init<>()); // empty ctor
p.def(py::init<const VecClass &>()); // copy ctor
Expand Down Expand Up @@ -230,26 +230,30 @@ T addCross(T p)
return p;
}

template<class T>
template<class T, template<sofa::Size, class> class V = sofa::type::Vec>
void addVectorsFor(py::module& m)
{
addVec<1, T>(m);
addCross( addVec<2, T>(m) );
addCross( addVec<3, T>(m) );
addVec<4, T>(m);
addVec<5, T>(m);
addVec<6, T>(m);
addVec<7, T>(m);
addVec<8, T>(m);
addVec<9, T>(m);
addVec<10, T>(m);
addVec<11, T>(m);
addVec<12, T>(m);
addVec<1, T, V>(m);
addCross( addVec<2, T, V>(m) );
addCross( addVec<3, T, V>(m) );
addVec<4, T, V>(m);
addVec<5, T, V>(m);
addVec<6, T, V>(m);
addVec<7, T, V>(m);
addVec<8, T, V>(m);
addVec<9, T, V>(m);
addVec<10, T, V>(m);
addVec<11, T, V>(m);
addVec<12, T, V>(m);
}

void moduleAddVec(py::module &m)
{
addVectorsFor<int>(m);
addVectorsFor<double>(m);
addVectorsFor<float>(m);
addVectorsFor<int, sofa::type::Vec>(m);
addVectorsFor<double, sofa::type::Vec>(m);
addVectorsFor<float, sofa::type::Vec>(m);

addVectorsFor<int, sofa::type::VecNoInit>(m);
addVectorsFor<double, sofa::type::VecNoInit>(m);
addVectorsFor<float, sofa::type::VecNoInit>(m);
}
1 change: 1 addition & 0 deletions bindings/SofaTypes/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(SOURCE_FILES

set(PYTHON_FILES
${CMAKE_CURRENT_SOURCE_DIR}/pyfiles/vector_test.py
${CMAKE_CURRENT_SOURCE_DIR}/pyfiles/mat_test.py
)

find_package(Sofa.Testing REQUIRED)
Expand Down
64 changes: 64 additions & 0 deletions bindings/SofaTypes/tests/pyfiles/mat_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import math
import unittest

import Sofa
from SofaTypes import Mat1x1, Mat2x2, Mat3x3, Vec2d

class TestMaterialMatrix(unittest.TestCase):

def test_Constructors(self):
# --- Mat1x1 (Scalar/Row Vector) Construction ---
m = Mat1x1() # Empty constructor
self.assertEqual(m[0][0], 0.0)

m = Mat1x1([[math.pi]]) # list ctor (or direct assignment)
self.assertEqual(m[0][0], math.pi)

# --- Mat2x2 Construction ---
m = Mat2x2([[1.0, 2.0], [3.0, 4.0]]) # list of lists ctor
self.assertEqual(m[0][0], 1.0)
self.assertEqual(m[0][1], 2.0)
self.assertEqual(m[1][0], 3.0)
self.assertEqual(m[1][1], 4.0)

# --- Mat3x3 Construction ---
m = Mat3x3([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]])
self.assertEqual(m[0][0], 1.0)
self.assertEqual(m[0][1], 2.0)
self.assertEqual(m[0][2], 3.0)
self.assertEqual(m[1][0], 4.0)
self.assertEqual(m[1][1], 5.0)
self.assertEqual(m[1][2], 6.0)
self.assertEqual(m[2][0], 7.0)
self.assertEqual(m[2][1], 8.0)
self.assertEqual(m[2][2], 9.0)

def test_Operators(self):
m1 = Mat2x2([[1.0, 2.0], [3.0, 4.0]])
m2 = Mat2x2([[5.0, 6.0], [7.0, 8.0]])

# Matrix addition
sum_mat = m1 + m2
expected_sum = Mat2x2([[6.0, 8.0], [10.0, 12.0]])
self.assertEqual(sum_mat, expected_sum)

# Matrix subtraction
diff_mat = m1 - m2
expected_diff = Mat2x2([[-4.0, -4.0], [-4.0, -4.0]])
self.assertEqual(diff_mat, expected_diff)

# Scalar multiplication (A * 2.0)
scaled_mat = m1 * 2.0
expected_scale = Mat2x2([[2.0, 4.0], [6.0, 8.0]])
self.assertEqual(scaled_mat, expected_scale)

# Matrix multiplication (A * B)
mat_product = m1 * m2
expected_mat_product = Mat2x2([[1.0 * 5.0 + 2.0 * 7.0, 1.0 * 6.0 + 2.0 * 8.0], [3.0 * 5.0 + 4.0 * 7.0, 3.0 * 6.0 + 4.0 * 8.0]])
self.assertEqual(mat_product, expected_mat_product)

# Testing assignment/in-place modification if available (e.g., /=)
m_test = Mat2x2([[1.0, 2.0], [3.0, 4.0]])
m_test /= 2.0
expected_inplace_div = Mat2x2([[0.5, 1.0], [1.5, 2.0]])
self.assertEqual(m_test, expected_inplace_div)
1 change: 1 addition & 0 deletions bindings/SofaTypes/tests/pyfiles/vector_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import math
import unittest

import Sofa
import SofaTypes
from SofaTypes import Vec1d, Vec2d, Vec3d, Vec4d, Vec4i

Expand Down
Loading