1
0

Various progress

This commit is contained in:
Bán Dénes 2020-06-28 22:35:53 +02:00
parent 8d6be0ea00
commit fad615045a
6 changed files with 135 additions and 65 deletions

View File

@ -310,7 +310,9 @@ neighbors: [dir_x, dir_y]
bind: num | [num_x, num_y] | [num_t, num_r, num_b, num_l] # default = 10
```
The former declares the directions we want to bind in, where `dir_x` can be one of `left`, `right`, or `both`; and `dir_y` can be one of `up`, `down`, or `both`.
Again, key-level declaration means that both of these should be specified in the `points` section, benefiting from the same extension process every key-level setting does.
The former declares the directions we want to bind in, where `dir_x` can be one of `left`, `right`, `both` or `neither`; and `dir_y` can be one of `up`, `down`, `both` or `neither`.
(If left empty, `neither` will be assumed.)
The latter declares how much we want to bind, i.e., the amount of overlap we want in that direction to make sure that we can reach the neighbor (`num` applies to all directions, `num_x` horizontally, `num_y` vertically, and the t/r/b/l versions to top/right/bottom/left, respectively).
If it's a one-piece design, we also need to "glue" the halves together (or we might want to leave some extra space for the controller on the inner side for splits).
@ -319,11 +321,11 @@ This is where the following section comes into play:
```yaml
glue:
top:
left: <line def>
right: <line def> | num
left: <anchor>
right: <anchor> | num
bottom:
left: <line def>
right: <line def> | num
left: <anchor>
right: <anchor> | num
waypoints:
- percent: num
width: num | [num_left, num_right]
@ -333,13 +335,12 @@ glue:
- ...
```
...where a `<line def>` looks like:
...where an `<anchor>` is the same as it was for points:
```yaml
ref: <point reference>
shift: [x, y]
rotate: num
origin: [x, y]
shift: [x, y] # default = [0, 0]
rotate: num # default = 0
```
The section's `top` and `bottom` are both formatted the same, and describe the center line's top and bottom intersections, respectively.
@ -359,6 +360,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.
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.
<hr />
@ -376,7 +378,9 @@ Now we can configure what we want to "export" as outlines from this phase, given
- `side: left | right` : the side we want
- `glue` : just the glue, but the "ideal" version of it. This means that instead of the `glue` we defined above, we get `all` - `left` - `right`, so the _exact_ middle piece we would have needed to glue everything together. Parameters:
- everything we could specify for `all` (since those are needed for the calculation)
- `side: left | right | both # default = both)` : optionally, we could choose only one side of the glue as well
- `raw: boolean # default = false)` : optionally, we could choose to get the "raw" (i.e., the non-idealized) glue as well
- `ref` : a previously defined outline, see below.
- `name: outline_name` : the name of the referenced outline
Additionally, we can use primitive shapes:
@ -384,8 +388,7 @@ Additionally, we can use primitive shapes:
- `ref: <point reference>` : what position and rotation to consider as the origin
- `rotate: num` : extra rotation
- `shift: [x, y]` : extra translation
- `width: num` : the width of the rectangle
- `height: num` : the height of the rectangle
- `size: num | [width, height]` : the size of the rectangle
- `circle` : an independent circle primitive. Parameters:
- `ref`, `rotate`, and `shift` are the same as above
- `radius: num` : the radius of the circle
@ -405,7 +408,7 @@ exports:
```
Operations are performed in order, and the resulting shape is exported as an output.
Additionally, it is going to be available to further export declarations under the name specified (`my_name`, in this case).
Additionally, it is going to be available to further export declarations (using the `ref` type) under the name specified (`my_name`, in this case).
If we only want to use it as a building block for further exports, we can start the name with an underscore (e.g., `_my_name`) to prevent it from being actually exported.

View File

@ -24,16 +24,28 @@ const detect_unexpected = exports.detect_unexpected = (obj, name, expected) => {
}
}
const xy = exports.xy = (raw, name) => {
assert(type(raw) == 'array' && raw.length == 2, `Field "${name}" should be an array of length 2!`)
const x = raw[0] || 0
const y = raw[1] || 0
assert(type(x) == 'number' && type(y) == 'number', `Field "${name}" should contain numbers!`)
return {x, y}
const numarr = exports.numarr = (raw, name, length) => {
assert(type(raw) == 'array' && raw.length == length, `Field "${name}" should be an array of length ${length}!`)
raw = raw.map(val => val || 0)
raw.map(val => assert(type(val) == 'number', `Field "${name}" should contain numbers!`))
return raw
}
exports.anchor = (raw, name, points={}) => {
detect_unexpected(raw, name, ['ref', 'shift', 'rotate'])
const xy = exports.xy = (raw, name) => numarr(raw, name, 2)
exports.wh = (raw, name) => {
if (!Array.isArray(raw)) raw = [raw, raw]
return a.xy(raw, name)
}
exports.trbl = (raw, name) => {
if (!Array.isArray(raw)) raw = [raw, raw, raw, raw]
if (raw.length == 2) raw = [raw[1], raw[0], raw[1], raw[0]]
return numarr(raw, name, 4)
}
exports.anchor = (raw, name, points={}, check_unexpected=true) => {
if (check_unexpected) detect_unexpected(raw, name, ['ref', 'shift', 'rotate'])
let a = new Point()
if (raw.ref !== undefined) {
assert(points[raw.ref], `Unknown point reference "${raw.ref}" in anchor "${name}"!`)
@ -41,8 +53,8 @@ exports.anchor = (raw, name, points={}) => {
}
if (raw.shift !== undefined) {
const xyval = xy(raw.shift, name + '.shift')
a.x += xyval.x
a.y += xyval.y
a.x += xyval[0]
a.y += xyval[1]
}
if (raw.rotate !== undefined) {
a.r += sane(raw.rotate || 0, name + '.rotate', 'number')

View File

@ -1,33 +1,26 @@
#!/usr/bin/env node
const m = require('makerjs')
// libs
const fs = require('fs-extra')
const path = require('path')
const yaml = require('js-yaml')
const yargs = require('yargs')
// internals
const u = require('./utils')
const io = require('./io')
const points_lib = require('./points')
// const outline_lib = require('./outline')
const outline_lib = require('./outline')
const dump_model = (model, file='model') => {
const assembly = m.model.originate({
models: u.deepcopy(model),
units: 'mm'
})
fs.mkdirpSync(path.dirname(`${file}.dxf`))
fs.writeFileSync(`${file}.dxf`, m.exporter.toDXF(assembly))
if (args.debug) {
fs.writeJSONSync(`${file}.json`, assembly, {spaces: 4})
}
}
// command line args
const args = yargs
.option('config', {
alias: 'c',
demandOption: true,
describe: 'Config yaml file',
describe: 'Config yaml/json file',
type: 'string'
})
.option('output', {
@ -37,8 +30,9 @@ const args = yargs
type: 'string'
})
.option('debug', {
alias: 'd',
default: false,
hidden: true,
describe: 'Debug mode',
type: 'boolean'
})
.argv
@ -46,15 +40,28 @@ const args = yargs
fs.mkdirpSync(args.o)
const config_parser = args.c.endsWith('.yaml') ? yaml.load : JSON.parse
const config = config_parser(fs.readFileSync(args.c).toString())
let config
try {
config = config_parser(fs.readFileSync(args.c).toString())
} catch (err) {
throw new Error(`Malformed input "${args.c}": ${err}`)
}
// points
console.log('Parsing points...')
const points = points_lib.parse(config.points)
if (args.debug) {
fs.writeJSONSync(path.join(args.o, 'points.json'), points, {spaces: 4})
const size = 14
const rect = u.rect(size, size, [-size/2, -size/2])
const points_demo = outline_lib.layout(points, rect)
dump_model(points_demo, path.join(args.o, 'points_demo'))
const rect = u.rect(18, 18, [-9, -9])
const points_demo = points_lib.position(points, rect)
io.dump_model(points_demo, path.join(args.o, 'points_demo'), args.debug)
}
// outlines
// console.log('Generating outlines...')
// goodbye
console.log('Done.')

18
src/io.js Normal file
View File

@ -0,0 +1,18 @@
const m = require('makerjs')
const fs = require('fs-extra')
const path = require('path')
const u = require('./utils')
exports.dump_model = (model, file='model', debug=false) => {
const assembly = m.model.originate({
models: u.deepcopy(model),
units: 'mm'
})
fs.mkdirpSync(path.dirname(`${file}.dxf`))
fs.writeFileSync(`${file}.dxf`, m.exporter.toDXF(assembly))
if (debug) {
fs.writeJSONSync(`${file}.json`, assembly, {spaces: 4})
}
}

View File

@ -1,20 +1,14 @@
const m = require('makerjs')
const u = require('./utils')
const layout = exports.layout = (points, shape) => {
const shapes = {}
for (const [pname, p] of Object.entries(points)) {
shapes[pname] = p.position(u.deepcopy(shape))
}
return {layout: {models: shapes}}
}
const a = require('./assert')
const outline = exports._outline = (points, config={}) => params => {
let size = params.size || [18, 18]
const size = a.wh(params.size || [18, 18], '')
if (!Array.isArray(size)) size = [size, size]
size = a.xy(size, `outline.exports.${params.name}.size`)
const corner = params.corner || 0
@ -142,3 +136,39 @@ const outline = exports._outline = (points, config={}) => params => {
u.dump_model({a: glue, b: left_keys, c: {models: right_keys}}, `all_after_left`)
glue = m.model.combineUnion(glue, right_keys)
u.dump_model({a: glue, b: {models: keys}}, `fullll`)
}
const parse_glue = exports._parse_glue = (config = {}, points = {}) => {
a.detect_unexpected(config, 'outline.glue', ['top', 'bottom', 'waypoints', 'extra'])
for (const y in ['top', 'bottom']) {
a.detect_unexpected(config[y], `outline.glue.${y}`, ['left', 'right'])
config[y].left = a.anchor(config[y].left, `outline.glue.${y}.left`, points)
if (a.type(config[y].right) != 'number') {
config[y].right = a.anchor(config[y].right, `outline.glue.${y}.right`, points)
}
}
config.bottom = a.sane(config.bottom, 'outline.glue.bottom', 'object')
config.bottom.left = a.anchor(config.bottom.left, 'outline.glue.bottom.left', points)
if (a.type(config.bottom.right) != 'number') {
config.bottom.right = a.anchor(config.bottom.right, 'outline.glue.bottom.right', points)
}
}
exports.parse = (config = {}, points = {}) => {
a.detect_unexpected(config, 'outline', ['glue', 'exports'])
const glue = parse_glue(config.glue, points)
}

View File

@ -8,7 +8,7 @@ const extend_pair = exports._extend_pair = (to, from) => {
if (from === undefined || from === null) return to
if (to_type != from_type) return from
if (from_type == 'object') {
const res = {}
const res = u.deepcopy(to)
for (const key of Object.keys(from)) {
res[key] = extend_pair(to[key], from[key])
}
@ -147,16 +147,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor) => {
col.rows[row] || {}
)
require('fs-extra').writeJSONSync('arst.json', {
default_key,
zone_wide_key,
col_key: col.key,
zone_wide_rows: zone_wide_rows[row] || {},
col_rows: col.rows[row] || {},
result: key
}, {spaces: 4})
throw 28
key.name = key.name || `${col_name}_${row}`
key.shift = a.xy(key.shift, `${key.name}.shift`)
key.rotate = a.sane(key.rotate, `${key.name}.rotate`, 'number')
@ -206,7 +196,9 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor) => {
exports.parse = (config) => {
exports.parse = (config = {}) => {
a.detect_unexpected(config, 'points', ['zones', 'rotate', 'mirror'])
let points = {}
@ -263,4 +255,12 @@ exports.parse = (config) => {
}
return filtered
}
exports.position = (points, shape) => {
const shapes = {}
for (const [pname, p] of Object.entries(points)) {
shapes[pname] = p.position(u.deepcopy(shape))
}
return {layout: {models: shapes}}
}