Skip to content

Commit 749a021

Browse files
authored
Merge pull request #946 from Geode-solutions/fix-order-vertices-in-solid-mesh-conversion
fix(ConvertSolidMesh): order vertices before converting solid mesh in…
2 parents 8cb77bd + 8ee6cb5 commit 749a021

File tree

3 files changed

+227
-11
lines changed

3 files changed

+227
-11
lines changed

src/geode/mesh/helpers/convert_solid_mesh.cpp

Lines changed: 148 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,148 @@ namespace
161161
}
162162
return true;
163163
}
164+
165+
std::array< geode::index_t, 8 > order_hexahedron_vertices(
166+
const geode::index_t hexahedron_id, const geode::SolidMesh3D& solid )
167+
{
168+
std::array< geode::index_t, 8 > ordered_vertices;
169+
const auto first_polyhedron_facet_vertices =
170+
solid.polyhedron_facet_vertices( { hexahedron_id, 0 } );
171+
ordered_vertices[0] = first_polyhedron_facet_vertices[0];
172+
ordered_vertices[1] = first_polyhedron_facet_vertices[3];
173+
ordered_vertices[2] = first_polyhedron_facet_vertices[2];
174+
ordered_vertices[3] = first_polyhedron_facet_vertices[1];
175+
for( const auto f : geode::LRange( 1, 6 ) )
176+
{
177+
const auto polyhedron_facet_vertices =
178+
solid.polyhedron_facet_vertices( { hexahedron_id, f } );
179+
const auto v_id_0 =
180+
absl::c_find( polyhedron_facet_vertices, ordered_vertices[0] );
181+
if( v_id_0 != polyhedron_facet_vertices.end()
182+
&& absl::c_find(
183+
polyhedron_facet_vertices, ordered_vertices[1] )
184+
!= polyhedron_facet_vertices.end() )
185+
{
186+
const auto index_v_id_0 =
187+
std::distance( polyhedron_facet_vertices.begin(), v_id_0 );
188+
ordered_vertices[4] =
189+
polyhedron_facet_vertices[( index_v_id_0 + 1 ) % 4];
190+
ordered_vertices[5] =
191+
polyhedron_facet_vertices[( index_v_id_0 + 2 ) % 4];
192+
continue;
193+
}
194+
const auto v_id_2 =
195+
absl::c_find( polyhedron_facet_vertices, ordered_vertices[2] );
196+
if( v_id_2 != polyhedron_facet_vertices.end()
197+
&& absl::c_find(
198+
polyhedron_facet_vertices, ordered_vertices[3] )
199+
!= polyhedron_facet_vertices.end() )
200+
{
201+
const auto index_v_id_2 =
202+
std::distance( polyhedron_facet_vertices.begin(), v_id_2 );
203+
ordered_vertices[6] =
204+
polyhedron_facet_vertices[( index_v_id_2 + 1 ) % 4];
205+
ordered_vertices[7] =
206+
polyhedron_facet_vertices[( index_v_id_2 + 2 ) % 4];
207+
continue;
208+
}
209+
}
210+
return ordered_vertices;
211+
}
212+
213+
std::array< geode::index_t, 6 > order_prism_vertices(
214+
const geode::index_t prism_id, const geode::SolidMesh3D& solid )
215+
{
216+
std::array< geode::index_t, 6 > ordered_vertices;
217+
geode::index_t already_used_facet{ 0 };
218+
for( const auto f : geode::LRange{ 5 } )
219+
{
220+
if( solid.nb_polyhedron_facet_vertices( { prism_id, f } ) == 3 )
221+
{
222+
const auto vertices =
223+
solid.polyhedron_facet_vertices( { prism_id, f } );
224+
ordered_vertices[0] = vertices[0];
225+
ordered_vertices[1] = vertices[2];
226+
ordered_vertices[2] = vertices[1];
227+
already_used_facet = f;
228+
break;
229+
}
230+
}
231+
for( const auto f : geode::LRange{ 5 } )
232+
{
233+
if( f == already_used_facet )
234+
{
235+
continue;
236+
}
237+
const auto facet_vertices =
238+
solid.polyhedron_facet_vertices( { prism_id, f } );
239+
const auto v_id =
240+
absl::c_find( facet_vertices, ordered_vertices[0] );
241+
if( v_id == facet_vertices.end()
242+
|| absl::c_find( facet_vertices, ordered_vertices[2] )
243+
== facet_vertices.end() )
244+
{
245+
continue;
246+
}
247+
const auto index_v_id =
248+
std::distance( facet_vertices.begin(), v_id );
249+
ordered_vertices[3] = facet_vertices[( index_v_id + 1 ) % 4];
250+
ordered_vertices[5] = facet_vertices[( index_v_id + 2 ) % 4];
251+
break;
252+
}
253+
for( const auto v : geode::LRange{ 6 } )
254+
{
255+
const auto solid_vertex =
256+
solid.polyhedron_vertex( { prism_id, v } );
257+
if( ordered_vertices[1] == solid_vertex
258+
|| ordered_vertices[2] == solid_vertex
259+
|| ordered_vertices[3] == solid_vertex
260+
|| ordered_vertices[5] == solid_vertex
261+
|| ordered_vertices[0] == solid_vertex )
262+
{
263+
continue;
264+
}
265+
ordered_vertices[4] = solid_vertex;
266+
break;
267+
}
268+
return ordered_vertices;
269+
}
164270
} // namespace
165271

272+
std::array< geode::index_t, 5 > order_pyramid_vertices(
273+
const geode::index_t pyramid_id, const geode::SolidMesh3D& solid )
274+
{
275+
std::array< geode::index_t, 5 > ordered_vertices;
276+
277+
for( const auto f : geode::LRange{ 5 } )
278+
{
279+
if( solid.nb_polyhedron_facet_vertices( { pyramid_id, f } ) == 4 )
280+
{
281+
const auto vertices =
282+
solid.polyhedron_facet_vertices( { pyramid_id, f } );
283+
ordered_vertices[0] = vertices[0];
284+
ordered_vertices[1] = vertices[3];
285+
ordered_vertices[2] = vertices[2];
286+
ordered_vertices[3] = vertices[1];
287+
break;
288+
}
289+
}
290+
for( const auto v : geode::LRange{ 5 } )
291+
{
292+
const auto solid_vertex = solid.polyhedron_vertex( { pyramid_id, v } );
293+
if( ordered_vertices[1] == solid_vertex
294+
|| ordered_vertices[2] == solid_vertex
295+
|| ordered_vertices[3] == solid_vertex
296+
|| ordered_vertices[0] == solid_vertex )
297+
{
298+
continue;
299+
}
300+
ordered_vertices[4] = solid_vertex;
301+
break;
302+
}
303+
return ordered_vertices;
304+
}
305+
166306
namespace geode
167307
{
168308
absl::optional< std::unique_ptr< TetrahedralSolid3D > >
@@ -253,19 +393,20 @@ namespace geode
253393
}
254394
else if( vertices.size() == 8 )
255395
{
256-
builder->create_hexahedron(
257-
{ vertices[0], vertices[1], vertices[2], vertices[3],
258-
vertices[4], vertices[5], vertices[6], vertices[7] } );
396+
const auto ordered_vertices =
397+
order_hexahedron_vertices( p, solid );
398+
builder->create_hexahedron( { ordered_vertices } );
259399
}
260400
else if( vertices.size() == 5 )
261401
{
262-
builder->create_pyramid( { vertices[0], vertices[1],
263-
vertices[2], vertices[3], vertices[4] } );
402+
const auto ordered_vertices =
403+
order_pyramid_vertices( p, solid );
404+
builder->create_pyramid( ordered_vertices );
264405
}
265406
else if( vertices.size() == 6 )
266407
{
267-
builder->create_prism( { vertices[0], vertices[1], vertices[2],
268-
vertices[3], vertices[4], vertices[5] } );
408+
const auto ordered_vertices = order_prism_vertices( p, solid );
409+
builder->create_prism( { ordered_vertices } );
269410
}
270411
}
271412
for( const auto p : Range{ solid.nb_polyhedra() } )

src/geode/mesh/helpers/detail/element_identifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,13 @@ namespace geode
8181
}
8282
const auto facets_vertices =
8383
solid.polyhedron_facets_vertices( polyhedron_id );
84-
if( facets_vertices.size() != 8 )
84+
if( facets_vertices.size() != 5 )
8585
{
8686
return false;
8787
}
8888
for( const auto &facet_vertices : facets_vertices )
8989
{
90-
if( facet_vertices.size() != 3 )
90+
if( facet_vertices.size() != 3 && facet_vertices.size() != 4 )
9191
{
9292
return false;
9393
}

tests/mesh/test-convert-solid.cpp

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,19 @@
3030

3131
#include <geode/mesh/builder/regular_grid_solid_builder.h>
3232
#include <geode/mesh/builder/tetrahedral_solid_builder.h>
33+
#include <geode/mesh/core/hybrid_solid.h>
3334
#include <geode/mesh/core/light_regular_grid.h>
3435
#include <geode/mesh/core/regular_grid_solid.h>
3536
#include <geode/mesh/core/tetrahedral_solid.h>
3637
#include <geode/mesh/helpers/detail/split_along_solid_facets.h>
38+
#include <geode/mesh/io/hybrid_solid_output.h>
3739
#include <geode/mesh/io/tetrahedral_solid_output.h>
3840

3941
#include <geode/mesh/helpers/convert_solid_mesh.h>
4042

41-
void test()
43+
// NOLINTBEGIN(*-magic-numbers)
44+
45+
void test_tetrahedral_solid()
4246
{
4347
geode::OpenGeodeMeshLibrary::initialize();
4448
auto mesh_grid = geode::RegularGrid3D::create();
@@ -86,4 +90,75 @@ void test()
8690
splitter.split_solid_along_facets( {} );
8791
}
8892

89-
OPENGEODE_TEST( "convert-solid" )
93+
void test_hybrid_solid()
94+
{
95+
geode::OpenGeodeMeshLibrary::initialize();
96+
std::vector< geode::Point3D > hex_points{
97+
{ { 0, 0, 0 } },
98+
{ { 1, 0, 0 } },
99+
{ { 0, 1, 0 } },
100+
{ { 1, 1, 0 } },
101+
{ { 0, 0, 1 } },
102+
{ { 1, 0, 1 } },
103+
{ { 0, 1, 1 } },
104+
{ { 1, 1, 1 } },
105+
};
106+
auto hex = geode::SolidMesh3D::create();
107+
auto builder_hex = geode::SolidMeshBuilder3D::create( *hex );
108+
for( const auto& point : hex_points )
109+
{
110+
builder_hex->create_point( point );
111+
}
112+
builder_hex->create_polyhedron( { 0, 1, 2, 3, 4, 5, 6, 7 },
113+
{ { 0, 2, 3, 1 }, { 0, 4, 5, 1 }, { 3, 1, 5, 7 }, { 4, 6, 7, 5 },
114+
{ 2, 3, 7, 6 }, { 0, 2, 6, 4 } } );
115+
auto hybrid_solid_hex = geode::convert_solid_mesh_into_hybrid_solid( *hex );
116+
geode::save_hybrid_solid(
117+
*hybrid_solid_hex.value(), "hybrid_solid_hex.og_hso3d" );
118+
std::vector< geode::Point3D > prism_points{
119+
{ { 0, 0, 0 } },
120+
{ { 1, 0, 0 } },
121+
{ { 0, 1, 0 } },
122+
{ { 0, 0, 1 } },
123+
{ { 1, 0, 1 } },
124+
{ { 0, 1, 1 } },
125+
};
126+
auto prism = geode::SolidMesh3D::create();
127+
auto builder_prism = geode::SolidMeshBuilder3D::create( *prism );
128+
for( const auto& point : prism_points )
129+
{
130+
builder_prism->create_point( point );
131+
}
132+
builder_prism->create_polyhedron(
133+
{ 0, 1, 2, 3, 4, 5 }, { { 0, 2, 1 }, { 3, 5, 4 }, { 0, 3, 4, 1 },
134+
{ 0, 3, 5, 2 }, { 1, 4, 5, 2 } } );
135+
auto hybrid_solid_prism =
136+
geode::convert_solid_mesh_into_hybrid_solid( *prism );
137+
geode::save_hybrid_solid(
138+
*hybrid_solid_prism.value(), "hybrid_solid_prism.og_hso3d" );
139+
std::vector< geode::Point3D > pyramid_points{ { { 0, 0, 0 } },
140+
{ { 1, 0, 0 } }, { { 1, 1, 0 } }, { { 0, 1, 0 } },
141+
{ { 0.5, 0.5, 1 } } };
142+
auto pyramid = geode::SolidMesh3D::create();
143+
auto builder_pyramid = geode::SolidMeshBuilder3D::create( *pyramid );
144+
for( const auto& point : pyramid_points )
145+
{
146+
builder_pyramid->create_point( point );
147+
}
148+
builder_pyramid->create_polyhedron(
149+
{ 0, 1, 2, 3, 4 }, { { 0, 4, 1 }, { 0, 4, 3 }, { 1, 4, 2 }, { 4, 3, 2 },
150+
{ 0, 3, 2, 1 } } );
151+
auto hybrid_solid_pyramid =
152+
geode::convert_solid_mesh_into_hybrid_solid( *pyramid );
153+
geode::save_hybrid_solid(
154+
*hybrid_solid_pyramid.value(), "hybrid_solid_pyramid.og_hso3d" );
155+
}
156+
157+
void test()
158+
{
159+
test_tetrahedral_solid();
160+
test_hybrid_solid();
161+
}
162+
163+
OPENGEODE_TEST( "convert-solid" )
164+
// NOLINTEND(*-magic-numbers)

0 commit comments

Comments
 (0)