Использование функций Map и Translate в обработке

Новичок в Processing, работающий над пониманием этого кода:

 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)**
}

Это в основном рисунок графика движения, обнаруженного по оси Y с использованием датчика Leap Motion. Вывод выглядит следующим образом: screenshot

В конце концов мне нужно сделать что-то подобное, чтобы определить амплитуду, а не скорость одновременно по всем трем осям, а не только по оси y.

Меня действительно смущает использование Map и Translate. Я прочитал определения этих функций на веб-сайте Processing, поэтому знаю, что это такое и синтаксис, но чего я не понимаю, так это почему?! (что, пожалуй, самая важная часть.

Я спрашиваю, может ли кто-нибудь привести простые примеры, объясняющие ПОЧЕМУ использование этих двух функций. Например, для программы, которой нужно выполнить A, B и C с данными foo, y и x, вы должны использовать Map или Translate, потому что A, B и C.

Я думаю, что руководства по программированию часто упускают из виду этот важный факт, но для меня очень важно правильно понять функцию.

Бонусные баллы за объяснение:

for (Integer val : values) and LinkedList<Integer> values; (не могу найти документацию на сайте обработки для них)

Спасибо!


person NASA Intern    schedule 10.12.2013    source источник


Ответы (1)


Сначала сделаем самый простой. LinkedList — это структура данных, похожая на ArrayList, с которой вы, возможно, более знакомы. Если нет, то это просто список значений (типа между угловыми скобками, в данном случае целого числа), которые вы можете вставлять и удалять. Это немного сложно внутри, но если этого нет в документации Processing, можно с уверенностью сказать, что он встроен в саму Java (документация по Java).

Эта строка:

for (Integer val : values)

называется циклом for-each или foreach, который имеет много очень хороших объяснений в Интернете, но я дам краткое объяснение здесь. Если у вас есть какой-то список (возможно, LinkedList, возможно, ArrayList и т. д.) и вы хотите что-то сделать со всеми элементами, вы можете сделать что-то вроде этого:

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));
}

Если вы много манипулируете каждым элементом, быстро становится утомительно записывать каждый раз values.get(i). Решением было бы захватить values.get(i) в какую-то переменную в начале цикла и вместо этого использовать ее везде. Однако это не на 100% элегантно, поэтому в java есть встроенный способ сделать это — цикл for-each. Код

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

эквивалентно

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

Надеюсь, это имеет смысл.

map() берет число из одной линейной системы и сопоставляет его с другой линейной системой. Представьте, если бы я был злым профессором и хотел бы давать студентам случайные оценки от 0 до 100. У меня есть функция, которая возвращает случайное десятичное число от 0 до 1, так что теперь я могу сделать map(rand(),0,1,0,100);, и она преобразует число для меня! В этом примере вы также можете просто умножить на 100 и получить тот же результат, но обычно это не так тривиально. В этом случае у вас есть показания датчика от 0 до 1500, но если вы просто нанесете это значение на график, иногда оно исчезнет с экрана! Таким образом, вы должны масштабировать его до соответствующего масштаба, что это и делает. 1500 — это максимальное значение, которое может быть для чтения, и, по-видимому, мы хотим, чтобы максимальная высота графика находилась на краю экрана.

Я не знаком с вашей настройкой, но похоже, что показания могут быть отрицательными, а это значит, что они могут отображаться и вне экрана. Лучшим решением было бы сопоставить показания от -1500,1500 до 0,высота, но похоже, что они решили сделать это по-другому. Всякий раз, когда вы вызываете функцию рисования в процессе обработки (например, point(x,y)), она рисует пиксели в (x,y) смещении от (0,0). Иногда вы не хотите, чтобы он рисовал его относительно (0,0), поэтому функция translate() позволяет вам изменить то, относительно чего он рисует. В этом случае перевод позволяет нанести точку (x,0) где-то в середине экрана, а не на краю.

Надеюсь, это поможет!

person kevinsa5    schedule 10.12.2013
comment
@kevinas5, это было здорово! Таким образом, комбинация функций перевода и двух линий создает иллюзию рисования движущейся линии? - person NASA Intern; 11.12.2013
comment
Я не уверен, что должна делать строка line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); //(x1, y1, x2, y2). Это рисует горизонтальную линию (но я ее не вижу, может быть, она не на экране). Фактическое перемещение выполняется путем удаления первого элемента списка (что сдвигает все остальные элементы влево на единицу). :) - person kevinsa5; 11.12.2013
comment
Я удалил первую строку (), и только с этой второй строкой все, что она делает, это рисует прямую линию. Я предполагаю, что это сделано для того, чтобы линия продолжала работать, даже если движение не обнаружено. - person NASA Intern; 11.12.2013
comment
Еще один быстрый вопрос, зачем нужно использовать связанный список в этой ситуации? Разве список массивов не мог сделать то же самое? - person NASA Intern; 11.12.2013
comment
Да. Однако это было бы неэффективно, потому что LinkedLists позволяют гораздо быстрее удалять. Поскольку (через некоторое время) первый элемент удаляется из списка, время, необходимое для выполнения этого действия, несколько важно (оно выполняется 120 раз в секунду). ArrayLists — это просто абстракции вокруг массивов, поэтому удаление первого элемента означает сдвиг каждого другого элемента в массиве, что ужасно. LinkedLists позволяют вам удалить элемент, ничего больше не делая. - person kevinsa5; 11.12.2013
comment
@ kevinas5 Я пытаюсь переварить это: функция translate () позволяет вам изменить то, относительно чего она рисует вещи. В этом случае перевод позволяет нанести точку (x,0) где-то в середине экрана, а не на краю. Я не совсем понимаю перевод (0, 180). Означает ли это просто, что при каждом розыгрыше мое происхождение теперь (0, 180) вместо (0,0)? - person NASA Intern; 11.12.2013
comment
Да. Итак, если вы переведете (0,180) и точку вызова (0,10), она появится на реальном пикселе экрана (0,190). - person kevinsa5; 11.12.2013