@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 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.259",
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.265",
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",