Rotating wired cube

Random walks on cube (with rotations)

Log in to post a comment.

const seed = 1100; // min=1, max=2000, step=1
const N = 250; // min=10, max=1000, step=1
const min_step = 0.005;
const phi_x = -35.0; // min=-180.0, max=180.0, step=0.1
const phi_y = 35.0; // min=-180.0, max=180.0, step=0.1
const phi_z = 25.0; // min=-180.0, max=180.0, step=0.1

Canvas.setpenopacity(-1);

const dash = 2.0;

const t = new Turtle();

const verts = [[-1, -1, -1], [-1, -1, +1], [-1, +1, +1], [-1, +1, -1],
               [+1, -1, -1], [+1, -1, +1], [+1, +1, +1], [+1, +1, -1]];

const edges = [[0, 1], [1, 2], [2, 3], [3, 0],
               [4, 5], [5, 6], [6, 7], [7, 4],
               [0, 4], [1, 5], [2, 6], [3, 7]];

const faces = [[3, 0, 1, 2], [4, 7, 6, 5], [1, 0, 4, 5], [2, 1, 5, 6], [3, 2, 6, 7], [0, 3, 7, 4]];

let cur_rand = seed;
function rand() { cur_rand = (cur_rand * 48271) % (2**31 - 1); return cur_rand; }
function rand_float() { return rand() / (2**31 - 1); }
function rand_bool() { return (rand() % 2 == 0); }

function deg2rad(x) { return x / 180.0 * Math.PI}

function plus(v1, v2) { return [v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]]; }
function minus(v1, v2) { return [v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]]; }
function mul(v, scale) { return [v[0] * scale, v[1] * scale, v[2] * scale] }
function len(v) { return Math.sqrt(v[0]**2 + v[1]**2); }
function cross(v1, v2) { return [v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0]]; }
function rotate(v, phi) { return [v[0] * Math.cos(phi) + v[1] * Math.sin(phi), -v[0] * Math.sin(phi) + v[1] * Math.cos(phi)]; }

function draw_cube(dx, dy, dz, scale, phi_x, phi_y, phi_z) {
    let v = [];
    
    for (let i = 0; i < verts.length; i++) {
        let vi = verts[i];
        let [x, y, z] = vi;
        
        [x, y, z] = mul([x, y, z], scale);
        
        [y, z] = rotate([y, z], phi_x);
        [x, z] = rotate([x, z], phi_y);
        [x, y] = rotate([x, y], phi_z);

        [x, y, z] = plus([x, y, z], [dx, dy, dz]);
        
        v[i] = [x, y, z];
    }
    
    let f_invisible = [];
   
    let v_invisible = [];
    for (let i = 0; i < verts.length; i++) {
        v_invisible[i] = true;
    }
    
    for (let i = 0; i < faces.length; i++) {
        let f = faces[i];
        let v1 = v[f[0]], v2 = v[f[1]], v3 = v[f[2]], v4 = v[f[3]];
        
        let v12 = minus(v2, v1), v13 = minus(v3, v1);
        let n = cross(v12, v13);
        
        f_invisible[i] = (n[2] < 0);
        
        for (let j = 0; j < f.length; j++) {
            v_invisible[f[j]] &&= f_invisible[i];
        }
    }
    
    let e_invisible = [];
    for (let i = 0; i < edges.length; i++) {
        let e = edges[i];
        
        e_invisible[i] = v_invisible[e[0]] || v_invisible[e[1]]
    }
    
    for (let i = 0; i < edges.length; i++) {
        let e = edges[i];
        let v1 = v[e[0]], v2 = v[e[1]];
        
        if (e_invisible[i]) {
            if (! v_invisible[e[0]]) {
                [v1, v2] = [v2, v1]
            }
            
            let v12 = minus(v2, v1)
            let L = len(v12)
            let dx = v12[0] / L * dash, dy = v12[1] / L * dash
            
            for (let x = v1[0], y = v1[1], cL = 0; cL <= L - dash; cL += 2 * dash, x += 2 * dx, y += 2 * dy) {
                t.jump(x, y)
                t.goto(x + dx, y + dy)
            }
        }
        else {
            t.jump(v1[0], v1[1])
            t.goto(v2[0], v2[1])
        }
    }


    let traj = [];
    traj[0] = [0, rand_float(), rand_float()];
    
    let prev_dir = rand() % 4; // 0 -- left, 1 -- up, 2 -- right, 3 -- down
    const stepx = [-1, 0, 1, 0];
    const stepy = [0, -1, 0, 1];

    for (let i = 1; i <= N; i++) {
        let new_dir = rand_bool() ? ((prev_dir + 1) % 4) : ((prev_dir + 3) % 4);
        
        //let new_step = min_step + (max_step - min_step) * rand_float();
        
        let maxs = (new_dir == 0) ? traj[i - 1][1] : ((new_dir == 1) ? (traj[i - 1][2]) : ((new_dir == 2) ? (1 - traj[i - 1][1]) : (1 - traj[i - 1][2])))
        let new_step = min_step + rand_float() * (maxs - min_step);
        
        traj[i] = [0, traj[i - 1][1] + stepx[new_dir] * new_step, traj[i - 1][2] + stepy[new_dir] * new_step];
        
        prev_dir = new_dir;
    }
    
    
    const gap = 0.02;
    
    let segm = [];
    
    segm.push([[traj[0][1], traj[0][2]], [traj[1][1], traj[1][2]]]);
    
    for (let i = 2; i <= N; i++) {
        let p1x = traj[i - 1][1], p1y = traj[i - 1][2];
        let p2x = traj[i][1], p2y = traj[i][2];
        
        if (p1x == p2x) {
            let px = p1x;
            [p1y, p2y] = [Math.min(p1y, p2y), Math.max(p1y, p2y)];
            
            let y = [];
            
            for (let s of segm) {
                if (s[0][1] == s[1][1]) {
                    let sy = s[0][1];
                    let sx1 = Math.min(s[0][0], s[1][0]), sx2 = Math.max(s[0][0], s[1][0]);
                    
                    if ((sx1 < px) && (px < sx2) && (p1y < sy) && (sy < p2y)) {
                        y.push(sy)
                    }
                }
            }
            
            if (y.length > 0) {
                y.sort((a, b) => a - b);
                
                if (p1y < y[0] - gap) {
                    segm.push([[px, p1y], [px, y[0] - gap]])
                }
                
                for (let j = 1; j < y.length; j++) {
                    if (y[j - 1] + gap < y[j] - gap) {
                        segm.push([[px, y[j - 1] + gap], [px, y[j] - gap]])
                    }
                }

                if (y[y.length - 1] + gap < p2y) {
                    segm.push([[px, y[y.length - 1] + gap], [px, p2y]])
                }
            }
            else {
                segm.push([[px, p1y], [px, p2y]])
            }
        }
        else {
            let py = p1y;
            [p1x, p2x] = [Math.min(p1x, p2x), Math.max(p1x, p2x)];
            
            let x = [];
            
            for (let s of segm) {
                if (s[0][0] == s[1][0]) {
                    let sx = s[0][0];
                    let sy1 = Math.min(s[0][1], s[1][1]), sy2 = Math.max(s[0][1], s[1][1]);
                    
                    if ((sy1 < py) && (py < sy2) && (p1x < sx) && (sx < p2x)) {
                        x.push(sx)
                    }
                }
            }
            
            if (x.length > 0) {
                x.sort((a, b) => a - b);
                
                if (p1x < x[0] - gap) {
                    segm.push([[p1x, py], [x[0] - gap, py]])
                }
                
                for (let j = 1; j < x.length; j++) {
                    if (x[j - 1] + gap < x[j] - gap) {
                        segm.push([[x[j - 1] + gap, py], [x[j] - gap, py]])
                    }
                }

                if (x[x.length - 1] + gap < p2x) {
                    segm.push([[x[x.length - 1] + gap, py], [p2x, py]])
                }
            }
            else {
                segm.push([[p1x, py], [p2x, py]])
            }
        }
    }

    for (let i = 0; i < faces.length; i++) {
        if (! f_invisible[i]) {
            let i1 = faces[i][0], i2 = faces[i][1], i3 = faces[i][3]
            
            let x0 = v[i1][0], y0 = v[i1][1];
            let ax = v[i2][0] - v[i1][0], ay = v[i2][1] - v[i1][1];
            let bx = v[i3][0] - v[i1][0], by = v[i3][1] - v[i1][1];
        
            for (let s of segm) {
                t.jump(x0 + s[0][0] * ax + s[0][1] * bx, y0 + s[0][0] * ay + s[0][1] * by);
                t.goto(x0 + s[1][0] * ax + s[1][1] * bx, y0 + s[1][0] * ay + s[1][1] * by);
            }
        }
    }
}

draw_cube(0, 0, 0, 55, deg2rad(phi_x), deg2rad(phi_y), deg2rad(phi_z))