diff --git a/bun.lockb b/bun.lockb index 924052a..b42bd2e 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts b/lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts index b530f54..8b4eb16 100644 --- a/lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts +++ b/lib/sch/svg-object-fns/create-svg-objects-from-sch-trace.ts @@ -14,34 +14,53 @@ export function createSchematicTrace( let path = "" // Process all edges - edges.forEach((edge: any, index: number) => { - // Get the points, applying trace offset - const fromPoint = { - x: edge.from.x ?? edge.from.center?.x, - y: edge.from.y ?? edge.from.center?.y, - } - const toPoint = { - x: edge.to.x ?? edge.to.center?.x, - y: edge.to.y ?? edge.to.center?.y, - } + for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) { + const edge = edges[edgeIndex]! // Transform the points using the matrix - const [transformedFromX, transformedFromY] = applyToPoint(transform, [ - fromPoint.x, - fromPoint.y, + const [screenFromX, screenFromY] = applyToPoint(transform, [ + edge.from.x, + edge.from.y, ]) - const [transformedToX, transformedToY] = applyToPoint(transform, [ - toPoint.x, - toPoint.y, + const [screenToX, screenToY] = applyToPoint(transform, [ + edge.to.x, + edge.to.y, ]) - // Build the path string - if (index === 0) { - path += `M ${transformedFromX} ${transformedFromY} L ${transformedToX} ${transformedToY}` + if (edge.is_crossing) { + // For crossing traces, create a small arc/hop + const midX = (screenFromX + screenToX) / 2 + const midY = (screenFromY + screenToY) / 2 + + // Calculate perpendicular offset for the arc + const dx = screenToX - screenFromX + const dy = screenToY - screenFromY + const len = Math.sqrt(dx * dx + dy * dy) + const hopHeight = len * 0.7 + + // Perpendicular vector + const perpX = (-dy / len) * hopHeight + const perpY = (dx / len) * hopHeight + + // Control point for the quadratic curve + const controlX = midX + perpX + const controlY = midY - Math.abs(perpY) + + // Build the path string with a quadratic curve for the hop + if (edgeIndex === 0) { + path += `M ${screenFromX} ${screenFromY} Q ${controlX} ${controlY} ${screenToX} ${screenToY}` + } else { + path += ` Q ${controlX} ${controlY} ${screenToX} ${screenToY}` + } + } + + // Regular straight line for non-crossing traces + if (edgeIndex === 0) { + path += `M ${screenFromX} ${screenFromY} L ${screenToX} ${screenToY}` } else { - path += ` L ${transformedToX} ${transformedToY}` + path += ` L ${screenToX} ${screenToY}` } - }) + } // Only create SVG object if we have a valid path return path diff --git a/package.json b/package.json index 115a995..5ef9b8c 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "@storybook/react": "^8.2.5", "@storybook/react-vite": "^8.2.5", "@storybook/test": "^8.2.5", - "@tscircuit/core": "^0.0.153", + "@tscircuit/core": "^0.0.155", "@tscircuit/plop": "^0.0.10", "@types/bun": "^1.1.9", "bun-match-svg": "^0.0.6", @@ -41,7 +41,7 @@ "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { - "circuit-json": "^0.0.95" + "circuit-json": "^0.0.97" }, "dependencies": { "@tscircuit/footprinter": "^0.0.57", diff --git a/tests/sch/__snapshots__/trace-overlap.snap.svg b/tests/sch/__snapshots__/trace-overlap.snap.svg new file mode 100644 index 0000000..010945f --- /dev/null +++ b/tests/sch/__snapshots__/trace-overlap.snap.svg @@ -0,0 +1,12 @@ +R110kΩR210kΩR310kΩ \ No newline at end of file diff --git a/tests/sch/trace-overlap.test.tsx b/tests/sch/trace-overlap.test.tsx new file mode 100644 index 0000000..a038866 --- /dev/null +++ b/tests/sch/trace-overlap.test.tsx @@ -0,0 +1,34 @@ +import { test, expect } from "bun:test" +import { convertCircuitJsonToSchematicSvg } from "lib" +import { getTestFixture } from "tests/fixtures/get-test-fixture" + +test("schematic trace overlap", () => { + const { project } = getTestFixture() + + project.add( + + + + + + + + , + ) + + expect( + convertCircuitJsonToSchematicSvg(project.getCircuitJson()), + ).toMatchSvgSnapshot(import.meta.path) +})