From 44650f9220f2bea1d676ce4e7be2535461196a78 Mon Sep 17 00:00:00 2001 From: Arnaud Botella Date: Wed, 8 Jul 2026 10:25:07 +0200 Subject: [PATCH 1/4] fix(Polygon): better control polygon triangulation orientation --- src/geode/geometry/basic_objects/polygon.cpp | 39 +++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/geode/geometry/basic_objects/polygon.cpp b/src/geode/geometry/basic_objects/polygon.cpp index 91cefabc4..89ecd9651 100644 --- a/src/geode/geometry/basic_objects/polygon.cpp +++ b/src/geode/geometry/basic_objects/polygon.cpp @@ -90,6 +90,43 @@ namespace } return polygons; } + + template < typename PointType > + void reoriente_triangulation( + const geode::GenericPolygon< PointType, 2 >& /*polygon*/, + std::vector< std::array< geode::index_t, 3 > >& /*triangles*/ ) + { + } + + template < typename PointType > + void reoriente_triangulation( + const geode::GenericPolygon< PointType, 3 >& polygon, + std::vector< std::array< geode::index_t, 3 > >& triangles ) + { + const auto normal = + polygon.normal().value_or( geode::Vector3D{ { 0, 0, 1 } } ); + geode::index_t nb_same_orientation{ 0 }; + for( const auto& triangle : triangles ) + { + const auto& p0 = polygon.vertices()[triangle[0]]; + const auto& p1 = polygon.vertices()[triangle[1]]; + const auto& p2 = polygon.vertices()[triangle[2]]; + const auto triangle_normal = + geode::Triangle< 3 >{ p0, p1, p2 }.normal(); + if( triangle_normal && triangle_normal->dot( normal ) > 0 ) + { + nb_same_orientation++; + } + } + if( nb_same_orientation > triangles.size() / 2 ) + { + return; + } + for( auto& triangle : triangles ) + { + std::swap( triangle[1], triangle[2] ); + } + } } // namespace namespace geode @@ -220,7 +257,6 @@ namespace geode std::vector< std::array< index_t, 3 > > GenericPolygon< PointType, dimension >::triangulate() const { - const std::array polygons{ vertices_ }; const auto new_triangles = mapbox::earcut< index_t >( polygon_points( *this ) ); const auto nb_new_triangles = new_triangles.size() / 3; @@ -232,6 +268,7 @@ namespace geode new_triangles[3 * trgl], new_triangles[3 * trgl + 1], new_triangles[3 * trgl + 2] } ); } + reoriente_triangulation( *this, result ); return result; } From bc54721ad87c3453cb29d82ebd0006b7e05e712b Mon Sep 17 00:00:00 2001 From: Arnaud Botella Date: Wed, 8 Jul 2026 10:25:53 +0200 Subject: [PATCH 2/4] fix(ComponentMeshEdge): more safety when two identical UV are given --- src/geode/model/helpers/component_mesh_edges.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/geode/model/helpers/component_mesh_edges.cpp b/src/geode/model/helpers/component_mesh_edges.cpp index 66416cbc0..1dd3a6db5 100644 --- a/src/geode/model/helpers/component_mesh_edges.cpp +++ b/src/geode/model/helpers/component_mesh_edges.cpp @@ -52,6 +52,10 @@ namespace const std::array< geode::index_t, 2 >& edge_unique_vertices, const geode::ComponentType& type ) { + if( edge_unique_vertices[0] == edge_unique_vertices[1] ) + { + return {}; + } return geode::component_mesh_vertex_pairs( model.component_mesh_vertices( edge_unique_vertices[0] ), model.component_mesh_vertices( edge_unique_vertices[1] ), type ); @@ -62,6 +66,10 @@ namespace const std::array< geode::index_t, 2 >& edge_unique_vertices, const geode::ComponentID& component ) { + if( edge_unique_vertices[0] == edge_unique_vertices[1] ) + { + return {}; + } return geode::component_mesh_vertex_pairs( model.component_mesh_vertices( edge_unique_vertices[0] ), model.component_mesh_vertices( edge_unique_vertices[1] ), From b86847fee90acee33c0c6cc94da0ab701c948d1f Mon Sep 17 00:00:00 2001 From: Arnaud Botella Date: Wed, 8 Jul 2026 10:51:16 +0200 Subject: [PATCH 3/4] tidy --- src/geode/geometry/basic_objects/polygon.cpp | 60 +++++++++---------- .../model/helpers/component_mesh_edges.cpp | 5 +- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/geode/geometry/basic_objects/polygon.cpp b/src/geode/geometry/basic_objects/polygon.cpp index 89ecd9651..668d53fd5 100644 --- a/src/geode/geometry/basic_objects/polygon.cpp +++ b/src/geode/geometry/basic_objects/polygon.cpp @@ -39,29 +39,26 @@ #include #include -namespace mapbox +namespace mapbox::util { - namespace util + template < std::size_t coord, geode::index_t dimension > + struct nth< coord, geode::Point< dimension > > { - template < std::size_t coord, geode::index_t dimension > - struct nth< coord, geode::Point< dimension > > + static auto get( const geode::Point< dimension >& point ) { - inline static auto get( const geode::Point< dimension >& point ) - { - return point.value( coord ); - }; + return point.value( coord ); }; + }; - template < std::size_t coord, geode::index_t dimension > - struct nth< coord, geode::RefPoint< dimension > > + template < std::size_t coord, geode::index_t dimension > + struct nth< coord, geode::RefPoint< dimension > > + { + static auto get( const geode::RefPoint< dimension >& point ) { - inline static auto get( const geode::RefPoint< dimension >& point ) - { - return point.get().value( coord ); - }; + return point.get().value( coord ); }; - } // namespace util -} // namespace mapbox + }; +} // namespace mapbox::util namespace { @@ -108,11 +105,12 @@ namespace geode::index_t nb_same_orientation{ 0 }; for( const auto& triangle : triangles ) { - const auto& p0 = polygon.vertices()[triangle[0]]; - const auto& p1 = polygon.vertices()[triangle[1]]; - const auto& p2 = polygon.vertices()[triangle[2]]; + const auto& vertices = polygon.vertices(); + const auto& point0 = vertices[triangle[0]]; + const auto& point1 = vertices[triangle[1]]; + const auto& point2 = vertices[triangle[2]]; const auto triangle_normal = - geode::Triangle< 3 >{ p0, p1, p2 }.normal(); + geode::Triangle< 3 >{ point0, point1, point2 }.normal(); if( triangle_normal && triangle_normal->dot( normal ) > 0 ) { nb_same_orientation++; @@ -174,13 +172,13 @@ namespace geode GenericPolygon< PointType, dimension >::normal() const { Vector3D normal; - const auto& p0 = vertices_[0]; + const auto& point0 = vertices_[0]; for( const auto v : Range{ 2, nb_vertices() } ) { - const auto& p1 = vertices_[v - 1]; - const auto& p2 = vertices_[v]; + const auto& point1 = vertices_[v - 1]; + const auto& point2 = vertices_[v]; if( const auto triangle_normal = - Triangle< T >{ p0, p1, p2 }.normal() ) + Triangle< T >{ point0, point1, point2 }.normal() ) { normal += triangle_normal.value(); } @@ -264,9 +262,9 @@ namespace geode result.reserve( nb_new_triangles ); for( const auto trgl : Range{ nb_new_triangles } ) { - result.emplace_back( std::array< index_t, 3 >{ - new_triangles[3 * trgl], new_triangles[3 * trgl + 1], - new_triangles[3 * trgl + 2] } ); + const auto cur_trgl = 3 * trgl; + result.emplace_back( std::array{ new_triangles[cur_trgl], + new_triangles[cur_trgl + 1], new_triangles[cur_trgl + 2] } ); } reoriente_triangulation( *this, result ); return result; @@ -301,7 +299,7 @@ namespace geode geode::Segment< dimension >{ vertices_[max_length_edge], vertices_[next] } }; - auto opposite_vertex = 0; + index_t opposite_vertex{ 0 }; for( const auto vertex : geode::Range{ nb_vertices } ) { if( vertex == max_length_edge || vertex == next ) @@ -324,12 +322,12 @@ namespace geode std::string GenericPolygon< PointType, dimension >::string() const { std::string result{ "[" }; - auto sep = ""; for( const Point< dimension >& point : vertices_ ) { - absl::StrAppend( &result, sep, point.string() ); - sep = ", "; + absl::StrAppend( &result, sep, point.string() ", " ); } + result.pop_back(); + result.pop_back(); result += "]"; return result; } diff --git a/src/geode/model/helpers/component_mesh_edges.cpp b/src/geode/model/helpers/component_mesh_edges.cpp index 1dd3a6db5..205cc3365 100644 --- a/src/geode/model/helpers/component_mesh_edges.cpp +++ b/src/geode/model/helpers/component_mesh_edges.cpp @@ -307,8 +307,7 @@ namespace geode if( auto edge = mesh.polyhedron_facet_edge_from_vertices( { pair[0], pair[1] } ) ) { - edges[block.id()].emplace_back( - std::move( edge.value() ) ); + edges[block.id()].emplace_back( edge.value() ); } } } @@ -339,7 +338,7 @@ namespace geode if( auto edge = mesh.polyhedron_facet_edge_from_vertices( { pair[0], pair[1] } ) ) { - edges.emplace_back( std::move( edge.value() ) ); + edges.emplace_back( edge.value() ); } } geode::sort_unique( edges ); From b2bdca887e9e04bcfadbcae7e4be18039d7e262a Mon Sep 17 00:00:00 2001 From: Arnaud Botella Date: Wed, 8 Jul 2026 10:51:36 +0200 Subject: [PATCH 4/4] fix --- src/geode/geometry/basic_objects/polygon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/geode/geometry/basic_objects/polygon.cpp b/src/geode/geometry/basic_objects/polygon.cpp index 668d53fd5..125da5b26 100644 --- a/src/geode/geometry/basic_objects/polygon.cpp +++ b/src/geode/geometry/basic_objects/polygon.cpp @@ -324,7 +324,7 @@ namespace geode std::string result{ "[" }; for( const Point< dimension >& point : vertices_ ) { - absl::StrAppend( &result, sep, point.string() ", " ); + absl::StrAppend( &result, point.string(), ", " ); } result.pop_back(); result.pop_back();