Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/mittsu/mesh_analysis/modifiers/decimator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -15,12 +16,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.edge_length(e.index)
cost: @geometry.collapse_cost(e.index)
} : nil
}.compact
}
end

def collapse(edge)
Expand Down
16 changes: 16 additions & 0 deletions lib/mittsu/mesh_analysis/winged_edge_geometry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,27 @@ def from_geometry(geometry, merge: true, normalize: true)
flatten!
end

def collapse_cost(index)
length = edge_length(index) || 100
curvature = edge_curvature(index) || 100
length * curvature
end

def edge_length(index)
e0 = edge(index)
return nil if e0.nil?
@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?
Expand Down
4 changes: 4 additions & 0 deletions spec/lib/mittsu/mesh_analysis/winged_edge_geometry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading