circuit-json-to-tscircuit 0.0.92 → 0.0.94
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/{chunk-GAMHGAGS.js → chunk-WQVP4ME2.js} +1100 -166
- package/dist/cli/main.js +3 -7
- package/dist/lib/index.js +1 -1
- package/lib/board-converter/stages/convert-pcb-components.ts +21 -2
- package/lib/generate-board-cad-models-tsx/converter-types.ts +6 -0
- package/lib/generate-board-cad-models-tsx/execute-jscad-operation.ts +7 -0
- package/lib/generate-board-cad-models-tsx/generate-cad-model-group-model-tsx.ts +38 -11
- package/lib/generate-board-cad-models-tsx/generate-cad-model-group-tsx.ts +17 -2
- package/lib/generate-board-cad-models-tsx/generate-jscad-cad-model-prop-tsx.ts +113 -0
- package/lib/generate-board-cad-models-tsx/get-cad-model-placement-attributes.ts +3 -3
- package/lib/generate-board-cad-models-tsx/get-jscad-operation-fit-scale-factors.ts +66 -0
- package/lib/generate-board-cad-models-tsx/get-jscad-operation-in-base-model-frame.ts +179 -0
- package/lib/generate-board-cad-models-tsx/is-jscad-cad-model-group-translucent.ts +15 -0
- package/lib/generate-board-cad-models-tsx/pack-jscad-operations.ts +69 -0
- package/lib/generate-board-schematic-tsx/convert-components.ts +67 -12
- package/lib/generate-board-schematic-tsx/convert-native-symbol-pin-numbers.ts +81 -0
- package/lib/generate-board-schematic-tsx/convert-primitives.ts +28 -5
- package/lib/generate-board-schematic-tsx/convert-symbol-primitives.ts +65 -22
- package/lib/generate-board-schematic-tsx/get-native-symbol-port-matching-inputs.ts +131 -0
- package/lib/generate-board-schematic-tsx/get-native-symbol-text-replacement-candidate.ts +153 -0
- package/lib/generate-board-schematic-tsx/get-native-symbol-text-replacements.ts +82 -0
- package/lib/generate-board-schematic-tsx/get-nearest-schematic-text.ts +104 -0
- package/lib/generate-board-schematic-tsx/get-replaced-schematic-component-ids.ts +21 -0
- package/lib/generate-board-schematic-tsx/get-schematic-primitive-paint.ts +2 -2
- package/lib/generate-board-schematic-tsx/get-schematic-primitives-in-render-order.ts +9 -2
- package/lib/generate-board-schematic-tsx/get-symbol-to-schematic-transform.ts +8 -1
- package/lib/generate-board-schematic-tsx/has-multiple-native-symbol-units.ts +23 -0
- package/lib/generate-board-schematic-tsx/has-preserved-package-value-text.ts +32 -0
- package/lib/generate-board-schematic-tsx/is-pin-designator-for-port.ts +32 -0
- package/lib/generate-board-schematic-tsx/match-symbol-ports-by-pin-identity.ts +9 -1
- package/lib/generate-board-schematic-tsx/resolve-native-schematic-symbol-name.ts +114 -0
- package/package.json +2 -6
- package/tests/board-grouped-jscad-cad-model-fit.test.ts +111 -0
- package/tests/board-grouped-jscad-cad-model.test.ts +28 -38
- package/tests/board-jscad-cad-model.test.ts +12 -2
- package/tests/board-mixed-url-and-jscad-cad-models.test.ts +31 -2
- package/tests/explicit-native-symbol-content.test.ts +60 -0
- package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-roundtrip-schematic-comparison.snap.svg +2 -2
- package/tests/ti-evms/__snapshots__/ti-lm251772evm-pd-roundtrip.test.tsx.snap +16 -20
- package/tests/ti-evms/__snapshots__/ti-lm5155evm-fly-roundtrip-schematic-comparison.snap.svg +1 -1
- package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-roundtrip-schematic-comparison.snap.svg +1 -1
- package/tests/ti-evms/__snapshots__/ti-lmg342x-bb-evm-roundtrip.test.tsx.snap +80 -128
- package/tests/ti-evms/ti-lm5155evm-fly-roundtrip.test.tsx +42 -81
- package/tests/ti-native-symbols.test.ts +528 -0
- package/lib/generate-board-cad-models-tsx/generate-jscad-cad-model-tsx.ts +0 -26
|
@@ -504,9 +504,9 @@ function getCadModelPlacementAttributes({
|
|
|
504
504
|
if (cadComponent.size !== void 0) {
|
|
505
505
|
attributes.push(`size={${formatPointProp(cadComponent.size)}}`);
|
|
506
506
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
507
|
+
attributes.push(
|
|
508
|
+
`showAsTranslucentModel={${cadComponent.show_as_translucent_model === true}}`
|
|
509
|
+
);
|
|
510
510
|
return attributes;
|
|
511
511
|
}
|
|
512
512
|
|
|
@@ -539,48 +539,397 @@ function generateCadModelTsx({
|
|
|
539
539
|
return `<cadmodel ${attributes.join(" ")} />`;
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
-
// lib/generate-board-cad-models-tsx/
|
|
543
|
-
|
|
542
|
+
// lib/generate-board-cad-models-tsx/get-jscad-operation-fit-scale-factors.ts
|
|
543
|
+
import jscad2 from "@jscad/modeling";
|
|
544
|
+
|
|
545
|
+
// lib/generate-board-cad-models-tsx/execute-jscad-operation.ts
|
|
546
|
+
import jscad from "@jscad/modeling";
|
|
547
|
+
import { executeJscadOperations } from "jscad-planner";
|
|
548
|
+
function executeJscadOperation(operation) {
|
|
549
|
+
return executeJscadOperations(jscad, operation);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// lib/generate-board-cad-models-tsx/get-jscad-operation-fit-scale-factors.ts
|
|
553
|
+
var identityScaleFactors = { x: 1, y: 1, z: 1 };
|
|
554
|
+
function getSafeScaleFactor({
|
|
555
|
+
sourceLength,
|
|
556
|
+
targetLength
|
|
557
|
+
}) {
|
|
558
|
+
return sourceLength > 0 ? targetLength / sourceLength : 1;
|
|
559
|
+
}
|
|
560
|
+
function getJscadOperationFitScaleFactors({
|
|
561
|
+
cadComponent,
|
|
562
|
+
operation
|
|
563
|
+
}) {
|
|
564
|
+
if (cadComponent.size === void 0) return identityScaleFactors;
|
|
565
|
+
const geometry = executeJscadOperation(operation);
|
|
566
|
+
if (!jscad2.geometries.geom3.isA(geometry)) return identityScaleFactors;
|
|
567
|
+
const [minimumPoint, maximumPoint] = jscad2.measurements.measureBoundingBox(geometry);
|
|
568
|
+
const modelUnitToMmScaleFactor = cadComponent.model_unit_to_mm_scale_factor ?? 1;
|
|
569
|
+
const axisScaleFactors = {
|
|
570
|
+
x: getSafeScaleFactor({
|
|
571
|
+
sourceLength: maximumPoint[0] - minimumPoint[0],
|
|
572
|
+
targetLength: cadComponent.size.x * modelUnitToMmScaleFactor
|
|
573
|
+
}),
|
|
574
|
+
y: getSafeScaleFactor({
|
|
575
|
+
sourceLength: maximumPoint[1] - minimumPoint[1],
|
|
576
|
+
targetLength: cadComponent.size.y * modelUnitToMmScaleFactor
|
|
577
|
+
}),
|
|
578
|
+
z: getSafeScaleFactor({
|
|
579
|
+
sourceLength: maximumPoint[2] - minimumPoint[2],
|
|
580
|
+
targetLength: cadComponent.size.z * modelUnitToMmScaleFactor
|
|
581
|
+
})
|
|
582
|
+
};
|
|
583
|
+
if (cadComponent.model_object_fit === "fill_bounds") {
|
|
584
|
+
return axisScaleFactors;
|
|
585
|
+
}
|
|
586
|
+
const uniformScaleFactor = Math.min(
|
|
587
|
+
axisScaleFactors.x,
|
|
588
|
+
axisScaleFactors.y,
|
|
589
|
+
axisScaleFactors.z
|
|
590
|
+
);
|
|
591
|
+
return {
|
|
592
|
+
x: uniformScaleFactor,
|
|
593
|
+
y: uniformScaleFactor,
|
|
594
|
+
z: uniformScaleFactor
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
// lib/generate-board-cad-models-tsx/get-jscad-operation-in-base-model-frame.ts
|
|
599
|
+
var degreesToRadians = (angleDegrees) => angleDegrees * Math.PI / 180;
|
|
600
|
+
var getCadComponentRotation = (cadComponent) => cadComponent.rotation ?? { x: 0, y: 0, z: 0 };
|
|
601
|
+
var getModelOriginPosition = (cadComponent) => cadComponent.model_origin_position ?? { x: 0, y: 0, z: 0 };
|
|
602
|
+
var getBoardNormalRotation = (cadComponent) => {
|
|
603
|
+
switch (cadComponent.model_board_normal_direction ?? "z+") {
|
|
604
|
+
case "x+":
|
|
605
|
+
return { x: 0, y: -90, z: 0 };
|
|
606
|
+
case "x-":
|
|
607
|
+
return { x: 0, y: 90, z: 0 };
|
|
608
|
+
case "y+":
|
|
609
|
+
return { x: 90, y: 0, z: 0 };
|
|
610
|
+
case "y-":
|
|
611
|
+
return { x: -90, y: 0, z: 0 };
|
|
612
|
+
case "z-":
|
|
613
|
+
return { x: 180, y: 0, z: 0 };
|
|
614
|
+
case "z+":
|
|
615
|
+
return { x: 0, y: 0, z: 0 };
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
var rotateOperation = ({
|
|
619
|
+
operation,
|
|
620
|
+
rotationDegrees
|
|
621
|
+
}) => {
|
|
622
|
+
let rotatedOperation = operation;
|
|
623
|
+
for (const [axis, angleDegrees] of [
|
|
624
|
+
["Z", rotationDegrees.z],
|
|
625
|
+
["Y", rotationDegrees.y],
|
|
626
|
+
["X", rotationDegrees.x]
|
|
627
|
+
]) {
|
|
628
|
+
if (angleDegrees === 0) continue;
|
|
629
|
+
rotatedOperation = {
|
|
630
|
+
type: `rotate${axis}`,
|
|
631
|
+
angle: degreesToRadians(angleDegrees),
|
|
632
|
+
shape: rotatedOperation
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
return rotatedOperation;
|
|
636
|
+
};
|
|
637
|
+
var rotateOperationByInverse = ({
|
|
638
|
+
operation,
|
|
639
|
+
rotationDegrees
|
|
640
|
+
}) => {
|
|
641
|
+
let rotatedOperation = operation;
|
|
642
|
+
for (const [axis, angleDegrees] of [
|
|
643
|
+
["X", rotationDegrees.x],
|
|
644
|
+
["Y", rotationDegrees.y],
|
|
645
|
+
["Z", rotationDegrees.z]
|
|
646
|
+
]) {
|
|
647
|
+
if (angleDegrees === 0) continue;
|
|
648
|
+
rotatedOperation = {
|
|
649
|
+
type: `rotate${axis}`,
|
|
650
|
+
angle: degreesToRadians(-angleDegrees),
|
|
651
|
+
shape: rotatedOperation
|
|
652
|
+
};
|
|
653
|
+
}
|
|
654
|
+
return rotatedOperation;
|
|
655
|
+
};
|
|
656
|
+
var translateOperation = ({
|
|
657
|
+
operation,
|
|
658
|
+
translation
|
|
659
|
+
}) => {
|
|
660
|
+
if (translation.x === 0 && translation.y === 0 && translation.z === 0) {
|
|
661
|
+
return operation;
|
|
662
|
+
}
|
|
663
|
+
return {
|
|
664
|
+
type: "translate",
|
|
665
|
+
vector: [translation.x, translation.y, translation.z],
|
|
666
|
+
shape: operation
|
|
667
|
+
};
|
|
668
|
+
};
|
|
669
|
+
var scaleOperation = ({
|
|
670
|
+
operation,
|
|
671
|
+
scaleFactors
|
|
672
|
+
}) => {
|
|
673
|
+
if (scaleFactors.x === 1 && scaleFactors.y === 1 && scaleFactors.z === 1) {
|
|
674
|
+
return operation;
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
type: "scale",
|
|
678
|
+
factors: [scaleFactors.x, scaleFactors.y, scaleFactors.z],
|
|
679
|
+
shape: operation
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
function getJscadOperationInBaseModelFrame({
|
|
683
|
+
baseCadComponent,
|
|
684
|
+
basePositionOffset,
|
|
685
|
+
cadComponent,
|
|
686
|
+
positionOffset
|
|
687
|
+
}) {
|
|
688
|
+
if (cadComponent.model_jscad === void 0) return void 0;
|
|
689
|
+
const modelOriginPosition = getModelOriginPosition(cadComponent);
|
|
690
|
+
const cadRotationDegrees = getCadComponentRotation(cadComponent);
|
|
691
|
+
const baseCadRotationDegrees = getCadComponentRotation(baseCadComponent);
|
|
692
|
+
const modelUnitToMmScaleFactor = cadComponent.model_unit_to_mm_scale_factor ?? 1;
|
|
693
|
+
let operation = cadComponent.model_jscad;
|
|
694
|
+
operation = scaleOperation({
|
|
695
|
+
operation,
|
|
696
|
+
scaleFactors: {
|
|
697
|
+
x: modelUnitToMmScaleFactor,
|
|
698
|
+
y: modelUnitToMmScaleFactor,
|
|
699
|
+
z: modelUnitToMmScaleFactor
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
operation = translateOperation({
|
|
703
|
+
operation,
|
|
704
|
+
translation: {
|
|
705
|
+
x: -modelOriginPosition.x,
|
|
706
|
+
y: -modelOriginPosition.y,
|
|
707
|
+
z: -modelOriginPosition.z
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
operation = rotateOperation({
|
|
711
|
+
operation,
|
|
712
|
+
rotationDegrees: getBoardNormalRotation(cadComponent)
|
|
713
|
+
});
|
|
714
|
+
operation = scaleOperation({
|
|
715
|
+
operation,
|
|
716
|
+
scaleFactors: getJscadOperationFitScaleFactors({
|
|
717
|
+
cadComponent,
|
|
718
|
+
operation
|
|
719
|
+
})
|
|
720
|
+
});
|
|
721
|
+
operation = rotateOperation({
|
|
722
|
+
operation,
|
|
723
|
+
rotationDegrees: cadRotationDegrees
|
|
724
|
+
});
|
|
725
|
+
operation = translateOperation({
|
|
726
|
+
operation,
|
|
727
|
+
translation: {
|
|
728
|
+
x: positionOffset.x - basePositionOffset.x,
|
|
729
|
+
y: positionOffset.y - basePositionOffset.y,
|
|
730
|
+
z: positionOffset.z - basePositionOffset.z
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
return rotateOperationByInverse({
|
|
734
|
+
operation,
|
|
735
|
+
rotationDegrees: baseCadRotationDegrees
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
// lib/generate-board-cad-models-tsx/pack-jscad-operations.ts
|
|
740
|
+
import jscad3 from "@jscad/modeling";
|
|
741
|
+
import "jscad-planner";
|
|
742
|
+
var copyPolygon = ({
|
|
743
|
+
polygon,
|
|
744
|
+
geometryColor
|
|
745
|
+
}) => ({
|
|
746
|
+
vertices: polygon.vertices.map(([x, y, z]) => [x, y, z]),
|
|
747
|
+
color: polygon.color ?? geometryColor
|
|
748
|
+
});
|
|
749
|
+
var getPackedJscadSize = (polygons) => {
|
|
750
|
+
const vertices = polygons.flatMap((polygon) => polygon.vertices);
|
|
751
|
+
if (vertices.length === 0) return void 0;
|
|
752
|
+
const [firstVertex, ...remainingVertices] = vertices;
|
|
753
|
+
let minX = firstVertex[0];
|
|
754
|
+
let minY = firstVertex[1];
|
|
755
|
+
let minZ = firstVertex[2];
|
|
756
|
+
let maxX = firstVertex[0];
|
|
757
|
+
let maxY = firstVertex[1];
|
|
758
|
+
let maxZ = firstVertex[2];
|
|
759
|
+
for (const [x, y, z] of remainingVertices) {
|
|
760
|
+
minX = Math.min(minX, x);
|
|
761
|
+
minY = Math.min(minY, y);
|
|
762
|
+
minZ = Math.min(minZ, z);
|
|
763
|
+
maxX = Math.max(maxX, x);
|
|
764
|
+
maxY = Math.max(maxY, y);
|
|
765
|
+
maxZ = Math.max(maxZ, z);
|
|
766
|
+
}
|
|
767
|
+
return { x: maxX - minX, y: maxY - minY, z: maxZ - minZ };
|
|
768
|
+
};
|
|
769
|
+
var packJscadOperations = (operations) => {
|
|
770
|
+
const polygons = [];
|
|
771
|
+
for (const operation of operations) {
|
|
772
|
+
const geometry = executeJscadOperation(operation);
|
|
773
|
+
if (!jscad3.geometries.geom3.isA(geometry)) return void 0;
|
|
774
|
+
polygons.push(
|
|
775
|
+
...jscad3.geometries.geom3.toPolygons(geometry).map(
|
|
776
|
+
(polygon) => copyPolygon({
|
|
777
|
+
polygon,
|
|
778
|
+
geometryColor: geometry.color
|
|
779
|
+
})
|
|
780
|
+
)
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
return {
|
|
784
|
+
jscad: { type: "createGeom3", polygons },
|
|
785
|
+
size: getPackedJscadSize(polygons)
|
|
786
|
+
};
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
// lib/generate-board-cad-models-tsx/generate-jscad-cad-model-prop-tsx.ts
|
|
790
|
+
function generateSingleJscadCadModelPropTsx({
|
|
544
791
|
cadComponent,
|
|
545
792
|
parentPlacement,
|
|
546
793
|
pcbBoard
|
|
547
794
|
}) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
795
|
+
const placement = getCadModelPlacement({
|
|
796
|
+
cadComponent,
|
|
797
|
+
parentPlacement,
|
|
798
|
+
pcbBoard
|
|
799
|
+
});
|
|
800
|
+
const properties = [
|
|
801
|
+
`jscad: ${JSON.stringify(cadComponent.model_jscad)}`,
|
|
802
|
+
`positionOffset: ${formatPointProp(placement.positionOffset)}`,
|
|
803
|
+
`rotationOffset: ${formatPointProp(placement.ccwRotationOffsetDegrees)}`
|
|
804
|
+
];
|
|
805
|
+
const modelOriginPosition = getCadModelOriginPosition(cadComponent);
|
|
806
|
+
if (modelOriginPosition !== void 0) {
|
|
807
|
+
properties.push(
|
|
808
|
+
`modelOriginPosition: ${formatPointProp(modelOriginPosition)}`
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
if (cadComponent.model_unit_to_mm_scale_factor !== void 0) {
|
|
812
|
+
properties.push(
|
|
813
|
+
`modelUnitToMmScale: ${cadComponent.model_unit_to_mm_scale_factor}`
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
if (cadComponent.model_board_normal_direction !== void 0) {
|
|
817
|
+
properties.push(
|
|
818
|
+
`modelBoardNormalDirection: ${JSON.stringify(cadComponent.model_board_normal_direction)}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
if (cadComponent.size !== void 0) {
|
|
822
|
+
properties.push(`size: ${formatPointProp(cadComponent.size)}`);
|
|
823
|
+
}
|
|
824
|
+
return `{ ${properties.join(", ")} }`;
|
|
825
|
+
}
|
|
826
|
+
function generateJscadCadModelPropTsx({
|
|
827
|
+
cadComponents,
|
|
828
|
+
parentPlacement,
|
|
829
|
+
pcbBoard
|
|
830
|
+
}) {
|
|
831
|
+
const baseCadComponent = cadComponents[0];
|
|
832
|
+
if (!baseCadComponent || baseCadComponent.model_jscad === void 0) {
|
|
833
|
+
return void 0;
|
|
834
|
+
}
|
|
835
|
+
if (cadComponents.length === 1) {
|
|
836
|
+
return generateSingleJscadCadModelPropTsx({
|
|
837
|
+
cadComponent: baseCadComponent,
|
|
838
|
+
parentPlacement,
|
|
839
|
+
pcbBoard
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
const basePlacement = getCadModelPlacement({
|
|
843
|
+
cadComponent: baseCadComponent,
|
|
844
|
+
parentPlacement,
|
|
845
|
+
pcbBoard
|
|
846
|
+
});
|
|
847
|
+
const shapes = cadComponents.flatMap((cadComponent) => {
|
|
848
|
+
const placement = getCadModelPlacement({
|
|
552
849
|
cadComponent,
|
|
553
850
|
parentPlacement,
|
|
554
851
|
pcbBoard
|
|
555
|
-
})
|
|
852
|
+
});
|
|
853
|
+
const operation = getJscadOperationInBaseModelFrame({
|
|
854
|
+
baseCadComponent,
|
|
855
|
+
basePositionOffset: basePlacement.positionOffset,
|
|
856
|
+
cadComponent,
|
|
857
|
+
positionOffset: placement.positionOffset
|
|
858
|
+
});
|
|
859
|
+
return operation ? [operation] : [];
|
|
860
|
+
});
|
|
861
|
+
if (shapes.length === 0) return void 0;
|
|
862
|
+
const packedJscadOperations = packJscadOperations(shapes);
|
|
863
|
+
const jscad4 = packedJscadOperations?.jscad ?? {
|
|
864
|
+
type: "union",
|
|
865
|
+
shapes
|
|
866
|
+
};
|
|
867
|
+
const properties = [
|
|
868
|
+
`jscad: ${JSON.stringify(jscad4)}`,
|
|
869
|
+
`positionOffset: ${formatPointProp(basePlacement.positionOffset)}`,
|
|
870
|
+
`rotationOffset: ${formatPointProp(basePlacement.ccwRotationOffsetDegrees)}`,
|
|
871
|
+
`modelOriginPosition: ${formatPointProp({ x: 0, y: 0, z: 0 })}`,
|
|
872
|
+
"modelUnitToMmScale: 1",
|
|
873
|
+
'modelBoardNormalDirection: "z+"'
|
|
556
874
|
];
|
|
557
|
-
|
|
875
|
+
if (packedJscadOperations?.size !== void 0) {
|
|
876
|
+
properties.push(`size: ${formatPointProp(packedJscadOperations.size)}`);
|
|
877
|
+
}
|
|
878
|
+
return `{ ${properties.join(", ")} }`;
|
|
558
879
|
}
|
|
559
880
|
|
|
560
881
|
// lib/generate-board-cad-models-tsx/generate-cad-model-group-model-tsx.ts
|
|
561
|
-
var
|
|
882
|
+
var generateUrlCadModelElementsTsx = ({
|
|
562
883
|
cadModelGroup,
|
|
563
884
|
pcbBoard
|
|
564
885
|
}) => cadModelGroup.cadComponents.flatMap((cadComponent) => {
|
|
565
|
-
|
|
566
|
-
const modelElement =
|
|
886
|
+
if (getCadModelUrl(cadComponent) === void 0) return [];
|
|
887
|
+
const modelElement = generateCadModelTsx({
|
|
567
888
|
cadComponent,
|
|
568
889
|
parentPlacement: cadModelGroup.parentPlacement,
|
|
569
890
|
pcbBoard
|
|
570
891
|
});
|
|
571
892
|
return modelElement ? [modelElement] : [];
|
|
572
893
|
});
|
|
894
|
+
var getJscadCadComponents = (cadModelGroup) => cadModelGroup.cadComponents.filter(
|
|
895
|
+
(cadComponent) => cadComponent.model_jscad !== void 0
|
|
896
|
+
);
|
|
573
897
|
function generateCadModelGroupModelTsx({
|
|
574
898
|
cadModelGroup,
|
|
575
899
|
pcbBoard
|
|
576
900
|
}) {
|
|
577
|
-
const
|
|
901
|
+
const jscadCadComponents = getJscadCadComponents(cadModelGroup);
|
|
902
|
+
if (jscadCadComponents.length > 0) {
|
|
903
|
+
return generateJscadCadModelPropTsx({
|
|
904
|
+
cadComponents: jscadCadComponents,
|
|
905
|
+
parentPlacement: cadModelGroup.parentPlacement,
|
|
906
|
+
pcbBoard
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
const urlCadModelElementsTsx = generateUrlCadModelElementsTsx({
|
|
578
910
|
cadModelGroup,
|
|
579
911
|
pcbBoard
|
|
580
912
|
});
|
|
581
|
-
if (
|
|
582
|
-
if (
|
|
583
|
-
return `<cadassembly>${
|
|
913
|
+
if (urlCadModelElementsTsx.length === 0) return void 0;
|
|
914
|
+
if (urlCadModelElementsTsx.length === 1) return urlCadModelElementsTsx[0];
|
|
915
|
+
return `<cadassembly>${urlCadModelElementsTsx.join("\n")}</cadassembly>`;
|
|
916
|
+
}
|
|
917
|
+
function generateCadModelGroupChildrenTsx({
|
|
918
|
+
cadModelGroup,
|
|
919
|
+
pcbBoard
|
|
920
|
+
}) {
|
|
921
|
+
if (getJscadCadComponents(cadModelGroup).length === 0) return [];
|
|
922
|
+
return generateUrlCadModelElementsTsx({ cadModelGroup, pcbBoard });
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
// lib/generate-board-cad-models-tsx/is-jscad-cad-model-group-translucent.ts
|
|
926
|
+
function isJscadCadModelGroupTranslucent(cadModelGroup) {
|
|
927
|
+
const jscadCadComponents = cadModelGroup.cadComponents.filter(
|
|
928
|
+
(cadComponent) => cadComponent.model_jscad !== void 0
|
|
929
|
+
);
|
|
930
|
+
return jscadCadComponents.length > 0 && jscadCadComponents.every(
|
|
931
|
+
(cadComponent) => cadComponent.show_as_translucent_model === true
|
|
932
|
+
);
|
|
584
933
|
}
|
|
585
934
|
|
|
586
935
|
// lib/generate-board-cad-models-tsx/generate-cad-model-group-tsx.ts
|
|
@@ -606,7 +955,17 @@ function generateCadModelGroupTsx({
|
|
|
606
955
|
"footprint={<footprint />}",
|
|
607
956
|
`cadModel={${cadModelTsx}}`
|
|
608
957
|
];
|
|
609
|
-
|
|
958
|
+
if (isJscadCadModelGroupTranslucent(cadModelGroup)) {
|
|
959
|
+
attributes.push("showAsTranslucentModel");
|
|
960
|
+
}
|
|
961
|
+
const childModelElementsTsx = generateCadModelGroupChildrenTsx({
|
|
962
|
+
cadModelGroup,
|
|
963
|
+
pcbBoard
|
|
964
|
+
});
|
|
965
|
+
if (childModelElementsTsx.length === 0) {
|
|
966
|
+
return `<chip ${attributes.join(" ")} />`;
|
|
967
|
+
}
|
|
968
|
+
return `<chip ${attributes.join(" ")}>${childModelElementsTsx.join("\n")}</chip>`;
|
|
610
969
|
}
|
|
611
970
|
|
|
612
971
|
// lib/board-converter/stages/convert-board-cad-models.ts
|
|
@@ -767,55 +1126,6 @@ ${schematicElements.join("\n")}
|
|
|
767
1126
|
// lib/generate-board-schematic-tsx/convert-primitives.ts
|
|
768
1127
|
import { schematic_text } from "circuit-json";
|
|
769
1128
|
|
|
770
|
-
// lib/generate-board-schematic-tsx/convert-rect.ts
|
|
771
|
-
import {
|
|
772
|
-
applyToPoint,
|
|
773
|
-
compose,
|
|
774
|
-
rotateDEG,
|
|
775
|
-
translate
|
|
776
|
-
} from "transformation-matrix";
|
|
777
|
-
|
|
778
|
-
// lib/generate-board-schematic-tsx/format-attributes.ts
|
|
779
|
-
var formatAttributes = (attributes) => Object.entries(attributes).filter(([, attribute]) => attribute !== void 0 && attribute !== null).map(([name, attribute]) => `${name}={${JSON.stringify(attribute)}}`).join(" ");
|
|
780
|
-
var formatElement = (tagName, attributes) => `<${tagName} ${formatAttributes(attributes)} />`;
|
|
781
|
-
|
|
782
|
-
// lib/generate-board-schematic-tsx/convert-rect.ts
|
|
783
|
-
var DEFAULT_SCHEMATIC_STROKE_WIDTH = 0.02;
|
|
784
|
-
var DASH_LENGTH_TO_STROKE_WIDTH_RATIO = 3;
|
|
785
|
-
var convertRect = ({
|
|
786
|
-
center,
|
|
787
|
-
width,
|
|
788
|
-
height,
|
|
789
|
-
ccwRotationDegrees,
|
|
790
|
-
strokeWidth,
|
|
791
|
-
color,
|
|
792
|
-
fillColor,
|
|
793
|
-
isFilled,
|
|
794
|
-
isDashed
|
|
795
|
-
}) => {
|
|
796
|
-
const rectToSchematicTransform = compose(
|
|
797
|
-
translate(center.x, center.y),
|
|
798
|
-
rotateDEG(ccwRotationDegrees ?? 0)
|
|
799
|
-
);
|
|
800
|
-
const points = [
|
|
801
|
-
{ x: -width / 2, y: -height / 2 },
|
|
802
|
-
{ x: width / 2, y: -height / 2 },
|
|
803
|
-
{ x: width / 2, y: height / 2 },
|
|
804
|
-
{ x: -width / 2, y: height / 2 },
|
|
805
|
-
{ x: -width / 2, y: -height / 2 }
|
|
806
|
-
].map((point) => applyToPoint(rectToSchematicTransform, point));
|
|
807
|
-
const dashLength = isDashed ? (strokeWidth ?? DEFAULT_SCHEMATIC_STROKE_WIDTH) * DASH_LENGTH_TO_STROKE_WIDTH_RATIO : void 0;
|
|
808
|
-
return formatElement("schematicpath", {
|
|
809
|
-
points,
|
|
810
|
-
strokeWidth,
|
|
811
|
-
strokeColor: color,
|
|
812
|
-
fillColor,
|
|
813
|
-
isFilled,
|
|
814
|
-
dashLength,
|
|
815
|
-
dashGap: dashLength
|
|
816
|
-
});
|
|
817
|
-
};
|
|
818
|
-
|
|
819
1129
|
// lib/generate-symbol-tsx.ts
|
|
820
1130
|
import { su } from "@tscircuit/soup-util";
|
|
821
1131
|
var escapeJsxText = (text) => text.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
@@ -1035,46 +1345,381 @@ var generateSymbolTsx = (circuitJson) => {
|
|
|
1035
1345
|
`.trim();
|
|
1036
1346
|
};
|
|
1037
1347
|
|
|
1038
|
-
// lib/generate-board-schematic-tsx/
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1348
|
+
// lib/generate-board-schematic-tsx/convert-rect.ts
|
|
1349
|
+
import {
|
|
1350
|
+
applyToPoint,
|
|
1351
|
+
compose,
|
|
1352
|
+
rotateDEG,
|
|
1353
|
+
translate
|
|
1354
|
+
} from "transformation-matrix";
|
|
1355
|
+
|
|
1356
|
+
// lib/generate-board-schematic-tsx/format-attributes.ts
|
|
1357
|
+
var formatAttributes = (attributes) => Object.entries(attributes).filter(([, attribute]) => attribute !== void 0 && attribute !== null).map(([name, attribute]) => `${name}={${JSON.stringify(attribute)}}`).join(" ");
|
|
1358
|
+
var formatElement = (tagName, attributes) => `<${tagName} ${formatAttributes(attributes)} />`;
|
|
1359
|
+
|
|
1360
|
+
// lib/generate-board-schematic-tsx/convert-rect.ts
|
|
1361
|
+
var DEFAULT_SCHEMATIC_STROKE_WIDTH = 0.02;
|
|
1362
|
+
var DASH_LENGTH_TO_STROKE_WIDTH_RATIO = 3;
|
|
1363
|
+
var convertRect = ({
|
|
1364
|
+
center,
|
|
1365
|
+
width,
|
|
1366
|
+
height,
|
|
1367
|
+
ccwRotationDegrees,
|
|
1368
|
+
strokeWidth,
|
|
1369
|
+
color,
|
|
1370
|
+
fillColor,
|
|
1371
|
+
isFilled,
|
|
1372
|
+
isDashed
|
|
1373
|
+
}) => {
|
|
1374
|
+
const rectToSchematicTransform = compose(
|
|
1375
|
+
translate(center.x, center.y),
|
|
1376
|
+
rotateDEG(ccwRotationDegrees ?? 0)
|
|
1377
|
+
);
|
|
1378
|
+
const points = [
|
|
1379
|
+
{ x: -width / 2, y: -height / 2 },
|
|
1380
|
+
{ x: width / 2, y: -height / 2 },
|
|
1381
|
+
{ x: width / 2, y: height / 2 },
|
|
1382
|
+
{ x: -width / 2, y: height / 2 },
|
|
1383
|
+
{ x: -width / 2, y: -height / 2 }
|
|
1384
|
+
].map((point) => applyToPoint(rectToSchematicTransform, point));
|
|
1385
|
+
const dashLength = isDashed ? (strokeWidth ?? DEFAULT_SCHEMATIC_STROKE_WIDTH) * DASH_LENGTH_TO_STROKE_WIDTH_RATIO : void 0;
|
|
1386
|
+
return formatElement("schematicpath", {
|
|
1387
|
+
points,
|
|
1388
|
+
strokeWidth,
|
|
1389
|
+
strokeColor: color,
|
|
1390
|
+
fillColor,
|
|
1391
|
+
isFilled,
|
|
1392
|
+
dashLength,
|
|
1393
|
+
dashGap: dashLength
|
|
1394
|
+
});
|
|
1395
|
+
};
|
|
1396
|
+
|
|
1397
|
+
// lib/generate-board-schematic-tsx/get-nearest-schematic-text.ts
|
|
1398
|
+
var DEGREES_TO_RADIANS = Math.PI / 180;
|
|
1399
|
+
var distanceFromComponentCenter = ({
|
|
1400
|
+
schematicText,
|
|
1401
|
+
schematicComponent
|
|
1402
|
+
}) => Math.hypot(
|
|
1403
|
+
schematicText.position.x - schematicComponent.center.x,
|
|
1404
|
+
schematicText.position.y - schematicComponent.center.y
|
|
1405
|
+
);
|
|
1406
|
+
var getNearestSchematicText = ({
|
|
1407
|
+
schematicTexts,
|
|
1408
|
+
schematicComponent
|
|
1409
|
+
}) => schematicTexts.toSorted(
|
|
1410
|
+
(firstText, secondText) => distanceFromComponentCenter({
|
|
1411
|
+
schematicText: firstText,
|
|
1412
|
+
schematicComponent
|
|
1413
|
+
}) - distanceFromComponentCenter({
|
|
1414
|
+
schematicText: secondText,
|
|
1415
|
+
schematicComponent
|
|
1416
|
+
})
|
|
1417
|
+
)[0];
|
|
1418
|
+
var getSchematicTextAxisDistances = ({
|
|
1419
|
+
schematicText,
|
|
1420
|
+
schematicComponent
|
|
1421
|
+
}) => {
|
|
1422
|
+
const rotationRadians = schematicText.rotation * DEGREES_TO_RADIANS;
|
|
1423
|
+
const deltaX = schematicComponent.center.x - schematicText.position.x;
|
|
1424
|
+
const deltaY = schematicComponent.center.y - schematicText.position.y;
|
|
1425
|
+
return {
|
|
1426
|
+
alongAxis: deltaX * Math.cos(rotationRadians) + deltaY * Math.sin(rotationRadians),
|
|
1427
|
+
acrossAxis: Math.abs(
|
|
1428
|
+
-deltaX * Math.sin(rotationRadians) + deltaY * Math.cos(rotationRadians)
|
|
1429
|
+
)
|
|
1430
|
+
};
|
|
1431
|
+
};
|
|
1432
|
+
var getSchematicTextAxisRange = ({
|
|
1433
|
+
schematicText,
|
|
1434
|
+
maximumDistance
|
|
1435
|
+
}) => {
|
|
1436
|
+
const maximumTextAdvance = Array.from(schematicText.text).length * schematicText.font_size;
|
|
1437
|
+
if (schematicText.anchor.includes("left")) {
|
|
1438
|
+
return {
|
|
1439
|
+
minimum: -maximumDistance,
|
|
1440
|
+
maximum: maximumTextAdvance + maximumDistance
|
|
1441
|
+
};
|
|
1050
1442
|
}
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
}
|
|
1057
|
-
const component = customComponentById.get(primitive.schematic_component_id);
|
|
1058
|
-
if (component && isCustomComponentBody({ component, rect: primitive })) {
|
|
1059
|
-
componentBodyById.set(primitive.schematic_component_id, primitive);
|
|
1060
|
-
}
|
|
1443
|
+
if (schematicText.anchor.includes("right")) {
|
|
1444
|
+
return {
|
|
1445
|
+
minimum: -maximumTextAdvance - maximumDistance,
|
|
1446
|
+
maximum: maximumDistance
|
|
1447
|
+
};
|
|
1061
1448
|
}
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1449
|
+
return {
|
|
1450
|
+
minimum: -maximumTextAdvance / 2 - maximumDistance,
|
|
1451
|
+
maximum: maximumTextAdvance / 2 + maximumDistance
|
|
1452
|
+
};
|
|
1453
|
+
};
|
|
1454
|
+
var isSchematicTextWithinComponentLabelRange = ({
|
|
1455
|
+
schematicText,
|
|
1456
|
+
schematicComponent,
|
|
1457
|
+
maximumDistance
|
|
1458
|
+
}) => {
|
|
1459
|
+
const distance = getSchematicTextAxisDistances({
|
|
1460
|
+
schematicText,
|
|
1461
|
+
schematicComponent
|
|
1462
|
+
});
|
|
1463
|
+
const textAxisRange = getSchematicTextAxisRange({
|
|
1464
|
+
schematicText,
|
|
1465
|
+
maximumDistance
|
|
1466
|
+
});
|
|
1467
|
+
return distance.alongAxis >= textAxisRange.minimum && distance.alongAxis <= textAxisRange.maximum && distance.acrossAxis <= maximumDistance;
|
|
1468
|
+
};
|
|
1469
|
+
|
|
1470
|
+
// lib/generate-board-schematic-tsx/resolve-native-schematic-symbol-name.ts
|
|
1471
|
+
var normalizePortName = (portName) => portName.toLowerCase().replace(/[^a-z0-9]/gu, "");
|
|
1472
|
+
var hasExactPortNames = (sourcePortNames, expectedPortNames) => sourcePortNames.size === expectedPortNames.length && expectedPortNames.every((portName) => sourcePortNames.has(portName));
|
|
1473
|
+
var resolveNativeSchematicSymbolName = ({
|
|
1474
|
+
circuitJson,
|
|
1475
|
+
schematicComponent
|
|
1476
|
+
}) => {
|
|
1477
|
+
if (schematicComponent.symbol_name) return schematicComponent.symbol_name;
|
|
1478
|
+
const sourceComponent = circuitJson.find(
|
|
1479
|
+
(element) => element.type === "source_component" && element.source_component_id === schematicComponent.source_component_id
|
|
1480
|
+
);
|
|
1481
|
+
if (sourceComponent?.type !== "source_component") return void 0;
|
|
1482
|
+
const sourcePorts = circuitJson.filter(
|
|
1483
|
+
(element) => element.type === "source_port" && element.source_component_id === sourceComponent.source_component_id
|
|
1484
|
+
);
|
|
1485
|
+
const sourcePortNames = new Set(
|
|
1486
|
+
sourcePorts.map((sourcePort) => normalizePortName(sourcePort.name))
|
|
1487
|
+
);
|
|
1488
|
+
const schematicPorts = circuitJson.filter(
|
|
1489
|
+
(element) => element.type === "schematic_port" && element.schematic_component_id === schematicComponent.schematic_component_id
|
|
1490
|
+
);
|
|
1491
|
+
const schematicSourcePortNames = new Set(
|
|
1492
|
+
schematicPorts.flatMap((schematicPort) => {
|
|
1493
|
+
const sourcePort = sourcePorts.find(
|
|
1494
|
+
(candidate) => candidate.source_port_id === schematicPort.source_port_id
|
|
1495
|
+
);
|
|
1496
|
+
return sourcePort ? [normalizePortName(sourcePort.name)] : [];
|
|
1497
|
+
})
|
|
1498
|
+
);
|
|
1499
|
+
const logicPortNames = new Set(
|
|
1500
|
+
[...schematicSourcePortNames].map(
|
|
1501
|
+
(portName) => portName.replace(/^\d+([aby])$/u, "$1")
|
|
1502
|
+
)
|
|
1503
|
+
);
|
|
1504
|
+
const designator = sourceComponent.display_name ?? "";
|
|
1505
|
+
const componentValue = sourceComponent.display_value?.toUpperCase() ?? "";
|
|
1506
|
+
if (componentValue.startsWith("SN74LVC2G08") && hasExactPortNames(logicPortNames, ["a", "b", "y"])) {
|
|
1507
|
+
return "and_gate_right";
|
|
1508
|
+
}
|
|
1509
|
+
if (/^SN74LVC[23]G14/u.test(componentValue) && hasExactPortNames(logicPortNames, ["a", "y"])) {
|
|
1510
|
+
return "schmitt_trigger_inverter_right";
|
|
1511
|
+
}
|
|
1512
|
+
if (designator.startsWith("U") && hasExactPortNames(sourcePortNames, ["a", "k", "c", "e"])) {
|
|
1513
|
+
return "phototransistor_optocoupler_right";
|
|
1514
|
+
}
|
|
1515
|
+
if (designator.startsWith("T") && hasExactPortNames(sourcePortNames, [
|
|
1516
|
+
"1",
|
|
1517
|
+
"2",
|
|
1518
|
+
"3",
|
|
1519
|
+
"5",
|
|
1520
|
+
"6",
|
|
1521
|
+
"7",
|
|
1522
|
+
"9",
|
|
1523
|
+
"10"
|
|
1524
|
+
])) {
|
|
1525
|
+
return "transformer_4_winding_right";
|
|
1526
|
+
}
|
|
1527
|
+
if (designator.startsWith("D") && hasExactPortNames(sourcePortNames, ["1anode", "2cathode", "1cathode2anode"])) {
|
|
1528
|
+
return "dual_series_schottky_diode_right";
|
|
1529
|
+
}
|
|
1530
|
+
return void 0;
|
|
1531
|
+
};
|
|
1532
|
+
|
|
1533
|
+
// lib/generate-board-schematic-tsx/has-multiple-native-symbol-units.ts
|
|
1534
|
+
var hasMultipleNativeSymbolUnits = ({
|
|
1535
|
+
circuitJson,
|
|
1536
|
+
schematicComponent,
|
|
1537
|
+
symbolName
|
|
1538
|
+
}) => circuitJson.filter(
|
|
1539
|
+
(candidate) => candidate.type === "schematic_component" && candidate.source_component_id === schematicComponent.source_component_id && !candidate.symbol_name && resolveNativeSchematicSymbolName({
|
|
1540
|
+
circuitJson,
|
|
1541
|
+
schematicComponent: candidate
|
|
1542
|
+
}) === symbolName
|
|
1543
|
+
).length > 1;
|
|
1544
|
+
|
|
1545
|
+
// lib/generate-board-schematic-tsx/has-preserved-package-value-text.ts
|
|
1546
|
+
var hasPreservedPackageValueText = ({
|
|
1547
|
+
circuitJson,
|
|
1548
|
+
schematicComponent,
|
|
1549
|
+
schematicComponents,
|
|
1550
|
+
replacedSchematicComponentIds,
|
|
1551
|
+
displayTexts
|
|
1552
|
+
}) => circuitJson.some((candidate) => {
|
|
1553
|
+
if (candidate.type !== "schematic_text" || !candidate.schematic_component_id || !displayTexts.has(candidate.text) || replacedSchematicComponentIds.has(candidate.schematic_component_id)) {
|
|
1554
|
+
return false;
|
|
1555
|
+
}
|
|
1556
|
+
return schematicComponents.some(
|
|
1557
|
+
(component) => component.schematic_component_id === candidate.schematic_component_id && component.source_component_id === schematicComponent.source_component_id
|
|
1558
|
+
);
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
// lib/generate-board-schematic-tsx/is-pin-designator-for-port.ts
|
|
1562
|
+
var isPinDesignatorForPort = ({
|
|
1563
|
+
schematicText,
|
|
1564
|
+
schematicPort,
|
|
1565
|
+
schematicComponent
|
|
1566
|
+
}) => {
|
|
1567
|
+
if (schematicText.text !== String(schematicPort.pin_number)) return false;
|
|
1568
|
+
const portToCenter = {
|
|
1569
|
+
x: schematicComponent.center.x - schematicPort.center.x,
|
|
1570
|
+
y: schematicComponent.center.y - schematicPort.center.y
|
|
1571
|
+
};
|
|
1572
|
+
const portToText = {
|
|
1573
|
+
x: schematicText.position.x - schematicPort.center.x,
|
|
1574
|
+
y: schematicText.position.y - schematicPort.center.y
|
|
1575
|
+
};
|
|
1576
|
+
const portDistance = Math.hypot(portToCenter.x, portToCenter.y);
|
|
1577
|
+
const textDistance = Math.hypot(portToText.x, portToText.y);
|
|
1578
|
+
const pointsTowardComponent = portToCenter.x * portToText.x + portToCenter.y * portToText.y >= 0;
|
|
1579
|
+
return pointsTowardComponent && textDistance <= Math.min(0.3, portDistance * 0.6);
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
// lib/generate-board-schematic-tsx/get-native-symbol-text-replacement-candidate.ts
|
|
1583
|
+
var distanceBetween = (firstPoint, secondPoint) => Math.hypot(firstPoint.x - secondPoint.x, firstPoint.y - secondPoint.y);
|
|
1584
|
+
var getNativeSymbolTextReplacementCandidate = (context) => {
|
|
1585
|
+
const { circuitJson, schematicComponent, unownedSchematicTexts } = context;
|
|
1586
|
+
if (schematicComponent.symbol_name) return void 0;
|
|
1587
|
+
const symbolName = resolveNativeSchematicSymbolName({
|
|
1588
|
+
circuitJson,
|
|
1589
|
+
schematicComponent
|
|
1590
|
+
});
|
|
1591
|
+
if (!symbolName) return void 0;
|
|
1592
|
+
const sourceComponent = circuitJson.find(
|
|
1593
|
+
(candidate) => candidate.type === "source_component" && candidate.source_component_id === schematicComponent.source_component_id
|
|
1594
|
+
);
|
|
1595
|
+
const reference = sourceComponent?.display_name ?? sourceComponent?.name;
|
|
1596
|
+
const displayTexts = new Set(
|
|
1597
|
+
[
|
|
1598
|
+
sourceComponent?.display_value,
|
|
1599
|
+
schematicComponent.symbol_display_value
|
|
1600
|
+
].filter((displayText) => Boolean(displayText))
|
|
1601
|
+
);
|
|
1602
|
+
const labelSearchDistance = Math.max(schematicComponent.size.width, schematicComponent.size.height) / 2 + 0.3;
|
|
1603
|
+
const referenceTexts = unownedSchematicTexts.filter(
|
|
1604
|
+
(schematicText) => schematicText.text === reference && distanceBetween(schematicText.position, schematicComponent.center) <= labelSearchDistance
|
|
1605
|
+
);
|
|
1606
|
+
const displayValueTextsInRange = unownedSchematicTexts.filter(
|
|
1607
|
+
(schematicText) => displayTexts.has(schematicText.text) && isSchematicTextWithinComponentLabelRange({
|
|
1608
|
+
schematicText,
|
|
1609
|
+
schematicComponent,
|
|
1610
|
+
maximumDistance: labelSearchDistance
|
|
1611
|
+
})
|
|
1612
|
+
);
|
|
1613
|
+
const nearestDisplayValueText = getNearestSchematicText({
|
|
1614
|
+
schematicTexts: displayValueTextsInRange,
|
|
1615
|
+
schematicComponent
|
|
1616
|
+
});
|
|
1617
|
+
const displayValueTexts = nearestDisplayValueText ? [nearestDisplayValueText] : [];
|
|
1618
|
+
const schematicPorts = circuitJson.filter(
|
|
1619
|
+
(candidate) => candidate.type === "schematic_port" && candidate.schematic_component_id === schematicComponent.schematic_component_id
|
|
1620
|
+
);
|
|
1621
|
+
const replacedPinPortIds = /* @__PURE__ */ new Set();
|
|
1622
|
+
const pinDesignatorTexts = schematicPorts.flatMap((schematicPort) => {
|
|
1623
|
+
const matches = unownedSchematicTexts.filter(
|
|
1624
|
+
(schematicText) => isPinDesignatorForPort({
|
|
1625
|
+
schematicText,
|
|
1626
|
+
schematicPort,
|
|
1627
|
+
schematicComponent
|
|
1628
|
+
})
|
|
1629
|
+
);
|
|
1630
|
+
if (matches.length > 0)
|
|
1631
|
+
replacedPinPortIds.add(schematicPort.schematic_port_id);
|
|
1632
|
+
return matches;
|
|
1633
|
+
});
|
|
1634
|
+
return {
|
|
1635
|
+
schematicComponentId: schematicComponent.schematic_component_id,
|
|
1636
|
+
importedTextIds: new Set(
|
|
1637
|
+
[...referenceTexts, ...displayValueTexts, ...pinDesignatorTexts].map(
|
|
1638
|
+
(schematicText) => schematicText.schematic_text_id
|
|
1639
|
+
)
|
|
1640
|
+
),
|
|
1641
|
+
replacedPinPortIds,
|
|
1642
|
+
replacesReference: referenceTexts.length > 0,
|
|
1643
|
+
includeNativeDisplayText: false,
|
|
1644
|
+
referenceFontSize: getNearestSchematicText({
|
|
1645
|
+
schematicTexts: referenceTexts,
|
|
1646
|
+
schematicComponent
|
|
1647
|
+
})?.font_size,
|
|
1648
|
+
displayTextFontSize: nearestDisplayValueText?.font_size,
|
|
1649
|
+
sourceComponentId: schematicComponent.source_component_id,
|
|
1650
|
+
symbolName,
|
|
1651
|
+
displayValueTextIds: new Set(
|
|
1652
|
+
displayValueTexts.map((schematicText) => schematicText.schematic_text_id)
|
|
1653
|
+
),
|
|
1654
|
+
isMultiUnitSymbol: hasMultipleNativeSymbolUnits({
|
|
1655
|
+
circuitJson,
|
|
1656
|
+
schematicComponent,
|
|
1657
|
+
symbolName
|
|
1658
|
+
}),
|
|
1659
|
+
hasPreservedPackageValueText: hasPreservedPackageValueText({
|
|
1660
|
+
circuitJson,
|
|
1661
|
+
schematicComponent,
|
|
1662
|
+
schematicComponents: context.schematicComponents,
|
|
1663
|
+
replacedSchematicComponentIds: context.replacedSchematicComponentIds,
|
|
1664
|
+
displayTexts
|
|
1665
|
+
})
|
|
1666
|
+
};
|
|
1667
|
+
};
|
|
1668
|
+
|
|
1669
|
+
// lib/generate-board-schematic-tsx/get-replaced-schematic-component-ids.ts
|
|
1670
|
+
import { symbols } from "schematic-symbols";
|
|
1671
|
+
var getReplacedSchematicComponentIds = (circuitJson) => {
|
|
1672
|
+
const replacedSchematicComponentIds = /* @__PURE__ */ new Set();
|
|
1673
|
+
for (const element of circuitJson) {
|
|
1674
|
+
if (element.type !== "schematic_component" || element.symbol_name) continue;
|
|
1675
|
+
const inferredSymbolName = resolveNativeSchematicSymbolName({
|
|
1676
|
+
circuitJson,
|
|
1677
|
+
schematicComponent: element
|
|
1678
|
+
});
|
|
1679
|
+
if (inferredSymbolName && inferredSymbolName in symbols) {
|
|
1680
|
+
replacedSchematicComponentIds.add(element.schematic_component_id);
|
|
1074
1681
|
}
|
|
1075
|
-
if (primitive !== componentBody) result.push(primitive);
|
|
1076
1682
|
}
|
|
1077
|
-
return
|
|
1683
|
+
return replacedSchematicComponentIds;
|
|
1684
|
+
};
|
|
1685
|
+
|
|
1686
|
+
// lib/generate-board-schematic-tsx/get-native-symbol-text-replacements.ts
|
|
1687
|
+
var isFirstUnitWithDisplayValue = ({
|
|
1688
|
+
candidate,
|
|
1689
|
+
allCandidates
|
|
1690
|
+
}) => allCandidates.find(
|
|
1691
|
+
(otherCandidate) => otherCandidate.sourceComponentId === candidate.sourceComponentId && otherCandidate.symbolName === candidate.symbolName && otherCandidate.displayValueTextIds.size > 0
|
|
1692
|
+
)?.schematicComponentId === candidate.schematicComponentId;
|
|
1693
|
+
var getNativeSymbolTextReplacements = (circuitJson) => {
|
|
1694
|
+
const unownedSchematicTexts = circuitJson.filter(
|
|
1695
|
+
(element) => element.type === "schematic_text" && element.schematic_component_id === void 0
|
|
1696
|
+
);
|
|
1697
|
+
const replacedSchematicComponentIds = getReplacedSchematicComponentIds(circuitJson);
|
|
1698
|
+
const schematicComponents = circuitJson.filter(
|
|
1699
|
+
(element) => element.type === "schematic_component"
|
|
1700
|
+
);
|
|
1701
|
+
const candidates = schematicComponents.flatMap((schematicComponent) => {
|
|
1702
|
+
const candidate = getNativeSymbolTextReplacementCandidate({
|
|
1703
|
+
circuitJson,
|
|
1704
|
+
schematicComponent,
|
|
1705
|
+
unownedSchematicTexts,
|
|
1706
|
+
replacedSchematicComponentIds,
|
|
1707
|
+
schematicComponents
|
|
1708
|
+
});
|
|
1709
|
+
return candidate ? [candidate] : [];
|
|
1710
|
+
});
|
|
1711
|
+
return candidates.map((candidate) => ({
|
|
1712
|
+
schematicComponentId: candidate.schematicComponentId,
|
|
1713
|
+
importedTextIds: candidate.importedTextIds,
|
|
1714
|
+
replacedPinPortIds: candidate.replacedPinPortIds,
|
|
1715
|
+
replacesReference: candidate.replacesReference,
|
|
1716
|
+
includeNativeDisplayText: candidate.displayValueTextIds.size > 0 && (!candidate.isMultiUnitSymbol || !candidate.hasPreservedPackageValueText && isFirstUnitWithDisplayValue({
|
|
1717
|
+
candidate,
|
|
1718
|
+
allCandidates: candidates
|
|
1719
|
+
})),
|
|
1720
|
+
referenceFontSize: candidate.referenceFontSize,
|
|
1721
|
+
displayTextFontSize: candidate.displayTextFontSize
|
|
1722
|
+
}));
|
|
1078
1723
|
};
|
|
1079
1724
|
|
|
1080
1725
|
// lib/generate-board-schematic-tsx/get-schematic-primitive-paint.ts
|
|
@@ -1159,14 +1804,71 @@ var getSchematicPrimitivePaint = (primitive) => {
|
|
|
1159
1804
|
};
|
|
1160
1805
|
};
|
|
1161
1806
|
|
|
1807
|
+
// lib/generate-board-schematic-tsx/get-schematic-primitives-in-render-order.ts
|
|
1808
|
+
var isSchematicPrimitive = (element) => element.type === "schematic_text" || element.type === "schematic_path" || element.type === "schematic_rect" || element.type === "schematic_line" || element.type === "schematic_circle" || element.type === "schematic_arc" || element.type === "schematic_box";
|
|
1809
|
+
var isCustomComponentBody = ({
|
|
1810
|
+
component,
|
|
1811
|
+
rect
|
|
1812
|
+
}) => component.is_box_with_pins === false && rect.is_filled && rect.center.x === component.center.x && rect.center.y === component.center.y && rect.width === component.size.width && rect.height === component.size.height;
|
|
1813
|
+
var getSchematicPrimitivesInRenderOrder = (circuitJson, nativeComponentIds = /* @__PURE__ */ new Set()) => {
|
|
1814
|
+
const customComponentById = /* @__PURE__ */ new Map();
|
|
1815
|
+
for (const element of circuitJson) {
|
|
1816
|
+
if (element.type === "schematic_component" && element.is_box_with_pins === false) {
|
|
1817
|
+
customComponentById.set(element.schematic_component_id, element);
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
const primitives = circuitJson.filter(isSchematicPrimitive).filter(
|
|
1821
|
+
(primitive) => !primitive.schematic_component_id || !nativeComponentIds.has(primitive.schematic_component_id)
|
|
1822
|
+
);
|
|
1823
|
+
const componentBodyById = /* @__PURE__ */ new Map();
|
|
1824
|
+
for (const primitive of primitives) {
|
|
1825
|
+
if (primitive.type !== "schematic_rect" || !primitive.schematic_component_id) {
|
|
1826
|
+
continue;
|
|
1827
|
+
}
|
|
1828
|
+
const component = customComponentById.get(primitive.schematic_component_id);
|
|
1829
|
+
if (component && isCustomComponentBody({ component, rect: primitive })) {
|
|
1830
|
+
componentBodyById.set(primitive.schematic_component_id, primitive);
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
const emittedComponentBodies = /* @__PURE__ */ new Set();
|
|
1834
|
+
const result = [];
|
|
1835
|
+
for (const primitive of primitives) {
|
|
1836
|
+
const componentId = primitive.schematic_component_id;
|
|
1837
|
+
const componentBody = componentId ? componentBodyById.get(componentId) : void 0;
|
|
1838
|
+
if (!componentId || !componentBody) {
|
|
1839
|
+
result.push(primitive);
|
|
1840
|
+
continue;
|
|
1841
|
+
}
|
|
1842
|
+
if (!emittedComponentBodies.has(componentId)) {
|
|
1843
|
+
result.push(componentBody);
|
|
1844
|
+
emittedComponentBodies.add(componentId);
|
|
1845
|
+
}
|
|
1846
|
+
if (primitive !== componentBody) result.push(primitive);
|
|
1847
|
+
}
|
|
1848
|
+
return result;
|
|
1849
|
+
};
|
|
1850
|
+
|
|
1162
1851
|
// lib/generate-board-schematic-tsx/convert-primitives.ts
|
|
1852
|
+
var getRenderablePrimitives = (circuitJson) => {
|
|
1853
|
+
const replacedTextIds = new Set(
|
|
1854
|
+
getNativeSymbolTextReplacements(circuitJson).flatMap((replacement) => [
|
|
1855
|
+
...replacement.importedTextIds
|
|
1856
|
+
])
|
|
1857
|
+
);
|
|
1858
|
+
return getSchematicPrimitivesInRenderOrder(
|
|
1859
|
+
circuitJson,
|
|
1860
|
+
getReplacedSchematicComponentIds(circuitJson)
|
|
1861
|
+
).filter(
|
|
1862
|
+
(primitive) => primitive.type !== "schematic_text" || !replacedTextIds.has(primitive.schematic_text_id)
|
|
1863
|
+
);
|
|
1864
|
+
};
|
|
1163
1865
|
var convertPrimitives = (circuitJson) => [
|
|
1164
1866
|
...generateSymbolElements(
|
|
1165
1867
|
circuitJson.filter(
|
|
1166
1868
|
(element) => element.type === "schematic_table" || element.type === "schematic_table_cell"
|
|
1167
1869
|
)
|
|
1168
1870
|
),
|
|
1169
|
-
...
|
|
1871
|
+
...getRenderablePrimitives(circuitJson).flatMap((element) => {
|
|
1170
1872
|
const paint = getSchematicPrimitivePaint(element);
|
|
1171
1873
|
switch (element.type) {
|
|
1172
1874
|
case "schematic_text":
|
|
@@ -1264,7 +1966,7 @@ var convertPrimitives = (circuitJson) => [
|
|
|
1264
1966
|
|
|
1265
1967
|
// lib/generate-board-schematic-tsx/convert-components.ts
|
|
1266
1968
|
import { su as su3 } from "@tscircuit/soup-util";
|
|
1267
|
-
import { symbols } from "schematic-symbols";
|
|
1969
|
+
import { symbols as symbols2 } from "schematic-symbols";
|
|
1268
1970
|
|
|
1269
1971
|
// lib/generate-board-schematic-tsx/get-symbol-to-schematic-transform.ts
|
|
1270
1972
|
import { fromTriangles as fromTriangles2 } from "transformation-matrix";
|
|
@@ -1442,18 +2144,21 @@ var isRigidUniformTransform = (transform) => {
|
|
|
1442
2144
|
};
|
|
1443
2145
|
|
|
1444
2146
|
// lib/generate-board-schematic-tsx/match-symbol-ports-by-pin-identity.ts
|
|
2147
|
+
var getLogicUnitPortAlias = (portName) => portName?.match(/^\d*([aby])$/iu)?.[1]?.toLowerCase();
|
|
1445
2148
|
var matchSymbolPortsByPinIdentity = ({
|
|
1446
2149
|
schematicPorts,
|
|
1447
2150
|
sourcePorts,
|
|
1448
|
-
symbol
|
|
2151
|
+
symbol,
|
|
2152
|
+
includeSchematicPinNumbers = true
|
|
1449
2153
|
}) => symbol.ports.flatMap((symbolPort) => {
|
|
1450
2154
|
const candidates = schematicPorts.filter((schematicPort) => {
|
|
1451
2155
|
const sourcePort = sourcePorts.find(
|
|
1452
2156
|
(port) => port.source_port_id === schematicPort.source_port_id
|
|
1453
2157
|
);
|
|
1454
|
-
const pinNumber = schematicPort.pin_number ?? sourcePort?.pin_number;
|
|
2158
|
+
const pinNumber = includeSchematicPinNumbers ? schematicPort.pin_number ?? sourcePort?.pin_number : sourcePort?.pin_number;
|
|
1455
2159
|
const portIdentities = [
|
|
1456
2160
|
sourcePort?.name,
|
|
2161
|
+
getLogicUnitPortAlias(sourcePort?.name),
|
|
1457
2162
|
...sourcePort?.port_hints ?? [],
|
|
1458
2163
|
...pinNumber === void 0 ? [] : [String(pinNumber), `pin${pinNumber}`]
|
|
1459
2164
|
];
|
|
@@ -1469,12 +2174,17 @@ var getSymbolToSchematicTransform = ({
|
|
|
1469
2174
|
symbol,
|
|
1470
2175
|
schematicComponent,
|
|
1471
2176
|
schematicPorts,
|
|
1472
|
-
sourcePorts
|
|
2177
|
+
sourcePorts,
|
|
2178
|
+
includeSchematicPinNumbers
|
|
1473
2179
|
}) => {
|
|
2180
|
+
const componentSourcePorts = sourcePorts.filter(
|
|
2181
|
+
(sourcePort) => sourcePort.source_component_id === schematicComponent.source_component_id
|
|
2182
|
+
);
|
|
1474
2183
|
const pinIdentityMatches = matchSymbolPortsByPinIdentity({
|
|
1475
2184
|
schematicPorts,
|
|
1476
|
-
sourcePorts,
|
|
1477
|
-
symbol
|
|
2185
|
+
sourcePorts: componentSourcePorts,
|
|
2186
|
+
symbol,
|
|
2187
|
+
includeSchematicPinNumbers
|
|
1478
2188
|
});
|
|
1479
2189
|
const rigidPinIdentityTransform = getRigidPinIdentityTransform(pinIdentityMatches);
|
|
1480
2190
|
if (rigidPinIdentityTransform) return rigidPinIdentityTransform;
|
|
@@ -1510,6 +2220,17 @@ var getSymbolToSchematicTransform = ({
|
|
|
1510
2220
|
import { schematic_text as schematic_text2 } from "circuit-json";
|
|
1511
2221
|
import { applyToPoint as applyToPoint4 } from "transformation-matrix";
|
|
1512
2222
|
var SYMBOL_OUTLINE_STROKE_WIDTH = 0.02;
|
|
2223
|
+
var MINIMUM_FILL_AREA = 1e-12;
|
|
2224
|
+
var pathHasFillArea = (points) => {
|
|
2225
|
+
if (points.length < 3) return false;
|
|
2226
|
+
let doubledArea = 0;
|
|
2227
|
+
for (const [pointIndex, point] of points.entries()) {
|
|
2228
|
+
const nextPoint = points[(pointIndex + 1) % points.length];
|
|
2229
|
+
if (!nextPoint) continue;
|
|
2230
|
+
doubledArea += point.x * nextPoint.y - nextPoint.x * point.y;
|
|
2231
|
+
}
|
|
2232
|
+
return Math.abs(doubledArea) > MINIMUM_FILL_AREA;
|
|
2233
|
+
};
|
|
1513
2234
|
var anchors = {
|
|
1514
2235
|
middle_top: "top_center",
|
|
1515
2236
|
middle_bottom: "bottom_center",
|
|
@@ -1525,8 +2246,13 @@ var convertSymbolPrimitives = ({
|
|
|
1525
2246
|
symbol,
|
|
1526
2247
|
symbolToSchematicTransform,
|
|
1527
2248
|
reference,
|
|
1528
|
-
displayText
|
|
1529
|
-
|
|
2249
|
+
displayText,
|
|
2250
|
+
includeReference = true,
|
|
2251
|
+
includeDisplayText = true,
|
|
2252
|
+
referenceFontSize,
|
|
2253
|
+
displayTextFontSize,
|
|
2254
|
+
filledPrimitiveColor
|
|
2255
|
+
}) => symbol.primitives.flatMap((primitive) => {
|
|
1530
2256
|
if (primitive.type === "path") {
|
|
1531
2257
|
const points = primitive.points.map(
|
|
1532
2258
|
(point) => applyToPoint4(symbolToSchematicTransform, point)
|
|
@@ -1535,19 +2261,25 @@ var convertSymbolPrimitives = ({
|
|
|
1535
2261
|
return formatElement("schematicpath", {
|
|
1536
2262
|
points,
|
|
1537
2263
|
strokeWidth: SYMBOL_OUTLINE_STROKE_WIDTH,
|
|
2264
|
+
fillColor: primitive.fill && pathHasFillArea(points) ? filledPrimitiveColor : void 0,
|
|
1538
2265
|
isFilled: primitive.fill
|
|
1539
2266
|
});
|
|
1540
2267
|
}
|
|
1541
2268
|
const center = applyToPoint4(symbolToSchematicTransform, primitive);
|
|
1542
2269
|
if (primitive.type === "text") {
|
|
2270
|
+
if (!includeReference && primitive.text === "{REF}") return [];
|
|
2271
|
+
if (!includeDisplayText && primitive.text === "{VAL}") return [];
|
|
1543
2272
|
const text = primitive.text === "{REF}" ? reference : primitive.text === "{VAL}" ? displayText : primitive.text;
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
2273
|
+
const importedFontSize = primitive.text === "{REF}" ? referenceFontSize : primitive.text === "{VAL}" ? displayTextFontSize : void 0;
|
|
2274
|
+
return [
|
|
2275
|
+
formatElement("schematictext", {
|
|
2276
|
+
text,
|
|
2277
|
+
schX: center.x,
|
|
2278
|
+
schY: center.y,
|
|
2279
|
+
anchor: anchors[primitive.anchor],
|
|
2280
|
+
fontSize: importedFontSize ?? primitive.fontSize ?? schematic_text2.shape.font_size.parse(void 0)
|
|
2281
|
+
})
|
|
2282
|
+
];
|
|
1551
2283
|
}
|
|
1552
2284
|
const symbolToSchematicVectorTransform = {
|
|
1553
2285
|
...symbolToSchematicTransform,
|
|
@@ -1559,12 +2291,15 @@ var convertSymbolPrimitives = ({
|
|
|
1559
2291
|
x: primitive.radius,
|
|
1560
2292
|
y: 0
|
|
1561
2293
|
});
|
|
1562
|
-
return
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
2294
|
+
return [
|
|
2295
|
+
formatElement("schematiccircle", {
|
|
2296
|
+
center,
|
|
2297
|
+
radius: Math.hypot(radiusVector.x, radiusVector.y),
|
|
2298
|
+
strokeWidth: SYMBOL_OUTLINE_STROKE_WIDTH,
|
|
2299
|
+
fillColor: primitive.fill ? filledPrimitiveColor : void 0,
|
|
2300
|
+
isFilled: primitive.fill
|
|
2301
|
+
})
|
|
2302
|
+
];
|
|
1568
2303
|
}
|
|
1569
2304
|
const widthVector = applyToPoint4(symbolToSchematicVectorTransform, {
|
|
1570
2305
|
x: primitive.width,
|
|
@@ -1575,13 +2310,15 @@ var convertSymbolPrimitives = ({
|
|
|
1575
2310
|
y: primitive.height
|
|
1576
2311
|
});
|
|
1577
2312
|
const ccwRotationDegrees = Math.atan2(widthVector.y, widthVector.x) * 180 / Math.PI;
|
|
1578
|
-
return
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
2313
|
+
return [
|
|
2314
|
+
formatElement("schematicrect", {
|
|
2315
|
+
schX: center.x,
|
|
2316
|
+
schY: center.y,
|
|
2317
|
+
width: Math.hypot(widthVector.x, widthVector.y),
|
|
2318
|
+
height: Math.hypot(heightVector.x, heightVector.y),
|
|
2319
|
+
rotation: ccwRotationDegrees
|
|
2320
|
+
})
|
|
2321
|
+
];
|
|
1585
2322
|
});
|
|
1586
2323
|
|
|
1587
2324
|
// lib/generate-board-schematic-tsx/convert-box-components.ts
|
|
@@ -1812,33 +2549,222 @@ var convertBoxComponent = ({
|
|
|
1812
2549
|
return primitives;
|
|
1813
2550
|
};
|
|
1814
2551
|
|
|
1815
|
-
// lib/generate-board-schematic-tsx/convert-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
return convertSymbolPrimitives({
|
|
1833
|
-
symbol,
|
|
1834
|
-
symbolToSchematicTransform,
|
|
1835
|
-
reference: sourceComponent?.display_name ?? sourceComponent?.name ?? "",
|
|
1836
|
-
displayText: schematicComponent.symbol_display_value ?? ""
|
|
1837
|
-
});
|
|
2552
|
+
// lib/generate-board-schematic-tsx/convert-native-symbol-pin-numbers.ts
|
|
2553
|
+
import { applyToPoint as applyToPoint5 } from "transformation-matrix";
|
|
2554
|
+
var PIN_TEXT_FONT_SIZE = 0.15;
|
|
2555
|
+
var PIN_TEXT_COLOR = "#a90000";
|
|
2556
|
+
var PIN_NUMBER_BASELINE_OFFSET = 0.02;
|
|
2557
|
+
var SYMBOL_POINT_TOLERANCE = 1e-6;
|
|
2558
|
+
var pointsMatch = (firstPoint, secondPoint) => Math.hypot(firstPoint.x - secondPoint.x, firstPoint.y - secondPoint.y) < SYMBOL_POINT_TOLERANCE;
|
|
2559
|
+
var getPortLeadInnerPoint = ({
|
|
2560
|
+
symbol,
|
|
2561
|
+
symbolPort
|
|
2562
|
+
}) => {
|
|
2563
|
+
for (const primitive of symbol.primitives) {
|
|
2564
|
+
if (primitive.type !== "path" || primitive.points.length < 2) continue;
|
|
2565
|
+
const firstPoint = primitive.points[0];
|
|
2566
|
+
const lastPoint = primitive.points.at(-1);
|
|
2567
|
+
if (pointsMatch(firstPoint, symbolPort)) return primitive.points[1];
|
|
2568
|
+
if (pointsMatch(lastPoint, symbolPort)) return primitive.points.at(-2);
|
|
1838
2569
|
}
|
|
1839
|
-
return
|
|
2570
|
+
return void 0;
|
|
2571
|
+
};
|
|
2572
|
+
var convertNativeSymbolPinNumbers = ({
|
|
2573
|
+
symbol,
|
|
2574
|
+
symbolToSchematicTransform,
|
|
2575
|
+
portMatches,
|
|
2576
|
+
replacedPinPortIds
|
|
2577
|
+
}) => portMatches.flatMap(({ schematicPort, symbolPort }) => {
|
|
2578
|
+
if (schematicPort.pin_number === void 0 || !replacedPinPortIds.has(schematicPort.schematic_port_id)) {
|
|
2579
|
+
return [];
|
|
2580
|
+
}
|
|
2581
|
+
const leadInnerPoint = getPortLeadInnerPoint({ symbol, symbolPort });
|
|
2582
|
+
if (!leadInnerPoint) return [];
|
|
2583
|
+
const portCenter = applyToPoint5(symbolToSchematicTransform, symbolPort);
|
|
2584
|
+
const leadInnerCenter = applyToPoint5(
|
|
2585
|
+
symbolToSchematicTransform,
|
|
2586
|
+
leadInnerPoint
|
|
2587
|
+
);
|
|
2588
|
+
const pinNumberPosition = {
|
|
2589
|
+
x: (portCenter.x + leadInnerCenter.x) / 2,
|
|
2590
|
+
y: (portCenter.y + leadInnerCenter.y) / 2
|
|
2591
|
+
};
|
|
2592
|
+
const isVerticalLead = Math.abs(leadInnerCenter.y - portCenter.y) > Math.abs(leadInnerCenter.x - portCenter.x);
|
|
2593
|
+
if (isVerticalLead) pinNumberPosition.x -= PIN_NUMBER_BASELINE_OFFSET;
|
|
2594
|
+
else pinNumberPosition.y += PIN_NUMBER_BASELINE_OFFSET;
|
|
2595
|
+
return [
|
|
2596
|
+
formatElement("schematictext", {
|
|
2597
|
+
text: String(schematicPort.pin_number),
|
|
2598
|
+
schX: pinNumberPosition.x,
|
|
2599
|
+
schY: pinNumberPosition.y,
|
|
2600
|
+
anchor: "bottom_center",
|
|
2601
|
+
fontSize: PIN_TEXT_FONT_SIZE,
|
|
2602
|
+
color: PIN_TEXT_COLOR,
|
|
2603
|
+
schRotation: isVerticalLead ? -90 : void 0
|
|
2604
|
+
})
|
|
2605
|
+
];
|
|
1840
2606
|
});
|
|
1841
2607
|
|
|
2608
|
+
// lib/generate-board-schematic-tsx/get-native-symbol-port-matching-inputs.ts
|
|
2609
|
+
var getNumericPortHint = (sourcePort) => {
|
|
2610
|
+
const numericPortHint = sourcePort.port_hints?.find(
|
|
2611
|
+
(portHint) => /^(?:pin)?\d+$/.test(portHint)
|
|
2612
|
+
);
|
|
2613
|
+
return numericPortHint?.replace(/^pin/, "");
|
|
2614
|
+
};
|
|
2615
|
+
var getNumericPortName = (sourcePort) => /^\d+$/.test(sourcePort.name) ? sourcePort.name : void 0;
|
|
2616
|
+
var getSourcePinNumber = ({
|
|
2617
|
+
sourcePort,
|
|
2618
|
+
schematicPorts
|
|
2619
|
+
}) => {
|
|
2620
|
+
const linkedSchematicPort = schematicPorts.find(
|
|
2621
|
+
(schematicPort) => schematicPort.source_port_id === sourcePort.source_port_id
|
|
2622
|
+
);
|
|
2623
|
+
const sourcePinNumber = sourcePort.pin_number ?? linkedSchematicPort?.pin_number ?? getNumericPortHint(sourcePort) ?? getNumericPortName(sourcePort);
|
|
2624
|
+
return sourcePinNumber === void 0 ? void 0 : String(sourcePinNumber);
|
|
2625
|
+
};
|
|
2626
|
+
var getFourWindingTransformerAlias = (sourcePinNumber) => {
|
|
2627
|
+
switch (sourcePinNumber) {
|
|
2628
|
+
case "1":
|
|
2629
|
+
return "primary_end";
|
|
2630
|
+
case "2":
|
|
2631
|
+
return "primary_start";
|
|
2632
|
+
case "5":
|
|
2633
|
+
return "auxiliary_end";
|
|
2634
|
+
case "3":
|
|
2635
|
+
return "auxiliary_start";
|
|
2636
|
+
case "9":
|
|
2637
|
+
return "secondary1_end";
|
|
2638
|
+
case "10":
|
|
2639
|
+
return "secondary1_start";
|
|
2640
|
+
case "6":
|
|
2641
|
+
return "secondary2_end";
|
|
2642
|
+
case "7":
|
|
2643
|
+
return "secondary2_start";
|
|
2644
|
+
default:
|
|
2645
|
+
return void 0;
|
|
2646
|
+
}
|
|
2647
|
+
};
|
|
2648
|
+
var getDualSeriesSchottkyAlias = (sourcePinNumber) => {
|
|
2649
|
+
switch (sourcePinNumber) {
|
|
2650
|
+
case "1":
|
|
2651
|
+
return "anode";
|
|
2652
|
+
case "2":
|
|
2653
|
+
return "cathode";
|
|
2654
|
+
case "3":
|
|
2655
|
+
return "common";
|
|
2656
|
+
default:
|
|
2657
|
+
return void 0;
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
var getInferredPortAlias = ({
|
|
2661
|
+
symbolName,
|
|
2662
|
+
sourcePinNumber
|
|
2663
|
+
}) => {
|
|
2664
|
+
if (symbolName === "transformer_4_winding_right") {
|
|
2665
|
+
return getFourWindingTransformerAlias(sourcePinNumber);
|
|
2666
|
+
}
|
|
2667
|
+
if (symbolName === "dual_series_schottky_diode_right") {
|
|
2668
|
+
return getDualSeriesSchottkyAlias(sourcePinNumber);
|
|
2669
|
+
}
|
|
2670
|
+
return void 0;
|
|
2671
|
+
};
|
|
2672
|
+
var getNativeSymbolPortMatchingInputs = ({
|
|
2673
|
+
symbolName,
|
|
2674
|
+
sourcePorts,
|
|
2675
|
+
schematicPorts,
|
|
2676
|
+
isInferredSymbol
|
|
2677
|
+
}) => {
|
|
2678
|
+
const usesInferredPortAliases = symbolName === "transformer_4_winding_right" || symbolName === "dual_series_schottky_diode_right";
|
|
2679
|
+
if (!isInferredSymbol || !usesInferredPortAliases) {
|
|
2680
|
+
return { sourcePorts, includeSchematicPinNumbers: true };
|
|
2681
|
+
}
|
|
2682
|
+
const aliasedSourcePorts = sourcePorts.map((sourcePort) => {
|
|
2683
|
+
const sourcePinNumber = getSourcePinNumber({ sourcePort, schematicPorts });
|
|
2684
|
+
if (!sourcePinNumber) return sourcePort;
|
|
2685
|
+
const inferredPortAlias = getInferredPortAlias({
|
|
2686
|
+
symbolName,
|
|
2687
|
+
sourcePinNumber
|
|
2688
|
+
});
|
|
2689
|
+
if (!inferredPortAlias) return sourcePort;
|
|
2690
|
+
return {
|
|
2691
|
+
...sourcePort,
|
|
2692
|
+
name: inferredPortAlias,
|
|
2693
|
+
port_hints: [inferredPortAlias],
|
|
2694
|
+
pin_number: void 0
|
|
2695
|
+
};
|
|
2696
|
+
});
|
|
2697
|
+
return {
|
|
2698
|
+
sourcePorts: aliasedSourcePorts,
|
|
2699
|
+
includeSchematicPinNumbers: false
|
|
2700
|
+
};
|
|
2701
|
+
};
|
|
2702
|
+
|
|
2703
|
+
// lib/generate-board-schematic-tsx/convert-components.ts
|
|
2704
|
+
var convertComponents = (circuitJson) => {
|
|
2705
|
+
const textReplacements = getNativeSymbolTextReplacements(circuitJson);
|
|
2706
|
+
return su3(circuitJson).schematic_component.list().flatMap((schematicComponent) => {
|
|
2707
|
+
const symbolName = resolveNativeSchematicSymbolName({
|
|
2708
|
+
circuitJson,
|
|
2709
|
+
schematicComponent
|
|
2710
|
+
});
|
|
2711
|
+
if (symbolName && symbolName in symbols2) {
|
|
2712
|
+
const symbol = symbols2[symbolName];
|
|
2713
|
+
if (!symbol) return [];
|
|
2714
|
+
const isInferredSymbol = !schematicComponent.symbol_name;
|
|
2715
|
+
const sourceComponent = su3(circuitJson).source_component.get(
|
|
2716
|
+
schematicComponent.source_component_id ?? ""
|
|
2717
|
+
);
|
|
2718
|
+
const schematicPorts = su3(circuitJson).schematic_port.list({
|
|
2719
|
+
schematic_component_id: schematicComponent.schematic_component_id
|
|
2720
|
+
});
|
|
2721
|
+
const sourcePorts = su3(circuitJson).source_port.list({
|
|
2722
|
+
source_component_id: schematicComponent.source_component_id
|
|
2723
|
+
});
|
|
2724
|
+
const portMatchingInputs = getNativeSymbolPortMatchingInputs({
|
|
2725
|
+
symbolName,
|
|
2726
|
+
sourcePorts,
|
|
2727
|
+
schematicPorts,
|
|
2728
|
+
isInferredSymbol
|
|
2729
|
+
});
|
|
2730
|
+
const symbolToSchematicTransform = getSymbolToSchematicTransform({
|
|
2731
|
+
symbol,
|
|
2732
|
+
schematicComponent,
|
|
2733
|
+
schematicPorts,
|
|
2734
|
+
...portMatchingInputs
|
|
2735
|
+
});
|
|
2736
|
+
const textReplacement = textReplacements.find(
|
|
2737
|
+
(replacement) => replacement.schematicComponentId === schematicComponent.schematic_component_id
|
|
2738
|
+
);
|
|
2739
|
+
const portMatches = matchSymbolPortsByPinIdentity({
|
|
2740
|
+
schematicPorts,
|
|
2741
|
+
symbol,
|
|
2742
|
+
...portMatchingInputs
|
|
2743
|
+
});
|
|
2744
|
+
return [
|
|
2745
|
+
...convertSymbolPrimitives({
|
|
2746
|
+
symbol,
|
|
2747
|
+
symbolToSchematicTransform,
|
|
2748
|
+
reference: sourceComponent?.display_name ?? sourceComponent?.name ?? "",
|
|
2749
|
+
displayText: isInferredSymbol ? sourceComponent?.display_value ?? schematicComponent.symbol_display_value ?? "" : schematicComponent.symbol_display_value ?? "",
|
|
2750
|
+
includeReference: !isInferredSymbol || textReplacement?.replacesReference,
|
|
2751
|
+
includeDisplayText: !isInferredSymbol || textReplacement?.includeNativeDisplayText,
|
|
2752
|
+
referenceFontSize: textReplacement?.referenceFontSize,
|
|
2753
|
+
displayTextFontSize: textReplacement?.displayTextFontSize,
|
|
2754
|
+
filledPrimitiveColor: isInferredSymbol ? COMPONENT_OUTLINE_COLOR : void 0
|
|
2755
|
+
}),
|
|
2756
|
+
...isInferredSymbol && textReplacement ? convertNativeSymbolPinNumbers({
|
|
2757
|
+
symbol,
|
|
2758
|
+
symbolToSchematicTransform,
|
|
2759
|
+
portMatches,
|
|
2760
|
+
replacedPinPortIds: textReplacement.replacedPinPortIds
|
|
2761
|
+
}) : []
|
|
2762
|
+
];
|
|
2763
|
+
}
|
|
2764
|
+
return schematicComponent.is_box_with_pins ? convertBoxComponent({ circuitJson, schematicComponent }) : [];
|
|
2765
|
+
});
|
|
2766
|
+
};
|
|
2767
|
+
|
|
1842
2768
|
// lib/generate-board-schematic-tsx/convert-schematic-graphics.ts
|
|
1843
2769
|
var convertSchematicGraphics = (circuitJson) => circuitJson.flatMap((element) => {
|
|
1844
2770
|
if (element.type !== "schematic_graphic") return [];
|
|
@@ -1855,7 +2781,7 @@ var convertSchematicGraphics = (circuitJson) => circuitJson.flatMap((element) =>
|
|
|
1855
2781
|
// lib/generate-board-schematic-tsx/convert-net-labels.ts
|
|
1856
2782
|
import { su as su4 } from "@tscircuit/soup-util";
|
|
1857
2783
|
import { schematic_text as schematic_text3 } from "circuit-json";
|
|
1858
|
-
import { symbols as
|
|
2784
|
+
import { symbols as symbols3 } from "schematic-symbols";
|
|
1859
2785
|
|
|
1860
2786
|
// lib/generate-board-schematic-tsx/get-net-label-symbol-to-schematic-transform.ts
|
|
1861
2787
|
import {
|
|
@@ -1884,8 +2810,8 @@ function canRenderNativeNetLabel(name) {
|
|
|
1884
2810
|
var convertNetLabels = (circuitJson) => su4(circuitJson).schematic_net_label.list().flatMap((schematicNetLabel) => {
|
|
1885
2811
|
const anchorPosition = schematicNetLabel.anchor_position ?? schematicNetLabel.center;
|
|
1886
2812
|
const symbolName = schematicNetLabel.symbol_name;
|
|
1887
|
-
if (symbolName && symbolName in
|
|
1888
|
-
const symbol =
|
|
2813
|
+
if (symbolName && symbolName in symbols3) {
|
|
2814
|
+
const symbol = symbols3[symbolName];
|
|
1889
2815
|
if (symbol)
|
|
1890
2816
|
return convertSymbolPrimitives({
|
|
1891
2817
|
symbol,
|
|
@@ -3094,7 +4020,7 @@ var generateFootprintTsx = (circuitJson, context) => {
|
|
|
3094
4020
|
|
|
3095
4021
|
// lib/board-converter/get-pcb-component-render-placement.ts
|
|
3096
4022
|
import { getBoundsOfPcbElements } from "@tscircuit/circuit-json-util";
|
|
3097
|
-
import { applyToPoint as
|
|
4023
|
+
import { applyToPoint as applyToPoint6, inverse, translate as translate5 } from "transformation-matrix";
|
|
3098
4024
|
var physicalPcbElementTypes = /* @__PURE__ */ new Set([
|
|
3099
4025
|
"pcb_copper_text",
|
|
3100
4026
|
"pcb_cutout",
|
|
@@ -3120,7 +4046,7 @@ var getPcbComponentRenderPlacement = ({
|
|
|
3120
4046
|
pcbBoard,
|
|
3121
4047
|
pcbComponent
|
|
3122
4048
|
}) => {
|
|
3123
|
-
const componentPosition =
|
|
4049
|
+
const componentPosition = applyToPoint6(
|
|
3124
4050
|
inverse(translate5(pcbBoard.center.x, pcbBoard.center.y)),
|
|
3125
4051
|
pcbComponent.center
|
|
3126
4052
|
);
|
|
@@ -3235,7 +4161,7 @@ var getSchematicComponentsForPcbComponent = ({
|
|
|
3235
4161
|
// lib/board-converter/localize-pcb-component-elements.ts
|
|
3236
4162
|
import { transformPCBElements } from "@tscircuit/circuit-json-util";
|
|
3237
4163
|
import {
|
|
3238
|
-
applyToPoint as
|
|
4164
|
+
applyToPoint as applyToPoint7,
|
|
3239
4165
|
compose as compose4,
|
|
3240
4166
|
decomposeTSR,
|
|
3241
4167
|
flipY,
|
|
@@ -3277,13 +4203,13 @@ var transformSilkscreenGraphic = ({
|
|
|
3277
4203
|
}) => {
|
|
3278
4204
|
if (graphic.shape !== "brep") return;
|
|
3279
4205
|
graphic.brep_shape.outer_ring.vertices = graphic.brep_shape.outer_ring.vertices.map(
|
|
3280
|
-
(vertex) =>
|
|
4206
|
+
(vertex) => applyToPoint7(absoluteToComponentLocalTransform, vertex)
|
|
3281
4207
|
);
|
|
3282
4208
|
graphic.brep_shape.inner_rings = graphic.brep_shape.inner_rings.map(
|
|
3283
4209
|
(ring) => ({
|
|
3284
4210
|
...ring,
|
|
3285
4211
|
vertices: ring.vertices.map(
|
|
3286
|
-
(vertex) =>
|
|
4212
|
+
(vertex) => applyToPoint7(absoluteToComponentLocalTransform, vertex)
|
|
3287
4213
|
)
|
|
3288
4214
|
})
|
|
3289
4215
|
);
|
|
@@ -3513,6 +4439,10 @@ var convertPcbComponents = ({
|
|
|
3513
4439
|
cadModelGroup: localizedCadModelGroup,
|
|
3514
4440
|
pcbBoard
|
|
3515
4441
|
}) : void 0;
|
|
4442
|
+
const childModelElementsTsx = localizedCadModelGroup ? generateCadModelGroupChildrenTsx({
|
|
4443
|
+
cadModelGroup: localizedCadModelGroup,
|
|
4444
|
+
pcbBoard
|
|
4445
|
+
}) : [];
|
|
3516
4446
|
const componentProps = [
|
|
3517
4447
|
`name=${formatJsxStringAttribute(componentName)}`,
|
|
3518
4448
|
`pcbX={${componentPosition.x}}`,
|
|
@@ -3524,6 +4454,9 @@ var convertPcbComponents = ({
|
|
|
3524
4454
|
if (cadModelTsx) {
|
|
3525
4455
|
componentProps.push(`cadModel={${cadModelTsx}}`);
|
|
3526
4456
|
}
|
|
4457
|
+
if (localizedCadModelGroup && isJscadCadModelGroupTranslucent(localizedCadModelGroup)) {
|
|
4458
|
+
componentProps.push("showAsTranslucentModel");
|
|
4459
|
+
}
|
|
3527
4460
|
if (pinLabels) {
|
|
3528
4461
|
componentProps.push(`pinLabels={${JSON.stringify(pinLabels)}}`);
|
|
3529
4462
|
}
|
|
@@ -3543,8 +4476,9 @@ var convertPcbComponents = ({
|
|
|
3543
4476
|
if (pcbComponent.obstructs_within_bounds === false) {
|
|
3544
4477
|
componentProps.push("obstructsWithinBounds={false}");
|
|
3545
4478
|
}
|
|
4479
|
+
const chipOpeningTsx = `<chip ${componentProps.join(" ")} footprint={${footprintTsx ?? "<footprint />"}}`;
|
|
3546
4480
|
boardChildren.push(
|
|
3547
|
-
|
|
4481
|
+
childModelElementsTsx.length === 0 ? `${chipOpeningTsx} />` : `${chipOpeningTsx}>${childModelElementsTsx.join("\n")}</chip>`
|
|
3548
4482
|
);
|
|
3549
4483
|
}
|
|
3550
4484
|
};
|