block by fogleman f625038a8a61f4abedb4bcd98f7953df

Virtual Plotter

Full Screen

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>body {padding: 0; margin: 0; overflow: hidden;}</style>
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.5/p5.min.js"></script>
    <script src="paths.js"></script>
    <script src="sketch.js"></script>
</body>
</html>

sketch.js

function pathLength(path) {
    var result = 0;
    for (var i = 1; i < path.length; i++) {
        var p1 = path[i-1];
        var p2 = path[i];
        result += dist(p1[0], p1[1], p2[0], p2[1]);
    }
    return result;
}

function drawPath(dc, path) {
    dc.beginShape();
    for (var i = 0; i < path.length; i++) {
        var point = path[i];
        dc.vertex(point[0], point[1]);
    }
    dc.endShape();
}

function computeBounds(paths) {
    var p = paths[0][0];
    var minx = p[0];
    var maxx = p[0];
    var miny = p[1];
    var maxy = p[1];
    for (var i = 0; i < paths.length; i++) {
        var path = paths[i];
        for (var j = 0; j < path.length; j++) {
            var point = path[j];
            minx = min(minx, point[0]);
            maxx = max(maxx, point[0]);
            miny = min(miny, point[1]);
            maxy = max(maxy, point[1]);
        }
    }
    var width = maxx - minx;
    var height = maxy - miny;
    return {
        minx: minx, miny: miny, maxx: maxx, maxy: maxy,
        width: width, height: height,
    }
}

function drawPathLength(dc, path, length) {
    if (length <= 0) {
        return;
    }
    dc.beginShape();
    dc.vertex(path[0][0], path[0][1]);
    for (var i = 1; i < path.length; i++) {
        var p1 = path[i-1];
        var p2 = path[i];
        var d = dist(p1[0], p1[1], p2[0], p2[1]);
        length -= d;
        if (length < 0) {
            var t = -length / d;
            t = 1 - t;
            var x = lerp(p1[0], p2[0], t);
            var y = lerp(p1[1], p2[1], t);
            dc.vertex(x, y);
            break;
        } else {
            dc.vertex(p2[0], p2[1]);
        }
    }
    dc.endShape();
}

function Drawing(paths) {
    this.paths = paths;
    this.bounds = computeBounds(paths);
    this.index = 0;
    this.length = 0;
    this.rate = 1 * 0.1;
    this.jogRate = 2 * 0.1;
    this.previousMillis = millis();
}

Drawing.prototype.update = function(dc) {
    var t = millis();
    var dt = t - this.previousMillis;
    if (dt < 0) {
        return;
    }
    this.previousMillis = t;

    var path = this.paths[this.index];
    var length = pathLength(path);
    var remainingLength = length - this.length;
    var traversalLength = dt * this.rate;
    if (traversalLength >= remainingLength) {
        drawPath(dc, path);
        this.index++;
        this.length = 0;
        var nextPath = this.paths[this.index];
        var d = dist(
            path[path.length-1][0], path[path.length-1][1],
            nextPath[0][0], nextPath[0][1]);
        this.previousMillis += d / this.jogRate + 200;
    } else {
        this.length += traversalLength;
    }
}

Drawing.prototype.draw = function(dc) {
    for (var i = 0; i < this.index; i++) {
        drawPath(dc, this.paths[i]);
    }
}

Drawing.prototype.setTransform = function(dc) {
    var bounds = this.bounds;
    var sx = dc.width / bounds.width;
    var sy = dc.height / bounds.height;
    var s = min(sx, sy);
    var dx = (dc.width - bounds.width * s) / 2;
    var dy = (dc.height - bounds.height * s) / 2;
    dc.resetMatrix();
    dc.translate(dx, dy);
    dc.scale(s);
    dc.translate(-bounds.minx, -bounds.miny);
}


var drawing;
var buffer;

function setup() {
    drawing = new Drawing(PATHS);
    createCanvas(windowWidth, windowHeight);
    restart();
}

function windowResized() {
    resizeCanvas(windowWidth, windowHeight);
    restart();
}

function setStyle(dc) {
    dc.stroke(0, 192);
    dc.strokeWeight(0.5);
    dc.strokeJoin(ROUND);
    dc.noFill();
}

function restart() {
    background(255);
    buffer = createGraphics(width, height);
    buffer.background(255);
    setStyle(buffer);
    drawing.setTransform(buffer);
    drawing.draw(buffer);
    setStyle(window);
}

function draw() {
    resetMatrix();
    drawing.update(buffer);
    image(buffer, 0, 0);
    drawing.setTransform(window);
    drawPathLength(window, drawing.paths[drawing.index], drawing.length);
}