// // colorpie.scad // 2026-03-06 ChatGPT // $Header$ // // Preview: // openscad colorpie.scad // // STL export: // openscad -o output.stl wedge.scad // $fn = 90; // ------------------------------------------------------------ // Global parameters // ------------------------------------------------------------ slice_count = 10; slice_angle = 360 / slice_count; // 36 degrees explode_gap = 10; // Footprint inner_r = 22; outer_r = 82; thickness = 6; // Crown profile across the wedge width crown_height = 10; table_frac = 0.42; // fraction of width occupied by table shoulder_frac = 0.18; // fraction on each side used by bevel/shoulder stations = 13; // more stations = more facet slices across width // Labeling label_size = 8; label_depth = 1.0; label_font = "Liberation Sans:style=Bold"; // Small geometry tolerance eps = 0.01; // ------------------------------------------------------------ // Helper functions // ------------------------------------------------------------ function deg(a) = a; function lerp(a,b,t) = a + (b-a)*t; // u is normalized from 0 at left cut face to 1 at right cut face // This defines the outside-elevation style profile: // // low edge -> bevel up -> flat table -> bevel down -> low edge // function crown_profile(u) = let( t0 = shoulder_frac, t1 = 0.5 - table_frac/2, t2 = 0.5 + table_frac/2, t3 = 1.0 - shoulder_frac ) (u <= t0) ? lerp(0.00, 0.70, u / t0) : (u <= t1) ? lerp(0.70, 1.00, (u - t0) / max(eps, t1 - t0)) : (u <= t2) ? 1.00 : (u <= t3) ? lerp(1.00, 0.70, (u - t2) / max(eps, t3 - t2)) : lerp(0.70, 0.00, (u - t3) / max(eps, 1.0 - t3)); // Z value of top surface at station u function top_z(u) = thickness + crown_height * crown_profile(u); // Angle at station i function station_angle(i) = slice_angle * i / (stations - 1); // Polar point helpers function p_inner(a,z) = [ inner_r * cos(a), inner_r * sin(a), z ]; function p_outer(a,z) = [ outer_r * cos(a), outer_r * sin(a), z ]; // Indices for point grid // per station: // 0 = bottom inner // 1 = bottom outer // 2 = top inner // 3 = top outer function idx_bi(i) = 4*i + 0; function idx_bo(i) = 4*i + 1; function idx_ti(i) = 4*i + 2; function idx_to(i) = 4*i + 3; // ------------------------------------------------------------ // Master wedge as a polyhedron // Top shape traverses the wedge width // ------------------------------------------------------------ module wedge_body() { pts = [ for (i = [0:stations-1]) let( a = station_angle(i), u = i / (stations - 1), zt = top_z(u) ) each [ p_inner(a, 0), // bottom inner p_outer(a, 0), // bottom outer p_inner(a, zt), // top inner p_outer(a, zt) // top outer ] ]; faces = concat( // bottom, triangulated [ for (i = [0:stations-2]) each [ [ idx_bi(i), idx_bi(i+1), idx_bo(i+1) ], [ idx_bi(i), idx_bo(i+1), idx_bo(i) ] ] ], // top, triangulated [ for (i = [0:stations-2]) each [ [ idx_ti(i), idx_to(i), idx_to(i+1) ], [ idx_ti(i), idx_to(i+1), idx_ti(i+1) ] ] ], // inner radius face, triangulated [ for (i = [0:stations-2]) each [ [ idx_bi(i), idx_ti(i), idx_ti(i+1) ], [ idx_bi(i), idx_ti(i+1), idx_bi(i+1) ] ] ], // outer radius face, triangulated [ for (i = [0:stations-2]) each [ [ idx_bo(i), idx_bo(i+1), idx_to(i+1) ], [ idx_bo(i), idx_to(i+1), idx_to(i) ] ] ], // left cut face, triangulated [ [ idx_bi(0), idx_bo(0), idx_to(0) ], [ idx_bi(0), idx_to(0), idx_ti(0) ] ], // right cut face, triangulated [ [ idx_bi(stations-1), idx_ti(stations-1), idx_to(stations-1) ], [ idx_bi(stations-1), idx_to(stations-1), idx_bo(stations-1) ] ] ); polyhedron(points = pts, faces = faces, convexity = 12); } // ------------------------------------------------------------ // raised bottom label so readable and not engulged/hidden // ------------------------------------------------------------ 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, 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]) mirror([1,0,0]) linear_extrude(height = 3) text(label_txt, size = 16, font = label_font, halign = "center", valign = "center"); } // ------------------------------------------------------------ // One numbered wedge // ------------------------------------------------------------ module wedge_unit(idx=0) { wedge_body(); wedge_label_raise(str(idx)); //wedge_label_raise_optional(str(idx)); } // ------------------------------------------------------------ // Assemble 10 wedges around the center // Each wedge is exploded outward along its centerline // ------------------------------------------------------------ module wheel_10() { for (i = [0:slice_count-1]) { a = i * slice_angle; mid_a = a + slice_angle/2; dx = explode_gap * cos(mid_a); dy = explode_gap * sin(mid_a); translate([dx, dy, 0]) rotate([0,0,a]) wedge_unit(i); } } // ------------------------------------------------------------ // Top level // ------------------------------------------------------------ wheel_10();