@tscircuit/pcb-viewer 1.11.260 → 1.11.262
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 +235 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7573,6 +7573,88 @@ var convertElementToPrimitives = (element, allElements) => {
|
|
|
7573
7573
|
ccw_rotation: hole_ccw_rotation
|
|
7574
7574
|
}
|
|
7575
7575
|
];
|
|
7576
|
+
} else if (element.shape === "hole_with_polygon_pad") {
|
|
7577
|
+
const {
|
|
7578
|
+
x,
|
|
7579
|
+
y,
|
|
7580
|
+
pad_outline,
|
|
7581
|
+
hole_shape,
|
|
7582
|
+
hole_diameter,
|
|
7583
|
+
hole_width,
|
|
7584
|
+
hole_height,
|
|
7585
|
+
layers
|
|
7586
|
+
} = element;
|
|
7587
|
+
const hole_offset_x = distance2.parse(
|
|
7588
|
+
element.hole_offset_x ?? 0
|
|
7589
|
+
);
|
|
7590
|
+
const hole_offset_y = distance2.parse(
|
|
7591
|
+
element.hole_offset_y ?? 0
|
|
7592
|
+
);
|
|
7593
|
+
const pcb_outline = pad_outline;
|
|
7594
|
+
const padPrimitives = [];
|
|
7595
|
+
if (pcb_outline && Array.isArray(pcb_outline)) {
|
|
7596
|
+
const translatedPoints = normalizePolygonPoints(pcb_outline).map(
|
|
7597
|
+
(p) => ({ x: p.x + x, y: p.y + y })
|
|
7598
|
+
);
|
|
7599
|
+
for (const layer of layers || ["top", "bottom"]) {
|
|
7600
|
+
padPrimitives.push({
|
|
7601
|
+
_pcb_drawing_object_id: `polygon_${globalPcbDrawingObjectCount++}`,
|
|
7602
|
+
pcb_drawing_type: "polygon",
|
|
7603
|
+
points: translatedPoints,
|
|
7604
|
+
layer,
|
|
7605
|
+
_element: element,
|
|
7606
|
+
_parent_pcb_component,
|
|
7607
|
+
_parent_source_component,
|
|
7608
|
+
_source_port
|
|
7609
|
+
});
|
|
7610
|
+
}
|
|
7611
|
+
}
|
|
7612
|
+
const holeCenter = {
|
|
7613
|
+
x: x + hole_offset_x,
|
|
7614
|
+
y: y + hole_offset_y
|
|
7615
|
+
};
|
|
7616
|
+
const holePrimitives = [];
|
|
7617
|
+
if (hole_shape === "circle") {
|
|
7618
|
+
holePrimitives.push({
|
|
7619
|
+
_pcb_drawing_object_id: `circle_${globalPcbDrawingObjectCount++}`,
|
|
7620
|
+
pcb_drawing_type: "circle",
|
|
7621
|
+
x: holeCenter.x,
|
|
7622
|
+
y: holeCenter.y,
|
|
7623
|
+
r: (hole_diameter ?? 0) / 2,
|
|
7624
|
+
layer: "drill",
|
|
7625
|
+
_element: element,
|
|
7626
|
+
_parent_pcb_component,
|
|
7627
|
+
_parent_source_component
|
|
7628
|
+
});
|
|
7629
|
+
} else if (hole_shape === "oval") {
|
|
7630
|
+
holePrimitives.push({
|
|
7631
|
+
_pcb_drawing_object_id: `oval_${globalPcbDrawingObjectCount++}`,
|
|
7632
|
+
pcb_drawing_type: "oval",
|
|
7633
|
+
x: holeCenter.x,
|
|
7634
|
+
y: holeCenter.y,
|
|
7635
|
+
rX: (hole_width ?? 0) / 2,
|
|
7636
|
+
rY: (hole_height ?? 0) / 2,
|
|
7637
|
+
layer: "drill",
|
|
7638
|
+
_element: element,
|
|
7639
|
+
_parent_pcb_component,
|
|
7640
|
+
_parent_source_component
|
|
7641
|
+
});
|
|
7642
|
+
} else if (hole_shape === "pill" || hole_shape === "rotated_pill") {
|
|
7643
|
+
holePrimitives.push({
|
|
7644
|
+
_pcb_drawing_object_id: `pill_${globalPcbDrawingObjectCount++}`,
|
|
7645
|
+
pcb_drawing_type: "pill",
|
|
7646
|
+
x: holeCenter.x,
|
|
7647
|
+
y: holeCenter.y,
|
|
7648
|
+
w: hole_width ?? 0,
|
|
7649
|
+
h: hole_height ?? 0,
|
|
7650
|
+
layer: "drill",
|
|
7651
|
+
_element: element,
|
|
7652
|
+
_parent_pcb_component,
|
|
7653
|
+
_parent_source_component,
|
|
7654
|
+
ccw_rotation: element.ccw_rotation
|
|
7655
|
+
});
|
|
7656
|
+
}
|
|
7657
|
+
return [...padPrimitives, ...holePrimitives];
|
|
7576
7658
|
} else {
|
|
7577
7659
|
return [];
|
|
7578
7660
|
}
|
|
@@ -10150,6 +10232,133 @@ function useDiagonalLabel(params) {
|
|
|
10150
10232
|
);
|
|
10151
10233
|
}
|
|
10152
10234
|
|
|
10235
|
+
// src/lib/util/get-primitive-snap-points.ts
|
|
10236
|
+
var rotatePoint2 = (point, center, rotationDeg) => {
|
|
10237
|
+
const radians = rotationDeg * Math.PI / 180;
|
|
10238
|
+
const cos = Math.cos(radians);
|
|
10239
|
+
const sin = Math.sin(radians);
|
|
10240
|
+
const translatedX = point.x - center.x;
|
|
10241
|
+
const translatedY = point.y - center.y;
|
|
10242
|
+
const rotatedX = translatedX * cos - translatedY * sin;
|
|
10243
|
+
const rotatedY = translatedX * sin + translatedY * cos;
|
|
10244
|
+
return {
|
|
10245
|
+
x: rotatedX + center.x,
|
|
10246
|
+
y: rotatedY + center.y
|
|
10247
|
+
};
|
|
10248
|
+
};
|
|
10249
|
+
var getNinePointAnchors = (center, halfWidth, halfHeight, rotationDeg) => {
|
|
10250
|
+
const basePoints = {
|
|
10251
|
+
top_left: { x: center.x - halfWidth, y: center.y - halfHeight },
|
|
10252
|
+
top_center: { x: center.x, y: center.y - halfHeight },
|
|
10253
|
+
top_right: { x: center.x + halfWidth, y: center.y - halfHeight },
|
|
10254
|
+
center_left: { x: center.x - halfWidth, y: center.y },
|
|
10255
|
+
center: { x: center.x, y: center.y },
|
|
10256
|
+
center_right: { x: center.x + halfWidth, y: center.y },
|
|
10257
|
+
bottom_left: { x: center.x - halfWidth, y: center.y + halfHeight },
|
|
10258
|
+
bottom_center: { x: center.x, y: center.y + halfHeight },
|
|
10259
|
+
bottom_right: { x: center.x + halfWidth, y: center.y + halfHeight }
|
|
10260
|
+
};
|
|
10261
|
+
if (rotationDeg === 0) {
|
|
10262
|
+
return Object.entries(basePoints).map(([anchor, point]) => ({
|
|
10263
|
+
anchor,
|
|
10264
|
+
point
|
|
10265
|
+
}));
|
|
10266
|
+
}
|
|
10267
|
+
return Object.entries(basePoints).map(([anchor, point]) => ({
|
|
10268
|
+
anchor,
|
|
10269
|
+
point: rotatePoint2(point, center, rotationDeg)
|
|
10270
|
+
}));
|
|
10271
|
+
};
|
|
10272
|
+
var getPrimitiveSnapPoints = (primitive) => {
|
|
10273
|
+
switch (primitive.pcb_drawing_type) {
|
|
10274
|
+
case "rect": {
|
|
10275
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
10276
|
+
return getNinePointAnchors(
|
|
10277
|
+
{ x: primitive.x, y: primitive.y },
|
|
10278
|
+
primitive.w / 2,
|
|
10279
|
+
primitive.h / 2,
|
|
10280
|
+
rotation
|
|
10281
|
+
);
|
|
10282
|
+
}
|
|
10283
|
+
case "pill": {
|
|
10284
|
+
const rotation = primitive.ccw_rotation ?? 0;
|
|
10285
|
+
return getNinePointAnchors(
|
|
10286
|
+
{ x: primitive.x, y: primitive.y },
|
|
10287
|
+
primitive.w / 2,
|
|
10288
|
+
primitive.h / 2,
|
|
10289
|
+
rotation
|
|
10290
|
+
);
|
|
10291
|
+
}
|
|
10292
|
+
case "circle": {
|
|
10293
|
+
return [
|
|
10294
|
+
{ anchor: "circle_center", point: { x: primitive.x, y: primitive.y } },
|
|
10295
|
+
{
|
|
10296
|
+
anchor: "circle_right",
|
|
10297
|
+
point: { x: primitive.x + primitive.r, y: primitive.y }
|
|
10298
|
+
},
|
|
10299
|
+
{
|
|
10300
|
+
anchor: "circle_left",
|
|
10301
|
+
point: { x: primitive.x - primitive.r, y: primitive.y }
|
|
10302
|
+
},
|
|
10303
|
+
{
|
|
10304
|
+
anchor: "circle_top",
|
|
10305
|
+
point: { x: primitive.x, y: primitive.y - primitive.r }
|
|
10306
|
+
},
|
|
10307
|
+
{
|
|
10308
|
+
anchor: "circle_bottom",
|
|
10309
|
+
point: { x: primitive.x, y: primitive.y + primitive.r }
|
|
10310
|
+
}
|
|
10311
|
+
];
|
|
10312
|
+
}
|
|
10313
|
+
case "oval": {
|
|
10314
|
+
return [
|
|
10315
|
+
{ anchor: "oval_center", point: { x: primitive.x, y: primitive.y } },
|
|
10316
|
+
{
|
|
10317
|
+
anchor: "oval_right",
|
|
10318
|
+
point: { x: primitive.x + primitive.rX, y: primitive.y }
|
|
10319
|
+
},
|
|
10320
|
+
{
|
|
10321
|
+
anchor: "oval_left",
|
|
10322
|
+
point: { x: primitive.x - primitive.rX, y: primitive.y }
|
|
10323
|
+
},
|
|
10324
|
+
{
|
|
10325
|
+
anchor: "oval_top",
|
|
10326
|
+
point: { x: primitive.x, y: primitive.y - primitive.rY }
|
|
10327
|
+
},
|
|
10328
|
+
{
|
|
10329
|
+
anchor: "oval_bottom",
|
|
10330
|
+
point: { x: primitive.x, y: primitive.y + primitive.rY }
|
|
10331
|
+
}
|
|
10332
|
+
];
|
|
10333
|
+
}
|
|
10334
|
+
case "line": {
|
|
10335
|
+
const midPoint = {
|
|
10336
|
+
x: (primitive.x1 + primitive.x2) / 2,
|
|
10337
|
+
y: (primitive.y1 + primitive.y2) / 2
|
|
10338
|
+
};
|
|
10339
|
+
return [
|
|
10340
|
+
{ anchor: "line_start", point: { x: primitive.x1, y: primitive.y1 } },
|
|
10341
|
+
{ anchor: "line_mid", point: midPoint },
|
|
10342
|
+
{ anchor: "line_end", point: { x: primitive.x2, y: primitive.y2 } }
|
|
10343
|
+
];
|
|
10344
|
+
}
|
|
10345
|
+
case "polygon": {
|
|
10346
|
+
return primitive.points.map((point, index) => ({
|
|
10347
|
+
anchor: `polygon_vertex_${index}`,
|
|
10348
|
+
point
|
|
10349
|
+
}));
|
|
10350
|
+
}
|
|
10351
|
+
case "polygon_with_arcs": {
|
|
10352
|
+
return primitive.brep_shape.outer_ring.vertices.map((vertex, index) => ({
|
|
10353
|
+
anchor: `polygon_with_arcs_vertex_${index}`,
|
|
10354
|
+
point: { x: vertex.x, y: vertex.y }
|
|
10355
|
+
}));
|
|
10356
|
+
}
|
|
10357
|
+
default:
|
|
10358
|
+
return [];
|
|
10359
|
+
}
|
|
10360
|
+
};
|
|
10361
|
+
|
|
10153
10362
|
// src/components/DimensionOverlay.tsx
|
|
10154
10363
|
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
10155
10364
|
var SNAP_THRESHOLD_PX = 16;
|
|
@@ -10201,6 +10410,9 @@ var DimensionOverlay = ({
|
|
|
10201
10410
|
for (const primitive of primitives) {
|
|
10202
10411
|
if (!primitive._element) continue;
|
|
10203
10412
|
if (shouldExcludePrimitiveFromSnapping(primitive)) continue;
|
|
10413
|
+
if (primitive.pcb_drawing_type === "pill") continue;
|
|
10414
|
+
if (primitive.pcb_drawing_type === "rect" && primitive.ccw_rotation && primitive.ccw_rotation !== 0)
|
|
10415
|
+
continue;
|
|
10204
10416
|
const bbox = getPrimitiveBoundingBox(primitive);
|
|
10205
10417
|
if (!bbox) continue;
|
|
10206
10418
|
const existing = boundingBoxes.get(primitive._element);
|
|
@@ -10211,6 +10423,23 @@ var DimensionOverlay = ({
|
|
|
10211
10423
|
}
|
|
10212
10424
|
return boundingBoxes;
|
|
10213
10425
|
}, [primitives]);
|
|
10426
|
+
const primitiveSnappingPoints = useMemo4(() => {
|
|
10427
|
+
const snapPoints = [];
|
|
10428
|
+
for (const primitive of primitives) {
|
|
10429
|
+
if (!primitive._element) continue;
|
|
10430
|
+
if (shouldExcludePrimitiveFromSnapping(primitive)) continue;
|
|
10431
|
+
const primitivePoints = getPrimitiveSnapPoints(primitive);
|
|
10432
|
+
if (primitivePoints.length === 0) continue;
|
|
10433
|
+
for (const snap of primitivePoints) {
|
|
10434
|
+
snapPoints.push({
|
|
10435
|
+
anchor: snap.anchor,
|
|
10436
|
+
point: snap.point,
|
|
10437
|
+
element: primitive._element
|
|
10438
|
+
});
|
|
10439
|
+
}
|
|
10440
|
+
}
|
|
10441
|
+
return snapPoints;
|
|
10442
|
+
}, [primitives]);
|
|
10214
10443
|
const snappingPoints = useMemo4(() => {
|
|
10215
10444
|
const points = [];
|
|
10216
10445
|
elementBoundingBoxes.forEach((bounds, element) => {
|
|
@@ -10236,13 +10465,16 @@ var DimensionOverlay = ({
|
|
|
10236
10465
|
});
|
|
10237
10466
|
}
|
|
10238
10467
|
});
|
|
10468
|
+
for (const snap of primitiveSnappingPoints) {
|
|
10469
|
+
points.push(snap);
|
|
10470
|
+
}
|
|
10239
10471
|
points.push({
|
|
10240
10472
|
anchor: "origin",
|
|
10241
10473
|
point: { x: 0, y: 0 },
|
|
10242
10474
|
element: null
|
|
10243
10475
|
});
|
|
10244
10476
|
return points;
|
|
10245
|
-
}, [elementBoundingBoxes]);
|
|
10477
|
+
}, [elementBoundingBoxes, primitiveSnappingPoints]);
|
|
10246
10478
|
const snappingPointsWithScreen = useMemo4(() => {
|
|
10247
10479
|
return snappingPoints.map((snap, index) => ({
|
|
10248
10480
|
...snap,
|
|
@@ -12587,7 +12819,7 @@ import { css as css3 } from "@emotion/css";
|
|
|
12587
12819
|
// package.json
|
|
12588
12820
|
var package_default = {
|
|
12589
12821
|
name: "@tscircuit/pcb-viewer",
|
|
12590
|
-
version: "1.11.
|
|
12822
|
+
version: "1.11.261",
|
|
12591
12823
|
main: "dist/index.js",
|
|
12592
12824
|
type: "module",
|
|
12593
12825
|
repository: "tscircuit/pcb-viewer",
|
|
@@ -12640,7 +12872,7 @@ var package_default = {
|
|
|
12640
12872
|
"@tscircuit/alphabet": "^0.0.3",
|
|
12641
12873
|
"@vitejs/plugin-react": "^5.0.2",
|
|
12642
12874
|
"circuit-json": "^0.0.307",
|
|
12643
|
-
"circuit-to-svg": "^0.0.
|
|
12875
|
+
"circuit-to-svg": "^0.0.271",
|
|
12644
12876
|
color: "^4.2.3",
|
|
12645
12877
|
"react-supergrid": "^1.0.10",
|
|
12646
12878
|
"react-toastify": "^10.0.5",
|