refactor: clean up SpatialQuery duplications and redundancies
Extract ArcToLineClosestDistance helper to eliminate duplicate Phase 3 arc-to-line loops, remove redundant MaxValue guard in curve-to-curve check, consolidate CollectVertices overloads, and add entity-based PushDirection overload for API consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -510,6 +510,17 @@ namespace OpenNest.Geometry
|
|||||||
return minDist;
|
return minDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the minimum translation distance along a push direction
|
||||||
|
/// before any vertex/edge of movingEntities contacts any vertex/edge of
|
||||||
|
/// stationaryEntities. Delegates to the Vector-based overload.
|
||||||
|
/// </summary>
|
||||||
|
public static double DirectionalDistance(
|
||||||
|
List<Entity> movingEntities, List<Entity> stationaryEntities, PushDirection direction)
|
||||||
|
{
|
||||||
|
return DirectionalDistance(movingEntities, stationaryEntities, DirectionToOffset(direction, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the minimum translation distance along an arbitrary unit direction
|
/// Computes the minimum translation distance along an arbitrary unit direction
|
||||||
/// before any vertex/edge of movingEntities contacts any vertex/edge of
|
/// before any vertex/edge of movingEntities contacts any vertex/edge of
|
||||||
@@ -566,43 +577,10 @@ namespace OpenNest.Geometry
|
|||||||
// Phases 1-2 sample arc endpoints and cardinal extremes, but the actual
|
// Phases 1-2 sample arc endpoints and cardinal extremes, but the actual
|
||||||
// closest point on a small corner arc to a straight edge may lie between
|
// closest point on a small corner arc to a straight edge may lie between
|
||||||
// those samples. Use ClosestPointTo to find it and fire a ray from there.
|
// those samples. Use ClosestPointTo to find it and fire a ray from there.
|
||||||
for (var i = 0; i < movingEntities.Count; i++)
|
minDist = ArcToLineClosestDistance(movingEntities, stationaryEntities, dirX, dirY, minDist);
|
||||||
{
|
if (minDist <= 0) return 0;
|
||||||
if (movingEntities[i] is Arc mArc)
|
minDist = ArcToLineClosestDistance(stationaryEntities, movingEntities, oppX, oppY, minDist);
|
||||||
{
|
if (minDist <= 0) return 0;
|
||||||
for (var j = 0; j < stationaryEntities.Count; j++)
|
|
||||||
{
|
|
||||||
if (stationaryEntities[j] is Line sLine)
|
|
||||||
{
|
|
||||||
var linePt = sLine.ClosestPointTo(mArc.Center);
|
|
||||||
var arcPt = mArc.ClosestPointTo(linePt);
|
|
||||||
var d = RayEdgeDistance(arcPt.X, arcPt.Y,
|
|
||||||
sLine.pt1.X, sLine.pt1.Y, sLine.pt2.X, sLine.pt2.Y,
|
|
||||||
dirX, dirY);
|
|
||||||
if (d < minDist) { minDist = d; if (d <= 0) return 0; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < stationaryEntities.Count; i++)
|
|
||||||
{
|
|
||||||
if (stationaryEntities[i] is Arc sArc2)
|
|
||||||
{
|
|
||||||
for (var j = 0; j < movingEntities.Count; j++)
|
|
||||||
{
|
|
||||||
if (movingEntities[j] is Line mLine)
|
|
||||||
{
|
|
||||||
var linePt = mLine.ClosestPointTo(sArc2.Center);
|
|
||||||
var arcPt = sArc2.ClosestPointTo(linePt);
|
|
||||||
var d = RayEdgeDistance(arcPt.X, arcPt.Y,
|
|
||||||
mLine.pt1.X, mLine.pt1.Y, mLine.pt2.X, mLine.pt2.Y,
|
|
||||||
oppX, oppY);
|
|
||||||
if (d < minDist) { minDist = d; if (d <= 0) return 0; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Phase 4: Curve-to-curve direct distance.
|
// Phase 4: Curve-to-curve direct distance.
|
||||||
// The vertex-to-entity approach misses the closest contact between two
|
// The vertex-to-entity approach misses the closest contact between two
|
||||||
@@ -624,7 +602,7 @@ namespace OpenNest.Geometry
|
|||||||
|
|
||||||
var d = RayCircleDistance(mcx, mcy, scx, scy, mr + sr, dirX, dirY);
|
var d = RayCircleDistance(mcx, mcy, scx, scy, mr + sr, dirX, dirY);
|
||||||
|
|
||||||
if (d >= minDist || d == double.MaxValue)
|
if (d >= minDist)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// For arcs, verify the contact point falls within both arcs' angular ranges.
|
// For arcs, verify the contact point falls within both arcs' angular ranges.
|
||||||
@@ -658,6 +636,31 @@ namespace OpenNest.Geometry
|
|||||||
return minDist;
|
return minDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static double ArcToLineClosestDistance(
|
||||||
|
List<Entity> arcEntities, List<Entity> lineEntities,
|
||||||
|
double dirX, double dirY, double minDist)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < arcEntities.Count; i++)
|
||||||
|
{
|
||||||
|
if (arcEntities[i] is Arc arc)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < lineEntities.Count; j++)
|
||||||
|
{
|
||||||
|
if (lineEntities[j] is Line line)
|
||||||
|
{
|
||||||
|
var linePt = line.ClosestPointTo(arc.Center);
|
||||||
|
var arcPt = arc.ClosestPointTo(linePt);
|
||||||
|
var d = RayEdgeDistance(arcPt.X, arcPt.Y,
|
||||||
|
line.pt1.X, line.pt1.Y, line.pt2.X, line.pt2.Y,
|
||||||
|
dirX, dirY);
|
||||||
|
if (d < minDist) { minDist = d; if (d <= 0) return 0; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return minDist;
|
||||||
|
}
|
||||||
|
|
||||||
private static double RayEntityDistance(
|
private static double RayEntityDistance(
|
||||||
double vx, double vy, Entity entity, double dirX, double dirY)
|
double vx, double vy, Entity entity, double dirX, double dirY)
|
||||||
{
|
{
|
||||||
@@ -737,13 +740,7 @@ namespace OpenNest.Geometry
|
|||||||
|
|
||||||
private static HashSet<Vector> CollectVertices(List<Line> lines, Vector offset)
|
private static HashSet<Vector> CollectVertices(List<Line> lines, Vector offset)
|
||||||
{
|
{
|
||||||
var vertices = new HashSet<Vector>();
|
return CollectVertices(ToEdgeArray(lines), offset);
|
||||||
for (var i = 0; i < lines.Count; i++)
|
|
||||||
{
|
|
||||||
vertices.Add(lines[i].pt1 + offset);
|
|
||||||
vertices.Add(lines[i].pt2 + offset);
|
|
||||||
}
|
|
||||||
return vertices;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HashSet<Vector> CollectVertices((Vector start, Vector end)[] edges, Vector offset)
|
private static HashSet<Vector> CollectVertices((Vector start, Vector end)[] edges, Vector offset)
|
||||||
|
|||||||
Reference in New Issue
Block a user