diff --git a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMapping.inl b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMapping.inl index 75e3f12cd89..981c0e22a39 100644 --- a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMapping.inl +++ b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMapping.inl @@ -57,6 +57,13 @@ void DistanceMapping::init() l_topology.set(this->getContext()->getMeshTopologyLink()); } + if (!l_topology) + { + msg_error() << "No topology found"; + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } + msg_info() << "Topology path used: '" << l_topology.getLinkedPath() << "'"; if (l_topology->getNbEdges() < 1) diff --git a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.h b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.h index b10cd4a93ab..fed60bcd234 100644 --- a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.h +++ b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.h @@ -43,7 +43,7 @@ namespace sofa::component::mapping::nonlinear * @author Matthieu Nesme */ template -class DistanceMultiMapping : public core::MultiMapping, public NonLinearMappingData +class DistanceMultiMapping : public core::MultiMapping, public StabilizedNonLinearMappingData { public: SOFA_CLASS(SOFA_TEMPLATE2(DistanceMultiMapping,TIn,TOut), SOFA_TEMPLATE2(core::MultiMapping,TIn,TOut)); diff --git a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.inl b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.inl index 4ad968aa54b..5986765486f 100644 --- a/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.inl +++ b/Sofa/Component/Mapping/NonLinear/src/sofa/component/mapping/nonlinear/DistanceMultiMapping.inl @@ -85,12 +85,19 @@ void DistanceMultiMapping::init() l_topology.set(this->getContext()->getMeshTopologyLink()); } + if (!l_topology) + { + msg_error() << "No topology found"; + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } + msg_info() << "Topology path used: '" << l_topology.getLinkedPath() << "'"; if (l_topology->getNbEdges() < 1) { msg_error() << "No Topology component containing edges found at path: " << l_topology.getLinkedPath() << ", nor in current context: " << this->getContext()->name; - sofa::core::objectmodel::BaseObject::d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } @@ -103,14 +110,20 @@ void DistanceMultiMapping::init() // compute the rest lengths if they are not known if(d_restLengths.getValue().size() != links.size() ) { - helper::WriteAccessor< Data > > restLengths(d_restLengths); - restLengths.resize( links.size() ); - if(!(d_computeDistance.getValue())) + helper::WriteAccessor restLengths(d_restLengths); + restLengths->clear(); + restLengths->reserve( links.size() ); + if(!d_computeDistance.getValue()) { - for(unsigned i=0; igetFromModels()[pair0[0]]->readPositions(); auto posPair1 = this->getFromModels()[pair1[0]]->readPositions(); @@ -118,7 +131,7 @@ void DistanceMultiMapping::init() const InCoord& pos0 = posPair0[pair0[1]]; const InCoord& pos1 = posPair1[pair1[1]]; - restLengths[i] = (pos0 - pos1).norm(); + restLengths->emplace_back((pos0 - pos1).norm()); } } else diff --git a/Sofa/Component/Mapping/NonLinear/tests/CMakeLists.txt b/Sofa/Component/Mapping/NonLinear/tests/CMakeLists.txt index a114e1de5c6..435528b719c 100644 --- a/Sofa/Component/Mapping/NonLinear/tests/CMakeLists.txt +++ b/Sofa/Component/Mapping/NonLinear/tests/CMakeLists.txt @@ -5,6 +5,7 @@ project(Sofa.Component.Mapping.NonLinear_test) set(SOURCE_FILES AreaMapping_test.cpp DistanceMapping_test.cpp + DistanceMultiMapping_test.cpp RigidMapping_test.cpp SquareDistanceMapping_test.cpp SquareMapping_test.cpp diff --git a/Sofa/Component/Mapping/NonLinear/tests/DistanceMultiMapping_test.cpp b/Sofa/Component/Mapping/NonLinear/tests/DistanceMultiMapping_test.cpp new file mode 100644 index 00000000000..873510f78db --- /dev/null +++ b/Sofa/Component/Mapping/NonLinear/tests/DistanceMultiMapping_test.cpp @@ -0,0 +1,96 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 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 . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include +#include +#include + +namespace sofa +{ +template +struct DistanceMultiMappingTest : public MultiMapping_test<_DistanceMultiMapping> +{ + using In = typename _DistanceMultiMapping::In; + using Out = typename _DistanceMultiMapping::Out; + + bool test(bool computeDistance) + { + constexpr int numberOfParents = 2; + this->setupScene(numberOfParents); // NP parents, 1 child + + _DistanceMultiMapping* map = static_cast<_DistanceMultiMapping*>( this->mapping ); + EXPECT_NE(map, nullptr); + + map->d_indexPairs.setValue({{0, 0}, {1, 0}}); + sofa::helper::getWriteAccessor(map->d_geometricStiffness)->setSelectedItem(1); + map->d_computeDistance.setValue(computeDistance); + + const component::topology::container::dynamic::EdgeSetTopologyContainer::SPtr edges = sofa::core::objectmodel::New(); + this->root->addObject(edges); + edges->addEdge( 0, 1 ); + + // parent positions + sofa::type::vector< VecCoord_t > incoords(numberOfParents); + for (auto& in : incoords) + { + in.resize(1); + } + + In::set( incoords[0][0], 1, 2, 3); + In::set( incoords[1][0], 4, 1, 5); + + VecCoord_t outcoords(1); + if (computeDistance) + { + const auto expectedDistance = (In::getCPos(incoords[1][0]) - In::getCPos(incoords[0][0])).norm(); + Out::set( outcoords[0], expectedDistance, 0.,0.); + } + else + { + Out::set( outcoords[0], 0,0,0); + } + return this->runTest(incoords,outcoords); + } +}; + +using ::testing::Types; +typedef Types< + sofa::component::mapping::nonlinear::DistanceMultiMapping, + sofa::component::mapping::nonlinear::DistanceMultiMapping +> DataTypes; + + +TYPED_TEST_SUITE(DistanceMultiMappingTest, DataTypes); + +TYPED_TEST( DistanceMultiMappingTest, computeDistance ) +{ + this->errorMax = 1000; + ASSERT_TRUE(this->test(true)); +} + +TYPED_TEST( DistanceMultiMappingTest, notComputeDistance ) +{ + this->errorMax = 1000; + ASSERT_TRUE(this->test(false)); +} + +} +