Buldging checkerboard

A straight checkerboard and then some dots, or not... (use sliders below) #illusion

Log in to post a comment.

let showDots = 1; //min=0, max=1, step=1
let size = 20; //min=8, max=50, step=2
let dotRatio = .25; //min=.1, max=.5, step=.05

Canvas.setpenopacity(1);
const turtle = new Turtle();

const canvasSize = 200;

const gridSize = Math.ceil(canvasSize / size) + (Math.ceil(canvasSize / size) % 2 == 0? 1: 0);

function drawCell(i) {
    var col = (i % gridSize) - ((gridSize / 2) | 0);
    var row = (i / gridSize | 0) - ((gridSize / 2) | 0);
    
    var x = (col * size) - (size / 2);
    var y = (row * size) - (size / 2);
    
    var color = i % 2 == 0;
    
    var circles = [];

    var useCircles = [];
    if(row == 0) {
        if(col != 0) { useCircles = (col < 0)? [0, 2]: [1, 3]; }
    } else if (col == 0) {
        if(row != 0) { useCircles = (row < 0)? [2, 3]: [0, 1]; }
    } else if(row < 0) {
        useCircles = (col < 0)? [0, 3]: [1, 2];
    } else {
        useCircles = (col < 0)? [1, 2]: [0, 3];
    }

    var cr = ((size * dotRatio) - 1) / 2;
    for(var c = 0; c < 4; c++) {
        if(useCircles.indexOf(c) < 0) {
            continue;
        }
        var cx = cy = cr + .5;
        if(1 < c) { cy = size - cy; }
        if(c == 0 || c == 2) { cx = size - cx; }
        circles.push([x + cx, y + cy]);
    }
        
    for(var yy = y; yy < y + size; yy += .1) {
        var intersections = [];
        
        for(var j = 0; j < circles.length; j++) {
            var M = circles[j];
            var D = [size, 0];
            var O = [x, yy];
            var OM = [O[0] - M[0], O[1] - M[1]];
            var A = size * size;
            var B = 2 * (D[0]*OM[0]) + (D[1]*OM[1]);
            var C = (Math.pow(OM[0], 2) + Math.pow(OM[1], 2)) - (cr * cr);
            var Q = (B*B) - (4*A*C);
            if(Q > 0) {
                var G = 1 / (2*A);
                Q = G*Math.sqrt(Q);
                B = (-1 * B * G);
                intersections.push((B+Q) * size);
                intersections.push((B-Q) * size);
            }
        }
        
        intersections.sort(function(a,b) { return a - b;});

        if(color) {
            turtle.jump(x, yy);
            if(showDots) {
                for(var i = 0; i < intersections.length; i += 2) {
                    turtle.goto(x + intersections[i], yy);
                    turtle.jump(x + intersections[i + 1], yy)
                }
            }
            turtle.goto(x + size, yy);
        } else if(showDots) {
            for(var i = 0; i < intersections.length; i += 2) {
                turtle.jump(x + intersections[i], yy);
                turtle.goto(x + intersections[i + 1], yy)
            }
        }
    }
}

// The walk function will be called until it returns false.
function walk(i) {
    drawCell(i);
    return i < Math.pow(gridSize, 2) - 1;
}