code wiki / (root) / nx_solid_mesh_column_candidate_t365.nx

nx_solid_mesh_column_candidate_t365.nx source

↩ module page · 45 lines · 3443 B

1// Mesh-column adapter for the versioned part-aware solid union. 2// Coordinates are caller-frame fixed-point integers. No axis remap or recentering. 3import "nx_solid_column_union_candidate_t365.nx" 4// Every edge product is bounded by 8L^2 and the barycentric numerator by 24L^3. 5// L=2^19-1 keeps both signed i64 expressions representable; this is arithmetic admission. 6const SFC_COORD:i64=524287 7const SFC_DOMAIN:i64=-711 8const SFC_PRECISION:i64=-712 9func sfc_edge_owned(ay:i64,az:i64,by:i64,bz:i64,sg:i64)->i64{ 10 let dy:i64=(by-ay)*sg;let dz:i64=(bz-az)*sg;if dz>0{return 1};if dz==0&&dy<0{return 1};return 0 11} 12func sfc_cross_v1(t:*i64,y:i64,z:i64,x:*i64)->i64{ 13 if (t as i64)<=0||(x as i64)<=0{return SFU_INVALID} 14 if y<0-SFC_COORD||y>SFC_COORD||z<0-SFC_COORD||z>SFC_COORD{return SFC_DOMAIN} 15 var i:i64=0;while i<9{if t[i]<0-SFC_COORD||t[i]>SFC_COORD{return SFC_DOMAIN};i=i+1} 16 let e0:i64=(t[4]-t[1])*(z-t[2])-(t[5]-t[2])*(y-t[1]) 17 let e1:i64=(t[7]-t[4])*(z-t[5])-(t[8]-t[5])*(y-t[4]) 18 let e2:i64=(t[1]-t[7])*(z-t[8])-(t[2]-t[8])*(y-t[7]) 19 let den:i64=e0+e1+e2;if den==0{return 0};var sg:i64=1;if den<0{sg=-1} 20 if e0*sg<0||e1*sg<0||e2*sg<0{return 0} 21 if e0==0&&sfc_edge_owned(t[1],t[2],t[4],t[5],sg)==0{return 0} 22 if e1==0&&sfc_edge_owned(t[4],t[5],t[7],t[8],sg)==0{return 0} 23 if e2==0&&sfc_edge_owned(t[7],t[8],t[1],t[2],sg)==0{return 0} 24 x[0]=(e1*t[0]+e2*t[3]+e0*t[6])/den;return 1 25} 26// Triangle counts partition the complete stream into explicitly identified closed solids. 27// Caller must separately qualify mesh closure; column odd parity refuses, never repairs. 28func sfc_mesh_column_v1(tri:*i64,nt:i64,part_tris:*i64,np:i64,y:i64,z:i64,budget:i64,out:*NxBufOwned,e:*SfuFailure)->i64{ 29 if (e as i64)<=0{return SFU_INVALID};e.code=0;e.part=-1;e.crossing=-1;if nt<0||np<0||nt>NX_BO_I64_MAX/72||np>(NX_BO_I64_MAX-8)/8{return sfu_fail(e,SFU_RESOURCE,-1,-1)} 30 if budget<0||nx_bo_state(out)!=0{return sfu_fail(e,SFU_INVALID,-1,-1)};if out.cap!=0{return sfu_fail(e,SFU_INVALID,-1,-1)} 31 if nt>0&&(tri as i64)<=0{return sfu_fail(e,SFU_INVALID,-1,-1)};if np>0&&(part_tris as i64)<=0{return sfu_fail(e,SFU_INVALID,-1,-1)} 32 var p:i64=0;var n:i64=0;while p<np{let c:i64=part_tris[p];if c<0||c>nt-n{return sfu_fail(e,SFU_INVALID,p,c)};n=n+c;p=p+1};if n!=nt{return sfu_fail(e,SFU_INVALID,np,n)} 33 if nt>0{if np==0{return sfu_fail(e,SFU_INVALID,-1,-1)}}else{return sfu_union_v1(tri,0,part_tris,np,budget,out,e)} 34 if nt> (NX_BO_I64_MAX-np*8-8)/16{return sfu_fail(e,SFU_RESOURCE,-1,-1)} 35 let peak:i64=nt*16+np*8+8;if budget>0&&peak>budget{return sfu_fail(e,SFU_RESOURCE,-1,peak)} 36 let temp_bytes:i64=nt*8+np*8+8;let temp:*u8=sys_mmap_try(temp_bytes);if (temp as i64)<=0{return sfu_fail(e,SFU_ALLOCATION,-1,temp_bytes)} 37 let hits:*i64=temp as *i64;let counts:*i64=(temp+nt*8) as *i64 38 let scratch:*i64=(temp+nt*8+np*8) as *i64 39 var ti:i64=0;var nh:i64=0;p=0;var rc:i64=0 40 while p<np&&rc==0{let start:i64=nh;var j:i64=0;while j<part_tris[p]&&rc==0{let r:i64=sfc_cross_v1((tri as *u8+ti*72) as *i64,y,z,scratch) 41 if r<0{rc=sfu_fail(e,r,p,ti)}else{if r==1{hits[nh]=scratch[0];nh=nh+1}};ti=ti+1;j=j+1} 42 nx_sort_insertion((temp+start*8) as *i64,nh-start);var k:i64=0;counts[p]=nh-start;k=start+1;while k<nh&&rc==0{if hits[k]==hits[k-1]{rc=sfu_fail(e,SFC_PRECISION,p,k-start)};k=k+1};p=p+1} 43 if rc==0{var remaining:i64=0;if budget>0{remaining=budget-temp_bytes};rc=sfu_union_v1(hits,nh,counts,np,remaining,out,e)} 44 sys_munmap_direct(temp,temp_bytes);return rc 45}