From 2107e18193b088203acf4ef091188923d318abb3 Mon Sep 17 00:00:00 2001 From: Alex Bilger Date: Mon, 6 Jul 2026 16:11:55 +0200 Subject: [PATCH] add quadratic topology --- .../Container/Constant/CMakeLists.txt | 2 + .../container/constant/MeshTopology.cpp | 78 ++------ .../container/constant/MeshTopology.h | 32 ++- .../constant/MeshTopologyContainer.cpp | 163 ++++++++++++++++ .../constant/MeshTopologyContainer.h | 183 ++++++++++++++++++ .../Constant/tests/MeshTopology_test.cpp | 5 + .../topology/container/grid/GridTopology.cpp | 6 +- .../grid/SparseGridRamificationTopology.cpp | 4 +- .../container/grid/SparseGridTopology.cpp | 4 +- .../src/sofa/core/topology/BaseMeshTopology.h | 21 ++ Sofa/framework/Geometry/CMakeLists.txt | 1 + .../Geometry/src/sofa/geometry/ElementType.h | 20 ++ .../src/sofa/geometry/QuadraticElements.h | 79 ++++++++ .../Topology/src/sofa/topology/Topology.h | 1 + 14 files changed, 507 insertions(+), 92 deletions(-) create mode 100644 Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.cpp create mode 100644 Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.h create mode 100644 Sofa/framework/Geometry/src/sofa/geometry/QuadraticElements.h diff --git a/Sofa/Component/Topology/Container/Constant/CMakeLists.txt b/Sofa/Component/Topology/Container/Constant/CMakeLists.txt index 958c2faaa08..ebf509cff7d 100644 --- a/Sofa/Component/Topology/Container/Constant/CMakeLists.txt +++ b/Sofa/Component/Topology/Container/Constant/CMakeLists.txt @@ -7,6 +7,7 @@ set(HEADER_FILES ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/config.h.in ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/init.h ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/MeshTopology.h + ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/MeshTopologyContainer.h ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/CubeTopology.h ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/SphereQuadTopology.h ) @@ -14,6 +15,7 @@ set(HEADER_FILES set(SOURCE_FILES ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/init.cpp ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/MeshTopology.cpp + ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/MeshTopologyContainer.cpp ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/CubeTopology.cpp ${SOFACOMPONENTTOPOLOGYCONTAINERCONSTANT_SOURCE_DIR}/SphereQuadTopology.cpp ) 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 b0e14ac3a76..a4beb496ea7 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 @@ -39,16 +39,16 @@ MeshTopology::EdgeUpdate::EdgeUpdate(MeshTopology* t) { if( topology->hasVolume() ) { - addInput(&topology->d_seqHexahedra); - addInput(&topology->d_seqTetrahedra); - addOutput(&topology->d_seqEdges); + addInput(&topology->d_seqHexahedra.toData()); + addInput(&topology->d_seqTetrahedra.toData()); + addOutput(&topology->d_seqEdges.toData()); setDirtyValue(); } else if( topology->hasSurface() ) { - addInput(&topology->d_seqTriangles); - addInput(&topology->d_seqQuads); - addOutput(&topology->d_seqEdges); + addInput(&topology->d_seqTriangles.toData()); + addInput(&topology->d_seqQuads.toData()); + addOutput(&topology->d_seqEdges.toData()); setDirtyValue(); } @@ -221,8 +221,8 @@ void MeshTopology::EdgeUpdate::updateFromSurface() MeshTopology::TriangleUpdate::TriangleUpdate(MeshTopology *t) :PrimitiveUpdate(t) { - addInput(&topology->d_seqTetrahedra); - addOutput(&topology->d_seqTriangles); + addInput(&topology->d_seqTetrahedra.toData()); + addOutput(&topology->d_seqTriangles.toData()); setDirtyValue(); } @@ -275,8 +275,8 @@ void MeshTopology::TriangleUpdate::doUpdate() MeshTopology::QuadUpdate::QuadUpdate(MeshTopology *t) :PrimitiveUpdate(t) { - addInput(&topology->d_seqHexahedra); - addOutput(&topology->d_seqQuads); + addInput(&topology->d_seqHexahedra.toData()); + addOutput(&topology->d_seqQuads.toData()); setDirtyValue(); } @@ -486,13 +486,6 @@ void registerMeshTopology(sofa::core::ObjectFactory* factory) MeshTopology::MeshTopology() : d_seqPoints(initData(&d_seqPoints, "position", "List of point positions")) - , d_seqEdges(initData(&d_seqEdges, "edges", "List of edge indices")) - , d_seqTriangles(initData(&d_seqTriangles, "triangles", "List of triangle indices")) - , d_seqQuads(initData(&d_seqQuads, "quads", "List of quad indices")) - , d_seqTetrahedra(initData(&d_seqTetrahedra, "tetrahedra", "List of tetrahedron indices")) - , d_seqHexahedra(initData(&d_seqHexahedra, "hexahedra", "List of hexahedron indices")) - , d_seqPrisms(initData(&d_seqPrisms, "prisms", "List of prisms indices")) - , d_seqPyramids(initData(&d_seqPyramids, "pyramids", "List of pyramids indices")) , d_seqUVs(initData(&d_seqUVs, "uv", "List of uv coordinates")) , d_computeAllBuffers(initData(&d_computeAllBuffers, false, "computeAllBuffers", "Option to compute all crossed topology buffers at init. False by default")) , nbPoints(0) @@ -506,9 +499,9 @@ MeshTopology::MeshTopology() { m_upperElementType = sofa::geometry::ElementType::EDGE; addAlias(&d_seqPoints, "points"); - addAlias(&d_seqEdges, "lines"); - addAlias(&d_seqTetrahedra, "tetras"); - addAlias(&d_seqHexahedra, "hexas"); + addAlias(&d_seqEdges.toData(), "lines"); + addAlias(&d_seqTetrahedra.toData(), "tetras"); + addAlias(&d_seqHexahedra.toData(), "hexas"); addAlias(&d_seqUVs, "texcoords"); } @@ -747,51 +740,6 @@ void MeshTopology::addUV(SReal u, SReal v) nbPoints = (int)d_seqUVs.getValue().size(); } -const MeshTopology::SeqEdges& MeshTopology::getEdges() -{ - return d_seqEdges.getValue(); -} - -const MeshTopology::SeqTriangles& MeshTopology::getTriangles() -{ - return d_seqTriangles.getValue(); -} - -const MeshTopology::SeqQuads& MeshTopology::getQuads() -{ - return d_seqQuads.getValue(); -} - -const MeshTopology::SeqTetrahedra& MeshTopology::getTetrahedra() -{ - if (!validTetrahedra) - { - updateTetrahedra(); - validTetrahedra = true; - } - return d_seqTetrahedra.getValue(); -} - -const MeshTopology::SeqHexahedra& MeshTopology::getHexahedra() -{ - if (!validHexahedra) - { - updateHexahedra(); - validHexahedra = true; - } - return d_seqHexahedra.getValue(); -} - -const BaseMeshTopology::SeqPrisms& MeshTopology::getPrisms() -{ - return d_seqPrisms.getValue(); -} - -const BaseMeshTopology::SeqPyramids& MeshTopology::getPyramids() -{ - return d_seqPyramids.getValue(); -} - const MeshTopology::SeqUV& MeshTopology::getUVs() { return d_seqUVs.getValue(); diff --git a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.h b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.h index 281f5ceeca1..ed2dd459cee 100644 --- a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.h +++ b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopology.h @@ -23,17 +23,17 @@ #include #include -#include +#include #include #include namespace sofa::component::topology::container::constant { -class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public core::topology::BaseMeshTopology +class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public MeshTopologyContainer { public: - SOFA_CLASS(MeshTopology,core::topology::BaseMeshTopology); + SOFA_CLASS(MeshTopology, MeshTopologyContainer); protected: class PrimitiveUpdate : public sofa::core::DataEngine @@ -91,16 +91,6 @@ class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public core: void setNbPoints(Size n) override; - // Complete sequence accessors - - const SeqEdges& getEdges() override; - const SeqTriangles& getTriangles() override; - const SeqQuads& getQuads() override; - const SeqTetrahedra& getTetrahedra() override; - const SeqHexahedra& getHexahedra() override; - const SeqPrisms& getPrisms() override; - const SeqPyramids& getPyramids() override; - // If using STEP loader, include also uv coordinates typedef Index UVID; typedef type::Vec2 UV; @@ -297,17 +287,19 @@ class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public core: typedef type::vector SeqPoints; Data< SeqPoints > d_seqPoints; ///< List of point positions - Data d_seqEdges; ///< List of edge indices - Data d_seqTriangles; ///< List of triangle indices - Data d_seqQuads; ///< List of quad indices - Data d_seqTetrahedra; ///< List of tetrahedron indices - Data d_seqHexahedra; ///< List of hexahedron indices - Data d_seqPrisms; - Data d_seqPyramids; + SeqElementProxy d_seqEdges { this }; + SeqElementProxy d_seqTriangles { this }; + SeqElementProxy d_seqQuads { this }; + SeqElementProxy d_seqTetrahedra { this }; + SeqElementProxy d_seqHexahedra { this }; + SeqElementProxy d_seqPrisms { this }; + SeqElementProxy d_seqPyramids { this }; + Data d_seqUVs; ///< List of uv coordinates Data d_computeAllBuffers; ///< Option to call method computeCrossElementBuffers. False by default protected: + Size nbPoints; template diff --git a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.cpp b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.cpp new file mode 100644 index 00000000000..fc62f37f5bf --- /dev/null +++ b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by * +* the Free Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#include + +namespace sofa::component::topology::container::constant +{ + +using sofa::geometry::ElementType; + +constexpr const char* elementTypeToDataName(ElementType type) +{ + switch (type) + { + case ElementType::POINT: { return "position"; } + case ElementType::EDGE: { return "edges"; } + case ElementType::TRIANGLE: { return "triangles"; } + case ElementType::QUAD: { return "quads"; } + case ElementType::TETRAHEDRON: { return "tetrahedra"; } + case ElementType::HEXAHEDRON: { return "hexahedra"; } + case ElementType::PRISM: { return "prisms"; } + case ElementType::PYRAMID: { return "pyramids"; } + + case ElementType::QUADRATIC_EDGE: { return "quadratic_edges"; } + case ElementType::QUADRATIC_TRIANGLE: { return "quadratic_triangles"; } + case ElementType::QUADRATIC_QUAD: { return "quadratic_quads"; } + case ElementType::QUADRATIC_TETRAHEDRON: { return "quadratic_tetrahedra"; } + case ElementType::QUADRATIC_HEXAHEDRON: { return "quadratic_hexahedra"; } + case ElementType::QUADRATIC_PRISM: { return "quadratic_prisms"; } + case ElementType::QUADRATIC_PYRAMID: { return "quadratic_pyramids"; } + + default: + return "Unknown"; + } +} +template +void registerSingleData(core::objectmodel::BaseComponent* meshTopology, auto& dataContainer) +{ + using AllElements = std::remove_cvref_t; + using DataSeqElementPtr = std::tuple_element_t; + using DataSeqElement = typename DataSeqElementPtr::element_type; + using SeqElement = typename DataSeqElement::value_type; + using TopologyElement = typename SeqElement::value_type; + static constexpr auto elementType = TopologyElement::Element_type; + + const char* elementName = sofa::geometry::elementTypeToString(elementType); + auto elementNameStr = sofa::helper::downcaseString(std::string(elementName)); + + auto dataName = elementTypeToDataName(elementType); + std::string dataNameStr { dataName }; + sofa::helper::replaceAll(dataNameStr, " ", "_"); + + auto& dataPtr = std::get(dataContainer); + dataPtr = std::make_unique("List of " + elementNameStr); + + sofa::core::objectmodel::BaseData& data = *dataPtr; + data.setName(dataName); + + meshTopology->addData(dataPtr.get(), dataName); +} + +template +void registerData(core::objectmodel::BaseComponent* meshTopology, auto& dataContainer, std::index_sequence) +{ + (registerSingleData(meshTopology, dataContainer), ...); +} + +const void* MeshTopologyContainer::getElementsRaw( + const sofa::geometry::ElementType& elementType) const noexcept +{ + switch (elementType) + { + case ElementType::UNKNOWN: + case ElementType::POINT: + break; + case ElementType::EDGE: + return &get()->getValue(); + case ElementType::TRIANGLE: + return &get()->getValue(); + case ElementType::QUAD: + return &get()->getValue(); + case ElementType::TETRAHEDRON: + return &get()->getValue(); + case ElementType::HEXAHEDRON: + return &get()->getValue(); + case ElementType::PRISM: + return &get()->getValue(); + case ElementType::PYRAMID: + return &get()->getValue(); + case ElementType::QUADRATIC_EDGE: + return &get()->getValue(); + case ElementType::QUADRATIC_TRIANGLE: + return &get()->getValue(); + case ElementType::QUADRATIC_QUAD: + return &get()->getValue(); + case ElementType::QUADRATIC_TETRAHEDRON: + return &get()->getValue(); + case ElementType::QUADRATIC_HEXAHEDRON: + return &get()->getValue(); + case ElementType::QUADRATIC_PRISM: + return &get()->getValue(); + case ElementType::QUADRATIC_PYRAMID: + return &get()->getValue(); + case ElementType::SIZE: + default: + return nullptr; + } + return nullptr; +} + +MeshTopologyContainer::MeshTopologyContainer() : Inherit1() +{ + registerData(this, m_container, std::make_index_sequence>{}); +} + +const core::topology::BaseMeshTopology::SeqEdges& MeshTopologyContainer::getEdges() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqTriangles& MeshTopologyContainer::getTriangles() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqQuads& MeshTopologyContainer::getQuads() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqTetrahedra& MeshTopologyContainer::getTetrahedra() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqHexahedra& MeshTopologyContainer::getHexahedra() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqPrisms& MeshTopologyContainer::getPrisms() +{ + return get()->getValue(); +} +const core::topology::BaseMeshTopology::SeqPyramids& MeshTopologyContainer::getPyramids() +{ + return get()->getValue(); +} + +} // namespace sofa::component::topology::container::constant diff --git a/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.h b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.h new file mode 100644 index 00000000000..f03a18c91dc --- /dev/null +++ b/Sofa/Component/Topology/Container/Constant/src/sofa/component/topology/container/constant/MeshTopologyContainer.h @@ -0,0 +1,183 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by * +* the Free Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#pragma once +#include +#include + +namespace sofa::component::topology::container::constant +{ + +class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopologyContainer : + public sofa::core::topology::BaseMeshTopology +{ +public: + SOFA_CLASS(MeshTopologyContainer, core::topology::BaseMeshTopology); + + template //e.g. sofa::geometry::Edge + using TopologyElement = sofa::topology::Element; + + template //e.g. sofa::geometry::Edge + using SeqElement = sofa::type::vector>; + + template //e.g. sofa::geometry::Edge + using DataSeqElement = sofa::Data>; + + template //e.g. sofa::geometry::Edge + using DataSeqElementPtr = std::unique_ptr>; + + using AllElements = std::tuple< + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr, + DataSeqElementPtr + >; + + AllElements m_container; + + const SeqEdges& getEdges() override; + const SeqTriangles& getTriangles() override; + const SeqQuads& getQuads() override; + const SeqTetrahedra& getTetrahedra() override; + const SeqHexahedra& getHexahedra() override; + const SeqPrisms& getPrisms() override; + const SeqPyramids& getPyramids() override; + + template + const DataSeqElementPtr& get() const + { + return std::get>(m_container); + } + + template + DataSeqElementPtr& get() + { + return std::get>(m_container); + } + +protected: + + const void* getElementsRaw(const sofa::geometry::ElementType& elementType) const noexcept override; + + MeshTopologyContainer(); + + // A proxy for legacy data members + template + struct SeqElementProxy + { + MeshTopologyContainer* m_meshTopologyContainer { nullptr }; + SeqElementProxy(MeshTopologyContainer* meshTopologyContainer) : m_meshTopologyContainer(meshTopologyContainer) {} + + DataSeqElement& toData() + { + return *m_meshTopologyContainer->get(); + } + + const DataSeqElement& toData() const + { + return *m_meshTopologyContainer->get(); + } + + operator const DataSeqElement&() const + { + return toData(); + } + + operator DataSeqElement&() + { + return toData(); + } + + SeqElement* beginEdit() + { + return toData().beginEdit(); + } + + void endEdit() + { + toData().endEdit(); + } + + const SeqElement& getValue() const + { + return toData().getValue(); + } + + void setValue(const DataSeqElement& value) + { + toData().setValue(value); + } + + core::BaseData* getParent() const + { + return toData().getParent(); + } + + bool setParent(core::BaseData* parent, const std::string& path = std::string()) + { + return toData().setParent(parent, path); + } + + void delInput(core::objectmodel::DDGNode* n) + { + toData().delInput(n); + } + + SeqElement* beginWriteOnly() + { + return toData().beginWriteOnly(); + } + }; +}; + +} + +namespace sofa::helper +{ +template +auto getWriteOnlyAccessor(sofa::component::topology::container::constant::MeshTopologyContainer::SeqElementProxy& m_container) +{ + return getWriteOnlyAccessor(m_container.toData()); +} + +template +auto getWriteAccessor(sofa::component::topology::container::constant::MeshTopologyContainer::SeqElementProxy& m_container) +{ + return getWriteAccessor(m_container.toData()); +} + +template +auto getReadAccessor(const sofa::component::topology::container::constant::MeshTopologyContainer::SeqElementProxy& m_container) +{ + return getReadAccessor(m_container.toData()); +} + +} diff --git a/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp b/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp index e580a134430..b538206d6e0 100644 --- a/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp +++ b/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp @@ -129,6 +129,7 @@ bool MeshTopology_test::testHexahedronTopology() // Check tetrahedra container buffers size EXPECT_EQ(topo->getNbHexahedra(), nbrHexahedron); EXPECT_EQ(topo->getHexahedra().size(), nbrHexahedron); + EXPECT_EQ(topo->getElements().size(), nbrHexahedron); //// check tetrahedron buffer const sofa::type::vector& hexahedra1 = topoCon->getHexahedronArray(); @@ -243,6 +244,7 @@ bool MeshTopology_test::testTetrahedronTopology() // Check tetrahedra container buffers size EXPECT_EQ(topo->getNbTetrahedra(), nbrTetrahedron); EXPECT_EQ(topo->getTetrahedra().size(), nbrTetrahedron); + EXPECT_EQ(topo->getElements().size(), nbrTetrahedron); //// check tetrahedron buffer const sofa::type::vector& tetrahedra1 = topoCon->getTetrahedronArray(); @@ -357,6 +359,7 @@ bool MeshTopology_test::testQuadTopology() // Check quads container buffers size EXPECT_EQ(topo->getNbQuads(), nbrQuad); EXPECT_EQ(topo->getQuads().size(), nbrQuad); + EXPECT_EQ(topo->getElements().size(), nbrQuad); //// check quad buffer const sofa::type::vector& quads1 = topoCon->getQuadArray(); @@ -453,6 +456,7 @@ bool MeshTopology_test::testTriangleTopology() // Check triangles container buffers size EXPECT_EQ(topo->getNbTriangles(), nbrTriangle); EXPECT_EQ(topo->getTriangles().size(), nbrTriangle); + EXPECT_EQ(topo->getElements().size(), nbrTriangle); //// check triangle buffer const sofa::type::vector& triangles1 = topoCon->getTriangleArray(); @@ -549,6 +553,7 @@ bool MeshTopology_test::testEdgeTopology() // Check edge container buffers size EXPECT_EQ(topo->getNbEdges(), nbrEdge); EXPECT_EQ(topo->getEdges().size(), nbrEdge); + EXPECT_EQ(topo->getElements().size(), nbrEdge); //// check edge buffer const sofa::type::vector& edges1 = topoCon->getEdgeArray(); diff --git a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/GridTopology.cpp b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/GridTopology.cpp index 86c7551c976..2a23965f9b7 100644 --- a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/GridTopology.cpp +++ b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/GridTopology.cpp @@ -37,9 +37,9 @@ GridTopology::GridUpdate::GridUpdate(GridTopology *t): m_topology(t) { addInput(&t->d_n); - addOutput(&t->d_seqEdges); - addOutput(&t->d_seqQuads); - addOutput(&t->d_seqHexahedra); + addOutput(&t->d_seqEdges.toData()); + addOutput(&t->d_seqQuads.toData()); + addOutput(&t->d_seqHexahedra.toData()); setDirtyValue(); } diff --git a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridRamificationTopology.cpp b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridRamificationTopology.cpp index cdd3e7bc6ac..73e59b30d3c 100644 --- a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridRamificationTopology.cpp +++ b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridRamificationTopology.cpp @@ -848,8 +848,8 @@ void SparseGridRamificationTopology::buildVirtualFinerLevels() { _virtualFinerLevels[0]->d_seqPoints.setParent(&this->d_seqPoints); _virtualFinerLevels[0]->d_facets.setParent(&this->d_facets); - _virtualFinerLevels[0]->d_seqTriangles.setParent(&this->d_seqTriangles); - _virtualFinerLevels[0]->d_seqQuads.setParent(&this->d_seqQuads); + _virtualFinerLevels[0]->d_seqTriangles.setParent(&this->d_seqTriangles.toData()); + _virtualFinerLevels[0]->d_seqQuads.setParent(&this->d_seqQuads.toData()); } else _virtualFinerLevels[0]->load(fileTopology.c_str()); diff --git a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridTopology.cpp b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridTopology.cpp index 3ad22bb854a..de497b8e115 100644 --- a/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridTopology.cpp +++ b/Sofa/Component/Topology/Container/Grid/src/sofa/component/topology/container/grid/SparseGridTopology.cpp @@ -1243,8 +1243,8 @@ void SparseGridTopology::buildVirtualFinerLevels() { _virtualFinerLevels[0]->d_seqPoints.setParent(&this->d_seqPoints); _virtualFinerLevels[0]->d_facets.setParent(&this->d_facets); - _virtualFinerLevels[0]->d_seqTriangles.setParent(&this->d_seqTriangles); - _virtualFinerLevels[0]->d_seqQuads.setParent(&this->d_seqQuads); + _virtualFinerLevels[0]->d_seqTriangles.setParent(&this->d_seqTriangles.toData()); + _virtualFinerLevels[0]->d_seqQuads.setParent(&this->d_seqQuads.toData()); } else _virtualFinerLevels[0]->load(fileTopology.c_str()); diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h index 7910c16640f..16122b905df 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h @@ -108,6 +108,21 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology virtual const SeqHexahedra& getHexahedra() = 0; virtual const SeqPrisms& getPrisms() = 0; virtual const SeqPyramids& getPyramids() = 0; + + template // e.g. sofa::geometry::Edge + const auto& getElements() const + { + using TopologyElement = sofa::topology::Element; + using SeqElement = sofa::type::vector; + const auto* rawSequence = getElementsRaw(ElementType::Element_type); + if (!rawSequence) + { + static SeqElement empty; + return empty; + } + return *static_cast(rawSequence); + } + /// @} /// Random accessors @@ -335,6 +350,12 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology sofa::core::objectmodel::DataFileName fileTopology; + + virtual const void* getElementsRaw(const sofa::geometry::ElementType& elementType) const noexcept + { + return nullptr; + } + public: bool insertInNode( objectmodel::BaseNode* node ) override; diff --git a/Sofa/framework/Geometry/CMakeLists.txt b/Sofa/framework/Geometry/CMakeLists.txt index 311e613ff22..e92ec8ac4f0 100644 --- a/Sofa/framework/Geometry/CMakeLists.txt +++ b/Sofa/framework/Geometry/CMakeLists.txt @@ -15,6 +15,7 @@ set(HEADER_FILES ${SOFAGEOMETRYSRC_ROOT}/Prism.h ${SOFAGEOMETRYSRC_ROOT}/Pyramid.h ${SOFAGEOMETRYSRC_ROOT}/Quad.h + ${SOFAGEOMETRYSRC_ROOT}/QuadraticElements.h ${SOFAGEOMETRYSRC_ROOT}/Tetrahedron.h ${SOFAGEOMETRYSRC_ROOT}/Triangle.h diff --git a/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h b/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h index 57ece622444..d850562e0df 100644 --- a/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h +++ b/Sofa/framework/Geometry/src/sofa/geometry/ElementType.h @@ -30,7 +30,9 @@ namespace sofa::geometry enum class ElementType : sofa::Size { UNKNOWN, + POINT, + EDGE, TRIANGLE, QUAD, @@ -38,6 +40,15 @@ enum class ElementType : sofa::Size HEXAHEDRON, PRISM, PYRAMID, + + QUADRATIC_EDGE, + QUADRATIC_TRIANGLE, + QUADRATIC_QUAD, + QUADRATIC_TETRAHEDRON, + QUADRATIC_HEXAHEDRON, + QUADRATIC_PRISM, + QUADRATIC_PYRAMID, + SIZE }; @@ -55,6 +66,15 @@ constexpr const char* elementTypeToString(ElementType type) case ElementType::HEXAHEDRON: { return "Hexahedron"; } case ElementType::PRISM: { return "Prism"; } case ElementType::PYRAMID: { return "Pyramid"; } + + case ElementType::QUADRATIC_EDGE: { return "Quadratic Edge"; } + case ElementType::QUADRATIC_TRIANGLE: { return "Quadratic Triangle"; } + case ElementType::QUADRATIC_QUAD: { return "Quadratic Quad"; } + case ElementType::QUADRATIC_TETRAHEDRON: { return "Quadratic Tetrahedron"; } + case ElementType::QUADRATIC_HEXAHEDRON: { return "Quadratic Hexahedron"; } + case ElementType::QUADRATIC_PRISM: { return "Quadratic Prism"; } + case ElementType::QUADRATIC_PYRAMID: { return "Quadratic Pyramid"; } + default: return "Unknown"; } diff --git a/Sofa/framework/Geometry/src/sofa/geometry/QuadraticElements.h b/Sofa/framework/Geometry/src/sofa/geometry/QuadraticElements.h new file mode 100644 index 00000000000..03913448bb4 --- /dev/null +++ b/Sofa/framework/Geometry/src/sofa/geometry/QuadraticElements.h @@ -0,0 +1,79 @@ +/****************************************************************************** +* SOFA, Simulation Open-Framework Architecture * +* (c) 2006 INRIA, USTL, UJF, CNRS, MGH * +* * +* This program is free software; you can redistribute it and/or modify it * +* under the terms of the GNU Lesser General Public License as published by * +* the Free Software Foundation; either version 2.1 of the License, or (at * +* your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, but WITHOUT * +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * +* for more details. * +* * +* You should have received a copy of the GNU Lesser General Public License * +* along with this program. If not, see . * +******************************************************************************* +* Authors: The SOFA Team and external contributors (see Authors.txt) * +* * +* Contact information: contact@sofa-framework.org * +******************************************************************************/ +#pragma once + +#include +#include + +namespace sofa::geometry +{ + +struct QuadraticEdge +{ + static constexpr sofa::Size NumberOfNodes = 3; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_EDGE; +}; + +struct QuadraticTriangle +{ + static constexpr sofa::Size NumberOfNodes = 6; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_TRIANGLE; +}; + +struct QuadraticQuad +{ + static constexpr sofa::Size NumberOfNodes = 9; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_QUAD; +}; + +struct QuadraticTetrahedron +{ + static constexpr sofa::Size NumberOfNodes = 10; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_TETRAHEDRON; +}; + +struct QuadraticHexahedron +{ + static constexpr sofa::Size NumberOfNodes = 27; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_HEXAHEDRON; +}; + +struct QuadraticPrism +{ + static constexpr sofa::Size NumberOfNodes = 18; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_PRISM; +}; + +struct QuadraticPyramid +{ + static constexpr sofa::Size NumberOfNodes = 14; + static constexpr sofa::Size PolynomialOrder = 2; + static constexpr ElementType Element_type = ElementType::QUADRATIC_PYRAMID; +}; + +} diff --git a/Sofa/framework/Topology/src/sofa/topology/Topology.h b/Sofa/framework/Topology/src/sofa/topology/Topology.h index 16a54ffcb80..108828dd683 100644 --- a/Sofa/framework/Topology/src/sofa/topology/Topology.h +++ b/Sofa/framework/Topology/src/sofa/topology/Topology.h @@ -30,4 +30,5 @@ #include #include #include +#include #include