Random walker through points

Hi there,

I am working on a random walker through points, and I am struggling to get the next closest point in the walker class.

The idea is to have one or few random walkers going from point to point until there is no point left.

void update(ArrayList<Anchor> anchors) {
    if (anchors.size()>0) {
      int idx = getNearest(anchors);
      println(""+idx);
      Anchor a = anchors.get(idx);
      PVector move = a.pos;
      previousPos.set(pos);
      pos.add(move);
      anchors.remove(idx);
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 1000;
    int idx = 0;
    for (int i = 0; i >= anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < record) {
        dist = record;
        idx = i;
      }
    }
    return idx;                                 // give index of nearest target
  }

It seem that the int idx never really update in the int getNearest(ArrayList anchors) function

Bellow the complete code;

ArrayList<Walker> walkers;
ArrayList<Anchor> anchors;


PVector pos;

int walkerCount = 1;
int anchorCount = 500;
float x = 0;
float y = 0;

void setup() {
  size(800, 800);
  background(51);
  frameRate(60);
  
  walkers = new ArrayList<Walker>();
  anchors = new ArrayList<Anchor>();
  
  for (int i = 0; i < walkerCount; i++) {
    PVector origin = new PVector(random(width), 0);
    walkers.add(new Walker(origin, color(random(256), random(256), random(256))));
  }
  for (int i = 0; i < anchorCount; i++) {
    PVector position = new PVector(random(width), random(height));
    anchors.add(new Anchor(position));
  }
}

void draw() {

  for (int i = 0; i < walkers.size(); i++) {
    Walker w = (Walker) walkers.get(i);
    w.update(anchors);
    w.show();
    
  }

  for (int i = 0; i < anchors.size(); i++) {
    Anchor a = (Anchor) anchors.get(i);
    a.show();
  }
}

class Walker {
  PVector pos;
  PVector previousPos;
  color col;


  Walker(PVector position, color c) {
    col = c;
    pos = new PVector(position.x, position.y);
    previousPos = pos.copy();
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    //point(pos.x, pos.y);
    line(previousPos.x, previousPos.y, pos.x, pos.y);
  }

  void update(ArrayList<Anchor> anchors) {
    if (anchors.size()>0) {
      int idx = getNearest(anchors);
      println(""+idx);
      Anchor a = anchors.get(idx);
      PVector move = a.pos;
      previousPos.set(pos);
      pos.add(move);
      anchors.remove(idx);
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 1000;
    int idx = 0;
    for (int i = 0; i >= anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < record) {
        dist = record;
        idx = i;
      }
    }
    return idx;                                 // give index of nearest target
  }
}


class Anchor {
  PVector pos;
  color col;


  Anchor(PVector position) {
    col = color(0);
    pos = new PVector(position.x, position.y);
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    point(pos.x, pos.y);
  }

  void update() {
  }
}

I am very grateful for any advice,

Many thanks

1 Like

that’s wrong; I think you want i < anchors.size() (think do this as long as)

Chrisir

1 Like

you had several minor errors

  • look at this line in getNearest: dist = record; !!!

  • also look at pos.add(move); in method update() in class Walker

1 Like

Thank you Chrisir, that right, and I also spotted that I didn’t sub the target with the pos. Thank you for your input.

  void update(ArrayList<Anchor> anchors) {
    if (anchors.size()>0) {
      int idx = getNearest(anchors);
      println(""+idx);
      Anchor a = anchors.get(idx);
      PVector target = a.pos;
      PVector move = target.sub(pos);
      previousPos.set(pos);
      pos.add(move);
      anchors.remove(idx);
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 1000;
    int idx=0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < 10) {
        if (dist < record) {
          dist = record;
          idx = i;
          if (idx == 0){break;}
        }
      }
    }
    return idx; 

I am getting closer to the desired solution :); A problem remains when the walker doesn’t find a smaller distance, the index becomes zero, so the walker jumps to the next zero of the list.

Furthermore, I am trying to stop the process if;

  • the walker doesn’t find a point close enough
  • the walker has to jump on another walker path

I would like to implement this kind of code on a mesh later on

thank you again :slight_smile:

1 Like

that is still wrong!!!

Please read again the section

That right, my bad! (still a beginner)

int getNearest(ArrayList<Anchor> anchors) {
    float record = 1000;
    int idx=0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < 50) {
        if (dist < record) {
          record = dist;
          idx = i;
          //if (idx == 0){break;}
        }
      }
    }
    return idx;   

Would you know a method to stop the waker should the point being too far?

thank you

1 Like

I think this was VERY important

here is my version (without stopping)



ArrayList<Walker> walkers;
ArrayList<Anchor> anchors;

PVector pos;

int walkerCount = 1;
int anchorCount = 500;

float x = 0;
float y = 0;

void setup() {
  size(800, 800);
  background(51);
  // frameRate(6);

  walkers = new ArrayList<Walker>();
  anchors = new ArrayList<Anchor>();

  for (int i = 0; i < walkerCount; i++) {
    PVector origin = new PVector(random(width), 0);
    walkers.add(new Walker(origin, color(random(256), random(256), random(256))));
  }

  for (int i = 0; i < anchorCount; i++) {
    PVector position = new PVector(random(width), random(height));
    anchors.add(new Anchor(position));
  }
}//setup()

void draw() {
  //  background(51);

  for (int i = 0; i < walkers.size(); i++) {  // for (Walker w : walkers) {  !!!!!!!!!!!!!!!!!!!!!!!
    Walker w = walkers.get(i);  // (Walker) walkers.get(i);
    w.update(anchors);
    w.show();
  }

  for (int i = 0; i < anchors.size(); i++) {
    Anchor a = anchors.get(i); // (Anchor) anchors.get(i);
    a.show();
  }
}//draw()

// ===========================================================================

class Walker {
  PVector pos;
  PVector previousPos;
  color col;

  Walker(PVector position, color c) {
    col = c;
    pos = position.copy(); //  new PVector(position.x, position.y);
    previousPos = pos.copy();
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    //point(pos.x, pos.y);
    line(previousPos.x, previousPos.y, 
      pos.x, pos.y);
  }

  void update(ArrayList<Anchor> anchors) {

    if (anchors.size()>0) {
      int idx = getNearest(anchors);
      println(""+idx);
      Anchor a = anchors.get(idx);
      PVector move = a.pos;
      previousPos.set(pos);

      /*
      float targetX = move.x;
       float dx = targetX - pos.x;
       pos.x += dx ; //  * easing;  
       
       float targetY = move.y;
       float dy = targetY - pos.y;
       pos.y += dy ; // * easing; 
       */

      // pos.add(move);
      pos=move.copy(); 
      anchors.remove(idx);
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 10000;
    int idx = 0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < record) {
        record = dist;  // YOU HAD  dist = record;   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        idx = i;
      }
    }
    return idx;    // give index of nearest target
  }
}

// ===========================================================================

class Anchor {
  PVector pos;
  color col;

  Anchor(PVector position) {
    col = color(0);
    pos = new PVector(position.x, position.y);
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    point(pos.x, pos.y);
  }

  void update() {
  }
}
//

here is a version that stops.

We return -1 (not an allowed index!) to indicate failure when dist > 86 or so

Then we evaluate idx and abort update in Walker class

ArrayList<Walker> walkers;
ArrayList<Anchor> anchors;

PVector pos;

int walkerCount = 1;
int anchorCount = 500;

float x = 0;
float y = 0;

void setup() {
  size(800, 800);
  background(51);
  // frameRate(6);

  walkers = new ArrayList<Walker>();
  anchors = new ArrayList<Anchor>();

  for (int i = 0; i < walkerCount; i++) {
    PVector origin = new PVector(random(width), 0);
    walkers.add(new Walker(origin, color(random(256), random(256), random(256))));
  }

  for (int i = 0; i < anchorCount; i++) {
    PVector position = new PVector(random(width), random(height));
    anchors.add(new Anchor(position));
  }
}//setup()

void draw() {
  //  background(51);

  for (int i = 0; i < walkers.size(); i++) {  // for (Walker w : walkers) {  !!!!!!!!!!!!!!!!!!!!!!!
    Walker w = walkers.get(i);  // (Walker) walkers.get(i);
    w.update(anchors);
    w.show();
  }

  for (int i = 0; i < anchors.size(); i++) {
    Anchor a = anchors.get(i); // (Anchor) anchors.get(i);
    a.show();
  }
}//draw()

// ===========================================================================

class Walker {
  PVector pos;
  PVector previousPos;
  color col;

  Walker(PVector position, color c) {
    col = c;
    pos = position.copy(); //  new PVector(position.x, position.y);
    previousPos = pos.copy();
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    //point(pos.x, pos.y);
    line(previousPos.x, previousPos.y, 
      pos.x, pos.y);
  }

  void update(ArrayList<Anchor> anchors) {

    if (anchors.size()>0) {
      int idx = getNearest(anchors);

      if (idx<0) 
        return;  // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

      println(""+idx);
      Anchor a = anchors.get(idx);
      PVector move = a.pos;
      previousPos.set(pos);

      /*
      float targetX = move.x;
       float dx = targetX - pos.x;
       pos.x += dx ; //  * easing;  
       
       float targetY = move.y;
       float dy = targetY - pos.y;
       pos.y += dy ; // * easing; 
       */

      // pos.add(move);
      pos=move.copy(); 
      anchors.remove(idx);
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 10000;
    int idx = 0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < record) {
        record = dist;  // YOU HAD  dist = record;   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        idx = i;
      }
    }
    if (record<86) 
      return idx;    // give index of nearest target
    else 
    return -1;
  }
}

// ===========================================================================

class Anchor {
  PVector pos;
  color col;

  Anchor(PVector position) {
    col = color(0);
    pos = new PVector(position.x, position.y);
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    point(pos.x, pos.y);
  }

  void update() {
  }
}
//
2 Likes

I know shame on me ;(

This is excellent thank you,

I will try to find some way to let start new walker when one die, get the walker to aim toward a direction, and not crossing the tail of another walker.

Thank you for your help.

You can make here:

if (idx<0) {
    alive=false; 
    return; // !!!
}

when alive is a boolean inside the walker class

Then make a for loop to remove walkers with !alive (NOT alive), this for loop must go backward by the way

for(int i=walkers.size()-1; i>=0; i--) {
    Walker w=walkers.get(i); 
    if(!alive) 
        w.remove();
}

3D version ================================

HERE is a 3D version:


ArrayList<Walker> walkers;
ArrayList<Anchor> anchors;
ArrayList<Line> lines= new ArrayList<Line>();

PVector pos;

int walkerCount = 1;
int anchorCount = 1500;

float x = 0;
float y = 0;

float a; 

void setup() {
  size(1800, 900, P3D);
  background(51);

  //frameRate(69);

  walkers = new ArrayList<Walker>();
  anchors = new ArrayList<Anchor>();

  for (int i = 0; i < walkerCount; i++) {
    PVector origin = new PVector(random(4, 400), 4);
    walkers.add(new Walker(origin, color(random(256), random(256), random(256))));
  }

  for (int i = 0; i < anchorCount; i++) {
    PVector position = new PVector(random(-400, 400), random(4, height-4), random(-800, 800));
    anchors.add(new Anchor(position));
  }
}//setup()

void draw() {
  background(51);
  lights();

  translate(width/2, 0); 
  rotateY(a);
  a+=0.01; 

  for (Line l : lines) {
    l.show();
  }

  for (Walker w : walkers) {  // !!!!!!!!!!!!!!!!!!!!!!!
    w.update(anchors);
    w.show();
  }

  for (int i = 0; i < anchors.size(); i++) {
    Anchor a = anchors.get(i); // (Anchor) anchors.get(i);
    a.show();
  }
}//draw()

// ===========================================================================

class Walker {
  PVector pos;
  PVector previousPos;
  color col;

  // for lerp
  float amt;
  float amtAdd = 0.1;   
  boolean running=false;
  PVector move; 

  // ID of anchor
  int idx;

  Walker(PVector position, color c) {
    col = c;
    pos = position.copy(); 
    previousPos = pos.copy();
  }

  void show() {

    /*
    strokeWeight(2);
     stroke(col);
     point(pos.x, pos.y, pos.z);
     */

    pushMatrix();
    translate(pos.x, pos.y, pos.z);
    noStroke();
    fill(col);
    sphere(14);
    popMatrix(); 

    /*
    strokeWeight(1);
     noFill();
     stroke(col); 
     ellipse(pos.x, pos.y, 8, 8);
     */


    /*
    strokeWeight(4);
     stroke(col);
     line(previousPos.x, previousPos.y, pos.x, pos.y);
     */
  }

  void update(ArrayList<Anchor> anchors) {

    //using lerp() !!! 

    if (anchors.size()>0) {

      if (running) {
        // lerping to the new pos
        pos.x=lerp(previousPos.x, move.x, amt);
        pos.y=lerp(previousPos.y, move.y, amt);
        pos.z=lerp(previousPos.z, move.z, amt);

        amt+=amtAdd;//.1;
        if (amt>1) {
          lines.add(new Line(previousPos, move)); 
          //reset 
          amt=0; 
          running=false;
          anchors.remove(idx);
        }
      } else {
        // find the new position and prepare lerp
        running=true; 

        idx = getNearest(anchors);
        // println(""+idx);

        Anchor a = anchors.get(idx);
        move = a.pos.copy();
        previousPos.set(pos);

        amtAdd = 1 / move.dist(pos) ;  
        amtAdd*=3; 
        // amtAdd = .5; 

        // pos.add(move); // WRONG 
        //pos=move.copy(); // OKAY
      }
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 100000;
    int idx = 0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < record) {
        record = dist; 
        idx = i;
      }
    }
    return idx;    // give index of nearest target
  }
}

// ===========================================================================

class Anchor {
  PVector pos;
  color col;

  Anchor(PVector position) {
    col = color(0);
    pos = position.copy();
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    point(pos.x, pos.y, pos.z);
  }

  void update() {
  }
}
//======================================================================================================

class Line {
  PVector f;
  PVector t;
  Line(PVector f_, PVector t_) { 
    f=f_.copy(); 
    t=t_.copy();
  }

  void show() {
    Walker w = walkers.get(0);
    stroke(w.col);
    line(f.x, f.y, f.z, 
      t.x, t.y, t.z );
  }
}//class
//
2 Likes

Here, you blow my mind hehe,
Thank you, I will update :slight_smile:

The 3D idea will not work with your plans to stop a walker when crossing another line though

Better stay 2D…

See Vector math for line-to-line intersection

1 Like

Hi Chrisir, thank you for your advice. I like what the lerp() does to the motion.

My goal is to uses this logic to fill 3d Mesh. Here is the version I updated, there is probably still some problem but, it is already very interesting.

ArrayList<Walker> walkers;
ArrayList<Anchor> anchors;
ArrayList<Line> lines= new ArrayList<Line>();

PVector pos;

int walkerCount = 1;
int anchorCount = 1500;

float x = 0;
float y = 0;

float a; 

void setup() {
  size(800, 800);
  background(51);

  frameRate(60);

  walkers = new ArrayList<Walker>();
  anchors = new ArrayList<Anchor>();

  for (int i = 0; i < anchorCount; i++) {
    PVector position = new PVector(random(width), random(height));
    anchors.add(new Anchor(position));
  }

  for (int i = 0; i < walkerCount; i++) {
    int idx = (int)random(anchors.size());
    Anchor origin = anchors.get(idx);
    PVector originVec = origin.pos;
    walkers.add(new Walker(originVec, color(random(256), random(256), random(256))));
    anchors.remove(idx);
  }
}

void draw() {
  background(51);

  for (int i = 0; i < anchors.size(); i++) {
    Anchor a = anchors.get(i); // (Anchor) anchors.get(i);
    a.show();
  }

  for (int i = walkers.size()-1; i >= 0; i--) {
    Walker w = walkers.get(i);


    w.update(anchors);
    w.show();

    if (w.alive == false && walkers.size() <= walkerCount) {
      addWalker(anchors);
      walkers.remove(i);
    }
    println("walkers"+walkers.size());
  }

  for (Line l : lines) {
    l.show();
  }
}//draw()

// ===========================================================================

void addWalker(ArrayList<Anchor> anchors) {
  int idx = (int)random(anchors.size());
  Anchor o = anchors.get(idx);
  PVector originVec = o.pos;
  walkers.add(new Walker(originVec, color(random(256), random(256), random(256))));
  anchors.remove(idx);
}

// ===========================================================================

class Walker {
  PVector pos;
  PVector previousPos;
  color col;

  // for lerp
  float amt;
  float amtAdd = 0.1;   
  boolean running = false;
  boolean alive;
  PVector move; 

  // ID of anchor
  int idx;


  Walker(PVector position, color c) {
    alive = true;
    col = c;
    pos = position.copy(); 
    previousPos = pos.copy();
  }

  void show() {

    pushMatrix();
    noStroke();
    fill(col);
    ellipse(pos.x, pos.y, 8, 8);
    popMatrix();
  }

  void update(ArrayList<Anchor> anchors) {

    if (anchors.size() > 0) {


      if (running) {

        idx = getNearest(anchors);
        pos.x = lerp(previousPos.x, move.x, amt);
        pos.y = lerp(previousPos.y, move.y, amt);

        amt += amtAdd;//.1;

        if (amt > 1) {
          lines.add(new Line(previousPos, pos, col)); 
          amt = 0; //reset 
          running = false;
          
        }
      } else {
        // find the new position and prepare lerp
        running=true; 

        idx = getNearest(anchors);
        // println(""+idx);

        if (idx < 0) {
          alive = false;
          return;
        }

        Anchor a = anchors.get(idx);
        move = a.pos.copy();
        previousPos.set(pos);

        amtAdd = 1 / move.dist(pos) ;  
        amtAdd*=3;
        anchors.remove(idx);
      }
    }
  }

  int getNearest(ArrayList<Anchor> anchors) {
    float record = 100000;
    int idx = 0;
    for (int i = 0; i < anchors.size(); i++) {
      Anchor anchor = anchors.get(i);
      float dist = pos.dist(anchor.pos);
      if (dist < 30) {
        if (dist < record) {
          record = dist; 
          idx = i;
        }
      }
    }
    if (record<30) 
      return idx;    // give index of nearest target
    else 
    return -1;
  }
}

// ===========================================================================

class Anchor {
  PVector pos;
  color col;

  Anchor(PVector position) {
    col = color(0);
    pos = position.copy();
  }

  void show() {
    strokeWeight(4);
    stroke(col);
    point(pos.x, pos.y);
  }

  void update() {
  }
}

// ===========================================================================

class Line {
  PVector f;
  PVector t;
  color col;
  
  Line(PVector f_, PVector t_, color inCol){ 
    f=f_.copy(); 
    t=t_.copy();
    col = inCol;
  }

  void show() {
    stroke(col);
    strokeWeight(3);
    line(f.x, f.y, t.x, t.y );
  }
}

Thank’s again.

2 Likes

lights(); are often nice in 3D

There is a bigger 3D line https://github.com/Kango/3DSketches/wiki

Do you know Peasycam? It allows you to look freely on a 3D sculpture

2 Likes

Just discover it now, it’s all new to me, I am a grasshopper user by trade. I’ll try it later for sure!

1 Like