code wiki / (root) / nx_supports_physics_test.nx

nx_supports_physics_test.nx source

↩ module page · 117 lines · 6048 B

1// nx_supports_physics_test.nx -- proves bits-up physics-aware pillar 2// sizing produces DIFFERENT pillar dimensions for DIFFERENT loads 3// within the same plan. Industry baseline (Orca/Bambu/Cura/Prusa) 4// cannot do this -- they emit identical pillars regardless of load. 5// 6// Closed-form invariants: 7// (a) plan_add_pillar_physics with LIGHT load on PLA -> MIN footprint 8// (matches industry baseline at the light end) 9// (b) plan_add_pillar_physics with HEAVY load on PLA -> footprint > MIN 10// (industry would underbuild here) 11// (c) Two pillars in same plan with different loads -> different 12// per-pillar footprints (industry: identical regardless) 13// (d) Same load, stiffer material (PEEK) -> smaller footprint than PLA 14// (industry: identical footprint regardless of material) 15// (e) Emit produces a square that scales with per-pillar footprint 16// (verify by ensuring HEAVY pillar emits a bigger square than 17// a NEAR-BY LIGHT pillar in the same emit pass) 18// (f) Merge policy: heavier load at same XY EXTENDS existing 19// footprint (never shrinks) 20// 21// expect_exit: 0 22// license_tier: ORIGINAL 23 24import "nx_syscalls.nx" 25import "nx_polygon.nx" 26import "nx_machine_graph.nx" 27import "nx_material_profile.nx" 28import "nx_gcode_emit.nx" 29import "nx_pillar_physics.nx" 30import "nx_supports.nx" 31 32const Q14: i64 = 16384 33 34func main() -> i64 { 35 let pla: *NxMaterialProfile = nx_material_profile_generic_pla() 36 let peek: *NxMaterialProfile = nx_material_profile_generic_peek() 37 38 // Plan: 16 pillars, default footprint 2 mm, 1 mm dedup spacing. 39 let plan: *NxSupportPlan = nx_support_plan_new(16, NX_MAT_PILLAR_MIN_FOOT_Q14, Q14) 40 41 // --- (a) Light load on PLA -> MIN footprint --- 42 if nx_support_plan_add_pillar_physics(plan, 43 10 * Q14, 10 * Q14, 5 * Q14, 44 1 * Q14, 1 * Q14, pla) != 0 { return 10 } 45 let p0: *NxSupportPillar = plan.pillars 46 if p0.footprint_q14 != NX_MAT_PILLAR_MIN_FOOT_Q14 { return 11 } 47 48 // --- (b) Heavy load on PLA -> footprint > MIN --- 49 if nx_support_plan_add_pillar_physics(plan, 50 30 * Q14, 30 * Q14, 5 * Q14, 51 10 * Q14, 10 * Q14, pla) != 0 { return 20 } 52 let p1: *NxSupportPillar = (((plan.pillars as i64) + 1 * NX_SUPPORT_PILLAR_BYTES)) as *NxSupportPillar 53 if p1.footprint_q14 <= NX_MAT_PILLAR_MIN_FOOT_Q14 { return 21 } 54 55 // --- (c) Different loads in same plan -> different per-pillar footprints --- 56 if p0.footprint_q14 == p1.footprint_q14 { return 30 } 57 58 // --- (d) Same load, stiffer material -> smaller footprint --- 59 let plan2: *NxSupportPlan = nx_support_plan_new(4, NX_MAT_PILLAR_MIN_FOOT_Q14, Q14) 60 // Heavy load that's NOT clamped to MIN on PLA but might be on PEEK. 61 nx_support_plan_add_pillar_physics(plan2, 0, 0, 5 * Q14, 62 10 * Q14, 10 * Q14, pla) 63 nx_support_plan_add_pillar_physics(plan2, 50 * Q14, 50 * Q14, 5 * Q14, 64 10 * Q14, 10 * Q14, peek) 65 let pla_pillar: *NxSupportPillar = plan2.pillars 66 let peek_pillar: *NxSupportPillar = (((plan2.pillars as i64) + 1 * NX_SUPPORT_PILLAR_BYTES)) as *NxSupportPillar 67 if pla_pillar.footprint_q14 <= peek_pillar.footprint_q14 { return 40 } 68 69 // --- (e) Emit: bigger-footprint pillar -> bigger emitted square. 70 // Verify by emitting from two single-pillar plans separately and 71 // comparing the byte counts (more area -> longer G1 perimeter). 72 let qidi: *NxMachineGraph = nx_machine_graph_qidi_xmax3() 73 let lh: i64 = 3277 74 let lw: i64 = 6554 75 76 let plan_light: *NxSupportPlan = nx_support_plan_new(1, NX_MAT_PILLAR_MIN_FOOT_Q14, Q14) 77 nx_support_plan_add_pillar_physics(plan_light, 0, 0, 5 * Q14, 78 1 * Q14, 1 * Q14, pla) 79 let e_light: *NxGcodeEmitter = nx_gemit_new(qidi, pla, lh, lw, 4096) 80 nx_support_plan_emit_layer(plan_light, e_light, 1 * Q14) 81 82 let plan_heavy: *NxSupportPlan = nx_support_plan_new(1, NX_MAT_PILLAR_MIN_FOOT_Q14, Q14) 83 nx_support_plan_add_pillar_physics(plan_heavy, 0, 0, 5 * Q14, 84 10 * Q14, 10 * Q14, pla) 85 let e_heavy: *NxGcodeEmitter = nx_gemit_new(qidi, pla, lh, lw, 4096) 86 nx_support_plan_emit_layer(plan_heavy, e_heavy, 1 * Q14) 87 88 // Heavy pillar (larger square) -> more coordinate digits per move. 89 // Not always true byte-wise for SAME perimeter count, but the heavy 90 // emit at minimum should NOT be smaller (since the footprint is 91 // strictly larger, X/Y coordinates are larger magnitude). 92 if e_heavy.len < e_light.len { return 50 } 93 94 // --- (f) Merge: heavier load at same XY extends footprint (never shrinks) --- 95 let plan3: *NxSupportPlan = nx_support_plan_new(4, NX_MAT_PILLAR_MIN_FOOT_Q14, Q14) 96 nx_support_plan_add_pillar_physics(plan3, 100 * Q14, 100 * Q14, 5 * Q14, 97 10 * Q14, 10 * Q14, pla) 98 let p3_first: *NxSupportPillar = plan3.pillars 99 let foot_before: i64 = p3_first.footprint_q14 100 101 // Add LIGHTER load at same XY -> should merge (return 1) and 102 // footprint must NOT shrink. 103 let r_light: i64 = nx_support_plan_add_pillar_physics(plan3, 104 100 * Q14, 100 * Q14, 5 * Q14, 105 1 * Q14, 1 * Q14, pla) 106 if r_light != 1 { return 60 } 107 if p3_first.footprint_q14 < foot_before { return 61 } 108 109 // Add HEAVIER load at same XY -> should merge AND extend footprint. 110 let r_heavy: i64 = nx_support_plan_add_pillar_physics(plan3, 111 100 * Q14, 100 * Q14, 10 * Q14, 112 20 * Q14, 20 * Q14, pla) 113 if r_heavy != 1 { return 70 } 114 if p3_first.footprint_q14 <= foot_before { return 71 } 115 116 return 0 117}