This commit is contained in:
Nick Estes
2026-09-07 12:11:43 -07:00
parent 518fe64b13
commit 59ab496f17
13 changed files with 168 additions and 32 deletions
+5
View File
@@ -9,6 +9,7 @@ class ConfigTest < Minitest::Test
assert_in_delta 463.0, config.maximum_diameter("eight_piece"), 0.001
assert_in_delta 1.6, config["shell"]["wall_mm"], 0.001
assert_in_delta 0.8, config["shell"]["minimum_feature_mm"], 0.001
assert_equal "solid", config["shell"]["interior"]
assert_in_delta 10.0, config["stand"]["base_clearance_mm"], 0.001
end
@@ -32,4 +33,8 @@ class ConfigTest < Minitest::Test
MoonModel::Config.new("stand" => { "base_clearance_mm" => -0.1 })
end
end
def test_rejects_unknown_interior_mode
assert_raises(ArgumentError) { MoonModel::Config.new("shell" => { "interior" => "foam" }) }
end
end
+4
View File
@@ -21,6 +21,10 @@ class GeneratorTest < Minitest::Test
assert_includes model, "<components>"
end
assert File.file?(File.join(result[:output_dir], "manifest.md"))
manifest = File.read(File.join(result[:output_dir], "manifest.md"))
assembly = File.read(File.join(result[:output_dir], "ASSEMBLY.md"))
assert_includes manifest, "Interior: solid slicer volume"
assert_includes assembly, "no internal cavity supports are required"
assert_in_delta 40.0, result[:statistics]["final_envelope_mm"], 0.01
end
end
+59
View File
@@ -0,0 +1,59 @@
# 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
+10 -1
View File
@@ -11,11 +11,20 @@ class SizingTest < Minitest::Test
MoonModel::Config.new(
"size" => { "input" => "diameter", "value" => 8.0, "unit" => "in", "meaning" => "datum" },
"vertical_exaggeration" => exaggeration,
"assembly" => assembly,
"assembly" => assembly, "shell" => { "interior" => "hollow" },
"resolution" => { "longitude_segments" => 48 }
)
end
def test_solid_one_piece_allows_more_relief_before_radial_collapse
hollow = datum_config(1, assembly: "one_piece")
solid = MoonModel::Config.new(hollow.to_h.merge("shell" => hollow["shell"].merge("interior" => "solid")))
assert_operator MoonModel::Sizing.maximum_safe_exaggeration(solid, @data), :>,
MoonModel::Sizing.maximum_safe_exaggeration(hollow, @data)
end
def test_eight_inch_relief_uses_consistent_units
one = MoonModel::Sizing.calculate(datum_config(1), @data)
ten = MoonModel::Sizing.calculate(datum_config(10), @data)
+12
View File
@@ -69,6 +69,18 @@ class WizardTest < Minitest::Test
assert_includes output.string, "waive the recommended terrain safety margin"
end
def test_one_piece_interior_choice_can_select_hollow
input = StringIO.new("\n\n\n\nn\n\n\n")
output = StringIO.new
wizard = MoonModel::Wizard.new(io: HighLine.new(input, output), data_set: MoonModel::DataSet.new)
values = { "printer" => MoonModel::Config::X2D.dup, "purpose" => "display", "assembly" => "auto" }
wizard.send(:sizing, values)
assert_equal "hollow", values.dig("shell", "interior")
assert_includes output.string, "use slicer-controlled infill instead of a hollow cavity"
end
private
def ask_yes_no(input, default)