fartagaintuxedo
fartagaintuxedo

Reputation: 749

Custom draw line function, why does coordinate orientation slow down the program?

I am writting my own draw line function in processing to improve speed when drawing large sets of lines from vector file (just a .txt with a bunch of coordinates that draw the map of seville). I am using the method pixel[int] to build such function but for some reason that i can not explain the program goes really fast when i enter the coordinates like this: drawline(y1,x1,y2,x2) but quite slow when its how its supposed to be: drawline(x1,y1,x2,y2) Is there a logical explanation for this?

The structure of the .txt code is simple and it goes like this (the full .txt file can be downloaded from folder):

1188156570;1188156570;37.417595;-5.9971519
1188156400;1188156400;37.4175115;-5.9970483
1188156720;1188156720;37.4174588;-5.9969338
1188156606;1188156606;37.4175833;-5.9966021
1188156462;1188156462;37.4177174;-5.9960534
1188156753;1188156753;37.4177413;-5.9958605
1188156643;1188156643;37.417703;-5.9955831
1132983943;1132983943;37.4176646;-5.995381
next
304791377;304791377;37.3968538;-6.0066269
1188156644;1188156644;37.3967509;-6.0064412
1188156521;1188156521;37.3956275;-6.0073602
next
1188216699;1188216699;37.4221365;-5.9959761
693311201;693311201;37.4253619;-5.9951655
1188216625;1188216625;37.4239123;-5.9924734
1188216567;1188216567;37.4233085;-5.9916937
1186512382;1186512382;37.4223597;-5.9910465
1188216642;1188216642;37.4216335;-5.9927836
1188216699;1188216699;37.4221365;-5.9959761
next

Below is the code of the Processing 1.5.1 sketch, i have shortened it as much as possible and made it as tidy as I could. Thanks for the help!

String[] polylines;
String[] streetArray=new String[0];
String[] empty=new String[0];
ArrayList vlist=new ArrayList();
float panX; float panY;

void setup() {
  size(600, 600);
  polylines=loadStrings("data/MapSeville.txt");
  panX=0; panY=0;
  prepare();
}

void draw() {
  background(255);
  PVector pan = pan();
  panX=panX+pan.x;
  panY=panY+pan.y;

  loadPixels();
  for(int i=0;i<vlist.size();i++){
    vertexgroup vg= (vertexgroup) vlist.get(i);
    for(int j=1;j<vg.listcoord.size();j++){
      Vertice v2=(Vertice) vg.listcoord.get((j-1));
      Vertice v1=(Vertice) vg.listcoord.get(j);
      float x1=v1.coord.x+panX;
      float y1=v1.coord.y+panY;
      float x2=v2.coord.x+panX;
      float y2=v2.coord.y+panY;
      drawline(x1, y1, x2, y2);//slow :( comment out this line and enable the next to see how smooth it can go
      //drawline(y1, x1, y2, x2);//fast!
    }
  } 
  updatePixels();
}

////////////////////////////// functions ////////////////////////////////////////////////

PVector pan(){
  PVector p;
  if (mousePressed){
    p = new PVector(mouseX-pmouseX, mouseY-pmouseY);
  }else{
    p=new PVector(0,0);
  }
  return p;
}

////////////////////

void drawline(float x1, float y1, float x2, float y2){
  int X1=int(x1);
  int X2=int(x2);
  color pink = color(0);
    if((X2>X1)){
      for (int i=0; i<=int(x2-x1); i++){ 
        if (((i+X1)>=0)&&((i+X1)<=width)){
          int g=int(y1+((y2-y1)/(x2-x1))*i)*(width) + i + X1;
          if ((g<width*height)&&(g>=0)){
            pixels[g]=pink;
          }
        }
      }
    }else if((X2<X1)){
      for (int i=0; i<=int(x1-x2); i++){
        if (((i+X2)>=0)&&((i+X2)<=width)){
          int f=int(y2+((y2-y1)/(x2-x1))*i)*(width) + i + X2;
          if ((f<width*height)&&(f>=0)){
            pixels[f]=pink; 
        }
      }
    }  
  }
}

//////////////////////////////

 void prepare(){
  for (int i=1;i<polylines.length;i++) {
    String[] pts = split(polylines[i], ";");

    if (pts.length>3) {
      streetArray=append(streetArray, polylines[i]); //adds coords strings to the array streetArray
    }
    if (pts.length==1) { //this is when the coords of a polyline ends: pts[0]==>"next" 
        vertexgroup vgroup;
        vgroup=new vertexgroup(create_polyArr(streetArray)); // this function is defined right below
        vlist.add(vgroup);
        streetArray=empty;
    }}}

    ArrayList create_polyArr(String[] streetpts) {
    ArrayList arrpts=new ArrayList();
    arrpts.clear();

    for (int i=0;i<streetpts.length;i++){ //iterates through coords strings of the polyline contained in streetpts
      String[] pts = split(streetpts[i], ";");
      float x=float(pts[3]);//get the x coord
      float y=float(pts[2]);//get the y coord
      x=((x+5.95)*15000+width/2);//scale and center coord x
      y=((-y+37.40)*15000+height/2);//scale and center coord y
      PVector coord=new PVector(x,y);
      Vertice govertex=new Vertice(coord);
      arrpts.add(govertex);
    }
    return(arrpts);
  }

 ////////////////////// end functions //////////////////////////////////

 //////////////////////// classes ///////////////////////////////////////

 class vertexgroup{

  ArrayList listcoord;

  vertexgroup(ArrayList _listcoord){
    listcoord=_listcoord;
  }}

  //////////

  class Vertice{

  PVector coord;

  Vertice(PVector _coord){
    coord=_coord;
  }}

  ////////////////////// end classes ///////////////////////////////////////

Upvotes: 0

Views: 569

Answers (1)

George Profenza
George Profenza

Reputation: 51837

Unfortunately I don't have as much time as I'd want to dig deep into this and do not have a complete and accurate answer to your question, but I do have a few observations and suggestions that might help.

You're code is actually not bad and runs smoothly outside of the browser. Depending on how you want this to work there are few suggestions, from the simpler to the more complex:

  1. Simply use a different renderer: size(600,600,P2D). I've noticed I get ~35fps with JAVA2D and ~60fps with P2D
  2. You're clearing pixels and redrawing all the time. You could create a large PGraphics or PImage (depending on how you prefer to draw) and draw the full map once in setup, then use mapGraphics.draw(0,0); or mapImage.draw(0,0); in draw(). Imagine there is a maximum image size though. Somewhat similar you can explore a texture atlas solution with OpenGL which should be pretty fast
  3. I haven't tested, but have you tried using the .svg format which you can use in Processing via PShape ?

Long story short: either use a different renderer and/or 'cache' the drawing instructions rather than redrawing continuously.

If you have the time and want to figure out where the different in speed might come from, you can launch jvisualvm from command line/terminal and profile/compare CPU usage snapshots.

One final note:

I'm getting the same frame rate (by calling fill(0);text((int)frameRate+" fps",10,20); or frame.setTitle((int)frameRate+" fps"); with both versions.

Could it be that you simply get different panning speeds/amounts ?

Upvotes: 1

Related Questions