Help with translation calculations

Hi guys, In this sketch, the user should be able to zoom in and out relative to the mouse's position. However the more you zoom in/out, the larger the error of translation there is. gif link: https://gyazo.com/bc19520eb98509299f9d0af9be548228

This is how I calculated the translation: trans += getStriplength() * deltascale getStriplength returns the length of the whole strip of objects while deltascale is the amount that is reduced each time when the mouse scrolls. Its default value is 0.2, which means the objects will be either 1.02 times bigger or 0.98 times smaller than the original. Therefore I am getting the difference of the lengths of the strip before and after, and adding it to the offset. However as I mentioned before it doesn't work the more you zoom in/out. Any help will be appreciated!

Code:

PImage backgroundImage;
PFont font;
int x = 0;
int xoffset = 0;
int deltax = 5;
float scale = 512/30;
float deltascale = 0.02;
ArrayList<celestialObject> ObjectList;
String[] objectfile;
String[] configfile;
int savetimer = 0;
static int screenwidth = 1920;
static int screenheight = 1080;
float trans = 0;

class celestialObject {
  String name;
  float diameter;
  String unit;
  String sprite;
  PImage img;
  int wid;
  int hei;
  int xpos;

  celestialObject(String Oname, float Odiameter, String Ounit, String Oimg) {
    name = Oname;
    diameter = Odiameter;
    unit = Ounit;
    sprite = Oimg;
    img = loadImage(Oimg);
    wid = img.width;
    hei = img.height;
  }
}

void setup() {
  size(1920, 1080);
  frameRate(200);
  objectfile = loadStrings("objects.txt");
  configfile = loadStrings("config.ini");
  backgroundImage = loadImage("background.png");
  font = createFont("Franklin Gothic Book Regular.ttf", 32);
  textFont(font, 32);
  textAlign(CENTER, CENTER);
  imageMode(CENTER);
  ObjectList = new ArrayList();
  readObjects();
  readConfig();
  loadOffset();
}

void addObject(String Aname, float Adiameter, String Aunit, String Aimg) {
  println("Loading "+Aname);
  if (Aimg.equals("null")) {
    ObjectList.add(new celestialObject(Aname, Adiameter, Aunit, "images/"+Aname+".png"));
  } else {
    ObjectList.add(new celestialObject(Aname, Adiameter, Aunit, "images/"+Aimg));
  }
}

void readObjects() {
  for (int i = 0; i < objectfile.length; i++) {
    String[] currentObject = split(objectfile[i], ",");
    addObject(currentObject[0], float(currentObject[1]), currentObject[2], currentObject[3]);
  }
}

void readConfig() {
  for (int i = 0; i < configfile.length; i++) {
    char slash = configfile[i].charAt(0);
    if (slash != '/') {
      //getting config values based on line number
      if (i == 1) {
        xoffset = int(configfile[i]);
      } else if (i == 3) {
        scale = float(configfile[i]);
      }
    }
  }
}

void loadOffset() {
  //for (int i = 0; i <= xoffset; i++) {
  //  int x = 0 + xoffset;
  //  for ( celestialObject drawObject : ObjectList ) {         
  //    float dia;
  //    if (drawObject.unit.equals("km")) {
  //      dia = drawObject.diameter * 1000;
  //    } else {
  //      dia = drawObject.diameter;
  //    }
  //    int drawWidth = int(scale * dia);
  //    //checks if image is too small to be drawn
  //    if (x+drawObject.img.width >= 0 && x <= 1500) {
  //      int drawWidth = int(scale * dia);
  //      int drawHeight = int(drawWidth * drawObject.hei / drawObject.wid);
  //      if (drawWidth > 0 && drawHeight > 0) {
  //        //drawObject.img.resize(drawWidth, drawHeight);
  //        image(drawObject.img, x+(drawWidth/2), 400,drawWidth, drawHeight);
  //        //calculates font size relative to object's current size
  //        int textSize;
  //        //checks if the name or diameter is longer, then uses the longer one for calculation
  //        if (drawObject.name.length() < str(drawObject.diameter).length()) {
  //          textSize = int(drawObject.img.width/str(drawObject.diameter).length());
  //        } else {
  //          textSize = int(drawObject.img.width/drawObject.name.length());
  //        }
  //        if (textSize > 0) {
  //          textSize(textSize);
  //          float texty = 418+(drawObject.img.height/2);
  //          if (texty < (418+(drawObject.img.height/2))) {
  //            texty = 418;
  //          }
  //          text(drawObject.name, x+(drawObject.img.width/2), texty);
  //          text(drawObject.diameter+drawObject.unit, x+(drawObject.img.width/2), texty+textSize);
  //        }
  //      }
  //    }
  //    drawObject.xpos = x;
  //    x += (drawObject.img.width*0.08 + drawObject.img.width);
  //  }
  //}
}

void draw() {
  image(backgroundImage, screenwidth/2, screenheight/2);
  int x = int(0 + xoffset + trans);
  for ( celestialObject drawObject : ObjectList ) {
    float dia;
    if (drawObject.unit.equals("km")) {
      dia = drawObject.diameter * 1000;
    } else {
      dia = drawObject.diameter;
    }
    int drawWidth = int(scale * dia);
    if (x+(scale*dia) >= 0 && x <= screenwidth) {
      //checks if image is too small to be drawn 
      int drawHeight = int(drawWidth * drawObject.hei / drawObject.wid);
      if (drawWidth > 0 && drawHeight > 0) {
        //drawObject.img.resize(drawWidth, drawHeight);
        image(drawObject.img, x+(drawWidth/2), screenheight/2, drawWidth, drawHeight);
        //calculates font size relative to object's current size
        int textSize;
        //checks if the name or diameter is longer, then uses the longer one for calculation
        if (drawObject.name.length() < str(drawObject.diameter).length()) {
          textSize = int(drawWidth/str(drawObject.diameter).length());
        } else {
          textSize = int(drawWidth/drawObject.name.length());
        }
        if (textSize > 0) {
          textSize(textSize);
          float texty = screenheight/2+18+(drawHeight/2);
          if (texty < (screenheight/2+18+(drawHeight/2))) {
            texty = screenheight/2+18;
          }
          text(drawObject.name, x+(drawWidth/2), texty);
          text(drawObject.diameter+drawObject.unit, x+(drawWidth/2), texty+textSize);
        }
      }
    }
    drawObject.xpos = x;
    x += (drawWidth*0.08 + drawWidth);
  }
  //display deltax
  textSize(32);
  text(str(deltax), screenwidth-50, 10);
  text(str(deltascale), screenwidth-50, 50);
  //display Saved
  if (savetimer > 0) {
    text("Saved", screenwidth-50, 90);
    //text(str(savetimer),1450,130);
  }
  if (savetimer > 0) {
    savetimer -= 1;
  }
  //println(str(scale));
}

void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  if (e < 0) {
    scale *= (1 + deltascale);
    mouseX = xoffset;
    trans -= (getStriplength() * deltascale);
  } else if (e > 0) {
    scale *= (1 - deltascale) ;
    mouseX = xoffset;
    trans += (getStriplength() * deltascale);
  }
}

void keyPressed() {
  if (key == CODED) {
    if (keyCode == LEFT) {
      xoffset += deltax;
    } else if (keyCode == RIGHT) {
      xoffset -= deltax;
    } else if (keyCode == UP) {
      deltax += 5;
    } else if (keyCode == DOWN) {
      deltax -= 5;
    }
  }
  if (key == 's') {
    for (int i = 0; i < configfile.length; i++) {
      if (i == 1) {
        configfile[i] = str(xoffset);
      } else if (i == 3) {
        configfile[i] = str(scale);
      }
    }
    saveStrings("config.ini", configfile);
    savetimer = 500;
  } else if (key == 'q') {
    deltascale += 0.02;
  } else if (key == 'a') {
    deltascale -= 0.02;
  }
  if (deltax < 0) {
    deltax = 0;
  } else if (deltascale < 0) {
    deltascale = 0;
  }
}

float getStriplength() {
  float x = 0;
  int i = 0;
  for ( celestialObject getObject : ObjectList ) {
    float dia;
    if (getObject.unit.equals("km")) {
      dia = getObject.diameter * 1000;
    } else {
      dia = getObject.diameter;
    }
    int drawWidth = int(scale * dia);
    x += (drawWidth*0.08 + drawWidth);
    i++;
    //println(ObjectList.size());
    if (i == ObjectList.size()) {
       x -= drawWidth*0.08;
    }
    //println(x);
  }
  //println(x);
  return x;  
}
Sign In or Register to comment.