### Attracted lines

Experimenting with attractors - bis.

```// 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 = [];

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;
}```