@tscircuit/capacity-autorouter 0.0.27 → 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 -10
- 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) {
|
|
@@ -3127,6 +3128,9 @@ var getConnectivityMapFromSimpleRouteJson = (srj) => {
|
|
|
3127
3128
|
}
|
|
3128
3129
|
}
|
|
3129
3130
|
}
|
|
3131
|
+
for (const obstacle of srj.obstacles) {
|
|
3132
|
+
connMap.addConnections([obstacle.connectedTo]);
|
|
3133
|
+
}
|
|
3130
3134
|
return connMap;
|
|
3131
3135
|
};
|
|
3132
3136
|
|
|
@@ -3332,13 +3336,13 @@ function buildMinimumSpanningTree(points) {
|
|
|
3332
3336
|
if (point.x === neighbor.x && point.y === neighbor.y) {
|
|
3333
3337
|
continue;
|
|
3334
3338
|
}
|
|
3335
|
-
const
|
|
3339
|
+
const distance4 = Math.sqrt(
|
|
3336
3340
|
(point.x - neighbor.x) ** 2 + (point.y - neighbor.y) ** 2
|
|
3337
3341
|
);
|
|
3338
3342
|
edges.push({
|
|
3339
3343
|
from: point,
|
|
3340
3344
|
to: neighbor,
|
|
3341
|
-
weight:
|
|
3345
|
+
weight: distance4
|
|
3342
3346
|
});
|
|
3343
3347
|
}
|
|
3344
3348
|
}
|
|
@@ -5105,11 +5109,11 @@ var CapacityPathingSolver = class extends BaseSolver {
|
|
|
5105
5109
|
let closestNode = this.nodes[0];
|
|
5106
5110
|
let minDistance = Number.MAX_VALUE;
|
|
5107
5111
|
for (const node of nodesWithTargets) {
|
|
5108
|
-
const
|
|
5112
|
+
const distance4 = Math.sqrt(
|
|
5109
5113
|
(node.center.x - point.x) ** 2 + (node.center.y - point.y) ** 2
|
|
5110
5114
|
);
|
|
5111
|
-
if (
|
|
5112
|
-
minDistance =
|
|
5115
|
+
if (distance4 < minDistance) {
|
|
5116
|
+
minDistance = distance4;
|
|
5113
5117
|
closestNode = node;
|
|
5114
5118
|
}
|
|
5115
5119
|
}
|
|
@@ -5827,6 +5831,694 @@ ${node.width}x${node.height}
|
|
|
5827
5831
|
}
|
|
5828
5832
|
};
|
|
5829
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
|
+
|
|
5830
6522
|
// lib/solvers/AutoroutingPipelineSolver.ts
|
|
5831
6523
|
function definePipelineStep(solverName, solverClass, getConstructorParams, opts = {}) {
|
|
5832
6524
|
return {
|
|
@@ -5872,6 +6564,7 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
5872
6564
|
highDensityStitchSolver;
|
|
5873
6565
|
singleLayerNodeMerger;
|
|
5874
6566
|
strawSolver;
|
|
6567
|
+
multiSimplifiedPathSolver;
|
|
5875
6568
|
startTimeOfPhase;
|
|
5876
6569
|
endTimeOfPhase;
|
|
5877
6570
|
timeSpentOnPhase;
|
|
@@ -6017,6 +6710,18 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6017
6710
|
layerCount: cms.srj.layerCount
|
|
6018
6711
|
}
|
|
6019
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
|
+
]
|
|
6020
6725
|
)
|
|
6021
6726
|
];
|
|
6022
6727
|
currentPipelineStepIndex = 0;
|
|
@@ -6065,12 +6770,21 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6065
6770
|
const segmentOptimizationViz = this.unravelMultiSectionSolver?.visualize() ?? this.segmentToPointOptimizer?.visualize();
|
|
6066
6771
|
const highDensityViz = this.highDensityRouteSolver?.visualize();
|
|
6067
6772
|
const highDensityStitchViz = this.highDensityStitchSolver?.visualize();
|
|
6773
|
+
const simplifiedPathSolverViz = this.multiSimplifiedPathSolver?.visualize();
|
|
6068
6774
|
const problemViz = {
|
|
6069
|
-
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
|
+
],
|
|
6070
6783
|
rects: [
|
|
6071
6784
|
...(this.srj.obstacles ?? []).map((o) => ({
|
|
6072
6785
|
...o,
|
|
6073
|
-
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(", ")
|
|
6074
6788
|
}))
|
|
6075
6789
|
],
|
|
6076
6790
|
lines: [
|
|
@@ -6108,6 +6822,7 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6108
6822
|
segmentOptimizationViz,
|
|
6109
6823
|
highDensityViz ? combineVisualizations(problemViz, highDensityViz) : null,
|
|
6110
6824
|
highDensityStitchViz,
|
|
6825
|
+
simplifiedPathSolverViz,
|
|
6111
6826
|
this.solved ? combineVisualizations(
|
|
6112
6827
|
problemViz,
|
|
6113
6828
|
convertSrjToGraphicsObject(this.getOutputSimpleRouteJson())
|
|
@@ -6124,6 +6839,9 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6124
6839
|
const match = mstConnectionName.match(/^(.+?)_mst\d+$/);
|
|
6125
6840
|
return match ? match[1] : mstConnectionName;
|
|
6126
6841
|
}
|
|
6842
|
+
_getOutputHdRoutes() {
|
|
6843
|
+
return this.multiSimplifiedPathSolver?.simplifiedHdRoutes ?? this.highDensityStitchSolver.mergedHdRoutes;
|
|
6844
|
+
}
|
|
6127
6845
|
/**
|
|
6128
6846
|
* Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces
|
|
6129
6847
|
*/
|
|
@@ -6132,11 +6850,12 @@ var CapacityMeshSolver = class extends BaseSolver {
|
|
|
6132
6850
|
throw new Error("Cannot get output before solving is complete");
|
|
6133
6851
|
}
|
|
6134
6852
|
const traces = [];
|
|
6853
|
+
const allHdRoutes = this._getOutputHdRoutes();
|
|
6135
6854
|
for (const connection of this.netToPointPairsSolver?.newConnections ?? []) {
|
|
6136
6855
|
const netConnection = this.srj.connections.find(
|
|
6137
6856
|
(c) => c.name === connection.netConnectionName
|
|
6138
6857
|
);
|
|
6139
|
-
const hdRoutes =
|
|
6858
|
+
const hdRoutes = allHdRoutes.filter(
|
|
6140
6859
|
(r) => r.connectionName === connection.name
|
|
6141
6860
|
);
|
|
6142
6861
|
for (let i = 0; i < hdRoutes.length; i++) {
|