Skip to content

Commit 6529da7

Browse files
BotellaAMelchiorSchuh
authored andcommitted
feat(Brep): check model non manifold edges
1 parent 5deb9ae commit 6529da7

File tree

4 files changed

+82
-2
lines changed

4 files changed

+82
-2
lines changed

bindings/python/src/inspector/manifold/brep_meshes_manifold.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
component_meshes_non_manifold_edges ) \
5050
.def( "component_meshes_non_manifold_facets", \
5151
&BRepComponentMeshesManifold:: \
52-
component_meshes_non_manifold_facets )
52+
component_meshes_non_manifold_facets ) \
53+
.def( "model_non_manifold_edges", \
54+
&BRepComponentMeshesManifold::model_non_manifold_edges )
5355

5456
namespace geode
5557
{

include/geode/inspector/criterion/manifold/brep_meshes_manifold.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ namespace geode
7474
absl::flat_hash_map< uuid, std::vector< PolyhedronFacetVertices > >
7575
component_meshes_non_manifold_facets() const;
7676

77+
absl::flat_hash_map< std::array< index_t, 2 >, std::vector< uuid > >
78+
model_non_manifold_edges() const;
79+
7780
private:
7881
IMPLEMENTATION_MEMBER( impl_ );
7982
};

src/bin/geode-inspector-brep.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ void inspect_brep( const geode::BRep& brep )
6363
{
6464
const auto verbose = absl::GetFlag( FLAGS_verbose );
6565
const geode::BRepInspector brep_inspector{ brep, verbose };
66-
absl::InlinedVector< async::task< void >, 28 > tasks;
66+
absl::InlinedVector< async::task< void >, 29 > tasks;
6767
if( absl::GetFlag( FLAGS_component_linking ) )
6868
{
6969
tasks.emplace_back( async::spawn( [&brep_inspector] {
@@ -287,6 +287,11 @@ void inspect_brep( const geode::BRep& brep )
287287
geode::Logger::info(
288288
nb, " components with non manifold facets in their mesh." );
289289
} ) );
290+
tasks.emplace_back( async::spawn( [&brep_inspector] {
291+
const auto nb = brep_inspector.model_non_manifold_edges().size();
292+
geode::Logger::info(
293+
nb, " components with non manifold model edges." );
294+
} ) );
290295
}
291296
async::when_all( tasks.begin(), tasks.end() ).wait();
292297
}

src/geode/inspector/criterion/manifold/brep_meshes_manifold.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@
2323

2424
#include <geode/inspector/criterion/manifold/brep_meshes_manifold.h>
2525

26+
#include <geode/basic/algorithm.h>
2627
#include <geode/basic/logger.h>
2728
#include <geode/basic/pimpl_impl.h>
2829

30+
#include <geode/mesh/core/detail/vertex_cycle.h>
2931
#include <geode/mesh/core/solid_mesh.h>
32+
#include <geode/mesh/core/surface_mesh.h>
3033

3134
#include <geode/model/mixin/core/block.h>
35+
#include <geode/model/mixin/core/surface.h>
3236
#include <geode/model/representation/core/brep.h>
3337

3438
#include <geode/inspector/criterion/manifold/solid_edge_manifold.h>
@@ -74,6 +78,18 @@ namespace geode
7478
non_manifold_components.push_back( block.id() );
7579
}
7680
}
81+
const auto& model_edges = model_non_manifold_edges();
82+
if( !model_edges.empty() )
83+
{
84+
for( const auto& model_edge : model_edges )
85+
{
86+
for( const auto& component_id : model_edge.second )
87+
{
88+
non_manifold_components.push_back( component_id );
89+
}
90+
}
91+
}
92+
sort_unique( non_manifold_components );
7793
return non_manifold_components;
7894
}
7995

@@ -193,6 +209,54 @@ namespace geode
193209
}
194210
return components_non_manifold_facets;
195211
}
212+
213+
absl::flat_hash_map< std::array< index_t, 2 >, std::vector< uuid > >
214+
model_non_manifold_edges() const
215+
{
216+
using Edge = detail::VertexCycle< std::array< index_t, 2 > >;
217+
absl::flat_hash_map< Edge, std::vector< uuid > > edges;
218+
for( const auto& surface : model().surfaces() )
219+
{
220+
const auto& mesh = surface.mesh();
221+
for( const auto p : Range{ mesh.nb_polygons() } )
222+
{
223+
const auto vertices = mesh.polygon_vertices( p );
224+
for( const auto e : LIndices{ vertices } )
225+
{
226+
const auto adj = mesh.polygon_adjacent( { p, e } );
227+
if( !adj || adj.value() < p )
228+
{
229+
continue;
230+
}
231+
const auto v0 = model().unique_vertex(
232+
{ surface.component_id(), vertices[e] } );
233+
const auto v1 =
234+
model().unique_vertex( { surface.component_id(),
235+
vertices[e == vertices.size() - 1 ? 0
236+
: e + 1] } );
237+
const auto info = edges.try_emplace(
238+
std::array< index_t, 2 >{ v0, v1 },
239+
std::vector< uuid >{ surface.id() } );
240+
if( !info.second )
241+
{
242+
info.first->second.push_back( surface.id() );
243+
}
244+
}
245+
}
246+
}
247+
absl::flat_hash_map< std::array< index_t, 2 >, std::vector< uuid > >
248+
result;
249+
for( auto& edge : edges )
250+
{
251+
sort_unique( edge.second );
252+
if( edge.second.size() > 1 )
253+
{
254+
result.emplace( std::move( edge.first.vertices() ),
255+
std::move( edge.second ) );
256+
}
257+
}
258+
return result;
259+
}
196260
};
197261

198262
BRepComponentMeshesManifold::BRepComponentMeshesManifold(
@@ -255,4 +319,10 @@ namespace geode
255319
{
256320
return impl_->component_meshes_non_manifold_facets();
257321
}
322+
323+
absl::flat_hash_map< std::array< index_t, 2 >, std::vector< uuid > >
324+
BRepComponentMeshesManifold::model_non_manifold_edges() const
325+
{
326+
return impl_->model_non_manifold_edges();
327+
}
258328
} // namespace geode

0 commit comments

Comments
 (0)