nx_step_write.nx source
↩ module page · 310 lines · 11263 B
1// nx_step_write.nx -- STEP WRITE (cadtwin P3a write half, first rung): emit a valid ISO-10303-21 file from a
2// twin mesh -- FACETED B-rep class (FACETED_BREP + CLOSED_SHELL + FACE/FACE_OUTER_BOUND/POLY_LOOP + shared
3// CARTESIAN_POINTs) with the full product-identity chain (PRODUCT->PDF->PD->PDS->SDR) and DECLARED mm units +
4// uncertainty (the anti-JPL doctrine: our files SAY their units). Coordinates are written as EXACT decimals:
5// fx256 -> "N.XXXXXXXX" (1/256 = 0.00390625 -> 8 fractional digits, lossless) so a round-trip through our own
6// reader is INTEGER-EXACT by construction. Includes the matching FACETED READ path (POLY_LOOP -> triangles) --
7// the interop pair in one organ. HONEST scope: faceted geometry write (the mesh-twin class); analytic/NURBS
8// B-rep WRITE = the named residual for full parity. NOTE: '#' cannot appear in NishiLang string literals
9// (scanner gotcha) -- every STEP ref emits byte 35 via swb_c. license_tier: ORIGINAL
10import "nx_step_nurbs.nx"
11const K_MAGIC_390625: i64 = 390625
12const K_MAGIC_10000000: i64 = 10000000
13const K_MAGIC_262144: i64 = 262144
14const K_MAGIC_32768: i64 = 32768
15const K_MAGIC_4000: i64 = 4000
16
17// ---- string builder b[]: [0]=buf ptr [1]=len [2]=cap
18func swb_init(b: *i64, cap: i64) -> i64 {
19 b[0] = sys_mmap(cap) as i64
20 b[1] = 0
21 b[2] = cap
22 return 0
23}
24func swb_c(b: *i64, ch: i64) -> i64 {
25 if b[1] >= b[2] { return 0 - 1 }
26 let p: *u8 = b[0] as *u8
27 p[b[1]] = ch as u8
28 b[1] = b[1] + 1
29 return 0
30}
31func swb_s(b: *i64, s: *u8) -> i64 {
32 var i: i64 = 0
33 while s[i] != (0 as u8) {
34 swb_c(b, s[i] as i64)
35 i = i + 1
36 }
37 return 0
38}
39func swb_n(b: *i64, v0: i64) -> i64 {
40 var v: i64 = v0
41 if v < 0 { swb_c(b, 45); v = 0 - v }
42 let t: *u8 = ((b[0] as i64) + b[2] - 32) as *u8 // scratch at buffer tail (cap includes headroom)
43 var k: i64 = 0
44 if v == 0 { swb_c(b, 48); return 0 }
45 while v > 0 { t[k] = (48 + (v % 10)) as u8; v = v / 10; k = k + 1 }
46 while k > 0 { k = k - 1; swb_c(b, t[k] as i64) }
47 return 0
48}
49// exact decimal mm from fx256: N.XXXXXXXX (8 frac digits = (fx&255)*390625, lossless)
50func swb_fx(b: *i64, v0: i64) -> i64 {
51 var v: i64 = v0
52 if v < 0 { swb_c(b, 45); v = 0 - v }
53 swb_n(b, v / 256)
54 swb_c(b, 46)
55 var f: i64 = (v % 256) * K_MAGIC_390625
56 // zero-pad to 8 digits
57 var dig: i64 = K_MAGIC_10000000
58 var i: i64 = 0
59 while i < 8 {
60 swb_c(b, 48 + (f / dig) % 10)
61 dig = dig / 10
62 i = i + 1
63 }
64 return 0
65}
66func swb_ref(b: *i64, id: i64) -> i64 {
67 swb_c(b, 35)
68 swb_n(b, id)
69 return 0
70}
71func swb_ent(b: *i64, id: i64) -> i64 {
72 swb_ref(b, id)
73 swb_s(b, " = " as *u8)
74 return 0
75}
76
77// ---- write the mesh as a faceted-brep STEP file. Entity ids: prelude 1..24, verts 30..30+nv-1, per-tri
78// (loop,bound,face) 30+nv+3t.., shell/brep at the end. Returns total entity count (>0) or -1.
79func sw_write_mesh(mesh: i64, path: *u8, pname: *u8) -> i64 {
80 let h: *i64 = m3_hdr(mesh)
81 let nv: i64 = h[0]
82 let nt: i64 = h[1]
83 if nv < 3 { return 0 - 1 }
84 if nt < 1 { return 0 - 1 }
85 let b: *i64 = sys_mmap(64) as *i64
86 swb_init(b, K_MAGIC_262144 + nv * 64 + nt * 128)
87 // header
88 swb_s(b, "ISO-10303-21;\nHEADER;\nFILE_DESCRIPTION(('Nishi twin faceted export'),'2;1');\nFILE_NAME('" as *u8)
89 swb_s(b, pname)
90 swb_s(b, "','2026-07-09T00:00:00',('nishi'),('nishi'),'nx_step_write','nx_cadtwin','');\nFILE_SCHEMA(('AUTOMOTIVE_DESIGN " as *u8)
91 swb_c(b, 123)
92 swb_s(b, " 1 0 10303 214 1 1 1 1 " as *u8)
93 swb_c(b, 125)
94 swb_s(b, "'));\nENDSEC;\nDATA;\n" as *u8)
95 // prelude: application + product chain
96 swb_ent(b, 1)
97 swb_s(b, "APPLICATION_PROTOCOL_DEFINITION('international standard','automotive_design',2000," as *u8)
98 swb_ref(b, 2)
99 swb_s(b, ");\n" as *u8)
100 swb_ent(b, 2)
101 swb_s(b, "APPLICATION_CONTEXT('core data for automotive mechanical design processes');\n" as *u8)
102 swb_ent(b, 3)
103 swb_s(b, "PRODUCT_CONTEXT(''," as *u8)
104 swb_ref(b, 2)
105 swb_s(b, ",'mechanical');\n" as *u8)
106 swb_ent(b, 4)
107 swb_s(b, "PRODUCT('" as *u8)
108 swb_s(b, pname)
109 swb_s(b, "','" as *u8)
110 swb_s(b, pname)
111 swb_s(b, "','',(" as *u8)
112 swb_ref(b, 3)
113 swb_s(b, "));\n" as *u8)
114 swb_ent(b, 5)
115 swb_s(b, "PRODUCT_DEFINITION_FORMATION('',''," as *u8)
116 swb_ref(b, 4)
117 swb_s(b, ");\n" as *u8)
118 swb_ent(b, 6)
119 swb_s(b, "PRODUCT_DEFINITION_CONTEXT('part definition'," as *u8)
120 swb_ref(b, 2)
121 swb_s(b, ",'design');\n" as *u8)
122 swb_ent(b, 7)
123 swb_s(b, "PRODUCT_DEFINITION('design',''," as *u8)
124 swb_ref(b, 5)
125 swb_s(b, "," as *u8)
126 swb_ref(b, 6)
127 swb_s(b, ");\n" as *u8)
128 swb_ent(b, 8)
129 swb_s(b, "PRODUCT_DEFINITION_SHAPE('',''," as *u8)
130 swb_ref(b, 7)
131 swb_s(b, ");\n" as *u8)
132 // units context (mm DECLARED + uncertainty)
133 swb_ent(b, 20)
134 swb_s(b, "( GEOMETRIC_REPRESENTATION_CONTEXT(3) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((" as *u8)
135 swb_ref(b, 24)
136 swb_s(b, ")) GLOBAL_UNIT_ASSIGNED_CONTEXT((" as *u8)
137 swb_ref(b, 21)
138 swb_s(b, "," as *u8)
139 swb_ref(b, 22)
140 swb_s(b, "," as *u8)
141 swb_ref(b, 23)
142 swb_s(b, ")) REPRESENTATION_CONTEXT('','') );\n" as *u8)
143 swb_ent(b, 21)
144 swb_s(b, "( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) );\n" as *u8)
145 swb_ent(b, 22)
146 swb_s(b, "( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) );\n" as *u8)
147 swb_ent(b, 23)
148 swb_s(b, "( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() );\n" as *u8)
149 swb_ent(b, 24)
150 swb_s(b, "UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(5.E-006)," as *u8)
151 swb_ref(b, 21)
152 swb_s(b, ",'distance_accuracy_value','confusion accuracy');\n" as *u8)
153 // placement
154 swb_ent(b, 13)
155 swb_s(b, "AXIS2_PLACEMENT_3D(''," as *u8)
156 swb_ref(b, 14)
157 swb_s(b, "," as *u8)
158 swb_ref(b, 15)
159 swb_s(b, "," as *u8)
160 swb_ref(b, 16)
161 swb_s(b, ");\n" as *u8)
162 swb_ent(b, 14)
163 swb_s(b, "CARTESIAN_POINT('',(0.,0.,0.));\n" as *u8)
164 swb_ent(b, 15)
165 swb_s(b, "DIRECTION('',(0.,0.,1.));\n" as *u8)
166 swb_ent(b, 16)
167 swb_s(b, "DIRECTION('',(1.,0.,0.));\n" as *u8)
168 // vertices (EXACT decimals)
169 let vbase: i64 = 30
170 var i: i64 = 0
171 while i < nv {
172 let v: *i64 = m3_vert(mesh, i)
173 swb_ent(b, vbase + i)
174 swb_s(b, "CARTESIAN_POINT('',(" as *u8)
175 swb_fx(b, v[0])
176 swb_c(b, 44)
177 swb_fx(b, v[1])
178 swb_c(b, 44)
179 swb_fx(b, v[2])
180 swb_s(b, "));\n" as *u8)
181 i = i + 1
182 }
183 // triangles: POLY_LOOP + FACE_OUTER_BOUND + FACE
184 let fbase: i64 = vbase + nv
185 var t: i64 = 0
186 while t < nt {
187 let tr: *i64 = m3_tri(mesh, t)
188 let lid: i64 = fbase + t * 3
189 swb_ent(b, lid)
190 swb_s(b, "POLY_LOOP('',(" as *u8)
191 swb_ref(b, vbase + tr[0])
192 swb_c(b, 44)
193 swb_ref(b, vbase + tr[1])
194 swb_c(b, 44)
195 swb_ref(b, vbase + tr[2])
196 swb_s(b, "));\n" as *u8)
197 swb_ent(b, lid + 1)
198 swb_s(b, "FACE_OUTER_BOUND(''," as *u8)
199 swb_ref(b, lid)
200 swb_s(b, ",.T.);\n" as *u8)
201 swb_ent(b, lid + 2)
202 swb_s(b, "FACE('',(" as *u8)
203 swb_ref(b, lid + 1)
204 swb_s(b, "));\n" as *u8)
205 t = t + 1
206 }
207 // shell + brep + shape rep + SDR
208 let shellid: i64 = fbase + nt * 3
209 swb_ent(b, shellid)
210 swb_s(b, "CLOSED_SHELL('',(" as *u8)
211 t = 0
212 while t < nt {
213 if t > 0 { swb_c(b, 44) }
214 swb_ref(b, fbase + t * 3 + 2)
215 t = t + 1
216 }
217 swb_s(b, "));\n" as *u8)
218 swb_ent(b, shellid + 1)
219 swb_s(b, "FACETED_BREP(''," as *u8)
220 swb_ref(b, shellid)
221 swb_s(b, ");\n" as *u8)
222 swb_ent(b, shellid + 2)
223 swb_s(b, "FACETED_BREP_SHAPE_REPRESENTATION('',(" as *u8)
224 swb_ref(b, 13)
225 swb_c(b, 44)
226 swb_ref(b, shellid + 1)
227 swb_s(b, ")," as *u8)
228 swb_ref(b, 20)
229 swb_s(b, ");\n" as *u8)
230 swb_ent(b, 9)
231 swb_s(b, "SHAPE_DEFINITION_REPRESENTATION(" as *u8)
232 swb_ref(b, 8)
233 swb_c(b, 44)
234 swb_ref(b, shellid + 2)
235 swb_s(b, ");\nENDSEC;\nEND-ISO-10303-21;\n" as *u8)
236 // write file
237 let fd: i64 = sys_openat_wr(path, 420)
238 if fd < 0 { return 0 - 1 }
239 sys_write(fd, b[0] as *u8, b[1])
240 sys_close(fd)
241 // entity count: 8 product-chain + 1 SDR + 4 placement + 5 units/ctx + nv points + 3*nt facet + 3 shell/brep/rep
242 return 21 + nv + 3 * nt
243}
244
245// ---- FACETED READ: FACETED_BREP -> CLOSED_SHELL -> FACE -> FACE_OUTER_BOUND -> POLY_LOOP -> triangles.
246// Keys on the POLY_LOOP loop type (robust to face entity naming). Returns triangles added to mesh.
247func sw_read_faceted(st: *i64, mesh: i64) -> i64 {
248 let out2: *i64 = st[9] as *i64
249 let cnt: i64 = st[7]
250 var added: i64 = 0
251 let faces: *i64 = sys_mmap(K_MAGIC_32768) as *i64
252 let p3: *i64 = sys_mmap(96) as *i64
253 var idx: i64 = 0
254 while idx < cnt {
255 if sp_name_is(st, idx, "FACETED_BREP" as *u8) == 1 {
256 let shid: i64 = sgt_arg_ref(st, idx, 1, out2)
257 if shid >= 0 {
258 let shidx: i64 = sp_find(st, shid)
259 if shidx >= 0 {
260 let aao: *i64 = st[5] as *i64
261 let aal: *i64 = st[6] as *i64
262 let nf: i64 = sgt_refs(st[0] as *u8, aao[shidx], aal[shidx], faces, K_MAGIC_4000)
263 var f: i64 = 0
264 while f < nf {
265 let fidx: i64 = sp_find(st, faces[f])
266 if fidx >= 0 {
267 let bid: i64 = sgt_arg_ref(st, fidx, 1, out2)
268 if bid >= 0 {
269 let bidx: i64 = sp_find(st, bid)
270 if bidx >= 0 {
271 let lid: i64 = sgt_arg_ref(st, bidx, 1, out2)
272 if lid >= 0 {
273 let lidx: i64 = sp_find(st, lid)
274 if lidx >= 0 { if sp_name_is(st, lidx, "POLY_LOOP" as *u8) == 1 {
275 added = added + sw_facet_tri(st, lidx, mesh, p3)
276 } }
277 }
278 }
279 }
280 }
281 f = f + 1
282 }
283 }
284 }
285 }
286 idx = idx + 1
287 }
288 return added
289}
290// one POLY_LOOP -> triangle (3 verts appended + tri). Returns 1 if added.
291func sw_facet_tri(st: *i64, lidx: i64, mesh: i64, p3: *i64) -> i64 {
292 let out2: *i64 = st[9] as *i64
293 let aao: *i64 = st[5] as *i64
294 let aal: *i64 = st[6] as *i64
295 let refs: *i64 = ((p3 as i64) + 72) as *i64 // needs p3 alloc >= 96+32
296 let nr: i64 = sgt_refs(st[0] as *u8, aao[lidx], aal[lidx], refs, 3)
297 if nr != 3 { return 0 }
298 var k: i64 = 0
299 while k < 3 {
300 if sgt_tuple_of(st, refs[k], ((p3 as i64) + k * 24) as *i64) == 0 { return 0 }
301 k = k + 1
302 }
303 let h: *i64 = m3_hdr(mesh)
304 let vb: i64 = h[0]
305 m3_add_vert(mesh, p3[0], p3[1], p3[2])
306 m3_add_vert(mesh, p3[3], p3[4], p3[5])
307 m3_add_vert(mesh, p3[6], p3[7], p3[8])
308 m3_add_tri(mesh, vb, vb + 1, vb + 2)
309 return 1
310}