@tscircuit/core 0.0.1873 → 0.0.1875

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as circuit_json from 'circuit-json';
2
- import { PcbGroup, PcbTraceError, PcbPlacementError, PcbManualEditConflictWarning, PcbViaClearanceError, LayerRef, AnyCircuitElement, Size, PcbTrace as PcbTrace$1, PcbVia as PcbVia$1, PcbTraceRoutePoint, AnySourceComponent, PcbComponent, SchematicPort, SchematicComponent, SimulationVoltageSource, SimulationCurrentSource, PcbSilkscreenGraphic, RouteHintPoint, PcbBoard, SchematicSheet as SchematicSheet$1, SchematicGraphic as SchematicGraphic$1, SimulationExperiment, SimulationParameterSweep, CircuitJson } from 'circuit-json';
2
+ import { PcbGroup, PcbTraceError, PcbPlacementError, PcbManualEditConflictWarning, PcbViaClearanceError, PcbVia as PcbVia$1, LayerRef, AnyCircuitElement, Size, PcbTrace as PcbTrace$1, PcbTraceRoutePoint, AnySourceComponent, PcbComponent, SchematicPort, SchematicComponent, SimulationVoltageSource, SimulationCurrentSource, PcbSilkscreenGraphic, RouteHintPoint, PcbBoard, SchematicSheet as SchematicSheet$1, SchematicGraphic as SchematicGraphic$1, SimulationExperiment, SimulationParameterSweep, CircuitJson } from 'circuit-json';
3
3
  import * as _tscircuit_props from '@tscircuit/props';
4
4
  import { PlatformConfig, traceProps, netProps, AutoroutingPhaseProps, AutorouterProp, subcircuitGroupProps, AutorouterConfig, PcbSx, portProps, PinAttributeMap, SupplierPartNumbers, CadModelProp, SchematicPortArrangement, groupProps, platedHoleProps, BoardOutlinePoint, boardProps, subcircuitProps, subpanelProps, capacitorProps, antennaProps, chipProps, pinoutProps, diodeProps, fuseProps, jumperProps, interconnectProps, solderjumperProps, ledProps, powerSourceProps, voltageSourceProps, currentSourceProps, ammeterProps, resistorProps, constraintProps, drcCheckProps, autoroutingPhaseProps, fabricationNoteRectProps, fabricationNotePathProps, fabricationNoteTextProps, fabricationNoteDimensionProps, pcbNoteLineProps, pcbNoteRectProps, pcbNoteTextProps, pcbNotePathProps, pcbNoteDimensionProps, footprintProps, breakoutProps, breakoutPointProps, holeProps, pcbKeepoutProps, netLabelProps, cadmodelProps, cadassemblyProps, courtyardCircleProps, courtyardOutlineProps, courtyardRectProps, silkscreenCircleProps, silkscreenPathProps, silkscreenRectProps, silkscreenTextProps, silkscreenLineProps, silkscreenGraphicProps, smtPadProps, fiducialProps, busProps, differentialPairProps, traceHintProps, viaProps, copperPourProps, copperTextProps, cutoutProps, assemblyDeviceProps, enclosureCutoutApertureProps, enclosureFdmBoxProps, batteryProps, pinHeaderProps, resonatorProps, inductorProps, potentiometerProps, pushButtonProps, crystalProps, CrystalPinLabels, transistorProps, mosfetProps, opampProps, OpAmpPinLabels, switchProps, SwitchProps, testpointProps, schematicTextProps, schematicLineProps, schematicRectProps, schematicArcProps, schematicCircleProps, schematicPathProps, schematicBoxProps, schematicSymbolProps, schematicSectionProps, schematicSheetProps, schematicGraphicProps, schematicTableProps, schematicRowProps, schematicCellProps, symbolProps, analogSimulationProps, analogTransientSimulationProps, analogDcOperatingPointSimulationProps, analogDcSweepSimulationProps, analogAcSweepSimulationProps, analogSweepParameterProps, voltageProbeProps, spicemodelProps, AnalogTransientSimulationProps, AnalogDcSweepSimulationProps, AnalogAcSweepSimulationProps, AnalogSweepParameterProps, AssemblyDevicePropsInput, EnclosureCutoutApertureProps, EnclosureFdmBoxProps, CapacitorProps, ChipProps, DiodeProps, ResistorProps, ManualEditEvent, ManualEditsFile, ChipConnections, manual_edits_file } from '@tscircuit/props';
5
5
  export { kicadFootprintStrings } from '@tscircuit/props';
@@ -360,9 +360,9 @@ interface IIsolatedCircuit {
360
360
  interface IRootCircuit extends IIsolatedCircuit {
361
361
  }
362
362
 
363
- declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "RenderIsolatedSubcircuits", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "FetchPartFootprint", "ResolveFootprintPinLabels", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "CreateAutoplacedBreakoutPoints", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "CheckRefDesConvention", "SourceComponentPropertyValidation", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicSectionRender", "SchematicTraceRender", "SchematicSheetRender", "SchematicReplaceNetLabelsWithSymbols", "SchematicLabelNetsWithConflictingNames", "PanelBoardLayout", "ValidatePcbCoordinates", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbCalcPlacementResolution", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "PcbImplicitCopperPourRender", "PcbCopperPourRender", "PcbViaStitchRender", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
363
+ declare const orderedRenderPhases: readonly ["ReactSubtreesRender", "RenderIsolatedSubcircuits", "InflateSubcircuitCircuitJson", "SourceNameDuplicateComponentRemoval", "PcbFootprintStringRender", "FetchPartFootprint", "ResolveFootprintPinLabels", "InitializePortsFromChildren", "CreateNetsFromProps", "AssignFallbackProps", "CreateTracesFromProps", "CreateTracesFromNetLabels", "CreateTraceHintsFromProps", "CreateAutoplacedBreakoutPoints", "SourceGroupRender", "AssignNameToUnnamedComponents", "SourceRender", "CheckRefDesConvention", "SourceComponentPropertyValidation", "SourceParentAttachment", "PortMatching", "OptimizeSelectorCache", "SourceTraceRender", "SourceAddConnectivityMapKey", "SourceDesignRuleChecks", "SimulationRender", "SchematicComponentRender", "SchematicPortRender", "SymbolContainerRender", "SchematicPrimitiveRender", "SchematicSymbolResize", "SchematicComponentSizeCalculation", "SchematicLayout", "SchematicSectionRender", "SchematicTraceRender", "SchematicSheetRender", "SchematicReplaceNetLabelsWithSymbols", "SchematicLabelNetsWithConflictingNames", "PanelBoardLayout", "ValidatePcbCoordinates", "PcbComponentRender", "PcbPrimitiveRender", "PcbFootprintLayout", "PcbPortRender", "PcbPortAttachment", "PcbComponentSizeCalculation", "PcbComponentAnchorAlignment", "PcbCalcPlacementResolution", "PcbLayout", "PcbBoardAutoSize", "PanelLayout", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "PcbImplicitCopperPourRender", "PcbCopperPourRender", "PcbViaStitchRender", "PcbCopperPourCleanup", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
364
364
  type RenderPhase = (typeof orderedRenderPhases)[number];
365
- declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "RenderIsolatedSubcircuits" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "FetchPartFootprint" | "ResolveFootprintPinLabels" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "CreateAutoplacedBreakoutPoints" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "CheckRefDesConvention" | "SourceComponentPropertyValidation" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicSectionRender" | "SchematicTraceRender" | "SchematicSheetRender" | "SchematicReplaceNetLabelsWithSymbols" | "SchematicLabelNetsWithConflictingNames" | "PanelBoardLayout" | "ValidatePcbCoordinates" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbCalcPlacementResolution" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbImplicitCopperPourRender" | "PcbCopperPourRender" | "PcbViaStitchRender" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
365
+ declare const renderPhaseIndexMap: Map<"ReactSubtreesRender" | "RenderIsolatedSubcircuits" | "InflateSubcircuitCircuitJson" | "SourceNameDuplicateComponentRemoval" | "PcbFootprintStringRender" | "FetchPartFootprint" | "ResolveFootprintPinLabels" | "InitializePortsFromChildren" | "CreateNetsFromProps" | "AssignFallbackProps" | "CreateTracesFromProps" | "CreateTracesFromNetLabels" | "CreateTraceHintsFromProps" | "CreateAutoplacedBreakoutPoints" | "SourceGroupRender" | "AssignNameToUnnamedComponents" | "SourceRender" | "CheckRefDesConvention" | "SourceComponentPropertyValidation" | "SourceParentAttachment" | "PortMatching" | "OptimizeSelectorCache" | "SourceTraceRender" | "SourceAddConnectivityMapKey" | "SourceDesignRuleChecks" | "SimulationRender" | "SchematicComponentRender" | "SchematicPortRender" | "SymbolContainerRender" | "SchematicPrimitiveRender" | "SchematicSymbolResize" | "SchematicComponentSizeCalculation" | "SchematicLayout" | "SchematicSectionRender" | "SchematicTraceRender" | "SchematicSheetRender" | "SchematicReplaceNetLabelsWithSymbols" | "SchematicLabelNetsWithConflictingNames" | "PanelBoardLayout" | "ValidatePcbCoordinates" | "PcbComponentRender" | "PcbPrimitiveRender" | "PcbFootprintLayout" | "PcbPortRender" | "PcbPortAttachment" | "PcbComponentSizeCalculation" | "PcbComponentAnchorAlignment" | "PcbCalcPlacementResolution" | "PcbLayout" | "PcbBoardAutoSize" | "PanelLayout" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbImplicitCopperPourRender" | "PcbCopperPourRender" | "PcbViaStitchRender" | "PcbCopperPourCleanup" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
366
366
  type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
367
367
  type RenderPhaseStates = Record<RenderPhase, {
368
368
  initialized: boolean;
@@ -496,6 +496,7 @@ interface BoardI {
496
496
  componentName: string;
497
497
  boardThickness: number;
498
498
  _connectedSchematicPortPairs: Set<string>;
499
+ _generatedStitchingViaIds?: Set<PcbVia$1["pcb_via_id"]>;
499
500
  allLayers: ReadonlyArray<LayerRef>;
500
501
  _getBoardCalcVariables(): Record<string, number>;
501
502
  pcb_board_id?: string | null;
@@ -6198,6 +6199,8 @@ declare class Board extends Group<typeof boardProps> implements BoardI, Subcircu
6198
6199
  doInitialPcbDesignRuleChecks(): void;
6199
6200
  doInitialPcbPlacementDesignRuleChecks(): void;
6200
6201
  doInitialPcbImplicitCopperPourRender(): void;
6202
+ _generatedStitchingViaIds: Set<string>;
6203
+ doInitialPcbCopperPourCleanup(): void;
6201
6204
  updatePcbDesignRuleChecks(): void;
6202
6205
  runRenderPhaseForChildren(phase: RenderPhase): void;
6203
6206
  _repositionOnPcb(position: {
package/dist/index.js CHANGED
@@ -453,6 +453,7 @@ var orderedRenderPhases = [
453
453
  "PcbImplicitCopperPourRender",
454
454
  "PcbCopperPourRender",
455
455
  "PcbViaStitchRender",
456
+ "PcbCopperPourCleanup",
456
457
  "PcbDesignRuleChecks",
457
458
  "SilkscreenOverlapAdjustment",
458
459
  "CadModelRender",
@@ -527,6 +528,16 @@ var asyncPhaseDependencies = {
527
528
  "PcbFootprintStringRender",
528
529
  "FetchPartFootprint"
529
530
  ],
531
+ PcbCopperPourCleanup: [
532
+ "PcbFootprintStringRender",
533
+ "FetchPartFootprint",
534
+ "PcbPlacementDesignRuleChecks",
535
+ "PcbTraceRender",
536
+ "PcbRouteNetIslands",
537
+ "PcbImplicitCopperPourRender",
538
+ "PcbCopperPourRender",
539
+ "PcbViaStitchRender"
540
+ ],
530
541
  PcbTraceRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
531
542
  PcbRouteNetIslands: [
532
543
  "PcbFootprintStringRender",
@@ -540,7 +551,8 @@ var asyncPhaseDependencies = {
540
551
  "PcbTraceRender",
541
552
  "PcbImplicitCopperPourRender",
542
553
  "PcbCopperPourRender",
543
- "PcbViaStitchRender"
554
+ "PcbViaStitchRender",
555
+ "PcbCopperPourCleanup"
544
556
  ],
545
557
  SilkscreenOverlapAdjustment: [
546
558
  "PcbFootprintStringRender",
@@ -16574,7 +16586,7 @@ import {
16574
16586
  } from "@tscircuit/checks";
16575
16587
  import { getBoundsFromPoints as getBoundsFromPoints10 } from "@tscircuit/math-utils";
16576
16588
  import { boardProps } from "@tscircuit/props";
16577
- import { compose as compose11, translate as translate11 } from "transformation-matrix";
16589
+ import { compose as compose12, translate as translate12 } from "transformation-matrix";
16578
16590
 
16579
16591
  // lib/utils/autorouting/getAncestorSubcircuitIds.ts
16580
16592
  var getDescendantSubcircuitIds = (db, root_subcircuit_id) => {
@@ -51455,7 +51467,7 @@ function Group_getRoutingPhasePlans(group) {
51455
51467
  var package_default = {
51456
51468
  name: "@tscircuit/core",
51457
51469
  type: "module",
51458
- version: "0.0.1872",
51470
+ version: "0.0.1874",
51459
51471
  types: "dist/index.d.ts",
51460
51472
  main: "dist/index.js",
51461
51473
  module: "dist/index.js",
@@ -51490,7 +51502,7 @@ var package_default = {
51490
51502
  "@tscircuit/alphabet": "0.0.25",
51491
51503
  "@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
51492
51504
  "@tscircuit/capacity-autorouter": "^0.0.890",
51493
- "@tscircuit/checks": "^0.0.184",
51505
+ "@tscircuit/checks": "^0.0.185",
51494
51506
  "@tscircuit/circuit-json-util": "^0.0.106",
51495
51507
  "@tscircuit/common": "^0.0.20",
51496
51508
  "@tscircuit/copper-pour-solver": "^0.0.54",
@@ -56664,7 +56676,8 @@ var renderViaStitchingForCopperPours = (copperPour) => {
56664
56676
  }
56665
56677
  for (const pcbVia of solver.getOutput().pcbVias) {
56666
56678
  const { pcb_via_id: _solverViaId, ...pcbViaInput } = pcbVia;
56667
- db.pcb_via.insert(pcbViaInput);
56679
+ const insertedVia = db.pcb_via.insert(pcbViaInput);
56680
+ boardComponent?._generatedStitchingViaIds?.add(insertedVia.pcb_via_id);
56668
56681
  }
56669
56682
  };
56670
56683
  function CopperPour_doInitialPcbViaStitchRender(copperPour) {
@@ -56749,6 +56762,429 @@ var Board_doInitialPcbImplicitCopperPourRender = (board) => {
56749
56762
  }
56750
56763
  };
56751
56764
 
56765
+ // lib/utils/copper-pour-connectivity/find-floating-copper.ts
56766
+ import {
56767
+ getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson5
56768
+ } from "circuit-json-to-connectivity-map";
56769
+ import Flatbush from "flatbush";
56770
+
56771
+ // lib/utils/copper-pour-connectivity/copper-geometry.ts
56772
+ import {
56773
+ Arc,
56774
+ Box as Box2,
56775
+ Circle,
56776
+ Matrix,
56777
+ ORIENTATION,
56778
+ Point,
56779
+ Polygon as Polygon2,
56780
+ Segment
56781
+ } from "@flatten-js/core";
56782
+ import { compose as compose11, rotate as rotate5, translate as translate11 } from "transformation-matrix";
56783
+ var placePolygon = (polygon, center, degrees = 0) => {
56784
+ const { a, b, c, d, e, f } = compose11(
56785
+ translate11(center.x, center.y),
56786
+ rotate5(degrees * Math.PI / 180)
56787
+ );
56788
+ return polygon.transform(new Matrix(a, b, c, d, e, f));
56789
+ };
56790
+ var ccw = (polygon) => polygon.orientation() === ORIENTATION.CCW ? polygon : polygon.reverse();
56791
+ var circlePolygon = (center, radius) => ccw(new Polygon2(new Circle(new Point(center.x, center.y), radius)));
56792
+ var roundedRectangle = (center, width, height, radius = 0, degrees = 0) => {
56793
+ const x = width / 2;
56794
+ const y = height / 2;
56795
+ const r = Math.max(0, Math.min(radius, x, y));
56796
+ if (r === 0)
56797
+ return placePolygon(
56798
+ ccw(new Polygon2(new Box2(-x, -y, x, y))),
56799
+ center,
56800
+ degrees
56801
+ );
56802
+ const arcs = [
56803
+ new Arc(new Point(x - r, -y + r), r, -Math.PI / 2, 0, true),
56804
+ new Arc(new Point(x - r, y - r), r, 0, Math.PI / 2, true),
56805
+ new Arc(new Point(-x + r, y - r), r, Math.PI / 2, Math.PI, true),
56806
+ new Arc(new Point(-x + r, -y + r), r, Math.PI, Math.PI * 1.5, true)
56807
+ ];
56808
+ const edges = [];
56809
+ for (let i = 0; i < arcs.length; i++) {
56810
+ const arc = arcs[i];
56811
+ const next = arcs[(i + 1) % arcs.length];
56812
+ edges.push(arc);
56813
+ if (arc.end.distanceTo(next.start)[0] > 1e-12)
56814
+ edges.push(new Segment(arc.end, next.start));
56815
+ }
56816
+ return placePolygon(ccw(new Polygon2(edges)), center, degrees);
56817
+ };
56818
+ var ringPolygon = (ring) => {
56819
+ const edges = [];
56820
+ for (let i = 0; i < ring.vertices.length; i++) {
56821
+ const start = ring.vertices[i];
56822
+ const end = ring.vertices[(i + 1) % ring.vertices.length];
56823
+ const dx = end.x - start.x;
56824
+ const dy = end.y - start.y;
56825
+ if (dx === 0 && dy === 0) continue;
56826
+ const bulge = start.bulge ?? 0;
56827
+ if (bulge === 0) {
56828
+ edges.push(
56829
+ new Segment(new Point(start.x, start.y), new Point(end.x, end.y))
56830
+ );
56831
+ } else {
56832
+ const offset = (1 - bulge * bulge) / (4 * bulge);
56833
+ const center = new Point(
56834
+ (start.x + end.x) / 2 - dy * offset,
56835
+ (start.y + end.y) / 2 + dx * offset
56836
+ );
56837
+ edges.push(
56838
+ new Arc(
56839
+ center,
56840
+ Math.hypot(dx, dy) * (1 + bulge * bulge) / (4 * Math.abs(bulge)),
56841
+ Math.atan2(start.y - center.y, start.x - center.x),
56842
+ Math.atan2(end.y - center.y, end.x - center.x),
56843
+ bulge > 0
56844
+ )
56845
+ );
56846
+ }
56847
+ }
56848
+ return ccw(new Polygon2(edges));
56849
+ };
56850
+ var subtractHole = (outer, hole) => {
56851
+ for (const face of hole.reverse().faces) outer.addFace(face.shapes);
56852
+ return outer;
56853
+ };
56854
+ var getPourPolygon = (pour) => {
56855
+ if (pour.shape === "rect")
56856
+ return roundedRectangle(
56857
+ pour.center,
56858
+ pour.width,
56859
+ pour.height,
56860
+ 0,
56861
+ pour.rotation
56862
+ );
56863
+ if (pour.shape === "polygon")
56864
+ return ccw(new Polygon2(pour.points.map((p) => new Point(p.x, p.y))));
56865
+ const polygon = ringPolygon(pour.brep_shape.outer_ring);
56866
+ for (const ring of pour.brep_shape.inner_rings)
56867
+ subtractHole(polygon, ringPolygon(ring));
56868
+ return polygon;
56869
+ };
56870
+ var getSmtPadPolygon = (pad) => {
56871
+ if (pad.shape === "polygon")
56872
+ return ccw(new Polygon2(pad.points.map((p) => new Point(p.x, p.y))));
56873
+ if (pad.shape === "circle") return circlePolygon(pad, pad.radius);
56874
+ const radius = pad.shape === "pill" || pad.shape === "rotated_pill" ? pad.radius : pad.corner_radius ?? pad.rect_border_radius ?? 0;
56875
+ return roundedRectangle(
56876
+ pad,
56877
+ pad.width,
56878
+ pad.height,
56879
+ radius,
56880
+ "ccw_rotation" in pad ? pad.ccw_rotation : 0
56881
+ );
56882
+ };
56883
+ var getViaPolygon = (center, outerDiameter, holeDiameter) => subtractHole(
56884
+ circlePolygon(center, outerDiameter / 2),
56885
+ circlePolygon(center, holeDiameter / 2)
56886
+ );
56887
+ var getPlatedHolePolygon = (pad, componentRotation = 0) => {
56888
+ if (pad.shape === "circle")
56889
+ return getViaPolygon(pad, pad.outer_diameter, pad.hole_diameter);
56890
+ if ("outer_width" in pad) {
56891
+ return subtractHole(
56892
+ roundedRectangle(
56893
+ pad,
56894
+ pad.outer_width,
56895
+ pad.outer_height,
56896
+ Math.min(pad.outer_width, pad.outer_height) / 2,
56897
+ pad.ccw_rotation
56898
+ ),
56899
+ roundedRectangle(
56900
+ pad,
56901
+ pad.hole_width,
56902
+ pad.hole_height,
56903
+ Math.min(pad.hole_width, pad.hole_height) / 2,
56904
+ pad.ccw_rotation
56905
+ )
56906
+ );
56907
+ }
56908
+ const center = { x: pad.x + pad.hole_offset_x, y: pad.y + pad.hole_offset_y };
56909
+ const outer = pad.shape === "hole_with_polygon_pad" ? placePolygon(
56910
+ ccw(new Polygon2(pad.pad_outline.map((p) => new Point(p.x, p.y)))),
56911
+ pad,
56912
+ pad.ccw_rotation ?? componentRotation
56913
+ ) : roundedRectangle(
56914
+ pad,
56915
+ pad.rect_pad_width,
56916
+ pad.rect_pad_height,
56917
+ pad.rect_border_radius,
56918
+ "rect_ccw_rotation" in pad ? pad.rect_ccw_rotation : 0
56919
+ );
56920
+ if (pad.shape === "circular_hole_with_rect_pad" || pad.shape === "hole_with_polygon_pad" && pad.hole_shape === "circle") {
56921
+ if (pad.hole_diameter === void 0)
56922
+ throw new Error("Circular plated hole requires hole_diameter");
56923
+ return subtractHole(outer, circlePolygon(center, pad.hole_diameter / 2));
56924
+ }
56925
+ if (!("hole_width" in pad) || pad.hole_width === void 0 || pad.hole_height === void 0)
56926
+ throw new Error("Slotted plated hole requires hole_width and hole_height");
56927
+ return subtractHole(
56928
+ outer,
56929
+ roundedRectangle(
56930
+ center,
56931
+ pad.hole_width,
56932
+ pad.hole_height,
56933
+ Math.min(pad.hole_width, pad.hole_height) / 2,
56934
+ "hole_ccw_rotation" in pad ? pad.hole_ccw_rotation : pad.shape === "hole_with_polygon_pad" ? pad.ccw_rotation ?? componentRotation : 0
56935
+ )
56936
+ );
56937
+ };
56938
+ var getTraceSegmentPolygon = (start, end, startWidth, endWidth = startWidth) => {
56939
+ const length7 = Math.hypot(end.x - start.x, end.y - start.y);
56940
+ const r1 = startWidth / 2;
56941
+ const r2 = endWidth / 2;
56942
+ if (length7 <= Math.abs(r2 - r1))
56943
+ return circlePolygon(r1 >= r2 ? start : end, Math.max(r1, r2));
56944
+ const angle = Math.atan2(end.y - start.y, end.x - start.x);
56945
+ const tangent = Math.acos((r1 - r2) / length7);
56946
+ const first = new Arc(
56947
+ new Point(start.x, start.y),
56948
+ r1,
56949
+ angle + tangent,
56950
+ angle - tangent,
56951
+ true
56952
+ );
56953
+ const second = new Arc(
56954
+ new Point(end.x, end.y),
56955
+ r2,
56956
+ angle - tangent,
56957
+ angle + tangent,
56958
+ true
56959
+ );
56960
+ return ccw(
56961
+ new Polygon2([
56962
+ first,
56963
+ new Segment(first.end, second.start),
56964
+ second,
56965
+ new Segment(second.end, first.start)
56966
+ ])
56967
+ );
56968
+ };
56969
+ var copperPolygonsTouch = (a, b, tolerance = 1e-7) => a.vertices.some((p) => b.contains(p)) || b.vertices.some((p) => a.contains(p)) || a.distanceTo(b)[0] <= tolerance;
56970
+
56971
+ // lib/utils/copper-pour-connectivity/find-floating-copper.ts
56972
+ var GEOMETRY_SCALE = 1e6;
56973
+ var CONTACT_TOLERANCE = 1e-7 * GEOMETRY_SCALE;
56974
+ var getRouteEndpoint = (routePoint, side) => {
56975
+ if (routePoint.route_type === "wire")
56976
+ return { point: routePoint, layer: routePoint.layer };
56977
+ if (routePoint.route_type === "via")
56978
+ return {
56979
+ point: routePoint,
56980
+ layer: side === "start" ? routePoint.from_layer : routePoint.to_layer
56981
+ };
56982
+ return {
56983
+ point: routePoint[side],
56984
+ layer: side === "start" ? routePoint.start_layer : routePoint.end_layer
56985
+ };
56986
+ };
56987
+ var findFloatingCopper = (circuitJson, generatedStitchingViaIds = /* @__PURE__ */ new Set()) => {
56988
+ const connectivity = getFullConnectivityMapFromCircuitJson5(circuitJson);
56989
+ const pours = circuitJson.filter((e) => e.type === "pcb_copper_pour");
56990
+ const pouredNets = new Set(
56991
+ pours.flatMap(
56992
+ (pour) => pour.source_net_id ? [
56993
+ connectivity.getNetConnectedToId(pour.source_net_id) ?? pour.source_net_id
56994
+ ] : []
56995
+ )
56996
+ );
56997
+ const conductors = [];
56998
+ const add = (conductor) => {
56999
+ if (pouredNets.has(conductor.netId) && !conductor.polygon.isEmpty())
57000
+ conductors.push({
57001
+ ...conductor,
57002
+ polygon: conductor.polygon.scale(GEOMETRY_SCALE, GEOMETRY_SCALE)
57003
+ });
57004
+ };
57005
+ const components = new Map(
57006
+ circuitJson.filter((e) => e.type === "pcb_component").map((e) => [e.pcb_component_id, e])
57007
+ );
57008
+ const vias = circuitJson.filter((e) => e.type === "pcb_via");
57009
+ const board = circuitJson.find((e) => e.type === "pcb_board");
57010
+ for (const pour of pours) {
57011
+ if (!pour.source_net_id) continue;
57012
+ add({
57013
+ polygon: getPourPolygon(pour),
57014
+ layers: [pour.layer],
57015
+ netId: connectivity.getNetConnectedToId(pour.source_net_id) ?? pour.source_net_id,
57016
+ isTerminal: false,
57017
+ pourId: pour.pcb_copper_pour_id
57018
+ });
57019
+ }
57020
+ for (const element of circuitJson) {
57021
+ if (element.type === "pcb_smtpad") {
57022
+ const netId = connectivity.getNetConnectedToId(element.pcb_smtpad_id);
57023
+ if (netId && pouredNets.has(netId))
57024
+ add({
57025
+ polygon: getSmtPadPolygon(element),
57026
+ layers: [element.layer],
57027
+ netId,
57028
+ isTerminal: !!element.pcb_port_id
57029
+ });
57030
+ } else if (element.type === "pcb_plated_hole") {
57031
+ const netId = connectivity.getNetConnectedToId(element.pcb_plated_hole_id);
57032
+ if (netId && pouredNets.has(netId))
57033
+ add({
57034
+ polygon: getPlatedHolePolygon(
57035
+ element,
57036
+ element.pcb_component_id ? components.get(element.pcb_component_id)?.rotation : 0
57037
+ ),
57038
+ layers: element.layers,
57039
+ netId,
57040
+ isTerminal: !!element.pcb_port_id
57041
+ });
57042
+ } else if (element.type === "pcb_via") {
57043
+ const netId = connectivity.getNetConnectedToId(element.pcb_via_id);
57044
+ if (netId && pouredNets.has(netId))
57045
+ add({
57046
+ polygon: getViaPolygon(
57047
+ element,
57048
+ element.outer_diameter,
57049
+ element.hole_diameter
57050
+ ),
57051
+ layers: element.layers,
57052
+ netId,
57053
+ isTerminal: !generatedStitchingViaIds.has(element.pcb_via_id),
57054
+ viaId: element.pcb_via_id
57055
+ });
57056
+ } else if (element.type === "pcb_trace") {
57057
+ const netId = connectivity.getNetConnectedToId(element.pcb_trace_id);
57058
+ if (!netId || !pouredNets.has(netId)) continue;
57059
+ for (let i = 0; i < element.route.length; i++) {
57060
+ const routePoint = element.route[i];
57061
+ if (routePoint.route_type === "via") {
57062
+ const actualVia = vias.find(
57063
+ (via) => via.x === routePoint.x && via.y === routePoint.y && via.layers.includes(routePoint.from_layer) && via.layers.includes(routePoint.to_layer)
57064
+ );
57065
+ add({
57066
+ polygon: getViaPolygon(
57067
+ routePoint,
57068
+ actualVia?.outer_diameter ?? routePoint.outer_diameter ?? board?.min_via_pad_diameter ?? 0.3,
57069
+ actualVia?.hole_diameter ?? routePoint.hole_diameter ?? board?.min_via_hole_diameter ?? 0.2
57070
+ ),
57071
+ layers: actualVia?.layers ?? getViaSpanLayers({
57072
+ fromLayer: routePoint.from_layer,
57073
+ toLayer: routePoint.to_layer,
57074
+ layerCount: board?.num_layers ?? 2
57075
+ }),
57076
+ netId,
57077
+ isTerminal: false
57078
+ });
57079
+ }
57080
+ const next = element.route[i + 1];
57081
+ if (!next) continue;
57082
+ const start = getRouteEndpoint(routePoint, "end");
57083
+ const end = getRouteEndpoint(next, "start");
57084
+ if (start.layer !== end.layer) continue;
57085
+ const startWidth = routePoint.route_type === "via" ? next.route_type === "via" ? void 0 : next.width : routePoint.width;
57086
+ if (startWidth === void 0) continue;
57087
+ const endWidth = element.route_thickness_mode === "interpolated" && next.route_type !== "via" ? next.width : startWidth;
57088
+ add({
57089
+ polygon: getTraceSegmentPolygon(
57090
+ start.point,
57091
+ end.point,
57092
+ startWidth,
57093
+ endWidth
57094
+ ),
57095
+ layers: [start.layer],
57096
+ netId,
57097
+ isTerminal: false
57098
+ });
57099
+ }
57100
+ }
57101
+ }
57102
+ const floatingPourIds = /* @__PURE__ */ new Set();
57103
+ const floatingViaIds = /* @__PURE__ */ new Set();
57104
+ if (conductors.length === 0) return { floatingPourIds, floatingViaIds };
57105
+ const parent = conductors.map((_, i) => i);
57106
+ const find = (i) => {
57107
+ while (parent[i] !== i) {
57108
+ parent[i] = parent[parent[i]];
57109
+ i = parent[i];
57110
+ }
57111
+ return i;
57112
+ };
57113
+ const bounds = conductors.map((conductor) => conductor.polygon.box);
57114
+ const spatialIndex = new Flatbush(conductors.length);
57115
+ for (const box of bounds)
57116
+ spatialIndex.add(box.xmin, box.ymin, box.xmax, box.ymax);
57117
+ spatialIndex.finish();
57118
+ for (const [i, conductor] of conductors.entries()) {
57119
+ const box = bounds[i];
57120
+ for (const j of spatialIndex.search(
57121
+ box.xmin - CONTACT_TOLERANCE,
57122
+ box.ymin - CONTACT_TOLERANCE,
57123
+ box.xmax + CONTACT_TOLERANCE,
57124
+ box.ymax + CONTACT_TOLERANCE
57125
+ )) {
57126
+ if (j <= i || find(i) === find(j)) continue;
57127
+ const neighbor = conductors[j];
57128
+ if (conductor.netId !== neighbor.netId || !conductor.layers.some((layer) => neighbor.layers.includes(layer)))
57129
+ continue;
57130
+ if (copperPolygonsTouch(
57131
+ conductor.polygon,
57132
+ neighbor.polygon,
57133
+ CONTACT_TOLERANCE
57134
+ ))
57135
+ parent[find(j)] = find(i);
57136
+ }
57137
+ }
57138
+ const netsWithTerminals = new Set(
57139
+ conductors.flatMap(
57140
+ (conductor) => conductor.isTerminal ? [conductor.netId] : []
57141
+ )
57142
+ );
57143
+ const terminalRoots = new Set(
57144
+ conductors.flatMap(
57145
+ (conductor, i) => conductor.isTerminal ? [find(i)] : []
57146
+ )
57147
+ );
57148
+ for (const [i, conductor] of conductors.entries()) {
57149
+ if (!netsWithTerminals.has(conductor.netId) || terminalRoots.has(find(i)))
57150
+ continue;
57151
+ if (conductor.pourId) floatingPourIds.add(conductor.pourId);
57152
+ if (conductor.viaId) floatingViaIds.add(conductor.viaId);
57153
+ }
57154
+ return { floatingPourIds, floatingViaIds };
57155
+ };
57156
+
57157
+ // lib/components/normal-components/Board_doInitialPcbCopperPourCleanup.ts
57158
+ var Board_doInitialPcbCopperPourCleanup = (board) => {
57159
+ if (!board.root || board.root.pcbDisabled) return;
57160
+ const { db } = board.root;
57161
+ const circuitJson = db.subtree({ subcircuit_id: board.subcircuit_id }).toArray();
57162
+ if (db.pcb_autorouting_error.list().length > 0) return;
57163
+ if (!circuitJson.some((element) => element.type === "pcb_copper_pour")) return;
57164
+ const { floatingPourIds, floatingViaIds } = findFloatingCopper(
57165
+ circuitJson,
57166
+ board._generatedStitchingViaIds
57167
+ );
57168
+ for (const pourId of floatingPourIds) db.pcb_copper_pour.delete(pourId);
57169
+ for (const viaId of floatingViaIds) {
57170
+ if (board._generatedStitchingViaIds.has(viaId)) db.pcb_via.delete(viaId);
57171
+ }
57172
+ for (const trace of db.pcb_trace.list()) {
57173
+ if (!trace.route.some(
57174
+ (point6) => "copper_pour_id" in point6 && point6.copper_pour_id && floatingPourIds.has(point6.copper_pour_id)
57175
+ ))
57176
+ continue;
57177
+ db.pcb_trace.update(trace.pcb_trace_id, {
57178
+ route: trace.route.map((point6) => {
57179
+ if (!("copper_pour_id" in point6) || !point6.copper_pour_id || !floatingPourIds.has(point6.copper_pour_id))
57180
+ return point6;
57181
+ const { copper_pour_id, is_inside_copper_pour, ...wireOrVia } = point6;
57182
+ return wireOrVia;
57183
+ })
57184
+ });
57185
+ }
57186
+ };
57187
+
56752
57188
  // lib/components/normal-components/Board_doInitialPcbPlacementDesignRuleChecks.ts
56753
57189
  import { runAllPlacementChecks } from "@tscircuit/checks";
56754
57190
  var resetPcbTraceRenderInSubtree = (renderable) => {
@@ -57028,9 +57464,9 @@ var Board = class extends Group5 {
57028
57464
  _computePcbGlobalTransformBeforeLayout() {
57029
57465
  if (this._panelPositionOffset) {
57030
57466
  const parentTransform = this.parent?._computePcbGlobalTransformBeforeLayout?.() ?? { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
57031
- return compose11(
57467
+ return compose12(
57032
57468
  parentTransform,
57033
- translate11(this._panelPositionOffset.x, this._panelPositionOffset.y)
57469
+ translate12(this._panelPositionOffset.x, this._panelPositionOffset.y)
57034
57470
  );
57035
57471
  }
57036
57472
  return super._computePcbGlobalTransformBeforeLayout();
@@ -57344,6 +57780,10 @@ var Board = class extends Group5 {
57344
57780
  doInitialPcbImplicitCopperPourRender() {
57345
57781
  Board_doInitialPcbImplicitCopperPourRender(this);
57346
57782
  }
57783
+ _generatedStitchingViaIds = /* @__PURE__ */ new Set();
57784
+ doInitialPcbCopperPourCleanup() {
57785
+ Board_doInitialPcbCopperPourCleanup(this);
57786
+ }
57347
57787
  updatePcbDesignRuleChecks() {
57348
57788
  const { db } = this.root;
57349
57789
  const routingDisabled = this.root?.pcbRoutingDisabled || this.getInheritedProperty("routingDisabled");
@@ -57647,11 +58087,11 @@ import { distance as distance20 } from "circuit-json";
57647
58087
  // lib/components/normal-components/Subpanel.ts
57648
58088
  import { subpanelProps } from "@tscircuit/props";
57649
58089
  import { distance as distance19 } from "circuit-json";
57650
- import { compose as compose12, identity as identity8, translate as translate12 } from "transformation-matrix";
58090
+ import { compose as compose13, identity as identity8, translate as translate13 } from "transformation-matrix";
57651
58091
 
57652
58092
  // lib/utils/panels/generate-panel-tabs-and-mouse-bites.ts
57653
58093
  import * as Flatten from "@flatten-js/core";
57654
- import { point as point5, Polygon as Polygon3 } from "@flatten-js/core";
58094
+ import { point as point5, Polygon as Polygon4 } from "@flatten-js/core";
57655
58095
  var DEFAULT_TAB_LENGTH = 5;
57656
58096
  var DEFAULT_TAB_WIDTH = 2;
57657
58097
  var generateCutoutsAndMousebitesForOutline = (outline, options) => {
@@ -57787,7 +58227,7 @@ function generatePanelTabsAndMouseBites(boards, options) {
57787
58227
  if (board.width && board.height) {
57788
58228
  boardDimensions.push(Math.min(board.width, board.height));
57789
58229
  } else if (board.outline && board.outline.length > 0) {
57790
- const outlinePolygon = new Polygon3(
58230
+ const outlinePolygon = new Polygon4(
57791
58231
  board.outline.map((p) => point5(p.x, p.y))
57792
58232
  );
57793
58233
  const area = Math.abs(outlinePolygon.area());
@@ -58159,9 +58599,9 @@ var Subpanel = class _Subpanel extends Group5 {
58159
58599
  _computePcbGlobalTransformBeforeLayout() {
58160
58600
  if (this._panelPositionOffset) {
58161
58601
  const parentTransform = this.parent?._computePcbGlobalTransformBeforeLayout?.() ?? identity8();
58162
- return compose12(
58602
+ return compose13(
58163
58603
  parentTransform,
58164
- translate12(this._panelPositionOffset.x, this._panelPositionOffset.y)
58604
+ translate13(this._panelPositionOffset.x, this._panelPositionOffset.y)
58165
58605
  );
58166
58606
  }
58167
58607
  return super._computePcbGlobalTransformBeforeLayout();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/core",
3
3
  "type": "module",
4
- "version": "0.0.1873",
4
+ "version": "0.0.1875",
5
5
  "types": "dist/index.d.ts",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
@@ -36,7 +36,7 @@
36
36
  "@tscircuit/alphabet": "0.0.25",
37
37
  "@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
38
38
  "@tscircuit/capacity-autorouter": "^0.0.890",
39
- "@tscircuit/checks": "^0.0.184",
39
+ "@tscircuit/checks": "^0.0.185",
40
40
  "@tscircuit/circuit-json-util": "^0.0.106",
41
41
  "@tscircuit/common": "^0.0.20",
42
42
  "@tscircuit/copper-pour-solver": "^0.0.54",