Skip to content

Commit

Permalink
fix scaling issue of dsn-converter
Browse files Browse the repository at this point in the history
  • Loading branch information
imrishabh18 committed Nov 21, 2024
1 parent 3fd51e7 commit fe5f3d6
Show file tree
Hide file tree
Showing 8 changed files with 380 additions and 14 deletions.
Binary file modified bun.lockb
Binary file not shown.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@types/bun": "latest",
"@types/debug": "^4.1.12",
"@types/react": "18.3.4",
"circuit-json-to-connectivity-map": "^0.0.17",
"debug": "^4.3.6",
"debug": "^4.3.7",
"next": "^14.2.5",
"performance-now": "^2.1.0",
"redaxios": "^0.5.1"
Expand All @@ -25,7 +26,8 @@
"@tscircuit/soup-util": "^0.0.38",
"bun-match-svg": "^0.0.6",
"circuit-to-svg": "^0.0.81",
"dsn-converter": "^0.0.16",
"dsn-converter": "^0.0.18",
"graphics-debug": "^0.0.1",
"kleur": "^4.1.5",
"schematic-symbols": "0.0.99",
"transformation-matrix": "^2.16.1",
Expand Down
64 changes: 52 additions & 12 deletions routes/_fake/run_autorouter.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { withRouteSpec } from "lib/middleware/with-winter-spec"
import { z } from "zod"
import {
parseDsnToCircuitJson,
convertCircuitJsonToDsnString,
convertCircuitJsonToDsnSession,
parseDsnToDsnJson,
type DsnPcb,
stringifyDsnSession,
} from "dsn-converter"
import type { AnyCircuitElement, PcbTrace } from "circuit-json"
import {
MultilayerIjump,
getSimpleRouteJson,
} from "@tscircuit/infgrid-ijump-astar"
import { su } from "@tscircuit/soup-util"
import type { AnyCircuitElement, PcbTrace } from "circuit-json"
import Debug from "debug"
import {
type DsnPcb,
convertCircuitJsonToDsnSession,
parseDsnToCircuitJson,
parseDsnToDsnJson,
stringifyDsnSession
} from "dsn-converter"
import { withRouteSpec } from "lib/middleware/with-winter-spec"
import { circuitJsonToMarkdownTable } from "tests/debug-utils/circuit-json-to-table"
import { analyzeWirePaths } from "tests/debug-utils/extract-trace-from-ses-file"
import { saveRouteAnalysis } from "tests/debug-utils/simple-route-json-to-table"
import { z } from "zod"

const debugGraphics = Debug("tscircuit:fake-autorouter")

function addPcbTracesToCircuitJson(
circuitJson: AnyCircuitElement[],
Expand Down Expand Up @@ -69,8 +73,25 @@ export default withRouteSpec({
const inputDsn = Buffer.from(job.input._input_dsn!, "base64").toString()
const dsnPcb = parseDsnToDsnJson(inputDsn) as DsnPcb
const circuitJson = parseDsnToCircuitJson(inputDsn)

if (debugGraphics.enabled) {
circuitJsonToMarkdownTable(
circuitJson,
"../routes/_fake/debug-files-stages/stage-1-circuit-json.md",
"Stage 1: Circuit JSON as input to fake",
)
}

const simpleRouteJson = getSimpleRouteJson(circuitJson)

if (debugGraphics.enabled) {
saveRouteAnalysis(
simpleRouteJson,
"../routes/_fake/debug-files-stages/stage-2-simple-route-json.md",
"Stage 2: Simple Route JSON as input to autorouter",
)
}

const autorouter = new MultilayerIjump({
input: simpleRouteJson,
OBSTACLE_MARGIN: 0.2,
Expand All @@ -83,6 +104,15 @@ export default withRouteSpec({
}
const routedCircuitJson = addPcbTracesToCircuitJson(circuitJson, traces)

if (debugGraphics.enabled) {
circuitJsonToMarkdownTable(
routedCircuitJson,
"../routes/_fake/debug-files-stages/stage-3-routed-circuit-json.md",
"Stage 3: Routed Circuit JSON as output from the fake autorouter",
)
// saveRouteAnalysis(traces, "routed-trace-points.md")
}

// console.dir(
// {
// simpleRouteJson,
Expand All @@ -99,6 +129,16 @@ export default withRouteSpec({
)

const routedDsnString = stringifyDsnSession(routedDsnSession)
if (debugGraphics.enabled) {
debugGraphics({
routedDsnString,
})
analyzeWirePaths(
routedDsnString,
"../routes/_fake/debug-files-stages/stage-4-ses-file-trace-points.md",
"Last stage: SES file conversion from routed circuit JSON",
)
}
// convert the DSN to a SES file

ctx.db.jobs[jobIndex] = {
Expand Down
86 changes: 86 additions & 0 deletions tests/debug-utils/circuit-json-to-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import type { AnyCircuitElement } from '@tscircuit/soup';
import fs from 'node:fs';
import path from 'node:path';

function formatNumber(num: number) {
return typeof num === 'number' ? Number(num.toFixed(1)) : 'N/A';
}

function formatPoint(x: number, y: number) {
return `(${formatNumber(x)}, ${formatNumber(y)})`;
}

function convertCircuitJsonToMarkdown(circuitJson: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : '# Circuit Component Analysis\n\n';

// Source Components
const sourceComponents = circuitJson.filter((item: AnyCircuitElement) => item.type === "source_component");
if (sourceComponents.length > 0) {
markdown += '## Source Components\n';
markdown += '| ID | Name | Type |\n';
markdown += '|----|------|------|\n';
for (const comp of sourceComponents) {
const shortId = comp.source_component_id.split(':').pop();
markdown += `| ${shortId} | ${comp.name} | ${comp.ftype} |\n`;
}
markdown += '\n';
}

// PCB Ports
const ports = circuitJson.filter((item: AnyCircuitElement) => item.type === "pcb_port");
if (ports.length > 0) {
markdown += '## PCB Ports\n';
markdown += '| ID | Position (x,y) |\n';
markdown += '|-----|---------------|\n';
for (const port of ports) {
const shortId = port.pcb_port_id.split('-').slice(-2).join('-');
markdown += `| ${shortId} | ${formatPoint(port.x, port.y)} |\n`;
}
markdown += '\n';
}

// SMT Pads
const pads = circuitJson.filter((item: AnyCircuitElement) => item.type === "pcb_smtpad");
if (pads.length > 0) {
markdown += '## SMT Pads\n';
markdown += '| Component | Position (x,y) | Size (w×h) |\n';
markdown += '|-----------|---------------|-------------|\n';
for (const pad of pads) {
const shortId = pad.pcb_smtpad_id.split('_').slice(-3).join('-');
markdown += `| ${shortId} | ${formatPoint(pad.x, pad.y)} | ${formatNumber(pad.width)} × ${formatNumber(pad.height)} |\n`;
}
markdown += '\n';
}

// Traces
const traces = circuitJson.filter((item: AnyCircuitElement) => item.type === "pcb_trace");
if (traces.length > 0) {
markdown += '## Trace Route Points\n';
markdown += '| Point | Position (x,y) | Width |\n';
markdown += '|-------|---------------|--------|\n';
for (const trace of traces) {
for (const [index, point] of trace.route.entries()) {
if (point.route_type === "wire") {
markdown += `| ${index + 1} | ${formatPoint(point.x, point.y)} | ${formatNumber(point.width)} |\n`;
}
}
}
}

return markdown;
}

export function circuitJsonToMarkdownTable(circuitJson: AnyCircuitElement[], outputPath: string, title?: string) {
try {
const markdown = convertCircuitJsonToMarkdown(circuitJson, title);
// Resolve the output path relative to the current file's directory
const resolvedOutputPath = path.resolve(__dirname, outputPath);
console.log(`Resolved output path: ${resolvedOutputPath}`);
fs.writeFileSync(resolvedOutputPath, markdown);
console.log(`Circuit JSON has been written to ${resolvedOutputPath}`);
return markdown;
} catch (error) {
console.error('Error processing circuit JSON:', error);
throw error;
}
}
76 changes: 76 additions & 0 deletions tests/debug-utils/extract-trace-from-ses-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import fs from 'node:fs';
import path from 'node:path';

function formatNumber(num: number) {
// Format number to 2 decimal places and remove trailing zeros
return parseFloat(num.toFixed(2)).toString();
}

function extractWirePathPoints(sesContent: string) {
const wirePathRegex = /path\s+([A-Za-z.]+)\s+([0-9.]+)\s+([\d.-\s]+)/g;
const paths = [];

let match: RegExpExecArray | null;
while (true) {
match = wirePathRegex.exec(sesContent)
if (match === null) break
const layer = match[1]
const width = match[2]
const coordinates = match[3].trim().split(/\s+/)

const points = []
for (let i = 0; i < coordinates.length; i += 2) {
points.push({
x: parseFloat(coordinates[i]),
y: parseFloat(coordinates[i + 1]),
})
}

paths.push({
layer,
width,
points,
})
}

return paths;
}

function generateMarkdownTable(paths: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : '# Wire Path Points Analysis\n\n';

for (const [index, path] of paths.entries()) {
markdown += `## Wire Path ${index + 1}\n`;
markdown += `- Layer: ${path.layer}\n`;
markdown += `- Width: ${path.width}mm\n\n`;

// Fixed width columns with padding
markdown += '| Point # | X (μm) | Y (μm) |\n';
markdown += '|---------|--------------|--------------||\n';

for (const [pointIndex, point] of path.points.entries()) {
const formattedX = formatNumber(point.x).padStart(12, ' ');
const formattedY = formatNumber(point.y).padStart(12, ' ');
markdown += `| ${(pointIndex + 1).toString().padStart(2)} |${formattedX}|${formattedY}|\n`;
}

markdown += '\n';
}

return markdown;
}

export function analyzeWirePaths(sesContent: string, outputPath: string, title?: string) {
try {
const paths = extractWirePathPoints(sesContent)
const markdown = generateMarkdownTable(paths, title);
const resolvedOutputPath = path.resolve(__dirname, outputPath);
fs.writeFileSync(resolvedOutputPath, markdown);
console.log(`Wire path analysis has been written to ${resolvedOutputPath}`);

return paths;
} catch (error) {
console.error('Error processing file:', error);
throw error;
}
}
67 changes: 67 additions & 0 deletions tests/debug-utils/simple-route-json-to-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import fs from 'node:fs';
import path from 'node:path';

function formatNumber(num: number) {
return parseFloat(num.toFixed(2)).toString().padStart(8, ' ');
}

function convertRouteJsonToMarkdown(routeJson: any, title?: string) {
let markdown = title ? `# ${title}\n\n` : '# Simple Route JSON Analysis\n\n';

// Basic Information
markdown += '## General Information\n';
markdown += `- Minimum Trace Width: ${routeJson.minTraceWidth}mm\n`;
markdown += `- Layer Count: ${routeJson.layerCount}\n\n`;

// Bounds Information
markdown += '## Board Bounds\n';
markdown += '| Dimension | Min (mm) | Max (mm) |\n';
markdown += '|-----------|----------|----------|\n';
markdown += `| X |${formatNumber(routeJson.bounds.minX)}|${formatNumber(routeJson.bounds.maxX)}|\n`;
markdown += `| Y |${formatNumber(routeJson.bounds.minY)}|${formatNumber(routeJson.bounds.maxY)}|\n\n`;

// Obstacles
markdown += '## Obstacles\n';
markdown += '| Type | Layer | X (mm) | Y (mm) | Width (mm) | Height (mm) | Connected To |\n';
markdown += '|-------|--------|---------|---------|------------|-------------|-------------|\n';

for (const obstacle of routeJson.obstacles) {
markdown += `| ${obstacle.type} | ${obstacle.layers.join(', ')} |`;
markdown += `${formatNumber(obstacle.center.x)}|${formatNumber(obstacle.center.y)}|`;
markdown += `${formatNumber(obstacle.width)}|${formatNumber(obstacle.height)}|`;
markdown += ` ${obstacle.connectedTo.map((conn: any) => `\n- ${conn}`).join('')} |\n`;
}
markdown += '\n';

// Connections
markdown += '## Connections\n';
for (const [index, connection] of routeJson.connections.entries()) {
markdown += `### Connection ${index + 1}: ${connection.name}\n`;
markdown += '| Point | X (mm) | Y (mm) | Layer | Port ID |\n';
markdown += '|--------|---------|---------|--------|----------|\n';

for (const [pointIndex, point] of connection.pointsToConnect.entries()) {
markdown += `| ${pointIndex + 1} |`;
markdown += `${formatNumber(point.x)}|${formatNumber(point.y)}|`;
markdown += ` ${point.layer} | ${point.pcb_port_id} |\n`;
}
markdown += '\n';
}

return markdown;
}

export function saveRouteAnalysis(routeJson: any, outputPath: string, title?: string) {
try {
const markdown = convertRouteJsonToMarkdown(routeJson, title);
// Resolve the output path relative to the current file's directory
const resolvedOutputPath = path.resolve(__dirname, outputPath);
fs.writeFileSync(resolvedOutputPath, markdown);
console.log(`Route analysis has been written to ${resolvedOutputPath}`);
return markdown;
} catch (error) {
console.error('Error processing route JSON:', error);
throw error;
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit fe5f3d6

Please sign in to comment.