Support full anchors in outline shapes
This commit is contained in:
parent
677fae0072
commit
26128f8db7
5 changed files with 68 additions and 50 deletions
|
@ -2,12 +2,23 @@ const u = require('./utils')
|
|||
const a = require('./assert')
|
||||
const Point = require('./point')
|
||||
|
||||
const anchor = module.exports = (raw, name, points={}, check_unexpected=true, default_point=new Point()) => units => {
|
||||
const mirror_ref = exports.mirror = (ref, mirror) => {
|
||||
if (mirror) {
|
||||
if (ref.startsWith('mirror_')) {
|
||||
return ref.substring(7)
|
||||
} else {
|
||||
return 'mirror_' + ref
|
||||
}
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
const anchor = exports.parse = (raw, name, points={}, check_unexpected=true, default_point=new Point(), mirror=false) => units => {
|
||||
if (a.type(raw)() == 'array') {
|
||||
// recursive call with incremental default_point mods, according to `affect`s
|
||||
let current = default_point.clone()
|
||||
for (const step of raw) {
|
||||
current = anchor(step, name, points, check_unexpected, current)(units)
|
||||
current = anchor(step, name, points, check_unexpected, current, mirror)(units)
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
@ -19,16 +30,18 @@ const anchor = module.exports = (raw, name, points={}, check_unexpected=true, de
|
|||
let x = 0, y = 0, r = 0
|
||||
const len = raw.ref.length
|
||||
for (const ref of raw.ref) {
|
||||
a.assert(points[ref], `Unknown point reference "${ref}" in anchor "${name}"!`)
|
||||
const resolved = points[ref]
|
||||
const parsed_ref = mirror_ref(ref, mirror)
|
||||
a.assert(points[parsed_ref], `Unknown point reference "${parsed_ref}" in anchor "${name}"!`)
|
||||
const resolved = points[parsed_ref]
|
||||
x += resolved.x
|
||||
y += resolved.y
|
||||
r += resolved.r
|
||||
}
|
||||
point = new Point(x / len, y / len, r / len)
|
||||
} else {
|
||||
a.assert(points[raw.ref], `Unknown point reference "${raw.ref}" in anchor "${name}"!`)
|
||||
point = points[raw.ref].clone()
|
||||
const parsed_ref = mirror_ref(raw.ref, mirror)
|
||||
a.assert(points[parsed_ref], `Unknown point reference "${parsed_ref}" in anchor "${name}"!`)
|
||||
point = points[parsed_ref].clone()
|
||||
}
|
||||
}
|
||||
if (raw.orient !== undefined) {
|
||||
|
|
|
@ -4,7 +4,7 @@ const a = require('./assert')
|
|||
const o = require('./operation')
|
||||
const Point = require('./point')
|
||||
const prep = require('./prepare')
|
||||
const make_anchor = require('./anchor')
|
||||
const anchor_lib = require('./anchor')
|
||||
|
||||
const rectangle = (w, h, corner, bevel, name='') => {
|
||||
const error = (dim, val) => `Rectangle for "${name}" isn't ${dim} enough for its corner and bevel (${val} - 2 * ${corner} - 2 * ${bevel} <= 0)!`
|
||||
|
@ -41,9 +41,9 @@ const layout = exports._layout = (config = {}, points = {}, units = {}) => {
|
|||
|
||||
for (const y of ['top', 'bottom']) {
|
||||
a.unexpected(gval[y], `outlines.glue.${gkey}.${y}`, ['left', 'right'])
|
||||
gval[y].left = make_anchor(gval[y].left, `outlines.glue.${gkey}.${y}.left`, points)
|
||||
gval[y].left = anchor_lib.parse(gval[y].left, `outlines.glue.${gkey}.${y}.left`, points)
|
||||
if (a.type(gval[y].right)(units) != 'number') {
|
||||
gval[y].right = make_anchor(gval[y].right, `outlines.glue.${gkey}.${y}.right`, points)
|
||||
gval[y].right = anchor_lib.parse(gval[y].right, `outlines.glue.${gkey}.${y}.right`, points)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ const layout = exports._layout = (config = {}, points = {}, units = {}) => {
|
|||
return u.line([anchor, -1000], [anchor, 1000])
|
||||
}
|
||||
|
||||
// if it wasn't a number, then it's a (possibly relative) achor
|
||||
// if it wasn't a number, then it's a (possibly relative) anchor
|
||||
const from = anchor(relative_units).clone()
|
||||
const to = from.clone().shift([from.meta.mirrored ? -1 : 1, 0])
|
||||
|
||||
|
@ -244,43 +244,45 @@ exports.parse = (config = {}, points = {}, units = {}) => {
|
|||
|
||||
let arg
|
||||
let anchor
|
||||
const anchor_def = part.anchor || {}
|
||||
switch (part.type) {
|
||||
case 'keys':
|
||||
arg = layout_fn(part, name, expected)
|
||||
break
|
||||
case 'rectangle':
|
||||
a.unexpected(part, name, expected.concat(['ref', 'shift', 'rotate', 'size', 'corner', 'bevel', 'mirror']))
|
||||
a.unexpected(part, name, expected.concat(['anchor', 'size', 'corner', 'bevel', 'mirror']))
|
||||
const size = a.wh(part.size, `${name}.size`)(units)
|
||||
const rec_units = prep.extend({
|
||||
sx: size[0],
|
||||
sy: size[1]
|
||||
}, units)
|
||||
anchor = make_anchor(part, name, points, false)(rec_units)
|
||||
anchor = anchor_lib.parse(anchor_def, `${name}.anchor`, points)(rec_units)
|
||||
const corner = a.sane(part.corner || 0, `${name}.corner`, 'number')(rec_units)
|
||||
const bevel = a.sane(part.bevel || 0, `${name}.bevel`, 'number')(rec_units)
|
||||
const rect_mirror = a.sane(part.mirror || false, `${name}.mirror`, 'boolean')()
|
||||
const rect = rectangle(size[0], size[1], corner, bevel, name)
|
||||
arg = anchor.position(u.deepcopy(rect))
|
||||
if (rect_mirror) {
|
||||
const mirror_part = u.deepcopy(part)
|
||||
a.assert(mirror_part.ref, `Field "${name}.ref" must be speficied if mirroring is required!`)
|
||||
mirror_part.ref = `mirror_${mirror_part.ref}`
|
||||
anchor = make_anchor(mirror_part, name, points, false)(rec_units)
|
||||
const mirror_anchor = u.deepcopy(anchor_def)
|
||||
a.assert(mirror_anchor.ref, `Field "${name}.anchor.ref" must be speficied if mirroring is required!`)
|
||||
anchor = anchor_lib.parse(mirror_anchor, `${name}.anchor --> mirror`, points, undefined, undefined, true)(rec_units)
|
||||
const mirror_rect = m.model.moveRelative(u.deepcopy(rect), [-size[0], 0])
|
||||
arg = u.union(arg, anchor.position(mirror_rect))
|
||||
}
|
||||
break
|
||||
case 'circle':
|
||||
a.unexpected(part, name, expected.concat(['ref', 'shift', 'rotate', 'radius', 'mirror']))
|
||||
anchor = make_anchor(part, name, points, false)(units)
|
||||
a.unexpected(part, name, expected.concat(['anchor', 'radius', 'mirror']))
|
||||
const radius = a.sane(part.radius, `${name}.radius`, 'number')(units)
|
||||
const circle_units = prep.extend({
|
||||
r: radius
|
||||
}, units)
|
||||
anchor = anchor_lib.parse(anchor_def, `${name}.anchor`, points)(circle_units)
|
||||
const circle_mirror = a.sane(part.mirror || false, `${name}.mirror`, 'boolean')()
|
||||
arg = u.circle(anchor.p, radius)
|
||||
if (circle_mirror) {
|
||||
const mirror_part = u.deepcopy(part)
|
||||
a.assert(mirror_part.ref, `Field "${name}.ref" must be speficied if mirroring is required!`)
|
||||
mirror_part.ref = `mirror_${mirror_part.ref}`
|
||||
anchor = make_anchor(mirror_part, name, points, false)(units)
|
||||
const mirror_anchor = u.deepcopy(anchor_def)
|
||||
a.assert(mirror_anchor.ref, `Field "${name}.anchor.ref" must be speficied if mirroring is required!`)
|
||||
anchor = anchor_lib.parse(mirror_anchor, `${name}.anchor --> mirror`, points, undefined, undefined, true)(circle_units)
|
||||
arg = u.union(arg, u.circle(anchor.p, radius))
|
||||
}
|
||||
break
|
||||
|
@ -294,12 +296,15 @@ exports.parse = (config = {}, points = {}, units = {}) => {
|
|||
let last_anchor = new Point()
|
||||
let poly_index = 0
|
||||
for (const poly_point of poly_points) {
|
||||
if (poly_index == 0 && poly_mirror) {
|
||||
a.assert(poly_point.ref, `Field "${name}.ref" must be speficied if mirroring is required!`)
|
||||
poly_mirror_x = (points[poly_point.ref].x + points[`mirror_${poly_point.ref}`].x) / 2
|
||||
}
|
||||
const poly_name = `${name}.points[${++poly_index}]`
|
||||
last_anchor = make_anchor(poly_point, poly_name, points, true, last_anchor)(units)
|
||||
if (poly_index == 1 && poly_mirror) {
|
||||
a.assert(poly_point.ref, `Field "${poly_name}.ref" must be speficied if mirroring is required!`)
|
||||
const mirrored_ref = anchor_lib.mirror(poly_point.ref, poly_mirror)
|
||||
a.assert(points[poly_point.ref], `Field "${poly_name}.ref" does not name an existing point!`)
|
||||
a.assert(points[mirrored_ref], `The mirror of field "${poly_name}.ref" ("${mirrored_ref}") does not name an existing point!`)
|
||||
poly_mirror_x = (points[poly_point.ref].x + points[mirrored_ref].x) / 2
|
||||
}
|
||||
last_anchor = anchor_lib.parse(poly_point, poly_name, points, true, last_anchor)(units)
|
||||
parsed_points.push(last_anchor.p)
|
||||
mirror_points.push(last_anchor.clone().mirror(poly_mirror_x).p)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const m = require('makerjs')
|
||||
const a = require('./assert')
|
||||
const prep = require('./prepare')
|
||||
const make_anchor = require('./anchor')
|
||||
const anchor_lib = require('./anchor')
|
||||
|
||||
const kicad_prefix = `
|
||||
(kicad_pcb (version 20171130) (host pcbnew 5.1.6)
|
||||
|
@ -156,7 +156,7 @@ const footprint = exports._footprint = (config, name, points, point, net_indexer
|
|||
// config sanitization
|
||||
a.unexpected(config, name, ['type', 'anchor', 'nets', 'anchors', 'params'])
|
||||
const type = a.in(config.type, `${name}.type`, Object.keys(footprint_types))
|
||||
let anchor = make_anchor(config.anchor || {}, `${name}.anchor`, points, true, point)(units)
|
||||
let anchor = anchor_lib.parse(config.anchor || {}, `${name}.anchor`, points, true, point)(units)
|
||||
const nets = a.sane(config.nets || {}, `${name}.nets`, 'object')()
|
||||
const anchors = a.sane(config.anchors || {}, `${name}.anchors`, 'object')()
|
||||
const params = a.sane(config.params || {}, `${name}.params`, 'object')()
|
||||
|
@ -187,7 +187,7 @@ const footprint = exports._footprint = (config, name, points, point, net_indexer
|
|||
parsed_params.at = `(at ${anchor.x} ${-anchor.y} ${anchor.r})`
|
||||
parsed_params.rot = anchor.r
|
||||
parsed_params.xy = (x, y) => {
|
||||
const new_anchor = make_anchor({
|
||||
const new_anchor = anchor_lib.parse({
|
||||
shift: [x, -y]
|
||||
}, '_internal_footprint_xy', points, true, anchor)(units)
|
||||
return `${new_anchor.x} ${-new_anchor.y}`
|
||||
|
@ -224,7 +224,7 @@ const footprint = exports._footprint = (config, name, points, point, net_indexer
|
|||
// parsing anchor-type parameters
|
||||
parsed_params.anchors = {}
|
||||
for (const [anchor_name, anchor_config] of Object.entries(prep.extend(fp.anchors || {}, anchors))) {
|
||||
let parsed_anchor = make_anchor(anchor_config || {}, `${name}.anchors.${anchor_name}`, points, true, anchor)(units)
|
||||
let parsed_anchor = anchor_lib.parse(anchor_config || {}, `${name}.anchors.${anchor_name}`, points, true, anchor)(units)
|
||||
parsed_anchor.y = -parsed_anchor.y
|
||||
parsed_params.anchors[anchor_name] = parsed_anchor
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ const m = require('makerjs')
|
|||
const u = require('./utils')
|
||||
const a = require('./assert')
|
||||
const prep = require('./prepare')
|
||||
const make_anchor = require('./anchor')
|
||||
const anchor_lib = require('./anchor')
|
||||
|
||||
const push_rotation = exports._push_rotation = (list, angle, origin) => {
|
||||
let candidate = origin
|
||||
|
@ -194,7 +194,7 @@ const parse_axis = exports._parse_axis = (config, name, points, units) => {
|
|||
const mirror_obj = a.sane(config || {}, name, 'object')()
|
||||
const distance = a.sane(mirror_obj.distance || 0, `${name}.distance`, 'number')(units)
|
||||
delete mirror_obj.distance
|
||||
let axis = make_anchor(mirror_obj, name, points)(units).x
|
||||
let axis = anchor_lib.parse(mirror_obj, name, points)(units).x
|
||||
axis += distance / 2
|
||||
return axis
|
||||
} else return config
|
||||
|
@ -235,7 +235,7 @@ exports.parse = (config, units) => {
|
|||
for (let [zone_name, zone] of Object.entries(zones)) {
|
||||
|
||||
// extracting keys that are handled here, not at the zone render level
|
||||
const anchor = make_anchor(zone.anchor || {}, `points.zones.${zone_name}.anchor`, all_points)(units)
|
||||
const anchor = anchor_lib.parse(zone.anchor || {}, `points.zones.${zone_name}.anchor`, all_points)(units)
|
||||
const rotate = a.sane(zone.rotate || 0, `points.zones.${zone_name}.rotate`, 'number')(units)
|
||||
const mirror = zone.mirror
|
||||
delete zone.anchor
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue