diff --git a/lib/sexpr/classes/GrArc.ts b/lib/sexpr/classes/GrArc.ts new file mode 100644 index 0000000..1e94f44 --- /dev/null +++ b/lib/sexpr/classes/GrArc.ts @@ -0,0 +1,393 @@ +import { SxClass } from "../base-classes/SxClass" +import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr" +import { Layer } from "./Layer" +import { Stroke } from "./Stroke" +import { Tstamp } from "./Tstamp" +import { Uuid } from "./Uuid" +import { Width } from "./Width" + +export interface GrArcPoint { + x: number + y: number +} + +const SUPPORTED_SINGLE_TOKENS = new Set([ + "start", + "mid", + "end", + "layer", + "width", + "stroke", + "tstamp", + "uuid", +]) + +export interface GrArcConstructorParams { + start?: GrArcStart | GrArcPoint + mid?: GrArcMid | GrArcPoint + end?: GrArcEnd | GrArcPoint + layer?: Layer | string | Array + width?: Width | number + stroke?: Stroke + tstamp?: Tstamp | string + uuid?: Uuid | string +} + +export class GrArc extends SxClass { + static override token = "gr_arc" + override token = "gr_arc" + + private _sxStart?: GrArcStart + private _sxMid?: GrArcMid + private _sxEnd?: GrArcEnd + private _sxLayer?: Layer + private _sxWidth?: Width + private _sxStroke?: Stroke + private _sxTstamp?: Tstamp + private _sxUuid?: Uuid + + constructor(params: GrArcConstructorParams = {}) { + super() + if (params.start !== undefined) this.start = params.start + if (params.mid !== undefined) this.mid = params.mid + if (params.end !== undefined) this.end = params.end + if (params.layer !== undefined) this.layer = params.layer + if (params.width !== undefined) this.width = params.width + if (params.stroke !== undefined) this.stroke = params.stroke + if (params.tstamp !== undefined) this.tstamp = params.tstamp + if (params.uuid !== undefined) this.uuid = params.uuid + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrArc { + const grArc = new GrArc() + + const { propertyMap, arrayPropertyMap } = + SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token) + + const unexpectedTokens = new Set() + for (const token of Object.keys(propertyMap)) { + if (!SUPPORTED_SINGLE_TOKENS.has(token)) { + unexpectedTokens.add(token) + } + } + for (const token of Object.keys(arrayPropertyMap)) { + if (!SUPPORTED_SINGLE_TOKENS.has(token)) { + unexpectedTokens.add(token) + continue + } + if (arrayPropertyMap[token]!.length > 1) { + throw new Error( + `gr_arc does not support repeated child tokens: ${token}`, + ) + } + } + + if (unexpectedTokens.size > 0) { + throw new Error( + `Unsupported child tokens inside gr_arc expression: ${[...unexpectedTokens].join(", ")}`, + ) + } + + for (const primitive of primitiveSexprs) { + if (Array.isArray(primitive)) continue + throw new Error( + `gr_arc encountered unexpected primitive child: ${JSON.stringify(primitive)}`, + ) + } + + grArc._sxStart = propertyMap.start as GrArcStart | undefined + grArc._sxMid = propertyMap.mid as GrArcMid | undefined + grArc._sxEnd = propertyMap.end as GrArcEnd | undefined + grArc._sxLayer = propertyMap.layer as Layer | undefined + grArc._sxWidth = propertyMap.width as Width | undefined + grArc._sxStroke = propertyMap.stroke as Stroke | undefined + grArc._sxTstamp = propertyMap.tstamp as Tstamp | undefined + grArc._sxUuid = propertyMap.uuid as Uuid | undefined + + if (!grArc._sxStart) { + throw new Error("gr_arc requires a start child token") + } + if (!grArc._sxMid) { + throw new Error("gr_arc requires a mid child token") + } + if (!grArc._sxEnd) { + throw new Error("gr_arc requires an end child token") + } + if (!grArc._sxLayer) { + throw new Error("gr_arc requires a layer child token") + } + + return grArc + } + + get start(): GrArcStart | undefined { + return this._sxStart + } + + set start(value: GrArcStart | GrArcPoint | undefined) { + this._sxStart = this.normalizeStart(value) + } + + get mid(): GrArcMid | undefined { + return this._sxMid + } + + set mid(value: GrArcMid | GrArcPoint | undefined) { + this._sxMid = this.normalizeMid(value) + } + + get end(): GrArcEnd | undefined { + return this._sxEnd + } + + set end(value: GrArcEnd | GrArcPoint | undefined) { + this._sxEnd = this.normalizeEnd(value) + } + + get startPoint(): GrArcPoint | undefined { + return this._sxStart?.toObject() + } + + get midPoint(): GrArcPoint | undefined { + return this._sxMid?.toObject() + } + + get endPoint(): GrArcPoint | undefined { + return this._sxEnd?.toObject() + } + + get layer(): Layer | undefined { + return this._sxLayer + } + + set layer(value: Layer | string | Array | undefined) { + if (value === undefined) { + this._sxLayer = undefined + return + } + if (value instanceof Layer) { + this._sxLayer = value + return + } + const names = Array.isArray(value) ? value : [value] + this._sxLayer = new Layer(names) + } + + get width(): number | undefined { + return this._sxWidth?.value + } + + set width(value: Width | number | undefined) { + if (value === undefined) { + this._sxWidth = undefined + return + } + this._sxWidth = value instanceof Width ? value : new Width(value) + } + + get widthClass(): Width | undefined { + return this._sxWidth + } + + set widthClass(value: Width | undefined) { + this._sxWidth = value + } + + get stroke(): Stroke | undefined { + return this._sxStroke + } + + set stroke(value: Stroke | undefined) { + this._sxStroke = value + } + + get tstamp(): Tstamp | undefined { + return this._sxTstamp + } + + set tstamp(value: Tstamp | string | undefined) { + if (value === undefined) { + this._sxTstamp = undefined + return + } + this._sxTstamp = value instanceof Tstamp ? value : new Tstamp(value) + } + + get uuid(): Uuid | undefined { + return this._sxUuid + } + + set uuid(value: Uuid | string | undefined) { + if (value === undefined) { + this._sxUuid = undefined + return + } + this._sxUuid = value instanceof Uuid ? value : new Uuid(value) + } + + override getChildren(): SxClass[] { + const children: SxClass[] = [] + if (this._sxStart) children.push(this._sxStart) + if (this._sxMid) children.push(this._sxMid) + if (this._sxEnd) children.push(this._sxEnd) + if (this._sxStroke) children.push(this._sxStroke) + if (this._sxWidth) children.push(this._sxWidth) + if (this._sxLayer) children.push(this._sxLayer) + if (this._sxTstamp) children.push(this._sxTstamp) + if (this._sxUuid) children.push(this._sxUuid) + return children + } + + private normalizeStart( + value: GrArcStart | GrArcPoint | undefined, + ): GrArcStart | undefined { + if (value === undefined) { + return undefined + } + if (value instanceof GrArcStart) { + return value + } + return new GrArcStart(value.x, value.y) + } + + private normalizeMid( + value: GrArcMid | GrArcPoint | undefined, + ): GrArcMid | undefined { + if (value === undefined) { + return undefined + } + if (value instanceof GrArcMid) { + return value + } + return new GrArcMid(value.x, value.y) + } + + private normalizeEnd( + value: GrArcEnd | GrArcPoint | undefined, + ): GrArcEnd | undefined { + if (value === undefined) { + return undefined + } + if (value instanceof GrArcEnd) { + return value + } + return new GrArcEnd(value.x, value.y) + } +} +SxClass.register(GrArc) + +export class GrArcStart extends SxClass { + static override token = "start" + static override parentToken = "gr_arc" + override token = "start" + + constructor( + public x: number, + public y: number, + ) { + super() + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrArcStart { + const [rawX, rawY] = primitiveSexprs + const x = Number(rawX) + const y = Number(rawY) + if (!Number.isFinite(x) || !Number.isFinite(y)) { + throw new Error("gr_arc start expects numeric coordinates") + } + return new GrArcStart(x, y) + } + + toObject(): GrArcPoint { + return { x: this.x, y: this.y } + } + + override getChildren(): SxClass[] { + return [] + } + + override getString(): string { + return `(start ${this.x} ${this.y})` + } +} +SxClass.register(GrArcStart) + +export class GrArcMid extends SxClass { + static override token = "mid" + static override parentToken = "gr_arc" + override token = "mid" + + constructor( + public x: number, + public y: number, + ) { + super() + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrArcMid { + const [rawX, rawY] = primitiveSexprs + const x = Number(rawX) + const y = Number(rawY) + if (!Number.isFinite(x) || !Number.isFinite(y)) { + throw new Error("gr_arc mid expects numeric coordinates") + } + return new GrArcMid(x, y) + } + + toObject(): GrArcPoint { + return { x: this.x, y: this.y } + } + + override getChildren(): SxClass[] { + return [] + } + + override getString(): string { + return `(mid ${this.x} ${this.y})` + } +} +SxClass.register(GrArcMid) + +export class GrArcEnd extends SxClass { + static override token = "end" + static override parentToken = "gr_arc" + override token = "end" + + constructor( + public x: number, + public y: number, + ) { + super() + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrArcEnd { + const [rawX, rawY] = primitiveSexprs + const x = Number(rawX) + const y = Number(rawY) + if (!Number.isFinite(x) || !Number.isFinite(y)) { + throw new Error("gr_arc end expects numeric coordinates") + } + return new GrArcEnd(x, y) + } + + toObject(): GrArcPoint { + return { x: this.x, y: this.y } + } + + override getChildren(): SxClass[] { + return [] + } + + override getString(): string { + return `(end ${this.x} ${this.y})` + } +} +SxClass.register(GrArcEnd) diff --git a/lib/sexpr/classes/GrCircle.ts b/lib/sexpr/classes/GrCircle.ts new file mode 100644 index 0000000..7ca96cc --- /dev/null +++ b/lib/sexpr/classes/GrCircle.ts @@ -0,0 +1,358 @@ +import { SxClass } from "../base-classes/SxClass" +import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr" +import { Layer } from "./Layer" +import { PadPrimitiveGrCircleFill } from "./PadPrimitiveGrCircle" +import { Stroke } from "./Stroke" +import { Tstamp } from "./Tstamp" +import { Uuid } from "./Uuid" +import { Width } from "./Width" + +export interface GrCirclePoint { + x: number + y: number +} + +const SUPPORTED_SINGLE_TOKENS = new Set([ + "center", + "end", + "layer", + "width", + "stroke", + "fill", + "tstamp", + "uuid", +]) + +export interface GrCircleConstructorParams { + center?: GrCircleCenter | GrCirclePoint + end?: GrCircleEnd | GrCirclePoint + layer?: Layer | string | Array + width?: Width | number + stroke?: Stroke + fill?: PadPrimitiveGrCircleFill | string + tstamp?: Tstamp | string + uuid?: Uuid | string +} + +export class GrCircle extends SxClass { + static override token = "gr_circle" + override token = "gr_circle" + + private _sxCenter?: GrCircleCenter + private _sxEnd?: GrCircleEnd + private _sxLayer?: Layer + private _sxWidth?: Width + private _sxStroke?: Stroke + private _sxFill?: PadPrimitiveGrCircleFill + private _sxTstamp?: Tstamp + private _sxUuid?: Uuid + + constructor(params: GrCircleConstructorParams = {}) { + super() + if (params.center !== undefined) this.center = params.center + if (params.end !== undefined) this.end = params.end + if (params.layer !== undefined) this.layer = params.layer + if (params.width !== undefined) this.width = params.width + if (params.stroke !== undefined) this.stroke = params.stroke + if (params.fill !== undefined) this.fill = params.fill + if (params.tstamp !== undefined) this.tstamp = params.tstamp + if (params.uuid !== undefined) this.uuid = params.uuid + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrCircle { + const grCircle = new GrCircle() + + const { propertyMap, arrayPropertyMap } = + SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token) + + const unexpectedTokens = new Set() + for (const token of Object.keys(propertyMap)) { + if (!SUPPORTED_SINGLE_TOKENS.has(token)) { + unexpectedTokens.add(token) + } + } + for (const token of Object.keys(arrayPropertyMap)) { + if (!SUPPORTED_SINGLE_TOKENS.has(token)) { + unexpectedTokens.add(token) + continue + } + if (arrayPropertyMap[token]!.length > 1) { + throw new Error( + `gr_circle does not support repeated child tokens: ${token}`, + ) + } + } + + if (unexpectedTokens.size > 0) { + throw new Error( + `Unsupported child tokens inside gr_circle expression: ${[...unexpectedTokens].join(", ")}`, + ) + } + + for (const primitive of primitiveSexprs) { + if (Array.isArray(primitive)) continue + throw new Error( + `gr_circle encountered unexpected primitive child: ${JSON.stringify(primitive)}`, + ) + } + + grCircle._sxCenter = propertyMap.center as GrCircleCenter | undefined + grCircle._sxEnd = propertyMap.end as GrCircleEnd | undefined + grCircle._sxLayer = propertyMap.layer as Layer | undefined + grCircle._sxWidth = propertyMap.width as Width | undefined + grCircle._sxStroke = propertyMap.stroke as Stroke | undefined + grCircle._sxFill = propertyMap.fill as PadPrimitiveGrCircleFill | undefined + grCircle._sxTstamp = propertyMap.tstamp as Tstamp | undefined + grCircle._sxUuid = propertyMap.uuid as Uuid | undefined + + if (!grCircle._sxCenter) { + throw new Error("gr_circle requires a center child token") + } + if (!grCircle._sxEnd) { + throw new Error("gr_circle requires an end child token") + } + if (!grCircle._sxLayer) { + throw new Error("gr_circle requires a layer child token") + } + + return grCircle + } + + get center(): GrCircleCenter | undefined { + return this._sxCenter + } + + set center(value: GrCircleCenter | GrCirclePoint | undefined) { + this._sxCenter = this.normalizeCenter(value) + } + + get end(): GrCircleEnd | undefined { + return this._sxEnd + } + + set end(value: GrCircleEnd | GrCirclePoint | undefined) { + this._sxEnd = this.normalizeEnd(value) + } + + get centerPoint(): GrCirclePoint | undefined { + return this._sxCenter?.toObject() + } + + get endPoint(): GrCirclePoint | undefined { + return this._sxEnd?.toObject() + } + + get layer(): Layer | undefined { + return this._sxLayer + } + + set layer(value: Layer | string | Array | undefined) { + if (value === undefined) { + this._sxLayer = undefined + return + } + if (value instanceof Layer) { + this._sxLayer = value + return + } + const names = Array.isArray(value) ? value : [value] + this._sxLayer = new Layer(names) + } + + get width(): number | undefined { + return this._sxWidth?.value + } + + set width(value: Width | number | undefined) { + if (value === undefined) { + this._sxWidth = undefined + return + } + this._sxWidth = value instanceof Width ? value : new Width(value) + } + + get widthClass(): Width | undefined { + return this._sxWidth + } + + set widthClass(value: Width | undefined) { + this._sxWidth = value + } + + get stroke(): Stroke | undefined { + return this._sxStroke + } + + set stroke(value: Stroke | undefined) { + this._sxStroke = value + } + + get fill(): PadPrimitiveGrCircleFill | undefined { + return this._sxFill + } + + set fill(value: PadPrimitiveGrCircleFill | string | undefined) { + if (value === undefined) { + this._sxFill = undefined + return + } + if (value instanceof PadPrimitiveGrCircleFill) { + this._sxFill = value + return + } + // Parse string to boolean or leave as string for "none" + const boolValue = + value === "yes" || value === "true" + ? true + : value === "no" || value === "false" + ? false + : value + if (typeof boolValue === "boolean") { + this._sxFill = new PadPrimitiveGrCircleFill(boolValue) + } else { + this._sxFill = new PadPrimitiveGrCircleFill( + value === "none" ? false : true, + ) + } + } + + get tstamp(): Tstamp | undefined { + return this._sxTstamp + } + + set tstamp(value: Tstamp | string | undefined) { + if (value === undefined) { + this._sxTstamp = undefined + return + } + this._sxTstamp = value instanceof Tstamp ? value : new Tstamp(value) + } + + get uuid(): Uuid | undefined { + return this._sxUuid + } + + set uuid(value: Uuid | string | undefined) { + if (value === undefined) { + this._sxUuid = undefined + return + } + this._sxUuid = value instanceof Uuid ? value : new Uuid(value) + } + + override getChildren(): SxClass[] { + const children: SxClass[] = [] + if (this._sxCenter) children.push(this._sxCenter) + if (this._sxEnd) children.push(this._sxEnd) + if (this._sxStroke) children.push(this._sxStroke) + if (this._sxWidth) children.push(this._sxWidth) + if (this._sxFill) children.push(this._sxFill) + if (this._sxLayer) children.push(this._sxLayer) + if (this._sxTstamp) children.push(this._sxTstamp) + if (this._sxUuid) children.push(this._sxUuid) + return children + } + + private normalizeCenter( + value: GrCircleCenter | GrCirclePoint | undefined, + ): GrCircleCenter | undefined { + if (value === undefined) { + return undefined + } + if (value instanceof GrCircleCenter) { + return value + } + return new GrCircleCenter(value.x, value.y) + } + + private normalizeEnd( + value: GrCircleEnd | GrCirclePoint | undefined, + ): GrCircleEnd | undefined { + if (value === undefined) { + return undefined + } + if (value instanceof GrCircleEnd) { + return value + } + return new GrCircleEnd(value.x, value.y) + } +} +SxClass.register(GrCircle) + +export class GrCircleCenter extends SxClass { + static override token = "center" + static override parentToken = "gr_circle" + override token = "center" + + constructor( + public x: number, + public y: number, + ) { + super() + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrCircleCenter { + const [rawX, rawY] = primitiveSexprs + const x = Number(rawX) + const y = Number(rawY) + if (!Number.isFinite(x) || !Number.isFinite(y)) { + throw new Error("gr_circle center expects numeric coordinates") + } + return new GrCircleCenter(x, y) + } + + toObject(): GrCirclePoint { + return { x: this.x, y: this.y } + } + + override getChildren(): SxClass[] { + return [] + } + + override getString(): string { + return `(center ${this.x} ${this.y})` + } +} +SxClass.register(GrCircleCenter) + +export class GrCircleEnd extends SxClass { + static override token = "end" + static override parentToken = "gr_circle" + override token = "end" + + constructor( + public x: number, + public y: number, + ) { + super() + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrCircleEnd { + const [rawX, rawY] = primitiveSexprs + const x = Number(rawX) + const y = Number(rawY) + if (!Number.isFinite(x) || !Number.isFinite(y)) { + throw new Error("gr_circle end expects numeric coordinates") + } + return new GrCircleEnd(x, y) + } + + toObject(): GrCirclePoint { + return { x: this.x, y: this.y } + } + + override getChildren(): SxClass[] { + return [] + } + + override getString(): string { + return `(end ${this.x} ${this.y})` + } +} +SxClass.register(GrCircleEnd) diff --git a/lib/sexpr/classes/GrCurve.ts b/lib/sexpr/classes/GrCurve.ts new file mode 100644 index 0000000..8abeab3 --- /dev/null +++ b/lib/sexpr/classes/GrCurve.ts @@ -0,0 +1,235 @@ +import { SxClass } from "../base-classes/SxClass" +import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr" +import { Layer } from "./Layer" +import { Pts } from "./Pts" +import { Stroke } from "./Stroke" +import { Tstamp } from "./Tstamp" +import { Uuid } from "./Uuid" +import { Width } from "./Width" +import { Xy } from "./Xy" + +const SUPPORTED_TOKENS = new Set([ + "pts", + "xy", + "layer", + "width", + "stroke", + "tstamp", + "uuid", +]) + +export interface GrCurveConstructorParams { + points?: Pts | Xy[] | Array<{ x: number; y: number }> + layer?: Layer | string | Array + width?: Width | number + stroke?: Stroke + tstamp?: Tstamp | string + uuid?: Uuid | string +} + +export class GrCurve extends SxClass { + static override token = "gr_curve" + override token = "gr_curve" + + private _sxPts?: Pts + private _sxLayer?: Layer + private _sxWidth?: Width + private _sxStroke?: Stroke + private _sxTstamp?: Tstamp + private _sxUuid?: Uuid + + constructor(params: GrCurveConstructorParams = {}) { + super() + if (params.points !== undefined) this.points = params.points + if (params.layer !== undefined) this.layer = params.layer + if (params.width !== undefined) this.width = params.width + if (params.stroke !== undefined) this.stroke = params.stroke + if (params.tstamp !== undefined) this.tstamp = params.tstamp + if (params.uuid !== undefined) this.uuid = params.uuid + } + + static override fromSexprPrimitives( + primitiveSexprs: PrimitiveSExpr[], + ): GrCurve { + const grCurve = new GrCurve() + + const { propertyMap, arrayPropertyMap } = + SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token) + + const unexpectedTokens = new Set() + for (const token of Object.keys(propertyMap)) { + if (!SUPPORTED_TOKENS.has(token)) { + unexpectedTokens.add(token) + } + } + for (const token of Object.keys(arrayPropertyMap)) { + if (!SUPPORTED_TOKENS.has(token)) { + unexpectedTokens.add(token) + continue + } + if (token !== "xy" && arrayPropertyMap[token]!.length > 1) { + throw new Error( + `gr_curve does not support repeated child token "${token}"`, + ) + } + } + + if (unexpectedTokens.size > 0) { + throw new Error( + `Unsupported child tokens inside gr_curve expression: ${[...unexpectedTokens].join(", ")}`, + ) + } + + const ptsEntries = arrayPropertyMap.pts as Pts[] | undefined + if (ptsEntries && ptsEntries.length > 1) { + throw new Error("gr_curve does not support repeated pts tokens") + } + + const xyEntries = arrayPropertyMap.xy as Xy[] | undefined + let pts = propertyMap.pts as Pts | undefined + + if (pts && xyEntries && xyEntries.length > 0) { + throw new Error("gr_curve cannot mix pts and xy child tokens") + } + + if (!pts && ptsEntries?.length) { + pts = ptsEntries[0] + } + + if (!pts && xyEntries && xyEntries.length > 0) { + pts = new Pts(xyEntries) + } + + grCurve._sxPts = pts + grCurve._sxLayer = propertyMap.layer as Layer | undefined + grCurve._sxWidth = propertyMap.width as Width | undefined + grCurve._sxStroke = propertyMap.stroke as Stroke | undefined + grCurve._sxTstamp = propertyMap.tstamp as Tstamp | undefined + grCurve._sxUuid = propertyMap.uuid as Uuid | undefined + + for (const primitive of primitiveSexprs) { + if (Array.isArray(primitive)) continue + throw new Error( + `gr_curve encountered unexpected primitive child: ${JSON.stringify(primitive)}`, + ) + } + + if (!grCurve._sxPts) { + throw new Error("gr_curve requires pts or xy child tokens") + } + if (!grCurve._sxLayer) { + throw new Error("gr_curve requires a layer child token") + } + + return grCurve + } + + get points(): Pts | undefined { + return this._sxPts + } + + set points(value: Pts | Xy[] | Array<{ x: number; y: number }> | undefined) { + if (value === undefined) { + this._sxPts = undefined + return + } + + if (value instanceof Pts) { + this._sxPts = value + return + } + + if (Array.isArray(value) && value.every((point) => point instanceof Xy)) { + this._sxPts = new Pts(value as Xy[]) + return + } + + if (Array.isArray(value)) { + this._sxPts = new Pts(value.map(({ x, y }) => new Xy(x, y))) + return + } + + throw new Error("Unsupported points value provided to gr_curve") + } + + get layer(): Layer | undefined { + return this._sxLayer + } + + set layer(value: Layer | string | Array | undefined) { + if (value === undefined) { + this._sxLayer = undefined + return + } + if (value instanceof Layer) { + this._sxLayer = value + return + } + const names = Array.isArray(value) ? value : [value] + this._sxLayer = new Layer(names) + } + + get width(): number | undefined { + return this._sxWidth?.value + } + + set width(value: Width | number | undefined) { + if (value === undefined) { + this._sxWidth = undefined + return + } + this._sxWidth = value instanceof Width ? value : new Width(value) + } + + get widthClass(): Width | undefined { + return this._sxWidth + } + + set widthClass(value: Width | undefined) { + this._sxWidth = value + } + + get stroke(): Stroke | undefined { + return this._sxStroke + } + + set stroke(value: Stroke | undefined) { + this._sxStroke = value + } + + get tstamp(): Tstamp | undefined { + return this._sxTstamp + } + + set tstamp(value: Tstamp | string | undefined) { + if (value === undefined) { + this._sxTstamp = undefined + return + } + this._sxTstamp = value instanceof Tstamp ? value : new Tstamp(value) + } + + get uuid(): Uuid | undefined { + return this._sxUuid + } + + set uuid(value: Uuid | string | undefined) { + if (value === undefined) { + this._sxUuid = undefined + return + } + this._sxUuid = value instanceof Uuid ? value : new Uuid(value) + } + + override getChildren(): SxClass[] { + const children: SxClass[] = [] + if (this._sxPts) children.push(this._sxPts) + if (this._sxLayer) children.push(this._sxLayer) + if (this._sxWidth) children.push(this._sxWidth) + if (this._sxStroke) children.push(this._sxStroke) + if (this._sxTstamp) children.push(this._sxTstamp) + if (this._sxUuid) children.push(this._sxUuid) + return children + } +} +SxClass.register(GrCurve) diff --git a/lib/sexpr/classes/PadPrimitiveGrCircle.ts b/lib/sexpr/classes/PadPrimitiveGrCircle.ts index 148295c..8dd7e89 100644 --- a/lib/sexpr/classes/PadPrimitiveGrCircle.ts +++ b/lib/sexpr/classes/PadPrimitiveGrCircle.ts @@ -262,7 +262,7 @@ class PadPrimitiveGrCircleEnd extends PadPrimitiveGrCirclePoint { } SxClass.register(PadPrimitiveGrCircleEnd) -class PadPrimitiveGrCircleFill extends SxPrimitiveBoolean { +export class PadPrimitiveGrCircleFill extends SxPrimitiveBoolean { static override token = "fill" static override parentToken = "gr_circle" override token = "fill" @@ -286,12 +286,16 @@ class PadPrimitiveGrCircleFill extends SxPrimitiveBoolean { if (normalized === "yes" || normalized === "true") { return new PadPrimitiveGrCircleFill(true) } - if (normalized === "no" || normalized === "false") { + if ( + normalized === "no" || + normalized === "false" || + normalized === "none" + ) { return new PadPrimitiveGrCircleFill(false) } } throw new Error( - `pad primitive gr_circle fill expects yes/no or boolean, received ${JSON.stringify(raw)}`, + `pad primitive gr_circle fill expects yes/no/none or boolean, received ${JSON.stringify(raw)}`, ) } } diff --git a/lib/sexpr/index.ts b/lib/sexpr/index.ts index 8055ead..1e4fd6a 100644 --- a/lib/sexpr/index.ts +++ b/lib/sexpr/index.ts @@ -53,6 +53,9 @@ export * from "./classes/FootprintThermalGap" export * from "./classes/FootprintAttr" export * from "./classes/FootprintPrivateLayers" export * from "./classes/FootprintNetTiePadGroups" +export * from "./classes/GrArc" +export * from "./classes/GrCircle" +export * from "./classes/GrCurve" export * from "./classes/GrLine" export * from "./classes/GrLineStart" export * from "./classes/GrLineEnd"