refactor(geometry): move polygon offset callers onto ClipperBridge
Per-entity offsetting left spikes and inverted loops wherever a feature is narrower than the spacing (1.nest), and RemoveSelfIntersections only caught proper crossings. The callers that already flatten to polygons now take a single Clipper region offset instead: - PolygonHelper (BestFit) and PartBoundary use the conservative mode, which keeps their never-under-estimate guarantee. PartBoundary also keeps holes that appear when a perimeter curls back on itself. - NestValidator offsets perimeter and cutouts in one region; Clipper drops collapsed cutouts, so the collapsed-or-flipped heuristic goes away. - CutOff.IntersectPerimeter offsets through the bridge. The old OffsetEntity(Left) grew CW perimeters but shrank CCW ones, so with the plate's perimeter cache a cut-off ran through the part; slots narrower than twice the clearance now close up instead of leaving a gap. - GetOffsetPartLines (3 overloads) and the AddOffset* helpers had no callers and are removed, as is EntityView's never-defined DRAW_OFFSET block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,7 @@ namespace OpenNest
|
||||
|
||||
/// <summary>
|
||||
/// Returns the perimeter entities (Line, Arc, Circle) with spacing offset applied,
|
||||
/// without tessellation. Much faster than GetOffsetPartLines for parts with many arcs.
|
||||
/// without tessellation, which keeps arc-heavy parts fast in directional-distance loops.
|
||||
/// </summary>
|
||||
public static List<Entity> GetOffsetPerimeterEntities(Part part, double spacing)
|
||||
{
|
||||
@@ -149,75 +149,6 @@ namespace OpenNest
|
||||
return result;
|
||||
}
|
||||
|
||||
public static List<Line> GetOffsetPartLines(
|
||||
Part part,
|
||||
double spacing,
|
||||
double chordTolerance = 0.001,
|
||||
bool perimeterOnly = false
|
||||
)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var profile = new ShapeProfile(
|
||||
entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()
|
||||
);
|
||||
var lines = new List<Line>();
|
||||
var totalSpacing = spacing;
|
||||
|
||||
AddOffsetLines(
|
||||
lines,
|
||||
profile.Perimeter.OffsetOutward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location
|
||||
);
|
||||
|
||||
if (!perimeterOnly)
|
||||
{
|
||||
foreach (var cutout in profile.Cutouts)
|
||||
AddOffsetLines(
|
||||
lines,
|
||||
cutout.OffsetInward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location
|
||||
);
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static List<Line> GetOffsetPartLines(
|
||||
Part part,
|
||||
double spacing,
|
||||
PushDirection facingDirection,
|
||||
double chordTolerance = 0.001
|
||||
)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var profile = new ShapeProfile(
|
||||
entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()
|
||||
);
|
||||
var lines = new List<Line>();
|
||||
var totalSpacing = spacing;
|
||||
|
||||
AddOffsetDirectionalLines(
|
||||
lines,
|
||||
profile.Perimeter.OffsetOutward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location,
|
||||
facingDirection
|
||||
);
|
||||
|
||||
foreach (var cutout in profile.Cutouts)
|
||||
AddOffsetDirectionalLines(
|
||||
lines,
|
||||
cutout.OffsetInward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location,
|
||||
facingDirection
|
||||
);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static List<Line> GetPartLines(
|
||||
Part part,
|
||||
Vector facingDirection,
|
||||
@@ -240,40 +171,6 @@ namespace OpenNest
|
||||
return lines;
|
||||
}
|
||||
|
||||
public static List<Line> GetOffsetPartLines(
|
||||
Part part,
|
||||
double spacing,
|
||||
Vector facingDirection,
|
||||
double chordTolerance = 0.001
|
||||
)
|
||||
{
|
||||
var entities = ConvertProgram.ToGeometry(part.Program);
|
||||
var profile = new ShapeProfile(
|
||||
entities.Where(e => e.Layer != SpecialLayers.Rapid).ToList()
|
||||
);
|
||||
var lines = new List<Line>();
|
||||
var totalSpacing = spacing;
|
||||
|
||||
AddOffsetDirectionalLines(
|
||||
lines,
|
||||
profile.Perimeter.OffsetOutward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location,
|
||||
facingDirection
|
||||
);
|
||||
|
||||
foreach (var cutout in profile.Cutouts)
|
||||
AddOffsetDirectionalLines(
|
||||
lines,
|
||||
cutout.OffsetInward(totalSpacing),
|
||||
chordTolerance,
|
||||
part.Location,
|
||||
facingDirection
|
||||
);
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns only polygon edges whose outward normal faces the specified direction vector.
|
||||
/// </summary>
|
||||
@@ -353,55 +250,5 @@ namespace OpenNest
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private static void AddOffsetLines(
|
||||
List<Line> lines,
|
||||
Shape offsetEntity,
|
||||
double chordTolerance,
|
||||
Vector location
|
||||
)
|
||||
{
|
||||
if (offsetEntity == null)
|
||||
return;
|
||||
|
||||
var polygon = offsetEntity.ToPolygonWithTolerance(chordTolerance);
|
||||
polygon.RemoveSelfIntersections();
|
||||
polygon.Offset(location);
|
||||
lines.AddRange(polygon.ToLines());
|
||||
}
|
||||
|
||||
private static void AddOffsetDirectionalLines(
|
||||
List<Line> lines,
|
||||
Shape offsetEntity,
|
||||
double chordTolerance,
|
||||
Vector location,
|
||||
PushDirection facingDirection
|
||||
)
|
||||
{
|
||||
if (offsetEntity == null)
|
||||
return;
|
||||
|
||||
var polygon = offsetEntity.ToPolygonWithTolerance(chordTolerance);
|
||||
polygon.RemoveSelfIntersections();
|
||||
polygon.Offset(location);
|
||||
lines.AddRange(GetDirectionalLines(polygon, facingDirection));
|
||||
}
|
||||
|
||||
private static void AddOffsetDirectionalLines(
|
||||
List<Line> lines,
|
||||
Shape offsetEntity,
|
||||
double chordTolerance,
|
||||
Vector location,
|
||||
Vector facingDirection
|
||||
)
|
||||
{
|
||||
if (offsetEntity == null)
|
||||
return;
|
||||
|
||||
var polygon = offsetEntity.ToPolygonWithTolerance(chordTolerance);
|
||||
polygon.RemoveSelfIntersections();
|
||||
polygon.Offset(location);
|
||||
lines.AddRange(GetDirectionalLines(polygon, facingDirection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user