function* drawing() {
replay;
const EPSILON = Math.pow(2, -52);
context.clearRect(0,0,context.canvas.width,context.canvas.height);
context2.clearRect(0,0,context2.canvas.width,context2.canvas.height);
drawCircles(context);
drawTriangles(context);
let allContours = {};
let levSegs;
let quadstart, quadend;
let contourLevels = linspace(-1,1,11);
for (let i = 0 ; i < contourLevels.length ; ++i) {
allContours[contourLevels[i]]=[];
levSegs = createSegments(contourLevels[i]);
if (levSegs.length == 0) continue;
quadstart = d3.quadtree(levSegs, function(d) { return d.p1.x ;}, function(d) { return d.p1.y; });
quadend = d3.quadtree(levSegs, function(d) { return d.p2.x ;}, function(d) { return d.p2.y; });
let contour = [];
let testSeg;
//loop through all segments
for (let j = 0; j < levSegs.length ; ++j) {
//if segment has already been tested for inclusion into contour, continue
if (levSegs[j].visited == true) continue;
contour.push(levSegs[j].p1);
allContours[contourLevels[i]].push(contour);
testSeg = levSegs[j];
testSeg.visited = true;
//find segment with starting point closest to this segment ending point
let closest = quadstart.find(testSeg.p2.x, testSeg.p2.y);
//if found segment sufficiently close (location should be equal, but floating point error means we can't compare using equality) and not already tested for inclusion into contour
while (Math.abs(closest.p1.x - testSeg.p2.x) < EPSILON && Math.abs(closest.p1.y - testSeg.p2.y) < EPSILON && !closest.visited) {
closest.visited = true;
contour.push(closest.p1);
testSeg = closest;
closest = quadstart.find(testSeg.p2.x, testSeg.p2.y);
//replace contour with updated contour
allContours[contourLevels[i]][allContours[contourLevels[i]].length-1] = contour;
//render updated contour
yield renderContour(context2, allContours);
}
//check if contour needs to be closed
if (Math.abs(testSeg.p2.x - contour[0].x) < EPSILON && Math.abs(testSeg.p2.y - contour[0].y) < EPSILON) {
contour.push(contour[0]);
contour.push(contour[1]);
allContours[contourLevels[i]][allContours[contourLevels[i]].length-1] = contour;
yield renderContour(context2, allContours);
}
//reverse contour to test the other direction
let reversedContour = contour.reverse();
testSeg = levSegs[j];
closest = quadend.find(testSeg.p1.x, testSeg.p1.y);
while (Math.abs(closest.p2.x - testSeg.p1.x) < EPSILON && Math.abs(closest.p2.y - testSeg.p1.y) < EPSILON && !closest.visited) {
closest.visited = true;
reversedContour.push(closest.p1);
testSeg = closest;
closest = quadend.find(testSeg.p1.x, testSeg.p1.y);
allContours[contourLevels[i]][allContours[contourLevels[i]].length-1] = reversedContour;
yield renderContour(context2, allContours);
}
//check if contour needs to be closed
if (Math.abs(testSeg.p2.x - reversedContour[0].x) < EPSILON && Math.abs(testSeg.p2.y - reversedContour[0].y) < EPSILON) {
reversedContour.push(reversedContour[0]);
reversedContour.push(reversedContour[1]);
allContours[contourLevels[i]][allContours[contourLevels[i]].length-1] = reversedContour;
yield renderContour(context2, allContours);
}
//reset contour
contour = [];
}
}
//renderContour(context2,allContours);
yield allContours;
}