1. 程式人生 > >繪制順序(draw order)是如何影響 grasshopper 的計算順序的

繪制順序(draw order)是如何影響 grasshopper 的計算順序的

else mic 簡單的 pre str 依次 expired 也會 沒有

一般情況下,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 號元素,所以確實被放到了畫布中所有組件的最下面。 太好了!

繪制順序(draw order)是如何影響 grasshopper 的計算順序的