block by fogleman c11a5cbcd845946b851518adedbf6a32

Roulette (curve)

Full Screen

In the differential geometry of curves, a roulette is a kind of curve, generalizing cycloids, epicycloids, hypocycloids, trochoids, and involutes.

This p5.js sketch implements hypotrochoid and epicycloid roulettes.

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/dat-gui/0.6.2/dat.gui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.5/p5.min.js"></script>
    <script src="sketch.js"></script>
</body>
</html>

sketch.js

function hypotrochoid(R, r, d, theta) {
    var x = (R - r) * cos(theta) + d * cos((R - r) / r * theta);
    var y = (R - r) * sin(theta) - d * sin((R - r) / r * theta);
    return createVector(x, y);
}

function epitrochoid(R, r, d, theta) {
    var x = (R + r) * cos(theta) - d * cos((R + r) / r * theta);
    var y = (R + r) * sin(theta) - d * sin((R + r) / r * theta);
    return createVector(x, y);
}

function reduceFraction(n, d) {
    var gcd = function gcd(a, b) {
        return b ? gcd(b, a % b) : a;
    };
    gcd = gcd(n, d);
    return [n / gcd, d / gcd];
}

var Controls = function() {
    this.type = 0;
    this.R = 10;
    this.r = 6;
    this.d = 4;
    this.rotation = 0;
};

var controls = new Controls();

function setup() {
    var gui = new dat.GUI({width: 400});
    gui.add(controls, 'type', {hypotrochoid: 0, epitrochoid: 1});
    gui.add(controls, 'R', 1, 32).step(1);
    gui.add(controls, 'r', 1, 32).step(1);
    gui.add(controls, 'd', 1, 32);
    gui.add(controls, 'rotation', 0, 360);
    createCanvas(windowWidth, windowHeight);
}

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

function draw() {
    var R = controls.R;
    var r = controls.r;
    var d = controls.d;
    var N = reduceFraction(R, r)[1];

    translate(width / 2, height / 2);
    rotate(radians(270 + controls.rotation));
    background(0);
    noFill();

    var func = hypotrochoid;
    if (controls.type != 0) {
        func = epitrochoid;
    }

    var lo = createVector(0, 0);
    var hi = createVector(0, 0);
    for (var i = 0; i < 360 * N; i++) {
        var v = func(R, r, d, radians(i));
        lo.x = min(lo.x, v.x);
        lo.y = min(lo.y, v.y);
        hi.x = max(hi.x, v.x);
        hi.y = max(hi.y, v.y);
    }
    var w = hi.x - lo.x;
    var h = hi.y - lo.y;
    var sx = (width * 0.8) / w;
    var sy = (height * 0.8) / h;
    var s = min(sx, sy);

    stroke(0, 255, 0);
    strokeWeight(4);
    strokeJoin(ROUND);
    beginShape();
    for (var i = 0; i < 360 * N; i++) {
        var v = func(R, r, d, radians(i));
        vertex(v.x * s, v.y * s);
    }
    endShape(CLOSE);
}