repair gaps in the gyroid

This commit is contained in:
Stewart Allen 2019-01-21 21:00:24 -05:00
commit 75405eb66b
3 changed files with 56 additions and 70 deletions

View file

@ -60,7 +60,7 @@ var gs_base_gyroid = exports;
let lval = vals[vals.length-1][x]; let lval = vals[vals.length-1][x];
for (let y=0; y<rez; y++) { for (let y=0; y<rez; y++) {
let val = vals[y][x]; let val = vals[y][x];
if (lval <= 0 && val >= 0) { if ((lval <= 0 && val >= 0) || (lval >= 0 && val <= 0)) {
if (edge[y][x]) { if (edge[y][x]) {
edge[y][x] = 3; edge[y][x] = 3;
} else { } else {
@ -119,7 +119,7 @@ var gs_base_gyroid = exports;
for (let i=0; i<sparse.length; i++) { for (let i=0; i<sparse.length; i++) {
let test_el = sparse[i]; let test_el = sparse[i];
if (test_el) { if (test_el) {
let dst = dist(target, test_el, dir); let dst = distTo(target, test_el, dir);
if (cl_idx === null || dst < cl_dst) { if (cl_idx === null || dst < cl_dst) {
cl_idx = i; cl_idx = i;
cl_elm = test_el; cl_elm = test_el;
@ -139,73 +139,49 @@ var gs_base_gyroid = exports;
} while (added); } while (added);
} while (cleared < sparse.length); } while (cleared < sparse.length);
return {edge, points, dir, polys: polys.map(poly => filter(poly,inc))}; let psimple = polys
.map(poly => filter(poly, 0))
.map(poly => filter(poly, inc));
return {edge, points, dir, polys: psimple};
} }
// merge x/y co-linear // merge co-linear and distance threshold
function filter(poly,inc) { function filter(poly, inc) {
if (poly.length === 1) { if (poly.length <= 2) {
return poly; return poly;
} }
let nuchain = []; let nupoly = [ poly[0] ];
let e1 = poly[0]; let e1 = poly[1];
let e2 = null; let e2 = null;
let last = poly.length - 1; let last = poly.length - 2;
for (let i=1; i<poly.length; i++) { for (let i=1; i<poly.length; i++) {
let el = poly[i]; let el = poly[i];
if (e1.x === el.x || e1.y === el.y) { let drop = inc ?
(distTo(e1, el) <= inc) :
(e1.x === el.x || e1.y === el.y);
if (drop) {
e2 = el; e2 = el;
if (i < last) { if (i < last) {
continue; continue;
} }
} }
if (e2) { if (e2) {
nuchain.push({x:(e1.x + e2.x)/2, y:(e1.y + e2.y)/2}); nupoly.push({x:(e1.x + e2.x)/2, y:(e1.y + e2.y)/2});
e2 = null; e2 = null;
} else { } else {
nuchain.push(e1); nupoly.push(e1);
if (i === last) { if (i === last) {
nuchain.push(el); nupoly.push(el);
} }
} }
e1 = el; e1 = el;
} }
return filter2(nuchain,inc); nupoly.push(poly[poly.length-1]);
return nupoly;
} }
// merge points within radius function distTo(a, b, dir) {
function filter2(poly,inc) {
if (poly.length === 1) {
return poly;
}
let nuchain = [];
let e1 = poly[0];
let e2 = null;
let last = poly.length - 1;
let merge = inc;
for (let i=1; i<poly.length; i++) {
let el = poly[i];
if (dist(e1, el) <= merge) {
e2 = el;
if (i < last) {
continue;
}
}
if (e2) {
nuchain.push({x:(e1.x + e2.x)/2, y:(e1.y + e2.y)/2});
e2 = null;
} else {
nuchain.push(e1);
if (i === last) {
nuchain.push(el);
}
}
e1 = el;
}
return nuchain;
}
function dist(a, b, dir) {
let dx = a.x - b.x; let dx = a.x - b.x;
let dy = a.y - b.y; let dy = a.y - b.y;
// bias distance by prevailing direction of discovery to join stragglers // bias distance by prevailing direction of discovery to join stragglers

View file

@ -1,7 +1,7 @@
var exports = { var exports = {
COPYRIGHT:"Copyright (C) 2014-2019 Stewart Allen <sa@grid.space> - All Rights Reserved", COPYRIGHT:"Copyright (C) 2014-2019 Stewart Allen <sa@grid.space> - All Rights Reserved",
LICENSE:"See the license.md file included with the source distribution", LICENSE:"See the license.md file included with the source distribution",
VERSION:"1.2.6b" VERSION:"1.2.6c"
}; };
if (!module) var module = {}; if (!module) var module = {};
module.exports = exports; module.exports = exports;

View file

@ -97,23 +97,23 @@
// left-right threshold search (red) // left-right threshold search (red)
vals.forEach((vrow, y) => { vals.forEach((vrow, y) => {
let erow = edge[y]; let erow = edge[y];
let lval = vrow[vrow.length - 1]; let v0 = vrow[vrow.length - 1];
vrow.forEach((val, x) => { vrow.forEach((v1, x) => {
if ((lval <= 0 && val >= 0) || (lval >= 0 && val <= 0)) { if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) {
erow[x] = 1; erow[x] = 1;
points++; points++;
points_lr++; points_lr++;
} }
lval = val; v0 = v1;
}) })
}); });
// top-down threshold search (green) // top-down threshold search (green)
for (let x=0; x<rez; x++) { for (let x=0; x<rez; x++) {
let lval = vals[vals.length-1][x]; let v0 = vals[vals.length-1][x];
for (let y=0; y<rez; y++) { for (let y=0; y<rez; y++) {
let val = vals[y][x]; let v1 = vals[y][x];
if (lval <= 0 && val >= 0) { if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) {
if (edge[y][x]) { if (edge[y][x]) {
edge[y][x] = 3; edge[y][x] = 3;
} else { } else {
@ -122,7 +122,7 @@
} }
points_td++; points_td++;
} }
lval = val; v0 = v1;
} }
} }
@ -145,6 +145,9 @@
return b.dist - a.dist; return b.dist - a.dist;
}); });
// preserve sparse points for rendering
let raw = sparse.slice();
// join sparse points array by closest distance // join sparse points array by closest distance
let polys = []; let polys = [];
let chain; let chain;
@ -195,17 +198,17 @@
// simplify poly // simplify poly
polys = polys.map(poly => filter(poly)); polys = polys.map(poly => filter(poly));
return zcache[zkey] = {edge, points, dir, polys}; return zcache[zkey] = { raw, points, dir, polys };
} }
function filter(poly) { function filter(poly) {
if (poly.length === 1) { if (poly.length <= 2) {
return poly; return poly;
} }
let nuchain = []; let nuchain = [ poly[0] ];
let e1 = poly[0]; let e1 = poly[1];
let e2 = null; let e2 = null;
let last = poly.length - 1; let last = poly.length - 2;
for (let i=1; i<poly.length; i++) { for (let i=1; i<poly.length; i++) {
let el = poly[i]; let el = poly[i];
if (e1.x === el.x || e1.y === el.y) { if (e1.x === el.x || e1.y === el.y) {
@ -225,6 +228,7 @@
} }
e1 = el; e1 = el;
} }
nuchain.push(poly[poly.length-1]);
return nuchain; return nuchain;
} }
@ -238,10 +242,10 @@
} }
function render(z) { function render(z) {
let size = 800; let size = 600;
let wh = size / rez; let wh = size / rez;
let html = [`<svg width=${size} height=${size}>`]; let html = [`<svg width=${size} height=${size}>`];
let { edge, points, dir, polys } = generate(z); let { raw, points, dir, polys } = generate(z);
$('points').value = points; $('points').value = points;
$('direction').value = dir; $('direction').value = dir;
@ -249,14 +253,20 @@
// raw threshold points // raw threshold points
html.push('<g>'); html.push('<g>');
polys.forEach(poly => { raw.forEach(point => {
poly.forEach(point => {
let x = point.x; let x = point.x;
let y = point.y; let y = point.y;
let color = ['black','#f00a','#0f0a','#00fa'][point.val]; let color = ['black','#f00a','#0f0a','#00fa'][point.val];
html.push(`<rect dist="${point.dist}" x="${x*wh}" y="${y*wh}" width="${wh}" height="${wh}" style="fill:${color};stroke-width:0"/>`); html.push(`<rect dist="${point.dist}" x="${x*wh}" y="${y*wh}" width="${wh}" height="${wh}" style="fill:${color};stroke-width:0"/>`);
}); })
}); // polys.forEach(poly => {
// poly.forEach(point => {
// let x = point.x;
// let y = point.y;
// let color = ['black','#f00a','#0f0a','#00fa'][point.val];
// html.push(`<rect dist="${point.dist}" x="${x*wh}" y="${y*wh}" width="${wh}" height="${wh}" style="fill:${color};stroke-width:0"/>`);
// });
// });
html.push('</g>'); html.push('</g>');
// points joined into poly lines // points joined into poly lines