Multiple line graphs


#1

Hi all - with the much appreciated help from TfGuy44, i managed to develop the below. which is great and very useful. I have decided however to go in a slightly different direction and want to view my data in the form of a terrain. there would be essentially 5 red coloured lines and 5 blue coloured lines. with a white line running down the middle. the lines would be going from right to left (new data points appearing at the right hand side - this may be a good place to start) and the visualisation would be rotated slightly on the x axis. Viewing this way i think will give it greater context.

Thanks in advance for any help.

Jared

color[] colors = { 
  color(0, 0, 255, 200), 
  color(255, 0, 0, 200), 
  color(255, 255, 255, 200), 
  color(255, 255, 255, 0) 
}; 
int[] bases = {
  35, 
  35, 
  30,
  50
};

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h, int type) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = bases[type];
    sy = h;
    c = colors[type];
  }
  void draw() {
    strokeWeight(1);
    pushMatrix();
    noStroke();
    translate(px, py, pz);
    translate(0, -sy/2, 0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();
float a =0;
int b = 1;
int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;
float atX = 0;
float atZ = 0;
boolean toggleLoop = true;

void setup() {
  size(1000, 2000, P3D);
  noStroke();
}

void draw() {
  background(0);

  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
 rotateX(map(mouseY, 0, height, -PI, PI));
  translate(0, 0, atZ-offset);
  
  for ( int i = 0; i< sbs.size(); i++) {
    sbs.get(i).draw();
  }
   
  if ( offset > 60 ) {
    atZ -= 60;
    offset %= 60;
    for ( int i = 0; i < 9; i++) {
      sbs.add( 0, new SingleBar(60*i+140, height/3, -atZ, random(60, 300), 0) );
      sbs.add( 0, new SingleBar(-60*i-140, height/3, -atZ, random(60, 300), 1) );
              }                
    sbs.add( 0, new SingleBar(0, height/3, -atZ, random(0, 75), 2) );
   
   }
  println(offset);
  offset+=OFFSET_SPEED;
  a = a+.05;
  b=b+1;
  if (-175+a > -125){
    a = 0;
  }
}
void mousePressed() {
  if (mouseButton == LEFT) {
    if (toggleLoop) { noLoop(); toggleLoop = false; }
    else { loop(); toggleLoop = true; }
  } }

#2

Sorry if I’m misunderstanding something, but what’s your question? Which part of this are you stuck on?

Please read this guide, which will help you ask a question that’s a little easier for us to help you with:


#3

Hey Kevin - thanks for pointing that out, i should have articulated my questions more clearly, let me re phrase.

  1. for the below code i am unsure on the following section,for some reason i cant understand what this is actually doing. how does the offset variable control the speed of the loop? why are we concerned with the offset not being larger than 60? also - the %=, i get what this does, just not how it helps?

if( offset > 60 ){
atZ -= 60;
offset %= 60;

  1. being new to processing i cant get my head around how the visualisation is constructed. i cant get the big picture. essentially, i think in each loop i am creating a “SingleBar” and storing it the “sbs” array. we then draw this array using the below. however - how does the new point always appear at the front if we are translating along the z axis before we draw the objects?
 translate(0,0,atZ-offset);
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
  }
  1. when i insert println(sbs.size())… the size of the array only increases after every 10 loops and the first 10 loops doesn’t add any objects to the list - why is this?

As always, thanks for your help. As i improve my processing skills i hope to start contributing to helping others.

Thanks

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = 60;
    sy = h;
    c = color( random(255), random(255), random(255) );
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0,-sy/2,0);
    fill(c);
    box(sx, sy, sz);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();//SingleBar[10];
int offset = 0;
final int OFFSET_SPEED = 6;
final int MAX_BARS = 300;
float atX = 0;
float atZ = 0;

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {
  if( sbs.size() > MAX_BARS ){
    sbs.remove(sbs.size()-1);
  }
  background(0);
  translate(width/2, height/2);
  lights();
  rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
  //rotateX(map(mouseY, 0, height, -PI, PI));
   println(atZ);
   
  if( offset > 60 ){
    atZ -= 90;
    offset %= 60;
    for( int i = -1; i < 2; i+=2){
      sbs.add( 0, new SingleBar(30*i, 170, -atZ, random(60,300)) );
    }
  }
   translate(0,0,atZ-offset);
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
  }
  offset+=OFFSET_SPEED;
}

#4

You need:
offset+=OFFSET_SPEED;

Now this can be explained. Offset is increased by 6 in every iteration. When offset is larger than 60, two things happen:

  • altZ is reduced by 60
  • offset is reset to the modulo of offset by 60… aka if offset is 61 then 61%1=1. Modulo is the reminder of the division. You can find a better explanation in the reference.

Question 1 down, two to go.

Kf


#5

Thank you - very helpful. and that answers question 3.

that just leaves questions two - the line that really throws me is - translate(0,0,atZ-offset); im not sure how translating before you print each of the objects in the array works.

cheers


#6

That translate is there to make sure that you follow along with the new bars as they are created.

If you comment out that line, you stay at the first bar.

If you remove the -offset from it, you “jump” to the latest bar added as it is added.

The atZ part makes you move along with the latest bars. The -offset part makes it a smooth transition.


#7

Thank you mate - the light globe just went off and i think i finally get it.

thanks to everyone that helped.

ive tried to apply this to a separate problem and again am coming up short. I dont want to waste anyone’s time but if you could point me in the right direction it would be greatly appreciated.

re the below - the objects now move right to left and a much slower speed. i have changed the perspective but am still working on that. what i want to do is connect each box/rectangle using a line. it will help the user view how the current point is related to past points. how would i do this?

thanks

color[] colors = { 
  color(0, 0, 255, 200), 
  color(255, 0, 0, 200), 
  color(255, 255, 255, 200), 
  color(255, 255, 255, 0) 
};

class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  color c;
  SingleBar(float ipx, float ipy, float ipz, float h, int type) {
    px = ipx;
    py = ipy;
    pz = ipz;
    sx = sz = 10;
    sy = h;
   c = colors[type];
  } 
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    translate(0,-sy/2,0);
    fill(c);
    box(5, sz, 0);
    popMatrix();
  }
}

ArrayList<SingleBar> sbs = new ArrayList();

int offset = 0;
final int OFFSET_SPEED = 1;
float atX = 0;
float atZ = 0;

void setup() {
  size(600, 400, P3D);
  noStroke();
}

void draw() {

  background(0);
  translate(width, height/2);
  lights();
 //rotateY(-map(mouseX, 0, width, -HALF_PI, HALF_PI));
 //rotateX(map(mouseY, 0, height, -PI, PI));
   println(atZ);
   
  if( offset > 20 ){
    atZ -= 20;
    offset %= 20;
    for( int i = -1; i < 1; i+=2){
      sbs.add( 0, new SingleBar(-atZ, 120, 20*i, random(60,300),1) );
      
    }
  }
  rotateX(-PI/3);
//rotateY(-PI/10);
    float cameraY = height/2.0;
  float fov = 500/float(width) * PI/2;
  float cameraZ = cameraY / tan(fov / 2.0);
  float aspect = float(width)/float(height);
  if (mousePressed) {
    aspect = aspect / 2.0;
  }
  perspective(fov, aspect, cameraZ/10.0, cameraZ*10.0);
    //rotateX(-PI/4);
 // rotateY(PI/3);
   translate(atZ-offset,0,0);
  for( int i = 0; i< sbs.size(); i++){
    sbs.get(i).draw();
  }
  offset+=OFFSET_SPEED;
}

#8

I had a go myself and almost got there. the offset isn’t working exactly how i want. the graph is updating in each loop but the object is disappearing to the left of screen instead of updating in the middle of the box.

thanks in advance. appreciate everyones time.

cheers

int[] x1 = {
  10, 
  20, 
  30,
  40,
  50,
  60,
  70
};

int[] y1 = {
  10, 
  -20, 
  30,
  -20,
  50,
  -60,
  70
};


class SingleBar {
  float px, py, pz;
  float sx, sy, sz;
  float x1,x2,y1,y2;
  color c;
  SingleBar(float ipx1, float ipy1, float ipx2, float ipy2, float ipx) {
    px = ipx;
    py = 0;
    pz = 0;
    x1 = ipx1;
    y1 = ipy1;
    x2 = ipx2;
    y2 = ipy2;
    c = (250);
  }
  void draw() {
    pushMatrix();
    translate(px, py, pz);
    //translate(0,-sy/2,0);
    fill(c);
    line(x1, y1, x2,y2);
    popMatrix();
      }
}
ArrayList<SingleBar> sbs = new ArrayList();
float offset = 0;
final float OFFSET_SPEED = 1;
float atX = 0;
float atZ = 0;
boolean toggleLoop = true;
int a = 0;
int b = 0;
void setup() {
  size(900, 900);
  background(0);
  }

void draw() {
  b++;
  background(0);
  translate(width/2, height/2);
  stroke(250,0,0);
  

// println(sbs.size());
//println(atZ);
  if ( offset > 60 ) {
    atZ -= 60;
    offset %= 60;
    a++;
     for(int i = 0; i<1;i++){
    sbs.add( 0, new SingleBar(x1[a+1], y1[a+1],x1[a],y1[a] , -atZ) );
     }
     
    if (a > 4){
      a = 0;
    }
  }
  
  
  translate(atZ-offset, 0);
  for ( int i = 0; i< sbs.size(); i++) {
      sbs.get(i).draw();
  //line(1, 2, 100, 2); 
  
}
    
  offset+=OFFSET_SPEED;
}

#9

Just solved it.

thanks everyone for your help. have a good weekend