From 488e0d454f24d6a9f677e0ad51968d0f36f4dcfa Mon Sep 17 00:00:00 2001 From: psomers3 Date: Tue, 9 Mar 2021 16:38:16 +0100 Subject: [PATCH 1/3] [ForceField] Specified template type for python classes --- .../Sofa/Core/Binding_ForceField.cpp | 99 ++++++++----------- examples/emptyForceField.py | 4 +- examples/example-forcefield.py | 4 +- 3 files changed, 43 insertions(+), 64 deletions(-) diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_ForceField.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_ForceField.cpp index fa3c9f8ee..b2dd89b61 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_ForceField.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_ForceField.cpp @@ -47,7 +47,10 @@ namespace sofapython3 using sofa::core::behavior::MultiMatrixAccessor; using sofa::core::behavior::ForceField; using sofa::defaulttype::Vec3dTypes; + using sofa::defaulttype::Vec2dTypes; + using sofa::defaulttype::Vec1dTypes; using sofa::defaulttype::Rigid3dTypes; + using sofa::defaulttype::Rigid2dTypes; template ForceField_Trampoline::ForceField_Trampoline() = default; @@ -163,68 +166,44 @@ namespace sofapython3 } } -void moduleAddForceField(py::module &m) { - py::class_, - BaseObject, ForceField_Trampoline, - py_shared_ptr>> f(m, "ForceField", - py::dynamic_attr(), - sofapython3::doc::forceField::forceFieldClass); - - f.def(py::init([](py::args &args, py::kwargs &kwargs) { - auto ff = sofa::core::sptr> (new ForceField_Trampoline()); - - ff->f_listening.setValue(true); - - if (args.size() == 1) ff->setName(py::cast(args[0])); - - py::object cc = py::cast(ff); - for (auto kv : kwargs) { - std::string key = py::cast(kv.first); - py::object value = py::reinterpret_borrow(kv.second); - if (key == "name") { - if (args.size() != 0) { - throw py::type_error("The name is setted twice as a " - "named argument='" + py::cast(value) + "' and as a" - "positional argument='" + - py::cast(args[0]) + "'."); - } - } - BindingBase::SetAttr(cc, key, value); - } - return ff; - })); - - - py::class_, - BaseObject, ForceField_Trampoline, - py_shared_ptr>> f2(m, "ForceFieldRigid3", - py::dynamic_attr(), - py::multiple_inheritance(), - sofapython3::doc::forceField::forceFieldClass); - - - f2.def(py::init([](py::args &args, py::kwargs &kwargs) { - auto c = sofa::core::sptr> (new ForceField_Trampoline()); - c->f_listening.setValue(true); - - if (args.size() == 1) c->setName(py::cast(args[0])); - - py::object cc = py::cast(c); - for (auto kv : kwargs) { - std::string key = py::cast(kv.first); - py::object value = py::reinterpret_borrow(kv.second); - if (key == "name") { - if (args.size() != 0) { - throw py::type_error("The name is setted twice as a " - "named argument='" + py::cast(value) + "' and as a" - "positional argument='" + - py::cast(args[0]) + "'."); + + template + void declare_forcefield(py::module &m, std::string typestr) { + std::string pyclass_name = std::string("ForceField") + typestr; + py::class_, BaseObject, ForceField_Trampoline, py_shared_ptr>> f(m, pyclass_name.c_str(), py::dynamic_attr(), py::multiple_inheritance(), sofapython3::doc::forceField::forceFieldClass); + + f.def(py::init([](py::args &args, py::kwargs &kwargs) { + auto ff = sofa::core::sptr> (new ForceField_Trampoline()); + + ff->f_listening.setValue(true); + + if (args.size() == 1) ff->setName(py::cast(args[0])); + + py::object cc = py::cast(ff); + for (auto kv : kwargs) { + std::string key = py::cast(kv.first); + py::object value = py::reinterpret_borrow(kv.second); + if (key == "name") { + if (args.size() != 0) { + throw py::type_error("The name is set twice as a " + "named argument='" + py::cast(value) + "' and as a" + "positional argument='" + + py::cast(args[0]) + "'."); + } } + BindingBase::SetAttr(cc, key, value); } - BindingBase::SetAttr(cc, key, value); - } - return c; - })); + return ff; + })); + } + + +void moduleAddForceField(py::module &m) { + declare_forcefield(m, "Vec3d"); + declare_forcefield(m, "Vec2d"); + declare_forcefield(m, "Vec1d"); + declare_forcefield(m, "Rigid3d"); + declare_forcefield(m, "Rigid2d"); } } // namespace sofapython3 diff --git a/examples/emptyForceField.py b/examples/emptyForceField.py index 8df3fc764..b19ba7bfc 100644 --- a/examples/emptyForceField.py +++ b/examples/emptyForceField.py @@ -5,9 +5,9 @@ # This python script shows the functions to be implemented # in order to create your ForceField in python -class EmptyForceField(Sofa.Core.ForceField): +class EmptyForceField(Sofa.Core.ForceFieldVec3d): def __init__(self, *args, **kwargs): - Sofa.Core.ForceField.__init__(self, *args, **kwargs) + Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs) pass # Function called at the component initialization diff --git a/examples/example-forcefield.py b/examples/example-forcefield.py index 4a1736dd5..3d0e08c3f 100644 --- a/examples/example-forcefield.py +++ b/examples/example-forcefield.py @@ -4,10 +4,10 @@ import numpy as np -class RestShapeForceField(Sofa.Core.ForceField): +class RestShapeForceField(Sofa.Core.ForceFieldVec3d): """Implementation of a RestShapeForceField in python""" def __init__(self, ks=1.0, kd=1.0, *args, **kwargs): - Sofa.Core.ForceField.__init__(self, *args, **kwargs) + Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs) self.addData("ks", type="float", value=ks, help="The stiffness spring", group="Spring's Properties") self.addData("kd", type="float", value=kd, help="The damping spring", group="Spring's Properties") From 4c5047e16a1addafd63786d6385f5a0c3fbc52fb Mon Sep 17 00:00:00 2001 From: psomers3 Date: Thu, 11 Mar 2021 14:11:59 +0100 Subject: [PATCH 2/3] updated ForceField unit tests --- bindings/Sofa/tests/Core/ForceField.py | 1 + bindings/Sofa/tests/Core/MyRestShapeForceField.py | 4 ++-- bindings/Sofa/tests/Core/PythonRestShapeForceField.py | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bindings/Sofa/tests/Core/ForceField.py b/bindings/Sofa/tests/Core/ForceField.py index 75bb9dd1d..e65a8f159 100644 --- a/bindings/Sofa/tests/Core/ForceField.py +++ b/bindings/Sofa/tests/Core/ForceField.py @@ -41,6 +41,7 @@ def createParticle(node, node_name, use_implicit_scheme, use_iterative_solver): def rssffScene(use_implicit_scheme=True, use_iterative_solver=True): node = Sofa.Core.Node("root") + node.addObject("RequiredPlugin", name="SofaComponentAll") node.addObject("RequiredPlugin", name="SofaSparseSolver") node.addObject("RequiredPlugin", name="SofaExplicitOdeSolver") node.addObject("RequiredPlugin", name="SofaImplicitOdeSolver") diff --git a/bindings/Sofa/tests/Core/MyRestShapeForceField.py b/bindings/Sofa/tests/Core/MyRestShapeForceField.py index e5aca6d7b..571f6eeea 100644 --- a/bindings/Sofa/tests/Core/MyRestShapeForceField.py +++ b/bindings/Sofa/tests/Core/MyRestShapeForceField.py @@ -2,9 +2,9 @@ import Sofa.Core import numpy as np -class NaiveRestShapeSpringsForcefield(Sofa.Core.ForceField): +class NaiveRestShapeSpringsForcefield(Sofa.Core.ForceFieldVec3d): def __init__(self, *args, **kwargs): - Sofa.Core.ForceField.__init__(self, *args, **kwargs) + Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs) self.addData(name="stiffness", value=kwargs.get("stiffness"), type="double", help="scalar value representing the stiffness between" "the actual position and the rest shape position") diff --git a/bindings/Sofa/tests/Core/PythonRestShapeForceField.py b/bindings/Sofa/tests/Core/PythonRestShapeForceField.py index 79d7b15bf..888ca0161 100644 --- a/bindings/Sofa/tests/Core/PythonRestShapeForceField.py +++ b/bindings/Sofa/tests/Core/PythonRestShapeForceField.py @@ -3,11 +3,11 @@ import Sofa.Core import numpy as np -class MyForceField(Sofa.Core.ForceField): +class MyForceField(Sofa.Core.ForceFieldVec3d): def __init__(self, *args, **kwargs): kwargs["ks"] = kwargs.get("ks", 1.0) kwargs["kd"] = kwargs.get("kd", 0.1) - Sofa.Core.ForceField.__init__(self, *args, **kwargs) + Sofa.Core.ForceFieldVec3d.__init__(self, *args, **kwargs) def init(self): self.initpos = self.mstate.position.array().copy() @@ -38,6 +38,7 @@ def RestShapeObject(impl, name="unnamed", position=[]): return node def createScene(node): + node.addObject("RequiredPlugin", name="SofaComponentAll") node.addObject("RequiredPlugin", name="SofaBaseLinearSolver") node.addObject("RequiredPlugin", name="SofaImplicitOdeSolver") node.addObject("DefaultAnimationLoop", name="loop") From 3c851d273c0b37cc20374b0ef84e97a35109ded4 Mon Sep 17 00:00:00 2001 From: psomers3 Date: Thu, 11 Mar 2021 14:17:43 +0100 Subject: [PATCH 3/3] removed SofaComponentAll --- bindings/Sofa/tests/Core/ForceField.py | 2 +- bindings/Sofa/tests/Core/PythonRestShapeForceField.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/Sofa/tests/Core/ForceField.py b/bindings/Sofa/tests/Core/ForceField.py index e65a8f159..423e1984d 100644 --- a/bindings/Sofa/tests/Core/ForceField.py +++ b/bindings/Sofa/tests/Core/ForceField.py @@ -41,7 +41,7 @@ def createParticle(node, node_name, use_implicit_scheme, use_iterative_solver): def rssffScene(use_implicit_scheme=True, use_iterative_solver=True): node = Sofa.Core.Node("root") - node.addObject("RequiredPlugin", name="SofaComponentAll") + node.addObject("RequiredPlugin", name="SofaBaseMechanics") node.addObject("RequiredPlugin", name="SofaSparseSolver") node.addObject("RequiredPlugin", name="SofaExplicitOdeSolver") node.addObject("RequiredPlugin", name="SofaImplicitOdeSolver") diff --git a/bindings/Sofa/tests/Core/PythonRestShapeForceField.py b/bindings/Sofa/tests/Core/PythonRestShapeForceField.py index 888ca0161..95e80490a 100644 --- a/bindings/Sofa/tests/Core/PythonRestShapeForceField.py +++ b/bindings/Sofa/tests/Core/PythonRestShapeForceField.py @@ -38,7 +38,7 @@ def RestShapeObject(impl, name="unnamed", position=[]): return node def createScene(node): - node.addObject("RequiredPlugin", name="SofaComponentAll") + node.addObject("RequiredPlugin", name="SofaBaseMechanics") node.addObject("RequiredPlugin", name="SofaBaseLinearSolver") node.addObject("RequiredPlugin", name="SofaImplicitOdeSolver") node.addObject("DefaultAnimationLoop", name="loop")