通常狀況下,grasshopper 的計算是沿着鏈接線從左至右進行的。首先被計算的是左邊的組件,而後觸發下游組件,直到 canvas 所有計算完成爲止。在你使用 grasshopper 幾個月以後,想都不用想就知道這是固然的。算法
直到有一天你想用 grasshopper 違反這個基本邏輯。我最近接到一個任務,須要用 Honybee 計算強光。強光計算組件使用了一個 Rhino 相機,這意味着當強光將要被正確計算的時候,相機要移動到正確的位置。canvas
我決定使用霍斯特相機控制(Horseter camera control)來調整相機,因而就有了這麼個東西:ssh
這個計算取決於相機 已經 被放置到正確的位置上。換句話來講,相機 必須 在計算完成以前被放到正確的位置。看出問題了嗎?若是沒有相機組件的輸出,計算模型確定來自「buidling」組件。所以,保證相機在計算完成以前移動到正確的位置是不可能的。ui
Grasshopper 首先計算的是哪個組件?spa
首先講一點基礎知識。當 Grasshopper 計算組件的時候,有一個屬性叫作 expired(終止)。若是一個組件須要計算,它就會被標上 expired=true。若是組件已經更新了,再也不須要計算,它就會被標上 expired=false。當你更改一個組件的時候(好比修改了它的輸入值),它就會被打上 expired 標誌。而且當一個組件被標誌爲 expired,全部下游組件(也就是右邊的組件)都會被標誌爲 expired。code
簡單來講,「expired」代表這個組件正在等待重算。對象
當 Grasshopper 有了一個已終止組件列表的時候,它必須決定以什麼方式去重算。Grasshopper 是從左至右進行重算的,從一個沒有已終止的輸入的組件開始。blog
對於大多數 Grasshopper 文件來講,這個解釋已經夠清楚了。但事實是,有更多複雜的算法在等着它。注意,在個人圖中,能夠計算組件的有效順序不止一種:string
因此 Grasshopper 有兩種選擇來肯定首先計算的組件,它總歸會選一個的,因此背後確定有它選擇計算順序的更深層次的緣由。我並無多作其餘探索,就去了 Grasshopper 論壇,看到了這篇文章,提問了一個問題。it
不會影響計算順序的東西:
Grasshopper 的計算順序不會被下列因素影響:
那麼會被哪些因素影響呢?
Grasshopper 的繪製順序
計算順序被一個關鍵性的因素左右:繪製順序(draw order)。在後臺, Grasshopper 把你的文件中的全部組件複製到一個列表中,列表的順序就是繪製的順序。
被稱爲「繪製順序」是由於它決定了哪個組件被「繪製」時能覆蓋其餘組件。請看下圖 panel 是如何覆蓋其餘 panel 的,這就是「繪製順序」的具體實現。
你能夠經過快捷鍵輕易地更改繪製順序:
Grasshopper 是如何利用繪製順序來計算的?
繪製順序不只僅是幫助你美化 Grasshopper 畫布— 它也一樣左右着計算順序。當 Grasshopper 在處理畫布的時候,基本上是這樣的狀況:
如何肯定繪製順序?
最簡單的肯定繪製順序,同時也是肯定計算順序的方法,是經過拖拽組件來看看哪一個覆蓋在上面。最底下的組件會被首先計算。若是咱們不滿意這個順序,能夠經過 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 號元素,因此確實被放到了畫布中全部組件的最下面。 太好了!