# Making lines converge to a point

Hi,
I’m working on my n-th mini project. I would like to have multiple parallel lines pointing to mouse position on a click. Here’s the code I wrote:

``````//introducing vectors
PVector vMouse, u, w;

//introducing arrays
//of integers, to store coordinates
int[] xA;
int[] yA;
int[] yB;

//and of vectors, to draw the lines
PVector[] v1;
PVector[] v2;

void setup() {
size(640, 370);
background(255);

//setting arrays' length
xA = new int[width/10];
yA = new int[height/20];
yB = new int[height/20];

v1 = new PVector[xA.length];
v2 = new PVector[xA.length];

//setting x coordinates for the lines
for (int i = 0, j = 0; i < width; i += 10) {
xA[j] = i + 10;
j++;
}

//setting a couple of y coordinates for the lines
for (int i = 10, j = 0; i < height; i += 20) {
yA[j] = i;
yB[j] = i + 10;
j++;
}

//based on coordinates previously set up,
//I define a bunch of vectors
for (int i = 0; i < width/10; i ++) {
for (int j = 0; j < height/20; j++) {
v1[i] = new PVector(xA[i], yA[j]);
v2[i] = new PVector(xA[i], yB[j]);
}
}
}

void draw() {
if (mousePressed == true) {
background(255);

//defining a vector going from origin to mouse position
vMouse = new PVector(mouseX, mouseY);

//using a for loop to cycle through the arrays of coordinates
for (int i = 0; i < width/10; i ++) {
for (int j = 0; j < height/20; j++) {

//copying the vector going from origin to (xA, yB)
u = v2[i].copy();
//copying the mouse position vector
w = vMouse.copy();
//finding the difference between vectors:
//u - v1
u.sub(v1[i]);

//finding the magnitude of u
float m = u.mag();

//finding the difference between vectors:
//w - v1
w.sub(v1[i]);

//finding w's unit length
w.normalize();

//and multiplying it by u's magnitude
//to have the same lengths
w.mult(m);

//then shifting the origin
translate(v1[i].x, v1[i].y);
//and drawing the line to the expected coordinates
line(0, 0, w.x, w.y);
}
}

//if mouse is not pressed
} else {
background(255);

//I use a for cycle to go through the arrays of coordinates
for (int i = 0; i < width/10; i ++) {
for (int j = 0; j < height/20; j++) {
//and draw the lines based on the coordinates
line(xA[i], yA[j], xA[i], yB[j]);
}
}
}
}
``````

Now, it seems all ok except for the fact that only 1 line is pointing to mouse position (by the way, why just that line on the lower left??). I guess the point is on lines 82 to 85

``````        //then shifting the origin
translate(v1[i].x, v1[i].y);
//and drawing the line to the expected coordinates
line(0, 0, w.x, w.y);
``````

where I shift the origin to draw the lines; I can’t figure out how to make the lines simultaneously rotate towards mouse position. Any idea?

HI,
you re really close (;
problem is certainly in the part of code you highlight:
if you compare inside the loop for mousepressed or not, there is a major difference
unpressed you just draw lines, mouse pressed you move inside you drawing area with translate before every line
(good news is certainly all your lines are draw but certainly out of screen)

two ways to fix that, or remove this translate mouvement and draw as when mouse is unpressed, or a good oportunity to play with pushMatrix(); / popMatrix

Hi,

The `translate()` function is cumulative, so if you call it several times in a row it just adds up on top of each other so most of your line are drawn out of the screen space.

To avoid this, use the push() and pop() functions. They act like save and load functions: `push()` save the current transformation matrix and `pop()` restore the transformation matrix.

In practice, if you wrap your `translate()` in between them, it won’t add up the transformation:

``````...

push();
translate(v1[i].x, v1[i].y);
pop();

...
``````

To be honest I had a hard time going through your code and instead of deep diving into it I thought about sharing a piece of code that does exactly the same thing but, I think, in a simpler manner. I hope it can be useful to you:

``````//Parameters
final int nbOfCols = 64;
final int nbOfRows = 16;
final int lineLen = 10;

//Helping variables
float xSpacing, ySpacing;

void setup() {
size(640, 370);

//Compute the spacing in the x and y directions
xSpacing = (float)width / (nbOfCols + 1);
ySpacing = (float)height / (nbOfRows + 1);

//Set the style
stroke(225);
strokeWeight(1);
}

void draw() {
background(20);

//Loop through each columns and row
for (int i = 0; i < nbOfCols; i++) {
for (int j = 0; j < nbOfRows; j++) {
//Find the center of the segment
float cx = (i + 1) * xSpacing;
float cy = (j + 1) * ySpacing;

//Call drawLine function with or without a target point depending if mouse is pressed or not
if (mousePressed) {
drawLine(cx, cy, new PVector(mouseX, mouseY));
} else {
drawLine(cx, cy, null);
}
}
}
}

void drawLine(float cx, float cy, PVector toPoint) {
//If mouse is not pressed, lines are verticals so the angle should be PI/2 (angle 0 is vector pointing right)
float angle = HALF_PI;

//If a target point is defined, find the angle from the center of the line to draw to the target point
if (toPoint != null) {
PVector dir = new PVector(toPoint.x - cx, toPoint.y - cy);
}

//Translate and rotate as needed
push(); //DO NOT FORGET
translate(cx, cy);
rotate(angle - HALF_PI);

//Draw the line
line(0, -lineLen / 2.0, 0, lineLen / 2.0);
pop(); //DO NOT FORGET
}
``````
2 Likes