circuit-to-svg 0.0.283 → 0.0.284

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
@@ -3508,180 +3508,503 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3508
3508
  }
3509
3509
 
3510
3510
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-board.ts
3511
+ import { applyToPoint as applyToPoint22 } from "transformation-matrix";
3512
+
3513
+ // lib/utils/create-pcb-component-anchor-offset-indicators.ts
3511
3514
  import { applyToPoint as applyToPoint21 } from "transformation-matrix";
3512
- function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3513
- const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3514
- const { width, height, center, outline } = pcbBoard;
3515
- let path;
3516
- if (outline && Array.isArray(outline) && outline.length >= 3) {
3517
- path = outline.map((point, index) => {
3518
- const [x, y] = applyToPoint21(transform, [point.x, point.y]);
3519
- return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
3520
- }).join(" ");
3521
- } else {
3522
- const halfWidth = width / 2;
3523
- const halfHeight = height / 2;
3524
- const topLeft = applyToPoint21(transform, [
3525
- center.x - halfWidth,
3526
- center.y - halfHeight
3527
- ]);
3528
- const topRight = applyToPoint21(transform, [
3529
- center.x + halfWidth,
3530
- center.y - halfHeight
3531
- ]);
3532
- const bottomRight = applyToPoint21(transform, [
3533
- center.x + halfWidth,
3534
- center.y + halfHeight
3535
- ]);
3536
- const bottomLeft = applyToPoint21(transform, [
3537
- center.x - halfWidth,
3538
- center.y + halfHeight
3539
- ]);
3540
- path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
3541
- }
3542
- path += " Z";
3543
- const svgObjects = [];
3544
- if (showSolderMask) {
3545
- const layer = ctx.layer ?? "top";
3546
- const maskLayer = layer === "bottom" ? "soldermask-bottom" : "soldermask-top";
3547
- svgObjects.push({
3548
- name: "path",
3549
- type: "element",
3550
- value: "",
3551
- children: [],
3552
- attributes: {
3553
- class: "pcb-board-soldermask",
3554
- d: path,
3555
- fill: colorMap2.soldermask.top,
3556
- "fill-opacity": "0.8",
3557
- stroke: "none",
3558
- "data-type": "pcb_soldermask",
3559
- "data-pcb-layer": maskLayer
3560
- }
3561
- });
3562
- }
3563
- svgObjects.push({
3564
- name: "path",
3515
+ var OFFSET_THRESHOLD_MM = 0.01;
3516
+ var TICK_SIZE_PX = 4;
3517
+ var LABEL_GAP_PX = 8;
3518
+ var LABEL_FONT_SIZE_PX = 11;
3519
+ var STROKE_WIDTH_PX = 1;
3520
+ var ANCHOR_MARKER_SIZE_PX = 5;
3521
+ var ANCHOR_MARKER_STROKE_WIDTH_PX = 1.5;
3522
+ var COMPONENT_GAP_PX = 15;
3523
+ var COMPONENT_SIDE_GAP_PX = 10;
3524
+ var DISTANCE_MULTIPLIER = 0.2;
3525
+ var MAX_OFFSET_PX = 50;
3526
+ function createAnchorOffsetIndicators(params) {
3527
+ const {
3528
+ groupAnchorPosition,
3529
+ componentPosition,
3530
+ transform,
3531
+ componentWidth = 0,
3532
+ componentHeight = 0
3533
+ } = params;
3534
+ const objects = [];
3535
+ const [screenGroupAnchorX, screenGroupAnchorY] = applyToPoint21(transform, [
3536
+ groupAnchorPosition.x,
3537
+ groupAnchorPosition.y
3538
+ ]);
3539
+ const [screenComponentX, screenComponentY] = applyToPoint21(transform, [
3540
+ componentPosition.x,
3541
+ componentPosition.y
3542
+ ]);
3543
+ const offsetX = componentPosition.x - groupAnchorPosition.x;
3544
+ const offsetY = componentPosition.y - groupAnchorPosition.y;
3545
+ const scale9 = Math.abs(transform.a);
3546
+ const screenComponentWidth = componentWidth * scale9;
3547
+ const screenComponentHeight = componentHeight * scale9;
3548
+ objects.push(createAnchorMarker(screenGroupAnchorX, screenGroupAnchorY));
3549
+ objects.push({
3550
+ name: "line",
3565
3551
  type: "element",
3566
- value: "",
3552
+ attributes: {
3553
+ x1: screenGroupAnchorX.toString(),
3554
+ y1: screenGroupAnchorY.toString(),
3555
+ x2: screenComponentX.toString(),
3556
+ y2: screenComponentY.toString(),
3557
+ stroke: "#ffffff",
3558
+ "stroke-width": "0.5",
3559
+ "stroke-dasharray": "3,3",
3560
+ opacity: "0.5",
3561
+ class: "anchor-offset-connector"
3562
+ },
3567
3563
  children: [],
3564
+ value: ""
3565
+ });
3566
+ objects.push({
3567
+ name: "circle",
3568
+ type: "element",
3568
3569
  attributes: {
3569
- class: "pcb-board",
3570
- d: path,
3571
- fill: "none",
3572
- stroke: colorMap2.boardOutline,
3573
- "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3574
- "data-type": "pcb_board",
3575
- "data-pcb-layer": "board"
3576
- }
3570
+ cx: screenComponentX.toString(),
3571
+ cy: screenComponentY.toString(),
3572
+ r: "2",
3573
+ fill: "#ffffff",
3574
+ opacity: "0.7",
3575
+ class: "anchor-offset-component-marker"
3576
+ },
3577
+ children: [],
3578
+ value: ""
3577
3579
  });
3578
- return svgObjects;
3579
- }
3580
-
3581
- // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-panel.ts
3582
- import { applyToPoint as applyToPoint22 } from "transformation-matrix";
3583
- function createSvgObjectsFromPcbPanel(pcbPanel, ctx) {
3584
- const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3585
- const width = Number(pcbPanel.width);
3586
- const height = Number(pcbPanel.height);
3587
- const center = pcbPanel.center ?? { x: width / 2, y: height / 2 };
3588
- const halfWidth = width / 2;
3589
- const halfHeight = height / 2;
3590
- const topLeft = applyToPoint22(transform, [
3591
- center.x - halfWidth,
3592
- center.y - halfHeight
3593
- ]);
3594
- const topRight = applyToPoint22(transform, [
3595
- center.x + halfWidth,
3596
- center.y - halfHeight
3597
- ]);
3598
- const bottomRight = applyToPoint22(transform, [
3599
- center.x + halfWidth,
3600
- center.y + halfHeight
3601
- ]);
3602
- const bottomLeft = applyToPoint22(transform, [
3603
- center.x - halfWidth,
3604
- center.y + halfHeight
3605
- ]);
3606
- const path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`;
3607
- const isCoveredWithSolderMask = pcbPanel.covered_with_solder_mask !== false;
3608
- const shouldShowSolderMask = Boolean(
3609
- showSolderMask && isCoveredWithSolderMask
3580
+ const yDistance = Math.abs(screenComponentY - screenGroupAnchorY);
3581
+ const xDistance = Math.abs(screenComponentX - screenGroupAnchorX);
3582
+ const totalDistance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
3583
+ const componentHeightOffset = screenComponentHeight / 2 + COMPONENT_GAP_PX;
3584
+ const dynamicOffset = Math.max(
3585
+ componentHeightOffset,
3586
+ Math.min(MAX_OFFSET_PX, totalDistance * DISTANCE_MULTIPLIER)
3610
3587
  );
3611
- return [
3612
- {
3613
- name: "path",
3614
- type: "element",
3615
- value: "",
3616
- children: [],
3617
- attributes: {
3618
- class: "pcb-panel",
3619
- d: path,
3620
- fill: "none",
3621
- stroke: colorMap2.boardOutline,
3622
- "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3623
- "data-type": "pcb_panel",
3624
- "data-pcb-layer": "board"
3625
- }
3626
- }
3627
- ];
3588
+ const horizontalLineY = offsetY > 0 ? screenComponentY - dynamicOffset : screenComponentY + dynamicOffset;
3589
+ const componentWidthOffset = screenComponentWidth / 2 + COMPONENT_SIDE_GAP_PX;
3590
+ const verticalLineX = offsetX > 0 ? screenComponentX + componentWidthOffset : screenComponentX - componentWidthOffset;
3591
+ if (Math.abs(offsetX) > OFFSET_THRESHOLD_MM) {
3592
+ objects.push(
3593
+ ...createHorizontalDimension({
3594
+ startX: screenGroupAnchorX,
3595
+ endX: screenComponentX,
3596
+ y: horizontalLineY,
3597
+ offsetMm: offsetX,
3598
+ offsetY
3599
+ })
3600
+ );
3601
+ }
3602
+ if (Math.abs(offsetY) > OFFSET_THRESHOLD_MM) {
3603
+ objects.push(
3604
+ ...createVerticalDimension({
3605
+ x: verticalLineX,
3606
+ startY: screenGroupAnchorY,
3607
+ endY: screenComponentY,
3608
+ offsetMm: offsetY,
3609
+ offsetX
3610
+ })
3611
+ );
3612
+ }
3613
+ return objects;
3628
3614
  }
3629
-
3630
- // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-via.ts
3631
- import { applyToPoint as applyToPoint23 } from "transformation-matrix";
3632
- function createSvgObjectsFromPcbVia(hole, ctx) {
3633
- const { transform, colorMap: colorMap2 } = ctx;
3634
- const [x, y] = applyToPoint23(transform, [hole.x, hole.y]);
3635
- const scaledOuterWidth = hole.outer_diameter * Math.abs(transform.a);
3636
- const scaledOuterHeight = hole.outer_diameter * Math.abs(transform.a);
3637
- const scaledHoleWidth = hole.hole_diameter * Math.abs(transform.a);
3638
- const scaledHoleHeight = hole.hole_diameter * Math.abs(transform.a);
3639
- const outerRadius = Math.min(scaledOuterWidth, scaledOuterHeight) / 2;
3640
- const innerRadius = Math.min(scaledHoleWidth, scaledHoleHeight) / 2;
3615
+ function createAnchorMarker(x, y) {
3641
3616
  return {
3642
3617
  name: "g",
3643
3618
  type: "element",
3644
3619
  attributes: {
3645
- "data-type": "pcb_via",
3646
- "data-pcb-layer": "through"
3620
+ class: "anchor-offset-marker",
3621
+ "data-type": "anchor_offset_marker"
3647
3622
  },
3648
3623
  children: [
3649
3624
  {
3650
- name: "circle",
3625
+ name: "line",
3651
3626
  type: "element",
3652
3627
  attributes: {
3653
- class: "pcb-hole-outer",
3654
- fill: colorMap2.copper.top,
3655
- cx: x.toString(),
3656
- cy: y.toString(),
3657
- r: outerRadius.toString(),
3658
- "data-type": "pcb_via",
3659
- "data-pcb-layer": "top"
3660
- }
3628
+ x1: x.toString(),
3629
+ y1: (y - ANCHOR_MARKER_SIZE_PX).toString(),
3630
+ x2: x.toString(),
3631
+ y2: (y + ANCHOR_MARKER_SIZE_PX).toString(),
3632
+ stroke: "#ffffff",
3633
+ "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
3634
+ "stroke-linecap": "round"
3635
+ },
3636
+ children: [],
3637
+ value: ""
3661
3638
  },
3662
3639
  {
3663
- name: "circle",
3640
+ name: "line",
3664
3641
  type: "element",
3665
3642
  attributes: {
3666
- class: "pcb-hole-inner",
3667
- fill: colorMap2.drill,
3668
- cx: x.toString(),
3669
- cy: y.toString(),
3670
- r: innerRadius.toString(),
3671
- "data-type": "pcb_via",
3672
- "data-pcb-layer": "drill"
3673
- }
3643
+ x1: (x - ANCHOR_MARKER_SIZE_PX).toString(),
3644
+ y1: y.toString(),
3645
+ x2: (x + ANCHOR_MARKER_SIZE_PX).toString(),
3646
+ y2: y.toString(),
3647
+ stroke: "#ffffff",
3648
+ "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
3649
+ "stroke-linecap": "round"
3650
+ },
3651
+ children: [],
3652
+ value: ""
3674
3653
  }
3675
- ]
3654
+ ],
3655
+ value: ""
3676
3656
  };
3677
3657
  }
3678
-
3679
- // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-hole.ts
3658
+ function createHorizontalDimension({
3659
+ startX,
3660
+ endX,
3661
+ y,
3662
+ offsetMm,
3663
+ offsetY
3664
+ }) {
3665
+ const objects = [];
3666
+ objects.push({
3667
+ name: "line",
3668
+ type: "element",
3669
+ attributes: {
3670
+ x1: startX.toString(),
3671
+ y1: y.toString(),
3672
+ x2: endX.toString(),
3673
+ y2: y.toString(),
3674
+ stroke: "#ffffff",
3675
+ "stroke-width": STROKE_WIDTH_PX.toString(),
3676
+ class: "anchor-offset-dimension-x"
3677
+ },
3678
+ children: [],
3679
+ value: ""
3680
+ });
3681
+ objects.push({
3682
+ name: "line",
3683
+ type: "element",
3684
+ attributes: {
3685
+ x1: startX.toString(),
3686
+ y1: (y - TICK_SIZE_PX).toString(),
3687
+ x2: startX.toString(),
3688
+ y2: (y + TICK_SIZE_PX).toString(),
3689
+ stroke: "#ffffff",
3690
+ "stroke-width": STROKE_WIDTH_PX.toString()
3691
+ },
3692
+ children: [],
3693
+ value: ""
3694
+ });
3695
+ objects.push({
3696
+ name: "line",
3697
+ type: "element",
3698
+ attributes: {
3699
+ x1: endX.toString(),
3700
+ y1: (y - TICK_SIZE_PX).toString(),
3701
+ x2: endX.toString(),
3702
+ y2: (y + TICK_SIZE_PX).toString(),
3703
+ stroke: "#ffffff",
3704
+ "stroke-width": STROKE_WIDTH_PX.toString()
3705
+ },
3706
+ children: [],
3707
+ value: ""
3708
+ });
3709
+ const midX = (startX + endX) / 2;
3710
+ const labelY = offsetY > 0 ? y - TICK_SIZE_PX - LABEL_GAP_PX : y + TICK_SIZE_PX + LABEL_GAP_PX;
3711
+ objects.push({
3712
+ name: "text",
3713
+ type: "element",
3714
+ attributes: {
3715
+ x: midX.toString(),
3716
+ y: labelY.toString(),
3717
+ fill: "#ffffff",
3718
+ "font-size": LABEL_FONT_SIZE_PX.toString(),
3719
+ "font-family": "Arial, sans-serif",
3720
+ "text-anchor": "middle",
3721
+ "dominant-baseline": offsetY > 0 ? "baseline" : "hanging",
3722
+ class: "anchor-offset-label"
3723
+ },
3724
+ children: [
3725
+ {
3726
+ type: "text",
3727
+ value: `X: ${offsetMm.toFixed(2)}mm`,
3728
+ name: "",
3729
+ attributes: {},
3730
+ children: []
3731
+ }
3732
+ ],
3733
+ value: ""
3734
+ });
3735
+ return objects;
3736
+ }
3737
+ function createVerticalDimension({
3738
+ x,
3739
+ startY,
3740
+ endY,
3741
+ offsetMm,
3742
+ offsetX
3743
+ }) {
3744
+ const objects = [];
3745
+ objects.push({
3746
+ name: "line",
3747
+ type: "element",
3748
+ attributes: {
3749
+ x1: x.toString(),
3750
+ y1: startY.toString(),
3751
+ x2: x.toString(),
3752
+ y2: endY.toString(),
3753
+ stroke: "#ffffff",
3754
+ "stroke-width": STROKE_WIDTH_PX.toString(),
3755
+ class: "anchor-offset-dimension-y"
3756
+ },
3757
+ children: [],
3758
+ value: ""
3759
+ });
3760
+ objects.push({
3761
+ name: "line",
3762
+ type: "element",
3763
+ attributes: {
3764
+ x1: (x - TICK_SIZE_PX).toString(),
3765
+ y1: startY.toString(),
3766
+ x2: (x + TICK_SIZE_PX).toString(),
3767
+ y2: startY.toString(),
3768
+ stroke: "#ffffff",
3769
+ "stroke-width": STROKE_WIDTH_PX.toString()
3770
+ },
3771
+ children: [],
3772
+ value: ""
3773
+ });
3774
+ objects.push({
3775
+ name: "line",
3776
+ type: "element",
3777
+ attributes: {
3778
+ x1: (x - TICK_SIZE_PX).toString(),
3779
+ y1: endY.toString(),
3780
+ x2: (x + TICK_SIZE_PX).toString(),
3781
+ y2: endY.toString(),
3782
+ stroke: "#ffffff",
3783
+ "stroke-width": STROKE_WIDTH_PX.toString()
3784
+ },
3785
+ children: [],
3786
+ value: ""
3787
+ });
3788
+ const midY = (startY + endY) / 2;
3789
+ const labelX = offsetX < 0 ? x - TICK_SIZE_PX - 4 : x + TICK_SIZE_PX + 4;
3790
+ objects.push({
3791
+ name: "text",
3792
+ type: "element",
3793
+ attributes: {
3794
+ x: labelX.toString(),
3795
+ y: midY.toString(),
3796
+ fill: "#ffffff",
3797
+ "font-size": LABEL_FONT_SIZE_PX.toString(),
3798
+ "font-family": "Arial, sans-serif",
3799
+ "text-anchor": offsetX < 0 ? "end" : "start",
3800
+ "dominant-baseline": "middle",
3801
+ class: "anchor-offset-label"
3802
+ },
3803
+ children: [
3804
+ {
3805
+ type: "text",
3806
+ value: `Y: ${offsetMm.toFixed(2)}mm`,
3807
+ name: "",
3808
+ attributes: {},
3809
+ children: []
3810
+ }
3811
+ ],
3812
+ value: ""
3813
+ });
3814
+ return objects;
3815
+ }
3816
+
3817
+ // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-board.ts
3818
+ function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3819
+ const { transform, colorMap: colorMap2, showSolderMask, circuitJson } = ctx;
3820
+ const { width, height, center, outline } = pcbBoard;
3821
+ let path;
3822
+ if (outline && Array.isArray(outline) && outline.length >= 3) {
3823
+ path = outline.map((point, index) => {
3824
+ const [x, y] = applyToPoint22(transform, [point.x, point.y]);
3825
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
3826
+ }).join(" ");
3827
+ } else {
3828
+ const halfWidth = width / 2;
3829
+ const halfHeight = height / 2;
3830
+ const topLeft = applyToPoint22(transform, [
3831
+ center.x - halfWidth,
3832
+ center.y - halfHeight
3833
+ ]);
3834
+ const topRight = applyToPoint22(transform, [
3835
+ center.x + halfWidth,
3836
+ center.y - halfHeight
3837
+ ]);
3838
+ const bottomRight = applyToPoint22(transform, [
3839
+ center.x + halfWidth,
3840
+ center.y + halfHeight
3841
+ ]);
3842
+ const bottomLeft = applyToPoint22(transform, [
3843
+ center.x - halfWidth,
3844
+ center.y + halfHeight
3845
+ ]);
3846
+ path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
3847
+ }
3848
+ path += " Z";
3849
+ const svgObjects = [];
3850
+ if (showSolderMask) {
3851
+ const layer = ctx.layer ?? "top";
3852
+ const maskLayer = layer === "bottom" ? "soldermask-bottom" : "soldermask-top";
3853
+ svgObjects.push({
3854
+ name: "path",
3855
+ type: "element",
3856
+ value: "",
3857
+ children: [],
3858
+ attributes: {
3859
+ class: "pcb-board-soldermask",
3860
+ d: path,
3861
+ fill: colorMap2.soldermask.top,
3862
+ "fill-opacity": "0.8",
3863
+ stroke: "none",
3864
+ "data-type": "pcb_soldermask",
3865
+ "data-pcb-layer": maskLayer
3866
+ }
3867
+ });
3868
+ }
3869
+ svgObjects.push({
3870
+ name: "path",
3871
+ type: "element",
3872
+ value: "",
3873
+ children: [],
3874
+ attributes: {
3875
+ class: "pcb-board",
3876
+ d: path,
3877
+ fill: "none",
3878
+ stroke: colorMap2.boardOutline,
3879
+ "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3880
+ "data-type": "pcb_board",
3881
+ "data-pcb-layer": "board"
3882
+ }
3883
+ });
3884
+ if (ctx.showAnchorOffsets && circuitJson) {
3885
+ const panel = circuitJson.find(
3886
+ (elm) => elm.type === "pcb_panel"
3887
+ );
3888
+ if (panel) {
3889
+ const panelCenter = panel.center ?? { x: 0, y: 0 };
3890
+ svgObjects.push(
3891
+ ...createAnchorOffsetIndicators({
3892
+ groupAnchorPosition: panelCenter,
3893
+ componentPosition: center,
3894
+ transform,
3895
+ componentWidth: width,
3896
+ componentHeight: height
3897
+ })
3898
+ );
3899
+ }
3900
+ }
3901
+ return svgObjects;
3902
+ }
3903
+
3904
+ // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-panel.ts
3905
+ import { applyToPoint as applyToPoint23 } from "transformation-matrix";
3906
+ function createSvgObjectsFromPcbPanel(pcbPanel, ctx) {
3907
+ const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3908
+ const width = Number(pcbPanel.width);
3909
+ const height = Number(pcbPanel.height);
3910
+ const center = pcbPanel.center ?? { x: width / 2, y: height / 2 };
3911
+ const halfWidth = width / 2;
3912
+ const halfHeight = height / 2;
3913
+ const topLeft = applyToPoint23(transform, [
3914
+ center.x - halfWidth,
3915
+ center.y - halfHeight
3916
+ ]);
3917
+ const topRight = applyToPoint23(transform, [
3918
+ center.x + halfWidth,
3919
+ center.y - halfHeight
3920
+ ]);
3921
+ const bottomRight = applyToPoint23(transform, [
3922
+ center.x + halfWidth,
3923
+ center.y + halfHeight
3924
+ ]);
3925
+ const bottomLeft = applyToPoint23(transform, [
3926
+ center.x - halfWidth,
3927
+ center.y + halfHeight
3928
+ ]);
3929
+ const path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`;
3930
+ const isCoveredWithSolderMask = pcbPanel.covered_with_solder_mask !== false;
3931
+ const shouldShowSolderMask = Boolean(
3932
+ showSolderMask && isCoveredWithSolderMask
3933
+ );
3934
+ return [
3935
+ {
3936
+ name: "path",
3937
+ type: "element",
3938
+ value: "",
3939
+ children: [],
3940
+ attributes: {
3941
+ class: "pcb-panel",
3942
+ d: path,
3943
+ fill: "none",
3944
+ stroke: colorMap2.boardOutline,
3945
+ "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3946
+ "data-type": "pcb_panel",
3947
+ "data-pcb-layer": "board"
3948
+ }
3949
+ }
3950
+ ];
3951
+ }
3952
+
3953
+ // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-via.ts
3680
3954
  import { applyToPoint as applyToPoint24 } from "transformation-matrix";
3955
+ function createSvgObjectsFromPcbVia(hole, ctx) {
3956
+ const { transform, colorMap: colorMap2 } = ctx;
3957
+ const [x, y] = applyToPoint24(transform, [hole.x, hole.y]);
3958
+ const scaledOuterWidth = hole.outer_diameter * Math.abs(transform.a);
3959
+ const scaledOuterHeight = hole.outer_diameter * Math.abs(transform.a);
3960
+ const scaledHoleWidth = hole.hole_diameter * Math.abs(transform.a);
3961
+ const scaledHoleHeight = hole.hole_diameter * Math.abs(transform.a);
3962
+ const outerRadius = Math.min(scaledOuterWidth, scaledOuterHeight) / 2;
3963
+ const innerRadius = Math.min(scaledHoleWidth, scaledHoleHeight) / 2;
3964
+ return {
3965
+ name: "g",
3966
+ type: "element",
3967
+ attributes: {
3968
+ "data-type": "pcb_via",
3969
+ "data-pcb-layer": "through"
3970
+ },
3971
+ children: [
3972
+ {
3973
+ name: "circle",
3974
+ type: "element",
3975
+ attributes: {
3976
+ class: "pcb-hole-outer",
3977
+ fill: colorMap2.copper.top,
3978
+ cx: x.toString(),
3979
+ cy: y.toString(),
3980
+ r: outerRadius.toString(),
3981
+ "data-type": "pcb_via",
3982
+ "data-pcb-layer": "top"
3983
+ }
3984
+ },
3985
+ {
3986
+ name: "circle",
3987
+ type: "element",
3988
+ attributes: {
3989
+ class: "pcb-hole-inner",
3990
+ fill: colorMap2.drill,
3991
+ cx: x.toString(),
3992
+ cy: y.toString(),
3993
+ r: innerRadius.toString(),
3994
+ "data-type": "pcb_via",
3995
+ "data-pcb-layer": "drill"
3996
+ }
3997
+ }
3998
+ ]
3999
+ };
4000
+ }
4001
+
4002
+ // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-hole.ts
4003
+ import { applyToPoint as applyToPoint25 } from "transformation-matrix";
3681
4004
  function createSvgObjectsFromPcbHole(hole, ctx) {
3682
4005
  const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3683
4006
  const layer = ctx.layer ?? "top";
3684
- const [x, y] = applyToPoint24(transform, [hole.x, hole.y]);
4007
+ const [x, y] = applyToPoint25(transform, [hole.x, hole.y]);
3685
4008
  const isCoveredWithSolderMask = Boolean(hole.is_covered_with_solder_mask);
3686
4009
  const soldermaskMargin = (hole.soldermask_margin ?? 0) * Math.abs(transform.a);
3687
4010
  const shouldShowSolderMask = showSolderMask && isCoveredWithSolderMask && soldermaskMargin !== 0;
@@ -4178,7 +4501,7 @@ import {
4178
4501
  getFullConnectivityMapFromCircuitJson
4179
4502
  } from "circuit-json-to-connectivity-map";
4180
4503
  import "svgson";
4181
- import { applyToPoint as applyToPoint25 } from "transformation-matrix";
4504
+ import { applyToPoint as applyToPoint26 } from "transformation-matrix";
4182
4505
 
4183
4506
  // lib/pcb/create-svg-objects-from-pcb-rats-nest/get-element-position.ts
4184
4507
  import { su } from "@tscircuit/circuit-json-util";
@@ -4258,11 +4581,11 @@ function createSvgObjectsForRatsNest(circuitJson, ctx) {
4258
4581
  });
4259
4582
  const svgObjects = [];
4260
4583
  for (const line of ratsNestLines) {
4261
- const transformedStart = applyToPoint25(transform, [
4584
+ const transformedStart = applyToPoint26(transform, [
4262
4585
  line.startPoint.x,
4263
4586
  line.startPoint.y
4264
4587
  ]);
4265
- const transformedEnd = applyToPoint25(transform, [
4588
+ const transformedEnd = applyToPoint26(transform, [
4266
4589
  line.endPoint.x,
4267
4590
  line.endPoint.y
4268
4591
  ]);
@@ -4290,7 +4613,7 @@ function createSvgObjectsForRatsNest(circuitJson, ctx) {
4290
4613
 
4291
4614
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-cutout.ts
4292
4615
  import {
4293
- applyToPoint as applyToPoint26,
4616
+ applyToPoint as applyToPoint27,
4294
4617
  compose as compose3,
4295
4618
  rotate as rotate3,
4296
4619
  translate as translate3,
@@ -4300,7 +4623,7 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
4300
4623
  const { transform, colorMap: colorMap2 } = ctx;
4301
4624
  if (cutout.shape === "rect") {
4302
4625
  const rectCutout = cutout;
4303
- const [cx, cy] = applyToPoint26(transform, [
4626
+ const [cx, cy] = applyToPoint27(transform, [
4304
4627
  rectCutout.center.x,
4305
4628
  rectCutout.center.y
4306
4629
  ]);
@@ -4342,7 +4665,7 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
4342
4665
  }
4343
4666
  if (cutout.shape === "circle") {
4344
4667
  const circleCutout = cutout;
4345
- const [cx, cy] = applyToPoint26(transform, [
4668
+ const [cx, cy] = applyToPoint27(transform, [
4346
4669
  circleCutout.center.x,
4347
4670
  circleCutout.center.y
4348
4671
  ]);
@@ -4369,7 +4692,7 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
4369
4692
  const polygonCutout = cutout;
4370
4693
  if (!polygonCutout.points || polygonCutout.points.length === 0) return [];
4371
4694
  const transformedPoints = polygonCutout.points.map(
4372
- (p) => applyToPoint26(transform, [p.x, p.y])
4695
+ (p) => applyToPoint27(transform, [p.x, p.y])
4373
4696
  );
4374
4697
  const pointsString = transformedPoints.map((p) => `${p[0]},${p[1]}`).join(" ");
4375
4698
  return [
@@ -4393,7 +4716,7 @@ function createSvgObjectsFromPcbCutout(cutout, ctx) {
4393
4716
 
4394
4717
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-copper-pour.ts
4395
4718
  import {
4396
- applyToPoint as applyToPoint28,
4719
+ applyToPoint as applyToPoint29,
4397
4720
  compose as compose4,
4398
4721
  rotate as rotate4,
4399
4722
  toString as matrixToString7,
@@ -4401,11 +4724,11 @@ import {
4401
4724
  } from "transformation-matrix";
4402
4725
 
4403
4726
  // lib/utils/ring-to-path-d.ts
4404
- import { applyToPoint as applyToPoint27 } from "transformation-matrix";
4727
+ import { applyToPoint as applyToPoint28 } from "transformation-matrix";
4405
4728
  function ringToPathD(vertices, transform) {
4406
4729
  if (vertices.length === 0) return "";
4407
4730
  const transformedVertices = vertices.map((v) => {
4408
- const [x, y] = applyToPoint27(transform, [v.x, v.y]);
4731
+ const [x, y] = applyToPoint28(transform, [v.x, v.y]);
4409
4732
  return { ...v, x, y };
4410
4733
  });
4411
4734
  let d = `M ${transformedVertices[0].x} ${transformedVertices[0].y}`;
@@ -4494,7 +4817,7 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
4494
4817
  const maskOverlayColor = layer === "bottom" ? colorMap2.soldermaskOverCopper.bottom : colorMap2.soldermaskOverCopper.top;
4495
4818
  const maskOverlayOpacity = "0.9";
4496
4819
  if (pour.shape === "rect") {
4497
- const [cx, cy] = applyToPoint28(transform, [pour.center.x, pour.center.y]);
4820
+ const [cx, cy] = applyToPoint29(transform, [pour.center.x, pour.center.y]);
4498
4821
  const scaledWidth = pour.width * Math.abs(transform.a);
4499
4822
  const scaledHeight = pour.height * Math.abs(transform.d);
4500
4823
  const svgRotation = -(pour.rotation ?? 0);
@@ -4546,7 +4869,7 @@ function createSvgObjectsFromPcbCopperPour(pour, ctx) {
4546
4869
  if (pour.shape === "polygon") {
4547
4870
  if (!pour.points || pour.points.length === 0) return [];
4548
4871
  const transformedPoints = pour.points.map(
4549
- (p) => applyToPoint28(transform, [p.x, p.y])
4872
+ (p) => applyToPoint29(transform, [p.x, p.y])
4550
4873
  );
4551
4874
  const pointsString = transformedPoints.map((p) => `${p[0]},${p[1]}`).join(" ");
4552
4875
  const copperPolygon = {
@@ -4684,398 +5007,92 @@ function createSvgObjectsForPcbGrid({
4684
5007
  stroke: gridLineColor,
4685
5008
  "stroke-width": "1",
4686
5009
  "shape-rendering": "crispEdges"
4687
- },
4688
- children: []
4689
- }
4690
- ];
4691
- const defs = {
4692
- name: "defs",
4693
- type: "element",
4694
- value: "",
4695
- attributes: {},
4696
- children: [
4697
- {
4698
- name: "pattern",
4699
- type: "element",
4700
- value: "",
4701
- attributes: {
4702
- id: GRID_PATTERN_ID,
4703
- width: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4704
- height: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4705
- patternUnits: "userSpaceOnUse"
4706
- },
4707
- children: patternChildren
4708
- }
4709
- ]
4710
- };
4711
- const rect = {
4712
- name: "rect",
4713
- type: "element",
4714
- value: "",
4715
- attributes: {
4716
- x: "0",
4717
- y: "0",
4718
- width: svgWidth.toString(),
4719
- height: svgHeight.toString(),
4720
- fill: `url(#${GRID_PATTERN_ID})`,
4721
- "pointer-events": "none",
4722
- "data-type": "pcb_grid",
4723
- "data-pcb-layer": "global"
4724
- },
4725
- children: []
4726
- };
4727
- return { defs, rect };
4728
- }
4729
- function createMajorGridPatternChildren(cellSize, majorCellSize, lineColor, majorLineColor) {
4730
- const children = [];
4731
- const steps = Math.round(majorCellSize / cellSize);
4732
- for (let step = 0; step < steps; step += 1) {
4733
- const offset = Number((step * cellSize).toFixed(6));
4734
- const offsetString = offset.toString();
4735
- const color = step === 0 ? majorLineColor : lineColor;
4736
- const majorSizeString = majorCellSize.toString();
4737
- children.push({
4738
- name: "line",
4739
- type: "element",
4740
- value: "",
4741
- attributes: {
4742
- x1: offsetString,
4743
- y1: "0",
4744
- x2: offsetString,
4745
- y2: majorSizeString,
4746
- stroke: color,
4747
- "stroke-width": "1",
4748
- "shape-rendering": "crispEdges"
4749
- },
4750
- children: []
4751
- });
4752
- children.push({
4753
- name: "line",
4754
- type: "element",
4755
- value: "",
4756
- attributes: {
4757
- x1: "0",
4758
- y1: offsetString,
4759
- x2: majorSizeString,
4760
- y2: offsetString,
4761
- stroke: color,
4762
- "stroke-width": "1",
4763
- "shape-rendering": "crispEdges"
4764
- },
4765
- children: []
4766
- });
4767
- }
4768
- return children;
4769
- }
4770
-
4771
- // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-component.ts
4772
- import { applyToPoint as applyToPoint30 } from "transformation-matrix";
4773
-
4774
- // lib/utils/create-pcb-component-anchor-offset-indicators.ts
4775
- import { applyToPoint as applyToPoint29 } from "transformation-matrix";
4776
- var OFFSET_THRESHOLD_MM = 0.01;
4777
- var TICK_SIZE_PX = 4;
4778
- var LABEL_GAP_PX = 8;
4779
- var LABEL_FONT_SIZE_PX = 11;
4780
- var STROKE_WIDTH_PX = 1;
4781
- var ANCHOR_MARKER_SIZE_PX = 5;
4782
- var ANCHOR_MARKER_STROKE_WIDTH_PX = 1.5;
4783
- var COMPONENT_GAP_PX = 15;
4784
- var COMPONENT_SIDE_GAP_PX = 10;
4785
- var DISTANCE_MULTIPLIER = 0.2;
4786
- var MAX_OFFSET_PX = 50;
4787
- function createAnchorOffsetIndicators(params) {
4788
- const {
4789
- groupAnchorPosition,
4790
- componentPosition,
4791
- transform,
4792
- componentWidth = 0,
4793
- componentHeight = 0
4794
- } = params;
4795
- const objects = [];
4796
- const [screenGroupAnchorX, screenGroupAnchorY] = applyToPoint29(transform, [
4797
- groupAnchorPosition.x,
4798
- groupAnchorPosition.y
4799
- ]);
4800
- const [screenComponentX, screenComponentY] = applyToPoint29(transform, [
4801
- componentPosition.x,
4802
- componentPosition.y
4803
- ]);
4804
- const offsetX = componentPosition.x - groupAnchorPosition.x;
4805
- const offsetY = componentPosition.y - groupAnchorPosition.y;
4806
- const scale9 = Math.abs(transform.a);
4807
- const screenComponentWidth = componentWidth * scale9;
4808
- const screenComponentHeight = componentHeight * scale9;
4809
- objects.push(createAnchorMarker(screenGroupAnchorX, screenGroupAnchorY));
4810
- objects.push({
4811
- name: "line",
4812
- type: "element",
4813
- attributes: {
4814
- x1: screenGroupAnchorX.toString(),
4815
- y1: screenGroupAnchorY.toString(),
4816
- x2: screenComponentX.toString(),
4817
- y2: screenComponentY.toString(),
4818
- stroke: "#ffffff",
4819
- "stroke-width": "0.5",
4820
- "stroke-dasharray": "3,3",
4821
- opacity: "0.5",
4822
- class: "anchor-offset-connector"
4823
- },
4824
- children: [],
4825
- value: ""
4826
- });
4827
- objects.push({
4828
- name: "circle",
4829
- type: "element",
4830
- attributes: {
4831
- cx: screenComponentX.toString(),
4832
- cy: screenComponentY.toString(),
4833
- r: "2",
4834
- fill: "#ffffff",
4835
- opacity: "0.7",
4836
- class: "anchor-offset-component-marker"
4837
- },
4838
- children: [],
4839
- value: ""
4840
- });
4841
- const yDistance = Math.abs(screenComponentY - screenGroupAnchorY);
4842
- const xDistance = Math.abs(screenComponentX - screenGroupAnchorX);
4843
- const totalDistance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
4844
- const componentHeightOffset = screenComponentHeight / 2 + COMPONENT_GAP_PX;
4845
- const dynamicOffset = Math.max(
4846
- componentHeightOffset,
4847
- Math.min(MAX_OFFSET_PX, totalDistance * DISTANCE_MULTIPLIER)
4848
- );
4849
- const horizontalLineY = offsetY > 0 ? screenComponentY - dynamicOffset : screenComponentY + dynamicOffset;
4850
- const componentWidthOffset = screenComponentWidth / 2 + COMPONENT_SIDE_GAP_PX;
4851
- const verticalLineX = offsetX > 0 ? screenComponentX + componentWidthOffset : screenComponentX - componentWidthOffset;
4852
- if (Math.abs(offsetX) > OFFSET_THRESHOLD_MM) {
4853
- objects.push(
4854
- ...createHorizontalDimension({
4855
- startX: screenGroupAnchorX,
4856
- endX: screenComponentX,
4857
- y: horizontalLineY,
4858
- offsetMm: offsetX,
4859
- offsetY
4860
- })
4861
- );
4862
- }
4863
- if (Math.abs(offsetY) > OFFSET_THRESHOLD_MM) {
4864
- objects.push(
4865
- ...createVerticalDimension({
4866
- x: verticalLineX,
4867
- startY: screenGroupAnchorY,
4868
- endY: screenComponentY,
4869
- offsetMm: -offsetY,
4870
- offsetX
4871
- })
4872
- );
4873
- }
4874
- return objects;
4875
- }
4876
- function createAnchorMarker(x, y) {
4877
- return {
4878
- name: "g",
5010
+ },
5011
+ children: []
5012
+ }
5013
+ ];
5014
+ const defs = {
5015
+ name: "defs",
4879
5016
  type: "element",
4880
- attributes: {
4881
- class: "anchor-offset-marker",
4882
- "data-type": "anchor_offset_marker"
4883
- },
5017
+ value: "",
5018
+ attributes: {},
4884
5019
  children: [
4885
5020
  {
4886
- name: "line",
4887
- type: "element",
4888
- attributes: {
4889
- x1: x.toString(),
4890
- y1: (y - ANCHOR_MARKER_SIZE_PX).toString(),
4891
- x2: x.toString(),
4892
- y2: (y + ANCHOR_MARKER_SIZE_PX).toString(),
4893
- stroke: "#ffffff",
4894
- "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
4895
- "stroke-linecap": "round"
4896
- },
4897
- children: [],
4898
- value: ""
4899
- },
4900
- {
4901
- name: "line",
5021
+ name: "pattern",
4902
5022
  type: "element",
5023
+ value: "",
4903
5024
  attributes: {
4904
- x1: (x - ANCHOR_MARKER_SIZE_PX).toString(),
4905
- y1: y.toString(),
4906
- x2: (x + ANCHOR_MARKER_SIZE_PX).toString(),
4907
- y2: y.toString(),
4908
- stroke: "#ffffff",
4909
- "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
4910
- "stroke-linecap": "round"
5025
+ id: GRID_PATTERN_ID,
5026
+ width: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
5027
+ height: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
5028
+ patternUnits: "userSpaceOnUse"
4911
5029
  },
4912
- children: [],
4913
- value: ""
5030
+ children: patternChildren
4914
5031
  }
4915
- ],
4916
- value: ""
5032
+ ]
4917
5033
  };
4918
- }
4919
- function createHorizontalDimension({
4920
- startX,
4921
- endX,
4922
- y,
4923
- offsetMm,
4924
- offsetY
4925
- }) {
4926
- const objects = [];
4927
- objects.push({
4928
- name: "line",
4929
- type: "element",
4930
- attributes: {
4931
- x1: startX.toString(),
4932
- y1: y.toString(),
4933
- x2: endX.toString(),
4934
- y2: y.toString(),
4935
- stroke: "#ffffff",
4936
- "stroke-width": STROKE_WIDTH_PX.toString(),
4937
- class: "anchor-offset-dimension-x"
4938
- },
4939
- children: [],
4940
- value: ""
4941
- });
4942
- objects.push({
4943
- name: "line",
4944
- type: "element",
4945
- attributes: {
4946
- x1: startX.toString(),
4947
- y1: (y - TICK_SIZE_PX).toString(),
4948
- x2: startX.toString(),
4949
- y2: (y + TICK_SIZE_PX).toString(),
4950
- stroke: "#ffffff",
4951
- "stroke-width": STROKE_WIDTH_PX.toString()
4952
- },
4953
- children: [],
4954
- value: ""
4955
- });
4956
- objects.push({
4957
- name: "line",
4958
- type: "element",
4959
- attributes: {
4960
- x1: endX.toString(),
4961
- y1: (y - TICK_SIZE_PX).toString(),
4962
- x2: endX.toString(),
4963
- y2: (y + TICK_SIZE_PX).toString(),
4964
- stroke: "#ffffff",
4965
- "stroke-width": STROKE_WIDTH_PX.toString()
4966
- },
4967
- children: [],
4968
- value: ""
4969
- });
4970
- const midX = (startX + endX) / 2;
4971
- const labelY = offsetY > 0 ? y - TICK_SIZE_PX - LABEL_GAP_PX : y + TICK_SIZE_PX + LABEL_GAP_PX;
4972
- objects.push({
4973
- name: "text",
5034
+ const rect = {
5035
+ name: "rect",
4974
5036
  type: "element",
5037
+ value: "",
4975
5038
  attributes: {
4976
- x: midX.toString(),
4977
- y: labelY.toString(),
4978
- fill: "#ffffff",
4979
- "font-size": LABEL_FONT_SIZE_PX.toString(),
4980
- "font-family": "Arial, sans-serif",
4981
- "text-anchor": "middle",
4982
- "dominant-baseline": offsetY > 0 ? "baseline" : "hanging",
4983
- class: "anchor-offset-label"
5039
+ x: "0",
5040
+ y: "0",
5041
+ width: svgWidth.toString(),
5042
+ height: svgHeight.toString(),
5043
+ fill: `url(#${GRID_PATTERN_ID})`,
5044
+ "pointer-events": "none",
5045
+ "data-type": "pcb_grid",
5046
+ "data-pcb-layer": "global"
4984
5047
  },
4985
- children: [
4986
- {
4987
- type: "text",
4988
- value: `X: ${offsetMm.toFixed(2)}mm`,
4989
- name: "",
4990
- attributes: {},
4991
- children: []
4992
- }
4993
- ],
4994
- value: ""
4995
- });
4996
- return objects;
5048
+ children: []
5049
+ };
5050
+ return { defs, rect };
4997
5051
  }
4998
- function createVerticalDimension({
4999
- x,
5000
- startY,
5001
- endY,
5002
- offsetMm,
5003
- offsetX
5004
- }) {
5005
- const objects = [];
5006
- objects.push({
5007
- name: "line",
5008
- type: "element",
5009
- attributes: {
5010
- x1: x.toString(),
5011
- y1: startY.toString(),
5012
- x2: x.toString(),
5013
- y2: endY.toString(),
5014
- stroke: "#ffffff",
5015
- "stroke-width": STROKE_WIDTH_PX.toString(),
5016
- class: "anchor-offset-dimension-y"
5017
- },
5018
- children: [],
5019
- value: ""
5020
- });
5021
- objects.push({
5022
- name: "line",
5023
- type: "element",
5024
- attributes: {
5025
- x1: (x - TICK_SIZE_PX).toString(),
5026
- y1: startY.toString(),
5027
- x2: (x + TICK_SIZE_PX).toString(),
5028
- y2: startY.toString(),
5029
- stroke: "#ffffff",
5030
- "stroke-width": STROKE_WIDTH_PX.toString()
5031
- },
5032
- children: [],
5033
- value: ""
5034
- });
5035
- objects.push({
5036
- name: "line",
5037
- type: "element",
5038
- attributes: {
5039
- x1: (x - TICK_SIZE_PX).toString(),
5040
- y1: endY.toString(),
5041
- x2: (x + TICK_SIZE_PX).toString(),
5042
- y2: endY.toString(),
5043
- stroke: "#ffffff",
5044
- "stroke-width": STROKE_WIDTH_PX.toString()
5045
- },
5046
- children: [],
5047
- value: ""
5048
- });
5049
- const midY = (startY + endY) / 2;
5050
- const labelX = offsetX < 0 ? x - TICK_SIZE_PX - 4 : x + TICK_SIZE_PX + 4;
5051
- objects.push({
5052
- name: "text",
5053
- type: "element",
5054
- attributes: {
5055
- x: labelX.toString(),
5056
- y: midY.toString(),
5057
- fill: "#ffffff",
5058
- "font-size": LABEL_FONT_SIZE_PX.toString(),
5059
- "font-family": "Arial, sans-serif",
5060
- "text-anchor": offsetX < 0 ? "end" : "start",
5061
- "dominant-baseline": "middle",
5062
- class: "anchor-offset-label"
5063
- },
5064
- children: [
5065
- {
5066
- type: "text",
5067
- value: `Y: ${offsetMm.toFixed(2)}mm`,
5068
- name: "",
5069
- attributes: {},
5070
- children: []
5071
- }
5072
- ],
5073
- value: ""
5074
- });
5075
- return objects;
5052
+ function createMajorGridPatternChildren(cellSize, majorCellSize, lineColor, majorLineColor) {
5053
+ const children = [];
5054
+ const steps = Math.round(majorCellSize / cellSize);
5055
+ for (let step = 0; step < steps; step += 1) {
5056
+ const offset = Number((step * cellSize).toFixed(6));
5057
+ const offsetString = offset.toString();
5058
+ const color = step === 0 ? majorLineColor : lineColor;
5059
+ const majorSizeString = majorCellSize.toString();
5060
+ children.push({
5061
+ name: "line",
5062
+ type: "element",
5063
+ value: "",
5064
+ attributes: {
5065
+ x1: offsetString,
5066
+ y1: "0",
5067
+ x2: offsetString,
5068
+ y2: majorSizeString,
5069
+ stroke: color,
5070
+ "stroke-width": "1",
5071
+ "shape-rendering": "crispEdges"
5072
+ },
5073
+ children: []
5074
+ });
5075
+ children.push({
5076
+ name: "line",
5077
+ type: "element",
5078
+ value: "",
5079
+ attributes: {
5080
+ x1: "0",
5081
+ y1: offsetString,
5082
+ x2: majorSizeString,
5083
+ y2: offsetString,
5084
+ stroke: color,
5085
+ "stroke-width": "1",
5086
+ "shape-rendering": "crispEdges"
5087
+ },
5088
+ children: []
5089
+ });
5090
+ }
5091
+ return children;
5076
5092
  }
5077
5093
 
5078
5094
  // lib/pcb/svg-object-fns/create-svg-objects-from-pcb-component.ts
5095
+ import { applyToPoint as applyToPoint30 } from "transformation-matrix";
5079
5096
  function createSvgObjectsFromPcbComponent(component, ctx) {
5080
5097
  const { transform, circuitJson } = ctx;
5081
5098
  const { center, width, height, rotation = 0 } = component;
@@ -5223,7 +5240,7 @@ function getSoftwareUsedString(circuitJson) {
5223
5240
  var package_default = {
5224
5241
  name: "circuit-to-svg",
5225
5242
  type: "module",
5226
- version: "0.0.282",
5243
+ version: "0.0.283",
5227
5244
  description: "Convert Circuit JSON to SVG",
5228
5245
  main: "dist/index.js",
5229
5246
  files: [
@@ -5247,12 +5264,12 @@ var package_default = {
5247
5264
  "bun-match-svg": "^0.0.12",
5248
5265
  esbuild: "^0.20.2",
5249
5266
  "performance-now": "^2.1.0",
5250
- "circuit-json": "^0.0.319",
5267
+ "circuit-json": "^0.0.327",
5251
5268
  react: "19.1.0",
5252
5269
  "react-cosmos": "7.0.0",
5253
5270
  "react-cosmos-plugin-vite": "7.0.0",
5254
5271
  "react-dom": "19.1.0",
5255
- tscircuit: "^0.0.937",
5272
+ tscircuit: "^0.0.1018",
5256
5273
  tsup: "^8.0.2",
5257
5274
  typescript: "^5.4.5",
5258
5275
  "vite-tsconfig-paths": "^5.0.1"