update some deisng parameters and add new cases
This commit is contained in:
@@ -14,13 +14,14 @@ module FeatherCaseWizard
|
||||
DEFAULT_PARAMETERS = {
|
||||
"top_profile" => "generic",
|
||||
"wing_count" => 1,
|
||||
"wing_pitch" => 11.0,
|
||||
"wing_pitch" => 12.25,
|
||||
"stack_height_override" => 0.0,
|
||||
"generic_component_height" => 3.0,
|
||||
"generic_top_gap" => 2.0,
|
||||
"gps_antenna_height" => 4.0,
|
||||
"gps_antenna_height" => 6.0,
|
||||
"gps_top_gap" => 5.0,
|
||||
"oled_component_height" => 2.4,
|
||||
"oled_display_height" => 1.5,
|
||||
"oled_face_gap" => 0.8,
|
||||
"button_a" => true,
|
||||
"button_b" => true,
|
||||
@@ -62,13 +63,19 @@ module FeatherCaseWizard
|
||||
"board_bottom_clearance" => 5.4,
|
||||
"board_side_clearance" => 7.0,
|
||||
"board_rear_clearance" => 4.0,
|
||||
"usb_board_wall_gap" => 1.2,
|
||||
"usb_board_wall_gap" => 2.0,
|
||||
"lid_lip_depth" => 2.4,
|
||||
"lid_lip_thickness" => 1.2,
|
||||
"fit_clearance" => 0.35,
|
||||
"cutout_min_web" => 1.2,
|
||||
"hole_compensation" => 0.2,
|
||||
"lid_screw_head_diameter" => 5.2,
|
||||
"lid_screw_head_height" => 2.5,
|
||||
"usb_opening_enabled" => true,
|
||||
"usb_guide_enabled" => true,
|
||||
"usb_connector_overhang" => 2.0,
|
||||
"usb_guide_wall_thickness" => 1.2,
|
||||
"usb_guide_end_gap" => 1.0,
|
||||
"usb_opening_width" => 12.5,
|
||||
"usb_opening_height" => 7.0,
|
||||
"usb_opening_radius" => 1.5,
|
||||
@@ -77,11 +84,12 @@ module FeatherCaseWizard
|
||||
|
||||
ADVANCED_FIELDS = {
|
||||
"Stack" => %w[wing_pitch generic_component_height generic_top_gap
|
||||
gps_antenna_height gps_top_gap oled_component_height oled_face_gap],
|
||||
gps_antenna_height gps_top_gap oled_component_height
|
||||
oled_display_height oled_face_gap],
|
||||
"Shell and fit" => %w[wall_thickness floor_thickness lid_thickness corner_radius
|
||||
board_bottom_clearance board_side_clearance board_rear_clearance
|
||||
usb_board_wall_gap lid_lip_depth lid_lip_thickness fit_clearance
|
||||
hole_compensation lid_screw_head_diameter lid_screw_head_height],
|
||||
board_bottom_clearance board_side_clearance lid_lip_depth
|
||||
lid_lip_thickness fit_clearance cutout_min_web hole_compensation
|
||||
lid_screw_head_diameter lid_screw_head_height],
|
||||
"M2.5 inserts" => %w[m25_insert_length m25_insert_hole_diameter
|
||||
m25_screw_clearance m25_boss_diameter
|
||||
insert_entry_chamfer insert_melt_relief],
|
||||
@@ -93,7 +101,8 @@ module FeatherCaseWizard
|
||||
switch_flange_diameter switch_body_length
|
||||
switch_body_diameter switch_wire_allowance],
|
||||
"USB-C opening" => %w[usb_opening_width usb_opening_height
|
||||
usb_opening_radius usb_vertical_offset],
|
||||
usb_opening_radius usb_vertical_offset usb_connector_overhang
|
||||
usb_guide_wall_thickness usb_guide_end_gap],
|
||||
"OLED buttons" => %w[button_projection button_flange_thickness
|
||||
button_travel button_contact_extension]
|
||||
}.freeze
|
||||
@@ -264,6 +273,9 @@ module FeatherCaseWizard
|
||||
unless (outputs["coupons"] - COUPONS).empty?
|
||||
raise ConfigError, "Unsupported calibration coupon"
|
||||
end
|
||||
if parameters["usb_guide_enabled"] && !parameters["usb_opening_enabled"]
|
||||
raise ConfigError, "USB guide requires the USB opening"
|
||||
end
|
||||
|
||||
positive = DEFAULT_PARAMETERS.keys - %w[usb_vertical_offset stack_height_override]
|
||||
positive.each do |key|
|
||||
@@ -289,7 +301,10 @@ module FeatherCaseWizard
|
||||
def normalize!
|
||||
data["schema_version"] = Integer(data.fetch("schema_version", SCHEMA_VERSION))
|
||||
data["generator"] ||= {}
|
||||
data["parameters"] = self.class.deep_copy(DEFAULT_PARAMETERS).merge(data["parameters"] || {})
|
||||
supplied_parameters = data["parameters"] || {}
|
||||
legacy_usb_guide = !supplied_parameters.key?("usb_guide_enabled")
|
||||
data["parameters"] = self.class.deep_copy(DEFAULT_PARAMETERS).merge(supplied_parameters)
|
||||
data["parameters"]["usb_guide_enabled"] = false if legacy_usb_guide
|
||||
data["cutouts"] ||= []
|
||||
data["outputs"] ||= {}
|
||||
data["outputs"]["formats"] ||= ["3mf"]
|
||||
@@ -302,6 +317,7 @@ module FeatherCaseWizard
|
||||
def validate_cutouts!
|
||||
dims = dimensions
|
||||
names = {}
|
||||
bounds = []
|
||||
cutouts.each do |cutout|
|
||||
name = cutout["name"].to_s.strip
|
||||
raise ConfigError, "Every cutout needs a name" if name.empty?
|
||||
@@ -328,9 +344,68 @@ module FeatherCaseWizard
|
||||
radius = Float(cutout.fetch("radius", [width, height].min / 2))
|
||||
raise ConfigError, "#{name} dimensions must be positive" unless
|
||||
width.positive? && height.positive? && radius.positive?
|
||||
bounds << {
|
||||
"name" => name, "face" => face,
|
||||
"left" => horizontal - width / 2, "right" => horizontal + width / 2,
|
||||
"bottom" => z - height / 2, "top" => z + height / 2
|
||||
}
|
||||
rescue ArgumentError, TypeError, KeyError => e
|
||||
raise ConfigError, "Invalid cutout #{name.inspect}: #{e.message}"
|
||||
end
|
||||
validate_cutout_spacing!(bounds, dims)
|
||||
end
|
||||
|
||||
def validate_cutout_spacing!(bounds, dims)
|
||||
web = parameters["cutout_min_web"]
|
||||
bounds.combination(2) do |first, second|
|
||||
next unless first["face"] == second["face"]
|
||||
next if bounds_separated?(first, second, web)
|
||||
|
||||
raise ConfigError,
|
||||
"#{first["name"]} and #{second["name"]} are too close on the #{first["face"]} wall"
|
||||
end
|
||||
return unless parameters["usb_opening_enabled"]
|
||||
|
||||
usb = usb_wall_bounds(dims)
|
||||
bounds.select { |item| item["face"] == "front" }.each do |cutout|
|
||||
next if bounds_separated?(cutout, usb, web)
|
||||
|
||||
raise ConfigError, "#{cutout["name"]} is too close to the USB opening or guide"
|
||||
end
|
||||
end
|
||||
|
||||
def bounds_separated?(first, second, web)
|
||||
first["right"] + web <= second["left"] ||
|
||||
second["right"] + web <= first["left"] ||
|
||||
first["top"] + web <= second["bottom"] ||
|
||||
second["top"] + web <= first["bottom"]
|
||||
end
|
||||
|
||||
def usb_wall_bounds(dims)
|
||||
p = parameters
|
||||
effective_floor = p["tripod_insert_enabled"] ?
|
||||
[p["floor_thickness"], p["tripod_insert_length"] + p["insert_melt_relief"] + 1.2].max :
|
||||
p["floor_thickness"]
|
||||
effective_board_clearance = [
|
||||
p["board_bottom_clearance"],
|
||||
p["m25_insert_length"] + p["insert_melt_relief"] + 0.6
|
||||
].max
|
||||
board_top_z = effective_floor + effective_board_clearance + 1.6
|
||||
global_y = p["wall_thickness"] + p["board_side_clearance"] + 11.43
|
||||
horizontal = dims["width"] - global_y
|
||||
z = board_top_z + 1.6 + p["usb_vertical_offset"]
|
||||
guide_length = [
|
||||
p["usb_board_wall_gap"] - p["usb_connector_overhang"] - p["usb_guide_end_gap"], 0
|
||||
].max
|
||||
guide_active = p["usb_guide_enabled"] && guide_length.positive?
|
||||
shell = guide_active ? 2 * p["usb_guide_wall_thickness"] : 0
|
||||
width = p["usb_opening_width"] + p["hole_compensation"] + shell
|
||||
height = p["usb_opening_height"] + p["hole_compensation"] + shell
|
||||
{
|
||||
"name" => "USB opening", "face" => "front",
|
||||
"left" => horizontal - width / 2, "right" => horizontal + width / 2,
|
||||
"bottom" => z - height / 2, "top" => z + height / 2
|
||||
}
|
||||
end
|
||||
|
||||
def stringify_keys(value)
|
||||
|
||||
Reference in New Issue
Block a user