easyeda 0.0.232 → 0.0.234

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.
@@ -14,7 +14,7 @@ import {
14
14
  toSVG,
15
15
  toString,
16
16
  translate
17
- } from "./chunk-U5UUPCU3.js";
17
+ } from "./chunk-CGLWJURY.js";
18
18
 
19
19
  // node_modules/circuit-to-svg/dist/index.js
20
20
  var import_svgson = __toESM(require_svgson_umd(), 1);
@@ -3447,164 +3447,482 @@ function createSvgObjectsFromSmtPad(pad, ctx) {
3447
3447
  }
3448
3448
  return [];
3449
3449
  }
3450
- function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3451
- const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3452
- const { width, height, center, outline } = pcbBoard;
3453
- let path;
3454
- if (outline && Array.isArray(outline) && outline.length >= 3) {
3455
- path = outline.map((point, index) => {
3456
- const [x, y] = applyToPoint(transform, [point.x, point.y]);
3457
- return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
3458
- }).join(" ");
3459
- } else {
3460
- const halfWidth = width / 2;
3461
- const halfHeight = height / 2;
3462
- const topLeft = applyToPoint(transform, [
3463
- center.x - halfWidth,
3464
- center.y - halfHeight
3465
- ]);
3466
- const topRight = applyToPoint(transform, [
3467
- center.x + halfWidth,
3468
- center.y - halfHeight
3469
- ]);
3470
- const bottomRight = applyToPoint(transform, [
3471
- center.x + halfWidth,
3472
- center.y + halfHeight
3473
- ]);
3474
- const bottomLeft = applyToPoint(transform, [
3475
- center.x - halfWidth,
3476
- center.y + halfHeight
3477
- ]);
3478
- path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
3479
- }
3480
- path += " Z";
3481
- const svgObjects = [];
3482
- if (showSolderMask) {
3483
- const layer = ctx.layer ?? "top";
3484
- const maskLayer = layer === "bottom" ? "soldermask-bottom" : "soldermask-top";
3485
- svgObjects.push({
3486
- name: "path",
3487
- type: "element",
3488
- value: "",
3489
- children: [],
3490
- attributes: {
3491
- class: "pcb-board-soldermask",
3492
- d: path,
3493
- fill: colorMap2.soldermask.top,
3494
- "fill-opacity": "0.8",
3495
- stroke: "none",
3496
- "data-type": "pcb_soldermask",
3497
- "data-pcb-layer": maskLayer
3498
- }
3499
- });
3500
- }
3501
- svgObjects.push({
3502
- name: "path",
3450
+ var OFFSET_THRESHOLD_MM = 0.01;
3451
+ var TICK_SIZE_PX = 4;
3452
+ var LABEL_GAP_PX = 8;
3453
+ var LABEL_FONT_SIZE_PX = 11;
3454
+ var STROKE_WIDTH_PX = 1;
3455
+ var ANCHOR_MARKER_SIZE_PX = 5;
3456
+ var ANCHOR_MARKER_STROKE_WIDTH_PX = 1.5;
3457
+ var COMPONENT_GAP_PX = 15;
3458
+ var COMPONENT_SIDE_GAP_PX = 10;
3459
+ var DISTANCE_MULTIPLIER = 0.2;
3460
+ var MAX_OFFSET_PX = 50;
3461
+ function createAnchorOffsetIndicators(params) {
3462
+ const {
3463
+ groupAnchorPosition,
3464
+ componentPosition,
3465
+ transform,
3466
+ componentWidth = 0,
3467
+ componentHeight = 0
3468
+ } = params;
3469
+ const objects = [];
3470
+ const [screenGroupAnchorX, screenGroupAnchorY] = applyToPoint(transform, [
3471
+ groupAnchorPosition.x,
3472
+ groupAnchorPosition.y
3473
+ ]);
3474
+ const [screenComponentX, screenComponentY] = applyToPoint(transform, [
3475
+ componentPosition.x,
3476
+ componentPosition.y
3477
+ ]);
3478
+ const offsetX = componentPosition.x - groupAnchorPosition.x;
3479
+ const offsetY = componentPosition.y - groupAnchorPosition.y;
3480
+ const scale9 = Math.abs(transform.a);
3481
+ const screenComponentWidth = componentWidth * scale9;
3482
+ const screenComponentHeight = componentHeight * scale9;
3483
+ objects.push(createAnchorMarker(screenGroupAnchorX, screenGroupAnchorY));
3484
+ objects.push({
3485
+ name: "line",
3503
3486
  type: "element",
3504
- value: "",
3487
+ attributes: {
3488
+ x1: screenGroupAnchorX.toString(),
3489
+ y1: screenGroupAnchorY.toString(),
3490
+ x2: screenComponentX.toString(),
3491
+ y2: screenComponentY.toString(),
3492
+ stroke: "#ffffff",
3493
+ "stroke-width": "0.5",
3494
+ "stroke-dasharray": "3,3",
3495
+ opacity: "0.5",
3496
+ class: "anchor-offset-connector"
3497
+ },
3505
3498
  children: [],
3499
+ value: ""
3500
+ });
3501
+ objects.push({
3502
+ name: "circle",
3503
+ type: "element",
3506
3504
  attributes: {
3507
- class: "pcb-board",
3508
- d: path,
3509
- fill: "none",
3510
- stroke: colorMap2.boardOutline,
3511
- "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3512
- "data-type": "pcb_board",
3513
- "data-pcb-layer": "board"
3514
- }
3505
+ cx: screenComponentX.toString(),
3506
+ cy: screenComponentY.toString(),
3507
+ r: "2",
3508
+ fill: "#ffffff",
3509
+ opacity: "0.7",
3510
+ class: "anchor-offset-component-marker"
3511
+ },
3512
+ children: [],
3513
+ value: ""
3515
3514
  });
3516
- return svgObjects;
3517
- }
3518
- function createSvgObjectsFromPcbPanel(pcbPanel, ctx) {
3519
- const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3520
- const width = Number(pcbPanel.width);
3521
- const height = Number(pcbPanel.height);
3522
- const center = pcbPanel.center ?? { x: width / 2, y: height / 2 };
3523
- const halfWidth = width / 2;
3524
- const halfHeight = height / 2;
3525
- const topLeft = applyToPoint(transform, [
3526
- center.x - halfWidth,
3527
- center.y - halfHeight
3528
- ]);
3529
- const topRight = applyToPoint(transform, [
3530
- center.x + halfWidth,
3531
- center.y - halfHeight
3532
- ]);
3533
- const bottomRight = applyToPoint(transform, [
3534
- center.x + halfWidth,
3535
- center.y + halfHeight
3536
- ]);
3537
- const bottomLeft = applyToPoint(transform, [
3538
- center.x - halfWidth,
3539
- center.y + halfHeight
3540
- ]);
3541
- const path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`;
3542
- const isCoveredWithSolderMask = pcbPanel.covered_with_solder_mask !== false;
3543
- const shouldShowSolderMask = Boolean(
3544
- showSolderMask && isCoveredWithSolderMask
3515
+ const yDistance = Math.abs(screenComponentY - screenGroupAnchorY);
3516
+ const xDistance = Math.abs(screenComponentX - screenGroupAnchorX);
3517
+ const totalDistance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
3518
+ const componentHeightOffset = screenComponentHeight / 2 + COMPONENT_GAP_PX;
3519
+ const dynamicOffset = Math.max(
3520
+ componentHeightOffset,
3521
+ Math.min(MAX_OFFSET_PX, totalDistance * DISTANCE_MULTIPLIER)
3545
3522
  );
3546
- return [
3547
- {
3548
- name: "path",
3549
- type: "element",
3550
- value: "",
3551
- children: [],
3552
- attributes: {
3553
- class: "pcb-panel",
3554
- d: path,
3555
- fill: "none",
3556
- stroke: colorMap2.boardOutline,
3557
- "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3558
- "data-type": "pcb_panel",
3559
- "data-pcb-layer": "board"
3560
- }
3561
- }
3562
- ];
3523
+ const horizontalLineY = offsetY > 0 ? screenComponentY - dynamicOffset : screenComponentY + dynamicOffset;
3524
+ const componentWidthOffset = screenComponentWidth / 2 + COMPONENT_SIDE_GAP_PX;
3525
+ const verticalLineX = offsetX > 0 ? screenComponentX + componentWidthOffset : screenComponentX - componentWidthOffset;
3526
+ if (Math.abs(offsetX) > OFFSET_THRESHOLD_MM) {
3527
+ objects.push(
3528
+ ...createHorizontalDimension({
3529
+ startX: screenGroupAnchorX,
3530
+ endX: screenComponentX,
3531
+ y: horizontalLineY,
3532
+ offsetMm: offsetX,
3533
+ offsetY
3534
+ })
3535
+ );
3536
+ }
3537
+ if (Math.abs(offsetY) > OFFSET_THRESHOLD_MM) {
3538
+ objects.push(
3539
+ ...createVerticalDimension({
3540
+ x: verticalLineX,
3541
+ startY: screenGroupAnchorY,
3542
+ endY: screenComponentY,
3543
+ offsetMm: offsetY,
3544
+ offsetX
3545
+ })
3546
+ );
3547
+ }
3548
+ return objects;
3563
3549
  }
3564
- function createSvgObjectsFromPcbVia(hole, ctx) {
3565
- const { transform, colorMap: colorMap2 } = ctx;
3566
- const [x, y] = applyToPoint(transform, [hole.x, hole.y]);
3567
- const scaledOuterWidth = hole.outer_diameter * Math.abs(transform.a);
3568
- const scaledOuterHeight = hole.outer_diameter * Math.abs(transform.a);
3569
- const scaledHoleWidth = hole.hole_diameter * Math.abs(transform.a);
3570
- const scaledHoleHeight = hole.hole_diameter * Math.abs(transform.a);
3571
- const outerRadius = Math.min(scaledOuterWidth, scaledOuterHeight) / 2;
3572
- const innerRadius = Math.min(scaledHoleWidth, scaledHoleHeight) / 2;
3550
+ function createAnchorMarker(x, y) {
3573
3551
  return {
3574
3552
  name: "g",
3575
3553
  type: "element",
3576
3554
  attributes: {
3577
- "data-type": "pcb_via",
3578
- "data-pcb-layer": "through"
3555
+ class: "anchor-offset-marker",
3556
+ "data-type": "anchor_offset_marker"
3579
3557
  },
3580
3558
  children: [
3581
3559
  {
3582
- name: "circle",
3560
+ name: "line",
3583
3561
  type: "element",
3584
3562
  attributes: {
3585
- class: "pcb-hole-outer",
3586
- fill: colorMap2.copper.top,
3587
- cx: x.toString(),
3588
- cy: y.toString(),
3589
- r: outerRadius.toString(),
3590
- "data-type": "pcb_via",
3591
- "data-pcb-layer": "top"
3592
- }
3563
+ x1: x.toString(),
3564
+ y1: (y - ANCHOR_MARKER_SIZE_PX).toString(),
3565
+ x2: x.toString(),
3566
+ y2: (y + ANCHOR_MARKER_SIZE_PX).toString(),
3567
+ stroke: "#ffffff",
3568
+ "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
3569
+ "stroke-linecap": "round"
3570
+ },
3571
+ children: [],
3572
+ value: ""
3593
3573
  },
3594
3574
  {
3595
- name: "circle",
3575
+ name: "line",
3596
3576
  type: "element",
3597
3577
  attributes: {
3598
- class: "pcb-hole-inner",
3599
- fill: colorMap2.drill,
3600
- cx: x.toString(),
3601
- cy: y.toString(),
3602
- r: innerRadius.toString(),
3603
- "data-type": "pcb_via",
3604
- "data-pcb-layer": "drill"
3605
- }
3578
+ x1: (x - ANCHOR_MARKER_SIZE_PX).toString(),
3579
+ y1: y.toString(),
3580
+ x2: (x + ANCHOR_MARKER_SIZE_PX).toString(),
3581
+ y2: y.toString(),
3582
+ stroke: "#ffffff",
3583
+ "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
3584
+ "stroke-linecap": "round"
3585
+ },
3586
+ children: [],
3587
+ value: ""
3606
3588
  }
3607
- ]
3589
+ ],
3590
+ value: ""
3591
+ };
3592
+ }
3593
+ function createHorizontalDimension({
3594
+ startX,
3595
+ endX,
3596
+ y,
3597
+ offsetMm,
3598
+ offsetY
3599
+ }) {
3600
+ const objects = [];
3601
+ objects.push({
3602
+ name: "line",
3603
+ type: "element",
3604
+ attributes: {
3605
+ x1: startX.toString(),
3606
+ y1: y.toString(),
3607
+ x2: endX.toString(),
3608
+ y2: y.toString(),
3609
+ stroke: "#ffffff",
3610
+ "stroke-width": STROKE_WIDTH_PX.toString(),
3611
+ class: "anchor-offset-dimension-x"
3612
+ },
3613
+ children: [],
3614
+ value: ""
3615
+ });
3616
+ objects.push({
3617
+ name: "line",
3618
+ type: "element",
3619
+ attributes: {
3620
+ x1: startX.toString(),
3621
+ y1: (y - TICK_SIZE_PX).toString(),
3622
+ x2: startX.toString(),
3623
+ y2: (y + TICK_SIZE_PX).toString(),
3624
+ stroke: "#ffffff",
3625
+ "stroke-width": STROKE_WIDTH_PX.toString()
3626
+ },
3627
+ children: [],
3628
+ value: ""
3629
+ });
3630
+ objects.push({
3631
+ name: "line",
3632
+ type: "element",
3633
+ attributes: {
3634
+ x1: endX.toString(),
3635
+ y1: (y - TICK_SIZE_PX).toString(),
3636
+ x2: endX.toString(),
3637
+ y2: (y + TICK_SIZE_PX).toString(),
3638
+ stroke: "#ffffff",
3639
+ "stroke-width": STROKE_WIDTH_PX.toString()
3640
+ },
3641
+ children: [],
3642
+ value: ""
3643
+ });
3644
+ const midX = (startX + endX) / 2;
3645
+ const labelY = offsetY > 0 ? y - TICK_SIZE_PX - LABEL_GAP_PX : y + TICK_SIZE_PX + LABEL_GAP_PX;
3646
+ objects.push({
3647
+ name: "text",
3648
+ type: "element",
3649
+ attributes: {
3650
+ x: midX.toString(),
3651
+ y: labelY.toString(),
3652
+ fill: "#ffffff",
3653
+ "font-size": LABEL_FONT_SIZE_PX.toString(),
3654
+ "font-family": "Arial, sans-serif",
3655
+ "text-anchor": "middle",
3656
+ "dominant-baseline": offsetY > 0 ? "baseline" : "hanging",
3657
+ class: "anchor-offset-label"
3658
+ },
3659
+ children: [
3660
+ {
3661
+ type: "text",
3662
+ value: `X: ${offsetMm.toFixed(2)}mm`,
3663
+ name: "",
3664
+ attributes: {},
3665
+ children: []
3666
+ }
3667
+ ],
3668
+ value: ""
3669
+ });
3670
+ return objects;
3671
+ }
3672
+ function createVerticalDimension({
3673
+ x,
3674
+ startY,
3675
+ endY,
3676
+ offsetMm,
3677
+ offsetX
3678
+ }) {
3679
+ const objects = [];
3680
+ objects.push({
3681
+ name: "line",
3682
+ type: "element",
3683
+ attributes: {
3684
+ x1: x.toString(),
3685
+ y1: startY.toString(),
3686
+ x2: x.toString(),
3687
+ y2: endY.toString(),
3688
+ stroke: "#ffffff",
3689
+ "stroke-width": STROKE_WIDTH_PX.toString(),
3690
+ class: "anchor-offset-dimension-y"
3691
+ },
3692
+ children: [],
3693
+ value: ""
3694
+ });
3695
+ objects.push({
3696
+ name: "line",
3697
+ type: "element",
3698
+ attributes: {
3699
+ x1: (x - TICK_SIZE_PX).toString(),
3700
+ y1: startY.toString(),
3701
+ x2: (x + TICK_SIZE_PX).toString(),
3702
+ y2: startY.toString(),
3703
+ stroke: "#ffffff",
3704
+ "stroke-width": STROKE_WIDTH_PX.toString()
3705
+ },
3706
+ children: [],
3707
+ value: ""
3708
+ });
3709
+ objects.push({
3710
+ name: "line",
3711
+ type: "element",
3712
+ attributes: {
3713
+ x1: (x - TICK_SIZE_PX).toString(),
3714
+ y1: endY.toString(),
3715
+ x2: (x + TICK_SIZE_PX).toString(),
3716
+ y2: endY.toString(),
3717
+ stroke: "#ffffff",
3718
+ "stroke-width": STROKE_WIDTH_PX.toString()
3719
+ },
3720
+ children: [],
3721
+ value: ""
3722
+ });
3723
+ const midY = (startY + endY) / 2;
3724
+ const labelX = offsetX < 0 ? x - TICK_SIZE_PX - 4 : x + TICK_SIZE_PX + 4;
3725
+ objects.push({
3726
+ name: "text",
3727
+ type: "element",
3728
+ attributes: {
3729
+ x: labelX.toString(),
3730
+ y: midY.toString(),
3731
+ fill: "#ffffff",
3732
+ "font-size": LABEL_FONT_SIZE_PX.toString(),
3733
+ "font-family": "Arial, sans-serif",
3734
+ "text-anchor": offsetX < 0 ? "end" : "start",
3735
+ "dominant-baseline": "middle",
3736
+ class: "anchor-offset-label"
3737
+ },
3738
+ children: [
3739
+ {
3740
+ type: "text",
3741
+ value: `Y: ${offsetMm.toFixed(2)}mm`,
3742
+ name: "",
3743
+ attributes: {},
3744
+ children: []
3745
+ }
3746
+ ],
3747
+ value: ""
3748
+ });
3749
+ return objects;
3750
+ }
3751
+ function createSvgObjectsFromPcbBoard(pcbBoard, ctx) {
3752
+ const { transform, colorMap: colorMap2, showSolderMask, circuitJson } = ctx;
3753
+ const { width, height, center, outline } = pcbBoard;
3754
+ let path;
3755
+ if (outline && Array.isArray(outline) && outline.length >= 3) {
3756
+ path = outline.map((point, index) => {
3757
+ const [x, y] = applyToPoint(transform, [point.x, point.y]);
3758
+ return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}`;
3759
+ }).join(" ");
3760
+ } else {
3761
+ const halfWidth = width / 2;
3762
+ const halfHeight = height / 2;
3763
+ const topLeft = applyToPoint(transform, [
3764
+ center.x - halfWidth,
3765
+ center.y - halfHeight
3766
+ ]);
3767
+ const topRight = applyToPoint(transform, [
3768
+ center.x + halfWidth,
3769
+ center.y - halfHeight
3770
+ ]);
3771
+ const bottomRight = applyToPoint(transform, [
3772
+ center.x + halfWidth,
3773
+ center.y + halfHeight
3774
+ ]);
3775
+ const bottomLeft = applyToPoint(transform, [
3776
+ center.x - halfWidth,
3777
+ center.y + halfHeight
3778
+ ]);
3779
+ path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]}`;
3780
+ }
3781
+ path += " Z";
3782
+ const svgObjects = [];
3783
+ if (showSolderMask) {
3784
+ const layer = ctx.layer ?? "top";
3785
+ const maskLayer = layer === "bottom" ? "soldermask-bottom" : "soldermask-top";
3786
+ svgObjects.push({
3787
+ name: "path",
3788
+ type: "element",
3789
+ value: "",
3790
+ children: [],
3791
+ attributes: {
3792
+ class: "pcb-board-soldermask",
3793
+ d: path,
3794
+ fill: colorMap2.soldermask.top,
3795
+ "fill-opacity": "0.8",
3796
+ stroke: "none",
3797
+ "data-type": "pcb_soldermask",
3798
+ "data-pcb-layer": maskLayer
3799
+ }
3800
+ });
3801
+ }
3802
+ svgObjects.push({
3803
+ name: "path",
3804
+ type: "element",
3805
+ value: "",
3806
+ children: [],
3807
+ attributes: {
3808
+ class: "pcb-board",
3809
+ d: path,
3810
+ fill: "none",
3811
+ stroke: colorMap2.boardOutline,
3812
+ "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3813
+ "data-type": "pcb_board",
3814
+ "data-pcb-layer": "board"
3815
+ }
3816
+ });
3817
+ if (ctx.showAnchorOffsets && circuitJson) {
3818
+ const panel = circuitJson.find(
3819
+ (elm) => elm.type === "pcb_panel"
3820
+ );
3821
+ if (panel) {
3822
+ const panelCenter = panel.center ?? { x: 0, y: 0 };
3823
+ svgObjects.push(
3824
+ ...createAnchorOffsetIndicators({
3825
+ groupAnchorPosition: panelCenter,
3826
+ componentPosition: center,
3827
+ transform,
3828
+ componentWidth: width,
3829
+ componentHeight: height
3830
+ })
3831
+ );
3832
+ }
3833
+ }
3834
+ return svgObjects;
3835
+ }
3836
+ function createSvgObjectsFromPcbPanel(pcbPanel, ctx) {
3837
+ const { transform, colorMap: colorMap2, showSolderMask } = ctx;
3838
+ const width = Number(pcbPanel.width);
3839
+ const height = Number(pcbPanel.height);
3840
+ const center = pcbPanel.center ?? { x: width / 2, y: height / 2 };
3841
+ const halfWidth = width / 2;
3842
+ const halfHeight = height / 2;
3843
+ const topLeft = applyToPoint(transform, [
3844
+ center.x - halfWidth,
3845
+ center.y - halfHeight
3846
+ ]);
3847
+ const topRight = applyToPoint(transform, [
3848
+ center.x + halfWidth,
3849
+ center.y - halfHeight
3850
+ ]);
3851
+ const bottomRight = applyToPoint(transform, [
3852
+ center.x + halfWidth,
3853
+ center.y + halfHeight
3854
+ ]);
3855
+ const bottomLeft = applyToPoint(transform, [
3856
+ center.x - halfWidth,
3857
+ center.y + halfHeight
3858
+ ]);
3859
+ const path = `M ${topLeft[0]} ${topLeft[1]} L ${topRight[0]} ${topRight[1]} L ${bottomRight[0]} ${bottomRight[1]} L ${bottomLeft[0]} ${bottomLeft[1]} Z`;
3860
+ const isCoveredWithSolderMask = pcbPanel.covered_with_solder_mask !== false;
3861
+ const shouldShowSolderMask = Boolean(
3862
+ showSolderMask && isCoveredWithSolderMask
3863
+ );
3864
+ return [
3865
+ {
3866
+ name: "path",
3867
+ type: "element",
3868
+ value: "",
3869
+ children: [],
3870
+ attributes: {
3871
+ class: "pcb-panel",
3872
+ d: path,
3873
+ fill: "none",
3874
+ stroke: colorMap2.boardOutline,
3875
+ "stroke-width": (0.1 * Math.abs(transform.a)).toString(),
3876
+ "data-type": "pcb_panel",
3877
+ "data-pcb-layer": "board"
3878
+ }
3879
+ }
3880
+ ];
3881
+ }
3882
+ function createSvgObjectsFromPcbVia(hole, ctx) {
3883
+ const { transform, colorMap: colorMap2 } = ctx;
3884
+ const [x, y] = applyToPoint(transform, [hole.x, hole.y]);
3885
+ const scaledOuterWidth = hole.outer_diameter * Math.abs(transform.a);
3886
+ const scaledOuterHeight = hole.outer_diameter * Math.abs(transform.a);
3887
+ const scaledHoleWidth = hole.hole_diameter * Math.abs(transform.a);
3888
+ const scaledHoleHeight = hole.hole_diameter * Math.abs(transform.a);
3889
+ const outerRadius = Math.min(scaledOuterWidth, scaledOuterHeight) / 2;
3890
+ const innerRadius = Math.min(scaledHoleWidth, scaledHoleHeight) / 2;
3891
+ return {
3892
+ name: "g",
3893
+ type: "element",
3894
+ attributes: {
3895
+ "data-type": "pcb_via",
3896
+ "data-pcb-layer": "through"
3897
+ },
3898
+ children: [
3899
+ {
3900
+ name: "circle",
3901
+ type: "element",
3902
+ attributes: {
3903
+ class: "pcb-hole-outer",
3904
+ fill: colorMap2.copper.top,
3905
+ cx: x.toString(),
3906
+ cy: y.toString(),
3907
+ r: outerRadius.toString(),
3908
+ "data-type": "pcb_via",
3909
+ "data-pcb-layer": "top"
3910
+ }
3911
+ },
3912
+ {
3913
+ name: "circle",
3914
+ type: "element",
3915
+ attributes: {
3916
+ class: "pcb-hole-inner",
3917
+ fill: colorMap2.drill,
3918
+ cx: x.toString(),
3919
+ cy: y.toString(),
3920
+ r: innerRadius.toString(),
3921
+ "data-type": "pcb_via",
3922
+ "data-pcb-layer": "drill"
3923
+ }
3924
+ }
3925
+ ]
3608
3926
  };
3609
3927
  }
3610
3928
  function createSvgObjectsFromPcbHole(hole, ctx) {
@@ -4566,390 +4884,89 @@ function createSvgObjectsForPcbGrid({
4566
4884
  fill: "none",
4567
4885
  stroke: gridLineColor,
4568
4886
  "stroke-width": "1",
4569
- "shape-rendering": "crispEdges"
4570
- },
4571
- children: []
4572
- }
4573
- ];
4574
- const defs = {
4575
- name: "defs",
4576
- type: "element",
4577
- value: "",
4578
- attributes: {},
4579
- children: [
4580
- {
4581
- name: "pattern",
4582
- type: "element",
4583
- value: "",
4584
- attributes: {
4585
- id: GRID_PATTERN_ID,
4586
- width: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4587
- height: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4588
- patternUnits: "userSpaceOnUse"
4589
- },
4590
- children: patternChildren
4591
- }
4592
- ]
4593
- };
4594
- const rect = {
4595
- name: "rect",
4596
- type: "element",
4597
- value: "",
4598
- attributes: {
4599
- x: "0",
4600
- y: "0",
4601
- width: svgWidth.toString(),
4602
- height: svgHeight.toString(),
4603
- fill: `url(#${GRID_PATTERN_ID})`,
4604
- "pointer-events": "none",
4605
- "data-type": "pcb_grid",
4606
- "data-pcb-layer": "global"
4607
- },
4608
- children: []
4609
- };
4610
- return { defs, rect };
4611
- }
4612
- function createMajorGridPatternChildren(cellSize, majorCellSize, lineColor, majorLineColor) {
4613
- const children = [];
4614
- const steps = Math.round(majorCellSize / cellSize);
4615
- for (let step = 0; step < steps; step += 1) {
4616
- const offset = Number((step * cellSize).toFixed(6));
4617
- const offsetString = offset.toString();
4618
- const color = step === 0 ? majorLineColor : lineColor;
4619
- const majorSizeString = majorCellSize.toString();
4620
- children.push({
4621
- name: "line",
4622
- type: "element",
4623
- value: "",
4624
- attributes: {
4625
- x1: offsetString,
4626
- y1: "0",
4627
- x2: offsetString,
4628
- y2: majorSizeString,
4629
- stroke: color,
4630
- "stroke-width": "1",
4631
- "shape-rendering": "crispEdges"
4632
- },
4633
- children: []
4634
- });
4635
- children.push({
4636
- name: "line",
4637
- type: "element",
4638
- value: "",
4639
- attributes: {
4640
- x1: "0",
4641
- y1: offsetString,
4642
- x2: majorSizeString,
4643
- y2: offsetString,
4644
- stroke: color,
4645
- "stroke-width": "1",
4646
- "shape-rendering": "crispEdges"
4647
- },
4648
- children: []
4649
- });
4650
- }
4651
- return children;
4652
- }
4653
- var OFFSET_THRESHOLD_MM = 0.01;
4654
- var TICK_SIZE_PX = 4;
4655
- var LABEL_GAP_PX = 8;
4656
- var LABEL_FONT_SIZE_PX = 11;
4657
- var STROKE_WIDTH_PX = 1;
4658
- var ANCHOR_MARKER_SIZE_PX = 5;
4659
- var ANCHOR_MARKER_STROKE_WIDTH_PX = 1.5;
4660
- var COMPONENT_GAP_PX = 15;
4661
- var COMPONENT_SIDE_GAP_PX = 10;
4662
- var DISTANCE_MULTIPLIER = 0.2;
4663
- var MAX_OFFSET_PX = 50;
4664
- function createAnchorOffsetIndicators(params) {
4665
- const {
4666
- groupAnchorPosition,
4667
- componentPosition,
4668
- transform,
4669
- componentWidth = 0,
4670
- componentHeight = 0
4671
- } = params;
4672
- const objects = [];
4673
- const [screenGroupAnchorX, screenGroupAnchorY] = applyToPoint(transform, [
4674
- groupAnchorPosition.x,
4675
- groupAnchorPosition.y
4676
- ]);
4677
- const [screenComponentX, screenComponentY] = applyToPoint(transform, [
4678
- componentPosition.x,
4679
- componentPosition.y
4680
- ]);
4681
- const offsetX = componentPosition.x - groupAnchorPosition.x;
4682
- const offsetY = componentPosition.y - groupAnchorPosition.y;
4683
- const scale9 = Math.abs(transform.a);
4684
- const screenComponentWidth = componentWidth * scale9;
4685
- const screenComponentHeight = componentHeight * scale9;
4686
- objects.push(createAnchorMarker(screenGroupAnchorX, screenGroupAnchorY));
4687
- objects.push({
4688
- name: "line",
4689
- type: "element",
4690
- attributes: {
4691
- x1: screenGroupAnchorX.toString(),
4692
- y1: screenGroupAnchorY.toString(),
4693
- x2: screenComponentX.toString(),
4694
- y2: screenComponentY.toString(),
4695
- stroke: "#ffffff",
4696
- "stroke-width": "0.5",
4697
- "stroke-dasharray": "3,3",
4698
- opacity: "0.5",
4699
- class: "anchor-offset-connector"
4700
- },
4701
- children: [],
4702
- value: ""
4703
- });
4704
- objects.push({
4705
- name: "circle",
4706
- type: "element",
4707
- attributes: {
4708
- cx: screenComponentX.toString(),
4709
- cy: screenComponentY.toString(),
4710
- r: "2",
4711
- fill: "#ffffff",
4712
- opacity: "0.7",
4713
- class: "anchor-offset-component-marker"
4714
- },
4715
- children: [],
4716
- value: ""
4717
- });
4718
- const yDistance = Math.abs(screenComponentY - screenGroupAnchorY);
4719
- const xDistance = Math.abs(screenComponentX - screenGroupAnchorX);
4720
- const totalDistance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
4721
- const componentHeightOffset = screenComponentHeight / 2 + COMPONENT_GAP_PX;
4722
- const dynamicOffset = Math.max(
4723
- componentHeightOffset,
4724
- Math.min(MAX_OFFSET_PX, totalDistance * DISTANCE_MULTIPLIER)
4725
- );
4726
- const horizontalLineY = offsetY > 0 ? screenComponentY - dynamicOffset : screenComponentY + dynamicOffset;
4727
- const componentWidthOffset = screenComponentWidth / 2 + COMPONENT_SIDE_GAP_PX;
4728
- const verticalLineX = offsetX > 0 ? screenComponentX + componentWidthOffset : screenComponentX - componentWidthOffset;
4729
- if (Math.abs(offsetX) > OFFSET_THRESHOLD_MM) {
4730
- objects.push(
4731
- ...createHorizontalDimension({
4732
- startX: screenGroupAnchorX,
4733
- endX: screenComponentX,
4734
- y: horizontalLineY,
4735
- offsetMm: offsetX,
4736
- offsetY
4737
- })
4738
- );
4739
- }
4740
- if (Math.abs(offsetY) > OFFSET_THRESHOLD_MM) {
4741
- objects.push(
4742
- ...createVerticalDimension({
4743
- x: verticalLineX,
4744
- startY: screenGroupAnchorY,
4745
- endY: screenComponentY,
4746
- offsetMm: -offsetY,
4747
- offsetX
4748
- })
4749
- );
4750
- }
4751
- return objects;
4752
- }
4753
- function createAnchorMarker(x, y) {
4754
- return {
4755
- name: "g",
4887
+ "shape-rendering": "crispEdges"
4888
+ },
4889
+ children: []
4890
+ }
4891
+ ];
4892
+ const defs = {
4893
+ name: "defs",
4756
4894
  type: "element",
4757
- attributes: {
4758
- class: "anchor-offset-marker",
4759
- "data-type": "anchor_offset_marker"
4760
- },
4895
+ value: "",
4896
+ attributes: {},
4761
4897
  children: [
4762
4898
  {
4763
- name: "line",
4764
- type: "element",
4765
- attributes: {
4766
- x1: x.toString(),
4767
- y1: (y - ANCHOR_MARKER_SIZE_PX).toString(),
4768
- x2: x.toString(),
4769
- y2: (y + ANCHOR_MARKER_SIZE_PX).toString(),
4770
- stroke: "#ffffff",
4771
- "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
4772
- "stroke-linecap": "round"
4773
- },
4774
- children: [],
4775
- value: ""
4776
- },
4777
- {
4778
- name: "line",
4899
+ name: "pattern",
4779
4900
  type: "element",
4901
+ value: "",
4780
4902
  attributes: {
4781
- x1: (x - ANCHOR_MARKER_SIZE_PX).toString(),
4782
- y1: y.toString(),
4783
- x2: (x + ANCHOR_MARKER_SIZE_PX).toString(),
4784
- y2: y.toString(),
4785
- stroke: "#ffffff",
4786
- "stroke-width": ANCHOR_MARKER_STROKE_WIDTH_PX.toString(),
4787
- "stroke-linecap": "round"
4903
+ id: GRID_PATTERN_ID,
4904
+ width: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4905
+ height: hasMajorGrid ? majorCellSize.toString() : gridCellSize.toString(),
4906
+ patternUnits: "userSpaceOnUse"
4788
4907
  },
4789
- children: [],
4790
- value: ""
4908
+ children: patternChildren
4791
4909
  }
4792
- ],
4793
- value: ""
4910
+ ]
4794
4911
  };
4795
- }
4796
- function createHorizontalDimension({
4797
- startX,
4798
- endX,
4799
- y,
4800
- offsetMm,
4801
- offsetY
4802
- }) {
4803
- const objects = [];
4804
- objects.push({
4805
- name: "line",
4806
- type: "element",
4807
- attributes: {
4808
- x1: startX.toString(),
4809
- y1: y.toString(),
4810
- x2: endX.toString(),
4811
- y2: y.toString(),
4812
- stroke: "#ffffff",
4813
- "stroke-width": STROKE_WIDTH_PX.toString(),
4814
- class: "anchor-offset-dimension-x"
4815
- },
4816
- children: [],
4817
- value: ""
4818
- });
4819
- objects.push({
4820
- name: "line",
4821
- type: "element",
4822
- attributes: {
4823
- x1: startX.toString(),
4824
- y1: (y - TICK_SIZE_PX).toString(),
4825
- x2: startX.toString(),
4826
- y2: (y + TICK_SIZE_PX).toString(),
4827
- stroke: "#ffffff",
4828
- "stroke-width": STROKE_WIDTH_PX.toString()
4829
- },
4830
- children: [],
4831
- value: ""
4832
- });
4833
- objects.push({
4834
- name: "line",
4835
- type: "element",
4836
- attributes: {
4837
- x1: endX.toString(),
4838
- y1: (y - TICK_SIZE_PX).toString(),
4839
- x2: endX.toString(),
4840
- y2: (y + TICK_SIZE_PX).toString(),
4841
- stroke: "#ffffff",
4842
- "stroke-width": STROKE_WIDTH_PX.toString()
4843
- },
4844
- children: [],
4845
- value: ""
4846
- });
4847
- const midX = (startX + endX) / 2;
4848
- const labelY = offsetY > 0 ? y - TICK_SIZE_PX - LABEL_GAP_PX : y + TICK_SIZE_PX + LABEL_GAP_PX;
4849
- objects.push({
4850
- name: "text",
4912
+ const rect = {
4913
+ name: "rect",
4851
4914
  type: "element",
4915
+ value: "",
4852
4916
  attributes: {
4853
- x: midX.toString(),
4854
- y: labelY.toString(),
4855
- fill: "#ffffff",
4856
- "font-size": LABEL_FONT_SIZE_PX.toString(),
4857
- "font-family": "Arial, sans-serif",
4858
- "text-anchor": "middle",
4859
- "dominant-baseline": offsetY > 0 ? "baseline" : "hanging",
4860
- class: "anchor-offset-label"
4917
+ x: "0",
4918
+ y: "0",
4919
+ width: svgWidth.toString(),
4920
+ height: svgHeight.toString(),
4921
+ fill: `url(#${GRID_PATTERN_ID})`,
4922
+ "pointer-events": "none",
4923
+ "data-type": "pcb_grid",
4924
+ "data-pcb-layer": "global"
4861
4925
  },
4862
- children: [
4863
- {
4864
- type: "text",
4865
- value: `X: ${offsetMm.toFixed(2)}mm`,
4866
- name: "",
4867
- attributes: {},
4868
- children: []
4869
- }
4870
- ],
4871
- value: ""
4872
- });
4873
- return objects;
4926
+ children: []
4927
+ };
4928
+ return { defs, rect };
4874
4929
  }
4875
- function createVerticalDimension({
4876
- x,
4877
- startY,
4878
- endY,
4879
- offsetMm,
4880
- offsetX
4881
- }) {
4882
- const objects = [];
4883
- objects.push({
4884
- name: "line",
4885
- type: "element",
4886
- attributes: {
4887
- x1: x.toString(),
4888
- y1: startY.toString(),
4889
- x2: x.toString(),
4890
- y2: endY.toString(),
4891
- stroke: "#ffffff",
4892
- "stroke-width": STROKE_WIDTH_PX.toString(),
4893
- class: "anchor-offset-dimension-y"
4894
- },
4895
- children: [],
4896
- value: ""
4897
- });
4898
- objects.push({
4899
- name: "line",
4900
- type: "element",
4901
- attributes: {
4902
- x1: (x - TICK_SIZE_PX).toString(),
4903
- y1: startY.toString(),
4904
- x2: (x + TICK_SIZE_PX).toString(),
4905
- y2: startY.toString(),
4906
- stroke: "#ffffff",
4907
- "stroke-width": STROKE_WIDTH_PX.toString()
4908
- },
4909
- children: [],
4910
- value: ""
4911
- });
4912
- objects.push({
4913
- name: "line",
4914
- type: "element",
4915
- attributes: {
4916
- x1: (x - TICK_SIZE_PX).toString(),
4917
- y1: endY.toString(),
4918
- x2: (x + TICK_SIZE_PX).toString(),
4919
- y2: endY.toString(),
4920
- stroke: "#ffffff",
4921
- "stroke-width": STROKE_WIDTH_PX.toString()
4922
- },
4923
- children: [],
4924
- value: ""
4925
- });
4926
- const midY = (startY + endY) / 2;
4927
- const labelX = offsetX < 0 ? x - TICK_SIZE_PX - 4 : x + TICK_SIZE_PX + 4;
4928
- objects.push({
4929
- name: "text",
4930
- type: "element",
4931
- attributes: {
4932
- x: labelX.toString(),
4933
- y: midY.toString(),
4934
- fill: "#ffffff",
4935
- "font-size": LABEL_FONT_SIZE_PX.toString(),
4936
- "font-family": "Arial, sans-serif",
4937
- "text-anchor": offsetX < 0 ? "end" : "start",
4938
- "dominant-baseline": "middle",
4939
- class: "anchor-offset-label"
4940
- },
4941
- children: [
4942
- {
4943
- type: "text",
4944
- value: `Y: ${offsetMm.toFixed(2)}mm`,
4945
- name: "",
4946
- attributes: {},
4947
- children: []
4948
- }
4949
- ],
4950
- value: ""
4951
- });
4952
- return objects;
4930
+ function createMajorGridPatternChildren(cellSize, majorCellSize, lineColor, majorLineColor) {
4931
+ const children = [];
4932
+ const steps = Math.round(majorCellSize / cellSize);
4933
+ for (let step = 0; step < steps; step += 1) {
4934
+ const offset = Number((step * cellSize).toFixed(6));
4935
+ const offsetString = offset.toString();
4936
+ const color = step === 0 ? majorLineColor : lineColor;
4937
+ const majorSizeString = majorCellSize.toString();
4938
+ children.push({
4939
+ name: "line",
4940
+ type: "element",
4941
+ value: "",
4942
+ attributes: {
4943
+ x1: offsetString,
4944
+ y1: "0",
4945
+ x2: offsetString,
4946
+ y2: majorSizeString,
4947
+ stroke: color,
4948
+ "stroke-width": "1",
4949
+ "shape-rendering": "crispEdges"
4950
+ },
4951
+ children: []
4952
+ });
4953
+ children.push({
4954
+ name: "line",
4955
+ type: "element",
4956
+ value: "",
4957
+ attributes: {
4958
+ x1: "0",
4959
+ y1: offsetString,
4960
+ x2: majorSizeString,
4961
+ y2: offsetString,
4962
+ stroke: color,
4963
+ "stroke-width": "1",
4964
+ "shape-rendering": "crispEdges"
4965
+ },
4966
+ children: []
4967
+ });
4968
+ }
4969
+ return children;
4953
4970
  }
4954
4971
  function createSvgObjectsFromPcbComponent(component, ctx) {
4955
4972
  const { transform, circuitJson } = ctx;
@@ -5091,7 +5108,7 @@ function getSoftwareUsedString(circuitJson) {
5091
5108
  var package_default = {
5092
5109
  name: "circuit-to-svg",
5093
5110
  type: "module",
5094
- version: "0.0.282",
5111
+ version: "0.0.283",
5095
5112
  description: "Convert Circuit JSON to SVG",
5096
5113
  main: "dist/index.js",
5097
5114
  files: [
@@ -5115,12 +5132,12 @@ var package_default = {
5115
5132
  "bun-match-svg": "^0.0.12",
5116
5133
  esbuild: "^0.20.2",
5117
5134
  "performance-now": "^2.1.0",
5118
- "circuit-json": "^0.0.319",
5135
+ "circuit-json": "^0.0.327",
5119
5136
  react: "19.1.0",
5120
5137
  "react-cosmos": "7.0.0",
5121
5138
  "react-cosmos-plugin-vite": "7.0.0",
5122
5139
  "react-dom": "19.1.0",
5123
- tscircuit: "^0.0.937",
5140
+ tscircuit: "^0.0.1018",
5124
5141
  tsup: "^8.0.2",
5125
5142
  typescript: "^5.4.5",
5126
5143
  "vite-tsconfig-paths": "^5.0.1"
@@ -12362,4 +12379,4 @@ export {
12362
12379
  isSimulationTransientVoltageGraph,
12363
12380
  isSimulationVoltageProbe
12364
12381
  };
12365
- //# sourceMappingURL=dist-7RT7ZSAD.js.map
12382
+ //# sourceMappingURL=dist-B53E6C7Z.js.map