@tscircuit/core 0.0.905 → 0.0.906
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 +277 -121
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2335,10 +2335,10 @@ var SmtPad = class extends PrimitiveComponent2 {
|
|
|
2335
2335
|
pcb_group_id: this.getGroup()?.pcb_group_id ?? void 0
|
|
2336
2336
|
});
|
|
2337
2337
|
} else if (props.shape === "polygon") {
|
|
2338
|
-
const transformedPoints = props.points.map((
|
|
2338
|
+
const transformedPoints = props.points.map((point2) => {
|
|
2339
2339
|
const transformed = applyToPoint2(globalTransform, {
|
|
2340
|
-
x: distance.parse(
|
|
2341
|
-
y: distance.parse(
|
|
2340
|
+
x: distance.parse(point2.x),
|
|
2341
|
+
y: distance.parse(point2.y)
|
|
2342
2342
|
});
|
|
2343
2343
|
return {
|
|
2344
2344
|
x: transformed.x,
|
|
@@ -2546,18 +2546,18 @@ var SilkscreenPath = class extends PrimitiveComponent2 {
|
|
|
2546
2546
|
if (!currentPath) return;
|
|
2547
2547
|
let currentCenterX = 0;
|
|
2548
2548
|
let currentCenterY = 0;
|
|
2549
|
-
for (const
|
|
2550
|
-
currentCenterX +=
|
|
2551
|
-
currentCenterY +=
|
|
2549
|
+
for (const point2 of currentPath.route) {
|
|
2550
|
+
currentCenterX += point2.x;
|
|
2551
|
+
currentCenterY += point2.y;
|
|
2552
2552
|
}
|
|
2553
2553
|
currentCenterX /= currentPath.route.length;
|
|
2554
2554
|
currentCenterY /= currentPath.route.length;
|
|
2555
2555
|
const offsetX = newCenter.x - currentCenterX;
|
|
2556
2556
|
const offsetY = newCenter.y - currentCenterY;
|
|
2557
|
-
const newRoute = currentPath.route.map((
|
|
2558
|
-
...
|
|
2559
|
-
x:
|
|
2560
|
-
y:
|
|
2557
|
+
const newRoute = currentPath.route.map((point2) => ({
|
|
2558
|
+
...point2,
|
|
2559
|
+
x: point2.x + offsetX,
|
|
2560
|
+
y: point2.y + offsetY
|
|
2561
2561
|
}));
|
|
2562
2562
|
db.pcb_silkscreen_path.update(this.pcb_silkscreen_path_id, {
|
|
2563
2563
|
route: newRoute
|
|
@@ -2569,11 +2569,11 @@ var SilkscreenPath = class extends PrimitiveComponent2 {
|
|
|
2569
2569
|
return { width: 0, height: 0 };
|
|
2570
2570
|
}
|
|
2571
2571
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
2572
|
-
for (const
|
|
2573
|
-
minX = Math.min(minX,
|
|
2574
|
-
maxX = Math.max(maxX,
|
|
2575
|
-
minY = Math.min(minY,
|
|
2576
|
-
maxY = Math.max(maxY,
|
|
2572
|
+
for (const point2 of props.route) {
|
|
2573
|
+
minX = Math.min(minX, point2.x);
|
|
2574
|
+
maxX = Math.max(maxX, point2.x);
|
|
2575
|
+
minY = Math.min(minY, point2.y);
|
|
2576
|
+
maxY = Math.max(maxY, point2.y);
|
|
2577
2577
|
}
|
|
2578
2578
|
return {
|
|
2579
2579
|
width: maxX - minX,
|
|
@@ -2609,14 +2609,14 @@ var PcbTrace = class extends PrimitiveComponent2 {
|
|
|
2609
2609
|
const subcircuit = this.getSubcircuit();
|
|
2610
2610
|
const { maybeFlipLayer } = this._getPcbPrimitiveFlippedHelpers();
|
|
2611
2611
|
const parentTransform = this._computePcbGlobalTransformBeforeLayout();
|
|
2612
|
-
const transformedRoute = props.route.map((
|
|
2613
|
-
const { x, y, ...restOfPoint } =
|
|
2612
|
+
const transformedRoute = props.route.map((point2) => {
|
|
2613
|
+
const { x, y, ...restOfPoint } = point2;
|
|
2614
2614
|
const transformedPoint = applyToPoint4(parentTransform, { x, y });
|
|
2615
|
-
if (
|
|
2615
|
+
if (point2.route_type === "wire" && point2.layer) {
|
|
2616
2616
|
return {
|
|
2617
2617
|
...transformedPoint,
|
|
2618
2618
|
...restOfPoint,
|
|
2619
|
-
layer: maybeFlipLayer(
|
|
2619
|
+
layer: maybeFlipLayer(point2.layer)
|
|
2620
2620
|
};
|
|
2621
2621
|
}
|
|
2622
2622
|
return { ...transformedPoint, ...restOfPoint };
|
|
@@ -2636,16 +2636,16 @@ var PcbTrace = class extends PrimitiveComponent2 {
|
|
|
2636
2636
|
return { width: 0, height: 0 };
|
|
2637
2637
|
}
|
|
2638
2638
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
2639
|
-
for (const
|
|
2640
|
-
minX = Math.min(minX,
|
|
2641
|
-
maxX = Math.max(maxX,
|
|
2642
|
-
minY = Math.min(minY,
|
|
2643
|
-
maxY = Math.max(maxY,
|
|
2644
|
-
if (
|
|
2645
|
-
minX = Math.min(minX,
|
|
2646
|
-
maxX = Math.max(maxX,
|
|
2647
|
-
minY = Math.min(minY,
|
|
2648
|
-
maxY = Math.max(maxY,
|
|
2639
|
+
for (const point2 of props.route) {
|
|
2640
|
+
minX = Math.min(minX, point2.x);
|
|
2641
|
+
maxX = Math.max(maxX, point2.x);
|
|
2642
|
+
minY = Math.min(minY, point2.y);
|
|
2643
|
+
maxY = Math.max(maxY, point2.y);
|
|
2644
|
+
if (point2.route_type === "wire") {
|
|
2645
|
+
minX = Math.min(minX, point2.x - point2.width / 2);
|
|
2646
|
+
maxX = Math.max(maxX, point2.x + point2.width / 2);
|
|
2647
|
+
minY = Math.min(minY, point2.y - point2.width / 2);
|
|
2648
|
+
maxY = Math.max(maxY, point2.y + point2.width / 2);
|
|
2649
2649
|
}
|
|
2650
2650
|
}
|
|
2651
2651
|
if (minX === Infinity || maxX === -Infinity || minY === Infinity || maxY === -Infinity) {
|
|
@@ -2911,9 +2911,9 @@ var PlatedHole = class extends PrimitiveComponent2 {
|
|
|
2911
2911
|
});
|
|
2912
2912
|
this.pcb_plated_hole_id = pcb_plated_hole.pcb_plated_hole_id;
|
|
2913
2913
|
} else if (props.shape === "hole_with_polygon_pad") {
|
|
2914
|
-
const padOutline = (props.padOutline || []).map((
|
|
2915
|
-
const x = typeof
|
|
2916
|
-
const y = typeof
|
|
2914
|
+
const padOutline = (props.padOutline || []).map((point2) => {
|
|
2915
|
+
const x = typeof point2.x === "number" ? point2.x : parseFloat(String(point2.x));
|
|
2916
|
+
const y = typeof point2.y === "number" ? point2.y : parseFloat(String(point2.y));
|
|
2917
2917
|
return {
|
|
2918
2918
|
x,
|
|
2919
2919
|
y
|
|
@@ -3273,11 +3273,11 @@ var Cutout = class extends PrimitiveComponent2 {
|
|
|
3273
3273
|
if (props.shape === "polygon") {
|
|
3274
3274
|
if (props.points.length === 0) return { width: 0, height: 0 };
|
|
3275
3275
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
3276
|
-
for (const
|
|
3277
|
-
minX = Math.min(minX,
|
|
3278
|
-
maxX = Math.max(maxX,
|
|
3279
|
-
minY = Math.min(minY,
|
|
3280
|
-
maxY = Math.max(maxY,
|
|
3276
|
+
for (const point2 of props.points) {
|
|
3277
|
+
minX = Math.min(minX, point2.x);
|
|
3278
|
+
maxX = Math.max(maxX, point2.x);
|
|
3279
|
+
minY = Math.min(minY, point2.y);
|
|
3280
|
+
maxY = Math.max(maxY, point2.y);
|
|
3281
3281
|
}
|
|
3282
3282
|
return { width: maxX - minX, height: maxY - minY };
|
|
3283
3283
|
}
|
|
@@ -3316,11 +3316,11 @@ var Cutout = class extends PrimitiveComponent2 {
|
|
|
3316
3316
|
} else if (cutout.shape === "polygon") {
|
|
3317
3317
|
if (cutout.points.length === 0) return super._getPcbCircuitJsonBounds();
|
|
3318
3318
|
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
3319
|
-
for (const
|
|
3320
|
-
minX = Math.min(minX,
|
|
3321
|
-
maxX = Math.max(maxX,
|
|
3322
|
-
minY = Math.min(minY,
|
|
3323
|
-
maxY = Math.max(maxY,
|
|
3319
|
+
for (const point2 of cutout.points) {
|
|
3320
|
+
minX = Math.min(minX, point2.x);
|
|
3321
|
+
maxX = Math.max(maxX, point2.x);
|
|
3322
|
+
minY = Math.min(minY, point2.y);
|
|
3323
|
+
maxY = Math.max(maxY, point2.y);
|
|
3324
3324
|
}
|
|
3325
3325
|
return {
|
|
3326
3326
|
center: { x: (minX + maxX) / 2, y: (minY + maxY) / 2 },
|
|
@@ -5324,13 +5324,13 @@ var getDistance = (a, b) => {
|
|
|
5324
5324
|
const bPos = "_getGlobalPcbPositionBeforeLayout" in b ? b._getGlobalPcbPositionBeforeLayout() : b;
|
|
5325
5325
|
return Math.sqrt((aPos.x - bPos.x) ** 2 + (aPos.y - bPos.y) ** 2);
|
|
5326
5326
|
};
|
|
5327
|
-
function getClosest(
|
|
5327
|
+
function getClosest(point2, candidates) {
|
|
5328
5328
|
if (candidates.length === 0)
|
|
5329
5329
|
throw new Error("No candidates given to getClosest method");
|
|
5330
5330
|
let closest = candidates[0];
|
|
5331
5331
|
let closestDist = Infinity;
|
|
5332
5332
|
for (const candidate of candidates) {
|
|
5333
|
-
const dist = getDistance(
|
|
5333
|
+
const dist = getDistance(point2, candidate);
|
|
5334
5334
|
if (dist < closestDist) {
|
|
5335
5335
|
closest = candidate;
|
|
5336
5336
|
closestDist = dist;
|
|
@@ -5464,24 +5464,24 @@ var isRouteOutsideBoard = (mergedRoute, { db }) => {
|
|
|
5464
5464
|
const pcbBoard = db.pcb_board.list()[0];
|
|
5465
5465
|
if (pcbBoard.outline) {
|
|
5466
5466
|
const boardOutline = pcbBoard.outline;
|
|
5467
|
-
const isInsidePolygon = (
|
|
5467
|
+
const isInsidePolygon = (point2, polygon) => {
|
|
5468
5468
|
let inside = false;
|
|
5469
5469
|
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
|
5470
5470
|
const xi = polygon[i].x, yi = polygon[i].y;
|
|
5471
5471
|
const xj = polygon[j].x, yj = polygon[j].y;
|
|
5472
|
-
const intersect = yi >
|
|
5472
|
+
const intersect = yi > point2.y !== yj > point2.y && point2.x < (xj - xi) * (point2.y - yi) / (yj - yi) + xi;
|
|
5473
5473
|
if (intersect) inside = !inside;
|
|
5474
5474
|
}
|
|
5475
5475
|
return inside;
|
|
5476
5476
|
};
|
|
5477
|
-
return mergedRoute.some((
|
|
5477
|
+
return mergedRoute.some((point2) => !isInsidePolygon(point2, boardOutline));
|
|
5478
5478
|
}
|
|
5479
5479
|
const boardWidth = pcbBoard.width;
|
|
5480
5480
|
const boardHeight = pcbBoard.height;
|
|
5481
5481
|
const boardCenterX = pcbBoard.center.x;
|
|
5482
5482
|
const boardCenterY = pcbBoard.center.y;
|
|
5483
|
-
const outsideBoard = mergedRoute.some((
|
|
5484
|
-
return
|
|
5483
|
+
const outsideBoard = mergedRoute.some((point2) => {
|
|
5484
|
+
return point2.x < boardCenterX - boardWidth / 2 || point2.y < boardCenterY - boardHeight / 2 || point2.x > boardCenterX + boardWidth / 2 || point2.y > boardCenterY + boardHeight / 2;
|
|
5485
5485
|
});
|
|
5486
5486
|
return outsideBoard;
|
|
5487
5487
|
};
|
|
@@ -6063,12 +6063,12 @@ var createSchematicTraceCrossingSegments = ({
|
|
|
6063
6063
|
|
|
6064
6064
|
// lib/components/primitive-components/Trace/trace-utils/create-schematic-trace-junctions.ts
|
|
6065
6065
|
var TOLERANCE = 1e-3;
|
|
6066
|
-
var isPointWithinEdge = (
|
|
6066
|
+
var isPointWithinEdge = (point2, edge) => {
|
|
6067
6067
|
const minX = Math.min(edge.from.x, edge.to.x);
|
|
6068
6068
|
const maxX = Math.max(edge.from.x, edge.to.x);
|
|
6069
6069
|
const minY = Math.min(edge.from.y, edge.to.y);
|
|
6070
6070
|
const maxY = Math.max(edge.from.y, edge.to.y);
|
|
6071
|
-
return
|
|
6071
|
+
return point2.x >= minX && point2.x <= maxX && point2.y >= minY && point2.y <= maxY;
|
|
6072
6072
|
};
|
|
6073
6073
|
var getEdgeOrientation = (edge) => {
|
|
6074
6074
|
const isVertical = Math.abs(edge.from.x - edge.to.x) < TOLERANCE;
|
|
@@ -6673,15 +6673,15 @@ import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectiv
|
|
|
6673
6673
|
function getTraceLength(route) {
|
|
6674
6674
|
let totalLength = 0;
|
|
6675
6675
|
for (let i = 0; i < route.length; i++) {
|
|
6676
|
-
const
|
|
6677
|
-
if (
|
|
6676
|
+
const point2 = route[i];
|
|
6677
|
+
if (point2.route_type === "wire") {
|
|
6678
6678
|
const nextPoint = route[i + 1];
|
|
6679
6679
|
if (nextPoint) {
|
|
6680
|
-
const dx = nextPoint.x -
|
|
6681
|
-
const dy = nextPoint.y -
|
|
6680
|
+
const dx = nextPoint.x - point2.x;
|
|
6681
|
+
const dy = nextPoint.y - point2.y;
|
|
6682
6682
|
totalLength += Math.sqrt(dx * dx + dy * dy);
|
|
6683
6683
|
}
|
|
6684
|
-
} else if (
|
|
6684
|
+
} else if (point2.route_type === "via") {
|
|
6685
6685
|
totalLength += 1.6;
|
|
6686
6686
|
}
|
|
6687
6687
|
}
|
|
@@ -6991,17 +6991,17 @@ function Trace_doInitialPcbTraceRender(trace) {
|
|
|
6991
6991
|
});
|
|
6992
6992
|
trace._portsRoutedOnPcb = ports;
|
|
6993
6993
|
trace.pcb_trace_id = pcb_trace.pcb_trace_id;
|
|
6994
|
-
for (const
|
|
6995
|
-
if (
|
|
6994
|
+
for (const point2 of mergedRoute) {
|
|
6995
|
+
if (point2.route_type === "via") {
|
|
6996
6996
|
db.pcb_via.insert({
|
|
6997
6997
|
pcb_trace_id: pcb_trace.pcb_trace_id,
|
|
6998
|
-
x:
|
|
6999
|
-
y:
|
|
6998
|
+
x: point2.x,
|
|
6999
|
+
y: point2.y,
|
|
7000
7000
|
hole_diameter: holeDiameter,
|
|
7001
7001
|
outer_diameter: padDiameter,
|
|
7002
|
-
layers: [
|
|
7003
|
-
from_layer:
|
|
7004
|
-
to_layer:
|
|
7002
|
+
layers: [point2.from_layer, point2.to_layer],
|
|
7003
|
+
from_layer: point2.from_layer,
|
|
7004
|
+
to_layer: point2.to_layer
|
|
7005
7005
|
});
|
|
7006
7006
|
}
|
|
7007
7007
|
}
|
|
@@ -10247,7 +10247,7 @@ var getSimpleRouteJsonFromCircuitJson = ({
|
|
|
10247
10247
|
// subcircuit
|
|
10248
10248
|
layerCount: board?.num_layers ?? 2,
|
|
10249
10249
|
minTraceWidth,
|
|
10250
|
-
outline: board?.outline?.map((
|
|
10250
|
+
outline: board?.outline?.map((point2) => ({ ...point2 }))
|
|
10251
10251
|
},
|
|
10252
10252
|
connMap
|
|
10253
10253
|
};
|
|
@@ -13735,9 +13735,9 @@ var Group6 = class extends NormalComponent3 {
|
|
|
13735
13735
|
const { _parsedProps: props } = this;
|
|
13736
13736
|
const groupProps2 = props;
|
|
13737
13737
|
const hasOutline = groupProps2.outline && groupProps2.outline.length > 0;
|
|
13738
|
-
const numericOutline = hasOutline ? groupProps2.outline.map((
|
|
13739
|
-
x: distance8.parse(
|
|
13740
|
-
y: distance8.parse(
|
|
13738
|
+
const numericOutline = hasOutline ? groupProps2.outline.map((point2) => ({
|
|
13739
|
+
x: distance8.parse(point2.x),
|
|
13740
|
+
y: distance8.parse(point2.y)
|
|
13741
13741
|
})) : void 0;
|
|
13742
13742
|
const pcb_group = db.pcb_group.insert({
|
|
13743
13743
|
is_subcircuit: this.isSubcircuit,
|
|
@@ -13766,9 +13766,9 @@ var Group6 = class extends NormalComponent3 {
|
|
|
13766
13766
|
if (this.pcb_group_id) {
|
|
13767
13767
|
const hasExplicitPositioning = this._parsedProps.pcbX !== void 0 || this._parsedProps.pcbY !== void 0;
|
|
13768
13768
|
if (hasOutline) {
|
|
13769
|
-
const numericOutline = props.outline.map((
|
|
13770
|
-
x: distance8.parse(
|
|
13771
|
-
y: distance8.parse(
|
|
13769
|
+
const numericOutline = props.outline.map((point2) => ({
|
|
13770
|
+
x: distance8.parse(point2.x),
|
|
13771
|
+
y: distance8.parse(point2.y)
|
|
13772
13772
|
}));
|
|
13773
13773
|
const outlineBounds = getBoundsFromPoints3(numericOutline);
|
|
13774
13774
|
if (!outlineBounds) return;
|
|
@@ -14183,20 +14183,20 @@ var Group6 = class extends NormalComponent3 {
|
|
|
14183
14183
|
continue;
|
|
14184
14184
|
}
|
|
14185
14185
|
if (pcb_trace.type === "pcb_trace") {
|
|
14186
|
-
for (const
|
|
14187
|
-
if (
|
|
14186
|
+
for (const point2 of pcb_trace.route) {
|
|
14187
|
+
if (point2.route_type === "via") {
|
|
14188
14188
|
db.pcb_via.insert({
|
|
14189
14189
|
pcb_trace_id: pcb_trace.pcb_trace_id,
|
|
14190
|
-
x:
|
|
14191
|
-
y:
|
|
14190
|
+
x: point2.x,
|
|
14191
|
+
y: point2.y,
|
|
14192
14192
|
hole_diameter: holeDiameter,
|
|
14193
14193
|
outer_diameter: padDiameter,
|
|
14194
14194
|
layers: [
|
|
14195
|
-
|
|
14196
|
-
|
|
14195
|
+
point2.from_layer,
|
|
14196
|
+
point2.to_layer
|
|
14197
14197
|
],
|
|
14198
|
-
from_layer:
|
|
14199
|
-
to_layer:
|
|
14198
|
+
from_layer: point2.from_layer,
|
|
14199
|
+
to_layer: point2.to_layer
|
|
14200
14200
|
});
|
|
14201
14201
|
}
|
|
14202
14202
|
}
|
|
@@ -15635,9 +15635,9 @@ var Board = class extends Group6 {
|
|
|
15635
15635
|
center
|
|
15636
15636
|
};
|
|
15637
15637
|
if (outline) {
|
|
15638
|
-
update.outline = outline.map((
|
|
15639
|
-
x:
|
|
15640
|
-
y:
|
|
15638
|
+
update.outline = outline.map((point2) => ({
|
|
15639
|
+
x: point2.x + (props.outlineOffsetX ?? 0),
|
|
15640
|
+
y: point2.y + (props.outlineOffsetY ?? 0)
|
|
15641
15641
|
}));
|
|
15642
15642
|
}
|
|
15643
15643
|
db.pcb_board.update(this.pcb_board_id, update);
|
|
@@ -15716,8 +15716,8 @@ var Board = class extends Group6 {
|
|
|
15716
15716
|
});
|
|
15717
15717
|
}
|
|
15718
15718
|
if (props.outline) {
|
|
15719
|
-
const xValues = props.outline.map((
|
|
15720
|
-
const yValues = props.outline.map((
|
|
15719
|
+
const xValues = props.outline.map((point2) => point2.x);
|
|
15720
|
+
const yValues = props.outline.map((point2) => point2.y);
|
|
15721
15721
|
const minX = Math.min(...xValues);
|
|
15722
15722
|
const maxX = Math.max(...xValues);
|
|
15723
15723
|
const minY = Math.min(...yValues);
|
|
@@ -15743,9 +15743,9 @@ var Board = class extends Group6 {
|
|
|
15743
15743
|
num_layers: this.allLayers.length,
|
|
15744
15744
|
width: computedWidth,
|
|
15745
15745
|
height: computedHeight,
|
|
15746
|
-
outline: outline?.map((
|
|
15747
|
-
x:
|
|
15748
|
-
y:
|
|
15746
|
+
outline: outline?.map((point2) => ({
|
|
15747
|
+
x: point2.x + (props.outlineOffsetX ?? 0),
|
|
15748
|
+
y: point2.y + (props.outlineOffsetY ?? 0)
|
|
15749
15749
|
})),
|
|
15750
15750
|
material: props.material
|
|
15751
15751
|
});
|
|
@@ -15821,6 +15821,7 @@ import { panelProps } from "@tscircuit/props";
|
|
|
15821
15821
|
import { distance as distance9 } from "circuit-json";
|
|
15822
15822
|
|
|
15823
15823
|
// lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
|
|
15824
|
+
import * as Flatten from "@flatten-js/core";
|
|
15824
15825
|
var DEFAULT_PANEL_MARGIN = 5;
|
|
15825
15826
|
var DEFAULT_TAB_LENGTH = 5;
|
|
15826
15827
|
var DEFAULT_TAB_WIDTH = 2;
|
|
@@ -15835,15 +15836,15 @@ function rectanglesOverlap(rect1, rect2) {
|
|
|
15835
15836
|
const r2Top = rect2.center.y + rect2.height / 2;
|
|
15836
15837
|
return !(r1Right <= r2Left || r1Left >= r2Right || r1Top <= r2Bottom || r1Bottom >= r2Top);
|
|
15837
15838
|
}
|
|
15838
|
-
function pointOverlapsRectangle(
|
|
15839
|
+
function pointOverlapsRectangle(point2, radius, rect) {
|
|
15839
15840
|
const rectLeft = rect.center.x - rect.width / 2;
|
|
15840
15841
|
const rectRight = rect.center.x + rect.width / 2;
|
|
15841
15842
|
const rectBottom = rect.center.y - rect.height / 2;
|
|
15842
15843
|
const rectTop = rect.center.y + rect.height / 2;
|
|
15843
|
-
const closestX = Math.max(rectLeft, Math.min(
|
|
15844
|
-
const closestY = Math.max(rectBottom, Math.min(
|
|
15845
|
-
const distanceX =
|
|
15846
|
-
const distanceY =
|
|
15844
|
+
const closestX = Math.max(rectLeft, Math.min(point2.x, rectRight));
|
|
15845
|
+
const closestY = Math.max(rectBottom, Math.min(point2.y, rectTop));
|
|
15846
|
+
const distanceX = point2.x - closestX;
|
|
15847
|
+
const distanceY = point2.y - closestY;
|
|
15847
15848
|
return distanceX * distanceX + distanceY * distanceY <= radius * radius;
|
|
15848
15849
|
}
|
|
15849
15850
|
function generateTabsForEdge({
|
|
@@ -16019,44 +16020,199 @@ function generateMouseBitesForEdge({
|
|
|
16019
16020
|
}
|
|
16020
16021
|
return mouseBites;
|
|
16021
16022
|
}
|
|
16023
|
+
var generatePanelTabsAndMouseBitesForOutlines = (outline, otherBoards, options) => {
|
|
16024
|
+
const {
|
|
16025
|
+
boardGap,
|
|
16026
|
+
tabLength,
|
|
16027
|
+
// along edge
|
|
16028
|
+
tabWidth,
|
|
16029
|
+
// extrusion
|
|
16030
|
+
mouseBites,
|
|
16031
|
+
mouseBiteHoleDiameter,
|
|
16032
|
+
mouseBiteHoleSpacing
|
|
16033
|
+
} = options;
|
|
16034
|
+
const tabCutouts = [];
|
|
16035
|
+
const mouseBiteHoles = [];
|
|
16036
|
+
if (outline.length < 2) {
|
|
16037
|
+
return { tabCutouts, mouseBiteHoles };
|
|
16038
|
+
}
|
|
16039
|
+
const outlinePolygon = new Flatten.Polygon(
|
|
16040
|
+
outline.map((p) => Flatten.point(p.x, p.y))
|
|
16041
|
+
);
|
|
16042
|
+
const otherBoardGeometries = otherBoards.map(
|
|
16043
|
+
(b) => b.outline ? new Flatten.Polygon(b.outline.map((p) => Flatten.point(p.x, p.y))) : b.width && b.height ? new Flatten.Box(
|
|
16044
|
+
b.center.x - b.width / 2,
|
|
16045
|
+
b.center.y - b.height / 2,
|
|
16046
|
+
b.center.x + b.width / 2,
|
|
16047
|
+
b.center.y + b.height / 2
|
|
16048
|
+
) : null
|
|
16049
|
+
);
|
|
16050
|
+
for (let i = 0; i < outline.length; i++) {
|
|
16051
|
+
const p1 = outline[i];
|
|
16052
|
+
const p2 = outline[(i + 1) % outline.length];
|
|
16053
|
+
const segmentVector = Flatten.vector(p2.x - p1.x, p2.y - p1.y);
|
|
16054
|
+
const segmentLength = segmentVector.length;
|
|
16055
|
+
const physicalTabLength = boardGap;
|
|
16056
|
+
const cutoutLength = tabLength;
|
|
16057
|
+
if (segmentLength < physicalTabLength) continue;
|
|
16058
|
+
const segmentDirVec = segmentVector.normalize();
|
|
16059
|
+
const isHorizontal = Math.abs(segmentVector.y) < 1e-9;
|
|
16060
|
+
const isVertical = Math.abs(segmentVector.x) < 1e-9;
|
|
16061
|
+
const isAxisAligned = isHorizontal || isVertical;
|
|
16062
|
+
let normalVec = segmentDirVec.rotate(Math.PI / 2);
|
|
16063
|
+
const midPoint = Flatten.point(p1.x, p1.y).translate(
|
|
16064
|
+
segmentDirVec.multiply(segmentLength / 2)
|
|
16065
|
+
);
|
|
16066
|
+
const testPointInward = midPoint.translate(normalVec.multiply(0.01));
|
|
16067
|
+
if (outlinePolygon.contains(testPointInward)) {
|
|
16068
|
+
normalVec = normalVec.multiply(-1);
|
|
16069
|
+
}
|
|
16070
|
+
const testPointOutward = midPoint.translate(
|
|
16071
|
+
normalVec.multiply((tabWidth + physicalTabLength) / 2)
|
|
16072
|
+
);
|
|
16073
|
+
let isExterior = true;
|
|
16074
|
+
for (const geom of otherBoardGeometries) {
|
|
16075
|
+
if (geom?.contains(testPointOutward)) {
|
|
16076
|
+
isExterior = false;
|
|
16077
|
+
break;
|
|
16078
|
+
}
|
|
16079
|
+
}
|
|
16080
|
+
if (!isExterior) continue;
|
|
16081
|
+
const numTabs = Math.max(
|
|
16082
|
+
1,
|
|
16083
|
+
Math.floor(segmentLength / (physicalTabLength + cutoutLength))
|
|
16084
|
+
);
|
|
16085
|
+
const totalContentLength = numTabs * physicalTabLength;
|
|
16086
|
+
const totalGapLength = segmentLength - totalContentLength;
|
|
16087
|
+
const gapSize = totalGapLength / (numTabs + 1);
|
|
16088
|
+
if (gapSize < 0) continue;
|
|
16089
|
+
const tabsOnSegment = [];
|
|
16090
|
+
for (let j = 0; j < numTabs; j++) {
|
|
16091
|
+
const tabStartDist = gapSize * (j + 1) + physicalTabLength * j;
|
|
16092
|
+
tabsOnSegment.push({
|
|
16093
|
+
start: tabStartDist,
|
|
16094
|
+
end: tabStartDist + physicalTabLength
|
|
16095
|
+
});
|
|
16096
|
+
}
|
|
16097
|
+
const extrusion = normalVec.multiply(tabWidth);
|
|
16098
|
+
for (let j = 0; j <= numTabs; j++) {
|
|
16099
|
+
const gapStartDist = j === 0 ? 0 : tabsOnSegment[j - 1].end;
|
|
16100
|
+
const gapEndDist = j === numTabs ? segmentLength : tabsOnSegment[j].start;
|
|
16101
|
+
const gapLength = gapEndDist - gapStartDist;
|
|
16102
|
+
if (gapLength < 1e-6) continue;
|
|
16103
|
+
if (isAxisAligned) {
|
|
16104
|
+
const width = isHorizontal ? gapLength : tabWidth;
|
|
16105
|
+
const height = isHorizontal ? tabWidth : gapLength;
|
|
16106
|
+
const gapCenterAlongSegment = Flatten.point(p1.x, p1.y).translate(
|
|
16107
|
+
segmentDirVec.multiply(gapStartDist + gapLength / 2)
|
|
16108
|
+
);
|
|
16109
|
+
const center = gapCenterAlongSegment.translate(extrusion.multiply(0.5));
|
|
16110
|
+
tabCutouts.push({
|
|
16111
|
+
type: "pcb_cutout",
|
|
16112
|
+
shape: "rect",
|
|
16113
|
+
center,
|
|
16114
|
+
width,
|
|
16115
|
+
height,
|
|
16116
|
+
corner_radius: Math.min(width, height) / 2
|
|
16117
|
+
});
|
|
16118
|
+
} else {
|
|
16119
|
+
const width = gapLength;
|
|
16120
|
+
const height = tabWidth;
|
|
16121
|
+
const gapCenterAlongSegment = Flatten.point(p1.x, p1.y).translate(
|
|
16122
|
+
segmentDirVec.multiply(gapStartDist + gapLength / 2)
|
|
16123
|
+
);
|
|
16124
|
+
const center = gapCenterAlongSegment.translate(extrusion.multiply(0.5));
|
|
16125
|
+
const rotationDeg = segmentDirVec.slope * 180 / Math.PI;
|
|
16126
|
+
tabCutouts.push({
|
|
16127
|
+
type: "pcb_cutout",
|
|
16128
|
+
shape: "rect",
|
|
16129
|
+
center,
|
|
16130
|
+
width,
|
|
16131
|
+
height,
|
|
16132
|
+
rotation: rotationDeg,
|
|
16133
|
+
corner_radius: Math.min(width, height) / 2
|
|
16134
|
+
});
|
|
16135
|
+
}
|
|
16136
|
+
}
|
|
16137
|
+
if (mouseBites) {
|
|
16138
|
+
const holeSpacing = mouseBiteHoleDiameter + mouseBiteHoleSpacing;
|
|
16139
|
+
for (const tab of tabsOnSegment) {
|
|
16140
|
+
const tabLength2 = tab.end - tab.start;
|
|
16141
|
+
if (tabLength2 < holeSpacing) continue;
|
|
16142
|
+
const numBitesInTab = Math.floor(tabLength2 / holeSpacing);
|
|
16143
|
+
if (numBitesInTab <= 0) continue;
|
|
16144
|
+
const biteStartOffset = tab.start + (tabLength2 - (numBitesInTab - 1) * holeSpacing) / 2;
|
|
16145
|
+
for (let k = 0; k < numBitesInTab; k++) {
|
|
16146
|
+
const biteDist = biteStartOffset + k * holeSpacing;
|
|
16147
|
+
const pos = Flatten.point(p1.x, p1.y).translate(
|
|
16148
|
+
segmentDirVec.multiply(biteDist)
|
|
16149
|
+
);
|
|
16150
|
+
mouseBiteHoles.push({
|
|
16151
|
+
x: pos.x,
|
|
16152
|
+
y: pos.y
|
|
16153
|
+
});
|
|
16154
|
+
}
|
|
16155
|
+
}
|
|
16156
|
+
}
|
|
16157
|
+
}
|
|
16158
|
+
return { tabCutouts, mouseBiteHoles };
|
|
16159
|
+
};
|
|
16022
16160
|
function generatePanelTabsAndMouseBites(boards, options) {
|
|
16023
|
-
const
|
|
16161
|
+
const finalTabCutouts = [];
|
|
16024
16162
|
const allMouseBites = [];
|
|
16025
16163
|
for (let boardIndex = 0; boardIndex < boards.length; boardIndex++) {
|
|
16026
16164
|
const board = boards[boardIndex];
|
|
16027
16165
|
const otherBoards = boards.filter((_, i) => i !== boardIndex);
|
|
16028
|
-
|
|
16029
|
-
const
|
|
16030
|
-
|
|
16031
|
-
|
|
16166
|
+
if (board.outline && board.outline.length > 0) {
|
|
16167
|
+
const mouseBiteDiameter2 = options.tabWidth * 0.45;
|
|
16168
|
+
const mouseBiteSpacing = mouseBiteDiameter2 * 0.1;
|
|
16169
|
+
const generated = generatePanelTabsAndMouseBitesForOutlines(
|
|
16170
|
+
board.outline,
|
|
16032
16171
|
otherBoards,
|
|
16033
|
-
|
|
16034
|
-
|
|
16035
|
-
|
|
16036
|
-
|
|
16037
|
-
|
|
16172
|
+
{
|
|
16173
|
+
...options,
|
|
16174
|
+
mouseBiteHoleDiameter: mouseBiteDiameter2,
|
|
16175
|
+
mouseBiteHoleSpacing: mouseBiteSpacing
|
|
16176
|
+
}
|
|
16177
|
+
);
|
|
16178
|
+
finalTabCutouts.push(...generated.tabCutouts);
|
|
16179
|
+
allMouseBites.push(...generated.mouseBiteHoles);
|
|
16180
|
+
} else {
|
|
16181
|
+
for (const edge of ["top", "bottom", "left", "right"]) {
|
|
16182
|
+
const edgeTabs = generateTabsForEdge({
|
|
16038
16183
|
board,
|
|
16039
16184
|
edge,
|
|
16040
|
-
|
|
16041
|
-
allBoards: otherBoards,
|
|
16185
|
+
otherBoards,
|
|
16042
16186
|
options
|
|
16043
16187
|
});
|
|
16044
|
-
|
|
16188
|
+
for (const tab of edgeTabs) {
|
|
16189
|
+
const tabWidthDimension = Math.min(tab.width, tab.height);
|
|
16190
|
+
finalTabCutouts.push({
|
|
16191
|
+
type: "pcb_cutout",
|
|
16192
|
+
shape: "rect",
|
|
16193
|
+
center: tab.center,
|
|
16194
|
+
width: tab.width,
|
|
16195
|
+
height: tab.height,
|
|
16196
|
+
corner_radius: tabWidthDimension / 2
|
|
16197
|
+
});
|
|
16198
|
+
}
|
|
16199
|
+
if (options.mouseBites) {
|
|
16200
|
+
const edgeMouseBites = generateMouseBitesForEdge({
|
|
16201
|
+
board,
|
|
16202
|
+
edge,
|
|
16203
|
+
edgeTabs,
|
|
16204
|
+
allBoards: otherBoards,
|
|
16205
|
+
options
|
|
16206
|
+
});
|
|
16207
|
+
allMouseBites.push(...edgeMouseBites);
|
|
16208
|
+
}
|
|
16045
16209
|
}
|
|
16046
16210
|
}
|
|
16047
16211
|
}
|
|
16048
|
-
const tabCutouts =
|
|
16049
|
-
|
|
16050
|
-
|
|
16051
|
-
|
|
16052
|
-
pcb_cutout_id: `panel_tab_${index}`,
|
|
16053
|
-
shape: "rect",
|
|
16054
|
-
center: tab.center,
|
|
16055
|
-
width: tab.width,
|
|
16056
|
-
height: tab.height,
|
|
16057
|
-
corner_radius: tabWidthDimension / 2
|
|
16058
|
-
};
|
|
16059
|
-
});
|
|
16212
|
+
const tabCutouts = finalTabCutouts.map((tab, index) => ({
|
|
16213
|
+
...tab,
|
|
16214
|
+
pcb_cutout_id: `panel_tab_${index}`
|
|
16215
|
+
}));
|
|
16060
16216
|
const mouseBiteDiameter = options.tabWidth * 0.45;
|
|
16061
16217
|
const mouseBiteHoles = allMouseBites.map((bite, index) => ({
|
|
16062
16218
|
type: "pcb_hole",
|
|
@@ -17211,8 +17367,8 @@ var PcbNotePath = class extends PrimitiveComponent2 {
|
|
|
17211
17367
|
const subcircuit = this.getSubcircuit();
|
|
17212
17368
|
const group = this.getGroup();
|
|
17213
17369
|
const pcb_component_id = this.parent?.pcb_component_id ?? this.getPrimitiveContainer()?.pcb_component_id ?? void 0;
|
|
17214
|
-
const transformedRoute = props.route.map((
|
|
17215
|
-
const { x, y, ...rest } =
|
|
17370
|
+
const transformedRoute = props.route.map((point2) => {
|
|
17371
|
+
const { x, y, ...rest } = point2;
|
|
17216
17372
|
const numericX = typeof x === "string" ? parseFloat(x) : x;
|
|
17217
17373
|
const numericY = typeof y === "string" ? parseFloat(y) : y;
|
|
17218
17374
|
const transformed = applyToPoint15(transform, { x: numericX, y: numericY });
|
|
@@ -17232,10 +17388,10 @@ var PcbNotePath = class extends PrimitiveComponent2 {
|
|
|
17232
17388
|
const { _parsedProps: props } = this;
|
|
17233
17389
|
if (props.route.length === 0) return { width: 0, height: 0 };
|
|
17234
17390
|
const xs = props.route.map(
|
|
17235
|
-
(
|
|
17391
|
+
(point2) => typeof point2.x === "string" ? parseFloat(point2.x) : point2.x
|
|
17236
17392
|
);
|
|
17237
17393
|
const ys = props.route.map(
|
|
17238
|
-
(
|
|
17394
|
+
(point2) => typeof point2.y === "string" ? parseFloat(point2.y) : point2.y
|
|
17239
17395
|
);
|
|
17240
17396
|
const minX = Math.min(...xs);
|
|
17241
17397
|
const maxX = Math.max(...xs);
|
|
@@ -19261,7 +19417,7 @@ import { identity as identity5 } from "transformation-matrix";
|
|
|
19261
19417
|
var package_default = {
|
|
19262
19418
|
name: "@tscircuit/core",
|
|
19263
19419
|
type: "module",
|
|
19264
|
-
version: "0.0.
|
|
19420
|
+
version: "0.0.905",
|
|
19265
19421
|
types: "dist/index.d.ts",
|
|
19266
19422
|
main: "dist/index.js",
|
|
19267
19423
|
module: "dist/index.js",
|