Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(MeshMerger): better handle degenerated cases #996

Merged
merged 2 commits into from
Jul 31, 2024
Merged
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: 1 addition & 1 deletion bindings/python/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
# pip-compile bindings/python/requirements.in
# pip-compile --pre bindings/python/requirements.in
#
3 changes: 2 additions & 1 deletion include/geode/mesh/helpers/repair_polygon_orientations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ namespace geode
namespace geode
{
template < index_t dimension >
void repair_polygon_orientations( SurfaceMesh< dimension >& mesh );
void OPENGEODE_MESH_DEPRECATED repair_polygon_orientations(
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
SurfaceMesh< dimension >& mesh );

template < index_t dimension >
void repair_polygon_orientations( const SurfaceMesh< dimension >& mesh,
Expand Down
147 changes: 97 additions & 50 deletions src/geode/mesh/helpers/detail/solid_merger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,30 @@
#include <geode/mesh/core/detail/vertex_cycle.hpp>
#include <geode/mesh/core/solid_mesh.hpp>

namespace
{
bool is_polyhedron_degenerated(
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
absl::Span< const geode::index_t > vertices )
{
for( const auto v : geode::LIndices{ vertices } )
{
const auto vertex = vertices[v];
for( const auto other_v : geode::LIndices{ vertices } )
{
if( v == other_v )
{
continue;
}
if( vertex == vertices[other_v] )
{
return true;
}
}
}
return false;
}
} // namespace

namespace geode
{
namespace detail
Expand Down Expand Up @@ -96,40 +120,6 @@ namespace geode
private:
void clean_solid( SolidMeshMerger< dimension >& merger )
{
bool delete_needed{ false };
std::vector< bool > to_delete(
merger.mesh().nb_polyhedra(), false );
for( const auto p : Range{ merger.mesh().nb_polyhedra() } )
{
const auto vertices =
merger.mesh().polyhedron_vertices( p );
for( const auto v : LIndices{ vertices } )
{
if( vertices[v]
== vertices[v == vertices.size() - 1 ? 0 : v + 1] )
{
to_delete[p] = true;
delete_needed = true;
}
}
}
if( delete_needed )
{
const auto old2new =
merger.builder().delete_polyhedra( to_delete );
delete_vector_elements( to_delete, polyhedra_origins_ );
delete_vector_elements( to_delete, solid_id_ );
const auto& meshes = merger.meshes();
for( const auto solid_id : Indices{ merger.meshes() } )
{
const auto& solid = meshes[solid_id].get();
for( const auto p : Range{ solid.nb_polyhedra() } )
{
const auto old = new_id_[solid_id][p];
new_id_[solid_id][p] = old2new[old];
}
}
}
separate_solids( merger );
}

Expand All @@ -149,6 +139,10 @@ namespace geode
vertices[v] = merger.vertex_in_merged(
s, solid.polyhedron_vertex( { p, v } ) );
}
if( is_polyhedron_degenerated( vertices ) )
{
continue;
}
const auto it =
polyhedra.try_emplace( TypedVertexCycle{ vertices },
merger.mesh().nb_polyhedra() );
Expand Down Expand Up @@ -209,33 +203,86 @@ namespace geode

void create_adjacencies( SolidMeshMerger< dimension >& merger )
{
absl::FixedArray< bool > visited_polyhedra(
merger.mesh().nb_polyhedra(), false );
const auto& meshes = merger.meshes();
for( const auto s : Indices{ merger.meshes() } )
merger.builder().compute_polyhedron_adjacencies();
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
for( const auto p : Range{ merger.mesh().nb_polyhedra() } )
{
const auto& solid = meshes[s].get();
for( const auto p : Range{ solid.nb_polyhedra() } )
for( const auto f :
LRange{ merger.mesh().nb_polyhedron_facets( p ) } )
{
const auto new_id = new_id_[s][p];
if( visited_polyhedra[new_id] )
const PolyhedronFacet facet{ p, f };
const auto adj =
merger.mesh().polyhedron_adjacent_facet( facet );
if( !adj )
{
continue;
}
visited_polyhedra[new_id] = true;
for( const auto f :
LRange{ solid.nb_polyhedron_facets( p ) } )
const auto facet_vertices =
merger.mesh().polyhedron_facet_vertices( facet );
bool keep_adj{ false };
for( const auto& origin : polyhedra_origins_[p] )
{
if( const auto adj =
solid.polyhedron_adjacent( { p, f } ) )
const auto facet_origin = find_facet_origin(
merger, facet_vertices, origin, f );
const auto& solid =
merger.meshes()[origin.solid].get();
if( !solid.is_polyhedron_facet_on_border(
facet_origin ) )
{
const auto new_adj_id = new_id_[s][adj.value()];
merger.builder().set_polyhedron_adjacent(
{ new_id, f }, new_adj_id );
keep_adj = true;
break;
}
}
if( !keep_adj )
{
merger.builder().unset_polyhedron_adjacent( facet );
merger.builder().unset_polyhedron_adjacent(
adj.value() );
}
}
}
}

PolyhedronFacet find_facet_origin(
SolidMeshMerger< dimension >& merger,
const PolyhedronFacetVertices& merged_facet_vertices,
BotellaA marked this conversation as resolved.
Show resolved Hide resolved
const PolyhedronOrigin& origin,
local_index_t hint ) const
{
using Facet = VertexCycle< PolyhedronFacetVertices >;
const Facet merged_cycle{ merged_facet_vertices };
const auto& solid = merger.meshes()[origin.solid].get();
const auto is_same_facet = [&merger, &merged_cycle, &solid,
&origin]( const auto& facet ) {
PolyhedronFacetVertices updated_vertices;
for( const auto vertex :
solid.polyhedron_facet_vertices( facet ) )
{
updated_vertices.push_back(
merger.vertex_in_merged( origin.solid, vertex ) );
}
return Facet{ updated_vertices } == merged_cycle;
};
const PolyhedronFacet hint_facet{ origin.polyhedron, hint };
if( is_same_facet( hint_facet ) )
{
return hint_facet;
}
for( const auto& f :
LRange{ solid.nb_polyhedron_facets( origin.polyhedron ) } )
{
if( f == hint )
{
continue;
}
const PolyhedronFacet facet{ origin.polyhedron, f };
if( is_same_facet( facet ) )
{
return facet;
}
}
OPENGEODE_ASSERT_NOT_REACHED(
"[SolidMerger::find_facet_origin] Facet not found" );
return hint_facet;
}

void separate_solids( SolidMeshMerger< dimension >& merger )
Expand Down
Loading
Loading