【问题标题】:Usage of Map and Translate Functions in ProcessingMap 和 Translate 函数在处理中的使用
【发布时间】:2013-12-11 05:12:51
【问题描述】:

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

它基本上绘制了使用 Leap Motion 传感器在 y 轴上检测到的运动图。输出如下所示:

我最终需要做一些类似的事情来同时检测所有 3 轴上的振幅而不是速度,而不仅仅是 y。

地图和翻译的使用让我很困惑。我已经在 Processing 网站上阅读了这些函数的定义,所以我知道它们是什么以及语法,但我不明白为什么?! (这可以说是最重要的部分。

我在问是否有人可以提供简单的示例来解释使用这两个函数背后的原因。例如,给定一个程序需要使用数据 foo、y 和 x 执行 A、B 和 C,您将使用 Map 或 Translate,因为 A、B 和 C。

我认为编程指南经常忽略这一重要事实,但对我来说,真正理解一个函数非常重要。

解释加分:

for (Integer val : values) and LinkedList&lt;Integer&gt; values;(在这些处理网站上找不到任何文档)

谢谢!

【问题讨论】:

    标签: map linked-list processing leap-motion


    【解决方案1】:

    首先,我们将做最简单的一个。 LinkedList是类似于ArrayList的数据结构,大家可能比较熟悉。如果不是,那么它只是一个可以插入和删除的值列表(尖括号之间的类型,在本例中为整数)。内部有点复杂,但如果它没有出现在 Processing 文档中,那么可以肯定的是它内置在 Java 本身中 (java documentation)。

    这一行:

    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,height,但看起来他们选择了不同的方式。每当您在处理过程中调用绘图函数(例如point(x,y))时,它都会从 (0,0) 绘制 (x,y) offset 处的像素。有时您不希望它相对于 (0,0) 绘制它,因此translate() 函数允许您更改它相对于绘制事物的对象。在这种情况下,平移允许您在屏幕中间某处而不是边缘绘制某个点 (x,0)。

    希望有帮助!

    【讨论】:

    • @kevinas5,太棒了!那么 translate 和 2 line 函数的结合是什么产生了基本绘制移动线的错觉?
    • 我不确定line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); //(x1, y1, x2, y2) 应该做什么。那画了一条水平线(但我看不到它,也许它不在屏幕上)。实际移动是通过删除列表的第一个元素来完成的(它将所有其他元素左移一个)。 :)
    • 我删除了第一行(),只有第二行,它所做的就是画一条直线。我想这样做是为了即使没有检测到运动也能保持线路畅通。
    • 另一个快速的问题,为什么在这种情况下需要使用链表?数组列表不能做同样的事情吗?
    • 是的。但是,这将是低效的,因为 LinkedLists 允许更快的删除。因为(一段时间后),第一个元素将从列表中删除,执行该操作所需的时间有点重要(它每秒运行 120 次)。 ArrayLists 只是对数组的抽象,因此删除第一个元素意味着移动数组中的每个其他元素,这很可怕。 LinkedLists 允许你删除一个元素而不做任何其他事情。
    猜你喜欢
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 2020-12-11
    • 2019-08-17
    • 1970-01-01
    • 2018-08-20
    相关资源
    最近更新 更多