From 0c4af5cb306ad03da67757d0cdda4eae302e969b Mon Sep 17 00:00:00 2001 From: Rishabh Gupta Date: Mon, 7 Oct 2024 00:58:45 +0530 Subject: [PATCH 1/2] fix: Chip placement --- .../getAllDimensionsForSchematicBox.ts | 307 ++++++++---------- .../__snapshots__/chip.snap.svg | 4 +- .../__snapshots__/jumper-schematic.snap.svg | 4 +- .../example4-kicad-schematic.snap.svg | 4 +- tests/examples/example4-kicad.test.tsx | 41 ++- .../__snapshots__/schematicbox1.snap.svg | 2 +- .../__snapshots__/schematicbox2.snap.svg | 2 +- .../__snapshots__/schematicbox3.snap.svg | 2 +- .../getAllDimensionsForSchematicBox.test.ts | 4 +- 9 files changed, 170 insertions(+), 200 deletions(-) diff --git a/lib/utils/schematic/getAllDimensionsForSchematicBox.ts b/lib/utils/schematic/getAllDimensionsForSchematicBox.ts index e3befb0..7857b8e 100644 --- a/lib/utils/schematic/getAllDimensionsForSchematicBox.ts +++ b/lib/utils/schematic/getAllDimensionsForSchematicBox.ts @@ -38,7 +38,6 @@ export type PortArrangement = interface Params { schWidth?: number schHeight?: number - portDistanceFromEdge?: number schPinSpacing: number schPinStyle?: Record< `pin${number}` | number | `${number}`, @@ -60,13 +59,6 @@ function isExplicitPinMappingArrangement( ): arrangement is ExplicitPinMappingArrangement { return (arrangement as ExplicitPinMappingArrangement).leftSide !== undefined } - -export interface SchematicBoxDimensions { - pinCount: number - getPortPositionByPinNumber(pinNumber: number): { x: number; y: number } - getSize(): { width: number; height: number } -} - /** * Get the dimensions of a schematic box based on the provided parameters. * @@ -81,11 +73,16 @@ export interface SchematicBoxDimensions { * * We basically iterate over each side and compute how far we are from the * edge for that side by adding margins together */ +export interface SchematicBoxDimensions { + pinCount: number + getPortPositionByPinNumber(pinNumber: number): { x: number; y: number } + getSize(): { width: number; height: number } +} + export const getAllDimensionsForSchematicBox = ( params: Params, ): SchematicBoxDimensions => { - const portDistanceFromEdge = - params.portDistanceFromEdge ?? params.schPinSpacing * 2 + const componentMargin = params.schPinSpacing // Margin around the component let sidePinCounts = params.schPortArrangement ? getSizeOfSidesFromPortArrangement(params.schPortArrangement) @@ -102,7 +99,10 @@ export const getAllDimensionsForSchematicBox = ( if (pinCount === null) { if (sidePinCounts) { pinCount = - sidePinCounts.leftSize + sidePinCounts.rightSize + sidePinCounts.topSize + sidePinCounts.leftSize + + sidePinCounts.rightSize + + sidePinCounts.topSize + + sidePinCounts.bottomSize } else { throw new Error("Could not determine pin count for the schematic box") } @@ -127,191 +127,152 @@ export const getAllDimensionsForSchematicBox = ( } } - // Map the indices to the sides they correspond to + // Use lengths to determine schWidth and schHeight + const schWidth = + params.schWidth ?? + Math.max(sidePinCounts.topSize, sidePinCounts.bottomSize) * + params.schPinSpacing + + 2 * componentMargin + const schHeight = + params.schHeight ?? + Math.max(sidePinCounts.leftSize, sidePinCounts.rightSize) * + params.schPinSpacing + + 2 * componentMargin + + const distributePorts = ( + sideSize: number, + sideLength: number, + totalMargin: number, + ) => { + if (sideSize <= 1) return 0 + return (sideLength - totalMargin) / (sideSize - 1) + } + const orderedTruePorts: Array<{ trueIndex: number pinNumber: number side: "left" | "right" | "top" | "bottom" distanceFromEdge: number }> = [] - let currentDistanceFromEdge = 0 - let truePinIndex = 0 - // moving downward from the top-left corner - for (let sideIndex = 0; sideIndex < sidePinCounts.leftSize; sideIndex++) { - const pinNumber = - params.schPortArrangement && - isExplicitPinMappingArrangement(params.schPortArrangement) - ? params.schPortArrangement?.leftSide?.pins[sideIndex]! - : truePinIndex + 1 - const pinStyle = - params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber] - - if (pinStyle?.topMargin) { - currentDistanceFromEdge += pinStyle.topMargin - } - orderedTruePorts.push({ - trueIndex: truePinIndex, - pinNumber, - side: "left", - distanceFromEdge: currentDistanceFromEdge, - }) + let truePinIndex = 0 - if (pinStyle?.bottomMargin) { - currentDistanceFromEdge += pinStyle.bottomMargin + // Function to process each side + const processSide = ( + side: "left" | "right" | "top" | "bottom", + pins: number[], + direction: string, + ) => { + const isVertical = side === "left" || side === "right" + const sideLength = isVertical ? schHeight : schWidth + let totalMargin = 0 + + // Calculate total margin for the side + for (const pin of pins) { + const pinStyle = + params.schPinStyle?.[`pin${pin}`] ?? params.schPinStyle?.[pin] + if (pinStyle) { + if (isVertical) { + totalMargin += + (pinStyle.topMargin ?? 0) + (pinStyle.bottomMargin ?? 0) + } else { + totalMargin += + (pinStyle.leftMargin ?? 0) + (pinStyle.rightMargin ?? 0) + } + } } - const isLastPinOnSide = sideIndex === sidePinCounts.leftSize - 1 - if (!isLastPinOnSide) { - currentDistanceFromEdge += params.schPinSpacing - } else { - sideLengths.left = currentDistanceFromEdge - } - truePinIndex++ - } + const spacing = distributePorts( + pins.length, + sideLength - 2 * componentMargin, + totalMargin, + ) + let currentDistanceFromEdge = componentMargin + + pins.forEach((pinNumber, index) => { + const pinStyle = + params.schPinStyle?.[`pin${pinNumber}`] ?? + params.schPinStyle?.[pinNumber] + + if (pinStyle) { + if (isVertical) { + currentDistanceFromEdge += pinStyle.topMargin ?? 0 + } else { + currentDistanceFromEdge += pinStyle.leftMargin ?? 0 + } + } - currentDistanceFromEdge = 0 - // moving rightward from the left-bottom corner - for (let sideIndex = 0; sideIndex < sidePinCounts.bottomSize; sideIndex++) { - const pinNumber = - params.schPortArrangement && - isExplicitPinMappingArrangement(params.schPortArrangement) - ? params.schPortArrangement.bottomSide?.pins[sideIndex]! - : truePinIndex + 1 - const pinStyle = - params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber] - - if (pinStyle?.leftMargin) { - currentDistanceFromEdge += pinStyle.leftMargin - } + orderedTruePorts.push({ + trueIndex: truePinIndex, + pinNumber, + side, + distanceFromEdge: currentDistanceFromEdge, + }) + + if (pinStyle) { + if (isVertical) { + currentDistanceFromEdge += pinStyle.bottomMargin ?? 0 + } else { + currentDistanceFromEdge += pinStyle.rightMargin ?? 0 + } + } - orderedTruePorts.push({ - trueIndex: truePinIndex, - pinNumber, - side: "bottom", - distanceFromEdge: currentDistanceFromEdge, + currentDistanceFromEdge += spacing + truePinIndex++ }) - if (pinStyle?.rightMargin) { - currentDistanceFromEdge += pinStyle.rightMargin - } - - const isLastPinOnSide = sideIndex === sidePinCounts.bottomSize - 1 - if (!isLastPinOnSide) { - currentDistanceFromEdge += params.schPinSpacing - } else { - sideLengths.bottom = currentDistanceFromEdge - } - truePinIndex++ + sideLengths[side] = sideLength } - currentDistanceFromEdge = 0 - // moving upward from the bottom-right corner - for (let sideIndex = 0; sideIndex < sidePinCounts.rightSize; sideIndex++) { - const pinNumber = - params.schPortArrangement && - isExplicitPinMappingArrangement(params.schPortArrangement) - ? params.schPortArrangement.rightSide?.pins[sideIndex]! - : truePinIndex + 1 - const pinStyle = - params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber] - - if (pinStyle?.bottomMargin) { - currentDistanceFromEdge += pinStyle.bottomMargin - } - - orderedTruePorts.push({ - trueIndex: truePinIndex, - pinNumber, - side: "right", - distanceFromEdge: currentDistanceFromEdge, - }) - - if (pinStyle?.topMargin) { - currentDistanceFromEdge += pinStyle.topMargin - } - - const isLastPinOnSide = sideIndex === sidePinCounts.rightSize - 1 - if (!isLastPinOnSide) { - currentDistanceFromEdge += params.schPinSpacing - } else { - sideLengths.right = currentDistanceFromEdge + // Process each side + if ( + params.schPortArrangement && + isExplicitPinMappingArrangement(params.schPortArrangement) + ) { + if (params.schPortArrangement.leftSide) { + processSide( + "left", + params.schPortArrangement.leftSide.pins, + params.schPortArrangement.leftSide.direction ?? "top-to-bottom", + ) } - truePinIndex++ - } - - currentDistanceFromEdge = 0 - // moving leftward from the top-right corner - for (let sideIndex = 0; sideIndex < sidePinCounts.topSize; sideIndex++) { - const pinNumber = - params.schPortArrangement && - isExplicitPinMappingArrangement(params.schPortArrangement) - ? params.schPortArrangement.topSide?.pins[sideIndex]! - : truePinIndex + 1 - const pinStyle = - params.schPinStyle?.[`pin${pinNumber}`] ?? params.schPinStyle?.[pinNumber] - - if (pinStyle?.rightMargin) { - currentDistanceFromEdge += pinStyle.rightMargin + if (params.schPortArrangement.rightSide) { + processSide( + "right", + params.schPortArrangement.rightSide.pins, + params.schPortArrangement.rightSide.direction ?? "bottom-to-top", + ) } - - orderedTruePorts.push({ - trueIndex: truePinIndex, - pinNumber, - side: "top", - distanceFromEdge: currentDistanceFromEdge, - }) - - if (pinStyle?.leftMargin) { - currentDistanceFromEdge += pinStyle.leftMargin + if (params.schPortArrangement.topSide) { + processSide( + "top", + params.schPortArrangement.topSide.pins, + params.schPortArrangement.topSide.direction ?? "left-to-right", + ) } - - const isLastPinOnSide = sideIndex === sidePinCounts.topSize - 1 - if (!isLastPinOnSide) { - currentDistanceFromEdge += params.schPinSpacing - } else { - sideLengths.top = currentDistanceFromEdge + if (params.schPortArrangement.bottomSide) { + processSide( + "bottom", + params.schPortArrangement.bottomSide.pins, + params.schPortArrangement.bottomSide.direction ?? "left-to-right", + ) } - truePinIndex++ - } - - // Use lengths to determine schWidth and schHeight - let schWidth = params.schWidth - if (!schWidth) { - schWidth = Math.max( - sideLengths.top + params.schPinSpacing * 2, - sideLengths.bottom + params.schPinSpacing * 2, - ) - } - let schHeight = params.schHeight - if (!schHeight) { - schHeight = Math.max( - sideLengths.left + params.schPinSpacing * 2, - sideLengths.right + params.schPinSpacing * 2, - ) + } else { + const leftSide = Array.from({ length: sidePinCounts.leftSize }, (_, i) => i + 1) + const rightSide = Array.from({ length: sidePinCounts.rightSize }, (_, i) => i + sidePinCounts.leftSize + 1) + const topSide = Array.from({ length: sidePinCounts.topSize }, (_, i) => i + sidePinCounts.leftSize + sidePinCounts.rightSize + 1) + const bottomSide = Array.from({ length: pinCount - sidePinCounts.leftSize - sidePinCounts.rightSize - sidePinCounts.topSize }, (_, i) => i + sidePinCounts.leftSize + sidePinCounts.rightSize + sidePinCounts.topSize + 1) + processSide("left", leftSide, "top-to-bottom") + processSide("right", rightSide, "top-to-bottom") + processSide("top", topSide, "left-to-right") + processSide("bottom", bottomSide, "left-to-right") } const trueEdgePositions = { - // Top left corner - left: { - x: -schWidth / 2 - portDistanceFromEdge, - y: sideLengths.left / 2, - }, - // bottom left corner - bottom: { - x: -sideLengths.bottom / 2, - y: -schHeight / 2 - portDistanceFromEdge, - }, - // bottom right corner - right: { - x: schWidth / 2 + portDistanceFromEdge, - y: -sideLengths.right / 2, - }, - // top right corner - top: { - x: sideLengths.top / 2, - y: schHeight / 2 + portDistanceFromEdge, - }, + left: { x: -schWidth / 2, y: schHeight / 2 }, + bottom: { x: -schWidth / 2, y: schHeight / 2 }, + right: { x: schWidth / 2, y: -schHeight / 2 }, + top: { x: schWidth / 2, y: -schHeight / 2 }, } const trueEdgeTraversalDirections = { diff --git a/tests/components/normal-components/__snapshots__/chip.snap.svg b/tests/components/normal-components/__snapshots__/chip.snap.svg index 4bd4f48..448dde3 100644 --- a/tests/components/normal-components/__snapshots__/chip.snap.svg +++ b/tests/components/normal-components/__snapshots__/chip.snap.svg @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/tests/components/normal-components/__snapshots__/jumper-schematic.snap.svg b/tests/components/normal-components/__snapshots__/jumper-schematic.snap.svg index 708249d..c64a78d 100644 --- a/tests/components/normal-components/__snapshots__/jumper-schematic.snap.svg +++ b/tests/components/normal-components/__snapshots__/jumper-schematic.snap.svg @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/tests/examples/__snapshots__/example4-kicad-schematic.snap.svg b/tests/examples/__snapshots__/example4-kicad-schematic.snap.svg index 81267d3..852b5d5 100644 --- a/tests/examples/__snapshots__/example4-kicad-schematic.snap.svg +++ b/tests/examples/__snapshots__/example4-kicad-schematic.snap.svg @@ -1,4 +1,4 @@ -100000R10.0001C1ATmega8-16AU229GND7-V+82019221213141516172341823 \ No newline at end of file diff --git a/tests/examples/example4-kicad.test.tsx b/tests/examples/example4-kicad.test.tsx index 329f528..81ffa3b 100644 --- a/tests/examples/example4-kicad.test.tsx +++ b/tests/examples/example4-kicad.test.tsx @@ -1,8 +1,8 @@ -import { it, expect } from "bun:test" -import { getTestFixture } from "tests/fixtures/get-test-fixture" - +import { expect, it } from "bun:test"; +import { getTestFixture } from "tests/fixtures/get-test-fixture"; +import * as fs from "fs" it("example 4: kicad theme demo", async () => { - const { project, logSoup } = getTestFixture() + const { project, logSoup } = getTestFixture(); project.add( @@ -14,7 +14,13 @@ it("example 4: kicad theme demo", async () => { schX={-2} /> - + { schWidth={3} schHeight={7} pinLabels={{ - pin7: "GND", - pin8: "-V+" + pin7: "GND", + pin8: "-V+", }} schPinStyle={{ - pin29: { bottomMargin: 0.5 }, + pin22: { topMargin: 0.8 }, + pin12: { bottomMargin: 0.5 }, + pin15: { topMargin: 0.8 }, }} schPortArrangement={{ leftSide: { @@ -43,15 +51,16 @@ it("example 4: kicad theme demo", async () => { direction: "bottom-to-top", pins: [12, 13, 14, 15, 16, 17, 23], }, + bottomSide: { + direction: "left-to-right", + pins: [2, 3], + }, }} /> - , - ) - const fs = require('node:fs'); - const circuitJson = project.getCircuitJson(); - fs.writeFileSync('circuit.json', JSON.stringify(circuitJson, null, 2)); + + ); - project.render() + project.render(); - expect(project).toMatchSchematicSnapshot(import.meta.path) -}) + expect(project).toMatchSchematicSnapshot(import.meta.path); +}); diff --git a/tests/utils/schematic/__snapshots__/schematicbox1.snap.svg b/tests/utils/schematic/__snapshots__/schematicbox1.snap.svg index f1c123b..890f36f 100644 --- a/tests/utils/schematic/__snapshots__/schematicbox1.snap.svg +++ b/tests/utils/schematic/__snapshots__/schematicbox1.snap.svg @@ -1 +1 @@ -12345678 \ No newline at end of file +12345678 \ No newline at end of file diff --git a/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg b/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg index 0201f28..d9ff4ab 100644 --- a/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg +++ b/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg @@ -1 +1 @@ -12345678 \ No newline at end of file +12345678 \ No newline at end of file diff --git a/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg b/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg index dc9b1f0..a14c474 100644 --- a/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg +++ b/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg @@ -1 +1 @@ -12345678910111213141516 \ No newline at end of file +12345678910111213141516 \ No newline at end of file diff --git a/tests/utils/schematic/getAllDimensionsForSchematicBox.test.ts b/tests/utils/schematic/getAllDimensionsForSchematicBox.test.ts index 88d8efc..944678e 100644 --- a/tests/utils/schematic/getAllDimensionsForSchematicBox.test.ts +++ b/tests/utils/schematic/getAllDimensionsForSchematicBox.test.ts @@ -42,9 +42,9 @@ test("getAllDimensionsForSchematicBox 3 (4 sided with margins)", () => { const params: Parameters[0] = { schPinSpacing: 0.2, schPinStyle: { - pin6: { rightMargin: 0.5 }, + pin6: { bottomMargin: 0.5 }, pin9: { topMargin: 0.4 }, - pin13: { leftMargin: 0.9 }, + pin13: { leftMargin: 0.2 }, }, schPortArrangement: { leftSize: 4, From 7d7a135e0ebf91d39683fc20207d0dea6f2bb7d6 Mon Sep 17 00:00:00 2001 From: Rishabh Gupta Date: Mon, 7 Oct 2024 01:19:29 +0530 Subject: [PATCH 2/2] fix the direction of margin --- .../getAllDimensionsForSchematicBox.ts | 83 +++++++++++++++++-- tests/examples/example4-kicad.test.tsx | 2 +- .../__snapshots__/schematicbox2.snap.svg | 2 +- .../__snapshots__/schematicbox3.snap.svg | 2 +- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/lib/utils/schematic/getAllDimensionsForSchematicBox.ts b/lib/utils/schematic/getAllDimensionsForSchematicBox.ts index 7857b8e..7e99e3f 100644 --- a/lib/utils/schematic/getAllDimensionsForSchematicBox.ts +++ b/lib/utils/schematic/getAllDimensionsForSchematicBox.ts @@ -196,9 +196,31 @@ export const getAllDimensionsForSchematicBox = ( if (pinStyle) { if (isVertical) { - currentDistanceFromEdge += pinStyle.topMargin ?? 0 + if (side === "left") { + currentDistanceFromEdge += + direction === "top-to-bottom" + ? (pinStyle.topMargin ?? 0) + : (pinStyle.bottomMargin ?? 0) + } else { + // right side + currentDistanceFromEdge += + direction === "top-to-bottom" + ? (pinStyle.bottomMargin ?? 0) + : (pinStyle.topMargin ?? 0) + } } else { - currentDistanceFromEdge += pinStyle.leftMargin ?? 0 + if (side === "top") { + currentDistanceFromEdge += + direction === "left-to-right" + ? (pinStyle.leftMargin ?? 0) + : (pinStyle.rightMargin ?? 0) + } else { + // bottom side + currentDistanceFromEdge += + direction === "left-to-right" + ? (pinStyle.rightMargin ?? 0) + : (pinStyle.leftMargin ?? 0) + } } } @@ -211,9 +233,31 @@ export const getAllDimensionsForSchematicBox = ( if (pinStyle) { if (isVertical) { - currentDistanceFromEdge += pinStyle.bottomMargin ?? 0 + if (side === "left") { + currentDistanceFromEdge += + direction === "top-to-bottom" + ? (pinStyle.bottomMargin ?? 0) + : (pinStyle.topMargin ?? 0) + } else { + // right side + currentDistanceFromEdge += + direction === "top-to-bottom" + ? (pinStyle.topMargin ?? 0) + : (pinStyle.bottomMargin ?? 0) + } } else { - currentDistanceFromEdge += pinStyle.rightMargin ?? 0 + if (side === "top") { + currentDistanceFromEdge += + direction === "left-to-right" + ? (pinStyle.rightMargin ?? 0) + : (pinStyle.leftMargin ?? 0) + } else { + // bottom side + currentDistanceFromEdge += + direction === "left-to-right" + ? (pinStyle.leftMargin ?? 0) + : (pinStyle.rightMargin ?? 0) + } } } @@ -258,10 +302,33 @@ export const getAllDimensionsForSchematicBox = ( ) } } else { - const leftSide = Array.from({ length: sidePinCounts.leftSize }, (_, i) => i + 1) - const rightSide = Array.from({ length: sidePinCounts.rightSize }, (_, i) => i + sidePinCounts.leftSize + 1) - const topSide = Array.from({ length: sidePinCounts.topSize }, (_, i) => i + sidePinCounts.leftSize + sidePinCounts.rightSize + 1) - const bottomSide = Array.from({ length: pinCount - sidePinCounts.leftSize - sidePinCounts.rightSize - sidePinCounts.topSize }, (_, i) => i + sidePinCounts.leftSize + sidePinCounts.rightSize + sidePinCounts.topSize + 1) + const leftSide = Array.from( + { length: sidePinCounts.leftSize }, + (_, i) => i + 1, + ) + const rightSide = Array.from( + { length: sidePinCounts.rightSize }, + (_, i) => i + sidePinCounts.leftSize + 1, + ) + const topSide = Array.from( + { length: sidePinCounts.topSize }, + (_, i) => i + sidePinCounts.leftSize + sidePinCounts.rightSize + 1, + ) + const bottomSide = Array.from( + { + length: + pinCount - + sidePinCounts.leftSize - + sidePinCounts.rightSize - + sidePinCounts.topSize, + }, + (_, i) => + i + + sidePinCounts.leftSize + + sidePinCounts.rightSize + + sidePinCounts.topSize + + 1, + ) processSide("left", leftSide, "top-to-bottom") processSide("right", rightSide, "top-to-bottom") processSide("top", topSide, "left-to-right") diff --git a/tests/examples/example4-kicad.test.tsx b/tests/examples/example4-kicad.test.tsx index 81ffa3b..392826a 100644 --- a/tests/examples/example4-kicad.test.tsx +++ b/tests/examples/example4-kicad.test.tsx @@ -1,6 +1,6 @@ import { expect, it } from "bun:test"; import { getTestFixture } from "tests/fixtures/get-test-fixture"; -import * as fs from "fs" + it("example 4: kicad theme demo", async () => { const { project, logSoup } = getTestFixture(); diff --git a/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg b/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg index d9ff4ab..4c710a3 100644 --- a/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg +++ b/tests/utils/schematic/__snapshots__/schematicbox2.snap.svg @@ -1 +1 @@ -12345678 \ No newline at end of file +12345678 \ No newline at end of file diff --git a/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg b/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg index a14c474..9115c0d 100644 --- a/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg +++ b/tests/utils/schematic/__snapshots__/schematicbox3.snap.svg @@ -1 +1 @@ -12345678910111213141516 \ No newline at end of file +12345678910111213141516 \ No newline at end of file