Deployable kirigami

Draw closed-loop cutting pattern that deploys into a 3D shape when a load is applied perpendicularly to the surface.

Log in to post a comment.

Canvas.setpenopacity(1);

const turtle = new Turtle();
// adjust to fit canvas
let scale = 1; // min=0, max=10, step=0.1

// ----------------------
// PARAMETERS
// ----------------------
// number of sections
let part = 8; // min=2, max=50, step=2

// total circles
let circle_number = 30; // min=1, max=50, step=1

// starting radius
let R_min = 15; // min=1, max=50, step=1

// spacing
let spacing = 2; // min=1, max=50, step=0.5

// Initial epsilon for first circle
let overlap = 5; // min=1, max=50, step=1

// ----------------------
// Examples slope functions

let mode = 1; // min=1, max=4, step=1

if (mode == 1) {
    // constant slope
    function D_slope(n) { return overlap; }
} else if (mode == 2) {
    // linear increase
    function D_slope(n) { return 0.5*overlap + n * 0.3; }
} else if (mode == 3) {
    // linear decrease
    function D_slope(n) { return 0.25*overlap - n * 0.1; }
} else {
    // sinusoidal variation
    function D_slope(n) { return overlap * (1 + 0.4 * Math.sin(n / 4)); }
}


// ----------------------
// DRAW ARC FUNCTION
// ----------------------
function draw_arc(radius, start, end) {
    const steps = 20;
    const step = (end - start) / steps;

    for (let k = 0; k <= steps; k++) {
        let angle = start + k * step;
        let x = scale * radius * Math.cos(angle);
        let y = scale * radius * Math.sin(angle);

        if (k === 0) {
            turtle.penup();
            turtle.goto(x, y);
            turtle.pendown();
        } else {
            turtle.goto(x, y);
        }
    }
}

// ----------------------
// WALK FUNCTION
// ----------------------
function walk(i) {
    if (i > 0) return false; // draw only once

    let r = R_min;

    for (let n = 0; n < circle_number; n++) {

        // Compute epsilon for this circle
        let overlap = D_slope(n);

        // Compute radius increment from slope equation
        if (n === 0) delta_r = 0; // first circle doesn't grow

        let start = 0;
        let end = start + 2 * Math.PI / part;
        let start2 = end;
        let end2 = start2 + 2 * Math.PI / part;

        for (let j = 1; j <= part; j++) {
            if (n % 2 === 0) {
                draw_arc(r, start - overlap / r, end + overlap / r);
            } else {
                draw_arc(r, start2 - overlap / r, end2 + overlap / r);
            }

            start = end + 2 * Math.PI / part;
            end = start + 2 * Math.PI / part;
            start2 = end2 + 2 * Math.PI / part;
            end2 = start2 + 2 * Math.PI / part;
        }

        // Update radius according to slope equation
        r += spacing;
    }

    return false;
}