gen fillable poly for gyroid example

This commit is contained in:
Stewart Allen 2020-05-05 11:56:34 -04:00
commit 102776fefc

View file

@ -44,10 +44,64 @@
} }
</style> </style>
<script> <script>
class Timer {
constructor() {
this.time = 0;
this.times = {};
this.order = [];
this.start();
}
start() {
this.time = Date.now();
}
mark(label) {
let newtime = Date.now();
let oldval = this.times[label] || 0;
if (oldval === 0) {
this.order.push(label);
}
this.times[label] = oldval + (newtime - this.time);
this.time = newtime;
}
toString() {
return this.order.map(l => `${l}:${this.times[l]}`);
}
}
class Map {
constructor(x,y,type) {
this.x = x;
this.y = y;
switch (type) {
case 'f': this.map = new Float32Array(x*y); break;
case 'i': this.map = new Int32Array(x*y); break;
case 'c': this.map = new Uint8Array(x*y); break;
default: throw `invalid type: ${type}`;
}
}
pos(x,y) {
return x+y*this.x;
}
get(x,y) {
return this.map[x+y*this.x];
}
put(x,y,v) {
this.map[x+y*this.x] = v;
}
}
let PI2 = Math.PI * 2; let PI2 = Math.PI * 2;
let rez = 200; let rez = 200;
let inc = PI2 / rez; let inc = PI2 / rez;
let zcache = {}; let zcache = {};
let timer = new Timer();
let maxdist = rez * 0.01;
function $(id) { function $(id) {
return document.getElementById(id); return document.getElementById(id);
@ -58,6 +112,7 @@
for (let z=0; z<PI2; z += inc) { for (let z=0; z<PI2; z += inc) {
generate(z); generate(z);
} }
console.log(timer.toString());
render(0); render(0);
} }
@ -73,58 +128,69 @@
if (cached) { if (cached) {
return cached; return cached;
} }
timer.start();
let edge = []; let size = ((PI2 / inc)|0) + 1;
let vals = []; let edge = new Map(size,size,'c');
let vals = new Map(size,size,'f');
let points = 0; let points = 0;
let points_lr = 0; let points_lr = 0;
let points_td = 0; let points_td = 0;
for (let x=0; x<PI2; x += inc) { let tip = 0.2;
let vrow = []; // raw values row let xv = 0;
let erow = []; // edge values row for (let x=0; x<size; x++) {
edge.push(erow); let yv = 0;
vals.push(vrow); for (let y=0; y<size; y++) {
for (let y=0; y<PI2; y += inc) { vals.put(x,y,
erow.push(0); Math.sin(xv) * Math.cos(yv) +
vrow.push( Math.sin(yv) * Math.cos(z) +
Math.sin(x) * Math.cos(y) + Math.sin(z) * Math.cos(xv)
Math.sin(y) * Math.cos(z) +
Math.sin(z) * Math.cos(x)
); );
yv += inc;
} }
xv += inc;
} }
timer.mark('points');
// left-right threshold search (red) // left-right threshold search (red)
vals.forEach((vrow, y) => { for (let x=1; x<size; x++) {
let erow = edge[y]; for (let y=0; y<size; y++) {
let v0 = vrow[vrow.length - 1]; let v0 = vals.get(x-1,y);
vrow.forEach((v1, x) => { let v1 = vals.get(x,y);
if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) { if (
erow[x] = 1; (v0 <= tip && v1 >= tip) || (v0 >= tip && v1 <= tip) ||
(v0 <= -tip && v1 >= -tip) || (v0 >= -tip && v1 <= -tip)
) {
// if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) {
edge.put(x,y,1);
points++; points++;
points_lr++; points_lr++;
} }
v0 = v1; }
}) }
}); timer.mark('gen_red');
// top-down threshold search (green) // top-down threshold search (green)
for (let x=0; x<rez; x++) { for (let y=1; y<size; y++) {
let v0 = vals[vals.length-1][x]; for (let x=0; x<size; x++) {
for (let y=0; y<rez; y++) { let v0 = vals.get(x,y-1);
let v1 = vals[y][x]; let v1 = vals.get(x,y);
if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) { if (
if (edge[y][x]) { (v0 <= tip && v1 >= tip) || (v0 >= tip && v1 <= tip) ||
edge[y][x] = 3; (v0 <= -tip && v1 >= -tip) || (v0 >= -tip && v1 <= -tip)
) {
// if ((v0 <= 0 && v1 >= 0) || (v0 >= 0 && v1 <= 0)) {
if (edge.get(x,y)) {
edge.put(x,y,3);
} else { } else {
edge[y][x] = 2; edge.put(x,y,2);
points++ points++;
} }
points_td++; points_td++;
} }
v0 = v1;
} }
} }
timer.mark('gen_grn');
// deterime prevailing direction for chaining // deterime prevailing direction for chaining
let dir = points_td > points_lr ? 'lr' : 'td'; let dir = points_td > points_lr ? 'lr' : 'td';
@ -132,18 +198,26 @@
// create sparse representation // create sparse representation
let sparse = []; let sparse = [];
let center = rez / 2; let center = rez / 2;
edge.forEach((row,y) => { let edgev = size-1;
row.forEach((val,x) => { for (let x=0; x<size; x++) {
for (let y=0; y<size; y++) {
let val = edge.get(x,y);
if (val) { if (val) {
let dx = Math.abs(x - center); let dx = Math.abs(x - center);
let dy = Math.abs(y - center); let dy = Math.abs(y - center);
sparse.push({x, y, val, dist: Math.max(dx,dy)}); sparse.push({
x, y, val,
dist: Math.max(dx,dy),
edge: (x === 0 || y === 0 || x === edgev || y === edgev)
});
} }
}); }
}); }
// order points farthest from center (edges, in other words)
sparse.sort((a,b) => { sparse.sort((a,b) => {
return b.dist - a.dist; return b.dist - a.dist;
}); });
timer.mark('sparse');
// preserve sparse points for rendering // preserve sparse points for rendering
let raw = sparse.slice(); let raw = sparse.slice();
@ -153,11 +227,11 @@
let chain; let chain;
let added; let added;
let cleared = 0; let cleared = 0;
let maxdist = rez * 0.05;
do { do {
chain = null;
for (let i=0; i<sparse.length; i++) { for (let i=0; i<sparse.length; i++) {
// find the unclaimed point farthest
// from center and start a chain
if (sparse[i]) { if (sparse[i]) {
chain = [ sparse[i] ]; chain = [ sparse[i] ];
polys.push(chain); polys.push(chain);
@ -169,9 +243,10 @@
do { do {
added = false; added = false;
let target = chain[chain.length - 1]; let target = chain[chain.length - 1];
let cl_elm = null; let cl_elm = null; // candidate closest element
let cl_idx = null; let cl_idx = null; // candidate closest index
let cl_dst = Infinity; let cl_dst = Infinity; // candidate distance
// look for next closest point to end of chain
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) {
@ -184,6 +259,9 @@
} }
} }
if (cl_elm) { if (cl_elm) {
// if (target.edge && !cl_elm.edge) {
// break;
// }
if (cl_dst > maxdist) { if (cl_dst > maxdist) {
break; break;
} }
@ -194,6 +272,7 @@
} }
} while (added); } while (added);
} while (cleared < sparse.length); } while (cleared < sparse.length);
timer.mark('chain');
// simplify poly // simplify poly
polys = polys.map(poly => filter(poly)); polys = polys.map(poly => filter(poly));