nx_polygon.nx
buildroot/runtime/nx_polygon.nx
about
nx_polygon.nx -- 2D polygon primitive with foundational ops +
constant-distance Minkowski offset. Foundational substrate for
the slicer pipeline (per NISHI_3D_PRINT_ROADMAP §2-3): every
slice contour, every perimeter loop, every infill region is an
NxPolygon manipulated through this primitive.
Distinct from:
nx_poly.nx -- polynomial algebra (p[0] + p[1]*x + ...)
nx_geom.nx -- Hough transform (vision-pipeline geometry)
nx_polyline -- (does not exist; if we add open polylines they
go in a separate primitive)
Coordinate convention: Q14 fixed-point xy. 1 Q14 unit = 1/16384.
Matches nx_mesh + nx_stl pipeline so slice contours derived from
triangle-plane intersections compose without unit conversion.
Winding convention: CCW = solid (positive signed area), CW = hole
(negative signed area). Same convention as nx_mesh (face front),
most CAD systems, and the SVG / PDF / PostScript "fill rule".
Per cardinal feedback-bits-up-exceed-never-match: composes the
substrate's nx_isqrt (Q14 sqrt for unit-normal computation) +
nx_i128 (overflow protection in line-line intersection). No
CGAL, no libigl, no Boost.Geometry.
Numerical robustness:
- Foundational ops (area, point-in-poly, segment-intersect) use
pure i64 arithmetic with cross-multiplication to avoid divides.
- Coordinate magnitudes ≤ 325 mm * 16384 ≈ 2^23 (Qidi X-Max 3
build volume). Products of two coord-deltas ≤ 2^46. Sums
of cross-products ≤ ~2^47. All fit in i64.
- Offset uses nx_i128 for the t_num * edge_delta product in
line-line intersection (would be 2^70 in i64, overflows).
Per cardinal feedback-real-playtest-loop-not-just-logs: smoke
passes are necessary but not sufficient. Offset on degenerate
polygons (180-degree vertices, near-180 acute corners, near-
collinear edges) needs print-evidence validation before claiming
S-class.
dependencies 3 imports · 20 importers
diagram shows first 10 each side; +0 more imports, +10 more importers in the complete lists below.
imports: nx_syscalls.nxnx_isqrt.nxnx_i128.nx
imported by: nx_bedmesh_emit_test.nxnx_gcode_arc_test.nxnx_gcode_brim_test.nxnx_gcode_emit.nxnx_gcode_emit_test.nxnx_infill.nxnx_infill_test.nxnx_polygon_test.nxnx_print_exceed_compose_test.nxnx_slice_auto_supports.nxnx_slice_auto_supports_test.nxnx_slice_bridge.nxnx_slice_bridge_gate.nxnx_slice_contour.nxnx_slice_contour_test.nxnx_slice_pipeline.nxnx_supports.nxnx_supports_physics_test.nxnx_supports_test.nxnx_supports_v2_test.nx
structs
| 76 | struct NxPolygon |
consts
| 47 | const NX_POLYGON_VERT_STRIDE: i64 = 16 // 2 × i64 per vertex (x, y) |
| 48 | const NX_POLYGON_Q14_ONE: i64 = 16384 |
| 52 | const NX_POLYGON_OK: i64 = 0 |
| 53 | const NX_POLYGON_ERR_TOO_FEW_VERTS: i64 = 1 |
| 54 | const NX_POLYGON_ERR_DEGENERATE_EDGE: i64 = 2 |
| 55 | const NX_POLYGON_ERR_OFFSET_COLLAPSED: i64 = 3 |
| 56 | const NX_POLYGON_ERR_CAPACITY: i64 = 4 |
| 57 | const NX_POLYGON_N_VERDICTS: i64 = 5 |
| 82 | const NX_POLYGON_BYTES: i64 = 24 |
functions
| 59 | func nx_polygon_verdict_is_valid(v: i64) -> i64 |
| 65 | func nx_polygon_verdict_name(v: i64) -> *u8 |
| 86 | func nx_polygon_alloc(capacity: i64) -> *NxPolygon called by 7: mainmainnx_polygon_offsetnx_polygon_make_squaremainnx_slice_walk_one+1 calls 1: sys_mmap |
| 95 | func nx_polygon_vert_ptr(p: *NxPolygon, i: i64) -> *i64 |
| 99 | func nx_polygon_get_x(p: *NxPolygon, i: i64) -> i64 |
| 104 | func nx_polygon_get_y(p: *NxPolygon, i: i64) -> i64 |
| 109 | func nx_polygon_set_vert(p: *NxPolygon, i: i64, x: i64, y: i64) -> i64 |
| 118 | func nx_polygon_add_vert(p: *NxPolygon, x: i64, y: i64) -> i64 |
| 134 | func nx_polygon_signed_2area_q28_hi(p: *NxPolygon) -> i64 |
| 164 | func nx_polygon_signed_2area_q28(p: *NxPolygon) -> i64 |
| 184 | func nx_polygon_is_ccw(p: *NxPolygon) -> i64 |
| 191 | func nx_polygon_bbox(p: *NxPolygon, out: *i64) -> i64 |
| 219 | func nx_polygon_point_inside(p: *NxPolygon, x: i64, y: i64) -> i64 |
| 260 | func nx_polygon_orient(ax: i64, ay: i64, bx: i64, by: i64, |
| 274 | func nx_polygon_segments_cross(ax: i64, ay: i64, bx: i64, by: i64, |
| 305 | func nx_polygon_offset(in_poly: *NxPolygon, d_q14: i64) -> *NxPolygon |
| 400 | func nx_polygon_make_square(x_min_q14: i64, y_min_q14: i64, |
| 428 | func nx_polygon_3point_circle(x1: i64, y1: i64, |
| 479 | func nx_polygon_point_on_circle(cx: i64, cy: i64, r_sq_q28: i64, |
| 501 | func nx_polygon_arc_winding(cx: i64, cy: i64, called by 1: nx_gemit_polygon |