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 c7ce634725c..b0e14ac3a76 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 @@ -518,6 +518,8 @@ void MeshTopology::init() const auto hexahedra = sofa::helper::getReadAccessor(d_seqHexahedra); const auto tetrahedra = sofa::helper::getReadAccessor(d_seqTetrahedra); + const auto prisms = sofa::helper::getReadAccessor(d_seqPrisms); + const auto pyramids = sofa::helper::getReadAccessor(d_seqPyramids); const auto quads = sofa::helper::getReadAccessor(d_seqQuads); const auto triangles = sofa::helper::getReadAccessor(d_seqTriangles); const auto edges = sofa::helper::getReadAccessor(d_seqEdges); @@ -527,6 +529,10 @@ void MeshTopology::init() m_upperElementType = geometry::ElementType::HEXAHEDRON; else if (!tetrahedra.empty()) m_upperElementType = sofa::geometry::ElementType::TETRAHEDRON; + else if (!prisms.empty()) + m_upperElementType = sofa::geometry::ElementType::PRISM; + else if (!pyramids.empty()) + m_upperElementType = sofa::geometry::ElementType::PYRAMID; else if (!quads.empty()) m_upperElementType = sofa::geometry::ElementType::QUAD; else if (!triangles.empty()) @@ -545,28 +551,13 @@ void MeshTopology::init() // 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) { - unsigned int n = 0; - const auto countPoints = [&n](const auto& seqElements) - { - for (const auto& element : seqElements) - { - for (const auto pointId : element) - { - if (n <= pointId) - { - n = 1 + pointId; - } - } - } - }; - - countPoints(edges); - countPoints(triangles); - countPoints(quads); - countPoints(tetrahedra); - countPoints(hexahedra); - - nbPoints = n; + nbPoints = std::max(nbPoints, countPoints(edges)); + nbPoints = std::max(nbPoints, countPoints(triangles)); + nbPoints = std::max(nbPoints, countPoints(quads)); + nbPoints = std::max(nbPoints, countPoints(tetrahedra)); + nbPoints = std::max(nbPoints, countPoints(hexahedra)); + nbPoints = std::max(nbPoints, countPoints(prisms)); + nbPoints = std::max(nbPoints, countPoints(pyramids)); } @@ -694,55 +685,58 @@ void MeshTopology::addPoint(SReal px, SReal py, SReal pz) void MeshTopology::addEdge( Index a, Index b ) { - d_seqEdges.beginEdit()->push_back(Edge(a, b)); - d_seqEdges.endEdit(); - if (a >= nbPoints) nbPoints = a+1; - if (b >= nbPoints) nbPoints = b+1; + const Edge addedElement { a, b }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqEdges); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); } void MeshTopology::addTriangle( Index a, Index b, Index c ) { - d_seqTriangles.beginEdit()->push_back(Triangle(a, b, c) ); - d_seqTriangles.endEdit(); - if (a >= nbPoints) nbPoints = a+1; - if (b >= nbPoints) nbPoints = b+1; - if (c >= nbPoints) nbPoints = c+1; + const Triangle addedElement { a, b, c }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqTriangles); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); } void MeshTopology::addQuad(Index a, Index b, Index c, Index d) { - d_seqQuads.beginEdit()->push_back(Quad(a, b, c, d)); - d_seqQuads.endEdit(); - if (a >= nbPoints) nbPoints = a+1; - if (b >= nbPoints) nbPoints = b+1; - if (c >= nbPoints) nbPoints = c+1; - if (d >= nbPoints) nbPoints = d+1; + const Quad addedElement { a, b, c, d }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqQuads); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); } void MeshTopology::addTetra( Index a, Index b, Index c, Index d ) { - d_seqTetrahedra.beginEdit()->push_back(Tetra(a, b, c, d) ); - d_seqTetrahedra.endEdit(); - if (a >= nbPoints) nbPoints = a+1; - if (b >= nbPoints) nbPoints = b+1; - if (c >= nbPoints) nbPoints = c+1; - if (d >= nbPoints) nbPoints = d+1; + const Tetrahedron addedElement { a, b, c, d }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqTetrahedra); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); } void MeshTopology::addHexa(Index p1, Index p2, Index p3, Index p4, Index p5, Index p6, Index p7, Index p8) { + const Hexahedron addedElement { p1, p2, p3, p4, p5, p6, p7, p8 }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqHexahedra); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); +} - d_seqHexahedra.beginEdit()->push_back(Hexa(p1, p2, p3, p4, p5, p6, p7, p8)); +void MeshTopology::addPrism(Index a, Index b, Index c, Index d, Index e, Index f) +{ + const Prism addedElement { a, b, c, d, e, f }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqPrisms); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); +} - d_seqHexahedra.endEdit(); - if (p1 >= nbPoints) nbPoints = p1+1; - if (p2 >= nbPoints) nbPoints = p2+1; - if (p3 >= nbPoints) nbPoints = p3+1; - if (p4 >= nbPoints) nbPoints = p4+1; - if (p5 >= nbPoints) nbPoints = p5+1; - if (p6 >= nbPoints) nbPoints = p6+1; - if (p7 >= nbPoints) nbPoints = p7+1; - if (p8 >= nbPoints) nbPoints = p8+1; +void MeshTopology::addPyramid(Index a, Index b, Index c, Index d, Index e) +{ + const Pyramid addedElement { a, b, c, d, e }; + auto seqElements = helper::getWriteOnlyAccessor(d_seqPyramids); + seqElements.push_back(addedElement); + nbPoints = std::max(nbPoints, countPoints(std::array{addedElement})); } void MeshTopology::addUV(SReal u, SReal v) 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 4b4962809c3..281f5ceeca1 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 @@ -250,6 +250,8 @@ class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public core: void addQuad( Index a, Index b, Index c, Index d ) override; void addTetra( Index a, Index b, Index c, Index d ) override; void addHexa( Index a, Index b, Index c, Index d, Index e, Index f, Index g, Index h ) override; + void addPrism( Index a, Index b, Index c, Index d, Index e, Index f ) override; + void addPyramid( Index a, Index b, Index c, Index d, Index e ) override; /// get the current revision of this mesh (use to detect changes) int getRevision() const override { return revision; } @@ -308,6 +310,23 @@ class SOFA_COMPONENT_TOPOLOGY_CONTAINER_CONSTANT_API MeshTopology : public core: protected: Size nbPoints; + template + Size countPoints(const ElementContainer& seqElements) + { + Size n = 0; + for (const auto& element : seqElements) + { + for (const auto pointId : element) + { + if (n <= pointId) + { + n = 1 + pointId; + } + } + } + return n; + } + bool validTetrahedra; bool validHexahedra; diff --git a/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp b/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp index 47d3f72da70..e580a134430 100644 --- a/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp +++ b/Sofa/Component/Topology/Container/Constant/tests/MeshTopology_test.cpp @@ -46,7 +46,14 @@ using namespace sofa::testing; class MeshTopology_test : public BaseTest { public: - bool testEmptyContainer(); + void doSetUp() override + { + m_topo = sofa::core::objectmodel::New< MeshTopology >(); + ASSERT_TRUE(m_topo != nullptr); + ASSERT_EQ(m_topo->getNbPoints(), 0u); + } + + bool testEmptyContainer() const; bool testHexahedronTopology(); bool testTetrahedronTopology(); @@ -56,30 +63,41 @@ class MeshTopology_test : public BaseTest bool testEdgeTopology(); bool testVertexTopology(); + + void testAddPoint() const; + void testAddEdge() const; + void testAddTriangle() const; + void testAddQuad() const; + void testAddTetrahedron() const; + void testAddHexahedron() const; + void testAddPrism() const; + void testAddPyramid() const; + +protected: + + MeshTopology::SPtr m_topo { nullptr }; }; -bool MeshTopology_test::testEmptyContainer() +bool MeshTopology_test::testEmptyContainer() const { - const MeshTopology::SPtr topoCon = sofa::core::objectmodel::New< MeshTopology >(); - - EXPECT_EQ(topoCon->getNbHexahedra(), 0); - EXPECT_EQ(topoCon->getHexahedra().size(), 0); + EXPECT_EQ(m_topo->getNbHexahedra(), 0); + EXPECT_EQ(m_topo->getHexahedra().size(), 0); - EXPECT_EQ(topoCon->getNbHexahedra(), 0); - EXPECT_EQ(topoCon->getTetrahedra().size(), 0); + EXPECT_EQ(m_topo->getNbHexahedra(), 0); + EXPECT_EQ(m_topo->getTetrahedra().size(), 0); - EXPECT_EQ(topoCon->getNbQuads(), 0); - EXPECT_EQ(topoCon->getQuads().size(), 0); + EXPECT_EQ(m_topo->getNbQuads(), 0); + EXPECT_EQ(m_topo->getQuads().size(), 0); - EXPECT_EQ(topoCon->getNbTriangles(), 0); - EXPECT_EQ(topoCon->getTriangles().size(), 0); + EXPECT_EQ(m_topo->getNbTriangles(), 0); + EXPECT_EQ(m_topo->getTriangles().size(), 0); - EXPECT_EQ(topoCon->getNbEdges(), 0); - EXPECT_EQ(topoCon->getEdges().size(), 0); + EXPECT_EQ(m_topo->getNbEdges(), 0); + EXPECT_EQ(m_topo->getEdges().size(), 0); - EXPECT_EQ(topoCon->getNbPoints(), 0); + EXPECT_EQ(m_topo->getNbPoints(), 0); return true; } @@ -576,11 +594,77 @@ bool MeshTopology_test::testVertexTopology() return true; } +void MeshTopology_test::testAddPoint() const +{ + const auto before = m_topo->getNbPoints(); + m_topo->addPoint(0.0, 0.0, 0.0); + EXPECT_EQ(m_topo->getNbPoints(), before + 1); +} + +void MeshTopology_test::testAddEdge() const +{ + m_topo->addEdge(0, 1); + EXPECT_EQ(m_topo->getNbPoints(), 2u); + m_topo->addEdge(2, 10); + EXPECT_EQ(m_topo->getNbPoints(), 11u); +} +void MeshTopology_test::testAddTriangle() const +{ + m_topo->addTriangle(0, 1, 2); + EXPECT_EQ(m_topo->getNbPoints(), 3u); + + m_topo->addTriangle(5, 3, 4); + EXPECT_EQ(m_topo->getNbPoints(), 6u); +} -TEST_F(MeshTopology_test, testEmptyContainer) +void MeshTopology_test::testAddQuad() const { + m_topo->addQuad(0, 1, 2, 3); + EXPECT_EQ(m_topo->getNbPoints(), 4u); + + m_topo->addQuad(7, 6, 5, 4); + EXPECT_EQ(m_topo->getNbPoints(), 8u); +} + +void MeshTopology_test::testAddTetrahedron() const +{ + m_topo->addTetra(0, 1, 2, 3); + EXPECT_EQ(m_topo->getNbPoints(), 4u); + + m_topo->addTetra(2, 5, 9, 3); + EXPECT_EQ(m_topo->getNbPoints(), 10u); +} + +void MeshTopology_test::testAddHexahedron() const +{ + m_topo->addHexa(0, 1, 2, 3, 4, 5, 6, 7); + EXPECT_EQ(m_topo->getNbPoints(), 8u); + + m_topo->addHexa(10, 11, 12, 13, 14, 15, 16, 31); + EXPECT_EQ(m_topo->getNbPoints(), 32u); +} + +void MeshTopology_test::testAddPrism() const +{ + m_topo->addPrism(0, 1, 2, 3, 4, 5); + EXPECT_EQ(m_topo->getNbPoints(), 6u); + + m_topo->addPrism(4, 8, 6, 7, 2, 12); + EXPECT_EQ(m_topo->getNbPoints(), 13u); +} + +void MeshTopology_test::testAddPyramid() const +{ + m_topo->addPyramid(0, 1, 2, 3, 4); + EXPECT_EQ(m_topo->getNbPoints(), 5u); + + m_topo->addPyramid(10, 11, 12, 13, 20); + EXPECT_EQ(m_topo->getNbPoints(), 21u); +} + +TEST_F(MeshTopology_test, testEmptyContainer) { ASSERT_TRUE(testEmptyContainer()); } @@ -615,6 +699,45 @@ TEST_F(MeshTopology_test, testEdgeTopology) // ASSERT_TRUE(testVertexTopology()); //} +TEST_F(MeshTopology_test, testAddPoint) +{ + testAddPoint(); +} + +TEST_F(MeshTopology_test, testAddEdge) +{ + testAddEdge(); +} + +TEST_F(MeshTopology_test, testAddTriangle) +{ + testAddTriangle(); +} + +TEST_F(MeshTopology_test, testAddQuad) +{ + testAddQuad(); +} + +TEST_F(MeshTopology_test, testAddTetrahedron) +{ + testAddTetrahedron(); +} + +TEST_F(MeshTopology_test, testAddHexahedron) +{ + testAddHexahedron(); +} + +TEST_F(MeshTopology_test, testAddPrism) +{ + testAddPrism(); +} + +TEST_F(MeshTopology_test, testAddPyramid) +{ + testAddPyramid(); +} // TODO epernod 2018-07-05: test element on Border diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp index bbca664a8ee..cca27efb3a2 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.cpp @@ -355,6 +355,16 @@ void BaseMeshTopology::addHexa(Index, Index, Index, Index, Index, Index, Index, msg_error() << "addHexa() not supported."; } +void BaseMeshTopology::addPrism(Index a, Index b, Index c, Index d, Index e, Index f) +{ + msg_error() << "addPrism() not supported."; +} + +void BaseMeshTopology::addPyramid(Index a, Index b, Index c, Index d, Index e) +{ + msg_error() << "addPyramid() not supported."; +} + void BaseMeshTopology::reOrientateTriangle(TriangleID /*id*/) { msg_error() << "reOrientateTriangle() not supported."; diff --git a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h index 78bedc85b30..7910c16640f 100644 --- a/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h +++ b/Sofa/framework/Core/src/sofa/core/topology/BaseMeshTopology.h @@ -278,6 +278,8 @@ class SOFA_CORE_API BaseMeshTopology : public core::topology::Topology virtual void addQuad( Index a, Index b, Index c, Index d ); virtual void addTetra( Index a, Index b, Index c, Index d ); virtual void addHexa( Index a, Index b, Index c, Index d, Index e, Index f, Index g, Index h ); + virtual void addPrism( Index a, Index b, Index c, Index d, Index e, Index f ); + virtual void addPyramid( Index a, Index b, Index c, Index d, Index e ); /// @} /// get information about connexity of the mesh