Why use Map & Translate?

Hello Community,

New to Processing working on understanding this code:

import com.onformative.leap.LeapMotionP5;
import java.util.*;

LeapMotionP5 leap;
LinkedList<Integer> values;

public void setup() {
  size(800, 300);
  frameRate(120);  //Specifies the number of frames to be displayed every second
  leap = new LeapMotionP5(this);
  values = new LinkedList<Integer>();
  stroke(255);
}

int lastY = 0;

public void draw() {
  **translate(0, 180)**; //(x, y, z)
  background(0);
  if (values.size() >= width) {
    values.removeFirst();
  }

  values.add((int) leap.getVelocity(leap.getHand(0)).y);
  System.out.println((int) leap.getVelocity(leap.getHand(0)).y);
  int counter = 0;
 ** for (Integer val : values)** {
    **val = (int) map(val, 0, 1500, 0, height);**
    line(counter, val, counter - 1, lastY);
    point(counter, val);
    lastY = val;
    counter++;
  }

 ** line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); //(x1, y1, x2, y2)**

}

It basically draws a graph of movement detected on the y axis using the Leap Motion sensor. Output looks like this:

velocity

I eventually need to do something similar to this that would detect amplitude instead of velocity simultaneously on all 3 axis.

The use of Map and Translate are whats really confusing me. I've read the definitions of these functions on the Processing website so I know what they are and the syntax, but what I don't understand is the why?! (which is arguably the most important part.

I am asking if someone can provide simple examples that explain the WHY behind using these 2 functions. For instance, given a program that needs to do A, B, and C, with data foo, y, and x, you would use Map or Translate because A, B, and C.

I think programming guides often overlook this important fact but to me it is very important to truly understanding a function.

Bonus points for explaining:

for (Integer val : values) and LinkedList values; (cant find any documentation on the processing website for these)

Thanks!

Answers

  • Translate shifts the coordinate system so that (0,0) is at a new position. You can then draw relative to that position. This allows you to create simple shape drawing routines that draw themselves realtive to (0,0). You can then translate these to any place you want in the coordinate system. You can also rotate() or scale() the coordinate system and your simple shape will appear rotated or scaled without you having to change the drawing routine.

    This is most useful when sandwiched between pushMatrix() and popMatrix() which can comparmentalize these coordinate shifts so they don't pile up cummulatively.

    map() is just computing things for you if you need to know where something in the warped coordinate system is in the real world.

  • @cems,

    Thanks. I get that part of translate but why not just re-draw the shape?

  • edited December 2013 Answer ✓

    translate doesn't move a particular shape. it moves the whole coordinate system in which the next shape drawing will take place.

    just try it:

            size(400,400);
            fill(200);
    
            ellipse(0,0,10,20);
    
            translate(40,50);     
            ellipse(0,0,10,20);  // same shape new location
    
            translate(40,50);    // these are cumulative!
            ellipse(0,0,10,20);
    
            translate(40,50);    
            rotate(0.5);          
            ellipse(0,0,10,20);
    
            translate(40,50);
            rotate(0.5);             // these are cumulative too!!
            scale(4);
            ellipse(0,0,10,20);
    
            translate(40,50);
            rotate(0.5);             // these are cumulative too!!
            scale(4);                 // these are cumulative too!!!!!!
            ellipse(0,0,10,20);
    
  • I see! So it saves whatever is currently drawn then moves the screen to wherever you tell it but still displays what was first drawn just from a different perspective? Is that the gist of it?

  • @cems,

    Thanks for that. Do you know anything about for (Integer val : values) and LinkedList values data structure?

  • Answer ✓

    not really 8)

    your picture for instance. those values make sense as a sine wave being both positive and negative. but drawing those without the translate just means you'd only see the bottom of the picture, the +ve values would be off the top. you COULD add half the screen height to every single value (which would ruin them) but it's just easier to move the coordinate system to the middle of the screen using translate and using the original values in the drawing.

    similarly, the map() amplifies (or reduces) those values to fit the screen, again without changing the original values.

    for (Integer val : values)

    iterates over all the values in the variable 'values' (which is a list). each time through the loop the current value will be placed in a variable called 'val' which is an Integer.

    LinkedList<Integer> values;

    defines storage structure for a list of Integers which it calls 'values'

    values.add((int) leap.getVelocity(leap.getHand(0)).y);

    adds a value to the end of the values list.

  • (it's not a sine wave, but close enough)

  • @koogs,

    Thanks for that explanation its starting to make sense! I get map() now.Can you post me a link or something where I can find out all the functions of the linked list? (like .size, .add, etc). Another strange thing I just noticed is how in these code you can have 2 statements on one line. Like values.add((int) leap.getVelocity(leap.getHand(0)).y);

    This is weird to see in Processing although I understand the what its doing the syntax just seems weird.

    You kinda lost me here though: you COULD add half the screen height to every single value (which would ruin them) but it's just easier to move the coordinate system to the middle of the screen using translate and using the original values in the drawing.

  • @koogs,

    Another example of the the strange compound, 1 line syntax I mentioned is this: val = (int) map(val, 0, 1500, 0, height);

    I get what the map() is doing but what about val = (int) ?

    I dont get that part. Map()'s first parameter is already val so why the need for the val = (int) and aren't these 2 separate statements? My knowledge of Processing syntax tells me this should be

    val = (int);
    map(val, 0, 1500, 0, height);
    
  • Answer ✓

    val = (int)map(val, 0, 1500, 0, height);

    it's taking the current value of val (the second one), mapping it from 0-1500 to 0-height, converting that to an int (because map returns a float by default iirc) and then storing that int back in val (the first one), just like a = a + 1 adds one to a.

    LinkedList documentation: http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html but, somehow, i imagine you won't be too pleased with that 8)

    you COULD add half the screen height to every single value (which would ruin them) but it's just easier to move the coordinate system to the middle of the screen using translate and using the original values in the drawing.

    the two alternatives are (roughly)

    for (Integer val : values) { // add half a screen to all y values to centre the graph line(counter, val + height / 2, counter - 1, lastY + height / 2); point(counter, val + height / 2); }

    or

    // move 0 to centre translate(0, height / 2); for (Integer val : values) { // no need to change values line(counter, val, counter - 1, lastY); point(counter, val); }

    second is easier to read and less typing - win, win

    values.add((int)leap.getVelocity(leap.getHand(0)).y);

    this is doing the same thing with the (int) - making sure the parameter is an integer before adding it to the list of values (which are defined as Integers in line 5). this is called 'casting'.

Sign In or Register to comment.