From ccf1da8a343f8eecd06ccc4c95299a9213d1bddd Mon Sep 17 00:00:00 2001 From: seveibar Date: Wed, 11 Sep 2024 09:45:04 -0700 Subject: [PATCH] fabrication note path and text implementation --- bun.lockb | Bin 340147 -> 347223 bytes package.json | 2 + src/lib/circuit-to-pcb-svg.ts | 43 ++-------- ...-objects-from-pcb-fabrication-note-path.ts | 43 ++++++++++ ...-objects-from-pcb-fabrication-note-text.ts | 78 ++++++++++++++++++ ...te-svg-objects-from-pcb-silkscreen-path.ts | 41 +++++++++ ...e-svg-objects-from-pcb-silkscreen-text.ts} | 9 +- src/lib/svg-object.ts | 1 + tests/__snapshots__/fabnotes.snap.svg | 12 +++ tests/fabnotes.test.tsx | 33 ++++++++ tsconfig.json | 2 +- 11 files changed, 225 insertions(+), 39 deletions(-) create mode 100644 src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts create mode 100644 src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts create mode 100644 src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts rename src/lib/svg-object-fns/{create-svg-objects-from-pcb-slikscreen-text.ts => create-svg-objects-from-pcb-silkscreen-text.ts} (86%) create mode 100644 src/lib/svg-object.ts create mode 100644 tests/__snapshots__/fabnotes.snap.svg create mode 100644 tests/fabnotes.test.tsx diff --git a/bun.lockb b/bun.lockb index 288ff3192a8a2df16766237d21e39e3ab9a690e9..1b3a21b963a7b2b83bf978fd38a043c42c731d28 100755 GIT binary patch delta 56350 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 z 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 elm.type === "pcb_silkscreen_path") - .flatMap((elm) => createPcbSilkscreenPath(elm, transform)) + .flatMap((elm) => createSvgObjectsFromPcbSilkscreenPath(elm, transform)) const otherElements = soup .filter( @@ -201,6 +204,10 @@ function createSvgObjects(elm: AnySoupElement, transform: Matrix): SvgObject[] { return createSvgObjectsFromSmtPad(elm, transform) case "pcb_silkscreen_text": return createSvgObjectsFromPcbSilkscreenText(elm, transform) + case "pcb_fabrication_note_path": + return createSvgObjectsFromPcbFabricationNotePath(elm, transform) + case "pcb_fabrication_note_text": + return createSvgObjectsFromPcbFabricationNoteText(elm, transform) default: return [] } @@ -276,38 +283,6 @@ function createSvgObjectsFromPcbHole(hole: any, transform: any): any { } } -function createPcbSilkscreenPath(silkscreenPath: any, transform: any): any { - if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return null - - let path = silkscreenPath.route - .map((point: any, index: number) => { - const [x, y] = applyToPoint(transform, [point.x, point.y]) - return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}` - }) - .join(" ") - - // Close the path if it's not already closed - const firstPoint = silkscreenPath.route[0] - const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1] - if (firstPoint.x !== lastPoint.x || firstPoint.y !== lastPoint.y) { - path += " Z" - } - - return { - name: "path", - type: "element", - attributes: { - class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`, - d: path, - "stroke-width": ( - silkscreenPath.stroke_width * Math.abs(transform.a) - ).toString(), - "data-pcb-component-id": silkscreenPath.pcb_component_id, - "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id, - }, - } -} - function createSvgObjectFromPcbBoundary( transform: any, minX: number, diff --git a/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts b/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts new file mode 100644 index 0000000..0ce7d25 --- /dev/null +++ b/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-path.ts @@ -0,0 +1,43 @@ +import type { PcbSilkscreenPath, PcbFabricationNotePath } from "@tscircuit/soup" +import { applyToPoint, type Matrix } from "transformation-matrix" +import type { SvgObject } from "../svg-object" + +export function createSvgObjectsFromPcbFabricationNotePath( + fabNotePath: PcbFabricationNotePath, + transform: Matrix, +): SvgObject[] { + if (!fabNotePath.route || !Array.isArray(fabNotePath.route)) return [] + + let path = fabNotePath.route + .map((point: any, index: number) => { + const [x, y] = applyToPoint(transform, [point.x, point.y]) + return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}` + }) + .join(" ") + + // Close the path if it's not already closed + const firstPoint = fabNotePath.route[0] + const lastPoint = fabNotePath.route[fabNotePath.route.length - 1] + if (firstPoint!.x !== lastPoint!.x || firstPoint!.y !== lastPoint!.y) { + path += " Z" + } + return [ + { + name: "path", + type: "element", + attributes: { + class: "pcb-fabrication-note-path", + stroke: "rgba(255,255,255,0.5)", + d: path, + "stroke-width": ( + fabNotePath.stroke_width * Math.abs(transform.a) + ).toString(), + "data-pcb-component-id": fabNotePath.pcb_component_id, + "data-pcb-fabrication-note-path-id": + fabNotePath.fabrication_note_path_id, + }, + value: "", + children: [], + }, + ] +} diff --git a/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts b/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts new file mode 100644 index 0000000..37c5df1 --- /dev/null +++ b/src/lib/svg-object-fns/create-svg-objects-from-pcb-fabrication-note-text.ts @@ -0,0 +1,78 @@ +import type { PcbFabricationNoteText } from "@tscircuit/soup" +import type { INode as SvgObject } from "svgson" +import { toString as matrixToString } from "transformation-matrix" +import { + type Matrix, + applyToPoint, + compose, + rotate, + translate, +} from "transformation-matrix" + +export function createSvgObjectsFromPcbFabricationNoteText( + pcbFabNoteText: PcbFabricationNoteText, + transform: Matrix, +): SvgObject[] { + const { + anchor_position, + anchor_alignment, + text, + font_size = 1, + layer = "top", + } = pcbFabNoteText + + if ( + !anchor_position || + typeof anchor_position.x !== "number" || + typeof anchor_position.y !== "number" + ) { + console.error("Invalid anchor_position:", anchor_position) + return [] + } + + const [transformedX, transformedY] = applyToPoint(transform, [ + anchor_position.x, + anchor_position.y, + ]) + const transformedFontSize = font_size * Math.abs(transform.a) + + // Remove ${} from text value and handle undefined text + const cleanedText = (text || "").replace(/\$\{|\}/g, "") + if (!cleanedText) { + return [] + } + + // Create a composite transformation + const textTransform = compose( + translate(transformedX, transformedY), // TODO do anchor_alignment + rotate(Math.PI / 180), // Convert degrees to radians + ) + + const svgObject: SvgObject = { + name: "text", + type: "element", + attributes: { + x: "0", + y: "0", + "font-family": "Arial, sans-serif", + "font-size": transformedFontSize.toString(), + "text-anchor": "middle", + "dominant-baseline": "central", + transform: matrixToString(textTransform), + class: "pcb-fabrication-note-text", + fill: "rgba(255,255,255,0.5)", + }, + children: [ + { + type: "text", + value: cleanedText, + name: "", + attributes: {}, + children: [], + }, + ], + value: "", + } + + return [svgObject] +} diff --git a/src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts b/src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts new file mode 100644 index 0000000..5924c28 --- /dev/null +++ b/src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-path.ts @@ -0,0 +1,41 @@ +import type { PcbSilkscreenPath } from "@tscircuit/soup" +import { applyToPoint, type Matrix } from "transformation-matrix" +import type { SvgObject } from "../svg-object" + +export function createSvgObjectsFromPcbSilkscreenPath( + silkscreenPath: PcbSilkscreenPath, + transform: Matrix, +): SvgObject[] { + if (!silkscreenPath.route || !Array.isArray(silkscreenPath.route)) return [] + + let path = silkscreenPath.route + .map((point: any, index: number) => { + const [x, y] = applyToPoint(transform, [point.x, point.y]) + return index === 0 ? `M ${x} ${y}` : `L ${x} ${y}` + }) + .join(" ") + + // Close the path if it's not already closed + const firstPoint = silkscreenPath.route[0] + const lastPoint = silkscreenPath.route[silkscreenPath.route.length - 1] + if (firstPoint!.x !== lastPoint!.x || firstPoint!.y !== lastPoint!.y) { + path += " Z" + } + return [ + { + name: "path", + type: "element", + attributes: { + class: `pcb-silkscreen pcb-silkscreen-${silkscreenPath.layer}`, + d: path, + "stroke-width": ( + silkscreenPath.stroke_width * Math.abs(transform.a) + ).toString(), + "data-pcb-component-id": silkscreenPath.pcb_component_id, + "data-pcb-silkscreen-path-id": silkscreenPath.pcb_silkscreen_path_id, + }, + value: "", + children: [], + }, + ] +} diff --git a/src/lib/svg-object-fns/create-svg-objects-from-pcb-slikscreen-text.ts b/src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-text.ts similarity index 86% rename from src/lib/svg-object-fns/create-svg-objects-from-pcb-slikscreen-text.ts rename to src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-text.ts index 8b6e6ab..f3b1d7d 100644 --- a/src/lib/svg-object-fns/create-svg-objects-from-pcb-slikscreen-text.ts +++ b/src/lib/svg-object-fns/create-svg-objects-from-pcb-silkscreen-text.ts @@ -6,10 +6,11 @@ import { compose, rotate, translate, + toString as matrixToString, } from "transformation-matrix" export function createSvgObjectsFromPcbSilkscreenText( - PcbSilkscreenText: PcbSilkscreenText, + pcbSilkscreenText: PcbSilkscreenText, transform: Matrix, ): SvgObject[] { const { @@ -17,7 +18,7 @@ export function createSvgObjectsFromPcbSilkscreenText( text, font_size = 1, layer = "top", - } = PcbSilkscreenText + } = pcbSilkscreenText if ( !anchor_position || @@ -56,9 +57,9 @@ export function createSvgObjectsFromPcbSilkscreenText( "font-size": transformedFontSize.toString(), "text-anchor": "middle", "dominant-baseline": "central", - transform: `matrix(${textTransform.a} ${textTransform.b} ${textTransform.c} ${textTransform.d} ${textTransform.e} ${textTransform.f})`, + transform: matrixToString(textTransform), class: `pcb-silkscreen-text pcb-silkscreen-${layer}`, - "data-pcb-silkscreen-text-id": PcbSilkscreenText.pcb_component_id, + "data-pcb-silkscreen-text-id": pcbSilkscreenText.pcb_component_id, }, children: [ { diff --git a/src/lib/svg-object.ts b/src/lib/svg-object.ts new file mode 100644 index 0000000..a051909 --- /dev/null +++ b/src/lib/svg-object.ts @@ -0,0 +1 @@ +export type { INode as SvgObject } from "svgson" diff --git a/tests/__snapshots__/fabnotes.snap.svg b/tests/__snapshots__/fabnotes.snap.svg new file mode 100644 index 0000000..36cba46 --- /dev/null +++ b/tests/__snapshots__/fabnotes.snap.svg @@ -0,0 +1,12 @@ +hello world! \ No newline at end of file diff --git a/tests/fabnotes.test.tsx b/tests/fabnotes.test.tsx new file mode 100644 index 0000000..35eb007 --- /dev/null +++ b/tests/fabnotes.test.tsx @@ -0,0 +1,33 @@ +import { test, expect } from "bun:test" +import { circuitJsonToPcbSvg } from "src" +import { Circuit } from "@tscircuit/core" + +test("fabrication note path and fabrication note text", () => { + const circuit = new Circuit() + + circuit.add( + + + + , + ) + + const circuitJson = circuit.getCircuitJson() + + const svg = circuitJsonToPcbSvg(circuitJson as any) + + expect(svg).toMatchSvgSnapshot(import.meta.path) +}) diff --git a/tsconfig.json b/tsconfig.json index de09764..9dfeb8f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "jsx": "react", + "jsx": "react-jsx", // Base Options recommended for all projects "esModuleInterop": true, "skipLibCheck": true,