-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathrenderCircuitToSvg.ts
More file actions
114 lines (99 loc) · 3.21 KB
/
renderCircuitToSvg.ts
File metadata and controls
114 lines (99 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import {
convertCircuitJsonToAssemblySvg,
convertCircuitJsonToPcbSvg,
convertCircuitJsonToSchematicSvg,
convertCircuitJsonToPinoutSvg,
convertCircuitJsonToSchematicSimulationSvg,
} from "circuit-to-svg"
import { render3dPng } from "./render3dPng"
import { Buffer } from "node:buffer"
import * as vectorizerMod from "@neplex/vectorizer"
export interface RenderOptions {
backgroundColor?: string
backgroundOpacity?: number
zoomMultiplier?: number
simulationExperimentId?: string
simulationTransientVoltageGraphIds?: string[]
schematicHeightRatio?: number
}
export type SvgRenderType =
| "pcb"
| "schematic"
| "pinout"
| "assembly"
| "3d"
| "schsim"
export async function renderCircuitToSvg(
circuitJson: any,
svgType: SvgRenderType,
options: RenderOptions = {},
): Promise<string> {
const {
backgroundColor = "#fff",
backgroundOpacity = 0.0,
zoomMultiplier = 1.2,
} = options
const bgOpacity = Number.isFinite(backgroundOpacity) ? backgroundOpacity : 0.0
const zoom = Number.isFinite(zoomMultiplier) ? zoomMultiplier : 1.2
if (svgType === "assembly") {
return convertCircuitJsonToAssemblySvg(circuitJson)
}
if (svgType === "pcb") {
return convertCircuitJsonToPcbSvg(circuitJson)
}
if (svgType === "schematic") {
return convertCircuitJsonToSchematicSvg(circuitJson)
}
if (svgType === "schsim") {
if (!options.simulationExperimentId) {
throw new Error(
"simulation_experiment_id is required when rendering schsim SVG output",
)
}
return convertCircuitJsonToSchematicSimulationSvg({
circuitJson,
simulation_experiment_id: options.simulationExperimentId,
simulation_transient_voltage_graph_ids:
options.simulationTransientVoltageGraphIds,
schematicHeightRatio: options.schematicHeightRatio,
})
}
if (svgType === "pinout") {
return convertCircuitJsonToPinoutSvg(circuitJson)
}
if (svgType === "3d") {
const pngBinary = await render3dPng(circuitJson, {
width: 1024,
height: 1024,
zoomMultiplier: zoom,
})
try {
const vectorize = vectorizerMod.vectorize
// Add missing required properties for vectorize config
const svgResult = await vectorize(Buffer.from(pngBinary), {
mode: vectorizerMod.PathSimplifyMode.Polygon,
colorMode: vectorizerMod.ColorMode.Color,
hierarchical: vectorizerMod.Hierarchical.Stacked,
filterSpeckle: 8,
colorPrecision: 8,
layerDifference: 8,
maxIterations: 100,
// Set required threshold properties with reasonable defaults
cornerThreshold: 60,
lengthThreshold: 4,
spliceThreshold: 30,
})
if (bgOpacity > 0) {
return svgResult.replace(
/<svg([^>]*)>/,
`<svg$1><rect width="100%" height="100%" fill="${backgroundColor}" fill-opacity="${bgOpacity}"/>`,
)
}
return svgResult
} catch {
const base64 = Buffer.from(pngBinary).toString("base64")
return `<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024"><image href="data:image/png;base64,${base64}" width="1024" height="1024"/></svg>`
}
}
throw new Error(`Invalid SVG type: ${svgType}`)
}