Skip to content

Commit 087e0ac

Browse files
EulalieCoevoetalxbilgerhugtalbotfredroybakpaul
authored
[Engine.Generate] Cleaning volume engines (#5595)
* [Engine.Generate] new components to compute volume from meshes * [helper] ComponentChange: remove const for external plugins * Update Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTetrahedrons.cpp Co-authored-by: Alex Bilger <[email protected]> * Update Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTriangles.cpp Co-authored-by: Alex Bilger <[email protected]> * [Engine] VolumeFrom: updates header * [CMake] Add SoftRobots.CUDA to the presets (#5492) * [CMake] Add SofaDistanceGrid.CUDA to the presets (#5493) * [CMake] Add BeamAdapter.CUDA to the presets (#5491) Co-authored-by: Hugo <[email protected]> * [Visual] VisualStyle: Set flags at init() (#5530) set flags at init() Co-authored-by: Hugo <[email protected]> * [CMake] Add SofaSphFluid.CUDA to the presets (#5494) Co-authored-by: Paul Baksic <[email protected]> Co-authored-by: Hugo <[email protected]> * [Elastic] Generalize the use of Tetrahedron::volume (#5532) * [Elastic] Generalize the use of Tetrahedron::volume * add constexpr qualifier for Vec3r1 ctor * fix unit test * typo --------- Co-authored-by: Frederick Roy <[email protected]> Co-authored-by: Frederick Roy <[email protected]> * [FEM.Elastic] Use triangle area function (#5555) * [Visual] Add a new component drawing an AABB (#5527) * add new component drawing a AABB * Update Sofa/Component/Visual/src/sofa/component/visual/VisualBoundingBox.cpp (not necessary to add draw state) Co-authored-by: Alex Bilger <[email protected]> * set template method pattern function private --------- Co-authored-by: Alex Bilger <[email protected]> * [Lagrangian.Model] BilateralLagrangianConstraint: enforce disabled state in getConstraintResolution (#5564) enforce disabled state in getConstraintResolution * [GitHub] Add dependabot for monthly update of github-actions (#5552) * [Engine.Generate] Cleaning volume components * Update Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTetrahedrons.inl Co-authored-by: Hugo <[email protected]> * Update Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTriangles.inl Co-authored-by: Hugo <[email protected]> * using links for topology and mechanical * cleaning --------- Co-authored-by: Alex Bilger <[email protected]> Co-authored-by: Hugo <[email protected]> Co-authored-by: Frederick Roy <[email protected]> Co-authored-by: Paul Baksic <[email protected]> Co-authored-by: Frederick Roy <[email protected]>
1 parent fb9d676 commit 087e0ac

File tree

6 files changed

+121
-97
lines changed

6 files changed

+121
-97
lines changed

Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTetrahedrons.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class VolumeFromTetrahedrons : public sofa::core::DataEngine
6060
////////////////////////// Inherited from BaseObject ///////////////////
6161
void init() override;
6262
void reinit() override;
63+
void parse(core::objectmodel::BaseObjectDescription* arg) override;
6364
////////////////////////////////////////////////////////////////////////
6465

6566
////////////////////////// Inherited from DataEngine////////////////////
@@ -70,8 +71,8 @@ class VolumeFromTetrahedrons : public sofa::core::DataEngine
7071

7172
protected:
7273

73-
MechanicalState* m_state;
74-
BaseMeshTopology* m_topology;
74+
SingleLink<VolumeFromTetrahedrons<DataTypes>, BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;
75+
SingleLink<VolumeFromTetrahedrons<DataTypes>, MechanicalState, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_state;
7576

7677
sofa::Data<VecCoord> d_positions;
7778
sofa::Data<VecTetras> d_tetras;
@@ -86,9 +87,6 @@ class VolumeFromTetrahedrons : public sofa::core::DataEngine
8687

8788
void initTopology();
8889
void checkTopology();
89-
90-
SReal getElementVolume(const Tetra& tetra);
91-
SReal getElementVolume(const Hexa& hexa);
9290
};
9391

9492
#if !defined(SOFA_COMPONENT_ENGINE_VOLUMEFROMTETRAHEDRONS_CPP)

Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTetrahedrons.inl

Lines changed: 54 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
#include <sofa/config.h>
2525
#include <sofa/component/engine/generate/VolumeFromTetrahedrons.h>
26+
#include <sofa/geometry/Hexahedron.h>
27+
#include <sofa/geometry/Tetrahedron.h>
2628

2729
namespace sofa::component::engine::generate
2830
{
@@ -36,15 +38,29 @@ using sofa::core::objectmodel::BaseData;
3638

3739
template <class DataTypes>
3840
VolumeFromTetrahedrons<DataTypes>::VolumeFromTetrahedrons()
39-
: d_positions(initData(&d_positions,"positions","If not set by user, find the context mechanical."))
41+
:
42+
l_topology(initLink("topology", "link to the topology"))
43+
, l_state(initLink("mechanical", "link to the mechanical"))
44+
, d_positions(initData(&d_positions,"position","If not set by user, find the context mechanical."))
4045
, d_tetras(initData(&d_tetras,"tetras","If not set by user, find the context topology."))
4146
, d_hexas(initData(&d_hexas,"hexas","If not set by user, find the context topology."))
42-
, d_volume(initData(&d_volume,Real(0.0),"volume",""))
47+
, d_volume(initData(&d_volume,Real(0.0),"volume","The computed volume."))
4348
, d_doUpdate(initData(&d_doUpdate,false,"update","If true, will update the volume at each time step of the simulation."))
4449
{
4550
d_volume.setReadOnly(true);
4651
}
4752

53+
template <class DataTypes>
54+
void VolumeFromTetrahedrons<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
55+
{
56+
Inherit1::parse(arg);
57+
58+
// SOFA_ATTRIBUTE_DISABLED("v25.06", "v26.06", "data positions renamed as position")
59+
// to be backward compatible with previous data structure
60+
const char* positionsChar = arg->getAttribute("positions");
61+
if( positionsChar )
62+
msg_deprecated() << "You are using a deprecated Data 'positions', please use 'position' instead.";
63+
}
4864

4965
template <class DataTypes>
5066
VolumeFromTetrahedrons<DataTypes>::~VolumeFromTetrahedrons()
@@ -55,6 +71,8 @@ VolumeFromTetrahedrons<DataTypes>::~VolumeFromTetrahedrons()
5571
template <class DataTypes>
5672
void VolumeFromTetrahedrons<DataTypes>::init()
5773
{
74+
Inherit1::init();
75+
5876
d_componentState.setValue(ComponentState::Valid);
5977

6078
addInput(&d_positions);
@@ -65,16 +83,20 @@ void VolumeFromTetrahedrons<DataTypes>::init()
6583

6684
if(!d_positions.isSet())
6785
{
68-
m_state = dynamic_cast<MechanicalState*>(getContext()->getMechanicalState());
86+
if(!l_state.get())
87+
{
88+
msg_info() << "Link to the mechanical state should be set to ensure right behavior. First mechanical state found in current context will be used.";
89+
l_state.set(dynamic_cast<MechanicalState*>(this->getContext()->getMechanicalState()));
90+
}
6991

70-
if(m_state == nullptr)
92+
if(!l_state.get())
7193
{
7294
msg_error() << "No positions given by the user and no mechanical state found in the context. The component cannot work.";
7395
d_componentState.setValue(ComponentState::Invalid);
7496
return;
7597
}
7698

77-
d_positions.setParent(m_state->findData("position")); // Links d_positions to m_state.position
99+
d_positions.setParent(l_state.get()->findData("position")); // Links d_positions to m_state.position
78100
}
79101

80102
initTopology();
@@ -96,20 +118,29 @@ void VolumeFromTetrahedrons<DataTypes>::reinit()
96118

97119
template <class DataTypes>
98120
void VolumeFromTetrahedrons<DataTypes>::initTopology()
99-
{
100-
m_topology = getContext()->getMeshTopology();
101-
102-
if(!d_tetras.isSet() && m_topology)
103-
d_tetras.setValue(m_topology->getTetras());
121+
{
122+
if (!l_topology.get())
123+
{
124+
msg_info() << "Link to Topology container should be set to ensure right behavior. First Topology found in current context will be used.";
125+
l_topology.set(this->getContext()->getMeshTopologyLink());
126+
}
104127

105-
if(!d_hexas.isSet() && m_topology)
106-
d_hexas.setValue(m_topology->getHexas());
128+
const auto& topology = l_topology.get();
129+
const bool hasTetras = d_tetras.isSet();
130+
const bool hasHexas = d_hexas.isSet();
107131

108-
if(!d_hexas.isSet() && !d_tetras.isSet() && !m_topology)
132+
if(!hasTetras && !hasHexas && !topology)
109133
{
110-
msg_error() << "No tetras or hexas given by the user and no topology context. The component cannot work.";
134+
msg_error() << "No tetras or hexas given by the user and no topology context. The component cannot work";
111135
d_componentState.setValue(ComponentState::Invalid);
136+
return;
112137
}
138+
139+
if(!hasTetras && topology)
140+
d_tetras.setValue(topology->getTetras());
141+
142+
if(!hasHexas && topology)
143+
d_hexas.setValue(topology->getHexas());
113144
}
114145

115146

@@ -168,9 +199,10 @@ void VolumeFromTetrahedrons<DataTypes>::doUpdate()
168199
if(d_componentState.getValue() != ComponentState::Valid)
169200
return ;
170201

171-
if(m_state && d_doUpdate.getValue())
202+
const auto& state = l_state.get();
203+
if(state && d_doUpdate.getValue())
172204
{
173-
ReadAccessor<sofa::Data<VecCoord> > positions = m_state->readPositions();
205+
ReadAccessor<sofa::Data<VecCoord> > positions = state->readPositions();
174206
d_positions.setValue(positions.ref());
175207
updateVolume();
176208
}
@@ -184,71 +216,18 @@ void VolumeFromTetrahedrons<DataTypes>::updateVolume()
184216

185217
ReadAccessor<sofa::Data<VecTetras>> tetras = d_tetras;
186218
ReadAccessor<sofa::Data<VecHexas>> hexas = d_hexas;
219+
ReadAccessor<sofa::Data<VecCoord> > positions = d_positions;
187220

188-
for (unsigned int t=0; t<tetras.size(); t++)
189-
volume += getElementVolume(tetras[t]);
221+
for (const auto& t: tetras)
222+
volume += sofa::geometry::Tetrahedron::volume(positions[t[0]], positions[t[1]], positions[t[2]], positions[t[3]]);
190223

191-
for (unsigned int t=0; t<hexas.size(); t++)
192-
volume += getElementVolume(hexas[t]);
224+
for (const auto& h: hexas)
225+
volume += sofa::geometry::Hexahedron::volume(positions[h[0]], positions[h[1]], positions[h[2]], positions[h[3]],
226+
positions[h[4]], positions[h[5]], positions[h[6]], positions[h[7]]);
193227

194228
if(volume<0) volume = -volume;
195229
d_volume.setValue(volume);
196230
}
197231

198232

199-
template <class DataTypes>
200-
SReal VolumeFromTetrahedrons<DataTypes>::getElementVolume(const Tetra& tetra)
201-
{
202-
ReadAccessor<sofa::Data<VecCoord> > positions = d_positions;
203-
204-
Coord p0 = positions[tetra[0]];
205-
Coord p1 = positions[tetra[1]];
206-
Coord p2 = positions[tetra[2]];
207-
Coord p3 = positions[tetra[3]];
208-
209-
Real volume = (p0-p1)*cross(p3-p1,p2-p1)/6.;
210-
211-
return volume;
212-
}
213-
214-
215-
template <class DataTypes>
216-
SReal VolumeFromTetrahedrons<DataTypes>::getElementVolume(const Hexa& hexa)
217-
{
218-
ReadAccessor<sofa::Data<VecCoord> > positions = d_positions;
219-
220-
Real volume = 0.;
221-
Coord p0, p1, p2, p3;
222-
223-
p0 = positions[hexa[6]];
224-
p1 = positions[hexa[1]];
225-
p2 = positions[hexa[2]];
226-
p3 = positions[hexa[3]];
227-
228-
volume += (p0-p1)*cross(p3-p1,p2-p1)/6.;
229-
230-
p0 = positions[hexa[4]];
231-
p1 = positions[hexa[0]];
232-
p2 = positions[hexa[1]];
233-
p3 = positions[hexa[3]];
234-
235-
volume += (p0-p1)*cross(p3-p1,p2-p1)/6.;
236-
237-
p0 = positions[hexa[5]];
238-
p1 = positions[hexa[4]];
239-
p2 = positions[hexa[6]];
240-
p3 = positions[hexa[1]];
241-
242-
volume += (p0-p1)*cross(p3-p1,p2-p1)/6.;
243-
244-
p0 = positions[hexa[7]];
245-
p1 = positions[hexa[4]];
246-
p2 = positions[hexa[6]];
247-
p3 = positions[hexa[3]];
248-
249-
volume += (p0-p1)*cross(p3-p1,p2-p1)/6.;
250-
251-
return volume;
252-
}
253-
254233
} // namespace

Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTriangles.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class VolumeFromTriangles : public sofa::core::DataEngine
6363
////////////////////////// Inherited from BaseObject ///////////////////
6464
void init() override;
6565
void reinit() override;
66+
void parse(core::objectmodel::BaseObjectDescription* arg) override;
67+
6668
////////////////////////////////////////////////////////////////////////
6769

6870
////////////////////////// Inherited from DataEngine////////////////////
@@ -73,8 +75,8 @@ class VolumeFromTriangles : public sofa::core::DataEngine
7375

7476
protected:
7577

76-
MechanicalState* m_state;
77-
BaseMeshTopology* m_topology;
78+
SingleLink<VolumeFromTriangles<DataTypes>, BaseMeshTopology, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_topology;
79+
SingleLink<VolumeFromTriangles<DataTypes>, MechanicalState, BaseLink::FLAG_STOREPATH | BaseLink::FLAG_STRONGLINK> l_state;
7880

7981
sofa::Data<VecCoord> d_positions;
8082
sofa::Data<VecTriangles> d_triangles;

Sofa/Component/Engine/Generate/src/sofa/component/engine/generate/VolumeFromTriangles.inl

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ using sofa::core::objectmodel::BaseData ;
3636

3737
template <class DataTypes>
3838
VolumeFromTriangles<DataTypes>::VolumeFromTriangles()
39-
: d_positions(initData(&d_positions,"positions","If not set by user, find the context mechanical."))
39+
:
40+
l_topology(initLink("topology", "link to the topology"))
41+
, l_state(initLink("mechanical", "link to the mechanical"))
42+
, d_positions(initData(&d_positions,"position","If not set by user, find the context mechanical."))
4043
, d_triangles(initData(&d_triangles,"triangles","If not set by user, find the context topology."))
4144
, d_quads(initData(&d_quads,"quads","If not set by user, find the context topology."))
4245
, d_volume(initData(&d_volume,Real(0.0),"volume","The volume is only relevant if the surface is closed."))
@@ -51,10 +54,23 @@ VolumeFromTriangles<DataTypes>::~VolumeFromTriangles()
5154
{
5255
}
5356

57+
template <class DataTypes>
58+
void VolumeFromTriangles<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
59+
{
60+
Inherit1::parse(arg);
61+
62+
// SOFA_ATTRIBUTE_DISABLED("v25.06", "v26.06", "data positions renamed as position")
63+
// to be backward compatible with previous data structure
64+
const char* positionsChar = arg->getAttribute("positions");
65+
if( positionsChar )
66+
msg_deprecated() << "You are using a deprecated Data 'positions', please use 'position' instead.";
67+
}
5468

5569
template <class DataTypes>
5670
void VolumeFromTriangles<DataTypes>::init()
5771
{
72+
Inherit1::init();
73+
5874
d_componentState.setValue(ComponentState::Valid);
5975

6076
addInput(&d_positions);
@@ -65,16 +81,20 @@ void VolumeFromTriangles<DataTypes>::init()
6581

6682
if(!d_positions.isSet())
6783
{
68-
m_state = dynamic_cast<MechanicalState*>(getContext()->getMechanicalState());
84+
if(!l_state.get())
85+
{
86+
msg_info() << "Link to the mechanical state should be set to ensure right behavior. First mechanical state found in current context will be used.";
87+
l_state.set(dynamic_cast<MechanicalState*>(this->getContext()->getMechanicalState()));
88+
}
6989

70-
if(m_state == nullptr)
90+
if(!l_state.get())
7191
{
7292
msg_error() << "No positions given by the user and no mechanical state found in the context. The component cannot work.";
7393
d_componentState.setValue(ComponentState::Invalid);
7494
return;
7595
}
7696

77-
d_positions.setParent(m_state->findData("position")); // Links d_positions to m_state.position
97+
d_positions.setParent(l_state.get()->findData("position")); // Links d_positions to m_state.position
7898
}
7999

80100
initTopology();
@@ -96,19 +116,29 @@ void VolumeFromTriangles<DataTypes>::reinit()
96116
template <class DataTypes>
97117
void VolumeFromTriangles<DataTypes>::initTopology()
98118
{
99-
m_topology = getContext()->getMeshTopology();
100-
101-
if(!d_triangles.isSet() && m_topology)
102-
d_triangles.setValue(m_topology->getTriangles());
119+
if (!l_topology.get())
120+
{
121+
msg_info() << "Link to Topology container should be set to ensure right behavior. First Topology found in current context will be used.";
122+
l_topology.set(this->getContext()->getMeshTopologyLink());
123+
}
103124

104-
if(!d_quads.isSet() && m_topology)
105-
d_quads.setValue(m_topology->getQuads());
125+
const auto& topology = l_topology.get();
126+
const bool hasTriangles = d_triangles.isSet();
127+
const bool hasQuads = d_quads.isSet();
106128

107-
if(!d_quads.isSet() && !d_triangles.isSet() && !m_topology)
129+
if(!hasQuads && !hasTriangles && !topology)
108130
{
109131
msg_error() << "No quads or triangles given by the user and no topology context. The component cannot work";
110132
d_componentState.setValue(ComponentState::Invalid);
133+
return;
111134
}
135+
136+
if(!hasTriangles && topology)
137+
d_triangles.setValue(topology->getTriangles());
138+
139+
if(!hasQuads && topology)
140+
d_quads.setValue(topology->getQuads());
141+
112142
}
113143

114144

@@ -160,9 +190,10 @@ void VolumeFromTriangles<DataTypes>::doUpdate()
160190
if(d_componentState.getValue() != ComponentState::Valid)
161191
return ;
162192

163-
if(m_state && d_doUpdate.getValue())
193+
const auto& state = l_state.get();
194+
if(state && d_doUpdate.getValue())
164195
{
165-
ReadAccessor<sofa::Data<VecCoord> > positions = m_state->readPositions();
196+
ReadAccessor<sofa::Data<VecCoord> > positions = state->readPositions();
166197
d_positions.setValue(positions.ref());
167198
updateVolume();
168199
}

examples/Component/Engine/Generate/VolumeFromTetrahedrons.scn

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@
33
<RequiredPlugin name="Sofa.Component.Engine.Generate"/> <!-- Needed to use components [VolumeFromTetrahedrons] -->
44
<RequiredPlugin name="Sofa.Component.IO.Mesh"/> <!-- Needed to use components [MeshVTKLoader] -->
55
<RequiredPlugin name="Sofa.Component.Setting"/> <!-- Needed to use components [BackgroundSetting] -->
6+
<RequiredPlugin name="Sofa.Component.StateContainer"/> <!-- Needed to use components [MechanicalObject] -->
7+
<RequiredPlugin name="Sofa.Component.Topology.Container.Constant"/> <!-- Needed to use components [MeshTopology] -->
8+
<RequiredPlugin name="Sofa.GL.Component.Rendering3D"/> <!-- Needed to use components [OglModel] -->
9+
610

711
<DefaultAnimationLoop/>
812
<BackgroundSetting color="1 1 1" />
913
<Node name="Volume" >
1014
<MeshVTKLoader name="mesh" filename="mesh/Bunny.vtk"/>
11-
<MeshTopology src="@mesh" name="topology" drawTetrahedra="1"/>
15+
<MeshTopology src="@mesh" name="topology"/>
1216
<MechanicalObject />
1317
<VolumeFromTetrahedrons/>
18+
<Node name="Visual" >
19+
<OglModel src="@../topology" color="0.5 0.5 0.5 0.1"/>
20+
</Node>
1421
</Node>
1522
</Node>

0 commit comments

Comments
 (0)