Child of #17: auto-extract 2D profile from segmented planar/axial point regions (prismatic + turned parts) #22

Closed
opened 2026-06-18 19:29:48 +00:00 by Mark · 0 comments
Owner

Parent

Child of #17 (mechanical reconstruction path, the core path of pc2cad). This issue scopes the profile extraction step that the existing reconstruction must perform before any Sketch + extrude or Sketch + revolve composition can happen.

Context

pc2cad's mechanical path needs to produce editable CAD solids from a point scan, not a triangle soup. For the dominant class of mechanical parts — milled/turned/cast pieces — the natural CAD representation is:

  • A 2D sketch (closed profile, lines + arcs)
  • A single sweep operation: extrude() for prismatic 2.5D parts, revolve() for turned/rotational parts
  • A tree of boolean cuts/adds for features (holes, pockets, slots, ribs, fillets, chamfers) layered on top

build123d and FreeCAD both expose this Sketch + Location + extrude/revolve workflow natively. The current pipeline already does primitive RANSAC fitting (plane, cylinder, sphere) and has some profile derivation in pc2cad.py, but the derivation is driven from cross-sections the user effectively supplies implicitly (or from primitives the user already has). For a scanning app — where the user has no CAD, only points — the profile must be recovered from the scan itself.

What's missing

The gap between "I have a point cloud" and "I have a build123d Sketch ready to extrude/revolve":

  1. Profile detection on a planar segment. Given a set of points lying on (or very near) a plane — output of #11's hardened RANSAC — extract the closed 2D boundary of the region as a polygon or as a set of line/arc segments that map to a build123d Sketch. This is the cross-section analysis step, but driven entirely by the points, not by a user cross-section.

  2. Axis detection for revolved parts. For turned parts (shafts, bosses, pulleys, lathe stock), the part is rotationally symmetric. Detect the axis of symmetry from the point cloud, then extract the meridional profile (a 2D curve in the plane containing the axis). This is the input to revolve().

  3. Profile classification: prismatic vs revolved. Decide which sweep operation to emit. Heuristic: a part is revolved iff its point set is approximately axisymmetric (low variance of radial distance at each axial position, constant cross-section shape under rotation). Otherwise extrude.

  4. Tolerance / underdetermined boundary handling. Real scans have noise, missing regions, and density variation (#12). The extracted profile must degrade gracefully: an open polyline, or a polygon with confidence intervals on each edge, not a brittle exact-curve fit that explodes on the first noisy scan.

  5. Composition. Hand the recovered Sketch + Location (plane for extrude, or axis for revolve) to the same exporter path that #6 unblocks for STEP/FCStd. The exporter must know whether to call extrude() or revolve() based on the classification above.

Out of scope (handled by siblings)

  • Export of derived profiles to STEP/FCStd — #6 (the downstream consumer of this work)
  • Plane segmentation quality — #11 (substrate)
  • Input scan quality / units / outliers — #12
  • Adjacency-driven fusing — #13 (related but distinct; profile extraction should not be coupled to it)
  • Hole/feature detection on top of the profile — #14 (a hole is a boolean cut into the swept solid, not part of the profile itself)

User-supplied sketches are explicitly out of scope: this is a scanning app. If the user already had the CAD, the workflow would be different.

Acceptance

  • New module/function in pc2cad.py (or extracted to a sibling module) that, given a segmented planar/axial point region, returns: a build123d Sketch, a Location (plane for extrude, or axis + plane for revolve), and a sweep_op field ∈ {extrude, revolve}.
  • Prismatic test: a synthetic L-bracket or flat plate with a base + step produces a single Sketch + extrude feature.
  • Revolved test: a synthetic shaft with two diameters and a chamfer produces a Sketch + revolve feature.
  • Robustness test: noise (Gaussian sigma = scan spacing), 5% missing points, 1% outliers — pipeline still emits a valid sketch, even if the boundary is a polyline rather than fitted arcs.
  • Integration: the new module's output flows through the export path that #6 unblocks. Combined test: synthetic L-bracket → pc2cad.py end-to-end → STEP file opens in FreeCAD and shows a solid with one feature.
  • Tests added under tests/ covering the three cases above.
  • Documentation update in pointcloud-to-cad-guide.md describing the profile extraction step in the pipeline.

Why this matters

The mechanical reconstruction path (#17) is the product. Without profile extraction, the path is stuck at "list of RANSAC primitives" — which is a description of a part, not an editable CAD model. Profiles + sweep operations are the bridge from description to editable solid. This issue is the missing link between the existing primitive fitter and the export path that #6 unblocks.

## Parent Child of #17 (mechanical reconstruction path, the core path of pc2cad). This issue scopes the **profile extraction** step that the existing reconstruction must perform before any `Sketch + extrude` or `Sketch + revolve` composition can happen. ## Context pc2cad's mechanical path needs to produce editable CAD solids from a point scan, not a triangle soup. For the dominant class of mechanical parts — milled/turned/cast pieces — the natural CAD representation is: - A 2D sketch (closed profile, lines + arcs) - A single sweep operation: `extrude()` for prismatic 2.5D parts, `revolve()` for turned/rotational parts - A tree of boolean cuts/adds for features (holes, pockets, slots, ribs, fillets, chamfers) layered on top build123d and FreeCAD both expose this `Sketch + Location + extrude/revolve` workflow natively. The current pipeline already does primitive RANSAC fitting (plane, cylinder, sphere) and has some profile derivation in `pc2cad.py`, but the derivation is driven from cross-sections the user effectively supplies implicitly (or from primitives the user already has). For a *scanning* app — where the user has no CAD, only points — the profile must be recovered from the scan itself. ## What's missing The gap between "I have a point cloud" and "I have a build123d `Sketch` ready to extrude/revolve": 1. **Profile detection on a planar segment.** Given a set of points lying on (or very near) a plane — output of #11's hardened RANSAC — extract the closed 2D boundary of the region as a polygon or as a set of line/arc segments that map to a build123d `Sketch`. This is the cross-section analysis step, *but driven entirely by the points*, not by a user cross-section. 2. **Axis detection for revolved parts.** For turned parts (shafts, bosses, pulleys, lathe stock), the part is rotationally symmetric. Detect the axis of symmetry from the point cloud, then extract the meridional profile (a 2D curve in the plane containing the axis). This is the input to `revolve()`. 3. **Profile classification: prismatic vs revolved.** Decide which sweep operation to emit. Heuristic: a part is revolved iff its point set is approximately axisymmetric (low variance of radial distance at each axial position, constant cross-section shape under rotation). Otherwise extrude. 4. **Tolerance / underdetermined boundary handling.** Real scans have noise, missing regions, and density variation (#12). The extracted profile must degrade gracefully: an open polyline, or a polygon with confidence intervals on each edge, not a brittle exact-curve fit that explodes on the first noisy scan. 5. **Composition.** Hand the recovered `Sketch` + `Location` (plane for extrude, or axis for revolve) to the same exporter path that #6 unblocks for STEP/FCStd. The exporter must know whether to call `extrude()` or `revolve()` based on the classification above. ## Out of scope (handled by siblings) - **Export of derived profiles to STEP/FCStd** — #6 (the downstream consumer of this work) - **Plane segmentation quality** — #11 (substrate) - **Input scan quality / units / outliers** — #12 - **Adjacency-driven fusing** — #13 (related but distinct; profile extraction should not be coupled to it) - **Hole/feature detection on top of the profile** — #14 (a hole is a boolean cut *into* the swept solid, not part of the profile itself) User-supplied sketches are explicitly out of scope: this is a scanning app. If the user already had the CAD, the workflow would be different. ## Acceptance - New module/function in `pc2cad.py` (or extracted to a sibling module) that, given a segmented planar/axial point region, returns: a build123d `Sketch`, a `Location` (plane for extrude, or axis + plane for revolve), and a `sweep_op` field ∈ {`extrude`, `revolve`}. - Prismatic test: a synthetic L-bracket or flat plate with a base + step produces a single `Sketch + extrude` feature. - Revolved test: a synthetic shaft with two diameters and a chamfer produces a `Sketch + revolve` feature. - Robustness test: noise (Gaussian sigma = scan spacing), 5% missing points, 1% outliers — pipeline still emits a valid sketch, even if the boundary is a polyline rather than fitted arcs. - Integration: the new module's output flows through the export path that #6 unblocks. Combined test: synthetic L-bracket → `pc2cad.py` end-to-end → STEP file opens in FreeCAD and shows a solid with one feature. - Tests added under `tests/` covering the three cases above. - Documentation update in `pointcloud-to-cad-guide.md` describing the profile extraction step in the pipeline. ## Why this matters The mechanical reconstruction path (#17) is the product. Without profile extraction, the path is stuck at "list of RANSAC primitives" — which is a *description* of a part, not an *editable CAD model*. Profiles + sweep operations are the bridge from description to editable solid. This issue is the missing link between the existing primitive fitter and the export path that #6 unblocks.
Mark closed this issue 2026-06-20 16:17:59 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Mark/pc2cad#22
No description provided.