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 => { 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) } return current } if (check_unexpected) a.unexpected(raw, name, ['ref', 'orient', 'shift', 'rotate', 'affect']) let point = default_point.clone() if (raw.ref !== undefined) { if (a.type(raw.ref)() == 'array') { // averaging multiple anchors 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] 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() } } if (raw.orient !== undefined) { point.r += a.sane(raw.orient, `${name}.orient`, 'number')(units) } if (raw.shift !== undefined) { let xyval = a.wh(raw.shift, `${name}.shift`)(units) if (point.meta.mirrored) { xyval[0] = -xyval[0] } point.shift(xyval, true) } if (raw.rotate !== undefined) { point.r += a.sane(raw.rotate, `${name}.rotate`, 'number')(units) } if (raw.affect !== undefined) { const candidate = point point = default_point.clone() let affect = raw.affect if (a.type(affect)() == 'string') affect = affect.split('') affect = a.strarr(affect, `${name}.affect`) let i = 0 for (const aff of affect) { a.in(aff, `${name}.affect[${++i}]`, ['x', 'y', 'r']) point[aff] = candidate[aff] } } return point }