diff --git a/scad/wedge.scad b/scad/wedge.scad index f7c6f10..63cf844 100644 --- a/scad/wedge.scad +++ b/scad/wedge.scad @@ -162,37 +162,69 @@ module wedge_body() { // ------------------------------------------------------------ -// Recessed bottom label so the base stays flat +// raised bottom label so readable and not engulged/hidden // ------------------------------------------------------------ - -module wedge_label_cut(idx=0) { +module wedge_label_raise_OLD(label_txt="0") { mid_r = (inner_r + outer_r) / 2; mid_a = slice_angle / 2; x = mid_r * cos(mid_a); y = mid_r * sin(mid_a); - translate([x, y, label_depth + 0.2]) - mirror([0,0,1]) - rotate([180,0,mid_a - 90]) - linear_extrude(height = label_depth + 0.2) - text(str(idx), - size = label_size, + translate([x, y, 0]) + rotate([0, 0, mid_a - 90]) + linear_extrude(height = 1.2) + text(label_txt, + size = 18, font = label_font, halign = "center", valign = "center"); } +// If the text is too close to the middle or too large, use this instead: + +module wedge_label_raise_optional(label_txt="0") { + mid_r = inner_r + (outer_r - inner_r) * 0.63; + mid_a = slice_angle / 2; + + x = mid_r * cos(mid_a); + y = mid_r * sin(mid_a); + + translate([x, y, 0]) + rotate([0, 0, mid_a - 90]) + linear_extrude(height = 10.2) + text(label_txt, + size = 18, + font = label_font, + halign = "center", + valign = "center"); +} + +module wedge_label_raise(label_txt="0") { + mid_r = inner_r + (outer_r - inner_r) * 0.63; + mid_a = slice_angle / 2; + + x = mid_r * cos(mid_a); + y = mid_r * sin(mid_a); + + translate([x, y, -3.2]) + rotate([0, 0, mid_a - 90]) + linear_extrude(height = 3) + text(label_txt, + size = 16, + font = label_font, + halign = "center", + valign = "center"); +} // ------------------------------------------------------------ // One numbered wedge // ------------------------------------------------------------ module wedge_unit(idx=0) { - difference() { - wedge_body(); - wedge_label_cut(idx); - } + wedge_body(); + wedge_label_raise(str(idx)); + //wedge_label_raise_optional(str(idx)); } diff --git a/scad/wedge.stl b/scad/wedge.stl new file mode 100644 index 0000000..355d94f Binary files /dev/null and b/scad/wedge.stl differ diff --git a/scripts/create_glb_colorpie.py b/scripts/create_glb_colorpie.py index 9ad0428..10e63e1 100644 --- a/scripts/create_glb_colorpie.py +++ b/scripts/create_glb_colorpie.py @@ -84,6 +84,42 @@ def group_parts_by_angle(parts, tolerance_deg=10.0): return groups +def pick_slot_pairs(parts, expected_groups=10, tolerance_deg=10.0): + groups = group_parts_by_angle(parts, tolerance_deg=tolerance_deg) + + log(f"Grouped {len(parts)} raw parts into {len(groups)} angle groups") + + slot_pairs = [] + + for gi, g in enumerate(groups): + g["parts"] = sorted(g["parts"], key=part_size_score, reverse=True) + log(f" group {gi:02d}: angle≈{g['angle']:7.3f} count={len(g['parts'])}") + for pj, obj in enumerate(g["parts"]): + dims = obj.dimensions + log( + f" part {pj}: name={obj.name!r} " + f"score={part_size_score(obj):10.3f} " + f"dims=({dims.x:8.3f},{dims.y:8.3f},{dims.z:8.3f})" + ) + + if len(g["parts"]) < 2: + die(f"Expected at least 2 parts in group {gi}, found {len(g['parts'])}") + + body = g["parts"][0] + text = g["parts"][1] + + slot_pairs.append({ + "angle": angle_deg_for_obj(body), + "body": body, + "text": text, + }) + + if len(slot_pairs) != expected_groups: + die(f"Expected {expected_groups} angle groups; found {len(slot_pairs)}") + + slot_pairs = sorted(slot_pairs, key=lambda s: s["angle"]) + return slot_pairs + def pick_main_parts(parts, expected_groups=10, tolerance_deg=10.0): groups = group_parts_by_angle(parts, tolerance_deg=tolerance_deg) @@ -350,6 +386,9 @@ def export_glb(outp, objs): if 'FINISHED' not in res: die(f"GLB export failed: {outp}") +def ensure_text_material(name="PIE_TEXT_BLACK"): + black = srgb_rgba_to_linear((0.0, 0.0, 0.0, 1.0)) + return ensure_material(name, black, roughness=0.7, metallic=0.0) def main(): log("create_glb_colorpie.py starting") @@ -387,29 +426,44 @@ def main(): # parts = sort_parts_by_angle(parts) # the following line replaces all of the above rem'd - parts = pick_main_parts(parts, expected_groups=10, tolerance_deg=10.0) - delete_other_meshes(parts) + slot_pairs = pick_slot_pairs(parts, expected_groups=10, tolerance_deg=10.0) + + text_mat = ensure_text_material() + + export_objs = [] + + for i, slot in enumerate(slot_pairs): + body = slot["body"] + text = slot["text"] - for i, obj in enumerate(parts): hexval = hexes[i] srgb = hex_to_srgb_rgba(hexval) linear = srgb_rgba_to_linear(srgb) - mat_name = f"PIE_{i}_{hexval.strip().lstrip('#').upper()}" - mat = ensure_material( - mat_name, + + body_mat_name = f"PIE_{i}_{hexval.strip().lstrip('#').upper()}" + body_mat = ensure_material( + body_mat_name, linear, roughness=roughness, metallic=metallic, ) - assign_material(obj, mat) - obj.name = f"wedge_{i}" + + assign_material(body, body_mat) + assign_material(text, text_mat) + + body.name = f"wedge_{i}" + text.name = f"label_{i}" + + export_objs.extend([body, text]) + log( - f"Assigned wedge_{i}: angle={angle_deg_for_obj(obj):7.3f} " - f"hex=#{hexval.strip().lstrip('#').upper()}" + f"Assigned wedge_{i}: angle={angle_deg_for_obj(body):7.3f} " + f"hex=#{hexval.strip().lstrip('#').upper()} " + f"text={text.name}" ) - center_all_meshes(parts) - export_glb(outp, parts) + center_all_meshes(export_objs) + export_glb(outp, export_objs) log(f"Wrote: {outp}")