Question

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 draw of graph of movement detected on the y axis using the Leap Motion sensor. Output looks like this: screenshot

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

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 dont 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<Integer> values; (cant find any documentation on the processing website for these)

Thanks!

Était-ce utile?

La solution

First, we'll do the easiest one. LinkedList is a data structure similar to ArrayList, which you may be more familiar with. If not, then it's just a list of values (of the type between the angle braces, in this case integer) that you can insert and remove from. It's a bit complicated on the inside, but if it doesn't appear in the Processing documentation, it's a safe bet that it's built into Java itself (java documentation).

This line:

for (Integer val : values)

is called a "for-each" or "foreach" loop, which has plenty of very good explanation on the internet, but I'll give a brief explanation here. If you have some list (perhaps a LinkedList, perhaps an ArrayList, whatever) and want to do something with all the elements, you might do something like this:

for(int i = 0; i < values.size(); i++){
    println(values.get(i)); //or whatever
    println(values.get(i) * 2);
    println(pow(values.get(i),3) - 2*pow(values.get(i),2) + values.get(i));
}

If you're doing a lot of manipulation with each element, it quickly gets tedious to write out values.get(i) each time. The solution would be to capture values.get(i) into some variable at the start of the loop and use that everywhere instead. However, this is not 100% elegant, so java has a built-in way to do this, which is the for-each loop. The code

for (Integer val : values){
    //use val
}

is equivalent to

for(int i = 0; i < values.size(); i++){
    int val = values.get(i);
    //use val
}

Hopefully that makes sense.

map() takes a number in one linear system and maps it onto another linear system. Imagine if I were an evil professor and wanted to give students random grades from 0 to 100. I have a function that returns a random decimal between 0 and 1, so I can now do map(rand(),0,1,0,100); and it will convert the number for me! In this example, you could also just multiply by 100 and get the same result, but it is usually not so trivial. In this case, you have a sensor reading between 0 and 1500, but if you just plotted that value directly, sometimes it would go off the screen! So you have to scale it to an appropriate scale, which is what that does. 1500 is the max that the reading can be, and presumably we want the maximum graphing height to be at the edge of the screen.

I'm not familiar with your setup, but it looks like the readings can be negative, which means that they might get graphed off the screen, too. The better solution would be to map the readings from -1500,1500 to 0,height, but it looks like they chose to do it a different way. Whenever you call a drawing function in processing (eg point(x,y)), it draws the pixels at (x,y) offset from (0,0). Sometimes you don't want it to draw it relative to (0,0), so the translate() function allows you to change what it draws things relative against. In this case, translating allows you to plot some point (x,0) somewhere in the middle of the screen, rather than on the edge.

Hope that helps!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top