1+ /*
2+ * Copyright (c) 2019 - 2025 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/helpers/detail/surface_mesh_validity_fix.hpp>
25+
26+ #include < absl/container/flat_hash_map.h>
27+
28+ #include < geode/basic/uuid.hpp>
29+
30+ #include < geode/geometry/point.hpp>
31+
32+ #include < geode/mesh/core/surface_mesh.hpp>
33+
34+ #include < geode/model/mixin/core/surface.hpp>
35+ #include < geode/model/representation/core/brep.hpp>
36+ #include < geode/model/representation/core/section.hpp>
37+
38+ namespace geode
39+ {
40+ namespace detail
41+ {
42+ template < typename Model >
43+ void repair_non_manifold_vertices (
44+ Model& model, const Surface< Model::dim >& surface )
45+ {
46+ const auto & mesh = surface.mesh ();
47+ typename Model::Builder model_builder{ model };
48+ auto mesh_builder =
49+ model_builder.surface_mesh_builder ( surface.id () );
50+ absl::FixedArray< PolygonsAroundVertex > polygons_around_vertices (
51+ mesh.nb_vertices () );
52+ for ( const auto p : Range{ mesh.nb_polygons () } )
53+ {
54+ for ( const auto v : LRange{ mesh.nb_polygon_vertices ( p ) } )
55+ {
56+ polygons_around_vertices[mesh.polygon_vertex ( { p, v } )]
57+ .emplace_back ( p, v );
58+ }
59+ }
60+ absl::flat_hash_map< index_t , std::vector< index_t > > mappings;
61+ for ( const auto v : Range{ mesh.nb_vertices () } )
62+ {
63+ auto polygons_around = mesh.polygons_around_vertex ( v );
64+ const auto & polygon_vertices = polygons_around_vertices[v];
65+ auto nb_polygons_around = polygons_around.size ();
66+ if ( nb_polygons_around == polygon_vertices.size () )
67+ {
68+ continue ;
69+ }
70+ std::vector< index_t > new_values;
71+ PolygonsAroundVertex total_polygons;
72+ while ( nb_polygons_around != polygon_vertices.size () )
73+ {
74+ for ( auto && polygon : polygons_around )
75+ {
76+ total_polygons.emplace_back ( std::move ( polygon ) );
77+ }
78+ const auto new_vertex_id =
79+ mesh_builder->create_point ( mesh.point ( v ) );
80+ mesh_builder->replace_vertex ( v, new_vertex_id );
81+ for ( const auto & polygon_vertex : polygon_vertices )
82+ {
83+ if ( absl::c_find ( total_polygons, polygon_vertex )
84+ == total_polygons.end () )
85+ {
86+ mesh_builder->associate_polygon_vertex_to_vertex (
87+ polygon_vertex, v );
88+ break ;
89+ }
90+ }
91+ new_values.push_back ( new_vertex_id );
92+ polygons_around = mesh.polygons_around_vertex ( v );
93+ nb_polygons_around += polygons_around.size ();
94+ }
95+ mappings.try_emplace ( v, std::move ( new_values ) );
96+ }
97+ for ( const auto & [old_vertex, new_vertices] : mappings )
98+ {
99+ const auto unique_vertex = model.unique_vertex (
100+ { surface.component_id (), old_vertex } );
101+ for ( const auto new_vertex : new_vertices )
102+ {
103+ model_builder.set_unique_vertex (
104+ { surface.component_id (), new_vertex }, unique_vertex );
105+ }
106+ }
107+ }
108+
109+ template void opengeode_model_api
110+ repair_non_manifold_vertices< Section >(
111+ Section&, const Surface2D& );
112+ template void opengeode_model_api repair_non_manifold_vertices< BRep >(
113+ BRep&, const Surface3D& );
114+ } // namespace detail
115+ } // namespace geode
0 commit comments