@tscircuit/core 0.0.97 → 0.0.99
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 +139 -140
- package/dist/index.js +860 -843
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -34,13 +34,12 @@ __export(components_exports, {
|
|
|
34
34
|
TraceHint: () => TraceHint
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
// lib/components/
|
|
38
|
-
import {
|
|
37
|
+
// lib/components/base-components/NormalComponent.ts
|
|
38
|
+
import { rotation } from "circuit-json";
|
|
39
|
+
import { fp } from "footprinter";
|
|
39
40
|
|
|
40
|
-
// lib/
|
|
41
|
-
import
|
|
42
|
-
import { symbols } from "schematic-symbols";
|
|
43
|
-
import "react";
|
|
41
|
+
// lib/fiber/create-instance-from-react-element.ts
|
|
42
|
+
import ReactReconciler from "react-reconciler";
|
|
44
43
|
|
|
45
44
|
// lib/components/base-components/Renderable.ts
|
|
46
45
|
var orderedRenderPhases = [
|
|
@@ -133,12 +132,169 @@ var Renderable = class {
|
|
|
133
132
|
}
|
|
134
133
|
};
|
|
135
134
|
|
|
135
|
+
// lib/fiber/catalogue.ts
|
|
136
|
+
var catalogue = {};
|
|
137
|
+
var extendCatalogue = (objects) => {
|
|
138
|
+
const altKeys = Object.fromEntries(
|
|
139
|
+
Object.entries(objects).map(([key, v]) => [key.toLowerCase(), v])
|
|
140
|
+
);
|
|
141
|
+
Object.assign(catalogue, objects);
|
|
142
|
+
Object.assign(catalogue, altKeys);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// lib/fiber/create-instance-from-react-element.ts
|
|
146
|
+
import { identity } from "transformation-matrix";
|
|
147
|
+
function prepare(object, state) {
|
|
148
|
+
const instance = object;
|
|
149
|
+
instance.__tsci = {
|
|
150
|
+
...state
|
|
151
|
+
};
|
|
152
|
+
return object;
|
|
153
|
+
}
|
|
154
|
+
var hostConfig = {
|
|
155
|
+
supportsMutation: true,
|
|
156
|
+
createInstance(type, props) {
|
|
157
|
+
const target = catalogue[type];
|
|
158
|
+
if (!target) {
|
|
159
|
+
if (Object.keys(catalogue).length === 0) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
"No components registered in catalogue, did you forget to import lib/register-catalogue in your test file?"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
throw new Error(
|
|
165
|
+
`Unsupported component type (not registered in @tscircuit/core catalogue): "${type}" See CREATING_NEW_COMPONENTS.md`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const instance = prepare(new target(props), {});
|
|
169
|
+
return instance;
|
|
170
|
+
},
|
|
171
|
+
createTextInstance() {
|
|
172
|
+
return {};
|
|
173
|
+
},
|
|
174
|
+
appendInitialChild(parentInstance, child) {
|
|
175
|
+
parentInstance.add(child);
|
|
176
|
+
},
|
|
177
|
+
appendChild(parentInstance, child) {
|
|
178
|
+
parentInstance.add(child);
|
|
179
|
+
},
|
|
180
|
+
appendChildToContainer(container, child) {
|
|
181
|
+
container.add(child);
|
|
182
|
+
},
|
|
183
|
+
finalizeInitialChildren() {
|
|
184
|
+
return false;
|
|
185
|
+
},
|
|
186
|
+
prepareUpdate() {
|
|
187
|
+
return null;
|
|
188
|
+
},
|
|
189
|
+
shouldSetTextContent() {
|
|
190
|
+
return false;
|
|
191
|
+
},
|
|
192
|
+
getRootHostContext() {
|
|
193
|
+
return {};
|
|
194
|
+
},
|
|
195
|
+
getChildHostContext() {
|
|
196
|
+
return {};
|
|
197
|
+
},
|
|
198
|
+
prepareForCommit() {
|
|
199
|
+
return null;
|
|
200
|
+
},
|
|
201
|
+
resetAfterCommit() {
|
|
202
|
+
},
|
|
203
|
+
commitMount() {
|
|
204
|
+
},
|
|
205
|
+
commitUpdate() {
|
|
206
|
+
},
|
|
207
|
+
removeChild() {
|
|
208
|
+
},
|
|
209
|
+
clearContainer() {
|
|
210
|
+
},
|
|
211
|
+
supportsPersistence: false,
|
|
212
|
+
getPublicInstance(instance) {
|
|
213
|
+
return instance;
|
|
214
|
+
},
|
|
215
|
+
preparePortalMount(containerInfo) {
|
|
216
|
+
throw new Error("Function not implemented.");
|
|
217
|
+
},
|
|
218
|
+
scheduleTimeout(fn, delay) {
|
|
219
|
+
throw new Error("Function not implemented.");
|
|
220
|
+
},
|
|
221
|
+
cancelTimeout(id) {
|
|
222
|
+
throw new Error("Function not implemented.");
|
|
223
|
+
},
|
|
224
|
+
noTimeout: void 0,
|
|
225
|
+
isPrimaryRenderer: false,
|
|
226
|
+
getCurrentEventPriority() {
|
|
227
|
+
throw new Error("Function not implemented.");
|
|
228
|
+
},
|
|
229
|
+
getInstanceFromNode(node) {
|
|
230
|
+
throw new Error("Function not implemented.");
|
|
231
|
+
},
|
|
232
|
+
beforeActiveInstanceBlur() {
|
|
233
|
+
throw new Error("Function not implemented.");
|
|
234
|
+
},
|
|
235
|
+
afterActiveInstanceBlur() {
|
|
236
|
+
throw new Error("Function not implemented.");
|
|
237
|
+
},
|
|
238
|
+
prepareScopeUpdate: (scopeInstance, instance) => {
|
|
239
|
+
throw new Error("Function not implemented.");
|
|
240
|
+
},
|
|
241
|
+
getInstanceFromScope: (scopeInstance) => {
|
|
242
|
+
throw new Error("Function not implemented.");
|
|
243
|
+
},
|
|
244
|
+
detachDeletedInstance: (node) => {
|
|
245
|
+
throw new Error("Function not implemented.");
|
|
246
|
+
},
|
|
247
|
+
supportsHydration: false
|
|
248
|
+
};
|
|
249
|
+
var reconciler = ReactReconciler(hostConfig);
|
|
250
|
+
var createInstanceFromReactElement = (reactElm) => {
|
|
251
|
+
const rootContainer = {
|
|
252
|
+
children: [],
|
|
253
|
+
props: {
|
|
254
|
+
name: "$root"
|
|
255
|
+
},
|
|
256
|
+
add(instance) {
|
|
257
|
+
instance.parent = this;
|
|
258
|
+
this.children.push(instance);
|
|
259
|
+
},
|
|
260
|
+
computePcbGlobalTransform() {
|
|
261
|
+
return identity();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
const container = reconciler.createContainer(
|
|
265
|
+
// TODO Replace with store like react-three-fiber
|
|
266
|
+
// https://github.com/pmndrs/react-three-fiber/blob/a457290856f57741bf8beef4f6ff9dbf4879c0a5/packages/fiber/src/core/index.tsx#L172
|
|
267
|
+
// https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/core/store.ts#L168
|
|
268
|
+
rootContainer,
|
|
269
|
+
0,
|
|
270
|
+
null,
|
|
271
|
+
false,
|
|
272
|
+
null,
|
|
273
|
+
"tsci",
|
|
274
|
+
(error) => {
|
|
275
|
+
console.log("Error in createContainer");
|
|
276
|
+
console.error(error);
|
|
277
|
+
},
|
|
278
|
+
null
|
|
279
|
+
);
|
|
280
|
+
reconciler.updateContainer(reactElm, container, null, () => {
|
|
281
|
+
});
|
|
282
|
+
const rootInstance = reconciler.getPublicRootInstance(
|
|
283
|
+
container
|
|
284
|
+
);
|
|
285
|
+
if (rootInstance) return rootInstance;
|
|
286
|
+
return rootContainer.children[0];
|
|
287
|
+
};
|
|
288
|
+
|
|
136
289
|
// lib/components/base-components/PrimitiveComponent.ts
|
|
290
|
+
import { z } from "zod";
|
|
291
|
+
import { symbols } from "schematic-symbols";
|
|
292
|
+
import "react";
|
|
137
293
|
import {
|
|
138
294
|
applyToPoint,
|
|
139
295
|
compose,
|
|
140
296
|
flipY,
|
|
141
|
-
identity,
|
|
297
|
+
identity as identity2,
|
|
142
298
|
rotate,
|
|
143
299
|
translate
|
|
144
300
|
} from "transformation-matrix";
|
|
@@ -267,7 +423,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
267
423
|
const manualPlacement = this.getSubcircuit()._getManualPlacementForComponent(this);
|
|
268
424
|
if (manualPlacement && this.props.pcbX === void 0 && this.props.pcbY === void 0) {
|
|
269
425
|
return compose(
|
|
270
|
-
this.parent?._computePcbGlobalTransformBeforeLayout() ??
|
|
426
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity2(),
|
|
271
427
|
compose(
|
|
272
428
|
translate(manualPlacement.x, manualPlacement.y),
|
|
273
429
|
rotate((props.pcbRotation ?? 0) * Math.PI / 180)
|
|
@@ -286,7 +442,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
286
442
|
translate(-containerCenter.x, -containerCenter.y)
|
|
287
443
|
);
|
|
288
444
|
return compose(
|
|
289
|
-
this.parent?._computePcbGlobalTransformBeforeLayout() ??
|
|
445
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity2(),
|
|
290
446
|
flipY(),
|
|
291
447
|
this.computePcbPropsTransform()
|
|
292
448
|
);
|
|
@@ -294,7 +450,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
294
450
|
}
|
|
295
451
|
}
|
|
296
452
|
return compose(
|
|
297
|
-
this.parent?._computePcbGlobalTransformBeforeLayout() ??
|
|
453
|
+
this.parent?._computePcbGlobalTransformBeforeLayout() ?? identity2(),
|
|
298
454
|
this.computePcbPropsTransform()
|
|
299
455
|
);
|
|
300
456
|
}
|
|
@@ -356,7 +512,7 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
356
512
|
*/
|
|
357
513
|
computeSchematicGlobalTransform() {
|
|
358
514
|
return compose(
|
|
359
|
-
this.parent?.computeSchematicGlobalTransform?.() ??
|
|
515
|
+
this.parent?.computeSchematicGlobalTransform?.() ?? identity2(),
|
|
360
516
|
this.computeSchematicPropsTransform()
|
|
361
517
|
);
|
|
362
518
|
}
|
|
@@ -566,603 +722,166 @@ var PrimitiveComponent = class extends Renderable {
|
|
|
566
722
|
}
|
|
567
723
|
};
|
|
568
724
|
|
|
569
|
-
// lib/components/primitive-components/
|
|
570
|
-
import
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
725
|
+
// lib/components/primitive-components/Net.ts
|
|
726
|
+
import { z as z2 } from "zod";
|
|
727
|
+
|
|
728
|
+
// lib/utils/pairs.ts
|
|
729
|
+
function pairs(arr) {
|
|
730
|
+
const result = [];
|
|
731
|
+
for (let i = 0; i < arr.length - 1; i++) {
|
|
732
|
+
result.push([arr[i], arr[i + 1]]);
|
|
733
|
+
}
|
|
734
|
+
return result;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// lib/components/primitive-components/Net.ts
|
|
738
|
+
import { autoroute } from "@tscircuit/infgrid-ijump-astar";
|
|
739
|
+
var netProps = z2.object({
|
|
740
|
+
name: z2.string()
|
|
741
|
+
});
|
|
742
|
+
var Net = class extends PrimitiveComponent {
|
|
743
|
+
source_net_id;
|
|
574
744
|
get config() {
|
|
575
745
|
return {
|
|
576
|
-
componentName: "
|
|
577
|
-
zodProps:
|
|
746
|
+
componentName: "Net",
|
|
747
|
+
zodProps: netProps
|
|
578
748
|
};
|
|
579
749
|
}
|
|
750
|
+
getPortSelector() {
|
|
751
|
+
return `net.${this.props.name}`;
|
|
752
|
+
}
|
|
753
|
+
doInitialSourceRender() {
|
|
754
|
+
const { db } = this.root;
|
|
755
|
+
const { _parsedProps: props } = this;
|
|
756
|
+
const net = db.source_net.insert({
|
|
757
|
+
name: props.name,
|
|
758
|
+
member_source_group_ids: []
|
|
759
|
+
});
|
|
760
|
+
this.source_net_id = net.source_net_id;
|
|
761
|
+
}
|
|
580
762
|
/**
|
|
581
|
-
*
|
|
582
|
-
*
|
|
763
|
+
* Get all ports connected to this net.
|
|
764
|
+
*
|
|
765
|
+
* TODO currently we're not checking for indirect connections (traces that are
|
|
766
|
+
* connected to other traces that are in turn connected to the net)
|
|
583
767
|
*/
|
|
584
|
-
|
|
585
|
-
const
|
|
586
|
-
|
|
587
|
-
)
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
return {
|
|
594
|
-
...props,
|
|
595
|
-
left: props.right,
|
|
596
|
-
right: props.left
|
|
597
|
-
};
|
|
768
|
+
getAllConnectedPorts() {
|
|
769
|
+
const allPorts = this.getSubcircuit().selectAll("port");
|
|
770
|
+
const connectedPorts = [];
|
|
771
|
+
for (const port of allPorts) {
|
|
772
|
+
const traces = port._getDirectlyConnectedTraces();
|
|
773
|
+
for (const trace of traces) {
|
|
774
|
+
if (trace._isExplicitlyConnectedToNet(this)) {
|
|
775
|
+
connectedPorts.push(port);
|
|
776
|
+
break;
|
|
598
777
|
}
|
|
599
778
|
}
|
|
600
|
-
return props;
|
|
601
|
-
};
|
|
602
|
-
const involvedComponents = constraints.flatMap(
|
|
603
|
-
(constraint) => constraint._getAllReferencedComponents().componentsWithSelectors
|
|
604
|
-
).map(({ component, selector, componentSelector, edge }) => ({
|
|
605
|
-
component,
|
|
606
|
-
selector,
|
|
607
|
-
componentSelector,
|
|
608
|
-
edge,
|
|
609
|
-
bounds: component._getPcbCircuitJsonBounds()
|
|
610
|
-
}));
|
|
611
|
-
if (involvedComponents.some((c) => c.edge)) {
|
|
612
|
-
throw new Error(
|
|
613
|
-
"edge constraints not implemented yet for footprint layout, contributions welcome!"
|
|
614
|
-
);
|
|
615
779
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
780
|
+
return connectedPorts;
|
|
781
|
+
}
|
|
782
|
+
/**
|
|
783
|
+
* Get all traces that are directly connected to this net, i.e. they list
|
|
784
|
+
* this net in their path, from, or to props
|
|
785
|
+
*/
|
|
786
|
+
_getAllDirectlyConnectedTraces() {
|
|
787
|
+
const allTraces = this.getSubcircuit().selectAll("trace");
|
|
788
|
+
const connectedTraces = [];
|
|
789
|
+
for (const trace of allTraces) {
|
|
790
|
+
if (trace._isExplicitlyConnectedToNet(this)) {
|
|
791
|
+
connectedTraces.push(trace);
|
|
625
792
|
}
|
|
626
|
-
return kVars[name];
|
|
627
793
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
794
|
+
return connectedTraces;
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Add PCB Traces to connect net islands together. A net island is a set of
|
|
798
|
+
* ports that are connected to each other. If a there are multiple net islands
|
|
799
|
+
* that means that the net is not fully connected and we need to add traces
|
|
800
|
+
* such that the nets are fully connected
|
|
801
|
+
*/
|
|
802
|
+
doInitialPcbRouteNetIslands() {
|
|
803
|
+
const { db } = this.root;
|
|
804
|
+
const { _parsedProps: props } = this;
|
|
805
|
+
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
806
|
+
(trace) => (trace._portsRoutedOnPcb?.length ?? 0) > 0
|
|
807
|
+
);
|
|
808
|
+
const islands = [];
|
|
809
|
+
for (const trace of traces) {
|
|
810
|
+
const tracePorts = trace._portsRoutedOnPcb;
|
|
811
|
+
const traceIsland = islands.find(
|
|
812
|
+
(island) => tracePorts.some((port) => island.ports.includes(port))
|
|
813
|
+
);
|
|
814
|
+
if (!traceIsland) {
|
|
815
|
+
islands.push({ ports: [...tracePorts], traces: [trace] });
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
traceIsland.traces.push(trace);
|
|
819
|
+
traceIsland.ports.push(...tracePorts);
|
|
633
820
|
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const expr = new kiwi.Expression(
|
|
654
|
-
rightVar,
|
|
655
|
-
-rightBounds.width / 2,
|
|
656
|
-
[-1, leftVar],
|
|
657
|
-
-leftBounds.width / 2
|
|
658
|
-
);
|
|
659
|
-
solver.addConstraint(
|
|
660
|
-
new kiwi.Constraint(
|
|
661
|
-
expr,
|
|
662
|
-
kiwi.Operator.Eq,
|
|
663
|
-
props.xDist,
|
|
664
|
-
kiwi.Strength.required
|
|
665
|
-
)
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
} else if ("yDist" in props) {
|
|
669
|
-
const { yDist, top, bottom, edgeToEdge, centerToCenter } = props;
|
|
670
|
-
const topVar = getKVar(`${top}_y`);
|
|
671
|
-
const bottomVar = getKVar(`${bottom}_y`);
|
|
672
|
-
const topBounds = getComponentDetails(top)?.bounds;
|
|
673
|
-
const bottomBounds = getComponentDetails(bottom)?.bounds;
|
|
674
|
-
if (centerToCenter) {
|
|
675
|
-
const expr = new kiwi.Expression(topVar, [-1, bottomVar]);
|
|
676
|
-
solver.addConstraint(
|
|
677
|
-
new kiwi.Constraint(
|
|
678
|
-
expr,
|
|
679
|
-
kiwi.Operator.Eq,
|
|
680
|
-
props.yDist,
|
|
681
|
-
kiwi.Strength.required
|
|
682
|
-
)
|
|
683
|
-
);
|
|
684
|
-
} else if (edgeToEdge) {
|
|
685
|
-
const expr = new kiwi.Expression(
|
|
686
|
-
topVar,
|
|
687
|
-
topBounds.height / 2,
|
|
688
|
-
[-1, bottomVar],
|
|
689
|
-
-bottomBounds.height / 2
|
|
690
|
-
);
|
|
691
|
-
solver.addConstraint(
|
|
692
|
-
new kiwi.Constraint(
|
|
693
|
-
expr,
|
|
694
|
-
kiwi.Operator.Eq,
|
|
695
|
-
props.yDist,
|
|
696
|
-
kiwi.Strength.required
|
|
697
|
-
)
|
|
821
|
+
if (islands.length === 0) {
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
const islandPairs = pairs(islands);
|
|
825
|
+
for (const [A, B] of islandPairs) {
|
|
826
|
+
const Apositions = A.ports.map(
|
|
827
|
+
(port) => port._getGlobalPcbPositionBeforeLayout()
|
|
828
|
+
);
|
|
829
|
+
const Bpositions = B.ports.map(
|
|
830
|
+
(port) => port._getGlobalPcbPositionBeforeLayout()
|
|
831
|
+
);
|
|
832
|
+
let closestDist = Infinity;
|
|
833
|
+
let closestPair = [-1, -1];
|
|
834
|
+
for (let i = 0; i < Apositions.length; i++) {
|
|
835
|
+
const Apos = Apositions[i];
|
|
836
|
+
for (let j = 0; j < Bpositions.length; j++) {
|
|
837
|
+
const Bpos = Bpositions[j];
|
|
838
|
+
const dist = Math.sqrt(
|
|
839
|
+
(Apos.x - Bpos.x) ** 2 + (Apos.y - Bpos.y) ** 2
|
|
698
840
|
);
|
|
841
|
+
if (dist < closestDist) {
|
|
842
|
+
closestDist = dist;
|
|
843
|
+
closestPair = [i, j];
|
|
844
|
+
}
|
|
699
845
|
}
|
|
700
|
-
} else if ("sameY" in props) {
|
|
701
|
-
const { for: selectors } = props;
|
|
702
|
-
if (selectors.length < 2) continue;
|
|
703
|
-
const vars = selectors.map((selector) => getKVar(`${selector}_y`));
|
|
704
|
-
const expr = new kiwi.Expression(...vars.slice(1));
|
|
705
|
-
solver.addConstraint(
|
|
706
|
-
new kiwi.Constraint(
|
|
707
|
-
expr,
|
|
708
|
-
kiwi.Operator.Eq,
|
|
709
|
-
vars[0],
|
|
710
|
-
kiwi.Strength.required
|
|
711
|
-
)
|
|
712
|
-
);
|
|
713
|
-
} else if ("sameX" in props) {
|
|
714
|
-
const { for: selectors } = props;
|
|
715
|
-
if (selectors.length < 2) continue;
|
|
716
|
-
const vars = selectors.map((selector) => getKVar(`${selector}_x`));
|
|
717
|
-
const expr = new kiwi.Expression(...vars.slice(1));
|
|
718
|
-
solver.addConstraint(
|
|
719
|
-
new kiwi.Constraint(
|
|
720
|
-
expr,
|
|
721
|
-
kiwi.Operator.Eq,
|
|
722
|
-
vars[0],
|
|
723
|
-
kiwi.Strength.required
|
|
724
|
-
)
|
|
725
|
-
);
|
|
726
846
|
}
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
console.table(
|
|
732
|
-
Object.entries(kVars).map(([key, kvar]) => ({
|
|
733
|
-
var: key,
|
|
734
|
-
val: kvar.value()
|
|
735
|
-
}))
|
|
736
|
-
);
|
|
737
|
-
}
|
|
738
|
-
const bounds = {
|
|
739
|
-
left: Infinity,
|
|
740
|
-
right: -Infinity,
|
|
741
|
-
top: -Infinity,
|
|
742
|
-
bottom: Infinity
|
|
743
|
-
};
|
|
744
|
-
for (const {
|
|
745
|
-
selector,
|
|
746
|
-
bounds: { width, height }
|
|
747
|
-
} of involvedComponents) {
|
|
748
|
-
const kvx = getKVar(`${selector}_x`);
|
|
749
|
-
const kvy = getKVar(`${selector}_y`);
|
|
750
|
-
const newLeft = kvx.value() - width / 2;
|
|
751
|
-
const newRight = kvx.value() + width / 2;
|
|
752
|
-
const newTop = kvy.value() + height / 2;
|
|
753
|
-
const newBottom = kvy.value() - height / 2;
|
|
754
|
-
bounds.left = Math.min(bounds.left, newLeft);
|
|
755
|
-
bounds.right = Math.max(bounds.right, newRight);
|
|
756
|
-
bounds.top = Math.max(bounds.top, newTop);
|
|
757
|
-
bounds.bottom = Math.min(bounds.bottom, newBottom);
|
|
758
|
-
}
|
|
759
|
-
const globalOffset = {
|
|
760
|
-
x: -(bounds.right + bounds.left) / 2,
|
|
761
|
-
y: -(bounds.top + bounds.bottom) / 2
|
|
762
|
-
};
|
|
763
|
-
const containerPos = this.getPrimitiveContainer()._getGlobalPcbPositionBeforeLayout();
|
|
764
|
-
globalOffset.x += containerPos.x;
|
|
765
|
-
globalOffset.y += containerPos.y;
|
|
766
|
-
for (const { component, selector } of involvedComponents) {
|
|
767
|
-
const kvx = getKVar(`${selector}_x`);
|
|
768
|
-
const kvy = getKVar(`${selector}_y`);
|
|
769
|
-
component._setPositionFromLayout({
|
|
770
|
-
x: kvx.value() + globalOffset.x,
|
|
771
|
-
y: kvy.value() + globalOffset.y
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
|
-
|
|
777
|
-
// lib/components/base-components/NormalComponent.ts
|
|
778
|
-
import { z as z4 } from "zod";
|
|
779
|
-
|
|
780
|
-
// lib/utils/get-relative-direction.ts
|
|
781
|
-
function getRelativeDirection(pointA, pointB) {
|
|
782
|
-
const dx = pointB.x - pointA.x;
|
|
783
|
-
const dy = pointB.y - pointA.y;
|
|
784
|
-
if (Math.abs(dx) > Math.abs(dy)) {
|
|
785
|
-
return dx > 0 ? "right" : "left";
|
|
786
|
-
}
|
|
787
|
-
return dy > 0 ? "down" : "up";
|
|
788
|
-
}
|
|
789
|
-
|
|
790
|
-
// lib/components/primitive-components/Port.ts
|
|
791
|
-
import "schematic-symbols";
|
|
792
|
-
import { applyToPoint as applyToPoint2, compose as compose2, translate as translate2 } from "transformation-matrix";
|
|
793
|
-
import { z as z2 } from "zod";
|
|
794
|
-
var portProps = z2.object({
|
|
795
|
-
name: z2.string().optional(),
|
|
796
|
-
pinNumber: z2.number().optional(),
|
|
797
|
-
aliases: z2.array(z2.string()).optional()
|
|
798
|
-
});
|
|
799
|
-
var Port = class extends PrimitiveComponent {
|
|
800
|
-
source_port_id = null;
|
|
801
|
-
pcb_port_id = null;
|
|
802
|
-
schematic_port_id = null;
|
|
803
|
-
schematicSymbolPortDef = null;
|
|
804
|
-
matchedComponents;
|
|
805
|
-
facingDirection = null;
|
|
806
|
-
get config() {
|
|
807
|
-
return {
|
|
808
|
-
componentName: "Port",
|
|
809
|
-
zodProps: portProps
|
|
810
|
-
};
|
|
811
|
-
}
|
|
812
|
-
constructor(props) {
|
|
813
|
-
if (!props.name && props.pinNumber) props.name = `pin${props.pinNumber}`;
|
|
814
|
-
if (!props.name) {
|
|
815
|
-
throw new Error("Port must have a name or a pinNumber");
|
|
816
|
-
}
|
|
817
|
-
super(props);
|
|
818
|
-
this.matchedComponents = [];
|
|
819
|
-
}
|
|
820
|
-
_getGlobalPcbPositionBeforeLayout() {
|
|
821
|
-
const matchedPcbElm = this.matchedComponents.find((c) => c.isPcbPrimitive);
|
|
822
|
-
if (!matchedPcbElm) {
|
|
823
|
-
throw new Error(
|
|
824
|
-
`Port ${this} has no matched pcb component, can't get global schematic position`
|
|
847
|
+
const Aport = A.ports[closestPair[0]];
|
|
848
|
+
const Bport = B.ports[closestPair[1]];
|
|
849
|
+
const pcbElements = db.toArray().filter(
|
|
850
|
+
(elm) => elm.type === "pcb_smtpad" || elm.type === "pcb_trace" || elm.type === "pcb_plated_hole" || elm.type === "pcb_hole" || elm.type === "source_port" || elm.type === "pcb_port"
|
|
825
851
|
);
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
width: 0,
|
|
839
|
-
height: 0
|
|
840
|
-
};
|
|
841
|
-
}
|
|
842
|
-
_getGlobalPcbPositionAfterLayout() {
|
|
843
|
-
return this._getPcbCircuitJsonBounds().center;
|
|
844
|
-
}
|
|
845
|
-
_getGlobalSchematicPositionBeforeLayout() {
|
|
846
|
-
if (!this.schematicSymbolPortDef) {
|
|
847
|
-
return applyToPoint2(this.parent.computeSchematicGlobalTransform(), {
|
|
848
|
-
x: 0,
|
|
849
|
-
y: 0
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
const symbol = this.parent?.getSchematicSymbol();
|
|
853
|
-
if (!symbol) {
|
|
854
|
-
console.warn(`Could not find parent symbol for ${this}`);
|
|
855
|
-
return { x: 0, y: 0 };
|
|
856
|
-
}
|
|
857
|
-
const transform = compose2(
|
|
858
|
-
this.parent.computeSchematicGlobalTransform(),
|
|
859
|
-
translate2(-symbol.center.x, -symbol.center.y)
|
|
860
|
-
);
|
|
861
|
-
return applyToPoint2(transform, this.schematicSymbolPortDef);
|
|
862
|
-
}
|
|
863
|
-
/**
|
|
864
|
-
* Smtpads and platedholes call this method to register themselves as a match
|
|
865
|
-
* for this port. All the matching is done by primitives other than the Port,
|
|
866
|
-
* but everyone registers themselves as a match with their Port.
|
|
867
|
-
*/
|
|
868
|
-
registerMatch(component) {
|
|
869
|
-
this.matchedComponents.push(component);
|
|
870
|
-
}
|
|
871
|
-
getNameAndAliases() {
|
|
872
|
-
const { _parsedProps: props } = this;
|
|
873
|
-
return Array.from(
|
|
874
|
-
/* @__PURE__ */ new Set([
|
|
875
|
-
...props.aliases ?? [],
|
|
876
|
-
props.name,
|
|
877
|
-
...typeof props.pinNumber === "number" ? [`pin${props.pinNumber}`, props.pinNumber.toString()] : [],
|
|
878
|
-
...this.externallyAddedAliases
|
|
879
|
-
])
|
|
880
|
-
);
|
|
881
|
-
}
|
|
882
|
-
isMatchingPort(port) {
|
|
883
|
-
return this.isMatchingAnyOf(port.getNameAndAliases());
|
|
884
|
-
}
|
|
885
|
-
getPortSelector() {
|
|
886
|
-
return `.${this.parent?.props.name} > port.${this.props.name}`;
|
|
887
|
-
}
|
|
888
|
-
getAvailablePcbLayers() {
|
|
889
|
-
return Array.from(
|
|
890
|
-
new Set(this.matchedComponents.flatMap((c) => c.getAvailablePcbLayers()))
|
|
891
|
-
);
|
|
892
|
-
}
|
|
893
|
-
/**
|
|
894
|
-
* Return traces that are explicitly connected to this port (not via a net)
|
|
895
|
-
*/
|
|
896
|
-
_getDirectlyConnectedTraces() {
|
|
897
|
-
const allSubcircuitTraces = this.getSubcircuit().selectAll(
|
|
898
|
-
"trace"
|
|
899
|
-
);
|
|
900
|
-
const connectedTraces = allSubcircuitTraces.filter(
|
|
901
|
-
(trace) => trace._isExplicitlyConnectedToPort(this)
|
|
902
|
-
);
|
|
903
|
-
return connectedTraces;
|
|
904
|
-
}
|
|
905
|
-
doInitialSourceRender() {
|
|
906
|
-
const { db } = this.root;
|
|
907
|
-
const { _parsedProps: props } = this;
|
|
908
|
-
const port_hints = this.getNameAndAliases();
|
|
909
|
-
const source_port = db.source_port.insert({
|
|
910
|
-
name: props.name,
|
|
911
|
-
pin_number: props.pinNumber,
|
|
912
|
-
port_hints,
|
|
913
|
-
source_component_id: this.parent?.source_component_id
|
|
914
|
-
});
|
|
915
|
-
this.source_port_id = source_port.source_port_id;
|
|
916
|
-
}
|
|
917
|
-
doInitialSourceParentAttachment() {
|
|
918
|
-
const { db } = this.root;
|
|
919
|
-
if (!this.parent?.source_component_id) {
|
|
920
|
-
throw new Error(
|
|
921
|
-
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
922
|
-
);
|
|
923
|
-
}
|
|
924
|
-
db.source_port.update(this.source_port_id, {
|
|
925
|
-
source_component_id: this.parent?.source_component_id
|
|
926
|
-
});
|
|
927
|
-
this.source_component_id = this.parent?.source_component_id;
|
|
928
|
-
}
|
|
929
|
-
doInitialPcbPortRender() {
|
|
930
|
-
const { db } = this.root;
|
|
931
|
-
const { matchedComponents } = this;
|
|
932
|
-
if (!this.parent?.pcb_component_id) {
|
|
933
|
-
throw new Error(
|
|
934
|
-
`${this.getString()} has no parent pcb component, cannot render pcb_port (parent: ${this.parent?.getString()})`
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
|
-
const pcbMatches = matchedComponents.filter((c) => c.isPcbPrimitive);
|
|
938
|
-
if (pcbMatches.length === 0) return;
|
|
939
|
-
if (pcbMatches.length > 1) {
|
|
940
|
-
throw new Error(
|
|
941
|
-
`${this.getString()} has multiple pcb matches, unclear how to place pcb_port: ${pcbMatches.map((c) => c.getString()).join(", ")}`
|
|
942
|
-
);
|
|
943
|
-
}
|
|
944
|
-
const pcbMatch = pcbMatches[0];
|
|
945
|
-
if ("_getPcbCircuitJsonBounds" in pcbMatch) {
|
|
946
|
-
const pcb_port = db.pcb_port.insert({
|
|
947
|
-
pcb_component_id: this.parent?.pcb_component_id,
|
|
948
|
-
layers: this.getAvailablePcbLayers(),
|
|
949
|
-
...pcbMatch._getPcbCircuitJsonBounds().center,
|
|
950
|
-
source_port_id: this.source_port_id
|
|
951
|
-
});
|
|
952
|
-
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
953
|
-
} else {
|
|
954
|
-
throw new Error(
|
|
955
|
-
`${pcbMatch.getString()} does not have a _getGlobalPcbPositionBeforeLayout method (needed for pcb_port placement)`
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
doInitialSchematicPortRender() {
|
|
960
|
-
const { db } = this.root;
|
|
961
|
-
const { _parsedProps: props } = this;
|
|
962
|
-
const container = this.getPrimitiveContainer();
|
|
963
|
-
if (!container) return;
|
|
964
|
-
let center = this._getGlobalSchematicPositionBeforeLayout();
|
|
965
|
-
if ("schematicDimensions" in container && props.pinNumber !== void 0) {
|
|
966
|
-
const chipDims = container.schematicDimensions;
|
|
967
|
-
center = chipDims.getPortPositionByPinNumber(props.pinNumber);
|
|
968
|
-
}
|
|
969
|
-
const containerCenter = container._getGlobalSchematicPositionBeforeLayout();
|
|
970
|
-
this.facingDirection = getRelativeDirection(containerCenter, center);
|
|
971
|
-
const schematic_port = db.schematic_port.insert({
|
|
972
|
-
schematic_component_id: this.parent?.schematic_component_id,
|
|
973
|
-
center,
|
|
974
|
-
source_port_id: this.source_port_id,
|
|
975
|
-
facing_direction: this.facingDirection
|
|
976
|
-
});
|
|
977
|
-
this.schematic_port_id = schematic_port.schematic_port_id;
|
|
978
|
-
}
|
|
979
|
-
_setPositionFromLayout(newCenter) {
|
|
980
|
-
const { db } = this.root;
|
|
981
|
-
if (!this.pcb_port_id) return;
|
|
982
|
-
db.pcb_port.update(this.pcb_port_id, {
|
|
983
|
-
x: newCenter.x,
|
|
984
|
-
y: newCenter.y
|
|
985
|
-
});
|
|
986
|
-
}
|
|
987
|
-
_hasMatchedPcbPrimitive() {
|
|
988
|
-
return this.matchedComponents.some((c) => c.isPcbPrimitive);
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
|
|
992
|
-
// lib/components/base-components/NormalComponent.ts
|
|
993
|
-
import { symbols as symbols2 } from "schematic-symbols";
|
|
994
|
-
import { fp } from "footprinter";
|
|
995
|
-
import {
|
|
996
|
-
isValidElement as isReactElement2,
|
|
997
|
-
isValidElement
|
|
998
|
-
} from "react";
|
|
999
|
-
|
|
1000
|
-
// lib/fiber/create-instance-from-react-element.ts
|
|
1001
|
-
import ReactReconciler from "react-reconciler";
|
|
1002
|
-
|
|
1003
|
-
// lib/fiber/catalogue.ts
|
|
1004
|
-
var catalogue = {};
|
|
1005
|
-
var extendCatalogue = (objects) => {
|
|
1006
|
-
const altKeys = Object.fromEntries(
|
|
1007
|
-
Object.entries(objects).map(([key, v]) => [key.toLowerCase(), v])
|
|
1008
|
-
);
|
|
1009
|
-
Object.assign(catalogue, objects);
|
|
1010
|
-
Object.assign(catalogue, altKeys);
|
|
1011
|
-
};
|
|
1012
|
-
|
|
1013
|
-
// lib/fiber/create-instance-from-react-element.ts
|
|
1014
|
-
import { identity as identity2 } from "transformation-matrix";
|
|
1015
|
-
function prepare(object, state) {
|
|
1016
|
-
const instance = object;
|
|
1017
|
-
instance.__tsci = {
|
|
1018
|
-
...state
|
|
1019
|
-
};
|
|
1020
|
-
return object;
|
|
1021
|
-
}
|
|
1022
|
-
var hostConfig = {
|
|
1023
|
-
supportsMutation: true,
|
|
1024
|
-
createInstance(type, props) {
|
|
1025
|
-
const target = catalogue[type];
|
|
1026
|
-
if (!target) {
|
|
1027
|
-
if (Object.keys(catalogue).length === 0) {
|
|
1028
|
-
throw new Error(
|
|
1029
|
-
"No components registered in catalogue, did you forget to import lib/register-catalogue in your test file?"
|
|
1030
|
-
);
|
|
1031
|
-
}
|
|
1032
|
-
throw new Error(
|
|
1033
|
-
`Unsupported component type (not registered in @tscircuit/core catalogue): "${type}" See CREATING_NEW_COMPONENTS.md`
|
|
852
|
+
const { solution } = autoroute(
|
|
853
|
+
pcbElements.concat([
|
|
854
|
+
{
|
|
855
|
+
type: "source_trace",
|
|
856
|
+
source_trace_id: "__net_trace_tmp",
|
|
857
|
+
connected_source_port_ids: [
|
|
858
|
+
Aport.source_port_id,
|
|
859
|
+
Bport.source_port_id
|
|
860
|
+
]
|
|
861
|
+
}
|
|
862
|
+
])
|
|
863
|
+
// Remove as any when autorouting-dataset has been updated
|
|
1034
864
|
);
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
parentInstance.add(child);
|
|
1044
|
-
},
|
|
1045
|
-
appendChild(parentInstance, child) {
|
|
1046
|
-
parentInstance.add(child);
|
|
1047
|
-
},
|
|
1048
|
-
appendChildToContainer(container, child) {
|
|
1049
|
-
container.add(child);
|
|
1050
|
-
},
|
|
1051
|
-
finalizeInitialChildren() {
|
|
1052
|
-
return false;
|
|
1053
|
-
},
|
|
1054
|
-
prepareUpdate() {
|
|
1055
|
-
return null;
|
|
1056
|
-
},
|
|
1057
|
-
shouldSetTextContent() {
|
|
1058
|
-
return false;
|
|
1059
|
-
},
|
|
1060
|
-
getRootHostContext() {
|
|
1061
|
-
return {};
|
|
1062
|
-
},
|
|
1063
|
-
getChildHostContext() {
|
|
1064
|
-
return {};
|
|
1065
|
-
},
|
|
1066
|
-
prepareForCommit() {
|
|
1067
|
-
return null;
|
|
1068
|
-
},
|
|
1069
|
-
resetAfterCommit() {
|
|
1070
|
-
},
|
|
1071
|
-
commitMount() {
|
|
1072
|
-
},
|
|
1073
|
-
commitUpdate() {
|
|
1074
|
-
},
|
|
1075
|
-
removeChild() {
|
|
1076
|
-
},
|
|
1077
|
-
clearContainer() {
|
|
1078
|
-
},
|
|
1079
|
-
supportsPersistence: false,
|
|
1080
|
-
getPublicInstance(instance) {
|
|
1081
|
-
return instance;
|
|
1082
|
-
},
|
|
1083
|
-
preparePortalMount(containerInfo) {
|
|
1084
|
-
throw new Error("Function not implemented.");
|
|
1085
|
-
},
|
|
1086
|
-
scheduleTimeout(fn, delay) {
|
|
1087
|
-
throw new Error("Function not implemented.");
|
|
1088
|
-
},
|
|
1089
|
-
cancelTimeout(id) {
|
|
1090
|
-
throw new Error("Function not implemented.");
|
|
1091
|
-
},
|
|
1092
|
-
noTimeout: void 0,
|
|
1093
|
-
isPrimaryRenderer: false,
|
|
1094
|
-
getCurrentEventPriority() {
|
|
1095
|
-
throw new Error("Function not implemented.");
|
|
1096
|
-
},
|
|
1097
|
-
getInstanceFromNode(node) {
|
|
1098
|
-
throw new Error("Function not implemented.");
|
|
1099
|
-
},
|
|
1100
|
-
beforeActiveInstanceBlur() {
|
|
1101
|
-
throw new Error("Function not implemented.");
|
|
1102
|
-
},
|
|
1103
|
-
afterActiveInstanceBlur() {
|
|
1104
|
-
throw new Error("Function not implemented.");
|
|
1105
|
-
},
|
|
1106
|
-
prepareScopeUpdate: (scopeInstance, instance) => {
|
|
1107
|
-
throw new Error("Function not implemented.");
|
|
1108
|
-
},
|
|
1109
|
-
getInstanceFromScope: (scopeInstance) => {
|
|
1110
|
-
throw new Error("Function not implemented.");
|
|
1111
|
-
},
|
|
1112
|
-
detachDeletedInstance: (node) => {
|
|
1113
|
-
throw new Error("Function not implemented.");
|
|
1114
|
-
},
|
|
1115
|
-
supportsHydration: false
|
|
1116
|
-
};
|
|
1117
|
-
var reconciler = ReactReconciler(hostConfig);
|
|
1118
|
-
var createInstanceFromReactElement = (reactElm) => {
|
|
1119
|
-
const rootContainer = {
|
|
1120
|
-
children: [],
|
|
1121
|
-
props: {
|
|
1122
|
-
name: "$root"
|
|
1123
|
-
},
|
|
1124
|
-
add(instance) {
|
|
1125
|
-
instance.parent = this;
|
|
1126
|
-
this.children.push(instance);
|
|
1127
|
-
},
|
|
1128
|
-
computePcbGlobalTransform() {
|
|
1129
|
-
return identity2();
|
|
1130
|
-
}
|
|
1131
|
-
};
|
|
1132
|
-
const container = reconciler.createContainer(
|
|
1133
|
-
// TODO Replace with store like react-three-fiber
|
|
1134
|
-
// https://github.com/pmndrs/react-three-fiber/blob/a457290856f57741bf8beef4f6ff9dbf4879c0a5/packages/fiber/src/core/index.tsx#L172
|
|
1135
|
-
// https://github.com/pmndrs/react-three-fiber/blob/master/packages/fiber/src/core/store.ts#L168
|
|
1136
|
-
rootContainer,
|
|
1137
|
-
0,
|
|
1138
|
-
null,
|
|
1139
|
-
false,
|
|
1140
|
-
null,
|
|
1141
|
-
"tsci",
|
|
1142
|
-
(error) => {
|
|
1143
|
-
console.log("Error in createContainer");
|
|
1144
|
-
console.error(error);
|
|
1145
|
-
},
|
|
1146
|
-
null
|
|
1147
|
-
);
|
|
1148
|
-
reconciler.updateContainer(reactElm, container, null, () => {
|
|
1149
|
-
});
|
|
1150
|
-
const rootInstance = reconciler.getPublicRootInstance(
|
|
1151
|
-
container
|
|
1152
|
-
);
|
|
1153
|
-
if (rootInstance) return rootInstance;
|
|
1154
|
-
return rootContainer.children[0];
|
|
865
|
+
const trace = solution[0];
|
|
866
|
+
if (!trace) {
|
|
867
|
+
this.renderError("Failed to route net islands");
|
|
868
|
+
return;
|
|
869
|
+
}
|
|
870
|
+
db.pcb_trace.insert(trace);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
1155
873
|
};
|
|
1156
874
|
|
|
1157
|
-
// lib/utils/
|
|
1158
|
-
|
|
1159
|
-
const
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
875
|
+
// lib/utils/components/createNetsFromProps.ts
|
|
876
|
+
var createNetsFromProps = (component, props) => {
|
|
877
|
+
for (const prop of props) {
|
|
878
|
+
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
879
|
+
if (!component.getSubcircuit().selectOne(prop)) {
|
|
880
|
+
component.getSubcircuit().add(new Net({ name: prop.split("net.")[1] }));
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
};
|
|
1166
885
|
|
|
1167
886
|
// lib/components/primitive-components/SmtPad.ts
|
|
1168
887
|
import { smtPadProps } from "@tscircuit/props";
|
|
@@ -1301,7 +1020,7 @@ var SmtPad = class extends PrimitiveComponent {
|
|
|
1301
1020
|
|
|
1302
1021
|
// lib/components/primitive-components/SilkscreenPath.ts
|
|
1303
1022
|
import { silkscreenPathProps } from "@tscircuit/props";
|
|
1304
|
-
import { applyToPoint as
|
|
1023
|
+
import { applyToPoint as applyToPoint3 } from "transformation-matrix";
|
|
1305
1024
|
var SilkscreenPath = class extends PrimitiveComponent {
|
|
1306
1025
|
pcb_silkscreen_path_id = null;
|
|
1307
1026
|
get config() {
|
|
@@ -1324,7 +1043,7 @@ var SilkscreenPath = class extends PrimitiveComponent {
|
|
|
1324
1043
|
pcb_component_id: this.parent?.pcb_component_id,
|
|
1325
1044
|
layer,
|
|
1326
1045
|
route: props.route.map((p) => {
|
|
1327
|
-
const transformedPosition =
|
|
1046
|
+
const transformedPosition = applyToPoint3(transform, {
|
|
1328
1047
|
x: p.x,
|
|
1329
1048
|
y: p.y
|
|
1330
1049
|
});
|
|
@@ -1554,208 +1273,485 @@ var createComponentsFromSoup = (soup) => {
|
|
|
1554
1273
|
);
|
|
1555
1274
|
}
|
|
1556
1275
|
}
|
|
1557
|
-
return components;
|
|
1276
|
+
return components;
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1279
|
+
// lib/utils/get-bounds-of-pcb-components.ts
|
|
1280
|
+
function getBoundsOfPcbComponents(components) {
|
|
1281
|
+
let minX = Infinity;
|
|
1282
|
+
let minY = Infinity;
|
|
1283
|
+
let maxX = -Infinity;
|
|
1284
|
+
let maxY = -Infinity;
|
|
1285
|
+
for (const child of components) {
|
|
1286
|
+
if (child.isPcbPrimitive) {
|
|
1287
|
+
const { x, y } = child._getGlobalPcbPositionBeforeLayout();
|
|
1288
|
+
const { width: width2, height: height2 } = child.getPcbSize();
|
|
1289
|
+
minX = Math.min(minX, x - width2 / 2);
|
|
1290
|
+
minY = Math.min(minY, y - height2 / 2);
|
|
1291
|
+
maxX = Math.max(maxX, x + width2 / 2);
|
|
1292
|
+
maxY = Math.max(maxY, y + height2 / 2);
|
|
1293
|
+
} else if (child.componentName === "Footprint") {
|
|
1294
|
+
const childBounds = getBoundsOfPcbComponents(child.children);
|
|
1295
|
+
minX = Math.min(minX, childBounds.minX);
|
|
1296
|
+
minY = Math.min(minY, childBounds.minY);
|
|
1297
|
+
maxX = Math.max(maxX, childBounds.maxX);
|
|
1298
|
+
maxY = Math.max(maxY, childBounds.maxY);
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
let width = maxX - minX;
|
|
1302
|
+
let height = maxY - minY;
|
|
1303
|
+
if (width < 0) width = 0;
|
|
1304
|
+
if (height < 0) height = 0;
|
|
1305
|
+
return {
|
|
1306
|
+
minX,
|
|
1307
|
+
minY,
|
|
1308
|
+
maxX,
|
|
1309
|
+
maxY,
|
|
1310
|
+
width,
|
|
1311
|
+
height
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
// lib/utils/get-relative-direction.ts
|
|
1316
|
+
function getRelativeDirection(pointA, pointB) {
|
|
1317
|
+
const dx = pointB.x - pointA.x;
|
|
1318
|
+
const dy = pointB.y - pointA.y;
|
|
1319
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
1320
|
+
return dx > 0 ? "right" : "left";
|
|
1321
|
+
}
|
|
1322
|
+
return dy > 0 ? "down" : "up";
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// lib/components/primitive-components/Port.ts
|
|
1326
|
+
import "schematic-symbols";
|
|
1327
|
+
import { applyToPoint as applyToPoint4, compose as compose3, translate as translate3 } from "transformation-matrix";
|
|
1328
|
+
import { z as z3 } from "zod";
|
|
1329
|
+
var portProps = z3.object({
|
|
1330
|
+
name: z3.string().optional(),
|
|
1331
|
+
pinNumber: z3.number().optional(),
|
|
1332
|
+
aliases: z3.array(z3.string()).optional()
|
|
1333
|
+
});
|
|
1334
|
+
var Port = class extends PrimitiveComponent {
|
|
1335
|
+
source_port_id = null;
|
|
1336
|
+
pcb_port_id = null;
|
|
1337
|
+
schematic_port_id = null;
|
|
1338
|
+
schematicSymbolPortDef = null;
|
|
1339
|
+
matchedComponents;
|
|
1340
|
+
facingDirection = null;
|
|
1341
|
+
get config() {
|
|
1342
|
+
return {
|
|
1343
|
+
componentName: "Port",
|
|
1344
|
+
zodProps: portProps
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
constructor(props) {
|
|
1348
|
+
if (!props.name && props.pinNumber) props.name = `pin${props.pinNumber}`;
|
|
1349
|
+
if (!props.name) {
|
|
1350
|
+
throw new Error("Port must have a name or a pinNumber");
|
|
1351
|
+
}
|
|
1352
|
+
super(props);
|
|
1353
|
+
this.matchedComponents = [];
|
|
1354
|
+
}
|
|
1355
|
+
_getGlobalPcbPositionBeforeLayout() {
|
|
1356
|
+
const matchedPcbElm = this.matchedComponents.find((c) => c.isPcbPrimitive);
|
|
1357
|
+
if (!matchedPcbElm) {
|
|
1358
|
+
throw new Error(
|
|
1359
|
+
`Port ${this} has no matched pcb component, can't get global schematic position`
|
|
1360
|
+
);
|
|
1361
|
+
}
|
|
1362
|
+
return matchedPcbElm?._getGlobalPcbPositionBeforeLayout() ?? { x: 0, y: 0 };
|
|
1363
|
+
}
|
|
1364
|
+
_getPcbCircuitJsonBounds() {
|
|
1365
|
+
if (!this.pcb_port_id) {
|
|
1366
|
+
return super._getPcbCircuitJsonBounds();
|
|
1367
|
+
}
|
|
1368
|
+
const { db } = this.root;
|
|
1369
|
+
const pcb_port = db.pcb_port.get(this.pcb_port_id);
|
|
1370
|
+
return {
|
|
1371
|
+
center: { x: pcb_port.x, y: pcb_port.y },
|
|
1372
|
+
bounds: { left: 0, top: 0, right: 0, bottom: 0 },
|
|
1373
|
+
width: 0,
|
|
1374
|
+
height: 0
|
|
1375
|
+
};
|
|
1376
|
+
}
|
|
1377
|
+
_getGlobalPcbPositionAfterLayout() {
|
|
1378
|
+
return this._getPcbCircuitJsonBounds().center;
|
|
1379
|
+
}
|
|
1380
|
+
_getGlobalSchematicPositionBeforeLayout() {
|
|
1381
|
+
if (!this.schematicSymbolPortDef) {
|
|
1382
|
+
return applyToPoint4(this.parent.computeSchematicGlobalTransform(), {
|
|
1383
|
+
x: 0,
|
|
1384
|
+
y: 0
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
const symbol = this.parent?.getSchematicSymbol();
|
|
1388
|
+
if (!symbol) {
|
|
1389
|
+
console.warn(`Could not find parent symbol for ${this}`);
|
|
1390
|
+
return { x: 0, y: 0 };
|
|
1391
|
+
}
|
|
1392
|
+
const transform = compose3(
|
|
1393
|
+
this.parent.computeSchematicGlobalTransform(),
|
|
1394
|
+
translate3(-symbol.center.x, -symbol.center.y)
|
|
1395
|
+
);
|
|
1396
|
+
return applyToPoint4(transform, this.schematicSymbolPortDef);
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* Smtpads and platedholes call this method to register themselves as a match
|
|
1400
|
+
* for this port. All the matching is done by primitives other than the Port,
|
|
1401
|
+
* but everyone registers themselves as a match with their Port.
|
|
1402
|
+
*/
|
|
1403
|
+
registerMatch(component) {
|
|
1404
|
+
this.matchedComponents.push(component);
|
|
1405
|
+
}
|
|
1406
|
+
getNameAndAliases() {
|
|
1407
|
+
const { _parsedProps: props } = this;
|
|
1408
|
+
return Array.from(
|
|
1409
|
+
/* @__PURE__ */ new Set([
|
|
1410
|
+
...props.aliases ?? [],
|
|
1411
|
+
props.name,
|
|
1412
|
+
...typeof props.pinNumber === "number" ? [`pin${props.pinNumber}`, props.pinNumber.toString()] : [],
|
|
1413
|
+
...this.externallyAddedAliases
|
|
1414
|
+
])
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
isMatchingPort(port) {
|
|
1418
|
+
return this.isMatchingAnyOf(port.getNameAndAliases());
|
|
1419
|
+
}
|
|
1420
|
+
getPortSelector() {
|
|
1421
|
+
return `.${this.parent?.props.name} > port.${this.props.name}`;
|
|
1422
|
+
}
|
|
1423
|
+
getAvailablePcbLayers() {
|
|
1424
|
+
return Array.from(
|
|
1425
|
+
new Set(this.matchedComponents.flatMap((c) => c.getAvailablePcbLayers()))
|
|
1426
|
+
);
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Return traces that are explicitly connected to this port (not via a net)
|
|
1430
|
+
*/
|
|
1431
|
+
_getDirectlyConnectedTraces() {
|
|
1432
|
+
const allSubcircuitTraces = this.getSubcircuit().selectAll(
|
|
1433
|
+
"trace"
|
|
1434
|
+
);
|
|
1435
|
+
const connectedTraces = allSubcircuitTraces.filter(
|
|
1436
|
+
(trace) => trace._isExplicitlyConnectedToPort(this)
|
|
1437
|
+
);
|
|
1438
|
+
return connectedTraces;
|
|
1439
|
+
}
|
|
1440
|
+
doInitialSourceRender() {
|
|
1441
|
+
const { db } = this.root;
|
|
1442
|
+
const { _parsedProps: props } = this;
|
|
1443
|
+
const port_hints = this.getNameAndAliases();
|
|
1444
|
+
const source_port = db.source_port.insert({
|
|
1445
|
+
name: props.name,
|
|
1446
|
+
pin_number: props.pinNumber,
|
|
1447
|
+
port_hints,
|
|
1448
|
+
source_component_id: this.parent?.source_component_id
|
|
1449
|
+
});
|
|
1450
|
+
this.source_port_id = source_port.source_port_id;
|
|
1451
|
+
}
|
|
1452
|
+
doInitialSourceParentAttachment() {
|
|
1453
|
+
const { db } = this.root;
|
|
1454
|
+
if (!this.parent?.source_component_id) {
|
|
1455
|
+
throw new Error(
|
|
1456
|
+
`${this.getString()} has no parent source component (parent: ${this.parent?.getString()})`
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1459
|
+
db.source_port.update(this.source_port_id, {
|
|
1460
|
+
source_component_id: this.parent?.source_component_id
|
|
1461
|
+
});
|
|
1462
|
+
this.source_component_id = this.parent?.source_component_id;
|
|
1463
|
+
}
|
|
1464
|
+
doInitialPcbPortRender() {
|
|
1465
|
+
const { db } = this.root;
|
|
1466
|
+
const { matchedComponents } = this;
|
|
1467
|
+
if (!this.parent?.pcb_component_id) {
|
|
1468
|
+
throw new Error(
|
|
1469
|
+
`${this.getString()} has no parent pcb component, cannot render pcb_port (parent: ${this.parent?.getString()})`
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
const pcbMatches = matchedComponents.filter((c) => c.isPcbPrimitive);
|
|
1473
|
+
if (pcbMatches.length === 0) return;
|
|
1474
|
+
if (pcbMatches.length > 1) {
|
|
1475
|
+
throw new Error(
|
|
1476
|
+
`${this.getString()} has multiple pcb matches, unclear how to place pcb_port: ${pcbMatches.map((c) => c.getString()).join(", ")}`
|
|
1477
|
+
);
|
|
1478
|
+
}
|
|
1479
|
+
const pcbMatch = pcbMatches[0];
|
|
1480
|
+
if ("_getPcbCircuitJsonBounds" in pcbMatch) {
|
|
1481
|
+
const pcb_port = db.pcb_port.insert({
|
|
1482
|
+
pcb_component_id: this.parent?.pcb_component_id,
|
|
1483
|
+
layers: this.getAvailablePcbLayers(),
|
|
1484
|
+
...pcbMatch._getPcbCircuitJsonBounds().center,
|
|
1485
|
+
source_port_id: this.source_port_id
|
|
1486
|
+
});
|
|
1487
|
+
this.pcb_port_id = pcb_port.pcb_port_id;
|
|
1488
|
+
} else {
|
|
1489
|
+
throw new Error(
|
|
1490
|
+
`${pcbMatch.getString()} does not have a _getGlobalPcbPositionBeforeLayout method (needed for pcb_port placement)`
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
doInitialSchematicPortRender() {
|
|
1495
|
+
const { db } = this.root;
|
|
1496
|
+
const { _parsedProps: props } = this;
|
|
1497
|
+
const container = this.getPrimitiveContainer();
|
|
1498
|
+
if (!container) return;
|
|
1499
|
+
let center = this._getGlobalSchematicPositionBeforeLayout();
|
|
1500
|
+
if ("schematicDimensions" in container && props.pinNumber !== void 0) {
|
|
1501
|
+
const chipDims = container.schematicDimensions;
|
|
1502
|
+
center = chipDims.getPortPositionByPinNumber(props.pinNumber);
|
|
1503
|
+
}
|
|
1504
|
+
const containerCenter = container._getGlobalSchematicPositionBeforeLayout();
|
|
1505
|
+
this.facingDirection = getRelativeDirection(containerCenter, center);
|
|
1506
|
+
const schematic_port = db.schematic_port.insert({
|
|
1507
|
+
schematic_component_id: this.parent?.schematic_component_id,
|
|
1508
|
+
center,
|
|
1509
|
+
source_port_id: this.source_port_id,
|
|
1510
|
+
facing_direction: this.facingDirection
|
|
1511
|
+
});
|
|
1512
|
+
this.schematic_port_id = schematic_port.schematic_port_id;
|
|
1513
|
+
}
|
|
1514
|
+
_setPositionFromLayout(newCenter) {
|
|
1515
|
+
const { db } = this.root;
|
|
1516
|
+
if (!this.pcb_port_id) return;
|
|
1517
|
+
db.pcb_port.update(this.pcb_port_id, {
|
|
1518
|
+
x: newCenter.x,
|
|
1519
|
+
y: newCenter.y
|
|
1520
|
+
});
|
|
1521
|
+
}
|
|
1522
|
+
_hasMatchedPcbPrimitive() {
|
|
1523
|
+
return this.matchedComponents.some((c) => c.isPcbPrimitive);
|
|
1524
|
+
}
|
|
1558
1525
|
};
|
|
1559
1526
|
|
|
1560
|
-
// lib/
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
}
|
|
1569
|
-
return result;
|
|
1527
|
+
// lib/utils/getPortFromHints.ts
|
|
1528
|
+
function getPortFromHints(hints) {
|
|
1529
|
+
const pinNumber = hints.find((p) => /^(pin)?\d+$/.test(p));
|
|
1530
|
+
if (!pinNumber) return null;
|
|
1531
|
+
return new Port({
|
|
1532
|
+
pinNumber: Number.parseInt(pinNumber.replace(/^pin/, "")),
|
|
1533
|
+
aliases: hints.filter((p) => p !== pinNumber)
|
|
1534
|
+
});
|
|
1570
1535
|
}
|
|
1571
1536
|
|
|
1572
|
-
// lib/components/
|
|
1573
|
-
import {
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
}
|
|
1577
|
-
|
|
1578
|
-
|
|
1537
|
+
// lib/components/base-components/NormalComponent.ts
|
|
1538
|
+
import {
|
|
1539
|
+
isValidElement as isReactElement2,
|
|
1540
|
+
isValidElement
|
|
1541
|
+
} from "react";
|
|
1542
|
+
import { symbols as symbols2 } from "schematic-symbols";
|
|
1543
|
+
import { z as z4 } from "zod";
|
|
1544
|
+
|
|
1545
|
+
// lib/components/primitive-components/Footprint.ts
|
|
1546
|
+
import { footprintProps } from "@tscircuit/props";
|
|
1547
|
+
import * as kiwi from "@lume/kiwi";
|
|
1548
|
+
import Debug from "debug";
|
|
1549
|
+
var debug = Debug("tscircuit:core:footprint");
|
|
1550
|
+
var Footprint = class extends PrimitiveComponent {
|
|
1579
1551
|
get config() {
|
|
1580
1552
|
return {
|
|
1581
|
-
componentName: "
|
|
1582
|
-
zodProps:
|
|
1553
|
+
componentName: "Footprint",
|
|
1554
|
+
zodProps: footprintProps
|
|
1583
1555
|
};
|
|
1584
1556
|
}
|
|
1585
|
-
getPortSelector() {
|
|
1586
|
-
return `net.${this.props.name}`;
|
|
1587
|
-
}
|
|
1588
|
-
doInitialSourceRender() {
|
|
1589
|
-
const { db } = this.root;
|
|
1590
|
-
const { _parsedProps: props } = this;
|
|
1591
|
-
const net = db.source_net.insert({
|
|
1592
|
-
name: props.name,
|
|
1593
|
-
member_source_group_ids: []
|
|
1594
|
-
});
|
|
1595
|
-
this.source_net_id = net.source_net_id;
|
|
1596
|
-
}
|
|
1597
1557
|
/**
|
|
1598
|
-
*
|
|
1599
|
-
*
|
|
1600
|
-
* TODO currently we're not checking for indirect connections (traces that are
|
|
1601
|
-
* connected to other traces that are in turn connected to the net)
|
|
1558
|
+
* A footprint is a constrainedlayout, the db elements are adjusted according
|
|
1559
|
+
* to any constraints that are defined.
|
|
1602
1560
|
*/
|
|
1603
|
-
|
|
1604
|
-
const
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1561
|
+
doInitialPcbFootprintLayout() {
|
|
1562
|
+
const constraints = this.children.filter(
|
|
1563
|
+
(child) => child.componentName === "Constraint"
|
|
1564
|
+
);
|
|
1565
|
+
if (constraints.length === 0) return;
|
|
1566
|
+
const { isFlipped } = this._getPcbPrimitiveFlippedHelpers();
|
|
1567
|
+
const maybeFlipLeftRight = (props) => {
|
|
1568
|
+
if (isFlipped) {
|
|
1569
|
+
if ("left" in props && "right" in props) {
|
|
1570
|
+
return {
|
|
1571
|
+
...props,
|
|
1572
|
+
left: props.right,
|
|
1573
|
+
right: props.left
|
|
1574
|
+
};
|
|
1612
1575
|
}
|
|
1613
1576
|
}
|
|
1577
|
+
return props;
|
|
1578
|
+
};
|
|
1579
|
+
const involvedComponents = constraints.flatMap(
|
|
1580
|
+
(constraint) => constraint._getAllReferencedComponents().componentsWithSelectors
|
|
1581
|
+
).map(({ component, selector, componentSelector, edge }) => ({
|
|
1582
|
+
component,
|
|
1583
|
+
selector,
|
|
1584
|
+
componentSelector,
|
|
1585
|
+
edge,
|
|
1586
|
+
bounds: component._getPcbCircuitJsonBounds()
|
|
1587
|
+
}));
|
|
1588
|
+
if (involvedComponents.some((c) => c.edge)) {
|
|
1589
|
+
throw new Error(
|
|
1590
|
+
"edge constraints not implemented yet for footprint layout, contributions welcome!"
|
|
1591
|
+
);
|
|
1614
1592
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
/**
|
|
1618
|
-
* Get all traces that are directly connected to this net, i.e. they list
|
|
1619
|
-
* this net in their path, from, or to props
|
|
1620
|
-
*/
|
|
1621
|
-
_getAllDirectlyConnectedTraces() {
|
|
1622
|
-
const allTraces = this.getSubcircuit().selectAll("trace");
|
|
1623
|
-
const connectedTraces = [];
|
|
1624
|
-
for (const trace of allTraces) {
|
|
1625
|
-
if (trace._isExplicitlyConnectedToNet(this)) {
|
|
1626
|
-
connectedTraces.push(trace);
|
|
1627
|
-
}
|
|
1593
|
+
function getComponentDetails(selector) {
|
|
1594
|
+
return involvedComponents.find(({ selector: s }) => s === selector);
|
|
1628
1595
|
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
* such that the nets are fully connected
|
|
1636
|
-
*/
|
|
1637
|
-
doInitialPcbRouteNetIslands() {
|
|
1638
|
-
const { db } = this.root;
|
|
1639
|
-
const { _parsedProps: props } = this;
|
|
1640
|
-
const traces = this._getAllDirectlyConnectedTraces().filter(
|
|
1641
|
-
(trace) => (trace._portsRoutedOnPcb?.length ?? 0) > 0
|
|
1642
|
-
);
|
|
1643
|
-
const islands = [];
|
|
1644
|
-
for (const trace of traces) {
|
|
1645
|
-
const tracePorts = trace._portsRoutedOnPcb;
|
|
1646
|
-
const traceIsland = islands.find(
|
|
1647
|
-
(island) => tracePorts.some((port) => island.ports.includes(port))
|
|
1648
|
-
);
|
|
1649
|
-
if (!traceIsland) {
|
|
1650
|
-
islands.push({ ports: [...tracePorts], traces: [trace] });
|
|
1651
|
-
continue;
|
|
1596
|
+
const solver = new kiwi.Solver();
|
|
1597
|
+
const kVars = {};
|
|
1598
|
+
function getKVar(name) {
|
|
1599
|
+
if (!(name in kVars)) {
|
|
1600
|
+
kVars[name] = new kiwi.Variable(name);
|
|
1601
|
+
solver.addEditVariable(kVars[name], kiwi.Strength.weak);
|
|
1652
1602
|
}
|
|
1653
|
-
|
|
1654
|
-
traceIsland.ports.push(...tracePorts);
|
|
1603
|
+
return kVars[name];
|
|
1655
1604
|
}
|
|
1656
|
-
|
|
1657
|
-
|
|
1605
|
+
for (const { selector, bounds: bounds2 } of involvedComponents) {
|
|
1606
|
+
const kvx = getKVar(`${selector}_x`);
|
|
1607
|
+
const kvy = getKVar(`${selector}_y`);
|
|
1608
|
+
solver.suggestValue(kvx, bounds2.center.x);
|
|
1609
|
+
solver.suggestValue(kvy, bounds2.center.y);
|
|
1658
1610
|
}
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1611
|
+
for (const constraint of constraints) {
|
|
1612
|
+
const props = constraint._parsedProps;
|
|
1613
|
+
if ("xDist" in props) {
|
|
1614
|
+
const { xDist, left, right, edgeToEdge, centerToCenter } = maybeFlipLeftRight(props);
|
|
1615
|
+
const leftVar = getKVar(`${left}_x`);
|
|
1616
|
+
const rightVar = getKVar(`${right}_x`);
|
|
1617
|
+
const leftBounds = getComponentDetails(left)?.bounds;
|
|
1618
|
+
const rightBounds = getComponentDetails(right)?.bounds;
|
|
1619
|
+
if (centerToCenter) {
|
|
1620
|
+
const expr = new kiwi.Expression(rightVar, [-1, leftVar]);
|
|
1621
|
+
solver.addConstraint(
|
|
1622
|
+
new kiwi.Constraint(
|
|
1623
|
+
expr,
|
|
1624
|
+
kiwi.Operator.Eq,
|
|
1625
|
+
props.xDist,
|
|
1626
|
+
kiwi.Strength.required
|
|
1627
|
+
)
|
|
1628
|
+
);
|
|
1629
|
+
} else if (edgeToEdge) {
|
|
1630
|
+
const expr = new kiwi.Expression(
|
|
1631
|
+
rightVar,
|
|
1632
|
+
-rightBounds.width / 2,
|
|
1633
|
+
[-1, leftVar],
|
|
1634
|
+
-leftBounds.width / 2
|
|
1635
|
+
);
|
|
1636
|
+
solver.addConstraint(
|
|
1637
|
+
new kiwi.Constraint(
|
|
1638
|
+
expr,
|
|
1639
|
+
kiwi.Operator.Eq,
|
|
1640
|
+
props.xDist,
|
|
1641
|
+
kiwi.Strength.required
|
|
1642
|
+
)
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
} else if ("yDist" in props) {
|
|
1646
|
+
const { yDist, top, bottom, edgeToEdge, centerToCenter } = props;
|
|
1647
|
+
const topVar = getKVar(`${top}_y`);
|
|
1648
|
+
const bottomVar = getKVar(`${bottom}_y`);
|
|
1649
|
+
const topBounds = getComponentDetails(top)?.bounds;
|
|
1650
|
+
const bottomBounds = getComponentDetails(bottom)?.bounds;
|
|
1651
|
+
if (centerToCenter) {
|
|
1652
|
+
const expr = new kiwi.Expression(topVar, [-1, bottomVar]);
|
|
1653
|
+
solver.addConstraint(
|
|
1654
|
+
new kiwi.Constraint(
|
|
1655
|
+
expr,
|
|
1656
|
+
kiwi.Operator.Eq,
|
|
1657
|
+
props.yDist,
|
|
1658
|
+
kiwi.Strength.required
|
|
1659
|
+
)
|
|
1660
|
+
);
|
|
1661
|
+
} else if (edgeToEdge) {
|
|
1662
|
+
const expr = new kiwi.Expression(
|
|
1663
|
+
topVar,
|
|
1664
|
+
topBounds.height / 2,
|
|
1665
|
+
[-1, bottomVar],
|
|
1666
|
+
-bottomBounds.height / 2
|
|
1667
|
+
);
|
|
1668
|
+
solver.addConstraint(
|
|
1669
|
+
new kiwi.Constraint(
|
|
1670
|
+
expr,
|
|
1671
|
+
kiwi.Operator.Eq,
|
|
1672
|
+
props.yDist,
|
|
1673
|
+
kiwi.Strength.required
|
|
1674
|
+
)
|
|
1675
1675
|
);
|
|
1676
|
-
if (dist < closestDist) {
|
|
1677
|
-
closestDist = dist;
|
|
1678
|
-
closestPair = [i, j];
|
|
1679
|
-
}
|
|
1680
1676
|
}
|
|
1677
|
+
} else if ("sameY" in props) {
|
|
1678
|
+
const { for: selectors } = props;
|
|
1679
|
+
if (selectors.length < 2) continue;
|
|
1680
|
+
const vars = selectors.map((selector) => getKVar(`${selector}_y`));
|
|
1681
|
+
const expr = new kiwi.Expression(...vars.slice(1));
|
|
1682
|
+
solver.addConstraint(
|
|
1683
|
+
new kiwi.Constraint(
|
|
1684
|
+
expr,
|
|
1685
|
+
kiwi.Operator.Eq,
|
|
1686
|
+
vars[0],
|
|
1687
|
+
kiwi.Strength.required
|
|
1688
|
+
)
|
|
1689
|
+
);
|
|
1690
|
+
} else if ("sameX" in props) {
|
|
1691
|
+
const { for: selectors } = props;
|
|
1692
|
+
if (selectors.length < 2) continue;
|
|
1693
|
+
const vars = selectors.map((selector) => getKVar(`${selector}_x`));
|
|
1694
|
+
const expr = new kiwi.Expression(...vars.slice(1));
|
|
1695
|
+
solver.addConstraint(
|
|
1696
|
+
new kiwi.Constraint(
|
|
1697
|
+
expr,
|
|
1698
|
+
kiwi.Operator.Eq,
|
|
1699
|
+
vars[0],
|
|
1700
|
+
kiwi.Strength.required
|
|
1701
|
+
)
|
|
1702
|
+
);
|
|
1681
1703
|
}
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
source_trace_id: "__net_trace_tmp",
|
|
1692
|
-
connected_source_port_ids: [
|
|
1693
|
-
Aport.source_port_id,
|
|
1694
|
-
Bport.source_port_id
|
|
1695
|
-
]
|
|
1696
|
-
}
|
|
1697
|
-
])
|
|
1698
|
-
// Remove as any when autorouting-dataset has been updated
|
|
1704
|
+
}
|
|
1705
|
+
solver.updateVariables();
|
|
1706
|
+
if (debug.enabled) {
|
|
1707
|
+
console.log("Solution to layout constraints:");
|
|
1708
|
+
console.table(
|
|
1709
|
+
Object.entries(kVars).map(([key, kvar]) => ({
|
|
1710
|
+
var: key,
|
|
1711
|
+
val: kvar.value()
|
|
1712
|
+
}))
|
|
1699
1713
|
);
|
|
1700
|
-
const trace = solution[0];
|
|
1701
|
-
if (!trace) {
|
|
1702
|
-
this.renderError("Failed to route net islands");
|
|
1703
|
-
return;
|
|
1704
|
-
}
|
|
1705
|
-
db.pcb_trace.insert(trace);
|
|
1706
1714
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1715
|
+
const bounds = {
|
|
1716
|
+
left: Infinity,
|
|
1717
|
+
right: -Infinity,
|
|
1718
|
+
top: -Infinity,
|
|
1719
|
+
bottom: Infinity
|
|
1720
|
+
};
|
|
1721
|
+
for (const {
|
|
1722
|
+
selector,
|
|
1723
|
+
bounds: { width, height }
|
|
1724
|
+
} of involvedComponents) {
|
|
1725
|
+
const kvx = getKVar(`${selector}_x`);
|
|
1726
|
+
const kvy = getKVar(`${selector}_y`);
|
|
1727
|
+
const newLeft = kvx.value() - width / 2;
|
|
1728
|
+
const newRight = kvx.value() + width / 2;
|
|
1729
|
+
const newTop = kvy.value() + height / 2;
|
|
1730
|
+
const newBottom = kvy.value() - height / 2;
|
|
1731
|
+
bounds.left = Math.min(bounds.left, newLeft);
|
|
1732
|
+
bounds.right = Math.max(bounds.right, newRight);
|
|
1733
|
+
bounds.top = Math.max(bounds.top, newTop);
|
|
1734
|
+
bounds.bottom = Math.min(bounds.bottom, newBottom);
|
|
1717
1735
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
minY = Math.min(minY, y - height2 / 2);
|
|
1733
|
-
maxX = Math.max(maxX, x + width2 / 2);
|
|
1734
|
-
maxY = Math.max(maxY, y + height2 / 2);
|
|
1735
|
-
} else if (child.componentName === "Footprint") {
|
|
1736
|
-
const childBounds = getBoundsOfPcbComponents(child.children);
|
|
1737
|
-
minX = Math.min(minX, childBounds.minX);
|
|
1738
|
-
minY = Math.min(minY, childBounds.minY);
|
|
1739
|
-
maxX = Math.max(maxX, childBounds.maxX);
|
|
1740
|
-
maxY = Math.max(maxY, childBounds.maxY);
|
|
1736
|
+
const globalOffset = {
|
|
1737
|
+
x: -(bounds.right + bounds.left) / 2,
|
|
1738
|
+
y: -(bounds.top + bounds.bottom) / 2
|
|
1739
|
+
};
|
|
1740
|
+
const containerPos = this.getPrimitiveContainer()._getGlobalPcbPositionBeforeLayout();
|
|
1741
|
+
globalOffset.x += containerPos.x;
|
|
1742
|
+
globalOffset.y += containerPos.y;
|
|
1743
|
+
for (const { component, selector } of involvedComponents) {
|
|
1744
|
+
const kvx = getKVar(`${selector}_x`);
|
|
1745
|
+
const kvy = getKVar(`${selector}_y`);
|
|
1746
|
+
component._setPositionFromLayout({
|
|
1747
|
+
x: kvx.value() + globalOffset.x,
|
|
1748
|
+
y: kvy.value() + globalOffset.y
|
|
1749
|
+
});
|
|
1741
1750
|
}
|
|
1742
1751
|
}
|
|
1743
|
-
|
|
1744
|
-
let height = maxY - minY;
|
|
1745
|
-
if (width < 0) width = 0;
|
|
1746
|
-
if (height < 0) height = 0;
|
|
1747
|
-
return {
|
|
1748
|
-
minX,
|
|
1749
|
-
minY,
|
|
1750
|
-
maxX,
|
|
1751
|
-
maxY,
|
|
1752
|
-
width,
|
|
1753
|
-
height
|
|
1754
|
-
};
|
|
1755
|
-
}
|
|
1752
|
+
};
|
|
1756
1753
|
|
|
1757
1754
|
// lib/components/base-components/NormalComponent.ts
|
|
1758
|
-
import { rotation } from "circuit-json";
|
|
1759
1755
|
var rotation3 = z4.object({
|
|
1760
1756
|
x: rotation,
|
|
1761
1757
|
y: rotation,
|
|
@@ -1786,6 +1782,36 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1786
1782
|
initPorts() {
|
|
1787
1783
|
const { config } = this;
|
|
1788
1784
|
const portsToCreate = [];
|
|
1785
|
+
const schPortArrangement = this._parsedProps.schPortArrangement;
|
|
1786
|
+
if (schPortArrangement) {
|
|
1787
|
+
for (const side in schPortArrangement) {
|
|
1788
|
+
const pins = schPortArrangement[side].pins;
|
|
1789
|
+
if (Array.isArray(pins)) {
|
|
1790
|
+
for (const pinNumber of pins) {
|
|
1791
|
+
portsToCreate.push(new Port({ pinNumber }));
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
const pinLabels = this._parsedProps.pinLabels;
|
|
1797
|
+
if (pinLabels) {
|
|
1798
|
+
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
1799
|
+
pinNumber = pinNumber.replace("pin", "");
|
|
1800
|
+
let existingPort = portsToCreate.find(
|
|
1801
|
+
(p) => p._parsedProps.pinNumber === Number(pinNumber)
|
|
1802
|
+
);
|
|
1803
|
+
if (!existingPort) {
|
|
1804
|
+
existingPort = new Port({
|
|
1805
|
+
pinNumber: parseInt(pinNumber),
|
|
1806
|
+
name: label
|
|
1807
|
+
});
|
|
1808
|
+
portsToCreate.push(existingPort);
|
|
1809
|
+
} else {
|
|
1810
|
+
existingPort.externallyAddedAliases.push(label);
|
|
1811
|
+
existingPort.props.name = label;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1789
1815
|
if (config.schematicSymbolName) {
|
|
1790
1816
|
const sym = symbols2[`${config.schematicSymbolName}_horz`];
|
|
1791
1817
|
if (!sym) return;
|
|
@@ -1800,21 +1826,9 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1800
1826
|
return;
|
|
1801
1827
|
}
|
|
1802
1828
|
const portsFromFootprint = this.getPortsFromFootprint();
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
for (let [pinNumber, label] of Object.entries(pinLabels)) {
|
|
1807
|
-
pinNumber = pinNumber.replace("pin", "");
|
|
1808
|
-
const existingPort = portsToCreate.find(
|
|
1809
|
-
(p) => p._parsedProps.pinNumber === Number(pinNumber)
|
|
1810
|
-
);
|
|
1811
|
-
if (!existingPort) {
|
|
1812
|
-
throw new Error(
|
|
1813
|
-
`Could not find port for pin number ${pinNumber} in chip ${this.getString()}`
|
|
1814
|
-
);
|
|
1815
|
-
}
|
|
1816
|
-
existingPort.externallyAddedAliases.push(label);
|
|
1817
|
-
existingPort.props.name = label;
|
|
1829
|
+
for (const port of portsFromFootprint) {
|
|
1830
|
+
if (!portsToCreate.some((p) => p.isMatchingAnyOf(port.getNameAndAliases()))) {
|
|
1831
|
+
portsToCreate.push(port);
|
|
1818
1832
|
}
|
|
1819
1833
|
}
|
|
1820
1834
|
if (portsToCreate.length > 0) {
|
|
@@ -2996,20 +3010,27 @@ var FTYPE = stringProxy;
|
|
|
2996
3010
|
|
|
2997
3011
|
// lib/components/normal-components/Diode.ts
|
|
2998
3012
|
var Diode = class extends NormalComponent {
|
|
2999
|
-
|
|
3000
|
-
pin2 = this.portMap.pin2;
|
|
3013
|
+
// @ts-ignore
|
|
3001
3014
|
get config() {
|
|
3002
3015
|
return {
|
|
3003
|
-
|
|
3016
|
+
schematicSymbolName: this.props.symbolName ?? "diode_horz",
|
|
3004
3017
|
componentName: "Diode",
|
|
3005
3018
|
zodProps: diodeProps,
|
|
3006
3019
|
sourceFtype: "simple_diode"
|
|
3007
3020
|
};
|
|
3008
3021
|
}
|
|
3009
3022
|
initPorts() {
|
|
3010
|
-
this.add(
|
|
3011
|
-
|
|
3023
|
+
this.add(
|
|
3024
|
+
new Port({ name: "pin1", pinNumber: 1, aliases: ["anode", "pos"] })
|
|
3025
|
+
);
|
|
3026
|
+
this.add(
|
|
3027
|
+
new Port({ name: "pin2", pinNumber: 2, aliases: ["cathode", "neg"] })
|
|
3028
|
+
);
|
|
3012
3029
|
}
|
|
3030
|
+
pos = this.portMap.pin1;
|
|
3031
|
+
anode = this.portMap.pin1;
|
|
3032
|
+
neg = this.portMap.pin2;
|
|
3033
|
+
cathode = this.portMap.pin2;
|
|
3013
3034
|
};
|
|
3014
3035
|
|
|
3015
3036
|
// lib/components/normal-components/Capacitor.ts
|
|
@@ -3068,8 +3089,52 @@ var Capacitor = class extends NormalComponent {
|
|
|
3068
3089
|
// lib/components/normal-components/Chip.ts
|
|
3069
3090
|
import { chipProps } from "@tscircuit/props";
|
|
3070
3091
|
|
|
3071
|
-
// lib/
|
|
3092
|
+
// lib/soup/underscorifyPinStyles.ts
|
|
3072
3093
|
import "circuit-json";
|
|
3094
|
+
import "zod";
|
|
3095
|
+
var underscorifyPinStyles = (pinStyles) => {
|
|
3096
|
+
if (!pinStyles) return void 0;
|
|
3097
|
+
const underscorePinStyles = {};
|
|
3098
|
+
for (const [pinName, pinStyle] of Object.entries(pinStyles)) {
|
|
3099
|
+
underscorePinStyles[pinName] = {
|
|
3100
|
+
bottom_margin: pinStyle.bottomMargin,
|
|
3101
|
+
left_margin: pinStyle.leftMargin,
|
|
3102
|
+
right_margin: pinStyle.rightMargin,
|
|
3103
|
+
top_margin: pinStyle.topMargin
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3106
|
+
return underscorePinStyles;
|
|
3107
|
+
};
|
|
3108
|
+
|
|
3109
|
+
// lib/soup/underscorifyPortArrangement.ts
|
|
3110
|
+
var underscorifyPortArrangement = (portArrangement) => {
|
|
3111
|
+
if (!portArrangement) return void 0;
|
|
3112
|
+
if ("leftSide" in portArrangement || "rightSide" in portArrangement || "topSide" in portArrangement || "bottomSide" in portArrangement) {
|
|
3113
|
+
return {
|
|
3114
|
+
left_side: portArrangement.leftSide,
|
|
3115
|
+
right_side: portArrangement.rightSide,
|
|
3116
|
+
top_side: portArrangement.topSide,
|
|
3117
|
+
bottom_side: portArrangement.bottomSide
|
|
3118
|
+
};
|
|
3119
|
+
}
|
|
3120
|
+
if ("leftPinCount" in portArrangement || "rightPinCount" in portArrangement || "topPinCount" in portArrangement || "bottomPinCount" in portArrangement) {
|
|
3121
|
+
return {
|
|
3122
|
+
left_size: portArrangement.leftPinCount,
|
|
3123
|
+
right_size: portArrangement.rightPinCount,
|
|
3124
|
+
top_size: portArrangement.topPinCount,
|
|
3125
|
+
bottom_size: portArrangement.bottomPinCount
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
if ("leftSize" in portArrangement || "rightSize" in portArrangement || "topSize" in portArrangement || "bottomSize" in portArrangement) {
|
|
3129
|
+
return {
|
|
3130
|
+
left_size: portArrangement.leftSize,
|
|
3131
|
+
right_size: portArrangement.rightSize,
|
|
3132
|
+
top_size: portArrangement.topSize,
|
|
3133
|
+
bottom_size: portArrangement.bottomSize
|
|
3134
|
+
};
|
|
3135
|
+
}
|
|
3136
|
+
return void 0;
|
|
3137
|
+
};
|
|
3073
3138
|
|
|
3074
3139
|
// lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts
|
|
3075
3140
|
var hasExplicitPinMapping = (pa) => {
|
|
@@ -3101,8 +3166,9 @@ var getSizeOfSidesFromPortArrangement = (pa) => {
|
|
|
3101
3166
|
};
|
|
3102
3167
|
|
|
3103
3168
|
// lib/utils/schematic/getAllDimensionsForSchematicBox.ts
|
|
3104
|
-
|
|
3105
|
-
|
|
3169
|
+
function isExplicitPinMappingArrangement(arrangement) {
|
|
3170
|
+
return arrangement.leftSide !== void 0;
|
|
3171
|
+
}
|
|
3106
3172
|
var getAllDimensionsForSchematicBox = (params) => {
|
|
3107
3173
|
const portDistanceFromEdge = params.portDistanceFromEdge ?? params.schPinSpacing * 2;
|
|
3108
3174
|
let sidePinCounts = params.schPortArrangement ? getSizeOfSidesFromPortArrangement(params.schPortArrangement) : null;
|
|
@@ -3141,7 +3207,7 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3141
3207
|
let currentDistanceFromEdge = 0;
|
|
3142
3208
|
let truePinIndex = 0;
|
|
3143
3209
|
for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) {
|
|
3144
|
-
const pinNumber = truePinIndex + 1;
|
|
3210
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement?.leftSide?.pins[sideIndex] : truePinIndex + 1;
|
|
3145
3211
|
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
3146
3212
|
if (pinStyle?.topMargin) {
|
|
3147
3213
|
currentDistanceFromEdge += pinStyle.topMargin;
|
|
@@ -3165,7 +3231,7 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3165
3231
|
}
|
|
3166
3232
|
currentDistanceFromEdge = 0;
|
|
3167
3233
|
for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) {
|
|
3168
|
-
const pinNumber = truePinIndex + 1;
|
|
3234
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.bottomSide?.pins[sideIndex] : truePinIndex + 1;
|
|
3169
3235
|
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
3170
3236
|
if (pinStyle?.leftMargin) {
|
|
3171
3237
|
currentDistanceFromEdge += pinStyle.leftMargin;
|
|
@@ -3189,7 +3255,7 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3189
3255
|
}
|
|
3190
3256
|
currentDistanceFromEdge = 0;
|
|
3191
3257
|
for (let sideIndex = 0; sideIndex < sidePinCounts.rightSize; sideIndex++) {
|
|
3192
|
-
const pinNumber = truePinIndex + 1;
|
|
3258
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.rightSide?.pins[sideIndex] : truePinIndex + 1;
|
|
3193
3259
|
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
3194
3260
|
if (pinStyle?.bottomMargin) {
|
|
3195
3261
|
currentDistanceFromEdge += pinStyle.bottomMargin;
|
|
@@ -3213,7 +3279,7 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3213
3279
|
}
|
|
3214
3280
|
currentDistanceFromEdge = 0;
|
|
3215
3281
|
for (let sideIndex = 0; sideIndex < sidePinCounts.topSize; sideIndex++) {
|
|
3216
|
-
const pinNumber = truePinIndex + 1;
|
|
3282
|
+
const pinNumber = params.schPortArrangement && isExplicitPinMappingArrangement(params.schPortArrangement) ? params.schPortArrangement.topSide?.pins[sideIndex] : truePinIndex + 1;
|
|
3217
3283
|
const pinStyle = params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber];
|
|
3218
3284
|
if (pinStyle?.rightMargin) {
|
|
3219
3285
|
currentDistanceFromEdge += pinStyle.rightMargin;
|
|
@@ -3293,9 +3359,7 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3293
3359
|
(p) => p.pinNumber.toString() === pinNumber.toString()
|
|
3294
3360
|
);
|
|
3295
3361
|
if (!port) {
|
|
3296
|
-
|
|
3297
|
-
`Could not find port for pin number ${pinNumber}, available pins: ${truePortsWithPositions.map((tp) => tp.pinNumber).join(", ")}`
|
|
3298
|
-
);
|
|
3362
|
+
return { x: 0, y: 0 };
|
|
3299
3363
|
}
|
|
3300
3364
|
return port;
|
|
3301
3365
|
},
|
|
@@ -3306,53 +3370,6 @@ var getAllDimensionsForSchematicBox = (params) => {
|
|
|
3306
3370
|
};
|
|
3307
3371
|
};
|
|
3308
3372
|
|
|
3309
|
-
// lib/soup/underscorifyPortArrangement.ts
|
|
3310
|
-
var underscorifyPortArrangement = (portArrangement) => {
|
|
3311
|
-
if (!portArrangement) return void 0;
|
|
3312
|
-
if ("leftSide" in portArrangement || "rightSide" in portArrangement || "topSide" in portArrangement || "bottomSide" in portArrangement) {
|
|
3313
|
-
return {
|
|
3314
|
-
left_side: portArrangement.leftSide,
|
|
3315
|
-
right_side: portArrangement.rightSide,
|
|
3316
|
-
top_side: portArrangement.topSide,
|
|
3317
|
-
bottom_side: portArrangement.bottomSide
|
|
3318
|
-
};
|
|
3319
|
-
}
|
|
3320
|
-
if ("leftPinCount" in portArrangement || "rightPinCount" in portArrangement || "topPinCount" in portArrangement || "bottomPinCount" in portArrangement) {
|
|
3321
|
-
return {
|
|
3322
|
-
left_size: portArrangement.leftPinCount,
|
|
3323
|
-
right_size: portArrangement.rightPinCount,
|
|
3324
|
-
top_size: portArrangement.topPinCount,
|
|
3325
|
-
bottom_size: portArrangement.bottomPinCount
|
|
3326
|
-
};
|
|
3327
|
-
}
|
|
3328
|
-
if ("leftSize" in portArrangement || "rightSize" in portArrangement || "topSize" in portArrangement || "bottomSize" in portArrangement) {
|
|
3329
|
-
return {
|
|
3330
|
-
left_size: portArrangement.leftSize,
|
|
3331
|
-
right_size: portArrangement.rightSize,
|
|
3332
|
-
top_size: portArrangement.topSize,
|
|
3333
|
-
bottom_size: portArrangement.bottomSize
|
|
3334
|
-
};
|
|
3335
|
-
}
|
|
3336
|
-
return void 0;
|
|
3337
|
-
};
|
|
3338
|
-
|
|
3339
|
-
// lib/soup/underscorifyPinStyles.ts
|
|
3340
|
-
import "circuit-json";
|
|
3341
|
-
import "zod";
|
|
3342
|
-
var underscorifyPinStyles = (pinStyles) => {
|
|
3343
|
-
if (!pinStyles) return void 0;
|
|
3344
|
-
const underscorePinStyles = {};
|
|
3345
|
-
for (const [pinName, pinStyle] of Object.entries(pinStyles)) {
|
|
3346
|
-
underscorePinStyles[pinName] = {
|
|
3347
|
-
bottom_margin: pinStyle.bottomMargin,
|
|
3348
|
-
left_margin: pinStyle.leftMargin,
|
|
3349
|
-
right_margin: pinStyle.rightMargin,
|
|
3350
|
-
top_margin: pinStyle.topMargin
|
|
3351
|
-
};
|
|
3352
|
-
}
|
|
3353
|
-
return underscorePinStyles;
|
|
3354
|
-
};
|
|
3355
|
-
|
|
3356
3373
|
// lib/components/normal-components/Chip.ts
|
|
3357
3374
|
var Chip = class extends NormalComponent {
|
|
3358
3375
|
schematicDimensions = null;
|