function getCirculations (imgdata) {
let [w,h] = [imgdata.width,imgdata.height];
let data = imgdata.data;
function getRuns (x) {
let last = false;
let run = null;
let runs = [];
for (let y = 0; y < h; y++) {
let pixel = data[(w*y+x)*4+3];
let current = pixel > 0;
if (current) {
if (run != null) run.ymax = y+1;
else {
run = { x:x, ymin: y, ymax:y+1 };
runs.push (run);
}
}
else {
run = null
}
}
return runs
}
function runDifference (runs0,runs1) {
runs0 = runs0.slice(0);
if (runs0.length == 0) return runs0;
if (runs1.length == 0) return runs0;
let result = [];
let [i0,i1] = [0,0];
while ( i0 < runs0.length && i1 < runs1.length ) {
let [r0,r1] = [runs0[i0], runs1[i1]];
if (r0.ymax <= r1.ymin) {
result.push(r0);
i0++;
} else if (r1.ymax <= r0.ymin) {
i1++;
} else {
if (r0.ymin < r1.ymin) {
result.push ({x:r0.x, ymin: r0.ymin, ymax:r1.ymin});
r0 = {x:r0.x, ymin:r1.ymin, ymax:r0.ymax};
} else {
r0 = {x:r0.x, ymin:r1.ymax, ymax:r0.ymax};
}
if (r0.ymax <= r0.ymin) i0++;
else runs0[i0] = r0;
}
}
result.push.apply(result,runs0.slice(i0))
return result;
}
let prevRuns = [];
let connected = new ConnectedComponents();
let vEdge = (x) => { return (run) => [Vec(x,run.ymin),Vec(x,run.ymax)] };
for (let x= 0; x <= w; x++) {
let runs = x == w ? [] : getRuns(x);
let currMinusPrev = runDifference(runs, prevRuns);
let prevMinusCurr = runDifference(prevRuns, runs);
let verticalEdges = currMinusPrev.map(vEdge(x)).concat(prevMinusCurr.map(vEdge(x)));
let horizontalEdges = [];
for (let r of runs) {
horizontalEdges.push ([Vec(r.x,r.ymin),Vec(r.x+1,r.ymin)]);
horizontalEdges.push ([Vec(r.x,r.ymax),Vec(r.x+1,r.ymax)]);
}
for (let vEdge of verticalEdges) {
connected.addVerticalEdge (vEdge);
}
for (let hEdge of horizontalEdges) {
connected.addHorizontalEdge (hEdge);
}
prevRuns = runs
}
return connected;
}