@tscircuit/capacity-autorouter 0.0.51 → 0.0.52
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 +103 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4030,20 +4030,17 @@ function distance2(p1, p2) {
|
|
|
4030
4030
|
|
|
4031
4031
|
// lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/calculateSideTraversal.ts
|
|
4032
4032
|
var EPSILON2 = 1e-9;
|
|
4033
|
-
function calculateSegmentTraversal(startPoint, endPoint, bounds) {
|
|
4033
|
+
function calculateSegmentTraversal(startPoint, endPoint, bounds, turnDirection = "cw") {
|
|
4034
4034
|
const startAngle = pointToAngle(startPoint, bounds);
|
|
4035
|
-
|
|
4036
|
-
if (endAngle < startAngle) {
|
|
4037
|
-
endAngle += 2 * Math.PI;
|
|
4038
|
-
}
|
|
4035
|
+
const endAngle = pointToAngle(endPoint, bounds);
|
|
4039
4036
|
if (Math.abs(endAngle - startAngle) < EPSILON2) {
|
|
4040
4037
|
return { left: 0, top: 0, right: 0, bottom: 0 };
|
|
4041
4038
|
}
|
|
4042
|
-
return calculateSidePercentages(startAngle, endAngle, bounds);
|
|
4039
|
+
return calculateSidePercentages(startAngle, endAngle, bounds, turnDirection);
|
|
4043
4040
|
}
|
|
4044
|
-
function calculateTraversalPercentages(A, B, C, bounds) {
|
|
4045
|
-
const percentagesAB = calculateSegmentTraversal(A, B, bounds);
|
|
4046
|
-
const percentagesBC = calculateSegmentTraversal(B, C, bounds);
|
|
4041
|
+
function calculateTraversalPercentages(A, B, C, bounds, turnDirection) {
|
|
4042
|
+
const percentagesAB = calculateSegmentTraversal(A, B, bounds, turnDirection);
|
|
4043
|
+
const percentagesBC = calculateSegmentTraversal(B, C, bounds, turnDirection);
|
|
4047
4044
|
const totalPercentages = {
|
|
4048
4045
|
left: Math.min(1, percentagesAB.left + percentagesBC.left),
|
|
4049
4046
|
top: Math.min(1, percentagesAB.top + percentagesBC.top),
|
|
@@ -4080,7 +4077,7 @@ function pointToAngle(point, bounds) {
|
|
|
4080
4077
|
distance6 = Math.max(0, Math.min(perimeter, distance6));
|
|
4081
4078
|
return perimeter > EPSILON2 ? distance6 / perimeter * (2 * Math.PI) : 0;
|
|
4082
4079
|
}
|
|
4083
|
-
function calculateSidePercentages(startAngle, endAngle, bounds) {
|
|
4080
|
+
function calculateSidePercentages(startAngle, endAngle, bounds, turnDirection) {
|
|
4084
4081
|
const width = bounds.maxX - bounds.minX;
|
|
4085
4082
|
const height = bounds.maxY - bounds.minY;
|
|
4086
4083
|
if (width < EPSILON2 && height < EPSILON2)
|
|
@@ -4104,17 +4101,54 @@ function calculateSidePercentages(startAngle, endAngle, bounds) {
|
|
|
4104
4101
|
// Ends at 2PI
|
|
4105
4102
|
];
|
|
4106
4103
|
const result = { left: 0, top: 0, right: 0, bottom: 0 };
|
|
4107
|
-
const
|
|
4108
|
-
|
|
4104
|
+
const calculateTraversalOverlap = (sStart, sEnd, tStart, tEnd, wrapsAround) => {
|
|
4105
|
+
const effectiveSEnd = sEnd > 2 * Math.PI - EPSILON2 ? 2 * Math.PI : sEnd;
|
|
4106
|
+
if (effectiveSEnd <= sStart + EPSILON2) return 0;
|
|
4107
|
+
if (!wrapsAround) {
|
|
4108
|
+
const overlapStart = Math.max(sStart, tStart);
|
|
4109
|
+
const overlapEnd = Math.min(effectiveSEnd, tEnd);
|
|
4110
|
+
return Math.max(0, overlapEnd - overlapStart);
|
|
4111
|
+
} else {
|
|
4112
|
+
const overlap1Start = Math.max(sStart, tStart);
|
|
4113
|
+
const overlap1End = Math.min(effectiveSEnd, 2 * Math.PI);
|
|
4114
|
+
const overlap1 = Math.max(0, overlap1End - overlap1Start);
|
|
4115
|
+
const overlap2Start = Math.max(sStart, 0);
|
|
4116
|
+
const overlap2End = Math.min(effectiveSEnd, tEnd);
|
|
4117
|
+
const overlap2 = Math.max(0, overlap2End - overlap2Start);
|
|
4118
|
+
return overlap1 + overlap2;
|
|
4119
|
+
}
|
|
4120
|
+
};
|
|
4109
4121
|
for (const side of sides) {
|
|
4110
4122
|
const sideAngleRange = side.end - side.start;
|
|
4111
4123
|
if (sideAngleRange < EPSILON2 || side.length < EPSILON2) continue;
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4124
|
+
let traversedAngleOnSide = 0;
|
|
4125
|
+
if (turnDirection === "cw") {
|
|
4126
|
+
const wraps = startAngle > endAngle + EPSILON2;
|
|
4127
|
+
traversedAngleOnSide = calculateTraversalOverlap(
|
|
4128
|
+
side.start,
|
|
4129
|
+
side.end,
|
|
4130
|
+
startAngle,
|
|
4131
|
+
endAngle,
|
|
4132
|
+
wraps
|
|
4133
|
+
);
|
|
4134
|
+
} else {
|
|
4135
|
+
const wraps = endAngle > startAngle + EPSILON2;
|
|
4136
|
+
traversedAngleOnSide = calculateTraversalOverlap(
|
|
4137
|
+
side.start,
|
|
4138
|
+
side.end,
|
|
4139
|
+
endAngle,
|
|
4140
|
+
// Start of equivalent CW traversal
|
|
4141
|
+
startAngle,
|
|
4142
|
+
// End of equivalent CW traversal
|
|
4143
|
+
wraps
|
|
4144
|
+
);
|
|
4145
|
+
}
|
|
4146
|
+
if (traversedAngleOnSide > EPSILON2) {
|
|
4116
4147
|
const percentage = traversedAngleOnSide / sideAngleRange;
|
|
4117
|
-
result[side.name] += Math.max(
|
|
4148
|
+
result[side.name] += Math.max(
|
|
4149
|
+
0,
|
|
4150
|
+
Number.isFinite(percentage) ? percentage : 0
|
|
4151
|
+
);
|
|
4118
4152
|
}
|
|
4119
4153
|
}
|
|
4120
4154
|
for (const key in result) {
|
|
@@ -4126,6 +4160,28 @@ function calculateSidePercentages(startAngle, endAngle, bounds) {
|
|
|
4126
4160
|
return result;
|
|
4127
4161
|
}
|
|
4128
4162
|
|
|
4163
|
+
// lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/computeTurnDirection.ts
|
|
4164
|
+
function triangleDirection({
|
|
4165
|
+
angleA,
|
|
4166
|
+
angleB,
|
|
4167
|
+
angleC
|
|
4168
|
+
}) {
|
|
4169
|
+
const Ax = Math.cos(angleA);
|
|
4170
|
+
const Ay = Math.sin(angleA);
|
|
4171
|
+
const Bx = Math.cos(angleB);
|
|
4172
|
+
const By = Math.sin(angleB);
|
|
4173
|
+
const Cx = Math.cos(angleC);
|
|
4174
|
+
const Cy = Math.sin(angleC);
|
|
4175
|
+
const signedArea = (Bx - Ax) * (Cy - Ay) - (By - Ay) * (Cx - Ax);
|
|
4176
|
+
return signedArea < 0 ? "ccw" : "cw";
|
|
4177
|
+
}
|
|
4178
|
+
function computeTurnDirection(A, B, C, bounds) {
|
|
4179
|
+
const angleA = pointToAngle(A, bounds);
|
|
4180
|
+
const angleB = pointToAngle(B, bounds);
|
|
4181
|
+
const angleC = pointToAngle(C, bounds);
|
|
4182
|
+
return triangleDirection({ angleA, angleB, angleC });
|
|
4183
|
+
}
|
|
4184
|
+
|
|
4129
4185
|
// lib/solvers/HighDensitySolver/TwoRouteHighDensitySolver/SingleTransitionCrossingRouteSolver.ts
|
|
4130
4186
|
var SingleTransitionCrossingRouteSolver = class extends BaseSolver {
|
|
4131
4187
|
// Input parameters
|
|
@@ -4213,7 +4269,14 @@ var SingleTransitionCrossingRouteSolver = class extends BaseSolver {
|
|
|
4213
4269
|
const A = flatRoute.A;
|
|
4214
4270
|
const B = ntrP1;
|
|
4215
4271
|
const C = flatRoute.B;
|
|
4216
|
-
const
|
|
4272
|
+
const turnDirection = computeTurnDirection(A, B, C, this.bounds);
|
|
4273
|
+
const sideTraversal = calculateTraversalPercentages(
|
|
4274
|
+
A,
|
|
4275
|
+
B,
|
|
4276
|
+
C,
|
|
4277
|
+
this.bounds,
|
|
4278
|
+
turnDirection
|
|
4279
|
+
);
|
|
4217
4280
|
const viaBounds = {
|
|
4218
4281
|
minX: this.bounds.minX + (sideTraversal.left > 0.5 ? marginFromBorderWithTrace : marginFromBorderWithoutTrace),
|
|
4219
4282
|
minY: this.bounds.minY + (sideTraversal.bottom > 0.5 ? marginFromBorderWithTrace : marginFromBorderWithoutTrace),
|
|
@@ -4291,23 +4354,29 @@ var SingleTransitionCrossingRouteSolver = class extends BaseSolver {
|
|
|
4291
4354
|
otherRouteStart.z !== flatStart.z ? otherRouteStart : otherRouteEnd,
|
|
4292
4355
|
this.traceThickness
|
|
4293
4356
|
);
|
|
4294
|
-
const
|
|
4295
|
-
center: { x: via.x, y: via.y },
|
|
4296
|
-
radius: minDistFromViaToTrace
|
|
4297
|
-
}).E;
|
|
4298
|
-
const p3 = findPointToGetAroundCircle(p2, flatEnd, {
|
|
4357
|
+
const viaCircle = {
|
|
4299
4358
|
center: { x: via.x, y: via.y },
|
|
4300
4359
|
radius: minDistFromViaToTrace
|
|
4301
|
-
}
|
|
4302
|
-
const
|
|
4303
|
-
const
|
|
4360
|
+
};
|
|
4361
|
+
const p1 = findPointToGetAroundCircle(flatStart, p2, viaCircle).E;
|
|
4362
|
+
const p3 = findPointToGetAroundCircle(p2, flatEnd, viaCircle).E;
|
|
4363
|
+
const p0_5 = findPointToGetAroundCircle(flatStart, p1, viaCircle).E;
|
|
4364
|
+
const p1_5 = findPointToGetAroundCircle(p1, p2, viaCircle).E;
|
|
4365
|
+
const p2_5 = findPointToGetAroundCircle(p2, p3, viaCircle).E;
|
|
4366
|
+
const p3_5 = findPointToGetAroundCircle(p3, flatEnd, viaCircle).E;
|
|
4367
|
+
const p2_better = findPointToGetAroundCircle(p1_5, p2_5, viaCircle).E;
|
|
4304
4368
|
return {
|
|
4305
4369
|
connectionName: flatRouteConnectionName,
|
|
4306
4370
|
route: [
|
|
4307
4371
|
{ x: flatStart.x, y: flatStart.y, z: flatStart.z ?? 0 },
|
|
4308
|
-
|
|
4309
|
-
{ x:
|
|
4310
|
-
|
|
4372
|
+
{ x: p0_5.x, y: p0_5.y, z: flatStart.z ?? 0 },
|
|
4373
|
+
{ x: p1.x, y: p1.y, z: flatStart.z ?? 0 },
|
|
4374
|
+
{ x: p1_5.x, y: p1_5.y, z: flatStart.z ?? 0 },
|
|
4375
|
+
// { x: p2.x, y: p2.y, z: flatStart.z ?? 0 },
|
|
4376
|
+
{ x: p2_better.x, y: p2_better.y, z: flatStart.z ?? 0 },
|
|
4377
|
+
{ x: p2_5.x, y: p2_5.y, z: flatStart.z ?? 0 },
|
|
4378
|
+
{ x: p3.x, y: p3.y, z: flatStart.z ?? 0 },
|
|
4379
|
+
{ x: p3_5.x, y: p3_5.y, z: flatStart.z ?? 0 },
|
|
4311
4380
|
{ x: flatEnd.x, y: flatEnd.y, z: flatEnd.z ?? 0 }
|
|
4312
4381
|
],
|
|
4313
4382
|
traceThickness: this.traceThickness,
|
|
@@ -7926,13 +7995,13 @@ function minimumDistanceBetweenSegments(A1, A2, B1, B2) {
|
|
|
7926
7995
|
if (segmentsIntersect(A1, A2, B1, B2)) {
|
|
7927
7996
|
return 0;
|
|
7928
7997
|
}
|
|
7929
|
-
const distA1 =
|
|
7930
|
-
const distA2 =
|
|
7931
|
-
const distB1 =
|
|
7932
|
-
const distB2 =
|
|
7998
|
+
const distA1 = pointToSegmentDistance5(A1, B1, B2);
|
|
7999
|
+
const distA2 = pointToSegmentDistance5(A2, B1, B2);
|
|
8000
|
+
const distB1 = pointToSegmentDistance5(B1, A1, A2);
|
|
8001
|
+
const distB2 = pointToSegmentDistance5(B2, A1, A2);
|
|
7933
8002
|
return Math.min(distA1, distA2, distB1, distB2);
|
|
7934
8003
|
}
|
|
7935
|
-
function
|
|
8004
|
+
function pointToSegmentDistance5(P, Q1, Q2) {
|
|
7936
8005
|
const v = { x: Q2.x - Q1.x, y: Q2.y - Q1.y };
|
|
7937
8006
|
const w = { x: P.x - Q1.x, y: P.y - Q1.y };
|
|
7938
8007
|
const c1 = dotProduct(w, v);
|