nx_underridge_cleaner.nx source
↩ module page · 140 lines · 7978 B
1// nx_underridge_cleaner.nx -- the UNDER-RIDGE toilet-bowl cleaner head, GENERATED OUT OF
2// THE TEAM as a sovereign N-primitive CSG scene (nx_csg_scene) -> watertight NxMesh ->
3// nx_stl_write_mesh -> slicer -> G-code. No 3rd-party CAD anywhere in the path.
4//
5// Design (a FLAT paddle = prints with zero supports; the strong, never-break geometry):
6// * rounded head plate (every glaze-facing edge filleted = never-break NB2)
7// * a recessed POCKET that holds a glaze-SAFE scour/melamine pad -- the pad stands proud
8// of the printed lip, so the ONLY thing that ever touches the porcelain is the soft pad
9// (never-break NB1: the tool cannot scratch the glaze)
10// * two strap slots to clamp the pad (zip-tie / rubber band)
11// * a neck for reach + two MOUNT HOLES to HOOK ONTO a handle ("hookable on")
12// * power vs the black biofilm = pad pressure under the rim + reach, not hard abrasion
13//
14// Axis-aligned v1 (SDF has no rotation yet -> the candy-cane hook tilt is a later rung;
15// the flat paddle is the strongest, most printable starting geometry). All dims Q14-mm
16// (1mm = 16384). The never-break gate reads these same numbers. license_tier: ORIGINAL
17import "nx_syscalls.nx"
18import "nx_mesh.nx"
19import "nx_sdf.nx"
20import "nx_csg_scene.nx"
21import "nx_stl_write.nx"
22
23const UC_MM: i64 = 16384
24
25// Build the cleaner as a 7-primitive scene. drop_slot lets the never-break / liar-kill
26// tests displace strap-slot A far away to prove the field depends on real parameters.
27func nx_uc_build(drop_slot: i64) -> *NxCsgScene {
28 let M: i64 = 16384
29 let s: *NxCsgScene = nx_csg_scene_new(12)
30
31 // p0 SEED: head plate 75 x 36 x 6 mm, 2mm rounded edges (overall half - r feeds the box).
32 nx_csg_scene_add(s, nx_sdf_make4(NX_SDF_ROUNDBOX, 0, 0, 3*M,
33 (75*M)/2 - 2*M, (36*M)/2 - 2*M, 3*M - 2*M, 2*M), NX_CSG_UNION, 0)
34
35 // p1 DIFF: pad pocket -- 68 x 30 mm, 3mm deep into the top face (centre z=6mm, floor z=3mm).
36 nx_csg_scene_add(s, nx_sdf_make4(NX_SDF_ROUNDBOX, 0, 0, 6*M,
37 (68*M)/2 - 1*M, (30*M)/2 - 1*M, 3*M - 1*M, 1*M), NX_CSG_DIFF, 0)
38
39 // p2 DIFF: strap slot A (4mm wide, through the plate) at x=-22.5mm. drop_slot moves it out.
40 var slotA_x: i64 = 0 - (45*M)/2
41 if drop_slot == 1 { slotA_x = 200*M }
42 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_BOX, slotA_x, 0, 3*M, 2*M, 10*M, 5*M), NX_CSG_DIFF, 0)
43
44 // p3 DIFF: strap slot B at x=+22.5mm.
45 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_BOX, (45*M)/2, 0, 3*M, 2*M, 10*M, 5*M), NX_CSG_DIFF, 0)
46
47 // p4 UNION: neck bar extends -X from the heel (overlaps the head ~4mm for a solid weld).
48 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_BOX, 0 - 58*M, 0, 3*M, 24*M + 8192, 8*M, 3*M), NX_CSG_UNION, 0)
49
50 // p5,p6 DIFF: two mount holes (5mm dia) through the neck -> HOOK ONTO / bolt onto a handle.
51 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_CYL, 0 - 70*M, 0, 3*M, 2*M + 8192, 6*M, 0), NX_CSG_DIFF, 0)
52 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_CYL, 0 - 60*M, 0, 3*M, 2*M + 8192, 6*M, 0), NX_CSG_DIFF, 0)
53
54 return s
55}
56
57// extraction bounds (mm*M) that tightly bound the part + 2-3mm padding.
58func nx_uc_lox() -> i64 { return 0 - 85*16384 }
59func nx_uc_loy() -> i64 { return 0 - 20*16384 }
60func nx_uc_loz() -> i64 { return 0 - 2*16384 }
61func nx_uc_hix() -> i64 { return 40*16384 }
62func nx_uc_hiy() -> i64 { return 20*16384 }
63func nx_uc_hiz() -> i64 { return 9*16384 }
64
65// generate the part mesh at grid resolution `res`.
66func nx_uc_mesh(res: i64) -> *NxMesh {
67 let s: *NxCsgScene = nx_uc_build(0)
68 return nx_csg_extract_scene(s, nx_uc_lox(), nx_uc_loy(), nx_uc_loz(),
69 nx_uc_hix(), nx_uc_hiy(), nx_uc_hiz(), res)
70}
71
72// ===== HOOK variant (candy-cane tilt) =====================================
73// Tilts the head + pocket + slots UP about the HEEL (where the head meets the neck),
74// keeping the neck + mount holes low -> the working face angles up UNDER the rim while
75// the handle stays clear of the bowl. Uses the nx_csg_scene Y-rotation about the heel
76// pivot. SAME never-break parameters as the flat paddle (neck cross-section unchanged,
77// pad stack unchanged), so nx_underridge_nevergate stays valid.
78const UC_HOOK_ANG: i64 = 43 // ~15 deg up (1024*15/360)
79func nx_uc_heel_x() -> i64 { return 0 - (75*16384)/2 } // -37.5mm = head heel (neck weld)
80func nx_uc_heel_z() -> i64 { return 3*16384 } // mid-plate pivot height
81
82func nx_uc_build_hook(drop_slot: i64) -> *NxCsgScene {
83 let MM: i64 = 16384
84 let px: i64 = nx_uc_heel_x()
85 let pz: i64 = nx_uc_heel_z()
86 let s: *NxCsgScene = nx_csg_scene_new(12)
87 // p0 head plate (tilted up about the heel)
88 nx_csg_scene_add_rot(s, nx_sdf_make4(NX_SDF_ROUNDBOX, 0,0,3*MM, (75*MM)/2-2*MM,(36*MM)/2-2*MM,3*MM-2*MM,2*MM),
89 NX_CSG_UNION, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
90 // p1 pad pocket (tilted with the head)
91 nx_csg_scene_add_rot(s, nx_sdf_make4(NX_SDF_ROUNDBOX, 0,0,6*MM, (68*MM)/2-1*MM,(30*MM)/2-1*MM,3*MM-1*MM,1*MM),
92 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
93 // p2,p3 strap slots (tilted with the head); drop_slot moves slot A out for liar-kill
94 var slotA_x: i64 = 0 - (45*MM)/2
95 if drop_slot == 1 { slotA_x = 200*MM }
96 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_BOX, slotA_x,0,3*MM, 2*MM,10*MM,5*MM),
97 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
98 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_BOX, (45*MM)/2,0,3*MM, 2*MM,10*MM,5*MM),
99 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
100 // p4 neck bar -- axis-aligned (stays low = the candy-cane handle)
101 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_BOX, 0-58*MM,0,3*MM, 24*MM+8192,8*MM,3*MM), NX_CSG_UNION, 0)
102 // p5,p6 mount holes -- axis-aligned
103 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_CYL, 0-70*MM,0,3*MM, 2*MM+8192,6*MM,0), NX_CSG_DIFF, 0)
104 nx_csg_scene_add(s, nx_sdf_make(NX_SDF_CYL, 0-60*MM,0,3*MM, 2*MM+8192,6*MM,0), NX_CSG_DIFF, 0)
105 return s
106}
107
108// hook mesh; wider +Z extraction box because the tilted toe lifts well above the flat 6mm.
109func nx_uc_mesh_hook(res: i64) -> *NxMesh {
110 let s: *NxCsgScene = nx_uc_build_hook(0)
111 return nx_csg_extract_scene(s, nx_uc_lox(), nx_uc_loy(), nx_uc_loz(),
112 nx_uc_hix(), nx_uc_hiy(), 30*16384, res)
113}
114
115// ===== HOOK + GEL DELIVERY ================================================
116// The "really powerful vs black biofilm" rung: 3 feed holes (3mm) through the pocket floor,
117// rotated WITH the head. Inject a glaze-safe descaling gel behind the pad -> it wicks through
118// to the rim and DWELLS while you scrub = chemistry power, not hard abrasion. Holes are kept
119// off the strap slots (x=+/-12mm vs slots at +/-22.5mm). Never-break is unaffected: plate
120// perforations don't change the sacrificial neck (NB4) or the pad-proud rule (NB1).
121func nx_uc_build_hook_gel(drop_slot: i64) -> *NxCsgScene {
122 let MM: i64 = 16384
123 let px: i64 = nx_uc_heel_x()
124 let pz: i64 = nx_uc_heel_z()
125 let s: *NxCsgScene = nx_uc_build_hook(drop_slot) // reuse the 7-feature hook...
126 // ...then add 3 gel feed holes (rotated with the head about the heel)
127 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_CYL, 0-12*MM, 0, 3*MM, 2*MM+8192, 6*MM, 0),
128 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
129 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_CYL, 0, 0, 3*MM, 2*MM+8192, 6*MM, 0),
130 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
131 nx_csg_scene_add_rot(s, nx_sdf_make(NX_SDF_CYL, 12*MM, 0, 3*MM, 2*MM+8192, 6*MM, 0),
132 NX_CSG_DIFF, 0, NX_ROT_Y, UC_HOOK_ANG, px, 0, pz)
133 return s
134}
135
136func nx_uc_mesh_hook_gel(res: i64) -> *NxMesh {
137 let s: *NxCsgScene = nx_uc_build_hook_gel(0)
138 return nx_csg_extract_scene(s, nx_uc_lox(), nx_uc_loy(), nx_uc_loz(),
139 nx_uc_hix(), nx_uc_hiy(), 30*16384, res)
140}