code wiki / (root) / nx_anatomy_placement.nx

nx_anatomy_placement.nx source

↩ module page · 147 lines · 6895 B

1// nx_anatomy_placement.nx -- out-of-place anatomy verification. 2// 3// Image #56 failure class: nipple rendered at a location that doesn't 4// match where the breast tissue actually projects. The nipple has to 5// be ON the breast mound, near the projection peak, slightly above 6// midline horizontally. Same problem for areola-on-nipple, navel-on- 7// torso-midline, pubic-mound-on-pelvis, etc. 8// 9// The substrate measures the DISTANCE between an anatomical feature's 10// observed centroid and its CANONICAL ZONE (computed from the parent 11// region's bbox + canon ratios). Outside the zone = OUT_OF_PLACE. 12// 13// Canon zones (per Loomis figure-drawing canon): 14// nipple on breast: centered horizontally on breast, 15// vertically at 0.55-0.70 of breast height from top 16// areola on nipple: concentric with nipple centroid 17// navel on torso: horizontal midline, vertical 0.50-0.60 from top of torso 18// pubic mound: horizontal midline, vertical 0.85-0.95 from top of torso 19// 20// Sealed verdict ladder: 21// OUT_OF_PLACE distance > 50% of parent dimension 22// SLIGHTLY_OFF 25-50% 23// CORRECT < 25% from expected zone 24 25// nx_safety_envelope: 26// intended_use: AUTO_APPLIED -- primitive-specific tuning queued 27// sil_target: SIL1 28// evidence: [bulk_applied_2026-05-16, see-file-comment-for-detail] 29// verdict: NOT_YET_EVALUATED 30 31import "nx_syscalls.nx" 32const NX_MAGIC_1024: i64 = 1024 33 34const NX_PLACE_RES_DIST_X_Q10: i64 = 0 // horizontal off-target Q10 (1024 = parent width) 35const NX_PLACE_RES_DIST_Y_Q10: i64 = 1 36const NX_PLACE_RES_DIST_TOTAL_Q10: i64 = 2 // euclidean approx (max(dx, dy)) 37const NX_PLACE_RES_VERDICT: i64 = 3 38const NX_PLACE_RES_FIELDS: i64 = 4 39 40const NX_PLACE_OUT_OF_PLACE: i64 = 0 41const NX_PLACE_SLIGHTLY_OFF: i64 = 1 42const NX_PLACE_CORRECT: i64 = 2 43 44// Canon zones (Q10 fractions of parent bbox). 45const NX_PLACE_NIPPLE_X_CENTER: i64 = 512 // 0.50 = horizontal center 46const NX_PLACE_NIPPLE_X_TOL: i64 = 102 // ±10% horizontally 47const NX_PLACE_NIPPLE_Y_MIN: i64 = 563 // 0.55 from top 48const NX_PLACE_NIPPLE_Y_MAX: i64 = 717 // 0.70 from top 49 50const NX_PLACE_NAVEL_X_CENTER: i64 = 512 51const NX_PLACE_NAVEL_X_TOL: i64 = 51 // ±5% horizontally (tighter) 52const NX_PLACE_NAVEL_Y_MIN: i64 = 512 53const NX_PLACE_NAVEL_Y_MAX: i64 = 614 54 55const NX_PLACE_PUBIC_X_CENTER: i64 = 512 56const NX_PLACE_PUBIC_X_TOL: i64 = 51 57const NX_PLACE_PUBIC_Y_MIN: i64 = 870 58const NX_PLACE_PUBIC_Y_MAX: i64 = 973 59 60// Generic placement scorer. 61// parent_x0..parent_y1 — bbox of parent region (e.g. breast) 62// feature_cx, feature_cy — observed centroid of feature (e.g. nipple) 63// expected_x_center_q10 — target X position as Q10 fraction of parent width 64// expected_x_tol_q10 — horizontal tolerance Q10 65// expected_y_min_q10 — vertical lower bound Q10 of parent height 66// expected_y_max_q10 — vertical upper bound Q10 67// result — pre-allocated NX_PLACE_RES_FIELDS i64 array 68func nx_anatomy_placement_score(parent_x0: i64, parent_y0: i64, 69 parent_x1: i64, parent_y1: i64, 70 feature_cx: i64, feature_cy: i64, 71 expected_x_center_q10: i64, 72 expected_x_tol_q10: i64, 73 expected_y_min_q10: i64, 74 expected_y_max_q10: i64, 75 result: *i64) -> i64 { 76 var i: i64 = 0 77 while i < NX_PLACE_RES_FIELDS { result[i] = 0; i = i + 1 } 78 79 let parent_w: i64 = parent_x1 - parent_x0 80 let parent_h: i64 = parent_y1 - parent_y0 81 if parent_w <= 0 { return 1 } 82 if parent_h <= 0 { return 2 } 83 84 // Convert observed centroid to Q10 fraction of parent bbox. 85 let feat_x_q10: i64 = ((feature_cx - parent_x0) * NX_MAGIC_1024) / parent_w 86 let feat_y_q10: i64 = ((feature_cy - parent_y0) * NX_MAGIC_1024) / parent_h 87 88 // Horizontal distance from expected center. 89 var dx: i64 = feat_x_q10 - expected_x_center_q10 90 if dx < 0 { dx = -dx } 91 var dx_off: i64 = 0 92 if dx > expected_x_tol_q10 { dx_off = dx - expected_x_tol_q10 } 93 result[NX_PLACE_RES_DIST_X_Q10] = dx_off 94 95 // Vertical distance from expected band. 96 var dy_off: i64 = 0 97 if feat_y_q10 < expected_y_min_q10 { dy_off = expected_y_min_q10 - feat_y_q10 } 98 if feat_y_q10 > expected_y_max_q10 { dy_off = feat_y_q10 - expected_y_max_q10 } 99 result[NX_PLACE_RES_DIST_Y_Q10] = dy_off 100 101 // Total = max for L∞ distance (cheap proxy for euclidean). 102 var total: i64 = dx_off 103 if dy_off > total { total = dy_off } 104 result[NX_PLACE_RES_DIST_TOTAL_Q10] = total 105 106 var verdict: i64 = NX_PLACE_CORRECT 107 if total > 256 { verdict = NX_PLACE_SLIGHTLY_OFF } 108 if total > 512 { verdict = NX_PLACE_OUT_OF_PLACE } 109 result[NX_PLACE_RES_VERDICT] = verdict 110 return 0 111} 112 113// Convenience wrapper: nipple on breast. 114func nx_nipple_on_breast_check(breast_x0: i64, breast_y0: i64, 115 breast_x1: i64, breast_y1: i64, 116 nipple_cx: i64, nipple_cy: i64, 117 result: *i64) -> i64 { 118 return nx_anatomy_placement_score(breast_x0, breast_y0, breast_x1, breast_y1, 119 nipple_cx, nipple_cy, 120 NX_PLACE_NIPPLE_X_CENTER, NX_PLACE_NIPPLE_X_TOL, 121 NX_PLACE_NIPPLE_Y_MIN, NX_PLACE_NIPPLE_Y_MAX, 122 result) 123} 124 125// Convenience wrapper: navel on torso. 126func nx_navel_on_torso_check(torso_x0: i64, torso_y0: i64, 127 torso_x1: i64, torso_y1: i64, 128 navel_cx: i64, navel_cy: i64, 129 result: *i64) -> i64 { 130 return nx_anatomy_placement_score(torso_x0, torso_y0, torso_x1, torso_y1, 131 navel_cx, navel_cy, 132 NX_PLACE_NAVEL_X_CENTER, NX_PLACE_NAVEL_X_TOL, 133 NX_PLACE_NAVEL_Y_MIN, NX_PLACE_NAVEL_Y_MAX, 134 result) 135} 136 137// Convenience wrapper: pubic mound on torso lower-band. 138func nx_pubic_on_torso_check(torso_x0: i64, torso_y0: i64, 139 torso_x1: i64, torso_y1: i64, 140 pubic_cx: i64, pubic_cy: i64, 141 result: *i64) -> i64 { 142 return nx_anatomy_placement_score(torso_x0, torso_y0, torso_x1, torso_y1, 143 pubic_cx, pubic_cy, 144 NX_PLACE_PUBIC_X_CENTER, NX_PLACE_PUBIC_X_TOL, 145 NX_PLACE_PUBIC_Y_MIN, NX_PLACE_PUBIC_Y_MAX, 146 result) 147}