← report · parts, clean 10k (renders of A and B) · middle slices

Fitted contours on point clouds: A vs B

2026-10-28 · clean 10k clouds (pointclouds/*_clean_10000.ply) · prototypes in scripts/ringfit.py, package untouched · slices: scripts/compare_slices.py, tables: report/ringfit_table_clean_10000.txt.

Verdict. Neither is a win yet. A works and is safe, but it only cleans the geometry of rings whose topology the slicer already decided, so it cannot reduce the parts: its counts and errors stay within a few percent of the package. B is the only one that attacks the cause (the topology of thin walls), but as built it is not usable: it loses whole layers and draws wild contours, with 3–10× the package's error. B is the more promising direction, A the more mature component; the useful product is probably B's topology with A's fitting, once B gets a proper 2D curve reconstruction instead of the angle ordering used here.

What the two do

Both replace the slicer's traced polylines with contours fitted to the points: for every layer, the points within a spacing of the plane are moved onto it along the surface (a point is used only when that move is under ¾ spacing, so slanted and near-horizontal surfaces count only near the plane), each contour is x(t), y(t) with Neff = min(16, (n/3 − 1)/2) harmonics for its n points (regularised by the point count, plus a light ridge on the high harmonics), and each point's t comes from its projection on the current fit (4 rounds). The fitted contours then go through the package's tracking, cuts and atom selection unchanged.

Results, clean 10k

tracks / parts / mean distance over the diagonal (×10⁻³). Mesh parts for reference. Red: error ≥ 2× the package's.

objectmesh partspackageA ringfitB graph
battery43 / 6 / 3.463 / 5 / 3.5510 / 17 / 26.3
dress1710 / 17 / 3.1914 / 22 / 3.4310 / 21 / 10.4
elephant2725 / 32 / 4.2926 / 31 / 4.157 / 17 / 21.1
bowl (ObjectFolder)512 / 14 / 2.6912 / 14 / 3.207 / 13 / 26.3
bowl (GSO)618 / 20 / 2.7518 / 20 / 3.1615 / 20 / 28.2
mug89 / 13 / 3.008 / 12 / 3.008 / 17 / 14.0
dino2518 / 27 / 2.4719 / 28 / 2.6519 / 28 / 11.1
shoe2217 / 30 / 7.7415 / 30 / 7.8823 / 36 / 14.3
loaf pan756 / 74 / 16.652 / 68 / 16.333 / 36 / 27.9
horse189 / 16 / 2.339 / 19 / 2.3916 / 26 / 9.6

B's lower part counts on the loaf pan (36) and the elephant (17) are not progress: they come from layers it lost, not from better tracking — the errors show it.

What the slices show

Each comparison page shows, per layer, the slicer's rings, A and B over GT (black) and the slab's points (grey): GSO bowl · loaf pan · battery · dino · shoe.

A: clean shapes, the slicer's topology

B: the right idea, a fragile implementation

Which is more promising

B, but not as it stands. Everything A can do is bounded by the slicer's topology, and the topology is the problem: at 10k the excess parts are tracks (GSO bowl 18 against 3, loaf pan 56 against 2), which no fitting of shapes removes. B is the only one of the two that can fix them, and on the layers where its sheets close it already does. Its four failures are all in the parts I simplified, not in the idea:

  1. the order of a sheet's points: replace the angle around the centre by a real curve reconstruction of the slab's points with normals (e.g. the nearest-neighbour crust, or a shortest cycle through the sheet's k-NN graph), which handles non-convex, elongated and stepped sections;
  2. open sheets: pair the two faces of a thin wall (opposite normals, a wall's width apart) into one ring (the crescent), and close a sheet across a gap under a few spacings instead of dropping it;
  3. solid or hole from the orientation of the reconstructed curve (signed area against the normals), not from the centre;
  4. a fallback per layer to A (the slicer's topology) where B's contours do not explain the points, so B can never lose a layer.

The honest risk: at 10k some walls are thinner than the spacing (47 % of the loaf pan's surface). There even a perfect reconstruction relies on the normals alone to separate the faces, and where the slicer's normals are wrong, B is wrong too. A's fitting step is worth keeping either way: it is the right last stage for whichever topology wins.