Creating an array of vectors in a line

Hello! I’m new here, hopefully this is the right place to ask.

I have an odd problem I’m trying to resolve. attempting to curve off a tutorial and turn the project into something of my own.

The problem being; I have a series of lines, creating a unique curved line. however these lines were created by translating the screen to 0, -len (10 in this case) to make the positioning of the lines easier. (not too difficult, but the screen was also rotated.)

The problem I’ve been working on for a while now is attempting to instead of using lines, turn the program into one that instead creates a shape using vertices, and draws the stroke. The code is a mess, but here’s what I’ve got so far.

import processing.pdf.*;

void setup() {
  //set xpos and ypos here so they're not set each loop later.
  float xpos = 1;
  float ypos = 1;

  size(1200, 600);
  beginRecord(PDF, "collatz.pdf");
  background(0);
  //This loop is just for looks right now, not using until one line works
  //the loop will create multiple lines.
  for (int i = 1; i < 100; i++) {

    IntList sequence = new IntList();
    //n = value for the line to process, will be set to i once working. 2000 for testing purposes
    int n = 2000;
    do {
      //sequence is an arraylist used to store the collatz results for n
      sequence.append(n);
      //collatz class defined below runs the collatz conjecture
      n = collatz(n);
    } while (n != 1);
    sequence.append(1);
    //reversing sequence to draw from one instead of 2000
    sequence.reverse();

    //len defines length of individual line segments (will be distance between vertices)
    int len = 5;
    //angle from previous vertex
    float angle = 0;
    float weight = 10;
    PVector vec;

    resetMatrix();
    //points are moving below the screen, set 0 to middle to view temporarily
    translate(width/2, height/2);

    //creates the rules for moving points based off odd or even numbers
    for (int j = 1; j < sequence.size(); j++) {
      int value = sequence.get(j);
      if (weight >= .2) {
        weight -= .2;
      }
      float rand = radians(noise(i));

      if (value % 2 == 0) {


        angle -= rand;
      } else {


        angle += rand;
      }
      //create a new pvector (vec) using starting xpos and ypos
      vec = new PVector(xpos, ypos);
      println(vec);
      //rotate the vector based on the angle determined above
      vec.rotate(angle);
      //thought normalizing and multiplying would give a point further out (as defined by mult())?
      vec.normalize();
      println(vec);
      vec.mult(-100);
      stroke(255);
      strokeWeight(weight);
      //using lines for debugging purposes while trying to get the code to work without transform
      line(xpos, ypos, vec.x, vec.y);
      //set xpos to vec.x and ypos to vec.y to move forward on the line
      xpos = vec.x;
      ypos = vec.y;
    }
  }
  endRecord();
}

int collatz(int n) {
  //even
  if (n%2==0) {
    return n/2;
  } else {
    //odd
    return (n * 3 + 1)/2;
  }
}

Any thoughts/advice?

All credit for the vast majority of this code to Mr. Daniel Shiffman and his very helpful videos

This is very achievable.

For starters:

Examples that come with Processing:

Explore away!

One of the best tools in a programmer’s tool chest is knowing the resources available to you and learning to navigate, filter, and use them.

A short list of resources to peruse:

Resources < Click here to expand !

Explore the resources available here:

I made these gears with PVectors, shapes, and vertices:
Planetary Gears < Visual example (no code).

:)

1 Like

Appreciate the response! I’ll check out your links and gears once I’m back from work.

The main issue I’m running into is being able to rotate a vector and get the position of the end of the vector instead of the beginning.

example:

. < – top of vector, I need to get this position after rotating the vector
| <-- vector
. <-- where the vector is created

I’ve searched and delved into the pvector reference and can’t seem to find an example that uses vectors for this purpose.

Going for a long hike…

My original example:

There is a good discussion of vectors here:
https://natureofcode.com/book/chapter-1-vectors/
https://processing.org/tutorials/pvector/

:)

1 Like

So if I’m reading that correctly, I may be able to create a shape using two vertices, then rotate that shape to the heading of the vector, then get the top vertex x and y to apply to the next vector?

This is getting complicated, just wanting to make sure I’m not going in the wrong direction.

And it will… keep it simple and work through PShapes and PVectors and then merge the two.

You just have to invest time in this.

This is just an example of creating a shape using vertices where the vertices are PVectors:

Example < Open here!
float rot = 0.0;
PVector v1, v2, v3, v4, v5;

void setup() 
  {
  size(500, 500);
  noSmooth();
  }
  
void draw()
  { 
  background(0);  
  translate(width/2, height/2);
  strokeWeight(5);
  strokeCap(ROUND);
  stroke(255, 255, 0);  
  v1 = new PVector(0, 0);  
  v2 = new PVector(0, 150);
  v3 = new PVector(150, 150);  
  v4 = new PVector(150, 0); 

  rot = map(mouseX, 0, width, -PI, +0);
  v1.rotate(rot);
  v2.rotate(rot);
  v3.rotate(rot);
  v4.rotate(rot); 

  //debugging
  println(v4);
  String s = str(v4.x) + "  " + str(v4.y);
  text(s, v3.x, v3.y);
  
  noFill();
  beginShape();
  vertex(v1.x, v1.y);
  vertex(v2.x, v2.y);
  vertex(v3.x, v3.y);
  vertex(v4.x, v4.y);
  endShape(CLOSE);
  
  line(v2.x, v2.y, -width/2, -height/2);
  }

Use println() statements to help you see what the variables are:
println() / Reference / Processing.org to show on console
or
text() / Reference / Processing.org to display on canvas

Keep in mind that there is always more than one way of doing things; you will learn that as you progress.

:)

1 Like

So here’s where I’m at right now. Working on a test script for debugging/figuring this out.

I have a script that can create an array of lines, but the main issue I’m having is it actually getting the proper x and y after rotation. (or maybe it’s not actually rotating, I’m not sure.)

ArrayList<Lines> lines;
float rot = 0.0;
Lines test = new Lines(0, 0, 0, 50, rot);

void setup() {
  size(1920, 1080);
  background(0);
  lines = new ArrayList<Lines>(1000);
}

void draw() {
  stroke(255);
  strokeWeight(2);
  //test.createShape();
  for (int i = 0; i < 100; i++) {
    rot = radians(i);
    lines.add(i, new Lines(0 + i, 0 + i, 0, 100 + i, rot));
    lines.get(i).createShape().rotate(rot);
    beginShape();
    for (int j = 0; j < lines.get(i).createShape().getVertexCount(); j++) {
      vertex(lines.get(i).createShape().getVertexX(j), lines.get(i).createShape().getVertexY(j));
    }
    endShape();
    shape(lines.get(i).createShape());
    println(lines.get(i).createShape().getVertexCount());
  }
}

class Lines {
  
  float x1, x2, y1, y2, rot;
  PShape shapey = new PShape();
  
  Lines(float x1_, float x2_, float y1_, float y2_, float rot_){
    x1 = x1_;
    x2 = x2_;
    y1 = y1_;
    y2 = y2_;
    rot = rot_;
    shapey.beginShape();
    shapey.vertex(x1, y1);
    shapey.vertex(x2, y2);
    shapey.endShape();
    shapey.rotate(90);
    
    
  }
  
  PShape createShape(){
    return shapey;
  }
  
}

I also tried using your example but for a 2 vertex object, but couldn’t get the rotation to work there.

from what I’m seeing in the processing reference this should be working, so I must be missing something here.

Hello,

I have not looked at your recent post.

An exploration from the other day:

POINTS version
float angle = 0;
int steps = 10;

PVector vec;

void setup() 
  {
  size(600, 600);
  background(0);
  stroke(255, 255, 0);
  strokeWeight(2);
 
  translate(width/2, height/2);
  
  vec = new PVector(1, 1);

  for (int j = 0; j < steps; j++) 
    {
    angle = TAU/steps;
    vec.normalize();
    vec.rotate(angle);
    vec.mult(-100);  // Try 100 and -100
    
    beginShape(POINTS);     
    vertex(vec.x, vec.y);
    endShape();       
    }
  } 
LINES version
float xposLast;
float yposLast;
 
float angle = 0;
int steps = 10;

PVector vec;

void setup() 
  {
  //noSmooth();
  size(600, 600); 
  background(0);
  
  stroke(255,255, 0);
  strokeWeight(2);
 
  translate(width/2, height/2);
  
  vec = new PVector(1, 1);
  vec.normalize();
  vec.mult(100);
  xposLast = vec.x;
  yposLast = vec.y;  

  for (int j = 0; j < steps; j++) 
    {
    angle = TAU/steps;
    vec.normalize();
    vec.rotate(angle);
    vec.mult(-100);  // Try 100 and -100
    
    stroke(255, 255, 0);
    strokeWeight(2);
    
    //line(vec.x, vec.y, xposLast, yposLast);

    beginShape(LINES);      
    vertex(vec.x, vec.y);
    vertex(xposLast,yposLast);
    endShape();      
    
    xposLast = vec.x;
    yposLast = vec.y;      
    }
  }    

I broke it into two versions for POINTS and LINES.

Any examples provided are meant for insight only; explore and scrutinize them and work on your project. That is my disclaimer. :)

Pleased to see you are working at this… that is why I shared my examples.

Each step will bring you closer.

:)

1 Like

Found the solution in a random coding train video, ended up using sin and cos instead of vectors. for some reason it’s way easier.

For anyone Curious, here’s the code.

float len = radians(10);

void setup(){
  size(800, 800);
  translate(width/2, height/2);
  beginShape();
  for(int i = 0; i < 10; i++){
   float inc = i * cos(len) * 50;
   float inc2 = i * sin(len) * 50;
   strokeWeight(2);
   vertex(inc, inc2);
   len += radians(90);
  }
  endShape();
}

void draw(){
  
}

Thanks for the help glv. Appreciate you <3

I’ll post the resulting image once it’s integrated into the main code.

And the end result, after running the collatz conjecture on 20,000 numbers, and converting each number sequence generated into a line with a right rotating segment for odds, and left rotating segment for evens.

I added a small noise value for rotation on each segment of the above image, for artistic value. For mathematical purity, the below image is lacking the randomness.

https://drive.google.com/file/d/1BBlNbC4dDWzPyn0DoxHYDo74pQVnWBpu/view?usp=sharing

I recommend downloading the files for full effect, the pdf is made of vectors so is infinitely zoomable.

The bit of code that ended up driving it was this:


      if (j > 0) {
        points.add(new PVector(points.get(j - 1).x + j * sin(angle) * -.1, points.get(j - 1).y + j * cos(angle) * -.1));
      } else {
        points.add(new PVector(j * sin(angle), j * cos(angle)));
      }

in a nested loop of i and j, where i creates the sequences, and j goes through them creating a vector in an arrayList using that vector. The trick here was getting the previous vector and adding it to the sin and cos functions which resulted in the long calculation. Could store the previous point in a variable for cleanliness, but I like seeing the maths.

2 Likes