Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 43 additions & 12 deletions lib/solvers/PortPointPathingSolver/getConnectionsWithNodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,48 @@ export interface GetConnectionsWithNodesResult {
connectionNameToGoalNodeIds: Map<string, CapacityMeshNodeId[]>
}

const getDistanceToNodeBox = (
point: { x: number; y: number },
node: InputNodeWithPortPoints,
) => {
const minX = node.center.x - node.width / 2
const maxX = node.center.x + node.width / 2
const minY = node.center.y - node.height / 2
const maxY = node.center.y + node.height / 2

const dx = point.x < minX ? minX - point.x : point.x > maxX ? point.x - maxX : 0
const dy = point.y < minY ? minY - point.y : point.y > maxY ? point.y - maxY : 0

return Math.sqrt(dx * dx + dy * dy)
}

const getNodeForConnectionPoint = (
point: { x: number; y: number },
nodesWithTargets: InputNodeWithPortPoints[],
) => {
let bestNode = nodesWithTargets[0]
let bestBoxDistance = Number.MAX_VALUE
let bestCenterDistance = Number.MAX_VALUE

for (const node of nodesWithTargets) {
const boxDistance = getDistanceToNodeBox(point, node)
const centerDistance = Math.sqrt(
(node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2,
)

if (
boxDistance < bestBoxDistance ||
(boxDistance === bestBoxDistance && centerDistance < bestCenterDistance)
) {
bestNode = node
bestBoxDistance = boxDistance
bestCenterDistance = centerDistance
}
}

return bestNode
}

/**
* Computes the connections with their node assignments and goal node IDs.
* This returns the unshuffled connections - shuffling should be done separately
Expand All @@ -29,18 +71,7 @@ export function getConnectionsWithNodes(
const nodesForConnection: InputNodeWithPortPoints[] = []

for (const point of connection.pointsToConnect) {
let closestNode = inputNodes[0]
let minDistance = Number.MAX_VALUE

for (const node of nodesWithTargets) {
const dist = Math.sqrt(
(node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2,
)
if (dist < minDistance) {
minDistance = dist
closestNode = node
}
}
const closestNode = getNodeForConnectionPoint(point, nodesWithTargets)
nodesForConnection.push(closestNode)
}

Expand Down
50 changes: 50 additions & 0 deletions tests/bugs/get-connections-with-nodes-prefers-box-distance.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { expect, test } from "bun:test"
import { getConnectionsWithNodes } from "lib/solvers/PortPointPathingSolver/getConnectionsWithNodes"
import type { SimpleRouteJson } from "lib/types"
import type { InputNodeWithPortPoints } from "lib/solvers/PortPointPathingSolver/PortPointPathingSolver"

test("getConnectionsWithNodes prefers node box distance over center distance", () => {
const simpleRouteJson: SimpleRouteJson = {
layerCount: 2,
minTraceWidth: 0.2,
minViaDiameter: 0.4,
obstacles: [],
connections: [
{
name: "conn-1",
pointsToConnect: [
{ x: 2.1, y: 0, layer: "top" },
{ x: 0, y: 0, layer: "top" },
],
},
],
}

const inputNodes: InputNodeWithPortPoints[] = [
{
capacityMeshNodeId: "A",
center: { x: 0, y: 0 },
width: 1,
height: 1,
availableZ: [0, 1],
portPoints: [],
_containsTarget: true,
},
{
capacityMeshNodeId: "B",
center: { x: 5, y: 0 },
width: 6,
height: 2,
availableZ: [0, 1],
portPoints: [],
_containsTarget: true,
},
]

const { unshuffledConnectionsWithResults } = getConnectionsWithNodes(
simpleRouteJson,
inputNodes,
)

expect(unshuffledConnectionsWithResults[0].nodeIds[0]).toBe("B")
})
Loading