@tscircuit/core 0.0.73 → 0.0.74

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.
Files changed (57) hide show
  1. package/package.json +2 -4
  2. package/index.ts +0 -1
  3. package/lib/Project.ts +0 -131
  4. package/lib/components/base-components/NormalComponent.ts +0 -419
  5. package/lib/components/base-components/PrimitiveComponent.ts +0 -478
  6. package/lib/components/base-components/Renderable.ts +0 -126
  7. package/lib/components/index.ts +0 -25
  8. package/lib/components/normal-components/Board.ts +0 -49
  9. package/lib/components/normal-components/Capacitor.ts +0 -70
  10. package/lib/components/normal-components/Chip.ts +0 -98
  11. package/lib/components/normal-components/Diode.ts +0 -27
  12. package/lib/components/normal-components/Jumper.ts +0 -101
  13. package/lib/components/normal-components/Led.ts +0 -27
  14. package/lib/components/normal-components/Resistor.ts +0 -59
  15. package/lib/components/primitive-components/Constraint.ts +0 -91
  16. package/lib/components/primitive-components/FabricationNotePath.ts +0 -50
  17. package/lib/components/primitive-components/FabricationNoteText.ts +0 -26
  18. package/lib/components/primitive-components/Footprint.ts +0 -239
  19. package/lib/components/primitive-components/Group.ts +0 -42
  20. package/lib/components/primitive-components/Hole.ts +0 -65
  21. package/lib/components/primitive-components/Keepout.ts +0 -58
  22. package/lib/components/primitive-components/Net.ts +0 -171
  23. package/lib/components/primitive-components/PlatedHole.ts +0 -116
  24. package/lib/components/primitive-components/Port.ts +0 -236
  25. package/lib/components/primitive-components/SilkscreenPath.ts +0 -48
  26. package/lib/components/primitive-components/SilkscreenText.ts +0 -25
  27. package/lib/components/primitive-components/SmtPad.ts +0 -162
  28. package/lib/components/primitive-components/Trace.ts +0 -635
  29. package/lib/components/primitive-components/TraceHint.ts +0 -71
  30. package/lib/fiber/catalogue.ts +0 -22
  31. package/lib/fiber/create-instance-from-react-element.ts +0 -179
  32. package/lib/fiber/intrinsic-jsx.ts +0 -48
  33. package/lib/index.ts +0 -5
  34. package/lib/register-catalogue.ts +0 -12
  35. package/lib/soup/underscorifyPinStyles.ts +0 -25
  36. package/lib/soup/underscorifyPortArrangement.ts +0 -51
  37. package/lib/utils/autorouting/SimpleRouteJson.ts +0 -48
  38. package/lib/utils/autorouting/computeObstacleBounds.ts +0 -10
  39. package/lib/utils/autorouting/findPossibleTraceLayerCombinations.ts +0 -102
  40. package/lib/utils/autorouting/mergeRoutes.ts +0 -71
  41. package/lib/utils/components/createNetsFromProps.ts +0 -15
  42. package/lib/utils/constants.ts +0 -35
  43. package/lib/utils/createComponentsFromSoup.ts +0 -79
  44. package/lib/utils/extend-aliases.ts +0 -12
  45. package/lib/utils/get-bounds-of-pcb-components.ts +0 -41
  46. package/lib/utils/get-relative-direction.ts +0 -14
  47. package/lib/utils/getClosest.ts +0 -35
  48. package/lib/utils/getPortFromHints.ts +0 -10
  49. package/lib/utils/pairs.ts +0 -10
  50. package/lib/utils/projectPointInDirection.ts +0 -18
  51. package/lib/utils/range.ts +0 -8
  52. package/lib/utils/schematic/getAllDimensionsForSchematicBox.ts +0 -330
  53. package/lib/utils/schematic/getSizeOfSidesFromPortArrangement.ts +0 -47
  54. package/lib/utils/selector-matching/index.ts +0 -2
  55. package/lib/utils/selector-matching/is-matching-path-selector.ts +0 -32
  56. package/lib/utils/selector-matching/is-matching-selector.ts +0 -64
  57. package/lib/utils/try-now.ts +0 -7
@@ -1,635 +0,0 @@
1
- import { traceProps } from "@tscircuit/props"
2
- import { PrimitiveComponent } from "../base-components/PrimitiveComponent"
3
- import type { Port } from "./Port"
4
- import {
5
- MultilayerIjump,
6
- IJumpAutorouter,
7
- autoroute,
8
- getObstaclesFromSoup,
9
- markObstaclesAsConnected,
10
- } from "@tscircuit/infgrid-ijump-astar"
11
- import type {
12
- AnySoupElement,
13
- LayerRef,
14
- PCBTrace,
15
- RouteHintPoint,
16
- SchematicTrace,
17
- SourceTrace,
18
- } from "@tscircuit/soup"
19
- import type {
20
- Obstacle,
21
- SimpleRouteConnection,
22
- SimpleRouteJson,
23
- SimplifiedPcbTrace,
24
- } from "lib/utils/autorouting/SimpleRouteJson"
25
- import { computeObstacleBounds } from "lib/utils/autorouting/computeObstacleBounds"
26
- import { projectPointInDirection } from "lib/utils/projectPointInDirection"
27
- import type { TraceHint } from "./TraceHint"
28
- import {
29
- findPossibleTraceLayerCombinations,
30
- type CandidateTraceLayerCombination,
31
- } from "lib/utils/autorouting/findPossibleTraceLayerCombinations"
32
- import { pairs } from "lib/utils/pairs"
33
- import { mergeRoutes } from "lib/utils/autorouting/mergeRoutes"
34
- import type { Net } from "./Net"
35
- import { getClosest } from "lib/utils/getClosest"
36
- import { z } from "zod"
37
- import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
38
- import {
39
- isMatchingPathSelector,
40
- isMatchingSelector,
41
- } from "lib/utils/selector-matching"
42
- import { tryNow } from "lib/utils/try-now"
43
- import { getFullConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map"
44
-
45
- type PcbRouteObjective =
46
- | RouteHintPoint
47
- | {
48
- layers: string[]
49
- x: number
50
- y: number
51
- via?: boolean
52
- pcb_port_id?: string
53
- }
54
-
55
- const portToObjective = (port: Port): PcbRouteObjective => {
56
- const portPosition = port._getGlobalPcbPositionAfterLayout()
57
- return {
58
- ...portPosition,
59
- layers: port.getAvailablePcbLayers(),
60
- }
61
- }
62
-
63
- const SHOULD_USE_SINGLE_LAYER_ROUTING = false
64
-
65
- export class Trace extends PrimitiveComponent<typeof traceProps> {
66
- source_trace_id: string | null = null
67
- pcb_trace_id: string | null = null
68
- schematic_trace_id: string | null = null
69
- _portsRoutedOnPcb: Port[]
70
-
71
- constructor(props: z.input<typeof traceProps>) {
72
- super(props)
73
- this._portsRoutedOnPcb = []
74
- }
75
-
76
- get config() {
77
- return {
78
- zodProps: traceProps,
79
- }
80
- }
81
-
82
- _getTracePortOrNetSelectorListFromProps(): string[] {
83
- if ("from" in this.props && "to" in this.props) {
84
- return [
85
- typeof this.props.from === "string"
86
- ? this.props.from
87
- : this.props.from.getPortSelector(),
88
- typeof this.props.to === "string"
89
- ? this.props.to
90
- : this.props.to.getPortSelector(),
91
- ]
92
- }
93
- if ("path" in this.props) {
94
- return this.props.path.map((p) =>
95
- typeof p === "string" ? p : p.getPortSelector(),
96
- )
97
- }
98
- return []
99
- }
100
-
101
- getTracePortPathSelectors(): string[] {
102
- return this._getTracePortOrNetSelectorListFromProps().filter(
103
- (selector) => !selector.includes("net."),
104
- )
105
- }
106
-
107
- getTracePathNetSelectors(): string[] {
108
- return this._getTracePortOrNetSelectorListFromProps().filter((selector) =>
109
- selector.includes("net."),
110
- )
111
- }
112
-
113
- _findConnectedPorts():
114
- | {
115
- allPortsFound: true
116
- ports: Port[]
117
- portsWithSelectors: Array<{ selector: string; port: Port }>
118
- }
119
- | {
120
- allPortsFound: false
121
- ports?: undefined
122
- portsWithSelectors?: undefined
123
- } {
124
- const { db } = this.root!
125
- const { _parsedProps: props, parent } = this
126
-
127
- if (!parent) throw new Error("Trace has no parent")
128
-
129
- const portSelectors = this.getTracePortPathSelectors()
130
-
131
- const portsWithSelectors = portSelectors.map((selector) => ({
132
- selector,
133
- port:
134
- (this.getSubcircuit().selectOne(selector, { type: "port" }) as Port) ??
135
- null,
136
- }))
137
-
138
- for (const { selector, port } of portsWithSelectors) {
139
- if (!port) {
140
- const parentSelector = selector.replace(/\>.*$/, "")
141
- const targetComponent = this.getSubcircuit().selectOne(parentSelector)
142
- if (!targetComponent) {
143
- this.renderError(`Could not find port for selector "${selector}"`)
144
- } else {
145
- this.renderError(
146
- `Could not find port for selector "${selector}"\nsearched component ${targetComponent.getString()}, which has ports: ${targetComponent.children
147
- .filter((c) => c.componentName === "Port")
148
- .map(
149
- (c) => `${c.getString()}(${c.getNameAndAliases().join(",")})`,
150
- )
151
- .join(" & ")}`,
152
- )
153
- }
154
- }
155
- }
156
-
157
- if (portsWithSelectors.some((p) => !p.port)) {
158
- return { allPortsFound: false }
159
- }
160
-
161
- return {
162
- allPortsFound: true,
163
- portsWithSelectors,
164
- ports: portsWithSelectors.map(({ port }) => port),
165
- }
166
- }
167
-
168
- _findConnectedNets(): {
169
- nets: Net[]
170
- netsWithSelectors: Array<{ selector: string; net: Net }>
171
- } {
172
- const netsWithSelectors = this.getTracePathNetSelectors().map(
173
- (selector) => ({
174
- selector,
175
- net: this.getSubcircuit().selectOne(selector, { type: "net" }) as Net,
176
- }),
177
- )
178
-
179
- const undefinedNets = netsWithSelectors.filter((n) => !n.net)
180
- if (undefinedNets.length > 0) {
181
- this.renderError(
182
- `Could not find net for selector "${undefinedNets[0].selector}" inside ${this}`,
183
- )
184
- }
185
-
186
- return { netsWithSelectors, nets: netsWithSelectors.map((n) => n.net) }
187
- }
188
-
189
- /**
190
- * Get all the traces that are connected in any degree to this trace, this is
191
- * used during autorouting to routes to pass through traces connected to the
192
- * same net.
193
- */
194
- _getAllTracesConnectedToSameNet(): Trace[] {
195
- const traces = this.getSubcircuit().selectAll("trace") as Trace[]
196
-
197
- const myNets = this._findConnectedNets().nets
198
- const myPorts = this._findConnectedPorts().ports ?? []
199
-
200
- return traces.filter((t) => {
201
- if (t === this) return false
202
- const tNets = t._findConnectedNets().nets
203
- const tPorts = t._findConnectedPorts().ports ?? []
204
- return (
205
- tNets.some((n) => myNets.includes(n)) ||
206
- tPorts.some((p) => myPorts.includes(p))
207
- )
208
- })
209
- }
210
-
211
- /**
212
- * Determine if a trace is explicitly connected to a port (not via a net)
213
- */
214
- _isExplicitlyConnectedToPort(port: Port) {
215
- const { allPortsFound, portsWithSelectors: portsWithMetadata } =
216
- this._findConnectedPorts()
217
- if (!allPortsFound) return false
218
- const ports = portsWithMetadata.map((p) => p.port)
219
- return ports.includes(port)
220
- }
221
-
222
- /**
223
- * Determine if a trace is explicitly connected to a net (not via a port)
224
- */
225
- _isExplicitlyConnectedToNet(net: Net) {
226
- const nets = this._findConnectedNets().nets
227
- return nets.includes(net)
228
- }
229
-
230
- doInitialCreateNetsFromProps(): void {
231
- createNetsFromProps(this, this.getTracePathNetSelectors())
232
- }
233
-
234
- doInitialSourceTraceRender(): void {
235
- const { db } = this.root!
236
- const { _parsedProps: props, parent } = this
237
-
238
- if (!parent) {
239
- this.renderError("Trace has no parent")
240
- return
241
- }
242
-
243
- const { allPortsFound, portsWithSelectors: ports } =
244
- this._findConnectedPorts()
245
- if (!allPortsFound) return
246
-
247
- const nets = this._findConnectedNets().nets
248
-
249
- const trace = db.source_trace.insert({
250
- connected_source_port_ids: ports.map((p) => p.port.source_port_id!),
251
- connected_source_net_ids: nets.map((n) => n.source_net_id!),
252
- })
253
-
254
- this.source_trace_id = trace.source_trace_id
255
- }
256
-
257
- doInitialPcbTraceRender(): void {
258
- const { db } = this.root!
259
- const { _parsedProps: props, parent } = this
260
-
261
- if (!parent) throw new Error("Trace has no parent")
262
-
263
- if (this.getSubcircuit()._parsedProps.routingDisabled) {
264
- return
265
- }
266
-
267
- const { allPortsFound, ports } = this._findConnectedPorts()
268
- const portsConnectedOnPcbViaNet: Port[] = []
269
-
270
- if (!allPortsFound) return
271
-
272
- const nets = this._findConnectedNets().netsWithSelectors
273
-
274
- if (ports.length === 0 && nets.length === 2) {
275
- // Find the two optimal points to connect the two nets
276
- this.renderError(
277
- `Trace connects two nets, we haven't implemented a way to route this yet`,
278
- )
279
- return
280
- // biome-ignore lint/style/noUselessElse: <explanation>
281
- } else if (ports.length === 1 && nets.length === 1) {
282
- // Add a port from the net that is closest to the port
283
- const port = ports[0]
284
- const portsInNet = nets[0].net.getAllConnectedPorts()
285
- const otherPortsInNet = portsInNet.filter((p) => p !== port)
286
- if (otherPortsInNet.length === 0) {
287
- console.log(
288
- "Nothing to connect this port to, the net is empty. TODO should emit a warning!",
289
- )
290
- return
291
- }
292
- const closestPortInNet = getClosest(port, otherPortsInNet)
293
-
294
- portsConnectedOnPcbViaNet.push(closestPortInNet)
295
-
296
- ports.push(closestPortInNet)
297
- } else if (ports.length > 1 && nets.length >= 1) {
298
- this.renderError(
299
- `Trace has more than one port and one or more nets, we don't currently support this type of complex trace routing`,
300
- )
301
- return
302
- }
303
-
304
- const hints = ports.flatMap((port) =>
305
- port.matchedComponents.filter((c) => c.componentName === "TraceHint"),
306
- ) as TraceHint[]
307
-
308
- const pcbRouteHints = (this._parsedProps.pcbRouteHints ?? []).concat(
309
- hints.flatMap((h) => h.getPcbRouteHints()),
310
- )
311
-
312
- if (ports.length > 2) {
313
- this.renderError(
314
- `Trace has more than two ports (${ports
315
- .map((p) => p.getString())
316
- .join(
317
- ", ",
318
- )}), routing between more than two ports for a single trace is not implemented`,
319
- )
320
- return
321
- }
322
-
323
- const alreadyRoutedTraces = this.getSubcircuit()
324
- .selectAll("trace")
325
- .filter(
326
- (trace) => trace.renderPhaseStates.PcbTraceRender.initialized,
327
- ) as Trace[]
328
-
329
- const isAlreadyRouted = alreadyRoutedTraces.some(
330
- (trace) =>
331
- trace._portsRoutedOnPcb.length === ports.length &&
332
- trace._portsRoutedOnPcb.every((portRoutedByOtherTrace) =>
333
- ports.includes(portRoutedByOtherTrace),
334
- ),
335
- )
336
-
337
- if (isAlreadyRouted) {
338
- return
339
- }
340
-
341
- let orderedRouteObjectives: PcbRouteObjective[] = []
342
-
343
- if (pcbRouteHints.length === 0) {
344
- orderedRouteObjectives = [
345
- portToObjective(ports[0]),
346
- portToObjective(ports[1]),
347
- ]
348
- } else {
349
- // When we have hints, we have to order the hints then route between each
350
- // terminal of the trace and the hints
351
- // TODO order based on proximity to ports
352
- orderedRouteObjectives = [
353
- portToObjective(ports[0]),
354
- ...pcbRouteHints,
355
- portToObjective(ports[1]),
356
- ]
357
- }
358
-
359
- // Hints can indicate where there should be a via, but the layer is allowed
360
- // to be unspecified, therefore we need to find possible layer combinations
361
- // to go to each hint and still route to the start and end points
362
- const candidateLayerCombinations = findPossibleTraceLayerCombinations(
363
- orderedRouteObjectives,
364
- )
365
-
366
- if (
367
- SHOULD_USE_SINGLE_LAYER_ROUTING &&
368
- candidateLayerCombinations.length === 0
369
- ) {
370
- this.renderError(
371
- `Could not find a common layer (using hints) for trace ${this.getString()}`,
372
- )
373
- return
374
- }
375
-
376
- const connMap = getFullConnectivityMapFromCircuitJson(
377
- this.root!.db.toArray(),
378
- )
379
-
380
- // Cache the PCB obstacles, they'll be needed for each segment between
381
- // ports/hints
382
- const [obstacles, errGettingObstacles] = tryNow(() =>
383
- getObstaclesFromSoup(this.root!.db.toArray()),
384
- )
385
-
386
- if (errGettingObstacles) {
387
- this.renderError({
388
- type: "pcb_error",
389
- error_type: "pcb_trace_error",
390
- message: `Error getting obstacles for autorouting: ${errGettingObstacles.message}`,
391
- source_trace_id: this.source_trace_id!,
392
- center: { x: 0, y: 0 },
393
- pcb_port_ids: ports.map((p) => p.pcb_port_id!),
394
- pcb_trace_id: this.pcb_trace_id!,
395
- pcb_component_ids: [],
396
- })
397
- return
398
- }
399
-
400
- for (const obstacle of obstacles) {
401
- const connectedTo = obstacle.connectedTo
402
- if (connectedTo.length > 0) {
403
- const netId = connMap.getNetConnectedToId(obstacle.connectedTo[0])
404
- if (netId) {
405
- obstacle.connectedTo.push(netId)
406
- }
407
- }
408
- }
409
-
410
- let orderedRoutePoints: PcbRouteObjective[] = []
411
- if (candidateLayerCombinations.length === 0) {
412
- orderedRoutePoints = orderedRouteObjectives
413
- } else {
414
- // TODO explore all candidate layer combinations if one fails
415
- const candidateLayerSelections = candidateLayerCombinations[0].layer_path
416
-
417
- /**
418
- * Apply the candidate layer selections to the route objectives, now we
419
- * have a set of points that have definite layers
420
- */
421
- orderedRoutePoints = orderedRouteObjectives.map((t, idx) => {
422
- if (t.via) {
423
- return {
424
- ...t,
425
- via_to_layer: candidateLayerSelections[idx],
426
- }
427
- }
428
- return { ...t, layers: [candidateLayerSelections[idx]] }
429
- })
430
- }
431
- ;(orderedRoutePoints[0] as any).pcb_port_id = ports[0].pcb_port_id
432
- ;(orderedRoutePoints[orderedRoutePoints.length - 1] as any).pcb_port_id =
433
- ports[1].pcb_port_id
434
-
435
- const routes: PCBTrace["route"][] = []
436
- for (const [a, b] of pairs(orderedRoutePoints)) {
437
- const dominantLayer =
438
- "via_to_layer" in a ? (a.via_to_layer as LayerRef) : null
439
- const BOUNDS_MARGIN = 2 //mm
440
-
441
- const aLayer =
442
- "layers" in a && a.layers.length === 1
443
- ? a.layers[0]
444
- : (dominantLayer ?? "top")
445
- const bLayer =
446
- "layers" in b && b.layers.length === 1
447
- ? b.layers[0]
448
- : (dominantLayer ?? "top")
449
-
450
- const pcbPortA = "pcb_port_id" in a ? a.pcb_port_id : null
451
- const pcbPortB = "pcb_port_id" in b ? b.pcb_port_id : null
452
-
453
- const minTraceWidth =
454
- this.getSubcircuit()._parsedProps.minTraceWidth ?? 0.16
455
-
456
- const ijump = new MultilayerIjump({
457
- OBSTACLE_MARGIN: minTraceWidth * 2,
458
- // isRemovePathLoopsEnabled: true,
459
- optimizeWithGoalBoxes: Boolean(pcbPortA && pcbPortB),
460
- connMap,
461
- input: {
462
- obstacles,
463
- minTraceWidth,
464
- connections: [
465
- {
466
- name: this.source_trace_id!,
467
- pointsToConnect: [
468
- { ...a, layer: aLayer, pcb_port_id: pcbPortA! },
469
- { ...b, layer: bLayer, pcb_port_id: pcbPortB! },
470
- ],
471
- },
472
- ],
473
- layerCount: 2,
474
- bounds: {
475
- minX: Math.min(a.x, b.x) - BOUNDS_MARGIN,
476
- maxX: Math.max(a.x, b.x) + BOUNDS_MARGIN,
477
- minY: Math.min(a.y, b.y) - BOUNDS_MARGIN,
478
- maxY: Math.max(a.y, b.y) + BOUNDS_MARGIN,
479
- },
480
- },
481
- })
482
- let traces: SimplifiedPcbTrace[] | null = null
483
- try {
484
- traces = ijump.solveAndMapToTraces()
485
- } catch (e: any) {
486
- this.renderError({
487
- type: "pcb_error",
488
- error_type: "pcb_trace_error",
489
- message: `error solving route: ${e.message}`,
490
- source_trace_id: this.source_trace_id!,
491
- center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
492
- pcb_port_ids: ports.map((p) => p.pcb_port_id!),
493
- pcb_trace_id: this.pcb_trace_id!,
494
- pcb_component_ids: ports.map((p) => p.pcb_component_id!),
495
- })
496
- }
497
- if (!traces) return
498
- if (traces.length === 0) {
499
- this.renderError({
500
- type: "pcb_error",
501
- error_type: "pcb_trace_error",
502
- message: `Could not find a route for ${this}`,
503
- source_trace_id: this.source_trace_id!,
504
- center: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
505
- pcb_port_ids: ports.map((p) => p.pcb_port_id!),
506
- pcb_trace_id: this.pcb_trace_id!,
507
- pcb_component_ids: ports.map((p) => p.pcb_component_id!),
508
- })
509
- return
510
- }
511
- const [trace] = traces as PCBTrace[]
512
-
513
- // If the autorouter didn't specify a layer, use the dominant layer
514
- // Some of the single-layer autorouters don't add the layer property
515
- if (dominantLayer) {
516
- trace.route = trace.route.map((p) => {
517
- if (p.route_type === "wire" && !p.layer) {
518
- p.layer = dominantLayer
519
- }
520
- return p
521
- })
522
- }
523
- routes.push(trace.route)
524
- }
525
-
526
- const mergedRoute = mergeRoutes(routes)
527
-
528
- for (const point of mergedRoute) {
529
- if (point.route_type === "via") {
530
- db.pcb_via.insert({
531
- x: point.x,
532
- y: point.y,
533
- hole_diameter: 0.3,
534
- outer_diameter: 0.6,
535
- layers: [point.from_layer as LayerRef, point.to_layer as LayerRef],
536
- from_layer: point.from_layer as LayerRef,
537
- to_layer: point.to_layer as LayerRef,
538
- })
539
- }
540
- }
541
-
542
- const pcb_trace = db.pcb_trace.insert({
543
- route: mergedRoute,
544
- source_trace_id: this.source_trace_id!,
545
- })
546
- this._portsRoutedOnPcb = ports
547
- this.pcb_trace_id = pcb_trace.pcb_trace_id
548
- }
549
-
550
- doInitialSchematicTraceRender(): void {
551
- const { db } = this.root!
552
- const { _parsedProps: props, parent } = this
553
-
554
- if (!parent) throw new Error("Trace has no parent")
555
-
556
- const { allPortsFound, portsWithSelectors: ports } =
557
- this._findConnectedPorts()
558
-
559
- if (!allPortsFound) return
560
-
561
- const obstacles: Obstacle[] = []
562
- const connection: SimpleRouteConnection = {
563
- name: this.source_trace_id!,
564
- pointsToConnect: [],
565
- }
566
-
567
- for (const elm of db.toArray()) {
568
- if (elm.type === "schematic_component") {
569
- obstacles.push({
570
- type: "rect",
571
- layers: ["top"],
572
- center: elm.center,
573
- width: elm.size.width,
574
- height: elm.size.height,
575
- connectedTo: [],
576
- })
577
- }
578
- }
579
-
580
- for (const { port } of ports) {
581
- connection.pointsToConnect.push({
582
- ...projectPointInDirection(
583
- port._getGlobalSchematicPositionBeforeLayout(),
584
- port.facingDirection!,
585
- 0.1501,
586
- ),
587
- layer: "top",
588
- })
589
- }
590
-
591
- const bounds = computeObstacleBounds(obstacles)
592
-
593
- const simpleRouteJsonInput: SimpleRouteJson = {
594
- minTraceWidth: 0.1,
595
- obstacles,
596
- connections: [connection],
597
- bounds,
598
- layerCount: 1,
599
- }
600
-
601
- const autorouter = new IJumpAutorouter({
602
- input: simpleRouteJsonInput,
603
- })
604
- const results = autorouter.solve()
605
-
606
- if (results.length === 0) return
607
-
608
- const [result] = results
609
-
610
- if (!result.solved) return
611
-
612
- const { route } = result
613
-
614
- const edges: SchematicTrace["edges"] = []
615
-
616
- for (let i = 0; i < route.length - 1; i++) {
617
- const from = route[i]
618
- const to = route[i + 1]
619
-
620
- edges.push({
621
- from,
622
- to,
623
- // TODO to_schematic_port_id and from_schematic_port_id
624
- })
625
- }
626
-
627
- const trace = db.schematic_trace.insert({
628
- source_trace_id: this.source_trace_id!,
629
-
630
- edges,
631
- })
632
-
633
- this.schematic_trace_id = trace.schematic_trace_id
634
- }
635
- }
@@ -1,71 +0,0 @@
1
- import { PrimitiveComponent } from "lib/components/base-components/PrimitiveComponent"
2
- import { traceHintProps } from "@tscircuit/props"
3
- import type { Port } from "./Port"
4
- import type { RouteHintPoint } from "@tscircuit/soup"
5
- import { applyToPoint } from "transformation-matrix"
6
-
7
- export class TraceHint extends PrimitiveComponent<typeof traceHintProps> {
8
- matchedPort: Port | null = null
9
-
10
- doInitialPortMatching(): void {
11
- const { db } = this.root!
12
- const { _parsedProps: props, parent } = this
13
-
14
- if (!parent) return
15
-
16
- if (parent.componentName === "Trace") {
17
- this.renderError(
18
- `Port inference inside trace is not yet supported (${this})`,
19
- )
20
- return
21
- }
22
-
23
- if (!parent) throw new Error("TraceHint has no parent")
24
-
25
- if (!props.for) {
26
- this.renderError(`TraceHint has no for property (${this})`)
27
- return
28
- }
29
-
30
- const port = parent.selectOne(props.for, { type: "port" }) as Port
31
-
32
- if (!port) {
33
- this.renderError(
34
- `${this} could not find port for selector "${props.for}"`,
35
- )
36
- }
37
-
38
- this.matchedPort = port
39
- port.registerMatch(this)
40
- }
41
-
42
- getPcbRouteHints(): Array<RouteHintPoint> {
43
- const { _parsedProps: props } = this
44
-
45
- const offsets = props.offset ? [props.offset] : props.offsets
46
-
47
- if (!offsets) return []
48
-
49
- const globalTransform = this._computePcbGlobalTransformBeforeLayout()
50
-
51
- return offsets.map(
52
- (offset): RouteHintPoint => ({
53
- ...applyToPoint(globalTransform, offset),
54
- via: offset.via,
55
- to_layer: (offset as any).to_layer,
56
- trace_width: (offset as any).trace_width,
57
- }),
58
- )
59
- }
60
-
61
- doInitialPcbTraceHintRender(): void {
62
- const { db } = this.root!
63
- const { _parsedProps: props } = this
64
-
65
- db.pcb_trace_hint.insert({
66
- pcb_component_id: this.matchedPort?.pcb_component_id!,
67
- pcb_port_id: this.matchedPort?.pcb_port_id!,
68
- route: this.getPcbRouteHints(),
69
- })
70
- }
71
- }