ShiboSoftwareDev/nema8-20mm-dual-usbc-stepper-controller

BAT54C dual Schottky diode in a 3-pin SMD package, with two anodes and a shared cathode.

Version
1.0.14
License
unset
Stars
0

scripts/search-segment-detours.mjs

import fs from "node:fs"
import { runAllRoutingChecks } from "@tscircuit/checks"

let circuit = JSON.parse(
  fs.readFileSync("dist/index/circuit.json", "utf8"),
).filter((element) => !String(element.type).endsWith("error"))

const samePoint = (point, x, y) =>
  Math.abs(point.x - x) < 1e-5 && Math.abs(point.y - y) < 1e-5

const viaMoves = [
  ["source_net_30", 0.3165170373, 2.4681926742, 0.1165, 2.3682],
  ["source_net_26", -4.9635288614, 0.8009878988, -5.2635, 0.601],
  ["source_net_26", -1.0149987646, -4.722238758, -1.215, -4.7222],
  ["source_net_22", -5.975494, -3.367, -6.2755, -3.567],
  ["source_net_22", 1.9745212144, 2.375001, 1.6745, 2.875],
  ["source_net_21", 1.6, -3.9750010113, 1.6, -3.775],
]

const applyViaMove = (input, [connectionName, oldX, oldY, newX, newY]) => input.map((element) => {
  if (element.type === "pcb_via" && element.pcb_trace_id?.startsWith(connectionName) &&
      samePoint(element, oldX, oldY)) return { ...element, x: newX, y: newY }
  if (element.type !== "pcb_trace" || element.connection_name !== connectionName) return element
  return {
    ...element,
    route: element.route.map((point) => samePoint(point, oldX, oldY)
      ? { ...point, x: newX, y: newY }
      : point),
  }
})

// The live build already contains the accepted via moves and trace detours.
if (false) for (const move of viaMoves) circuit = applyViaMove(circuit, move)

const shiftTraceWindow = (input, traceId, center, windowRadius, dx, dy) => input.map((element) => {
  if (element.type !== "pcb_trace" || element.pcb_trace_id !== traceId) return element
  const viaCoordinates = element.route
    .filter((point) => point.route_type === "via")
    .map((point) => [point.x, point.y])
  let nearestIndex = -1
  let nearestDistance = Infinity
  element.route.forEach((point, index) => {
    if (point.route_type !== "wire" || index === 0 || index === element.route.length - 1) return
    if (viaCoordinates.some(([x, y]) => samePoint(point, x, y))) return
    const distance = Math.hypot(point.x - center.x, point.y - center.y)
    if (distance < nearestDistance) {
      nearestIndex = index
      nearestDistance = distance
    }
  })
  if (nearestIndex < 0) return element
  const anchor = element.route[nearestIndex]
  return {
    ...element,
    route: element.route.map((point, index) => {
      if (point.route_type !== "wire" || index === 0 || index === element.route.length - 1) return point
      if (viaCoordinates.some(([x, y]) => samePoint(point, x, y))) return point
      const distance = Math.hypot(point.x - anchor.x, point.y - anchor.y)
      return distance <= windowRadius ? { ...point, x: point.x + dx, y: point.y + dy } : point
    }),
  }
})

let errors = await runAllRoutingChecks(circuit)
console.log(`start\t${errors.length}`)
const deltas = [-0.3, -0.2, -0.1, -0.05, 0.05, 0.1, 0.2, 0.3]

for (let pass = 0; pass < 4; pass++) {
  let improved = false
  const traceErrors = errors.filter((error) => error.pcb_trace_id && error.center)
  for (const error of traceErrors) {
    let best = { count: errors.length, circuit, errors, detail: null }
    for (const windowRadius of [0.01, 0.2, 0.45]) {
      for (const dx of [0, ...deltas]) {
        for (const dy of [0, ...deltas]) {
          if (dx === 0 && dy === 0) continue
          if (dx !== 0 && dy !== 0 && Math.abs(dx) !== Math.abs(dy)) continue
          const candidate = shiftTraceWindow(
            circuit,
            error.pcb_trace_id,
            error.center,
            windowRadius,
            dx,
            dy,
          )
          let candidateErrors
          try {
            candidateErrors = await runAllRoutingChecks(candidate)
          } catch {
            continue
          }
          if (candidateErrors.length < best.count) {
            best = {
              count: candidateErrors.length,
              circuit: candidate,
              errors: candidateErrors,
              detail: [error.pcb_trace_id, error.center.x, error.center.y, windowRadius, dx, dy],
            }
          }
        }
      }
    }
    if (best.count < errors.length) {
      circuit = best.circuit
      errors = best.errors
      improved = true
      console.log(`accept\t${best.count}\t${best.detail.join("\t")}`)
    }
  }
  console.log(`pass\t${pass}\t${errors.length}`)
  if (!improved) break
}

console.log(Object.entries(Object.groupBy(errors, (error) => error.type))
  .map(([kind, group]) => `${kind}\t${group.length}`)
  .join("\n"))
console.log(errors.map((error) => error.message).join("\n"))