@tscircuit/core 0.0.1966 → 0.0.1968
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 +8 -4
- package/dist/index.js +373 -409
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -358,6 +358,7 @@ interface DebugLogOutputEvent {
|
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
interface IIsolatedCircuit {
|
|
361
|
+
_hasRenderLifecycleListeners?: boolean;
|
|
361
362
|
hasEventListener?(event: RootCircuitEventName): boolean;
|
|
362
363
|
emit(event: RootCircuitEventName, ...args: any[]): void;
|
|
363
364
|
on(event: RootCircuitEventName, listener: (...args: any[]) => void): void;
|
|
@@ -368,9 +369,9 @@ interface IIsolatedCircuit {
|
|
|
368
369
|
interface IRootCircuit extends IIsolatedCircuit {
|
|
369
370
|
}
|
|
370
371
|
|
|
371
|
-
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", "PcbFlexRender", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "
|
|
372
|
+
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", "PcbFlexRender", "PcbAutoplaceBreakoutPoints", "PcbTraceHintRender", "PcbManualTraceRender", "PcbPlacementDesignRuleChecks", "PcbTraceRender", "PcbRouteNetIslands", "PcbCopperPourRender", "PcbViaStitchRender", "PcbCopperPourCleanup", "PcbDesignRuleChecks", "SilkscreenOverlapAdjustment", "CadModelRender", "PartsEngineRender", "PartOrientationAnalysis", "SupplierFootprintMismatchWarning", "SimulationSpiceEngineRender"];
|
|
372
373
|
type RenderPhase = (typeof orderedRenderPhases)[number];
|
|
373
|
-
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" | "PcbFlexRender" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "
|
|
374
|
+
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" | "PcbFlexRender" | "PcbAutoplaceBreakoutPoints" | "PcbTraceHintRender" | "PcbManualTraceRender" | "PcbPlacementDesignRuleChecks" | "PcbTraceRender" | "PcbRouteNetIslands" | "PcbCopperPourRender" | "PcbViaStitchRender" | "PcbCopperPourCleanup" | "PcbDesignRuleChecks" | "SilkscreenOverlapAdjustment" | "CadModelRender" | "PartsEngineRender" | "PartOrientationAnalysis" | "SupplierFootprintMismatchWarning" | "SimulationSpiceEngineRender", number>;
|
|
374
375
|
type RenderPhaseFn<K extends RenderPhase = RenderPhase> = `doInitial${K}` | `update${K}` | `remove${K}`;
|
|
375
376
|
type RenderPhaseStates = Record<RenderPhase, {
|
|
376
377
|
initialized: boolean;
|
|
@@ -395,7 +396,10 @@ type IRenderable = RenderPhaseFunctions & {
|
|
|
395
396
|
runRenderCycle(): void;
|
|
396
397
|
};
|
|
397
398
|
declare abstract class Renderable implements IRenderable {
|
|
398
|
-
|
|
399
|
+
private _phaseStatesByName?;
|
|
400
|
+
private readonly _phaseStatesByIndex;
|
|
401
|
+
get renderPhaseStates(): RenderPhaseStates;
|
|
402
|
+
set renderPhaseStates(states: RenderPhaseStates);
|
|
399
403
|
shouldBeRemoved: boolean;
|
|
400
404
|
children: IRenderable[];
|
|
401
405
|
/** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
|
|
@@ -595,6 +599,7 @@ declare class IsolatedCircuit {
|
|
|
595
599
|
selectOne(selector: string, opts?: {
|
|
596
600
|
type?: "component" | "port";
|
|
597
601
|
}): PrimitiveComponent | null;
|
|
602
|
+
_hasRenderLifecycleListeners: boolean;
|
|
598
603
|
_eventListeners: Record<RootCircuitEventName, Array<(...args: any[]) => void>>;
|
|
599
604
|
emit(event: RootCircuitEventName, ...args: any[]): void;
|
|
600
605
|
hasEventListener(event: RootCircuitEventName): boolean;
|
|
@@ -6246,7 +6251,6 @@ declare class Board extends Group<typeof boardProps> implements BoardI, Subcircu
|
|
|
6246
6251
|
removePcbComponentRender(): void;
|
|
6247
6252
|
doInitialPcbDesignRuleChecks(): void;
|
|
6248
6253
|
doInitialPcbPlacementDesignRuleChecks(): void;
|
|
6249
|
-
doInitialPcbImplicitCopperPourRender(): void;
|
|
6250
6254
|
_generatedStitchingViaIds: Set<string>;
|
|
6251
6255
|
doInitialPcbCopperPourCleanup(): void;
|
|
6252
6256
|
updatePcbDesignRuleChecks(): void;
|
package/dist/index.js
CHANGED
|
@@ -484,7 +484,6 @@ var orderedRenderPhases = [
|
|
|
484
484
|
"PcbPlacementDesignRuleChecks",
|
|
485
485
|
"PcbTraceRender",
|
|
486
486
|
"PcbRouteNetIslands",
|
|
487
|
-
"PcbImplicitCopperPourRender",
|
|
488
487
|
"PcbCopperPourRender",
|
|
489
488
|
"PcbViaStitchRender",
|
|
490
489
|
"PcbCopperPourCleanup",
|
|
@@ -535,14 +534,6 @@ var asyncPhaseDependencies = {
|
|
|
535
534
|
PcbTraceHintRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
|
|
536
535
|
PcbManualTraceRender: ["PcbFootprintStringRender", "FetchPartFootprint"],
|
|
537
536
|
PcbCopperPourRender: [
|
|
538
|
-
"PcbFootprintStringRender",
|
|
539
|
-
"FetchPartFootprint",
|
|
540
|
-
"PcbPlacementDesignRuleChecks",
|
|
541
|
-
"PcbTraceRender",
|
|
542
|
-
"PcbRouteNetIslands",
|
|
543
|
-
"PcbImplicitCopperPourRender"
|
|
544
|
-
],
|
|
545
|
-
PcbImplicitCopperPourRender: [
|
|
546
537
|
"PcbFootprintStringRender",
|
|
547
538
|
"FetchPartFootprint",
|
|
548
539
|
"PcbPlacementDesignRuleChecks",
|
|
@@ -555,7 +546,6 @@ var asyncPhaseDependencies = {
|
|
|
555
546
|
"PcbPlacementDesignRuleChecks",
|
|
556
547
|
"PcbTraceRender",
|
|
557
548
|
"PcbRouteNetIslands",
|
|
558
|
-
"PcbImplicitCopperPourRender",
|
|
559
549
|
"PcbCopperPourRender"
|
|
560
550
|
],
|
|
561
551
|
PcbPlacementDesignRuleChecks: [
|
|
@@ -568,7 +558,6 @@ var asyncPhaseDependencies = {
|
|
|
568
558
|
"PcbPlacementDesignRuleChecks",
|
|
569
559
|
"PcbTraceRender",
|
|
570
560
|
"PcbRouteNetIslands",
|
|
571
|
-
"PcbImplicitCopperPourRender",
|
|
572
561
|
"PcbCopperPourRender",
|
|
573
562
|
"PcbViaStitchRender"
|
|
574
563
|
],
|
|
@@ -583,7 +572,6 @@ var asyncPhaseDependencies = {
|
|
|
583
572
|
"FetchPartFootprint",
|
|
584
573
|
"PcbPlacementDesignRuleChecks",
|
|
585
574
|
"PcbTraceRender",
|
|
586
|
-
"PcbImplicitCopperPourRender",
|
|
587
575
|
"PcbCopperPourRender",
|
|
588
576
|
"PcbViaStitchRender",
|
|
589
577
|
"PcbCopperPourCleanup"
|
|
@@ -622,7 +610,21 @@ var asyncPhaseDependencies = {
|
|
|
622
610
|
var globalRenderCounter = 0;
|
|
623
611
|
var globalAsyncEffectCounter = 0;
|
|
624
612
|
var Renderable = class _Renderable {
|
|
625
|
-
|
|
613
|
+
_phaseStatesByName;
|
|
614
|
+
_phaseStatesByIndex;
|
|
615
|
+
// Build the named map once, sharing the state objects used by the render loop.
|
|
616
|
+
// Once exposed, use the map so callers can also replace individual entries.
|
|
617
|
+
get renderPhaseStates() {
|
|
618
|
+
return this._phaseStatesByName ??= Object.fromEntries(
|
|
619
|
+
orderedRenderPhases.map((phase, index) => [
|
|
620
|
+
phase,
|
|
621
|
+
this._phaseStatesByIndex[index]
|
|
622
|
+
])
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
set renderPhaseStates(states) {
|
|
626
|
+
this._phaseStatesByName = states;
|
|
627
|
+
}
|
|
626
628
|
shouldBeRemoved = false;
|
|
627
629
|
children;
|
|
628
630
|
/** PCB-only SMTPads, PlatedHoles, Holes, Silkscreen elements etc. */
|
|
@@ -637,19 +639,19 @@ var Renderable = class _Renderable {
|
|
|
637
639
|
constructor(props) {
|
|
638
640
|
this._renderId = `${globalRenderCounter++}`;
|
|
639
641
|
this.children = [];
|
|
640
|
-
this.
|
|
641
|
-
|
|
642
|
-
|
|
642
|
+
this._phaseStatesByIndex = Array.from(
|
|
643
|
+
{ length: orderedRenderPhases.length },
|
|
644
|
+
() => ({
|
|
643
645
|
initialized: false,
|
|
644
646
|
dirty: false
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
+
})
|
|
648
|
+
);
|
|
647
649
|
}
|
|
648
650
|
_markDirty(phase) {
|
|
649
|
-
this.renderPhaseStates[phase].dirty = true;
|
|
650
651
|
const phaseIndex = renderPhaseIndexMap.get(phase);
|
|
651
|
-
for (let i = phaseIndex
|
|
652
|
-
this.
|
|
652
|
+
for (let i = phaseIndex; i < orderedRenderPhases.length; i++) {
|
|
653
|
+
const state = this._phaseStatesByName?.[orderedRenderPhases[i]] ?? this._phaseStatesByIndex[i];
|
|
654
|
+
state.dirty = true;
|
|
653
655
|
}
|
|
654
656
|
if (this.parent?._markDirty) {
|
|
655
657
|
this.parent._markDirty(phase);
|
|
@@ -705,8 +707,9 @@ ${error.stack}`
|
|
|
705
707
|
});
|
|
706
708
|
}
|
|
707
709
|
_emitRenderLifecycleEvent(phase, startOrEnd) {
|
|
708
|
-
const granular_event_type = `renderable:renderLifecycle:${phase}:${startOrEnd}`;
|
|
709
710
|
const root = this._getRootCircuit();
|
|
711
|
+
if (root?._hasRenderLifecycleListeners === false && !debug.enabled) return;
|
|
712
|
+
const granular_event_type = `renderable:renderLifecycle:${phase}:${startOrEnd}`;
|
|
710
713
|
const hasListeners = root && (!root.hasEventListener || root.hasEventListener(granular_event_type) || root.hasEventListener("renderable:renderLifecycle:anyEvent"));
|
|
711
714
|
if (!debug.enabled && !hasListeners) return;
|
|
712
715
|
const componentDisplayName = this.getString();
|
|
@@ -786,9 +789,9 @@ ${error.stack}`
|
|
|
786
789
|
*/
|
|
787
790
|
runRenderPhase(phase) {
|
|
788
791
|
this._currentRenderPhase = phase;
|
|
789
|
-
const
|
|
790
|
-
const
|
|
791
|
-
const isDirty = phaseState
|
|
792
|
+
const phaseIndex = renderPhaseIndexMap.get(phase);
|
|
793
|
+
const phaseState = this._phaseStatesByName?.[phase] ?? this._phaseStatesByIndex[phaseIndex];
|
|
794
|
+
const { initialized: isInitialized, dirty: isDirty } = phaseState;
|
|
792
795
|
if (!isInitialized && this.shouldBeRemoved) return;
|
|
793
796
|
if (this.shouldBeRemoved && isInitialized) {
|
|
794
797
|
this._emitRenderLifecycleEvent(phase, "start");
|
|
@@ -798,10 +801,12 @@ ${error.stack}`
|
|
|
798
801
|
this._emitRenderLifecycleEvent(phase, "end");
|
|
799
802
|
return;
|
|
800
803
|
}
|
|
801
|
-
const prevPhaseIndex =
|
|
802
|
-
if (prevPhaseIndex >= 0) {
|
|
804
|
+
const prevPhaseIndex = phaseIndex - 1;
|
|
805
|
+
if (this._asyncEffects.length > 0 && prevPhaseIndex >= 0) {
|
|
803
806
|
const prevPhase = orderedRenderPhases[prevPhaseIndex];
|
|
804
|
-
const hasIncompleteEffects = this._asyncEffects.
|
|
807
|
+
const hasIncompleteEffects = this._asyncEffects.some(
|
|
808
|
+
(e) => e.phase === prevPhase && !e.complete
|
|
809
|
+
);
|
|
805
810
|
if (hasIncompleteEffects) return;
|
|
806
811
|
}
|
|
807
812
|
const deps = asyncPhaseDependencies[phase] || [];
|
|
@@ -829,7 +834,7 @@ ${error.stack}`
|
|
|
829
834
|
}
|
|
830
835
|
runRenderPhaseForChildren(phase) {
|
|
831
836
|
for (const child of this.children) {
|
|
832
|
-
if ("_isIsolatedSubcircuit" in this && this._isIsolatedSubcircuit && "doInitialRenderIsolatedSubcircuits" in this
|
|
837
|
+
if (phase === "RenderIsolatedSubcircuits" && "_isIsolatedSubcircuit" in this && this._isIsolatedSubcircuit && "doInitialRenderIsolatedSubcircuits" in this) {
|
|
833
838
|
continue;
|
|
834
839
|
}
|
|
835
840
|
child.runRenderPhaseForChildren(phase);
|
|
@@ -63783,7 +63788,7 @@ function Group_getRoutingPhasePlans(group) {
|
|
|
63783
63788
|
var package_default = {
|
|
63784
63789
|
name: "@tscircuit/core",
|
|
63785
63790
|
type: "module",
|
|
63786
|
-
version: "0.0.
|
|
63791
|
+
version: "0.0.1967",
|
|
63787
63792
|
types: "dist/index.d.ts",
|
|
63788
63793
|
main: "dist/index.js",
|
|
63789
63794
|
module: "dist/index.js",
|
|
@@ -68649,6 +68654,7 @@ var IsolatedCircuit = class {
|
|
|
68649
68654
|
this._guessRootComponent();
|
|
68650
68655
|
return this.firstChild?.selectOne(selector, opts) ?? null;
|
|
68651
68656
|
}
|
|
68657
|
+
_hasRenderLifecycleListeners = false;
|
|
68652
68658
|
_eventListeners = {};
|
|
68653
68659
|
emit(event, ...args) {
|
|
68654
68660
|
if (event === "asyncEffect:start") {
|
|
@@ -68669,12 +68675,22 @@ var IsolatedCircuit = class {
|
|
|
68669
68675
|
this._eventListeners[event] = [];
|
|
68670
68676
|
}
|
|
68671
68677
|
this._eventListeners[event].push(listener);
|
|
68678
|
+
if (event.startsWith("renderable:renderLifecycle:")) {
|
|
68679
|
+
this._hasRenderLifecycleListeners = true;
|
|
68680
|
+
}
|
|
68672
68681
|
}
|
|
68673
68682
|
removeListener(event, listener) {
|
|
68674
68683
|
if (!this._eventListeners[event]) return;
|
|
68675
68684
|
this._eventListeners[event] = this._eventListeners[event].filter(
|
|
68676
68685
|
(l) => l !== listener
|
|
68677
68686
|
);
|
|
68687
|
+
if (event.startsWith("renderable:renderLifecycle:")) {
|
|
68688
|
+
this._hasRenderLifecycleListeners = Object.entries(
|
|
68689
|
+
this._eventListeners
|
|
68690
|
+
).some(
|
|
68691
|
+
([eventName, listeners]) => eventName.startsWith("renderable:renderLifecycle:") && listeners.length > 0
|
|
68692
|
+
);
|
|
68693
|
+
}
|
|
68678
68694
|
}
|
|
68679
68695
|
enableDebug(debug13) {
|
|
68680
68696
|
if (typeof debug13 === "string") {
|
|
@@ -68875,382 +68891,6 @@ function Subcircuit_getSubcircuitPropHash(subcircuit) {
|
|
|
68875
68891
|
return computeHash(hashableData);
|
|
68876
68892
|
}
|
|
68877
68893
|
|
|
68878
|
-
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
68879
|
-
import { copperPourProps } from "@tscircuit/props";
|
|
68880
|
-
|
|
68881
|
-
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbCopperPourRender.ts
|
|
68882
|
-
import {
|
|
68883
|
-
CopperPourPipelineSolver as CopperPourPipelineSolver2,
|
|
68884
|
-
convertCircuitJsonToInputProblem,
|
|
68885
|
-
initializeManifoldGeometry
|
|
68886
|
-
} from "@tscircuit/copper-pour-solver";
|
|
68887
|
-
|
|
68888
|
-
// lib/components/primitive-components/CopperPour/utils/mark-trace-segments-inside-copper-pour.ts
|
|
68889
|
-
var EPSILON24 = 1e-9;
|
|
68890
|
-
var isWireRoutePoint = (routePoint) => routePoint.route_type === "wire";
|
|
68891
|
-
var isPointOnSegment2 = (p, a, b) => {
|
|
68892
|
-
const cross4 = (p.y - a.y) * (b.x - a.x) - (p.x - a.x) * (b.y - a.y);
|
|
68893
|
-
if (Math.abs(cross4) > EPSILON24) return false;
|
|
68894
|
-
const dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
|
|
68895
|
-
if (dot < -EPSILON24) return false;
|
|
68896
|
-
const squaredLength = (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
|
|
68897
|
-
if (dot - squaredLength > EPSILON24) return false;
|
|
68898
|
-
return true;
|
|
68899
|
-
};
|
|
68900
|
-
var isPointInRing2 = (point6, ring) => {
|
|
68901
|
-
if (ring.length < 3) return false;
|
|
68902
|
-
let inside2 = false;
|
|
68903
|
-
let previous = ring[ring.length - 1];
|
|
68904
|
-
for (const current of ring) {
|
|
68905
|
-
if (isPointOnSegment2(point6, previous, current)) return true;
|
|
68906
|
-
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;
|
|
68907
|
-
if (intersects) inside2 = !inside2;
|
|
68908
|
-
previous = current;
|
|
68909
|
-
}
|
|
68910
|
-
return inside2;
|
|
68911
|
-
};
|
|
68912
|
-
var isPointInRectPour = (p, pour) => {
|
|
68913
|
-
const { center, width, height } = pour;
|
|
68914
|
-
const rotationRad = (pour.rotation ?? 0) * Math.PI / 180;
|
|
68915
|
-
const cosR = Math.cos(-rotationRad);
|
|
68916
|
-
const sinR = Math.sin(-rotationRad);
|
|
68917
|
-
const dx = p.x - center.x;
|
|
68918
|
-
const dy = p.y - center.y;
|
|
68919
|
-
const localX = dx * cosR - dy * sinR;
|
|
68920
|
-
const localY = dx * sinR + dy * cosR;
|
|
68921
|
-
return Math.abs(localX) <= width / 2 + EPSILON24 && Math.abs(localY) <= height / 2 + EPSILON24;
|
|
68922
|
-
};
|
|
68923
|
-
var isPointInBrepPour = (p, pour) => {
|
|
68924
|
-
const outerRing = pour.brep_shape.outer_ring.vertices.map((v) => ({
|
|
68925
|
-
x: v.x,
|
|
68926
|
-
y: v.y
|
|
68927
|
-
}));
|
|
68928
|
-
if (!isPointInRing2(p, outerRing)) return false;
|
|
68929
|
-
for (const innerRing of pour.brep_shape.inner_rings) {
|
|
68930
|
-
const points = innerRing.vertices.map((v) => ({ x: v.x, y: v.y }));
|
|
68931
|
-
if (isPointInRing2(p, points)) return false;
|
|
68932
|
-
}
|
|
68933
|
-
return true;
|
|
68934
|
-
};
|
|
68935
|
-
var isPointInCopperPour = (point6, pour) => {
|
|
68936
|
-
if (pour.shape === "rect") {
|
|
68937
|
-
return isPointInRectPour(point6, pour);
|
|
68938
|
-
}
|
|
68939
|
-
if (pour.shape === "brep") {
|
|
68940
|
-
return isPointInBrepPour(point6, pour);
|
|
68941
|
-
}
|
|
68942
|
-
return false;
|
|
68943
|
-
};
|
|
68944
|
-
var isTraceConnectedToSourceNet = (trace, sourceNetId, sourceTraceById) => {
|
|
68945
|
-
if (trace.source_trace_id === sourceNetId) return true;
|
|
68946
|
-
if (!trace.source_trace_id) return false;
|
|
68947
|
-
const sourceTrace = sourceTraceById.get(trace.source_trace_id);
|
|
68948
|
-
if (!sourceTrace) return false;
|
|
68949
|
-
return sourceTrace.connected_source_net_ids.includes(sourceNetId);
|
|
68950
|
-
};
|
|
68951
|
-
var isSegmentFullyInsideCopperPour = (start, end, pour) => {
|
|
68952
|
-
const dx = end.x - start.x;
|
|
68953
|
-
const dy = end.y - start.y;
|
|
68954
|
-
const length8 = Math.hypot(dx, dy);
|
|
68955
|
-
if (length8 <= EPSILON24) return false;
|
|
68956
|
-
const samples = [0, 0.25, 0.5, 0.75, 1];
|
|
68957
|
-
return samples.every(
|
|
68958
|
-
(t) => isPointInCopperPour(
|
|
68959
|
-
{
|
|
68960
|
-
x: start.x + dx * t,
|
|
68961
|
-
y: start.y + dy * t
|
|
68962
|
-
},
|
|
68963
|
-
pour
|
|
68964
|
-
)
|
|
68965
|
-
);
|
|
68966
|
-
};
|
|
68967
|
-
var markTraceSegmentsInsideCopperPour = ({
|
|
68968
|
-
db,
|
|
68969
|
-
copperPour
|
|
68970
|
-
}) => {
|
|
68971
|
-
if (!copperPour.source_net_id) return;
|
|
68972
|
-
const sourceTraceById = new Map(
|
|
68973
|
-
db.source_trace.list().map((sourceTrace) => [sourceTrace.source_trace_id, sourceTrace])
|
|
68974
|
-
);
|
|
68975
|
-
for (const trace of db.pcb_trace.list()) {
|
|
68976
|
-
if (!isTraceConnectedToSourceNet(
|
|
68977
|
-
trace,
|
|
68978
|
-
copperPour.source_net_id,
|
|
68979
|
-
sourceTraceById
|
|
68980
|
-
)) {
|
|
68981
|
-
continue;
|
|
68982
|
-
}
|
|
68983
|
-
let routeChanged = false;
|
|
68984
|
-
const nextRoute = trace.route.map((routePoint) => ({ ...routePoint }));
|
|
68985
|
-
for (let i = 0; i < nextRoute.length - 1; i++) {
|
|
68986
|
-
const fromRoutePoint = nextRoute[i];
|
|
68987
|
-
const toRoutePoint = nextRoute[i + 1];
|
|
68988
|
-
if (!fromRoutePoint || !toRoutePoint) continue;
|
|
68989
|
-
if (!isWireRoutePoint(fromRoutePoint) || !isWireRoutePoint(toRoutePoint))
|
|
68990
|
-
continue;
|
|
68991
|
-
if (fromRoutePoint.layer !== copperPour.layer || toRoutePoint.layer !== copperPour.layer)
|
|
68992
|
-
continue;
|
|
68993
|
-
if (isSegmentFullyInsideCopperPour(
|
|
68994
|
-
{ x: fromRoutePoint.x, y: fromRoutePoint.y },
|
|
68995
|
-
{ x: toRoutePoint.x, y: toRoutePoint.y },
|
|
68996
|
-
copperPour
|
|
68997
|
-
)) {
|
|
68998
|
-
fromRoutePoint.is_inside_copper_pour = true;
|
|
68999
|
-
fromRoutePoint.copper_pour_id = copperPour.pcb_copper_pour_id;
|
|
69000
|
-
toRoutePoint.is_inside_copper_pour = true;
|
|
69001
|
-
toRoutePoint.copper_pour_id = copperPour.pcb_copper_pour_id;
|
|
69002
|
-
routeChanged = true;
|
|
69003
|
-
}
|
|
69004
|
-
}
|
|
69005
|
-
if (routeChanged) {
|
|
69006
|
-
db.pcb_trace.update(trace.pcb_trace_id, { route: nextRoute });
|
|
69007
|
-
}
|
|
69008
|
-
}
|
|
69009
|
-
};
|
|
69010
|
-
|
|
69011
|
-
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbCopperPourRender.ts
|
|
69012
|
-
var pendingCopperPourRenders = /* @__PURE__ */ new WeakMap();
|
|
69013
|
-
var DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM = 0.3;
|
|
69014
|
-
var renderAllCopperPoursForSubcircuit = async (subcircuit) => {
|
|
69015
|
-
if (!subcircuit.root) return;
|
|
69016
|
-
const { db } = subcircuit.root;
|
|
69017
|
-
const copperPours = subcircuit.selectAll("copperpour").filter((copperPour) => copperPour.getSubcircuit() === subcircuit);
|
|
69018
|
-
const resolvedCopperPours = [];
|
|
69019
|
-
for (const copperPour of copperPours) {
|
|
69020
|
-
const { _parsedProps: props } = copperPour;
|
|
69021
|
-
const net = subcircuit.selectOne(props.connectsTo);
|
|
69022
|
-
const sourceNetId = net?.source_net_id;
|
|
69023
|
-
if (!sourceNetId) {
|
|
69024
|
-
copperPour.renderError(
|
|
69025
|
-
`Net "${props.connectsTo}" not found for copper pour`
|
|
69026
|
-
);
|
|
69027
|
-
continue;
|
|
69028
|
-
}
|
|
69029
|
-
resolvedCopperPours.push({ copperPour, sourceNetId });
|
|
69030
|
-
}
|
|
69031
|
-
if (resolvedCopperPours.length === 0) return;
|
|
69032
|
-
const circuitJson = db.toArray();
|
|
69033
|
-
const boardComponent = subcircuit._getBoard();
|
|
69034
|
-
const pcbBoard = boardComponent?.pcb_board_id ? db.pcb_board.get(boardComponent.pcb_board_id) : void 0;
|
|
69035
|
-
let resolvedPcbBoardOutline = pcbBoard?.outline?.length ? pcbBoard.outline : void 0;
|
|
69036
|
-
if (!resolvedPcbBoardOutline && pcbBoard?.width !== void 0 && pcbBoard.height !== void 0) {
|
|
69037
|
-
const { center, width, height } = pcbBoard;
|
|
69038
|
-
resolvedPcbBoardOutline = [
|
|
69039
|
-
{ x: center.x - width / 2, y: center.y - height / 2 },
|
|
69040
|
-
{ x: center.x + width / 2, y: center.y - height / 2 },
|
|
69041
|
-
{ x: center.x + width / 2, y: center.y + height / 2 },
|
|
69042
|
-
{ x: center.x - width / 2, y: center.y + height / 2 }
|
|
69043
|
-
];
|
|
69044
|
-
}
|
|
69045
|
-
const inputProblem = convertCircuitJsonToInputProblem(
|
|
69046
|
-
circuitJson,
|
|
69047
|
-
resolvedCopperPours.map(({ copperPour, sourceNetId }) => {
|
|
69048
|
-
const { _parsedProps: props } = copperPour;
|
|
69049
|
-
const clearance = props.clearance ?? 0.2;
|
|
69050
|
-
return {
|
|
69051
|
-
layer: props.layer,
|
|
69052
|
-
subcircuit_id: subcircuit.subcircuit_id ?? void 0,
|
|
69053
|
-
source_net_id: sourceNetId,
|
|
69054
|
-
pad_margin: props.padMargin ?? clearance,
|
|
69055
|
-
trace_margin: props.traceMargin ?? clearance,
|
|
69056
|
-
pour_margin: clearance,
|
|
69057
|
-
board_edge_margin: props.boardEdgeMargin ?? clearance,
|
|
69058
|
-
board_edge_outline: copperPour._isImplicitCopperPour ? resolvedPcbBoardOutline : void 0,
|
|
69059
|
-
cutout_margin: props.cutoutMargin ?? clearance,
|
|
69060
|
-
...props.useThermalReliefs ? {
|
|
69061
|
-
use_thermal_reliefs: true,
|
|
69062
|
-
thermal_relief_spoke_width: DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM
|
|
69063
|
-
} : {},
|
|
69064
|
-
outline: props.outline ?? resolvedPcbBoardOutline
|
|
69065
|
-
};
|
|
69066
|
-
})
|
|
69067
|
-
);
|
|
69068
|
-
await initializeManifoldGeometry();
|
|
69069
|
-
const solver = new CopperPourPipelineSolver2(inputProblem);
|
|
69070
|
-
subcircuit.root.emit("solver:started", {
|
|
69071
|
-
type: "solver:started",
|
|
69072
|
-
solverName: "CopperPourPipelineSolver",
|
|
69073
|
-
solverParams: inputProblem,
|
|
69074
|
-
solverConstructorArgs: [inputProblem],
|
|
69075
|
-
componentName: subcircuit.getString()
|
|
69076
|
-
});
|
|
69077
|
-
const { brep_shapes_by_region } = solver.getOutput();
|
|
69078
|
-
for (const [
|
|
69079
|
-
regionIndex,
|
|
69080
|
-
{ copperPour, sourceNetId }
|
|
69081
|
-
] of resolvedCopperPours.entries()) {
|
|
69082
|
-
const { _parsedProps: props } = copperPour;
|
|
69083
|
-
const coveredWithSolderMask = props.coveredWithSolderMask ?? false;
|
|
69084
|
-
for (const brepShape of brep_shapes_by_region[regionIndex] ?? []) {
|
|
69085
|
-
const insertedPour = db.pcb_copper_pour.insert({
|
|
69086
|
-
shape: "brep",
|
|
69087
|
-
layer: props.layer,
|
|
69088
|
-
brep_shape: brepShape,
|
|
69089
|
-
source_net_id: sourceNetId,
|
|
69090
|
-
subcircuit_id: subcircuit.subcircuit_id ?? void 0,
|
|
69091
|
-
covered_with_solder_mask: coveredWithSolderMask
|
|
69092
|
-
});
|
|
69093
|
-
markTraceSegmentsInsideCopperPour({
|
|
69094
|
-
db,
|
|
69095
|
-
copperPour: insertedPour
|
|
69096
|
-
});
|
|
69097
|
-
}
|
|
69098
|
-
}
|
|
69099
|
-
};
|
|
69100
|
-
function CopperPour_doInitialPcbCopperPourRender(copperPour) {
|
|
69101
|
-
if (copperPour.root?.pcbDisabled) return;
|
|
69102
|
-
copperPour._queueAsyncEffect("PcbCopperPourRender", async () => {
|
|
69103
|
-
const subcircuit = copperPour.getSubcircuit();
|
|
69104
|
-
const pendingRender = pendingCopperPourRenders.get(subcircuit);
|
|
69105
|
-
if (pendingRender) {
|
|
69106
|
-
await pendingRender;
|
|
69107
|
-
return;
|
|
69108
|
-
}
|
|
69109
|
-
const renderPromise = renderAllCopperPoursForSubcircuit(subcircuit);
|
|
69110
|
-
pendingCopperPourRenders.set(subcircuit, renderPromise);
|
|
69111
|
-
try {
|
|
69112
|
-
await renderPromise;
|
|
69113
|
-
} finally {
|
|
69114
|
-
pendingCopperPourRenders.delete(subcircuit);
|
|
69115
|
-
}
|
|
69116
|
-
});
|
|
69117
|
-
}
|
|
69118
|
-
|
|
69119
|
-
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbViaStitchRender.ts
|
|
69120
|
-
import { pcb_via as pcb_via3 } from "circuit-json";
|
|
69121
|
-
var renderViaStitchingForCopperPours = (copperPour) => {
|
|
69122
|
-
const subcircuit = copperPour.getSubcircuit();
|
|
69123
|
-
if (!subcircuit.root) return;
|
|
69124
|
-
const copperPours = subcircuit.selectAll("copperpour").filter(
|
|
69125
|
-
(candidateCopperPour) => candidateCopperPour.getSubcircuit() === subcircuit
|
|
69126
|
-
);
|
|
69127
|
-
if (copperPours[0] !== copperPour) return;
|
|
69128
|
-
const sourceNetIds = copperPours.flatMap((candidateCopperPour) => {
|
|
69129
|
-
const net = subcircuit.selectOne(
|
|
69130
|
-
candidateCopperPour._parsedProps.connectsTo
|
|
69131
|
-
);
|
|
69132
|
-
return net?.source_net_id ? [net.source_net_id] : [];
|
|
69133
|
-
});
|
|
69134
|
-
if (sourceNetIds.length === 0) return;
|
|
69135
|
-
const { db } = subcircuit.root;
|
|
69136
|
-
const pcbStyle = copperPour.getInheritedMergedProperty("pcbStyle");
|
|
69137
|
-
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle);
|
|
69138
|
-
const boardComponent = copperPour._getBoard();
|
|
69139
|
-
const pcbBoard = boardComponent?.pcb_board_id ? db.pcb_board.get(boardComponent.pcb_board_id) : void 0;
|
|
69140
|
-
const solverInput = {
|
|
69141
|
-
circuitJson: db.toArray(),
|
|
69142
|
-
options: {
|
|
69143
|
-
sourceNetIds: [...new Set(sourceNetIds)],
|
|
69144
|
-
viaHoleDiameter: pcbBoard?.min_via_hole_diameter ?? holeDiameter,
|
|
69145
|
-
viaOuterDiameter: pcbBoard?.min_via_pad_diameter ?? padDiameter,
|
|
69146
|
-
viaStitchPitch: boardComponent?._parsedProps.viaStitchPitch
|
|
69147
|
-
}
|
|
69148
|
-
};
|
|
69149
|
-
const solver = new ViaStitchSolver(solverInput);
|
|
69150
|
-
subcircuit.root.emit("solver:started", {
|
|
69151
|
-
type: "solver:started",
|
|
69152
|
-
solverName: "ViaStitchSolver",
|
|
69153
|
-
solverParams: solverInput,
|
|
69154
|
-
solverConstructorArgs: [solverInput],
|
|
69155
|
-
componentName: subcircuit.getString()
|
|
69156
|
-
});
|
|
69157
|
-
solver.solve();
|
|
69158
|
-
if (solver.failed) {
|
|
69159
|
-
throw new Error(solver.error ?? "Via stitching solver failed");
|
|
69160
|
-
}
|
|
69161
|
-
for (const pcbVia of solver.getOutput().pcbVias) {
|
|
69162
|
-
const { pcb_via_id: _solverViaId, ...pcbViaInput } = pcb_via3.parse(pcbVia);
|
|
69163
|
-
const insertedVia = db.pcb_via.insert({
|
|
69164
|
-
...pcbViaInput,
|
|
69165
|
-
tented_on_top: void 0,
|
|
69166
|
-
tented_on_bottom: void 0
|
|
69167
|
-
});
|
|
69168
|
-
boardComponent?._generatedStitchingViaIds?.add(insertedVia.pcb_via_id);
|
|
69169
|
-
}
|
|
69170
|
-
};
|
|
69171
|
-
function CopperPour_doInitialPcbViaStitchRender(copperPour) {
|
|
69172
|
-
if (copperPour.root?.pcbDisabled || !copperPour.root?._featurePcbViaStitching)
|
|
69173
|
-
return;
|
|
69174
|
-
if (!copperPour._getBoard()?._parsedProps.enableViaStitching) return;
|
|
69175
|
-
copperPour._queueAsyncEffect("PcbViaStitchRender", async () => {
|
|
69176
|
-
renderViaStitchingForCopperPours(copperPour);
|
|
69177
|
-
});
|
|
69178
|
-
}
|
|
69179
|
-
|
|
69180
|
-
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
69181
|
-
var CopperPour = class extends PrimitiveComponent2 {
|
|
69182
|
-
isPcbPrimitive = true;
|
|
69183
|
-
_isImplicitCopperPour = false;
|
|
69184
|
-
get config() {
|
|
69185
|
-
return {
|
|
69186
|
-
componentName: "CopperPour",
|
|
69187
|
-
zodProps: copperPourProps
|
|
69188
|
-
};
|
|
69189
|
-
}
|
|
69190
|
-
getPcbSize() {
|
|
69191
|
-
return { width: 0, height: 0 };
|
|
69192
|
-
}
|
|
69193
|
-
doInitialCreateNetsFromProps() {
|
|
69194
|
-
const { _parsedProps: props } = this;
|
|
69195
|
-
createNetsFromProps(this, [props.connectsTo]);
|
|
69196
|
-
}
|
|
69197
|
-
doInitialPcbCopperPourRender() {
|
|
69198
|
-
CopperPour_doInitialPcbCopperPourRender(this);
|
|
69199
|
-
}
|
|
69200
|
-
doInitialPcbViaStitchRender() {
|
|
69201
|
-
CopperPour_doInitialPcbViaStitchRender(this);
|
|
69202
|
-
}
|
|
69203
|
-
};
|
|
69204
|
-
|
|
69205
|
-
// lib/components/normal-components/Board_doInitialPcbImplicitCopperPourRender.ts
|
|
69206
|
-
var Board_doInitialPcbImplicitCopperPourRender = (board) => {
|
|
69207
|
-
const { root } = board;
|
|
69208
|
-
if (!root || root.pcbDisabled) return;
|
|
69209
|
-
if (!board._parsedProps.automaticPoursEnabled) return;
|
|
69210
|
-
if (root.pcbRoutingDisabled || board.getInheritedProperty("routingDisabled"))
|
|
69211
|
-
return;
|
|
69212
|
-
const { db } = root;
|
|
69213
|
-
const circuitJson = db.subtree({ subcircuit_id: board.subcircuit_id }).toArray();
|
|
69214
|
-
const hasPowerNet = circuitJson.some(
|
|
69215
|
-
(element) => element.type === "source_net" && (element.is_power || element.is_ground || element.is_positive_voltage_source)
|
|
69216
|
-
);
|
|
69217
|
-
if (!hasPowerNet) return;
|
|
69218
|
-
const inputProblem = {
|
|
69219
|
-
circuitJson,
|
|
69220
|
-
layers: [...board.allLayers]
|
|
69221
|
-
};
|
|
69222
|
-
const solver = new ImplicitCopperPourPipelineSolver(inputProblem);
|
|
69223
|
-
const solverConstructorArgs = solver.getConstructorParams();
|
|
69224
|
-
root.emit("solver:started", {
|
|
69225
|
-
type: "solver:started",
|
|
69226
|
-
solverName: "ImplicitCopperPourPipelineSolver",
|
|
69227
|
-
solverParams: solverConstructorArgs[0],
|
|
69228
|
-
solverConstructorArgs,
|
|
69229
|
-
componentName: board.getString()
|
|
69230
|
-
});
|
|
69231
|
-
solver.solve();
|
|
69232
|
-
const boardNets = board.selectAll("net");
|
|
69233
|
-
for (const implicitRegion of solver.getOutput()) {
|
|
69234
|
-
if (implicitRegion.shape !== "polygon") continue;
|
|
69235
|
-
const owningNet = boardNets.find(
|
|
69236
|
-
(net) => net.source_net_id === implicitRegion.source_net_id
|
|
69237
|
-
);
|
|
69238
|
-
if (!owningNet) {
|
|
69239
|
-
throw new Error(
|
|
69240
|
-
`Unable to find the power net for implicit copper region ${implicitRegion.pcb_copper_pour_id}`
|
|
69241
|
-
);
|
|
69242
|
-
}
|
|
69243
|
-
const copperPour = new CopperPour({
|
|
69244
|
-
layer: implicitRegion.layer,
|
|
69245
|
-
connectsTo: owningNet.getPortSelector(),
|
|
69246
|
-
outline: implicitRegion.points,
|
|
69247
|
-
coveredWithSolderMask: implicitRegion.covered_with_solder_mask
|
|
69248
|
-
});
|
|
69249
|
-
copperPour._isImplicitCopperPour = true;
|
|
69250
|
-
owningNet.getSubcircuit().add(copperPour);
|
|
69251
|
-
}
|
|
69252
|
-
};
|
|
69253
|
-
|
|
69254
68894
|
// lib/utils/copper-pour-connectivity/find-floating-copper.ts
|
|
69255
68895
|
import {
|
|
69256
68896
|
getFullConnectivityMapFromCircuitJson as getFullConnectivityMapFromCircuitJson5
|
|
@@ -70084,9 +69724,6 @@ var Board = class extends Group5 {
|
|
|
70084
69724
|
doInitialPcbPlacementDesignRuleChecks() {
|
|
70085
69725
|
Board_doInitialPcbPlacementDesignRuleChecks(this);
|
|
70086
69726
|
}
|
|
70087
|
-
doInitialPcbImplicitCopperPourRender() {
|
|
70088
|
-
Board_doInitialPcbImplicitCopperPourRender(this);
|
|
70089
|
-
}
|
|
70090
69727
|
_generatedStitchingViaIds = /* @__PURE__ */ new Set();
|
|
70091
69728
|
doInitialPcbCopperPourCleanup() {
|
|
70092
69729
|
Board_doInitialPcbCopperPourCleanup(this);
|
|
@@ -75725,6 +75362,333 @@ var Fiducial = class extends PrimitiveComponent2 {
|
|
|
75725
75362
|
}
|
|
75726
75363
|
};
|
|
75727
75364
|
|
|
75365
|
+
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
75366
|
+
import { copperPourProps } from "@tscircuit/props";
|
|
75367
|
+
|
|
75368
|
+
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbCopperPourRender.ts
|
|
75369
|
+
import {
|
|
75370
|
+
CopperPourPipelineSolver as CopperPourPipelineSolver2,
|
|
75371
|
+
convertCircuitJsonToInputProblem,
|
|
75372
|
+
initializeManifoldGeometry
|
|
75373
|
+
} from "@tscircuit/copper-pour-solver";
|
|
75374
|
+
|
|
75375
|
+
// lib/components/primitive-components/CopperPour/utils/mark-trace-segments-inside-copper-pour.ts
|
|
75376
|
+
var EPSILON24 = 1e-9;
|
|
75377
|
+
var isWireRoutePoint = (routePoint) => routePoint.route_type === "wire";
|
|
75378
|
+
var isPointOnSegment2 = (p, a, b) => {
|
|
75379
|
+
const cross4 = (p.y - a.y) * (b.x - a.x) - (p.x - a.x) * (b.y - a.y);
|
|
75380
|
+
if (Math.abs(cross4) > EPSILON24) return false;
|
|
75381
|
+
const dot = (p.x - a.x) * (b.x - a.x) + (p.y - a.y) * (b.y - a.y);
|
|
75382
|
+
if (dot < -EPSILON24) return false;
|
|
75383
|
+
const squaredLength = (b.x - a.x) ** 2 + (b.y - a.y) ** 2;
|
|
75384
|
+
if (dot - squaredLength > EPSILON24) return false;
|
|
75385
|
+
return true;
|
|
75386
|
+
};
|
|
75387
|
+
var isPointInRing2 = (point6, ring) => {
|
|
75388
|
+
if (ring.length < 3) return false;
|
|
75389
|
+
let inside2 = false;
|
|
75390
|
+
let previous = ring[ring.length - 1];
|
|
75391
|
+
for (const current of ring) {
|
|
75392
|
+
if (isPointOnSegment2(point6, previous, current)) return true;
|
|
75393
|
+
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;
|
|
75394
|
+
if (intersects) inside2 = !inside2;
|
|
75395
|
+
previous = current;
|
|
75396
|
+
}
|
|
75397
|
+
return inside2;
|
|
75398
|
+
};
|
|
75399
|
+
var isPointInRectPour = (p, pour) => {
|
|
75400
|
+
const { center, width, height } = pour;
|
|
75401
|
+
const rotationRad = (pour.rotation ?? 0) * Math.PI / 180;
|
|
75402
|
+
const cosR = Math.cos(-rotationRad);
|
|
75403
|
+
const sinR = Math.sin(-rotationRad);
|
|
75404
|
+
const dx = p.x - center.x;
|
|
75405
|
+
const dy = p.y - center.y;
|
|
75406
|
+
const localX = dx * cosR - dy * sinR;
|
|
75407
|
+
const localY = dx * sinR + dy * cosR;
|
|
75408
|
+
return Math.abs(localX) <= width / 2 + EPSILON24 && Math.abs(localY) <= height / 2 + EPSILON24;
|
|
75409
|
+
};
|
|
75410
|
+
var isPointInBrepPour = (p, pour) => {
|
|
75411
|
+
const outerRing = pour.brep_shape.outer_ring.vertices.map((v) => ({
|
|
75412
|
+
x: v.x,
|
|
75413
|
+
y: v.y
|
|
75414
|
+
}));
|
|
75415
|
+
if (!isPointInRing2(p, outerRing)) return false;
|
|
75416
|
+
for (const innerRing of pour.brep_shape.inner_rings) {
|
|
75417
|
+
const points = innerRing.vertices.map((v) => ({ x: v.x, y: v.y }));
|
|
75418
|
+
if (isPointInRing2(p, points)) return false;
|
|
75419
|
+
}
|
|
75420
|
+
return true;
|
|
75421
|
+
};
|
|
75422
|
+
var isPointInCopperPour = (point6, pour) => {
|
|
75423
|
+
if (pour.shape === "rect") {
|
|
75424
|
+
return isPointInRectPour(point6, pour);
|
|
75425
|
+
}
|
|
75426
|
+
if (pour.shape === "brep") {
|
|
75427
|
+
return isPointInBrepPour(point6, pour);
|
|
75428
|
+
}
|
|
75429
|
+
return false;
|
|
75430
|
+
};
|
|
75431
|
+
var isTraceConnectedToSourceNet = (trace, sourceNetId, sourceTraceById) => {
|
|
75432
|
+
if (trace.source_trace_id === sourceNetId) return true;
|
|
75433
|
+
if (!trace.source_trace_id) return false;
|
|
75434
|
+
const sourceTrace = sourceTraceById.get(trace.source_trace_id);
|
|
75435
|
+
if (!sourceTrace) return false;
|
|
75436
|
+
return sourceTrace.connected_source_net_ids.includes(sourceNetId);
|
|
75437
|
+
};
|
|
75438
|
+
var isSegmentFullyInsideCopperPour = (start, end, pour) => {
|
|
75439
|
+
const dx = end.x - start.x;
|
|
75440
|
+
const dy = end.y - start.y;
|
|
75441
|
+
const length8 = Math.hypot(dx, dy);
|
|
75442
|
+
if (length8 <= EPSILON24) return false;
|
|
75443
|
+
const samples = [0, 0.25, 0.5, 0.75, 1];
|
|
75444
|
+
return samples.every(
|
|
75445
|
+
(t) => isPointInCopperPour(
|
|
75446
|
+
{
|
|
75447
|
+
x: start.x + dx * t,
|
|
75448
|
+
y: start.y + dy * t
|
|
75449
|
+
},
|
|
75450
|
+
pour
|
|
75451
|
+
)
|
|
75452
|
+
);
|
|
75453
|
+
};
|
|
75454
|
+
var markTraceSegmentsInsideCopperPour = ({
|
|
75455
|
+
db,
|
|
75456
|
+
copperPour
|
|
75457
|
+
}) => {
|
|
75458
|
+
if (!copperPour.source_net_id) return;
|
|
75459
|
+
const sourceTraceById = new Map(
|
|
75460
|
+
db.source_trace.list().map((sourceTrace) => [sourceTrace.source_trace_id, sourceTrace])
|
|
75461
|
+
);
|
|
75462
|
+
for (const trace of db.pcb_trace.list()) {
|
|
75463
|
+
if (!isTraceConnectedToSourceNet(
|
|
75464
|
+
trace,
|
|
75465
|
+
copperPour.source_net_id,
|
|
75466
|
+
sourceTraceById
|
|
75467
|
+
)) {
|
|
75468
|
+
continue;
|
|
75469
|
+
}
|
|
75470
|
+
let routeChanged = false;
|
|
75471
|
+
const nextRoute = trace.route.map((routePoint) => ({ ...routePoint }));
|
|
75472
|
+
for (let i = 0; i < nextRoute.length - 1; i++) {
|
|
75473
|
+
const fromRoutePoint = nextRoute[i];
|
|
75474
|
+
const toRoutePoint = nextRoute[i + 1];
|
|
75475
|
+
if (!fromRoutePoint || !toRoutePoint) continue;
|
|
75476
|
+
if (!isWireRoutePoint(fromRoutePoint) || !isWireRoutePoint(toRoutePoint))
|
|
75477
|
+
continue;
|
|
75478
|
+
if (fromRoutePoint.layer !== copperPour.layer || toRoutePoint.layer !== copperPour.layer)
|
|
75479
|
+
continue;
|
|
75480
|
+
if (isSegmentFullyInsideCopperPour(
|
|
75481
|
+
{ x: fromRoutePoint.x, y: fromRoutePoint.y },
|
|
75482
|
+
{ x: toRoutePoint.x, y: toRoutePoint.y },
|
|
75483
|
+
copperPour
|
|
75484
|
+
)) {
|
|
75485
|
+
fromRoutePoint.is_inside_copper_pour = true;
|
|
75486
|
+
fromRoutePoint.copper_pour_id = copperPour.pcb_copper_pour_id;
|
|
75487
|
+
toRoutePoint.is_inside_copper_pour = true;
|
|
75488
|
+
toRoutePoint.copper_pour_id = copperPour.pcb_copper_pour_id;
|
|
75489
|
+
routeChanged = true;
|
|
75490
|
+
}
|
|
75491
|
+
}
|
|
75492
|
+
if (routeChanged) {
|
|
75493
|
+
db.pcb_trace.update(trace.pcb_trace_id, { route: nextRoute });
|
|
75494
|
+
}
|
|
75495
|
+
}
|
|
75496
|
+
};
|
|
75497
|
+
|
|
75498
|
+
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbCopperPourRender.ts
|
|
75499
|
+
var pendingCopperPourRenders = /* @__PURE__ */ new WeakMap();
|
|
75500
|
+
var DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM = 0.3;
|
|
75501
|
+
var renderAllCopperPoursForSubcircuit = async (subcircuit) => {
|
|
75502
|
+
if (!subcircuit.root) return;
|
|
75503
|
+
const { db } = subcircuit.root;
|
|
75504
|
+
const copperPours = subcircuit.selectAll("copperpour").filter((copperPour) => copperPour.getSubcircuit() === subcircuit);
|
|
75505
|
+
const resolvedCopperPours = [];
|
|
75506
|
+
for (const copperPour of copperPours) {
|
|
75507
|
+
const { _parsedProps: props } = copperPour;
|
|
75508
|
+
const net = subcircuit.selectOne(props.connectsTo);
|
|
75509
|
+
const sourceNetId = net?.source_net_id;
|
|
75510
|
+
if (!sourceNetId) {
|
|
75511
|
+
copperPour.renderError(
|
|
75512
|
+
`Net "${props.connectsTo}" not found for copper pour`
|
|
75513
|
+
);
|
|
75514
|
+
continue;
|
|
75515
|
+
}
|
|
75516
|
+
resolvedCopperPours.push({ copperPour, sourceNetId });
|
|
75517
|
+
}
|
|
75518
|
+
if (resolvedCopperPours.length === 0) return;
|
|
75519
|
+
const circuitJson = db.toArray();
|
|
75520
|
+
const boardComponent = subcircuit._getBoard();
|
|
75521
|
+
const pcbBoard = boardComponent?.pcb_board_id ? db.pcb_board.get(boardComponent.pcb_board_id) : void 0;
|
|
75522
|
+
let resolvedPcbBoardOutline = pcbBoard?.outline?.length ? pcbBoard.outline : void 0;
|
|
75523
|
+
if (!resolvedPcbBoardOutline && pcbBoard?.width !== void 0 && pcbBoard.height !== void 0) {
|
|
75524
|
+
const { center, width, height } = pcbBoard;
|
|
75525
|
+
resolvedPcbBoardOutline = [
|
|
75526
|
+
{ x: center.x - width / 2, y: center.y - height / 2 },
|
|
75527
|
+
{ x: center.x + width / 2, y: center.y - height / 2 },
|
|
75528
|
+
{ x: center.x + width / 2, y: center.y + height / 2 },
|
|
75529
|
+
{ x: center.x - width / 2, y: center.y + height / 2 }
|
|
75530
|
+
];
|
|
75531
|
+
}
|
|
75532
|
+
const inputProblem = convertCircuitJsonToInputProblem(
|
|
75533
|
+
circuitJson,
|
|
75534
|
+
resolvedCopperPours.map(({ copperPour, sourceNetId }) => {
|
|
75535
|
+
const { _parsedProps: props } = copperPour;
|
|
75536
|
+
const clearance = props.clearance ?? 0.2;
|
|
75537
|
+
return {
|
|
75538
|
+
layer: props.layer,
|
|
75539
|
+
subcircuit_id: subcircuit.subcircuit_id ?? void 0,
|
|
75540
|
+
source_net_id: sourceNetId,
|
|
75541
|
+
pad_margin: props.padMargin ?? clearance,
|
|
75542
|
+
trace_margin: props.traceMargin ?? clearance,
|
|
75543
|
+
pour_margin: clearance,
|
|
75544
|
+
board_edge_margin: props.boardEdgeMargin ?? clearance,
|
|
75545
|
+
board_edge_outline: copperPour._isImplicitCopperPour ? resolvedPcbBoardOutline : void 0,
|
|
75546
|
+
cutout_margin: props.cutoutMargin ?? clearance,
|
|
75547
|
+
...props.useThermalReliefs ? {
|
|
75548
|
+
use_thermal_reliefs: true,
|
|
75549
|
+
thermal_relief_spoke_width: DEFAULT_THERMAL_RELIEF_SPOKE_WIDTH_MM
|
|
75550
|
+
} : {},
|
|
75551
|
+
outline: props.outline ?? resolvedPcbBoardOutline
|
|
75552
|
+
};
|
|
75553
|
+
})
|
|
75554
|
+
);
|
|
75555
|
+
await initializeManifoldGeometry();
|
|
75556
|
+
const solver = new CopperPourPipelineSolver2(inputProblem);
|
|
75557
|
+
subcircuit.root.emit("solver:started", {
|
|
75558
|
+
type: "solver:started",
|
|
75559
|
+
solverName: "CopperPourPipelineSolver",
|
|
75560
|
+
solverParams: inputProblem,
|
|
75561
|
+
solverConstructorArgs: [inputProblem],
|
|
75562
|
+
componentName: subcircuit.getString()
|
|
75563
|
+
});
|
|
75564
|
+
const { brep_shapes_by_region } = solver.getOutput();
|
|
75565
|
+
for (const [
|
|
75566
|
+
regionIndex,
|
|
75567
|
+
{ copperPour, sourceNetId }
|
|
75568
|
+
] of resolvedCopperPours.entries()) {
|
|
75569
|
+
const { _parsedProps: props } = copperPour;
|
|
75570
|
+
const coveredWithSolderMask = props.coveredWithSolderMask ?? false;
|
|
75571
|
+
for (const brepShape of brep_shapes_by_region[regionIndex] ?? []) {
|
|
75572
|
+
const insertedPour = db.pcb_copper_pour.insert({
|
|
75573
|
+
shape: "brep",
|
|
75574
|
+
layer: props.layer,
|
|
75575
|
+
brep_shape: brepShape,
|
|
75576
|
+
source_net_id: sourceNetId,
|
|
75577
|
+
subcircuit_id: subcircuit.subcircuit_id ?? void 0,
|
|
75578
|
+
covered_with_solder_mask: coveredWithSolderMask
|
|
75579
|
+
});
|
|
75580
|
+
markTraceSegmentsInsideCopperPour({
|
|
75581
|
+
db,
|
|
75582
|
+
copperPour: insertedPour
|
|
75583
|
+
});
|
|
75584
|
+
}
|
|
75585
|
+
}
|
|
75586
|
+
};
|
|
75587
|
+
function CopperPour_doInitialPcbCopperPourRender(copperPour) {
|
|
75588
|
+
if (copperPour.root?.pcbDisabled) return;
|
|
75589
|
+
copperPour._queueAsyncEffect("PcbCopperPourRender", async () => {
|
|
75590
|
+
const subcircuit = copperPour.getSubcircuit();
|
|
75591
|
+
const pendingRender = pendingCopperPourRenders.get(subcircuit);
|
|
75592
|
+
if (pendingRender) {
|
|
75593
|
+
await pendingRender;
|
|
75594
|
+
return;
|
|
75595
|
+
}
|
|
75596
|
+
const renderPromise = renderAllCopperPoursForSubcircuit(subcircuit);
|
|
75597
|
+
pendingCopperPourRenders.set(subcircuit, renderPromise);
|
|
75598
|
+
try {
|
|
75599
|
+
await renderPromise;
|
|
75600
|
+
} finally {
|
|
75601
|
+
pendingCopperPourRenders.delete(subcircuit);
|
|
75602
|
+
}
|
|
75603
|
+
});
|
|
75604
|
+
}
|
|
75605
|
+
|
|
75606
|
+
// lib/components/primitive-components/CopperPour/CopperPour_doInitialPcbViaStitchRender.ts
|
|
75607
|
+
import { pcb_via as pcb_via3 } from "circuit-json";
|
|
75608
|
+
var renderViaStitchingForCopperPours = (copperPour) => {
|
|
75609
|
+
const subcircuit = copperPour.getSubcircuit();
|
|
75610
|
+
if (!subcircuit.root) return;
|
|
75611
|
+
const copperPours = subcircuit.selectAll("copperpour").filter(
|
|
75612
|
+
(candidateCopperPour) => candidateCopperPour.getSubcircuit() === subcircuit
|
|
75613
|
+
);
|
|
75614
|
+
if (copperPours[0] !== copperPour) return;
|
|
75615
|
+
const sourceNetIds = copperPours.flatMap((candidateCopperPour) => {
|
|
75616
|
+
const net = subcircuit.selectOne(
|
|
75617
|
+
candidateCopperPour._parsedProps.connectsTo
|
|
75618
|
+
);
|
|
75619
|
+
return net?.source_net_id ? [net.source_net_id] : [];
|
|
75620
|
+
});
|
|
75621
|
+
if (sourceNetIds.length === 0) return;
|
|
75622
|
+
const { db } = subcircuit.root;
|
|
75623
|
+
const pcbStyle = copperPour.getInheritedMergedProperty("pcbStyle");
|
|
75624
|
+
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle);
|
|
75625
|
+
const boardComponent = copperPour._getBoard();
|
|
75626
|
+
const pcbBoard = boardComponent?.pcb_board_id ? db.pcb_board.get(boardComponent.pcb_board_id) : void 0;
|
|
75627
|
+
const solverInput = {
|
|
75628
|
+
circuitJson: db.toArray(),
|
|
75629
|
+
options: {
|
|
75630
|
+
sourceNetIds: [...new Set(sourceNetIds)],
|
|
75631
|
+
viaHoleDiameter: pcbBoard?.min_via_hole_diameter ?? holeDiameter,
|
|
75632
|
+
viaOuterDiameter: pcbBoard?.min_via_pad_diameter ?? padDiameter,
|
|
75633
|
+
viaStitchPitch: boardComponent?._parsedProps.viaStitchPitch
|
|
75634
|
+
}
|
|
75635
|
+
};
|
|
75636
|
+
const solver = new ViaStitchSolver(solverInput);
|
|
75637
|
+
subcircuit.root.emit("solver:started", {
|
|
75638
|
+
type: "solver:started",
|
|
75639
|
+
solverName: "ViaStitchSolver",
|
|
75640
|
+
solverParams: solverInput,
|
|
75641
|
+
solverConstructorArgs: [solverInput],
|
|
75642
|
+
componentName: subcircuit.getString()
|
|
75643
|
+
});
|
|
75644
|
+
solver.solve();
|
|
75645
|
+
if (solver.failed) {
|
|
75646
|
+
throw new Error(solver.error ?? "Via stitching solver failed");
|
|
75647
|
+
}
|
|
75648
|
+
for (const pcbVia of solver.getOutput().pcbVias) {
|
|
75649
|
+
const { pcb_via_id: _solverViaId, ...pcbViaInput } = pcb_via3.parse(pcbVia);
|
|
75650
|
+
const insertedVia = db.pcb_via.insert({
|
|
75651
|
+
...pcbViaInput,
|
|
75652
|
+
tented_on_top: void 0,
|
|
75653
|
+
tented_on_bottom: void 0
|
|
75654
|
+
});
|
|
75655
|
+
boardComponent?._generatedStitchingViaIds?.add(insertedVia.pcb_via_id);
|
|
75656
|
+
}
|
|
75657
|
+
};
|
|
75658
|
+
function CopperPour_doInitialPcbViaStitchRender(copperPour) {
|
|
75659
|
+
if (copperPour.root?.pcbDisabled || !copperPour.root?._featurePcbViaStitching)
|
|
75660
|
+
return;
|
|
75661
|
+
if (!copperPour._getBoard()?._parsedProps.enableViaStitching) return;
|
|
75662
|
+
copperPour._queueAsyncEffect("PcbViaStitchRender", async () => {
|
|
75663
|
+
renderViaStitchingForCopperPours(copperPour);
|
|
75664
|
+
});
|
|
75665
|
+
}
|
|
75666
|
+
|
|
75667
|
+
// lib/components/primitive-components/CopperPour/CopperPour.ts
|
|
75668
|
+
var CopperPour = class extends PrimitiveComponent2 {
|
|
75669
|
+
isPcbPrimitive = true;
|
|
75670
|
+
_isImplicitCopperPour = false;
|
|
75671
|
+
get config() {
|
|
75672
|
+
return {
|
|
75673
|
+
componentName: "CopperPour",
|
|
75674
|
+
zodProps: copperPourProps
|
|
75675
|
+
};
|
|
75676
|
+
}
|
|
75677
|
+
getPcbSize() {
|
|
75678
|
+
return { width: 0, height: 0 };
|
|
75679
|
+
}
|
|
75680
|
+
doInitialCreateNetsFromProps() {
|
|
75681
|
+
const { _parsedProps: props } = this;
|
|
75682
|
+
createNetsFromProps(this, [props.connectsTo]);
|
|
75683
|
+
}
|
|
75684
|
+
doInitialPcbCopperPourRender() {
|
|
75685
|
+
CopperPour_doInitialPcbCopperPourRender(this);
|
|
75686
|
+
}
|
|
75687
|
+
doInitialPcbViaStitchRender() {
|
|
75688
|
+
CopperPour_doInitialPcbViaStitchRender(this);
|
|
75689
|
+
}
|
|
75690
|
+
};
|
|
75691
|
+
|
|
75728
75692
|
// lib/components/primitive-components/AssemblyDevice.ts
|
|
75729
75693
|
import { assemblyDeviceProps } from "@tscircuit/props";
|
|
75730
75694
|
import { identity as identity10 } from "transformation-matrix";
|