@tscircuit/core 0.0.1857 → 0.0.1859
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 +7 -2
- package/dist/index.js +560 -15
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { FanoutSolver } from '@tscircuit/fanout-solver';
|
|
|
18
18
|
import { ImplicitCopperPourPipelineSolver } from '@tscircuit/implicit-copper-pour-solver/lib/index';
|
|
19
19
|
import { LayoutPipelineSolver } from '@tscircuit/matchpack';
|
|
20
20
|
import { SchematicTracePipelineSolver } from '@tscircuit/schematic-trace-solver';
|
|
21
|
+
import { ViaStitchSolver } from '@tscircuit/via-stitch-solver';
|
|
21
22
|
import { PackSolver2 } from 'calculate-packing';
|
|
22
23
|
import { Box, Bounds } from '@tscircuit/math-utils';
|
|
23
24
|
import { ConnectivityMap } from 'circuit-json-to-connectivity-map';
|
|
@@ -42,6 +43,7 @@ declare const SOLVERS: {
|
|
|
42
43
|
FanoutSolver: typeof FanoutSolver;
|
|
43
44
|
ImplicitCopperPourPipelineSolver: typeof ImplicitCopperPourPipelineSolver;
|
|
44
45
|
SchematicTracePipelineSolver: typeof SchematicTracePipelineSolver;
|
|
46
|
+
ViaStitchSolver: typeof ViaStitchSolver;
|
|
45
47
|
};
|
|
46
48
|
type SolverName = keyof typeof SOLVERS;
|
|
47
49
|
|
|
@@ -358,9 +360,9 @@ interface IIsolatedCircuit {
|
|
|
358
360
|
interface IRootCircuit extends IIsolatedCircuit {
|
|
359
361
|
}
|
|
360
362
|
|
|
361
|
-
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", "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", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
|
|
362
364
|
type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
363
|
-
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" | "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" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
|
|
364
366
|
type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
|
|
365
367
|
type RenderPhaseStates = Record<RenderPhase, {
|
|
366
368
|
initialized: boolean;
|
|
@@ -522,6 +524,8 @@ declare class IsolatedCircuit {
|
|
|
522
524
|
pcbDisabled: boolean;
|
|
523
525
|
pcbRoutingDisabled: boolean;
|
|
524
526
|
_featureMspSchematicTraceRouting: boolean;
|
|
527
|
+
/** Experimental automatic via stitching; opt in before rendering. */
|
|
528
|
+
_featurePcbViaStitching: boolean;
|
|
525
529
|
/**
|
|
526
530
|
* The IsolatedCircuit name is usually set by the platform, it's not required but
|
|
527
531
|
* if supplied can identify the circuit in certain effects, e.g. it is passed
|
|
@@ -107902,6 +107906,7 @@ declare class CopperPour extends PrimitiveComponent<typeof copperPourProps> {
|
|
|
107902
107906
|
};
|
|
107903
107907
|
doInitialCreateNetsFromProps(): void;
|
|
107904
107908
|
doInitialPcbCopperPourRender(): void;
|
|
107909
|
+
doInitialPcbViaStitchRender(): void;
|
|
107905
107910
|
}
|
|
107906
107911
|
|
|
107907
107912
|
declare class CopperText extends PrimitiveComponent<typeof copperTextProps> {
|
package/dist/index.js
CHANGED
|
@@ -452,6 +452,7 @@ var orderedRenderPhases = [
|
|
|
452
452
|
"PcbRouteNetIslands",
|
|
453
453
|
"PcbImplicitCopperPourRender",
|
|
454
454
|
"PcbCopperPourRender",
|
|
455
|
+
"PcbViaStitchRender",
|
|
455
456
|
"PcbDesignRuleChecks",
|
|
456
457
|
"SilkscreenOverlapAdjustment",
|
|
457
458
|
"CadModelRender",
|
|
@@ -513,6 +514,15 @@ var asyncPhaseDependencies = {
|
|
|
513
514
|
"PcbTraceRender",
|
|
514
515
|
"PcbRouteNetIslands"
|
|
515
516
|
],
|
|
517
|
+
PcbViaStitchRender: [
|
|
518
|
+
"PcbFootprintStringRender",
|
|
519
|
+
"FetchPartFootprint",
|
|
520
|
+
"PcbPlacementDesignRuleChecks",
|
|
521
|
+
"PcbTraceRender",
|
|
522
|
+
"PcbRouteNetIslands",
|
|
523
|
+
"PcbImplicitCopperPourRender",
|
|
524
|
+
"PcbCopperPourRender"
|
|
525
|
+
],
|
|
516
526
|
PcbPlacementDesignRuleChecks: [
|
|
517
527
|
"PcbFootprintStringRender",
|
|
518
528
|
"FetchPartFootprint"
|
|
@@ -529,7 +539,8 @@ var asyncPhaseDependencies = {
|
|
|
529
539
|
"PcbPlacementDesignRuleChecks",
|
|
530
540
|
"PcbTraceRender",
|
|
531
541
|
"PcbImplicitCopperPourRender",
|
|
532
|
-
"PcbCopperPourRender"
|
|
542
|
+
"PcbCopperPourRender",
|
|
543
|
+
"PcbViaStitchRender"
|
|
533
544
|
],
|
|
534
545
|
SilkscreenOverlapAdjustment: [
|
|
535
546
|
"PcbFootprintStringRender",
|
|
@@ -40819,6 +40830,480 @@ var ImplicitCopperPourPipelineSolver = class extends BasePipelineSolver {
|
|
|
40819
40830
|
// lib/solvers.ts
|
|
40820
40831
|
import { LayoutPipelineSolver } from "@tscircuit/matchpack";
|
|
40821
40832
|
import { SchematicTracePipelineSolver } from "@tscircuit/schematic-trace-solver";
|
|
40833
|
+
|
|
40834
|
+
// node_modules/@tscircuit/via-stitch-solver/lib/solvers/ViaStitchSolver.ts
|
|
40835
|
+
import { BaseSolver as BaseSolver3 } from "@tscircuit/solver-utils";
|
|
40836
|
+
|
|
40837
|
+
// node_modules/@tscircuit/via-stitch-solver/lib/geometry/brep-point-containment.ts
|
|
40838
|
+
var POINT_EPSILON = 1e-8;
|
|
40839
|
+
var isPointOnSegment = (point6, start, end) => {
|
|
40840
|
+
const cross3 = (point6.y - start.y) * (end.x - start.x) - (point6.x - start.x) * (end.y - start.y);
|
|
40841
|
+
if (Math.abs(cross3) > POINT_EPSILON) return false;
|
|
40842
|
+
const dot = (point6.x - start.x) * (end.x - start.x) + (point6.y - start.y) * (end.y - start.y);
|
|
40843
|
+
if (dot < -POINT_EPSILON) return false;
|
|
40844
|
+
const squaredLength = (end.x - start.x) ** 2 + (end.y - start.y) ** 2;
|
|
40845
|
+
return dot <= squaredLength + POINT_EPSILON;
|
|
40846
|
+
};
|
|
40847
|
+
var isPointInRing = (point6, ring) => {
|
|
40848
|
+
let isInside = false;
|
|
40849
|
+
for (let currentIndex = 0, previousIndex = ring.vertices.length - 1; currentIndex < ring.vertices.length; previousIndex = currentIndex++) {
|
|
40850
|
+
const current = ring.vertices[currentIndex];
|
|
40851
|
+
const previous = ring.vertices[previousIndex];
|
|
40852
|
+
if (isPointOnSegment(point6, previous, current)) return true;
|
|
40853
|
+
const crossesRay = current.y > point6.y !== previous.y > point6.y && point6.x < (previous.x - current.x) * (point6.y - current.y) / (previous.y - current.y) + current.x;
|
|
40854
|
+
if (crossesRay) isInside = !isInside;
|
|
40855
|
+
}
|
|
40856
|
+
return isInside;
|
|
40857
|
+
};
|
|
40858
|
+
var isPointInShape = (point6, shape) => isPointInRing(point6, shape.outer_ring) && !shape.inner_rings.some((innerRing) => isPointInRing(point6, innerRing));
|
|
40859
|
+
var isPointInShapeUnion = (point6, shapes) => shapes.some((shape) => isPointInShape(point6, shape));
|
|
40860
|
+
var getShapeUnionBounds = (shapes) => {
|
|
40861
|
+
const vertices = shapes.flatMap((shape) => shape.outer_ring.vertices);
|
|
40862
|
+
if (vertices.length === 0) return void 0;
|
|
40863
|
+
return {
|
|
40864
|
+
minX: Math.min(...vertices.map((vertex) => vertex.x)),
|
|
40865
|
+
maxX: Math.max(...vertices.map((vertex) => vertex.x)),
|
|
40866
|
+
minY: Math.min(...vertices.map((vertex) => vertex.y)),
|
|
40867
|
+
maxY: Math.max(...vertices.map((vertex) => vertex.y))
|
|
40868
|
+
};
|
|
40869
|
+
};
|
|
40870
|
+
var isViaAnnulusInsideShapeUnion = ({
|
|
40871
|
+
center,
|
|
40872
|
+
radius,
|
|
40873
|
+
shapes
|
|
40874
|
+
}) => {
|
|
40875
|
+
const samplePoints = [center];
|
|
40876
|
+
for (let sampleIndex = 0; sampleIndex < 32; sampleIndex++) {
|
|
40877
|
+
const angle = sampleIndex / 32 * Math.PI * 2;
|
|
40878
|
+
samplePoints.push({
|
|
40879
|
+
x: center.x + Math.cos(angle) * radius,
|
|
40880
|
+
y: center.y + Math.sin(angle) * radius
|
|
40881
|
+
});
|
|
40882
|
+
}
|
|
40883
|
+
return samplePoints.every(
|
|
40884
|
+
(samplePoint) => isPointInShapeUnion(samplePoint, shapes)
|
|
40885
|
+
);
|
|
40886
|
+
};
|
|
40887
|
+
|
|
40888
|
+
// node_modules/@tscircuit/via-stitch-solver/lib/geometry/circuit-element-obstacles.ts
|
|
40889
|
+
var layerMatches = (layer, layers) => layers.some((candidateLayer) => String(candidateLayer) === String(layer));
|
|
40890
|
+
var componentToObstacle = (component) => {
|
|
40891
|
+
if (component.do_not_place || !component.obstructs_within_bounds) {
|
|
40892
|
+
return void 0;
|
|
40893
|
+
}
|
|
40894
|
+
return {
|
|
40895
|
+
kind: "rect",
|
|
40896
|
+
center: component.center,
|
|
40897
|
+
width: component.width,
|
|
40898
|
+
height: component.height,
|
|
40899
|
+
ccwRotation: component.rotation
|
|
40900
|
+
};
|
|
40901
|
+
};
|
|
40902
|
+
var smtPadToObstacle = (smtPad) => {
|
|
40903
|
+
if (smtPad.shape === "circle") {
|
|
40904
|
+
return {
|
|
40905
|
+
kind: "circle",
|
|
40906
|
+
center: { x: smtPad.x, y: smtPad.y },
|
|
40907
|
+
radius: smtPad.radius
|
|
40908
|
+
};
|
|
40909
|
+
}
|
|
40910
|
+
if (smtPad.shape === "polygon") {
|
|
40911
|
+
return { kind: "polygon", points: smtPad.points };
|
|
40912
|
+
}
|
|
40913
|
+
return {
|
|
40914
|
+
kind: "rect",
|
|
40915
|
+
center: { x: smtPad.x, y: smtPad.y },
|
|
40916
|
+
width: smtPad.width,
|
|
40917
|
+
height: smtPad.height,
|
|
40918
|
+
ccwRotation: smtPad.shape === "rotated_rect" || smtPad.shape === "rotated_pill" ? smtPad.ccw_rotation : 0
|
|
40919
|
+
};
|
|
40920
|
+
};
|
|
40921
|
+
var platedHoleToObstacle = (platedHole) => {
|
|
40922
|
+
if (platedHole.shape === "circle") {
|
|
40923
|
+
return {
|
|
40924
|
+
kind: "circle",
|
|
40925
|
+
center: { x: platedHole.x, y: platedHole.y },
|
|
40926
|
+
radius: platedHole.outer_diameter / 2
|
|
40927
|
+
};
|
|
40928
|
+
}
|
|
40929
|
+
if ("outer_width" in platedHole) {
|
|
40930
|
+
return {
|
|
40931
|
+
kind: "rect",
|
|
40932
|
+
center: { x: platedHole.x, y: platedHole.y },
|
|
40933
|
+
width: platedHole.outer_width,
|
|
40934
|
+
height: platedHole.outer_height,
|
|
40935
|
+
ccwRotation: platedHole.ccw_rotation
|
|
40936
|
+
};
|
|
40937
|
+
}
|
|
40938
|
+
if (platedHole.shape === "hole_with_polygon_pad") {
|
|
40939
|
+
const rotationRadians = (platedHole.ccw_rotation ?? 0) * Math.PI / 180;
|
|
40940
|
+
const cosine = Math.cos(rotationRadians);
|
|
40941
|
+
const sine = Math.sin(rotationRadians);
|
|
40942
|
+
return {
|
|
40943
|
+
kind: "polygon",
|
|
40944
|
+
points: platedHole.pad_outline.map((point6) => ({
|
|
40945
|
+
x: platedHole.x + point6.x * cosine - point6.y * sine,
|
|
40946
|
+
y: platedHole.y + point6.x * sine + point6.y * cosine
|
|
40947
|
+
}))
|
|
40948
|
+
};
|
|
40949
|
+
}
|
|
40950
|
+
return {
|
|
40951
|
+
kind: "rect",
|
|
40952
|
+
center: { x: platedHole.x, y: platedHole.y },
|
|
40953
|
+
width: platedHole.rect_pad_width,
|
|
40954
|
+
height: platedHole.rect_pad_height,
|
|
40955
|
+
ccwRotation: "rect_ccw_rotation" in platedHole ? platedHole.rect_ccw_rotation ?? 0 : 0
|
|
40956
|
+
};
|
|
40957
|
+
};
|
|
40958
|
+
var holeToObstacle = (hole) => {
|
|
40959
|
+
if ("hole_diameter" in hole) {
|
|
40960
|
+
if (hole.hole_shape === "circle") {
|
|
40961
|
+
return {
|
|
40962
|
+
kind: "circle",
|
|
40963
|
+
center: { x: hole.x, y: hole.y },
|
|
40964
|
+
radius: hole.hole_diameter / 2
|
|
40965
|
+
};
|
|
40966
|
+
}
|
|
40967
|
+
return {
|
|
40968
|
+
kind: "rect",
|
|
40969
|
+
center: { x: hole.x, y: hole.y },
|
|
40970
|
+
width: hole.hole_diameter,
|
|
40971
|
+
height: hole.hole_diameter,
|
|
40972
|
+
ccwRotation: 0
|
|
40973
|
+
};
|
|
40974
|
+
}
|
|
40975
|
+
return {
|
|
40976
|
+
kind: "rect",
|
|
40977
|
+
center: { x: hole.x, y: hole.y },
|
|
40978
|
+
width: hole.hole_width,
|
|
40979
|
+
height: hole.hole_height,
|
|
40980
|
+
ccwRotation: hole.hole_shape === "rotated_pill" ? hole.ccw_rotation : 0
|
|
40981
|
+
};
|
|
40982
|
+
};
|
|
40983
|
+
var getDistanceToSegment = (point6, start, end) => {
|
|
40984
|
+
const segmentX = end.x - start.x;
|
|
40985
|
+
const segmentY = end.y - start.y;
|
|
40986
|
+
const squaredLength = segmentX ** 2 + segmentY ** 2;
|
|
40987
|
+
if (squaredLength === 0)
|
|
40988
|
+
return Math.hypot(point6.x - start.x, point6.y - start.y);
|
|
40989
|
+
const projection = Math.max(
|
|
40990
|
+
0,
|
|
40991
|
+
Math.min(
|
|
40992
|
+
1,
|
|
40993
|
+
((point6.x - start.x) * segmentX + (point6.y - start.y) * segmentY) / squaredLength
|
|
40994
|
+
)
|
|
40995
|
+
);
|
|
40996
|
+
return Math.hypot(
|
|
40997
|
+
point6.x - (start.x + projection * segmentX),
|
|
40998
|
+
point6.y - (start.y + projection * segmentY)
|
|
40999
|
+
);
|
|
41000
|
+
};
|
|
41001
|
+
var isPointInPolygon = (point6, polygon) => {
|
|
41002
|
+
let isInside = false;
|
|
41003
|
+
for (let currentIndex = 0, previousIndex = polygon.length - 1; currentIndex < polygon.length; previousIndex = currentIndex++) {
|
|
41004
|
+
const current = polygon[currentIndex];
|
|
41005
|
+
const previous = polygon[previousIndex];
|
|
41006
|
+
const crossesRay = current.y > point6.y !== previous.y > point6.y && point6.x < (previous.x - current.x) * (point6.y - current.y) / (previous.y - current.y) + current.x;
|
|
41007
|
+
if (crossesRay) isInside = !isInside;
|
|
41008
|
+
}
|
|
41009
|
+
return isInside;
|
|
41010
|
+
};
|
|
41011
|
+
var doesCircleIntersectObstacle = (center, radius, obstacle) => {
|
|
41012
|
+
if (obstacle.kind === "circle") {
|
|
41013
|
+
return Math.hypot(center.x - obstacle.center.x, center.y - obstacle.center.y) < radius + obstacle.radius;
|
|
41014
|
+
}
|
|
41015
|
+
if (obstacle.kind === "polygon") {
|
|
41016
|
+
if (isPointInPolygon(center, obstacle.points)) return true;
|
|
41017
|
+
return obstacle.points.some(
|
|
41018
|
+
(point6, pointIndex) => Boolean(
|
|
41019
|
+
getDistanceToSegment(
|
|
41020
|
+
center,
|
|
41021
|
+
point6,
|
|
41022
|
+
obstacle.points[(pointIndex + 1) % obstacle.points.length]
|
|
41023
|
+
) < radius
|
|
41024
|
+
)
|
|
41025
|
+
);
|
|
41026
|
+
}
|
|
41027
|
+
const rotationRadians = -obstacle.ccwRotation * Math.PI / 180;
|
|
41028
|
+
const deltaX = center.x - obstacle.center.x;
|
|
41029
|
+
const deltaY = center.y - obstacle.center.y;
|
|
41030
|
+
const localX = deltaX * Math.cos(rotationRadians) - deltaY * Math.sin(rotationRadians);
|
|
41031
|
+
const localY = deltaX * Math.sin(rotationRadians) + deltaY * Math.cos(rotationRadians);
|
|
41032
|
+
const outsideX = Math.max(Math.abs(localX) - obstacle.width / 2, 0);
|
|
41033
|
+
const outsideY = Math.max(Math.abs(localY) - obstacle.height / 2, 0);
|
|
41034
|
+
return Math.hypot(outsideX, outsideY) < radius;
|
|
41035
|
+
};
|
|
41036
|
+
var getStitchingObstacles = (circuitJson, layers) => circuitJson.flatMap((element) => {
|
|
41037
|
+
if (element.type === "pcb_component" && layerMatches(element.layer, layers)) {
|
|
41038
|
+
const obstacle = componentToObstacle(element);
|
|
41039
|
+
return obstacle ? [obstacle] : [];
|
|
41040
|
+
}
|
|
41041
|
+
if (element.type === "pcb_smtpad" && layerMatches(element.layer, layers)) {
|
|
41042
|
+
return [smtPadToObstacle(element)];
|
|
41043
|
+
}
|
|
41044
|
+
if (element.type === "pcb_plated_hole" && element.layers.some((layer) => layerMatches(layer, layers))) {
|
|
41045
|
+
return [platedHoleToObstacle(element)];
|
|
41046
|
+
}
|
|
41047
|
+
if (element.type === "pcb_hole") return [holeToObstacle(element)];
|
|
41048
|
+
return [];
|
|
41049
|
+
});
|
|
41050
|
+
var doesViaIntersectStitchingObstacle = ({
|
|
41051
|
+
center,
|
|
41052
|
+
radius,
|
|
41053
|
+
obstacles
|
|
41054
|
+
}) => obstacles.some(
|
|
41055
|
+
(obstacle) => doesCircleIntersectObstacle(center, radius, obstacle)
|
|
41056
|
+
);
|
|
41057
|
+
|
|
41058
|
+
// node_modules/@tscircuit/via-stitch-solver/lib/solvers/ViaStitchSolver.ts
|
|
41059
|
+
var resolveOptions = (options = {}) => {
|
|
41060
|
+
const resolvedOptions = {
|
|
41061
|
+
sourceNetIds: options.sourceNetIds ? new Set(options.sourceNetIds) : void 0,
|
|
41062
|
+
layers: options.layers ?? ["top", "bottom"],
|
|
41063
|
+
viaPitch: options.viaPitch ?? 1,
|
|
41064
|
+
viaHoleDiameter: options.viaHoleDiameter ?? 0.3,
|
|
41065
|
+
viaOuterDiameter: options.viaOuterDiameter ?? 0.6,
|
|
41066
|
+
pourEdgeClearance: options.pourEdgeClearance ?? 0.2,
|
|
41067
|
+
obstacleClearance: options.obstacleClearance ?? 0.2,
|
|
41068
|
+
minimumViaSeparation: options.minimumViaSeparation ?? Math.max(options.viaOuterDiameter ?? 0.6, 0.8),
|
|
41069
|
+
gridOrigin: options.gridOrigin ?? { x: 0, y: 0 },
|
|
41070
|
+
isTented: options.isTented ?? true
|
|
41071
|
+
};
|
|
41072
|
+
for (const [optionName, optionValue] of [
|
|
41073
|
+
["viaPitch", resolvedOptions.viaPitch],
|
|
41074
|
+
["viaHoleDiameter", resolvedOptions.viaHoleDiameter],
|
|
41075
|
+
["viaOuterDiameter", resolvedOptions.viaOuterDiameter],
|
|
41076
|
+
["minimumViaSeparation", resolvedOptions.minimumViaSeparation]
|
|
41077
|
+
]) {
|
|
41078
|
+
if (!Number.isFinite(optionValue) || optionValue <= 0) {
|
|
41079
|
+
throw new Error(`${optionName} must be a finite number greater than zero`);
|
|
41080
|
+
}
|
|
41081
|
+
}
|
|
41082
|
+
if (!Number.isFinite(resolvedOptions.pourEdgeClearance) || resolvedOptions.pourEdgeClearance < 0) {
|
|
41083
|
+
throw new Error("pourEdgeClearance must be a finite non-negative number");
|
|
41084
|
+
}
|
|
41085
|
+
if (!Number.isFinite(resolvedOptions.obstacleClearance) || resolvedOptions.obstacleClearance < 0) {
|
|
41086
|
+
throw new Error("obstacleClearance must be a finite non-negative number");
|
|
41087
|
+
}
|
|
41088
|
+
if (!Number.isFinite(resolvedOptions.gridOrigin.x) || !Number.isFinite(resolvedOptions.gridOrigin.y)) {
|
|
41089
|
+
throw new Error("gridOrigin coordinates must be finite numbers");
|
|
41090
|
+
}
|
|
41091
|
+
if (resolvedOptions.viaHoleDiameter >= resolvedOptions.viaOuterDiameter) {
|
|
41092
|
+
throw new Error("viaHoleDiameter must be smaller than viaOuterDiameter");
|
|
41093
|
+
}
|
|
41094
|
+
if (String(resolvedOptions.layers[0]) === String(resolvedOptions.layers[1])) {
|
|
41095
|
+
throw new Error("layers must contain two distinct PCB layers");
|
|
41096
|
+
}
|
|
41097
|
+
return resolvedOptions;
|
|
41098
|
+
};
|
|
41099
|
+
var isBrepCopperPour = (element) => element.type === "pcb_copper_pour" && element.shape === "brep";
|
|
41100
|
+
var getCopperPourPairContexts = (input, options) => {
|
|
41101
|
+
const sourceNetsById = new Map(
|
|
41102
|
+
input.circuitJson.filter((element) => element.type === "source_net").map((sourceNet) => [sourceNet.source_net_id, sourceNet])
|
|
41103
|
+
);
|
|
41104
|
+
const poursBySourceNetId = /* @__PURE__ */ new Map();
|
|
41105
|
+
for (const element of input.circuitJson) {
|
|
41106
|
+
if (!isBrepCopperPour(element) || !element.source_net_id) continue;
|
|
41107
|
+
if (options.sourceNetIds && !options.sourceNetIds.has(element.source_net_id)) {
|
|
41108
|
+
continue;
|
|
41109
|
+
}
|
|
41110
|
+
const sourceNetPours = poursBySourceNetId.get(element.source_net_id) ?? [];
|
|
41111
|
+
sourceNetPours.push(element);
|
|
41112
|
+
poursBySourceNetId.set(element.source_net_id, sourceNetPours);
|
|
41113
|
+
}
|
|
41114
|
+
const [fromLayer, toLayer] = options.layers;
|
|
41115
|
+
const contexts = [];
|
|
41116
|
+
for (const [sourceNetId, sourceNetPours] of poursBySourceNetId) {
|
|
41117
|
+
const fromLayerPours = sourceNetPours.filter(
|
|
41118
|
+
(copperPour) => String(copperPour.layer) === String(fromLayer)
|
|
41119
|
+
);
|
|
41120
|
+
const toLayerPours = sourceNetPours.filter(
|
|
41121
|
+
(copperPour) => String(copperPour.layer) === String(toLayer)
|
|
41122
|
+
);
|
|
41123
|
+
if (fromLayerPours.length === 0 || toLayerPours.length === 0) continue;
|
|
41124
|
+
contexts.push({
|
|
41125
|
+
sourceNetId,
|
|
41126
|
+
sourceNet: sourceNetsById.get(sourceNetId),
|
|
41127
|
+
fromLayerPours,
|
|
41128
|
+
toLayerPours
|
|
41129
|
+
});
|
|
41130
|
+
}
|
|
41131
|
+
return contexts;
|
|
41132
|
+
};
|
|
41133
|
+
var getPcbTraceViaRadius = (routePoint, fallbackRadius) => {
|
|
41134
|
+
const routePointWithDiameter = routePoint;
|
|
41135
|
+
return (routePointWithDiameter.outer_diameter ?? fallbackRadius * 2) / 2;
|
|
41136
|
+
};
|
|
41137
|
+
var isTooCloseToOccupiedVia = ({
|
|
41138
|
+
center,
|
|
41139
|
+
radius,
|
|
41140
|
+
occupiedVias,
|
|
41141
|
+
minimumViaSeparation
|
|
41142
|
+
}) => occupiedVias.some(
|
|
41143
|
+
(occupiedVia) => Math.hypot(
|
|
41144
|
+
center.x - occupiedVia.center.x,
|
|
41145
|
+
center.y - occupiedVia.center.y
|
|
41146
|
+
) < Math.max(minimumViaSeparation, radius + occupiedVia.radius)
|
|
41147
|
+
);
|
|
41148
|
+
var getGridCoordinates = ({
|
|
41149
|
+
minimum,
|
|
41150
|
+
maximum,
|
|
41151
|
+
origin,
|
|
41152
|
+
pitch
|
|
41153
|
+
}) => {
|
|
41154
|
+
const coordinates = [];
|
|
41155
|
+
const firstGridIndex = Math.ceil((minimum - origin) / pitch);
|
|
41156
|
+
const lastGridIndex = Math.floor((maximum - origin) / pitch);
|
|
41157
|
+
for (let gridIndex = firstGridIndex; gridIndex <= lastGridIndex; gridIndex++) {
|
|
41158
|
+
coordinates.push(origin + gridIndex * pitch);
|
|
41159
|
+
}
|
|
41160
|
+
return coordinates;
|
|
41161
|
+
};
|
|
41162
|
+
var ViaStitchSolver = class extends BaseSolver3 {
|
|
41163
|
+
constructor(input) {
|
|
41164
|
+
super();
|
|
41165
|
+
this.input = input;
|
|
41166
|
+
this.options = resolveOptions(input.options);
|
|
41167
|
+
this.copperPourPairContexts = getCopperPourPairContexts(input, this.options);
|
|
41168
|
+
this.stitchingObstacles = getStitchingObstacles(
|
|
41169
|
+
input.circuitJson,
|
|
41170
|
+
this.options.layers
|
|
41171
|
+
);
|
|
41172
|
+
const fallbackViaRadius = this.options.viaOuterDiameter / 2;
|
|
41173
|
+
for (const element of input.circuitJson) {
|
|
41174
|
+
if (element.type === "pcb_via") {
|
|
41175
|
+
const pcbVia = element;
|
|
41176
|
+
this.existingPcbViaIds.add(pcbVia.pcb_via_id);
|
|
41177
|
+
this.occupiedVias.push({
|
|
41178
|
+
center: { x: pcbVia.x, y: pcbVia.y },
|
|
41179
|
+
radius: pcbVia.outer_diameter / 2
|
|
41180
|
+
});
|
|
41181
|
+
} else if (element.type === "pcb_trace") {
|
|
41182
|
+
for (const routePoint of element.route) {
|
|
41183
|
+
if (routePoint.route_type !== "via") continue;
|
|
41184
|
+
this.occupiedVias.push({
|
|
41185
|
+
center: { x: routePoint.x, y: routePoint.y },
|
|
41186
|
+
radius: getPcbTraceViaRadius(routePoint, fallbackViaRadius)
|
|
41187
|
+
});
|
|
41188
|
+
}
|
|
41189
|
+
}
|
|
41190
|
+
}
|
|
41191
|
+
}
|
|
41192
|
+
input;
|
|
41193
|
+
options;
|
|
41194
|
+
copperPourPairContexts;
|
|
41195
|
+
pcbVias = [];
|
|
41196
|
+
occupiedVias = [];
|
|
41197
|
+
existingPcbViaIds = /* @__PURE__ */ new Set();
|
|
41198
|
+
stitchingObstacles;
|
|
41199
|
+
nextCopperPourPairIndex = 0;
|
|
41200
|
+
nextViaId = 0;
|
|
41201
|
+
_step() {
|
|
41202
|
+
const copperPourPairContext = this.copperPourPairContexts[this.nextCopperPourPairIndex];
|
|
41203
|
+
if (!copperPourPairContext) {
|
|
41204
|
+
this.solved = true;
|
|
41205
|
+
this.progress = 1;
|
|
41206
|
+
return;
|
|
41207
|
+
}
|
|
41208
|
+
this.processCopperPourPair(copperPourPairContext);
|
|
41209
|
+
this.nextCopperPourPairIndex += 1;
|
|
41210
|
+
this.progress = this.copperPourPairContexts.length === 0 ? 1 : this.nextCopperPourPairIndex / this.copperPourPairContexts.length;
|
|
41211
|
+
this.solved = this.nextCopperPourPairIndex === this.copperPourPairContexts.length;
|
|
41212
|
+
}
|
|
41213
|
+
processCopperPourPair(context) {
|
|
41214
|
+
const [fromLayer, toLayer] = this.options.layers;
|
|
41215
|
+
const fromLayerShapes = context.fromLayerPours.map(
|
|
41216
|
+
(copperPour) => copperPour.brep_shape
|
|
41217
|
+
);
|
|
41218
|
+
const toLayerShapes = context.toLayerPours.map(
|
|
41219
|
+
(copperPour) => copperPour.brep_shape
|
|
41220
|
+
);
|
|
41221
|
+
const fromBounds = getShapeUnionBounds(fromLayerShapes);
|
|
41222
|
+
const toBounds = getShapeUnionBounds(toLayerShapes);
|
|
41223
|
+
if (!fromBounds || !toBounds) return;
|
|
41224
|
+
const overlapBounds = {
|
|
41225
|
+
minX: Math.max(fromBounds.minX, toBounds.minX),
|
|
41226
|
+
maxX: Math.min(fromBounds.maxX, toBounds.maxX),
|
|
41227
|
+
minY: Math.max(fromBounds.minY, toBounds.minY),
|
|
41228
|
+
maxY: Math.min(fromBounds.maxY, toBounds.maxY)
|
|
41229
|
+
};
|
|
41230
|
+
if (overlapBounds.minX > overlapBounds.maxX || overlapBounds.minY > overlapBounds.maxY) {
|
|
41231
|
+
return;
|
|
41232
|
+
}
|
|
41233
|
+
const viaRadius = this.options.viaOuterDiameter / 2;
|
|
41234
|
+
const requiredCopperRadius = viaRadius + this.options.pourEdgeClearance;
|
|
41235
|
+
const requiredObstacleRadius = viaRadius + this.options.obstacleClearance;
|
|
41236
|
+
const xCoordinates = getGridCoordinates({
|
|
41237
|
+
minimum: overlapBounds.minX + requiredCopperRadius,
|
|
41238
|
+
maximum: overlapBounds.maxX - requiredCopperRadius,
|
|
41239
|
+
origin: this.options.gridOrigin.x,
|
|
41240
|
+
pitch: this.options.viaPitch
|
|
41241
|
+
});
|
|
41242
|
+
const yCoordinates = getGridCoordinates({
|
|
41243
|
+
minimum: overlapBounds.minY + requiredCopperRadius,
|
|
41244
|
+
maximum: overlapBounds.maxY - requiredCopperRadius,
|
|
41245
|
+
origin: this.options.gridOrigin.y,
|
|
41246
|
+
pitch: this.options.viaPitch
|
|
41247
|
+
});
|
|
41248
|
+
for (const y of yCoordinates) {
|
|
41249
|
+
for (const x of xCoordinates) {
|
|
41250
|
+
const center = { x, y };
|
|
41251
|
+
if (isTooCloseToOccupiedVia({
|
|
41252
|
+
center,
|
|
41253
|
+
radius: viaRadius,
|
|
41254
|
+
occupiedVias: this.occupiedVias,
|
|
41255
|
+
minimumViaSeparation: this.options.minimumViaSeparation
|
|
41256
|
+
}) || doesViaIntersectStitchingObstacle({
|
|
41257
|
+
center,
|
|
41258
|
+
radius: requiredObstacleRadius,
|
|
41259
|
+
obstacles: this.stitchingObstacles
|
|
41260
|
+
}) || !isViaAnnulusInsideShapeUnion({
|
|
41261
|
+
center,
|
|
41262
|
+
radius: requiredCopperRadius,
|
|
41263
|
+
shapes: fromLayerShapes
|
|
41264
|
+
}) || !isViaAnnulusInsideShapeUnion({
|
|
41265
|
+
center,
|
|
41266
|
+
radius: requiredCopperRadius,
|
|
41267
|
+
shapes: toLayerShapes
|
|
41268
|
+
})) {
|
|
41269
|
+
continue;
|
|
41270
|
+
}
|
|
41271
|
+
let pcbViaId = `via_stitch_via_${this.nextViaId++}`;
|
|
41272
|
+
while (this.existingPcbViaIds.has(pcbViaId)) {
|
|
41273
|
+
pcbViaId = `via_stitch_via_${this.nextViaId++}`;
|
|
41274
|
+
}
|
|
41275
|
+
const referencePour = context.fromLayerPours[0];
|
|
41276
|
+
const pcbVia = {
|
|
41277
|
+
type: "pcb_via",
|
|
41278
|
+
pcb_via_id: pcbViaId,
|
|
41279
|
+
x,
|
|
41280
|
+
y,
|
|
41281
|
+
hole_diameter: this.options.viaHoleDiameter,
|
|
41282
|
+
outer_diameter: this.options.viaOuterDiameter,
|
|
41283
|
+
layers: [fromLayer, toLayer],
|
|
41284
|
+
from_layer: fromLayer,
|
|
41285
|
+
to_layer: toLayer,
|
|
41286
|
+
source_net_id: context.sourceNetId,
|
|
41287
|
+
subcircuit_id: referencePour.subcircuit_id,
|
|
41288
|
+
pcb_group_id: referencePour.pcb_group_id,
|
|
41289
|
+
subcircuit_connectivity_map_key: context.sourceNet?.subcircuit_connectivity_map_key,
|
|
41290
|
+
is_tented: this.options.isTented
|
|
41291
|
+
};
|
|
41292
|
+
this.pcbVias.push(pcbVia);
|
|
41293
|
+
this.existingPcbViaIds.add(pcbViaId);
|
|
41294
|
+
this.occupiedVias.push({ center, radius: viaRadius });
|
|
41295
|
+
}
|
|
41296
|
+
}
|
|
41297
|
+
}
|
|
41298
|
+
getOutput() {
|
|
41299
|
+
return {
|
|
41300
|
+
processedCopperPourPairCount: this.copperPourPairContexts.length,
|
|
41301
|
+
pcbVias: this.pcbVias
|
|
41302
|
+
};
|
|
41303
|
+
}
|
|
41304
|
+
};
|
|
41305
|
+
|
|
41306
|
+
// lib/solvers.ts
|
|
40822
41307
|
import { PackSolver2 } from "calculate-packing";
|
|
40823
41308
|
var SOLVERS = {
|
|
40824
41309
|
PackSolver2,
|
|
@@ -40838,7 +41323,8 @@ var SOLVERS = {
|
|
|
40838
41323
|
CreateFdmEnclosureSolver,
|
|
40839
41324
|
FanoutSolver,
|
|
40840
41325
|
ImplicitCopperPourPipelineSolver,
|
|
40841
|
-
SchematicTracePipelineSolver
|
|
41326
|
+
SchematicTracePipelineSolver,
|
|
41327
|
+
ViaStitchSolver
|
|
40842
41328
|
};
|
|
40843
41329
|
|
|
40844
41330
|
// lib/utils/autorouting/LocalCacheEngineCacheProvider.ts
|
|
@@ -50925,7 +51411,7 @@ function Group_getRoutingPhasePlans(group) {
|
|
|
50925
51411
|
var package_default = {
|
|
50926
51412
|
name: "@tscircuit/core",
|
|
50927
51413
|
type: "module",
|
|
50928
|
-
version: "0.0.
|
|
51414
|
+
version: "0.0.1858",
|
|
50929
51415
|
types: "dist/index.d.ts",
|
|
50930
51416
|
main: "dist/index.js",
|
|
50931
51417
|
module: "dist/index.js",
|
|
@@ -50959,7 +51445,7 @@ var package_default = {
|
|
|
50959
51445
|
"@tsci/tscircuit.ti": "github:tscircuit/ti#57e314be4b2b06bc546d4def7453e619604d1157",
|
|
50960
51446
|
"@tscircuit/alphabet": "0.0.25",
|
|
50961
51447
|
"@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
|
|
50962
|
-
"@tscircuit/capacity-autorouter": "^0.0.
|
|
51448
|
+
"@tscircuit/capacity-autorouter": "^0.0.886",
|
|
50963
51449
|
"@tscircuit/checks": "^0.0.184",
|
|
50964
51450
|
"@tscircuit/circuit-json-util": "^0.0.106",
|
|
50965
51451
|
"@tscircuit/common": "^0.0.20",
|
|
@@ -50983,6 +51469,7 @@ var package_default = {
|
|
|
50983
51469
|
"@tscircuit/schematic-trace-solver": "^0.0.186",
|
|
50984
51470
|
"@tscircuit/solver-utils": "^0.0.16",
|
|
50985
51471
|
"@tscircuit/soup-util": "^0.0.41",
|
|
51472
|
+
"@tscircuit/via-stitch-solver": "github:tscircuit/via-stitch-solver#75653b6440e75584b052f03595afd34283ae7558",
|
|
50986
51473
|
"@tscircuit/winding-breakout-point-solver": "github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803",
|
|
50987
51474
|
"@types/bun": "^1.2.16",
|
|
50988
51475
|
"@types/debug": "^4.1.12",
|
|
@@ -51654,7 +52141,7 @@ function getAccumulatedPcbTracesWithStageOutputReplacements({
|
|
|
51654
52141
|
// lib/components/primitive-components/Group/get-source-trace-id-for-routed-trace.ts
|
|
51655
52142
|
import { distance as distance14, pointToSegmentDistance as pointToSegmentDistance3 } from "@tscircuit/math-utils";
|
|
51656
52143
|
import { ConnectivityMap as ConnectivityMap5 } from "circuit-json-to-connectivity-map";
|
|
51657
|
-
var
|
|
52144
|
+
var POINT_EPSILON2 = 1e-6;
|
|
51658
52145
|
function isPointOnWireSegment({
|
|
51659
52146
|
point: point6,
|
|
51660
52147
|
segmentStart,
|
|
@@ -51663,7 +52150,7 @@ function isPointOnWireSegment({
|
|
|
51663
52150
|
if (point6.layer && (segmentStart.layer !== point6.layer || segmentEnd.layer !== point6.layer)) {
|
|
51664
52151
|
return false;
|
|
51665
52152
|
}
|
|
51666
|
-
return pointToSegmentDistance3(point6, segmentStart, segmentEnd) <=
|
|
52153
|
+
return pointToSegmentDistance3(point6, segmentStart, segmentEnd) <= POINT_EPSILON2;
|
|
51667
52154
|
}
|
|
51668
52155
|
function isPointInSmtPad({
|
|
51669
52156
|
point: point6,
|
|
@@ -55449,6 +55936,8 @@ var IsolatedCircuit = class {
|
|
|
55449
55936
|
pcbDisabled = false;
|
|
55450
55937
|
pcbRoutingDisabled = false;
|
|
55451
55938
|
_featureMspSchematicTraceRouting = true;
|
|
55939
|
+
/** Experimental automatic via stitching; opt in before rendering. */
|
|
55940
|
+
_featurePcbViaStitching = false;
|
|
55452
55941
|
/**
|
|
55453
55942
|
* The IsolatedCircuit name is usually set by the platform, it's not required but
|
|
55454
55943
|
* if supplied can identify the circuit in certain effects, e.g. it is passed
|
|
@@ -55873,7 +56362,7 @@ import {
|
|
|
55873
56362
|
// lib/components/primitive-components/CopperPour/utils/mark-trace-segments-inside-copper-pour.ts
|
|
55874
56363
|
var EPSILON14 = 1e-9;
|
|
55875
56364
|
var isWireRoutePoint = (routePoint) => routePoint.route_type === "wire";
|
|
55876
|
-
var
|
|
56365
|
+
var isPointOnSegment2 = (p, a, b) => {
|
|
55877
56366
|
const cross3 = (p.y - a.y) * (b.x - a.x) - (p.x - a.x) * (b.y - a.y);
|
|
55878
56367
|
if (Math.abs(cross3) > EPSILON14) return false;
|
|
55879
56368
|
const dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
|
|
@@ -55882,12 +56371,12 @@ var isPointOnSegment = (p, a, b) => {
|
|
|
55882
56371
|
if (dot - squaredLength > EPSILON14) return false;
|
|
55883
56372
|
return true;
|
|
55884
56373
|
};
|
|
55885
|
-
var
|
|
56374
|
+
var isPointInRing2 = (point6, ring) => {
|
|
55886
56375
|
if (ring.length < 3) return false;
|
|
55887
56376
|
let inside = false;
|
|
55888
56377
|
let previous = ring[ring.length - 1];
|
|
55889
56378
|
for (const current of ring) {
|
|
55890
|
-
if (
|
|
56379
|
+
if (isPointOnSegment2(point6, previous, current)) return true;
|
|
55891
56380
|
const intersects = current.y > point6.y !== previous.y > point6.y && point6.x < (previous.x - current.x) * (point6.y - current.y) / (previous.y - current.y) + current.x;
|
|
55892
56381
|
if (intersects) inside = !inside;
|
|
55893
56382
|
previous = current;
|
|
@@ -55910,10 +56399,10 @@ var isPointInBrepPour = (p, pour) => {
|
|
|
55910
56399
|
x: v.x,
|
|
55911
56400
|
y: v.y
|
|
55912
56401
|
}));
|
|
55913
|
-
if (!
|
|
56402
|
+
if (!isPointInRing2(p, outerRing)) return false;
|
|
55914
56403
|
for (const innerRing of pour.brep_shape.inner_rings) {
|
|
55915
56404
|
const points = innerRing.vertices.map((v) => ({ x: v.x, y: v.y }));
|
|
55916
|
-
if (
|
|
56405
|
+
if (isPointInRing2(p, points)) return false;
|
|
55917
56406
|
}
|
|
55918
56407
|
return true;
|
|
55919
56408
|
};
|
|
@@ -56100,6 +56589,59 @@ function CopperPour_doInitialPcbCopperPourRender(copperPour) {
|
|
|
56100
56589
|
});
|
|
56101
56590
|
}
|
|
56102
56591
|
|
|
56592
|
+
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbViaStitchRender.ts
|
|
56593
|
+
var renderViaStitchingForCopperPours = (copperPour) => {
|
|
56594
|
+
const subcircuit = copperPour.getSubcircuit();
|
|
56595
|
+
if (!subcircuit.root) return;
|
|
56596
|
+
const copperPours = subcircuit.selectAll("copperpour").filter(
|
|
56597
|
+
(candidateCopperPour) => candidateCopperPour.getSubcircuit() === subcircuit
|
|
56598
|
+
);
|
|
56599
|
+
if (copperPours[0] !== copperPour) return;
|
|
56600
|
+
const sourceNetIds = copperPours.flatMap((candidateCopperPour) => {
|
|
56601
|
+
const net = subcircuit.selectOne(
|
|
56602
|
+
candidateCopperPour._parsedProps.connectsTo
|
|
56603
|
+
);
|
|
56604
|
+
return net?.source_net_id ? [net.source_net_id] : [];
|
|
56605
|
+
});
|
|
56606
|
+
if (sourceNetIds.length === 0) return;
|
|
56607
|
+
const { db } = subcircuit.root;
|
|
56608
|
+
const pcbStyle = copperPour.getInheritedMergedProperty("pcbStyle");
|
|
56609
|
+
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle);
|
|
56610
|
+
const boardComponent = copperPour._getBoard();
|
|
56611
|
+
const pcbBoard = boardComponent?.pcb_board_id ? db.pcb_board.get(boardComponent.pcb_board_id) : void 0;
|
|
56612
|
+
const solverInput = {
|
|
56613
|
+
circuitJson: db.toArray(),
|
|
56614
|
+
options: {
|
|
56615
|
+
sourceNetIds: [...new Set(sourceNetIds)],
|
|
56616
|
+
viaHoleDiameter: pcbBoard?.min_via_hole_diameter ?? holeDiameter,
|
|
56617
|
+
viaOuterDiameter: pcbBoard?.min_via_pad_diameter ?? padDiameter
|
|
56618
|
+
}
|
|
56619
|
+
};
|
|
56620
|
+
const solver = new ViaStitchSolver(solverInput);
|
|
56621
|
+
subcircuit.root.emit("solver:started", {
|
|
56622
|
+
type: "solver:started",
|
|
56623
|
+
solverName: "ViaStitchSolver",
|
|
56624
|
+
solverParams: solverInput,
|
|
56625
|
+
solverConstructorArgs: [solverInput],
|
|
56626
|
+
componentName: subcircuit.getString()
|
|
56627
|
+
});
|
|
56628
|
+
solver.solve();
|
|
56629
|
+
if (solver.failed) {
|
|
56630
|
+
throw new Error(solver.error ?? "Via stitching solver failed");
|
|
56631
|
+
}
|
|
56632
|
+
for (const pcbVia of solver.getOutput().pcbVias) {
|
|
56633
|
+
const { pcb_via_id: _solverViaId, ...pcbViaInput } = pcbVia;
|
|
56634
|
+
db.pcb_via.insert(pcbViaInput);
|
|
56635
|
+
}
|
|
56636
|
+
};
|
|
56637
|
+
function CopperPour_doInitialPcbViaStitchRender(copperPour) {
|
|
56638
|
+
if (copperPour.root?.pcbDisabled || !copperPour.root?._featurePcbViaStitching)
|
|
56639
|
+
return;
|
|
56640
|
+
copperPour._queueAsyncEffect("PcbViaStitchRender", async () => {
|
|
56641
|
+
renderViaStitchingForCopperPours(copperPour);
|
|
56642
|
+
});
|
|
56643
|
+
}
|
|
56644
|
+
|
|
56103
56645
|
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
56104
56646
|
var CopperPour = class extends PrimitiveComponent2 {
|
|
56105
56647
|
isPcbPrimitive = true;
|
|
@@ -56120,6 +56662,9 @@ var CopperPour = class extends PrimitiveComponent2 {
|
|
|
56120
56662
|
doInitialPcbCopperPourRender() {
|
|
56121
56663
|
CopperPour_doInitialPcbCopperPourRender(this);
|
|
56122
56664
|
}
|
|
56665
|
+
doInitialPcbViaStitchRender() {
|
|
56666
|
+
CopperPour_doInitialPcbViaStitchRender(this);
|
|
56667
|
+
}
|
|
56123
56668
|
};
|
|
56124
56669
|
|
|
56125
56670
|
// lib/components/normal-components/Board_doInitialPcbImplicitCopperPourRender.ts
|
|
@@ -60225,7 +60770,7 @@ var validateWindingBreakoutInput = (input) => {
|
|
|
60225
60770
|
};
|
|
60226
60771
|
|
|
60227
60772
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/GatePlacementSolver.ts
|
|
60228
|
-
import { BaseSolver as
|
|
60773
|
+
import { BaseSolver as BaseSolver4 } from "@tscircuit/solver-utils";
|
|
60229
60774
|
|
|
60230
60775
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/gate-placement/place-breakout-gates.ts
|
|
60231
60776
|
var GEOMETRY_EPSILON = 1e-9;
|
|
@@ -60755,7 +61300,7 @@ var getSharedGateSlotCount = (points) => new Set(
|
|
|
60755
61300
|
(point6) => `${point6.regionId}:${point6.x.toFixed(9)}:${point6.y.toFixed(9)}`
|
|
60756
61301
|
)
|
|
60757
61302
|
).size;
|
|
60758
|
-
var GatePlacementSolver = class extends
|
|
61303
|
+
var GatePlacementSolver = class extends BaseSolver4 {
|
|
60759
61304
|
constructor(params) {
|
|
60760
61305
|
super();
|
|
60761
61306
|
this.params = params;
|
|
@@ -60894,7 +61439,7 @@ var GatePlacementSolver = class extends BaseSolver3 {
|
|
|
60894
61439
|
};
|
|
60895
61440
|
|
|
60896
61441
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/ReferenceOrderingSolver.ts
|
|
60897
|
-
import { BaseSolver as
|
|
61442
|
+
import { BaseSolver as BaseSolver5 } from "@tscircuit/solver-utils";
|
|
60898
61443
|
|
|
60899
61444
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/ordering/get-natural-winding-order.ts
|
|
60900
61445
|
var getNaturalWindingOrder = (region, connections) => connections.map((connection) => {
|
|
@@ -60961,7 +61506,7 @@ var getReferenceWindingOrder = (naturalOrder, atomicGroups, buses) => {
|
|
|
60961
61506
|
};
|
|
60962
61507
|
|
|
60963
61508
|
// node_modules/@tscircuit/winding-breakout-point-solver/lib/solvers/ReferenceOrderingSolver.ts
|
|
60964
|
-
var ReferenceOrderingSolver = class extends
|
|
61509
|
+
var ReferenceOrderingSolver = class extends BaseSolver5 {
|
|
60965
61510
|
constructor(params) {
|
|
60966
61511
|
super();
|
|
60967
61512
|
this.params = params;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.1859",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@tsci/tscircuit.ti": "github:tscircuit/ti#57e314be4b2b06bc546d4def7453e619604d1157",
|
|
36
36
|
"@tscircuit/alphabet": "0.0.25",
|
|
37
37
|
"@tscircuit/bga-fanout-solver": "github:tscircuit/bga-fanout-solver#247c835cb8d69b65e53891dcf869731079415b39",
|
|
38
|
-
"@tscircuit/capacity-autorouter": "^0.0.
|
|
38
|
+
"@tscircuit/capacity-autorouter": "^0.0.886",
|
|
39
39
|
"@tscircuit/checks": "^0.0.184",
|
|
40
40
|
"@tscircuit/circuit-json-util": "^0.0.106",
|
|
41
41
|
"@tscircuit/common": "^0.0.20",
|
|
@@ -59,6 +59,7 @@
|
|
|
59
59
|
"@tscircuit/schematic-trace-solver": "^0.0.186",
|
|
60
60
|
"@tscircuit/solver-utils": "^0.0.16",
|
|
61
61
|
"@tscircuit/soup-util": "^0.0.41",
|
|
62
|
+
"@tscircuit/via-stitch-solver": "github:tscircuit/via-stitch-solver#75653b6440e75584b052f03595afd34283ae7558",
|
|
62
63
|
"@tscircuit/winding-breakout-point-solver": "github:tscircuit/winding-breakout-point-solver#202dbe9eb0088633b6fa094120dba6f2f41f8803",
|
|
63
64
|
"@types/bun": "^1.2.16",
|
|
64
65
|
"@types/debug": "^4.1.12",
|