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
+17 -5
View File
@@ -40,12 +40,13 @@ module MoonModel
dimensions = unit.map { |min, max| (max - min) * datum }
minimum_radius, maximum_radius = conservative_radial_bounds(config, data_set, datum, exaggeration,
lon_segments, lat_segments)
safe = validate_safety ? maximum_safe_exaggeration(config, data_set) : nil
interior = prospective_interior(config, data_set, datum, exaggeration, lon_segments, lat_segments)
safe = validate_safety ? maximum_safe_exaggeration(config, data_set, interior: interior) : nil
if safe && exaggeration > safe + 1e-9
raise ArgumentError, format("vertical exaggeration %.3gx is unsafe; maximum is %.3gx", exaggeration, safe)
end
mode, source = resolve_mode(config, data_set, datum, exaggeration, lon_segments, lat_segments)
Result.new(
datum_diameter_mm: datum,
final_envelope_mm: dimensions.max,
@@ -61,6 +62,14 @@ module MoonModel
)
end
def prospective_interior(config, data_set, datum, exaggeration, lon_segments, lat_segments)
return "hollow" if config["purpose"] == "box" || config["assembly"] == "eight_piece"
return config["shell"]["interior"] if config["assembly"] == "one_piece"
dimensions = full_dimensions(data_set, datum, exaggeration, lon_segments, lat_segments)
fits?(dimensions, config) ? config["shell"]["interior"] : "hollow"
end
def conservative_radial_bounds(config, data_set, datum, exaggeration, lon_segments, lat_segments)
base_radius = datum / 2.0
radii = (0..lat_segments).flat_map do |iy|
@@ -112,11 +121,13 @@ module MoonModel
bounds
end
def maximum_safe_exaggeration(config, data_set)
def maximum_safe_exaggeration(config, data_set, interior: config["shell"]["interior"])
minimum_offset = data_set.metadata.fetch("elevation_offset_range_m", [-data_set.relief_range_m, 0]).first.to_f
return Float::INFINITY unless minimum_offset.negative?
required = config["shell"]["wall_mm"] + config["shell"]["minimum_feature_mm"]
solid = interior == "solid"
required = config["shell"]["minimum_feature_mm"]
required += config["shell"]["wall_mm"] unless solid
if config["size"]["meaning"] == "datum"
available = config.diameter_mm / 2.0
return 0.0 if available <= required
@@ -132,7 +143,8 @@ module MoonModel
mid = (low + high) / 2.0
factor = sampled_bounds(data_set, mid, segment_count(config), segment_count(config) / 2).map { |a, b| b - a }.max
radius = config.diameter_mm / (2.0 * factor)
inner = radius * (1.0 + minimum_offset / DataSet::DATUM_RADIUS_M * mid) - config["shell"]["wall_mm"]
inner = radius * (1.0 + minimum_offset / DataSet::DATUM_RADIUS_M * mid)
inner -= config["shell"]["wall_mm"] unless solid
inner >= config["shell"]["minimum_feature_mm"] ? low = mid : high = mid
end
low