1
0

Points practically done

This commit is contained in:
Bán Dénes 2020-05-30 15:17:53 +02:00
parent f9460f6c45
commit cdb081a377
6 changed files with 301 additions and 259 deletions

3
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/ node_modules/
*.dxf *.dxf
*.json

View File

@ -3,6 +3,9 @@ const path = require('path')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const yargs = require('yargs') const yargs = require('yargs')
const points_lib = require('./helpers/points')
const outline_lib = require('./helpers/outline')
const args = yargs const args = yargs
.option('config', { .option('config', {
alias: 'c', alias: 'c',
@ -16,8 +19,13 @@ const args = yargs
describe: 'Output folder', describe: 'Output folder',
type: 'string' type: 'string'
}) })
.option('outline', { .option('debug', {
default: false, default: false,
hidden: true,
type: 'boolean'
})
.option('outline', {
default: true,
describe: 'Generate 2D outlines', describe: 'Generate 2D outlines',
type: 'boolean' type: 'boolean'
}) })
@ -34,12 +42,20 @@ const args = yargs
.argv .argv
if (!args.outline && !args.pcb && !args.case) { if (!args.outline && !args.pcb && !args.case) {
yargs.showHelp("log") yargs.showHelp('log')
console.log('Nothing to do...') console.log('Nothing to do...')
process.exit(0) process.exit(0)
} }
const config = yaml.load(fs.readFileSync(args.c).toString()) const config = yaml.load(fs.readFileSync(args.c).toString())
const points = require('./helpers/points').parse(config) const points = points_lib.parse(config)
console.log(points) if (args.debug) {
points_lib.dump(points)
}
// if (args.outline) {
// outline_lib.draw(points, config)
// }
console.log('Done.')

View File

@ -1,39 +1,56 @@
anchor: zones:
angle: -5 matrix:
columns: anchor:
- name: pinky angle: 5
rotate: 5 columns:
origin: [7, -7] - name: pinky
- name: ring rotate: -5
stagger: 12 origin: [7, -7]
- name: middle - name: ring
stagger: 5 stagger: 12
- name: index - name: middle
stagger: -6 stagger: 5
- name: inner - name: index
stagger: -2 stagger: -6
rows: - name: inner
- name: bottom stagger: -2
- name: home rows:
- name: top - name: bottom
thumbfan: - name: home
- name: palmward - name: top
anchor: thumbfan:
anchor:
ref: inner_bottom ref: inner_bottom
shift: [-7, -19] shift: [-7, -19]
column: ring columns:
padding: 21.25 - name: near
rotate: 28 column_wire: ring
origin: [9.5, -9] padding: 21.25
- name: home rotate: -28
column: middle origin: [9.5, -9]
padding: 21.25 - name: home
rotate: 28 column_wire: middle
origin: [11.75, -9] padding: 21.25
- name: outward rotate: -28
column: index origin: [11.75, -9]
angle: 20 - name: far
column_wire: index
rows:
- name: thumb
angle: -20
mirror: mirror:
column: pinky ref: pinky_bottom
row: bottom # The mk1's origin was the bottom left corner of the bottom pinky key.
distance: 250 # But it later got rotated by the bottom *right* corner as the pinky angle
# and then rotated again for the inter-half angle so [0, 0] was nowhere on
# the actual result.
#
# Since the new origin is the center of the pinky bottom, we have to convert
# the old, round 250 width to this new coordinate system if we want backward
# compatibility. The following snippet was used to arrive at 233.5881016.
#
# old_origin = new Point(7, 7)
# old_origin.rotate(5, [14, 0])
# old_origin.rotate(-20, [0, 0])
# new_width = 250 - (2 * old_origin.x)
distance: 233.5881016

79
config/squished.yaml Normal file
View File

@ -0,0 +1,79 @@
zones:
matrix:
anchor:
angle: 5
columns:
- name: pinky
rotate: -5
origin: [7, -7]
- name: ring
stagger: 12
- name: middle
stagger: 5
- name: index
stagger: -6
padding: 16
- name: inner
stagger: -2
rows:
- name: bottom
padding: 16
- name: home
padding: 16
- name: top
thumbfan:
anchor:
ref: inner_bottom
shift: [-4, -22]
columns:
- name: wrong_near
padding: 21.25
rotate: -28
origin: [9.5, -9]
skip: yes
- name: home
column_wire: middle
rotate: -28
origin: [9.5, -9]
- name: far
column_wire: index
rows:
- name: thumb
thumbfan_reverse_pass:
anchor:
ref: home_thumb
reverse: yes
columns:
- name: home_again
rotate: 28
origin: [-9.5, -9]
skip: yes
- name: near
padding: 16
column_wire: ring
# TODO: this is just a test for Dan
- name: nearer
column_wire: pinky
rows:
- name: thumb
angle: -20
mirror:
ref: pinky_bottom
# The mk1's origin was the bottom left corner of the bottom pinky key.
# But it later got rotated by the bottom *right* corner as the pinky angle
# and then rotated again for the inter-half angle so [0, 0] was nowhere on
# the actual result.
#
# Since the new origin is the center of the pinky bottom, we have to convert
# the old, round 250 width to this new coordinate system if we want backward
# compatibility. The following snippet was used to arrive at 233.5881016.
#
# old_origin = new Point(7, 7)
# old_origin.rotate(5, [14, 0])
# old_origin.rotate(-20, [0, 0])
# new_width = 250 - (2 * old_origin.x)
#
# TODO: Hahaaa, the squishing fails, because the width reference points are
# NOT stationary! gotta move to distances between some other points
# (definitely something from among the HOME positions!!!)
distance: 233.5881016

20
helpers/outline.js Normal file
View File

@ -0,0 +1,20 @@
const m = require('makerjs')
const fs = require('fs-extra')
const outline = (points, radius, expansion=5, patches=[]) => {
}
exports.draw = (points, config) => {
const lefts = {}
const rights = {}
for (const [k, p] of Object.entries(points)) {
if (p.meta.mirrored) {
rights[k] = p
} else {
lefts[k] = p
}
}
}

View File

@ -1,91 +1,61 @@
const m = require('makerjs') const m = require('makerjs')
const fs = require('fs-extra') const fs = require('fs-extra')
const Point = exports.Point = class Point {
constructor(x=0, y=0, r=0, meta={}) {
if (Array.isArray(x)) {
this.x = x[0]
this.y = x[1]
this.r = 0
this.meta = {}
} else {
this.x = x
this.y = y
this.r = r
this.meta = meta
}
}
get p() {
return [this.x, this.y]
}
set p(val) {
[this.x, this.y] = val
}
// TODO: refactor this to use the new config format add(a) {
const res = this.clone()
res.x += a[0]
res.y += a[1]
return res
}
// const column = (func, col) => ({ shift(s) {
// models: { this.x += s[0]
// bottom: up(func(col, 'bottom'), 0 * (side + padding)), this.y += s[1]
// middle: up(func(col, 'middle'), 1 * (side + padding)), return this
// top: up(func(col, 'top'), 2 * (side + padding)) }
// }
// })
// const matrix = (func) => { rotate(angle, origin=[0, 0]) {
// const models = {} this.p = m.point.rotate(this.p, angle, origin)
// let i = 0 this.r += angle
// let sum = 0 return this
// for (const {name, shift} of columns) { }
// let col = column(func, name)
// sum += shift
// if (name == 'pinky') {
// col = rotate(col, pinky_angle, [side, 0])
// }
// col = up(col, sum)
// col = right(col, i * (side + padding))
// models[name] = col
// i++
// }
// return {models}
// }
// const thumbfan = (func) => ({ mirror(x) {
// models: { this.x = 2 * x - this.x
// inner: func('thumb', 'inner'), this.r = 180 - this.r
// home: rotate( return this
// right( }
// func('thumb', 'home'),
// side + padding + kc_diff
// ),
// thumb_angle,
// [side + padding / 2, -overhang]
// ),
// outer: rotate(
// right(
// rotate(
// right(
// func('thumb', 'outer'),
// side + padding + kc_diff
// ),
// thumb_angle,
// [side + padding / 2 + kc_diff, -overhang]
// ),
// side + padding + kc_diff
// ),
// thumb_angle,
// [side + padding / 2, -overhang]
// )
// }
// })
// const half = (func) => { clone() {
// const result = { return new Point(
// models: { this.x,
// matrix: matrix(func), this.y,
// thumbfan: move( this.r,
// thumbfan(func), this.meta
// [ )
// 3 * (side + padding) + thumb_start,
// -(side + padding) + staggers_sum
// ]
// )
// }
// }
// return m.model.rotate(result, half_angle)
// }
// TODO temp
let _debug_key = 0
const _debug = {}
const debug = (xy) => {
_debug[_debug_key++] = {
type: 'circle',
origin: [xy[0], xy[1]],
radius: 1
} }
} }
@ -109,39 +79,15 @@ const dump = exports.dump = (points, opts={}) => {
models[key] = m.model.moveRelative(m.model.rotate({paths}, point.r), point.p) models[key] = m.model.moveRelative(m.model.rotate({paths}, point.r), point.p)
} }
// TODO
models['debug'] = {paths: _debug}
const assembly = m.model.originate({ const assembly = m.model.originate({
models, models,
units: 'mm' units: 'mm'
}) })
fs.writeFileSync(`${opts.file || 'dump'}.json`, JSON.stringify(points, null, ' '))
fs.writeFileSync(`${opts.file || 'dump'}.dxf`, m.exporter.toDXF(assembly)) fs.writeFileSync(`${opts.file || 'dump'}.dxf`, m.exporter.toDXF(assembly))
} }
const Point = exports.Point = class Point {
constructor(x, y, r, col={}, row={}) {
this.x = x
this.y = y
this.r = r
this.col = col
this.row = row
}
get p() {
return [this.x, this.y]
}
set p(val) {
[this.x, this.y] = val
}
}
const push_rotation = (list, angle, origin) => { const push_rotation = (list, angle, origin) => {
let candidate = origin let candidate = origin
for (const r of list) { for (const r of list) {
@ -153,143 +99,106 @@ const push_rotation = (list, angle, origin) => {
}) })
} }
const render_zone = (cols, rows, anchor=new Point(), reverse=false) => {
const matrix = (cols, rows, anchor=new Point(0, 0, 0), reverse=false) => {
console.log('matrix', cols, rows, anchor, reverse)
const sign = reverse ? -1 : 1 const sign = reverse ? -1 : 1
const points = {} const points = {}
let x = anchor.x const rotations = []
let stagger_sum = anchor.y
let rotation_sum = anchor.r // transferring the anchor rotation to "real" rotations
const rotations = [{ rotations.push({
angle: anchor.r, angle: anchor.r,
origin: [0, 0] origin: anchor.p
}] })
for (const col of cols) { for (const col of cols) {
anchor.y += col.stagger || 0
const col_anchor = anchor.clone()
// clear potential rotations, as they will get re-applied anyway
// and we don't want to apply them twice...
col_anchor.r = 0
// TODO rotation origin reversal is not this easy for (const row of col.rows || rows) {
// and probably the whole reversal idea is not even necessary let point = col_anchor.clone()
// sleep on it, and possibly remove to simplify
if (reverse) {
x -= col.padding || 19
if (col.rotate) {
let ox = 0, oy = 0
if (col.origin) {
ox = -col.origin[0]
oy = col.origin[1]
}
push_rotation(
rotations,
col.rotate,
m.point.add([ox, oy], [x, stagger_sum])
)
rotation_sum += col.rotate
}
}
stagger_sum += sign * col.stagger || 0
let y = stagger_sum
for (const row of (col.rows || rows || [{name: 'default'}])) {
let point = [x, y]
debug(point)
for (const r of rotations) { for (const r of rotations) {
point = m.point.rotate(point, r.angle, r.origin) point.rotate(r.angle, r.origin)
debug(point)
} }
points[col.name + '_' + row.name] = new Point( point.r += col.angle || 0
point[0], point.meta = {col, row}
point[1],
rotation_sum + (row.angle || 0), const key = `${col.name}_${row.name}`
col, points[key] = point
row
col_anchor.y += row.padding || 19
}
if (col.rotate) {
push_rotation(
rotations,
col.rotate,
anchor.add(col.origin || [0, 0]).p
) )
console.log('new Point', points[col.name + '_' + row.name])
y += row.padding || 19
} }
anchor.x += sign * (col.padding || 19)
if (!reverse) {
if (col.rotate) {
push_rotation(
rotations,
-col.rotate,
m.point.add(col.origin || [0, 0], [x, stagger_sum])
)
a = rotations.pop()
debug(a.origin)
rotations.push(a)
rotation_sum += -col.rotate
}
x += col.padding || 19
}
} }
return points return points
} }
const anchor = (raw, points={}) => {
let a = new Point()
if (raw) {
if (raw.ref && points[raw.ref]) {
a = points[raw.ref].clone()
}
if (raw.shift) {
a.x += raw.shift[0]
a.y += raw.shift[1]
}
a.r += raw.angle || 0
}
return a
}
exports.parse = (config) => { exports.parse = (config) => {
// basic matrix let points = {}
let matrix_anchor
if (config.anchor) { for (const zone of Object.values(config.zones)) {
let x = 0 points = Object.assign(points, render_zone(
let y = 0 zone.columns || [],
if (config.anchor.shift) { zone.rows || [{name: 'default'}],
x = config.anchor.shift[0] anchor(zone.anchor, points),
y = config.anchor.shift[1] !!zone.reverse
))
}
if (config.angle) {
for (const p of Object.values(points)) {
p.rotate(config.angle)
} }
const r = -config.anchor.angle || 0
matrix_anchor = new Point(x, y, r)
}
let points = matrix(config.columns, config.rows, matrix_anchor)
// thumbfan
let thumb_anchor = new Point(0, 0, 0)
let thumb_anchor_index = -1
for (const key of config.thumbfan) {
thumb_anchor_index++
if (key.anchor) {
const ref = points[key.anchor.ref] || thumb_anchor
thumb_anchor.p = m.point.add(ref.p, key.anchor.shift)
thumb_anchor.r += key.anchor.angle || 0
break
} else continue
} }
const forward = config.thumbfan.slice(thumb_anchor_index) if (config.mirror) {
const rewind = config.thumbfan.slice(0, thumb_anchor_index) let x = anchor(config.mirror, points).x
const thumb_rows = config.thumb_rows || [{name: 'thumb'}] x += (config.mirror.distance || 0) / 2
const mirrored_points = {}
points = Object.assign(points, matrix(forward, thumb_rows, thumb_anchor)) for (const [name, p] of Object.entries(points)) {
points = Object.assign(points, matrix(rewind, thumb_rows, thumb_anchor, true)) const mp = p.clone().mirror(x)
mp.meta.mirrored = true
const mname = `mirror_${name}`
mirrored_points[mname] = mp
}
Object.assign(points, mirrored_points)
}
const filtered = {}
for (const [k, p] of Object.entries(points)) {
if (p.meta.col.skip || p.meta.row.skip) continue
filtered[k] = p
}
dump(points) return filtered
throw 2
return points
} }