@tscircuit/capacity-autorouter 0.0.54 → 0.0.56

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.js CHANGED
@@ -47,6 +47,7 @@ var BaseSolver = class {
47
47
  activeSubSolver;
48
48
  failedSubSolvers;
49
49
  timeToSolve;
50
+ stats = {};
50
51
  /** DO NOT OVERRIDE! Override _step() instead */
51
52
  step() {
52
53
  if (this.solved) return;
@@ -65,6 +66,9 @@ var BaseSolver = class {
65
66
  console.error(this.error);
66
67
  this.failed = true;
67
68
  }
69
+ if ("computeProgress" in this) {
70
+ this.progress = this.computeProgress();
71
+ }
68
72
  }
69
73
  _step() {
70
74
  }
@@ -968,8 +972,935 @@ var calculateOptimalCapacityDepth = (initialWidth, targetMinCapacity = 0.5, maxD
968
972
  return Math.max(1, depth);
969
973
  };
970
974
 
975
+ // node_modules/quickselect/index.js
976
+ function quickselect(arr, k, left = 0, right = arr.length - 1, compare = defaultCompare) {
977
+ while (right > left) {
978
+ if (right - left > 600) {
979
+ const n = right - left + 1;
980
+ const m = k - left + 1;
981
+ const z = Math.log(n);
982
+ const s = 0.5 * Math.exp(2 * z / 3);
983
+ const sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
984
+ const newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
985
+ const newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
986
+ quickselect(arr, k, newLeft, newRight, compare);
987
+ }
988
+ const t = arr[k];
989
+ let i = left;
990
+ let j = right;
991
+ swap(arr, left, k);
992
+ if (compare(arr[right], t) > 0) swap(arr, left, right);
993
+ while (i < j) {
994
+ swap(arr, i, j);
995
+ i++;
996
+ j--;
997
+ while (compare(arr[i], t) < 0) i++;
998
+ while (compare(arr[j], t) > 0) j--;
999
+ }
1000
+ if (compare(arr[left], t) === 0) swap(arr, left, j);
1001
+ else {
1002
+ j++;
1003
+ swap(arr, j, right);
1004
+ }
1005
+ if (j <= k) left = j + 1;
1006
+ if (k <= j) right = j - 1;
1007
+ }
1008
+ }
1009
+ function swap(arr, i, j) {
1010
+ const tmp = arr[i];
1011
+ arr[i] = arr[j];
1012
+ arr[j] = tmp;
1013
+ }
1014
+ function defaultCompare(a, b) {
1015
+ return a < b ? -1 : a > b ? 1 : 0;
1016
+ }
1017
+
1018
+ // node_modules/rbush/index.js
1019
+ var RBush = class {
1020
+ constructor(maxEntries = 9) {
1021
+ this._maxEntries = Math.max(4, maxEntries);
1022
+ this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
1023
+ this.clear();
1024
+ }
1025
+ all() {
1026
+ return this._all(this.data, []);
1027
+ }
1028
+ search(bbox) {
1029
+ let node = this.data;
1030
+ const result = [];
1031
+ if (!intersects(bbox, node)) return result;
1032
+ const toBBox = this.toBBox;
1033
+ const nodesToSearch = [];
1034
+ while (node) {
1035
+ for (let i = 0; i < node.children.length; i++) {
1036
+ const child = node.children[i];
1037
+ const childBBox = node.leaf ? toBBox(child) : child;
1038
+ if (intersects(bbox, childBBox)) {
1039
+ if (node.leaf) result.push(child);
1040
+ else if (contains(bbox, childBBox)) this._all(child, result);
1041
+ else nodesToSearch.push(child);
1042
+ }
1043
+ }
1044
+ node = nodesToSearch.pop();
1045
+ }
1046
+ return result;
1047
+ }
1048
+ collides(bbox) {
1049
+ let node = this.data;
1050
+ if (!intersects(bbox, node)) return false;
1051
+ const nodesToSearch = [];
1052
+ while (node) {
1053
+ for (let i = 0; i < node.children.length; i++) {
1054
+ const child = node.children[i];
1055
+ const childBBox = node.leaf ? this.toBBox(child) : child;
1056
+ if (intersects(bbox, childBBox)) {
1057
+ if (node.leaf || contains(bbox, childBBox)) return true;
1058
+ nodesToSearch.push(child);
1059
+ }
1060
+ }
1061
+ node = nodesToSearch.pop();
1062
+ }
1063
+ return false;
1064
+ }
1065
+ load(data) {
1066
+ if (!(data && data.length)) return this;
1067
+ if (data.length < this._minEntries) {
1068
+ for (let i = 0; i < data.length; i++) {
1069
+ this.insert(data[i]);
1070
+ }
1071
+ return this;
1072
+ }
1073
+ let node = this._build(data.slice(), 0, data.length - 1, 0);
1074
+ if (!this.data.children.length) {
1075
+ this.data = node;
1076
+ } else if (this.data.height === node.height) {
1077
+ this._splitRoot(this.data, node);
1078
+ } else {
1079
+ if (this.data.height < node.height) {
1080
+ const tmpNode = this.data;
1081
+ this.data = node;
1082
+ node = tmpNode;
1083
+ }
1084
+ this._insert(node, this.data.height - node.height - 1, true);
1085
+ }
1086
+ return this;
1087
+ }
1088
+ insert(item) {
1089
+ if (item) this._insert(item, this.data.height - 1);
1090
+ return this;
1091
+ }
1092
+ clear() {
1093
+ this.data = createNode([]);
1094
+ return this;
1095
+ }
1096
+ remove(item, equalsFn) {
1097
+ if (!item) return this;
1098
+ let node = this.data;
1099
+ const bbox = this.toBBox(item);
1100
+ const path = [];
1101
+ const indexes = [];
1102
+ let i, parent, goingUp;
1103
+ while (node || path.length) {
1104
+ if (!node) {
1105
+ node = path.pop();
1106
+ parent = path[path.length - 1];
1107
+ i = indexes.pop();
1108
+ goingUp = true;
1109
+ }
1110
+ if (node.leaf) {
1111
+ const index = findItem(item, node.children, equalsFn);
1112
+ if (index !== -1) {
1113
+ node.children.splice(index, 1);
1114
+ path.push(node);
1115
+ this._condense(path);
1116
+ return this;
1117
+ }
1118
+ }
1119
+ if (!goingUp && !node.leaf && contains(node, bbox)) {
1120
+ path.push(node);
1121
+ indexes.push(i);
1122
+ i = 0;
1123
+ parent = node;
1124
+ node = node.children[0];
1125
+ } else if (parent) {
1126
+ i++;
1127
+ node = parent.children[i];
1128
+ goingUp = false;
1129
+ } else node = null;
1130
+ }
1131
+ return this;
1132
+ }
1133
+ toBBox(item) {
1134
+ return item;
1135
+ }
1136
+ compareMinX(a, b) {
1137
+ return a.minX - b.minX;
1138
+ }
1139
+ compareMinY(a, b) {
1140
+ return a.minY - b.minY;
1141
+ }
1142
+ toJSON() {
1143
+ return this.data;
1144
+ }
1145
+ fromJSON(data) {
1146
+ this.data = data;
1147
+ return this;
1148
+ }
1149
+ _all(node, result) {
1150
+ const nodesToSearch = [];
1151
+ while (node) {
1152
+ if (node.leaf) result.push(...node.children);
1153
+ else nodesToSearch.push(...node.children);
1154
+ node = nodesToSearch.pop();
1155
+ }
1156
+ return result;
1157
+ }
1158
+ _build(items, left, right, height) {
1159
+ const N = right - left + 1;
1160
+ let M = this._maxEntries;
1161
+ let node;
1162
+ if (N <= M) {
1163
+ node = createNode(items.slice(left, right + 1));
1164
+ calcBBox(node, this.toBBox);
1165
+ return node;
1166
+ }
1167
+ if (!height) {
1168
+ height = Math.ceil(Math.log(N) / Math.log(M));
1169
+ M = Math.ceil(N / Math.pow(M, height - 1));
1170
+ }
1171
+ node = createNode([]);
1172
+ node.leaf = false;
1173
+ node.height = height;
1174
+ const N2 = Math.ceil(N / M);
1175
+ const N1 = N2 * Math.ceil(Math.sqrt(M));
1176
+ multiSelect(items, left, right, N1, this.compareMinX);
1177
+ for (let i = left; i <= right; i += N1) {
1178
+ const right2 = Math.min(i + N1 - 1, right);
1179
+ multiSelect(items, i, right2, N2, this.compareMinY);
1180
+ for (let j = i; j <= right2; j += N2) {
1181
+ const right3 = Math.min(j + N2 - 1, right2);
1182
+ node.children.push(this._build(items, j, right3, height - 1));
1183
+ }
1184
+ }
1185
+ calcBBox(node, this.toBBox);
1186
+ return node;
1187
+ }
1188
+ _chooseSubtree(bbox, node, level, path) {
1189
+ while (true) {
1190
+ path.push(node);
1191
+ if (node.leaf || path.length - 1 === level) break;
1192
+ let minArea = Infinity;
1193
+ let minEnlargement = Infinity;
1194
+ let targetNode;
1195
+ for (let i = 0; i < node.children.length; i++) {
1196
+ const child = node.children[i];
1197
+ const area = bboxArea(child);
1198
+ const enlargement = enlargedArea(bbox, child) - area;
1199
+ if (enlargement < minEnlargement) {
1200
+ minEnlargement = enlargement;
1201
+ minArea = area < minArea ? area : minArea;
1202
+ targetNode = child;
1203
+ } else if (enlargement === minEnlargement) {
1204
+ if (area < minArea) {
1205
+ minArea = area;
1206
+ targetNode = child;
1207
+ }
1208
+ }
1209
+ }
1210
+ node = targetNode || node.children[0];
1211
+ }
1212
+ return node;
1213
+ }
1214
+ _insert(item, level, isNode) {
1215
+ const bbox = isNode ? item : this.toBBox(item);
1216
+ const insertPath = [];
1217
+ const node = this._chooseSubtree(bbox, this.data, level, insertPath);
1218
+ node.children.push(item);
1219
+ extend(node, bbox);
1220
+ while (level >= 0) {
1221
+ if (insertPath[level].children.length > this._maxEntries) {
1222
+ this._split(insertPath, level);
1223
+ level--;
1224
+ } else break;
1225
+ }
1226
+ this._adjustParentBBoxes(bbox, insertPath, level);
1227
+ }
1228
+ // split overflowed node into two
1229
+ _split(insertPath, level) {
1230
+ const node = insertPath[level];
1231
+ const M = node.children.length;
1232
+ const m = this._minEntries;
1233
+ this._chooseSplitAxis(node, m, M);
1234
+ const splitIndex = this._chooseSplitIndex(node, m, M);
1235
+ const newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
1236
+ newNode.height = node.height;
1237
+ newNode.leaf = node.leaf;
1238
+ calcBBox(node, this.toBBox);
1239
+ calcBBox(newNode, this.toBBox);
1240
+ if (level) insertPath[level - 1].children.push(newNode);
1241
+ else this._splitRoot(node, newNode);
1242
+ }
1243
+ _splitRoot(node, newNode) {
1244
+ this.data = createNode([node, newNode]);
1245
+ this.data.height = node.height + 1;
1246
+ this.data.leaf = false;
1247
+ calcBBox(this.data, this.toBBox);
1248
+ }
1249
+ _chooseSplitIndex(node, m, M) {
1250
+ let index;
1251
+ let minOverlap = Infinity;
1252
+ let minArea = Infinity;
1253
+ for (let i = m; i <= M - m; i++) {
1254
+ const bbox1 = distBBox(node, 0, i, this.toBBox);
1255
+ const bbox2 = distBBox(node, i, M, this.toBBox);
1256
+ const overlap = intersectionArea(bbox1, bbox2);
1257
+ const area = bboxArea(bbox1) + bboxArea(bbox2);
1258
+ if (overlap < minOverlap) {
1259
+ minOverlap = overlap;
1260
+ index = i;
1261
+ minArea = area < minArea ? area : minArea;
1262
+ } else if (overlap === minOverlap) {
1263
+ if (area < minArea) {
1264
+ minArea = area;
1265
+ index = i;
1266
+ }
1267
+ }
1268
+ }
1269
+ return index || M - m;
1270
+ }
1271
+ // sorts node children by the best axis for split
1272
+ _chooseSplitAxis(node, m, M) {
1273
+ const compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
1274
+ const compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
1275
+ const xMargin = this._allDistMargin(node, m, M, compareMinX);
1276
+ const yMargin = this._allDistMargin(node, m, M, compareMinY);
1277
+ if (xMargin < yMargin) node.children.sort(compareMinX);
1278
+ }
1279
+ // total margin of all possible split distributions where each node is at least m full
1280
+ _allDistMargin(node, m, M, compare) {
1281
+ node.children.sort(compare);
1282
+ const toBBox = this.toBBox;
1283
+ const leftBBox = distBBox(node, 0, m, toBBox);
1284
+ const rightBBox = distBBox(node, M - m, M, toBBox);
1285
+ let margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
1286
+ for (let i = m; i < M - m; i++) {
1287
+ const child = node.children[i];
1288
+ extend(leftBBox, node.leaf ? toBBox(child) : child);
1289
+ margin += bboxMargin(leftBBox);
1290
+ }
1291
+ for (let i = M - m - 1; i >= m; i--) {
1292
+ const child = node.children[i];
1293
+ extend(rightBBox, node.leaf ? toBBox(child) : child);
1294
+ margin += bboxMargin(rightBBox);
1295
+ }
1296
+ return margin;
1297
+ }
1298
+ _adjustParentBBoxes(bbox, path, level) {
1299
+ for (let i = level; i >= 0; i--) {
1300
+ extend(path[i], bbox);
1301
+ }
1302
+ }
1303
+ _condense(path) {
1304
+ for (let i = path.length - 1, siblings; i >= 0; i--) {
1305
+ if (path[i].children.length === 0) {
1306
+ if (i > 0) {
1307
+ siblings = path[i - 1].children;
1308
+ siblings.splice(siblings.indexOf(path[i]), 1);
1309
+ } else this.clear();
1310
+ } else calcBBox(path[i], this.toBBox);
1311
+ }
1312
+ }
1313
+ };
1314
+ function findItem(item, items, equalsFn) {
1315
+ if (!equalsFn) return items.indexOf(item);
1316
+ for (let i = 0; i < items.length; i++) {
1317
+ if (equalsFn(item, items[i])) return i;
1318
+ }
1319
+ return -1;
1320
+ }
1321
+ function calcBBox(node, toBBox) {
1322
+ distBBox(node, 0, node.children.length, toBBox, node);
1323
+ }
1324
+ function distBBox(node, k, p, toBBox, destNode) {
1325
+ if (!destNode) destNode = createNode(null);
1326
+ destNode.minX = Infinity;
1327
+ destNode.minY = Infinity;
1328
+ destNode.maxX = -Infinity;
1329
+ destNode.maxY = -Infinity;
1330
+ for (let i = k; i < p; i++) {
1331
+ const child = node.children[i];
1332
+ extend(destNode, node.leaf ? toBBox(child) : child);
1333
+ }
1334
+ return destNode;
1335
+ }
1336
+ function extend(a, b) {
1337
+ a.minX = Math.min(a.minX, b.minX);
1338
+ a.minY = Math.min(a.minY, b.minY);
1339
+ a.maxX = Math.max(a.maxX, b.maxX);
1340
+ a.maxY = Math.max(a.maxY, b.maxY);
1341
+ return a;
1342
+ }
1343
+ function compareNodeMinX(a, b) {
1344
+ return a.minX - b.minX;
1345
+ }
1346
+ function compareNodeMinY(a, b) {
1347
+ return a.minY - b.minY;
1348
+ }
1349
+ function bboxArea(a) {
1350
+ return (a.maxX - a.minX) * (a.maxY - a.minY);
1351
+ }
1352
+ function bboxMargin(a) {
1353
+ return a.maxX - a.minX + (a.maxY - a.minY);
1354
+ }
1355
+ function enlargedArea(a, b) {
1356
+ return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
1357
+ }
1358
+ function intersectionArea(a, b) {
1359
+ const minX = Math.max(a.minX, b.minX);
1360
+ const minY = Math.max(a.minY, b.minY);
1361
+ const maxX = Math.min(a.maxX, b.maxX);
1362
+ const maxY = Math.min(a.maxY, b.maxY);
1363
+ return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
1364
+ }
1365
+ function contains(a, b) {
1366
+ return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
1367
+ }
1368
+ function intersects(a, b) {
1369
+ return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
1370
+ }
1371
+ function createNode(children) {
1372
+ return {
1373
+ children,
1374
+ height: 1,
1375
+ leaf: true,
1376
+ minX: Infinity,
1377
+ minY: Infinity,
1378
+ maxX: -Infinity,
1379
+ maxY: -Infinity
1380
+ };
1381
+ }
1382
+ function multiSelect(arr, left, right, n, compare) {
1383
+ const stack = [left, right];
1384
+ while (stack.length) {
1385
+ right = stack.pop();
1386
+ left = stack.pop();
1387
+ if (right - left <= n) continue;
1388
+ const mid = left + Math.ceil((right - left) / n / 2) * n;
1389
+ quickselect(arr, mid, left, right, compare);
1390
+ stack.push(left, mid, mid, right);
1391
+ }
1392
+ }
1393
+
1394
+ // lib/data-structures/RbushIndex.ts
1395
+ var RbushIndex = class {
1396
+ tree;
1397
+ constructor(maxEntries = 9) {
1398
+ this.tree = new RBush(maxEntries);
1399
+ }
1400
+ insert(item, minX, minY, maxX, maxY) {
1401
+ this.tree.insert({ minX, minY, maxX, maxY, data: item });
1402
+ }
1403
+ bulkLoad(items) {
1404
+ const nodes = items.map(({ item, minX, minY, maxX, maxY }) => ({
1405
+ minX,
1406
+ minY,
1407
+ maxX,
1408
+ maxY,
1409
+ data: item
1410
+ }));
1411
+ this.tree.load(nodes);
1412
+ }
1413
+ search(minX, minY, maxX, maxY) {
1414
+ return this.tree.search({ minX, minY, maxX, maxY }).map((n) => n.data);
1415
+ }
1416
+ clear() {
1417
+ this.tree.clear();
1418
+ }
1419
+ };
1420
+
1421
+ // node_modules/flatqueue/index.js
1422
+ var FlatQueue = class {
1423
+ constructor() {
1424
+ this.ids = [];
1425
+ this.values = [];
1426
+ this.length = 0;
1427
+ }
1428
+ clear() {
1429
+ this.length = 0;
1430
+ }
1431
+ push(id, value) {
1432
+ let pos = this.length++;
1433
+ while (pos > 0) {
1434
+ const parent = pos - 1 >> 1;
1435
+ const parentValue = this.values[parent];
1436
+ if (value >= parentValue) break;
1437
+ this.ids[pos] = this.ids[parent];
1438
+ this.values[pos] = parentValue;
1439
+ pos = parent;
1440
+ }
1441
+ this.ids[pos] = id;
1442
+ this.values[pos] = value;
1443
+ }
1444
+ pop() {
1445
+ if (this.length === 0) return void 0;
1446
+ const top = this.ids[0];
1447
+ this.length--;
1448
+ if (this.length > 0) {
1449
+ const id = this.ids[0] = this.ids[this.length];
1450
+ const value = this.values[0] = this.values[this.length];
1451
+ const halfLength = this.length >> 1;
1452
+ let pos = 0;
1453
+ while (pos < halfLength) {
1454
+ let left = (pos << 1) + 1;
1455
+ const right = left + 1;
1456
+ let bestIndex = this.ids[left];
1457
+ let bestValue = this.values[left];
1458
+ const rightValue = this.values[right];
1459
+ if (right < this.length && rightValue < bestValue) {
1460
+ left = right;
1461
+ bestIndex = this.ids[right];
1462
+ bestValue = rightValue;
1463
+ }
1464
+ if (bestValue >= value) break;
1465
+ this.ids[pos] = bestIndex;
1466
+ this.values[pos] = bestValue;
1467
+ pos = left;
1468
+ }
1469
+ this.ids[pos] = id;
1470
+ this.values[pos] = value;
1471
+ }
1472
+ return top;
1473
+ }
1474
+ peek() {
1475
+ if (this.length === 0) return void 0;
1476
+ return this.ids[0];
1477
+ }
1478
+ peekValue() {
1479
+ if (this.length === 0) return void 0;
1480
+ return this.values[0];
1481
+ }
1482
+ shrink() {
1483
+ this.ids.length = this.values.length = this.length;
1484
+ }
1485
+ };
1486
+
1487
+ // node_modules/flatbush/index.js
1488
+ var ARRAY_TYPES = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
1489
+ var VERSION = 3;
1490
+ var Flatbush = class _Flatbush {
1491
+ /**
1492
+ * Recreate a Flatbush index from raw `ArrayBuffer` or `SharedArrayBuffer` data.
1493
+ * @param {ArrayBuffer | SharedArrayBuffer} data
1494
+ * @param {number} [byteOffset=0] byte offset to the start of the Flatbush buffer in the referenced ArrayBuffer.
1495
+ * @returns {Flatbush} index
1496
+ */
1497
+ static from(data, byteOffset = 0) {
1498
+ if (byteOffset % 8 !== 0) {
1499
+ throw new Error("byteOffset must be 8-byte aligned.");
1500
+ }
1501
+ if (!data || data.byteLength === void 0 || data.buffer) {
1502
+ throw new Error("Data must be an instance of ArrayBuffer or SharedArrayBuffer.");
1503
+ }
1504
+ const [magic, versionAndType] = new Uint8Array(data, byteOffset + 0, 2);
1505
+ if (magic !== 251) {
1506
+ throw new Error("Data does not appear to be in a Flatbush format.");
1507
+ }
1508
+ const version = versionAndType >> 4;
1509
+ if (version !== VERSION) {
1510
+ throw new Error(`Got v${version} data when expected v${VERSION}.`);
1511
+ }
1512
+ const ArrayType = ARRAY_TYPES[versionAndType & 15];
1513
+ if (!ArrayType) {
1514
+ throw new Error("Unrecognized array type.");
1515
+ }
1516
+ const [nodeSize] = new Uint16Array(data, byteOffset + 2, 1);
1517
+ const [numItems] = new Uint32Array(data, byteOffset + 4, 1);
1518
+ return new _Flatbush(numItems, nodeSize, ArrayType, void 0, data, byteOffset);
1519
+ }
1520
+ /**
1521
+ * Create a Flatbush index that will hold a given number of items.
1522
+ * @param {number} numItems
1523
+ * @param {number} [nodeSize=16] Size of the tree node (16 by default).
1524
+ * @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default).
1525
+ * @param {ArrayBufferConstructor | SharedArrayBufferConstructor} [ArrayBufferType=ArrayBuffer] The array buffer type used to store data (`ArrayBuffer` by default).
1526
+ * @param {ArrayBuffer | SharedArrayBuffer} [data] (Only used internally)
1527
+ * @param {number} [byteOffset=0] (Only used internally)
1528
+ */
1529
+ constructor(numItems, nodeSize = 16, ArrayType = Float64Array, ArrayBufferType = ArrayBuffer, data, byteOffset = 0) {
1530
+ if (numItems === void 0) throw new Error("Missing required argument: numItems.");
1531
+ if (isNaN(numItems) || numItems <= 0) throw new Error(`Unexpected numItems value: ${numItems}.`);
1532
+ this.numItems = +numItems;
1533
+ this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535);
1534
+ this.byteOffset = byteOffset;
1535
+ let n = numItems;
1536
+ let numNodes = n;
1537
+ this._levelBounds = [n * 4];
1538
+ do {
1539
+ n = Math.ceil(n / this.nodeSize);
1540
+ numNodes += n;
1541
+ this._levelBounds.push(numNodes * 4);
1542
+ } while (n !== 1);
1543
+ this.ArrayType = ArrayType;
1544
+ this.IndexArrayType = numNodes < 16384 ? Uint16Array : Uint32Array;
1545
+ const arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType);
1546
+ const nodesByteSize = numNodes * 4 * this.ArrayType.BYTES_PER_ELEMENT;
1547
+ if (arrayTypeIndex < 0) {
1548
+ throw new Error(`Unexpected typed array class: ${ArrayType}.`);
1549
+ }
1550
+ if (data && data.byteLength !== void 0 && !data.buffer) {
1551
+ this.data = data;
1552
+ this._boxes = new this.ArrayType(this.data, byteOffset + 8, numNodes * 4);
1553
+ this._indices = new this.IndexArrayType(this.data, byteOffset + 8 + nodesByteSize, numNodes);
1554
+ this._pos = numNodes * 4;
1555
+ this.minX = this._boxes[this._pos - 4];
1556
+ this.minY = this._boxes[this._pos - 3];
1557
+ this.maxX = this._boxes[this._pos - 2];
1558
+ this.maxY = this._boxes[this._pos - 1];
1559
+ } else {
1560
+ this.data = new ArrayBufferType(8 + nodesByteSize + numNodes * this.IndexArrayType.BYTES_PER_ELEMENT);
1561
+ this._boxes = new this.ArrayType(this.data, 8, numNodes * 4);
1562
+ this._indices = new this.IndexArrayType(this.data, 8 + nodesByteSize, numNodes);
1563
+ this._pos = 0;
1564
+ this.minX = Infinity;
1565
+ this.minY = Infinity;
1566
+ this.maxX = -Infinity;
1567
+ this.maxY = -Infinity;
1568
+ new Uint8Array(this.data, 0, 2).set([251, (VERSION << 4) + arrayTypeIndex]);
1569
+ new Uint16Array(this.data, 2, 1)[0] = nodeSize;
1570
+ new Uint32Array(this.data, 4, 1)[0] = numItems;
1571
+ }
1572
+ this._queue = new FlatQueue();
1573
+ }
1574
+ /**
1575
+ * Add a given rectangle to the index.
1576
+ * @param {number} minX
1577
+ * @param {number} minY
1578
+ * @param {number} maxX
1579
+ * @param {number} maxY
1580
+ * @returns {number} A zero-based, incremental number that represents the newly added rectangle.
1581
+ */
1582
+ add(minX, minY, maxX = minX, maxY = minY) {
1583
+ const index = this._pos >> 2;
1584
+ const boxes = this._boxes;
1585
+ this._indices[index] = index;
1586
+ boxes[this._pos++] = minX;
1587
+ boxes[this._pos++] = minY;
1588
+ boxes[this._pos++] = maxX;
1589
+ boxes[this._pos++] = maxY;
1590
+ if (minX < this.minX) this.minX = minX;
1591
+ if (minY < this.minY) this.minY = minY;
1592
+ if (maxX > this.maxX) this.maxX = maxX;
1593
+ if (maxY > this.maxY) this.maxY = maxY;
1594
+ return index;
1595
+ }
1596
+ /** Perform indexing of the added rectangles. */
1597
+ finish() {
1598
+ if (this._pos >> 2 !== this.numItems) {
1599
+ throw new Error(`Added ${this._pos >> 2} items when expected ${this.numItems}.`);
1600
+ }
1601
+ const boxes = this._boxes;
1602
+ if (this.numItems <= this.nodeSize) {
1603
+ boxes[this._pos++] = this.minX;
1604
+ boxes[this._pos++] = this.minY;
1605
+ boxes[this._pos++] = this.maxX;
1606
+ boxes[this._pos++] = this.maxY;
1607
+ return;
1608
+ }
1609
+ const width = this.maxX - this.minX || 1;
1610
+ const height = this.maxY - this.minY || 1;
1611
+ const hilbertValues = new Uint32Array(this.numItems);
1612
+ const hilbertMax = (1 << 16) - 1;
1613
+ for (let i = 0, pos = 0; i < this.numItems; i++) {
1614
+ const minX = boxes[pos++];
1615
+ const minY = boxes[pos++];
1616
+ const maxX = boxes[pos++];
1617
+ const maxY = boxes[pos++];
1618
+ const x = Math.floor(hilbertMax * ((minX + maxX) / 2 - this.minX) / width);
1619
+ const y = Math.floor(hilbertMax * ((minY + maxY) / 2 - this.minY) / height);
1620
+ hilbertValues[i] = hilbert(x, y);
1621
+ }
1622
+ sort(hilbertValues, boxes, this._indices, 0, this.numItems - 1, this.nodeSize);
1623
+ for (let i = 0, pos = 0; i < this._levelBounds.length - 1; i++) {
1624
+ const end = this._levelBounds[i];
1625
+ while (pos < end) {
1626
+ const nodeIndex = pos;
1627
+ let nodeMinX = boxes[pos++];
1628
+ let nodeMinY = boxes[pos++];
1629
+ let nodeMaxX = boxes[pos++];
1630
+ let nodeMaxY = boxes[pos++];
1631
+ for (let j = 1; j < this.nodeSize && pos < end; j++) {
1632
+ nodeMinX = Math.min(nodeMinX, boxes[pos++]);
1633
+ nodeMinY = Math.min(nodeMinY, boxes[pos++]);
1634
+ nodeMaxX = Math.max(nodeMaxX, boxes[pos++]);
1635
+ nodeMaxY = Math.max(nodeMaxY, boxes[pos++]);
1636
+ }
1637
+ this._indices[this._pos >> 2] = nodeIndex;
1638
+ boxes[this._pos++] = nodeMinX;
1639
+ boxes[this._pos++] = nodeMinY;
1640
+ boxes[this._pos++] = nodeMaxX;
1641
+ boxes[this._pos++] = nodeMaxY;
1642
+ }
1643
+ }
1644
+ }
1645
+ /**
1646
+ * Search the index by a bounding box.
1647
+ * @param {number} minX
1648
+ * @param {number} minY
1649
+ * @param {number} maxX
1650
+ * @param {number} maxY
1651
+ * @param {(index: number) => boolean} [filterFn] An optional function for filtering the results.
1652
+ * @returns {number[]} An array of indices of items intersecting or touching the given bounding box.
1653
+ */
1654
+ search(minX, minY, maxX, maxY, filterFn) {
1655
+ if (this._pos !== this._boxes.length) {
1656
+ throw new Error("Data not yet indexed - call index.finish().");
1657
+ }
1658
+ let nodeIndex = this._boxes.length - 4;
1659
+ const queue = [];
1660
+ const results = [];
1661
+ while (nodeIndex !== void 0) {
1662
+ const end = Math.min(nodeIndex + this.nodeSize * 4, upperBound(nodeIndex, this._levelBounds));
1663
+ for (let pos = nodeIndex; pos < end; pos += 4) {
1664
+ if (maxX < this._boxes[pos]) continue;
1665
+ if (maxY < this._boxes[pos + 1]) continue;
1666
+ if (minX > this._boxes[pos + 2]) continue;
1667
+ if (minY > this._boxes[pos + 3]) continue;
1668
+ const index = this._indices[pos >> 2] | 0;
1669
+ if (nodeIndex >= this.numItems * 4) {
1670
+ queue.push(index);
1671
+ } else if (filterFn === void 0 || filterFn(index)) {
1672
+ results.push(index);
1673
+ }
1674
+ }
1675
+ nodeIndex = queue.pop();
1676
+ }
1677
+ return results;
1678
+ }
1679
+ /**
1680
+ * Search items in order of distance from the given point.
1681
+ * @param {number} x
1682
+ * @param {number} y
1683
+ * @param {number} [maxResults=Infinity]
1684
+ * @param {number} [maxDistance=Infinity]
1685
+ * @param {(index: number) => boolean} [filterFn] An optional function for filtering the results.
1686
+ * @returns {number[]} An array of indices of items found.
1687
+ */
1688
+ neighbors(x, y, maxResults = Infinity, maxDistance = Infinity, filterFn) {
1689
+ if (this._pos !== this._boxes.length) {
1690
+ throw new Error("Data not yet indexed - call index.finish().");
1691
+ }
1692
+ let nodeIndex = this._boxes.length - 4;
1693
+ const q = this._queue;
1694
+ const results = [];
1695
+ const maxDistSquared = maxDistance * maxDistance;
1696
+ outer: while (nodeIndex !== void 0) {
1697
+ const end = Math.min(nodeIndex + this.nodeSize * 4, upperBound(nodeIndex, this._levelBounds));
1698
+ for (let pos = nodeIndex; pos < end; pos += 4) {
1699
+ const index = this._indices[pos >> 2] | 0;
1700
+ const dx = axisDist(x, this._boxes[pos], this._boxes[pos + 2]);
1701
+ const dy = axisDist(y, this._boxes[pos + 1], this._boxes[pos + 3]);
1702
+ const dist = dx * dx + dy * dy;
1703
+ if (dist > maxDistSquared) continue;
1704
+ if (nodeIndex >= this.numItems * 4) {
1705
+ q.push(index << 1, dist);
1706
+ } else if (filterFn === void 0 || filterFn(index)) {
1707
+ q.push((index << 1) + 1, dist);
1708
+ }
1709
+ }
1710
+ while (q.length && q.peek() & 1) {
1711
+ const dist = q.peekValue();
1712
+ if (dist > maxDistSquared) break outer;
1713
+ results.push(q.pop() >> 1);
1714
+ if (results.length === maxResults) break outer;
1715
+ }
1716
+ nodeIndex = q.length ? q.pop() >> 1 : void 0;
1717
+ }
1718
+ q.clear();
1719
+ return results;
1720
+ }
1721
+ };
1722
+ function axisDist(k, min, max) {
1723
+ return k < min ? min - k : k <= max ? 0 : k - max;
1724
+ }
1725
+ function upperBound(value, arr) {
1726
+ let i = 0;
1727
+ let j = arr.length - 1;
1728
+ while (i < j) {
1729
+ const m = i + j >> 1;
1730
+ if (arr[m] > value) {
1731
+ j = m;
1732
+ } else {
1733
+ i = m + 1;
1734
+ }
1735
+ }
1736
+ return arr[i];
1737
+ }
1738
+ function sort(values, boxes, indices, left, right, nodeSize) {
1739
+ if (Math.floor(left / nodeSize) >= Math.floor(right / nodeSize)) return;
1740
+ const pivot = values[left + right >> 1];
1741
+ let i = left - 1;
1742
+ let j = right + 1;
1743
+ while (true) {
1744
+ do
1745
+ i++;
1746
+ while (values[i] < pivot);
1747
+ do
1748
+ j--;
1749
+ while (values[j] > pivot);
1750
+ if (i >= j) break;
1751
+ swap2(values, boxes, indices, i, j);
1752
+ }
1753
+ sort(values, boxes, indices, left, j, nodeSize);
1754
+ sort(values, boxes, indices, j + 1, right, nodeSize);
1755
+ }
1756
+ function swap2(values, boxes, indices, i, j) {
1757
+ const temp = values[i];
1758
+ values[i] = values[j];
1759
+ values[j] = temp;
1760
+ const k = 4 * i;
1761
+ const m = 4 * j;
1762
+ const a = boxes[k];
1763
+ const b = boxes[k + 1];
1764
+ const c = boxes[k + 2];
1765
+ const d = boxes[k + 3];
1766
+ boxes[k] = boxes[m];
1767
+ boxes[k + 1] = boxes[m + 1];
1768
+ boxes[k + 2] = boxes[m + 2];
1769
+ boxes[k + 3] = boxes[m + 3];
1770
+ boxes[m] = a;
1771
+ boxes[m + 1] = b;
1772
+ boxes[m + 2] = c;
1773
+ boxes[m + 3] = d;
1774
+ const e = indices[i];
1775
+ indices[i] = indices[j];
1776
+ indices[j] = e;
1777
+ }
1778
+ function hilbert(x, y) {
1779
+ let a = x ^ y;
1780
+ let b = 65535 ^ a;
1781
+ let c = 65535 ^ (x | y);
1782
+ let d = x & (y ^ 65535);
1783
+ let A = a | b >> 1;
1784
+ let B = a >> 1 ^ a;
1785
+ let C = c >> 1 ^ b & d >> 1 ^ c;
1786
+ let D = a & c >> 1 ^ d >> 1 ^ d;
1787
+ a = A;
1788
+ b = B;
1789
+ c = C;
1790
+ d = D;
1791
+ A = a & a >> 2 ^ b & b >> 2;
1792
+ B = a & b >> 2 ^ b & (a ^ b) >> 2;
1793
+ C ^= a & c >> 2 ^ b & d >> 2;
1794
+ D ^= b & c >> 2 ^ (a ^ b) & d >> 2;
1795
+ a = A;
1796
+ b = B;
1797
+ c = C;
1798
+ d = D;
1799
+ A = a & a >> 4 ^ b & b >> 4;
1800
+ B = a & b >> 4 ^ b & (a ^ b) >> 4;
1801
+ C ^= a & c >> 4 ^ b & d >> 4;
1802
+ D ^= b & c >> 4 ^ (a ^ b) & d >> 4;
1803
+ a = A;
1804
+ b = B;
1805
+ c = C;
1806
+ d = D;
1807
+ C ^= a & c >> 8 ^ b & d >> 8;
1808
+ D ^= b & c >> 8 ^ (a ^ b) & d >> 8;
1809
+ a = C ^ C >> 1;
1810
+ b = D ^ D >> 1;
1811
+ let i0 = x ^ y;
1812
+ let i1 = b | 65535 ^ (i0 | a);
1813
+ i0 = (i0 | i0 << 8) & 16711935;
1814
+ i0 = (i0 | i0 << 4) & 252645135;
1815
+ i0 = (i0 | i0 << 2) & 858993459;
1816
+ i0 = (i0 | i0 << 1) & 1431655765;
1817
+ i1 = (i1 | i1 << 8) & 16711935;
1818
+ i1 = (i1 | i1 << 4) & 252645135;
1819
+ i1 = (i1 | i1 << 2) & 858993459;
1820
+ i1 = (i1 | i1 << 1) & 1431655765;
1821
+ return (i1 << 1 | i0) >>> 0;
1822
+ }
1823
+
1824
+ // lib/data-structures/FlatbushIndex.ts
1825
+ var FlatbushIndex = class {
1826
+ index;
1827
+ items = [];
1828
+ currentIndex = 0;
1829
+ constructor(numItems) {
1830
+ this.index = new Flatbush(numItems);
1831
+ }
1832
+ insert(item, minX, minY, maxX, maxY) {
1833
+ if (this.currentIndex >= this.index.numItems) {
1834
+ throw new Error("Exceeded initial capacity");
1835
+ }
1836
+ this.items[this.currentIndex] = item;
1837
+ this.index.add(minX, minY, maxX, maxY);
1838
+ this.currentIndex++;
1839
+ }
1840
+ finish() {
1841
+ this.index.finish();
1842
+ }
1843
+ search(minX, minY, maxX, maxY) {
1844
+ const ids = this.index.search(minX, minY, maxX, maxY);
1845
+ return ids.map((id) => this.items[id] || null).filter(Boolean);
1846
+ }
1847
+ clear() {
1848
+ this.items = [];
1849
+ this.index = new Flatbush(0);
1850
+ }
1851
+ };
1852
+
971
1853
  // lib/data-structures/ObstacleTree.ts
972
1854
  var ObstacleSpatialHashIndex = class {
1855
+ idx;
1856
+ storage = [];
1857
+ constructor(implementation = "native", obstacles = []) {
1858
+ if (implementation === "flatbush") {
1859
+ this.idx = new FlatbushIndex(obstacles.length);
1860
+ } else if (implementation === "rbush") {
1861
+ this.idx = new RbushIndex();
1862
+ } else {
1863
+ this.idx = new class {
1864
+ shi = new NativeObstacleTree(obstacles);
1865
+ insert(item) {
1866
+ }
1867
+ search(minX, minY, maxX, maxY) {
1868
+ const centerX = (minX + maxX) / 2;
1869
+ const centerY = (minY + maxY) / 2;
1870
+ const width = maxX - minX;
1871
+ const height = maxY - minY;
1872
+ return this.shi.getNodesInArea(centerX, centerY, width, height);
1873
+ }
1874
+ clear() {
1875
+ }
1876
+ }();
1877
+ }
1878
+ obstacles.forEach((o) => this.insert(o));
1879
+ if (implementation === "flatbush") this.idx.finish?.();
1880
+ }
1881
+ insert(o) {
1882
+ this.storage.push(o);
1883
+ this.idx.insert(
1884
+ o,
1885
+ o.center.x - o.width / 2,
1886
+ o.center.y - o.height / 2,
1887
+ o.center.x + o.width / 2,
1888
+ o.center.y + o.height / 2
1889
+ );
1890
+ }
1891
+ search(bbox) {
1892
+ return this.idx.search(bbox.minX, bbox.minY, bbox.maxX, bbox.maxY);
1893
+ }
1894
+ searchArea(centerX, centerY, width, height) {
1895
+ return this.search({
1896
+ minX: centerX - width / 2,
1897
+ minY: centerY - height / 2,
1898
+ maxX: centerX + width / 2,
1899
+ maxY: centerY + height / 2
1900
+ });
1901
+ }
1902
+ };
1903
+ var NativeObstacleTree = class {
973
1904
  constructor(obstacles) {
974
1905
  this.obstacles = obstacles;
975
1906
  this.buckets = /* @__PURE__ */ new Map();
@@ -1115,7 +2046,10 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
1115
2046
  ];
1116
2047
  this.finishedNodes = [];
1117
2048
  this.nodeToXYOverlappingObstaclesMap = /* @__PURE__ */ new Map();
1118
- this.obstacleTree = new ObstacleSpatialHashIndex(this.srj.obstacles);
2049
+ this.obstacleTree = new ObstacleSpatialHashIndex(
2050
+ "flatbush",
2051
+ this.srj.obstacles
2052
+ );
1119
2053
  this.targets = this.computeTargets();
1120
2054
  this.targetTree = new TargetTree(this.targets);
1121
2055
  }
@@ -1132,7 +2066,7 @@ var CapacityMeshNodeSolver = class extends BaseSolver {
1132
2066
  const targets = [];
1133
2067
  for (const conn of this.srj.connections) {
1134
2068
  for (const ptc of conn.pointsToConnect) {
1135
- const obstacles = this.obstacleTree.getNodesInArea(ptc.x, ptc.y, 0.01, 0.01).filter(
2069
+ const obstacles = this.obstacleTree.searchArea(ptc.x, ptc.y, 0.01, 0.01).filter(
1136
2070
  (o) => o.zLayers.some((z) => ptc.layer === "top" ? z === 0 : z === 1)
1137
2071
  );
1138
2072
  let bounds = {
@@ -1972,7 +2906,7 @@ var CapacitySegmentToPointSolver = class extends BaseSolver {
1972
2906
  }
1973
2907
  };
1974
2908
 
1975
- // node_modules/@tscircuit/math-utils/dist/chunk-CHQOCSFB.js
2909
+ // node_modules/@tscircuit/math-utils/dist/chunk-3453HRP7.js
1976
2910
  function doSegmentsIntersect(p1, q1, p2, q2) {
1977
2911
  const o1 = orientation(p1, q1, p2);
1978
2912
  const o2 = orientation(p1, q1, q2);
@@ -2044,7 +2978,7 @@ function clamp(value, min, max) {
2044
2978
  return Math.max(min, Math.min(max, value));
2045
2979
  }
2046
2980
 
2047
- // node_modules/@tscircuit/math-utils/dist/chunk-RNQKFERU.js
2981
+ // node_modules/@tscircuit/math-utils/dist/chunk-FWQGMQBW.js
2048
2982
  function segmentToSegmentMinDistance(a, b, u, v) {
2049
2983
  if (a.x === b.x && a.y === b.y) {
2050
2984
  return pointToSegmentDistance(a, u, v);
@@ -3078,12 +4012,15 @@ var HyperParameterSupervisorSolver = class extends BaseSolver {
3078
4012
  }
3079
4013
  return bestSolver;
3080
4014
  }
4015
+ getFailureMessage() {
4016
+ return "All solvers failed in hyper solver.";
4017
+ }
3081
4018
  _step() {
3082
4019
  if (!this.supervisedSolvers) this.initializeSolvers();
3083
4020
  const supervisedSolver = this.getSupervisedSolverWithBestFitness();
3084
4021
  if (!supervisedSolver) {
3085
4022
  this.failed = true;
3086
- this.error = "All solvers failed";
4023
+ this.error = this.getFailureMessage();
3087
4024
  return;
3088
4025
  }
3089
4026
  for (let i = 0; i < this.MIN_SUBSTEPS; i++) {
@@ -5332,10 +6269,13 @@ var Vertex = class {
5332
6269
  y;
5333
6270
  out;
5334
6271
  // Outgoing half-edge indices
6272
+ connectionNames;
6273
+ // Names of connections passing through this vertex
5335
6274
  constructor(x, y) {
5336
6275
  this.x = x;
5337
6276
  this.y = y;
5338
6277
  this.out = [];
6278
+ this.connectionNames = /* @__PURE__ */ new Set();
5339
6279
  }
5340
6280
  };
5341
6281
  var HalfEdge = class {
@@ -5419,9 +6359,17 @@ function getCentroidsFromInnerBoxIntersections(rectangle, userSegments) {
5419
6359
  return t1 - t2;
5420
6360
  });
5421
6361
  for (let k = 0; k < list.length - 1; ++k) {
5422
- const v1 = getVertexId(list[k]);
5423
- const v2 = getVertexId(list[k + 1]);
5424
- if (v1 !== v2) undirectedEdges.push([v1, v2]);
6362
+ const p1 = list[k];
6363
+ const p2 = list[k + 1];
6364
+ const v1 = getVertexId(p1);
6365
+ const v2 = getVertexId(p2);
6366
+ if (v1 !== v2) {
6367
+ undirectedEdges.push([v1, v2]);
6368
+ if (s.connectionName) {
6369
+ vertices[v1].connectionNames.add(s.connectionName);
6370
+ vertices[v2].connectionNames.add(s.connectionName);
6371
+ }
6372
+ }
5425
6373
  }
5426
6374
  }
5427
6375
  const halfEdges = [];
@@ -5478,8 +6426,11 @@ function getCentroidsFromInnerBoxIntersections(rectangle, userSegments) {
5478
6426
  if (c) {
5479
6427
  centroids.push(c);
5480
6428
  faces.push({
5481
- vertices: poly.map((p) => ({ x: p.x, y: p.y })),
5482
- // Convert Vertex back to simple Point
6429
+ vertices: poly.map((v) => ({
6430
+ x: v.x,
6431
+ y: v.y,
6432
+ connectionNames: v.connectionNames.size > 0 ? v.connectionNames : void 0
6433
+ })),
5483
6434
  centroid: c
5484
6435
  });
5485
6436
  }
@@ -6065,6 +7016,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
6065
7016
  obstacleMargin = 0.1;
6066
7017
  traceWidth = 0.15;
6067
7018
  availableZ = [];
7019
+ uniqueConnections = 0;
6068
7020
  lastCandidate = null;
6069
7021
  maxViaCount;
6070
7022
  minViaCount;
@@ -6092,6 +7044,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
6092
7044
  const uniqueConnections = new Set(
6093
7045
  this.nodeWithPortPoints.portPoints.map((pp) => pp.connectionName)
6094
7046
  ).size;
7047
+ this.uniqueConnections = uniqueConnections;
6095
7048
  const { numSameLayerCrossings, numTransitions } = getIntraNodeCrossings(
6096
7049
  this.nodeWithPortPoints
6097
7050
  );
@@ -6100,11 +7053,6 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
6100
7053
  Math.floor(areaInsideNode / areaPerVia),
6101
7054
  Math.ceil(uniqueConnections * 1.5)
6102
7055
  );
6103
- if (uniqueConnections > 5) {
6104
- this.failed = true;
6105
- this.error = `Limit is currently set to 6 unique connections, ${uniqueConnections} found`;
6106
- return;
6107
- }
6108
7056
  if (this.minViaCount > this.SEGMENTS_PER_POLYLINE * (uniqueConnections / 2)) {
6109
7057
  this.failed = true;
6110
7058
  this.error = `Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`;
@@ -6843,7 +7791,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
6843
7791
  strokeColor: segmentColor,
6844
7792
  strokeWidth: this.traceWidth,
6845
7793
  // TODO: Use actual trace thickness from HighDensityRoute?
6846
- strokeDash: !isLayer0 ? "5,5" : void 0,
7794
+ strokeDash: !isLayer0 ? [0.15, 0.15] : void 0,
6847
7795
  // Dashed for layers > 0
6848
7796
  label: `${polyLine.connectionName} segment (z=${segmentLayer})`
6849
7797
  });
@@ -7572,7 +8520,7 @@ var HighDensitySolver = class extends BaseSolver {
7572
8520
  if (this.failedSolvers.length > 0) {
7573
8521
  this.solved = false;
7574
8522
  this.failed = true;
7575
- this.error = `Failed to solve ${this.failedSolvers.length} nodes`;
8523
+ this.error = `Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0, 5).map((fs) => fs.nodeWithPortPoints.capacityMeshNodeId)}`;
7576
8524
  return;
7577
8525
  }
7578
8526
  this.solved = true;
@@ -7644,7 +8592,8 @@ var HighDensitySolver = class extends BaseSolver {
7644
8592
  graphics.lines.push({
7645
8593
  points: [start, end],
7646
8594
  strokeColor: "red",
7647
- strokeDash: "10, 5"
8595
+ strokeDash: "10, 5",
8596
+ layer: "did_not_connect"
7648
8597
  });
7649
8598
  }
7650
8599
  }
@@ -8128,7 +9077,7 @@ var SingleHighDensityRouteStitchSolver = class extends BaseSolver {
8128
9077
  super();
8129
9078
  this.remainingHdRoutes = [...opts.hdRoutes];
8130
9079
  this.colorMap = opts.colorMap ?? {};
8131
- const firstRoute = this.remainingHdRoutes[0];
9080
+ const { firstRoute } = this.getDisjointedRoute();
8132
9081
  const firstRouteToStartDist = Math.min(
8133
9082
  distance(firstRoute.route[0], opts.start),
8134
9083
  distance(firstRoute.route[firstRoute.route.length - 1], opts.start)
@@ -8154,10 +9103,42 @@ var SingleHighDensityRouteStitchSolver = class extends BaseSolver {
8154
9103
  }
8155
9104
  ],
8156
9105
  vias: [],
8157
- viaDiameter: opts.hdRoutes?.[0]?.viaDiameter ?? 0.6,
8158
- traceThickness: opts.hdRoutes?.[0]?.traceThickness ?? 0.15
9106
+ viaDiameter: firstRoute.viaDiameter,
9107
+ traceThickness: firstRoute.traceThickness
8159
9108
  };
8160
9109
  }
9110
+ /**
9111
+ * Scan `remainingHdRoutes` and find a route that has **one** end that is not
9112
+ * within `5e-6` of the start or end of any other route on the same layer.
9113
+ * That “lonely” end marks one extremity of the whole chain, which we use as
9114
+ * our starting segment. If no such route exists (e.g., the data form a loop),
9115
+ * we simply return the first route so the solver can proceed.
9116
+ */
9117
+ getDisjointedRoute() {
9118
+ const TOL = 5e-6;
9119
+ for (const candidate of this.remainingHdRoutes) {
9120
+ const candidateEnds = [
9121
+ candidate.route[0],
9122
+ candidate.route[candidate.route.length - 1]
9123
+ ];
9124
+ const hasLonelyEnd = candidateEnds.some((end) => {
9125
+ return !this.remainingHdRoutes.some((other) => {
9126
+ if (other === candidate) return false;
9127
+ const otherEnds = [
9128
+ other.route[0],
9129
+ other.route[other.route.length - 1]
9130
+ ];
9131
+ return otherEnds.some(
9132
+ (oe) => oe.z === end.z && distance(end, oe) < TOL
9133
+ );
9134
+ });
9135
+ });
9136
+ if (hasLonelyEnd) {
9137
+ return { firstRoute: candidate };
9138
+ }
9139
+ }
9140
+ return { firstRoute: this.remainingHdRoutes[0] };
9141
+ }
8161
9142
  _step() {
8162
9143
  if (this.remainingHdRoutes.length === 0) {
8163
9144
  this.mergedHdRoute.route.push({
@@ -10514,7 +11495,7 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
10514
11495
  }
10515
11496
 
10516
11497
  // lib/solvers/CapacityPathingSectionSolver/CapacityPathingSingleSectionPathingSolver.ts
10517
- var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
11498
+ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
10518
11499
  GREEDY_MULTIPLIER = 1.5;
10519
11500
  sectionNodes;
10520
11501
  sectionEdges;
@@ -10526,6 +11507,7 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
10526
11507
  colorMap;
10527
11508
  usedNodeCapacityMap;
10528
11509
  // Tracks capacity usage *within this solver's run*
11510
+ centerNodeId;
10529
11511
  MAX_CANDIDATES_IN_MEMORY = 1e4;
10530
11512
  // A* state
10531
11513
  currentConnectionIndex = 0;
@@ -10539,6 +11521,7 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
10539
11521
  // Default, similar to CapacityPathingSolver5
10540
11522
  constructor(params) {
10541
11523
  super();
11524
+ this.centerNodeId = params.centerNodeId;
10542
11525
  this.sectionNodes = params.sectionNodes;
10543
11526
  this.sectionEdges = params.sectionEdges;
10544
11527
  this.sectionConnectionTerminals = params.sectionConnectionTerminals.map(
@@ -10712,6 +11695,28 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
10712
11695
  candidates.push(newCandidate);
10713
11696
  }
10714
11697
  }
11698
+ computeProgress() {
11699
+ const totalConnections = this.sectionConnectionTerminals.length;
11700
+ if (totalConnections === 0) return 1;
11701
+ const completedConnections = this.currentConnectionIndex;
11702
+ let progress = completedConnections / totalConnections;
11703
+ if (this.currentConnectionIndex < totalConnections && this.candidates && this.candidates.length > 0 && this.activeCandidateStraightLineDistance && this.activeCandidateStraightLineDistance > 0) {
11704
+ const bestCandidate = this.candidates.reduce(
11705
+ (best, current) => current.f < best.f ? current : best
11706
+ );
11707
+ const currentConnectionProgress = Math.max(
11708
+ 0,
11709
+ Math.min(
11710
+ 1,
11711
+ 1 - bestCandidate.h / this.activeCandidateStraightLineDistance
11712
+ )
11713
+ );
11714
+ progress += currentConnectionProgress / totalConnections;
11715
+ } else if (this.solved) {
11716
+ progress = 1;
11717
+ }
11718
+ return Math.min(1, progress);
11719
+ }
10715
11720
  _setupAStar(startNode, endNode) {
10716
11721
  this.candidates = [
10717
11722
  { prevCandidate: null, node: startNode, f: 0, g: 0, h: 0 }
@@ -10816,133 +11821,157 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
10816
11821
  return baseGraphics;
10817
11822
  }
10818
11823
  };
11824
+ var CapacityPathingSingleSectionPathingSolver = CapacityPathingSingleSectionSolver;
10819
11825
 
10820
- // lib/solvers/CapacityPathingSectionSolver/CapacityPathingSingleSectionSolver.ts
10821
- var CapacityPathingSingleSectionSolver = class extends BaseSolver {
10822
- centerNodeId;
10823
- connectionsWithNodes;
10824
- nodes;
10825
- nodeMap;
10826
- edges;
10827
- nodeEdgeMap;
10828
- expansionDegrees;
10829
- colorMap;
10830
- sectionNodes;
10831
- sectionEdges;
10832
- // Added sectionEdges property
10833
- sectionConnectionTerminals;
10834
- activeSubSolver = null;
11826
+ // lib/solvers/CapacityPathingSectionSolver/HyperCapacityPathingSingleSectionSolver.ts
11827
+ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSupervisorSolver {
11828
+ constructorParams;
11829
+ winningSolver;
10835
11830
  constructor(params) {
10836
11831
  super();
10837
- this.MAX_ITERATIONS = 1e5;
10838
- this.colorMap = params.colorMap;
10839
- this.centerNodeId = params.centerNodeId;
10840
- this.connectionsWithNodes = params.connectionsWithNodes;
10841
- this.nodes = params.nodes;
10842
- this.nodeMap = new Map(this.nodes.map((n) => [n.capacityMeshNodeId, n]));
10843
- this.edges = params.edges;
10844
- this.nodeEdgeMap = getNodeEdgeMap(this.edges);
10845
- this.expansionDegrees = params.hyperParameters?.EXPANSION_DEGREES ?? 3;
10846
- this.sectionNodes = [];
10847
- this.sectionEdges = [];
10848
- this.sectionConnectionTerminals = [];
10849
- this.computeSectionNodesTerminalsAndEdges();
10850
- this.activeSubSolver = new CapacityPathingSingleSectionPathingSolver({
10851
- sectionConnectionTerminals: this.sectionConnectionTerminals,
10852
- sectionNodes: this.sectionNodes,
10853
- sectionEdges: this.sectionEdges,
10854
- colorMap: this.colorMap,
10855
- hyperParameters: params.hyperParameters
10856
- });
11832
+ this.MAX_ITERATIONS = 1e4;
11833
+ this.constructorParams = params;
10857
11834
  }
10858
- computeSectionNodesTerminalsAndEdges() {
10859
- const sectionNodeIds = /* @__PURE__ */ new Set();
10860
- const queue = [
10861
- { nodeId: this.centerNodeId, depth: 0 }
10862
- ];
10863
- sectionNodeIds.add(this.centerNodeId);
10864
- let head = 0;
10865
- while (head < queue.length) {
10866
- const { nodeId, depth } = queue[head++];
10867
- if (depth >= this.expansionDegrees) continue;
10868
- const neighbors = this.nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
10869
- for (const neighborId of neighbors) {
10870
- if (!sectionNodeIds.has(neighborId)) {
10871
- sectionNodeIds.add(neighborId);
10872
- queue.push({ nodeId: neighborId, depth: depth + 1 });
10873
- }
10874
- }
10875
- }
10876
- this.sectionNodes = Array.from(sectionNodeIds).map(
10877
- (id) => this.nodeMap.get(id)
10878
- );
10879
- this.sectionEdges = this.edges.filter((edge) => {
10880
- const [nodeIdA, nodeIdB] = edge.nodeIds;
10881
- return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
10882
- });
10883
- this.sectionConnectionTerminals = [];
10884
- for (const conn of this.connectionsWithNodes) {
10885
- if (!conn.path) continue;
10886
- let startNodeId = null;
10887
- let endNodeId = null;
10888
- for (const node of conn.path) {
10889
- if (sectionNodeIds.has(node.capacityMeshNodeId)) {
10890
- startNodeId = node.capacityMeshNodeId;
10891
- break;
10892
- }
10893
- }
10894
- for (let i = conn.path.length - 1; i >= 0; i--) {
10895
- const node = conn.path[i];
10896
- if (sectionNodeIds.has(node.capacityMeshNodeId)) {
10897
- endNodeId = node.capacityMeshNodeId;
10898
- break;
10899
- }
10900
- }
10901
- if (startNodeId && endNodeId) {
10902
- this.sectionConnectionTerminals.push({
10903
- connectionName: conn.connection.name,
10904
- startNodeId,
10905
- endNodeId
10906
- });
10907
- }
10908
- }
11835
+ computeG(solver) {
11836
+ return solver.iterations / 100;
10909
11837
  }
10910
- _step() {
10911
- this.activeSubSolver?.step();
10912
- if (this.activeSubSolver?.solved) {
10913
- this.solved = true;
10914
- return;
10915
- }
10916
- if (this.activeSubSolver?.failed) {
10917
- this.failed = true;
10918
- this.error = this.activeSubSolver.error;
10919
- return;
10920
- }
11838
+ computeH(solver) {
11839
+ return solver.computeProgress();
10921
11840
  }
10922
- getConstructorParams() {
11841
+ getCombinationDefs() {
11842
+ return [["orderings10"]];
11843
+ }
11844
+ getFailureMessage() {
11845
+ return `All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`;
11846
+ }
11847
+ getHyperParameterDefs() {
10923
11848
  return [
10924
11849
  {
10925
- centerNodeId: this.centerNodeId,
10926
- connectionsWithNodes: this.connectionsWithNodes,
10927
- nodes: this.nodes,
10928
- edges: this.edges,
10929
- expansionDegrees: this.expansionDegrees
11850
+ name: "orderings10",
11851
+ possibleValues: [
11852
+ {
11853
+ SHUFFLE_SEED: 0
11854
+ },
11855
+ {
11856
+ SHUFFLE_SEED: 1
11857
+ },
11858
+ {
11859
+ SHUFFLE_SEED: 2
11860
+ },
11861
+ {
11862
+ SHUFFLE_SEED: 3
11863
+ },
11864
+ {
11865
+ SHUFFLE_SEED: 4
11866
+ },
11867
+ {
11868
+ SHUFFLE_SEED: 5
11869
+ },
11870
+ {
11871
+ SHUFFLE_SEED: 6
11872
+ },
11873
+ {
11874
+ SHUFFLE_SEED: 7
11875
+ },
11876
+ {
11877
+ SHUFFLE_SEED: 8
11878
+ },
11879
+ {
11880
+ SHUFFLE_SEED: 9
11881
+ }
11882
+ ]
10930
11883
  }
10931
11884
  ];
10932
11885
  }
10933
- visualize() {
10934
- return visualizeSection({
10935
- sectionNodes: this.sectionNodes,
10936
- sectionEdges: this.sectionEdges,
10937
- // Use the computed class property
10938
- sectionConnectionTerminals: this.sectionConnectionTerminals,
10939
- nodeMap: this.nodeMap,
10940
- colorMap: this.colorMap,
10941
- centerNodeId: this.centerNodeId,
10942
- nodeOpacity: 1e-3,
10943
- title: `Section Solver (Center: ${this.centerNodeId}, Hops: ${this.expansionDegrees})`
11886
+ generateSolver(hyperParameters) {
11887
+ return new CapacityPathingSingleSectionPathingSolver({
11888
+ ...this.constructorParams,
11889
+ hyperParameters: {
11890
+ ...this.constructorParams.hyperParameters,
11891
+ ...hyperParameters
11892
+ }
10944
11893
  });
10945
11894
  }
11895
+ onSolve({
11896
+ solver
11897
+ }) {
11898
+ this.winningSolver = solver;
11899
+ }
11900
+ get centerNodeId() {
11901
+ return this.constructorParams.centerNodeId;
11902
+ }
11903
+ get sectionNodes() {
11904
+ return this.constructorParams.sectionNodes;
11905
+ }
11906
+ get sectionConnectionTerminals() {
11907
+ return this.winningSolver?.sectionConnectionTerminals;
11908
+ }
11909
+ };
11910
+
11911
+ // lib/solvers/CapacityPathingSectionSolver/computeSectionNodesTerminalsAndEdges.ts
11912
+ var computeSectionNodesTerminalsAndEdges = (opts) => {
11913
+ const {
11914
+ centerNodeId,
11915
+ connectionsWithNodes,
11916
+ nodeMap,
11917
+ edges,
11918
+ nodeEdgeMap,
11919
+ expansionDegrees
11920
+ } = opts;
11921
+ const sectionNodeIds = /* @__PURE__ */ new Set();
11922
+ const queue = [
11923
+ { nodeId: centerNodeId, depth: 0 }
11924
+ ];
11925
+ sectionNodeIds.add(centerNodeId);
11926
+ let head = 0;
11927
+ while (head < queue.length) {
11928
+ const { nodeId, depth } = queue[head++];
11929
+ if (depth >= expansionDegrees) continue;
11930
+ const neighbors = nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
11931
+ for (const neighborId of neighbors) {
11932
+ if (!sectionNodeIds.has(neighborId)) {
11933
+ sectionNodeIds.add(neighborId);
11934
+ queue.push({ nodeId: neighborId, depth: depth + 1 });
11935
+ }
11936
+ }
11937
+ }
11938
+ const sectionNodes = Array.from(sectionNodeIds).map((id) => nodeMap.get(id));
11939
+ const sectionEdges = edges.filter((edge) => {
11940
+ const [nodeIdA, nodeIdB] = edge.nodeIds;
11941
+ return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
11942
+ });
11943
+ const sectionConnectionTerminals = [];
11944
+ for (const conn of connectionsWithNodes) {
11945
+ if (!conn.path) continue;
11946
+ let startNodeId = null;
11947
+ let endNodeId = null;
11948
+ for (const node of conn.path) {
11949
+ if (sectionNodeIds.has(node.capacityMeshNodeId)) {
11950
+ startNodeId = node.capacityMeshNodeId;
11951
+ break;
11952
+ }
11953
+ }
11954
+ for (let i = conn.path.length - 1; i >= 0; i--) {
11955
+ const node = conn.path[i];
11956
+ if (sectionNodeIds.has(node.capacityMeshNodeId)) {
11957
+ endNodeId = node.capacityMeshNodeId;
11958
+ break;
11959
+ }
11960
+ }
11961
+ if (startNodeId && endNodeId) {
11962
+ sectionConnectionTerminals.push({
11963
+ connectionName: conn.connection.name,
11964
+ startNodeId,
11965
+ endNodeId
11966
+ });
11967
+ }
11968
+ }
11969
+ return {
11970
+ sectionConnectionTerminals,
11971
+ sectionNodes,
11972
+ sectionEdges,
11973
+ centerNodeId
11974
+ };
10946
11975
  };
10947
11976
 
10948
11977
  // lib/solvers/CapacityPathingSectionSolver/CapacityPathingMultiSectionSolver.ts
@@ -10950,6 +11979,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
10950
11979
  simpleRouteJson;
10951
11980
  nodes;
10952
11981
  edges;
11982
+ nodeEdgeMap;
10953
11983
  connectionsWithNodes = [];
10954
11984
  // Initialize here
10955
11985
  colorMap;
@@ -10961,6 +11991,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
10961
11991
  // Added
10962
11992
  nodeCapacityPercentMap = /* @__PURE__ */ new Map();
10963
11993
  nodeOptimizationAttemptCountMap = /* @__PURE__ */ new Map();
11994
+ currentSection = null;
10964
11995
  sectionSolver = null;
10965
11996
  MAX_ATTEMPTS_PER_NODE = 10;
10966
11997
  MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE = 0.05;
@@ -10975,6 +12006,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
10975
12006
  this.nodeMap = new Map(
10976
12007
  this.nodes.map((node) => [node.capacityMeshNodeId, node])
10977
12008
  );
12009
+ this.nodeEdgeMap = getNodeEdgeMap(this.edges);
10978
12010
  this.initialSolver = new CapacityPathingGreedySolver({
10979
12011
  simpleRouteJson: this.simpleRouteJson,
10980
12012
  nodes: this.nodes,
@@ -11040,16 +12072,21 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
11040
12072
  this.solved = true;
11041
12073
  return;
11042
12074
  }
11043
- this.sectionSolver = new CapacityPathingSingleSectionSolver({
12075
+ const section = computeSectionNodesTerminalsAndEdges({
11044
12076
  centerNodeId,
11045
12077
  connectionsWithNodes: this.connectionsWithNodes,
11046
- nodes: this.nodes,
12078
+ nodeMap: this.nodeMap,
11047
12079
  edges: this.edges,
12080
+ expansionDegrees: this.MAX_EXPANSION_DEGREES,
12081
+ nodeEdgeMap: this.nodeEdgeMap
12082
+ });
12083
+ this.currentSection = section;
12084
+ this.sectionSolver = new HyperCapacityPathingSingleSectionSolver({
12085
+ sectionConnectionTerminals: section.sectionConnectionTerminals,
12086
+ sectionEdges: section.sectionEdges,
12087
+ sectionNodes: section.sectionNodes,
11048
12088
  colorMap: this.colorMap,
11049
- hyperParameters: {
11050
- EXPANSION_DEGREES: this.MAX_EXPANSION_DEGREES,
11051
- SHUFFLE_SEED: this.iterations
11052
- }
12089
+ centerNodeId: section.centerNodeId
11053
12090
  });
11054
12091
  this.activeSubSolver = this.sectionSolver;
11055
12092
  this.nodeOptimizationAttemptCountMap.set(
@@ -11060,7 +12097,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
11060
12097
  this.sectionSolver.step();
11061
12098
  if (this.sectionSolver.failed) {
11062
12099
  console.warn(
11063
- `Section solver failed for node ${this.sectionSolver.centerNodeId}. Error: ${this.sectionSolver.error}`
12100
+ `Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`
11064
12101
  );
11065
12102
  this.sectionSolver = null;
11066
12103
  this.activeSubSolver = null;
@@ -11068,12 +12105,12 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
11068
12105
  }
11069
12106
  if (this.sectionSolver.solved) {
11070
12107
  const solvedSectionSolver = this.sectionSolver;
11071
- const pathingSolver = solvedSectionSolver.activeSubSolver;
12108
+ const pathingSolver = solvedSectionSolver?.activeSubSolver || solvedSectionSolver;
11072
12109
  this.sectionSolver = null;
11073
12110
  this.activeSubSolver = null;
11074
12111
  if (!pathingSolver || !pathingSolver.solved) {
11075
12112
  console.warn(
11076
- `Pathing sub-solver for section ${solvedSectionSolver.centerNodeId} did not complete successfully. Discarding results.`
12113
+ `Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`
11077
12114
  );
11078
12115
  return;
11079
12116
  }
@@ -11134,18 +12171,18 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
11134
12171
  * connectionsWithNodes list.
11135
12172
  */
11136
12173
  _mergeSolvedSectionPaths(solvedSectionSolver) {
11137
- const pathingSolver = solvedSectionSolver.activeSubSolver;
11138
- if (!pathingSolver || !pathingSolver.solved) {
12174
+ const centerNodeId = solvedSectionSolver.centerNodeId;
12175
+ if (!solvedSectionSolver || !solvedSectionSolver.solved) {
11139
12176
  console.warn(
11140
- `Pathing sub-solver for section ${solvedSectionSolver.centerNodeId} did not complete successfully. Skipping merge.`
12177
+ `Pathing sub-solver for section ${centerNodeId} did not complete successfully. Skipping merge.`
11141
12178
  );
11142
12179
  return;
11143
12180
  }
11144
- const solvedTerminals = pathingSolver.sectionConnectionTerminals;
12181
+ const solvedTerminals = solvedSectionSolver.sectionConnectionTerminals;
11145
12182
  for (const solvedTerminal of solvedTerminals) {
11146
12183
  if (!solvedTerminal.path) {
11147
12184
  console.warn(
11148
- `No path found for connection ${solvedTerminal.connectionName} in section ${solvedSectionSolver.centerNodeId}`
12185
+ `No path found for connection ${solvedTerminal.connectionName} in section ${centerNodeId}`
11149
12186
  );
11150
12187
  continue;
11151
12188
  }
@@ -13299,7 +14336,7 @@ var SingleRouteUselessViaRemovalSolver = class extends BaseSolver {
13299
14336
  width: Math.abs(A.x - B.x),
13300
14337
  height: Math.abs(A.y - B.y)
13301
14338
  };
13302
- const obstacles = this.obstacleSHI.getNodesInArea(
14339
+ const obstacles = this.obstacleSHI.searchArea(
13303
14340
  segmentBox.centerX,
13304
14341
  segmentBox.centerY,
13305
14342
  segmentBox.width + (this.TRACE_THICKNESS + this.OBSTACLE_MARGIN) * 2,
@@ -13372,7 +14409,7 @@ var UselessViaRemovalSolver = class extends BaseSolver {
13372
14409
  this.unsimplifiedHdRoutes = input.unsimplifiedHdRoutes;
13373
14410
  this.optimizedHdRoutes = [];
13374
14411
  this.unprocessedRoutes = [...input.unsimplifiedHdRoutes];
13375
- this.obstacleSHI = new ObstacleSpatialHashIndex(input.obstacles);
14412
+ this.obstacleSHI = new ObstacleSpatialHashIndex("flatbush", input.obstacles);
13376
14413
  this.hdRouteSHI = new HighDensityRouteSpatialIndex(
13377
14414
  this.unsimplifiedHdRoutes
13378
14415
  );