Autobind vs. mirroring bugfix (#119)

This commit is contained in:
Bán Dénes 2024-01-22 15:56:45 +01:00
parent 1f57ec4e19
commit e1697e367f
6 changed files with 130 additions and 93 deletions

View file

@ -132,12 +132,14 @@ try {
// output helpers
const yamldump = data => yaml.dump(data, {indent: 4, noRefs: true})
const single = (data, rel) => {
if (!data) return
const abs = path.join(args.o, rel)
fs.mkdirpSync(path.dirname(abs))
if (abs.endsWith('.yaml')) {
fs.writeFileSync(abs, yaml.dump(data, {indent: 4}))
fs.writeFileSync(abs, yamldump(data))
} else {
fs.writeFileSync(abs, data)
}
@ -148,7 +150,7 @@ const composite = (data, rel) => {
const abs = path.join(args.o, rel)
if (data.yaml) {
fs.mkdirpSync(path.dirname(abs))
fs.writeFileSync(abs + '.yaml', yaml.dump(data.yaml, {indent: 4}))
fs.writeFileSync(abs + '.yaml', yamldump(data.yaml))
}
for (const format of ['svg', 'dxf', 'jscad']) {
if (data[format]) {

View file

@ -21,7 +21,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
a.unexpected(zone, `points.zones.${zone_name}`, ['columns', 'rows', 'key'])
// the anchor comes from "above", because it needs other zones too (for references)
const cols = a.sane(zone.columns || {}, `points.zones.${zone_name}.columns`, 'object')()
const cols = zone.columns = a.sane(zone.columns || {}, `points.zones.${zone_name}.columns`, 'object')()
const zone_wide_rows = a.sane(zone.rows || {}, `points.zones.${zone_name}.rows`, 'object')()
for (const [key, val] of Object.entries(zone_wide_rows)) {
zone_wide_rows[key] = val || {} // no check yet, as it will be extended later
@ -43,7 +43,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
// column layout
const col_minmax = {}
if (!Object.keys(cols).length) {
cols.default = {}
}
@ -53,7 +52,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
// column-level sanitization
col = col || {}
col_minmax[col_name] = {min: Infinity, max: -Infinity}
a.unexpected(
col,
@ -184,10 +182,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
point.meta = key
points[key.name] = point
// collect minmax stats for autobind
col_minmax[col_name].min = Math.min(col_minmax[col_name].min, point.y)
col_minmax[col_name].max = Math.max(col_minmax[col_name].max, point.y)
// advance the running anchor to the next position
running_anchor.shift([0, key.padding])
}
@ -195,56 +189,6 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key,
first_col = false
}
// autobind
let col_names = Object.keys(col_minmax)
let col_index = 0
for (const [col_name, bounds] of Object.entries(col_minmax)) {
for (const point of Object.values(points)) {
if (point.meta.col.name != col_name) continue
if (!point.meta.autobind) continue
const autobind = a.sane(point.meta.autobind, `${point.meta.name}.autobind`, 'number')(units)
// specify default as -1, so we can recognize where it was left undefined even after number-ification
const bind = point.meta.bind = a.trbl(point.meta.bind, `${point.meta.name}.bind`, -1)(units)
// up
if (bind[0] == -1) {
if (point.y < bounds.max) bind[0] = autobind
else bind[0] = 0
}
// right
if (bind[1] == -1) {
bind[1] = 0
if (col_index < col_names.length - 1) {
const right = col_minmax[col_names[col_index + 1]]
if (point.y >= right.min && point.y <= right.max) {
bind[1] = autobind
}
}
}
// down
if (bind[2] == -1) {
if (point.y > bounds.min) bind[2] = autobind
else bind[2] = 0
}
// left
if (bind[3] == -1) {
bind[3] = 0
if (col_index > 0) {
const left = col_minmax[col_names[col_index - 1]]
if (point.y >= left.min && point.y <= left.max) {
bind[3] = autobind
}
}
}
}
col_index++
}
return points
}
@ -274,6 +218,79 @@ const perform_mirror = exports._perform_mirror = (point, axis) => {
return [mirrored_name, mp]
}
const perform_autobind = exports._perform_autobind = (points, units) => {
const bounds = {}
const col_lists = {}
const mirrorzone = p => (p.meta.mirrored ? 'mirror_' : '') + p.meta.zone.name
// round one: get column upper/lower bounds and per-zone column lists
for (const p of Object.values(points)) {
const zone = mirrorzone(p)
const col = p.meta.col.name
if (!bounds[zone]) bounds[zone] = {}
if (!bounds[zone][col]) bounds[zone][col] = {min: Infinity, max: -Infinity}
if (!col_lists[zone]) col_lists[zone] = Object.keys(p.meta.zone.columns)
bounds[zone][col].min = Math.min(bounds[zone][col].min, p.y)
bounds[zone][col].max = Math.max(bounds[zone][col].max, p.y)
}
// round two: apply autobind as appropriate
for (const p of Object.values(points)) {
const autobind = a.sane(p.meta.autobind, `${p.meta.name}.autobind`, 'number')(units)
if (!autobind) continue
const zone = mirrorzone(p)
const col = p.meta.col.name
const col_list = col_lists[zone]
const col_bounds = bounds[zone][col]
// specify default as -1, so we can recognize where it was left undefined even after number-ification
const bind = p.meta.bind = a.trbl(p.meta.bind, `${p.meta.name}.bind`, -1)(units)
// up
if (bind[0] == -1) {
if (p.y < col_bounds.max) bind[0] = autobind
else bind[0] = 0
}
// down
if (bind[2] == -1) {
if (p.y > col_bounds.min) bind[2] = autobind
else bind[2] = 0
}
// left
if (bind[3] == -1) {
bind[3] = 0
const col_index = col_list.indexOf(col)
if (col_index > 0) {
const left = bounds[zone][col_list[col_index - 1]]
if (left && p.y >= left.min && p.y <= left.max) {
bind[3] = autobind
}
}
}
// right
if (bind[1] == -1) {
bind[1] = 0
const col_index = col_list.indexOf(col)
if (col_index < col_list.length - 1) {
const right = bounds[zone][col_list[col_index + 1]]
if (right && p.y >= right.min && p.y <= right.max) {
bind[1] = autobind
}
}
}
}
}
exports.parse = (config, units) => {
// config sanitization
@ -369,6 +386,9 @@ exports.parse = (config, units) => {
filtered[k] = p
}
// apply autobind
perform_autobind(filtered, units)
// done
return filtered
}

View file

@ -24,6 +24,11 @@ matrix:
colrow: default_default
name: matrix
zone:
columns:
default:
rows: {}
key: {}
name: default
name: matrix
col:
rows: {}

View file

@ -25,14 +25,17 @@ matrix_col_row:
name: matrix_col_row
zone:
columns:
col: &ref_0
col:
rows: {}
key: {}
name: col
rows:
row: {}
name: matrix
col: *ref_0
col:
rows: {}
key: {}
name: col
row: row
bind:
- 0

View file

@ -27,6 +27,13 @@
"colrow": "default_default",
"name": "matrix",
"zone": {
"columns": {
"default": {
"rows": {},
"key": {},
"name": "default"
}
},
"name": "matrix"
},
"col": {

View file

@ -61,13 +61,13 @@
"name": "left"
},
"row": "bottom",
"mirrored": false,
"bind": [
10,
0,
10,
0,
0
],
"mirrored": false
]
}
},
"matrix_right_bottom": {
@ -125,13 +125,13 @@
"name": "right"
},
"row": "bottom",
"mirrored": false,
"bind": [
10,
0,
0,
10
],
"mirrored": false
]
}
},
"matrix_right_top": {
@ -189,13 +189,13 @@
"name": "right"
},
"row": "top",
"mirrored": false,
"bind": [
0,
0,
10,
10
],
"mirrored": false
0
]
}
},
"other_left_bottom": {
@ -260,13 +260,13 @@
"name": "left"
},
"row": "bottom",
"mirrored": false,
"bind": [
10,
0,
10,
0,
0
],
"mirrored": false
]
}
},
"other_right_bottom": {
@ -324,13 +324,13 @@
"name": "right"
},
"row": "bottom",
"mirrored": false,
"bind": [
10,
0,
0,
10
],
"mirrored": false
]
}
},
"other_right_top": {
@ -388,13 +388,13 @@
"name": "right"
},
"row": "top",
"mirrored": false,
"bind": [
0,
0,
10,
10
],
"mirrored": false
0
]
}
},
"mirror_other_left_top": {
@ -459,13 +459,13 @@
"name": "left"
},
"row": "top",
"mirrored": true,
"bind": [
0,
10,
10,
0,
0
],
"mirrored": true
]
}
},
"mirror_other_right_bottom": {
@ -523,13 +523,13 @@
"name": "right"
},
"row": "bottom",
"mirrored": true,
"bind": [
10,
0,
0,
10
],
"mirrored": true
0
]
}
},
"mirror_other_right_top": {
@ -587,13 +587,13 @@
"name": "right"
},
"row": "top",
"mirrored": true,
"bind": [
0,
0,
10,
10
],
"mirrored": true
]
}
},
"mirror_matrix_left_top": {
@ -658,13 +658,13 @@
"name": "left"
},
"row": "top",
"mirrored": true,
"bind": [
0,
10,
10,
0,
0
],
"mirrored": true
]
}
},
"mirror_matrix_right_bottom": {
@ -722,13 +722,13 @@
"name": "right"
},
"row": "bottom",
"mirrored": true,
"bind": [
10,
0,
0,
10
],
"mirrored": true
0
]
}
},
"mirror_matrix_right_top": {
@ -786,13 +786,13 @@
"name": "right"
},
"row": "top",
"mirrored": true,
"bind": [
0,
0,
10,
10
],
"mirrored": true
]
}
}
}