绘制顺序(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 在处理画布的时候,基本上是这样的情况:

  1. Grasshopper 根据你的画布中的所有组件,生成了一个列表。它的顺序和绘制顺序是一样的,0 号元素被绘制在所有元素的下面,其他元素则根据列表的顺序依次绘制在上面。
  2. Grasshopper 找到绘制在最后面的已终止的组件,要求它重算自身。
  3. 在这个组件真正开始计算任何东西之前,首先它会去检查有没有已终止的输入。如果有,就让这些输入也重算自身。
  4. 同样,这些组件在它们开始计算之前也会检查输入,直到找到一个没有已终止输入,但是自身已终止的组件为止,这个组件会重算自身并设置为非终止。
  5. 回到步骤 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 号元素,所以确实被放到了画布中所有组件的最下面。 太好了!

猜你喜欢

转载自www.cnblogs.com/ppJuan/p/7084222.html