code wiki / (root) / nx_cad.nx

nx_cad.nx source

↩ module page · 140 lines · 5106 B

1// nx_cad.nx -- parametric solid modeling (AutoCAD / Fusion / Siemens-class), the 2// "sketch -> extrude" core, sovereign. Takes a 2D profile (a sketch) in the XY 3// plane and extrudes it +Z into a closed solid: two end caps (fan-triangulated) 4// plus a ring of side quads. Convex profiles only in v1 (fan triangulation); 5// concave/holed profiles need ear-clipping + CSG (the next CAD rungs). Output is 6// a pipeline-native Q14-mm NxMesh -> flows straight to nx_stl_write_mesh -> slicer, 7// exactly like the DCC tools. Reuses nx_mesh + nx_trig (for round profiles). No 8// dup: grepped, no nx_cad/extrude/revolve existed. license_tier: ORIGINAL. 9 10import "nx_syscalls.nx" 11import "nx_mesh.nx" 12import "nx_trig.nx" 13 14// ===== extrude a convex 2D profile into a solid prism ============ 15// 16// px[i], py[i] (Q14), i in [0,n), wound CCW. Extrudes by height_q14 along +Z. 17// Verts: 2n (bottom ring z=0 at [0,n), top ring z=h at [n,2n)). 18// Tris: 2*(n-2) caps + 2*n sides = 4n - 4. 19 20func nx_cad_extrude(px: *i64, py: *i64, n: i64, height_q14: i64, color: i64) -> *NxMesh { 21 if n < 3 { return 0 as *NxMesh } 22 let nv: i64 = 2 * n 23 let nt: i64 = 4 * n - 4 24 let m: *NxMesh = nx_mesh_alloc(nv, nt, 0) 25 if (m as i64) == 0 { return m } 26 27 var i: i64 = 0 28 while i < n { 29 nx_mesh_set_vertex(m, i, px[i], py[i], 0, color) 30 nx_mesh_set_vertex(m, n + i, px[i], py[i], height_q14, color) 31 i = i + 1 32 } 33 34 var t: i64 = 0 35 // bottom cap fan (faces -Z): (0, f+1, f) 36 var f: i64 = 1 37 while f < n - 1 { 38 nx_mesh_set_triangle(m, t, 0, f + 1, f) 39 t = t + 1 40 f = f + 1 41 } 42 // top cap fan (faces +Z): (n, n+f, n+f+1) 43 f = 1 44 while f < n - 1 { 45 nx_mesh_set_triangle(m, t, n, n + f, n + f + 1) 46 t = t + 1 47 f = f + 1 48 } 49 // side quads: edge i -> (i+1)%n, each split into 2 outward tris 50 i = 0 51 while i < n { 52 let j: i64 = (i + 1) % n 53 let ti: i64 = n + i 54 let tj: i64 = n + j 55 nx_mesh_set_triangle(m, t, i, j, tj) 56 t = t + 1 57 nx_mesh_set_triangle(m, t, i, tj, ti) 58 t = t + 1 59 i = i + 1 60 } 61 return m 62} 63 64// ===== parametric box ============================================ 65// Rectangular prism wx*wy footprint (centred on origin in XY), height wz, 66// base on the z=0 plane. A rectangle sketch extruded. 67 68func nx_cad_make_box(wx_q14: i64, wy_q14: i64, wz_q14: i64, color: i64) -> *NxMesh { 69 let px: *i64 = (sys_mmap(4 * 8)) as *i64 70 let py: *i64 = (sys_mmap(4 * 8)) as *i64 71 let hx: i64 = wx_q14 / 2 72 let hy: i64 = wy_q14 / 2 73 px[0] = 0 - hx; py[0] = 0 - hy 74 px[1] = hx; py[1] = 0 - hy 75 px[2] = hx; py[2] = hy 76 px[3] = 0 - hx; py[3] = hy 77 return nx_cad_extrude(px, py, 4, wz_q14, color) 78} 79 80// ===== parametric cylinder ======================================= 81// A regular `segments`-gon sketch (approximating a circle of radius_q14 via 82// nx_trig) extruded to height_q14. Faceted, like every mesh-CAD cylinder. 83 84func nx_cad_make_cylinder(radius_q14: i64, height_q14: i64, 85 segments: i64, color: i64) -> *NxMesh { 86 if segments < 3 { return 0 as *NxMesh } 87 let px: *i64 = (sys_mmap(segments * 8)) as *i64 88 let py: *i64 = (sys_mmap(segments * 8)) as *i64 89 var k: i64 = 0 90 while k < segments { 91 let turn: i64 = k * 1024 / segments // turn in Q10 (1024 = full circle) 92 let cv: i64 = nx_cos_turn_q10(turn) // Q10 cos 93 let sv: i64 = nx_sin_turn_q10(turn) // Q10 sin 94 px[k] = radius_q14 * cv / 1024 95 py[k] = radius_q14 * sv / 1024 96 k = k + 1 97 } 98 return nx_cad_extrude(px, py, segments, height_q14, color) 99} 100 101// ===== parametric cone =========================================== 102// A `segments`-gon base circle (radius_q14, z=0) tapering to an apex at 103// (0,0,height_q14). Direct factory (light): segments+1 verts, 2*segments-2 tris 104// (base cap fan + side triangles). A closed, printable solid. 105 106func nx_cad_make_cone(radius_q14: i64, height_q14: i64, 107 segments: i64, color: i64) -> *NxMesh { 108 if segments < 3 { return 0 as *NxMesh } 109 let nv: i64 = segments + 1 110 let nt: i64 = 2 * segments - 2 111 let m: *NxMesh = nx_mesh_alloc(nv, nt, 0) 112 if (m as i64) == 0 { return m } 113 var k: i64 = 0 114 while k < segments { 115 let turn: i64 = k * 1024 / segments 116 let cv: i64 = nx_cos_turn_q10(turn) 117 let sv: i64 = nx_sin_turn_q10(turn) 118 nx_mesh_set_vertex(m, k, radius_q14 * cv / 1024, radius_q14 * sv / 1024, 0, color) 119 k = k + 1 120 } 121 let apex: i64 = segments 122 nx_mesh_set_vertex(m, apex, 0, 0, height_q14, color) 123 var t: i64 = 0 124 // base cap fan (faces -Z) 125 var f: i64 = 1 126 while f < segments - 1 { 127 nx_mesh_set_triangle(m, t, 0, f + 1, f) 128 t = t + 1 129 f = f + 1 130 } 131 // side triangles to the apex 132 var i: i64 = 0 133 while i < segments { 134 let j: i64 = (i + 1) % segments 135 nx_mesh_set_triangle(m, t, i, j, apex) 136 t = t + 1 137 i = i + 1 138 } 139 return m 140}