Skip to content

Commit 5004809

Browse files
committed
fix(Mesh): add helper to convert grid into hybrid solid full of hexahedra
1 parent 42beb16 commit 5004809

File tree

3 files changed

+131
-9
lines changed

3 files changed

+131
-9
lines changed

include/geode/mesh/helpers/convert_solid_mesh.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ namespace geode
5050
[[nodiscard]] std::unique_ptr< TetrahedralSolid3D > opengeode_mesh_api
5151
convert_grid_into_tetrahedral_solid( const Grid3D& grid );
5252

53+
[[nodiscard]] std::unique_ptr< HybridSolid3D >
54+
opengeode_mesh_api convert_grid_into_hybrid_solid( const Grid3D& grid );
55+
5356
[[nodiscard]] std::unique_ptr< TetrahedralSolid3D > opengeode_mesh_api
5457
convert_grid_into_densified_tetrahedral_solid( const Grid3D& grid,
5558
absl::Span< const geode::index_t > cells_to_densify );

src/geode/mesh/helpers/convert_solid_mesh.cpp

Lines changed: 112 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
#include <geode/mesh/builder/hybrid_solid_builder.hpp>
3131
#include <geode/mesh/builder/tetrahedral_solid_builder.hpp>
32+
#include <geode/mesh/core/detail/geode_elements.hpp>
3233
#include <geode/mesh/core/hybrid_solid.hpp>
3334
#include <geode/mesh/core/light_regular_grid.hpp>
3435
#include <geode/mesh/core/regular_grid_solid.hpp>
@@ -39,6 +40,19 @@
3940

4041
namespace
4142
{
43+
std::array< geode::index_t, 8 > grid_cell_vertices(
44+
const geode::Grid3D& grid,
45+
const geode::Grid3D::CellIndices& cell_indices )
46+
{
47+
std::array< geode::index_t, 8 > cell_vertices;
48+
const auto vertex_indices = grid.cell_vertices( cell_indices );
49+
for( const auto v : geode::LIndices{ cell_vertices } )
50+
{
51+
cell_vertices[v] = grid.vertex_index( vertex_indices[v] );
52+
}
53+
return cell_vertices;
54+
}
55+
4256
bool all_polyhedra_are_simplex( const geode::SolidMesh3D& solid )
4357
{
4458
for( const auto p : geode::Range{ solid.nb_polyhedra() } )
@@ -104,6 +118,36 @@ namespace
104118
return tetras;
105119
}
106120

121+
std::array< geode::index_t, 6 > create_pyramid_pattern(
122+
geode::HybridSolidBuilder3D& builder,
123+
const geode::Grid3D& grid,
124+
const geode::Grid3D::CellIndices& cell_indices,
125+
geode::index_t additional_vertex_id )
126+
{
127+
std::array< geode::index_t, 6 > pyramids;
128+
const auto cell_vertices = grid.cell_vertices( cell_indices );
129+
std::array< geode::index_t, 8 > cell_mesh_vertices;
130+
for( const auto v : geode::LIndices{ cell_mesh_vertices } )
131+
{
132+
const auto cell_vertex_id = grid.vertex_index( cell_vertices[v] );
133+
cell_mesh_vertices[v] = cell_vertex_id;
134+
}
135+
for( const auto p : geode::LIndices{ pyramids } )
136+
{
137+
pyramids[p] = builder.create_pyramid(
138+
{ cell_mesh_vertices
139+
[geode::detail::HEXAHEDRON_FACET_VERTICES[p][0]],
140+
cell_mesh_vertices
141+
[geode::detail::HEXAHEDRON_FACET_VERTICES[p][1]],
142+
cell_mesh_vertices
143+
[geode::detail::HEXAHEDRON_FACET_VERTICES[p][2]],
144+
cell_mesh_vertices
145+
[geode::detail::HEXAHEDRON_FACET_VERTICES[p][3]],
146+
additional_vertex_id } );
147+
}
148+
return pyramids;
149+
}
150+
107151
std::array< geode::index_t, 6 > create_tetrahedra_from_pIpI_pattern(
108152
geode::TetrahedralSolidBuilder3D& builder,
109153
const geode::Grid3D& grid,
@@ -191,8 +235,55 @@ namespace
191235
grid.cell_attribute_manager(), old2new_mapping );
192236
}
193237

194-
void create_vertices_from_grid( const geode::TetrahedralSolid3D& tet_solid,
195-
geode::TetrahedralSolidBuilder3D& builder,
238+
void create_hexahedra_from_grid_cells( const geode::HybridSolid3D& solid,
239+
geode::HybridSolidBuilder3D& builder,
240+
const geode::Grid3D& grid,
241+
absl::Span< const geode::index_t > cells_to_densify )
242+
{
243+
std::vector< bool > to_densify( grid.nb_cells(), false );
244+
for( const auto& cell_id : cells_to_densify )
245+
{
246+
to_densify[cell_id] = true;
247+
}
248+
geode::GenericMapping< geode::index_t > old2new_mapping;
249+
for( const auto k : geode::Range{ grid.nb_cells_in_direction( 2 ) } )
250+
{
251+
for( const auto j :
252+
geode::Range{ grid.nb_cells_in_direction( 1 ) } )
253+
{
254+
for( const auto i :
255+
geode::Range{ grid.nb_cells_in_direction( 0 ) } )
256+
{
257+
const auto cell_id = grid.cell_index( { i, j, k } );
258+
if( to_densify[cell_id] )
259+
{
260+
continue;
261+
}
262+
const auto hex_id = builder.create_hexahedron(
263+
grid_cell_vertices( grid, { i, j, k } ) );
264+
old2new_mapping.map( cell_id, hex_id );
265+
}
266+
}
267+
}
268+
for( const auto cell_index : geode::Indices{ cells_to_densify } )
269+
{
270+
const auto cell_indices =
271+
grid.cell_indices( cells_to_densify[cell_index] );
272+
const auto additional_vertex_id =
273+
grid.nb_grid_vertices() + cell_index;
274+
for( const auto tetra_id : create_pyramid_pattern(
275+
builder, grid, cell_indices, additional_vertex_id ) )
276+
{
277+
old2new_mapping.map( cells_to_densify[cell_index], tetra_id );
278+
}
279+
}
280+
builder.compute_polyhedron_adjacencies();
281+
solid.polyhedron_attribute_manager().import(
282+
grid.cell_attribute_manager(), old2new_mapping );
283+
}
284+
285+
void create_vertices_from_grid( const geode::SolidMesh3D& solid,
286+
geode::SolidMeshBuilder3D& builder,
196287
const geode::Grid3D& grid,
197288
absl::Span< const geode::index_t > cells_to_densify )
198289
{
@@ -203,7 +294,7 @@ namespace
203294
builder.set_point( vertex_id,
204295
grid.grid_point( grid.vertex_indices( vertex_id ) ) );
205296
}
206-
auto& solid_attribute_manager = tet_solid.vertex_attribute_manager();
297+
auto& solid_attribute_manager = solid.vertex_attribute_manager();
207298
geode::internal::copy_attributes(
208299
grid.grid_vertex_attribute_manager(), solid_attribute_manager );
209300
geode::index_t counter{ grid.nb_grid_vertices() };
@@ -240,6 +331,18 @@ namespace
240331
return tet_solid;
241332
}
242333

334+
std::unique_ptr< geode::HybridSolid3D > create_hybrid_solid_from_grid(
335+
const geode::Grid3D& grid,
336+
absl::Span< const geode::index_t > cells_to_densify )
337+
{
338+
auto solid = geode::HybridSolid3D::create();
339+
auto builder = geode::HybridSolidBuilder3D::create( *solid );
340+
create_vertices_from_grid( *solid, *builder, grid, cells_to_densify );
341+
create_hexahedra_from_grid_cells(
342+
*solid, *builder, grid, cells_to_densify );
343+
return solid;
344+
}
345+
243346
bool all_polyhedra_are_hybrid( const geode::SolidMesh3D& solid )
244347
{
245348
for( const auto p : geode::Range{ solid.nb_polyhedra() } )
@@ -473,6 +576,12 @@ namespace geode
473576
return create_tetrahedral_solid_from_grid( grid, {} );
474577
}
475578

579+
std::unique_ptr< HybridSolid3D > convert_grid_into_hybrid_solid(
580+
const Grid3D& grid )
581+
{
582+
return create_hybrid_solid_from_grid( grid, {} );
583+
}
584+
476585
std::unique_ptr< TetrahedralSolid3D >
477586
convert_grid_into_densified_tetrahedral_solid( const Grid3D& grid,
478587
absl::Span< const geode::index_t > cells_to_densify )

tests/mesh/test-convert-solid.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
// NOLINTBEGIN(*-magic-numbers)
4444

45-
void test_tetrahedral_solid()
45+
void test_grid_to_solids()
4646
{
4747
geode::OpenGeodeMeshLibrary::initialize();
4848
auto mesh_grid = geode::RegularGrid3D::create();
@@ -53,6 +53,8 @@ void test_tetrahedral_solid()
5353
geode::convert_solid_mesh_into_tetrahedral_solid( *mesh_grid );
5454
const auto tet_solid_from_mesh_grid_2 =
5555
geode::convert_grid_into_tetrahedral_solid( *mesh_grid );
56+
const auto hybrid_solid_from_mesh_grid =
57+
geode::convert_grid_into_hybrid_solid( *mesh_grid );
5658
const geode::LightRegularGrid3D light_grid{
5759
geode::Point3D{ { 1, 1.5, 1.1 } }, { 5, 5, 5 }, { 5, 5, 5 }
5860
};
@@ -72,6 +74,10 @@ void test_tetrahedral_solid()
7274
tet_solid_from_mesh_grid_2->nb_vertices() == nb_vertices,
7375
"[Test] Number of vertices in TetrahedralSolid3D from RegularGrid3D as "
7476
"grid is not correct." );
77+
OPENGEODE_EXCEPTION(
78+
hybrid_solid_from_mesh_grid->nb_vertices() == nb_vertices,
79+
"[Test] Number of vertices in HybridSolid3D from RegularGrid3D as "
80+
"grid is not correct." );
7581
const geode::index_t nb_densified_vertices =
7682
nb_vertices + cells_to_densify.size();
7783
OPENGEODE_EXCEPTION( tet_solid_from_light_grid->nb_vertices()
@@ -88,10 +94,14 @@ void test_tetrahedral_solid()
8894
tet_solid_from_mesh_grid_2->nb_polyhedra() == nb_tetrahedra,
8995
"[Test] Number of tetrahedra in TetrahedralSolid3D from RegularGrid3D "
9096
"as grid is not correct." );
91-
OPENGEODE_EXCEPTION( tet_solid_from_light_grid->nb_polyhedra()
92-
== nb_tetrahedra + 6 * cells_to_densify.size(),
93-
"[Test] Number of tetrahedra in TetrahedralSolid3D from "
94-
"LightRegularGrid is not correct" );
97+
OPENGEODE_EXCEPTION(
98+
tet_solid_from_mesh_grid_2->nb_polyhedra() == nb_tetrahedra,
99+
"[Test] Number of tetrahedra in TetrahedralSolid3D from RegularGrid3D "
100+
"as grid is not correct." );
101+
OPENGEODE_EXCEPTION(
102+
hybrid_solid_from_mesh_grid->nb_polyhedra() == mesh_grid->nb_cells(),
103+
"[Test] Number of hexahedra in HybridSolid3D from "
104+
"RegularGrid is not correct" );
95105
for( const auto polyhedron_id :
96106
geode::Range{ tet_solid_from_light_grid->nb_polyhedra() } )
97107
{
@@ -177,7 +187,7 @@ void test_hybrid_solid()
177187

178188
void test()
179189
{
180-
test_tetrahedral_solid();
190+
test_grid_to_solids();
181191
test_hybrid_solid();
182192
}
183193

0 commit comments

Comments
 (0)