Replace bounding-box push with analytical polygon directional-distance so parts nestle together based on actual cut geometry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2.8 KiB
Geometry-Based Push
Problem
PlateView.PushSelected uses bounding boxes to determine how far to slide parts. For irregular shapes, this leaves large gaps between actual cut geometry. Parts should nestle together based on their true shape.
Behavior
When pushing a selected part in a cardinal direction:
- The moving part's geometry is offset outward by
Plate.PartSpacing(the kerf buffer) - That offset geometry slides until it touches the actual cut geometry of stationary parts (zero gap between offset and cut)
- The actual cut paths end up separated by exactly
PartSpacing - For plate edges: the actual geometry bounding box stops at the work area boundary (no offset applied to edges — same as current behavior)
Algorithm: Analytical Polygon Directional-Distance
Conversion Pipeline
Part.Program → ConvertProgram.ToGeometry() → Helper.GetShapes() → Shape.ToPolygon() → Polygon.ToLines()
For the moving part, insert an offset step after getting shapes:
shapes → Shape.OffsetEntity(PartSpacing, OffsetSide.Left) → ToPolygon() → ToLines()
Directional Distance
For a given push direction, compute the minimum translation distance before any edge of the offset moving polygon contacts any edge of a stationary polygon.
Three cases per polygon pair:
- Moving vertex → stationary edge: For each vertex of the offset polygon, cast a ray in the push direction. Find where it crosses a stationary edge. Record the distance.
- Stationary vertex → moving edge: For each vertex of the stationary polygon, cast a ray in the opposite direction. Find where it crosses an offset-moving edge. Record the distance.
- Edge-edge sliding contact: For non-parallel edge pairs, compute the translation distance along the push axis where they first intersect.
The minimum positive distance across all cases and all polygon pairs is the push distance.
Early-Out
Before polygon math, check bounding box overlap on the perpendicular axis. If a stationary part's bounding box doesn't overlap the moving part's bounding box on the axis perpendicular to the push direction, skip that pair.
Changes
| File | Change |
|---|---|
OpenNest.Core\Helper.cs |
Add DirectionalDistance(List<Line>, List<Line>, PushDirection) |
OpenNest.Core\Helper.cs |
Add RayEdgeDistance(Vector, Line, PushDirection) helper |
OpenNest\Controls\PlateView.cs |
Rewrite PushSelected to use polygon directional-distance |
What stays the same
- Plate edge distance check (actual bounding box vs work area)
- Key bindings (X/Y/Shift combinations)
- Existing
ClosestDistance*methods remain (may be used elsewhere)
What changes
PushSelectedconverts parts to polygons instead of using bounding boxes- Distance calculation uses actual geometry edges instead of box edges