Attracted lines

Experimenting with attractors - bis.

Log in to post a comment.

// You can find the Turtle API reference here: https://turtletoy.net/syntax
Canvas.setpenopacity(0.5);

const size = 160;                   //min = 100, max = 200, step = 1
//const lines = 40;                   //min = 1, max = 250, step = 1
const hLines = 00;                  //min = 0, max = 250, step = 1
const vLines = 120;                  //min = 0, max = 250, step = 1
const randomLines = 0;             //min = 0, max = 1000, step = 1

//const force = 30;                 // min = -200, max = 200, step = 1
const attractors = 3;               //min = 1, max = 50, step = 1
const attractorsFieldSize = 120;    //min = 40, max = 200, step = 1

const resolution = 0.1; //min = 0.01, max = 1, step = 0.01

// help function to compute the distance from a point (i.e., the hypothenuse of a triangle rectangle)
function distance(x, y){
    return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}

// An attractor is a point which deflects drawing. It has a position and a force.
class Attractor{
    constructor(x = 0, y = 0, force = 0){
            this.x = x;
            this.y = y;
            this.force = force;
            
            if( x == 0 && y == 0 && force == 0){
            this.x = Math.random() * attractorsFieldSize - attractorsFieldSize / 2;
            this.y = Math.random() * attractorsFieldSize - attractorsFieldSize / 2;
            this.force = Math.random() * 200;
        }
    }
}

class Line{
    constructor(a, b, c, d, att){
        this.xs = a;
        this.ys = b;
        this.xe = c;
        this.ye = d;
        this.attractors = att;
        
        this.turtle = new Turtle();
        this.turtle.jump(a, b);
        
        this.deltaX = c - a;
        this.deltaY = d - b;
        
        this.x = a;
        this.y = b;
        
        this.index = 0;
        this.limit = size / resolution;
        
        this.incX = this.deltaX / this.limit;
        this.incY = this.deltaY / this.limit;
    }
    
    walk(){
        
        this.x = this.xs + this.incX * this.index;
        this.y = this.ys + this.incY * this.index;
        
        if(this.attractors){
            let delta;
            let coef;
            
            for(let item of this.attractors){
                let deltaX = this.x - item.x;
                let deltaY = this.y - item.y;
        
                delta = distance(deltaX, deltaY);
                coef = Math.pow(item.force/delta, 2);
            
                let moveX = (deltaX / delta) * coef;
                let moveY = (deltaY / delta) * coef;
                
                let dist = distance(moveX, moveY);
                
                if(dist > delta){
                    moveX = deltaX;
                    moveY = deltaY;
                }

                this.x -= moveX;
                this.y -= moveY;
            }
        }
        
//        this.x += this.incX;
//        this.y += this.incY;
        if(this.index == 0) this.turtle.jump(this.x, this.y)
        else this.turtle.goto(this.x, this.y);
        
        
        if(this.index++ < this.limit) return true;
        return false;
    }
}

// generate random attractors.
const attractorList = [];

for(let i = 0; i < attractors; i++){
    attractorList.push(new Attractor());
}

const lineList = [];

// Start with horizontal Lines
for(let i = 0; i < hLines; i++){
    let delta = size / (hLines - 1);
    lineList.push(new Line(-size/2, -size/2 + i * delta, size/2, -size/2 + i * delta, attractorList));
    // push random lines

}

// Then vertical lines
for(let i = 0; i < vLines; i++){
    let delta = size / (vLines - 1);
    lineList.push(new Line(-size/2 + i * delta, -size/2, -size/2 + i * delta, size/2, attractorList));
}

//random lines ?
for(let i = 0; i < randomLines; i++){
    let delta = size / (randomLines - 1);
    
    let a, b, c, d;
/*    
    if(Math.random() < 0.5){
        a = -size / 2;
        b = Math.random() * size - size / 2;
        c = size / 2;
        d = Math.random() * size - size / 2;
    } else {
        a = Math.random() * size - size / 2;
        b = -size / 2;
        c = Math.random() * size - size / 2;
        d = size / 2;
    }
    
    lineList.push(new Line(a, b, c, d, attractorList));
*/
    let p = [];
    
    p.push(-size / 2);
    p.push(Math.random() * size -size / 2);
    p.push(size / 2);
    p.push(Math.random() * size -size / 2);
    
    let rand = Math.random();
    
    // Choose one quadrant for starting the line
    if(rand < 0.25){
//        [p[0], p[2]] = [p[2], p[0]];          // no change : x is fixed and <0, y is random
    } else if(rand < 0.5){
        [p[0], p[1]] = [p[1], p[0]];            // x-y swap : x is random, y is fixed and < 0
    } else if(rand < 0.75){
        [p[0], p[2]] = [p[2], p[0]];            // x is fixed and > 0, y is random
    } else {
        [p[0], p[2]] = [p[2], p[0]];            // x is random, , y is fixed and > 0
        [p[0], p[1]] = [p[1], p[0]];
    }
    
    // Then once the line is started it can land on the opposite side, or on an adjacent side.
    if(Math.random() < 0.5) [p[2], p[3]] = [p[3], p[2]];

    lineList.push(new Line(p[0], p[1], p[2], p[3], attractorList));

}


// The walk function will be called until it returns false.
function walk(i) {
    let goOn = true;
    for(let item of lineList){
        goOn = item.walk();
    }
    return goOn;
}