# Drawing array of curves from PVector

**URL:** <https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775>\
**Category:** Coding Questions\
**Created:** [November 26, 2021, 8:36pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775 "2021-11-26T20:36:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [November 26, 2021, 8:36pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/1 "2021-11-26T20:36:16Z")

</div>

Hi friends! I am trying to draw an array of curves from PVector coordinates.  
Basically it is similar to [Particle system tutorial](https://www.youtube.com/watch?v=vdgiqMkFygc&ab_channel=TheCodingTrain), just instead of points, I need to get curves.

I try to use begin shape (in class Particle), storing x,y coordinates in arraylists, but I am getting an error while iterating over the ArrayList ( **NullPointException** ).

Heeeeeeeeeeeeeeeeeeeelp :[

```auto
ArrayList<ParticleSystem> systems;

void setup() {
  size(640, 360);
  systems = new ArrayList<ParticleSystem>();
}

void draw() {
  background(0);
  for (ParticleSystem ps : systems) {
    ps.run();
    ps.addParticle();
  }
  if (systems.isEmpty()) {
    fill(255,255,0);
  }
}

void mousePressed() {
  systems.add(new ParticleSystem(1, new PVector(mouseX, mouseY)));
}

// A simple Particle class

class Particle {
  PVector position;
  //ArrayList<PVector> position;
  PVector velocity;
  float vector_scale;
  float lifespan;
  
  FloatList xx;
  FloatList yy;
  ArrayList<FloatList> old_x;
  ArrayList<FloatList> old_y;

  Particle(PVector l) {
    float vector_scale = 0.05;//ector scaling factor, we want small steps
    
    FloatList xx = new FloatList();
    FloatList yy = new FloatList();
    ArrayList<FloatList> old_x = new ArrayList<FloatList>();
    ArrayList<FloatList> old_y = new ArrayList<FloatList>();
    
    // v is vector from the field
    float n = 3 * map(noise(l.x/155,l.y/155),0,1,-1,1); // 100, 300 or 1000
    velocity = new PVector(cos(n),sin(n));
    
    l.x += vector_scale * velocity.x;
    l.y += vector_scale * velocity.y;
    
    //velocity = new PVector(random(-1, 1), random(-2, 0)); //moving vector
    position = l.copy();
    
    
    
    lifespan = 100.0;
  }

  void run() {
    update();
    display();
  }

  // Method to update position
  void update() {
    position.add(velocity);
    
    lifespan -= 1.0;
  }

  // Method to display
  void display() {
    strokeWeight(2);
    stroke(255, lifespan);

    beginShape();
    
    for (int i = xx.size()-1; i <= 0; i--) {
      curveVertex(xx.get(i), yy.get(i));
    }
    endShape();
    // populate the x and y lists
    xx.append(position.x);
    yy.append(position.y);
    
  
    
  }

  // Is the particle still useful?
  boolean isDead() {
    return (lifespan < 0.0);
  }
}

// An ArrayList is used to manage the list of Particles

class ParticleSystem {

  ArrayList<Particle> particles; // An arraylist for all the particles
  PVector origin; // An origin point for where particles are birthed
  
  
  ParticleSystem(int num, PVector v) {
    particles = new ArrayList<Particle>(); // Initialize the arraylist
    origin = v.copy();  
    
    // Store the origin point
    for (int i = 0; i < num; i++) {
      particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
      
  }
  }

  void run() {
    // Cycle through the ArrayList backwards, because we are deleting while iterating
    for (int i = particles.size()-1; i >= 0; i--) {
      Particle p = particles.get(i);
      p.run();
      
      
      //println(XXorigin.get(i));
      stroke(255,0,0);
      strokeWeight(8);
      strokeJoin(ROUND);
      //point(XXorigin.get(i), YYorigin.get(i));
      //line(XXorigin.get(0), YYorigin.get(0), XXorigin.get(i), YYorigin.get(i));
      if (p.isDead()) {
        particles.remove(i);
      }
    }
  }

  void addParticle() {
    Particle p;
    // Add either a Particle or CrazyParticle to the system
    p = new Particle(origin);

    particles.add(p);
  }

  void addParticle(Particle p) {
    particles.add(p);
  }

  // A method to test if the particle system still has particles
  boolean dead() {
    return particles.isEmpty();
  }
}

```

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [November 26, 2021, 9:03pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/2 "2021-11-26T21:03:02Z")

</div>

change this

```auto
  FloatList xx;
  FloatList yy;
  ArrayList<FloatList> old_x;
  ArrayList<FloatList> old_y;

  Particle(PVector l) {
    float vector_scale = 0.05;//ector scaling factor, we want small steps
    
    FloatList xx = new FloatList();
    FloatList yy = new FloatList();
    ArrayList<FloatList> old_x = new ArrayList<FloatList>();
    ArrayList<FloatList> old_y = new ArrayList<FloatList>();

```

to this

```auto
  FloatList xx;
  FloatList yy;
  ArrayList<FloatList> old_x;
  ArrayList<FloatList> old_y;

  Particle(PVector l) {
    float vector_scale = 0.05;//ector scaling factor, we want small steps

    xx = new FloatList();
    yy = new FloatList();
    old_x = new ArrayList<FloatList>();
    old_y = new ArrayList<FloatList>();

```

also wouldn’t it be easier just to maintain an arraylist of PVectors instead of two seperate lists for each ordinate… just a thought.

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [November 27, 2021, 10:11am UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/3 "2021-11-27T10:11:55Z")

</div>

Thank you for your reply @hotfooted !

I also changed

> [@mrbro](#):
>
> ```auto
> for (int i = xx.size()-1; i <= 0; i--) {
> curveVertex(xx.get(i), yy.get(i));
> }
> 
> ```

to this:

```auto
for (int i = 0; i < xx.size(); i++) {
      curveVertex(xx.get(i), yy.get(i));
    }

```

And it started to work!

Thus, adding every new curve slows down the process by a lot! ☹

Also it produces a new curve form the starting point to every new coordinate. What I want is to draw 1 curve from the beginning, following every new coordinate. And repeat that for every new origin I add.

Maybe I need to do that in ParticleSystem Class instead? Or something wrong with the for loop?

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/9/9642e083335552908839c6ba34bd08a21f03d065.png)

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [November 27, 2021, 10:16pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/4 "2021-11-27T22:16:56Z")

</div>

you call

> ps.addParticle();

every draw

```auto
void draw() {
  background(0);
  for (ParticleSystem ps : systems) {
    ps.run();
    ps.addParticle();
  }
  if (systems.isEmpty()) {
    fill(255, 255, 0);
  }
}

```

but that function just adds another particle at the origin of that particle system

```auto
  void addParticle() {
    Particle p;
    // Add either a Particle or CrazyParticle to the system
    p = new Particle(origin);

    particles.add(p);
  }

```

so basically you end up drawing multiple curves from origin. remove that and you will have a single curve i believe.

edit: i think this is what you are aiming for yeh?

```auto
ArrayList<Particle> particles;

void setup() {
  size(640, 480);
  noFill();
  strokeWeight(2);
  particles = new ArrayList<Particle>();
}

void draw() {
  background(255);
  for(int i = particles.size() - 1; i >= 0; i--) {
    Particle p = particles.get(i);
    p.update();
    //if(p.pos.x < -100 || p.pos.x > width+100 || p.pos.y < -100 || p.pos.y > height+100)
      //particles.remove(i);
    p.present();
  }
}

void mousePressed() {
  Particle p = new Particle(mouseX, mouseY);
  p.addForce(random(-1, 1), random(-1, 1));
  particles.add(p);
}

class Particle {
  PVector pos;
  PVector vel;
  PVector acc;
  ArrayList<PVector> history;
  int maxHistory;
  float maxWander;
  float maxSpeed;
  
  Particle(float x, float y) {
      this.pos = new PVector(x, y);
      this.vel = new PVector();
      this.acc = new PVector();
      this.history = new ArrayList<PVector>();
      this.history.add(this.pos.copy());
      this.maxHistory = 50;
      this.maxWander = 45 * (PI / 180);
      this.maxSpeed = 2;
  }
  
  void addForce(float fx, float fy) {
    this.acc.x += fx;
    this.acc.y += fy;
  }
  
  void update() {
    //add some wander to the particle to make it more interesting
    float heading = this.vel.heading();
    heading += random(-this.maxWander, this.maxWander);
    this.addForce(cos(heading), sin(heading));
    
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.acc.mult(0);
    this.pos.add(this.vel);
    
    float dist = PVector.dist(this.pos, this.history.get(this.history.size() - 1));
    if(dist > 5) {
      this.history.add(this.pos.copy());
      if(this.history.size() > this.maxHistory) {
        this.history.remove(0);
      }
    }
  }
  
  void present() {    
    float k = (float)this.history.size();
    for(int i = 1; i < this.history.size(); i++) {
      stroke(0, (i / k) * 255);
      PVector p1 = this.history.get(i - 1);
      PVector p2 = this.history.get(i);
      line(p1.x, p1.y, p2.x, p2.y);
    }     
  }
}

```

it’s just you are repurposing code that has a lot of superfluous stuff for your goal making the situation a bit confusing

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [December 2, 2021, 7:40pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/5 "2021-12-02T19:40:35Z")

</div>

Thank you so much for your help :]

Your code is wonderful, but has totally different structure than mine.  
Could you please explain it a bit?  
For instance, if I want to map a big noise field to draw it on, or an image to follow, how can I apply it with this code?  
I tried to do that here, but it results in particles moving in circles.

```auto
    //add some wander to the particle to make it more interesting
    float heading = 2 * map(noise(this.acc.x/500,this.acc.y/500),0,1,-1,1);
    this.vel = new PVector(cos(heading),sin(heading));
    this.addForce(cos(heading), sin(heading));

```

Also, using **this** just made me so confused…

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [December 2, 2021, 9:19pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/6 "2021-12-02T21:19:23Z")

</div>

you basically have it correct. i was being lazy though and really the movement code should be removed from the particle update and instead the particles should be fed a force using the addForce method from outside. this whole thing follows Daniel’s work closely (for good reason 😉 ) so it might be worth checking out this video

[![](https://img.youtube.com/vi/XXEK3UEDDIg/maxresdefault.jpg "6.4: Steering Behaviors: Flow FIeld Following - The Nature of Code") ](https://www.youtube.com/watch?v=XXEK3UEDDIg)

and he might have actually made an updated version of that as well.  
further you can read more on his book The Nature of Code website [here](https://natureofcode.com/book/chapter-6-autonomous-agents/)

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [December 3, 2021, 10:52am UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/7 "2021-12-03T10:52:56Z")

</div>

Thank you again so much 🙂  
I am shy to ask more, you already helped a lot…

But I guess, if you say

> [@hotfooted](#):
>
> so basically you end up drawing multiple curves from origin. remove that and you will have a single curve i believe.

Then my main question is how can I put data from particles.add into run() function, without adding new particles?  
I guess the answer is somewhere in using “.this”?

```auto
class ParticleSystem {

  ArrayList<Particle> particles; // An arraylist for all the particles
  PVector origin; // An origin point for where particles are birthed
  FloatList xx;
  FloatList yy;

  ParticleSystem(int num, PVector v) {
    particles = new ArrayList<Particle>(); // Initialize the arraylist
    origin = v.copy(); // Store the origin point
    xx = new FloatList();
    yy = new FloatList();
    
    for (int i = 0; i < num; i++) {
      particles.add(new Particle(origin)); // Add "num" amount of particles to the arraylist
    }
  }

  void run() {
// Use origins of created particles here, witout creating new particles??
}
    
    

```

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [December 3, 2021, 11:32am UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/8 "2021-12-03T11:32:29Z")

</div>

have a read of [chapter 4](https://natureofcode.com/book/chapter-4-particle-systems/) of Daniel’s book. Nearer to the end of the chapter you should find your answer. best of luck!

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [December 7, 2021, 9:13pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/9 "2021-12-07T21:13:05Z")

</div>

Hi @hotfooted ! 🙂

I red and watched everything, and I finally understood your code!

However, when reviewing the created lines from

```auto
line(p1.x, p1.y, p2.x, p2.y);

```

It actually creates many many copies of the same line in the same place, so it does not create 1 constant vertex.  
Here take a look for one of them

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/0/01807f393300c6214674673645fb476b7fa93805.png)  
Is there a way to avoid it, to create one vertex from each origin, without making copies?

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [December 7, 2021, 10:14pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/10 "2021-12-07T22:14:34Z")

</div>

please show your code

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [December 8, 2021, 9:05am UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/11 "2021-12-08T09:05:17Z")

</div>

This is your code, minimally modified to just record pdf.  
It creates copies of lines in the same location with geometric progression, like so:

 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/1/1ce3dd4b715e0f9ed9741b28f1d742c23a58ce18.png)  
(the amount of lines visualized)

```auto
import processing.pdf.*;

ArrayList<Particle> particles;

void setup() {
  size(640, 480);
  noFill();
  strokeWeight(2);
  particles = new ArrayList<Particle>();
  beginRecord(PDF, "vector.pdf"); 
}

void draw() {
  background(255);
  for(int i = particles.size() - 1; i >= 0; i--) {
    Particle p = particles.get(i);
    p.update();
    p.present();
  }
  
  if (keyPressed) { 
   exit();
   saveFrame();  
   endRecord();
  }
  
}

void mousePressed() {
  Particle p = new Particle(mouseX, mouseY);
  p.addForce(random(-1, 1), random(-1, 1));
  particles.add(p);
}

class Particle {
  PVector pos;
  PVector vel;
  PVector acc;
  ArrayList<PVector> history;
  int maxHistory;
  float maxWander;
  float maxSpeed;
  
  Particle(float x, float y) {
      this.pos = new PVector(x, y);
      this.vel = new PVector();
      this.acc = new PVector();
      this.history = new ArrayList<PVector>();
      this.history.add(this.pos.copy());
      this.maxHistory = 50;
      this.maxWander = 45 * (PI / 180);
      this.maxSpeed = 2;
  }
  
  void addForce(float fx, float fy) {
    this.acc.x += fx;
    this.acc.y += fy;
  }
  
  void update() {
    float heading = this.vel.heading();
    heading += random(-this.maxWander, this.maxWander);
    this.addForce(cos(heading), sin(heading));
    
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.acc.mult(0);
    this.pos.add(this.vel);
    
    float dist = PVector.dist(this.pos, this.history.get(this.history.size() - 1));
    if(dist > 5) {
      this.history.add(this.pos.copy());
      if(this.history.size() > this.maxHistory) {
        this.history.remove(0);
      }
    }
  }
  
  void present() {    
    float k = (float)this.history.size();
    for(int i = 1; i < this.history.size(); i++) {
      stroke(0, (i / k) * 255);
      PVector p1 = this.history.get(i - 1);
      PVector p2 = this.history.get(i);
      line(p1.x, p1.y, p2.x, p2.y);
    }     
  }
}

```

---

<div class="post-metadata">

**Author:** ![mrbro](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/mrbro/32/8485_2.png) [@mrbro](https://discourse.processing.org/u/mrbro)\
**Post date:** [December 8, 2021, 8:31pm UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/12 "2021-12-08T20:31:05Z")

</div>

Adding this at the end of for loop in void present(0

```auto
this.history.remove(i-1)

```

Helps, but it creates separated lines one by one.

I am trying to create a vertex insted, but I cannot create vertex with history.remove(i-1)…

I tried using lerp as well, but this did not help

```auto
    noFill();
    beginShape();
    for(int i = 2; i < this.history.size(); i++) {
      //PVector p1 = this.history.get(i - 1);
      PVector p1 = this.history.get(i-1);
      PVector p2 = this.history.get(i);
      float x = lerp(p1.x, p2.x, 1);
      float y = lerp(p1.y, p2.y, 1);
      vertex(x,y);
      //this.history.remove(i-1); //remove previous origin
    }
    endShape();

```

---

<div class="post-metadata">

**Author:** ![hotfooted](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/hotfooted/32/3670_2.png) [@hotfooted](https://discourse.processing.org/u/hotfooted)\
**Post date:** [December 9, 2021, 12:41am UTC](https://discourse.processing.org/t/drawing-array-of-curves-from-pvector/33775/13 "2021-12-09T00:41:34Z")

</div>

the curve is made up of many line segments. each of which is created using pairs of vertices.

here i’ve increased the line segment length by increasing the distance between vertices. i have also highlighted each vertex with an ellipse.

```auto
ArrayList<Particle> particles;

void setup() {
  size(640, 480);
  noFill();
  strokeWeight(2);
  particles = new ArrayList<Particle>();
}

void draw() {
  background(255);
  for(int i = particles.size() - 1; i >= 0; i--) {
    Particle p = particles.get(i);
    p.update();
    //if(p.pos.x < -100 || p.pos.x > width+100 || p.pos.y < -100 || p.pos.y > height+100)
      //particles.remove(i);
    p.present();
  }
}

void mousePressed() {
  Particle p = new Particle(mouseX, mouseY);
  p.addForce(random(-1, 1), random(-1, 1));
  particles.add(p);
}

class Particle {
  PVector pos;
  PVector vel;
  PVector acc;
  ArrayList<PVector> history;
  int maxHistory;
  float maxWander;
  float maxSpeed;
  
  Particle(float x, float y) {
      this.pos = new PVector(x, y);
      this.vel = new PVector();
      this.acc = new PVector();
      this.history = new ArrayList<PVector>();
      this.history.add(this.pos.copy());
      this.maxHistory = 50;
      this.maxWander = 45 * (PI / 180);
      this.maxSpeed = 2;
  }
  
  void addForce(float fx, float fy) {
    this.acc.x += fx;
    this.acc.y += fy;
  }
  
  void update() {
    //add some wander to the particle to make it more interesting
    float heading = this.vel.heading();
    heading += random(-this.maxWander, this.maxWander);
    this.addForce(cos(heading), sin(heading));
    
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.acc.mult(0);
    this.pos.add(this.vel);
    
    float dist = PVector.dist(this.pos, this.history.get(this.history.size() - 1));
    //this controls the length of the line segments or the resolution if you like of the curve which is made up of line segments
    if(dist > 25) {
      this.history.add(this.pos.copy());
      if(this.history.size() > this.maxHistory) {
        this.history.remove(0);
      }
    }
  }
  
  void present() {    
    float k = (float)this.history.size();
    for(int i = 1; i < this.history.size(); i++) {
      stroke(0, (i / k) * 255);
      PVector p1 = this.history.get(i - 1);
      PVector p2 = this.history.get(i);
      ellipse(p2.x, p2.y, 8, 8);
      line(p1.x, p1.y, p2.x, p2.y);
    }     
  }
}

```

you can see the resolution of the curve is controlled by the distance between each vertex and the smaller the distance the smoother the curve. i feel like there is a misunderstanding on one or both of our ends. i cannot see where you are calculating that there is multiple lines drawn. if you could demonstrate how you arrive at that conclusion i can look further into it but until then i am unsure if there is an issue.

perhaps someone else will weigh in with a solution?
