From 4ffec70621b6cbddaf459e0f055506eb4fae8946 Mon Sep 17 00:00:00 2001 From: epernod Date: Fri, 21 Oct 2022 01:32:29 +0200 Subject: [PATCH 01/13] [TopologicalMapping] move some implementation into cpp file --- .../sofa/core/topology/TopologicalMapping.cpp | 55 +++++++++++++++++ .../sofa/core/topology/TopologicalMapping.h | 59 ++++--------------- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp index 9307e312020..99420ac3c27 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp +++ b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp @@ -24,6 +24,61 @@ namespace sofa::core::topology { +TopologicalMapping::TopologicalMapping() + : fromModel(initLink("input", "Input topology to map")) + , toModel(initLink("output", "Output topology to map")) +{ + +} + + +void TopologicalMapping::setTopologies(In* from, Out* to) +{ + this->fromModel.set(from); + this->toModel.set(to); +} + + +Index TopologicalMapping::getGlobIndex(Index ind) +{ + if (ind < (Loc2GlobDataVec.getValue()).size()) + { + return (Loc2GlobDataVec.getValue())[ind]; + } + else + { + return 0; + } +} + +Index TopologicalMapping::getFromIndex(Index ind) +{ + SOFA_UNUSED(ind); + return 0; +} + + +void TopologicalMapping::dumpGlob2LocMap() +{ + std::map::iterator itM; + msg_info() << "## Log Glob2LocMap - size: " << Glob2LocMap.size() << " ##"; + for (itM = Glob2LocMap.begin(); itM != Glob2LocMap.end(); ++itM) + msg_info() << (*itM).first << " - " << (*itM).second; + + msg_info() << "#################"; +} + + +void TopologicalMapping::dumpLoc2GlobVec() +{ + const sofa::type::vector& buffer = Loc2GlobDataVec.getValue(); + msg_info() << "## Log Loc2GlobDataVec - size: " << buffer.size() << " ##"; + for (Index i = 0; i < buffer.size(); ++i) + msg_info() << i << " - " << buffer[i]; + + msg_info() << "#################"; +} + } /// namespace sofa::core::topology diff --git a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h index 42a18d941f4..69ee548f9a4 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h +++ b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h @@ -45,32 +45,26 @@ namespace topology * So, at each time step, the geometrical and adjacency information are consistent in both topologies. * */ -class TopologicalMapping : public virtual objectmodel::BaseObject +class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject { public: SOFA_ABSTRACT_CLASS(TopologicalMapping, objectmodel::BaseObject); /// Input Topology - typedef BaseMeshTopology In; + using In = BaseMeshTopology; /// Output Topology - typedef BaseMeshTopology Out; + using Out = BaseMeshTopology; using Index = sofa::Index; protected: - TopologicalMapping() - : fromModel(initLink("input", "Input topology to map")) - , toModel(initLink("output", "Output topology to map")) - {} + TopologicalMapping(); ~TopologicalMapping() override { } + public: /// Specify the input and output models. - virtual void setTopologies(In* from, Out* to) - { - this->fromModel.set( from ); - this->toModel.set( to ); - }; + virtual void setTopologies(In* from, Out* to); /// Set the path to the objects mapped in the scene graph void setPathInputObject(const std::string &o) {fromModel.setPath(o);} @@ -103,42 +97,13 @@ class TopologicalMapping : public virtual objectmodel::BaseObject Data >& getLoc2GlobVec() {return Loc2GlobDataVec;} - virtual Index getGlobIndex(Index ind) - { - if(ind< (Loc2GlobDataVec.getValue()).size()) - { - return (Loc2GlobDataVec.getValue())[ind]; - } - else - { - return 0; - } - } - - virtual Index getFromIndex(Index /*ind*/) - { - return 0; - } + virtual Index getGlobIndex(Index ind); - void dumpGlob2LocMap() - { - std::map::iterator itM; - msg_info() << "## Log Glob2LocMap - size: " << Glob2LocMap.size() << " ##"; - for (itM = Glob2LocMap.begin(); itM != Glob2LocMap.end(); ++itM) - msg_info() << (*itM).first << " - " << (*itM).second; + virtual Index getFromIndex(Index ind); - msg_info() << "#################"; - } + void dumpGlob2LocMap(); - void dumpLoc2GlobVec() - { - const sofa::type::vector& buffer = Loc2GlobDataVec.getValue(); - msg_info() << "## Log Loc2GlobDataVec - size: " << buffer.size() << " ##"; - for (Index i=0; i fromModel; - //In* fromModel; + /// Output target BaseTopology SingleLink toModel; - //Out* toModel; + // Two index maps : From 4ffb541da865de61f44c9a845152ea410f91cf44 Mon Sep 17 00:00:00 2001 From: epernod Date: Tue, 25 Oct 2022 19:48:08 +0200 Subject: [PATCH 02/13] [Geometry] Add method to convert elementType into const char* for error messages --- .../Geometry/src/sofa/geometry/ElementType.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h b/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h index 9fb7b9549c9..8bbd91d00de 100644 --- a/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h +++ b/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h @@ -43,4 +43,21 @@ enum class ElementType : sofa::Size constexpr sofa::Size NumberOfElementType = static_cast(sofa::geometry::ElementType::SIZE); +constexpr const char* elementTypeToString(ElementType type) +{ + switch (type) + { + case ElementType::POINT: { return "Point"; } + case ElementType::EDGE: { return "Edge"; } + case ElementType::TRIANGLE: { return "Triangle"; } + case ElementType::QUAD: { return "Quad"; } + case ElementType::TETRAHEDRON: { return "Tetrahedron"; } + case ElementType::HEXAHEDRON: { return "Hexahedron"; } + case ElementType::PENTAHEDRON: { return "Pentahedron"; } + case ElementType::PYRAMID: { return "Pyramid"; } + default: + return "Unknown"; + } +} + } // namespace sofa::geometry From 6ec5480e6cea319031b6ca279c799222053d2ceb Mon Sep 17 00:00:00 2001 From: epernod Date: Tue, 25 Oct 2022 19:48:47 +0200 Subject: [PATCH 03/13] Add method in TopologicalMapping to check the type of element --- .../sofa/core/topology/TopologicalMapping.cpp | 30 +++++++++++++++++++ .../sofa/core/topology/TopologicalMapping.h | 8 +++++ 2 files changed, 38 insertions(+) diff --git a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp index 99420ac3c27..0fbed96deb7 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp +++ b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.cpp @@ -80,5 +80,35 @@ void TopologicalMapping::dumpLoc2GlobVec() } +bool TopologicalMapping::checkTopologyInputTypes() +{ + if (m_inputType == TopologyElementType::UNKNOWN) + { + dmsg_error() << "The input TopologyElementType has not be set. Define 'm_inputType' to the correct TopologyElementType in the constructor."; + return false; + } + + if (m_outputType == TopologyElementType::UNKNOWN) + { + dmsg_error() << "The output TopologyElementType has not be set. Define 'm_outputType' to the correct TopologyElementType in the constructor."; + return false; + } + + + if (fromModel.get()->getTopologyType() != m_inputType) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a valid '" << elementTypeToString(m_inputType) << "' topology."; + return false; + } + + if (toModel.get()->getTopologyType() != m_outputType) + { + msg_error() << "The type of the output topology '" << toModel.getPath() << "' does not correspond to a valid '" << elementTypeToString(m_outputType) << "' topology."; + return false; + } + + return true; +} + } /// namespace sofa::core::topology diff --git a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h index 69ee548f9a4..45103161369 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h +++ b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h @@ -55,6 +55,8 @@ class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject /// Output Topology using Out = BaseMeshTopology; + using TopologyElementType = sofa::core::topology::TopologyElementType; + using Index = sofa::Index; protected: @@ -197,6 +199,9 @@ class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject return obj; } +protected: + [[nodiscard]] bool checkTopologyInputTypes(); + protected: /// Input source BaseTopology SingleLink fromModel; @@ -216,6 +221,9 @@ class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject std::map Glob2LocMap; //TODO put it in Data => Data allow map std::map > In2OutMap; + + TopologyElementType m_inputType = TopologyElementType::UNKNOWN; + TopologyElementType m_outputType = TopologyElementType::UNKNOWN; }; } // namespace topology From 23947813d7d03f85a3dc51d8bd37642429c72958 Mon Sep 17 00:00:00 2001 From: epernod Date: Wed, 26 Oct 2022 10:32:52 +0200 Subject: [PATCH 04/13] [Topology] Some more cleaning in TopologicalMapping --- .../src/sofa/core/topology/TopologicalMapping.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h index 45103161369..4a2fe8b2dd3 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h +++ b/Sofa/framework/Core/src/sofa/core/topology/TopologicalMapping.h @@ -95,9 +95,6 @@ class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject /// Accessor to index maps : const std::map& getGlob2LocMap() { return Glob2LocMap;} - //const sofa::type::vector& getLoc2GlobVec(){ return Loc2GlobVec.getValue();} - - Data >& getLoc2GlobVec() {return Loc2GlobDataVec;} virtual Index getGlobIndex(Index ind); @@ -202,23 +199,21 @@ class SOFA_CORE_API TopologicalMapping : public virtual objectmodel::BaseObject protected: [[nodiscard]] bool checkTopologyInputTypes(); -protected: +public: /// Input source BaseTopology - SingleLink fromModel; + SingleLink fromModel; /// Output target BaseTopology - SingleLink toModel; - - - // Two index maps : + SingleLink toModel; // Array which gives for each index (local index) of an element in the OUTPUT topology // the corresponding index (global index) of the same element in the INPUT topology : Data > Loc2GlobDataVec; +protected: // Map which gives for each index (global index) of an element in the INPUT topology // the corresponding index (local index) of the same element in the OUTPUT topology : - std::map Glob2LocMap; //TODO put it in Data => Data allow map + std::map Glob2LocMap; std::map > In2OutMap; From fed60b905900a5af9b78f60ffe569e90bbfb8781 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Tue, 27 Sep 2022 08:08:47 +0200 Subject: [PATCH 05/13] [Mapping] Add checks at init in TopologicalMapping --- ...SimpleTesselatedHexaTopologicalMapping.cpp | 578 ++++++++++-------- ...impleTesselatedTetraTopologicalMapping.cpp | 165 +++-- .../mapping/Edge2QuadTopologicalMapping.cpp | 47 ++ .../mapping/Hexa2QuadTopologicalMapping.cpp | 45 +- .../mapping/Hexa2TetraTopologicalMapping.cpp | 12 + .../Quad2TriangleTopologicalMapping.cpp | 47 +- .../Tetra2TriangleTopologicalMapping.cpp | 49 +- .../Triangle2EdgeTopologicalMapping.cpp | 25 +- 8 files changed, 585 insertions(+), 383 deletions(-) diff --git a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp index 7a663569be1..17290900681 100644 --- a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp +++ b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp @@ -53,280 +53,318 @@ SimpleTesselatedHexaTopologicalMapping::SimpleTesselatedHexaTopologicalMapping() void SimpleTesselatedHexaTopologicalMapping::init() { - if(fromModel) + bool modelsOk = true; + + // Check input topology + if (!fromModel) + { + // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no input mesh topology could be found. + msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; + modelsOk = false; + } + else + { + // Making sure the input topology corresponds to a hexahedral topology + if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; + modelsOk = false; + } + } + + // Check output topology + if (!toModel) + { + // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no output mesh topology could be found. + msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; + modelsOk = false; + } + else { - if(toModel) + // Making sure the output topology corresponds to a hexahedral topology + if (toModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) { - toModel->clear(); - - for (std::size_t i=0; igetNbPoints(); ++i) - { - // points mapped from points - pointMappedFromPoint.push_back(i); - toModel->addPoint(fromModel->getPX(i), fromModel->getPY(i), fromModel->getPZ(i)); - } - - size_t pointIndex = pointMappedFromPoint.size(); - Vector3 p; - - for (std::size_t i=0; igetNbHexahedra(); ++i) - { - core::topology::BaseMeshTopology::Hexa h = fromModel->getHexahedron(i); - - Vector3 p0(fromModel->getPX(h[0]), fromModel->getPY(h[0]), fromModel->getPZ(h[0])); - Vector3 p1(fromModel->getPX(h[1]), fromModel->getPY(h[1]), fromModel->getPZ(h[1])); - Vector3 p2(fromModel->getPX(h[2]), fromModel->getPY(h[2]), fromModel->getPZ(h[2])); - Vector3 p3(fromModel->getPX(h[3]), fromModel->getPY(h[3]), fromModel->getPZ(h[3])); - Vector3 p4(fromModel->getPX(h[4]), fromModel->getPY(h[4]), fromModel->getPZ(h[4])); - Vector3 p5(fromModel->getPX(h[5]), fromModel->getPY(h[5]), fromModel->getPZ(h[5])); - Vector3 p6(fromModel->getPX(h[6]), fromModel->getPY(h[6]), fromModel->getPZ(h[6])); - Vector3 p7(fromModel->getPX(h[7]), fromModel->getPY(h[7]), fromModel->getPZ(h[7])); - - // points mapped from edges - std::pair, int>::iterator, bool> insert_result; - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[1]),pointIndex)); - if(insert_result.second) - { - p = (p0+p1)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[1],h[(2)]),pointIndex)); - if(insert_result.second) - { - p = (p1+p2)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[3],h[2]),pointIndex)); - if(insert_result.second) - { - p = (p3+p2)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[3]),pointIndex)); - if(insert_result.second) - { - p = (p0+p3)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[4]),pointIndex)); - if(insert_result.second) - { - p = (p0+p4)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[1],h[5]),pointIndex)); - if(insert_result.second) - { - p = (p1+p5)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[2],h[6]),pointIndex)); - if(insert_result.second) - { - p = (p2+p6)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[3],h[7]),pointIndex)); - if(insert_result.second) - { - p = (p3+p7)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[4],h[5]),pointIndex)); - if(insert_result.second) - { - p = (p4+p5)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[5],h[6]),pointIndex)); - if(insert_result.second) - { - p = (p5+p6)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[7],h[6]),pointIndex)); - if(insert_result.second) - { - p = (p7+p6)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[4],h[7]),pointIndex)); - if(insert_result.second) - { - p = (p4+p7)/2; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - // points mapped from facets - std::pair, int>::iterator, bool> insert_facets_result; - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[1], h[2], h[3]), pointIndex)); - if (insert_facets_result.second) - { - p = (p0+p1+p2+p3)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[1], h[5], h[4]), pointIndex)); - if (insert_facets_result.second) - { - p = (p0+p1+p5+p4)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[1], h[2], h[6], h[5]), pointIndex)); - if (insert_facets_result.second) - { - p = (p1+p2+p6+p5)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[3], h[2], h[6], h[7]), pointIndex)); - if (insert_facets_result.second) - { - p = (p3+p2+p6+p7)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[3], h[7], h[4]), pointIndex)); - if (insert_facets_result.second) - { - p = (p0+p4+p7+p3)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[4], h[5], h[6], h[7]), pointIndex)); - if (insert_facets_result.second) - { - p = (p4+p5+p6+p7)/4; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - // points mapped from hexahedra - pointMappedFromHexa.push_back((int)pointIndex); - p = (p0+p1+p2+p3+p4+p5+p6+p7)/8; - toModel->addPoint(p[0], p[1], p[2]); - pointIndex++; - } - - for (unsigned int i=0; igetNbHexahedra(); ++i) - { - core::topology::BaseMeshTopology::Hexa h = fromModel->getHexahedron(i); - - Vec3d p0(fromModel->getPX(h[0]), fromModel->getPY(h[0]), fromModel->getPZ(h[0])); - Vec3d p1(fromModel->getPX(h[1]), fromModel->getPY(h[1]), fromModel->getPZ(h[1])); - Vec3d p2(fromModel->getPX(h[2]), fromModel->getPY(h[2]), fromModel->getPZ(h[2])); - Vec3d p3(fromModel->getPX(h[3]), fromModel->getPY(h[3]), fromModel->getPZ(h[3])); - Vec3d p4(fromModel->getPX(h[4]), fromModel->getPY(h[4]), fromModel->getPZ(h[4])); - Vec3d p5(fromModel->getPX(h[5]), fromModel->getPY(h[5]), fromModel->getPZ(h[5])); - Vec3d p6(fromModel->getPX(h[6]), fromModel->getPY(h[6]), fromModel->getPZ(h[6])); - Vec3d p7(fromModel->getPX(h[7]), fromModel->getPY(h[7]), fromModel->getPZ(h[7])); - - toModel->addHexa(h[0], - pointMappedFromEdge[fixed_array(h[0],h[1])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], - pointMappedFromEdge[fixed_array(h[0],h[3])], - pointMappedFromEdge[fixed_array(h[0],h[4])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], - pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])]); - - toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[1])], - h[1], - pointMappedFromEdge[fixed_array(h[1],h[2])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], - pointMappedFromEdge[fixed_array(h[1],h[5])], - pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], - pointMappedFromHexa[i]); - - toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], - pointMappedFromEdge[fixed_array(h[1],h[2])], - h[2], - pointMappedFromEdge[fixed_array(h[3],h[2])], - pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], - pointMappedFromEdge[fixed_array(h[2],h[6])], - pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])]); - - toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[3])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], - pointMappedFromEdge[fixed_array(h[3],h[2])], - h[3], - pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], - pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], - pointMappedFromEdge[fixed_array(h[3],h[7])]); - - toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[4])], - pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], - pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], - h[4], - pointMappedFromEdge[fixed_array(h[4],h[5])], - pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], - pointMappedFromEdge[fixed_array(h[4],h[7])]); - - toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], - pointMappedFromEdge[fixed_array(h[1],h[5])], - pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], - pointMappedFromHexa[i], - pointMappedFromEdge[fixed_array(h[4],h[5])], - h[5], - pointMappedFromEdge[fixed_array(h[5],h[6])], - pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])]); - - toModel->addHexa(pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], - pointMappedFromEdge[fixed_array(h[2],h[6])], - pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], - pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], - pointMappedFromEdge[fixed_array(h[5],h[6])], - h[6], - pointMappedFromEdge[fixed_array(h[7],h[6])]); - - toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], - pointMappedFromHexa[i], - pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], - pointMappedFromEdge[fixed_array(h[3],h[7])], - pointMappedFromEdge[fixed_array(h[4],h[7])], - pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], - pointMappedFromEdge[fixed_array(h[7],h[6])], - h[7]); - } - - // Need to fully init the target topology - toModel->init(); + msg_error() << "The type of the output topology '" << toModel.getPath() << "' does not correspond to a hexahedral topology."; + modelsOk = false; } } + + if (!modelsOk) + { + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } + + toModel->clear(); + + for (std::size_t i=0; igetNbPoints(); ++i) + { + // points mapped from points + pointMappedFromPoint.push_back(i); + toModel->addPoint(fromModel->getPX(i), fromModel->getPY(i), fromModel->getPZ(i)); + } + + size_t pointIndex = pointMappedFromPoint.size(); + Vector3 p; + + for (std::size_t i=0; igetNbHexahedra(); ++i) + { + core::topology::BaseMeshTopology::Hexa h = fromModel->getHexahedron(i); + + Vector3 p0(fromModel->getPX(h[0]), fromModel->getPY(h[0]), fromModel->getPZ(h[0])); + Vector3 p1(fromModel->getPX(h[1]), fromModel->getPY(h[1]), fromModel->getPZ(h[1])); + Vector3 p2(fromModel->getPX(h[2]), fromModel->getPY(h[2]), fromModel->getPZ(h[2])); + Vector3 p3(fromModel->getPX(h[3]), fromModel->getPY(h[3]), fromModel->getPZ(h[3])); + Vector3 p4(fromModel->getPX(h[4]), fromModel->getPY(h[4]), fromModel->getPZ(h[4])); + Vector3 p5(fromModel->getPX(h[5]), fromModel->getPY(h[5]), fromModel->getPZ(h[5])); + Vector3 p6(fromModel->getPX(h[6]), fromModel->getPY(h[6]), fromModel->getPZ(h[6])); + Vector3 p7(fromModel->getPX(h[7]), fromModel->getPY(h[7]), fromModel->getPZ(h[7])); + + // points mapped from edges + std::pair, int>::iterator, bool> insert_result; + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[1]),pointIndex)); + if(insert_result.second) + { + p = (p0+p1)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[1],h[(2)]),pointIndex)); + if(insert_result.second) + { + p = (p1+p2)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[3],h[2]),pointIndex)); + if(insert_result.second) + { + p = (p3+p2)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[3]),pointIndex)); + if(insert_result.second) + { + p = (p0+p3)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[0],h[4]),pointIndex)); + if(insert_result.second) + { + p = (p0+p4)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[1],h[5]),pointIndex)); + if(insert_result.second) + { + p = (p1+p5)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[2],h[6]),pointIndex)); + if(insert_result.second) + { + p = (p2+p6)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[3],h[7]),pointIndex)); + if(insert_result.second) + { + p = (p3+p7)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[4],h[5]),pointIndex)); + if(insert_result.second) + { + p = (p4+p5)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[5],h[6]),pointIndex)); + if(insert_result.second) + { + p = (p5+p6)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[7],h[6]),pointIndex)); + if(insert_result.second) + { + p = (p7+p6)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_result = pointMappedFromEdge.insert(std::make_pair(fixed_array(h[4],h[7]),pointIndex)); + if(insert_result.second) + { + p = (p4+p7)/2; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + // points mapped from facets + std::pair, int>::iterator, bool> insert_facets_result; + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[1], h[2], h[3]), pointIndex)); + if (insert_facets_result.second) + { + p = (p0+p1+p2+p3)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[1], h[5], h[4]), pointIndex)); + if (insert_facets_result.second) + { + p = (p0+p1+p5+p4)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[1], h[2], h[6], h[5]), pointIndex)); + if (insert_facets_result.second) + { + p = (p1+p2+p6+p5)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[3], h[2], h[6], h[7]), pointIndex)); + if (insert_facets_result.second) + { + p = (p3+p2+p6+p7)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[0], h[3], h[7], h[4]), pointIndex)); + if (insert_facets_result.second) + { + p = (p0+p4+p7+p3)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + insert_facets_result = pointMappedFromFacet.insert(std::make_pair(fixed_array(h[4], h[5], h[6], h[7]), pointIndex)); + if (insert_facets_result.second) + { + p = (p4+p5+p6+p7)/4; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + // points mapped from hexahedra + pointMappedFromHexa.push_back((int)pointIndex); + p = (p0+p1+p2+p3+p4+p5+p6+p7)/8; + toModel->addPoint(p[0], p[1], p[2]); + pointIndex++; + } + + for (unsigned int i=0; igetNbHexahedra(); ++i) + { + core::topology::BaseMeshTopology::Hexa h = fromModel->getHexahedron(i); + + Vec3d p0(fromModel->getPX(h[0]), fromModel->getPY(h[0]), fromModel->getPZ(h[0])); + Vec3d p1(fromModel->getPX(h[1]), fromModel->getPY(h[1]), fromModel->getPZ(h[1])); + Vec3d p2(fromModel->getPX(h[2]), fromModel->getPY(h[2]), fromModel->getPZ(h[2])); + Vec3d p3(fromModel->getPX(h[3]), fromModel->getPY(h[3]), fromModel->getPZ(h[3])); + Vec3d p4(fromModel->getPX(h[4]), fromModel->getPY(h[4]), fromModel->getPZ(h[4])); + Vec3d p5(fromModel->getPX(h[5]), fromModel->getPY(h[5]), fromModel->getPZ(h[5])); + Vec3d p6(fromModel->getPX(h[6]), fromModel->getPY(h[6]), fromModel->getPZ(h[6])); + Vec3d p7(fromModel->getPX(h[7]), fromModel->getPY(h[7]), fromModel->getPZ(h[7])); + + toModel->addHexa(h[0], + pointMappedFromEdge[fixed_array(h[0],h[1])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], + pointMappedFromEdge[fixed_array(h[0],h[3])], + pointMappedFromEdge[fixed_array(h[0],h[4])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], + pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])]); + + toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[1])], + h[1], + pointMappedFromEdge[fixed_array(h[1],h[2])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], + pointMappedFromEdge[fixed_array(h[1],h[5])], + pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], + pointMappedFromHexa[i]); + + toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], + pointMappedFromEdge[fixed_array(h[1],h[2])], + h[2], + pointMappedFromEdge[fixed_array(h[3],h[2])], + pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], + pointMappedFromEdge[fixed_array(h[2],h[6])], + pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])]); + + toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[3])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[2],h[3])], + pointMappedFromEdge[fixed_array(h[3],h[2])], + h[3], + pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], + pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], + pointMappedFromEdge[fixed_array(h[3],h[7])]); + + toModel->addHexa(pointMappedFromEdge[fixed_array(h[0],h[4])], + pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], + pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], + h[4], + pointMappedFromEdge[fixed_array(h[4],h[5])], + pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], + pointMappedFromEdge[fixed_array(h[4],h[7])]); + + toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[1],h[5],h[4])], + pointMappedFromEdge[fixed_array(h[1],h[5])], + pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], + pointMappedFromHexa[i], + pointMappedFromEdge[fixed_array(h[4],h[5])], + h[5], + pointMappedFromEdge[fixed_array(h[5],h[6])], + pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])]); + + toModel->addHexa(pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[1],h[2],h[6],h[5])], + pointMappedFromEdge[fixed_array(h[2],h[6])], + pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], + pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], + pointMappedFromEdge[fixed_array(h[5],h[6])], + h[6], + pointMappedFromEdge[fixed_array(h[7],h[6])]); + + toModel->addHexa(pointMappedFromFacet[fixed_array(h[0],h[3],h[7],h[4])], + pointMappedFromHexa[i], + pointMappedFromFacet[fixed_array(h[3],h[2],h[6],h[7])], + pointMappedFromEdge[fixed_array(h[3],h[7])], + pointMappedFromEdge[fixed_array(h[4],h[7])], + pointMappedFromFacet[fixed_array(h[4],h[5],h[6],h[7])], + pointMappedFromEdge[fixed_array(h[7],h[6])], + h[7]); + } + + // Need to fully init the target topology + toModel->init(); } } //namespace sofa::component::mapping::linear diff --git a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp index 4b44fca6acd..9e1264aa084 100644 --- a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp +++ b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp @@ -59,97 +59,136 @@ SimpleTesselatedTetraTopologicalMapping::SimpleTesselatedTetraTopologicalMapping void SimpleTesselatedTetraTopologicalMapping::init() { - if(fromModel) + bool modelsOk = true; + + // Check input topology + if (!fromModel) + { + // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no input mesh topology could be found. + msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; + modelsOk = false; + } + else { - TetrahedronSetTopologyContainer *from_tstc; - fromModel->getContext()->get(from_tstc); - if(toModel) + // Making sure the input topology corresponds to a tetrahedral topology + if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a tetrahedral topology."; + modelsOk = false; + } + } - helper::WriteAccessor< Data< sofa::type::vector > > pointSourceData = d_pointSource; - helper::WriteAccessor< Data< sofa::type::vector > > pointMappedFromPointData = d_pointMappedFromPoint; - helper::WriteAccessor< Data< sofa::type::vector > > pointMappedFromEdgeData = d_pointMappedFromEdge; + // Check output topology + if (!toModel) + { + // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no output mesh topology could be found. + msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; + modelsOk = false; + } + else + { + // Making sure the output topology corresponds to a tetrahedral topology + if (toModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) + { + msg_error() << "The type of the output topology '" << toModel.getPath() << "' does not correspond to a tetrahedral topology."; + modelsOk = false; + } + } - sofa::type::vector >& tetrahedraMappedFromTetraData = *(tetrahedraMappedFromTetra.beginEdit()); - type::vector& tetraSourceData = *(tetraSource.beginEdit()); + if (!modelsOk) + { + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } - TetrahedronSetTopologyContainer *to_tstc; - toModel->getContext()->get(to_tstc); - to_tstc->clear(); - if(!from_tstc->hasPos()) - { + + TetrahedronSetTopologyContainer *from_tstc; + fromModel->getContext()->get(from_tstc); + + helper::WriteAccessor< Data< sofa::type::vector > > pointSourceData = d_pointSource; + helper::WriteAccessor< Data< sofa::type::vector > > pointMappedFromPointData = d_pointMappedFromPoint; + helper::WriteAccessor< Data< sofa::type::vector > > pointMappedFromEdgeData = d_pointMappedFromEdge; + + sofa::type::vector >& tetrahedraMappedFromTetraData = *(tetrahedraMappedFromTetra.beginEdit()); + type::vector& tetraSourceData = *(tetraSource.beginEdit()); + + TetrahedronSetTopologyContainer *to_tstc; + toModel->getContext()->get(to_tstc); + to_tstc->clear(); + if(!from_tstc->hasPos()) + { // MeshLoader *mshLoader; // fromModel->getContext()->get(mshLoader); // from_tstc->loadFromMeshLoader(mshLoader); - } + } - pointSourceData.resize(from_tstc->getNbPoints()+from_tstc->getNbEdges()); + pointSourceData.resize(from_tstc->getNbPoints()+from_tstc->getNbEdges()); - for (std::size_t i=0; igetNbPoints(); i++) - { - to_tstc->addPoint(from_tstc->getPX(i), from_tstc->getPY(i), from_tstc->getPZ(i)); + for (std::size_t i=0; igetNbPoints(); i++) + { + to_tstc->addPoint(from_tstc->getPX(i), from_tstc->getPY(i), from_tstc->getPZ(i)); - pointMappedFromPointData.push_back(i); - pointSourceData[i] = i+1; - } + pointMappedFromPointData.push_back(i); + pointSourceData[i] = i+1; + } - Index newPointIndex = to_tstc->getNbPoints(); + Index newPointIndex = to_tstc->getNbPoints(); - for (unsigned int i=0; igetNbEdges(); i++) - { - Edge e = from_tstc->getEdge(i); + for (unsigned int i=0; igetNbEdges(); i++) + { + Edge e = from_tstc->getEdge(i); - to_tstc->addPoint( - (from_tstc->getPX(e[0]) + from_tstc->getPX(e[1]))/2, - (from_tstc->getPY(e[0]) + from_tstc->getPY(e[1]))/2, - (from_tstc->getPZ(e[0]) + from_tstc->getPZ(e[1]))/2 - ); + to_tstc->addPoint( + (from_tstc->getPX(e[0]) + from_tstc->getPX(e[1]))/2, + (from_tstc->getPY(e[0]) + from_tstc->getPY(e[1]))/2, + (from_tstc->getPZ(e[0]) + from_tstc->getPZ(e[1]))/2 + ); - pointMappedFromEdgeData.push_back(newPointIndex); - pointSourceData[newPointIndex] = -(i+1); - newPointIndex++; - } + pointMappedFromEdgeData.push_back(newPointIndex); + pointSourceData[newPointIndex] = -(i+1); + newPointIndex++; + } - fixed_array newTetrahedraIndices; - unsigned int newTetraIndex = (unsigned int)to_tstc->getNbTetrahedra(); + fixed_array newTetrahedraIndices; + unsigned int newTetraIndex = (unsigned int)to_tstc->getNbTetrahedra(); - tetraSourceData.resize(8*from_tstc->getNbTetrahedra()); + tetraSourceData.resize(8*from_tstc->getNbTetrahedra()); - for (unsigned int i=0; igetNbTetrahedra(); i++) - { - core::topology::BaseMeshTopology::Tetra t = from_tstc->getTetrahedron(i); - core::topology::BaseMeshTopology::EdgesInTetrahedron e = from_tstc->getEdgesInTetrahedron(i); - to_tstc->addTetra(t[0], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[2]]); - newTetrahedraIndices[0] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + for (unsigned int i=0; igetNbTetrahedra(); i++) + { + core::topology::BaseMeshTopology::Tetra t = from_tstc->getTetrahedron(i); + core::topology::BaseMeshTopology::EdgesInTetrahedron e = from_tstc->getEdgesInTetrahedron(i); + to_tstc->addTetra(t[0], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[2]]); + newTetrahedraIndices[0] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(t[1], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[3]]); - newTetrahedraIndices[1] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(t[1], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[3]]); + newTetrahedraIndices[1] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(t[2], pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[3]], pointMappedFromEdgeData[e[5]]); - newTetrahedraIndices[2] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(t[2], pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[3]], pointMappedFromEdgeData[e[5]]); + newTetrahedraIndices[2] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(t[3], pointMappedFromEdgeData[e[2]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[4]]); - newTetrahedraIndices[3] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(t[3], pointMappedFromEdgeData[e[2]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[4]]); + newTetrahedraIndices[3] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[3]], pointMappedFromEdgeData[e[5]]); - newTetrahedraIndices[4] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[3]], pointMappedFromEdgeData[e[5]]); + newTetrahedraIndices[4] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[2]]); - newTetrahedraIndices[5] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(pointMappedFromEdgeData[e[1]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[2]]); + newTetrahedraIndices[5] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[3]]); - newTetrahedraIndices[6] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[5]], pointMappedFromEdgeData[e[3]]); + newTetrahedraIndices[6] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - to_tstc->addTetra(pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[2]], pointMappedFromEdgeData[e[5]]); - newTetrahedraIndices[7] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; + to_tstc->addTetra(pointMappedFromEdgeData[e[4]], pointMappedFromEdgeData[e[0]], pointMappedFromEdgeData[e[2]], pointMappedFromEdgeData[e[5]]); + newTetrahedraIndices[7] = newTetraIndex; tetraSourceData[newTetraIndex] = i; newTetraIndex++; - tetrahedraMappedFromTetraData.push_back(newTetrahedraIndices); - } - toModel->init(); - tetrahedraMappedFromTetra.endEdit(); - } + tetrahedraMappedFromTetraData.push_back(newTetrahedraIndices); } + toModel->init(); + tetrahedraMappedFromTetra.endEdit(); } void SimpleTesselatedTetraTopologicalMapping::updateTopologicalMappingBottomUp() diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index 54d22e4624e..1a9bbb3522f 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -97,6 +97,53 @@ void Edge2QuadTopologicalMapping::init() } unsigned int N = d_nbPointsOnEachCircle.getValue(); + bool modelsOk = true; + + // Check input topology + if (!fromModel) + { + // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no input mesh topology could be found. + msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; + modelsOk = false; + } + else + { + // Making sure the input topology is derived from the edge topology container + if (!dynamic_cast(fromModel.get())) + { + msg_error() << "The input topology '" << fromModel.getPath() << "' is not a derived class of EdgeSetTopologyContainer. " + << "Consider setting the '" << fromModel.getName() << "' data attribute to a valid" + " EdgeSetTopologyContainer derived object."; + modelsOk = false; + } + } + + // Check output topology + if (!toModel) + { + // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. + // If it is null at this point, it means no output mesh topology could be found. + msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; + modelsOk = false; + } + else + { + // Making sure the output topology is derived from the quad topology container + if (!dynamic_cast(toModel.get())) + { + msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " + << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" + " QuadSetTopologyContainer derived object."; + modelsOk = false; + } + } + + if (!modelsOk) + { + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; + } // INITIALISATION of QUADULAR mesh from EDGE mesh : diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp index 45bb1d737d1..e4552c193e7 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp @@ -63,6 +63,7 @@ void Hexa2QuadTopologicalMapping::init() using namespace container::dynamic; bool modelsOk = true; + // Check input topology if (!fromModel) { // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -70,7 +71,17 @@ void Hexa2QuadTopologicalMapping::init() msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; modelsOk = false; } + else + { + // Making sure the input topology corresponds to a tetrahedral topology + if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; + modelsOk = false; + } + } + // Check output topology if (!toModel) { // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -78,22 +89,27 @@ void Hexa2QuadTopologicalMapping::init() msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; modelsOk = false; } - - // Making sure the output topology is derived from the quad topology container - if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " QuadSetTopologyContainer derived object."; - modelsOk = false; - } else { - // Making sure a topology modifier exists at the same level as the output topology - QuadSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) { - msg_error() << "No QuadSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; + else + { + // Making sure the output topology is derived from the quad topology container + if (!dynamic_cast(toModel.get())) + { + msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " + << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" + " QuadSetTopologyContainer derived object."; modelsOk = false; } + else + { + // Making sure a topology modifier exists at the same level as the output topology + QuadSetTopologyModifier *to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No QuadSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; + modelsOk = false; + } + } } if (!modelsOk) @@ -102,6 +118,7 @@ void Hexa2QuadTopologicalMapping::init() return; } + // Clear output topology toModel->clear(); diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp index bfb08bd13ec..9dfe76593a2 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp @@ -71,12 +71,24 @@ void Hexa2TetraTopologicalMapping::init() // recheck models bool modelsOk = true; + + // Check input topology if (!fromModel) { msg_error() << "Pointer to input topology is invalid."; modelsOk = false; } + else + { + // Making sure the input topology corresponds to a tetrahedral topology + if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; + modelsOk = false; + } + } + // Check ouput topology if (!toModel) { msg_error() << "Pointer to output topology is invalid."; diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp index 4bbab4d41ee..062fb560b9b 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp @@ -73,6 +73,8 @@ void Quad2TriangleTopologicalMapping::init() using namespace container::dynamic; bool modelsOk = true; + + // Check input topology if (!fromModel) { // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -80,7 +82,19 @@ void Quad2TriangleTopologicalMapping::init() msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; modelsOk = false; } + else + { + // Making sure the input topology is derived from the quad topology container + if (!dynamic_cast(fromModel.get())) + { + msg_error() << "The input topology '" << fromModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " + << "Consider setting the '" << fromModel.getName() << "' data attribute to a valid" + " QuadSetTopologyContainer derived object."; + modelsOk = false; + } + } + // Check output topology if (!toModel) { // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -88,23 +102,28 @@ void Quad2TriangleTopologicalMapping::init() msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; modelsOk = false; } - - // Making sure the output topology is derived from the triangle topology container - if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " TriangleSetTopologyContainer derived object."; - modelsOk = false; - } else { - // Making sure a topology modifier exists at the same level as the output topology - TriangleSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) + else + { + // Making sure the output topology is derived from the triangle topology container + if (!dynamic_cast(toModel.get())) { - msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; + msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " + << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" + " TriangleSetTopologyContainer derived object."; modelsOk = false; } + else + { + // Making sure a topology modifier exists at the same level as the output topology + TriangleSetTopologyModifier *to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) + { + msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; + modelsOk = false; + } + } } if (!modelsOk) diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp index bd7af151aa1..b3c833d6af9 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp @@ -65,6 +65,8 @@ Tetra2TriangleTopologicalMapping::Tetra2TriangleTopologicalMapping() void Tetra2TriangleTopologicalMapping::init() { bool modelsOk = true; + + // Check input topology if (!fromModel) { // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -72,7 +74,17 @@ void Tetra2TriangleTopologicalMapping::init() msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; modelsOk = false; } + else + { + // Making sure the input topology corresponds to a tetrahedral topology + if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a tetrahedral topology."; + modelsOk = false; + } + } + // Check output topology if (!toModel) { // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. @@ -80,23 +92,28 @@ void Tetra2TriangleTopologicalMapping::init() msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; modelsOk = false; } - - // Making sure the output topology is derived from the triangle topology container - if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " TriangleSetTopologyContainer derived object."; - modelsOk = false; - } else { - // Making sure a topology modifier exists at the same level as the output topology - container::dynamic::TriangleSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) { - msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; + else + { + // Making sure the output topology is derived from the triangle topology container + if (!dynamic_cast(toModel.get())) + { + msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " + << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" + " TriangleSetTopologyContainer derived object."; modelsOk = false; - } else { - m_outTopoModifier = to_tstm; + } + else + { + // Making sure a topology modifier exists at the same level as the output topology + container::dynamic::TriangleSetTopologyModifier *to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; + modelsOk = false; + } else { + m_outTopoModifier = to_tstm; + } } } diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp index 5d8257c0591..9e7e886e466 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp @@ -66,25 +66,38 @@ Triangle2EdgeTopologicalMapping::~Triangle2EdgeTopologicalMapping() void Triangle2EdgeTopologicalMapping::init() { - // recheck models bool modelsOk = true; + + // Check input topology if (!fromModel) { msg_error() << "Pointer to input topology is invalid."; modelsOk = false; } + else + { + // Making sure the input topology includes triangle elements + if (fromModel.get()->getNbTriangles() != 0) + { + msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a valid triangle topology."; + modelsOk = false; + } + } + // Check output topology if (!toModel) { msg_error() << "Pointer to output topology is invalid."; modelsOk = false; } - - toModel->getContext()->get(m_outTopoModifier); - if (!m_outTopoModifier) + else { - msg_error() << "No EdgeSetTopologyModifier found in the Edge topology Node."; - modelsOk = false; + toModel->getContext()->get(m_outTopoModifier); + if (!m_outTopoModifier) + { + msg_error() << "No EdgeSetTopologyModifier found in the Edge topology Node."; + modelsOk = false; + } } if (!modelsOk) From e3d8edd3aa1c6171950d6e79bddee12d213a498e Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Tue, 27 Sep 2022 08:09:07 +0200 Subject: [PATCH 06/13] remove useless file --- .../constraint/BilateralInteractionConstraint.scn.view | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 examples/Components/constraint/BilateralInteractionConstraint.scn.view diff --git a/examples/Components/constraint/BilateralInteractionConstraint.scn.view b/examples/Components/constraint/BilateralInteractionConstraint.scn.view deleted file mode 100644 index 33267fe946d..00000000000 --- a/examples/Components/constraint/BilateralInteractionConstraint.scn.view +++ /dev/null @@ -1,2 +0,0 @@ -0.0290281 1.52398 -35.4868 --0.0102872 -0.693185 -0.011295 -0.720598 From 104cebf7e052cb05b825acb7a71913927b5cb7f9 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Thu, 29 Sep 2022 14:17:11 +0200 Subject: [PATCH 07/13] Update error message to better guide the user --- .../topology/mapping/Edge2QuadTopologicalMapping.cpp | 10 ++++------ .../topology/mapping/Hexa2QuadTopologicalMapping.cpp | 5 ++--- .../mapping/Quad2TriangleTopologicalMapping.cpp | 10 ++++------ .../mapping/Tetra2TriangleTopologicalMapping.cpp | 5 ++--- 4 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index 1a9bbb3522f..c5afc6a8e9d 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -112,9 +112,8 @@ void Edge2QuadTopologicalMapping::init() // Making sure the input topology is derived from the edge topology container if (!dynamic_cast(fromModel.get())) { - msg_error() << "The input topology '" << fromModel.getPath() << "' is not a derived class of EdgeSetTopologyContainer. " - << "Consider setting the '" << fromModel.getName() << "' data attribute to a valid" - " EdgeSetTopologyContainer derived object."; + msg_error() << "The input topology '" << fromModel.getPath() << "' is not homogeneous with a EdgeSetTopologyContainer. The '" << fromModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } } @@ -132,9 +131,8 @@ void Edge2QuadTopologicalMapping::init() // Making sure the output topology is derived from the quad topology container if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " QuadSetTopologyContainer derived object."; + msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } } diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp index e4552c193e7..0e951164022 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp @@ -94,9 +94,8 @@ void Hexa2QuadTopologicalMapping::init() // Making sure the output topology is derived from the quad topology container if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " QuadSetTopologyContainer derived object."; + msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } else diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp index 062fb560b9b..81b696766a7 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp @@ -87,9 +87,8 @@ void Quad2TriangleTopologicalMapping::init() // Making sure the input topology is derived from the quad topology container if (!dynamic_cast(fromModel.get())) { - msg_error() << "The input topology '" << fromModel.getPath() << "' is not a derived class of QuadSetTopologyContainer. " - << "Consider setting the '" << fromModel.getName() << "' data attribute to a valid" - " QuadSetTopologyContainer derived object."; + msg_error() << "The input topology '" << fromModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << fromModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } } @@ -107,9 +106,8 @@ void Quad2TriangleTopologicalMapping::init() // Making sure the output topology is derived from the triangle topology container if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " TriangleSetTopologyContainer derived object."; + msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a TriangleSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } else diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp index b3c833d6af9..d3e268b1349 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp @@ -97,9 +97,8 @@ void Tetra2TriangleTopologicalMapping::init() // Making sure the output topology is derived from the triangle topology container if (!dynamic_cast(toModel.get())) { - msg_error() << "The output topology '" << toModel.getPath() << "' is not a derived class of TriangleSetTopologyContainer. " - << "Consider setting the '" << toModel.getName() << "' data attribute to a valid" - " TriangleSetTopologyContainer derived object."; + msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a TriangleSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); modelsOk = false; } else From 4f245b7ee54adb9c6b2f4a9f6c24362f7ebcb593 Mon Sep 17 00:00:00 2001 From: epernod Date: Wed, 26 Oct 2022 01:00:49 +0200 Subject: [PATCH 08/13] [topology.mapping] Update all topological mapping ot use method from TopologicalMapping.h to test input/output --- ...SimpleTesselatedHexaTopologicalMapping.cpp | 44 ++----------- ...impleTesselatedTetraTopologicalMapping.cpp | 54 +++------------ .../mapping/Edge2QuadTopologicalMapping.cpp | 47 +++----------- .../mapping/Hexa2QuadTopologicalMapping.cpp | 63 ++++-------------- .../mapping/Hexa2TetraTopologicalMapping.cpp | 50 ++++---------- .../Quad2TriangleTopologicalMapping.cpp | 64 ++++-------------- .../Tetra2TriangleTopologicalMapping.cpp | 65 ++++--------------- .../Triangle2EdgeTopologicalMapping.cpp | 39 +++-------- 8 files changed, 86 insertions(+), 340 deletions(-) diff --git a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp index 17290900681..6032a8cdd66 100644 --- a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp +++ b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedHexaTopologicalMapping.cpp @@ -48,50 +48,16 @@ int SimpleTesselatedHexaTopologicalMappingClass = core::RegisterObject ( "Specia // Implementation SimpleTesselatedHexaTopologicalMapping::SimpleTesselatedHexaTopologicalMapping() + : sofa::core::topology::TopologicalMapping() { + m_inputType = TopologyElementType::HEXAHEDRON; + m_outputType = TopologyElementType::HEXAHEDRON; } void SimpleTesselatedHexaTopologicalMapping::init() { - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the input topology corresponds to a hexahedral topology - if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology corresponds to a hexahedral topology - if (toModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) - { - msg_error() << "The type of the output topology '" << toModel.getPath() << "' does not correspond to a hexahedral topology."; - modelsOk = false; - } - } - - if (!modelsOk) + // Check input/output topology + if (!this->checkTopologyInputTypes()) // method will display error message if false { this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; diff --git a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp index 9e1264aa084..35948dbfcb4 100644 --- a/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp +++ b/Sofa/Component/Mapping/Linear/src/sofa/component/mapping/linear/SimpleTesselatedTetraTopologicalMapping.cpp @@ -49,55 +49,21 @@ int SimpleTesselatedTetraTopologicalMappingClass = core::RegisterObject ( "Speci // Implementation SimpleTesselatedTetraTopologicalMapping::SimpleTesselatedTetraTopologicalMapping () - : tetrahedraMappedFromTetra( initData ( &tetrahedraMappedFromTetra, "tetrahedraMappedFromTetra", "Each Tetrahedron of the input topology is mapped to the 8 tetrahedrons in which it can be divided")), - tetraSource( initData ( &tetraSource, "tetraSource", "Which tetra from the input topology map to a given tetra in the output topology (sofa::InvalidID if none)")), - d_pointMappedFromPoint( initData ( &d_pointMappedFromPoint, "pointMappedFromPoint", "Each point of the input topology is mapped to the same point")), - d_pointMappedFromEdge( initData ( &d_pointMappedFromEdge, "pointMappedFromEdge", "Each edge of the input topology is mapped to his midpoint")), - d_pointSource( initData ( &d_pointSource, "pointSource", "Which input topology element map to a given point in the output topology : 0 -> none, > 0 -> point index + 1, < 0 , - edge index -1")) + : sofa::core::topology::TopologicalMapping() + , tetrahedraMappedFromTetra( initData ( &tetrahedraMappedFromTetra, "tetrahedraMappedFromTetra", "Each Tetrahedron of the input topology is mapped to the 8 tetrahedrons in which it can be divided")) + , tetraSource( initData ( &tetraSource, "tetraSource", "Which tetra from the input topology map to a given tetra in the output topology (sofa::InvalidID if none)")) + , d_pointMappedFromPoint( initData ( &d_pointMappedFromPoint, "pointMappedFromPoint", "Each point of the input topology is mapped to the same point")) + , d_pointMappedFromEdge( initData ( &d_pointMappedFromEdge, "pointMappedFromEdge", "Each edge of the input topology is mapped to his midpoint")) + , d_pointSource( initData ( &d_pointSource, "pointSource", "Which input topology element map to a given point in the output topology : 0 -> none, > 0 -> point index + 1, < 0 , - edge index -1")) { + m_inputType = TopologyElementType::TETRAHEDRON; + m_outputType = TopologyElementType::TETRAHEDRON; } void SimpleTesselatedTetraTopologicalMapping::init() { - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the input topology corresponds to a tetrahedral topology - if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a tetrahedral topology."; - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology corresponds to a tetrahedral topology - if (toModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) - { - msg_error() << "The type of the output topology '" << toModel.getPath() << "' does not correspond to a tetrahedral topology."; - modelsOk = false; - } - } - - if (!modelsOk) + // Check input/output topology + if (!this->checkTopologyInputTypes()) // method will display error message if false { this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index c5afc6a8e9d..993b0846442 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -99,50 +99,23 @@ void Edge2QuadTopologicalMapping::init() unsigned int N = d_nbPointsOnEachCircle.getValue(); bool modelsOk = true; - // Check input topology - if (!fromModel) + // Check input/output topology + if (!this->checkTopologyInputTypes()) // method will display error message if false { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the input topology is derived from the edge topology container - if (!dynamic_cast(fromModel.get())) - { - msg_error() << "The input topology '" << fromModel.getPath() << "' is not homogeneous with a EdgeSetTopologyContainer. The '" << fromModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology is derived from the quad topology container - if (!dynamic_cast(toModel.get())) - { - msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - if (!modelsOk) + + // Making sure the output topology is derived from the quad topology container + if (!dynamic_cast(toModel.get())) { + msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl + << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } - + // INITIALISATION of QUADULAR mesh from EDGE mesh : core::behavior::MechanicalState* from_mstate = dynamic_cast*>(fromModel->getContext()->getMechanicalState()); diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp index 0e951164022..c1306984692 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2QuadTopologicalMapping.cpp @@ -54,70 +54,33 @@ int Hexa2QuadTopologicalMappingClass = core::RegisterObject("Special case of map // Implementation Hexa2QuadTopologicalMapping::Hexa2QuadTopologicalMapping() - : flipNormals(initData(&flipNormals, bool(false), "flipNormals", "Flip Normal ? (Inverse point order when creating triangle)")) + : sofa::core::topology::TopologicalMapping() + , flipNormals(initData(&flipNormals, bool(false), "flipNormals", "Flip Normal ? (Inverse point order when creating triangle)")) { + m_inputType = TopologyElementType::HEXAHEDRON; + m_outputType = TopologyElementType::QUAD; } void Hexa2QuadTopologicalMapping::init() { using namespace container::dynamic; - bool modelsOk = true; - // Check input topology - if (!fromModel) + if (!this->checkTopologyInputTypes()) // method will display error message if false { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the input topology corresponds to a tetrahedral topology - if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology is derived from the quad topology container - if (!dynamic_cast(toModel.get())) - { - msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } - else - { - // Making sure a topology modifier exists at the same level as the output topology - QuadSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) { - msg_error() << "No QuadSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; - modelsOk = false; - } - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - if (!modelsOk) - { + // Making sure a topology modifier exists at the same level as the output topology + QuadSetTopologyModifier *to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No QuadSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } - // Clear output topology toModel->clear(); diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp index 9dfe76593a2..b7d3eb65283 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Hexa2TetraTopologicalMapping.cpp @@ -55,8 +55,11 @@ int Hexa2TetraTopologicalMappingClass = core::RegisterObject("Special case of ma // Implementation Hexa2TetraTopologicalMapping::Hexa2TetraTopologicalMapping() - : swapping(initData(&swapping, false, "swapping","Boolean enabling to swapp hexa-edges\n in order to avoid bias effect")) + : sofa::core::topology::TopologicalMapping() + , swapping(initData(&swapping, false, "swapping","Boolean enabling to swapp hexa-edges\n in order to avoid bias effect")) { + m_inputType = TopologyElementType::HEXAHEDRON; + m_outputType = TopologyElementType::TETRAHEDRON; } Hexa2TetraTopologicalMapping::~Hexa2TetraTopologicalMapping() @@ -67,50 +70,23 @@ void Hexa2TetraTopologicalMapping::init() { using namespace container::dynamic; - // INITIALISATION of TETRAHEDRAL mesh from HEXAHEDRAL mesh : - - // recheck models - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - msg_error() << "Pointer to input topology is invalid."; - modelsOk = false; - } - else - { - // Making sure the input topology corresponds to a tetrahedral topology - if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::HEXAHEDRON) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a hexahedral topology."; - modelsOk = false; - } - } - - // Check ouput topology - if (!toModel) - { - msg_error() << "Pointer to output topology is invalid."; - modelsOk = false; - } - else + if (!this->checkTopologyInputTypes()) // method will display error message if false { - TetrahedronSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) - { - msg_error() << "No TetrahedronSetTopologyModifier found in the Tetrahedron topology Node."; - modelsOk = false; - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - if (!modelsOk) + TetrahedronSetTopologyModifier* to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No TetrahedronSetTopologyModifier found in the Tetrahedron topology Node."; this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } + // INITIALISATION of TETRAHEDRAL mesh from HEXAHEDRAL mesh : + TetrahedronSetTopologyContainer *to_tstc; toModel->getContext()->get(to_tstc); // Clear output topology diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp index 81b696766a7..1f8464e9b80 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Quad2TriangleTopologicalMapping.cpp @@ -60,7 +60,10 @@ int Quad2TriangleTopologicalMappingClass = core::RegisterObject("Special case of // Implementation Quad2TriangleTopologicalMapping::Quad2TriangleTopologicalMapping() + : sofa::core::topology::TopologicalMapping() { + m_inputType = TopologyElementType::QUAD; + m_outputType = TopologyElementType::TRIANGLE; } @@ -72,65 +75,24 @@ void Quad2TriangleTopologicalMapping::init() { using namespace container::dynamic; - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else + if (!this->checkTopologyInputTypes()) // method will display error message if false { - // Making sure the input topology is derived from the quad topology container - if (!dynamic_cast(fromModel.get())) - { - msg_error() << "The input topology '" << fromModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << fromModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology is derived from the triangle topology container - if (!dynamic_cast(toModel.get())) - { - msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a TriangleSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } - else - { - // Making sure a topology modifier exists at the same level as the output topology - TriangleSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) - { - msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; - modelsOk = false; - } - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - if (!modelsOk) + + // Making sure a topology modifier exists at the same level as the output topology + TriangleSetTopologyModifier *to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } - // Clear output topology toModel->clear(); diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp index d3e268b1349..769e24b4647 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Tetra2TriangleTopologicalMapping.cpp @@ -60,68 +60,31 @@ Tetra2TriangleTopologicalMapping::Tetra2TriangleTopologicalMapping() , noInitialTriangles(initData(&noInitialTriangles, bool(false), "noInitialTriangles", "If true the list of initial triangles is initially empty. Only additional triangles will be added in the list")) , m_outTopoModifier(nullptr) { + m_inputType = TopologyElementType::TETRAHEDRON; + m_outputType = TopologyElementType::TRIANGLE; } void Tetra2TriangleTopologicalMapping::init() { - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - // If the input topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no input mesh topology could be found. - msg_error() << "No input mesh topology found. Consider setting the '" << fromModel.getName() << "' data attribute."; - modelsOk = false; - } - else + if (!this->checkTopologyInputTypes()) // method will display error message if false { - // Making sure the input topology corresponds to a tetrahedral topology - if (fromModel.get()->getTopologyType() != sofa::geometry::ElementType::TETRAHEDRON) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a tetrahedral topology."; - modelsOk = false; - } - } - - // Check output topology - if (!toModel) - { - // If the output topology link isn't set by the user, the TopologicalMapping::create method tries to find it. - // If it is null at this point, it means no output mesh topology could be found. - msg_error() << "No output mesh topology found. Consider setting the '" << toModel.getName() << "' data attribute."; - modelsOk = false; - } - else - { - // Making sure the output topology is derived from the triangle topology container - if (!dynamic_cast(toModel.get())) - { - msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a TriangleSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - modelsOk = false; - } - else - { - // Making sure a topology modifier exists at the same level as the output topology - container::dynamic::TriangleSetTopologyModifier *to_tstm; - toModel->getContext()->get(to_tstm); - if (!to_tstm) { - msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" - << toModel->getContext()->getName() << "'."; - modelsOk = false; - } else { - m_outTopoModifier = to_tstm; - } - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - if (!modelsOk) + container::dynamic::TriangleSetTopologyModifier* to_tstm; + toModel->getContext()->get(to_tstm); + if (!to_tstm) { + msg_error() << "No TriangleSetTopologyModifier found in the output topology node '" + << toModel->getContext()->getName() << "'."; this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } - + else { + m_outTopoModifier = to_tstm; + } + // INITIALISATION of Triangle mesh from Tetrahedral mesh : // Clear output topology diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp index 9e7e886e466..ed4c6cca6c4 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Triangle2EdgeTopologicalMapping.cpp @@ -52,6 +52,8 @@ Triangle2EdgeTopologicalMapping::Triangle2EdgeTopologicalMapping() : sofa::core::topology::TopologicalMapping() , m_outTopoModifier(nullptr) { + m_inputType = TopologyElementType::TRIANGLE; + m_outputType = TopologyElementType::EDGE; } @@ -66,42 +68,17 @@ Triangle2EdgeTopologicalMapping::~Triangle2EdgeTopologicalMapping() void Triangle2EdgeTopologicalMapping::init() { - bool modelsOk = true; - - // Check input topology - if (!fromModel) - { - msg_error() << "Pointer to input topology is invalid."; - modelsOk = false; - } - else + if (!this->checkTopologyInputTypes()) // method will display error message if false { - // Making sure the input topology includes triangle elements - if (fromModel.get()->getNbTriangles() != 0) - { - msg_error() << "The type of the input topology '" << fromModel.getPath() << "' does not correspond to a valid triangle topology."; - modelsOk = false; - } + this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + return; } - // Check output topology - if (!toModel) - { - msg_error() << "Pointer to output topology is invalid."; - modelsOk = false; - } - else - { - toModel->getContext()->get(m_outTopoModifier); - if (!m_outTopoModifier) - { - msg_error() << "No EdgeSetTopologyModifier found in the Edge topology Node."; - modelsOk = false; - } - } - if (!modelsOk) + toModel->getContext()->get(m_outTopoModifier); + if (!m_outTopoModifier) { + msg_error() << "No EdgeSetTopologyModifier found in the Edge topology Node."; this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); return; } From 6030f269cdda5a08d82e8adee5073a7ba91ad018 Mon Sep 17 00:00:00 2001 From: epernod Date: Wed, 26 Oct 2022 13:30:37 +0200 Subject: [PATCH 09/13] [topology.mapping] Fix edge2QuadTopologicalMapping types --- .../topology/mapping/Edge2QuadTopologicalMapping.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index 993b0846442..e0c0d981009 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -64,6 +64,8 @@ Edge2QuadTopologicalMapping::Edge2QuadTopologicalMapping() , d_edgeList(initData(&d_edgeList, "edgeList", "list of input edges for the topological mapping: by default, all considered")) , d_flipNormals(initData(&d_flipNormals, bool(false), "flipNormals", "Flip Normal ? (Inverse point order when creating quad)")) { + m_inputType = TopologyElementType::EDGE; + m_outputType = TopologyElementType::QUAD; } void Edge2QuadTopologicalMapping::init() @@ -107,15 +109,6 @@ void Edge2QuadTopologicalMapping::init() } - // Making sure the output topology is derived from the quad topology container - if (!dynamic_cast(toModel.get())) - { - msg_error() << "The input topology '" << toModel.getPath() << "' is not homogeneous with a QuadSetTopologyContainer. The '" << toModel.getName() << "' data attribute must be linked to a valid component, among the following list of eligible components:" << msgendl - << sofa::core::ObjectFactory::getInstance()->listClassesDerivedFrom(); - this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); - return; - } - // INITIALISATION of QUADULAR mesh from EDGE mesh : core::behavior::MechanicalState* from_mstate = dynamic_cast*>(fromModel->getContext()->getMechanicalState()); From ec04fce518ac1ddccf80b7d6fdcee67ad08c2422 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Fri, 28 Oct 2022 11:38:30 +0200 Subject: [PATCH 10/13] fix compilation due to removal of getLoc2GlobVec() in TopologicalMapping.h --- .../sofa/gui/component/performer/RemovePrimitivePerformer.inl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sofa/GUI/Component/src/sofa/gui/component/performer/RemovePrimitivePerformer.inl b/Sofa/GUI/Component/src/sofa/gui/component/performer/RemovePrimitivePerformer.inl index f69a5aa0542..2600a72b3bd 100644 --- a/Sofa/GUI/Component/src/sofa/gui/component/performer/RemovePrimitivePerformer.inl +++ b/Sofa/GUI/Component/src/sofa/gui/component/performer/RemovePrimitivePerformer.inl @@ -373,7 +373,7 @@ bool RemovePrimitivePerformer::createElementList() if (topoMap) { // Mapping found: 1- get surface element ID in volumique topology, 2- get volume element ID behind surface element, 3- switching all variables to volumique case - unsigned int volTmp = (topoMap->getLoc2GlobVec()).getValue()[selectedElem[0]]; + unsigned int volTmp = topoMap->Loc2GlobDataVec.getValue()[selectedElem[0]]; topo_curr = topoMap->getFrom(); selectedElem[0] = topo_curr->getTetrahedraAroundTriangle(volTmp)[0]; surfaceOnVolume = true; From ba0cdb955b3f876ae81598c8f6c5519fd1793a85 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Fri, 28 Oct 2022 11:38:56 +0200 Subject: [PATCH 11/13] Add warning notifying the requested types from this specific TopologicalMapping --- .../topology/mapping/Edge2QuadTopologicalMapping.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index e0c0d981009..3e32a83de4a 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -280,6 +280,12 @@ void Edge2QuadTopologicalMapping::init() } } + else + { + // Check type Rigid3 of input mechanical object (required) + msg_error() << "Mechanical object associated with the input is not of type Rigid. Edge2QuadTopologicalMapping only supports Rigid3Types to Vec3Types"; + d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid); + } } From 4e92ffac3ea1ea1439a68a15cb436615b4cf6180 Mon Sep 17 00:00:00 2001 From: Hugo Talbot Date: Fri, 28 Oct 2022 11:51:37 +0200 Subject: [PATCH 12/13] remove unused variable --- .../component/topology/mapping/Edge2QuadTopologicalMapping.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp index 3e32a83de4a..412b4092713 100644 --- a/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp +++ b/Sofa/Component/Topology/Mapping/src/sofa/component/topology/mapping/Edge2QuadTopologicalMapping.cpp @@ -99,7 +99,6 @@ void Edge2QuadTopologicalMapping::init() } unsigned int N = d_nbPointsOnEachCircle.getValue(); - bool modelsOk = true; // Check input/output topology if (!this->checkTopologyInputTypes()) // method will display error message if false From 84dbf2fea3eb9a12a9455b79e163cbca79bdc5bc Mon Sep 17 00:00:00 2001 From: epernod Date: Thu, 3 Nov 2022 00:41:57 +0100 Subject: [PATCH 13/13] [MeshTopology FIx missing ElementType attribution at init --- .../container/constant/MeshTopology.cpp | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.cpp b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.cpp index 1c1259cd1ce..fa763f85a3c 100644 --- a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.cpp +++ b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.cpp @@ -540,20 +540,21 @@ void MeshTopology::init() const auto triangles = sofa::helper::getReadAccessor(seqTriangles); const auto edges = sofa::helper::getReadAccessor(seqEdges); - if (nbPoints==0) - { - // looking for upper topology - if (!hexahedra.empty()) - m_upperElementType = core::topology::TopologyElementType::HEXAHEDRON; - else if (!tetrahedra.empty()) - m_upperElementType = sofa::core::topology::TopologyElementType::TETRAHEDRON; - else if (!quads.empty()) - m_upperElementType = sofa::core::topology::TopologyElementType::QUAD; - else if (!triangles.empty()) - m_upperElementType = sofa::core::topology::TopologyElementType::TRIANGLE; - else - m_upperElementType = sofa::core::topology::TopologyElementType::EDGE; - } + + // looking for upper topology + if (!hexahedra.empty()) + m_upperElementType = core::topology::TopologyElementType::HEXAHEDRON; + else if (!tetrahedra.empty()) + m_upperElementType = sofa::core::topology::TopologyElementType::TETRAHEDRON; + else if (!quads.empty()) + m_upperElementType = sofa::core::topology::TopologyElementType::QUAD; + else if (!triangles.empty()) + m_upperElementType = sofa::core::topology::TopologyElementType::TRIANGLE; + else if (!edges.empty()) + m_upperElementType = sofa::core::topology::TopologyElementType::EDGE; + else + m_upperElementType = sofa::core::topology::TopologyElementType::POINT; + // compute the number of points, if the topology is charged from the scene or if it was loaded from a MeshLoader without any points data. if (nbPoints==0)