Skip to content

Commit

Permalink
Merge pull request #5 from tscircuit/hack
Browse files Browse the repository at this point in the history
add hack allowing missing start_pcb_port_ids and end_pcb_port_ids to not break overlap testing when a trace only contains two ports
  • Loading branch information
seveibar authored Jul 24, 2024
2 parents 1cbeb64 + 97f1664 commit 22dac95
Show file tree
Hide file tree
Showing 7 changed files with 1,876 additions and 39 deletions.
60 changes: 50 additions & 10 deletions lib/add-start-and-end-port-ids-if-missing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,77 @@ import type {
SourceTrace,
AnySoupElement,
PCBTraceError,
PCBSMTPad,
} from "@tscircuit/soup"

function distance(x1: number, y1: number, x2: number, y2: number): number {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
}

/**
* HACK: this whole method and all usage of it is a hack because of this issue:
* https://github.com/tscircuit/tscircuit/issues/291
*/
export const addStartAndEndPortIdsIfMissing = (
soup: AnySoupElement[],
): void => {
const pcbPorts: PCBPort[] = soup.filter((item) => item.type === "pcb_port")
const pcbSmtPads: PCBSMTPad[] = soup.filter(
(item) => item.type === "pcb_smtpad",
)
const pcbTraces: PCBTrace[] = soup.filter((item) => item.type === "pcb_trace")

function findPortIdOverlappingPoint(
point: {
x: number
y: number
},
options: { isFirstOrLastPoint?: boolean } = {},
): string | null {
const directPort = pcbPorts.find(
(port) => distance(port.x, port.y, point.x, point.y) < 0.01,
)
if (directPort) return directPort.pcb_port_id

// If it starts or ends inside an smtpad, we'll connect it to the por
if (options.isFirstOrLastPoint) {
const smtPad = pcbSmtPads.find((pad) => {
if (pad.shape === "rect") {
return (
Math.abs(point.x - pad.x) < pad.width / 2 &&
Math.abs(point.y - pad.y) < pad.height / 2
)
// biome-ignore lint/style/noUselessElse: <explanation>
} else if (pad.shape === "circle") {
return distance(point.x, point.y, pad.x, pad.y) < pad.radius
}
})
if (smtPad) return smtPad.pcb_port_id ?? null
}

return null
}

// Add start_pcb_port_id and end_pcb_port_id if not present
for (const trace of pcbTraces) {
for (let index = 0; index < trace.route.length; index++) {
const segment = trace.route[index]
const isFirstOrLastPoint = index === 0 || index === trace.route.length - 1
if (segment.route_type === "wire") {
if (!segment.start_pcb_port_id && index === 0) {
const startPort = pcbPorts.find(
(port) => distance(port.x, port.y, segment.x, segment.y) < 0.001,
)
if (startPort) {
segment.start_pcb_port_id = startPort.pcb_port_id
const startPortId = findPortIdOverlappingPoint(segment, {
isFirstOrLastPoint,
})
if (startPortId) {
segment.start_pcb_port_id = startPortId
}
}
if (!segment.end_pcb_port_id && index === trace.route.length - 1) {
const endPort = pcbPorts.find(
(port) => distance(port.x, port.y, segment.x, segment.y) < 0.001,
)
if (endPort) {
segment.end_pcb_port_id = endPort.pcb_port_id
const endPortId = findPortIdOverlappingPoint(segment, {
isFirstOrLastPoint,
})
if (endPortId) {
segment.end_pcb_port_id = endPortId
}
}
}
Expand Down
55 changes: 35 additions & 20 deletions lib/check-each-pcb-trace-non-overlapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
import { NetManager } from "./net-manager"
import { addStartAndEndPortIdsIfMissing } from "./add-start-and-end-port-ids-if-missing"
import Debug from "debug"
import { su } from "@tscircuit/soup-util"

const debug = Debug("tscircuit:checks:check-each-pcb-trace-non-overlapping")

Expand Down Expand Up @@ -58,7 +59,7 @@ function tracesOverlap(trace1: PCBTrace, trace2: PCBTrace): boolean {
seg4.x,
seg4.y,
)
return areLinesIntersecting
if (areLinesIntersecting) return true
}
}
}
Expand Down Expand Up @@ -130,22 +131,24 @@ function traceOverlapsWithPad(trace: PCBTrace, pad: PCBSMTPad): boolean {
return false
}

function getPortIdsConnectedToTrace(trace: PCBTrace) {
const connectedPorts = new Set<string>()
function getPcbPortIdsConnectedToTrace(trace: PCBTrace) {
const connectedPcbPorts = new Set<string>()
for (const segment of trace.route) {
if (segment.route_type === "wire") {
if (segment.start_pcb_port_id)
connectedPorts.add(segment.start_pcb_port_id)
if (segment.end_pcb_port_id) connectedPorts.add(segment.end_pcb_port_id)
connectedPcbPorts.add(segment.start_pcb_port_id)
if (segment.end_pcb_port_id)
connectedPcbPorts.add(segment.end_pcb_port_id)
}
}
return Array.from(connectedPorts)

return Array.from(connectedPcbPorts)
}

function getPortIdsConnectedToTraces(...traces: PCBTrace[]) {
function getPcbPortIdsConnectedToTraces(traces: PCBTrace[]) {
const connectedPorts = new Set<string>()
for (const trace of traces) {
for (const portId of getPortIdsConnectedToTrace(trace)) {
for (const portId of getPcbPortIdsConnectedToTrace(trace)) {
connectedPorts.add(portId)
}
}
Expand All @@ -167,22 +170,31 @@ function checkEachPcbTraceNonOverlapping(

// TODO use source port ids instead of port ids, parse source ports for connections
for (const trace of pcbTraces) {
netManager.setConnected(getPortIdsConnectedToTrace(trace))
netManager.setConnected(getPcbPortIdsConnectedToTrace(trace))
}

for (let i = 0; i < pcbTraces.length; i++) {
for (let j = i + 1; j < pcbTraces.length; j++) {
debug(
`Checking overlap for ${pcbTraces[i].pcb_trace_id} and ${pcbTraces[j].pcb_trace_id}`,
)
debug(
`Connected ports: ${getPortIdsConnectedToTraces(pcbTraces[i], pcbTraces[j])}`,
)
if (
netManager.isConnected(
getPortIdsConnectedToTraces(pcbTraces[i], pcbTraces[j]),
)
) {
const connectedPorts = getPcbPortIdsConnectedToTraces([
pcbTraces[i],
pcbTraces[j],
])
debug(`Connected ports: ${connectedPorts.join(",")}`)

if (connectedPorts.length === 0) {
debug("No ports connected to trace, skipping")
continue
}

if (connectedPorts.length === 1) {
debug("Only one port connected, skipping")
continue
}

if (netManager.isConnected(connectedPorts)) {
continue
}
if (tracesOverlap(pcbTraces[i], pcbTraces[j])) {
Expand All @@ -194,7 +206,10 @@ function checkEachPcbTraceNonOverlapping(
source_trace_id: "",
pcb_error_id: `overlap_${pcbTraces[i].pcb_trace_id}_${pcbTraces[j].pcb_trace_id}`,
pcb_component_ids: [],
pcb_port_ids: getPortIdsConnectedToTraces(pcbTraces[i], pcbTraces[j]),
pcb_port_ids: getPcbPortIdsConnectedToTraces([
pcbTraces[i],
pcbTraces[j],
]),
})
}
}
Expand All @@ -203,7 +218,7 @@ function checkEachPcbTraceNonOverlapping(
if (
pad.pcb_port_id &&
netManager.isConnected(
getPortIdsConnectedToTrace(pcbTraces[i]).concat([pad.pcb_port_id]),
getPcbPortIdsConnectedToTrace(pcbTraces[i]).concat([pad.pcb_port_id]),
)
) {
continue
Expand All @@ -217,7 +232,7 @@ function checkEachPcbTraceNonOverlapping(
source_trace_id: "",
pcb_error_id: `overlap_${pcbTraces[i].pcb_trace_id}_${pad.pcb_smtpad_id}`,
pcb_component_ids: [],
pcb_port_ids: getPortIdsConnectedToTrace(pcbTraces[i]),
pcb_port_ids: getPcbPortIdsConnectedToTrace(pcbTraces[i]),
})
}
}
Expand Down
31 changes: 25 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"tsup": "^8.2.3"
},
"peerDependencies": {
"typescript": "^5.5.3",
"@tscircuit/soup": "*",
"@tscircuit/soup-util": "*"
"@tscircuit/soup-util": "*",
"typescript": "^5.5.3"
}
}
Loading

0 comments on commit 22dac95

Please sign in to comment.