Generalize part objects/arrays, add combination shorthands, update docs

This commit is contained in:
Bán Dénes 2020-10-17 19:05:38 +02:00
parent 5b1da540ac
commit d60c9dbc94
5 changed files with 104 additions and 134 deletions

View file

@ -162,4 +162,24 @@ const inherit = exports.inherit = (name_prefix, name, set) => {
result = extend.apply(this, list)
}
return result
}
const op_prefix = exports.op_prefix = str => {
const suffix = str.slice(1)
if (str.startsWith('+')) return {name: suffix, operation: 'add'}
if (str.startsWith('-')) return {name: suffix, operation: 'subtract'}
if (str.startsWith('~')) return {name: suffix, operation: 'intersect'}
if (str.startsWith('^')) return {name: suffix, operation: 'stack'}
return {name: str, operation: 'add'}
}
exports.op_str = (str, choices={}, order=Object.keys(choices)) => {
let res = op_prefix(str)
for (const key of order) {
if (choices[key].includes(res.name)) {
res.type = key
break
}
}
return res
}

View file

@ -36,30 +36,40 @@ exports.parse = (config, outlines) => {
return result.join('')
}
for (const [case_name, case_config] of Object.entries(cases_config)) {
for (let [case_name, case_config] of Object.entries(cases_config)) {
// config sanitization
const parts = a.sane(case_config, `cases.${case_name}`, 'array')
case_config = a.inherit('cases', case_name, cases_config)
if (a.type(case_config) == 'array') {
case_config = {...case_config}
}
const parts = a.sane(case_config, `cases.${case_name}`, 'object')
const body = []
const case_dependencies = []
const outline_dependencies = []
let part_index = 0
for (const part of parts) {
const part_name = `cases.${case_name}[${++part_index}]`
const part_var = `${case_name}__part_${part_index}`
a.detect_unexpected(part, part_name, ['type', 'name', 'extrude', 'shift', 'rotate', 'operation'])
const type = a.in(part.type, `${part_name}.type`, ['outline', 'case'])
const name = a.sane(part.name, `${part_name}.name`, 'string')
const shift = a.numarr(part.shift || [0, 0, 0], `${part_name}.shift`, 3)
const rotate = a.numarr(part.rotate || [0, 0, 0], `${part_name}.rotate`, 3)
const operation = a.in(part.operation || 'add', `${part_name}.operation`, ['add', 'subtract', 'intersect'])
let first = true
for (let [part_name, part] of Object.entries(parts)) {
if (a.type(part) == 'string') {
part = a.op_str(part, {
outline: Object.keys(outlines),
case: Object.keys(cases)
}, ['case', 'outline'])
}
const part_qname = `cases.${case_name}.${part_name}`
const part_var = `${case_name}__part_${part_name}`
a.detect_unexpected(part, part_qname, ['type', 'name', 'extrude', 'shift', 'rotate', 'operation'])
const type = a.in(part.type || 'outline', `${part_qname}.type`, ['outline', 'case'])
const name = a.sane(part.name, `${part_qname}.name`, 'string')
const shift = a.numarr(part.shift || [0, 0, 0], `${part_qname}.shift`, 3)
const rotate = a.numarr(part.rotate || [0, 0, 0], `${part_qname}.rotate`, 3)
const operation = a.in(part.operation || 'add', `${part_qname}.operation`, ['add', 'subtract', 'intersect'])
let base
if (type == 'outline') {
const extrude = a.sane(part.extrude || 1, `${part_name}.extrude`, 'number')
const extrude = a.sane(part.extrude || 1, `${part_qname}.extrude`, 'number')
const outline = outlines[name]
a.assert(outline, `Field "${part_name}.name" does not name a valid outline!`)
a.assert(outline, `Field "${part_qname}.name" does not name a valid outline!`)
if (!scripts[name]) {
scripts[name] = m.exporter.toJscadScript(outline, {
functionName: `${name}_outline_fn`,
@ -70,8 +80,8 @@ exports.parse = (config, outlines) => {
outline_dependencies.push(name)
base = `${name}_outline_fn()`
} else {
a.assert(part.extrude === undefined, `Field "${part_name}.extrude" should not be used when type=case!`)
a.in(name, `${part_name}.name`, Object.keys(cases))
a.assert(part.extrude === undefined, `Field "${part_qname}.extrude" should not be used when type=case!`)
a.in(name, `${part_qname}.name`, Object.keys(cases))
case_dependencies.push(name)
base = `${name}_case_fn()`
}
@ -81,13 +91,14 @@ exports.parse = (config, outlines) => {
else if (operation == 'intersect') op = 'intersect'
let op_statement = `let result = ${part_var};`
if (part_index > 1) {
if (!first) {
op_statement = `result = result.${op}(${part_var});`
}
first = false
body.push(`
// creating part ${part_index} of case ${case_name}
// creating part ${part_name} of case ${case_name}
let ${part_var} = ${base};
// make sure that rotations are relative

View file

@ -212,11 +212,18 @@ exports.parse = (config = {}, points = {}) => {
const ex = a.sane(config.exports || {}, 'outlines.exports', 'object')
for (let [key, parts] of Object.entries(ex)) {
parts = a.inherit('outlines.exports', key, ex)
if (a.type(parts) == 'array') {
parts = {...parts}
}
parts = a.sane(parts, `outlines.exports.${key}`, 'object')
let result = {models: {}}
for (const [part_name, part] of Object.entries(parts)) {
for (let [part_name, part] of Object.entries(parts)) {
const name = `outlines.exports.${key}.${part_name}`
if (a.type(part) == 'string') {
part = a.op_str(part, {outline: Object.keys(outlines)})
}
const expected = ['type', 'operation']
part.type = a.in(part.type, `${name}.type`, ['keys', 'rectangle', 'circle', 'polygon', 'outline'])
part.type = a.in(part.type || 'outline', `${name}.type`, ['keys', 'rectangle', 'circle', 'polygon', 'outline'])
part.operation = a.in(part.operation || 'add', `${name}.operation`, ['add', 'subtract', 'intersect', 'stack'])
let op = u.union

View file

@ -215,6 +215,9 @@ exports.parse = (config, points, outlines) => {
a.detect_unexpected(pcb_config, `pcbs.${pcb_name}`, ['outlines', 'footprints'])
// outline conversion
if (a.type(pcb_config.outlines) == 'array') {
pcb_config.outlines = {...pcb_config.outlines}
}
const config_outlines = a.sane(pcb_config.outlines || {}, `pcbs.${pcb_name}.outlines`, 'object')
const kicad_outlines = {}
for (const [outline_name, outline] of Object.entries(config_outlines)) {
@ -250,6 +253,9 @@ exports.parse = (config, points, outlines) => {
}
// global one-off footprints
if (a.type(pcb_config.footprints) == 'array') {
pcb_config.footprints = {...pcb_config.footprints}
}
const global_footprints = a.sane(pcb_config.footprints || {}, `pcbs.${pcb_name}.footprints`, 'object')
for (const [gf_name, gf] of Object.entries(global_footprints)) {
footprints.push(footprint(gf, `pcbs.${pcb_name}.footprints.${gf_name}`, points, undefined, net_indexer, component_indexer))