diff --git a/bindings/python/src/inspector/topology/brep_topology.hpp b/bindings/python/src/inspector/topology/brep_topology.hpp index b948671c..bb101c79 100644 --- a/bindings/python/src/inspector/topology/brep_topology.hpp +++ b/bindings/python/src/inspector/topology/brep_topology.hpp @@ -76,6 +76,9 @@ namespace geode "linked_to_a_corner", &BRepLinesTopologyInspectionResult:: unique_vertices_linked_to_several_lines_but_not_linked_to_a_corner ) + .def_readwrite( "line_edges_with_wrong_component_edges_around", + &BRepLinesTopologyInspectionResult:: + line_edges_with_wrong_component_edges_around ) .def( "string", &BRepLinesTopologyInspectionResult::string ) .def( "inspection_type", &BRepLinesTopologyInspectionResult::inspection_type ); @@ -100,6 +103,10 @@ namespace geode "surface_border", &BRepSurfacesTopologyInspectionResult:: unique_vertices_linked_to_a_line_but_is_not_on_a_surface_border ) + .def_readwrite( + "surface_polygons_with_wrong_component_facets_around", + &BRepSurfacesTopologyInspectionResult:: + surface_polygons_with_wrong_component_facets_around ) .def( "string", &BRepSurfacesTopologyInspectionResult::string ) .def( "inspection_type", &BRepSurfacesTopologyInspectionResult::inspection_type ); @@ -109,6 +116,9 @@ namespace geode .def( pybind11::init<>() ) .def_readwrite( "some_blocks_not_meshed", &BRepBlocksTopologyInspectionResult::some_blocks_not_meshed ) + .def_readwrite( "wrong_block_boundary_surface", + &BRepBlocksTopologyInspectionResult:: + wrong_block_boundary_surface ) .def_readwrite( "blocks_not_linked_to_a_unique_vertex", &BRepBlocksTopologyInspectionResult:: blocks_not_linked_to_a_unique_vertex ) diff --git a/bindings/python/tests/test-py-brep.py b/bindings/python/tests/test-py-brep.py index 07909e85..d47d4f3d 100644 --- a/bindings/python/tests/test-py-brep.py +++ b/bindings/python/tests/test-py-brep.py @@ -62,6 +62,7 @@ def lines_topological_validity(result, verbose): nb_issues += ( result.unique_vertices_linked_to_several_lines_but_not_linked_to_a_corner.nb_issues() ) + nb_issues+=result.line_edges_with_wrong_component_edges_around.nb_issues() print("BRep Lines Topology check: ", nb_issues, " issues.") if verbose: print(result.string(), "\n") @@ -79,6 +80,8 @@ def surfaces_topological_validity(result, verbose): nb_issues += ( result.unique_vertices_linked_to_several_and_invalid_surfaces.nb_issues() ) + nb_issues+=result.unique_vertices_linked_to_a_surface_with_invalid_embbedings.nb_issues() + nb_issues +=result.surface_polygons_with_wrong_component_facets_around.nb_issues() print("BRep Surfaces Topology check: ", nb_issues, " issues.") if verbose: print(result.string(), "\n") @@ -90,6 +93,7 @@ def blocks_topological_validity(result, verbose): for issue in result.blocks_not_linked_to_a_unique_vertex.issues_map(): nb_issues += issue[1].nb_issues() nb_issues += result.some_blocks_not_meshed.nb_issues() + nb_issues += result.wrong_block_boundary_surface.nb_issues() nb_issues += ( result.unique_vertices_part_of_two_blocks_and_no_boundary_surface.nb_issues() ) @@ -97,12 +101,12 @@ def blocks_topological_validity(result, verbose): nb_issues += ( result.unique_vertices_linked_to_a_single_and_invalid_surface.nb_issues() ) + nb_issues += result.blocks_with_not_closed_boundary_surfaces.nb_issues() nb_issues += ( result.unique_vertices_linked_to_surface_with_wrong_relationship_to_blocks.nb_issues() ) nb_issues += result.unique_vertex_linked_to_multiple_invalid_surfaces.nb_issues() nb_issues += result.model_boundaries_dont_form_a_closed_surface.nb_issues() - nb_issues += result.blocks_with_not_closed_boundary_surfaces.nb_issues() print("BRep Blocks Topology check: ", nb_issues, " issues.") if verbose: print(result.string(), "\n") @@ -212,9 +216,9 @@ def check_a1(verbose): else: print("model_A1 topology is invalid.") nb_model_issues = launch_topological_validity_checks(result.topology, verbose) - if nb_model_issues != 5165: + if nb_model_issues != 5201: raise ValueError( - "[Test] model model_A1 should have 5615 unique vertices with topological problems." + "[Test] model model_A1 should have 5201 unique vertices with topological problems." ) nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, verbose @@ -232,9 +236,9 @@ def inspect_model_A1(model_brep,verbose): else: print("model_A1_valid topology is invalid.") nb_model_issues = launch_topological_validity_checks(result.topology, verbose) - if nb_model_issues != 5165: + if nb_model_issues != 5201: raise ValueError( - "[Test] model model_A1_valid should have 5165 topological problems." + "[Test] model model_A1_valid should have 5201 topological problems." ) nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, verbose @@ -258,9 +262,9 @@ def inspect_model_mss(model_brep,verbose): else: print("model mss topology is invalid.") nb_model_issues = launch_topological_validity_checks(result.topology, verbose) - if nb_model_issues != 36: + if nb_model_issues != 37: raise ValueError( - "[Test] model mss.og_strm should have 36 topological problems." + "[Test] model mss.og_strm should have 37 topological problems, not " + str(nb_model_issues) ) nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, verbose diff --git a/src/geode/inspector/topology/brep_lines_topology.cpp b/src/geode/inspector/topology/brep_lines_topology.cpp index c8fb86ec..a2aa1b0a 100644 --- a/src/geode/inspector/topology/brep_lines_topology.cpp +++ b/src/geode/inspector/topology/brep_lines_topology.cpp @@ -341,7 +341,7 @@ namespace geode if( surface_edges.size() <= 1 ) { return absl::StrCat( "unique vertex ", unique_vertex_index, - " is part of Line", + " is part of Line ", brep_.line( cmv.component_id.id() ).name(), " (", cmv.component_id.id().string(), "), which should not be embedded in Surface ", diff --git a/src/geode/inspector/topology/internal/expected_nb_cmvs.cpp b/src/geode/inspector/topology/internal/expected_nb_cmvs.cpp index 59d97f25..5747aefd 100644 --- a/src/geode/inspector/topology/internal/expected_nb_cmvs.cpp +++ b/src/geode/inspector/topology/internal/expected_nb_cmvs.cpp @@ -23,6 +23,8 @@ #include +#include + #include #include @@ -114,7 +116,7 @@ namespace .point( unique_vertex_cmvs.block_cmvs[0].vertex ) .string(), - "]", " is part of Block ", + "] is part of Block ", brep.block( block_uuid ).name(), " (", block_uuid.string(), ") and exactly one Corner and one Line but has ", @@ -167,40 +169,108 @@ namespace nb_block_cmvs, " Block mesh vertices (should be ", predicted_nb_block_cmvs, ")." ) ) ); } + // const auto nb_internal_surface_cmvs = count_cmvs( + // unique_vertex_cmvs.surface_cmvs, + // [&block_uuid, &brep]( const auto& cmv ) { + // return brep.is_internal( brep.surface( cmv.component_id.id() + // ), + // brep.block( block_uuid ) ); + // } ); + const auto nb_line_internal_to_internal_surface_cmvs = + count_cmvs( unique_vertex_cmvs.line_cmvs, + [&block_uuid, &brep]( const auto& cmv ) { + const auto& cmv_line = brep.line( cmv.component_id.id() ); + if( brep.nb_embedding_surfaces( cmv_line ) != 1 ) + { + return false; + } + for( const auto& incident_surface : + brep.embedding_surfaces( cmv_line ) ) + { + if( !brep.is_internal( + incident_surface, brep.block( block_uuid ) ) ) + { + return false; + } + } + return true; + } ); + // absl::flat_hash_set< geode::uuid > uuids_used; + /// Lines that are free but incident to the same surface are counted + /// only once const auto nb_free_line_cmvs = count_cmvs( unique_vertex_cmvs.line_cmvs, [&brep]( const auto& cmv ) { - return brep.nb_incidences( cmv.component_id.id() ) == 1 - && brep.nb_embedding_surfaces( - brep.line( cmv.component_id.id() ) ) - == 0; + if( brep.nb_incidences( cmv.component_id.id() ) != 1 ) + { + return false; + } + // for( const auto& incident_surface : + // brep.incidences( brep.line( cmv.component_id.id() ) ) ) + // { + // if( !uuids_used.emplace( incident_surface.id() ).second ) + // { + // return false; + // } + // } + return brep.nb_embedding_surfaces( + brep.line( cmv.component_id.id() ) ) + == 0; } ); - auto predicted_nb_block_cmvs = - nb_internal_surface_cmvs < nb_free_line_cmvs + 1 - ? static_cast< geode::index_t >( 1 ) - : nb_internal_surface_cmvs - nb_free_line_cmvs; - if( nb_internal_surface_cmvs - nb_free_line_cmvs == 1 ) + // uuids_used.clear(); + const auto nb_lines_boundary_to_two_internal_surfaces_cmvs = + count_cmvs( unique_vertex_cmvs.line_cmvs, + [&block_uuid, &brep]( const auto& cmv ) { + if( brep.nb_incidences( cmv.component_id.id() ) != 2 ) + { + return false; + } + for( const auto& incident_surface : + brep.incidences( brep.line( cmv.component_id.id() ) ) ) + { + if( !brep.is_internal( + incident_surface, brep.block( block_uuid ) ) ) + { + return false; + } + } + return true; + } ); + geode::index_t predicted_nb_block_cmvs{ 1 + nb_internal_surface_cmvs }; + const geode::index_t nb_line_cmvs_to_remove{ + nb_line_internal_to_internal_surface_cmvs + nb_free_line_cmvs + + nb_lines_boundary_to_two_internal_surfaces_cmvs + }; + if( predicted_nb_block_cmvs > nb_line_cmvs_to_remove ) { - predicted_nb_block_cmvs++; + predicted_nb_block_cmvs -= nb_line_cmvs_to_remove; } - if( nb_boundary_surface_cmvs > 1 - && unique_vertex_cmvs.corner_cmvs.empty() ) + else { - predicted_nb_block_cmvs += ( nb_boundary_surface_cmvs - 2 ) / 2; + predicted_nb_block_cmvs = 1; } return std::make_pair( predicted_nb_block_cmvs, nb_block_cmvs == predicted_nb_block_cmvs ? std::nullopt : std::make_optional( absl::StrCat( "unique vertex ", - unique_vertex_id, " is part of Block ", - brep.block( block_uuid ).name(), " (", - block_uuid.string(), "), has ", nb_internal_surface_cmvs, - " internal Surface(s) mesh vertices (CMVs), " - "has ", - nb_boundary_surface_cmvs, - " boundary Surface(s) CMVs, and has ", nb_free_line_cmvs, - " free Line(s) CMVs, with ", nb_block_cmvs, - " Block CMVs (should be ", predicted_nb_block_cmvs, - ")." ) ) ); + unique_vertex_id, " at position [", + brep.block( unique_vertex_cmvs.block_cmvs[0] + .component_id.id() ) + .mesh() + .point( unique_vertex_cmvs.block_cmvs[0].vertex ) + .string(), + "] is part of Block ", brep.block( block_uuid ).name(), + " (", block_uuid.string(), "), and has ", + nb_internal_surface_cmvs, + " cmvs of surfaces internal to that block, ", + nb_line_internal_to_internal_surface_cmvs, + " cmvs of lines internal to one surface internal to that " + "block, ", + nb_free_line_cmvs, " cmvs of free lines, and ", + nb_lines_boundary_to_two_internal_surfaces_cmvs, + " cmvs of lines boundary to strictly two internal lines, " + "with ", + nb_block_cmvs, " Block CMVs (should be ", + predicted_nb_block_cmvs, ")." ) ) ); } } // namespace diff --git a/tests/inspector/test-brep.cpp b/tests/inspector/test-brep.cpp index 37c2aa82..3f2fded0 100644 --- a/tests/inspector/test-brep.cpp +++ b/tests/inspector/test-brep.cpp @@ -79,6 +79,8 @@ geode::index_t lines_topological_validity( result .unique_vertices_linked_to_several_lines_but_not_linked_to_a_corner .nb_issues(); + nb_issues += + result.line_edges_with_wrong_component_edges_around.nb_issues(); geode::Logger::info( "BRep Lines Topology check: ", nb_issues, " issues." ); if( string ) { @@ -102,6 +104,11 @@ geode::index_t surfaces_topological_validity( .nb_issues(); nb_issues += result.unique_vertices_linked_to_several_and_invalid_surfaces .nb_issues(); + nb_issues += + result.unique_vertices_linked_to_a_surface_with_invalid_embbedings + .nb_issues(); + nb_issues += + result.surface_polygons_with_wrong_component_facets_around.nb_issues(); geode::Logger::info( "BRep Surfaces Topology check: ", nb_issues, " issues." ); if( string ) @@ -121,6 +128,7 @@ geode::index_t blocks_topological_validity( nb_issues += issue.second.nb_issues(); } nb_issues += result.some_blocks_not_meshed.nb_issues(); + nb_issues += result.wrong_block_boundary_surface.nb_issues(); nb_issues += result.unique_vertices_part_of_two_blocks_and_no_boundary_surface .nb_issues(); @@ -128,6 +136,10 @@ geode::index_t blocks_topological_validity( result.unique_vertices_with_incorrect_block_cmvs_count.nb_issues(); nb_issues += result.unique_vertices_linked_to_a_single_and_invalid_surface .nb_issues(); + nb_issues += result.blocks_with_not_closed_boundary_surfaces.nb_issues(); + nb_issues += result.model_boundaries_dont_form_a_closed_surface.nb_issues(); + nb_issues += + result.unique_vertex_linked_to_multiple_invalid_surfaces.nb_issues(); nb_issues += result .unique_vertices_linked_to_surface_with_wrong_relationship_to_blocks @@ -312,8 +324,8 @@ void check_model_a1( bool string ) const auto nb_topological_issues = launch_topological_validity_checks( result.topology, string ); - OPENGEODE_EXCEPTION( nb_topological_issues == 5164, "[Test] model_A1 has ", - nb_topological_issues, " topological problems instead of 5164." ); + OPENGEODE_EXCEPTION( nb_topological_issues == 5201, "[Test] model_A1 has ", + nb_topological_issues, " topological problems instead of 5201." ); const auto nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, string ); @@ -334,9 +346,9 @@ void check_model_a1_valid( bool string ) const auto nb_topological_issues = launch_topological_validity_checks( result.topology, string ); - OPENGEODE_EXCEPTION( nb_topological_issues == 5164, + OPENGEODE_EXCEPTION( nb_topological_issues == 5201, "[Test] model_A1_valid has ", nb_topological_issues, - " topological problems instead of 5164." ); + " topological problems instead of 5201." ); const auto nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, string ); @@ -357,8 +369,8 @@ void check_model_mss( bool string ) const auto nb_topological_issues = launch_topological_validity_checks( result.topology, string ); - OPENGEODE_EXCEPTION( nb_topological_issues == 34, "[Test] mss has ", - nb_topological_issues, " topological problems instead of 34." ); + OPENGEODE_EXCEPTION( nb_topological_issues == 37, "[Test] mss has ", + nb_topological_issues, " topological problems instead of 37." ); const auto nb_component_meshes_issues = launch_component_meshes_validity_checks( result.meshes, string );