corney-island/ergogen/footprints/router.js

180 lines
5.2 KiB
JavaScript

// Router
// Version: 0.1
// Snippets of code used here were taken from https://github.com/infused-kim/kb_ergogen_fp (adjust_oint)
// Credits goes to Github infused-kim, Thanks!
module.exports = {
params: {
net: { type: "net", value: "" },
width: { type: "number", value: 0.25 },
route: { type: "string", value: "" },
routes: { type: "array", value: [] },
via_size: { type: "number", value: 0.8 },
via_drill: { type: "number", value: 0.4 },
locked: false,
},
body: (p) => {
const get_at_coordinates = () => {
const pattern = /\(at (-?[\d\.]*) (-?[\d\.]*) (-?[\d\.]*)\)/
const matches = p.at.match(pattern)
if (matches && matches.length == 4) {
return [
parseFloat(matches[1]),
parseFloat(matches[2]),
parseFloat(matches[3]),
]
} else {
return null
}
}
const adjust_point = (x, y) => {
const at_l = get_at_coordinates()
if (at_l == null) {
throw new Error(`Could not get x and y coordinates from p.at: ${p.at}`)
}
const at_x = at_l[0]
const at_y = at_l[1]
const at_angle = at_l[2]
const radians = (Math.PI / 180) * at_angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = cos * x + sin * y + at_x,
ny = cos * y - sin * x + at_y
const point_str = `${nx.toFixed(5)/1} ${ny.toFixed(5)/1}` // the division by 1 is to remove trailing zeros
return point_str
}
// (segment (start 108.8 108) (end 109.7 108) (width 0.2) (layer "F.Cu") (net 0))
const get_segment = (start, end, layer, net) => {
if (!layer) {
throw new Error(
"Can't place segment before layer is set, use 'f' or 'b', to set starting layer"
)
}
return `(segment ${locked}(start ${adjust_point(
start[0],
start[1]
)}) (end ${adjust_point(end[0], end[1])}) (width ${
p.width
}) (layer ${layer}) (net ${net}))`
}
// (via (at 108.8 108) (size 0.8) (drill 0.4) (layers "F.Cu" "B.Cu") (net 0))
const get_via = (pos, net) => {
if (!pos) {
throw new Error(
"Can't place via when position is not set, use (x,y) to set position"
)
}
return `(via ${locked}(at ${adjust_point(pos[0], pos[1])}) (size ${
p.via_size
}) (drill ${p.via_drill}) (layers "F.Cu" "B.Cu") (net ${net}))`
}
const parse_tuple = (t) => {
let str_tuple = JSON.parse(t.replace(/\(/g, "[").replace(/\)/g, "]"))
let num_tuple = str_tuple.map((v) => Number(v))
if (isNaN(num_tuple[0] || isNaN(num_tuple[1]))) {
throw new Error(`Invalid position encountered: ${str_tuple}`)
}
return num_tuple
}
const get_traces = (route, net) => {
let traces = ""
let layer = undefined
let start = undefined // [x, y]
for (let i = 0; i < route.length; i++) {
ch = route[i].toLowerCase()
switch (ch) {
case "f":
layer = "F.Cu"
break
case "b":
layer = "B.Cu"
break
case "v":
traces = traces + get_via(start, net) + "\n"
switch (layer) {
case "F.Cu":
layer = "B.Cu"
break
case "B.Cu":
layer = "F.Cu"
break
}
break
case "(":
let tuple_str = "("
let parenthesis_idx = i
for (i = i + 1; i < route.length; i++) {
let ch = route[i]
tuple_str += ch
if (route[i] == ")") {
break
}
if (i > route.length) {
throw new Error(
`Unclosed position parenthesis in ${route} at character position ${parenthesis_idx}`
)
}
}
let pos = parse_tuple(tuple_str)
if (start) {
traces = traces + get_segment(start, pos, layer, net) + "\n"
}
start = pos
break
case "<":
let net_name = ""
let lt_idx = i
for (i = i + 1; i < route.length; i++) {
let ch = route[i]
if (route[i] == ">") {
break
}
net_name += ch
if (i > route.length) {
throw new Error(
`Unclosed net parenthesis in ${route} at character position ${lt_idx}`
)
}
}
net = p.global_net(net_name)
case "x":
case "|":
start = undefined
break
default:
throw new Error(`Unsupported character '${ch}' at position ${i}.`)
}
}
return traces
}
const get_routes_traces = (routes, net) => {
let routes_traces = routes.reduce((acc_traces, route) => {
return acc_traces + get_traces(route, net)
}, "")
return routes_traces
}
let combined_traces = ""
let locked = p.locked ? 'locked ' : ''
if (p.route) {
combined_traces += get_traces(p.route, p.net.index)
}
if (p.routes) {
combined_traces += get_routes_traces(p.routes, p.net.index)
}
return combined_traces
},
}