kicadts 0.0.1
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/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
- package/.vscode/settings.json +16 -0
- package/AGENTS.md +30 -0
- package/README.md +206 -0
- package/biome.json +93 -0
- package/bun.lock +48 -0
- package/bunfig.toml +5 -0
- package/lib/index.ts +1 -0
- package/lib/sexpr/base-classes/SxClass.ts +164 -0
- package/lib/sexpr/base-classes/SxPrimitiveBoolean.ts +35 -0
- package/lib/sexpr/base-classes/SxPrimitiveNumber.ts +26 -0
- package/lib/sexpr/base-classes/SxPrimitiveString.ts +26 -0
- package/lib/sexpr/classes/At.ts +38 -0
- package/lib/sexpr/classes/Bus.ts +83 -0
- package/lib/sexpr/classes/BusEntry.ts +142 -0
- package/lib/sexpr/classes/Color.ts +29 -0
- package/lib/sexpr/classes/Dnp.ts +8 -0
- package/lib/sexpr/classes/EmbeddedFonts.ts +70 -0
- package/lib/sexpr/classes/ExcludeFromSim.ts +8 -0
- package/lib/sexpr/classes/FieldsAutoplaced.ts +8 -0
- package/lib/sexpr/classes/Footprint.ts +719 -0
- package/lib/sexpr/classes/FootprintAttr.ts +102 -0
- package/lib/sexpr/classes/FootprintAutoplaceCost180.ts +9 -0
- package/lib/sexpr/classes/FootprintAutoplaceCost90.ts +9 -0
- package/lib/sexpr/classes/FootprintClearance.ts +9 -0
- package/lib/sexpr/classes/FootprintDescr.ts +44 -0
- package/lib/sexpr/classes/FootprintLocked.ts +32 -0
- package/lib/sexpr/classes/FootprintModel.ts +145 -0
- package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +50 -0
- package/lib/sexpr/classes/FootprintPad.ts +705 -0
- package/lib/sexpr/classes/FootprintPath.ts +44 -0
- package/lib/sexpr/classes/FootprintPlaced.ts +32 -0
- package/lib/sexpr/classes/FootprintPrivateLayers.ts +56 -0
- package/lib/sexpr/classes/FootprintSheetfile.ts +44 -0
- package/lib/sexpr/classes/FootprintSheetname.ts +44 -0
- package/lib/sexpr/classes/FootprintSolderMaskMargin.ts +9 -0
- package/lib/sexpr/classes/FootprintSolderPasteMargin.ts +9 -0
- package/lib/sexpr/classes/FootprintSolderPasteRatio.ts +9 -0
- package/lib/sexpr/classes/FootprintTags.ts +44 -0
- package/lib/sexpr/classes/FootprintTedit.ts +21 -0
- package/lib/sexpr/classes/FootprintThermalGap.ts +9 -0
- package/lib/sexpr/classes/FootprintThermalWidth.ts +9 -0
- package/lib/sexpr/classes/FootprintZoneConnect.ts +9 -0
- package/lib/sexpr/classes/FpArc.ts +289 -0
- package/lib/sexpr/classes/FpCircle.ts +293 -0
- package/lib/sexpr/classes/FpLine.ts +288 -0
- package/lib/sexpr/classes/FpPoly.ts +266 -0
- package/lib/sexpr/classes/FpPolyFill.ts +48 -0
- package/lib/sexpr/classes/FpPolyLocked.ts +40 -0
- package/lib/sexpr/classes/FpRect.ts +293 -0
- package/lib/sexpr/classes/FpText.ts +341 -0
- package/lib/sexpr/classes/FpTextBox.ts +412 -0
- package/lib/sexpr/classes/GrLine.ts +245 -0
- package/lib/sexpr/classes/GrLineAngle.ts +32 -0
- package/lib/sexpr/classes/GrLineEnd.ts +61 -0
- package/lib/sexpr/classes/GrLineLocked.ts +40 -0
- package/lib/sexpr/classes/GrLineStart.ts +61 -0
- package/lib/sexpr/classes/GrText.ts +202 -0
- package/lib/sexpr/classes/Image.ts +256 -0
- package/lib/sexpr/classes/InBom.ts +8 -0
- package/lib/sexpr/classes/Junction.ts +134 -0
- package/lib/sexpr/classes/KicadPcb.ts +313 -0
- package/lib/sexpr/classes/KicadSch.ts +303 -0
- package/lib/sexpr/classes/KicadSchGenerator.ts +32 -0
- package/lib/sexpr/classes/KicadSchGeneratorVersion.ts +30 -0
- package/lib/sexpr/classes/KicadSchVersion.ts +22 -0
- package/lib/sexpr/classes/Label.ts +136 -0
- package/lib/sexpr/classes/Layer.ts +51 -0
- package/lib/sexpr/classes/Layers.ts +47 -0
- package/lib/sexpr/classes/LibSymbols.ts +61 -0
- package/lib/sexpr/classes/NoConnect.ts +73 -0
- package/lib/sexpr/classes/OnBoard.ts +8 -0
- package/lib/sexpr/classes/PadChamfer.ts +50 -0
- package/lib/sexpr/classes/PadChamferRatio.ts +9 -0
- package/lib/sexpr/classes/PadClearance.ts +9 -0
- package/lib/sexpr/classes/PadDieLength.ts +9 -0
- package/lib/sexpr/classes/PadDrill.ts +145 -0
- package/lib/sexpr/classes/PadDrillOffset.ts +54 -0
- package/lib/sexpr/classes/PadLayers.ts +59 -0
- package/lib/sexpr/classes/PadNet.ts +56 -0
- package/lib/sexpr/classes/PadOptions.ts +182 -0
- package/lib/sexpr/classes/PadPinFunction.ts +9 -0
- package/lib/sexpr/classes/PadPinType.ts +9 -0
- package/lib/sexpr/classes/PadPrimitiveGrArc.ts +254 -0
- package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +279 -0
- package/lib/sexpr/classes/PadPrimitiveGrLine.ts +126 -0
- package/lib/sexpr/classes/PadPrimitives.ts +289 -0
- package/lib/sexpr/classes/PadRectDelta.ts +57 -0
- package/lib/sexpr/classes/PadRoundrectRratio.ts +9 -0
- package/lib/sexpr/classes/PadSize.ts +54 -0
- package/lib/sexpr/classes/PadSolderMaskMargin.ts +9 -0
- package/lib/sexpr/classes/PadSolderPasteMargin.ts +9 -0
- package/lib/sexpr/classes/PadSolderPasteMarginRatio.ts +9 -0
- package/lib/sexpr/classes/PadTeardrops.ts +208 -0
- package/lib/sexpr/classes/PadThermalBridgeAngle.ts +9 -0
- package/lib/sexpr/classes/PadThermalGap.ts +9 -0
- package/lib/sexpr/classes/PadThermalWidth.ts +9 -0
- package/lib/sexpr/classes/PadZoneConnect.ts +9 -0
- package/lib/sexpr/classes/Paper.ts +119 -0
- package/lib/sexpr/classes/PcbGeneral.ts +75 -0
- package/lib/sexpr/classes/PcbGeneralLegacyTeardrops.ts +44 -0
- package/lib/sexpr/classes/PcbGeneralThickness.ts +9 -0
- package/lib/sexpr/classes/PcbGenerator.ts +16 -0
- package/lib/sexpr/classes/PcbGeneratorVersion.ts +16 -0
- package/lib/sexpr/classes/PcbLayerDefinition.ts +102 -0
- package/lib/sexpr/classes/PcbLayers.ts +34 -0
- package/lib/sexpr/classes/PcbNet.ts +56 -0
- package/lib/sexpr/classes/PcbVersion.ts +9 -0
- package/lib/sexpr/classes/Property.ts +246 -0
- package/lib/sexpr/classes/PropertyHide.ts +9 -0
- package/lib/sexpr/classes/PropertyUnlocked.ts +9 -0
- package/lib/sexpr/classes/Pts.ts +65 -0
- package/lib/sexpr/classes/RenderCache.ts +221 -0
- package/lib/sexpr/classes/SchematicText.ts +141 -0
- package/lib/sexpr/classes/Segment.ts +222 -0
- package/lib/sexpr/classes/SegmentEnd.ts +59 -0
- package/lib/sexpr/classes/SegmentLocked.ts +33 -0
- package/lib/sexpr/classes/SegmentNet.ts +62 -0
- package/lib/sexpr/classes/SegmentStart.ts +59 -0
- package/lib/sexpr/classes/Setup/PcbPlotParams.ts +729 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsBase.ts +9 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsNumericProperties.ts +105 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesA.ts +104 -0
- package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesB.ts +105 -0
- package/lib/sexpr/classes/Setup/Setup.ts +573 -0
- package/lib/sexpr/classes/Setup/SetupPropertyTypes.ts +119 -0
- package/lib/sexpr/classes/Setup/Stackup.ts +140 -0
- package/lib/sexpr/classes/Setup/StackupLayer.ts +233 -0
- package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +78 -0
- package/lib/sexpr/classes/Setup/StackupProperties.ts +41 -0
- package/lib/sexpr/classes/Setup/base.ts +167 -0
- package/lib/sexpr/classes/Setup/index.ts +14 -0
- package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +54 -0
- package/lib/sexpr/classes/Setup/setupNumericProperties.ts +151 -0
- package/lib/sexpr/classes/Setup/setupPropertyHandlers.ts +90 -0
- package/lib/sexpr/classes/Setup/setupStringProperties.ts +75 -0
- package/lib/sexpr/classes/Sheet.ts +205 -0
- package/lib/sexpr/classes/SheetFill.ts +44 -0
- package/lib/sexpr/classes/SheetInstances.ts +168 -0
- package/lib/sexpr/classes/SheetInstancesRoot.ts +165 -0
- package/lib/sexpr/classes/SheetPin.ts +122 -0
- package/lib/sexpr/classes/SheetProperty.ts +115 -0
- package/lib/sexpr/classes/SheetSize.ts +44 -0
- package/lib/sexpr/classes/Stroke.ts +58 -0
- package/lib/sexpr/classes/StrokeType.ts +34 -0
- package/lib/sexpr/classes/Symbol.ts +1541 -0
- package/lib/sexpr/classes/TextEffects.ts +444 -0
- package/lib/sexpr/classes/TitleBlock.ts +352 -0
- package/lib/sexpr/classes/Unit.ts +28 -0
- package/lib/sexpr/classes/Uuid.ts +8 -0
- package/lib/sexpr/classes/Via.ts +328 -0
- package/lib/sexpr/classes/ViaNet.ts +59 -0
- package/lib/sexpr/classes/Width.ts +8 -0
- package/lib/sexpr/classes/Wire.ts +91 -0
- package/lib/sexpr/classes/Xy.ts +35 -0
- package/lib/sexpr/classes/Zone.ts +41 -0
- package/lib/sexpr/index.ts +130 -0
- package/lib/sexpr/parseKicadSexpr.ts +5 -0
- package/lib/sexpr/parseToPrimitiveSExpr.ts +240 -0
- package/lib/sexpr/utils/indentLines.ts +3 -0
- package/lib/sexpr/utils/parseYesNo.ts +12 -0
- package/lib/sexpr/utils/quoteSExprString.ts +8 -0
- package/lib/sexpr/utils/strokeFromArgs.ts +19 -0
- package/lib/sexpr/utils/toNumberValue.ts +13 -0
- package/lib/sexpr/utils/toStringValue.ts +10 -0
- package/package.json +26 -0
- package/scripts/download-references.ts +66 -0
- package/tests/fixtures/expectEqualPrimitiveSExpr.ts +200 -0
- package/tests/sexpr/KicadPcbDemos.test.ts +48 -0
- package/tests/sexpr/KicadSchDemos.test.ts +49 -0
- package/tests/sexpr/classes/Footprint.test.ts +277 -0
- package/tests/sexpr/classes/FootprintPad.test.ts +71 -0
- package/tests/sexpr/classes/FpArc.test.ts +45 -0
- package/tests/sexpr/classes/FpCircle.test.ts +39 -0
- package/tests/sexpr/classes/FpPoly.test.ts +43 -0
- package/tests/sexpr/classes/FpRect.test.ts +40 -0
- package/tests/sexpr/classes/FpTextBox.test.ts +84 -0
- package/tests/sexpr/classes/Image.test.ts +50 -0
- package/tests/sexpr/classes/KicadSch.test.ts +97 -0
- package/tests/sexpr/classes/Paper.test.ts +30 -0
- package/tests/sexpr/classes/Property.test.ts +48 -0
- package/tests/sexpr/classes/Setup.test.ts +189 -0
- package/tests/sexpr/classes/Sheet.test.ts +107 -0
- package/tests/sexpr/classes/Stroke.test.ts +15 -0
- package/tests/sexpr/classes/Symbol.test.ts +96 -0
- package/tests/sexpr/classes/TextEffects.test.ts +56 -0
- package/tests/sexpr/classes/TitleBlock.test.ts +40 -0
- package/tsconfig.json +35 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { Width } from "./Width"
|
|
4
|
+
import { toNumberValue } from "../utils/toNumberValue"
|
|
5
|
+
|
|
6
|
+
const SUPPORTED_TOKENS = new Set(["start", "mid", "end", "width"])
|
|
7
|
+
|
|
8
|
+
export class PadPrimitiveGrArc extends SxClass {
|
|
9
|
+
static override token = "gr_arc"
|
|
10
|
+
static override parentToken = "primitives"
|
|
11
|
+
override token = "gr_arc"
|
|
12
|
+
|
|
13
|
+
private _sxStart?: PadPrimitiveGrArcStart
|
|
14
|
+
private _sxMid?: PadPrimitiveGrArcMid
|
|
15
|
+
private _sxEnd?: PadPrimitiveGrArcEnd
|
|
16
|
+
private _sxWidth?: Width
|
|
17
|
+
|
|
18
|
+
static override fromSexprPrimitives(
|
|
19
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
20
|
+
): PadPrimitiveGrArc {
|
|
21
|
+
const arc = new PadPrimitiveGrArc()
|
|
22
|
+
|
|
23
|
+
const { propertyMap, arrayPropertyMap } =
|
|
24
|
+
SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
|
|
25
|
+
|
|
26
|
+
for (const token of Object.keys(propertyMap)) {
|
|
27
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`pad primitive gr_arc encountered unsupported child token "${token}"`,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (const [token, entries] of Object.entries(arrayPropertyMap)) {
|
|
35
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`pad primitive gr_arc encountered unsupported child token "${token}"`,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
if (entries.length > 1) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`pad primitive gr_arc does not support repeated "${token}" tokens`,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
arc._sxStart = propertyMap.start as PadPrimitiveGrArcStart | undefined
|
|
48
|
+
arc._sxMid = propertyMap.mid as PadPrimitiveGrArcMid | undefined
|
|
49
|
+
arc._sxEnd = propertyMap.end as PadPrimitiveGrArcEnd | undefined
|
|
50
|
+
arc._sxWidth = propertyMap.width as Width | undefined
|
|
51
|
+
|
|
52
|
+
if (!arc._sxStart) {
|
|
53
|
+
throw new Error("pad primitive gr_arc requires a start child token")
|
|
54
|
+
}
|
|
55
|
+
if (!arc._sxMid) {
|
|
56
|
+
throw new Error("pad primitive gr_arc requires a mid child token")
|
|
57
|
+
}
|
|
58
|
+
if (!arc._sxEnd) {
|
|
59
|
+
throw new Error("pad primitive gr_arc requires an end child token")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return arc
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get start(): PadPrimitiveGrArcStart | undefined {
|
|
66
|
+
return this._sxStart
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
set start(
|
|
70
|
+
value: PadPrimitiveGrArcStart | { x: number; y: number } | undefined,
|
|
71
|
+
) {
|
|
72
|
+
this._sxStart = normalizeArcPoint(value, PadPrimitiveGrArcStart)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get mid(): PadPrimitiveGrArcMid | undefined {
|
|
76
|
+
return this._sxMid
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set mid(value: PadPrimitiveGrArcMid | { x: number; y: number } | undefined) {
|
|
80
|
+
this._sxMid = normalizeArcPoint(value, PadPrimitiveGrArcMid)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get end(): PadPrimitiveGrArcEnd | undefined {
|
|
84
|
+
return this._sxEnd
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
set end(value: PadPrimitiveGrArcEnd | { x: number; y: number } | undefined) {
|
|
88
|
+
this._sxEnd = normalizeArcPoint(value, PadPrimitiveGrArcEnd)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get width(): number | undefined {
|
|
92
|
+
return this._sxWidth?.value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
set width(value: Width | number | undefined) {
|
|
96
|
+
if (value === undefined) {
|
|
97
|
+
this._sxWidth = undefined
|
|
98
|
+
return
|
|
99
|
+
}
|
|
100
|
+
this._sxWidth = value instanceof Width ? value : new Width(value)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
get widthClass(): Width | undefined {
|
|
104
|
+
return this._sxWidth
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
override getChildren(): SxClass[] {
|
|
108
|
+
const children: SxClass[] = []
|
|
109
|
+
if (this._sxStart) children.push(this._sxStart)
|
|
110
|
+
if (this._sxMid) children.push(this._sxMid)
|
|
111
|
+
if (this._sxEnd) children.push(this._sxEnd)
|
|
112
|
+
if (this._sxWidth) children.push(this._sxWidth)
|
|
113
|
+
return children
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
override getString(): string {
|
|
117
|
+
const lines = ["(gr_arc"]
|
|
118
|
+
if (this._sxStart) lines.push(this._sxStart.getStringIndented())
|
|
119
|
+
if (this._sxMid) lines.push(this._sxMid.getStringIndented())
|
|
120
|
+
if (this._sxEnd) lines.push(this._sxEnd.getStringIndented())
|
|
121
|
+
if (this._sxWidth) lines.push(this._sxWidth.getStringIndented())
|
|
122
|
+
lines.push(")")
|
|
123
|
+
return lines.join("\n")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
SxClass.register(PadPrimitiveGrArc)
|
|
127
|
+
|
|
128
|
+
type ArcPointConstructor<T extends PadPrimitiveGrArcPoint> = new (
|
|
129
|
+
x: number,
|
|
130
|
+
y: number,
|
|
131
|
+
) => T
|
|
132
|
+
|
|
133
|
+
const normalizeArcPoint = <T extends PadPrimitiveGrArcPoint>(
|
|
134
|
+
value: T | { x: number; y: number } | undefined,
|
|
135
|
+
Constructor: ArcPointConstructor<T>,
|
|
136
|
+
): T | undefined => {
|
|
137
|
+
if (value === undefined) {
|
|
138
|
+
return undefined
|
|
139
|
+
}
|
|
140
|
+
if (value instanceof Constructor) {
|
|
141
|
+
return value
|
|
142
|
+
}
|
|
143
|
+
return new Constructor(value.x, value.y)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
abstract class PadPrimitiveGrArcPoint extends SxClass {
|
|
147
|
+
protected _x: number
|
|
148
|
+
protected _y: number
|
|
149
|
+
|
|
150
|
+
protected constructor(x: number, y: number) {
|
|
151
|
+
super()
|
|
152
|
+
this._x = x
|
|
153
|
+
this._y = y
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get x(): number {
|
|
157
|
+
return this._x
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
set x(value: number) {
|
|
161
|
+
this._x = value
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
get y(): number {
|
|
165
|
+
return this._y
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
set y(value: number) {
|
|
169
|
+
this._y = value
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override getChildren(): SxClass[] {
|
|
173
|
+
return []
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
override getString(): string {
|
|
177
|
+
return `(${this.token} ${this._x} ${this._y})`
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
class PadPrimitiveGrArcStart extends PadPrimitiveGrArcPoint {
|
|
182
|
+
static override token = "start"
|
|
183
|
+
static override parentToken = "gr_arc"
|
|
184
|
+
override token = "start"
|
|
185
|
+
|
|
186
|
+
constructor(x: number, y: number) {
|
|
187
|
+
super(x, y)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
static override fromSexprPrimitives(
|
|
191
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
192
|
+
): PadPrimitiveGrArcStart {
|
|
193
|
+
const [rawX, rawY] = primitiveSexprs
|
|
194
|
+
const x = toNumberValue(rawX)
|
|
195
|
+
const y = toNumberValue(rawY)
|
|
196
|
+
|
|
197
|
+
if (x === undefined || y === undefined) {
|
|
198
|
+
throw new Error("pad primitive gr_arc start expects two numeric arguments")
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return new PadPrimitiveGrArcStart(x, y)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
SxClass.register(PadPrimitiveGrArcStart)
|
|
205
|
+
|
|
206
|
+
class PadPrimitiveGrArcMid extends PadPrimitiveGrArcPoint {
|
|
207
|
+
static override token = "mid"
|
|
208
|
+
static override parentToken = "gr_arc"
|
|
209
|
+
override token = "mid"
|
|
210
|
+
|
|
211
|
+
constructor(x: number, y: number) {
|
|
212
|
+
super(x, y)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static override fromSexprPrimitives(
|
|
216
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
217
|
+
): PadPrimitiveGrArcMid {
|
|
218
|
+
const [rawX, rawY] = primitiveSexprs
|
|
219
|
+
const x = toNumberValue(rawX)
|
|
220
|
+
const y = toNumberValue(rawY)
|
|
221
|
+
|
|
222
|
+
if (x === undefined || y === undefined) {
|
|
223
|
+
throw new Error("pad primitive gr_arc mid expects two numeric arguments")
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return new PadPrimitiveGrArcMid(x, y)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
SxClass.register(PadPrimitiveGrArcMid)
|
|
230
|
+
|
|
231
|
+
class PadPrimitiveGrArcEnd extends PadPrimitiveGrArcPoint {
|
|
232
|
+
static override token = "end"
|
|
233
|
+
static override parentToken = "gr_arc"
|
|
234
|
+
override token = "end"
|
|
235
|
+
|
|
236
|
+
constructor(x: number, y: number) {
|
|
237
|
+
super(x, y)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
static override fromSexprPrimitives(
|
|
241
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
242
|
+
): PadPrimitiveGrArcEnd {
|
|
243
|
+
const [rawX, rawY] = primitiveSexprs
|
|
244
|
+
const x = toNumberValue(rawX)
|
|
245
|
+
const y = toNumberValue(rawY)
|
|
246
|
+
|
|
247
|
+
if (x === undefined || y === undefined) {
|
|
248
|
+
throw new Error("pad primitive gr_arc end expects two numeric arguments")
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return new PadPrimitiveGrArcEnd(x, y)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
SxClass.register(PadPrimitiveGrArcEnd)
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import { SxPrimitiveBoolean } from "../base-classes/SxPrimitiveBoolean"
|
|
3
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
4
|
+
import { Width } from "./Width"
|
|
5
|
+
import { toNumberValue } from "../utils/toNumberValue"
|
|
6
|
+
|
|
7
|
+
const SUPPORTED_TOKENS = new Set(["center", "end", "width", "fill"])
|
|
8
|
+
|
|
9
|
+
export class PadPrimitiveGrCircle extends SxClass {
|
|
10
|
+
static override token = "gr_circle"
|
|
11
|
+
static override parentToken = "primitives"
|
|
12
|
+
override token = "gr_circle"
|
|
13
|
+
|
|
14
|
+
private _sxCenter?: PadPrimitiveGrCircleCenter
|
|
15
|
+
private _sxEnd?: PadPrimitiveGrCircleEnd
|
|
16
|
+
private _sxWidth?: Width
|
|
17
|
+
private _sxFill?: PadPrimitiveGrCircleFill
|
|
18
|
+
|
|
19
|
+
static override fromSexprPrimitives(
|
|
20
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
21
|
+
): PadPrimitiveGrCircle {
|
|
22
|
+
const circle = new PadPrimitiveGrCircle()
|
|
23
|
+
|
|
24
|
+
const { propertyMap, arrayPropertyMap } =
|
|
25
|
+
SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
|
|
26
|
+
|
|
27
|
+
for (const token of Object.keys(propertyMap)) {
|
|
28
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`pad primitive gr_circle encountered unsupported child token "${token}"`,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const [token, entries] of Object.entries(arrayPropertyMap)) {
|
|
36
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`pad primitive gr_circle encountered unsupported child token "${token}"`,
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
if (entries.length > 1) {
|
|
42
|
+
throw new Error(
|
|
43
|
+
`pad primitive gr_circle does not support repeated "${token}" tokens`,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
circle._sxCenter = propertyMap.center as
|
|
49
|
+
| PadPrimitiveGrCircleCenter
|
|
50
|
+
| undefined
|
|
51
|
+
circle._sxEnd = propertyMap.end as PadPrimitiveGrCircleEnd | undefined
|
|
52
|
+
circle._sxWidth = propertyMap.width as Width | undefined
|
|
53
|
+
circle._sxFill = propertyMap.fill as PadPrimitiveGrCircleFill | undefined
|
|
54
|
+
|
|
55
|
+
if (!circle._sxCenter) {
|
|
56
|
+
throw new Error("pad primitive gr_circle requires a center child token")
|
|
57
|
+
}
|
|
58
|
+
if (!circle._sxEnd) {
|
|
59
|
+
throw new Error("pad primitive gr_circle requires an end child token")
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return circle
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get center(): PadPrimitiveGrCircleCenter | undefined {
|
|
66
|
+
return this._sxCenter
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
set center(
|
|
70
|
+
value: PadPrimitiveGrCircleCenter | { x: number; y: number } | undefined,
|
|
71
|
+
) {
|
|
72
|
+
this._sxCenter = normalizeCirclePoint(value, PadPrimitiveGrCircleCenter)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get end(): PadPrimitiveGrCircleEnd | undefined {
|
|
76
|
+
return this._sxEnd
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set end(value: PadPrimitiveGrCircleEnd | { x: number; y: number } | undefined) {
|
|
80
|
+
this._sxEnd = normalizeCirclePoint(value, PadPrimitiveGrCircleEnd)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get width(): number | undefined {
|
|
84
|
+
return this._sxWidth?.value
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
set width(value: Width | number | undefined) {
|
|
88
|
+
if (value === undefined) {
|
|
89
|
+
this._sxWidth = undefined
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
this._sxWidth = value instanceof Width ? value : new Width(value)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get widthClass(): Width | undefined {
|
|
96
|
+
return this._sxWidth
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
get fill(): boolean | undefined {
|
|
100
|
+
return this._sxFill?.value
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
set fill(value: PadPrimitiveGrCircleFill | boolean | undefined) {
|
|
104
|
+
if (value === undefined) {
|
|
105
|
+
this._sxFill = undefined
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
this._sxFill =
|
|
109
|
+
value instanceof PadPrimitiveGrCircleFill
|
|
110
|
+
? value
|
|
111
|
+
: new PadPrimitiveGrCircleFill(value)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get fillClass(): PadPrimitiveGrCircleFill | undefined {
|
|
115
|
+
return this._sxFill
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
override getChildren(): SxClass[] {
|
|
119
|
+
const children: SxClass[] = []
|
|
120
|
+
if (this._sxCenter) children.push(this._sxCenter)
|
|
121
|
+
if (this._sxEnd) children.push(this._sxEnd)
|
|
122
|
+
if (this._sxWidth) children.push(this._sxWidth)
|
|
123
|
+
if (this._sxFill) children.push(this._sxFill)
|
|
124
|
+
return children
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
override getString(): string {
|
|
128
|
+
const lines = ["(gr_circle"]
|
|
129
|
+
if (this._sxCenter) lines.push(this._sxCenter.getStringIndented())
|
|
130
|
+
if (this._sxEnd) lines.push(this._sxEnd.getStringIndented())
|
|
131
|
+
if (this._sxWidth) lines.push(this._sxWidth.getStringIndented())
|
|
132
|
+
if (this._sxFill) lines.push(this._sxFill.getStringIndented())
|
|
133
|
+
lines.push(")")
|
|
134
|
+
return lines.join("\n")
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
SxClass.register(PadPrimitiveGrCircle)
|
|
138
|
+
|
|
139
|
+
type CirclePointConstructor<T extends PadPrimitiveGrCirclePoint> = new (
|
|
140
|
+
x: number,
|
|
141
|
+
y: number,
|
|
142
|
+
) => T
|
|
143
|
+
|
|
144
|
+
const normalizeCirclePoint = <T extends PadPrimitiveGrCirclePoint>(
|
|
145
|
+
value: T | { x: number; y: number } | undefined,
|
|
146
|
+
Constructor: CirclePointConstructor<T>,
|
|
147
|
+
): T | undefined => {
|
|
148
|
+
if (value === undefined) {
|
|
149
|
+
return undefined
|
|
150
|
+
}
|
|
151
|
+
if (value instanceof Constructor) {
|
|
152
|
+
return value
|
|
153
|
+
}
|
|
154
|
+
return new Constructor(value.x, value.y)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
abstract class PadPrimitiveGrCirclePoint extends SxClass {
|
|
158
|
+
protected _x: number
|
|
159
|
+
protected _y: number
|
|
160
|
+
|
|
161
|
+
protected constructor(x: number, y: number) {
|
|
162
|
+
super()
|
|
163
|
+
this._x = x
|
|
164
|
+
this._y = y
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get x(): number {
|
|
168
|
+
return this._x
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
set x(value: number) {
|
|
172
|
+
this._x = value
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
get y(): number {
|
|
176
|
+
return this._y
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
set y(value: number) {
|
|
180
|
+
this._y = value
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
override getChildren(): SxClass[] {
|
|
184
|
+
return []
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
override getString(): string {
|
|
188
|
+
return `(${this.token} ${this._x} ${this._y})`
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
class PadPrimitiveGrCircleCenter extends PadPrimitiveGrCirclePoint {
|
|
193
|
+
static override token = "center"
|
|
194
|
+
static override parentToken = "gr_circle"
|
|
195
|
+
override token = "center"
|
|
196
|
+
|
|
197
|
+
constructor(x: number, y: number) {
|
|
198
|
+
super(x, y)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static override fromSexprPrimitives(
|
|
202
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
203
|
+
): PadPrimitiveGrCircleCenter {
|
|
204
|
+
const [rawX, rawY] = primitiveSexprs
|
|
205
|
+
const x = toNumberValue(rawX)
|
|
206
|
+
const y = toNumberValue(rawY)
|
|
207
|
+
|
|
208
|
+
if (x === undefined || y === undefined) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
"pad primitive gr_circle center expects two numeric arguments",
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return new PadPrimitiveGrCircleCenter(x, y)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
SxClass.register(PadPrimitiveGrCircleCenter)
|
|
218
|
+
|
|
219
|
+
class PadPrimitiveGrCircleEnd extends PadPrimitiveGrCirclePoint {
|
|
220
|
+
static override token = "end"
|
|
221
|
+
static override parentToken = "gr_circle"
|
|
222
|
+
override token = "end"
|
|
223
|
+
|
|
224
|
+
constructor(x: number, y: number) {
|
|
225
|
+
super(x, y)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
static override fromSexprPrimitives(
|
|
229
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
230
|
+
): PadPrimitiveGrCircleEnd {
|
|
231
|
+
const [rawX, rawY] = primitiveSexprs
|
|
232
|
+
const x = toNumberValue(rawX)
|
|
233
|
+
const y = toNumberValue(rawY)
|
|
234
|
+
|
|
235
|
+
if (x === undefined || y === undefined) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
"pad primitive gr_circle end expects two numeric arguments",
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return new PadPrimitiveGrCircleEnd(x, y)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
SxClass.register(PadPrimitiveGrCircleEnd)
|
|
245
|
+
|
|
246
|
+
class PadPrimitiveGrCircleFill extends SxPrimitiveBoolean {
|
|
247
|
+
static override token = "fill"
|
|
248
|
+
static override parentToken = "gr_circle"
|
|
249
|
+
override token = "fill"
|
|
250
|
+
|
|
251
|
+
constructor(value?: boolean) {
|
|
252
|
+
super(value ?? false)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
static override fromSexprPrimitives(
|
|
256
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
257
|
+
): PadPrimitiveGrCircleFill {
|
|
258
|
+
const [raw] = primitiveSexprs
|
|
259
|
+
if (raw === undefined) {
|
|
260
|
+
return new PadPrimitiveGrCircleFill(false)
|
|
261
|
+
}
|
|
262
|
+
if (typeof raw === "boolean") {
|
|
263
|
+
return new PadPrimitiveGrCircleFill(raw)
|
|
264
|
+
}
|
|
265
|
+
if (typeof raw === "string") {
|
|
266
|
+
const normalized = raw.toLowerCase()
|
|
267
|
+
if (normalized === "yes" || normalized === "true") {
|
|
268
|
+
return new PadPrimitiveGrCircleFill(true)
|
|
269
|
+
}
|
|
270
|
+
if (normalized === "no" || normalized === "false") {
|
|
271
|
+
return new PadPrimitiveGrCircleFill(false)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
throw new Error(
|
|
275
|
+
`pad primitive gr_circle fill expects yes/no or boolean, received ${JSON.stringify(raw)}`,
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
SxClass.register(PadPrimitiveGrCircleFill)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { SxClass } from "../base-classes/SxClass"
|
|
2
|
+
import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
|
|
3
|
+
import { GrLineEnd } from "./GrLineEnd"
|
|
4
|
+
import { GrLineStart } from "./GrLineStart"
|
|
5
|
+
import { Width } from "./Width"
|
|
6
|
+
|
|
7
|
+
const SUPPORTED_TOKENS = new Set(["start", "end", "width"])
|
|
8
|
+
|
|
9
|
+
export class PadPrimitiveGrLine extends SxClass {
|
|
10
|
+
static override token = "gr_line"
|
|
11
|
+
static override parentToken = "primitives"
|
|
12
|
+
override token = "gr_line"
|
|
13
|
+
|
|
14
|
+
private _sxStart?: GrLineStart
|
|
15
|
+
private _sxEnd?: GrLineEnd
|
|
16
|
+
private _sxWidth?: Width
|
|
17
|
+
|
|
18
|
+
static override fromSexprPrimitives(
|
|
19
|
+
primitiveSexprs: PrimitiveSExpr[],
|
|
20
|
+
): PadPrimitiveGrLine {
|
|
21
|
+
const line = new PadPrimitiveGrLine()
|
|
22
|
+
|
|
23
|
+
const { propertyMap, arrayPropertyMap } =
|
|
24
|
+
SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
|
|
25
|
+
|
|
26
|
+
for (const token of Object.keys(propertyMap)) {
|
|
27
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`pad primitive gr_line encountered unsupported child token "${token}"`,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
for (const [token, entries] of Object.entries(arrayPropertyMap)) {
|
|
35
|
+
if (!SUPPORTED_TOKENS.has(token)) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`pad primitive gr_line encountered unsupported child token "${token}"`,
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
if (entries.length > 1) {
|
|
41
|
+
throw new Error(
|
|
42
|
+
`pad primitive gr_line does not support repeated "${token}" tokens`,
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
line._sxStart = propertyMap.start as GrLineStart | undefined
|
|
48
|
+
line._sxEnd = propertyMap.end as GrLineEnd | undefined
|
|
49
|
+
line._sxWidth = propertyMap.width as Width | undefined
|
|
50
|
+
|
|
51
|
+
if (!line._sxStart) {
|
|
52
|
+
throw new Error("pad primitive gr_line requires a start child token")
|
|
53
|
+
}
|
|
54
|
+
if (!line._sxEnd) {
|
|
55
|
+
throw new Error("pad primitive gr_line requires an end child token")
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return line
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get start(): GrLineStart | undefined {
|
|
62
|
+
return this._sxStart
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
set start(value: GrLineStart | { x: number; y: number } | undefined) {
|
|
66
|
+
if (value === undefined) {
|
|
67
|
+
this._sxStart = undefined
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
if (value instanceof GrLineStart) {
|
|
71
|
+
this._sxStart = value
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
this._sxStart = new GrLineStart(value.x, value.y)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get end(): GrLineEnd | undefined {
|
|
78
|
+
return this._sxEnd
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
set end(value: GrLineEnd | { x: number; y: number } | undefined) {
|
|
82
|
+
if (value === undefined) {
|
|
83
|
+
this._sxEnd = undefined
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
if (value instanceof GrLineEnd) {
|
|
87
|
+
this._sxEnd = value
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
this._sxEnd = new GrLineEnd(value.x, value.y)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get width(): number | undefined {
|
|
94
|
+
return this._sxWidth?.value
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
set width(value: Width | number | undefined) {
|
|
98
|
+
if (value === undefined) {
|
|
99
|
+
this._sxWidth = undefined
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
this._sxWidth = value instanceof Width ? value : new Width(value)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get widthClass(): Width | undefined {
|
|
106
|
+
return this._sxWidth
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
override getChildren(): SxClass[] {
|
|
110
|
+
const children: SxClass[] = []
|
|
111
|
+
if (this._sxStart) children.push(this._sxStart)
|
|
112
|
+
if (this._sxEnd) children.push(this._sxEnd)
|
|
113
|
+
if (this._sxWidth) children.push(this._sxWidth)
|
|
114
|
+
return children
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
override getString(): string {
|
|
118
|
+
const lines = ["(gr_line"]
|
|
119
|
+
if (this._sxStart) lines.push(this._sxStart.getStringIndented())
|
|
120
|
+
if (this._sxEnd) lines.push(this._sxEnd.getStringIndented())
|
|
121
|
+
if (this._sxWidth) lines.push(this._sxWidth.getStringIndented())
|
|
122
|
+
lines.push(")")
|
|
123
|
+
return lines.join("\n")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
SxClass.register(PadPrimitiveGrLine)
|