Outlines progress
This commit is contained in:
parent
fad615045a
commit
8da97611e4
3 changed files with 106 additions and 19 deletions
26
README.md
26
README.md
|
@ -369,21 +369,15 @@ Note that this outline is still parametric, so that we can specify different wid
|
|||
|
||||
Now we can configure what we want to "export" as outlines from this phase, given by the combination/subtraction of the following primitives:
|
||||
|
||||
- `all` : the combined outline that we've just created. Its parameters include:
|
||||
- `keys` : the combined outline that we've just created. Its parameters include:
|
||||
- `side: left | right | both | glue | raw` : the part we want to use
|
||||
- `left` and `right` are just the appropriate side of the laid out keys, without the glue.
|
||||
- `both` means both sides, held together by the glue
|
||||
- `glue` means an "ideal" version of the glue (meaning that instead of the `outline.glue` we defined above, we get `both` - `left` - `right`, so the _exact_ middle piece we would have needed to glue everything together
|
||||
- `raw` is the raw glue shape we defined above under `outline.glue`
|
||||
- `size: num | [num_x, num_y]` : the width/height of the rectangles to lay onto the points
|
||||
- `corner: num # default = 0)` : corner radius of the rectangle
|
||||
- `bevel: num # default = 0)` : corner bevel of the rectangle, can be combined with rounding
|
||||
- `keys` : only one side of the laid out keys, without the glue. Parameters:
|
||||
- everything we could specify for `all`
|
||||
- `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)
|
||||
- `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:
|
||||
|
||||
- `corner: num # default = 0)` : corner radius of the rectangles
|
||||
- `bevel: num # default = 0)` : corner bevel of the rectangles, can be combined with rounding
|
||||
- `rectangle` : an independent rectangle primitive. Parameters:
|
||||
- `ref: <point reference>` : what position and rotation to consider as the origin
|
||||
- `rotate: num` : extra rotation
|
||||
|
@ -395,6 +389,8 @@ Additionally, we can use primitive shapes:
|
|||
- `polygon` : an independent polygon primitive. Parameters:
|
||||
- `ref`, `rotate`, and `shift` are the same as above
|
||||
- `points: [[x, y], ...]` : the points of the polygon
|
||||
- `ref` : a previously defined outline, see below.
|
||||
- `name: outline_name` : the name of the referenced outline
|
||||
|
||||
Using these, we define exports as follows:
|
||||
|
||||
|
@ -408,7 +404,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 (using the `ref` type) under the name specified (`my_name`, in this case).
|
||||
Additionally, it is going to be available for further export declarations to use (through 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.
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,11 @@ const detect_unexpected = exports.detect_unexpected = (obj, name, expected) => {
|
|||
}
|
||||
}
|
||||
|
||||
exports.in = (raw, name, arr) => {
|
||||
assert(arr.includes(raw), `Field "${name}" should be one of [${arr.join(', ')}]!`)
|
||||
return raw
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -158,17 +158,103 @@ const parse_glue = exports._parse_glue = (config = {}, points = {}) => {
|
|||
}
|
||||
}
|
||||
|
||||
config.waypoints = a.sane(config.waypoints || [], 'outline.glue.waypoints', 'array')
|
||||
let wi = 0
|
||||
config.waypoints = config.waypoints.map(w => {
|
||||
const name = `outline.glue.waypoints[${++wi}]`
|
||||
a.detect_unexpected(w, name, ['percent', 'width'])
|
||||
w.percent = a.sane(w.percent, name + '.percent', 'number')
|
||||
w.width = a.wh(w.width, name + '.width')
|
||||
return w
|
||||
})
|
||||
|
||||
// TODO: handle glue.extra (or revoke it from the docs)
|
||||
|
||||
return (export_name, params) => {
|
||||
|
||||
a.detect_unexpected(params, `outline.exports.${export_name}`, ['side', 'size', 'corner', 'bevel'])
|
||||
params.side = a.in(params.side, `outline.exports.${export_name}.side`, ['left', 'right', 'both', 'glue', 'raw'])
|
||||
params.size = a.wh(params.size, `outline.exports.${export_name}.size`)
|
||||
params.corner = a.sane(params.corner || 0, `outline.exports.${export_name}.corner`, 'number')
|
||||
params.bevel = a.sane(params.bevel || 0, `outline.exports.${export_name}.bevel`, 'number')
|
||||
|
||||
let glue
|
||||
if (['both', 'glue', 'raw'].includes(params.side)) {
|
||||
|
||||
const get_line = (anchor) => {
|
||||
if (a.type(anchor) == 'number') {
|
||||
return u.line([anchor, -1000], [anchor, 1000])
|
||||
}
|
||||
|
||||
let from = anchor.clone()
|
||||
let to = anchor.add([anchor.meta.mirrored ? -1 : 1, 0])
|
||||
to = to.rotate(anchor.r, anchor.p).p
|
||||
|
||||
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)
|
||||
return u.line(from, to)
|
||||
}
|
||||
|
||||
const tll = get_line(config.top.left)
|
||||
const trl = get_line(config.top.right)
|
||||
const tip = m.path.converge(tll, trl)
|
||||
const tlp = u.eq(tll.origin, tip) ? tll.end : tll.origin
|
||||
const trp = u.eq(trl.origin, tip) ? trl.end : trl.origin
|
||||
|
||||
const bll = get_line(config.bottom.left)
|
||||
const brl = get_line(config.bottom.right)
|
||||
const bip = m.path.converge(bll, brl)
|
||||
const blp = u.eq(bll.origin, bip) ? bll.end : bll.origin
|
||||
const brp = u.eq(brl.origin, bip) ? brl.end : brl.origin
|
||||
|
||||
const left_waypoints = []
|
||||
const right_waypoints = []
|
||||
|
||||
for (const w of config.waypoints) {
|
||||
const percent = w.percent / 100
|
||||
const center_x = tip[0] + percent * (bip[0] - tip[0])
|
||||
const center_y = tip[1] + percent * (bip[1] - tip[1])
|
||||
const left_x = center_x - (w.left || w.width / 2)
|
||||
const right_x = center_x + (w.right || w.width / 2)
|
||||
left_waypoints.push([left_x, center_y])
|
||||
right_waypoints.unshift([right_x, center_y])
|
||||
}
|
||||
|
||||
let waypoints
|
||||
const is_split = a.type(config.top.right) == 'number'
|
||||
if (is_split) {
|
||||
waypoints = [tip, tlp]
|
||||
.concat(left_waypoints)
|
||||
.concat([blp, bip])
|
||||
} else {
|
||||
waypoints = [trp, tip, tlp]
|
||||
.concat(left_waypoints)
|
||||
.concat([blp, bip, brp])
|
||||
.concat(right_waypoints)
|
||||
}
|
||||
|
||||
glue = u.poly(waypoints)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const parse_exports = exports._parse_exports = (config = {}, points = {}) => {
|
||||
|
||||
config = a.sane(config, 'outline.exports', 'object')
|
||||
for (const [key, val] of Object.entries(config)) {
|
||||
params.op = a.in(params.op || 'add', `outline.exports.${key}.op`, ['add', 'sub', 'diff'])
|
||||
params.type = a.in(params.type, `outline.exports.${key}.type`, ['add', 'sub', 'diff'])
|
||||
}
|
||||
}
|
||||
|
||||
exports.parse = (config = {}, points = {}) => {
|
||||
a.detect_unexpected(config, 'outline', ['glue', 'exports'])
|
||||
const glue = parse_glue(config.glue, points)
|
||||
|
||||
config = a.sane(config, 'outline.exports', 'object')
|
||||
for (const [key, val] of Object.entries(config)) {
|
||||
params.op = a.in(params.op || 'add', `outline.exports.${key}.op`, ['add', 'sub', 'diff'])
|
||||
params.type = a.in(params.type, `outline.exports.${key}.type`, ['add', 'sub', 'diff'])
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue