nx_slice_plane.nx
buildroot/runtime/nx_slice_plane.nx
about
nx_slice_plane.nx -- intersect a triangle mesh with a Z-plane.
Returns a flat "segment soup" of 2D line segments (Q14 xy) where
each segment is one triangle's intersection with the plane.
This IS the slicer kernel. Bridges nx_mesh + nx_bvh + nx_polygon:
- nx_bvh walk prunes triangles whose AABB doesn't straddle the
plane (the slice-time win lever vs naive O(n_tris) scan)
- per-candidate triangle, compute the 0/1/2 line segments the
plane intersects
- emit segments into a flat soup buffer
Polygon assembly (linking endpoint-shared segments into closed
contours) is a SEPARATE primitive (nx_slice_contour, P2.2) per
Cardinal 9. Slice-plane is one job: mesh -> segment soup.
Per cardinal NISHI_3D_PRINT_ROADMAP §2.7 (incremental slice):
re-slicing on parameter changes with the same mesh reuses the
same BVH; only this kernel re-runs. The win lever vs OrcaSlicer
is: BVH-pruned candidates instead of full-mesh sweep, integer-
only intersection arithmetic (no per-coord float epsilon drift).
Triangle vs plane case analysis (signs s0, s1, s2 of vi.z - plane_z):
all same sign (not zero) -> no intersection
two same sign, one opposite -> one segment from the two
straddled edges
exactly one zero, others opposite -> one segment from the
on-plane vertex to the
straddled edge crossing
exactly one zero, others same sign -> degenerate touch, skip
exactly two zeros -> the triangle edge IS the
segment (already 2D)
all three zero -> coplanar tri, emit no
segment (caller's slicer
handles coplanar surfaces
via a separate "horizontal
face" pass)
Coordinate convention: Q14 fixed-point inherited from nx_mesh.
Plane-edge intersection (no overflow in i64 for slicer-scale coords):
dependencies 4 imports · 18 importers
diagram shows first 10 each side; +0 more imports, +8 more importers in the complete lists below.
imports: nx_syscalls.nxnx_mesh.nxnx_mesh_print_check.nxnx_bvh.nx
imported by: nx_cad_exceed.nxnx_cad_prims2_test.nxnx_cad_test.nxnx_csg_fillet_test.nxnx_csg_scene_gate.nxnx_csg_test.nxnx_csg_torus_test.nxnx_dcc_slice_watertight_gate.nxnx_infill.nxnx_infill_test.nxnx_print_e2e_gate.nxnx_slice_auto_supports.nxnx_slice_contour.nxnx_slice_contour_test.nxnx_slice_layer_probe.nxnx_slice_pipeline.nxnx_slice_plane_test.nxnx_underridge_cleaner_gate.nx
structs
| 74 | struct NxSliceSoup |
consts
| 54 | const NX_SLICE_SEG_STRIDE: i64 = 32 // 4 × i64 per segment (x1,y1,x2,y2) |
| 58 | const NX_SLICE_OK: i64 = 0 |
| 59 | const NX_SLICE_ERR_NULL_MESH: i64 = 1 |
| 60 | const NX_SLICE_ERR_NULL_BVH: i64 = 2 |
| 61 | const NX_SLICE_ERR_CAPACITY: i64 = 3 |
| 62 | const NX_SLICE_N_VERDICTS: i64 = 4 |
| 81 | const NX_SLICE_SOUP_BYTES: i64 = 32 |
functions
| 64 | func nx_slice_verdict_name(v: i64) -> *u8 |
| 83 | func nx_slice_soup_new(capacity: i64) -> *NxSliceSoup |
| 92 | func nx_slice_soup_seg_ptr(s: *NxSliceSoup, i: i64) -> *i64 |
| 96 | func nx_slice_soup_emit(s: *NxSliceSoup, x1: i64, y1: i64, |
| 113 | func nx_slice_edge_at_z(va_x: i64, va_y: i64, va_z: i64, called by 1: nx_slice_one_tri |
| 161 | func nx_slice_one_tri(m: *NxMesh, ti: i64, plane_z: i64, |
| 343 | func nx_slice_walk_node(m: *NxMesh, b: *NxBvh, plane_z: i64, called by 2: nx_slice_walk_nodenx_slice_plane calls 3: nx_bvh_node_atnx_slice_one_trinx_slice_walk_node |
| 367 | func nx_slice_plane(m: *NxMesh, b: *NxBvh, plane_z: i64) -> *NxSliceSoup |