60 lines
1.7 KiB
Ruby
60 lines
1.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
class GeometryTest < Minitest::Test
|
|
def setup
|
|
@data = MoonModel::DataSet.new
|
|
end
|
|
|
|
def test_solid_one_piece_is_a_closed_outer_volume_without_inner_surface
|
|
solid = structure("solid")
|
|
hollow = structure("hollow")
|
|
|
|
assert solid.valid?
|
|
assert_manifold solid
|
|
assert_equal hollow.triangles.length / 2, solid.triangles.length
|
|
assert_equal hollow.vertices.length / 2, solid.vertices.length
|
|
end
|
|
|
|
def test_solid_single_color_grid_remains_manifold
|
|
config = config_for("solid", "grid" => { "enabled" => true, "depth_mm" => 0.4 })
|
|
mesh = MoonModel::Geometry.build(config, @data).parts.first[:meshes].first
|
|
|
|
assert mesh.valid?
|
|
assert_manifold mesh
|
|
end
|
|
|
|
def test_segmented_output_is_hollow_even_when_solid_is_requested
|
|
config = config_for("solid", "purpose" => "box", "assembly" => "eight_piece")
|
|
result = MoonModel::Geometry.build(config, @data)
|
|
|
|
assert result.segmented?
|
|
assert_equal "hollow", result.statistics["interior"]
|
|
end
|
|
|
|
private
|
|
|
|
def structure(interior)
|
|
MoonModel::Geometry.build(config_for(interior), @data).parts.first[:meshes].first
|
|
end
|
|
|
|
def config_for(interior, extra = {})
|
|
MoonModel::Config.new({
|
|
"size" => { "value" => 40 },
|
|
"shell" => { "interior" => interior },
|
|
"resolution" => { "longitude_segments" => 24 }
|
|
}.merge(extra))
|
|
end
|
|
|
|
def assert_manifold(mesh)
|
|
edge_uses = Hash.new(0)
|
|
mesh.triangles.each do |triangle|
|
|
triangle.each_index do |index|
|
|
edge_uses[[triangle[index], triangle[(index + 1) % 3]].sort] += 1
|
|
end
|
|
end
|
|
assert edge_uses.values.all? { |count| count == 2 }, "every edge must belong to exactly two faces"
|
|
end
|
|
end
|