nx_solid_column_union_candidate_t365.nx source
↩ module page · 50 lines · 3394 B
1// Versioned solid-column composition shared by mesh-field consumers.
2// Crossings are sorted, distinct, parity events for each CLOSED part, in caller units.
3// Output is disjoint union intervals; this is not a Euclidean distance field.
4import "nx_buf_dyn.nx"
5import "nx_syscalls.nx"
6import "nx_sort.nx"
7const SFU_INVALID:i64=-701
8const SFU_ODD:i64=-702
9const SFU_ORDER:i64=-703
10const SFU_RESOURCE:i64=-704
11const SFU_ALLOCATION:i64=-705
12struct SfuFailure { code:i64, part:i64, crossing:i64, }
13func sfu_fail(e:*SfuFailure,code:i64,part:i64,crossing:i64)->i64{e.code=code;e.part=part;e.crossing=crossing;return code}
14// In-place workspace path for callers retaining an allocation across many columns.
15// Input contains paired intervals. Caller has already checked each part's parity/order.
16func sfu_merge_workspace_v1(pairs:*i64,nh:i64)->i64{
17 if nh<0||(nh&1)!=0{return SFU_INVALID};if nh==0{return 0}
18 let sorted:i64=nx_sort_pairs_first(pairs,nh/2);if sorted<0{return sorted}
19 var used:i64=2;var i:i64=2;while i<nh{if pairs[i]<=pairs[used-1]{if pairs[i+1]>pairs[used-1]{pairs[used-1]=pairs[i+1]}}else{pairs[used]=pairs[i];pairs[used+1]=pairs[i+1];used=used+2};i=i+2};return used
20}
21func sfu_union_v1(h:*i64,nh:i64,counts:*i64,np:i64,budget:i64,out:*NxBufOwned,e:*SfuFailure)->i64{
22 if (e as i64)<=0{return SFU_INVALID};e.code=0;e.part=-1;e.crossing=-1
23 if nh<0||np<0||budget<0{return sfu_fail(e,SFU_INVALID,-1,-1)}
24 if nx_bo_state(out)!=0{return sfu_fail(e,SFU_INVALID,-1,-1)}
25 if out.cap!=0{return sfu_fail(e,SFU_INVALID,-1,-1)}
26 if nh>NX_BO_I64_MAX/8||np>NX_BO_I64_MAX/8{return sfu_fail(e,SFU_RESOURCE,-1,-1)}
27 if nh>0&&(h as i64)<=0{return sfu_fail(e,SFU_INVALID,-1,-1)}
28 if np>0&&(counts as i64)<=0{return sfu_fail(e,SFU_INVALID,-1,-1)}
29 var off:i64=0;var p:i64=0
30 while p<np{let n:i64=counts[p];if n<0||n>nh-off{return sfu_fail(e,SFU_INVALID,p,n)};if (n&1)!=0{return sfu_fail(e,SFU_ODD,p,n)}
31 var i:i64=1;while i<n{if h[off+i]<=h[off+i-1]{return sfu_fail(e,SFU_ORDER,p,i)};i=i+1};off=off+n;p=p+1}
32 if off!=nh{return sfu_fail(e,SFU_INVALID,np,off)}
33 if nh==0{return 0};let bytes:i64=nh*8;if budget>0&&bytes>budget{return sfu_fail(e,SFU_RESOURCE,-1,bytes)}
34 let raw:*u8=sys_mmap_try(bytes);if (raw as i64)<=0{return sfu_fail(e,SFU_ALLOCATION,-1,bytes)};let pairs:*i64=raw as *i64
35 var i:i64=0;while i<nh{pairs[i]=h[i];i=i+1}
36 let used:i64=sfu_merge_workspace_v1(pairs,nh);if used<0{sys_munmap_direct(raw,bytes);return sfu_fail(e,used,-1,nh/2)}
37 out.buf=raw;out.len=used*8;out.cap=bytes;return 0
38}
39// Exact capped distance to the union boundary ALONG THIS COLUMN, not metric SDF.
40// The symmetric coordinate domain makes every subtraction representable in signed i64.
41const SFU_COORD:i64=4611686018427387903
42func sfu_column_value(intervals:*i64,n:i64,x:i64,far:i64,value:*i64)->i64{
43 if n<0||(n&1)!=0||n>NX_BO_I64_MAX/8||far<=0||x<0-SFU_COORD||x>SFU_COORD{return SFU_INVALID}
44 if (value as i64)<=0{return SFU_INVALID};if n>0&&(intervals as i64)<=0{return SFU_INVALID}
45 var i:i64=0;while i<n{if intervals[i]<0-SFU_COORD||intervals[i]>SFU_COORD{return SFU_INVALID};if i>0{if intervals[i]<=intervals[i-1]{return SFU_ORDER}};i=i+1}
46 var best:i64=far;var inside:i64=0;i=0
47 while i<n{let lo:i64=intervals[i];let hi:i64=intervals[i+1];var d:i64=0
48 if x<lo{d=lo-x}else{if x>hi{d=x-hi}else{inside=1;d=x-lo;if hi-x<d{d=hi-x}}};if d<best{best=d};i=i+2}
49 if inside==1{best=0-best};value[0]=best;return 0
50}