diff --git a/roadmap.md b/roadmap.md index 727e87a..2a7acfe 100644 --- a/roadmap.md +++ b/roadmap.md @@ -35,6 +35,7 @@ - Maybe a partial markdown preprocess to support bold and italic? - Look into gr_curve to possibly add beziers to the kicad conversion - Support curves (arcs as well as Béziers) in polygons + - Also, three point arcs, tangents, earier "circle tools" in general - Add snappable line footprint - Figure out a manual, but still reasonably comfortable routing method directly from the config - Eeschema support for pcbs diff --git a/src/assert.js b/src/assert.js index 916fa81..ad55436 100644 --- a/src/assert.js +++ b/src/assert.js @@ -67,3 +67,14 @@ exports.trbl = (raw, name, _default=0) => units => { if (raw.length == 2) raw = [raw[1], raw[0], raw[1], raw[0]] return arr(raw, name, 4, 'number', _default)(units) } + +exports.asym = (raw, name) => { + // allow different aliases + source_aliases = ['source', 'origin', 'base', 'primary', 'left'] + clone_aliases = ['clone', 'image', 'derived', 'secondary', 'right'] + _in(raw, name, ['both'].concat(source_aliases, clone_aliases)) + // return aliases to canonical names + if (source_aliases.includes(raw)) return 'source' + if (clone_aliases.includes(raw)) return 'clone' + return raw +} diff --git a/src/filter.js b/src/filter.js index cbece43..ba7f5e7 100644 --- a/src/filter.js +++ b/src/filter.js @@ -108,7 +108,7 @@ const contains_object = (val) => { return false } -exports.parse = (config, name, points={}, units={}, include_mirrors=false) => { +exports.parse = (config, name, points={}, units={}, asym='source') => { let result = [] @@ -118,18 +118,23 @@ exports.parse = (config, name, points={}, units={}, include_mirrors=false) => { // if a filter decl is an object, or an array that contains an object at any depth, it is an anchor } else if (contains_object(config)) { - result.push(anchor(config, name, points)(units)) - if (include_mirrors) { + if (['source', 'both'].includes(asym)) { + result.push(anchor(config, name, points)(units)) + } + if (['clone', 'both'].includes(asym)) { // this is strict: if the ref of the anchor doesn't have a mirror pair, it will error out result.push(anchor(config, name, points, undefined, true)(units)) } - // otherwise, it is treated as a condition to filter all available points + // otherwise, it is treated as a condition to filter all available points } else { - result = Object.values(points).filter(complex(config, name, units)) - if (include_mirrors) { + source = Object.values(points).filter(complex(config, name, units)) + if (['source', 'both'].includes(asym)) { + result = result.concat(source) + } + if (['source', 'both'].includes(asym)) { // this is permissive: we only include mirrored versions if they exist, and don't fuss if they don't - result = result.concat(result.map(p => points[anchor_lib.mirror(p.meta.name)]).filter(p => !!p)) + result = result.concat(source.map(p => points[anchor_lib.mirror(p.meta.name)]).filter(p => !!p)) } } diff --git a/src/outlines.js b/src/outlines.js index 8afcd9b..fe08c04 100644 --- a/src/outlines.js +++ b/src/outlines.js @@ -191,12 +191,12 @@ exports.parse = (config = {}, points = {}, units = {}) => { const operation = u[a.in(part.operation || 'add', `${name}.operation`, ['add', 'subtract', 'intersect', 'stack'])] const what = a.in(part.what || 'outline', `${name}.what`, ['rectangle', 'circle', 'polygon', 'outline']) const bound = !!part.bound - const mirror = a.sane(part.mirror || false, `${name}.mirror`, 'boolean')() + const asym = a.asym(part.asym || 'source', `${name}.asym`) // `where` is delayed until we have all, potentially what-dependent units // default where is [0, 0], as per filter parsing const original_where = part.where // need to save, so the delete's don't get rid of it below - const where = units => filter(original_where, `${name}.where`, points, units, mirror) + const where = units => filter(original_where, `${name}.where`, points, units, asym) const adjust = anchor(part.adjust || {}, `${name}.adjust`, points)(units) const fillet = a.sane(part.fillet || 0, `${name}.fillet`, 'number')(units) @@ -209,7 +209,7 @@ exports.parse = (config = {}, points = {}, units = {}) => { delete part.operation delete part.what delete part.bound - delete part.mirror + delete part.asym delete part.where delete part.adjust delete part.fillet diff --git a/src/pcbs.js b/src/pcbs.js index bf07401..bb49ce6 100644 --- a/src/pcbs.js +++ b/src/pcbs.js @@ -281,9 +281,9 @@ exports.parse = (config, points, outlines, units) => { for (const [f_name, f] of Object.entries(footprints_config)) { const name = `pcbs.${pcb_name}.footprints.${f_name}` a.sane(f, name, 'object')() - const mirror = a.sane(f.mirror || false, `${name}.mirror`, 'boolean')() - const where = filter(f.where, `${name}.where`, points, units, mirror) - delete f.mirror + const asym = a.asym(f.asym || 'source', `${name}.asym`) + const where = filter(f.where, `${name}.where`, points, units, asym) + delete f.asym delete f.where for (const w of where) { footprints.push(footprint_factory(f, name, w)) diff --git a/src/points.js b/src/points.js index 2fd72f7..10ba6ed 100644 --- a/src/points.js +++ b/src/points.js @@ -128,7 +128,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key, key.height = a.sane(key.height, `${key.name}.height`, 'number')(units) key.padding = a.sane(key.padding, `${key.name}.padding`, 'number')(units) key.skip = a.sane(key.skip, `${key.name}.skip`, 'boolean')() - key.asym = a.in(key.asym, `${key.name}.asym`, ['left', 'right', 'both']) + key.asym = a.asym(key.asym, `${key.name}.asym`) // templating support for (const [k, v] of Object.entries(key)) { @@ -256,14 +256,14 @@ const parse_axis = exports._parse_axis = (config, name, points, units) => { const perform_mirror = exports._perform_mirror = (point, axis) => { if (axis !== undefined) { point.meta.mirrored = false - if (point.meta.asym == 'left') return ['', null] + if (point.meta.asym == 'source') return ['', null] const mp = point.clone().mirror(axis) const mirrored_name = `mirror_${point.meta.name}` mp.meta = prep.extend(mp.meta, mp.meta.mirror || {}) mp.meta.name = mirrored_name mp.meta.colrow = `mirror_${mp.meta.colrow}` mp.meta.mirrored = true - if (point.meta.asym == 'right') { + if (point.meta.asym == 'clone') { point.meta.skip = true } return [mirrored_name, mp] diff --git a/test/outlines/circles.yaml b/test/outlines/circles.yaml index f1aaa51..e83e4e7 100644 --- a/test/outlines/circles.yaml +++ b/test/outlines/circles.yaml @@ -22,4 +22,4 @@ outlines: ref: matrix shift: [-10, 10] radius: 5 - mirror: true \ No newline at end of file + asym: both \ No newline at end of file diff --git a/test/outlines/polygons.yaml b/test/outlines/polygons.yaml index 09bf345..7dfc88e 100644 --- a/test/outlines/polygons.yaml +++ b/test/outlines/polygons.yaml @@ -25,4 +25,4 @@ outlines: - shift: [-10, 15] - shift: [5, -10] - shift: [-10, 0] - mirror: true \ No newline at end of file + asym: both \ No newline at end of file diff --git a/test/outlines/rectangles.yaml b/test/outlines/rectangles.yaml index df2cab0..2982e5e 100644 --- a/test/outlines/rectangles.yaml +++ b/test/outlines/rectangles.yaml @@ -23,4 +23,4 @@ outlines: ref: matrix shift: [-10, 10] size: 10 - mirror: true \ No newline at end of file + asym: both \ No newline at end of file