Skip to content

Commit 497d3d4

Browse files
committed
feat(SectionInspector): Added the inspection of a Section topology.
1 parent 2cfbe37 commit 497d3d4

27 files changed

+1950
-4
lines changed

bindings/python/src/inspector/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ add_geode_python_binding(
3232
"manifold/surface_edge_manifold.h"
3333
"manifold/surface_vertex_manifold.h"
3434
"topology/brep_topology.h"
35+
"topology/section_topology.h"
3536
"inspector.cpp"
3637
DEPENDENCIES
3738
${PROJECT_NAME}::inspector

bindings/python/src/inspector/inspector.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "manifold/surface_vertex_manifold.h"
4141

4242
#include "topology/brep_topology.h"
43+
#include "topology/section_topology.h"
4344

4445
PYBIND11_MODULE( opengeode_inspector_py_inspector, module )
4546
{
@@ -55,4 +56,5 @@ PYBIND11_MODULE( opengeode_inspector_py_inspector, module )
5556
geode::define_surface_edge_manifold( module );
5657
geode::define_surface_vertex_manifold( module );
5758
geode::define_brep_topology_inspector( module );
59+
geode::define_section_topology_inspector( module );
5860
}

bindings/python/src/inspector/topology/brep_topology.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
.def( "not_internal_nor_boundary_corner_vertices", \
5656
&BRepTopologyInspector:: \
5757
not_internal_nor_boundary_corner_vertices ) \
58+
.def( "internal_with_multiple_incidences_corner_vertices", \
59+
&BRepTopologyInspector:: \
60+
internal_with_multiple_incidences_corner_vertices ) \
5861
.def( "line_corners_without_boundary_status", \
5962
&BRepTopologyInspector::line_corners_without_boundary_status ) \
6063
.def( "part_of_not_boundary_nor_internal_line_unique_vertices", \
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright (c) 2019 - 2022 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#include <geode/model/representation/core/section.h>
25+
26+
#include <geode/inspector/topology/section_topology.h>
27+
28+
#define PYTHON_SECTION_TOPOLOGY() \
29+
pybind11::class_< SectionTopologyInspector >( \
30+
module, "SectionTopologyInspector" ) \
31+
.def( pybind11::init< const Section& >() ) \
32+
.def( "section_topology_is_valid", \
33+
&SectionTopologyInspector::section_topology_is_valid ) \
34+
.def( "section_meshed_components_are_linked_to_a_unique_vertex", \
35+
&SectionTopologyInspector:: \
36+
section_meshed_components_are_linked_to_a_unique_vertex ) \
37+
.def( "nb_corners_not_linked_to_a_unique_vertex", \
38+
&SectionTopologyInspector:: \
39+
nb_corners_not_linked_to_a_unique_vertex ) \
40+
.def( "nb_lines_meshed_but_not_linked_to_a_unique_vertex", \
41+
&SectionTopologyInspector:: \
42+
nb_lines_meshed_but_not_linked_to_a_unique_vertex ) \
43+
.def( "nb_surfaces_meshed_but_not_linked_to_a_unique_vertex", \
44+
&SectionTopologyInspector:: \
45+
nb_surfaces_meshed_but_not_linked_to_a_unique_vertex ) \
46+
.def( "nb_blocks_meshed_but_not_linked_to_a_unique_vertex", \
47+
&SectionTopologyInspector:: \
48+
nb_blocks_meshed_but_not_linked_to_a_unique_vertex ) \
49+
.def( "invalid_components_topology_unique_vertices", \
50+
&SectionTopologyInspector:: \
51+
invalid_components_topology_unique_vertices ) \
52+
.def( "multiple_corners_unique_vertices", \
53+
&SectionTopologyInspector::multiple_corners_unique_vertices ) \
54+
.def( "multiple_internals_corner_vertices", \
55+
&SectionTopologyInspector::multiple_internals_corner_vertices ) \
56+
.def( "not_internal_nor_boundary_corner_vertices", \
57+
&SectionTopologyInspector:: \
58+
not_internal_nor_boundary_corner_vertices ) \
59+
.def( "internal_with_multiple_incidences_corner_vertices", \
60+
&SectionTopologyInspector:: \
61+
internal_with_multiple_incidences_corner_vertices ) \
62+
.def( "line_corners_without_boundary_status", \
63+
&SectionTopologyInspector::line_corners_without_boundary_status ) \
64+
.def( "part_of_not_boundary_nor_internal_line_unique_vertices", \
65+
&SectionTopologyInspector:: \
66+
part_of_not_boundary_nor_internal_line_unique_vertices ) \
67+
.def( "part_of_line_with_invalid_internal_topology_unique_vertices", \
68+
&SectionTopologyInspector:: \
69+
part_of_line_with_invalid_internal_topology_unique_vertices ) \
70+
.def( "part_of_invalid_unique_line_unique_vertices", \
71+
&SectionTopologyInspector:: \
72+
part_of_invalid_unique_line_unique_vertices ) \
73+
.def( "part_of_lines_but_not_corner_unique_vertices", \
74+
&SectionTopologyInspector:: \
75+
part_of_lines_but_not_corner_unique_vertices ) \
76+
.def( "part_of_invalid_surfaces_unique_vertices", \
77+
&SectionTopologyInspector:: \
78+
part_of_invalid_surfaces_unique_vertices )
79+
80+
namespace geode
81+
{
82+
void define_section_topology_inspector( pybind11::module& module )
83+
{
84+
PYTHON_SECTION_TOPOLOGY();
85+
}
86+
} // namespace geode

bindings/python/tests/test-py-brep-topology.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ def check_not_internal_nor_boundary_corner_vertices( brep_inspector ):
6161
for vertex_index in not_internal_nor_boundary_corner_vertices:
6262
print( "[Test] Model unique vertex with index ", vertex_index, " is neither internal nor a boundary." )
6363

64+
def check_internal_with_multiple_incidences_corner_vertices( brep_inspector ):
65+
internal_with_multiple_incidences_corner_vertices = brep_inspector.internal_with_multiple_incidences_corner_vertices()
66+
print( "There are ", len( internal_with_multiple_incidences_corner_vertices ), " embedded corner vertices with multiple incidences." )
67+
for vertex_index in internal_with_multiple_incidences_corner_vertices:
68+
print( "[Test] Model unique vertex with index ", vertex_index, " is internal but has multiple incidences." )
69+
6470
def check_line_corners_without_boundary_status( brep_inspector ):
6571
line_corners_without_boundary_status = brep_inspector.line_corners_without_boundary_status()
6672
print( "There are ", len( line_corners_without_boundary_status ), " corner vertices part of a line but not its boundary." )
@@ -127,6 +133,7 @@ def launch_topological_validity_checks( brep_inspector ):
127133
check_multiple_corners_unique_vertices( brep_inspector )
128134
check_multiple_internals_corner_vertices( brep_inspector )
129135
check_not_internal_nor_boundary_corner_vertices( brep_inspector )
136+
check_internal_with_multiple_incidences_corner_vertices( brep_inspector )
130137
check_line_corners_without_boundary_status( brep_inspector )
131138
check_part_of_not_boundary_nor_internal_line_unique_vertices( brep_inspector )
132139
check_part_of_invalid_unique_line_unique_vertices( brep_inspector )
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (c) 2019 - 2022 Geode-solutions
3+
#
4+
# Permission is hereby granted, free of charge, to any person obtaining a copy
5+
# of this software and associated documentation files (the "Software"), to deal
6+
# in the Software without restriction, including without limitation the rights
7+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
# copies of the Software, and to permit persons to whom the Software is
9+
# furnished to do so, subject to the following conditions:
10+
#
11+
# The above copyright notice and this permission notice shall be included in
12+
# all copies or substantial portions of the Software.
13+
#
14+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
# SOFTWARE.
21+
22+
import os, sys, platform
23+
if sys.version_info >= (3,8,0) and platform.system() == "Windows":
24+
for path in [x.strip() for x in os.environ['PATH'].split(';') if x]:
25+
os.add_dll_directory(path)
26+
27+
import opengeode
28+
import opengeode_inspector_py_inspector as inspector
29+
30+
def check_components_linking( section_inspector ):
31+
nb_unlinked_corners = section_inspector.nb_corners_not_linked_to_a_unique_vertex()
32+
print( "There are ", nb_unlinked_corners, " corners not linked to a unique vertex." )
33+
nb_unlinked_lines = section_inspector.nb_lines_meshed_but_not_linked_to_a_unique_vertex()
34+
print( "There are ", nb_unlinked_lines, " lines meshed but not linked to a unique vertex." )
35+
nb_unlinked_surfaces = section_inspector.nb_surfaces_meshed_but_not_linked_to_a_unique_vertex()
36+
print( "There are ", nb_unlinked_surfaces, " surfaces meshed but not linked to a unique vertex." )
37+
38+
def check_invalid_components_topology_unique_vertices( section_inspector ):
39+
invalid_components_unique_vertices = section_inspector.invalid_components_topology_unique_vertices()
40+
print( "There are ", len( invalid_components_unique_vertices ), " vertices with invalid components." )
41+
for vertex_index in invalid_components_unique_vertices:
42+
print( "[Test] Model unique vertex with index ", vertex_index, " has invalid components." )
43+
44+
def check_multiple_corners_unique_vertices( section_inspector ):
45+
multiple_corners_unique_vertices = section_inspector.multiple_corners_unique_vertices()
46+
print( "There are ", len( multiple_corners_unique_vertices ), " vertices with multiple corners." )
47+
for vertex_index in multiple_corners_unique_vertices:
48+
print( "[Test] Model unique vertex with index ", vertex_index, " is associated to multiple corners." )
49+
50+
def check_multiple_internals_corner_vertices( section_inspector ):
51+
multiple_internals_corner_vertices = section_inspector.multiple_internals_corner_vertices()
52+
print( "There are ", len( multiple_internals_corner_vertices ), " vertices with multiple internals." )
53+
for vertex_index in multiple_internals_corner_vertices:
54+
print( "[Test] Model unique vertex with index ", vertex_index, " is a corner associated with multiple embeddings." )
55+
56+
def check_not_internal_nor_boundary_corner_vertices( section_inspector ):
57+
not_internal_nor_boundary_corner_vertices = section_inspector.not_internal_nor_boundary_corner_vertices()
58+
print( "There are ", len( not_internal_nor_boundary_corner_vertices ), " corner vertices with no boundary nor internal property." )
59+
for vertex_index in not_internal_nor_boundary_corner_vertices:
60+
print( "[Test] Model unique vertex with index ", vertex_index, " is neither internal nor a boundary." )
61+
62+
def check_internal_with_multiple_incidences_corner_vertices( section_inspector ):
63+
internal_with_multiple_incidences_corner_vertices = section_inspector.internal_with_multiple_incidences_corner_vertices()
64+
print( "There are ", len( internal_with_multiple_incidences_corner_vertices ), " embedded corner vertices with multiple incidences." )
65+
for vertex_index in internal_with_multiple_incidences_corner_vertices:
66+
print( "[Test] Model unique vertex with index ", vertex_index, " is internal but has multiple incidences." )
67+
68+
def check_line_corners_without_boundary_status( section_inspector ):
69+
line_corners_without_boundary_status = section_inspector.line_corners_without_boundary_status()
70+
print( "There are ", len( line_corners_without_boundary_status ), " corner vertices part of a line but not its boundary." )
71+
for vertex_index in line_corners_without_boundary_status:
72+
print( "[Test] Model unique vertex with index ", vertex_index, " is a corner but has a line for which it is not a boundary." )
73+
74+
def check_part_of_not_boundary_nor_internal_line_unique_vertices( section_inspector ):
75+
part_of_not_boundary_nor_internal_line_unique_vertices = section_inspector.part_of_not_boundary_nor_internal_line_unique_vertices()
76+
print( "There are ", len( part_of_not_boundary_nor_internal_line_unique_vertices ), " vertices part of a line which is not boundary not internal." )
77+
for vertex_index in part_of_not_boundary_nor_internal_line_unique_vertices:
78+
print( "[Test] Model unique vertex with index ", vertex_index, " is part of a line which is neither boundary nor internal." )
79+
80+
def check_part_of_line_with_invalid_internal_topology_unique_vertices( section_inspector ):
81+
part_of_line_with_invalid_internal_topology_unique_vertices = section_inspector.part_of_line_with_invalid_internal_topology_unique_vertices()
82+
print( "There are ", len( part_of_line_with_invalid_internal_topology_unique_vertices ), " vertices part of lines with invalid internal property." )
83+
for vertex_index in part_of_line_with_invalid_internal_topology_unique_vertices:
84+
print( "[Test] Model unique vertex with index ", vertex_index, " is part of a line with invalid internal properties." )
85+
86+
def check_part_of_invalid_unique_line_unique_vertices( section_inspector ):
87+
part_of_invalid_unique_line_unique_vertices = section_inspector.part_of_invalid_unique_line_unique_vertices()
88+
print( "There are ", len( part_of_invalid_unique_line_unique_vertices ), " vertices part of a unique line with invalid toplogy." )
89+
for vertex_index in part_of_invalid_unique_line_unique_vertices:
90+
print( "[Test] Model unique vertex with index ", vertex_index, " is part of a unique line with invalid topological properties." )
91+
92+
def check_part_of_lines_but_not_corner_unique_vertices( section_inspector ):
93+
part_of_lines_but_not_corner_unique_vertices = section_inspector.part_of_lines_but_not_corner_unique_vertices()
94+
print( "There are ", len( part_of_lines_but_not_corner_unique_vertices ), " vertices part of multiple lines but not corner." )
95+
for vertex_index in part_of_lines_but_not_corner_unique_vertices:
96+
print( "[Test] Model unique vertex with index ", vertex_index, " is part of multiple lines but is not a corner." )
97+
98+
def check_part_of_invalid_surfaces_unique_vertices( section_inspector ):
99+
part_of_invalid_surfaces_unique_vertices = section_inspector.part_of_invalid_surfaces_unique_vertices()
100+
print( "There are ", len( part_of_invalid_surfaces_unique_vertices ), " vertices with invalid surface topology." )
101+
for vertex_index in part_of_invalid_surfaces_unique_vertices:
102+
print( "[Test] Model unique vertex with index ", vertex_index, " has invalid surfaces topology." )
103+
104+
def launch_topological_validity_checks( section_inspector ):
105+
check_components_linking( section_inspector )
106+
check_invalid_components_topology_unique_vertices( section_inspector )
107+
check_multiple_corners_unique_vertices( section_inspector )
108+
check_multiple_internals_corner_vertices( section_inspector )
109+
check_not_internal_nor_boundary_corner_vertices( section_inspector )
110+
check_internal_with_multiple_incidences_corner_vertices( section_inspector )
111+
check_line_corners_without_boundary_status( section_inspector )
112+
check_part_of_not_boundary_nor_internal_line_unique_vertices( section_inspector )
113+
check_part_of_invalid_unique_line_unique_vertices( section_inspector )
114+
check_part_of_invalid_unique_line_unique_vertices( section_inspector )
115+
check_part_of_lines_but_not_corner_unique_vertices( section_inspector )
116+
check_part_of_invalid_surfaces_unique_vertices( section_inspector )
117+
118+
def check_a1_vertices_topology():
119+
test_dir = os.path.dirname(__file__)
120+
data_dir = os.path.abspath(os.path.join(test_dir, "../../../tests/data"))
121+
model_section = opengeode.load_section( data_dir + "/model_A1.og_section" )
122+
section_inspector = inspector.BRepTopologyInspector( model_section )
123+
if section_inspector.section_topology_is_valid():
124+
print( "model_A1 topology is valid." )
125+
else:
126+
print( "model_A1 topology is invalid." )
127+
launch_topological_validity_checks( section_inspector )
128+
129+
def check_a1_valid_vertices_topology():
130+
test_dir = os.path.dirname(__file__)
131+
data_dir = os.path.abspath(os.path.join(test_dir, "../../../tests/data"))
132+
model_section = opengeode.load_section( data_dir + "/model_A1_valid.og_section" )
133+
section_inspector = inspector.BRepTopologyInspector( model_section )
134+
if section_inspector.section_topology_is_valid():
135+
print( "model_A1_valid topology is valid." )
136+
else:
137+
print( "model_A1_valid topology is invalid." )
138+
launch_topological_validity_checks( section_inspector )
139+
140+
if __name__ == '__main__':
141+
check_a1_vertices_topology()
142+
check_a1_valid_vertices_topology()

include/geode/inspector/topology/brep_topology.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ namespace geode
7171
std::vector< index_t >
7272
not_internal_nor_boundary_corner_vertices() const;
7373

74+
std::vector< index_t >
75+
internal_with_multiple_incidences_corner_vertices() const;
76+
7477
std::vector< index_t > line_corners_without_boundary_status() const;
7578

7679
std::vector< index_t >

include/geode/inspector/topology/private/brep_corners_topology_impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ namespace geode
5959
bool corner_is_not_internal_nor_boundary(
6060
index_t unique_vertex_index ) const;
6161

62+
bool corner_is_internal_with_multiple_incidences(
63+
index_t unique_vertex_index ) const;
64+
6265
bool corner_is_part_of_line_but_not_boundary(
6366
index_t unique_vertex_index ) const;
6467

include/geode/inspector/topology/private/brep_lines_topology_impl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ namespace geode
4747
* Checks if the brep unique vertices are parts of valid lines, i.e.
4848
* verify:
4949
* Each line is either internal or boundary.
50-
* Each internal line is internal to only one object and is not
51-
* boundary.
50+
* If a line is internal to an object, it cannot be incident to it.
5251
* If the vertex is part of only one line, the line is either
5352
* internal to a surface, internal to a block, or a boundary of
5453
* multiple surfaces.

0 commit comments

Comments
 (0)