Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sofa/Component/Topology/Mapping/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(HEADER_FILES
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/init.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/CenterPointTopologicalMapping.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Edge2QuadTopologicalMapping.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2PrismTopologicalMapping.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2QuadTopologicalMapping.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2TetraTopologicalMapping.h
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/IdentityTopologicalMapping.h
Expand All @@ -21,6 +22,7 @@ set(SOURCE_FILES
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/init.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/CenterPointTopologicalMapping.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Edge2QuadTopologicalMapping.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2PrismTopologicalMapping.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2QuadTopologicalMapping.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/Hexa2TetraTopologicalMapping.cpp
${SOFACOMPONENTTOPOLOGYMAPPING_SOURCE_DIR}/IdentityTopologicalMapping.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/******************************************************************************
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt) *
* *
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#include <sofa/component/topology/mapping/Hexa2PrismTopologicalMapping.h>
#include <sofa/core/ObjectFactory.h>

namespace sofa::component::topology::mapping
{

void registerHexa2PrismTopologicalMapping(sofa::core::ObjectFactory* factory)
{
factory->registerObjects(core::ObjectRegistrationData("Topological mapping where HexahedronSetTopology is converted to PrismSetTopology")
.add< Hexa2PrismTopologicalMapping >());
}

Hexa2PrismTopologicalMapping::Hexa2PrismTopologicalMapping()
{
m_inputType = geometry::ElementType::HEXAHEDRON;
m_outputType = geometry::ElementType::PRISM;
}

void Hexa2PrismTopologicalMapping::init()
{
Inherit1::init();

if (toModel == nullptr)
{
msg_error() << "No target topology container found.";
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
return;
}

convertHexaToPrisms();
}

void Hexa2PrismTopologicalMapping::convertHexaToPrisms()
{
// Clear output topology
toModel->clear();

// Set the same number of points
toModel->setNbPoints(fromModel->getNbPoints());

auto Loc2GlobVec = sofa::helper::getWriteOnlyAccessor(Loc2GlobDataVec);
Loc2GlobVec.clear();
Glob2LocMap.clear();

const sofa::Size nbCubes = fromModel->getNbHexahedra();

static constexpr std::size_t numberPrismsInHexa = 2;
Loc2GlobVec.reserve(nbCubes * numberPrismsInHexa);

// Tessellation of each cube into 2 triangular prisms
// Hexahedron vertices:
// Y n3---------n2
// ^ / /|
// | / / |
// n7---------n6 |
// | | |
// | n0------|--n1
// | / | /
// |/ |/
// n4---------n5-->X
// /
// /
// Z
//
// Decomposition into 2 prisms:
// - Prism 1: vertices [0, 5, 1] (bottom triangle) and [3, 6, 2] (top triangle)
// - Prism 2: vertices [0, 4, 5] (bottom triangle) and [3, 7, 6] (top triangle)

for (size_t i = 0; i < nbCubes; ++i)
{
core::topology::BaseMeshTopology::Hexa c = fromModel->getHexahedron(i);

// Standard decomposition ensuring face consistency between neighbors
toModel->addPrism(c[0], c[5], c[1], c[3], c[6], c[2]); // Prism 1
toModel->addPrism(c[0], c[4], c[5], c[3], c[7], c[6]); // Prism 2

for (unsigned j = 0; j < numberPrismsInHexa; ++j)
{
Loc2GlobVec.push_back(i);
}
Glob2LocMap[i] = static_cast<unsigned int>(Loc2GlobVec.size()) - 1;
}

// Need to fully init the target topology
toModel->init();

this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Valid);
}

Index Hexa2PrismTopologicalMapping::getFromIndex(Index /*ind*/)
{
return sofa::InvalidID;
}

void Hexa2PrismTopologicalMapping::updateTopologicalMappingTopDown()
{
msg_warning() << "Method Hexa2PrismTopologicalMapping::updateTopologicalMappingTopDown() not yet implemented!";
// TODO...
}

} // namespace sofa::component::topology::mapping
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/******************************************************************************
* 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 <http://www.gnu.org/licenses/>. *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt) *
* *
* Contact information: contact@sofa-framework.org *
******************************************************************************/
#pragma once

#include <sofa/core/topology/TopologicalMapping.h>
#include <sofa/component/topology/mapping/config.h>

namespace sofa::component::topology::mapping
{

class SOFA_COMPONENT_TOPOLOGY_MAPPING_API Hexa2PrismTopologicalMapping : public sofa::core::topology::TopologicalMapping
{
public:
SOFA_CLASS(Hexa2PrismTopologicalMapping, sofa::core::topology::TopologicalMapping);

virtual void init() override;
virtual Index getFromIndex(Index ind) override;
virtual void updateTopologicalMappingTopDown() override;

protected:
Hexa2PrismTopologicalMapping();

void convertHexaToPrisms();
};

} // namespace sofa::component::topology::mapping
Original file line number Diff line number Diff line change
Expand Up @@ -68,34 +68,17 @@ void Hexa2TetraTopologicalMapping::init()

Inherit1::init();

if (!this->checkTopologyInputTypes()) // method will display error message if false
if (toModel == nullptr)
{
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
return;
}

TetrahedronSetTopologyModifier* to_tstm { nullptr };
toModel->getContext()->get(to_tstm);
if (!to_tstm)
{
msg_error() << "No TetrahedronSetTopologyModifier found in the Tetrahedron topology Node.";
msg_error() << "No target topology container found.";
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
return;
}

// INITIALISATION of TETRAHEDRAL mesh from HEXAHEDRAL mesh :

TetrahedronSetTopologyContainer *to_tstc { nullptr };
toModel->getContext()->get(to_tstc);
if (!to_tstc)
{
msg_error() << "No TetrahedronSetTopologyContainer found in the Tetrahedron topology Node.";
this->d_componentState.setValue(sofa::core::objectmodel::ComponentState::Invalid);
return;
}

// Clear output topology
to_tstc->clear();
toModel->clear();

// Set the same number of points
toModel->setNbPoints(fromModel->getNbPoints());
Expand Down Expand Up @@ -165,21 +148,21 @@ void Hexa2TetraTopologicalMapping::init()

if(!swapped)
{
to_tstc->addTetra(c[0],c[5],c[1],c[6]);
to_tstc->addTetra(c[0],c[1],c[3],c[6]);
to_tstc->addTetra(c[1],c[3],c[6],c[2]);
to_tstc->addTetra(c[6],c[3],c[0],c[7]);
to_tstc->addTetra(c[6],c[7],c[0],c[5]);
to_tstc->addTetra(c[7],c[5],c[4],c[0]);
toModel->addTetra(c[0],c[5],c[1],c[6]);
toModel->addTetra(c[0],c[1],c[3],c[6]);
toModel->addTetra(c[1],c[3],c[6],c[2]);
toModel->addTetra(c[6],c[3],c[0],c[7]);
toModel->addTetra(c[6],c[7],c[0],c[5]);
toModel->addTetra(c[7],c[5],c[4],c[0]);
}
else
{
to_tstc->addTetra(c[0],c[5],c[6],c[1]);
to_tstc->addTetra(c[0],c[1],c[6],c[3]);
to_tstc->addTetra(c[1],c[3],c[2],c[6]);
to_tstc->addTetra(c[6],c[3],c[7],c[0]);
to_tstc->addTetra(c[6],c[7],c[5],c[0]);
to_tstc->addTetra(c[7],c[5],c[0],c[4]);
toModel->addTetra(c[0],c[5],c[6],c[1]);
toModel->addTetra(c[0],c[1],c[6],c[3]);
toModel->addTetra(c[1],c[3],c[2],c[6]);
toModel->addTetra(c[6],c[3],c[7],c[0]);
toModel->addTetra(c[6],c[7],c[5],c[0]);
toModel->addTetra(c[7],c[5],c[0],c[4]);
}
for (int j = 0; j < numberTetraInHexa; j++)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace sofa::component::topology::mapping

extern void registerCenterPointTopologicalMapping(sofa::core::ObjectFactory* factory);
extern void registerEdge2QuadTopologicalMapping(sofa::core::ObjectFactory* factory);
extern void registerHexa2PrismTopologicalMapping(sofa::core::ObjectFactory* factory);
extern void registerHexa2QuadTopologicalMapping(sofa::core::ObjectFactory* factory);
extern void registerHexa2TetraTopologicalMapping(sofa::core::ObjectFactory* factory);
extern void registerIdentityTopologicalMapping(sofa::core::ObjectFactory* factory);
Expand Down Expand Up @@ -62,6 +63,7 @@ void registerObjects(sofa::core::ObjectFactory* factory)
{
registerCenterPointTopologicalMapping(factory);
registerEdge2QuadTopologicalMapping(factory);
registerHexa2PrismTopologicalMapping(factory);
registerHexa2QuadTopologicalMapping(factory);
registerHexa2TetraTopologicalMapping(factory);
registerIdentityTopologicalMapping(factory);
Expand Down
88 changes: 86 additions & 2 deletions Sofa/framework/Core/src/sofa/core/visual/DrawMesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,87 @@ struct SOFA_CORE_API DrawElementMesh<sofa::geometry::Tetrahedron>
}
};

template<>
struct SOFA_CORE_API DrawElementMesh<sofa::geometry::Prism>
: public BaseDrawMesh<DrawElementMesh<sofa::geometry::Prism>, 5>
{
using ElementType = sofa::geometry::Prism;
friend BaseDrawMesh;
static constexpr std::size_t NumberTrianglesInPrism = 2;
static constexpr std::size_t NumberQuadsInPrism = 3;

static constexpr ColorContainer defaultColors {
sofa::type::RGBAColor::green(),
sofa::type::RGBAColor::teal(),
sofa::type::RGBAColor::navy(),
sofa::type::RGBAColor::gold(),
sofa::type::RGBAColor::purple()
};

private:
template<class PositionContainer, class IndicesContainer>
void doDraw(
sofa::helper::visual::DrawTool* drawTool,
const PositionContainer& position,
sofa::core::topology::BaseMeshTopology* topology,
const IndicesContainer& elementIndices,
const ColorContainer& colors)
{
if (!topology)
return;

const auto& elements = topology->getPrisms();

// Allocate space for rendering points
renderedPoints[0].resize(elementIndices.size() * sofa::geometry::Triangle::NumberOfNodes);
renderedPoints[1].resize(elementIndices.size() * sofa::geometry::Triangle::NumberOfNodes);
renderedPoints[2].resize(elementIndices.size() * sofa::geometry::Quad::NumberOfNodes);
renderedPoints[3].resize(elementIndices.size() * sofa::geometry::Quad::NumberOfNodes);
renderedPoints[4].resize(elementIndices.size() * sofa::geometry::Quad::NumberOfNodes);

std::array<std::size_t, NumberColors> renderedPointId {};

for (auto i : elementIndices)
{
const auto& prism = elements[i];
const auto center = this->elementCenter(position, prism);

const auto drawTriangle = [&](sofa::Index bufferId, sofa::Index v0, sofa::Index v1, sofa::Index v2)
{
const std::array vertexIndices { prism[v0], prism[v1], prism[v2] };
for (std::size_t k = 0; k < sofa::geometry::Triangle::NumberOfNodes; ++k)
{
const auto p = this->applyElementSpace(position[vertexIndices[k]], center);
renderedPoints[bufferId][renderedPointId[bufferId]++] = sofa::type::toVec3(p);
}
};

drawTriangle(0, 0, 1, 2);
drawTriangle(1, 5, 4, 3);

const auto drawQuad = [&](sofa::Index bufferId, sofa::Index v0, sofa::Index v1, sofa::Index v2, sofa::Index v3)
{
const std::array vertexIndices { prism[v0], prism[v1], prism[v2], prism[v3] };
for (std::size_t k = 0; k < sofa::geometry::Quad::NumberOfNodes; ++k)
{
const auto p = this->applyElementSpace(position[vertexIndices[k]], center);
renderedPoints[bufferId][renderedPointId[bufferId]++] = sofa::type::toVec3(p);
}
};

drawQuad(2, 0, 2, 5, 3);
drawQuad(3, 0, 3, 4, 1);
drawQuad(4, 1, 4, 5, 2);
}

drawTool->drawTriangles(renderedPoints[0], colors[0]);
drawTool->drawTriangles(renderedPoints[1], colors[1]);
drawTool->drawQuads(renderedPoints[2], colors[2]);
drawTool->drawQuads(renderedPoints[3], colors[3]);
drawTool->drawQuads(renderedPoints[4], colors[4]);
}
};

template<>
struct SOFA_CORE_API DrawElementMesh<sofa::geometry::Hexahedron>
: public BaseDrawMesh<DrawElementMesh<sofa::geometry::Hexahedron>, 6>
Expand Down Expand Up @@ -460,6 +541,7 @@ class SOFA_CORE_API DrawMesh
{
drawElements<sofa::geometry::Tetrahedron>(drawTool, position, topology);
drawElements<sofa::geometry::Hexahedron>(drawTool, position, topology);
drawElements<sofa::geometry::Prism>(drawTool, position, topology);
}

template<class PositionContainer>
Expand All @@ -477,8 +559,9 @@ class SOFA_CORE_API DrawMesh

const auto hasTetra = !topology->getTetrahedra().empty();
const auto hasHexa = !topology->getHexahedra().empty();
const auto hasPrism = !topology->getPrisms().empty();

const bool hasVolumeElements = hasTetra || hasHexa;
const bool hasVolumeElements = hasTetra || hasHexa || hasPrism;

if (!hasSurfaceElements && !hasVolumeElements)
{
Expand All @@ -503,7 +586,8 @@ class SOFA_CORE_API DrawMesh
DrawElementMesh<sofa::geometry::Triangle>,
DrawElementMesh<sofa::geometry::Quad>,
DrawElementMesh<sofa::geometry::Tetrahedron>,
DrawElementMesh<sofa::geometry::Hexahedron>
DrawElementMesh<sofa::geometry::Hexahedron>,
DrawElementMesh<sofa::geometry::Prism>
> m_meshes;
};

Expand Down
Loading
Loading