Skip to content

Commit 1d9bf4b

Browse files
Merge branch 'main' into f/board_title
2 parents 71db826 + 93a68ce commit 1d9bf4b

File tree

48 files changed

+1137
-1079
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1137
-1079
lines changed

lib/components/base-components/PrimitiveComponent/PrimitiveComponent.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,22 @@ export abstract class PrimitiveComponent<
868868
return super.renderError(message)
869869
}
870870
// TODO this needs to be cleaned up at some point!
871-
this.root?.db.pcb_placement_error.insert(message as any)
871+
switch (message.type) {
872+
case "pcb_placement_error":
873+
this.root?.db.pcb_placement_error.insert(message as any)
874+
break
875+
case "pcb_via_clearance_error":
876+
this.root?.db.pcb_via_clearance_error.insert(message as any)
877+
break
878+
case "pcb_trace_error":
879+
this.root?.db.pcb_trace_error.insert(message as any)
880+
break
881+
case "pcb_manual_edit_conflict_warning":
882+
this.root?.db.pcb_manual_edit_conflict_warning.insert(message as any)
883+
break
884+
default:
885+
this.root?.db.pcb_placement_error.insert(message as any) // fallback
886+
}
872887
}
873888

874889
getString(): string {

lib/components/base-components/Renderable.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
PcbManualEditConflictWarning,
33
PcbPlacementError,
44
PcbTraceError,
5+
PcbViaClearanceError,
56
} from "circuit-json"
67
import Debug from "debug"
78

@@ -342,7 +343,8 @@ export abstract class Renderable implements IRenderable {
342343
| string
343344
| Omit<PcbTraceError, "pcb_error_id">
344345
| Omit<PcbPlacementError, "pcb_error_id">
345-
| Omit<PcbManualEditConflictWarning, "pcb_error_id">,
346+
| Omit<PcbManualEditConflictWarning, "pcb_error_id">
347+
| Omit<PcbViaClearanceError, "pcb_error_id">,
346348
) {
347349
// TODO add to render phase error list and try to add position or
348350
// relationships etc

lib/components/normal-components/Board.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getBoardCenterFromAnchor } from "../../utils/boards/get-board-center-from-anchor"
12
import { boardProps } from "@tscircuit/props"
23
import { type Matrix, identity } from "transformation-matrix"
34
import { Group } from "../primitive-components/Group/Group"
@@ -6,6 +7,8 @@ import {
67
checkEachPcbTraceNonOverlapping,
78
checkPcbComponentsOutOfBoard,
89
checkPcbTracesOutOfBoard,
10+
checkDifferentNetViaSpacing,
11+
checkSameNetViaSpacing,
912
} from "@tscircuit/checks"
1013
import type { RenderPhase } from "../base-components/Renderable"
1114
import { getDescendantSubcircuitIds } from "../../utils/autorouting/getAncestorSubcircuitIds"
@@ -157,6 +160,14 @@ export class Board extends Group<typeof boardProps> {
157160
updateBounds(pcbGroup.center, pcbGroup.width, pcbGroup.height)
158161
}
159162

163+
if (props.boardAnchorPosition) {
164+
const { x, y } = props.boardAnchorPosition
165+
minX = Math.min(minX, x)
166+
minY = Math.min(minY, y)
167+
maxX = Math.max(maxX, x)
168+
maxY = Math.max(maxY, y)
169+
}
170+
160171
// Add padding around components
161172
const padding = 2
162173

@@ -165,7 +176,7 @@ export class Board extends Group<typeof boardProps> {
165176
const computedHeight = hasComponents ? maxY - minY + padding * 2 : 0
166177

167178
// Center the board around the components or use (0,0) for empty boards
168-
const center = {
179+
let center = {
169180
x: hasComponents
170181
? (minX + maxX) / 2 + (props.outlineOffsetX ?? 0)
171182
: (props.outlineOffsetX ?? 0),
@@ -174,7 +185,6 @@ export class Board extends Group<typeof boardProps> {
174185
: (props.outlineOffsetY ?? 0),
175186
}
176187

177-
// Update the board dimensions, preserving any explicit dimension provided
178188
// by the user while auto-calculating the missing one.
179189
const finalWidth = props.width ?? computedWidth
180190
const finalHeight = props.height ?? computedHeight
@@ -267,6 +277,17 @@ export class Board extends Group<typeof boardProps> {
267277
y: (props.pcbY ?? 0) + (props.outlineOffsetY ?? 0),
268278
}
269279

280+
const { boardAnchorPosition, boardAnchorAlignment } = props
281+
282+
if (boardAnchorPosition) {
283+
center = getBoardCenterFromAnchor({
284+
boardAnchorPosition,
285+
boardAnchorAlignment: boardAnchorAlignment ?? "center",
286+
width: computedWidth,
287+
height: computedHeight,
288+
})
289+
}
290+
270291
// Compute width and height from outline if not provided
271292
if (props.outline) {
272293
const xValues = props.outline.map((point) => point.x)
@@ -370,6 +391,16 @@ export class Board extends Group<typeof boardProps> {
370391
for (const error of pcbTracesOutOfBoardErrors) {
371392
db.pcb_trace_error.insert(error)
372393
}
394+
395+
const differentNetViaErrors = checkDifferentNetViaSpacing(db.toArray())
396+
for (const error of differentNetViaErrors) {
397+
db.pcb_via_clearance_error.insert(error)
398+
}
399+
400+
const sameNetViaErrors = checkSameNetViaSpacing(db.toArray())
401+
for (const error of sameNetViaErrors) {
402+
db.pcb_via_clearance_error.insert(error)
403+
}
373404
}
374405

375406
override _emitRenderLifecycleEvent(
Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { analogSimulationProps } from "@tscircuit/props"
1+
import {
2+
analogSimulationProps,
3+
analogSimulationProps as baseAnalogSimulationProps,
4+
} from "@tscircuit/props"
25
import { PrimitiveComponent } from "../base-components/PrimitiveComponent"
6+
import { z } from "zod"
37

48
export class AnalogSimulation extends PrimitiveComponent<
59
typeof analogSimulationProps
@@ -11,8 +15,18 @@ export class AnalogSimulation extends PrimitiveComponent<
1115
}
1216
}
1317

14-
doInitialSourceRender(): void {
15-
// AnalogSimulation is a configuration component that doesn't
16-
// render circuit elements but configures simulation parameters
18+
doInitialSimulationRender(): void {
19+
const { db } = this.root!
20+
const { duration, timePerStep } = this._parsedProps
21+
22+
const durationMs = duration || 10 // ms
23+
const timePerStepMs = timePerStep || 0.01 // ms
24+
25+
db.simulation_experiment.insert({
26+
name: "spice_transient_analysis",
27+
experiment_type: "spice_transient_analysis" as const,
28+
end_time_ms: durationMs,
29+
time_per_step: timePerStepMs,
30+
})
1731
}
1832
}

lib/components/primitive-components/Group/Group.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,14 @@ export class Group<Props extends z.ZodType<any, any, any> = typeof groupProps>
6262

6363
doInitialSourceGroupRender() {
6464
const { db } = this.root!
65+
const hasExplicitName =
66+
typeof (this._parsedProps as { name?: unknown }).name === "string" &&
67+
(this._parsedProps as { name?: string }).name!.length > 0
68+
6569
const source_group = db.source_group.insert({
6670
name: this.name,
6771
is_subcircuit: this.isSubcircuit,
72+
was_automatically_named: !hasExplicitName,
6873
})
6974
this.source_group_id = source_group.source_group_id
7075
if (this.isSubcircuit) {

lib/components/primitive-components/Group/Group_doInitialSimulationSpiceEngineRender.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function Group_doInitialSimulationSpiceEngineRender(group: Group<any>) {
2929
// Convert circuit JSON to SPICE string
3030
let spiceString: string
3131
try {
32-
const spiceNetlist = circuitJsonToSpice(circuitJson)
32+
const spiceNetlist = circuitJsonToSpice(circuitJson as any)
3333
spiceString = spiceNetlist.toSpiceString()
3434
debug(`Generated SPICE string:\n${spiceString}`)
3535
} catch (error) {
@@ -50,8 +50,19 @@ export function Group_doInitialSimulationSpiceEngineRender(group: Group<any>) {
5050
`Simulation completed, received ${result.simulationResultCircuitJson.length} elements`,
5151
)
5252

53+
const simulationExperiment = root.db.simulation_experiment.list()[0]
54+
if (!simulationExperiment) {
55+
debug("No simulation experiment found, skipping result insertion")
56+
return
57+
}
58+
5359
// Add simulation results to the database
5460
for (const element of result.simulationResultCircuitJson) {
61+
if (element.type === "simulation_transient_voltage_graph") {
62+
element.simulation_experiment_id =
63+
simulationExperiment.simulation_experiment_id
64+
}
65+
5566
// Insert the simulation result into the database
5667
const elementType = element.type
5768
if (elementType && (root.db as any)[elementType]) {

lib/spice/get-spicey-engine.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,13 @@
11
import type { SpiceEngine } from "@tscircuit/props"
2-
import type { SimulationExperiment } from "circuit-json"
32
import { simulate, spiceyTranToVGraphs } from "spicey"
43

54
export const getSpiceyEngine = (): SpiceEngine => {
65
return {
76
async simulate(spiceString: string) {
87
const simulation_experiment_id = "spice-experiment-1"
98

10-
// Add .tran directive before .END if not present
11-
let spiceNetlist = spiceString
12-
if (!spiceNetlist.includes(".tran")) {
13-
spiceNetlist = spiceNetlist.replace(/\.END/i, ".tran 1us 10ms\n.END")
14-
}
15-
169
// Run spicey simulation
17-
const { circuit: parsedCircuit, tran } = simulate(spiceNetlist)
10+
const { circuit: parsedCircuit, tran } = simulate(spiceString)
1811

1912
// Convert transient results to voltage graphs
2013
const voltageGraphs = spiceyTranToVGraphs(
@@ -24,13 +17,7 @@ export const getSpiceyEngine = (): SpiceEngine => {
2417
)
2518

2619
return {
27-
simulationResultCircuitJson: [
28-
{
29-
type: "simulation_experiment",
30-
simulation_experiment_id,
31-
} as SimulationExperiment,
32-
...voltageGraphs,
33-
],
20+
simulationResultCircuitJson: voltageGraphs,
3421
}
3522
},
3623
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
export const getBoardCenterFromAnchor = ({
2+
boardAnchorPosition,
3+
boardAnchorAlignment,
4+
width,
5+
height,
6+
}: {
7+
boardAnchorPosition: { x: number; y: number }
8+
boardAnchorAlignment: string
9+
width: number
10+
height: number
11+
}) => {
12+
const { x: ax, y: ay } = boardAnchorPosition
13+
14+
let cx = ax
15+
let cy = ay
16+
17+
switch (boardAnchorAlignment) {
18+
case "top_left":
19+
cx = ax + width / 2
20+
cy = ay - height / 2
21+
break
22+
case "top_right":
23+
cx = ax - width / 2
24+
cy = ay - height / 2
25+
break
26+
case "bottom_left":
27+
cx = ax + width / 2
28+
cy = ay + height / 2
29+
break
30+
case "bottom_right":
31+
cx = ax - width / 2
32+
cy = ay + height / 2
33+
break
34+
case "top":
35+
cx = ax
36+
cy = ay - height / 2
37+
break
38+
case "bottom":
39+
cx = ax
40+
cy = ay + height / 2
41+
break
42+
case "left":
43+
cx = ax + width / 2
44+
cy = ay
45+
break
46+
case "right":
47+
cx = ax - width / 2
48+
cy = ay
49+
break
50+
case "center":
51+
default:
52+
// center is the default
53+
break
54+
}
55+
56+
return { x: cx, y: cy }
57+
}

package.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@tscircuit/core",
33
"type": "module",
4-
"version": "0.0.764",
4+
"version": "0.0.770",
55
"types": "dist/index.d.ts",
66
"main": "dist/index.js",
77
"module": "dist/index.js",
@@ -30,9 +30,10 @@
3030
},
3131
"devDependencies": {
3232
"@biomejs/biome": "^1.8.3",
33-
"@tscircuit/capacity-autorouter": "^0.0.129",
34-
"@tscircuit/checks": "^0.0.79",
33+
"@tscircuit/capacity-autorouter": "^0.0.131",
34+
"@tscircuit/checks": "^0.0.84",
3535
"@tscircuit/circuit-json-util": "^0.0.67",
36+
"@tscircuit/common": "^0.0.9",
3637
"@tscircuit/footprinter": "^0.0.236",
3738
"@tscircuit/import-snippet": "^0.0.4",
3839
"@tscircuit/infgrid-ijump-astar": "^0.0.33",
@@ -43,7 +44,7 @@
4344
"@tscircuit/props": "^0.0.353",
4445
"@tscircuit/schematic-autolayout": "^0.0.6",
4546
"@tscircuit/schematic-match-adapt": "^0.0.16",
46-
"@tscircuit/schematic-trace-solver": "^0.0.40",
47+
"@tscircuit/schematic-trace-solver": "^0.0.41",
4748
"@types/bun": "^1.2.16",
4849
"@types/debug": "^4.1.12",
4950
"@types/react": "^19.1.8",
@@ -53,12 +54,12 @@
5354
"bun-match-svg": "0.0.12",
5455
"calculate-elbow": "^0.0.12",
5556
"chokidar-cli": "^3.0.0",
56-
"circuit-json": "^0.0.268",
57+
"circuit-json": "^0.0.273",
5758
"circuit-json-to-bpc": "^0.0.13",
5859
"circuit-json-to-connectivity-map": "^0.0.22",
5960
"circuit-json-to-gltf": "^0.0.7",
6061
"circuit-json-to-simple-3d": "^0.0.9",
61-
"circuit-json-to-spice": "^0.0.10",
62+
"circuit-json-to-spice": "^0.0.13",
6263
"circuit-to-svg": "^0.0.221",
6364
"concurrently": "^9.1.2",
6465
"connectivity-map": "^1.0.0",
@@ -99,7 +100,7 @@
99100
"dependencies": {
100101
"@flatten-js/core": "^1.6.2",
101102
"@lume/kiwi": "^0.4.3",
102-
"calculate-packing": "0.0.41",
103+
"calculate-packing": "0.0.48",
103104
"css-select": "5.1.0",
104105
"format-si-unit": "^0.0.3",
105106
"nanoid": "^5.0.7",

tests/components/normal-components/__snapshots__/capacitor-polarized-schematic.snap.svg

Lines changed: 67 additions & 115 deletions
Loading

0 commit comments

Comments
 (0)