@tscircuit/capacity-autorouter 0.0.26 → 0.0.28
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 +51 -1
- package/dist/index.js +729 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1434,6 +1434,7 @@ var CapacityMeshNodeSolver2_NodeUnderObstacle = class extends CapacityMeshNodeSo
|
|
|
1434
1434
|
this.srj = srj;
|
|
1435
1435
|
this.opts = opts;
|
|
1436
1436
|
}
|
|
1437
|
+
VIA_DIAMETER = 0.6;
|
|
1437
1438
|
isNodeCompletelyOutsideBounds(node) {
|
|
1438
1439
|
return node.center.x + node.width / 2 < this.srj.bounds.minX || node.center.x - node.width / 2 > this.srj.bounds.maxX || node.center.y + node.height / 2 < this.srj.bounds.minY || node.center.y - node.height / 2 > this.srj.bounds.maxY;
|
|
1439
1440
|
}
|
|
@@ -1538,10 +1539,10 @@ var CapacityMeshNodeSolver2_NodeUnderObstacle = class extends CapacityMeshNodeSo
|
|
|
1538
1539
|
const unfinishedNewNodes = [];
|
|
1539
1540
|
for (const childNode of childNodes) {
|
|
1540
1541
|
const shouldBeXYSubdivided = this.shouldNodeBeXYSubdivided(childNode);
|
|
1541
|
-
const shouldBeZSubdivided = childNode.availableZ.length > 1 && !shouldBeXYSubdivided && childNode._containsObstacle;
|
|
1542
|
+
const shouldBeZSubdivided = childNode.availableZ.length > 1 && !shouldBeXYSubdivided && (childNode._containsObstacle || childNode.width < this.VIA_DIAMETER);
|
|
1542
1543
|
if (shouldBeXYSubdivided) {
|
|
1543
1544
|
unfinishedNewNodes.push(childNode);
|
|
1544
|
-
} else if (!shouldBeXYSubdivided && !childNode._containsObstacle) {
|
|
1545
|
+
} else if (!shouldBeXYSubdivided && !childNode._containsObstacle && !shouldBeZSubdivided) {
|
|
1545
1546
|
finishedNewNodes.push(childNode);
|
|
1546
1547
|
} else if (!shouldBeXYSubdivided && childNode._containsTarget) {
|
|
1547
1548
|
if (shouldBeZSubdivided) {
|
|
@@ -2503,7 +2504,6 @@ var IntraNodeRouteSolver = class extends BaseSolver {
|
|
|
2503
2504
|
{ x, y, z: z ?? 0 }
|
|
2504
2505
|
]);
|
|
2505
2506
|
}
|
|
2506
|
-
console.log({ unsolvedConnectionsMap });
|
|
2507
2507
|
this.unsolvedConnections = Array.from(
|
|
2508
2508
|
unsolvedConnectionsMap.entries().map(([connectionName, points]) => ({
|
|
2509
2509
|
connectionName,
|
|
@@ -3128,6 +3128,9 @@ var getConnectivityMapFromSimpleRouteJson = (srj) => {
|
|
|
3128
3128
|
}
|
|
3129
3129
|
}
|
|
3130
3130
|
}
|
|
3131
|
+
for (const obstacle of srj.obstacles) {
|
|
3132
|
+
connMap.addConnections([obstacle.connectedTo]);
|
|
3133
|
+
}
|
|
3131
3134
|
return connMap;
|
|
3132
3135
|
};
|
|
3133
3136
|
|
|
@@ -3333,13 +3336,13 @@ function buildMinimumSpanningTree(points) {
|
|
|
3333
3336
|
if (point.x === neighbor.x && point.y === neighbor.y) {
|
|
3334
3337
|
continue;
|
|
3335
3338
|
}
|
|
3336
|
-
const
|
|
3339
|
+
const distance4 = Math.sqrt(
|
|
3337
3340
|
(point.x - neighbor.x) ** 2 + (point.y - neighbor.y) ** 2
|
|
3338
3341
|
);
|
|
3339
3342
|
edges.push({
|
|
3340
3343
|
from: point,
|
|
3341
3344
|
to: neighbor,
|
|
3342
|
-
weight:
|
|
3345
|
+
weight: distance4
|
|
3343
3346
|
});
|
|
3344
3347
|
}
|
|
3345
3348
|
}
|
|
@@ -5106,11 +5109,11 @@ var CapacityPathingSolver = class extends BaseSolver {
|
|
|
5106
5109
|
let closestNode = this.nodes[0];
|
|
5107
5110
|
let minDistance = Number.MAX_VALUE;
|
|
5108
5111
|
for (const node of nodesWithTargets) {
|
|
5109
|
-
const
|
|
5112
|
+
const distance4 = Math.sqrt(
|
|
5110
5113
|
(node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2
|
|
5111
5114
|
);
|
|
5112
|
-
if (
|
|
5113
|
-
minDistance =
|
|
5115
|
+
if (distance4 < minDistance) {
|
|
5116
|
+
minDistance = distance4;
|
|
5114
5117
|
closestNode = node;
|
|
5115
5118
|
}
|
|
5116
5119
|
}
|
|
@@ -5828,6 +5831,694 @@ ${node.width}x${node.height}
|
|
|
5828
5831
|
}
|
|
5829
5832
|
};
|
|
5830
5833
|
|
|
5834
|
+
// lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver.ts
|
|
5835
|
+
var SingleSimplifiedPathSolver = class extends BaseSolver {
|
|
5836
|
+
newRoute;
|
|
5837
|
+
newVias;
|
|
5838
|
+
headIndex = 0;
|
|
5839
|
+
tailIndex = 0;
|
|
5840
|
+
inputRoute;
|
|
5841
|
+
otherHdRoutes;
|
|
5842
|
+
obstacles;
|
|
5843
|
+
connMap;
|
|
5844
|
+
colorMap;
|
|
5845
|
+
constructor(params) {
|
|
5846
|
+
super();
|
|
5847
|
+
this.inputRoute = params.inputRoute;
|
|
5848
|
+
this.otherHdRoutes = params.otherHdRoutes;
|
|
5849
|
+
this.obstacles = params.obstacles;
|
|
5850
|
+
this.connMap = params.connMap;
|
|
5851
|
+
this.colorMap = params.colorMap;
|
|
5852
|
+
this.newRoute = [];
|
|
5853
|
+
this.newVias = [];
|
|
5854
|
+
}
|
|
5855
|
+
get simplifiedRoute() {
|
|
5856
|
+
return {
|
|
5857
|
+
connectionName: this.inputRoute.connectionName,
|
|
5858
|
+
traceThickness: this.inputRoute.traceThickness,
|
|
5859
|
+
viaDiameter: this.inputRoute.viaDiameter,
|
|
5860
|
+
route: this.newRoute,
|
|
5861
|
+
vias: this.newVias
|
|
5862
|
+
};
|
|
5863
|
+
}
|
|
5864
|
+
isValidPath(pointsInRoute) {
|
|
5865
|
+
throw new Error("Not implemented");
|
|
5866
|
+
}
|
|
5867
|
+
_step() {
|
|
5868
|
+
throw new Error("Not implemented");
|
|
5869
|
+
}
|
|
5870
|
+
getVisualsForNewRouteAndObstacles() {
|
|
5871
|
+
const graphics = {
|
|
5872
|
+
lines: [],
|
|
5873
|
+
points: [],
|
|
5874
|
+
circles: [],
|
|
5875
|
+
rects: [],
|
|
5876
|
+
coordinateSystem: "cartesian",
|
|
5877
|
+
title: "Simplified Path Solver"
|
|
5878
|
+
};
|
|
5879
|
+
for (let i = 0; i < this.inputRoute.route.length - 1; i++) {
|
|
5880
|
+
graphics.lines.push({
|
|
5881
|
+
points: [
|
|
5882
|
+
{ x: this.inputRoute.route[i].x, y: this.inputRoute.route[i].y },
|
|
5883
|
+
{
|
|
5884
|
+
x: this.inputRoute.route[i + 1].x,
|
|
5885
|
+
y: this.inputRoute.route[i + 1].y
|
|
5886
|
+
}
|
|
5887
|
+
],
|
|
5888
|
+
strokeColor: "rgba(255, 0, 0, 0.8)",
|
|
5889
|
+
strokeDash: this.inputRoute.route[i].z === 1 ? "5, 5" : void 0,
|
|
5890
|
+
layer: this.inputRoute.route[i].z.toString()
|
|
5891
|
+
});
|
|
5892
|
+
}
|
|
5893
|
+
for (let i = 0; i < this.newRoute.length; i++) {
|
|
5894
|
+
if (i < this.newRoute.length - 1) {
|
|
5895
|
+
graphics.lines.push({
|
|
5896
|
+
points: [
|
|
5897
|
+
{ x: this.newRoute[i].x, y: this.newRoute[i].y },
|
|
5898
|
+
{ x: this.newRoute[i + 1].x, y: this.newRoute[i + 1].y }
|
|
5899
|
+
],
|
|
5900
|
+
strokeWidth: 0.15,
|
|
5901
|
+
strokeColor: "rgba(0, 255, 0, 0.8)",
|
|
5902
|
+
strokeDash: this.newRoute[i].z === 1 ? [0.4, 0.4] : void 0,
|
|
5903
|
+
layer: this.newRoute[i].z.toString()
|
|
5904
|
+
});
|
|
5905
|
+
}
|
|
5906
|
+
graphics.points.push({
|
|
5907
|
+
x: this.newRoute[i].x,
|
|
5908
|
+
y: this.newRoute[i].y,
|
|
5909
|
+
color: "rgba(0, 255, 0, 0.8)",
|
|
5910
|
+
label: `z: ${this.newRoute[i].z}`,
|
|
5911
|
+
layer: this.newRoute[i].z.toString()
|
|
5912
|
+
});
|
|
5913
|
+
}
|
|
5914
|
+
for (const via of this.newVias) {
|
|
5915
|
+
graphics.circles.push({
|
|
5916
|
+
center: via,
|
|
5917
|
+
radius: this.inputRoute.viaDiameter / 2,
|
|
5918
|
+
fill: "rgba(0, 0, 255, 0.5)"
|
|
5919
|
+
});
|
|
5920
|
+
}
|
|
5921
|
+
for (const obstacle of this.obstacles) {
|
|
5922
|
+
graphics.rects.push({
|
|
5923
|
+
center: obstacle.center,
|
|
5924
|
+
width: obstacle.width,
|
|
5925
|
+
height: obstacle.height,
|
|
5926
|
+
fill: obstacle.layers?.includes("top") ? "rgba(255, 0, 0, 0.3)" : obstacle.layers?.includes("bottom") ? "rgba(0, 0, 255, 0.3)" : "rgba(128, 128, 128, 0.3)"
|
|
5927
|
+
});
|
|
5928
|
+
}
|
|
5929
|
+
for (const route of this.otherHdRoutes) {
|
|
5930
|
+
for (let i = 0; i < route.route.length - 1; i++) {
|
|
5931
|
+
graphics.lines.push({
|
|
5932
|
+
points: [
|
|
5933
|
+
{ x: route.route[i].x, y: route.route[i].y },
|
|
5934
|
+
{ x: route.route[i + 1].x, y: route.route[i + 1].y }
|
|
5935
|
+
],
|
|
5936
|
+
strokeWidth: 0.15,
|
|
5937
|
+
strokeColor: route.route[i].z === 0 ? "rgba(255, 0, 255, 0.5)" : route.route[i].z === 1 ? "rgba(128, 0, 128, 0.5)" : "rgba(0, 0, 255, 0.5)",
|
|
5938
|
+
// bottom layer (blue)
|
|
5939
|
+
layer: route.route[i].z.toString()
|
|
5940
|
+
});
|
|
5941
|
+
}
|
|
5942
|
+
}
|
|
5943
|
+
return graphics;
|
|
5944
|
+
}
|
|
5945
|
+
};
|
|
5946
|
+
|
|
5947
|
+
// lib/utils/calculate45DegreePaths.ts
|
|
5948
|
+
var calculate45DegreePaths = (pointA, pointB) => {
|
|
5949
|
+
const result = [];
|
|
5950
|
+
const dx = Math.abs(pointB.x - pointA.x);
|
|
5951
|
+
const dy = Math.abs(pointB.y - pointA.y);
|
|
5952
|
+
const signX = pointB.x > pointA.x ? 1 : -1;
|
|
5953
|
+
const signY = pointB.y > pointA.y ? 1 : -1;
|
|
5954
|
+
const midPoint1 = {
|
|
5955
|
+
x: pointB.x - signX * Math.abs(pointB.y - pointA.y),
|
|
5956
|
+
y: pointA.y
|
|
5957
|
+
};
|
|
5958
|
+
if ((midPoint1.x - pointA.x) * signX >= 0 && (midPoint1.x - pointB.x) * signX <= 0) {
|
|
5959
|
+
result.push([pointA, midPoint1, pointB]);
|
|
5960
|
+
}
|
|
5961
|
+
const midPoint2 = {
|
|
5962
|
+
x: pointA.x,
|
|
5963
|
+
y: pointB.y - signY * Math.abs(pointB.x - pointA.x)
|
|
5964
|
+
};
|
|
5965
|
+
if ((midPoint2.y - pointA.y) * signY >= 0 && (midPoint2.y - pointB.y) * signY <= 0) {
|
|
5966
|
+
result.push([pointA, midPoint2, pointB]);
|
|
5967
|
+
}
|
|
5968
|
+
const minDist = Math.min(dx, dy);
|
|
5969
|
+
const midPoint3 = {
|
|
5970
|
+
x: pointA.x + signX * minDist,
|
|
5971
|
+
y: pointA.y + signY * minDist
|
|
5972
|
+
};
|
|
5973
|
+
if ((midPoint3.x - pointA.x) * signX >= 0 && (midPoint3.x - pointB.x) * signX <= 0 && (midPoint3.y - pointA.y) * signY >= 0 && (midPoint3.y - pointB.y) * signY <= 0) {
|
|
5974
|
+
result.push([pointA, midPoint3, pointB]);
|
|
5975
|
+
}
|
|
5976
|
+
return result;
|
|
5977
|
+
};
|
|
5978
|
+
|
|
5979
|
+
// lib/utils/minimumDistanceBetweenSegments.ts
|
|
5980
|
+
function minimumDistanceBetweenSegments(A1, A2, B1, B2) {
|
|
5981
|
+
if (segmentsIntersect(A1, A2, B1, B2)) {
|
|
5982
|
+
return 0;
|
|
5983
|
+
}
|
|
5984
|
+
const distA1 = pointToSegmentDistance3(A1, B1, B2);
|
|
5985
|
+
const distA2 = pointToSegmentDistance3(A2, B1, B2);
|
|
5986
|
+
const distB1 = pointToSegmentDistance3(B1, A1, A2);
|
|
5987
|
+
const distB2 = pointToSegmentDistance3(B2, A1, A2);
|
|
5988
|
+
return Math.min(distA1, distA2, distB1, distB2);
|
|
5989
|
+
}
|
|
5990
|
+
function pointToSegmentDistance3(P, Q1, Q2) {
|
|
5991
|
+
const v = { x: Q2.x - Q1.x, y: Q2.y - Q1.y };
|
|
5992
|
+
const w = { x: P.x - Q1.x, y: P.y - Q1.y };
|
|
5993
|
+
const c1 = dotProduct(w, v);
|
|
5994
|
+
if (c1 <= 0) {
|
|
5995
|
+
return distance3(P, Q1);
|
|
5996
|
+
}
|
|
5997
|
+
const c2 = dotProduct(v, v);
|
|
5998
|
+
if (c2 <= c1) {
|
|
5999
|
+
return distance3(P, Q2);
|
|
6000
|
+
}
|
|
6001
|
+
const b = c1 / c2;
|
|
6002
|
+
const Pb = {
|
|
6003
|
+
x: Q1.x + b * v.x,
|
|
6004
|
+
y: Q1.y + b * v.y
|
|
6005
|
+
};
|
|
6006
|
+
return distance3(P, Pb);
|
|
6007
|
+
}
|
|
6008
|
+
function dotProduct(v1, v2) {
|
|
6009
|
+
return v1.x * v2.x + v1.y * v2.y;
|
|
6010
|
+
}
|
|
6011
|
+
function distance3(p1, p2) {
|
|
6012
|
+
const dx = p2.x - p1.x;
|
|
6013
|
+
const dy = p2.y - p1.y;
|
|
6014
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
6015
|
+
}
|
|
6016
|
+
function orientation3(p, q, r) {
|
|
6017
|
+
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
6018
|
+
if (val === 0) return 0;
|
|
6019
|
+
return val > 0 ? 1 : 2;
|
|
6020
|
+
}
|
|
6021
|
+
function onSegment3(p, q, r) {
|
|
6022
|
+
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);
|
|
6023
|
+
}
|
|
6024
|
+
function segmentsIntersect(A1, A2, B1, B2) {
|
|
6025
|
+
const o1 = orientation3(A1, A2, B1);
|
|
6026
|
+
const o2 = orientation3(A1, A2, B2);
|
|
6027
|
+
const o3 = orientation3(B1, B2, A1);
|
|
6028
|
+
const o4 = orientation3(B1, B2, A2);
|
|
6029
|
+
if (o1 !== o2 && o3 !== o4) return true;
|
|
6030
|
+
if (o1 === 0 && onSegment3(A1, B1, A2)) return true;
|
|
6031
|
+
if (o2 === 0 && onSegment3(A1, B2, A2)) return true;
|
|
6032
|
+
if (o3 === 0 && onSegment3(B1, A1, B2)) return true;
|
|
6033
|
+
if (o4 === 0 && onSegment3(B1, A2, B2)) return true;
|
|
6034
|
+
return false;
|
|
6035
|
+
}
|
|
6036
|
+
|
|
6037
|
+
// lib/solvers/SimplifiedPathSolver/SingleSimplifiedPathSolver5_Deg45.ts
|
|
6038
|
+
var SingleSimplifiedPathSolver5 = class extends SingleSimplifiedPathSolver {
|
|
6039
|
+
pathSegments = [];
|
|
6040
|
+
totalPathLength = 0;
|
|
6041
|
+
headDistanceAlongPath = 0;
|
|
6042
|
+
tailDistanceAlongPath = 0;
|
|
6043
|
+
stepSize = 0.25;
|
|
6044
|
+
// Default step size, can be adjusted
|
|
6045
|
+
lastValidPath = null;
|
|
6046
|
+
// Store the current valid path
|
|
6047
|
+
lastValidPathHeadDistance = 0;
|
|
6048
|
+
filteredObstacles = [];
|
|
6049
|
+
OBSTACLE_MARGIN = 0.15;
|
|
6050
|
+
TAIL_JUMP_RATIO = 0.8;
|
|
6051
|
+
constructor(params) {
|
|
6052
|
+
super(params);
|
|
6053
|
+
if (this.inputRoute.route.length <= 1) {
|
|
6054
|
+
this.newRoute = [...this.inputRoute.route];
|
|
6055
|
+
this.solved = true;
|
|
6056
|
+
return;
|
|
6057
|
+
}
|
|
6058
|
+
this.filteredObstacles = this.obstacles.filter(
|
|
6059
|
+
(obstacle) => !obstacle.connectedTo.some(
|
|
6060
|
+
(id) => this.connMap.areIdsConnected(this.inputRoute.connectionName, id)
|
|
6061
|
+
)
|
|
6062
|
+
);
|
|
6063
|
+
this.computePathSegments();
|
|
6064
|
+
}
|
|
6065
|
+
// Compute the path segments and their distances
|
|
6066
|
+
computePathSegments() {
|
|
6067
|
+
let cumulativeDistance = 0;
|
|
6068
|
+
for (let i = 0; i < this.inputRoute.route.length - 1; i++) {
|
|
6069
|
+
const start = this.inputRoute.route[i];
|
|
6070
|
+
const end = this.inputRoute.route[i + 1];
|
|
6071
|
+
const length = Math.sqrt((end.x - start.x) ** 2 + (end.y - start.y) ** 2) + i / 1e4;
|
|
6072
|
+
this.pathSegments.push({
|
|
6073
|
+
start,
|
|
6074
|
+
end,
|
|
6075
|
+
length,
|
|
6076
|
+
startDistance: cumulativeDistance,
|
|
6077
|
+
endDistance: cumulativeDistance + length
|
|
6078
|
+
});
|
|
6079
|
+
cumulativeDistance += length;
|
|
6080
|
+
}
|
|
6081
|
+
this.totalPathLength = cumulativeDistance;
|
|
6082
|
+
}
|
|
6083
|
+
// Helper to check if two points are the same
|
|
6084
|
+
arePointsEqual(p1, p2) {
|
|
6085
|
+
return p1.x === p2.x && p1.y === p2.y && p1.z === p2.z;
|
|
6086
|
+
}
|
|
6087
|
+
// Get point at a specific distance along the path
|
|
6088
|
+
getPointAtDistance(distance4) {
|
|
6089
|
+
distance4 = Math.max(0, Math.min(distance4, this.totalPathLength));
|
|
6090
|
+
const segment = this.pathSegments.find(
|
|
6091
|
+
(seg) => distance4 >= seg.startDistance && distance4 <= seg.endDistance
|
|
6092
|
+
);
|
|
6093
|
+
if (!segment) {
|
|
6094
|
+
return this.inputRoute.route[this.inputRoute.route.length - 1];
|
|
6095
|
+
}
|
|
6096
|
+
const factor = (distance4 - segment.startDistance) / segment.length;
|
|
6097
|
+
return {
|
|
6098
|
+
x: segment.start.x + factor * (segment.end.x - segment.start.x),
|
|
6099
|
+
y: segment.start.y + factor * (segment.end.y - segment.start.y),
|
|
6100
|
+
z: segment.start.z
|
|
6101
|
+
// Z doesn't interpolate - use the segment's start z value
|
|
6102
|
+
};
|
|
6103
|
+
}
|
|
6104
|
+
// Find nearest index in the original route for a given distance
|
|
6105
|
+
getNearestIndexForDistance(distance4) {
|
|
6106
|
+
if (distance4 <= 0) return 0;
|
|
6107
|
+
if (distance4 >= this.totalPathLength)
|
|
6108
|
+
return this.inputRoute.route.length - 1;
|
|
6109
|
+
const segmentIndex = this.pathSegments.findIndex(
|
|
6110
|
+
(seg) => distance4 >= seg.startDistance && distance4 <= seg.endDistance
|
|
6111
|
+
);
|
|
6112
|
+
if (segmentIndex === -1) return 0;
|
|
6113
|
+
const segment = this.pathSegments[segmentIndex];
|
|
6114
|
+
const midDistance = (segment.startDistance + segment.endDistance) / 2;
|
|
6115
|
+
return distance4 > midDistance ? segmentIndex + 1 : segmentIndex;
|
|
6116
|
+
}
|
|
6117
|
+
// Check if a path segment is valid
|
|
6118
|
+
isValidPathSegment(start, end) {
|
|
6119
|
+
for (const obstacle of this.filteredObstacles) {
|
|
6120
|
+
if (!obstacle.zLayers?.includes(start.z)) {
|
|
6121
|
+
continue;
|
|
6122
|
+
}
|
|
6123
|
+
const obstacleLeft = obstacle.center.x - obstacle.width / 2 - this.OBSTACLE_MARGIN;
|
|
6124
|
+
const obstacleRight = obstacle.center.x + obstacle.width / 2 + this.OBSTACLE_MARGIN;
|
|
6125
|
+
const obstacleTop = obstacle.center.y - obstacle.height / 2 - this.OBSTACLE_MARGIN;
|
|
6126
|
+
const obstacleBottom = obstacle.center.y + obstacle.height / 2 + this.OBSTACLE_MARGIN;
|
|
6127
|
+
if (doSegmentsIntersect(
|
|
6128
|
+
{ x: start.x, y: start.y },
|
|
6129
|
+
{ x: end.x, y: end.y },
|
|
6130
|
+
{ x: obstacleLeft, y: obstacleTop },
|
|
6131
|
+
{ x: obstacleRight, y: obstacleTop }
|
|
6132
|
+
) || doSegmentsIntersect(
|
|
6133
|
+
{ x: start.x, y: start.y },
|
|
6134
|
+
{ x: end.x, y: end.y },
|
|
6135
|
+
{ x: obstacleRight, y: obstacleTop },
|
|
6136
|
+
{ x: obstacleRight, y: obstacleBottom }
|
|
6137
|
+
) || doSegmentsIntersect(
|
|
6138
|
+
{ x: start.x, y: start.y },
|
|
6139
|
+
{ x: end.x, y: end.y },
|
|
6140
|
+
{ x: obstacleRight, y: obstacleBottom },
|
|
6141
|
+
{ x: obstacleLeft, y: obstacleBottom }
|
|
6142
|
+
) || doSegmentsIntersect(
|
|
6143
|
+
{ x: start.x, y: start.y },
|
|
6144
|
+
{ x: end.x, y: end.y },
|
|
6145
|
+
{ x: obstacleLeft, y: obstacleBottom },
|
|
6146
|
+
{ x: obstacleLeft, y: obstacleTop }
|
|
6147
|
+
)) {
|
|
6148
|
+
return false;
|
|
6149
|
+
}
|
|
6150
|
+
}
|
|
6151
|
+
for (const route of this.otherHdRoutes) {
|
|
6152
|
+
if (this.connMap.areIdsConnected(
|
|
6153
|
+
this.inputRoute.connectionName,
|
|
6154
|
+
route.connectionName
|
|
6155
|
+
)) {
|
|
6156
|
+
continue;
|
|
6157
|
+
}
|
|
6158
|
+
for (let j = 0; j < route.route.length - 1; j++) {
|
|
6159
|
+
const routeStart = route.route[j];
|
|
6160
|
+
const routeEnd = route.route[j + 1];
|
|
6161
|
+
if (routeStart.z === start.z && routeEnd.z === start.z) {
|
|
6162
|
+
if (minimumDistanceBetweenSegments(
|
|
6163
|
+
{ x: start.x, y: start.y },
|
|
6164
|
+
{ x: end.x, y: end.y },
|
|
6165
|
+
{ x: routeStart.x, y: routeStart.y },
|
|
6166
|
+
{ x: routeEnd.x, y: routeEnd.y }
|
|
6167
|
+
) < this.OBSTACLE_MARGIN) {
|
|
6168
|
+
return false;
|
|
6169
|
+
}
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
for (const via of route.vias) {
|
|
6173
|
+
if (pointToSegmentDistance(via, start, end) < this.OBSTACLE_MARGIN + route.viaDiameter / 2) {
|
|
6174
|
+
return false;
|
|
6175
|
+
}
|
|
6176
|
+
}
|
|
6177
|
+
}
|
|
6178
|
+
return true;
|
|
6179
|
+
}
|
|
6180
|
+
// Check if a path with multiple points is valid
|
|
6181
|
+
isValidPath(pointsInRoute) {
|
|
6182
|
+
if (pointsInRoute.length < 2) return true;
|
|
6183
|
+
for (let i = 0; i < pointsInRoute.length - 1; i++) {
|
|
6184
|
+
if (pointsInRoute[i].z !== pointsInRoute[i + 1].z) {
|
|
6185
|
+
return false;
|
|
6186
|
+
}
|
|
6187
|
+
}
|
|
6188
|
+
for (let i = 0; i < pointsInRoute.length - 1; i++) {
|
|
6189
|
+
if (!this.isValidPathSegment(pointsInRoute[i], pointsInRoute[i + 1])) {
|
|
6190
|
+
return false;
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
return true;
|
|
6194
|
+
}
|
|
6195
|
+
// Find a valid 45-degree path between two points
|
|
6196
|
+
find45DegreePath(start, end) {
|
|
6197
|
+
if (this.arePointsEqual(start, end)) {
|
|
6198
|
+
return [start];
|
|
6199
|
+
}
|
|
6200
|
+
if (start.z !== end.z) {
|
|
6201
|
+
return null;
|
|
6202
|
+
}
|
|
6203
|
+
const possiblePaths = calculate45DegreePaths(
|
|
6204
|
+
{ x: start.x, y: start.y },
|
|
6205
|
+
{ x: end.x, y: end.y }
|
|
6206
|
+
);
|
|
6207
|
+
for (const path of possiblePaths) {
|
|
6208
|
+
const fullPath = path.map((p) => ({ x: p.x, y: p.y, z: start.z }));
|
|
6209
|
+
if (this.isValidPath(fullPath)) {
|
|
6210
|
+
return fullPath;
|
|
6211
|
+
}
|
|
6212
|
+
}
|
|
6213
|
+
return null;
|
|
6214
|
+
}
|
|
6215
|
+
// Add a path to the result, skipping the first point if it's already added
|
|
6216
|
+
addPathToResult(path) {
|
|
6217
|
+
if (path.length === 0) return;
|
|
6218
|
+
for (let i = 0; i < path.length; i++) {
|
|
6219
|
+
if (i === 0 && this.newRoute.length > 0 && this.arePointsEqual(this.newRoute[this.newRoute.length - 1], path[i])) {
|
|
6220
|
+
continue;
|
|
6221
|
+
}
|
|
6222
|
+
this.newRoute.push(path[i]);
|
|
6223
|
+
}
|
|
6224
|
+
}
|
|
6225
|
+
_step() {
|
|
6226
|
+
const tailHasReachedEnd = this.tailDistanceAlongPath >= this.totalPathLength;
|
|
6227
|
+
const headHasReachedEnd = this.headDistanceAlongPath >= this.totalPathLength;
|
|
6228
|
+
if (tailHasReachedEnd) {
|
|
6229
|
+
const lastPoint = this.inputRoute.route[this.inputRoute.route.length - 1];
|
|
6230
|
+
if (this.newRoute.length === 0 || !this.arePointsEqual(this.newRoute[this.newRoute.length - 1], lastPoint)) {
|
|
6231
|
+
this.newRoute.push(lastPoint);
|
|
6232
|
+
}
|
|
6233
|
+
this.solved = true;
|
|
6234
|
+
return;
|
|
6235
|
+
}
|
|
6236
|
+
if (headHasReachedEnd) {
|
|
6237
|
+
const tailPoint2 = this.getPointAtDistance(this.tailDistanceAlongPath);
|
|
6238
|
+
const endPoint = this.inputRoute.route[this.inputRoute.route.length - 1];
|
|
6239
|
+
const path452 = this.find45DegreePath(tailPoint2, endPoint);
|
|
6240
|
+
if (path452) {
|
|
6241
|
+
this.addPathToResult(path452);
|
|
6242
|
+
this.solved = true;
|
|
6243
|
+
return;
|
|
6244
|
+
} else {
|
|
6245
|
+
if (this.lastValidPath) {
|
|
6246
|
+
this.addPathToResult(this.lastValidPath);
|
|
6247
|
+
this.lastValidPath = null;
|
|
6248
|
+
this.tailDistanceAlongPath = this.lastValidPathHeadDistance;
|
|
6249
|
+
} else {
|
|
6250
|
+
this.newRoute.push(endPoint);
|
|
6251
|
+
this.solved = true;
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
}
|
|
6255
|
+
this.headDistanceAlongPath = Math.min(
|
|
6256
|
+
this.headDistanceAlongPath + this.stepSize,
|
|
6257
|
+
this.totalPathLength
|
|
6258
|
+
);
|
|
6259
|
+
const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath);
|
|
6260
|
+
const headPoint = this.getPointAtDistance(this.headDistanceAlongPath);
|
|
6261
|
+
const tailIndex = this.getNearestIndexForDistance(
|
|
6262
|
+
this.tailDistanceAlongPath
|
|
6263
|
+
);
|
|
6264
|
+
const headIndex = this.getNearestIndexForDistance(
|
|
6265
|
+
this.headDistanceAlongPath
|
|
6266
|
+
);
|
|
6267
|
+
let layerChangeBtwHeadAndTail = false;
|
|
6268
|
+
let layerChangeAtDistance = -1;
|
|
6269
|
+
for (let i = tailIndex; i < headIndex; i++) {
|
|
6270
|
+
if (i + 1 < this.inputRoute.route.length && this.inputRoute.route[i].z !== this.inputRoute.route[i + 1].z) {
|
|
6271
|
+
layerChangeBtwHeadAndTail = true;
|
|
6272
|
+
const changeSegmentIndex = i;
|
|
6273
|
+
layerChangeAtDistance = this.pathSegments[changeSegmentIndex].startDistance;
|
|
6274
|
+
break;
|
|
6275
|
+
}
|
|
6276
|
+
}
|
|
6277
|
+
if (layerChangeBtwHeadAndTail && layerChangeAtDistance > 0) {
|
|
6278
|
+
if (this.lastValidPath) {
|
|
6279
|
+
this.addPathToResult(this.lastValidPath);
|
|
6280
|
+
this.lastValidPath = null;
|
|
6281
|
+
}
|
|
6282
|
+
const pointBeforeChange = this.getPointAtDistance(layerChangeAtDistance);
|
|
6283
|
+
const pointAfterChange = this.inputRoute.route[this.getNearestIndexForDistance(layerChangeAtDistance) + 1];
|
|
6284
|
+
this.newVias.push({
|
|
6285
|
+
x: pointAfterChange.x,
|
|
6286
|
+
y: pointAfterChange.y
|
|
6287
|
+
});
|
|
6288
|
+
this.newRoute.push(pointAfterChange);
|
|
6289
|
+
const nextTailIndex = this.getNearestIndexForDistance(layerChangeAtDistance) + 1;
|
|
6290
|
+
if (this.pathSegments[nextTailIndex]) {
|
|
6291
|
+
this.tailDistanceAlongPath = this.pathSegments[nextTailIndex].startDistance;
|
|
6292
|
+
this.headDistanceAlongPath = this.tailDistanceAlongPath;
|
|
6293
|
+
} else {
|
|
6294
|
+
console.error("Creating via at end, this is probably not right");
|
|
6295
|
+
this.solved = true;
|
|
6296
|
+
return;
|
|
6297
|
+
}
|
|
6298
|
+
return;
|
|
6299
|
+
}
|
|
6300
|
+
const path45 = this.find45DegreePath(tailPoint, headPoint);
|
|
6301
|
+
if (!path45 && !this.lastValidPath) {
|
|
6302
|
+
this.tailDistanceAlongPath += this.stepSize;
|
|
6303
|
+
this.headDistanceAlongPath += this.stepSize;
|
|
6304
|
+
return;
|
|
6305
|
+
}
|
|
6306
|
+
if (path45) {
|
|
6307
|
+
this.lastValidPath = path45;
|
|
6308
|
+
this.lastValidPathHeadDistance = this.headDistanceAlongPath;
|
|
6309
|
+
return;
|
|
6310
|
+
}
|
|
6311
|
+
if (this.lastValidPath) {
|
|
6312
|
+
this.addPathToResult(this.lastValidPath);
|
|
6313
|
+
this.lastValidPath = null;
|
|
6314
|
+
this.tailDistanceAlongPath = this.lastValidPathHeadDistance;
|
|
6315
|
+
}
|
|
6316
|
+
this.headDistanceAlongPath = Math.min(
|
|
6317
|
+
this.headDistanceAlongPath + this.stepSize,
|
|
6318
|
+
this.totalPathLength
|
|
6319
|
+
);
|
|
6320
|
+
}
|
|
6321
|
+
visualize() {
|
|
6322
|
+
const graphics = this.getVisualsForNewRouteAndObstacles();
|
|
6323
|
+
const tailPoint = this.getPointAtDistance(this.tailDistanceAlongPath);
|
|
6324
|
+
const headPoint = this.getPointAtDistance(this.headDistanceAlongPath);
|
|
6325
|
+
graphics.points.push({
|
|
6326
|
+
x: tailPoint.x,
|
|
6327
|
+
y: tailPoint.y,
|
|
6328
|
+
color: "yellow",
|
|
6329
|
+
label: ["Tail", `z: ${tailPoint.z}`].join("\n")
|
|
6330
|
+
});
|
|
6331
|
+
graphics.points.push({
|
|
6332
|
+
x: headPoint.x,
|
|
6333
|
+
y: headPoint.y,
|
|
6334
|
+
color: "orange",
|
|
6335
|
+
label: ["Head", `z: ${headPoint.z}`].join("\n")
|
|
6336
|
+
});
|
|
6337
|
+
let distance4 = 0;
|
|
6338
|
+
while (distance4 < this.totalPathLength) {
|
|
6339
|
+
const point = this.getPointAtDistance(distance4);
|
|
6340
|
+
graphics.circles.push({
|
|
6341
|
+
center: {
|
|
6342
|
+
x: point.x,
|
|
6343
|
+
y: point.y
|
|
6344
|
+
},
|
|
6345
|
+
radius: 0.05,
|
|
6346
|
+
fill: "rgba(100, 100, 100, 0.5)"
|
|
6347
|
+
});
|
|
6348
|
+
distance4 += this.totalPathLength / 20;
|
|
6349
|
+
}
|
|
6350
|
+
if (this.lastValidPath && this.lastValidPath.length > 1) {
|
|
6351
|
+
for (let i = 0; i < this.lastValidPath.length - 1; i++) {
|
|
6352
|
+
graphics.lines.push({
|
|
6353
|
+
points: [
|
|
6354
|
+
{ x: this.lastValidPath[i].x, y: this.lastValidPath[i].y },
|
|
6355
|
+
{
|
|
6356
|
+
x: this.lastValidPath[i + 1].x,
|
|
6357
|
+
y: this.lastValidPath[i + 1].y
|
|
6358
|
+
}
|
|
6359
|
+
],
|
|
6360
|
+
strokeColor: "rgba(0, 255, 255, 0.9)",
|
|
6361
|
+
// Bright cyan
|
|
6362
|
+
strokeDash: "3, 3"
|
|
6363
|
+
// Dashed line to indicate it's a prospective path
|
|
6364
|
+
});
|
|
6365
|
+
}
|
|
6366
|
+
}
|
|
6367
|
+
return graphics;
|
|
6368
|
+
}
|
|
6369
|
+
};
|
|
6370
|
+
|
|
6371
|
+
// lib/solvers/SimplifiedPathSolver/MultiSimplifiedPathSolver.ts
|
|
6372
|
+
var MultiSimplifiedPathSolver = class extends BaseSolver {
|
|
6373
|
+
simplifiedHdRoutes;
|
|
6374
|
+
currentUnsimplifiedHdRouteIndex = 0;
|
|
6375
|
+
activeSubSolver = null;
|
|
6376
|
+
unsimplifiedHdRoutes;
|
|
6377
|
+
obstacles;
|
|
6378
|
+
connMap;
|
|
6379
|
+
colorMap;
|
|
6380
|
+
constructor(params) {
|
|
6381
|
+
super();
|
|
6382
|
+
this.MAX_ITERATIONS = 1e8;
|
|
6383
|
+
this.unsimplifiedHdRoutes = params.unsimplifiedHdRoutes;
|
|
6384
|
+
this.obstacles = params.obstacles;
|
|
6385
|
+
this.connMap = params.connMap || new ConnectivityMap({});
|
|
6386
|
+
this.colorMap = params.colorMap || {};
|
|
6387
|
+
this.simplifiedHdRoutes = [];
|
|
6388
|
+
}
|
|
6389
|
+
_step() {
|
|
6390
|
+
const hdRoute = this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];
|
|
6391
|
+
if (!this.activeSubSolver) {
|
|
6392
|
+
if (!hdRoute) {
|
|
6393
|
+
this.solved = true;
|
|
6394
|
+
return;
|
|
6395
|
+
}
|
|
6396
|
+
this.activeSubSolver = new SingleSimplifiedPathSolver5({
|
|
6397
|
+
inputRoute: hdRoute,
|
|
6398
|
+
otherHdRoutes: this.unsimplifiedHdRoutes.slice(this.currentUnsimplifiedHdRouteIndex + 1).concat(this.simplifiedHdRoutes),
|
|
6399
|
+
obstacles: this.obstacles,
|
|
6400
|
+
connMap: this.connMap,
|
|
6401
|
+
colorMap: this.colorMap
|
|
6402
|
+
});
|
|
6403
|
+
this.currentUnsimplifiedHdRouteIndex++;
|
|
6404
|
+
return;
|
|
6405
|
+
}
|
|
6406
|
+
this.activeSubSolver.step();
|
|
6407
|
+
if (this.activeSubSolver.solved) {
|
|
6408
|
+
this.simplifiedHdRoutes.push(this.activeSubSolver.simplifiedRoute);
|
|
6409
|
+
this.activeSubSolver = null;
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
visualize() {
|
|
6413
|
+
if (this.activeSubSolver) {
|
|
6414
|
+
return this.activeSubSolver.visualize();
|
|
6415
|
+
}
|
|
6416
|
+
const graphics = {
|
|
6417
|
+
lines: [],
|
|
6418
|
+
points: [],
|
|
6419
|
+
circles: [],
|
|
6420
|
+
rects: [],
|
|
6421
|
+
coordinateSystem: "cartesian",
|
|
6422
|
+
title: "Multi Simplified Path Solver"
|
|
6423
|
+
};
|
|
6424
|
+
for (const route of this.unsimplifiedHdRoutes) {
|
|
6425
|
+
if (this.simplifiedHdRoutes.some(
|
|
6426
|
+
(r) => r.connectionName === route.connectionName
|
|
6427
|
+
)) {
|
|
6428
|
+
continue;
|
|
6429
|
+
}
|
|
6430
|
+
for (let i = 0; i < route.route.length - 1; i++) {
|
|
6431
|
+
graphics.lines.push({
|
|
6432
|
+
points: [
|
|
6433
|
+
{ x: route.route[i].x, y: route.route[i].y },
|
|
6434
|
+
{ x: route.route[i + 1].x, y: route.route[i + 1].y }
|
|
6435
|
+
],
|
|
6436
|
+
strokeColor: route.route[i].z === 1 ? "rgba(0, 0, 255, 0.4)" : "rgba(255, 0, 0, 0.4)",
|
|
6437
|
+
strokeWidth: 0.15,
|
|
6438
|
+
strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : void 0
|
|
6439
|
+
});
|
|
6440
|
+
}
|
|
6441
|
+
for (const via of route.vias || []) {
|
|
6442
|
+
graphics.circles.push({
|
|
6443
|
+
center: via,
|
|
6444
|
+
radius: route.viaDiameter / 2 || 0.3,
|
|
6445
|
+
// Default radius if viaDiameter not specified
|
|
6446
|
+
fill: "rgba(0, 0, 255, 0.4)"
|
|
6447
|
+
});
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
for (const route of this.simplifiedHdRoutes) {
|
|
6451
|
+
const routeColor = this.colorMap?.[route.connectionName] || "rgba(128, 128, 128, 0.8)";
|
|
6452
|
+
for (let i = 0; i < route.route.length - 1; i++) {
|
|
6453
|
+
graphics.lines.push({
|
|
6454
|
+
points: [
|
|
6455
|
+
{ x: route.route[i].x, y: route.route[i].y },
|
|
6456
|
+
{ x: route.route[i + 1].x, y: route.route[i + 1].y }
|
|
6457
|
+
],
|
|
6458
|
+
strokeWidth: 0.15,
|
|
6459
|
+
strokeColor: routeColor,
|
|
6460
|
+
strokeDash: route.route[i].z === 1 ? [0.5, 0.5] : void 0,
|
|
6461
|
+
step: 1
|
|
6462
|
+
});
|
|
6463
|
+
}
|
|
6464
|
+
for (const via of route.vias || []) {
|
|
6465
|
+
graphics.circles.push({
|
|
6466
|
+
center: via,
|
|
6467
|
+
radius: route.viaDiameter / 2,
|
|
6468
|
+
fill: "rgba(0, 0, 255, 0.5)",
|
|
6469
|
+
step: 1
|
|
6470
|
+
});
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
for (const route of this.unsimplifiedHdRoutes) {
|
|
6474
|
+
for (let i = 0; i < route.route.length - 1; i++) {
|
|
6475
|
+
graphics.lines.push({
|
|
6476
|
+
points: [
|
|
6477
|
+
{ x: route.route[i].x, y: route.route[i].y },
|
|
6478
|
+
{ x: route.route[i + 1].x, y: route.route[i + 1].y }
|
|
6479
|
+
],
|
|
6480
|
+
strokeWidth: 0.15,
|
|
6481
|
+
strokeColor: "rgba(255, 0, 0, 0.2)",
|
|
6482
|
+
strokeDash: [0.5, 0.5],
|
|
6483
|
+
step: 0,
|
|
6484
|
+
layer: route.route[i].z.toString()
|
|
6485
|
+
});
|
|
6486
|
+
}
|
|
6487
|
+
for (const point of route.vias) {
|
|
6488
|
+
graphics.circles.push({
|
|
6489
|
+
center: { x: point.x, y: point.y },
|
|
6490
|
+
radius: route.viaDiameter / 2,
|
|
6491
|
+
fill: "rgba(255, 0, 0, 0.2)",
|
|
6492
|
+
step: 0
|
|
6493
|
+
});
|
|
6494
|
+
}
|
|
6495
|
+
}
|
|
6496
|
+
for (const obstacle of this.obstacles) {
|
|
6497
|
+
graphics.rects.push({
|
|
6498
|
+
center: obstacle.center,
|
|
6499
|
+
width: obstacle.width,
|
|
6500
|
+
height: obstacle.height,
|
|
6501
|
+
fill: obstacle.layers?.includes("top") ? "rgba(255, 0, 0, 0.3)" : obstacle.layers?.includes("bottom") ? "rgba(0, 0, 255, 0.3)" : "rgba(128, 128, 128, 0.3)"
|
|
6502
|
+
});
|
|
6503
|
+
}
|
|
6504
|
+
if (this.currentUnsimplifiedHdRouteIndex < this.unsimplifiedHdRoutes.length) {
|
|
6505
|
+
const currentRoute = this.unsimplifiedHdRoutes[this.currentUnsimplifiedHdRouteIndex];
|
|
6506
|
+
if (currentRoute.route.length > 0) {
|
|
6507
|
+
graphics.circles.push({
|
|
6508
|
+
center: {
|
|
6509
|
+
x: currentRoute.route[0].x,
|
|
6510
|
+
y: currentRoute.route[0].y
|
|
6511
|
+
},
|
|
6512
|
+
radius: 0.2,
|
|
6513
|
+
fill: "yellow",
|
|
6514
|
+
label: "Current"
|
|
6515
|
+
});
|
|
6516
|
+
}
|
|
6517
|
+
}
|
|
6518
|
+
return graphics;
|
|
6519
|
+
}
|
|
6520
|
+
};
|
|
6521
|
+
|
|
5831
6522
|
// lib/solvers/AutoroutingPipelineSolver.ts
|
|
5832
6523
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
5833
6524
|
return {
|
|
@@ -5873,6 +6564,7 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
5873
6564
|
highDensityStitchSolver;
|
|
5874
6565
|
singleLayerNodeMerger;
|
|
5875
6566
|
strawSolver;
|
|
6567
|
+
multiSimplifiedPathSolver;
|
|
5876
6568
|
startTimeOfPhase;
|
|
5877
6569
|
endTimeOfPhase;
|
|
5878
6570
|
timeSpentOnPhase;
|
|
@@ -6018,6 +6710,18 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6018
6710
|
layerCount: cms.srj.layerCount
|
|
6019
6711
|
}
|
|
6020
6712
|
]
|
|
6713
|
+
),
|
|
6714
|
+
definePipelineStep(
|
|
6715
|
+
"multiSimplifiedPathSolver",
|
|
6716
|
+
MultiSimplifiedPathSolver,
|
|
6717
|
+
(cms) => [
|
|
6718
|
+
{
|
|
6719
|
+
unsimplifiedHdRoutes: cms.highDensityStitchSolver.mergedHdRoutes,
|
|
6720
|
+
obstacles: cms.srj.obstacles,
|
|
6721
|
+
connMap: cms.connMap,
|
|
6722
|
+
colorMap: cms.colorMap
|
|
6723
|
+
}
|
|
6724
|
+
]
|
|
6021
6725
|
)
|
|
6022
6726
|
];
|
|
6023
6727
|
currentPipelineStepIndex = 0;
|
|
@@ -6066,12 +6770,21 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6066
6770
|
const segmentOptimizationViz = this.unravelMultiSectionSolver?.visualize() ?? this.segmentToPointOptimizer?.visualize();
|
|
6067
6771
|
const highDensityViz = this.highDensityRouteSolver?.visualize();
|
|
6068
6772
|
const highDensityStitchViz = this.highDensityStitchSolver?.visualize();
|
|
6773
|
+
const simplifiedPathSolverViz = this.multiSimplifiedPathSolver?.visualize();
|
|
6069
6774
|
const problemViz = {
|
|
6070
|
-
points: [
|
|
6775
|
+
points: [
|
|
6776
|
+
...this.srj.connections.flatMap(
|
|
6777
|
+
(c) => c.pointsToConnect.map((p) => ({
|
|
6778
|
+
...p,
|
|
6779
|
+
label: `${c.name} ${p.pcb_port_id ?? ""}`
|
|
6780
|
+
}))
|
|
6781
|
+
)
|
|
6782
|
+
],
|
|
6071
6783
|
rects: [
|
|
6072
6784
|
...(this.srj.obstacles ?? []).map((o) => ({
|
|
6073
6785
|
...o,
|
|
6074
|
-
fill: o.layers?.includes("top") ? "rgba(255,0,0,0.25)" : o.layers?.includes("bottom") ? "rgba(0,0,255,0.25)" : "rgba(255,0,0,0.25)"
|
|
6786
|
+
fill: o.layers?.includes("top") ? "rgba(255,0,0,0.25)" : o.layers?.includes("bottom") ? "rgba(0,0,255,0.25)" : "rgba(255,0,0,0.25)",
|
|
6787
|
+
label: o.layers?.join(", ")
|
|
6075
6788
|
}))
|
|
6076
6789
|
],
|
|
6077
6790
|
lines: [
|
|
@@ -6109,6 +6822,7 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6109
6822
|
segmentOptimizationViz,
|
|
6110
6823
|
highDensityViz ? combineVisualizations(problemViz, highDensityViz) : null,
|
|
6111
6824
|
highDensityStitchViz,
|
|
6825
|
+
simplifiedPathSolverViz,
|
|
6112
6826
|
this.solved ? combineVisualizations(
|
|
6113
6827
|
problemViz,
|
|
6114
6828
|
convertSrjToGraphicsObject(this.getOutputSimpleRouteJson())
|
|
@@ -6125,6 +6839,9 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6125
6839
|
const match = mstConnectionName.match(/^(.+?)_mst\d+$/);
|
|
6126
6840
|
return match ? match[1] : mstConnectionName;
|
|
6127
6841
|
}
|
|
6842
|
+
_getOutputHdRoutes() {
|
|
6843
|
+
return this.multiSimplifiedPathSolver?.simplifiedHdRoutes ?? this.highDensityStitchSolver.mergedHdRoutes;
|
|
6844
|
+
}
|
|
6128
6845
|
/**
|
|
6129
6846
|
* Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
|
|
6130
6847
|
*/
|
|
@@ -6133,11 +6850,12 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6133
6850
|
throw new Error("Cannot get output before solving is complete");
|
|
6134
6851
|
}
|
|
6135
6852
|
const traces = [];
|
|
6853
|
+
const allHdRoutes = this._getOutputHdRoutes();
|
|
6136
6854
|
for (const connection of this.netToPointPairsSolver?.newConnections ?? []) {
|
|
6137
6855
|
const netConnection = this.srj.connections.find(
|
|
6138
6856
|
(c) => c.name === connection.netConnectionName
|
|
6139
6857
|
);
|
|
6140
|
-
const hdRoutes =
|
|
6858
|
+
const hdRoutes = allHdRoutes.filter(
|
|
6141
6859
|
(r) => r.connectionName === connection.name
|
|
6142
6860
|
);
|
|
6143
6861
|
for (let i = 0; i < hdRoutes.length; i++) {
|