@tscircuit/capacity-autorouter 0.0.29 → 0.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +69 -4
- package/dist/index.js +796 -340
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -85,177 +85,6 @@ var BaseSolver = class {
|
|
|
85
85
|
}
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
// node_modules/@tscircuit/math-utils/dist/chunk-CHQOCSFB.js
|
|
89
|
-
function doSegmentsIntersect(p1, q1, p2, q2) {
|
|
90
|
-
const o1 = orientation(p1, q1, p2);
|
|
91
|
-
const o2 = orientation(p1, q1, q2);
|
|
92
|
-
const o3 = orientation(p2, q2, p1);
|
|
93
|
-
const o4 = orientation(p2, q2, q1);
|
|
94
|
-
if (o1 !== o2 && o3 !== o4) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
98
|
-
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
99
|
-
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
100
|
-
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
function orientation(p, q, r) {
|
|
104
|
-
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
105
|
-
if (val === 0) return 0;
|
|
106
|
-
return val > 0 ? 1 : 2;
|
|
107
|
-
}
|
|
108
|
-
function onSegment(p, q, r) {
|
|
109
|
-
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
110
|
-
}
|
|
111
|
-
function pointToSegmentDistance(p, v, w) {
|
|
112
|
-
const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2;
|
|
113
|
-
if (l2 === 0) return distance(p, v);
|
|
114
|
-
let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
|
|
115
|
-
t = Math.max(0, Math.min(1, t));
|
|
116
|
-
const projection = {
|
|
117
|
-
x: v.x + t * (w.x - v.x),
|
|
118
|
-
y: v.y + t * (w.y - v.y)
|
|
119
|
-
};
|
|
120
|
-
return distance(p, projection);
|
|
121
|
-
}
|
|
122
|
-
function distance(p1, p2) {
|
|
123
|
-
const dx = p1.x - p2.x;
|
|
124
|
-
const dy = p1.y - p2.y;
|
|
125
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// lib/utils/areNodesBordering.ts
|
|
129
|
-
function areNodesBordering(node1, node2) {
|
|
130
|
-
const n1Left = node1.center.x - node1.width / 2;
|
|
131
|
-
const n1Right = node1.center.x + node1.width / 2;
|
|
132
|
-
const n1Top = node1.center.y - node1.height / 2;
|
|
133
|
-
const n1Bottom = node1.center.y + node1.height / 2;
|
|
134
|
-
const n2Left = node2.center.x - node2.width / 2;
|
|
135
|
-
const n2Right = node2.center.x + node2.width / 2;
|
|
136
|
-
const n2Top = node2.center.y - node2.height / 2;
|
|
137
|
-
const n2Bottom = node2.center.y + node2.height / 2;
|
|
138
|
-
const epsilon = 1e-3;
|
|
139
|
-
const shareVerticalBorder = (Math.abs(n1Right - n2Left) < epsilon || Math.abs(n1Left - n2Right) < epsilon) && Math.min(n1Bottom, n2Bottom) - Math.max(n1Top, n2Top) >= epsilon;
|
|
140
|
-
const shareHorizontalBorder = (Math.abs(n1Bottom - n2Top) < epsilon || Math.abs(n1Top - n2Bottom) < epsilon) && Math.min(n1Right, n2Right) - Math.max(n1Left, n2Left) >= epsilon;
|
|
141
|
-
return shareVerticalBorder || shareHorizontalBorder;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver.ts
|
|
145
|
-
var CapacityMeshEdgeSolver = class extends BaseSolver {
|
|
146
|
-
constructor(nodes) {
|
|
147
|
-
super();
|
|
148
|
-
this.nodes = nodes;
|
|
149
|
-
this.edges = [];
|
|
150
|
-
}
|
|
151
|
-
edges;
|
|
152
|
-
getNextCapacityMeshEdgeId() {
|
|
153
|
-
return `ce${this.edges.length}`;
|
|
154
|
-
}
|
|
155
|
-
step() {
|
|
156
|
-
this.edges = [];
|
|
157
|
-
for (let i = 0; i < this.nodes.length; i++) {
|
|
158
|
-
for (let j = i + 1; j < this.nodes.length; j++) {
|
|
159
|
-
const strawNodesWithSameParent = this.nodes[i]._strawNode && this.nodes[j]._strawNode && this.nodes[i]._strawParentCapacityMeshNodeId === this.nodes[j]._strawParentCapacityMeshNodeId;
|
|
160
|
-
if (!strawNodesWithSameParent && areNodesBordering(this.nodes[i], this.nodes[j]) && this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])) {
|
|
161
|
-
this.edges.push({
|
|
162
|
-
capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
|
|
163
|
-
nodeIds: [
|
|
164
|
-
this.nodes[i].capacityMeshNodeId,
|
|
165
|
-
this.nodes[j].capacityMeshNodeId
|
|
166
|
-
]
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
const targetNodes = this.nodes.filter((node) => node._containsTarget);
|
|
172
|
-
for (const targetNode of targetNodes) {
|
|
173
|
-
const hasEdge = this.edges.some(
|
|
174
|
-
(edge) => edge.nodeIds.includes(targetNode.capacityMeshNodeId)
|
|
175
|
-
);
|
|
176
|
-
if (hasEdge) continue;
|
|
177
|
-
let nearestNode = null;
|
|
178
|
-
let nearestDistance = Infinity;
|
|
179
|
-
for (const node of this.nodes) {
|
|
180
|
-
if (node._containsObstacle) continue;
|
|
181
|
-
if (node._containsTarget) continue;
|
|
182
|
-
const dist = distance(targetNode.center, node.center);
|
|
183
|
-
if (dist < nearestDistance) {
|
|
184
|
-
nearestDistance = dist;
|
|
185
|
-
nearestNode = node;
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
if (nearestNode) {
|
|
189
|
-
this.edges.push({
|
|
190
|
-
capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
|
|
191
|
-
nodeIds: [
|
|
192
|
-
targetNode.capacityMeshNodeId,
|
|
193
|
-
nearestNode.capacityMeshNodeId
|
|
194
|
-
]
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
this.solved = true;
|
|
199
|
-
}
|
|
200
|
-
doNodesHaveSharedLayer(node1, node2) {
|
|
201
|
-
return node1.availableZ.some((z) => node2.availableZ.includes(z));
|
|
202
|
-
}
|
|
203
|
-
visualize() {
|
|
204
|
-
const graphics = {
|
|
205
|
-
lines: [],
|
|
206
|
-
points: [],
|
|
207
|
-
rects: this.nodes.map((node) => {
|
|
208
|
-
const lowestZ = Math.min(...node.availableZ);
|
|
209
|
-
return {
|
|
210
|
-
width: Math.max(node.width - 2, node.width * 0.8),
|
|
211
|
-
height: Math.max(node.height - 2, node.height * 0.8),
|
|
212
|
-
center: {
|
|
213
|
-
x: node.center.x + lowestZ * node.width * 0.05,
|
|
214
|
-
y: node.center.y - lowestZ * node.width * 0.05
|
|
215
|
-
},
|
|
216
|
-
fill: node._containsObstacle ? "rgba(255,0,0,0.1)" : {
|
|
217
|
-
"0,1": "rgba(0,0,0,0.1)",
|
|
218
|
-
"0": "rgba(0,200,200, 0.1)",
|
|
219
|
-
"1": "rgba(0,0,200, 0.1)"
|
|
220
|
-
}[node.availableZ.join(",")] ?? "rgba(0,200,200,0.1)",
|
|
221
|
-
label: [
|
|
222
|
-
node.capacityMeshNodeId,
|
|
223
|
-
`availableZ: ${node.availableZ.join(",")}`,
|
|
224
|
-
`target? ${node._containsTarget ?? false}`,
|
|
225
|
-
`obs? ${node._containsObstacle ?? false}`
|
|
226
|
-
].join("\n")
|
|
227
|
-
};
|
|
228
|
-
}),
|
|
229
|
-
circles: []
|
|
230
|
-
};
|
|
231
|
-
for (const edge of this.edges) {
|
|
232
|
-
const node1 = this.nodes.find(
|
|
233
|
-
(node) => node.capacityMeshNodeId === edge.nodeIds[0]
|
|
234
|
-
);
|
|
235
|
-
const node2 = this.nodes.find(
|
|
236
|
-
(node) => node.capacityMeshNodeId === edge.nodeIds[1]
|
|
237
|
-
);
|
|
238
|
-
if (node1?.center && node2?.center) {
|
|
239
|
-
const lowestZ1 = Math.min(...node1.availableZ);
|
|
240
|
-
const lowestZ2 = Math.min(...node2.availableZ);
|
|
241
|
-
const nodeCenter1Adj = {
|
|
242
|
-
x: node1.center.x + lowestZ1 * node1.width * 0.05,
|
|
243
|
-
y: node1.center.y - lowestZ1 * node1.width * 0.05
|
|
244
|
-
};
|
|
245
|
-
const nodeCenter2Adj = {
|
|
246
|
-
x: node2.center.x + lowestZ2 * node2.width * 0.05,
|
|
247
|
-
y: node2.center.y - lowestZ2 * node2.width * 0.05
|
|
248
|
-
};
|
|
249
|
-
graphics.lines.push({
|
|
250
|
-
points: [nodeCenter1Adj, nodeCenter2Adj],
|
|
251
|
-
strokeDash: node1.availableZ.join(",") === node2.availableZ.join(",") ? void 0 : "10 5"
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return graphics;
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
88
|
// node_modules/@babel/runtime/helpers/esm/extends.js
|
|
260
89
|
function _extends() {
|
|
261
90
|
return _extends = Object.assign ? Object.assign.bind() : function(n) {
|
|
@@ -1089,24 +918,6 @@ var safeTransparentize = (color, amount) => {
|
|
|
1089
918
|
}
|
|
1090
919
|
};
|
|
1091
920
|
|
|
1092
|
-
// lib/utils/isPointInRect.ts
|
|
1093
|
-
function isPointInRect(point, rect) {
|
|
1094
|
-
return point.x >= rect.center.x - rect.width / 2 && point.x <= rect.center.x + rect.width / 2 && point.y >= rect.center.y - rect.height / 2 && point.y <= rect.center.y + rect.height / 2;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
// lib/utils/doRectsOverlap.ts
|
|
1098
|
-
function doRectsOverlap(rect1, rect2) {
|
|
1099
|
-
const rect1Left = rect1.center.x - rect1.width / 2;
|
|
1100
|
-
const rect1Right = rect1.center.x + rect1.width / 2;
|
|
1101
|
-
const rect1Top = rect1.center.y - rect1.height / 2;
|
|
1102
|
-
const rect1Bottom = rect1.center.y + rect1.height / 2;
|
|
1103
|
-
const rect2Left = rect2.center.x - rect2.width / 2;
|
|
1104
|
-
const rect2Right = rect2.center.x + rect2.width / 2;
|
|
1105
|
-
const rect2Top = rect2.center.y - rect2.height / 2;
|
|
1106
|
-
const rect2Bottom = rect2.center.y + rect2.height / 2;
|
|
1107
|
-
return rect1Left <= rect2Right && rect1Right >= rect2Left && rect1Top <= rect2Bottom && rect1Bottom >= rect2Top;
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
921
|
// lib/utils/mapLayerNameToZ.ts
|
|
1111
922
|
var mapLayerNameToZ = (layerName, layerCount) => {
|
|
1112
923
|
if (layerName === "top") return 0;
|
|
@@ -1137,6 +948,108 @@ var calculateOptimalCapacityDepth = (initialWidth, targetMinCapacity = 0.5, maxD
|
|
|
1137
948
|
return Math.max(1, depth);
|
|
1138
949
|
};
|
|
1139
950
|
|
|
951
|
+
// lib/data-structures/ObstacleTree.ts
|
|
952
|
+
var ObstacleTree = class {
|
|
953
|
+
constructor(obstacles) {
|
|
954
|
+
this.obstacles = obstacles;
|
|
955
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
956
|
+
for (let i = 0; i < obstacles.length; i++) {
|
|
957
|
+
const obstacle = obstacles[i];
|
|
958
|
+
const nodeMinX = obstacle.center.x - obstacle.width / 2;
|
|
959
|
+
const nodeMinY = obstacle.center.y - obstacle.height / 2;
|
|
960
|
+
const nodeMaxX = obstacle.center.x + obstacle.width / 2;
|
|
961
|
+
const nodeMaxY = obstacle.center.y + obstacle.height / 2;
|
|
962
|
+
for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {
|
|
963
|
+
for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {
|
|
964
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
965
|
+
const bucket = this.buckets.get(bucketKey);
|
|
966
|
+
if (!bucket) {
|
|
967
|
+
this.buckets.set(bucketKey, [[obstacle, i]]);
|
|
968
|
+
} else {
|
|
969
|
+
bucket.push([obstacle, i]);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
buckets;
|
|
976
|
+
CELL_SIZE = 0.4;
|
|
977
|
+
getBucketKey(x, y) {
|
|
978
|
+
return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`;
|
|
979
|
+
}
|
|
980
|
+
getNodesInArea(centerX, centerY, width, height) {
|
|
981
|
+
const obstacles = [];
|
|
982
|
+
const alreadyAddedObstacles = /* @__PURE__ */ new Set();
|
|
983
|
+
const minX = centerX - width / 2;
|
|
984
|
+
const minY = centerY - height / 2;
|
|
985
|
+
const maxX = centerX + width / 2;
|
|
986
|
+
const maxY = centerY + height / 2;
|
|
987
|
+
for (let x = minX; x <= maxX; x += this.CELL_SIZE) {
|
|
988
|
+
for (let y = minY; y <= maxY; y += this.CELL_SIZE) {
|
|
989
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
990
|
+
const bucket = this.buckets.get(bucketKey) || [];
|
|
991
|
+
for (const obstacleWithIndex of bucket) {
|
|
992
|
+
if (alreadyAddedObstacles.has(obstacleWithIndex[1])) continue;
|
|
993
|
+
alreadyAddedObstacles.add(obstacleWithIndex[1]);
|
|
994
|
+
obstacles.push(obstacleWithIndex[0]);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
return obstacles;
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
// lib/data-structures/TargetTree.ts
|
|
1003
|
+
var TargetTree = class {
|
|
1004
|
+
constructor(targets) {
|
|
1005
|
+
this.targets = targets;
|
|
1006
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
1007
|
+
for (let i = 0; i < targets.length; i++) {
|
|
1008
|
+
const target = targets[i];
|
|
1009
|
+
const targetBucketMinX = Math.floor(target.bounds.minX / this.CELL_SIZE) * this.CELL_SIZE;
|
|
1010
|
+
const targetBucketMinY = Math.floor(target.bounds.minY / this.CELL_SIZE) * this.CELL_SIZE;
|
|
1011
|
+
const targetMaxX = target.bounds.maxX;
|
|
1012
|
+
const targetMaxY = target.bounds.maxY;
|
|
1013
|
+
for (let x = targetBucketMinX; x <= targetMaxX; x += this.CELL_SIZE) {
|
|
1014
|
+
for (let y = targetBucketMinY; y <= targetMaxY; y += this.CELL_SIZE) {
|
|
1015
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
1016
|
+
const bucket = this.buckets.get(bucketKey);
|
|
1017
|
+
if (!bucket) {
|
|
1018
|
+
this.buckets.set(bucketKey, [[target, i]]);
|
|
1019
|
+
} else {
|
|
1020
|
+
bucket.push([target, i]);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
buckets;
|
|
1027
|
+
CELL_SIZE = 5;
|
|
1028
|
+
getBucketKey(x, y) {
|
|
1029
|
+
return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`;
|
|
1030
|
+
}
|
|
1031
|
+
getTargetsInArea(centerX, centerY, width, height) {
|
|
1032
|
+
const targets = [];
|
|
1033
|
+
const alreadyAddedTargets = /* @__PURE__ */ new Set();
|
|
1034
|
+
const minX = Math.floor((centerX - width / 2) / this.CELL_SIZE) * this.CELL_SIZE;
|
|
1035
|
+
const minY = Math.floor((centerY - height / 2) / this.CELL_SIZE) * this.CELL_SIZE;
|
|
1036
|
+
const maxX = centerX + width / 2;
|
|
1037
|
+
const maxY = centerY + height / 2;
|
|
1038
|
+
for (let x = minX; x <= maxX; x += this.CELL_SIZE) {
|
|
1039
|
+
for (let y = minY; y <= maxY; y += this.CELL_SIZE) {
|
|
1040
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
1041
|
+
const bucket = this.buckets.get(bucketKey) || [];
|
|
1042
|
+
for (const targetWithIndex of bucket) {
|
|
1043
|
+
if (alreadyAddedTargets.has(targetWithIndex[1])) continue;
|
|
1044
|
+
alreadyAddedTargets.add(targetWithIndex[1]);
|
|
1045
|
+
targets.push(targetWithIndex[0]);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
return targets;
|
|
1050
|
+
}
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1140
1053
|
// lib/solvers/CapacityMeshSolver/CapacityMeshNodeSolver1.ts
|
|
1141
1054
|
var CapacityMeshNodeSolver = class extends BaseSolver {
|
|
1142
1055
|
constructor(srj, opts = {}) {
|
|
@@ -1180,13 +1093,9 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
|
|
|
1180
1093
|
];
|
|
1181
1094
|
this.finishedNodes = [];
|
|
1182
1095
|
this.nodeToXYOverlappingObstaclesMap = /* @__PURE__ */ new Map();
|
|
1183
|
-
this.
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
connectionName: c.name,
|
|
1187
|
-
availableZ: p.layer === "top" ? [0] : [1]
|
|
1188
|
-
}))
|
|
1189
|
-
);
|
|
1096
|
+
this.obstacleTree = new ObstacleTree(this.srj.obstacles);
|
|
1097
|
+
this.targets = this.computeTargets();
|
|
1098
|
+
this.targetTree = new TargetTree(this.targets);
|
|
1190
1099
|
}
|
|
1191
1100
|
unfinishedNodes;
|
|
1192
1101
|
finishedNodes;
|
|
@@ -1195,6 +1104,40 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
|
|
|
1195
1104
|
// targetObstacleMap: Record<string, { obstacle: Obstacle, node: CapacityMeshNode }>
|
|
1196
1105
|
MAX_DEPTH = 4;
|
|
1197
1106
|
targets;
|
|
1107
|
+
targetTree;
|
|
1108
|
+
obstacleTree;
|
|
1109
|
+
computeTargets() {
|
|
1110
|
+
const targets = [];
|
|
1111
|
+
for (const conn of this.srj.connections) {
|
|
1112
|
+
for (const ptc of conn.pointsToConnect) {
|
|
1113
|
+
const obstacles = this.obstacleTree.getNodesInArea(ptc.x, ptc.y, 0.01, 0.01).filter(
|
|
1114
|
+
(o) => o.zLayers.some((z) => ptc.layer === "top" ? z === 0 : z === 1)
|
|
1115
|
+
);
|
|
1116
|
+
let bounds = {
|
|
1117
|
+
minX: ptc.x - 5e-3,
|
|
1118
|
+
minY: ptc.y - 5e-3,
|
|
1119
|
+
maxX: ptc.x + 5e-3,
|
|
1120
|
+
maxY: ptc.y + 5e-3
|
|
1121
|
+
};
|
|
1122
|
+
if (obstacles.length > 0) {
|
|
1123
|
+
bounds = {
|
|
1124
|
+
minX: Math.min(...obstacles.map((o) => o.center.x - o.width / 2)),
|
|
1125
|
+
minY: Math.min(...obstacles.map((o) => o.center.y - o.height / 2)),
|
|
1126
|
+
maxX: Math.max(...obstacles.map((o) => o.center.x + o.width / 2)),
|
|
1127
|
+
maxY: Math.max(...obstacles.map((o) => o.center.y + o.height / 2))
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
const target = {
|
|
1131
|
+
...ptc,
|
|
1132
|
+
connectionName: conn.name,
|
|
1133
|
+
availableZ: ptc.layer === "top" ? [0] : [1],
|
|
1134
|
+
bounds
|
|
1135
|
+
};
|
|
1136
|
+
targets.push(target);
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
return targets;
|
|
1140
|
+
}
|
|
1198
1141
|
_nextNodeCounter = 0;
|
|
1199
1142
|
getNextNodeId() {
|
|
1200
1143
|
return `cn${this._nextNodeCounter++}`;
|
|
@@ -1203,18 +1146,17 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
|
|
|
1203
1146
|
return (this.MAX_DEPTH - depth + 1) ** 2;
|
|
1204
1147
|
}
|
|
1205
1148
|
getTargetIfNodeContainsTarget(node) {
|
|
1206
|
-
const
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
if (target.x >= node.center.x - node.width / 2 && target.x <= node.center.x + node.width / 2 && target.y >= node.center.y - node.height / 2 && target.y <= node.center.y + node.height / 2) {
|
|
1149
|
+
const nearbyTargets = node.width > this.targetTree.CELL_SIZE * 4 ? this.targets : this.targetTree.getTargetsInArea(
|
|
1150
|
+
node.center.x,
|
|
1151
|
+
node.center.y,
|
|
1152
|
+
node.width,
|
|
1153
|
+
node.height
|
|
1154
|
+
);
|
|
1155
|
+
for (const target of nearbyTargets) {
|
|
1156
|
+
if (
|
|
1157
|
+
// Check if the node and target bounds overlap
|
|
1158
|
+
target.bounds.minX <= node.center.x + node.width / 2 && target.bounds.maxX >= node.center.x - node.width / 2 && target.bounds.minY <= node.center.y + node.height / 2 && target.bounds.maxY >= node.center.y - node.height / 2 && target.availableZ.some((z) => node.availableZ.includes(z))
|
|
1159
|
+
) {
|
|
1218
1160
|
return target;
|
|
1219
1161
|
}
|
|
1220
1162
|
}
|
|
@@ -1942,6 +1884,46 @@ var CapacitySegmentToPointSolver = class extends BaseSolver {
|
|
|
1942
1884
|
}
|
|
1943
1885
|
};
|
|
1944
1886
|
|
|
1887
|
+
// node_modules/@tscircuit/math-utils/dist/chunk-CHQOCSFB.js
|
|
1888
|
+
function doSegmentsIntersect(p1, q1, p2, q2) {
|
|
1889
|
+
const o1 = orientation(p1, q1, p2);
|
|
1890
|
+
const o2 = orientation(p1, q1, q2);
|
|
1891
|
+
const o3 = orientation(p2, q2, p1);
|
|
1892
|
+
const o4 = orientation(p2, q2, q1);
|
|
1893
|
+
if (o1 !== o2 && o3 !== o4) {
|
|
1894
|
+
return true;
|
|
1895
|
+
}
|
|
1896
|
+
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
1897
|
+
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
1898
|
+
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
1899
|
+
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
1900
|
+
return false;
|
|
1901
|
+
}
|
|
1902
|
+
function orientation(p, q, r) {
|
|
1903
|
+
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
1904
|
+
if (val === 0) return 0;
|
|
1905
|
+
return val > 0 ? 1 : 2;
|
|
1906
|
+
}
|
|
1907
|
+
function onSegment(p, q, r) {
|
|
1908
|
+
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
1909
|
+
}
|
|
1910
|
+
function pointToSegmentDistance(p, v, w) {
|
|
1911
|
+
const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2;
|
|
1912
|
+
if (l2 === 0) return distance(p, v);
|
|
1913
|
+
let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
|
|
1914
|
+
t = Math.max(0, Math.min(1, t));
|
|
1915
|
+
const projection = {
|
|
1916
|
+
x: v.x + t * (w.x - v.x),
|
|
1917
|
+
y: v.y + t * (w.y - v.y)
|
|
1918
|
+
};
|
|
1919
|
+
return distance(p, projection);
|
|
1920
|
+
}
|
|
1921
|
+
function distance(p1, p2) {
|
|
1922
|
+
const dx = p1.x - p2.x;
|
|
1923
|
+
const dy = p1.y - p2.y;
|
|
1924
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1945
1927
|
// lib/solvers/HighDensitySolver/SingleHighDensityRouteSolver.ts
|
|
1946
1928
|
var SingleHighDensityRouteSolver = class extends BaseSolver {
|
|
1947
1929
|
obstacleRoutes;
|
|
@@ -3685,6 +3667,7 @@ var MultipleHighDensityRouteStitchSolver = class extends BaseSolver {
|
|
|
3685
3667
|
z: mapLayerNameToZ(c.pointsToConnect[1].layer, opts.layerCount)
|
|
3686
3668
|
}
|
|
3687
3669
|
}));
|
|
3670
|
+
this.MAX_ITERATIONS = 1e5;
|
|
3688
3671
|
}
|
|
3689
3672
|
_step() {
|
|
3690
3673
|
if (this.activeSolver) {
|
|
@@ -3921,20 +3904,15 @@ var hasZRangeOverlap = (A_z1, A_z2, B_z1, B_z2) => {
|
|
|
3921
3904
|
// lib/solvers/UnravelSolver/getIssuesInSection.ts
|
|
3922
3905
|
var getIssuesInSection = (section, nodeMap, pointModifications, connMap) => {
|
|
3923
3906
|
const issues = [];
|
|
3924
|
-
const points =
|
|
3925
|
-
for (const
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
z: modPoint?.z ?? ogPoint.z
|
|
3934
|
-
});
|
|
3935
|
-
}
|
|
3936
|
-
}
|
|
3937
|
-
}
|
|
3907
|
+
const points = new Map(section.originalPointMap);
|
|
3908
|
+
for (const [segmentPointId, modPoint] of pointModifications.entries()) {
|
|
3909
|
+
const ogPoint = points.get(segmentPointId);
|
|
3910
|
+
points.set(segmentPointId, {
|
|
3911
|
+
x: modPoint.x ?? ogPoint.x,
|
|
3912
|
+
y: modPoint.y ?? ogPoint.y,
|
|
3913
|
+
z: modPoint.z ?? ogPoint.z
|
|
3914
|
+
});
|
|
3915
|
+
}
|
|
3938
3916
|
for (const nodeId of section.allNodeIds) {
|
|
3939
3917
|
const node = nodeMap.get(nodeId);
|
|
3940
3918
|
if (!node) continue;
|
|
@@ -4058,11 +4036,14 @@ var applyOperationToPointModifications = (pointModifications, operation, getPoin
|
|
|
4058
4036
|
|
|
4059
4037
|
// lib/solvers/UnravelSolver/createSegmentPointMap.ts
|
|
4060
4038
|
var createSegmentPointMap = (dedupedSegments, segmentIdToNodeIds) => {
|
|
4039
|
+
const segmentPointMap = /* @__PURE__ */ new Map();
|
|
4040
|
+
const nodeToSegmentPointMap = /* @__PURE__ */ new Map();
|
|
4041
|
+
const segmentToSegmentPointMap = /* @__PURE__ */ new Map();
|
|
4061
4042
|
const segmentPoints = [];
|
|
4062
4043
|
let highestSegmentPointId = 0;
|
|
4063
4044
|
for (const segment of dedupedSegments) {
|
|
4064
4045
|
for (const point of segment.assignedPoints) {
|
|
4065
|
-
|
|
4046
|
+
const sp = {
|
|
4066
4047
|
segmentPointId: `SP${highestSegmentPointId++}`,
|
|
4067
4048
|
segmentId: segment.nodePortSegmentId,
|
|
4068
4049
|
capacityMeshNodeIds: segmentIdToNodeIds.get(
|
|
@@ -4073,14 +4054,26 @@ var createSegmentPointMap = (dedupedSegments, segmentIdToNodeIds) => {
|
|
|
4073
4054
|
y: point.point.y,
|
|
4074
4055
|
z: point.point.z,
|
|
4075
4056
|
directlyConnectedSegmentPointIds: []
|
|
4076
|
-
}
|
|
4057
|
+
};
|
|
4058
|
+
segmentPointMap.set(sp.segmentPointId, sp);
|
|
4059
|
+
for (const nodeId of sp.capacityMeshNodeIds) {
|
|
4060
|
+
nodeToSegmentPointMap.set(nodeId, [
|
|
4061
|
+
...nodeToSegmentPointMap.get(nodeId) ?? [],
|
|
4062
|
+
sp.segmentPointId
|
|
4063
|
+
]);
|
|
4064
|
+
}
|
|
4065
|
+
segmentToSegmentPointMap.set(segment.nodePortSegmentId, [
|
|
4066
|
+
...segmentToSegmentPointMap.get(segment.nodePortSegmentId) ?? [],
|
|
4067
|
+
sp.segmentPointId
|
|
4068
|
+
]);
|
|
4069
|
+
segmentPoints.push(sp);
|
|
4077
4070
|
}
|
|
4078
4071
|
}
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4072
|
+
return {
|
|
4073
|
+
segmentPointMap,
|
|
4074
|
+
nodeToSegmentPointMap,
|
|
4075
|
+
segmentToSegmentPointMap
|
|
4076
|
+
};
|
|
4084
4077
|
};
|
|
4085
4078
|
|
|
4086
4079
|
// lib/solvers/UnravelSolver/UnravelSectionSolver.ts
|
|
@@ -4119,7 +4112,11 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4119
4112
|
this.segmentIdToNodeIds = params.segmentIdToNodeIds;
|
|
4120
4113
|
this.rootNodeId = params.rootNodeId;
|
|
4121
4114
|
this.colorMap = params.colorMap ?? {};
|
|
4122
|
-
this.unravelSection = this.createUnravelSection(
|
|
4115
|
+
this.unravelSection = this.createUnravelSection({
|
|
4116
|
+
segmentPointMap: params.segmentPointMap,
|
|
4117
|
+
nodeToSegmentPointMap: params.nodeToSegmentPointMap,
|
|
4118
|
+
segmentToSegmentPointMap: params.segmentToSegmentPointMap
|
|
4119
|
+
});
|
|
4123
4120
|
this.tunedNodeCapacityMap = /* @__PURE__ */ new Map();
|
|
4124
4121
|
for (const nodeId of this.unravelSection.allNodeIds) {
|
|
4125
4122
|
this.tunedNodeCapacityMap.set(
|
|
@@ -4130,38 +4127,43 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4130
4127
|
this.originalCandidate = this.createInitialCandidate();
|
|
4131
4128
|
this.candidates = [this.originalCandidate];
|
|
4132
4129
|
}
|
|
4133
|
-
createUnravelSection(
|
|
4130
|
+
createUnravelSection(largeSpMaps) {
|
|
4134
4131
|
const mutableNodeIds = getNodesNearNode({
|
|
4135
4132
|
nodeId: this.rootNodeId,
|
|
4136
4133
|
nodeIdToSegmentIds: this.nodeIdToSegmentIds,
|
|
4137
4134
|
segmentIdToNodeIds: this.segmentIdToNodeIds,
|
|
4138
4135
|
hops: this.MUTABLE_HOPS
|
|
4139
4136
|
});
|
|
4140
|
-
const
|
|
4137
|
+
const allSectionNodeIds = getNodesNearNode({
|
|
4141
4138
|
nodeId: this.rootNodeId,
|
|
4142
4139
|
nodeIdToSegmentIds: this.nodeIdToSegmentIds,
|
|
4143
4140
|
segmentIdToNodeIds: this.segmentIdToNodeIds,
|
|
4144
4141
|
hops: this.MUTABLE_HOPS + 1
|
|
4145
4142
|
});
|
|
4146
4143
|
const immutableNodeIds = Array.from(
|
|
4147
|
-
new Set(
|
|
4144
|
+
new Set(allSectionNodeIds).difference(new Set(mutableNodeIds))
|
|
4148
4145
|
);
|
|
4149
|
-
if (!segmentPointMap) {
|
|
4150
|
-
|
|
4146
|
+
if (!largeSpMaps?.segmentPointMap) {
|
|
4147
|
+
largeSpMaps = createSegmentPointMap(
|
|
4151
4148
|
this.dedupedSegments,
|
|
4152
4149
|
this.segmentIdToNodeIds
|
|
4153
4150
|
);
|
|
4154
4151
|
}
|
|
4155
|
-
const segmentPoints = Array.from(segmentPointMap.values());
|
|
4156
4152
|
const segmentPointsInNode = /* @__PURE__ */ new Map();
|
|
4157
|
-
for (const
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4153
|
+
for (const nodeId of allSectionNodeIds) {
|
|
4154
|
+
segmentPointsInNode.set(
|
|
4155
|
+
nodeId,
|
|
4156
|
+
largeSpMaps.nodeToSegmentPointMap.get(nodeId)
|
|
4157
|
+
);
|
|
4158
|
+
}
|
|
4159
|
+
const sectionPointMap = /* @__PURE__ */ new Map();
|
|
4160
|
+
for (const nodeId of allSectionNodeIds) {
|
|
4161
|
+
for (const segmentPointId of segmentPointsInNode.get(nodeId)) {
|
|
4162
|
+
const point = largeSpMaps.segmentPointMap.get(segmentPointId);
|
|
4163
|
+
sectionPointMap.set(segmentPointId, point);
|
|
4163
4164
|
}
|
|
4164
4165
|
}
|
|
4166
|
+
const segmentPoints = Array.from(sectionPointMap.values());
|
|
4165
4167
|
const segmentPointsInSegment = /* @__PURE__ */ new Map();
|
|
4166
4168
|
for (const segmentPoint of segmentPoints) {
|
|
4167
4169
|
segmentPointsInSegment.set(segmentPoint.segmentId, [
|
|
@@ -4169,32 +4171,31 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4169
4171
|
segmentPoint.segmentPointId
|
|
4170
4172
|
]);
|
|
4171
4173
|
}
|
|
4172
|
-
for (
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
(
|
|
4181
|
-
|
|
4174
|
+
for (const [nodeId, segmentPoints2] of segmentPointsInNode.entries()) {
|
|
4175
|
+
for (let i = 0; i < segmentPoints2.length; i++) {
|
|
4176
|
+
const A = largeSpMaps.segmentPointMap.get(segmentPoints2[i]);
|
|
4177
|
+
for (let j = i + 1; j < segmentPoints2.length; j++) {
|
|
4178
|
+
const B = largeSpMaps.segmentPointMap.get(segmentPoints2[j]);
|
|
4179
|
+
if (B.segmentPointId === A.segmentPointId) continue;
|
|
4180
|
+
if (B.segmentId === A.segmentId) continue;
|
|
4181
|
+
if (B.connectionName !== A.connectionName) continue;
|
|
4182
|
+
if (B.directlyConnectedSegmentPointIds.includes(A.segmentPointId))
|
|
4183
|
+
continue;
|
|
4182
4184
|
A.directlyConnectedSegmentPointIds.push(B.segmentPointId);
|
|
4183
4185
|
B.directlyConnectedSegmentPointIds.push(A.segmentPointId);
|
|
4184
4186
|
}
|
|
4185
4187
|
}
|
|
4186
4188
|
}
|
|
4187
4189
|
const segmentPairsInNode = /* @__PURE__ */ new Map();
|
|
4188
|
-
for (const nodeId of
|
|
4190
|
+
for (const nodeId of allSectionNodeIds) {
|
|
4189
4191
|
segmentPairsInNode.set(nodeId, []);
|
|
4190
4192
|
}
|
|
4191
4193
|
for (const A of segmentPoints) {
|
|
4192
4194
|
for (const nodeId of A.capacityMeshNodeIds) {
|
|
4193
|
-
const otherSegmentPoints = segmentPointsInNode.get(nodeId).map((spId) => segmentPointMap.get(spId));
|
|
4194
4195
|
const segmentPairs = segmentPairsInNode.get(nodeId);
|
|
4195
4196
|
if (!segmentPairs) continue;
|
|
4196
4197
|
for (const BId of A.directlyConnectedSegmentPointIds) {
|
|
4197
|
-
const B = segmentPointMap.get(BId);
|
|
4198
|
+
const B = largeSpMaps.segmentPointMap.get(BId);
|
|
4198
4199
|
if (B.segmentPointId === A.segmentPointId) continue;
|
|
4199
4200
|
if (!B.capacityMeshNodeIds.some((nId) => nId === nodeId)) continue;
|
|
4200
4201
|
if (!segmentPairs.some(
|
|
@@ -4217,14 +4218,15 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4217
4218
|
}
|
|
4218
4219
|
}
|
|
4219
4220
|
return {
|
|
4220
|
-
allNodeIds,
|
|
4221
|
+
allNodeIds: allSectionNodeIds,
|
|
4221
4222
|
mutableNodeIds,
|
|
4222
4223
|
immutableNodeIds,
|
|
4223
4224
|
mutableSegmentIds,
|
|
4224
4225
|
segmentPairsInNode,
|
|
4225
|
-
segmentPointMap,
|
|
4226
|
+
segmentPointMap: sectionPointMap,
|
|
4226
4227
|
segmentPointsInNode,
|
|
4227
|
-
segmentPointsInSegment
|
|
4228
|
+
segmentPointsInSegment,
|
|
4229
|
+
originalPointMap: sectionPointMap
|
|
4228
4230
|
};
|
|
4229
4231
|
}
|
|
4230
4232
|
createInitialCandidate() {
|
|
@@ -4407,13 +4409,17 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4407
4409
|
}
|
|
4408
4410
|
return cost;
|
|
4409
4411
|
}
|
|
4410
|
-
|
|
4412
|
+
getUnexploredNeighborByApplyingOperation(currentCandidate, operation) {
|
|
4411
4413
|
const pointModifications = new Map(currentCandidate.pointModifications);
|
|
4412
4414
|
applyOperationToPointModifications(
|
|
4413
4415
|
pointModifications,
|
|
4414
4416
|
operation,
|
|
4415
4417
|
(segmentPointId) => this.getPointInCandidate(currentCandidate, segmentPointId)
|
|
4416
4418
|
);
|
|
4419
|
+
const candidateHash = createPointModificationsHash(pointModifications);
|
|
4420
|
+
if (this.queuedOrExploredCandidatePointModificationHashes.has(candidateHash)) {
|
|
4421
|
+
return null;
|
|
4422
|
+
}
|
|
4417
4423
|
const issues = getIssuesInSection(
|
|
4418
4424
|
this.unravelSection,
|
|
4419
4425
|
this.nodeMap,
|
|
@@ -4432,7 +4438,7 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4432
4438
|
h: 0,
|
|
4433
4439
|
f: g,
|
|
4434
4440
|
pointModifications,
|
|
4435
|
-
candidateHash
|
|
4441
|
+
candidateHash,
|
|
4436
4442
|
// TODO PERFORMANCE allow disabling this
|
|
4437
4443
|
// candidateFullHash: createFullPointModificationsHash(
|
|
4438
4444
|
// this.unravelSection.segmentPointMap,
|
|
@@ -4450,8 +4456,15 @@ var UnravelSectionSolver = class extends BaseSolver {
|
|
|
4450
4456
|
const neighbors = [];
|
|
4451
4457
|
const operations = this.getNeighborOperationsForCandidate(candidate);
|
|
4452
4458
|
for (const operation of operations) {
|
|
4453
|
-
const neighbor = this.
|
|
4459
|
+
const neighbor = this.getUnexploredNeighborByApplyingOperation(
|
|
4460
|
+
candidate,
|
|
4461
|
+
operation
|
|
4462
|
+
);
|
|
4463
|
+
if (!neighbor) continue;
|
|
4454
4464
|
neighbors.push(neighbor);
|
|
4465
|
+
this.queuedOrExploredCandidatePointModificationHashes.add(
|
|
4466
|
+
neighbor.candidateHash
|
|
4467
|
+
);
|
|
4455
4468
|
}
|
|
4456
4469
|
return neighbors;
|
|
4457
4470
|
}
|
|
@@ -4745,6 +4758,8 @@ var UnravelMultiSectionSolver = class extends BaseSolver {
|
|
|
4745
4758
|
dedupedSegments;
|
|
4746
4759
|
nodeIdToSegmentIds;
|
|
4747
4760
|
segmentIdToNodeIds;
|
|
4761
|
+
nodeToSegmentPointMap;
|
|
4762
|
+
segmentToSegmentPointMap;
|
|
4748
4763
|
colorMap;
|
|
4749
4764
|
tunedNodeCapacityMap;
|
|
4750
4765
|
MAX_NODE_ATTEMPTS = 2;
|
|
@@ -4791,10 +4806,10 @@ var UnravelMultiSectionSolver = class extends BaseSolver {
|
|
|
4791
4806
|
for (const [nodeId, node] of this.nodeMap) {
|
|
4792
4807
|
this.tunedNodeCapacityMap.set(nodeId, getTunedTotalCapacity1(node));
|
|
4793
4808
|
}
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4809
|
+
const { segmentPointMap, nodeToSegmentPointMap, segmentToSegmentPointMap } = createSegmentPointMap(this.dedupedSegments, this.segmentIdToNodeIds);
|
|
4810
|
+
this.segmentPointMap = segmentPointMap;
|
|
4811
|
+
this.nodeToSegmentPointMap = nodeToSegmentPointMap;
|
|
4812
|
+
this.segmentToSegmentPointMap = segmentToSegmentPointMap;
|
|
4798
4813
|
this.nodePfMap = this.computeInitialPfMap();
|
|
4799
4814
|
}
|
|
4800
4815
|
computeInitialPfMap() {
|
|
@@ -4810,9 +4825,7 @@ var UnravelMultiSectionSolver = class extends BaseSolver {
|
|
|
4810
4825
|
numEntryExitLayerChanges,
|
|
4811
4826
|
numTransitionCrossings
|
|
4812
4827
|
} = getIntraNodeCrossingsFromSegments(
|
|
4813
|
-
this.
|
|
4814
|
-
(seg) => this.segmentIdToNodeIds.get(seg.nodePortSegmentId).includes(node.capacityMeshNodeId)
|
|
4815
|
-
)
|
|
4828
|
+
this.nodeIdToSegmentIds.get(node.capacityMeshNodeId)?.map((segId) => this.dedupedSegmentMap.get(segId)) || []
|
|
4816
4829
|
);
|
|
4817
4830
|
const probabilityOfFailure = calculateNodeProbabilityOfFailure(
|
|
4818
4831
|
node,
|
|
@@ -4854,7 +4867,9 @@ var UnravelMultiSectionSolver = class extends BaseSolver {
|
|
|
4854
4867
|
colorMap: this.colorMap,
|
|
4855
4868
|
rootNodeId: highestPfNodeId,
|
|
4856
4869
|
MUTABLE_HOPS: this.MUTABLE_HOPS,
|
|
4857
|
-
segmentPointMap: this.segmentPointMap
|
|
4870
|
+
segmentPointMap: this.segmentPointMap,
|
|
4871
|
+
nodeToSegmentPointMap: this.nodeToSegmentPointMap,
|
|
4872
|
+
segmentToSegmentPointMap: this.segmentToSegmentPointMap
|
|
4858
4873
|
});
|
|
4859
4874
|
}
|
|
4860
4875
|
this.activeSolver.step();
|
|
@@ -5423,6 +5438,7 @@ var StrawSolver = class extends BaseSolver {
|
|
|
5423
5438
|
nodeIdCounter;
|
|
5424
5439
|
constructor(params) {
|
|
5425
5440
|
super();
|
|
5441
|
+
this.MAX_ITERATIONS = 1e5;
|
|
5426
5442
|
this.strawSize = params.strawSize ?? 0.5;
|
|
5427
5443
|
this.multiLayerNodes = [];
|
|
5428
5444
|
this.strawNodes = [];
|
|
@@ -5615,6 +5631,72 @@ ${node.width}x${node.height}`
|
|
|
5615
5631
|
}
|
|
5616
5632
|
};
|
|
5617
5633
|
|
|
5634
|
+
// lib/utils/areNodesBordering.ts
|
|
5635
|
+
function areNodesBordering(node1, node2) {
|
|
5636
|
+
const n1Left = node1.center.x - node1.width / 2;
|
|
5637
|
+
const n1Right = node1.center.x + node1.width / 2;
|
|
5638
|
+
const n1Top = node1.center.y - node1.height / 2;
|
|
5639
|
+
const n1Bottom = node1.center.y + node1.height / 2;
|
|
5640
|
+
const n2Left = node2.center.x - node2.width / 2;
|
|
5641
|
+
const n2Right = node2.center.x + node2.width / 2;
|
|
5642
|
+
const n2Top = node2.center.y - node2.height / 2;
|
|
5643
|
+
const n2Bottom = node2.center.y + node2.height / 2;
|
|
5644
|
+
const epsilon = 1e-3;
|
|
5645
|
+
const shareVerticalBorder = (Math.abs(n1Right - n2Left) < epsilon || Math.abs(n1Left - n2Right) < epsilon) && Math.min(n1Bottom, n2Bottom) - Math.max(n1Top, n2Top) >= epsilon;
|
|
5646
|
+
const shareHorizontalBorder = (Math.abs(n1Bottom - n2Top) < epsilon || Math.abs(n1Top - n2Bottom) < epsilon) && Math.min(n1Right, n2Right) - Math.max(n1Left, n2Left) >= epsilon;
|
|
5647
|
+
return shareVerticalBorder || shareHorizontalBorder;
|
|
5648
|
+
}
|
|
5649
|
+
|
|
5650
|
+
// lib/data-structures/CapacityNodeTree.ts
|
|
5651
|
+
var CapacityNodeTree = class {
|
|
5652
|
+
constructor(nodes) {
|
|
5653
|
+
this.nodes = nodes;
|
|
5654
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
5655
|
+
for (const node of nodes) {
|
|
5656
|
+
const nodeMinX = node.center.x - node.width / 2;
|
|
5657
|
+
const nodeMinY = node.center.y - node.height / 2;
|
|
5658
|
+
const nodeMaxX = node.center.x + node.width / 2;
|
|
5659
|
+
const nodeMaxY = node.center.y + node.height / 2;
|
|
5660
|
+
for (let x = nodeMinX; x <= nodeMaxX; x += this.CELL_SIZE) {
|
|
5661
|
+
for (let y = nodeMinY; y <= nodeMaxY; y += this.CELL_SIZE) {
|
|
5662
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
5663
|
+
const bucket = this.buckets.get(bucketKey);
|
|
5664
|
+
if (!bucket) {
|
|
5665
|
+
this.buckets.set(bucketKey, [node]);
|
|
5666
|
+
} else {
|
|
5667
|
+
bucket.push(node);
|
|
5668
|
+
}
|
|
5669
|
+
}
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
buckets;
|
|
5674
|
+
CELL_SIZE = 0.4;
|
|
5675
|
+
getBucketKey(x, y) {
|
|
5676
|
+
return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`;
|
|
5677
|
+
}
|
|
5678
|
+
getNodesInArea(centerX, centerY, width, height) {
|
|
5679
|
+
const nodes = [];
|
|
5680
|
+
const alreadyAddedNodes = /* @__PURE__ */ new Set();
|
|
5681
|
+
const minX = centerX - width / 2;
|
|
5682
|
+
const minY = centerY - height / 2;
|
|
5683
|
+
const maxX = centerX + width / 2;
|
|
5684
|
+
const maxY = centerY + height / 2;
|
|
5685
|
+
for (let x = minX; x <= maxX; x += this.CELL_SIZE) {
|
|
5686
|
+
for (let y = minY; y <= maxY; y += this.CELL_SIZE) {
|
|
5687
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
5688
|
+
const bucket = this.buckets.get(bucketKey) || [];
|
|
5689
|
+
for (const node of bucket) {
|
|
5690
|
+
if (alreadyAddedNodes.has(node.capacityMeshNodeId)) continue;
|
|
5691
|
+
alreadyAddedNodes.add(node.capacityMeshNodeId);
|
|
5692
|
+
nodes.push(node);
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
return nodes;
|
|
5697
|
+
}
|
|
5698
|
+
};
|
|
5699
|
+
|
|
5618
5700
|
// lib/solvers/SingleLayerNodeMerger/SingleLayerNodeMergerSolver.ts
|
|
5619
5701
|
var EPSILON = 5e-3;
|
|
5620
5702
|
var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
@@ -5623,6 +5705,7 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5623
5705
|
absorbedNodeIds;
|
|
5624
5706
|
nextBatchNodeIds;
|
|
5625
5707
|
batchHadModifications;
|
|
5708
|
+
hasComputedAdjacentNodeIds = false;
|
|
5626
5709
|
newNodes;
|
|
5627
5710
|
constructor(nodes) {
|
|
5628
5711
|
super();
|
|
@@ -5633,41 +5716,94 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5633
5716
|
}
|
|
5634
5717
|
this.newNodes = [];
|
|
5635
5718
|
this.absorbedNodeIds = /* @__PURE__ */ new Set();
|
|
5636
|
-
const
|
|
5719
|
+
const unprocessedNodesWithArea = [];
|
|
5637
5720
|
for (const node of nodes) {
|
|
5638
5721
|
if (node.availableZ.length > 1) {
|
|
5639
5722
|
this.newNodes.push(node);
|
|
5640
5723
|
this.absorbedNodeIds.add(node.capacityMeshNodeId);
|
|
5641
5724
|
} else {
|
|
5642
|
-
|
|
5725
|
+
unprocessedNodesWithArea.push([node, node.width * node.height]);
|
|
5643
5726
|
}
|
|
5644
5727
|
}
|
|
5645
|
-
|
|
5646
|
-
for (const [
|
|
5647
|
-
const
|
|
5648
|
-
this.nodeMap.set(nodeId, {
|
|
5728
|
+
unprocessedNodesWithArea.sort((a, b) => a[1] - b[1]);
|
|
5729
|
+
for (const [node, area] of unprocessedNodesWithArea) {
|
|
5730
|
+
const unprocessedNode = {
|
|
5649
5731
|
...node,
|
|
5650
5732
|
center: { ...node.center }
|
|
5651
|
-
}
|
|
5733
|
+
};
|
|
5734
|
+
this.nodeMap.set(node.capacityMeshNodeId, unprocessedNode);
|
|
5652
5735
|
}
|
|
5653
|
-
this.currentBatchNodeIds =
|
|
5736
|
+
this.currentBatchNodeIds = unprocessedNodesWithArea.map(
|
|
5737
|
+
([node]) => node.capacityMeshNodeId
|
|
5738
|
+
);
|
|
5654
5739
|
this.nextBatchNodeIds = [];
|
|
5655
5740
|
this.batchHadModifications = false;
|
|
5656
5741
|
}
|
|
5742
|
+
computeAdjacentNodeIdsForFirstBatch(nodes) {
|
|
5743
|
+
const nodeTrees = [
|
|
5744
|
+
new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 0)),
|
|
5745
|
+
new CapacityNodeTree(nodes.filter((n) => n.availableZ[0] === 1))
|
|
5746
|
+
];
|
|
5747
|
+
for (const node of nodes) {
|
|
5748
|
+
const adjacentNodes = [];
|
|
5749
|
+
const z = node.availableZ[0];
|
|
5750
|
+
const nodesInArea = nodeTrees[z].getNodesInArea(
|
|
5751
|
+
node.center.x,
|
|
5752
|
+
node.center.y,
|
|
5753
|
+
node.width * 4,
|
|
5754
|
+
node.height * 4
|
|
5755
|
+
);
|
|
5756
|
+
for (const unprocessedNode of nodesInArea) {
|
|
5757
|
+
if (unprocessedNode._containsTarget && unprocessedNode._targetConnectionName !== node._targetConnectionName)
|
|
5758
|
+
continue;
|
|
5759
|
+
if (unprocessedNode.capacityMeshNodeId === node.capacityMeshNodeId)
|
|
5760
|
+
continue;
|
|
5761
|
+
if (!areNodesBordering(node, unprocessedNode)) continue;
|
|
5762
|
+
adjacentNodes.push(unprocessedNode);
|
|
5763
|
+
}
|
|
5764
|
+
node._adjacentNodeIds = adjacentNodes.map((n) => n.capacityMeshNodeId);
|
|
5765
|
+
}
|
|
5766
|
+
}
|
|
5767
|
+
// getAdjacentSameLayerUnprocessedNodes1(rootNode: CapacityMeshNode) {
|
|
5768
|
+
// const adjacentNodes: CapacityMeshNode[] = []
|
|
5769
|
+
// for (const unprocessedNodeId of this.currentBatchNodeIds) {
|
|
5770
|
+
// const unprocessedNode = this.nodeMap.get(unprocessedNodeId)!
|
|
5771
|
+
// if (!areNodesBordering(rootNode, unprocessedNode)) continue
|
|
5772
|
+
// if (unprocessedNode.availableZ[0] !== rootNode.availableZ[0]) continue
|
|
5773
|
+
// if (
|
|
5774
|
+
// unprocessedNode._containsTarget &&
|
|
5775
|
+
// unprocessedNode._targetConnectionName !== rootNode._targetConnectionName
|
|
5776
|
+
// )
|
|
5777
|
+
// continue
|
|
5778
|
+
// if (this.absorbedNodeIds.has(unprocessedNodeId)) continue
|
|
5779
|
+
// adjacentNodes.push(unprocessedNode)
|
|
5780
|
+
// }
|
|
5781
|
+
// return adjacentNodes
|
|
5782
|
+
// }
|
|
5657
5783
|
getAdjacentSameLayerUnprocessedNodes(rootNode) {
|
|
5784
|
+
return this.getAdjacentSameLayerUnprocessedNodes2(rootNode);
|
|
5785
|
+
}
|
|
5786
|
+
getAdjacentSameLayerUnprocessedNodes2(rootNode) {
|
|
5658
5787
|
const adjacentNodes = [];
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5788
|
+
const unprocessedAdjNodes = Array.from(
|
|
5789
|
+
new Set(
|
|
5790
|
+
(rootNode._adjacentNodeIds ?? []).map((a) => this.nodeMap.get(a))
|
|
5791
|
+
)
|
|
5792
|
+
);
|
|
5793
|
+
unprocessedAdjNodes.sort((a, b) => a.width * a.height - b.width * b.height);
|
|
5794
|
+
for (const unprocessedNode of unprocessedAdjNodes) {
|
|
5795
|
+
if (this.absorbedNodeIds.has(unprocessedNode.capacityMeshNodeId)) continue;
|
|
5666
5796
|
adjacentNodes.push(unprocessedNode);
|
|
5667
5797
|
}
|
|
5668
5798
|
return adjacentNodes;
|
|
5669
5799
|
}
|
|
5670
5800
|
_step() {
|
|
5801
|
+
if (!this.hasComputedAdjacentNodeIds) {
|
|
5802
|
+
this.computeAdjacentNodeIdsForFirstBatch(
|
|
5803
|
+
this.currentBatchNodeIds.map((id) => this.nodeMap.get(id))
|
|
5804
|
+
);
|
|
5805
|
+
this.hasComputedAdjacentNodeIds = true;
|
|
5806
|
+
}
|
|
5671
5807
|
let rootNodeId = this.currentBatchNodeIds.pop();
|
|
5672
5808
|
while (rootNodeId && this.absorbedNodeIds.has(rootNodeId)) {
|
|
5673
5809
|
rootNodeId = this.currentBatchNodeIds.pop();
|
|
@@ -5696,6 +5832,19 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5696
5832
|
this.nextBatchNodeIds.push(rootNodeId);
|
|
5697
5833
|
return;
|
|
5698
5834
|
}
|
|
5835
|
+
const absorbAdjacentNodeIds = (nodesToAbsorb) => {
|
|
5836
|
+
for (const adjNode of nodesToAbsorb) {
|
|
5837
|
+
this.absorbedNodeIds.add(adjNode.capacityMeshNodeId);
|
|
5838
|
+
}
|
|
5839
|
+
rootNode._adjacentNodeIds = Array.from(
|
|
5840
|
+
new Set(
|
|
5841
|
+
[
|
|
5842
|
+
...rootNode._adjacentNodeIds ?? [],
|
|
5843
|
+
...nodesToAbsorb.flatMap((n) => n._adjacentNodeIds ?? [])
|
|
5844
|
+
].filter((id) => !this.absorbedNodeIds.has(id))
|
|
5845
|
+
)
|
|
5846
|
+
);
|
|
5847
|
+
};
|
|
5699
5848
|
const adjacentNodesToLeft = adjacentNodes.filter(
|
|
5700
5849
|
(adjNode) => adjNode.center.x < rootNode.center.x && Math.abs(adjNode.center.y - rootNode.center.y) < rootNode.height / 2
|
|
5701
5850
|
);
|
|
@@ -5712,9 +5861,7 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5712
5861
|
if (leftAdjNodesTakeUpEntireHeight && leftAdjNodesAreAllSameSize) {
|
|
5713
5862
|
rootNode.width += leftAdjNodeWidth;
|
|
5714
5863
|
rootNode.center.x = rootNode.center.x - leftAdjNodeWidth / 2;
|
|
5715
|
-
|
|
5716
|
-
this.absorbedNodeIds.add(adjNode.capacityMeshNodeId);
|
|
5717
|
-
}
|
|
5864
|
+
absorbAdjacentNodeIds(adjacentNodesToLeft);
|
|
5718
5865
|
rootNodeHasGrown = true;
|
|
5719
5866
|
}
|
|
5720
5867
|
}
|
|
@@ -5734,9 +5881,7 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5734
5881
|
if (rightAdjNodesTakeUpEntireHeight && rightAdjNodesAreAllSameSize) {
|
|
5735
5882
|
rootNode.width += rightAdjNodeWidth;
|
|
5736
5883
|
rootNode.center.x = rootNode.center.x + rightAdjNodeWidth / 2;
|
|
5737
|
-
|
|
5738
|
-
this.absorbedNodeIds.add(adjNode.capacityMeshNodeId);
|
|
5739
|
-
}
|
|
5884
|
+
absorbAdjacentNodeIds(adjacentNodesToRight);
|
|
5740
5885
|
rootNodeHasGrown = true;
|
|
5741
5886
|
}
|
|
5742
5887
|
}
|
|
@@ -5756,9 +5901,7 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5756
5901
|
if (topAdjNodesTakeUpEntireWidth && topAdjNodesAreAllSameSize) {
|
|
5757
5902
|
rootNode.height += topAdjNodeHeight;
|
|
5758
5903
|
rootNode.center.y = rootNode.center.y + topAdjNodeHeight / 2;
|
|
5759
|
-
|
|
5760
|
-
this.absorbedNodeIds.add(adjNode.capacityMeshNodeId);
|
|
5761
|
-
}
|
|
5904
|
+
absorbAdjacentNodeIds(adjacentNodesToTop);
|
|
5762
5905
|
rootNodeHasGrown = true;
|
|
5763
5906
|
}
|
|
5764
5907
|
}
|
|
@@ -5778,9 +5921,7 @@ var SingleLayerNodeMergerSolver = class extends BaseSolver {
|
|
|
5778
5921
|
if (bottomAdjNodesTakeUpEntireWidth && bottomAdjNodesAreAllSameSize) {
|
|
5779
5922
|
rootNode.height += bottomAdjNodeHeight;
|
|
5780
5923
|
rootNode.center.y = rootNode.center.y - bottomAdjNodeHeight / 2;
|
|
5781
|
-
|
|
5782
|
-
this.absorbedNodeIds.add(adjNode.capacityMeshNodeId);
|
|
5783
|
-
}
|
|
5924
|
+
absorbAdjacentNodeIds(adjacentNodesToBottom);
|
|
5784
5925
|
rootNodeHasGrown = true;
|
|
5785
5926
|
}
|
|
5786
5927
|
}
|
|
@@ -5870,7 +6011,7 @@ var SingleSimplifiedPathSolver = class extends BaseSolver {
|
|
|
5870
6011
|
this.obstacles = params.obstacles;
|
|
5871
6012
|
this.connMap = params.connMap;
|
|
5872
6013
|
this.colorMap = params.colorMap;
|
|
5873
|
-
this.newRoute = [];
|
|
6014
|
+
this.newRoute = [this.inputRoute.route[0]];
|
|
5874
6015
|
this.newVias = [];
|
|
5875
6016
|
}
|
|
5876
6017
|
get simplifiedRoute() {
|
|
@@ -6055,32 +6196,173 @@ function segmentsIntersect(A1, A2, B1, B2) {
|
|
|
6055
6196
|
return false;
|
|
6056
6197
|
}
|
|
6057
6198
|
|
|
6199
|
+
// lib/data-structures/SegmentTree.ts
|
|
6200
|
+
var getSegmentBounds = (segment) => {
|
|
6201
|
+
return {
|
|
6202
|
+
minX: Math.min(segment[0].x, segment[1].x),
|
|
6203
|
+
maxX: Math.max(segment[0].x, segment[1].x),
|
|
6204
|
+
minY: Math.min(segment[0].y, segment[1].y),
|
|
6205
|
+
maxY: Math.max(segment[0].y, segment[1].y)
|
|
6206
|
+
};
|
|
6207
|
+
};
|
|
6208
|
+
var SegmentTree = class {
|
|
6209
|
+
constructor(segments) {
|
|
6210
|
+
this.segments = segments;
|
|
6211
|
+
this.buckets = /* @__PURE__ */ new Map();
|
|
6212
|
+
for (const segment of segments) {
|
|
6213
|
+
const bounds = getSegmentBounds(segment);
|
|
6214
|
+
const bucketMinX = Math.floor(bounds.minX / this.CELL_SIZE) * this.CELL_SIZE;
|
|
6215
|
+
const bucketMinY = Math.floor(bounds.minY / this.CELL_SIZE) * this.CELL_SIZE;
|
|
6216
|
+
for (let x = bucketMinX; x <= bounds.maxX; x += this.CELL_SIZE) {
|
|
6217
|
+
for (let y = bucketMinY; y <= bounds.maxY; y += this.CELL_SIZE) {
|
|
6218
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
6219
|
+
const bucket = this.buckets.get(bucketKey);
|
|
6220
|
+
if (!bucket) {
|
|
6221
|
+
this.buckets.set(bucketKey, [
|
|
6222
|
+
[segment[0], segment[1], this.getSegmentKey(segment)]
|
|
6223
|
+
]);
|
|
6224
|
+
} else {
|
|
6225
|
+
bucket.push([segment[0], segment[1], this.getSegmentKey(segment)]);
|
|
6226
|
+
}
|
|
6227
|
+
}
|
|
6228
|
+
}
|
|
6229
|
+
}
|
|
6230
|
+
}
|
|
6231
|
+
buckets;
|
|
6232
|
+
CELL_SIZE = 0.4;
|
|
6233
|
+
getBucketKey(x, y) {
|
|
6234
|
+
return `${Math.floor(x / this.CELL_SIZE)}x${Math.floor(y / this.CELL_SIZE)}`;
|
|
6235
|
+
}
|
|
6236
|
+
getSegmentKey(segment) {
|
|
6237
|
+
return `${segment[0].x}-${segment[0].y}-${segment[0].z}-${segment[1].x}-${segment[1].y}-${segment[1].z}`;
|
|
6238
|
+
}
|
|
6239
|
+
getSegmentsThatCouldIntersect(A, B) {
|
|
6240
|
+
const segments = [];
|
|
6241
|
+
const alreadyAddedSegments = /* @__PURE__ */ new Set();
|
|
6242
|
+
const minX = Math.min(A.x, B.x);
|
|
6243
|
+
const minY = Math.min(A.y, B.y);
|
|
6244
|
+
const maxX = Math.max(A.x, B.x);
|
|
6245
|
+
const maxY = Math.max(A.y, B.y);
|
|
6246
|
+
const bucketMinX = Math.floor(minX / this.CELL_SIZE) * this.CELL_SIZE;
|
|
6247
|
+
const bucketMinY = Math.floor(minY / this.CELL_SIZE) * this.CELL_SIZE;
|
|
6248
|
+
for (let x = bucketMinX; x <= maxX; x += this.CELL_SIZE) {
|
|
6249
|
+
for (let y = bucketMinY; y <= maxY; y += this.CELL_SIZE) {
|
|
6250
|
+
const bucketKey = this.getBucketKey(x, y);
|
|
6251
|
+
const bucket = this.buckets.get(bucketKey) || [];
|
|
6252
|
+
for (const segment of bucket) {
|
|
6253
|
+
const key = segment[2];
|
|
6254
|
+
if (alreadyAddedSegments.has(key)) continue;
|
|
6255
|
+
alreadyAddedSegments.add(key);
|
|
6256
|
+
segments.push(segment);
|
|
6257
|
+
}
|
|
6258
|
+
}
|
|
6259
|
+
}
|
|
6260
|
+
return segments;
|
|
6261
|
+
}
|
|
6262
|
+
};
|
|
6263
|
+
|
|
6058
6264
|
// lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver5_Deg45.ts
|
|
6059
6265
|
var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
6060
6266
|
pathSegments = [];
|
|
6061
6267
|
totalPathLength = 0;
|
|
6062
6268
|
headDistanceAlongPath = 0;
|
|
6063
6269
|
tailDistanceAlongPath = 0;
|
|
6064
|
-
|
|
6270
|
+
minStepSize = 0.25;
|
|
6065
6271
|
// Default step size, can be adjusted
|
|
6066
6272
|
lastValidPath = null;
|
|
6067
6273
|
// Store the current valid path
|
|
6068
6274
|
lastValidPathHeadDistance = 0;
|
|
6275
|
+
/** Amount the step size is reduced when the step isn't possible */
|
|
6276
|
+
STEP_SIZE_REDUCTION_FACTOR = 0.25;
|
|
6277
|
+
maxStepSize = 4;
|
|
6278
|
+
currentStepSize = this.maxStepSize;
|
|
6279
|
+
lastHeadMoveDistance = 0;
|
|
6280
|
+
cachedValidPathSegments;
|
|
6069
6281
|
filteredObstacles = [];
|
|
6282
|
+
filteredObstaclePathSegments = [];
|
|
6283
|
+
filteredVias = [];
|
|
6284
|
+
segmentTree;
|
|
6070
6285
|
OBSTACLE_MARGIN = 0.15;
|
|
6071
6286
|
TAIL_JUMP_RATIO = 0.8;
|
|
6072
6287
|
constructor(params) {
|
|
6073
6288
|
super(params);
|
|
6289
|
+
this.cachedValidPathSegments = /* @__PURE__ */ new Set();
|
|
6074
6290
|
if (this.inputRoute.route.length <= 1) {
|
|
6075
6291
|
this.newRoute = [...this.inputRoute.route];
|
|
6076
6292
|
this.solved = true;
|
|
6077
6293
|
return;
|
|
6078
6294
|
}
|
|
6295
|
+
const bounds = this.inputRoute.route.reduce(
|
|
6296
|
+
(acc, point) => {
|
|
6297
|
+
acc.minX = Math.min(acc.minX, point.x);
|
|
6298
|
+
acc.maxX = Math.max(acc.maxX, point.x);
|
|
6299
|
+
acc.minY = Math.min(acc.minY, point.y);
|
|
6300
|
+
acc.maxY = Math.max(acc.maxY, point.y);
|
|
6301
|
+
return acc;
|
|
6302
|
+
},
|
|
6303
|
+
{ minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
|
|
6304
|
+
);
|
|
6079
6305
|
this.filteredObstacles = this.obstacles.filter(
|
|
6080
6306
|
(obstacle) => !obstacle.connectedTo.some(
|
|
6081
6307
|
(id) => this.connMap.areIdsConnected(this.inputRoute.connectionName, id)
|
|
6082
6308
|
)
|
|
6309
|
+
).filter((obstacle) => {
|
|
6310
|
+
if (obstacle.connectedTo.some(
|
|
6311
|
+
(obsId) => this.connMap.areIdsConnected(this.inputRoute.connectionName, obsId)
|
|
6312
|
+
)) {
|
|
6313
|
+
return false;
|
|
6314
|
+
}
|
|
6315
|
+
const obstacleMinX = obstacle.center.x - obstacle.width / 2 - this.OBSTACLE_MARGIN;
|
|
6316
|
+
const obstacleMaxX = obstacle.center.x + obstacle.width / 2 + this.OBSTACLE_MARGIN;
|
|
6317
|
+
const obstacleMinY = obstacle.center.y - obstacle.height / 2 - this.OBSTACLE_MARGIN;
|
|
6318
|
+
const obstacleMaxY = obstacle.center.y + obstacle.height / 2 + this.OBSTACLE_MARGIN;
|
|
6319
|
+
return obstacleMinX <= bounds.maxX && obstacleMaxX >= bounds.minX && obstacleMinY <= bounds.maxY && obstacleMaxY >= bounds.minY;
|
|
6320
|
+
});
|
|
6321
|
+
this.filteredObstaclePathSegments = this.otherHdRoutes.flatMap(
|
|
6322
|
+
(hdRoute) => {
|
|
6323
|
+
if (this.connMap.areIdsConnected(
|
|
6324
|
+
this.inputRoute.connectionName,
|
|
6325
|
+
hdRoute.connectionName
|
|
6326
|
+
)) {
|
|
6327
|
+
return [];
|
|
6328
|
+
}
|
|
6329
|
+
const route = hdRoute.route;
|
|
6330
|
+
const segments = [];
|
|
6331
|
+
for (let i = 0; i < route.length - 1; i++) {
|
|
6332
|
+
const start = route[i];
|
|
6333
|
+
const end = route[i + 1];
|
|
6334
|
+
const minX = Math.min(start.x, end.x);
|
|
6335
|
+
const maxX = Math.max(start.x, end.x);
|
|
6336
|
+
const minY = Math.min(start.y, end.y);
|
|
6337
|
+
const maxY = Math.max(start.y, end.y);
|
|
6338
|
+
if (minX <= bounds.maxX && maxX >= bounds.minX && minY <= bounds.maxY && maxY >= bounds.minY) {
|
|
6339
|
+
segments.push([start, end]);
|
|
6340
|
+
}
|
|
6341
|
+
}
|
|
6342
|
+
return segments;
|
|
6343
|
+
}
|
|
6083
6344
|
);
|
|
6345
|
+
this.segmentTree = new SegmentTree(this.filteredObstaclePathSegments);
|
|
6346
|
+
this.filteredVias = this.otherHdRoutes.flatMap((hdRoute) => {
|
|
6347
|
+
if (this.connMap.areIdsConnected(
|
|
6348
|
+
this.inputRoute.connectionName,
|
|
6349
|
+
hdRoute.connectionName
|
|
6350
|
+
)) {
|
|
6351
|
+
return [];
|
|
6352
|
+
}
|
|
6353
|
+
const vias = hdRoute.vias;
|
|
6354
|
+
const filteredVias = [];
|
|
6355
|
+
for (const via of vias) {
|
|
6356
|
+
const minX = via.x - hdRoute.viaDiameter / 2;
|
|
6357
|
+
const maxX = via.x + hdRoute.viaDiameter / 2;
|
|
6358
|
+
const minY = via.y - hdRoute.viaDiameter / 2;
|
|
6359
|
+
const maxY = via.y + hdRoute.viaDiameter / 2;
|
|
6360
|
+
if (minX <= bounds.maxX && maxX >= bounds.minX && minY <= bounds.maxY && maxY >= bounds.minY) {
|
|
6361
|
+
filteredVias.push({ ...via, diameter: hdRoute.viaDiameter });
|
|
6362
|
+
}
|
|
6363
|
+
}
|
|
6364
|
+
return filteredVias;
|
|
6365
|
+
});
|
|
6084
6366
|
this.computePathSegments();
|
|
6085
6367
|
}
|
|
6086
6368
|
// Compute the path segments and their distances
|
|
@@ -6118,7 +6400,7 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6118
6400
|
return {
|
|
6119
6401
|
x: segment.start.x + factor * (segment.end.x - segment.start.x),
|
|
6120
6402
|
y: segment.start.y + factor * (segment.end.y - segment.start.y),
|
|
6121
|
-
z: segment.start.z
|
|
6403
|
+
z: factor < 0.5 ? segment.start.z : segment.end.z
|
|
6122
6404
|
// Z doesn't interpolate - use the segment's start z value
|
|
6123
6405
|
};
|
|
6124
6406
|
}
|
|
@@ -6169,33 +6451,24 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6169
6451
|
return false;
|
|
6170
6452
|
}
|
|
6171
6453
|
}
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
const routeEnd = route.route[j + 1];
|
|
6182
|
-
if (routeStart.z === start.z && routeEnd.z === start.z) {
|
|
6183
|
-
if (minimumDistanceBetweenSegments(
|
|
6184
|
-
{ x: start.x, y: start.y },
|
|
6185
|
-
{ x: end.x, y: end.y },
|
|
6186
|
-
{ x: routeStart.x, y: routeStart.y },
|
|
6187
|
-
{ x: routeEnd.x, y: routeEnd.y }
|
|
6188
|
-
) < this.OBSTACLE_MARGIN) {
|
|
6189
|
-
return false;
|
|
6190
|
-
}
|
|
6191
|
-
}
|
|
6192
|
-
}
|
|
6193
|
-
for (const via of route.vias) {
|
|
6194
|
-
if (pointToSegmentDistance(via, start, end) < this.OBSTACLE_MARGIN + route.viaDiameter / 2) {
|
|
6454
|
+
const segmentsThatCouldIntersect = this.segmentTree.getSegmentsThatCouldIntersect(start, end);
|
|
6455
|
+
for (const [otherSegA, otherSegB] of segmentsThatCouldIntersect) {
|
|
6456
|
+
if (otherSegA.z === start.z && otherSegB.z === start.z) {
|
|
6457
|
+
if (minimumDistanceBetweenSegments(
|
|
6458
|
+
{ x: start.x, y: start.y },
|
|
6459
|
+
{ x: end.x, y: end.y },
|
|
6460
|
+
{ x: otherSegA.x, y: otherSegA.y },
|
|
6461
|
+
{ x: otherSegB.x, y: otherSegB.y }
|
|
6462
|
+
) < this.OBSTACLE_MARGIN) {
|
|
6195
6463
|
return false;
|
|
6196
6464
|
}
|
|
6197
6465
|
}
|
|
6198
6466
|
}
|
|
6467
|
+
for (const via of this.filteredVias) {
|
|
6468
|
+
if (pointToSegmentDistance(via, start, end) < this.OBSTACLE_MARGIN + via.diameter / 2) {
|
|
6469
|
+
return false;
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6199
6472
|
return true;
|
|
6200
6473
|
}
|
|
6201
6474
|
// Check if a path with multiple points is valid
|
|
@@ -6242,6 +6515,24 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6242
6515
|
}
|
|
6243
6516
|
this.newRoute.push(path[i]);
|
|
6244
6517
|
}
|
|
6518
|
+
this.currentStepSize = this.maxStepSize;
|
|
6519
|
+
}
|
|
6520
|
+
moveHead(distance4) {
|
|
6521
|
+
this.lastHeadMoveDistance = distance4;
|
|
6522
|
+
this.headDistanceAlongPath = Math.min(
|
|
6523
|
+
this.headDistanceAlongPath + distance4,
|
|
6524
|
+
this.totalPathLength
|
|
6525
|
+
);
|
|
6526
|
+
}
|
|
6527
|
+
stepBackAndReduceStepSize() {
|
|
6528
|
+
this.headDistanceAlongPath = Math.max(
|
|
6529
|
+
this.tailDistanceAlongPath,
|
|
6530
|
+
this.headDistanceAlongPath - this.lastHeadMoveDistance
|
|
6531
|
+
);
|
|
6532
|
+
this.currentStepSize = Math.max(
|
|
6533
|
+
this.minStepSize,
|
|
6534
|
+
this.currentStepSize * this.STEP_SIZE_REDUCTION_FACTOR
|
|
6535
|
+
);
|
|
6245
6536
|
}
|
|
6246
6537
|
_step() {
|
|
6247
6538
|
const tailHasReachedEnd = this.tailDistanceAlongPath >= this.totalPathLength;
|
|
@@ -6273,10 +6564,7 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6273
6564
|
}
|
|
6274
6565
|
}
|
|
6275
6566
|
}
|
|
6276
|
-
this.
|
|
6277
|
-
this.headDistanceAlongPath + this.stepSize,
|
|
6278
|
-
this.totalPathLength
|
|
6279
|
-
);
|
|
6567
|
+
this.moveHead(this.currentStepSize);
|
|
6280
6568
|
const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath);
|
|
6281
6569
|
const headPoint = this.getPointAtDistance(this.headDistanceAlongPath);
|
|
6282
6570
|
const tailIndex = this.getNearestIndexForDistance(
|
|
@@ -6295,21 +6583,26 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6295
6583
|
break;
|
|
6296
6584
|
}
|
|
6297
6585
|
}
|
|
6586
|
+
if (layerChangeBtwHeadAndTail && this.lastHeadMoveDistance > this.minStepSize) {
|
|
6587
|
+
this.stepBackAndReduceStepSize();
|
|
6588
|
+
return;
|
|
6589
|
+
}
|
|
6298
6590
|
if (layerChangeBtwHeadAndTail && layerChangeAtDistance > 0) {
|
|
6591
|
+
const pointBeforeChange = this.getPointAtDistance(layerChangeAtDistance);
|
|
6299
6592
|
if (this.lastValidPath) {
|
|
6300
6593
|
this.addPathToResult(this.lastValidPath);
|
|
6301
6594
|
this.lastValidPath = null;
|
|
6302
6595
|
}
|
|
6303
|
-
const
|
|
6304
|
-
const pointAfterChange = this.inputRoute.route[
|
|
6596
|
+
const indexAfterLayerChange = this.getNearestIndexForDistance(layerChangeAtDistance) + 1;
|
|
6597
|
+
const pointAfterChange = this.inputRoute.route[indexAfterLayerChange];
|
|
6305
6598
|
this.newVias.push({
|
|
6306
6599
|
x: pointAfterChange.x,
|
|
6307
6600
|
y: pointAfterChange.y
|
|
6308
6601
|
});
|
|
6309
6602
|
this.newRoute.push(pointAfterChange);
|
|
6310
|
-
|
|
6311
|
-
if (this.pathSegments[
|
|
6312
|
-
this.tailDistanceAlongPath = this.pathSegments[
|
|
6603
|
+
this.currentStepSize = this.maxStepSize;
|
|
6604
|
+
if (this.pathSegments[indexAfterLayerChange]) {
|
|
6605
|
+
this.tailDistanceAlongPath = this.pathSegments[indexAfterLayerChange].startDistance;
|
|
6313
6606
|
this.headDistanceAlongPath = this.tailDistanceAlongPath;
|
|
6314
6607
|
} else {
|
|
6315
6608
|
console.error("Creating via at end, this is probably not right");
|
|
@@ -6319,9 +6612,13 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6319
6612
|
return;
|
|
6320
6613
|
}
|
|
6321
6614
|
const path45 = this.find45DegreePath(tailPoint, headPoint);
|
|
6615
|
+
if (!path45 && this.lastHeadMoveDistance > this.minStepSize) {
|
|
6616
|
+
this.stepBackAndReduceStepSize();
|
|
6617
|
+
return;
|
|
6618
|
+
}
|
|
6322
6619
|
if (!path45 && !this.lastValidPath) {
|
|
6323
|
-
this.tailDistanceAlongPath += this.
|
|
6324
|
-
this.
|
|
6620
|
+
this.tailDistanceAlongPath += this.minStepSize;
|
|
6621
|
+
this.moveHead(this.minStepSize);
|
|
6325
6622
|
return;
|
|
6326
6623
|
}
|
|
6327
6624
|
if (path45) {
|
|
@@ -6333,11 +6630,8 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6333
6630
|
this.addPathToResult(this.lastValidPath);
|
|
6334
6631
|
this.lastValidPath = null;
|
|
6335
6632
|
this.tailDistanceAlongPath = this.lastValidPathHeadDistance;
|
|
6633
|
+
this.moveHead(this.minStepSize);
|
|
6336
6634
|
}
|
|
6337
|
-
this.headDistanceAlongPath = Math.min(
|
|
6338
|
-
this.headDistanceAlongPath + this.stepSize,
|
|
6339
|
-
this.totalPathLength
|
|
6340
|
-
);
|
|
6341
6635
|
}
|
|
6342
6636
|
visualize() {
|
|
6343
6637
|
const graphics = this.getVisualsForNewRouteAndObstacles();
|
|
@@ -6355,6 +6649,15 @@ var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
|
6355
6649
|
color: "orange",
|
|
6356
6650
|
label: ["Head", `z: ${headPoint.z}`].join("\n")
|
|
6357
6651
|
});
|
|
6652
|
+
const tentativeHead = this.getPointAtDistance(
|
|
6653
|
+
this.headDistanceAlongPath + this.currentStepSize
|
|
6654
|
+
);
|
|
6655
|
+
graphics.points.push({
|
|
6656
|
+
x: tentativeHead.x,
|
|
6657
|
+
y: tentativeHead.y,
|
|
6658
|
+
color: "red",
|
|
6659
|
+
label: ["Tentative Head", `z: ${tentativeHead.z}`].join("\n")
|
|
6660
|
+
});
|
|
6358
6661
|
let distance4 = 0;
|
|
6359
6662
|
while (distance4 < this.totalPathLength) {
|
|
6360
6663
|
const point = this.getPointAtDistance(distance4);
|
|
@@ -6540,6 +6843,157 @@ var MultiSimplifiedPathSolver = class extends BaseSolver {
|
|
|
6540
6843
|
}
|
|
6541
6844
|
};
|
|
6542
6845
|
|
|
6846
|
+
// lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver.ts
|
|
6847
|
+
var CapacityMeshEdgeSolver = class extends BaseSolver {
|
|
6848
|
+
constructor(nodes) {
|
|
6849
|
+
super();
|
|
6850
|
+
this.nodes = nodes;
|
|
6851
|
+
this.edges = [];
|
|
6852
|
+
}
|
|
6853
|
+
edges;
|
|
6854
|
+
getNextCapacityMeshEdgeId() {
|
|
6855
|
+
return `ce${this.edges.length}`;
|
|
6856
|
+
}
|
|
6857
|
+
step() {
|
|
6858
|
+
this.edges = [];
|
|
6859
|
+
for (let i = 0; i < this.nodes.length; i++) {
|
|
6860
|
+
for (let j = i + 1; j < this.nodes.length; j++) {
|
|
6861
|
+
const strawNodesWithSameParent = this.nodes[i]._strawNode && this.nodes[j]._strawNode && this.nodes[i]._strawParentCapacityMeshNodeId === this.nodes[j]._strawParentCapacityMeshNodeId;
|
|
6862
|
+
if (!strawNodesWithSameParent && areNodesBordering(this.nodes[i], this.nodes[j]) && this.doNodesHaveSharedLayer(this.nodes[i], this.nodes[j])) {
|
|
6863
|
+
this.edges.push({
|
|
6864
|
+
capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
|
|
6865
|
+
nodeIds: [
|
|
6866
|
+
this.nodes[i].capacityMeshNodeId,
|
|
6867
|
+
this.nodes[j].capacityMeshNodeId
|
|
6868
|
+
]
|
|
6869
|
+
});
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
}
|
|
6873
|
+
this.handleTargetNodes();
|
|
6874
|
+
this.solved = true;
|
|
6875
|
+
}
|
|
6876
|
+
handleTargetNodes() {
|
|
6877
|
+
const targetNodes = this.nodes.filter((node) => node._containsTarget);
|
|
6878
|
+
for (const targetNode of targetNodes) {
|
|
6879
|
+
const hasEdge = this.edges.some(
|
|
6880
|
+
(edge) => edge.nodeIds.includes(targetNode.capacityMeshNodeId)
|
|
6881
|
+
);
|
|
6882
|
+
if (hasEdge) continue;
|
|
6883
|
+
let nearestNode = null;
|
|
6884
|
+
let nearestDistance = Infinity;
|
|
6885
|
+
for (const node of this.nodes) {
|
|
6886
|
+
if (node._containsObstacle) continue;
|
|
6887
|
+
if (node._containsTarget) continue;
|
|
6888
|
+
const dist = distance(targetNode.center, node.center);
|
|
6889
|
+
if (dist < nearestDistance) {
|
|
6890
|
+
nearestDistance = dist;
|
|
6891
|
+
nearestNode = node;
|
|
6892
|
+
}
|
|
6893
|
+
}
|
|
6894
|
+
if (nearestNode) {
|
|
6895
|
+
this.edges.push({
|
|
6896
|
+
capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
|
|
6897
|
+
nodeIds: [
|
|
6898
|
+
targetNode.capacityMeshNodeId,
|
|
6899
|
+
nearestNode.capacityMeshNodeId
|
|
6900
|
+
]
|
|
6901
|
+
});
|
|
6902
|
+
}
|
|
6903
|
+
}
|
|
6904
|
+
}
|
|
6905
|
+
doNodesHaveSharedLayer(node1, node2) {
|
|
6906
|
+
return node1.availableZ.some((z) => node2.availableZ.includes(z));
|
|
6907
|
+
}
|
|
6908
|
+
visualize() {
|
|
6909
|
+
const graphics = {
|
|
6910
|
+
lines: [],
|
|
6911
|
+
points: [],
|
|
6912
|
+
rects: this.nodes.map((node) => {
|
|
6913
|
+
const lowestZ = Math.min(...node.availableZ);
|
|
6914
|
+
return {
|
|
6915
|
+
width: Math.max(node.width - 2, node.width * 0.8),
|
|
6916
|
+
height: Math.max(node.height - 2, node.height * 0.8),
|
|
6917
|
+
center: {
|
|
6918
|
+
x: node.center.x + lowestZ * node.width * 0.05,
|
|
6919
|
+
y: node.center.y - lowestZ * node.width * 0.05
|
|
6920
|
+
},
|
|
6921
|
+
fill: node._containsObstacle ? "rgba(255,0,0,0.1)" : {
|
|
6922
|
+
"0,1": "rgba(0,0,0,0.1)",
|
|
6923
|
+
"0": "rgba(0,200,200, 0.1)",
|
|
6924
|
+
"1": "rgba(0,0,200, 0.1)"
|
|
6925
|
+
}[node.availableZ.join(",")] ?? "rgba(0,200,200,0.1)",
|
|
6926
|
+
label: [
|
|
6927
|
+
node.capacityMeshNodeId,
|
|
6928
|
+
`availableZ: ${node.availableZ.join(",")}`,
|
|
6929
|
+
`target? ${node._containsTarget ?? false}`,
|
|
6930
|
+
`obs? ${node._containsObstacle ?? false}`
|
|
6931
|
+
].join("\n")
|
|
6932
|
+
};
|
|
6933
|
+
}),
|
|
6934
|
+
circles: []
|
|
6935
|
+
};
|
|
6936
|
+
for (const edge of this.edges) {
|
|
6937
|
+
const node1 = this.nodes.find(
|
|
6938
|
+
(node) => node.capacityMeshNodeId === edge.nodeIds[0]
|
|
6939
|
+
);
|
|
6940
|
+
const node2 = this.nodes.find(
|
|
6941
|
+
(node) => node.capacityMeshNodeId === edge.nodeIds[1]
|
|
6942
|
+
);
|
|
6943
|
+
if (node1?.center && node2?.center) {
|
|
6944
|
+
const lowestZ1 = Math.min(...node1.availableZ);
|
|
6945
|
+
const lowestZ2 = Math.min(...node2.availableZ);
|
|
6946
|
+
const nodeCenter1Adj = {
|
|
6947
|
+
x: node1.center.x + lowestZ1 * node1.width * 0.05,
|
|
6948
|
+
y: node1.center.y - lowestZ1 * node1.width * 0.05
|
|
6949
|
+
};
|
|
6950
|
+
const nodeCenter2Adj = {
|
|
6951
|
+
x: node2.center.x + lowestZ2 * node2.width * 0.05,
|
|
6952
|
+
y: node2.center.y - lowestZ2 * node2.width * 0.05
|
|
6953
|
+
};
|
|
6954
|
+
graphics.lines.push({
|
|
6955
|
+
points: [nodeCenter1Adj, nodeCenter2Adj],
|
|
6956
|
+
strokeDash: node1.availableZ.join(",") === node2.availableZ.join(",") ? void 0 : "10 5"
|
|
6957
|
+
});
|
|
6958
|
+
}
|
|
6959
|
+
}
|
|
6960
|
+
return graphics;
|
|
6961
|
+
}
|
|
6962
|
+
};
|
|
6963
|
+
|
|
6964
|
+
// lib/solvers/CapacityMeshSolver/CapacityMeshEdgeSolver2_NodeTreeOptimization.ts
|
|
6965
|
+
var CapacityMeshEdgeSolver2_NodeTreeOptimization = class extends CapacityMeshEdgeSolver {
|
|
6966
|
+
step() {
|
|
6967
|
+
this.edges = [];
|
|
6968
|
+
const edgeSet = /* @__PURE__ */ new Set();
|
|
6969
|
+
const nodeTree = new CapacityNodeTree(this.nodes);
|
|
6970
|
+
for (let i = 0; i < this.nodes.length; i++) {
|
|
6971
|
+
const A = this.nodes[i];
|
|
6972
|
+
const maybeAdjNodes = nodeTree.getNodesInArea(
|
|
6973
|
+
A.center.x,
|
|
6974
|
+
A.center.y,
|
|
6975
|
+
A.width * 2,
|
|
6976
|
+
A.height * 2
|
|
6977
|
+
);
|
|
6978
|
+
for (const B of maybeAdjNodes) {
|
|
6979
|
+
const areBordering = areNodesBordering(A, B);
|
|
6980
|
+
if (!areBordering) continue;
|
|
6981
|
+
const strawNodesWithSameParent = A._strawNode && B._strawNode && A._strawParentCapacityMeshNodeId === B._strawParentCapacityMeshNodeId;
|
|
6982
|
+
if (!strawNodesWithSameParent && this.doNodesHaveSharedLayer(A, B) && !edgeSet.has(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`)) {
|
|
6983
|
+
edgeSet.add(`${A.capacityMeshNodeId}-${B.capacityMeshNodeId}`);
|
|
6984
|
+
edgeSet.add(`${B.capacityMeshNodeId}-${A.capacityMeshNodeId}`);
|
|
6985
|
+
this.edges.push({
|
|
6986
|
+
capacityMeshEdgeId: this.getNextCapacityMeshEdgeId(),
|
|
6987
|
+
nodeIds: [A.capacityMeshNodeId, B.capacityMeshNodeId]
|
|
6988
|
+
});
|
|
6989
|
+
}
|
|
6990
|
+
}
|
|
6991
|
+
}
|
|
6992
|
+
this.handleTargetNodes();
|
|
6993
|
+
this.solved = true;
|
|
6994
|
+
}
|
|
6995
|
+
};
|
|
6996
|
+
|
|
6543
6997
|
// lib/solvers/AutoroutingPipelineSolver.ts
|
|
6544
6998
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
6545
6999
|
return {
|
|
@@ -6653,9 +7107,11 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6653
7107
|
}
|
|
6654
7108
|
}
|
|
6655
7109
|
),
|
|
6656
|
-
definePipelineStep(
|
|
6657
|
-
|
|
6658
|
-
|
|
7110
|
+
definePipelineStep(
|
|
7111
|
+
"edgeSolver",
|
|
7112
|
+
CapacityMeshEdgeSolver2_NodeTreeOptimization,
|
|
7113
|
+
(cms) => [cms.capacityNodes]
|
|
7114
|
+
),
|
|
6659
7115
|
definePipelineStep("pathingSolver", CapacityPathingSolver5, (cms) => [
|
|
6660
7116
|
{
|
|
6661
7117
|
simpleRouteJson: cms.srjWithPointPairs,
|