diff --git a/CMake/SofaPython3Tools.cmake b/CMake/SofaPython3Tools.cmake index 678743f65..4a519582a 100644 --- a/CMake/SofaPython3Tools.cmake +++ b/CMake/SofaPython3Tools.cmake @@ -219,12 +219,15 @@ function(SP3_add_python_module) if (APPLE) # In MacOS, the target dependency name is RPATH/site-packages/PackageName, so we need to add - # an RPATH to the directory that contains "site-packages" + # an RPATH to the directory that contains "site-packages" (e.g. "../.." for site-packages/Sofa/Core.so, + # "../../../.." for site-packages/Sofa/Component/SolidMechanics/Spring.so) + file(RELATIVE_PATH from_target_to_python_root "${TARGET_LIBRARY_OUTPUT_DIRECTORY}" "${CMAKE_BINARY_DIR}/lib/${SP3_PYTHON_PACKAGES_DIRECTORY}/..") + file(TO_CMAKE_PATH "${from_target_to_python_root}" from_target_to_python_root) list(APPEND TARGET_DEPENDENCIES_RPATH - "$ORIGIN/../.." - "$$ORIGIN/../.." - "@loader_path/../.." - "@executable_path/../.." + "$ORIGIN/${from_target_to_python_root}" + "$$ORIGIN/${from_target_to_python_root}" + "@loader_path/${from_target_to_python_root}" + "@executable_path/${from_target_to_python_root}" ) endif() @@ -303,7 +306,7 @@ function(SP3_add_python_module) if (APPLE) set_target_properties( - ${PROJECT_NAME} + ${A_TARGET} PROPERTIES INSTALL_NAME_DIR "@rpath/${SP3_PYTHON_PACKAGES_DIRECTORY}/${DESTINATION}" ) diff --git a/bindings/BindingsConfig.cmake.in b/bindings/BindingsConfig.cmake.in index 1c73cc1f2..24c66382e 100644 --- a/bindings/BindingsConfig.cmake.in +++ b/bindings/BindingsConfig.cmake.in @@ -3,21 +3,15 @@ @PACKAGE_GUARD@ @PACKAGE_INIT@ -set(SP3_WITH_SOFAEXPORTER @SP3_WITH_SOFAEXPORTER@) - find_package(Sofa.Config QUIET REQUIRED) sofa_find_package(SofaPython3 QUIET REQUIRED COMPONENTS - Bindings.Modules + Bindings.Component Bindings.Sofa Bindings.SofaGui Bindings.SofaRuntime Bindings.SofaTypes ) -if(SP3_WITH_SOFAEXPORTER) - sofa_find_package(SofaPython3 QUIET REQUIRED COMPONENTS Bindings.SofaExporter) -endif() - # If we are importing this config file and the target is not yet there this is indicating that # target is an imported one. So we include it if(NOT TARGET @PROJECT_NAME@) diff --git a/bindings/CMakeLists.txt b/bindings/CMakeLists.txt index fbab2c18f..f8a9af2ed 100644 --- a/bindings/CMakeLists.txt +++ b/bindings/CMakeLists.txt @@ -1,15 +1,11 @@ project(Bindings) -set(BINDINGS_MODULE_LIST Sofa SofaRuntime SofaTypes Modules) +set(BINDINGS_MODULE_LIST Sofa SofaRuntime SofaTypes Component) if(SP3_WITH_SOFAGUI) list(APPEND BINDINGS_MODULE_LIST SofaGui) endif() -if(SP3_WITH_SOFAEXPORTER) - list(APPEND BINDINGS_MODULE_LIST SofaExporter) -endif() - # This will set rpaths relative to SP3 plugin library if(UNIX) set(CMAKE_INSTALL_RPATH diff --git a/bindings/Modules/Bindings.ModulesConfig.cmake.in b/bindings/Component/Bindings.ComponentConfig.cmake.in similarity index 60% rename from bindings/Modules/Bindings.ModulesConfig.cmake.in rename to bindings/Component/Bindings.ComponentConfig.cmake.in index 1f281c241..e417df8c8 100644 --- a/bindings/Modules/Bindings.ModulesConfig.cmake.in +++ b/bindings/Component/Bindings.ComponentConfig.cmake.in @@ -3,17 +3,16 @@ @PACKAGE_GUARD@ @PACKAGE_INIT@ +set(SP3_WITH_SOFAEXPORTER @SP3_WITH_SOFAEXPORTER@) + find_package(Sofa.Config QUIET REQUIRED) sofa_find_package(SofaPython3 QUIET REQUIRED COMPONENTS Plugin Bindings.Sofa) -# Required by Bindings.Modules.SofaBaseTopology -sofa_find_package(Sofa.Component.Topology.Container.Grid QUIET REQUIRED) - -# Required by Bindings.Modules.SofaDeformable -sofa_find_package(Sofa.Component.SolidMechanics.Spring QUIET REQUIRED) - -# Required by Bindings.Modules.SofaLinearSolver -sofa_find_package(Sofa.Component.LinearSolver.Iterative QUIET REQUIRED) +# SOFA modules bound by the Bindings.Component.* targets that were built +set(SP3_BOUND_SOFA_COMPONENT_MODULES "@COMPONENTBINDINGS_SOFA_MODULES@") +foreach(sofa_module ${SP3_BOUND_SOFA_COMPONENT_MODULES}) + sofa_find_package(${sofa_module} QUIET REQUIRED) +endforeach() # If we are importing this config file and the target is not yet there this is indicating that # target is an imported one. So we include it diff --git a/bindings/Component/CMakeLists.txt b/bindings/Component/CMakeLists.txt new file mode 100644 index 000000000..477cea752 --- /dev/null +++ b/bindings/Component/CMakeLists.txt @@ -0,0 +1,84 @@ +project(Bindings.Component) + +# Python bindings for SOFA's Sofa.Component.* modules. +# +# The directory layout mirrors SOFA's Sofa/Component tree: the bindings of the SOFA module +# Sofa.Component.. live in // and are compiled into the python module +# Sofa.Component.. (i.e. site-packages/Sofa/Component//.). +# +# A binding is only built when the SOFA module it binds is available. + +# - Create the python module binding a SOFA Sofa.Component.* module. +# +# SP3_add_component_binding( SOURCES ... HEADERS ... [DEPENDS ...]) +# The target name is the current PROJECT_NAME (Bindings.Component..), the python module is +# the last part of the SOFA module name, installed in the python package made of the other parts. +function(SP3_add_component_binding sofa_module) + cmake_parse_arguments(A "" "" "SOURCES;HEADERS;DEPENDS" ${ARGN}) + + string(REPLACE "." ";" module_path "${sofa_module}") + list(POP_BACK module_path module_name) + string(REPLACE ";" "/" module_destination "${module_path}") + + SP3_add_python_module( + TARGET ${PROJECT_NAME} + PACKAGE Bindings.Component + MODULE ${module_name} + DESTINATION ${module_destination} + SOURCES ${A_SOURCES} + HEADERS ${A_HEADERS} + DEPENDS ${sofa_module} ${A_DEPENDS} SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core + ) + set_target_properties(${PROJECT_NAME} PROPERTIES FOLDER "Bindings/Component") + set_property(GLOBAL APPEND PROPERTY SP3_COMPONENT_BINDING_TARGETS ${PROJECT_NAME}) + set_property(GLOBAL APPEND PROPERTY SP3_COMPONENT_BINDING_SOFA_MODULES ${sofa_module}) +endfunction() + +if (NOT TARGET SofaPython3::Plugin) + find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) +endif() + +set(COMPONENTBINDINGS_MODULE_LIST + Constraint/Lagrangian/Solver + LinearSolver/Iterative + LinearSystem + SolidMechanics/FEM/Elastic + SolidMechanics/Spring + Topology/Container/Grid +) +if(SP3_WITH_SOFAEXPORTER) + list(APPEND COMPONENTBINDINGS_MODULE_LIST IO/Mesh) +endif() + +set_property(GLOBAL PROPERTY SP3_COMPONENT_BINDING_TARGETS "") +set_property(GLOBAL PROPERTY SP3_COMPONENT_BINDING_SOFA_MODULES "") +foreach(binding_dir ${COMPONENTBINDINGS_MODULE_LIST}) + string(REPLACE "/" "." sofa_module "Sofa.Component.${binding_dir}") + sofa_find_package(${sofa_module} QUIET) + if(${sofa_module}_FOUND) + message(STATUS "Adding binding module ${sofa_module}") + add_subdirectory(${binding_dir}) + else() + message(STATUS "${sofa_module} not found: its python bindings will not be compiled.") + endif() +endforeach() +get_property(COMPONENTBINDINGS_TARGETS GLOBAL PROPERTY SP3_COMPONENT_BINDING_TARGETS) +get_property(COMPONENTBINDINGS_SOFA_MODULES GLOBAL PROPERTY SP3_COMPONENT_BINDING_SOFA_MODULES) + +add_library(${PROJECT_NAME} INTERFACE) +add_library(SofaPython3::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME} INTERFACE ${COMPONENTBINDINGS_TARGETS}) + +# Deprecated names (Sofa.SofaDeformable, SofaExporter, Bindings.Modules, ...) +add_subdirectory(legacy) + +if(SP3_BUILD_TEST) + add_subdirectory(tests) +endif() + +sofa_create_component_in_package_with_targets( + COMPONENT_NAME ${PROJECT_NAME} + COMPONENT_VERSION ${SofaPython3_VERSION} + PACKAGE_NAME SofaPython3 + TARGETS ${PROJECT_NAME} + ) diff --git a/bindings/Component/Constraint/Lagrangian/Solver/CMakeLists.txt b/bindings/Component/Constraint/Lagrangian/Solver/CMakeLists.txt new file mode 100644 index 000000000..d8339a88e --- /dev/null +++ b/bindings/Component/Constraint/Lagrangian/Solver/CMakeLists.txt @@ -0,0 +1,16 @@ +project(Bindings.Component.Constraint.Lagrangian.Solver) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Module_Solver.cpp +) + +SP3_add_component_binding(Sofa.Component.Constraint.Lagrangian.Solver + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver.cpp b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.cpp similarity index 94% rename from bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver.cpp rename to bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.cpp index d81fba1a9..e07c32035 100644 --- a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver.cpp +++ b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.cpp @@ -17,8 +17,8 @@ ******************************************************************************* * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include -#include +#include +#include #include #include diff --git a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver.h b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver.h rename to bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver.h diff --git a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver_doc.h b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver_doc.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaConstraintSolver/Binding_ConstraintSolver_doc.h rename to bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Binding_ConstraintSolver_doc.h diff --git a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Module_SofaConstraintSolver.cpp b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Module_Solver.cpp similarity index 93% rename from bindings/Modules/src/SofaPython3/SofaConstraintSolver/Module_SofaConstraintSolver.cpp rename to bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Module_Solver.cpp index 15961fa4f..36268c0e6 100644 --- a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/Module_SofaConstraintSolver.cpp +++ b/bindings/Component/Constraint/Lagrangian/Solver/src/SofaPython3/Sofa/Component/Constraint/Lagrangian/Solver/Module_Solver.cpp @@ -19,12 +19,12 @@ ******************************************************************************/ #include -#include +#include namespace sofapython3 { -PYBIND11_MODULE(SofaConstraintSolver, m) +PYBIND11_MODULE(Solver, m) { m.doc() = "Implements the solver for constraint problems"; diff --git a/bindings/Component/IO/Mesh/CMakeLists.txt b/bindings/Component/IO/Mesh/CMakeLists.txt new file mode 100644 index 000000000..c28bd5907 --- /dev/null +++ b/bindings/Component/IO/Mesh/CMakeLists.txt @@ -0,0 +1,19 @@ +project(Bindings.Component.IO.Mesh) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter_doc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/IO/Mesh/Module_Mesh.cpp +) + +SP3_add_component_binding(Sofa.Component.IO.Mesh + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_STLExporter.cpp b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.cpp similarity index 92% rename from bindings/SofaExporter/src/SofaExporter/Binding_STLExporter.cpp rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.cpp index 5cfba4e9c..70ba4a336 100644 --- a/bindings/SofaExporter/src/SofaExporter/Binding_STLExporter.cpp +++ b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.cpp @@ -19,8 +19,8 @@ ******************************************************************************/ #include -#include -#include +#include +#include #include #include @@ -41,7 +41,7 @@ void moduleAddSTLExporter(py::module &m) return py::cast(dynamic_cast(object)); }); - py::class_> p(m, "STLExporter", sofapython3::doc::SofaExporter::STLExporter::docstring); + py::class_> p(m, "STLExporter", sofapython3::doc::io::mesh::STLExporter::docstring); p.def("write", &STLExporter::write); } diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_STLExporter.h b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.h similarity index 100% rename from bindings/SofaExporter/src/SofaExporter/Binding_STLExporter.h rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter.h diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_STLExporter_doc.h b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter_doc.h similarity index 95% rename from bindings/SofaExporter/src/SofaExporter/Binding_STLExporter_doc.h rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter_doc.h index fbd67c76d..21c610480 100644 --- a/bindings/SofaExporter/src/SofaExporter/Binding_STLExporter_doc.h +++ b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_STLExporter_doc.h @@ -21,7 +21,7 @@ #pragma once -namespace sofapython3::doc::SofaExporter::STLExporter +namespace sofapython3::doc::io::mesh::STLExporter { static auto docstring = @@ -35,7 +35,7 @@ static auto docstring = .. code-block:: python import Sofa - import SofaExporter + import Sofa.Component.IO.Mesh # Create a new node n = Sofa.Core.Node("root"") diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter.cpp b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.cpp similarity index 90% rename from bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter.cpp rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.cpp index 3a9b4af8e..ba95d6a66 100644 --- a/bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter.cpp +++ b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.cpp @@ -19,8 +19,8 @@ ******************************************************************************/ #include -#include -#include +#include +#include #include #include @@ -39,7 +39,7 @@ void moduleAddVisualModelOBJExporter(py::module &m) return py::cast(dynamic_cast(object)); }); - py::class_> p(m, "VisualModelOBJExporter", sofapython3::doc::SofaExporter::VisualModelOBJExporter::docstring); + py::class_> p(m, "VisualModelOBJExporter", sofapython3::doc::io::mesh::VisualModelOBJExporter::docstring); p.def("write", &VisualModelOBJExporter::write); } diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter.h b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.h similarity index 100% rename from bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter.h rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter.h diff --git a/bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter_doc.h b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter_doc.h similarity index 95% rename from bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter_doc.h rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter_doc.h index 0b3ee4585..2abf5bef3 100644 --- a/bindings/SofaExporter/src/SofaExporter/Binding_VisualModelOBJExporter_doc.h +++ b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Binding_VisualModelOBJExporter_doc.h @@ -20,7 +20,7 @@ #pragma once -namespace sofapython3::doc::SofaExporter::VisualModelOBJExporter { +namespace sofapython3::doc::io::mesh::VisualModelOBJExporter { static auto docstring = R"( @@ -33,7 +33,7 @@ static auto docstring = .. code-block:: python import Sofa - import SofaExporter + import Sofa.Component.IO.Mesh # Create a new node n = Sofa.Core.Node("root"") diff --git a/bindings/SofaExporter/src/SofaExporter/Module_SofaExporter.cpp b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Module_Mesh.cpp similarity index 89% rename from bindings/SofaExporter/src/SofaExporter/Module_SofaExporter.cpp rename to bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Module_Mesh.cpp index 91db0d863..3d4090ffd 100644 --- a/bindings/SofaExporter/src/SofaExporter/Module_SofaExporter.cpp +++ b/bindings/Component/IO/Mesh/src/SofaPython3/Sofa/Component/IO/Mesh/Module_Mesh.cpp @@ -21,20 +21,20 @@ #include namespace py = pybind11; -#include -#include +#include +#include namespace sofapython3 { -PYBIND11_MODULE(SofaExporter, m) { +PYBIND11_MODULE(Mesh, m) { m.doc() = R"doc( Export in STL or OBJ from from a SOFA simulation Example: .. code-block:: python - import SofaExporter + import Sofa.Component.IO.Mesh )doc"; diff --git a/bindings/Component/LinearSolver/Iterative/CMakeLists.txt b/bindings/Component/LinearSolver/Iterative/CMakeLists.txt new file mode 100644 index 000000000..c0274563a --- /dev/null +++ b/bindings/Component/LinearSolver/Iterative/CMakeLists.txt @@ -0,0 +1,16 @@ +project(Bindings.Component.LinearSolver.Iterative) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Module_Iterative.cpp +) + +SP3_add_component_binding(Sofa.Component.LinearSolver.Iterative + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver.cpp b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.cpp similarity index 96% rename from bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver.cpp rename to bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.cpp index bdcbaabb3..356feb06e 100644 --- a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver.cpp +++ b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.cpp @@ -17,8 +17,8 @@ ******************************************************************************* * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include -#include +#include +#include #include #include diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver.h b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver.h rename to bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver.h diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver_doc.h b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver_doc.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaLinearSolver/Binding_LinearSolver_doc.h rename to bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Binding_LinearSolver_doc.h diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Module_SofaLinearSolver.cpp b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Module_Iterative.cpp similarity index 93% rename from bindings/Modules/src/SofaPython3/SofaLinearSolver/Module_SofaLinearSolver.cpp rename to bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Module_Iterative.cpp index bff4a9e20..a13a069fa 100644 --- a/bindings/Modules/src/SofaPython3/SofaLinearSolver/Module_SofaLinearSolver.cpp +++ b/bindings/Component/LinearSolver/Iterative/src/SofaPython3/Sofa/Component/LinearSolver/Iterative/Module_Iterative.cpp @@ -19,12 +19,12 @@ ******************************************************************************/ #include -#include +#include namespace sofapython3 { -PYBIND11_MODULE(SofaLinearSolver, m) +PYBIND11_MODULE(Iterative, m) { moduleAddLinearSolver(m); } diff --git a/bindings/Component/LinearSystem/CMakeLists.txt b/bindings/Component/LinearSystem/CMakeLists.txt new file mode 100644 index 000000000..071c04cf8 --- /dev/null +++ b/bindings/Component/LinearSystem/CMakeLists.txt @@ -0,0 +1,17 @@ +project(Bindings.Component.LinearSystem) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.inl + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/LinearSystem/Module_LinearSystem.cpp +) + +SP3_add_component_binding(Sofa.Component.LinearSystem + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.cpp b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.cpp similarity index 99% rename from bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.cpp rename to bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.cpp index d03773972..0d7a9cd96 100644 --- a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.cpp +++ b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.cpp @@ -17,7 +17,7 @@ ******************************************************************************* * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.h b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.h rename to bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.h diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.inl b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.inl similarity index 96% rename from bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.inl rename to bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.inl index b1f4b40f3..2b6bb828f 100644 --- a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem.inl +++ b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem.inl @@ -18,8 +18,8 @@ * Contact information: contact@sofa-framework.org * ******************************************************************************/ #pragma once -#include -#include +#include +#include #include #include diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem_doc.h b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem_doc.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaLinearSystem/Binding_LinearSystem_doc.h rename to bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Binding_LinearSystem_doc.h diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Module_SofaLinearSystem.cpp b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Module_LinearSystem.cpp similarity index 93% rename from bindings/Modules/src/SofaPython3/SofaLinearSystem/Module_SofaLinearSystem.cpp rename to bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Module_LinearSystem.cpp index 2bb150c2f..1c83a905e 100644 --- a/bindings/Modules/src/SofaPython3/SofaLinearSystem/Module_SofaLinearSystem.cpp +++ b/bindings/Component/LinearSystem/src/SofaPython3/Sofa/Component/LinearSystem/Module_LinearSystem.cpp @@ -19,12 +19,12 @@ ******************************************************************************/ #include -#include +#include namespace sofapython3 { -PYBIND11_MODULE(SofaLinearSystem, m) +PYBIND11_MODULE(LinearSystem, m) { moduleAddLinearSystem(m); } diff --git a/bindings/Component/SolidMechanics/FEM/Elastic/CMakeLists.txt b/bindings/Component/SolidMechanics/FEM/Elastic/CMakeLists.txt new file mode 100644 index 000000000..d027702fb --- /dev/null +++ b/bindings/Component/SolidMechanics/FEM/Elastic/CMakeLists.txt @@ -0,0 +1,17 @@ +project(Bindings.Component.SolidMechanics.FEM.Elastic) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Module_Elastic.cpp +) + +SP3_add_component_binding(Sofa.Component.SolidMechanics.FEM.Elastic + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_CauchyStress.cpp b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.cpp similarity index 98% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_CauchyStress.cpp rename to bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.cpp index 2a9b22509..1b0b35db7 100644 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_CauchyStress.cpp +++ b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.cpp @@ -17,7 +17,7 @@ ******************************************************************************* * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_CauchyStress.h b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_CauchyStress.h rename to bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_CauchyStress.h diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.cpp similarity index 97% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp rename to bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.cpp index 313a04600..f3ecca00d 100644 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.cpp +++ b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.cpp @@ -20,7 +20,7 @@ #include -#include +#include #include namespace sofapython3 diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.h b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LameParameters.h rename to bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Binding_LameParameters.h diff --git a/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Module_Elastic.cpp b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Module_Elastic.cpp new file mode 100644 index 000000000..aade619f5 --- /dev/null +++ b/bindings/Component/SolidMechanics/FEM/Elastic/src/SofaPython3/Sofa/Component/SolidMechanics/FEM/Elastic/Module_Elastic.cpp @@ -0,0 +1,39 @@ +/****************************************************************************** +* 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 + + +namespace py { using namespace pybind11; } + +namespace sofapython3 +{ + +PYBIND11_MODULE(Elastic, m) +{ + m.doc() = "Bindings for Sofa.Component.SolidMechanics.FEM.Elastic (Lamé parameters, Cauchy stress)"; + + moduleAddLameParameters(m); + moduleAddCauchyStress(m); +} + +} // namespace sofapython3 diff --git a/bindings/Component/SolidMechanics/Spring/CMakeLists.txt b/bindings/Component/SolidMechanics/Spring/CMakeLists.txt new file mode 100644 index 000000000..6d8e1e491 --- /dev/null +++ b/bindings/Component/SolidMechanics/Spring/CMakeLists.txt @@ -0,0 +1,19 @@ +project(Bindings.Component.SolidMechanics.Spring) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring_doc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Module_Spring.cpp +) + +SP3_add_component_binding(Sofa.Component.SolidMechanics.Spring + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LinearSpring.cpp b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring.cpp similarity index 88% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LinearSpring.cpp rename to bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring.cpp index fbdc5180b..369b08119 100644 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_LinearSpring.cpp +++ b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_LinearSpring.cpp @@ -22,8 +22,8 @@ #include -#include -#include +#include +#include namespace sofapython3 { @@ -34,8 +34,8 @@ typedef LinearSpring LinearSpringR; namespace py { using namespace pybind11; } void moduleAddLinearSpring(pybind11::module& m) { - // create a python binding for the C++ class LinearSpring from SofaDeformable - py::class_ s (m, "LinearSpring", sofapython3::doc::SofaDeformable::LinearSpringClass); + // create a python binding for the C++ class LinearSpring from Sofa.Component.SolidMechanics.Spring + py::class_ s (m, "LinearSpring", sofapython3::doc::solidmechanics::spring::LinearSpringClass); // initializer for the class s.def(py::init #include -#include -#include +#include +#include #include #include @@ -45,26 +45,26 @@ void bindSpringForcefield(py::module& m) { using sofa::component::solidmechanics::spring::LinearSpring; typedef LinearSpring LinearSpringR; - // create a python binding for the c++ class SpringForceField from SofaDeformable + // create a python binding for the c++ class SpringForceField from Sofa.Component.SolidMechanics.Spring // no init binding, because creation should be done via node.addObject("SpringForceField") std::string type_name = SpringForceField::GetClass()->className+"_"+ DataType::Name(); py::class_> s (m, type_name.c_str(), sofapython3::doc::SofaDeformable::SpringForceFieldClass); + py_shared_ptr> s (m, type_name.c_str(), sofapython3::doc::solidmechanics::spring::SpringForceFieldClass); // remove all springs and optionally reserve memory for #reserve springs in the vector of springs - s.def("clear", &SpringForceField::clear, py::arg("reserve") = 0, sofapython3::doc::SofaDeformable::SpringForceFieldClear); + s.def("clear", &SpringForceField::clear, py::arg("reserve") = 0, sofapython3::doc::solidmechanics::spring::SpringForceFieldClear); // directly binding this one with &SpringForceField::getSprings returns a vector including CPUMemoryManager s.def("getSprings", [](const SpringForceField& self){ std::vector springs = self.getSprings(); return springs; - }, sofapython3::doc::SofaDeformable::SpringForceFieldGetSprings); + }, sofapython3::doc::solidmechanics::spring::SpringForceFieldGetSprings); // remove the nth spring - s.def("removeSpring", &SpringForceField::removeSpring, py::arg("index"), sofapython3::doc::SofaDeformable::SpringForceFieldRemoveSpring); + s.def("removeSpring", &SpringForceField::removeSpring, py::arg("index"), sofapython3::doc::solidmechanics::spring::SpringForceFieldRemoveSpring); // remove springs specified by a list of indices s.def("removeSprings", [](SpringForceField& self, const std::vector &v){ @@ -75,10 +75,10 @@ void bindSpringForcefield(py::module& m) { for (const auto & index : indices) { self.removeSpring(index); } - }, py::arg("indices"), sofapython3::doc::SofaDeformable::SpringForceFieldRemoveSprings); + }, py::arg("indices"), sofapython3::doc::solidmechanics::spring::SpringForceFieldRemoveSprings); // add spring form a LinearSpringR - s.def("addSpring", py::overload_cast(&SpringForceField::addSpring), py::arg("spring"), sofapython3::doc::SofaDeformable::SpringForceFieldAddSpring); + s.def("addSpring", py::overload_cast(&SpringForceField::addSpring), py::arg("spring"), sofapython3::doc::solidmechanics::spring::SpringForceFieldAddSpring); // add spring from construtor arguments for a LinearSpringR s.def("addSpring", py::overload_cast(&SpringForceField::addSpring), @@ -87,14 +87,14 @@ void bindSpringForcefield(py::module& m) { py::arg("springStiffness"), py::arg("dampingFactor"), py::arg("restLength"), - sofapython3::doc::SofaDeformable::SpringForceFieldAddSpring); + sofapython3::doc::solidmechanics::spring::SpringForceFieldAddSpring); // add multiple springs at once s.def("addSprings", [](SpringForceField& self, const std::vector &v){ for (const auto spring: v){ self.addSpring(spring); } - }, py::arg("springs"), sofapython3::doc::SofaDeformable::SpringForceFieldAddSprings); + }, py::arg("springs"), sofapython3::doc::solidmechanics::spring::SpringForceFieldAddSprings); // register the binding in the downcasting subsystem diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_SpringForceField.h b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_SpringForceField.h rename to bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField.h diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_SpringForceField_doc.h b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField_doc.h similarity index 85% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Binding_SpringForceField_doc.h rename to bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField_doc.h index 5acf094c3..d69c85d95 100644 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/Binding_SpringForceField_doc.h +++ b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Binding_SpringForceField_doc.h @@ -20,7 +20,7 @@ #pragma once -namespace sofapython3::doc::SofaDeformable { +namespace sofapython3::doc::solidmechanics::spring { static auto SpringForceFieldClass = R"( @@ -53,14 +53,14 @@ Returns all springs currently stored in the SpringForceField. static auto SpringForceFieldAddSpring = R"( -Adds a new spring to the SpringForceField. Can be done either by passing an existing Sofa.SofaDeformable.LinearSpring object, or by passing arguments to construct a new LinearSpring. +Adds a new spring to the SpringForceField. Can be done either by passing an existing Sofa.Component.SolidMechanics.Spring.LinearSpring object, or by passing arguments to construct a new LinearSpring. examples: ------------ # Adding an existing spring to the force field spring_force_field = node.addObject("SpringForceField") -spring = Sofa.SofaDeformable.LinearSpring(index1=0, index2=0, springStiffness=100, dampingFactor=5, restLength=5) +spring = Sofa.Component.SolidMechanics.Spring.LinearSpring(index1=0, index2=0, springStiffness=100, dampingFactor=5, restLength=5) spring_force_field.addSpring(spring) # Adding a new spring to the force field @@ -77,9 +77,9 @@ Like addSpring, but for a list of springs. ------------ spring_force_field = node.addObject("SpringForceField") -springs = [Sofa.SofaDeformable.LinearSpring(index1=i, index2=i, springStiffness=100, dampingFactor=5, restLength=5) for i in range(1)] +springs = [Sofa.Component.SolidMechanics.Spring.LinearSpring(index1=i, index2=i, springStiffness=100, dampingFactor=5, restLength=5) for i in range(1)] spring_force_field.addSprings(springs) )"; -} // sofapython3::doc::SofaDeformable +} // sofapython3::doc::solidmechanics::spring diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Module_Spring.cpp similarity index 83% rename from bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp rename to bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Module_Spring.cpp index 09b58d72b..3404f52fe 100644 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/Module_SofaDeformable.cpp +++ b/bindings/Component/SolidMechanics/Spring/src/SofaPython3/Sofa/Component/SolidMechanics/Spring/Module_Spring.cpp @@ -19,10 +19,8 @@ ******************************************************************************/ #include -#include -#include -#include -#include +#include +#include namespace py { using namespace pybind11; } @@ -30,14 +28,12 @@ namespace py { using namespace pybind11; } namespace sofapython3 { -PYBIND11_MODULE(SofaDeformable, m) +PYBIND11_MODULE(Spring, m) { m.doc() = "Implements linear springs between objects"; moduleAddLinearSpring(m); moduleAddSpringForceField(m); - moduleAddLameParameters(m); - moduleAddCauchyStress(m); } } // namespace sofapython3 diff --git a/bindings/Component/Topology/Container/Grid/CMakeLists.txt b/bindings/Component/Topology/Container/Grid/CMakeLists.txt new file mode 100644 index 000000000..21916f76b --- /dev/null +++ b/bindings/Component/Topology/Container/Grid/CMakeLists.txt @@ -0,0 +1,19 @@ +project(Bindings.Component.Topology.Container.Grid) + +set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology_doc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology_doc.h +) + +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Module_Grid.cpp +) + +SP3_add_component_binding(Sofa.Component.Topology.Container.Grid + SOURCES ${SOURCE_FILES} + HEADERS ${HEADER_FILES} +) diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology.cpp b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.cpp similarity index 92% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology.cpp rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.cpp index 627f2a477..4342b380a 100644 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology.cpp +++ b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.cpp @@ -36,9 +36,9 @@ namespace py { using namespace pybind11; } void moduleAddRegularGridTopology(pybind11::module& m) { py::class_> - c (m, "RegularGridTopology", doc::SofaBaseTopology::regularGridTopologyClass); + c (m, "RegularGridTopology", doc::topology::container::grid::regularGridTopologyClass); - c.def("getPoint", &RegularGridTopology::getPoint, doc::SofaBaseTopology::getPoint); + c.def("getPoint", &RegularGridTopology::getPoint, doc::topology::container::grid::getPoint); /// register the binding in the downcasting subsystem PythonFactory::registerType([](sofa::core::objectmodel::Base* object){ diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology.h b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology.h rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology.h diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology_doc.h b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology_doc.h similarity index 94% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology_doc.h rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology_doc.h index d48e90437..999eab87b 100644 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_RegularGridTopology_doc.h +++ b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_RegularGridTopology_doc.h @@ -20,7 +20,7 @@ #pragma once -namespace sofapython3::doc::SofaBaseTopology { +namespace sofapython3::doc::topology::container::grid { static auto regularGridTopologyClass = R"( @@ -37,4 +37,4 @@ Get the position of node of the grid from its index. :return: A vector3 containing the position of the given node index. :rtype: Vector3 )"; -} // sofapython3::doc::SofaBaseTopology +} // sofapython3::doc::topology::container::grid diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology.cpp b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.cpp similarity index 93% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology.cpp rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.cpp index eca392812..8cb7fbc89 100644 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology.cpp +++ b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.cpp @@ -37,12 +37,12 @@ namespace py { using namespace pybind11; } void moduleAddSparseGridTopology(pybind11::module& m) { py::class_> - c(m, "SparseGridTopology", doc::SofaBaseTopology::sparseGridTopologyClass); + c(m, "SparseGridTopology", doc::topology::container::grid::sparseGridTopologyClass); // getRegularGrid () c.def("getRegularGrid", [](SparseGridTopology & self){ return self._regularGrid.get(); - }, doc::SofaBaseTopology::getRegularGrid); + }, doc::topology::container::grid::getRegularGrid); // findCube (pos) c.def("findCube", [](SparseGridTopology & self, const py::list & l) { @@ -87,7 +87,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { } return py::make_tuple(cube_id, fx, fy, fz); - }, doc::SofaBaseTopology::findCube); + }, doc::topology::container::grid::findCube); // getRegularGridNodeIndex (sparse_grid_node_index) c.def("getRegularGridNodeIndex", [](SparseGridTopology & self, size_t sparse_grid_node_index) { @@ -99,7 +99,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { const auto pos = self.getPointPos(sparse_grid_node_index); return self._regularGrid->findPoint(pos); - }, doc::SofaBaseTopology::getRegularGridNodeIndex); + }, doc::topology::container::grid::getRegularGridNodeIndex); // getRegularGridCubeIndex (sparse_grid_cube_index) c.def("getRegularGridCubeIndex", [](SparseGridTopology & self, size_t sparse_grid_cube_index) { @@ -110,7 +110,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { } return self._indicesOfCubeinRegularGrid[sparse_grid_cube_index]; - }, doc::SofaBaseTopology::getRegularGridCubeIndex); + }, doc::topology::container::grid::getRegularGridCubeIndex); // getBoundaryCells () c.def("getBoundaryCells", [] (SparseGridTopology & self) { @@ -120,7 +120,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { indices.push_back(hexa_id); } return indices; - }, doc::SofaBaseTopology::getBoundaryCells); + }, doc::topology::container::grid::getBoundaryCells); // getBoundaryNodes () c.def("getBoundaryNodes", [] (SparseGridTopology & self) { @@ -131,7 +131,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { indices.push_back(node_id); } return indices; - }, doc::SofaBaseTopology::getBoundaryNodes); + }, doc::topology::container::grid::getBoundaryNodes); // getNodeIndicesOfCube (cube_index) c.def("getNodeIndicesOfCube", [](SparseGridTopology & self, size_t cube_index) { @@ -146,7 +146,7 @@ void moduleAddSparseGridTopology(pybind11::module& m) { indices[i] = hexa[i]; } return indices; - }, doc::SofaBaseTopology::getRegularGridCubeIndex); + }, doc::topology::container::grid::getRegularGridCubeIndex); /// register the binding in the downcasting subsystem PythonFactory::registerType([](sofa::core::objectmodel::Base* object){ diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology.h b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology.h rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology.h diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology_doc.h b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology_doc.h similarity index 97% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology_doc.h rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology_doc.h index 75c238551..9a0342ca1 100644 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Binding_SparseGridTopology_doc.h +++ b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Binding_SparseGridTopology_doc.h @@ -20,7 +20,7 @@ #pragma once -namespace sofapython3::doc::SofaBaseTopology { +namespace sofapython3::doc::topology::container::grid { static auto sparseGridTopologyClass = R"( @@ -90,4 +90,4 @@ Get the indices of the nodes of a given cube (grid cell). :rtype: list )"; -} // sofapython3::doc::SofaBaseTopology +} // sofapython3::doc::topology::container::grid diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Module_SofaBaseTopology.cpp b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Module_Grid.cpp similarity index 90% rename from bindings/Modules/src/SofaPython3/SofaBaseTopology/Module_SofaBaseTopology.cpp rename to bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Module_Grid.cpp index f208d106d..f5cbacf16 100644 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/Module_SofaBaseTopology.cpp +++ b/bindings/Component/Topology/Container/Grid/src/SofaPython3/Sofa/Component/Topology/Container/Grid/Module_Grid.cpp @@ -20,8 +20,8 @@ #include -#include -#include +#include +#include #include @@ -30,7 +30,7 @@ namespace py { using namespace pybind11; } namespace sofapython3 { -PYBIND11_MODULE(SofaBaseTopology, m) +PYBIND11_MODULE(Grid, m) { m.doc() = "Implements some topology component (Regular and SparseGridTopology)"; diff --git a/bindings/SofaExporter/Bindings.SofaExporterConfig.cmake.in b/bindings/Component/legacy/Bindings.ModulesConfig.cmake.in similarity index 69% rename from bindings/SofaExporter/Bindings.SofaExporterConfig.cmake.in rename to bindings/Component/legacy/Bindings.ModulesConfig.cmake.in index 1e13a89b4..9335be4d4 100644 --- a/bindings/SofaExporter/Bindings.SofaExporterConfig.cmake.in +++ b/bindings/Component/legacy/Bindings.ModulesConfig.cmake.in @@ -1,11 +1,11 @@ # CMake package configuration file for @PROJECT_NAME@ +# Deprecated: Bindings.Modules has been replaced by Bindings.Component. @PACKAGE_GUARD@ @PACKAGE_INIT@ -find_package(SofaPython3 QUIET REQUIRED COMPONENTS Plugin Bindings.Sofa) - -find_package(Sofa.Component.IO.Mesh QUIET REQUIRED) +find_package(Sofa.Config QUIET REQUIRED) +sofa_find_package(SofaPython3 QUIET REQUIRED COMPONENTS Bindings.Component) # If we are importing this config file and the target is not yet there this is indicating that # target is an imported one. So we include it diff --git a/bindings/Component/legacy/CMakeLists.txt b/bindings/Component/legacy/CMakeLists.txt new file mode 100644 index 000000000..a77f75fbd --- /dev/null +++ b/bindings/Component/legacy/CMakeLists.txt @@ -0,0 +1,48 @@ +project(Bindings.Modules) + +# Backward compatibility with the layout used before the bindings followed SOFA's Sofa.Component tree. +# +# - python: Sofa.SofaBaseTopology, Sofa.SofaDeformable, Sofa.SofaLinearSolver, Sofa.SofaLinearSystem, +# Sofa.SofaConstraintSolver and SofaExporter are now thin modules re-exporting the new +# Sofa.Component.* modules (with a deprecation message). +# - cmake: the Bindings.Modules component is an alias of Bindings.Component. + +SP3_add_python_package( + SOURCE_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR}/python + TARGET_DIRECTORY + . +) + +# Compiled modules left over from a previous build would shadow the python modules above (python +# loads extension modules before source files): remove them from the build tree. +set(SP3_SITE_PACKAGES_BUILD_DIR "${CMAKE_BINARY_DIR}/lib/${SP3_PYTHON_PACKAGES_DIRECTORY}") +set(SP3_LEGACY_COMPILED_MODULES + Sofa/SofaBaseTopology + Sofa/SofaConstraintSolver + Sofa/SofaDeformable + Sofa/SofaFEM + Sofa/SofaGL + Sofa/SofaLinearSolver + Sofa/SofaLinearSystem + SofaExporter +) +foreach(legacy_module ${SP3_LEGACY_COMPILED_MODULES}) + file(GLOB legacy_files "${SP3_SITE_PACKAGES_BUILD_DIR}/${legacy_module}.*") + list(FILTER legacy_files EXCLUDE REGEX "\\.py$") + if(legacy_files) + message(STATUS "Removing outdated python module ${legacy_files}") + file(REMOVE ${legacy_files}) + endif() +endforeach() + +add_library(${PROJECT_NAME} INTERFACE) +add_library(SofaPython3::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) +target_link_libraries(${PROJECT_NAME} INTERFACE Bindings.Component) + +sofa_create_component_in_package_with_targets( + COMPONENT_NAME ${PROJECT_NAME} + COMPONENT_VERSION ${SofaPython3_VERSION} + PACKAGE_NAME SofaPython3 + TARGETS ${PROJECT_NAME} + ) diff --git a/bindings/Component/legacy/python/Sofa/SofaBaseTopology.py b/bindings/Component/legacy/python/Sofa/SofaBaseTopology.py new file mode 100644 index 000000000..ea2234c3a --- /dev/null +++ b/bindings/Component/legacy/python/Sofa/SofaBaseTopology.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.Topology.Container.Grid instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaBaseTopology' is deprecated and will be removed: " + "use 'Sofa.Component.Topology.Container.Grid' instead.") + +from Sofa.Component.Topology.Container.Grid import * diff --git a/bindings/Component/legacy/python/Sofa/SofaConstraintSolver.py b/bindings/Component/legacy/python/Sofa/SofaConstraintSolver.py new file mode 100644 index 000000000..57fde0f12 --- /dev/null +++ b/bindings/Component/legacy/python/Sofa/SofaConstraintSolver.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.Constraint.Lagrangian.Solver instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaConstraintSolver' is deprecated and will be removed: " + "use 'Sofa.Component.Constraint.Lagrangian.Solver' instead.") + +from Sofa.Component.Constraint.Lagrangian.Solver import * diff --git a/bindings/Component/legacy/python/Sofa/SofaDeformable.py b/bindings/Component/legacy/python/Sofa/SofaDeformable.py new file mode 100644 index 000000000..05e36539d --- /dev/null +++ b/bindings/Component/legacy/python/Sofa/SofaDeformable.py @@ -0,0 +1,8 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.SolidMechanics.Spring and Sofa.Component.SolidMechanics.FEM.Elastic instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaDeformable' is deprecated and will be removed: " + "use 'Sofa.Component.SolidMechanics.Spring' and 'Sofa.Component.SolidMechanics.FEM.Elastic' instead.") + +from Sofa.Component.SolidMechanics.Spring import * +from Sofa.Component.SolidMechanics.FEM.Elastic import * diff --git a/bindings/Component/legacy/python/Sofa/SofaLinearSolver.py b/bindings/Component/legacy/python/Sofa/SofaLinearSolver.py new file mode 100644 index 000000000..8d50a6f54 --- /dev/null +++ b/bindings/Component/legacy/python/Sofa/SofaLinearSolver.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.LinearSolver.Iterative instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaLinearSolver' is deprecated and will be removed: " + "use 'Sofa.Component.LinearSolver.Iterative' instead.") + +from Sofa.Component.LinearSolver.Iterative import * diff --git a/bindings/Component/legacy/python/Sofa/SofaLinearSystem.py b/bindings/Component/legacy/python/Sofa/SofaLinearSystem.py new file mode 100644 index 000000000..c7907b333 --- /dev/null +++ b/bindings/Component/legacy/python/Sofa/SofaLinearSystem.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.LinearSystem instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaLinearSystem' is deprecated and will be removed: " + "use 'Sofa.Component.LinearSystem' instead.") + +from Sofa.Component.LinearSystem import * diff --git a/bindings/Component/legacy/python/SofaExporter.py b/bindings/Component/legacy/python/SofaExporter.py new file mode 100644 index 000000000..3575f552e --- /dev/null +++ b/bindings/Component/legacy/python/SofaExporter.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.Component.IO.Mesh instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'SofaExporter' is deprecated and will be removed: " + "use 'Sofa.Component.IO.Mesh' instead.") + +from Sofa.Component.IO.Mesh import * diff --git a/bindings/Modules/tests/CMakeLists.txt b/bindings/Component/tests/CMakeLists.txt similarity index 54% rename from bindings/Modules/tests/CMakeLists.txt rename to bindings/Component/tests/CMakeLists.txt index d1055b36a..fb96b7a7d 100644 --- a/bindings/Modules/tests/CMakeLists.txt +++ b/bindings/Component/tests/CMakeLists.txt @@ -1,18 +1,22 @@ -project(Bindings.Modules.Tests) +project(Bindings.Component.Tests) set(SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp ) -set(PYTHON_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/SofaDeformable/LinearSpring.py - ${CMAKE_CURRENT_SOURCE_DIR}/SofaDeformable/SpringForceField.py - - ${CMAKE_CURRENT_SOURCE_DIR}/SofaLinearSolver/matrix_access.py - - ${CMAKE_CURRENT_SOURCE_DIR}/SofaConstraintSolver/matrix_access.py +# Python test directories, one per bound SOFA module (same layout as the bindings) +set(TEST_DIRECTORIES + Constraint/Lagrangian/Solver + LinearSolver/Iterative + SolidMechanics/Spring ) +set(PYTHON_FILES) +foreach(test_dir ${TEST_DIRECTORIES}) + file(GLOB test_dir_files "${CMAKE_CURRENT_SOURCE_DIR}/${test_dir}/*.py") + list(APPEND PYTHON_FILES ${test_dir_files}) +endforeach() + find_package(Sofa.Testing REQUIRED) enable_testing() @@ -29,20 +33,20 @@ sofa_auto_set_target_rpath( add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) -set(DIR_BINDING_LIST SofaBaseTopology SofaDeformable SofaLinearSolver SofaConstraintSolver) get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) -foreach(dir_binding ${DIR_BINDING_LIST}) - if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${dir_binding}") +foreach(test_dir ${TEST_DIRECTORIES}) + string(REPLACE "/" "." binding_target "Bindings.Component.${test_dir}") + if (NOT TARGET ${binding_target}) continue() endif() if (_isMultiConfig) # MSVC foreach(config_type ${CMAKE_CONFIGURATION_TYPES}) - SP3_configure_directory(${CMAKE_CURRENT_SOURCE_DIR}/${dir_binding} ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${config_type}/${PROJECT_NAME}.d/${dir_binding}) - install(DIRECTORY ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${config_type}/${PROJECT_NAME}.d/${dir_binding} DESTINATION ${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d) + SP3_configure_directory(${CMAKE_CURRENT_SOURCE_DIR}/${test_dir} ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${config_type}/${PROJECT_NAME}.d/${test_dir}) + install(DIRECTORY ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${config_type}/${PROJECT_NAME}.d/${test_dir}/ DESTINATION ${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${test_dir}) endforeach() else() - SP3_configure_directory(${CMAKE_CURRENT_SOURCE_DIR}/${dir_binding} ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${dir_binding}) - install(DIRECTORY ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${dir_binding} DESTINATION ${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d) + SP3_configure_directory(${CMAKE_CURRENT_SOURCE_DIR}/${test_dir} ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${test_dir}) + install(DIRECTORY ${CMAKE_BINARY_DIR}/${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${test_dir}/ DESTINATION ${RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.d/${test_dir}) endif() endforeach() diff --git a/bindings/Modules/tests/SofaConstraintSolver/matrix_access.py b/bindings/Component/tests/Constraint/Lagrangian/Solver/matrix_access.py similarity index 95% rename from bindings/Modules/tests/SofaConstraintSolver/matrix_access.py rename to bindings/Component/tests/Constraint/Lagrangian/Solver/matrix_access.py index 9dd87dd45..42a7de971 100644 --- a/bindings/Modules/tests/SofaConstraintSolver/matrix_access.py +++ b/bindings/Component/tests/Constraint/Lagrangian/Solver/matrix_access.py @@ -1,6 +1,6 @@ import unittest import Sofa.Core -from Sofa import SofaConstraintSolver +import Sofa.Component.Constraint.Lagrangian.Solver class Test(unittest.TestCase): @@ -18,6 +18,7 @@ def simulate_pendulum(self): "Sofa.Component.Mapping.MappedMatrix", "Sofa.Component.Mass", "Sofa.Component.IntegrationScheme.Backward", + "Sofa.Component.StateContainer", "Sofa.Component.Topology.Container.Dynamic"]) root.addObject("FreeMotionAnimationLoop", solveVelocityConstraintFirst=True) diff --git a/bindings/Modules/tests/SofaLinearSolver/matrix_access.py b/bindings/Component/tests/LinearSolver/Iterative/matrix_access.py similarity index 91% rename from bindings/Modules/tests/SofaLinearSolver/matrix_access.py rename to bindings/Component/tests/LinearSolver/Iterative/matrix_access.py index cd84eb4bf..fade8eb0b 100644 --- a/bindings/Modules/tests/SofaLinearSolver/matrix_access.py +++ b/bindings/Component/tests/LinearSolver/Iterative/matrix_access.py @@ -1,6 +1,6 @@ import unittest import Sofa.Core -from Sofa import SofaLinearSolver +import Sofa.Component.LinearSolver.Iterative class Test(unittest.TestCase): @@ -15,6 +15,8 @@ def simulate_beam(self, linear_solver_template): root.addObject('RequiredPlugin', pluginName='Sofa.Component.Constraint.Projective') root.addObject('RequiredPlugin', pluginName='Sofa.Component.SolidMechanics.FEM.Elastic') root.addObject('RequiredPlugin', pluginName='Sofa.Component.Mass') + root.addObject('RequiredPlugin', pluginName='Sofa.Component.StateContainer') + root.addObject('RequiredPlugin', pluginName='Sofa.Component.Topology.Container.Grid') root.addObject('EulerImplicitIntegrationScheme', rayleighStiffness="0.1", rayleighMass="0.1") linear_solver = root.addObject('SparseLDLSolver', name='linear_solver', template=linear_solver_template) diff --git a/bindings/Component/tests/SolidMechanics/Spring/LegacyModuleName.py b/bindings/Component/tests/SolidMechanics/Spring/LegacyModuleName.py new file mode 100644 index 000000000..1ec3506bb --- /dev/null +++ b/bindings/Component/tests/SolidMechanics/Spring/LegacyModuleName.py @@ -0,0 +1,27 @@ +# coding: utf8 + +import unittest + +import Sofa.Component.SolidMechanics.Spring as Spring +import Sofa.Component.SolidMechanics.FEM.Elastic as Elastic + + +class Test(unittest.TestCase): + def __init__(self, a): + unittest.TestCase.__init__(self, a) + + def test_module_path(self): + self.assertEqual(Spring.__name__, "Sofa.Component.SolidMechanics.Spring") + self.assertEqual(Spring.LinearSpring.__module__, "Sofa.Component.SolidMechanics.Spring") + self.assertEqual(Spring.SpringForceField_Vec3d.__module__, "Sofa.Component.SolidMechanics.Spring") + + def test_deprecated_SofaDeformable(self): + # The deprecated module re-exports the bindings of both SOFA modules it used to contain + from Sofa import SofaDeformable + self.assertIs(SofaDeformable.LinearSpring, Spring.LinearSpring) + self.assertIs(SofaDeformable.SpringForceField_Vec3d, Spring.SpringForceField_Vec3d) + self.assertIs(SofaDeformable.toLameParameters3D, Elastic.toLameParameters3D) + + +if __name__ == '__main__': + unittest.main() diff --git a/bindings/Modules/tests/SofaDeformable/LinearSpring.py b/bindings/Component/tests/SolidMechanics/Spring/LinearSpring.py similarity index 96% rename from bindings/Modules/tests/SofaDeformable/LinearSpring.py rename to bindings/Component/tests/SolidMechanics/Spring/LinearSpring.py index fbd2de924..dd649d5f0 100644 --- a/bindings/Modules/tests/SofaDeformable/LinearSpring.py +++ b/bindings/Component/tests/SolidMechanics/Spring/LinearSpring.py @@ -1,7 +1,7 @@ # coding: utf8 import unittest -from Sofa.SofaDeformable import LinearSpring +from Sofa.Component.SolidMechanics.Spring import LinearSpring class Test(unittest.TestCase): diff --git a/bindings/Modules/tests/SofaDeformable/SpringForceField.py b/bindings/Component/tests/SolidMechanics/Spring/SpringForceField.py similarity index 91% rename from bindings/Modules/tests/SofaDeformable/SpringForceField.py rename to bindings/Component/tests/SolidMechanics/Spring/SpringForceField.py index 20a71fb97..2a4f3ddda 100644 --- a/bindings/Modules/tests/SofaDeformable/SpringForceField.py +++ b/bindings/Component/tests/SolidMechanics/Spring/SpringForceField.py @@ -1,6 +1,6 @@ import unittest import Sofa -from Sofa import SofaDeformable +from Sofa.Component.SolidMechanics import Spring import numpy as np @@ -76,7 +76,7 @@ def test_clear(self): def test_add_one_spring(self): self.root.spring_ff.clear() self.root.spring_ff.addSpring( - SofaDeformable.LinearSpring(index1=2, index2=2, springStiffness=1, dampingFactor=1, restLength=1, elongationOnly=True, enabled=False) + Spring.LinearSpring(index1=2, index2=2, springStiffness=1, dampingFactor=1, restLength=1, elongationOnly=True, enabled=False) ) self.assertEqual(len(self.root.spring_ff.getSprings()), 1) spring_1 = self.root.spring_ff.getSprings()[0] @@ -102,8 +102,8 @@ def test_add_one_spring(self): def test_add_many_springs(self): self.root.spring_ff.clear() self.root.spring_ff.addSprings([ - SofaDeformable.LinearSpring(index1=2, index2=2, springStiffness=1, dampingFactor=1, restLength=1, elongationOnly=True, enabled=False), - SofaDeformable.LinearSpring(index1=3, index2=3, springStiffness=2, dampingFactor=2, restLength=2, elongationOnly=False, enabled=True) + Spring.LinearSpring(index1=2, index2=2, springStiffness=1, dampingFactor=1, restLength=1, elongationOnly=True, enabled=False), + Spring.LinearSpring(index1=3, index2=3, springStiffness=2, dampingFactor=2, restLength=2, elongationOnly=False, enabled=True) ]) self.assertEqual(len(self.root.spring_ff.getSprings()), 2) spring_1 = self.root.spring_ff.getSprings()[0] diff --git a/bindings/Modules/tests/main.cpp b/bindings/Component/tests/main.cpp similarity index 74% rename from bindings/Modules/tests/main.cpp rename to bindings/Component/tests/main.cpp index daf9b21f4..376173705 100644 --- a/bindings/Modules/tests/main.cpp +++ b/bindings/Component/tests/main.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -38,18 +40,26 @@ static struct Tests : public sofapython3::PythonTestExtractor MessageDispatcher::addHandler(&MainPerComponentLoggingMessageHandler::getInstance()) ; const std::string executable_directory = sofa::helper::Utils::getExecutableDirectory(); - addTestDirectory(executable_directory+"/Bindings.Modules.Tests.d/SofaDeformable", "SofaDeformable_"); - addTestDirectory(executable_directory+"/Bindings.Modules.Tests.d/SofaLinearSolver", "SofaLinearSolver_"); - addTestDirectory(executable_directory+"/Bindings.Modules.Tests.d/SofaConstraintSolver", "SofaConstraintSolver_"); + // One directory per bound SOFA module, only present if the module bindings were built + for (const std::string module : {"Constraint/Lagrangian/Solver", "LinearSolver/Iterative", "SolidMechanics/Spring"}) + { + const std::string directory = executable_directory + "/Bindings.Component.Tests.d/" + module; + if (sofa::helper::system::FileSystem::exists(directory)) + { + std::string testgroup = module + "_"; + std::replace(testgroup.begin(), testgroup.end(), '/', '_'); + addTestDirectory(directory, testgroup); + } + } } } python_tests; /// run test list using the custom name function getTestName. /// this allows to do gtest_filter=*FileName* -class Modules : public sofapython3::PythonTest {}; +class Component : public sofapython3::PythonTest {}; INSTANTIATE_TEST_SUITE_P(SofaPython3, - Modules, + Component, ::testing::ValuesIn(python_tests.extract()), - Modules::getTestName); + Component::getTestName); -TEST_P(Modules, all_tests) { run(GetParam()); } +TEST_P(Component, all_tests) { run(GetParam()); } diff --git a/bindings/Modules/CMakeLists.txt b/bindings/Modules/CMakeLists.txt deleted file mode 100644 index e47f53071..000000000 --- a/bindings/Modules/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -project(Bindings.Modules) - -set(MODULEBINDINGS_MODULE_LIST - SofaBaseTopology - SofaDeformable - SofaLinearSolver - SofaLinearSystem - SofaConstraintSolver - SofaFEM -) - -sofa_find_package(Sofa.GL QUIET) -if(Sofa.GL_FOUND) - list(APPEND MODULEBINDINGS_MODULE_LIST SofaGL) -else() - message("Sofa.GL not detected. Python3 Bindings for Sofa.SofaGL will not be compiled.") -endif() - - -foreach(modulebindings_module ${MODULEBINDINGS_MODULE_LIST}) - message(STATUS "Adding binding module ${modulebindings_module}") - add_subdirectory(src/SofaPython3/${modulebindings_module}) -endforeach() - - -add_library(${PROJECT_NAME} INTERFACE) -add_library(SofaPython3::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) - -foreach(modulebindings_module ${MODULEBINDINGS_MODULE_LIST}) - target_link_libraries(${PROJECT_NAME} INTERFACE ${PROJECT_NAME}.${modulebindings_module}) - set_target_properties(${PROJECT_NAME}.${modulebindings_module} PROPERTIES FOLDER "Bindings/Modules") -endforeach() - -if(SP3_BUILD_TEST) - add_subdirectory(tests) -endif() - -sofa_create_component_in_package_with_targets( - COMPONENT_NAME ${PROJECT_NAME} - COMPONENT_VERSION ${SofaPython3_VERSION} - PACKAGE_NAME SofaPython3 - TARGETS ${PROJECT_NAME} - ) diff --git a/bindings/Modules/src/SofaPython3/SofaBaseTopology/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaBaseTopology/CMakeLists.txt deleted file mode 100644 index 6e56ae462..000000000 --- a/bindings/Modules/src/SofaPython3/SofaBaseTopology/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -project(Bindings.Modules.SofaBaseTopology) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_RegularGridTopology.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SparseGridTopology.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaBaseTopology.cpp -) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_RegularGridTopology.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_RegularGridTopology_doc.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SparseGridTopology.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SparseGridTopology_doc.h -) - -sofa_find_package(Sofa.Component.Topology.Container.Grid REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaBaseTopology - DESTINATION Sofa - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.Topology.Container.Grid SofaPython3::Plugin -) diff --git a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaConstraintSolver/CMakeLists.txt deleted file mode 100644 index 3818293b1..000000000 --- a/bindings/Modules/src/SofaPython3/SofaConstraintSolver/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -project(Bindings.Modules.SofaConstraintSolver) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_ConstraintSolver.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_ConstraintSolver_doc.h -) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_ConstraintSolver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaConstraintSolver.cpp -) - -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() - -sofa_find_package(Sofa.Component.Constraint.Lagrangian.Solver REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaConstraintSolver - DESTINATION Sofa - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.Constraint.Lagrangian.Solver SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core -) diff --git a/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt deleted file mode 100644 index c884ff1af..000000000 --- a/bindings/Modules/src/SofaPython3/SofaDeformable/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -project(Bindings.Modules.SofaDeformable) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_CauchyStress.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LameParameters.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SpringForceField.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaDeformable.cpp -) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_CauchyStress.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LameParameters.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSpring_doc.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SpringForceField.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_SpringForceField_doc.h -) - -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() - -sofa_find_package(Sofa.Component.SolidMechanics.Spring REQUIRED) -sofa_find_package(Sofa.Component.SolidMechanics.FEM.Elastic REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaDeformable - DESTINATION Sofa - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.SolidMechanics.Spring Sofa.Component.SolidMechanics.FEM.Elastic SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core - -) diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSolver/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaLinearSolver/CMakeLists.txt deleted file mode 100644 index 9e709544a..000000000 --- a/bindings/Modules/src/SofaPython3/SofaLinearSolver/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -project(Bindings.Modules.SofaLinearSolver) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSolver.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSolver_doc.h -) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSolver.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaLinearSolver.cpp -) - -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() - -sofa_find_package(Sofa.Component.LinearSolver.Iterative REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaLinearSolver - DESTINATION Sofa - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.LinearSolver.Iterative SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core -) diff --git a/bindings/Modules/src/SofaPython3/SofaLinearSystem/CMakeLists.txt b/bindings/Modules/src/SofaPython3/SofaLinearSystem/CMakeLists.txt deleted file mode 100644 index fd0805488..000000000 --- a/bindings/Modules/src/SofaPython3/SofaLinearSystem/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -project(Bindings.Modules.SofaLinearSystem) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSystem.h - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSystem.inl - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSystem_doc.h -) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_LinearSystem.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaLinearSystem.cpp -) - -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() - -sofa_find_package(Sofa.Component.LinearSystem REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaLinearSystem - DESTINATION Sofa - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.LinearSystem SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core -) diff --git a/bindings/Sofa/Bindings.SofaConfig.cmake.in b/bindings/Sofa/Bindings.SofaConfig.cmake.in index 42f003bce..0affc00b8 100644 --- a/bindings/Sofa/Bindings.SofaConfig.cmake.in +++ b/bindings/Sofa/Bindings.SofaConfig.cmake.in @@ -21,6 +21,15 @@ sofa_find_package(Sofa.SimpleApi QUIET REQUIRED) # Required by Bindings.Sofa.Simulation sofa_find_package(Sofa.Simulation.Graph QUIET REQUIRED) +# Optional framework modules bound by Bindings.Sofa.FEM and Bindings.Sofa.GL +set(SP3_BINDINGS_SOFA_MODULES "@SOFABINDINGS_MODULE_LIST@") +if("FEM" IN_LIST SP3_BINDINGS_SOFA_MODULES) + sofa_find_package(Sofa.FEM QUIET REQUIRED) +endif() +if("GL" IN_LIST SP3_BINDINGS_SOFA_MODULES) + sofa_find_package(Sofa.GL QUIET REQUIRED) +endif() + # If we are importing this config file and the target is not yet there this is indicating that # target is an imported one. So we include it if(NOT TARGET @PROJECT_NAME@) diff --git a/bindings/Sofa/CMakeLists.txt b/bindings/Sofa/CMakeLists.txt index 63227a2b9..a5d3f04da 100644 --- a/bindings/Sofa/CMakeLists.txt +++ b/bindings/Sofa/CMakeLists.txt @@ -7,6 +7,20 @@ set(SOFABINDINGS_MODULE_LIST Types ) +# Optional framework modules +sofa_find_package(Sofa.FEM QUIET) +if(Sofa.FEM_FOUND) + list(APPEND SOFABINDINGS_MODULE_LIST FEM) +else() + message(STATUS "Sofa.FEM not found: python bindings Sofa.FEM will not be compiled.") +endif() +sofa_find_package(Sofa.GL QUIET) +if(Sofa.GL_FOUND) + list(APPEND SOFABINDINGS_MODULE_LIST GL) +else() + message(STATUS "Sofa.GL not found: python bindings Sofa.GL will not be compiled.") +endif() + foreach(sofabindings_module ${SOFABINDINGS_MODULE_LIST}) add_subdirectory(src/SofaPython3/Sofa/${sofabindings_module}) endforeach() diff --git a/bindings/Sofa/package/SofaFEM.py b/bindings/Sofa/package/SofaFEM.py new file mode 100644 index 000000000..6a979b836 --- /dev/null +++ b/bindings/Sofa/package/SofaFEM.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.FEM instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaFEM' is deprecated and will be removed: " + "use 'Sofa.FEM' instead.") + +from Sofa.FEM import * diff --git a/bindings/Sofa/package/SofaGL.py b/bindings/Sofa/package/SofaGL.py new file mode 100644 index 000000000..e0cd5c162 --- /dev/null +++ b/bindings/Sofa/package/SofaGL.py @@ -0,0 +1,7 @@ +"""Deprecated module, kept for backward compatibility. Use Sofa.GL instead.""" +import Sofa.Helper + +Sofa.Helper.msg_deprecated("SofaPython3", "The python module 'Sofa.SofaGL' is deprecated and will be removed: " + "use 'Sofa.GL' instead.") + +from Sofa.GL import * diff --git a/bindings/Modules/src/SofaPython3/SofaFEM/Binding_Quadrature.cpp b/bindings/Sofa/src/SofaPython3/Sofa/FEM/Binding_Quadrature.cpp similarity index 98% rename from bindings/Modules/src/SofaPython3/SofaFEM/Binding_Quadrature.cpp rename to bindings/Sofa/src/SofaPython3/Sofa/FEM/Binding_Quadrature.cpp index 2ef429746..5bd782307 100644 --- a/bindings/Modules/src/SofaPython3/SofaFEM/Binding_Quadrature.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/FEM/Binding_Quadrature.cpp @@ -17,7 +17,7 @@ ******************************************************************************* * Contact information: contact@sofa-framework.org * ******************************************************************************/ -#include +#include #include @@ -64,7 +64,7 @@ static py::tuple withElement(const std::string& element, py::ssize_t dim, Functi if (element == "Tetrahedron" && dim == 3) return f(ElementTag{}); if (element == "Hexahedron" && dim == 3) return f(ElementTag{}); - throw py::value_error("SofaFEM: unsupported element '" + element + "' for dimension " + std::to_string(dim)); + throw py::value_error("Sofa.FEM: unsupported element '" + element + "' for dimension " + std::to_string(dim)); } // Reference-space quadrature points' data for one FiniteElement specialization: diff --git a/bindings/Modules/src/SofaPython3/SofaFEM/Binding_Quadrature.h b/bindings/Sofa/src/SofaPython3/Sofa/FEM/Binding_Quadrature.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaFEM/Binding_Quadrature.h rename to bindings/Sofa/src/SofaPython3/Sofa/FEM/Binding_Quadrature.h diff --git a/bindings/Modules/src/SofaPython3/SofaFEM/CMakeLists.txt b/bindings/Sofa/src/SofaPython3/Sofa/FEM/CMakeLists.txt similarity index 61% rename from bindings/Modules/src/SofaPython3/SofaFEM/CMakeLists.txt rename to bindings/Sofa/src/SofaPython3/Sofa/FEM/CMakeLists.txt index f6111c328..464333fee 100644 --- a/bindings/Modules/src/SofaPython3/SofaFEM/CMakeLists.txt +++ b/bindings/Sofa/src/SofaPython3/Sofa/FEM/CMakeLists.txt @@ -1,24 +1,20 @@ -project(Bindings.Modules.SofaFEM) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Quadrature.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaFEM.cpp -) +project(Bindings.Sofa.FEM) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Quadrature.h ) -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/Binding_Quadrature.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Submodule_FEM.cpp +) sofa_find_package(Sofa.FEM REQUIRED) SP3_add_python_module( TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaFEM + PACKAGE Bindings.Sofa + MODULE FEM DESTINATION Sofa SOURCES ${SOURCE_FILES} HEADERS ${HEADER_FILES} diff --git a/bindings/Modules/src/SofaPython3/SofaFEM/Module_SofaFEM.cpp b/bindings/Sofa/src/SofaPython3/Sofa/FEM/Submodule_FEM.cpp similarity index 95% rename from bindings/Modules/src/SofaPython3/SofaFEM/Module_SofaFEM.cpp rename to bindings/Sofa/src/SofaPython3/Sofa/FEM/Submodule_FEM.cpp index ff000ca2c..f53de852d 100644 --- a/bindings/Modules/src/SofaPython3/SofaFEM/Module_SofaFEM.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/FEM/Submodule_FEM.cpp @@ -19,14 +19,14 @@ ******************************************************************************/ #include -#include +#include namespace py { using namespace pybind11; } namespace sofapython3 { -PYBIND11_MODULE(SofaFEM, m) +PYBIND11_MODULE(FEM, m) { m.doc() = "Bindings for the sofa::fem finite-element machinery"; diff --git a/bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.cpp b/bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL.cpp similarity index 93% rename from bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.cpp rename to bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL.cpp index 3c4377185..1880f4426 100644 --- a/bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL.cpp @@ -28,8 +28,8 @@ using sofa::simulation::Node; #include #include -#include -#include +#include +#include namespace sofapython3 { @@ -51,11 +51,11 @@ void moduleAddDrawToolGL(pybind11::module& m) { vparam->setSupported(sofa::core::visual::API_OpenGL); } sofa::simulation::node::draw(vparam, node); - }, doc::SofaGL::draw); + }, doc::gl::draw); m.def("glewInit", [](){ glewInit(); - }, doc::SofaGL::glewInit); + }, doc::gl::glewInit); } } // namespace sofapython3 diff --git a/bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.h b/bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL.h similarity index 100% rename from bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL.h rename to bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL.h diff --git a/bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL_doc.h b/bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL_doc.h similarity index 96% rename from bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL_doc.h rename to bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL_doc.h index 085024f68..c8f47d755 100644 --- a/bindings/Modules/src/SofaPython3/SofaGL/Binding_DrawToolGL_doc.h +++ b/bindings/Sofa/src/SofaPython3/Sofa/GL/Binding_DrawToolGL_doc.h @@ -20,7 +20,7 @@ #pragma once -namespace sofapython3::doc::SofaGL { +namespace sofapython3::doc::gl { static auto draw = R"( Draw the openGL visual loop from the provided Node. @@ -33,4 +33,4 @@ R"( Initialize GLEW. This should be called once before drawing. )"; -} // sofapython3::doc::SofaGL +} // sofapython3::doc::gl diff --git a/bindings/Modules/src/SofaPython3/SofaGL/CMakeLists.txt b/bindings/Sofa/src/SofaPython3/Sofa/GL/CMakeLists.txt similarity index 64% rename from bindings/Modules/src/SofaPython3/SofaGL/CMakeLists.txt rename to bindings/Sofa/src/SofaPython3/Sofa/GL/CMakeLists.txt index 257122946..cd2909abc 100644 --- a/bindings/Modules/src/SofaPython3/SofaGL/CMakeLists.txt +++ b/bindings/Sofa/src/SofaPython3/Sofa/GL/CMakeLists.txt @@ -1,28 +1,23 @@ -project(Bindings.Modules.SofaGL) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/Module_SofaGL.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.cpp -) +project(Bindings.Sofa.GL) set(HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.h ${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL_doc.h ) -if (NOT TARGET SofaPython3::Plugin) - find_package(SofaPython3 REQUIRED COMPONENTS Plugin Bindings.Sofa) -endif() +set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/Binding_DrawToolGL.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Submodule_GL.cpp +) sofa_find_package(Sofa.GL REQUIRED) SP3_add_python_module( TARGET ${PROJECT_NAME} - PACKAGE Bindings.Modules - MODULE SofaGL + PACKAGE Bindings.Sofa + MODULE GL DESTINATION Sofa SOURCES ${SOURCE_FILES} HEADERS ${HEADER_FILES} DEPENDS Sofa.GL SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core - ) diff --git a/bindings/Modules/src/SofaPython3/SofaGL/Module_SofaGL.cpp b/bindings/Sofa/src/SofaPython3/Sofa/GL/Submodule_GL.cpp similarity index 95% rename from bindings/Modules/src/SofaPython3/SofaGL/Module_SofaGL.cpp rename to bindings/Sofa/src/SofaPython3/Sofa/GL/Submodule_GL.cpp index b302bf801..55cbd4d15 100644 --- a/bindings/Modules/src/SofaPython3/SofaGL/Module_SofaGL.cpp +++ b/bindings/Sofa/src/SofaPython3/Sofa/GL/Submodule_GL.cpp @@ -19,7 +19,7 @@ ******************************************************************************/ #include -#include +#include namespace py { using namespace pybind11; } @@ -27,7 +27,7 @@ namespace py { using namespace pybind11; } namespace sofapython3 { -PYBIND11_MODULE(SofaGL, m) +PYBIND11_MODULE(GL, m) { m.doc() = "Exposes the rendering API using OpenGL"; diff --git a/bindings/SofaExporter/CMakeLists.txt b/bindings/SofaExporter/CMakeLists.txt deleted file mode 100644 index 58a5b286c..000000000 --- a/bindings/SofaExporter/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -project(Bindings.SofaExporter) - -set(HEADER_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_STLExporter.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_STLExporter_doc.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_VisualModelOBJExporter.h - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_VisualModelOBJExporter_doc.h -) - -set(SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_STLExporter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Binding_VisualModelOBJExporter.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/src/SofaExporter/Module_SofaExporter.cpp -) - -sofa_find_package(Sofa.Component.IO.Mesh REQUIRED) - -SP3_add_python_module( - TARGET ${PROJECT_NAME} - MODULE SofaExporter - DESTINATION . - SOURCES ${SOURCE_FILES} - HEADERS ${HEADER_FILES} - DEPENDS Sofa.Component.IO.Mesh SofaPython3::Plugin SofaPython3::Bindings.Sofa.Core -) - -sofa_create_component_in_package_with_targets( - COMPONENT_NAME ${PROJECT_NAME} - COMPONENT_VERSION ${SofaPython3_VERSION} - PACKAGE_NAME SofaPython3 - TARGETS ${PROJECT_NAME} - ) diff --git a/docs/README.md b/docs/README.md index 7a67c2000..8560b5ffd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -40,7 +40,11 @@ Go inside the `SofaPython3/docs` directory and run ```shell pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" SofaRuntime pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" Sofa -pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" SofaExporter +for module in Sofa.FEM Sofa.GL Sofa.Component.IO.Mesh Sofa.Component.Topology.Container.Grid Sofa.Component.LinearSystem \ + Sofa.Component.LinearSolver.Iterative Sofa.Component.Constraint.Lagrangian.Solver \ + Sofa.Component.SolidMechanics.Spring Sofa.Component.SolidMechanics.FEM.Elastic; do + pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" $module +done pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" SofaTypes pybind11-stubgen -o sphinx-stubs --no-setup-py --ignore-invalid=signature --root-module-suffix="" splib ``` diff --git a/docs/sphinx/source/content/Modules.rst b/docs/sphinx/source/content/Modules.rst index 602ae0405..e0fddcbaa 100644 --- a/docs/sphinx/source/content/Modules.rst +++ b/docs/sphinx/source/content/Modules.rst @@ -8,7 +8,6 @@ Modules modules/Sofa/index modules/SofaRuntime/index - modules/SofaExporter/index The SofaPython3 binding is highly modular allowing to select only the modules strictly relevant to your needs. @@ -18,6 +17,5 @@ Most commonly used modules provided by the Sofa-consortium are: Sofa SofaRuntime - SofaExporter \ No newline at end of file diff --git a/docs/sphinx/source/content/modules/Sofa/additionalmodules.rst b/docs/sphinx/source/content/modules/Sofa/additionalmodules.rst index 8d9c5dfb0..aae086bde 100644 --- a/docs/sphinx/source/content/modules/Sofa/additionalmodules.rst +++ b/docs/sphinx/source/content/modules/Sofa/additionalmodules.rst @@ -6,7 +6,12 @@ Additional modules :template: autosummary/sub-modules.rst :recursive: - Sofa.SofaBaseTopology - Sofa.SofaConstraintSolver - Sofa.SofaDeformable - Sofa.SofaGL \ No newline at end of file + Sofa.Component.Constraint.Lagrangian.Solver + Sofa.Component.IO.Mesh + Sofa.Component.LinearSolver.Iterative + Sofa.Component.LinearSystem + Sofa.Component.SolidMechanics.FEM.Elastic + Sofa.Component.SolidMechanics.Spring + Sofa.Component.Topology.Container.Grid + Sofa.FEM + Sofa.GL diff --git a/docs/sphinx/source/content/modules/Sofa/index.rst b/docs/sphinx/source/content/modules/Sofa/index.rst index 69a69e542..b01df1c93 100644 --- a/docs/sphinx/source/content/modules/Sofa/index.rst +++ b/docs/sphinx/source/content/modules/Sofa/index.rst @@ -50,7 +50,12 @@ Sofa .. autosummary:: :template: autosummary/sub-modules.rst - SofaBaseTopology - SofaConstraintSolver - SofaDeformable - SofaGL + Component.Constraint.Lagrangian.Solver + Component.IO.Mesh + Component.LinearSolver.Iterative + Component.LinearSystem + Component.SolidMechanics.FEM.Elastic + Component.SolidMechanics.Spring + Component.Topology.Container.Grid + FEM + GL diff --git a/docs/sphinx/source/content/modules/SofaExporter/index.rst b/docs/sphinx/source/content/modules/SofaExporter/index.rst deleted file mode 100644 index 1b6896444..000000000 --- a/docs/sphinx/source/content/modules/SofaExporter/index.rst +++ /dev/null @@ -1,17 +0,0 @@ -SofaExporter -************ - -.. currentmodule:: SofaExporter - -.. automodule:: SofaExporter - -API Table of Content --------------------- - -.. autosummary:: - :toctree: generated - :template: autosummary/base.rst - :recursive: - - STLExporter - VisualModelOBJExporter diff --git a/examples/access_compliance_matrix.py b/examples/access_compliance_matrix.py index b1007a5c2..f182002ff 100644 --- a/examples/access_compliance_matrix.py +++ b/examples/access_compliance_matrix.py @@ -1,7 +1,7 @@ # Required import for python import Sofa import SofaRuntime -from Sofa import SofaConstraintSolver +import Sofa.Component.Constraint.Lagrangian.Solver import numpy as np diff --git a/examples/access_mass_matrix.py b/examples/access_mass_matrix.py index 1bd6519f4..dd6a4ceca 100644 --- a/examples/access_mass_matrix.py +++ b/examples/access_mass_matrix.py @@ -1,7 +1,7 @@ # Required import for python import Sofa import SofaRuntime -from Sofa import SofaLinearSystem +import Sofa.Component.LinearSystem from scipy import sparse from scipy import linalg from matplotlib import pyplot as plt diff --git a/examples/access_matrix.py b/examples/access_matrix.py index fd654b6ce..f1cf7068f 100644 --- a/examples/access_matrix.py +++ b/examples/access_matrix.py @@ -1,8 +1,8 @@ # Required import for python import Sofa import SofaRuntime -from Sofa import SofaLinearSystem -from Sofa import SofaLinearSolver +import Sofa.Component.LinearSystem +import Sofa.Component.LinearSolver.Iterative from scipy import sparse def createBeam(root, matrix_type): diff --git a/examples/additional-examples/pygame_example.py b/examples/additional-examples/pygame_example.py index b7f876f1f..63e9ecc5e 100644 --- a/examples/additional-examples/pygame_example.py +++ b/examples/additional-examples/pygame_example.py @@ -1,5 +1,5 @@ import Sofa -import Sofa.SofaGL +import Sofa.GL import SofaRuntime import Sofa.Simulation as sim import os @@ -19,7 +19,7 @@ def init_display(node): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glEnable(GL_LIGHTING) glEnable(GL_DEPTH_TEST) - Sofa.SofaGL.glewInit() + Sofa.GL.glewInit() Sofa.Simulation.initVisual(node) Sofa.Simulation.initTextures(node) glMatrixMode(GL_PROJECTION) @@ -44,7 +44,7 @@ def simple_render(rootNode): cameraMVM = rootNode.camera.getOpenGLModelViewMatrix() glMultMatrixd(cameraMVM) - Sofa.SofaGL.draw(rootNode) + Sofa.GL.draw(rootNode) pygame.display.get_surface().fill((0,0,0)) pygame.display.flip() diff --git a/examples/additional-examples/pyqt_example.py b/examples/additional-examples/pyqt_example.py index bde909363..6cbf4143c 100644 --- a/examples/additional-examples/pyqt_example.py +++ b/examples/additional-examples/pyqt_example.py @@ -1,7 +1,7 @@ from qtpy.QtCore import * from qtpy.QtWidgets import * from qtpy.QtOpenGL import * -import Sofa.SofaGL +import Sofa.GL import Sofa import SofaRuntime import Sofa.Simulation as sim @@ -55,7 +55,7 @@ def initializeGL(self): glEnable(GL_LIGHTING) glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) - Sofa.SofaGL.glewInit() + Sofa.GL.glewInit() Sofa.Simulation.initVisual(self.visuals_node) Sofa.Simulation.initTextures(self.visuals_node) glMatrixMode(GL_PROJECTION) @@ -76,7 +76,7 @@ def paintGL(self): cameraMVM = self.visuals_node.camera.getOpenGLModelViewMatrix() glMultMatrixd(cameraMVM) - Sofa.SofaGL.draw(self.visuals_node) + Sofa.GL.draw(self.visuals_node) def get_depth_image(self): _, _, width, height = glGetIntegerv(GL_VIEWPORT) diff --git a/examples/source-terms/example-quadrature-rules.py b/examples/source-terms/example-quadrature-rules.py index 05259f5d9..3f7220ae3 100644 --- a/examples/source-terms/example-quadrature-rules.py +++ b/examples/source-terms/example-quadrature-rules.py @@ -1,6 +1,6 @@ """Solves a linear elastic problem with a prescribed load on the RHS. The load is assembled from a manufactured body-force density. The assembly is done by -integrating the density using quadrature information provided by the SofaFEM +integrating the density using quadrature information provided by the Sofa.FEM quadrature bindings. The resulting displacement should match the manufactured solution: @@ -16,7 +16,7 @@ import numpy as np import Sofa import Sofa.Core -from Sofa import SofaFEM +from Sofa import FEM AMPLITUDE = 0.03 WAVENUMBER = 2 * np.pi @@ -42,8 +42,8 @@ def assemble_nodal_force(node_coordinates, node_indices, quadrature_degree, noda F_a = sum_q w_q * measure_q * N_a(q) * r(q), with r(q) = sum_a N_a(q) * density_a""" # First get the quadrature data and mapping information for the corresponding topological element - weights, shape_functions, reference_gradients = SofaFEM.quadrature_data("Triangle", 2, quadrature_degree) - _, measures = SofaFEM.element_mapping_batch("Triangle", node_coordinates, node_indices, reference_gradients) + weights, shape_functions, reference_gradients = FEM.quadrature_data("Triangle", 2, quadrature_degree) + _, measures = FEM.element_mapping_batch("Triangle", node_coordinates, node_indices, reference_gradients) element_density = nodal_density[node_indices] # density at each element's local nodes, (E, nbNodes, dof) nb_nodes_per_element = node_indices.shape[1] diff --git a/examples/springForceField.py b/examples/springForceField.py index aa8ad9a22..a0cad0337 100644 --- a/examples/springForceField.py +++ b/examples/springForceField.py @@ -1,6 +1,6 @@ import Sofa import SofaRuntime -from Sofa import SofaDeformable +import Sofa.Component.SolidMechanics.Spring def createScene(root): diff --git a/examples/stvenant_kirchhoff.py b/examples/stvenant_kirchhoff.py index 68d78fdaa..92a84bf44 100644 --- a/examples/stvenant_kirchhoff.py +++ b/examples/stvenant_kirchhoff.py @@ -1,5 +1,5 @@ import Sofa -import Sofa.SofaDeformable +import Sofa.Component.SolidMechanics.FEM.Elastic from Sofa.Units.Definitions import s, m, cm, N, g, kg, MPa from Sofa.Units.UnitSystem import MechanicalUnitSystem @@ -44,7 +44,7 @@ def createScene(root_node): young_modulus = scene_unit(0.5, MPa) poisson_ratio = 0.45 - lame_parameters = Sofa.SofaDeformable.toLameParameters3D(young_modulus, poisson_ratio) + lame_parameters = Sofa.Component.SolidMechanics.FEM.Elastic.toLameParameters3D(young_modulus, poisson_ratio) tetra.addObject('TetrahedronHyperelasticityFEMForceField', name="FEM", topology="@Tetra_topo", ParameterSet=lame_parameters, materialName="StVenantKirchhoff") diff --git a/scripts/generate_stubs.py b/scripts/generate_stubs.py index f221ea72f..9ae946f0d 100644 --- a/scripts/generate_stubs.py +++ b/scripts/generate_stubs.py @@ -17,7 +17,7 @@ def main(site_package_dir,modules_name,use_pybind11 = False): #Generate stubs for components using the factory target_name="Sofa.Component" - generate_component_stubs(work_dir,target_name) + generate_component_stubs(work_dir, target_name, use_pybind11) diff --git a/scripts/sofaStubgen.py b/scripts/sofaStubgen.py index bc184dd54..03c05bf54 100644 --- a/scripts/sofaStubgen.py +++ b/scripts/sofaStubgen.py @@ -7,6 +7,7 @@ """ import re import sys, os +import keyword import pprint import argparse @@ -39,9 +40,9 @@ def sofa_to_python_typename(name, short=False): "LinkPath" : "LinkPath" } - SofaArray = "TypeHints.SofaArray" + SofaArray = "SofaArray" if short: - SofaArray = "TypeHints.SofaArray" + SofaArray = "SofaArray" if name in t: return t[name] @@ -75,31 +76,40 @@ def sofa_datafields_to_constructor_arguments_list(data_fields, object_name, has_ # 'type': 'bool'}, required_data_fields = [] optional_data_fields = [] + argument_names = {"self", "template"} for data_field in data_fields: name = data_field["name"] - if name in reserved: + if name in reserved or keyword.iskeyword(name): print(f"Warning: {object_name} contains a the data field named '{name}' which is also a python keyword") continue - if " " in name: + if len(name) == 0: + print("Warning: empty data field empty name") + continue + + if not name.isidentifier(): print(f"Warning: this is an invalid arguments name: '{name}'") continue - if len(name) == 0: - print("Warning: empty data field empty name") + if name in argument_names: + print(f"Warning: {object_name} contains several data fields named '{name}'") continue + argument_names.add(name) if data_field["isRequired"]: required_data_fields.append(data_field) else: optional_data_fields.append(data_field) - result_params = "" + # The arguments are keyword-only (as SOFA objects are created with keyword arguments): this allows the arguments + # without default value to follow the optional template argument. + params = [] if has_template: - result_params = "template: Optional[str] = None, " - result_params += ",".join([data["name"]+": "+sofa_to_python_typename(data["type"]) for data in required_data_fields]) - result_params += ",".join([data["name"]+": Optional["+sofa_to_python_typename(data["type"])+"] = None" for data in optional_data_fields]) + params.append("template: Optional[str] = None") + params += [data["name"]+": "+sofa_to_python_typename(data["type"]) for data in required_data_fields] + params += [data["name"]+": Optional["+sofa_to_python_typename(data["type"])+"] = None" for data in optional_data_fields] + result_params = ", ".join(["*"] + params) if params else "" ordered_fields = sorted(data_fields, key=lambda x: x["name"]) @@ -125,10 +135,15 @@ def sofa_datafields_to_doc(data_fields): return p def clean_sofa_text(t): + t = t.replace("\\", "\\\\") t = t.replace("\n","") t = t.replace("'", "") return t +def escape_docstring(t): + """Makes a text usable in a triple-quoted string""" + return t.replace("\\", "\\\\").replace('"', '\\"') + def sofa_datafields_to_typehints(data_fields, mode="Sofa"): p = "" p2 = "" @@ -139,11 +154,11 @@ def sofa_datafields_to_typehints(data_fields, mode="Sofa"): if len(name) == 0: continue - if " " in name: + if not name.isidentifier(): continue - if name in reserved: - p += " " + name + ": " + help + " (NB: use the kwargs syntax as name is a reserved word in python)\n\n" + if name in reserved or keyword.iskeyword(name): + p += " # " + name + ": " + help + " (NB: use the kwargs syntax as name is a reserved word in python)\n\n" else: p += f" {name}: Data[{type}] \n '{help}'\n\n" p2 += f" {name}: Optional[{type} | LinkPath] = None \n '{help}'\n\n" @@ -192,6 +207,8 @@ def wrapper_code(class_name, description, data_list, properties_doc, constructor_params_typehints, constructor_params_docs): properties_doc = "" + description = escape_docstring(description) + constructor_params_docs = escape_docstring(constructor_params_docs) return f""" class {class_name}(Object): \"\"\"{description}\"\"\" @@ -300,8 +317,56 @@ def load_component_list(target_name): return selected_entries -def create_sofa_stubs(code_model, target_path): +def find_bound_modules(target_name): + """Returns the compiled python binding modules found in the package target_name. + + The bindings of a SOFA module (eg. Sofa.Component.SolidMechanics.Spring) are compiled into an extension + module with the same name (eg. Sofa/Component/SolidMechanics/Spring.). + + Returns a dict {module name: set of the names it defines}. + """ + import importlib + import importlib.machinery + + root_package, _, sub_package = target_name.partition(".") + package = importlib.import_module(root_package) + + bound_modules = {} + for package_dir in package.__path__: + search_dir = os.path.join(package_dir, *sub_package.split(".")) if sub_package else package_dir + for dirpath, _, filenames in os.walk(search_dir): + for filename in filenames: + suffix = next((s for s in importlib.machinery.EXTENSION_SUFFIXES if filename.endswith(s)), None) + if suffix is None: + continue + relative_path = os.path.relpath(os.path.join(dirpath, filename[:-len(suffix)]), package_dir) + module_name = ".".join([root_package] + relative_path.split(os.sep)) + try: + bound_modules[module_name] = set(dir(importlib.import_module(module_name))) + except ImportError as e: + print(f"Warning: cannot import the binding module '{module_name}': {e}") + bound_modules[module_name] = set() + return bound_modules + +def bound_module_stub_header(module_name): + return f""" +# Type hints for the components of {module_name} that have no dedicated python binding +from Sofa.Core import Object, LinkPath +from Sofa.Component.TypeHints import Data, Optional, SofaArray +""" + +def create_sofa_stubs(code_model, target_path, bound_modules=None): + """Writes in target_path a python stub for each component of the code model. + + Components of a SOFA module with no python binding get a stub module per component in a package named after + the SOFA module (eg. Sofa/Component/Mass/UniformMass.py). + When the SOFA module has a compiled python binding (see find_bound_modules), such a package would shadow it. + The stubs of its components without binding are then gathered in a .pyi file next to the binding + (eg. Sofa/Component/SolidMechanics/Spring.pyi), to be merged with the stubs of the binding itself. + """ blacklist = ["RequiredPlugin"] + bound_modules = bound_modules or {} + bound_module_stubs = {} template_nodes = dict() not_created_objects = list() @@ -343,6 +408,13 @@ def create_sofa_stubs(code_model, target_path): class_typehint, params_typehint, arguments_list, constructor_params_doc) + if target in bound_modules: + if class_name in bound_modules[target]: + print(f"Skipping {object_name}: already bound in {target}") + else: + bound_module_stubs.setdefault(target, []).append(code) + continue + pathname = target_path + target.replace(".","/") + "/" full_component_name = target + "." + class_name @@ -358,7 +430,15 @@ def create_sofa_stubs(code_model, target_path): if full_component_name in code_model: raise Exception("Already existing entry") - # In every directory, scan the object that are in and generates an init.py file + for module_name, codes in bound_module_stubs.items(): + pathname = target_path + module_name.replace(".", "/") + ".pyi" + os.makedirs(os.path.dirname(pathname), exist_ok=True) + with open(pathname, "wt") as outfile: + outfile.write(bound_module_stub_header(module_name)) + for code in codes: + outfile.write(code) + + # In every directory, scan the object that are in and generates an init.py file make_all_init_files(target_path) return code_model @@ -376,5 +456,5 @@ def create_sofa_stubs(code_model, target_path): print(f"Generating SOFA's components python interfaces for {target_name}") components = load_component_list(target_name) - create_sofa_stubs(components, output_directory) + create_sofa_stubs(components, output_directory, find_bound_modules(target_name)) diff --git a/scripts/utils.py b/scripts/utils.py index 223366d09..64d95d27b 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -1,7 +1,7 @@ import sys import os import shutil -from sofaStubgen import load_component_list, create_sofa_stubs +from sofaStubgen import load_component_list, create_sofa_stubs, find_bound_modules from mypy.stubgen import parse_options, generate_stubs import argparse @@ -78,6 +78,46 @@ def __call__(self,path, objectList): returnList.append(obj) return returnList +# pybind11-stubgen can write imports (e.g. 'import Sofa.Core') before 'from __future__ import annotations', +# which is a SyntaxError: move the __future__ imports right after the module docstring. +def fix_future_imports(stub_path): + import io + import tokenize + + with open(stub_path, encoding="utf-8") as f: + source = f.read() + lines = source.splitlines(keepends=True) + + # index of the first line after the module docstring (0 if there is none) + insert_at = 0 + try: + for token in tokenize.generate_tokens(io.StringIO(source).readline): + if token.type in (tokenize.ENCODING, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT): + continue + if token.type == tokenize.STRING: + insert_at = token.end[0] + break + except (tokenize.TokenError, SyntaxError): + return + + future_lines = [i for i, line in enumerate(lines) + if i >= insert_at and line.startswith("from __future__ import")] + if not future_lines: + return + + future = [line if line.endswith("\n") else line + "\n" for i, line in enumerate(lines) if i in future_lines] + others = [line for i, line in enumerate(lines) if i not in future_lines] + fixed = "".join(others[:insert_at] + future + others[insert_at:]) + if fixed != source: + with open(stub_path, "w", encoding="utf-8") as f: + f.write(fixed) + +def fix_stubs_in_directory(directory): + for root, _, files in os.walk(directory): + for file in files: + if file.endswith(".pyi"): + fix_future_imports(os.path.join(root, file)) + #Generate stubs using either pybind11-stubgen or mypy version of stubgen def generate_module_stubs(module_name, work_dir, usePybind11_stubgen = False): print(f"Generating stubgen for {module_name} in {work_dir}") @@ -92,22 +132,52 @@ def generate_module_stubs(module_name, work_dir, usePybind11_stubgen = False): options = parse_options(["-v","-p",module_name,"--include-docstrings","--no-analysis", "--ignore-errors"]) generate_stubs(options) - module_out_dir = os.path.join("out", module_name) - target_dir = os.path.join(work_dir, module_name) + fix_stubs_in_directory("out") + + module_path = os.path.join(*module_name.split(".")) + module_out_dir = os.path.join("out", module_path) + target_dir = os.path.join(work_dir, module_path) if os.path.isdir(module_out_dir): + # a package: out/Sofa/... shutil.copytree(module_out_dir, target_dir, dirs_exist_ok=True) print(f"Resync terminated for copying '{module_name}' to '{target_dir}'") + elif os.path.isfile(module_out_dir + ".pyi"): + # a single module: out/Sofa/Component/SolidMechanics/Spring.pyi + os.makedirs(os.path.dirname(target_dir), exist_ok=True) + shutil.copyfile(module_out_dir + ".pyi", target_dir + ".pyi") + print(f"Resync terminated for copying '{module_name}' to '{target_dir}.pyi'") shutil.rmtree("out", ignore_errors=True) #Generate stubs for components using the factory -def generate_component_stubs(work_dir,target_name): +def generate_component_stubs(work_dir,target_name, usePybind11_stubgen = False): print(f"Generating stubgen for all components in Sofa.Components using custom sofaStubgen.py") + # SOFA modules having python bindings (eg. Sofa.Component.SolidMechanics.Spring) are compiled modules: their + # stubs are a .pyi file next to them, made of the stubs of the bindings completed by the stubs of the + # components having no binding. + bound_modules = find_bound_modules(target_name) + for module_name in bound_modules: + stale_stub_package = os.path.join(work_dir, *module_name.split(".")) + if os.path.isdir(stale_stub_package): + print(f"Warning: the directory '{stale_stub_package}' shadows the python binding '{module_name}'. " + f"It has probably been generated by a previous version of this script and should be removed.") + generate_module_stubs(module_name, work_dir, usePybind11_stubgen) + components = load_component_list(target_name) - create_sofa_stubs(components, "out/") + create_sofa_stubs(components, "out/", bound_modules) + + for module_name in bound_modules: + module_stub = os.path.join(*module_name.split(".")) + ".pyi" + out_stub = os.path.join("out", module_stub) + target_stub = os.path.join(work_dir, module_stub) + if os.path.isfile(out_stub) and os.path.isfile(target_stub): + with open(target_stub, "a") as target_file, open(out_stub) as out_file: + target_file.write("\n" + out_file.read()) + os.remove(out_stub) + print(f"Merged the stubs of the components without binding into '{target_stub}'") sofa_out_dir = os.path.join("out",*target_name.split('.'))