@tscircuit/core 0.0.24 → 0.0.26
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 +14 -4
- package/dist/index.js +70 -52
- package/lib/components/base-components/NormalComponent.ts +2 -11
- package/lib/components/primitive-components/Trace.ts +81 -50
- package/lib/utils/autorouting/findPossibleTraceLayerCombinations.ts +1 -1
- package/lib/utils/autorouting/mergeRoutes.ts +1 -0
- package/lib/utils/components/createNetsFromProps.ts +15 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -401,10 +401,19 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
401
401
|
ports?: undefined;
|
|
402
402
|
portsWithSelectors?: undefined;
|
|
403
403
|
};
|
|
404
|
-
_findConnectedNets():
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
404
|
+
_findConnectedNets(): {
|
|
405
|
+
nets: Net[];
|
|
406
|
+
netsWithSelectors: Array<{
|
|
407
|
+
selector: string;
|
|
408
|
+
net: Net;
|
|
409
|
+
}>;
|
|
410
|
+
};
|
|
411
|
+
/**
|
|
412
|
+
* Get all the traces that are connected in any degree to this trace, this is
|
|
413
|
+
* used during autorouting to routes to pass through traces connected to the
|
|
414
|
+
* same net.
|
|
415
|
+
*/
|
|
416
|
+
_getAllTracesConnectedToSameNet(): Trace[];
|
|
408
417
|
/**
|
|
409
418
|
* Determine if a trace is explicitly connected to a port (not via a net)
|
|
410
419
|
*/
|
|
@@ -413,6 +422,7 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
413
422
|
* Determine if a trace is explicitly connected to a net (not via a port)
|
|
414
423
|
*/
|
|
415
424
|
_isExplicitlyConnectedToNet(net: Net): boolean;
|
|
425
|
+
doInitialCreateNetsFromProps(): void;
|
|
416
426
|
doInitialSourceTraceRender(): void;
|
|
417
427
|
doInitialPcbTraceRender(): void;
|
|
418
428
|
doInitialSchematicTraceRender(): void;
|
package/dist/index.js
CHANGED
|
@@ -1143,6 +1143,17 @@ var Net = class extends PrimitiveComponent {
|
|
|
1143
1143
|
}
|
|
1144
1144
|
};
|
|
1145
1145
|
|
|
1146
|
+
// lib/utils/components/createNetsFromProps.ts
|
|
1147
|
+
var createNetsFromProps = (component, props) => {
|
|
1148
|
+
for (const prop of props) {
|
|
1149
|
+
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
1150
|
+
if (!component.getSubcircuit().selectOne(prop)) {
|
|
1151
|
+
component.getSubcircuit().add(new Net({ name: prop.split("net.")[1] }));
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1146
1157
|
// lib/components/base-components/NormalComponent.ts
|
|
1147
1158
|
var NormalComponent = class extends PrimitiveComponent {
|
|
1148
1159
|
reactSubtrees = [];
|
|
@@ -1365,17 +1376,7 @@ var NormalComponent = class extends PrimitiveComponent {
|
|
|
1365
1376
|
return newPorts;
|
|
1366
1377
|
}
|
|
1367
1378
|
_createNetsFromProps(propsWithConnections) {
|
|
1368
|
-
|
|
1369
|
-
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
1370
|
-
if (!this.getSubcircuit().selectOne(prop)) {
|
|
1371
|
-
this.getSubcircuit().add(
|
|
1372
|
-
new Net({
|
|
1373
|
-
name: prop.split(".")[1]
|
|
1374
|
-
})
|
|
1375
|
-
);
|
|
1376
|
-
}
|
|
1377
|
-
}
|
|
1378
|
-
}
|
|
1379
|
+
createNetsFromProps(this, propsWithConnections);
|
|
1379
1380
|
}
|
|
1380
1381
|
/**
|
|
1381
1382
|
* Use data from our props to create ports for this component.
|
|
@@ -1469,7 +1470,6 @@ import "zod";
|
|
|
1469
1470
|
import { traceProps } from "@tscircuit/props";
|
|
1470
1471
|
import {
|
|
1471
1472
|
IJumpAutorouter,
|
|
1472
|
-
autoroute as autoroute2,
|
|
1473
1473
|
getObstaclesFromSoup,
|
|
1474
1474
|
markObstaclesAsConnected
|
|
1475
1475
|
} from "@tscircuit/infgrid-ijump-astar";
|
|
@@ -1558,6 +1558,7 @@ function pdist(a, b) {
|
|
|
1558
1558
|
return Math.hypot(a.x - b.x, a.y - b.y);
|
|
1559
1559
|
}
|
|
1560
1560
|
var mergeRoutes = (routes) => {
|
|
1561
|
+
if (routes.length === 1) return routes[0];
|
|
1561
1562
|
if (routes.some((r) => r.length === 0)) {
|
|
1562
1563
|
throw new Error("Cannot merge routes with zero length");
|
|
1563
1564
|
}
|
|
@@ -1698,17 +1699,35 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1698
1699
|
};
|
|
1699
1700
|
}
|
|
1700
1701
|
_findConnectedNets() {
|
|
1701
|
-
const
|
|
1702
|
-
selector
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1702
|
+
const netsWithSelectors = this.getTracePathNetSelectors().map(
|
|
1703
|
+
(selector) => ({
|
|
1704
|
+
selector,
|
|
1705
|
+
net: this.getSubcircuit().selectOne(selector, { type: "net" })
|
|
1706
|
+
})
|
|
1707
|
+
);
|
|
1708
|
+
const undefinedNets = netsWithSelectors.filter((n) => !n.net);
|
|
1706
1709
|
if (undefinedNets.length > 0) {
|
|
1707
1710
|
this.renderError(
|
|
1708
1711
|
`Could not find net for selector "${undefinedNets[0].selector}" inside ${this}`
|
|
1709
1712
|
);
|
|
1710
1713
|
}
|
|
1711
|
-
return nets;
|
|
1714
|
+
return { netsWithSelectors, nets: netsWithSelectors.map((n) => n.net) };
|
|
1715
|
+
}
|
|
1716
|
+
/**
|
|
1717
|
+
* Get all the traces that are connected in any degree to this trace, this is
|
|
1718
|
+
* used during autorouting to routes to pass through traces connected to the
|
|
1719
|
+
* same net.
|
|
1720
|
+
*/
|
|
1721
|
+
_getAllTracesConnectedToSameNet() {
|
|
1722
|
+
const traces = this.getSubcircuit().selectAll("trace");
|
|
1723
|
+
const myNets = this._findConnectedNets().nets;
|
|
1724
|
+
const myPorts = this._findConnectedPorts().ports ?? [];
|
|
1725
|
+
return traces.filter((t) => {
|
|
1726
|
+
if (t === this) return false;
|
|
1727
|
+
const tNets = t._findConnectedNets().nets;
|
|
1728
|
+
const tPorts = t._findConnectedPorts().ports ?? [];
|
|
1729
|
+
return tNets.some((n) => myNets.includes(n)) || tPorts.some((p) => myPorts.includes(p));
|
|
1730
|
+
});
|
|
1712
1731
|
}
|
|
1713
1732
|
/**
|
|
1714
1733
|
* Determine if a trace is explicitly connected to a port (not via a net)
|
|
@@ -1723,9 +1742,12 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1723
1742
|
* Determine if a trace is explicitly connected to a net (not via a port)
|
|
1724
1743
|
*/
|
|
1725
1744
|
_isExplicitlyConnectedToNet(net) {
|
|
1726
|
-
const nets = this._findConnectedNets().
|
|
1745
|
+
const nets = this._findConnectedNets().nets;
|
|
1727
1746
|
return nets.includes(net);
|
|
1728
1747
|
}
|
|
1748
|
+
doInitialCreateNetsFromProps() {
|
|
1749
|
+
createNetsFromProps(this, this.getTracePathNetSelectors());
|
|
1750
|
+
}
|
|
1729
1751
|
doInitialSourceTraceRender() {
|
|
1730
1752
|
const { db } = this.project;
|
|
1731
1753
|
const { _parsedProps: props, parent } = this;
|
|
@@ -1735,10 +1757,10 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1735
1757
|
}
|
|
1736
1758
|
const { allPortsFound, portsWithSelectors: ports } = this._findConnectedPorts();
|
|
1737
1759
|
if (!allPortsFound) return;
|
|
1738
|
-
const nets = this._findConnectedNets();
|
|
1760
|
+
const nets = this._findConnectedNets().nets;
|
|
1739
1761
|
const trace = db.source_trace.insert({
|
|
1740
1762
|
connected_source_port_ids: ports.map((p) => p.port.source_port_id),
|
|
1741
|
-
connected_source_net_ids: nets.map((n) => n.
|
|
1763
|
+
connected_source_net_ids: nets.map((n) => n.source_net_id)
|
|
1742
1764
|
});
|
|
1743
1765
|
this.source_trace_id = trace.source_trace_id;
|
|
1744
1766
|
}
|
|
@@ -1749,7 +1771,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1749
1771
|
const { allPortsFound, ports } = this._findConnectedPorts();
|
|
1750
1772
|
const portsConnectedOnPcbViaNet = [];
|
|
1751
1773
|
if (!allPortsFound) return;
|
|
1752
|
-
const nets = this._findConnectedNets();
|
|
1774
|
+
const nets = this._findConnectedNets().netsWithSelectors;
|
|
1753
1775
|
if (ports.length === 0 && nets.length === 2) {
|
|
1754
1776
|
this.renderError(
|
|
1755
1777
|
`Trace connects two nets, we haven't implemented a way to route this yet`
|
|
@@ -1775,7 +1797,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1775
1797
|
return;
|
|
1776
1798
|
}
|
|
1777
1799
|
const pcbElements = db.toArray().filter(
|
|
1778
|
-
(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"
|
|
1800
|
+
(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" || elm.type === "source_trace"
|
|
1779
1801
|
);
|
|
1780
1802
|
const source_trace = db.source_trace.get(this.source_trace_id);
|
|
1781
1803
|
const hints = ports.flatMap(
|
|
@@ -1803,35 +1825,19 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1803
1825
|
if (isAlreadyRouted) {
|
|
1804
1826
|
return;
|
|
1805
1827
|
}
|
|
1828
|
+
let orderedRouteObjectives = [];
|
|
1806
1829
|
if (pcbRouteHints.length === 0) {
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
);
|
|
1818
|
-
const inputPcbTrace = solution[0];
|
|
1819
|
-
if (!inputPcbTrace) {
|
|
1820
|
-
console.log(
|
|
1821
|
-
`Failed to find route from ${ports[0]} to ${ports[1]} (TODO render error!)`
|
|
1822
|
-
);
|
|
1823
|
-
return;
|
|
1824
|
-
}
|
|
1825
|
-
const pcb_trace2 = db.pcb_trace.insert(inputPcbTrace);
|
|
1826
|
-
this.pcb_trace_id = pcb_trace2.pcb_trace_id;
|
|
1827
|
-
this._portsRoutedOnPcb = ports;
|
|
1828
|
-
return;
|
|
1830
|
+
orderedRouteObjectives = [
|
|
1831
|
+
portToObjective(ports[0]),
|
|
1832
|
+
portToObjective(ports[1])
|
|
1833
|
+
];
|
|
1834
|
+
} else {
|
|
1835
|
+
orderedRouteObjectives = [
|
|
1836
|
+
portToObjective(ports[0]),
|
|
1837
|
+
...pcbRouteHints,
|
|
1838
|
+
portToObjective(ports[1])
|
|
1839
|
+
];
|
|
1829
1840
|
}
|
|
1830
|
-
const orderedRouteObjectives = [
|
|
1831
|
-
portToObjective(ports[0]),
|
|
1832
|
-
...pcbRouteHints,
|
|
1833
|
-
portToObjective(ports[1])
|
|
1834
|
-
];
|
|
1835
1841
|
const candidateLayerCombinations = findPossibleTraceLayerCombinations(
|
|
1836
1842
|
orderedRouteObjectives
|
|
1837
1843
|
);
|
|
@@ -1846,6 +1852,16 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1846
1852
|
orderedRouteObjectives,
|
|
1847
1853
|
this.source_trace_id
|
|
1848
1854
|
);
|
|
1855
|
+
const allConnectedTraceIds = this._getAllTracesConnectedToSameNet().map(
|
|
1856
|
+
(t) => t.source_trace_id
|
|
1857
|
+
);
|
|
1858
|
+
for (const obstacle of obstacles) {
|
|
1859
|
+
if (obstacle.connectedTo.some(
|
|
1860
|
+
(connection) => allConnectedTraceIds.includes(connection)
|
|
1861
|
+
)) {
|
|
1862
|
+
obstacle.connectedTo.push(this.source_trace_id);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1849
1865
|
const candidateLayerSelections = candidateLayerCombinations[0].layer_path;
|
|
1850
1866
|
const orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
|
|
1851
1867
|
if (t.via) {
|
|
@@ -1860,6 +1876,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1860
1876
|
for (const [a, b] of pairs(orderedRoutePoints)) {
|
|
1861
1877
|
const BOUNDS_MARGIN = 2;
|
|
1862
1878
|
const ijump = new IJumpAutorouter({
|
|
1879
|
+
OBSTACLE_MARGIN: 0.3,
|
|
1863
1880
|
input: {
|
|
1864
1881
|
obstacles,
|
|
1865
1882
|
connections: [
|
|
@@ -1879,8 +1896,8 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1879
1896
|
});
|
|
1880
1897
|
const traces = ijump.solveAndMapToTraces();
|
|
1881
1898
|
if (traces.length === 0) {
|
|
1882
|
-
|
|
1883
|
-
`Could not find a route between ${a
|
|
1899
|
+
console.log(
|
|
1900
|
+
`Could not find a route between ${a} and ${b} for ${this} (TODO render error)`
|
|
1884
1901
|
);
|
|
1885
1902
|
return;
|
|
1886
1903
|
}
|
|
@@ -1891,6 +1908,7 @@ searched component ${targetComponent.getString()}, which has ports: ${targetComp
|
|
|
1891
1908
|
route: mergeRoutes(routes),
|
|
1892
1909
|
source_trace_id: this.source_trace_id
|
|
1893
1910
|
});
|
|
1911
|
+
this._portsRoutedOnPcb = ports;
|
|
1894
1912
|
this.pcb_trace_id = pcb_trace.pcb_trace_id;
|
|
1895
1913
|
}
|
|
1896
1914
|
doInitialSchematicTraceRender() {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { getPortFromHints } from "lib/utils/getPortFromHints"
|
|
18
18
|
import { createComponentsFromSoup } from "lib/utils/createComponentsFromSoup"
|
|
19
19
|
import { Net } from "../primitive-components/Net"
|
|
20
|
+
import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
|
|
20
21
|
|
|
21
22
|
export type PortMap<T extends string> = {
|
|
22
23
|
[K in T]: Port
|
|
@@ -309,17 +310,7 @@ export class NormalComponent<
|
|
|
309
310
|
}
|
|
310
311
|
|
|
311
312
|
_createNetsFromProps(propsWithConnections: (string | undefined | null)[]) {
|
|
312
|
-
|
|
313
|
-
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
314
|
-
if (!this.getSubcircuit().selectOne(prop)) {
|
|
315
|
-
this.getSubcircuit().add(
|
|
316
|
-
new Net({
|
|
317
|
-
name: prop.split(".")[1],
|
|
318
|
-
}),
|
|
319
|
-
)
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
313
|
+
createNetsFromProps(this, propsWithConnections)
|
|
323
314
|
}
|
|
324
315
|
|
|
325
316
|
/**
|
|
@@ -22,12 +22,16 @@ import type {
|
|
|
22
22
|
import { computeObstacleBounds } from "lib/utils/autorouting/computeObstacleBounds"
|
|
23
23
|
import { projectPointInDirection } from "lib/utils/projectPointInDirection"
|
|
24
24
|
import type { TraceHint } from "./TraceHint"
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
findPossibleTraceLayerCombinations,
|
|
27
|
+
type CandidateTraceLayerCombination,
|
|
28
|
+
} from "lib/utils/autorouting/findPossibleTraceLayerCombinations"
|
|
26
29
|
import { pairs } from "lib/utils/pairs"
|
|
27
30
|
import { mergeRoutes } from "lib/utils/autorouting/mergeRoutes"
|
|
28
31
|
import type { Net } from "./Net"
|
|
29
32
|
import { getClosest } from "lib/utils/getClosest"
|
|
30
33
|
import { z } from "zod"
|
|
34
|
+
import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
|
|
31
35
|
|
|
32
36
|
type PcbRouteObjective =
|
|
33
37
|
| RouteHintPoint
|
|
@@ -144,20 +148,47 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
|
|
147
|
-
_findConnectedNets():
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
_findConnectedNets(): {
|
|
152
|
+
nets: Net[]
|
|
153
|
+
netsWithSelectors: Array<{ selector: string; net: Net }>
|
|
154
|
+
} {
|
|
155
|
+
const netsWithSelectors = this.getTracePathNetSelectors().map(
|
|
156
|
+
(selector) => ({
|
|
157
|
+
selector,
|
|
158
|
+
net: this.getSubcircuit().selectOne(selector, { type: "net" }) as Net,
|
|
159
|
+
}),
|
|
160
|
+
)
|
|
152
161
|
|
|
153
|
-
const undefinedNets =
|
|
162
|
+
const undefinedNets = netsWithSelectors.filter((n) => !n.net)
|
|
154
163
|
if (undefinedNets.length > 0) {
|
|
155
164
|
this.renderError(
|
|
156
165
|
`Could not find net for selector "${undefinedNets[0].selector}" inside ${this}`,
|
|
157
166
|
)
|
|
158
167
|
}
|
|
159
168
|
|
|
160
|
-
return nets
|
|
169
|
+
return { netsWithSelectors, nets: netsWithSelectors.map((n) => n.net) }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Get all the traces that are connected in any degree to this trace, this is
|
|
174
|
+
* used during autorouting to routes to pass through traces connected to the
|
|
175
|
+
* same net.
|
|
176
|
+
*/
|
|
177
|
+
_getAllTracesConnectedToSameNet(): Trace[] {
|
|
178
|
+
const traces = this.getSubcircuit().selectAll("trace") as Trace[]
|
|
179
|
+
|
|
180
|
+
const myNets = this._findConnectedNets().nets
|
|
181
|
+
const myPorts = this._findConnectedPorts().ports ?? []
|
|
182
|
+
|
|
183
|
+
return traces.filter((t) => {
|
|
184
|
+
if (t === this) return false
|
|
185
|
+
const tNets = t._findConnectedNets().nets
|
|
186
|
+
const tPorts = t._findConnectedPorts().ports ?? []
|
|
187
|
+
return (
|
|
188
|
+
tNets.some((n) => myNets.includes(n)) ||
|
|
189
|
+
tPorts.some((p) => myPorts.includes(p))
|
|
190
|
+
)
|
|
191
|
+
})
|
|
161
192
|
}
|
|
162
193
|
|
|
163
194
|
/**
|
|
@@ -175,10 +206,14 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
175
206
|
* Determine if a trace is explicitly connected to a net (not via a port)
|
|
176
207
|
*/
|
|
177
208
|
_isExplicitlyConnectedToNet(net: Net) {
|
|
178
|
-
const nets = this._findConnectedNets().
|
|
209
|
+
const nets = this._findConnectedNets().nets
|
|
179
210
|
return nets.includes(net)
|
|
180
211
|
}
|
|
181
212
|
|
|
213
|
+
doInitialCreateNetsFromProps(): void {
|
|
214
|
+
createNetsFromProps(this, this.getTracePathNetSelectors())
|
|
215
|
+
}
|
|
216
|
+
|
|
182
217
|
doInitialSourceTraceRender(): void {
|
|
183
218
|
const { db } = this.project!
|
|
184
219
|
const { _parsedProps: props, parent } = this
|
|
@@ -192,11 +227,11 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
192
227
|
this._findConnectedPorts()
|
|
193
228
|
if (!allPortsFound) return
|
|
194
229
|
|
|
195
|
-
const nets = this._findConnectedNets()
|
|
230
|
+
const nets = this._findConnectedNets().nets
|
|
196
231
|
|
|
197
232
|
const trace = db.source_trace.insert({
|
|
198
233
|
connected_source_port_ids: ports.map((p) => p.port.source_port_id!),
|
|
199
|
-
connected_source_net_ids: nets.map((n) => n.
|
|
234
|
+
connected_source_net_ids: nets.map((n) => n.source_net_id!),
|
|
200
235
|
})
|
|
201
236
|
|
|
202
237
|
this.source_trace_id = trace.source_trace_id
|
|
@@ -213,7 +248,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
213
248
|
|
|
214
249
|
if (!allPortsFound) return
|
|
215
250
|
|
|
216
|
-
const nets = this._findConnectedNets()
|
|
251
|
+
const nets = this._findConnectedNets().netsWithSelectors
|
|
217
252
|
|
|
218
253
|
if (ports.length === 0 && nets.length === 2) {
|
|
219
254
|
// Find the two optimal points to connect the two nets
|
|
@@ -254,7 +289,8 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
254
289
|
elm.type === "pcb_plated_hole" ||
|
|
255
290
|
elm.type === "pcb_hole" ||
|
|
256
291
|
elm.type === "source_port" ||
|
|
257
|
-
elm.type === "pcb_port"
|
|
292
|
+
elm.type === "pcb_port" ||
|
|
293
|
+
elm.type === "source_trace",
|
|
258
294
|
)
|
|
259
295
|
|
|
260
296
|
const source_trace = db.source_trace.get(this.source_trace_id!)!
|
|
@@ -296,44 +332,24 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
296
332
|
return
|
|
297
333
|
}
|
|
298
334
|
|
|
299
|
-
|
|
300
|
-
const { solution } = autoroute(
|
|
301
|
-
pcbElements.concat([
|
|
302
|
-
{
|
|
303
|
-
...source_trace,
|
|
304
|
-
// manually override b/c some of the ports may be connected via nets
|
|
305
|
-
// so they don't appear properly in the source_trace, we don't need
|
|
306
|
-
// to do this if the algorithm correctly looks at connected_source_net_ids
|
|
307
|
-
connected_source_port_ids: ports.map((p) => p.source_port_id!),
|
|
308
|
-
} as SourceTrace,
|
|
309
|
-
]),
|
|
310
|
-
)
|
|
311
|
-
// TODO for some reason, the solution gets duplicated inside ijump-astar
|
|
312
|
-
const inputPcbTrace = solution[0]
|
|
313
|
-
|
|
314
|
-
if (!inputPcbTrace) {
|
|
315
|
-
// TODO render error indicating we could not find a route
|
|
316
|
-
console.log(
|
|
317
|
-
`Failed to find route from ${ports[0]} to ${ports[1]} (TODO render error!)`,
|
|
318
|
-
)
|
|
319
|
-
return
|
|
320
|
-
}
|
|
321
|
-
const pcb_trace = db.pcb_trace.insert(inputPcbTrace as any)
|
|
335
|
+
let orderedRouteObjectives: PcbRouteObjective[] = []
|
|
322
336
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
337
|
+
if (pcbRouteHints.length === 0) {
|
|
338
|
+
orderedRouteObjectives = [
|
|
339
|
+
portToObjective(ports[0]),
|
|
340
|
+
portToObjective(ports[1]),
|
|
341
|
+
]
|
|
342
|
+
} else {
|
|
343
|
+
// When we have hints, we have to order the hints then route between each
|
|
344
|
+
// terminal of the trace and the hints
|
|
345
|
+
// TODO order based on proximity to ports
|
|
346
|
+
orderedRouteObjectives = [
|
|
347
|
+
portToObjective(ports[0]),
|
|
348
|
+
...pcbRouteHints,
|
|
349
|
+
portToObjective(ports[1]),
|
|
350
|
+
]
|
|
326
351
|
}
|
|
327
352
|
|
|
328
|
-
// When we have hints, we have to order the hints then route between each
|
|
329
|
-
// terminal of the trace and the hints
|
|
330
|
-
// TODO order based on proximity to ports
|
|
331
|
-
const orderedRouteObjectives: PcbRouteObjective[] = [
|
|
332
|
-
portToObjective(ports[0]),
|
|
333
|
-
...pcbRouteHints,
|
|
334
|
-
portToObjective(ports[1]),
|
|
335
|
-
]
|
|
336
|
-
|
|
337
353
|
// Hints can indicate where there should be a via, but the layer is allowed
|
|
338
354
|
// to be unspecified, therefore we need to find possible layer combinations
|
|
339
355
|
// to go to each hint and still route to the start and end points
|
|
@@ -356,6 +372,19 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
356
372
|
this.source_trace_id!,
|
|
357
373
|
)
|
|
358
374
|
|
|
375
|
+
const allConnectedTraceIds = this._getAllTracesConnectedToSameNet().map(
|
|
376
|
+
(t) => t.source_trace_id,
|
|
377
|
+
)
|
|
378
|
+
for (const obstacle of obstacles) {
|
|
379
|
+
if (
|
|
380
|
+
obstacle.connectedTo.some((connection) =>
|
|
381
|
+
allConnectedTraceIds.includes(connection),
|
|
382
|
+
)
|
|
383
|
+
) {
|
|
384
|
+
obstacle.connectedTo.push(this.source_trace_id!)
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
359
388
|
// TODO explore all candidate layer combinations if one fails
|
|
360
389
|
const candidateLayerSelections = candidateLayerCombinations[0].layer_path
|
|
361
390
|
|
|
@@ -377,6 +406,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
377
406
|
for (const [a, b] of pairs(orderedRoutePoints)) {
|
|
378
407
|
const BOUNDS_MARGIN = 2 //mm
|
|
379
408
|
const ijump = new IJumpAutorouter({
|
|
409
|
+
OBSTACLE_MARGIN: 0.3,
|
|
380
410
|
input: {
|
|
381
411
|
obstacles,
|
|
382
412
|
connections: [
|
|
@@ -396,8 +426,8 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
396
426
|
})
|
|
397
427
|
const traces = ijump.solveAndMapToTraces()
|
|
398
428
|
if (traces.length === 0) {
|
|
399
|
-
|
|
400
|
-
`Could not find a route between ${a
|
|
429
|
+
console.log(
|
|
430
|
+
`Could not find a route between ${a} and ${b} for ${this} (TODO render error)`,
|
|
401
431
|
)
|
|
402
432
|
return
|
|
403
433
|
}
|
|
@@ -410,6 +440,7 @@ export class Trace extends PrimitiveComponent<typeof traceProps> {
|
|
|
410
440
|
route: mergeRoutes(routes),
|
|
411
441
|
source_trace_id: this.source_trace_id!,
|
|
412
442
|
})
|
|
443
|
+
this._portsRoutedOnPcb = ports
|
|
413
444
|
this.pcb_trace_id = pcb_trace.pcb_trace_id
|
|
414
445
|
}
|
|
415
446
|
|
|
@@ -13,7 +13,7 @@ const LAYER_SELECTION_PREFERENCE = ["top", "bottom", "inner1", "inner2"]
|
|
|
13
13
|
* top -> bottom -> bottom -> top
|
|
14
14
|
* bottom -> top -> top -> bottom
|
|
15
15
|
*/
|
|
16
|
-
interface CandidateTraceLayerCombination {
|
|
16
|
+
export interface CandidateTraceLayerCombination {
|
|
17
17
|
layer_path: string[]
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -11,6 +11,7 @@ function pdist(a: any, b: any) {
|
|
|
11
11
|
* reverse the next route and append it to the previous route.
|
|
12
12
|
*/
|
|
13
13
|
export const mergeRoutes = (routes: PCBTrace["route"][]) => {
|
|
14
|
+
if (routes.length === 1) return routes[0]
|
|
14
15
|
// routes = routes.filter((route) => route.length > 0)
|
|
15
16
|
if (routes.some((r) => r.length === 0)) {
|
|
16
17
|
throw new Error("Cannot merge routes with zero length")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PrimitiveComponent } from "lib/components/base-components/PrimitiveComponent"
|
|
2
|
+
import { Net } from "lib/components/primitive-components/Net"
|
|
3
|
+
|
|
4
|
+
export const createNetsFromProps = (
|
|
5
|
+
component: PrimitiveComponent,
|
|
6
|
+
props: (string | undefined | null)[],
|
|
7
|
+
) => {
|
|
8
|
+
for (const prop of props) {
|
|
9
|
+
if (typeof prop === "string" && prop.startsWith("net.")) {
|
|
10
|
+
if (!component.getSubcircuit().selectOne(prop)) {
|
|
11
|
+
component.getSubcircuit().add(new Net({ name: prop.split("net.")[1] }))
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@tscircuit/core",
|
|
3
3
|
"module": "index.ts",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.26",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"files": [
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@types/react": "^18.3.3",
|
|
23
23
|
"@types/react-reconciler": "^0.28.8",
|
|
24
24
|
"bun-match-svg": "0.0.2",
|
|
25
|
-
"circuit-to-svg": "^0.0.
|
|
25
|
+
"circuit-to-svg": "^0.0.18",
|
|
26
26
|
"howfat": "^0.3.8",
|
|
27
27
|
"looks-same": "^9.0.1",
|
|
28
28
|
"tsup": "^8.2.4"
|