Published
Edited
Jul 20, 2021
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function marching_squares (m,level) {

let chains = new Set();
var prev = [], curr = [];
var iy = 0;
var above = [];
var width = m[0].length;
var height = m.length;

for (var ix = 0; ix < width; ix++) {
prev[ix] = m[0][ix];
above [ix] = null;
}

for (var iy = 1; iy < height; iy++) {
curr [0] = m [iy][0];
var left = null;
for (var ix = 1; ix < width; ix++) {
curr [ix] = m [iy][ix];
var nw = prev[ix-1], ne = prev[ix], sw = curr[ix-1], se = curr[ix];
var n = (nw < level) != (ne < level);
var w = (nw < level) != (sw < level);
var e = (ne < level) != (se < level);
var s = (sw < level) != (se < level);
var np = n ? Vec ( mapRange (level, nw, ne, ix-1,ix), iy-1) : null;
var sp = s ? Vec ( mapRange (level, sw, se, ix-1,ix), iy) : null;
var wp = w ? Vec (ix-1, mapRange (level, nw, sw, iy-1,iy)) : null;
var ep = e ? Vec (ix, mapRange (level, ne, se, iy-1,iy)) : null;
var below = null, right = null;
if (s) {
if (n) {
if (joinSegmentChain (np, sp, above[ix])) {
below = above[ix];
}
if (!below) {
below = [np, sp];
chains.add (below);
}
}
else if (w) {
if (joinSegmentChain (wp, sp, left)) {
below = left;
}
if (!below) {
below = [wp, sp];
chains.add (below);
}
}

else if (e) {
below = right = [ep,sp];
chains.add (right);
}
else {
console.assert (false, "Singleton South");
}
}
if (e) {
if (w) {
if (joinSegmentChain (wp, ep, left)) {
right = left;
}
if (!right) {
right = [wp, ep];
chains.add (right);
}
}
else if (n) {
if (joinSegmentChain (np, ep, above[ix])) {
right = above[ix];
}
if (!right) {
right = [np, ep];
chains.add (right);
}
}
else {
console.assert (s, "Singleton East");
}
}
if (n) {
if (w && !e) {
if (joinSegmentChain (wp,np,left)) {
if (left != above[ix]) {
var joined = joinChains (left, above[ix]);
if (joined) {
for (var i = 1; i < width; i++) {
if (i != ix && above [i] == left) {
above [i] = joined;
}
}
if (below == left) below = joined;
if (right == left) right = joined;
chains.delete (left);
}
}
}
else if (joinSegmentChain (wp,np,above[ix])) {

}
else {
var seg = [wp, np];
chains.add (seg);
}
}
else {
console.assert (s || e, "Singleton North");
}
}
if (w) {
console.assert (n || e || s, "Singleton West");
}
above[ix] = below;
left = right;
}
prev = curr;
curr = [];
}

var carray = [];
for (let c of chains) {
carray.push (c);
}

for (var iterations = 0, havejoined = true; havejoined; iterations++) {
var joinCount = 0;
for (var i = 0; i < carray.length; i++) {
if (!carray [i]) continue;
for (var j = i+1; j < carray.length; j++) {
if (!carray[j]) continue;
var joined = joinChains (carray[j], carray[i]);
if (joined) {
chains.delete(carray[j]);
carray[j] = null;
joinCount++;
}
}
}
havejoined = joinCount>0;
}

var result = [];
for (var i = 0; i < carray.length; i++) {
if (!carray [i]) continue;
var c = new CurveLCR();
c.pts = carray[i];
c.closed = true;
result.push(c);
}
return result;

}

Insert cell
Insert cell
function mapRange (value, a, b, c, d) {
// first map value from (a..b) to (0..1)
value = (value - a) / (b - a);
// then map it from (0..1) to (c..d) and return it
return c + value * (d - c);
}
Insert cell
Insert cell
function joinSegmentChain (a, b, p) {
if (!p) return false;
var c = p[0], d = p[p.length-1];
if (a.x == c.x && a.y == c.y) {
p.reverse(); p.push (b); return p;
}
if (b.x == c.x && b.y == c.y) {
p.reverse(); p.push (a); return p;
}
if (a.x == d.x && a.y == d.y) {
p.push (b); return p;
}
if (b.x == d.x && b.y == d.y) {
p.push (a); return p;
}
return false;
}

Insert cell
Insert cell
joinChains = function (l, p) {
if (!l) return false;
if (!p) return false;
console.assert (l!=p, "Can't join chain with itself");
var a = l[0], b = l[l.length-1];
var c = p[0], d = p[p.length-1];
if (a.x == c.x && a.y == c.y) {
p.reverse();
}
else if (b.x == c.x && b.y == c.y) {
p.reverse(); l.reverse();
}
else if (a.x == d.x && a.y == d.y) {
}
else if (b.x == d.x && b.y == d.y) {
l.reverse();
}
else {
return false;
}
for (var i = 1; i < l.length; i++) {
p.push(l[i]);
}
return p;
}


Insert cell
Insert cell
class GridSample {

// Initializes for a given 2D range
constructor (xmin,xmax,ymin,ymax) {
this.xmin = xmin;
this.xmax = xmax;
this.ymin = ymin;
this.ymax = ymax;
var bigDist = 1e10;
this.s = [];
for (var i = 0; i < (ymax-ymin); i++) {
var row = [];
for (var j = 0; j < (xmax-xmin); j++) {
row[j] = bigDist;
}
this.s[i] = row;
}
}

addField (field, imin, jmin, imax, jmax) {
let i = imin;
let j = jmin
let difx = imax-i;
let dify = jmax-j;
if (difx > field[0].length) i = i + (difx-field[0].length);
if (dify > field.length) j = j + (dify-field.length);
for (var x = i; x < imax; x++) {
for (var y = j; y < jmax; y++) {
if (y >=0 && x >= 0 && y < this.ymax && x < this.xmax) {
var v = Math.min(this.s[y][x], field[y-j][x-i]);
this.s[y][x] = v;
}
}
}
}
extractField (xmin, xmax, ymin, ymax) {
let result = [];
for (var i = ymin; i < (ymax); i++) {
var row = [];
for (var j = xmin; j < (xmax); j++) {
row[j-xmin] = this.s[i][j];
}
result[i-ymin] = row;
}
return result;
}

}

Insert cell
class MasterGrid { //test

// Initializes for a given 2D range
constructor (xmin,xmax,ymin,ymax) {
this.xmin = xmin;
this.xmax = xmax;
this.ymin = ymin;
this.ymax = ymax;
var bigDist = 1e10; // A Big number
this.s = [];
for (var i = 0; i < (ymax-ymin); i++) {
var row = [];
for (var j = 0; j < (xmax-xmin); j++) {
row[j] = bigDist;
}
this.s[i] = row;
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more