From d23bd71b7ad53ef8c19947986a63b77993ff99d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1n=20D=C3=A9nes?= Date: Sun, 27 Feb 2022 13:44:24 +0100 Subject: [PATCH] Support orient/rotate towards other points --- roadmap.md | 11 ++++++----- src/anchor.js | 27 +++++++++++++++++---------- src/point.js | 6 ++++++ test/unit/anchor.js | 10 ++++++++++ 4 files changed, 39 insertions(+), 15 deletions(-) diff --git a/roadmap.md b/roadmap.md index e2fa5a9..547f0ad 100644 --- a/roadmap.md +++ b/roadmap.md @@ -6,20 +6,20 @@ ### Major -- Anchor overhaul - - Recursive-ize anchors - - This will potentially cause `ref` to be ambiguous, so maybe introduce a separate `refs` plural? - - Add `orient`/`rotate` **towards** other anchors (again, recursively) - Restructure pcb point/footprint filtering - Use the same `what`/`where` infrastructure as outlines - Collapse params/nets/anchors into a single hierarchy from the user's POV - Add per-footprint mirror support - Add some way for footprints to be able to "resist" the mirroring-related special treatment of negative X shift, rotation, etc. - Add auto-bind -- Merge, generalize, and uniform-ize footprints +- Merge, generalize, uniform-ize and externalize footprints! + - Separate npm package for dependency, onnx-like incremental opset versioning - Template for creating them, built-in variables they can use, documentation, external links, etc. - Also considering how (or, on which layer) they define their silks, universal mirroring behaviour, etc. - Rename class to designator in this context (https://en.wikipedia.org/wiki/Reference_designator#Designators) + - Include raw kicad footprint integrations + - pull torik's script to be able to convert raw kicad footprints into positionable ergogen ones + - have a `dummy` footprint which can just be updated from schematic ### Minor @@ -49,6 +49,7 @@ ### Patch +- Prevent double mirroring (see discord "mirror_mirror_") - Check unexpected keys at top level, too - Better error handling for the fillet option? - Integration and end2end tests to get coverage to 100% diff --git a/src/anchor.js b/src/anchor.js index 031b50b..0d5ae4d 100644 --- a/src/anchor.js +++ b/src/anchor.js @@ -91,12 +91,23 @@ const anchor = exports.parse = (raw, name, points={}, default_point=new Point(), // Actual orient/shift/rotate/affect handling // + const rotator = (config, name, point) => { + // simple case: number gets added to point rotation + if (a.type(config)(units) == 'number') { + let angle = a.sane(config, name, 'number')(units) + if (point.meta.mirrored) { + angle = -angle + } + point.r += angle + // recursive case: points turns "towards" target anchor + } else { + const target = anchor(config, name, points, default_point, mirror)(units) + point.r = point.angle(target) + } + } + if (raw.orient !== undefined) { - let angle = a.sane(raw.orient, `${name}.orient`, 'number')(units) - if (point.meta.mirrored) { - angle = -angle - } - point.r += angle + rotator(raw.orient, `${name}.orient`, point) } if (raw.shift !== undefined) { let xyval = a.wh(raw.shift, `${name}.shift`)(units) @@ -106,11 +117,7 @@ const anchor = exports.parse = (raw, name, points={}, default_point=new Point(), point.shift(xyval, true) } if (raw.rotate !== undefined) { - let angle = a.sane(raw.rotate, `${name}.rotate`, 'number')(units) - if (point.meta.mirrored) { - angle = -angle - } - point.r += angle + rotator(raw.rotate, `${name}.rotate`, point) } if (raw.affect !== undefined) { const candidate = point.clone() diff --git a/src/point.js b/src/point.js index b86d48d..9e32b7c 100644 --- a/src/point.js +++ b/src/point.js @@ -66,4 +66,10 @@ module.exports = class Point { let rect = u.rect(size, size, [-size/2, -size/2]) return this.position(rect) } + + angle(other) { + const dx = other.x - this.x + const dy = other.y - this.y + return -Math.atan2(dx, dy) * (180 / Math.PI) + } } diff --git a/test/unit/anchor.js b/test/unit/anchor.js index 0cde3ee..135ad2a 100644 --- a/test/unit/anchor.js +++ b/test/unit/anchor.js @@ -83,6 +83,11 @@ describe('Anchor', function() { parse({orient: -90, shift: [0, 1]}, 'name')(), [1, 0, -90, {}] ) + // orient towards another point (and then move a diagonal to get to [1, 1]) + check( + parse({orient: 'ten', shift: [0, Math.SQRT2]}, 'name', points)(), + [1, 1, -45, {}] + ) }) it('rotate', function() { @@ -97,6 +102,11 @@ describe('Anchor', function() { parse({shift: [0, 1], rotate: -90}, 'name')(), [0, 1, -90, {}] ) + // rotate towards another point + check( + parse({rotate: {shift: [-1, -1]}}, 'name')(), + [0, 0, 135, {}] + ) }) it('affect', function() {