From 00b83ac950d8cc3fed56d57c8df705df34ff24d6 Mon Sep 17 00:00:00 2001 From: Paul Maria Scheikl Date: Sun, 24 Jul 2022 16:31:45 +0200 Subject: [PATCH 1/2] Added WIP for binding PointSetTopologyModifier. On first call, addPoints works as expected, every call after that does not. Remove points works well, but validity of point to be removed is not checked yet. --- .../Sofa/Core/Binding_BaseMeshTopology.cpp | 2 +- .../Core/Binding_PointSetTopologyModifier.cpp | 63 +++++++++++++++++++ .../Core/Binding_PointSetTopologyModifier.h | 29 +++++++++ .../src/SofaPython3/Sofa/Core/CMakeLists.txt | 2 + .../SofaPython3/Sofa/Core/Submodule_Core.cpp | 2 + examples/pointSetTopologyModifier.py | 38 +++++++++++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.cpp create mode 100644 bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.h create mode 100644 examples/pointSetTopologyModifier.py diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp index 8ed12bd2..b75c70e4 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_BaseMeshTopology.cpp @@ -39,7 +39,7 @@ namespace sofapython3 { void moduleAddBaseMeshTopology(py::module& m) { py::class_> c (m, "BaseMeshTopology"); - /// register the ContactListener binding in the downcasting subsystem + /// register the BaseMeshTopology binding in the downcasting subsystem PythonFactory::registerType([](sofa::core::objectmodel::Base* object) { return py::cast(dynamic_cast(object)); diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.cpp new file mode 100644 index 00000000..04b1ca2e --- /dev/null +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.cpp @@ -0,0 +1,63 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2021 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by * +* the Free Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this program. If not, see . * +******************************************************************************* +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include +#include +#include +#include +#include +#include + +typedef sofa::component::topology::container::dynamic::PointSetTopologyModifier PointSetTopologyModifier; +typedef sofa::core::topology::BaseMeshTopology::PointID PointID; + +namespace py { +using namespace pybind11; +} + +using namespace sofa::core::objectmodel; +using namespace sofa::core::topology; + +namespace sofapython3 { + +void moduleAddPointSetTopologyModifier(py::module& m) { + py::class_> c(m, "PointSetTopologyModifier"); + + /// register the PointSetTopologyModifier binding in the downcasting subsystem + PythonFactory::registerType([](sofa::core::objectmodel::Base* object) { + return py::cast(dynamic_cast(object)); + }); + + c.def("addPoints", + [](PointSetTopologyModifier& self, const sofa::Size nPoints, const bool addDOF) { + self.addPoints(nPoints, addDOF); + }); + c.def("removePoints", + [](PointSetTopologyModifier& self, const std::vector& indices, const bool removeDOF) { + sofa::type::vector index_vector; + index_vector.reserve(indices.size()); + for (const auto i : indices) { + index_vector.emplace_back(i); + } + + self.removePoints(index_vector, removeDOF); + }); +} + +} // namespace sofapython3 diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.h b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.h new file mode 100644 index 00000000..a2f6a72c --- /dev/null +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Binding_PointSetTopologyModifier.h @@ -0,0 +1,29 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2021 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by * +* the Free Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this program. If not, see . * +******************************************************************************* +* Contact information: contact@sofa-framework.org * +******************************************************************************/ + +#pragma once + +#include + +namespace sofapython3 { + +void moduleAddPointSetTopologyModifier(pybind11::module &m); + +} // namespace sofapython3 diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt b/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt index 81bb3d6f..4118bc29 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Node.h ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Node_doc.h ${CMAKE_CURRENT_SOURCE_DIR}/Binding_NodeIterator.h + ${CMAKE_CURRENT_SOURCE_DIR}/Binding_PointSetTopologyModifier.h ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Prefab.h ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Prefab_doc.h ${CMAKE_CURRENT_SOURCE_DIR}/Data/Binding_DataContainer.h @@ -64,6 +65,7 @@ set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Binding_ObjectFactory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Node.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Binding_NodeIterator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Binding_PointSetTopologyModifier.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Prefab.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Submodule_Core.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Binding_PythonScriptEvent.cpp diff --git a/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp b/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp index 932568e5..af62f297 100644 --- a/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/Core/Submodule_Core.cpp @@ -39,6 +39,7 @@ using sofa::helper::logging::Message; #include #include #include +#include #include #include #include @@ -123,6 +124,7 @@ PYBIND11_MODULE(Core, core) moduleAddBaseLink(core); moduleAddTopology(core); moduleAddBaseMeshTopology(core); + moduleAddPointSetTopologyModifier(core); } } ///namespace sofapython3 diff --git a/examples/pointSetTopologyModifier.py b/examples/pointSetTopologyModifier.py new file mode 100644 index 00000000..6db4fec7 --- /dev/null +++ b/examples/pointSetTopologyModifier.py @@ -0,0 +1,38 @@ +import Sofa +import Sofa.Core +import numpy as np + + +def createScene(root): + root.gravity = [0, -9.81, 0] + + root.addObject("DefaultAnimationLoop") + root.addObject("DefaultVisualManagerLoop") + root.addObject("RequiredPlugin", name="Sofa.Component.Topology.Container.Dynamic") + + container = root.addObject("PointSetTopologyContainer", points=[[0, 0, 0], [1, 0, 0]]) + modifier = root.addObject("PointSetTopologyModifier") + state = root.addObject("MechanicalObject", template="Vec3d", showObject=True, showObjectScale=10) + + root.addObject(PointController(modifier=modifier, state=state, container=container)) + + +class PointController(Sofa.Core.Controller): + def __init__(self, modifier, state, container): + super().__init__() + self.container = container + self.modifier = modifier + self.state = state + + def onKeypressedEvent(self, event): + if event["key"] == "A": + print("Add 10 points") + self.modifier.addPoints(10, True) + + with self.state.position.writeable() as state: + for i in range(len(state)): + state[i] = np.array([i, 0, 0]) + + elif event["key"] == "D": + print("Remove point 0") + self.modifier.removePoints(np.array([0]), True) From ef5cc55e74ba5a464f3ae9c284fd160a92ca02fb Mon Sep 17 00:00:00 2001 From: Paul Maria Scheikl Date: Wed, 19 Oct 2022 15:20:58 +0200 Subject: [PATCH 2/2] Extend example. Memcache does not update correctly. --- examples/pointSetTopologyModifier.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/examples/pointSetTopologyModifier.py b/examples/pointSetTopologyModifier.py index 6db4fec7..e0ab20d3 100644 --- a/examples/pointSetTopologyModifier.py +++ b/examples/pointSetTopologyModifier.py @@ -28,11 +28,17 @@ def onKeypressedEvent(self, event): if event["key"] == "A": print("Add 10 points") self.modifier.addPoints(10, True) - - with self.state.position.writeable() as state: - for i in range(len(state)): - state[i] = np.array([i, 0, 0]) + # print("Before setting positions", self.state.position.array()) elif event["key"] == "D": print("Remove point 0") self.modifier.removePoints(np.array([0]), True) + + elif event["key"] == "B": + print(f"{len(self.state.position.array())=}") + with self.state.position.writeable() as state: + print(f"{len(state)=}") + # for i in range(len(state)): + # state[i] = np.array([i, 0, 0]) + + # print("After setting positions", self.state.position.array())