Mixed progress
- point tagging - extends clauses for drier config - classic/uniform support - mx/choc spacing support - intersect outlines - per-key footprint customization
This commit is contained in:
parent
55d60ba599
commit
c3d7643371
6 changed files with 305 additions and 141 deletions
36
README.md
36
README.md
|
@ -324,19 +324,21 @@ This is where the following section comes into play:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
glue:
|
glue:
|
||||||
top:
|
glue_name:
|
||||||
left: <anchor>
|
top:
|
||||||
right: <anchor> | num
|
left: <anchor>
|
||||||
bottom:
|
right: <anchor> | num
|
||||||
left: <anchor>
|
bottom:
|
||||||
right: <anchor> | num
|
left: <anchor>
|
||||||
waypoints:
|
right: <anchor> | num
|
||||||
- percent: num
|
waypoints:
|
||||||
width: num | [num_left, num_right]
|
- percent: num
|
||||||
- ...
|
width: num | [num_left, num_right]
|
||||||
extra:
|
- ...
|
||||||
- <primitive shape>
|
extra:
|
||||||
- ...
|
- <primitive shape>
|
||||||
|
- ...
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
...where an `<anchor>` is (mostly) the same as it was for points:
|
...where an `<anchor>` is (mostly) the same as it was for points:
|
||||||
|
@ -348,7 +350,7 @@ rotate: num # default = 0
|
||||||
relative: boolean # default = true
|
relative: boolean # default = true
|
||||||
```
|
```
|
||||||
|
|
||||||
The section's `top` and `bottom` are both formatted the same, and describe the center line's top and bottom intersections, respectively.
|
The `top` and `bottom` fields in each glue's section are both formatted the same, and describe the center line's top and bottom intersections, respectively.
|
||||||
In a one-piece case, this means that we project a line from a left-side reference point (optionally rotated and translated), another from the right, and converge them to where they meet.
|
In a one-piece case, this means that we project a line from a left-side reference point (optionally rotated and translated), another from the right, and converge them to where they meet.
|
||||||
Split designs can specify `right` as a single number to mean the x coordinate where the side should be "cut off".
|
Split designs can specify `right` as a single number to mean the x coordinate where the side should be "cut off".
|
||||||
The `relative` flag means that the `shift` is interpreted in layout size units instead of mms (see below).
|
The `relative` flag means that the `shift` is interpreted in layout size units instead of mms (see below).
|
||||||
|
@ -366,7 +368,7 @@ If this is insufficient (maybe because it would leave holes), the `waypoints` ca
|
||||||
Here, `percent` means the y coordinate along the centerline (going from the top intersection to the bottom intersection), and `width` means the offset on the x axis.
|
Here, `percent` means the y coordinate along the centerline (going from the top intersection to the bottom intersection), and `width` means the offset on the x axis.
|
||||||
|
|
||||||
If this is somehow _still_ insufficient (or there were problems with the binding phase), we can specify additional primitive shapes under the `extra` key (similarly to how we would use them in the exports; see below).
|
If this is somehow _still_ insufficient (or there were problems with the binding phase), we can specify additional primitive shapes under the `extra` key (similarly to how we would use them in the exports; see below).
|
||||||
These are then added to what we have so far to finish out the glue.
|
These are then added to what we have so far to finish out the glue. TODO!
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
@ -381,6 +383,8 @@ Now we can configure what we want to "export" as outlines from this phase, given
|
||||||
- `middle` means an "ideal" version of the glue (meaning that instead of the `outline.glue` we defined above, we get `both` - `left` - `right`, so the _exact_ middle piece we would have needed to glue everything together
|
- `middle` means an "ideal" version of the glue (meaning that instead of the `outline.glue` we defined above, we get `both` - `left` - `right`, so the _exact_ middle piece we would have needed to glue everything together
|
||||||
- `both` means both sides, held together by the glue
|
- `both` means both sides, held together by the glue
|
||||||
- `glue` is just the raw glue shape we defined above under `outline.glue`
|
- `glue` is just the raw glue shape we defined above under `outline.glue`
|
||||||
|
- `tag: <array of tags>` : optional tags to filter which points to consider in this step, where tags can be specified as key-level attributes.
|
||||||
|
- `glue: <glue_name>` : the name of the glue to use, if applicable
|
||||||
- `size: num | [num_x, num_y]` : the width/height of the rectangles to lay onto the points. Note that the `relative` flag for the glue declaration above meant this size as the basis of the shift. So during a `keys` layout with a size of 18, for example, a relative shift of `[.5, .5]` actually means `[9, 9]` in mms.
|
- `size: num | [num_x, num_y]` : the width/height of the rectangles to lay onto the points. Note that the `relative` flag for the glue declaration above meant this size as the basis of the shift. So during a `keys` layout with a size of 18, for example, a relative shift of `[.5, .5]` actually means `[9, 9]` in mms.
|
||||||
- `corner: num # default = 0)` : corner radius of the rectangles
|
- `corner: num # default = 0)` : corner radius of the rectangles
|
||||||
- `bevel: num # default = 0)` : corner bevel of the rectangles, can be combined with rounding
|
- `bevel: num # default = 0)` : corner bevel of the rectangles, can be combined with rounding
|
||||||
|
@ -395,7 +399,7 @@ Now we can configure what we want to "export" as outlines from this phase, given
|
||||||
- `radius: num` : the radius of the circle
|
- `radius: num` : the radius of the circle
|
||||||
- `polygon` : an independent polygon primitive. Parameters:
|
- `polygon` : an independent polygon primitive. Parameters:
|
||||||
- `points: [<point_def>, ...]` : the points of the polygon. Each `<point_def>` can have its own `ref` and `shift`, all of which are still the same as above. If `ref` is unspecified, the previous point's will be assumed. For the first, it's `[0, 0]` by default.
|
- `points: [<point_def>, ...]` : the points of the polygon. Each `<point_def>` can have its own `ref` and `shift`, all of which are still the same as above. If `ref` is unspecified, the previous point's will be assumed. For the first, it's `[0, 0]` by default.
|
||||||
- `ref` : a previously defined outline, see below.
|
- `outline` : a previously defined outline, see below.
|
||||||
- `name: outline_name` : the name of the referenced outline
|
- `name: outline_name` : the name of the referenced outline
|
||||||
|
|
||||||
Using these, we define exports as follows:
|
Using these, we define exports as follows:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const m = require('makerjs')
|
const m = require('makerjs')
|
||||||
|
const u = require('./utils')
|
||||||
const Point = require('./point')
|
const Point = require('./point')
|
||||||
|
|
||||||
const assert = exports.assert = (exp, msg) => {
|
const assert = exports.assert = (exp, msg) => {
|
||||||
|
@ -79,11 +80,53 @@ exports.anchor = (raw, name, points={}, check_unexpected=true, default_point=new
|
||||||
point.shift(xyval, true)
|
point.shift(xyval, true)
|
||||||
}
|
}
|
||||||
if (raw.rotate !== undefined) {
|
if (raw.rotate !== undefined) {
|
||||||
let rot = sane(raw.rotate || 0, name + '.rotate', 'number')
|
point.r += sane(raw.rotate || 0, name + '.rotate', 'number')
|
||||||
if (point.meta.mirrored) {
|
|
||||||
rot = -rot
|
|
||||||
}
|
|
||||||
point.r += rot
|
|
||||||
}
|
}
|
||||||
return point
|
return point
|
||||||
|
}
|
||||||
|
|
||||||
|
const extend_pair = exports.extend_pair = (to, from) => {
|
||||||
|
const to_type = type(to)
|
||||||
|
const from_type = type(from)
|
||||||
|
if (from === undefined || from === null) return to
|
||||||
|
if (from === '!!unset') return undefined
|
||||||
|
if (to_type != from_type) return from
|
||||||
|
if (from_type == 'object') {
|
||||||
|
const res = u.deepcopy(to)
|
||||||
|
for (const key of Object.keys(from)) {
|
||||||
|
res[key] = extend_pair(to[key], from[key])
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
} else if (from_type == 'array') {
|
||||||
|
const res = u.deepcopy(to)
|
||||||
|
for (const [i, val] of from.entries()) {
|
||||||
|
res[i] = extend_pair(res[i], val)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
} else return from
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.extend = (...args) => {
|
||||||
|
let res = args[0]
|
||||||
|
for (const arg of args) {
|
||||||
|
if (res == arg) continue
|
||||||
|
res = extend_pair(res, arg)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
const inherit = exports.inherit = (config, name_prefix, name, set) => {
|
||||||
|
let result = u.deepcopy(config)
|
||||||
|
if (config.extends !== undefined) {
|
||||||
|
let list = config.extends
|
||||||
|
if (type(list) !== 'array') list = [list]
|
||||||
|
for (const item of list) {
|
||||||
|
const other = set[item]
|
||||||
|
assert(other, `Field "${name_prefix}.${name}" does not name a valid target!`)
|
||||||
|
result = extend_pair(inherit(other, name_prefix, config.extends, set), result)
|
||||||
|
|
||||||
|
}
|
||||||
|
delete result.extends
|
||||||
|
}
|
||||||
|
return result
|
||||||
}
|
}
|
|
@ -35,27 +35,32 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
|
|
||||||
// Glue config sanitization
|
// Glue config sanitization
|
||||||
|
|
||||||
a.detect_unexpected(config, 'outline.glue', ['top', 'bottom', 'waypoints', 'extra'])
|
const parsed_glue = u.deepcopy(a.sane(config, 'outline.glue', 'object'))
|
||||||
|
for (let [gkey, gval] of Object.entries(parsed_glue)) {
|
||||||
|
gval = a.inherit(gval, 'outline.glue', gkey, config)
|
||||||
|
a.detect_unexpected(gval, `outline.glue.${gkey}`, ['top', 'bottom', 'waypoints', 'extra'])
|
||||||
|
|
||||||
|
for (const y of ['top', 'bottom']) {
|
||||||
for (const y of ['top', 'bottom']) {
|
a.detect_unexpected(gval[y], `outline.glue.${gkey}.${y}`, ['left', 'right'])
|
||||||
a.detect_unexpected(config[y], `outline.glue.${y}`, ['left', 'right'])
|
gval[y].left = relative_anchor(gval[y].left, `outline.glue.${gkey}.${y}.left`, points)
|
||||||
config[y].left = relative_anchor(config[y].left, `outline.glue.${y}.left`, points)
|
if (a.type(gval[y].right) != 'number') {
|
||||||
if (a.type(config[y].right) != 'number') {
|
gval[y].right = relative_anchor(gval[y].right, `outline.glue.${gkey}.${y}.right`, points)
|
||||||
config[y].right = relative_anchor(config[y].right, `outline.glue.${y}.right`, points)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gval.waypoints = a.sane(gval.waypoints || [], `outline.glue.${gkey}.waypoints`, 'array')
|
||||||
|
let wi = 0
|
||||||
|
gval.waypoints = gval.waypoints.map(w => {
|
||||||
|
const name = `outline.glue.${gkey}.waypoints[${++wi}]`
|
||||||
|
a.detect_unexpected(w, name, ['percent', 'width'])
|
||||||
|
w.percent = a.sane(w.percent, name + '.percent', 'number')
|
||||||
|
w.width = a.wh(w.width, name + '.width')
|
||||||
|
return w
|
||||||
|
})
|
||||||
|
|
||||||
|
parsed_glue[gkey] = gval
|
||||||
}
|
}
|
||||||
|
|
||||||
config.waypoints = a.sane(config.waypoints || [], 'outline.glue.waypoints', 'array')
|
|
||||||
let wi = 0
|
|
||||||
config.waypoints = config.waypoints.map(w => {
|
|
||||||
const name = `outline.glue.waypoints[${++wi}]`
|
|
||||||
a.detect_unexpected(w, name, ['percent', 'width'])
|
|
||||||
w.percent = a.sane(w.percent, name + '.percent', 'number')
|
|
||||||
w.width = a.wh(w.width, name + '.width')
|
|
||||||
return w
|
|
||||||
})
|
|
||||||
|
|
||||||
// TODO: handle glue.extra (or revoke it from the docs)
|
// TODO: handle glue.extra (or revoke it from the docs)
|
||||||
|
|
||||||
|
@ -63,8 +68,12 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
|
|
||||||
// Layout params sanitization
|
// Layout params sanitization
|
||||||
|
|
||||||
a.detect_unexpected(params, `${export_name}`, expected.concat(['side', 'size', 'corner', 'bevel', 'bound']))
|
a.detect_unexpected(params, `${export_name}`, expected.concat(['side', 'tags', 'glue', 'size', 'corner', 'bevel', 'bound']))
|
||||||
const side = a.in(params.side, `${export_name}.side`, ['left', 'right', 'middle', 'both', 'glue'])
|
const side = a.in(params.side, `${export_name}.side`, ['left', 'right', 'middle', 'both', 'glue'])
|
||||||
|
const tags = a.sane(params.tags || [], `${export_name}.tags`, 'array')
|
||||||
|
const default_glue_name = Object.keys(parsed_glue)[0]
|
||||||
|
const glue_def = parsed_glue[a.sane(params.glue || default_glue_name, `${export_name}.glue`, 'string')]
|
||||||
|
a.assert(glue_def, `Field "${export_name}.glue" does not name a valid glue!`)
|
||||||
const size = a.wh(params.size, `${export_name}.size`)
|
const size = a.wh(params.size, `${export_name}.size`)
|
||||||
const corner = a.sane(params.corner || 0, `${export_name}.corner`, 'number')
|
const corner = a.sane(params.corner || 0, `${export_name}.corner`, 'number')
|
||||||
const bevel = a.sane(params.bevel || 0, `${export_name}.bevel`, 'number')
|
const bevel = a.sane(params.bevel || 0, `${export_name}.bevel`, 'number')
|
||||||
|
@ -77,6 +86,14 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
if (['left', 'right', 'middle', 'both'].includes(side)) {
|
if (['left', 'right', 'middle', 'both'].includes(side)) {
|
||||||
for (const [pname, p] of Object.entries(points)) {
|
for (const [pname, p] of Object.entries(points)) {
|
||||||
|
|
||||||
|
// filter by tags, if necessary
|
||||||
|
if (tags.length) {
|
||||||
|
const source = p.meta.tags || {}
|
||||||
|
const point_tags = Object.keys(source).filter(t => !!source[t])
|
||||||
|
const relevant = point_tags.some(pt => tags.includes(pt))
|
||||||
|
if (!relevant) continue
|
||||||
|
}
|
||||||
|
|
||||||
let from_x = -size[0] / 2, to_x = size[0] / 2
|
let from_x = -size[0] / 2, to_x = size[0] / 2
|
||||||
let from_y = -size[1] / 2, to_y = size[1] / 2
|
let from_y = -size[1] / 2, to_y = size[1] / 2
|
||||||
|
|
||||||
|
@ -130,15 +147,15 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
|
|
||||||
return u.line(from.p, to.p)
|
return u.line(from.p, to.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tll = get_line(config.top.left)
|
const tll = get_line(glue_def.top.left)
|
||||||
const trl = get_line(config.top.right)
|
const trl = get_line(glue_def.top.right)
|
||||||
const tip = m.path.converge(tll, trl)
|
const tip = m.path.converge(tll, trl)
|
||||||
const tlp = u.eq(tll.origin, tip) ? tll.end : tll.origin
|
const tlp = u.eq(tll.origin, tip) ? tll.end : tll.origin
|
||||||
const trp = u.eq(trl.origin, tip) ? trl.end : trl.origin
|
const trp = u.eq(trl.origin, tip) ? trl.end : trl.origin
|
||||||
|
|
||||||
const bll = get_line(config.bottom.left)
|
const bll = get_line(glue_def.bottom.left)
|
||||||
const brl = get_line(config.bottom.right)
|
const brl = get_line(glue_def.bottom.right)
|
||||||
const bip = m.path.converge(bll, brl)
|
const bip = m.path.converge(bll, brl)
|
||||||
const blp = u.eq(bll.origin, bip) ? bll.end : bll.origin
|
const blp = u.eq(bll.origin, bip) ? bll.end : bll.origin
|
||||||
const brp = u.eq(brl.origin, bip) ? brl.end : brl.origin
|
const brp = u.eq(brl.origin, bip) ? brl.end : brl.origin
|
||||||
|
@ -146,7 +163,7 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
const left_waypoints = []
|
const left_waypoints = []
|
||||||
const right_waypoints = []
|
const right_waypoints = []
|
||||||
|
|
||||||
for (const w of config.waypoints) {
|
for (const w of glue_def.waypoints) {
|
||||||
const percent = w.percent / 100
|
const percent = w.percent / 100
|
||||||
const center_x = tip[0] + percent * (bip[0] - tip[0])
|
const center_x = tip[0] + percent * (bip[0] - tip[0])
|
||||||
const center_y = tip[1] + percent * (bip[1] - tip[1])
|
const center_y = tip[1] + percent * (bip[1] - tip[1])
|
||||||
|
@ -157,7 +174,7 @@ const layout = exports._layout = (config = {}, points = {}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let waypoints
|
let waypoints
|
||||||
const is_split = a.type(config.top.right) == 'number'
|
const is_split = a.type(glue_def.top.right) == 'number'
|
||||||
if (is_split) {
|
if (is_split) {
|
||||||
waypoints = [tip, tlp]
|
waypoints = [tip, tlp]
|
||||||
.concat(left_waypoints)
|
.concat(left_waypoints)
|
||||||
|
@ -198,7 +215,7 @@ exports.parse = (config = {}, points = {}) => {
|
||||||
for (const part of parts) {
|
for (const part of parts) {
|
||||||
const name = `outline.exports.${key}[${++index}]`
|
const name = `outline.exports.${key}[${++index}]`
|
||||||
const expected = ['type', 'operation']
|
const expected = ['type', 'operation']
|
||||||
part.type = a.in(part.type, `${name}.type`, ['keys', 'rectangle', 'circle', 'polygon', 'ref'])
|
part.type = a.in(part.type, `${name}.type`, ['keys', 'rectangle', 'circle', 'polygon', 'outline'])
|
||||||
part.operation = a.in(part.operation || 'add', `${name}.operation`, ['add', 'subtract', 'intersect', 'stack'])
|
part.operation = a.in(part.operation || 'add', `${name}.operation`, ['add', 'subtract', 'intersect', 'stack'])
|
||||||
|
|
||||||
let op = u.union
|
let op = u.union
|
||||||
|
@ -240,10 +257,12 @@ exports.parse = (config = {}, points = {}) => {
|
||||||
}
|
}
|
||||||
arg = u.poly(parsed_points)
|
arg = u.poly(parsed_points)
|
||||||
break
|
break
|
||||||
case 'ref':
|
case 'outline':
|
||||||
a.assert(outlines[part.name], `Field "${name}.name" does not name an existing outline!`)
|
a.assert(outlines[part.name], `Field "${name}.name" does not name an existing outline!`)
|
||||||
arg = u.deepcopy(outlines[part.name])
|
arg = u.deepcopy(outlines[part.name])
|
||||||
break
|
break
|
||||||
|
default:
|
||||||
|
throw new Error(`Field "${name}.type" (${part.type}) does not name a valid outline part type!`)
|
||||||
}
|
}
|
||||||
|
|
||||||
result = op(result, arg)
|
result = op(result, arg)
|
||||||
|
|
|
@ -143,6 +143,8 @@ const makerjs2kicad = exports._makerjs2kicad = (model, layer='Edge.Cuts') => {
|
||||||
|
|
||||||
const footprint_types = require('./footprints')
|
const footprint_types = require('./footprints')
|
||||||
const footprint = exports._footprint = (config, name, points, net_indexer, point) => {
|
const footprint = exports._footprint = (config, name, points, net_indexer, point) => {
|
||||||
|
|
||||||
|
if (config === false) return ''
|
||||||
|
|
||||||
// config sanitization
|
// config sanitization
|
||||||
a.detect_unexpected(config, name, ['type', 'anchor', 'nets', 'params'])
|
a.detect_unexpected(config, name, ['type', 'anchor', 'nets', 'params'])
|
||||||
|
|
|
@ -2,35 +2,6 @@ const m = require('makerjs')
|
||||||
const u = require('./utils')
|
const u = require('./utils')
|
||||||
const a = require('./assert')
|
const a = require('./assert')
|
||||||
|
|
||||||
const extend_pair = exports._extend_pair = (to, from) => {
|
|
||||||
const to_type = a.type(to)
|
|
||||||
const from_type = a.type(from)
|
|
||||||
if (from === undefined || from === null) return to
|
|
||||||
if (to_type != from_type) return from
|
|
||||||
if (from_type == 'object') {
|
|
||||||
const res = u.deepcopy(to)
|
|
||||||
for (const key of Object.keys(from)) {
|
|
||||||
res[key] = extend_pair(to[key], from[key])
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
} else if (from_type == 'array') {
|
|
||||||
const res = u.deepcopy(to)
|
|
||||||
for (const [i, val] of from.entries()) {
|
|
||||||
res[i] = extend_pair(res[i], val)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
} else return from
|
|
||||||
}
|
|
||||||
|
|
||||||
const extend = exports._extend = (...args) => {
|
|
||||||
let res = args[0]
|
|
||||||
for (const arg of args) {
|
|
||||||
if (res == arg) continue
|
|
||||||
res = extend_pair(res, arg)
|
|
||||||
}
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
const push_rotation = exports._push_rotation = (list, angle, origin) => {
|
const push_rotation = exports._push_rotation = (list, angle, origin) => {
|
||||||
let candidate = origin
|
let candidate = origin
|
||||||
for (const r of list) {
|
for (const r of list) {
|
||||||
|
@ -139,7 +110,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key)
|
||||||
asym: 'both'
|
asym: 'both'
|
||||||
}
|
}
|
||||||
for (const row of Object.keys(actual_rows)) {
|
for (const row of Object.keys(actual_rows)) {
|
||||||
const key = extend(
|
const key = a.extend(
|
||||||
default_key,
|
default_key,
|
||||||
global_key,
|
global_key,
|
||||||
zone_wide_key,
|
zone_wide_key,
|
||||||
|
@ -148,7 +119,8 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key)
|
||||||
col.rows[row] || {}
|
col.rows[row] || {}
|
||||||
)
|
)
|
||||||
|
|
||||||
key.name = key.name || `${col_name}_${row}`
|
key.name = key.name || `${zone_name}_${col_name}_${row}`
|
||||||
|
key.colrow = `${col_name}_${row}`
|
||||||
key.shift = a.xy(key.shift, `${key.name}.shift`)
|
key.shift = a.xy(key.shift, `${key.name}.shift`)
|
||||||
key.rotate = a.sane(key.rotate, `${key.name}.rotate`, 'number')
|
key.rotate = a.sane(key.rotate, `${key.name}.rotate`, 'number')
|
||||||
key.padding = a.sane(key.padding, `${key.name}.padding`, 'number')
|
key.padding = a.sane(key.padding, `${key.name}.padding`, 'number')
|
||||||
|
@ -195,8 +167,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key)
|
||||||
return points
|
return points
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.parse = (config = {}) => {
|
exports.parse = (config = {}) => {
|
||||||
|
|
||||||
a.detect_unexpected(config, 'points', ['zones', 'key', 'rotate', 'mirror'])
|
a.detect_unexpected(config, 'points', ['zones', 'key', 'rotate', 'mirror'])
|
||||||
|
@ -207,7 +177,11 @@ exports.parse = (config = {}) => {
|
||||||
|
|
||||||
const zones = a.sane(config.zones || {}, 'points.zones', 'object')
|
const zones = a.sane(config.zones || {}, 'points.zones', 'object')
|
||||||
const global_key = a.sane(config.key || {}, 'points.key', 'object')
|
const global_key = a.sane(config.key || {}, 'points.key', 'object')
|
||||||
for (const [zone_name, zone] of Object.entries(zones)) {
|
for (let [zone_name, zone] of Object.entries(zones)) {
|
||||||
|
|
||||||
|
// handle zone-level `extends` clauses
|
||||||
|
zone = a.inherit(zone, 'points.zones', zone_name, zones)
|
||||||
|
|
||||||
const anchor = a.anchor(zone.anchor || {}, `points.zones.${zone_name}.anchor`, points)
|
const anchor = a.anchor(zone.anchor || {}, `points.zones.${zone_name}.anchor`, points)
|
||||||
points = Object.assign(points, render_zone(zone_name, zone, anchor, global_key))
|
points = Object.assign(points, render_zone(zone_name, zone, anchor, global_key))
|
||||||
}
|
}
|
||||||
|
@ -238,9 +212,11 @@ exports.parse = (config = {}) => {
|
||||||
for (const [name, p] of Object.entries(points)) {
|
for (const [name, p] of Object.entries(points)) {
|
||||||
if (p.meta.asym == 'left') continue
|
if (p.meta.asym == 'left') continue
|
||||||
const mp = p.clone().mirror(axis)
|
const mp = p.clone().mirror(axis)
|
||||||
mp.meta = extend(mp.meta, mp.meta.mirror || {})
|
mp.meta = a.extend(mp.meta, mp.meta.mirror || {})
|
||||||
mp.meta.mirrored = true
|
mp.meta.mirrored = true
|
||||||
mirrored_points[`mirror_${name}`] = mp
|
const new_name = `mirror_${name}`
|
||||||
|
mp.meta.name = new_name
|
||||||
|
mirrored_points[new_name] = mp
|
||||||
if (p.meta.asym == 'right') {
|
if (p.meta.asym == 'right') {
|
||||||
p.meta.skip = true
|
p.meta.skip = true
|
||||||
}
|
}
|
||||||
|
|
234
test/fixtures/absolem.yaml
vendored
234
test/fixtures/absolem.yaml
vendored
|
@ -10,9 +10,9 @@ points:
|
||||||
rows:
|
rows:
|
||||||
bottom:
|
bottom:
|
||||||
home:
|
home:
|
||||||
bind: [,10]
|
bind: [,15]
|
||||||
top:
|
top:
|
||||||
bind: [,10]
|
bind: [,15]
|
||||||
key:
|
key:
|
||||||
column_net: P1
|
column_net: P1
|
||||||
ring:
|
ring:
|
||||||
|
@ -61,21 +61,35 @@ points:
|
||||||
rows:
|
rows:
|
||||||
bottom:
|
bottom:
|
||||||
bind: [10]
|
bind: [10]
|
||||||
row_net: P7
|
row_net: P16
|
||||||
mirror:
|
mirror:
|
||||||
row_net: P16
|
row_net: P7
|
||||||
home:
|
home:
|
||||||
bind: [10]
|
bind: [10]
|
||||||
row_net: P6
|
row_net: P14
|
||||||
mirror:
|
mirror:
|
||||||
row_net: P14
|
row_net: P6
|
||||||
top:
|
top:
|
||||||
row_net: P5
|
row_net: P15
|
||||||
mirror:
|
mirror:
|
||||||
row_net: P15
|
row_net: P5
|
||||||
|
key:
|
||||||
|
tags:
|
||||||
|
s19: true
|
||||||
|
choc:
|
||||||
|
extends: matrix
|
||||||
|
columns:
|
||||||
|
pinky:
|
||||||
|
stagger: 1
|
||||||
|
origin: [7, -8]
|
||||||
|
key:
|
||||||
|
padding: 18
|
||||||
|
tags:
|
||||||
|
s19: false
|
||||||
|
s18: true
|
||||||
thumbfan:
|
thumbfan:
|
||||||
anchor:
|
anchor:
|
||||||
ref: inner_bottom
|
ref: matrix_inner_bottom
|
||||||
shift: [-7, -19]
|
shift: [-7, -19]
|
||||||
columns:
|
columns:
|
||||||
near:
|
near:
|
||||||
|
@ -84,9 +98,11 @@ points:
|
||||||
origin: [9.5, -9]
|
origin: [9.5, -9]
|
||||||
rows:
|
rows:
|
||||||
thumb:
|
thumb:
|
||||||
bind: [10,1,,]
|
bind: [10,5,,]
|
||||||
key:
|
key:
|
||||||
column_net: P2
|
column_net: P2
|
||||||
|
tags:
|
||||||
|
classic: true
|
||||||
home:
|
home:
|
||||||
spread: 21.25
|
spread: 21.25
|
||||||
rotate: -28
|
rotate: -28
|
||||||
|
@ -96,17 +112,71 @@ points:
|
||||||
bind: [,10,,15]
|
bind: [,10,,15]
|
||||||
key:
|
key:
|
||||||
column_net: P3
|
column_net: P3
|
||||||
|
tags:
|
||||||
|
classic: true
|
||||||
|
uniform: true
|
||||||
far:
|
far:
|
||||||
rows:
|
rows:
|
||||||
thumb:
|
thumb:
|
||||||
bind: [-1,,,5]
|
bind: [-1,,,5]
|
||||||
key:
|
key:
|
||||||
column_net: P4
|
column_net: P4
|
||||||
|
tags:
|
||||||
|
classic: true
|
||||||
rows:
|
rows:
|
||||||
thumb:
|
thumb:
|
||||||
row_net: P8
|
row_net: P10
|
||||||
mirror:
|
mirror:
|
||||||
row_net: P10
|
row_net: P8
|
||||||
|
unifar:
|
||||||
|
anchor:
|
||||||
|
ref: thumbfan_home_thumb
|
||||||
|
columns:
|
||||||
|
home_again:
|
||||||
|
rotate: -28
|
||||||
|
origin: [9.5, -9]
|
||||||
|
key:
|
||||||
|
skip: true
|
||||||
|
far1u:
|
||||||
|
rows:
|
||||||
|
thumb:
|
||||||
|
bind: [-1,,,5]
|
||||||
|
key:
|
||||||
|
column_net: P4
|
||||||
|
footprints:
|
||||||
|
diode: false
|
||||||
|
tags:
|
||||||
|
uniform: true
|
||||||
|
rows:
|
||||||
|
thumb:
|
||||||
|
row_net: P10
|
||||||
|
mirror:
|
||||||
|
row_net: P8
|
||||||
|
uninear:
|
||||||
|
anchor:
|
||||||
|
ref: thumbfan_home_thumb
|
||||||
|
columns:
|
||||||
|
home_again:
|
||||||
|
spread: -19
|
||||||
|
rotate: 28
|
||||||
|
origin: [-9.5, -9]
|
||||||
|
key:
|
||||||
|
skip: true
|
||||||
|
near1u:
|
||||||
|
rows:
|
||||||
|
thumb:
|
||||||
|
bind: [10,5,,]
|
||||||
|
key:
|
||||||
|
column_net: P2
|
||||||
|
footprints:
|
||||||
|
diode: false
|
||||||
|
tags:
|
||||||
|
uniform: true
|
||||||
|
rows:
|
||||||
|
thumb:
|
||||||
|
row_net: P10
|
||||||
|
mirror:
|
||||||
|
row_net: P8
|
||||||
key:
|
key:
|
||||||
bind: [0,0,0,0]
|
bind: [0,0,0,0]
|
||||||
footprints:
|
footprints:
|
||||||
|
@ -114,95 +184,145 @@ points:
|
||||||
type: mx
|
type: mx
|
||||||
nets:
|
nets:
|
||||||
from: '!column_net'
|
from: '!column_net'
|
||||||
to: '!name'
|
to: '!colrow'
|
||||||
diode:
|
diode:
|
||||||
type: diode
|
type: diode
|
||||||
anchor:
|
anchor:
|
||||||
rotate: 90
|
rotate: 90
|
||||||
shift: [-8, 0]
|
shift: [8, 0]
|
||||||
nets:
|
nets:
|
||||||
from: '!name'
|
from: '!name'
|
||||||
to: '!row_net'
|
to: '!row_net'
|
||||||
|
mirror:
|
||||||
|
footprints:
|
||||||
|
mx:
|
||||||
|
nets:
|
||||||
|
from: '!colrow'
|
||||||
|
to: '!column_net'
|
||||||
rotate: -20
|
rotate: -20
|
||||||
mirror:
|
mirror:
|
||||||
ref: pinky_home
|
ref: matrix_pinky_home
|
||||||
distance: 223.7529778
|
distance: 223.7529778
|
||||||
outline:
|
outline:
|
||||||
glue:
|
glue:
|
||||||
top:
|
classic:
|
||||||
left:
|
top:
|
||||||
ref: inner_top
|
left:
|
||||||
shift: [, 0.5]
|
ref: matrix_inner_top
|
||||||
right:
|
shift: [, 0.5]
|
||||||
ref: mirror_inner_top
|
right:
|
||||||
shift: [, 0.5]
|
ref: mirror_matrix_inner_top
|
||||||
bottom:
|
shift: [, 0.5]
|
||||||
left:
|
bottom:
|
||||||
ref: far_thumb
|
left:
|
||||||
shift: [0.5, 0]
|
ref: thumbfan_far_thumb
|
||||||
rotate: 90
|
shift: [0.5, 0]
|
||||||
right:
|
rotate: 90
|
||||||
ref: mirror_far_thumb
|
right:
|
||||||
shift: [0.5, 0]
|
ref: mirror_thumbfan_far_thumb
|
||||||
rotate: 90
|
shift: [0.5, 0]
|
||||||
waypoints:
|
rotate: 90
|
||||||
- percent: 50
|
waypoints:
|
||||||
width: 50
|
- percent: 50
|
||||||
- percent: 90
|
width: 50
|
||||||
width: 25
|
- percent: 90
|
||||||
|
width: 25
|
||||||
|
uniform:
|
||||||
|
extends: classic
|
||||||
|
bottom:
|
||||||
|
left:
|
||||||
|
ref: unifar_far1u_thumb
|
||||||
|
right:
|
||||||
|
ref: mirror_unifar_far1u_thumb
|
||||||
|
choc:
|
||||||
|
extends: classic
|
||||||
|
top:
|
||||||
|
left:
|
||||||
|
ref: choc_inner_top
|
||||||
|
right:
|
||||||
|
ref: mirror_choc_inner_top
|
||||||
|
uniform_choc:
|
||||||
|
extends:
|
||||||
|
- uniform
|
||||||
|
- choc
|
||||||
exports:
|
exports:
|
||||||
outline:
|
classic_outline:
|
||||||
- type: keys
|
- type: keys
|
||||||
side: both
|
side: both
|
||||||
size: 18
|
tags:
|
||||||
|
- s19
|
||||||
|
- classic
|
||||||
|
glue: classic
|
||||||
|
size: 13.5
|
||||||
corner: .5
|
corner: .5
|
||||||
holes:
|
uniform_outline:
|
||||||
- type: keys
|
- type: keys
|
||||||
operation: stack
|
|
||||||
side: both
|
side: both
|
||||||
|
tags:
|
||||||
|
- s19
|
||||||
|
- uniform
|
||||||
|
glue: uniform
|
||||||
|
size: 13.5
|
||||||
|
corner: .5
|
||||||
|
intersected_outline:
|
||||||
|
- type: outline
|
||||||
|
name: classic_outline
|
||||||
|
- type: outline
|
||||||
|
name: uniform_outline
|
||||||
|
operation: intersect
|
||||||
|
classic_holes:
|
||||||
|
- type: keys
|
||||||
|
side: both
|
||||||
|
tags:
|
||||||
|
- s19
|
||||||
|
- classic
|
||||||
|
glue: classic
|
||||||
size: 14
|
size: 14
|
||||||
bound: false
|
bound: false
|
||||||
middle:
|
classic_middle:
|
||||||
- type: keys
|
- type: keys
|
||||||
operation: stack
|
|
||||||
side: middle
|
side: middle
|
||||||
|
tags:
|
||||||
|
- s19
|
||||||
|
- classic
|
||||||
|
glue: classic
|
||||||
size: 24
|
size: 24
|
||||||
- type: rectangle
|
- type: rectangle
|
||||||
size: [25, 5]
|
size: [25, 5]
|
||||||
ref: home_thumb
|
ref: thumbfan_home_thumb
|
||||||
shift: [0, 12]
|
shift: [0, 12]
|
||||||
- type: rectangle
|
- type: rectangle
|
||||||
size: [25, 5]
|
size: [25, 5]
|
||||||
ref: far_thumb
|
ref: thumbfan_far_thumb
|
||||||
shift: [25, 12]
|
shift: [25, 12]
|
||||||
- type: rectangle
|
- type: rectangle
|
||||||
size: [25, 5]
|
size: [25, 5]
|
||||||
ref: mirror_home_thumb
|
ref: mirror_thumbfan_home_thumb
|
||||||
shift: [25, 12]
|
shift: [25, 12]
|
||||||
- type: rectangle
|
- type: rectangle
|
||||||
size: [25, 5]
|
size: [25, 5]
|
||||||
ref: mirror_far_thumb
|
ref: mirror_thumbfan_far_thumb
|
||||||
shift: [0, 12]
|
shift: [0, 12]
|
||||||
- type: ref
|
- type: outline
|
||||||
name: outline
|
name: classic_outline
|
||||||
operation: intersect
|
operation: intersect
|
||||||
complex:
|
complex:
|
||||||
- type: ref
|
- type: outline
|
||||||
name: outline
|
name: classic_outline
|
||||||
- type: ref
|
- type: outline
|
||||||
name: holes
|
name: classic_holes
|
||||||
operation: stack
|
operation: stack
|
||||||
- type: ref
|
- type: outline
|
||||||
name: middle
|
name: classic_middle
|
||||||
operation: stack
|
operation: stack
|
||||||
pcb:
|
pcb:
|
||||||
edge: outline
|
edge: intersected_outline
|
||||||
footprints:
|
footprints:
|
||||||
mcu:
|
mcu:
|
||||||
type: promicro
|
type: promicro
|
||||||
anchor:
|
anchor:
|
||||||
ref:
|
ref:
|
||||||
- inner_top
|
- choc_inner_top
|
||||||
- mirror_inner_top
|
- mirror_choc_inner_top
|
||||||
shift: [0, -20]
|
shift: [0, -20]
|
||||||
rotate: 270
|
rotate: 270
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue