绘制顺序(draw order)是如何影响 grasshopper 的计算顺序的
Posted ppjuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绘制顺序(draw order)是如何影响 grasshopper 的计算顺序的相关的知识,希望对你有一定的参考价值。
一般情况下,grasshopper 的计算是沿着连接线从左至右进行的。首先被计算的是左边的组件,然后触发下游组件,直到 canvas 全部计算完成为止。在你使用 grasshopper 几个月之后,想都不用想就知道这是当然的。
直到有一天你想用 grasshopper 违反这个基本逻辑。我最近接到一个任务,需要用 Honybee 计算强光。强光计算组件使用了一个 Rhino 相机,这意味着当强光将要被正确计算的时候,相机要移动到正确的位置。
我决定使用霍斯特相机控制(Horseter camera control)来调整相机,于是就有了这么个东西:
这个计算取决于相机 已经 被放置到正确的位置上。换句话来说,相机 必须 在计算完成之前被放到正确的位置。看出问题了吗?如果没有相机组件的输出,计算模型肯定来自“buidling”组件。因此,保证相机在计算完成之前移动到正确的位置是不可能的。
Grasshopper 首先计算的是哪一个组件?
首先讲一点基础知识。当 Grasshopper 计算组件的时候,有一个属性叫做 expired(终止)。如果一个组件需要计算,它就会被标上 expired=true。如果组件已经更新了,不再需要计算,它就会被标上 expired=false。当你更改一个组件的时候(比如修改了它的输入值),它就会被打上 expired 标志。并且当一个组件被标志为 expired,所有下游组件(也就是右边的组件)都会被标志为 expired。
简单来说,“expired”表明这个组件正在等待重算。
当 Grasshopper 有了一个已终止组件列表的时候,它必须决定以什么方式去重算。Grasshopper 是从左至右进行重算的,从一个没有已终止的输入的组件开始。
对于大多数 Grasshopper 文件来说,这个解释已经够清楚了。但事实是,有更多复杂的算法在等着它。注意,在我的图中,可以计算组件的有效顺序不止一种:
- Building, setCam, Docals, result
- Building, Docals, setCam, result
所以 Grasshopper 有两种选择来确定首先计算的组件,它总归会选一个的,所以背后肯定有它选择计算顺序的更深层次的原因。我并没有多做其他探索,就去了 Grasshopper 论坛,看到了这篇文章,提问了一个问题。
不会影响计算顺序的东西:
Grasshopper 的计算顺序不会被下列因素影响:
- 组件位置(也就是x,y坐标)
- 输入或输出的顺序
- 组件内的数据
- 组件的类型*
那么会被哪些因素影响呢?
Grasshopper 的绘制顺序
计算顺序被一个关键性的因素左右:绘制顺序(draw order)。在后台, Grasshopper 把你的文件中的所有组件复制到一个列表中,列表的顺序就是绘制的顺序。
被称为“绘制顺序”是因为它决定了哪一个组件被“绘制”时能覆盖其他组件。请看下图 panel 是如何覆盖其他 panel 的,这就是“绘制顺序”的具体实现。
你可以通过快捷键轻易地更改绘制顺序:
- CTRL+B 把组件送到下面
- CTRL+F 把组件送到上面
Grasshopper 是如何利用绘制顺序来计算的?
绘制顺序不仅仅是帮助你美化 Grasshopper 画布— 它也同样左右着计算顺序。当 Grasshopper 在处理画布的时候,基本上是这样的情况:
- Grasshopper 根据你的画布中的所有组件,生成了一个列表。它的顺序和绘制顺序是一样的,0 号元素被绘制在所有元素的下面,其他元素则根据列表的顺序依次绘制在上面。
- Grasshopper 找到绘制在最后面的已终止的组件,要求它重算自身。
- 在这个组件真正开始计算任何东西之前,首先它会去检查有没有已终止的输入。如果有,就让这些输入也重算自身。
- 同样,这些组件在它们开始计算之前也会检查输入,直到找到一个没有已终止输入,但是自身已终止的组件为止,这个组件会重算自身并设置为非终止。
- 回到步骤 2,重复直到没有已终止的组件。
如何确定绘制顺序?
最简单的确定绘制顺序,同时也是确定计算顺序的方法,是通过拖拽组件来看看哪个覆盖在上面。最底下的组件会被首先计算。如果我们不满意这个顺序,可以通过 CTRL+B 和CTRL+F 来更改。
看起来是 setCam 先被计算,耶!
等等 —— 并没有那么简单! 如果 setCam 组件在 DoCals 下面,但是 result 组件在 setCam 和 DoCals 的下面呢?“result”会被 Grasshopper 首先触发,它也会接着触发 DoCals。所以即使 setCam 是在 DoCals 的下面,由于 results 的愿原因,setCam 也会在 DoCals 之后计算。
我们需要确保 setCam 在所有组件之前计算,而不仅仅是 DoCals。我们可以用 CTRL+B 快捷键实现,但是怎么确定它正确运行了呢?没有视觉上的反馈是否快捷键已经把组件送到了最下面,我们只有手动地去确认每个组件。
如何确定绘制顺序 —— 给极客
再一次,C# 拯救世界!用一个 C# 组件,我们可以得到 Grasshopper 文件中所有对象的一个列表 —— 以绘制顺序。用一个 timer 和一个连接的 panel,我们可以加一些额外的功能 —— 点击任何一个组件,在 panel 中会显示“selected”。
你可以复制以下代码到一个 C# 组件中,并且在图中设置好。启动 timer,选择任何一个组件(或多个组件)。
1 var rtnlsit = new List<string>(); 2 3 foreach (IGH_DocumentObject obj in GrasshopperDocument.Objects) 4 { 5 if(obj.Attributes.Selected) rtnlist.Add(obj.NickName + "(" + obj.Name + ")SELECTED"); 6 else rtnlist.Add(obj.NickName + "(" + obj.Name + ")"); 7 A = rtnlist; 8 }
使用这个组件, 可以验证我们成功地把 setCam 设置到了绘制顺序列表的最底层。
我们选择的组件是列表中的 0 号元素,所以确实被放到了画布中所有组件的最下面。 太好了!
以上是关于绘制顺序(draw order)是如何影响 grasshopper 的计算顺序的的主要内容,如果未能解决你的问题,请参考以下文章
Android视图的绘制流程(下)——View的Layout与Draw过程