@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 CHANGED
@@ -401,10 +401,19 @@ declare class Trace extends PrimitiveComponent<typeof traceProps> {
401
401
  ports?: undefined;
402
402
  portsWithSelectors?: undefined;
403
403
  };
404
- _findConnectedNets(): Array<{
405
- selector: string;
406
- net: Net;
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
- for (const prop of propsWithConnections) {
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 nets = this.getTracePathNetSelectors().map((selector) => ({
1702
- selector,
1703
- net: this.getSubcircuit().selectOne(selector, { type: "net" })
1704
- }));
1705
- const undefinedNets = nets.filter((n) => !n.net);
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().map((n) => n.net);
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.net.source_net_id)
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
- const { solution } = autoroute2(
1808
- pcbElements.concat([
1809
- {
1810
- ...source_trace,
1811
- // manually override b/c some of the ports may be connected via nets
1812
- // so they don't appear properly in the source_trace, we don't need
1813
- // to do this if the algorithm correctly looks at connected_source_net_ids
1814
- connected_source_port_ids: ports.map((p) => p.source_port_id)
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
- this.renderError(
1883
- `Could not find a route between ${a.x}, ${a.y} and ${b.x}, ${b.y}`
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
- for (const prop of propsWithConnections) {
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 { findPossibleTraceLayerCombinations } from "lib/utils/autorouting/findPossibleTraceLayerCombinations"
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(): Array<{ selector: string; net: Net }> {
148
- const nets = this.getTracePathNetSelectors().map((selector) => ({
149
- selector,
150
- net: this.getSubcircuit().selectOne(selector, { type: "net" }) as Net,
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 = nets.filter((n) => !n.net)
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().map((n) => n.net)
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.net.source_net_id!),
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
- if (pcbRouteHints.length === 0) {
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
- this.pcb_trace_id = pcb_trace.pcb_trace_id
324
- this._portsRoutedOnPcb = ports
325
- return
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
- this.renderError(
400
- `Could not find a route between ${a.x}, ${a.y} and ${b.x}, ${b.y}`,
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.24",
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.13",
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"