From 95d295110c3c07e354ebf7cb5511ca2451e59a4c Mon Sep 17 00:00:00 2001 From: James Smith Date: Tue, 10 Dec 2024 17:18:21 +0000 Subject: [PATCH 1/4] add collapse cost method for edges --- lib/mittsu/mesh_analysis/modifiers/decimator.rb | 2 +- lib/mittsu/mesh_analysis/winged_edge_geometry.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/mittsu/mesh_analysis/modifiers/decimator.rb b/lib/mittsu/mesh_analysis/modifiers/decimator.rb index 803ecda..0e843b6 100644 --- a/lib/mittsu/mesh_analysis/modifiers/decimator.rb +++ b/lib/mittsu/mesh_analysis/modifiers/decimator.rb @@ -18,7 +18,7 @@ def edge_collapse_costs @geometry.edges.map { |e| e ? { edge_index: e.index, - cost: @geometry.edge_length(e.index) + cost: @geometry.collapse_cost(e.index) } : nil }.compact end diff --git a/lib/mittsu/mesh_analysis/winged_edge_geometry.rb b/lib/mittsu/mesh_analysis/winged_edge_geometry.rb index da91f79..6d3f5db 100644 --- a/lib/mittsu/mesh_analysis/winged_edge_geometry.rb +++ b/lib/mittsu/mesh_analysis/winged_edge_geometry.rb @@ -51,8 +51,13 @@ def from_geometry(geometry, merge: true, normalize: true) flatten! end + def collapse_cost(index) + edge_length(index) || 100 + end + def edge_length(index) e0 = edge(index) + return nil if e0.nil? @vertices[e0.start].distance_to(@vertices[e0.finish]) end From 016e8a8bfc1d83f8fa69b8a27c74f7b2c6919187 Mon Sep 17 00:00:00 2001 From: James Smith Date: Tue, 10 Dec 2024 17:18:40 +0000 Subject: [PATCH 2/4] lint: use filter_map instead of map and compact --- lib/mittsu/mesh_analysis/modifiers/decimator.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mittsu/mesh_analysis/modifiers/decimator.rb b/lib/mittsu/mesh_analysis/modifiers/decimator.rb index 0e843b6..3cc7b95 100644 --- a/lib/mittsu/mesh_analysis/modifiers/decimator.rb +++ b/lib/mittsu/mesh_analysis/modifiers/decimator.rb @@ -15,12 +15,12 @@ def decimate(target_face_count) end def edge_collapse_costs - @geometry.edges.map { |e| + @geometry.edges.filter_map { |e| e ? { edge_index: e.index, cost: @geometry.collapse_cost(e.index) } : nil - }.compact + } end def collapse(edge) From 0c9eb027998bba1ed60db763ff9ed3fe7a8d0afb Mon Sep 17 00:00:00 2001 From: James Smith Date: Tue, 10 Dec 2024 17:18:55 +0000 Subject: [PATCH 3/4] flatten geometry before decimation --- lib/mittsu/mesh_analysis/modifiers/decimator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/mittsu/mesh_analysis/modifiers/decimator.rb b/lib/mittsu/mesh_analysis/modifiers/decimator.rb index 3cc7b95..1f2c574 100644 --- a/lib/mittsu/mesh_analysis/modifiers/decimator.rb +++ b/lib/mittsu/mesh_analysis/modifiers/decimator.rb @@ -5,6 +5,7 @@ def initialize(geometry) end def decimate(target_face_count) + @geometry.flatten! edge_collapses = edge_collapse_costs.sort_by { |x| x[:cost] } loop do break if @geometry.faces.count <= target_face_count From 2b6ce422141061cef764967b8aad529285de7b2d Mon Sep 17 00:00:00 2001 From: James Smith Date: Wed, 11 Dec 2024 11:08:14 +0000 Subject: [PATCH 4/4] WIP curvature-based collapse --- lib/mittsu/mesh_analysis/winged_edge_geometry.rb | 13 ++++++++++++- .../mesh_analysis/winged_edge_geometry_spec.rb | 4 ++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/mittsu/mesh_analysis/winged_edge_geometry.rb b/lib/mittsu/mesh_analysis/winged_edge_geometry.rb index 6d3f5db..5bbfd97 100644 --- a/lib/mittsu/mesh_analysis/winged_edge_geometry.rb +++ b/lib/mittsu/mesh_analysis/winged_edge_geometry.rb @@ -52,7 +52,9 @@ def from_geometry(geometry, merge: true, normalize: true) end def collapse_cost(index) - edge_length(index) || 100 + length = edge_length(index) || 100 + curvature = edge_curvature(index) || 100 + length * curvature end def edge_length(index) @@ -61,6 +63,15 @@ def edge_length(index) @vertices[e0.start].distance_to(@vertices[e0.finish]) end + def edge_curvature(index) + e0 = edge(index) + unless e0.nil? + vl = @faces[e0.left]&.normal + vr = @faces[e0.right]&.normal + (1 - vl.normalize.dot(vr.normalize)) / 2 if vl && vr + end + end + def flatten! @faces = @face_indices.map do |face| next if face.nil? diff --git a/spec/lib/mittsu/mesh_analysis/winged_edge_geometry_spec.rb b/spec/lib/mittsu/mesh_analysis/winged_edge_geometry_spec.rb index b89980e..d9a0c43 100644 --- a/spec/lib/mittsu/mesh_analysis/winged_edge_geometry_spec.rb +++ b/spec/lib/mittsu/mesh_analysis/winged_edge_geometry_spec.rb @@ -25,6 +25,10 @@ # These are the joined opposite corner vertices in the PlaneGeometry let(:edge) { geometry.between(1, 2) } + it "calculates curvature" do + expect(geometry.edge_curvature(edge.index)).to eq 0 + end + it "calculates edge lengths" do expect(geometry.edge_length(edge.index)).to be_within(0.1).of(1.414) end