Grasshopper中的數(shù)據(jù)控制

作者:Dixon
McNeel Asia 技術(shù)支持
Rhino 中國技術(shù)支持與推廣中心負(fù)責(zé)人
Shaper3d(西普設(shè)計(jì)咨詢)聯(lián)合創(chuàng)始人
Rhino原廠GH課程與開發(fā)負(fù)責(zé)人

【為了讓不同程度的使用者包括初學(xué)者也可以閱讀這篇文章。本文使用的范例程序結(jié)構(gòu)簡單但足夠典型。著重于介紹思路的分析,反映設(shè)計(jì)過程中遇到的數(shù)據(jù)處理及如何解決問題的思維過程。對(duì)涉及的工具就使用不做細(xì)致的介紹,敬請(qǐng)見諒】
在使用參數(shù)化設(shè)計(jì)工具輔助設(shè)計(jì)的過程中用戶需要解決兩個(gè)階段的問題:
根據(jù)設(shè)計(jì)要求規(guī)劃合理的編程邏輯順序。(編程思維過程)
使用參數(shù)化設(shè)計(jì)工具實(shí)現(xiàn)設(shè)計(jì)功能。(技術(shù)處理過程)
在這幾年接觸學(xué)習(xí)參數(shù)化設(shè)計(jì)的學(xué)員的過程中,我們發(fā)現(xiàn)大部分學(xué)員會(huì)在這兩個(gè)階段遇到不同的問題。
其中,第一個(gè)階段屬于使用者編程思維方式主導(dǎo)的部分。由于大部分設(shè)計(jì)背景的學(xué)員之前并沒有接受過系統(tǒng)的編程課程的訓(xùn)練,因此普偏在編程邏輯思維方面較為欠缺。本文的范例中對(duì)實(shí)際的設(shè)計(jì)要求有簡單的編程邏輯思維方法的解釋可作為參考。
第二個(gè)階段屬于技術(shù)細(xì)節(jié)的部分。我們注意到大部分GH用戶遇到的技術(shù)細(xì)節(jié)問題可以歸類于以下三方面:
1. 對(duì)GH的工具的運(yùn)行原理和使用方法不夠理解。這是比較初級(jí)的問題。
2. 對(duì)GH工具涉及到的曲面造型技術(shù)缺乏足夠了解。具體為:對(duì)Nurbs的幾何特性、Nurbs數(shù)據(jù)的編程控制方法和曲面造型思路缺乏了解。因此程序中涉及曲線曲面控制處理的部分較難深入和靈活運(yùn)用。這部分較為欠缺的用戶建議可以參加rhino原廠開設(shè)的曲面造型課程的短期學(xué)習(xí)班做系統(tǒng)的補(bǔ)充。
3. 除了以上兩個(gè)參見的問題之外,大部分學(xué)員都會(huì)在學(xué)習(xí)到一個(gè)階段后遇到GH樹形據(jù)結(jié)構(gòu)數(shù)據(jù)管理的理解和控制方面的困難。這通常是所有學(xué)習(xí)GH者都需要跨過的一道坎?
和其他的參數(shù)化設(shè)計(jì)軟件和編程軟件不同,GH采用的樹形據(jù)結(jié)構(gòu)的數(shù)據(jù)管理是很特別的,,它可以讓用戶更容易的管理和控制龐大和復(fù)雜的數(shù)據(jù),以實(shí)現(xiàn)用參數(shù)化控制復(fù)雜的功能甚至是系統(tǒng)的設(shè)計(jì)(如一整棟建筑),但前提是使用者必須對(duì)這種數(shù)據(jù)管理和控制的原理有對(duì)應(yīng)的了解,才能對(duì)其進(jìn)行合理和靈活的控制。這部分是很多人學(xué)習(xí)中遇到的難點(diǎn)或者難以深入到的部分。
為了幫助GH使用者GH的理解樹形數(shù)據(jù)結(jié)構(gòu)在參數(shù)化設(shè)計(jì)過程中起到的作用,以及如何配合設(shè)計(jì)需求處理和控制它,我們使用GH原廠課程中的一個(gè)范例來做介紹。

范例
我要設(shè)計(jì)一座懸掛結(jié)構(gòu)的橋!
這是一個(gè)懸掛結(jié)構(gòu)的橋,如圖是整個(gè)橋的側(cè)面結(jié)構(gòu)。黑色矩形方框是橋體。橋體上10個(gè)紅色點(diǎn)橋體的固定點(diǎn)。用鋼絲懸掛固定。頂上的兩個(gè)藍(lán)色矩形代表懸掛橋的兩個(gè)立柱,每個(gè)立柱上各有3個(gè)鋼絲固定點(diǎn)。我們需要解決的問題就是如何在橋體和柱子的固定點(diǎn)之間拉鋼絲。

這個(gè)設(shè)計(jì)中遇到的實(shí)際問題可以被簡化為點(diǎn)連線的問題,即:
如何在下面10個(gè)點(diǎn)和上面6個(gè)點(diǎn)(2*3結(jié)構(gòu))之間做各種連線方式的設(shè)計(jì)。
為了理清設(shè)計(jì)思路,我們先看兩種最極端的連線方式:
????????? 1.最穩(wěn)固的方式(連線最復(fù)雜)
????????? 2.和最省材料的方式(連線最簡單)
最穩(wěn)固的連線方式(連線最復(fù)雜)
所謂最穩(wěn)固的方式(并且是合理的),也即是:?
?橋體的每個(gè)點(diǎn)(地下的10個(gè))都和柱子上的每個(gè)點(diǎn)(頂上的6個(gè))都做連線
?這個(gè)連線方式題就可以簡化為:10個(gè)點(diǎn)和6個(gè)點(diǎn)之間的連線組合,很明顯會(huì)有60條線(10*6)。
雖說是最復(fù)雜的連線方式,但是在編程邏輯中卻是最簡單的,程序如下圖:

為了集中表述問題的關(guān)鍵部分,圖片中去掉了點(diǎn)生成的程序部分。
在程序處理細(xì)節(jié)方面注意line工具的內(nèi)部必須切換成cross的數(shù)據(jù)對(duì)應(yīng)方式,這在程序外部看不出來。
連接效果如圖:

雖然這是最穩(wěn)固的連接方式,邏輯上來講很簡單,程序處理也很容易。但連接的視覺效果卻不夠好,因?yàn)闃蝮w每個(gè)點(diǎn)都有6跟連線,因此連線過于密集(60根連線),造價(jià)也較貴(很多更多鋼纜)。
最省材料的方式(連線最簡單)
再來看最省材料的連接方式:
即:橋體上的每個(gè)點(diǎn)(10個(gè)點(diǎn))只使用一根鋼絲做固定。從連接的角度可以理解為:
底部的10個(gè)點(diǎn)每個(gè)點(diǎn)都和上面的6個(gè)點(diǎn)的其中之一做連接。
那么具體和頂部的哪一個(gè)點(diǎn)做連接呢?我認(rèn)為和最近的一個(gè)點(diǎn)連接是最合理的,因?yàn)樽钍〔牧隙忆摾|牽引的角度也更趨近于垂直向上,力學(xué)上來說較為合理。?所以,整個(gè)連線的邏輯就是:
底部的10個(gè)點(diǎn)中每個(gè)點(diǎn)與頂上的6個(gè)點(diǎn)中最近的一個(gè)點(diǎn)做連線。
這個(gè)邏輯就稍微復(fù)雜一點(diǎn)了,從編程邏輯考慮實(shí)現(xiàn)這個(gè)效果可以分為兩個(gè)步驟實(shí)現(xiàn):
1.首先分別做出底部的每個(gè)點(diǎn)和頂上6個(gè)點(diǎn)的連線。
2.然后從每個(gè)底部點(diǎn)的6個(gè)連線中挑選出最短的一根。
在這個(gè)編程邏輯中要特別注意:第一步驟的程序輸出的數(shù)據(jù)是有結(jié)構(gòu)分支做管理的,因?yàn)榈谝徊綄?shí)際上仍然是得到60根線(10個(gè)點(diǎn)其中每個(gè)點(diǎn)6根線),但是如果這60根線是混在一起的,那么在第二步驟中就無法找出屬于某一點(diǎn)的6根連線,因此也無法完成第二個(gè)步驟中規(guī)劃的邏輯效果。因此這60跟線應(yīng)該是依據(jù)底部的10個(gè)點(diǎn)來做分支處理的,也即是:第一步輸出的數(shù)據(jù)結(jié)構(gòu)應(yīng)該包含有10個(gè)分支,對(duì)應(yīng)的是底部的10個(gè)點(diǎn),而每個(gè)分支里面有6個(gè)數(shù)據(jù),代表連接到某個(gè)點(diǎn)的6根線。這種數(shù)據(jù)結(jié)構(gòu)可以反映60跟線中那些線是連接那個(gè)點(diǎn)的,數(shù)據(jù)結(jié)構(gòu)圖和GH中的Param Viewer觀察輸出結(jié)構(gòu)應(yīng)該如下圖所示:

Param Viewer是用于檢查樹形結(jié)構(gòu)常用的工具,用戶應(yīng)該熟悉如何去閱讀它。
第一個(gè)步驟的程序如下圖所示:

程序處理細(xì)節(jié):為了保證輸出結(jié)果是分組樹形結(jié)構(gòu),因此根據(jù)GH的數(shù)據(jù)對(duì)應(yīng)法則,必須把B端的數(shù)據(jù)做Graft處理,這樣數(shù)據(jù)的對(duì)應(yīng)方式就變成每個(gè)點(diǎn)和頂部的六個(gè)點(diǎn)做數(shù)據(jù)對(duì)應(yīng)連接線。
用戶應(yīng)該了解:做Graft之后數(shù)據(jù)產(chǎn)生什么樣的結(jié)構(gòu)變化?為什么要把B端做Graft,而不是把A端做Graft?如果對(duì)A端做Graft數(shù)據(jù)會(huì)變成什么樣的數(shù)據(jù)結(jié)構(gòu)?為什么需要這樣的數(shù)據(jù)結(jié)構(gòu)?
接下來的程序?qū)崿F(xiàn)第二個(gè)步驟:從得到的60根條線中,找出連接每個(gè)點(diǎn)的6條線中最短的一根。
這個(gè)功能從編程邏輯角度思考可以這樣解決:首先對(duì)每個(gè)點(diǎn)的六條線的長度做從小到大的排序,然后從中挑第一條線,因?yàn)榈谝粭l線必定是每個(gè)點(diǎn)的六條線中最短的一根。這部分并不涉及數(shù)據(jù)結(jié)構(gòu)的處理,理解工具運(yùn)作的原理就可以做出來,程序如下。

?如下圖,每條線都是底部的每個(gè)點(diǎn)與頂部6個(gè)點(diǎn)中最近的一個(gè)點(diǎn)的連線:

在這個(gè)例子中,如何控制程序?qū)⑤敵龅?0根線使用樹形結(jié)構(gòu)做正確的歸屬管理是程序?qū)崿F(xiàn)正確連線效果的關(guān)鍵。
綜合優(yōu)化的方案?
在實(shí)際設(shè)計(jì)中,很多時(shí)候采用的解決方案都不是那么極端的,例如第一個(gè)方案安全性自然是最好,但是因?yàn)檫B線很多意味著實(shí)際項(xiàng)目中鋼纜也必須使用很多因此造價(jià)很貴。而第二種方案雖然造假最便宜,但是因?yàn)槊總€(gè)橋體上的固定點(diǎn)子只有一根鋼纜固定,因此安全性最差。而且可以試想如果其中有一根柱子斷了,那么整個(gè)橋就有一半的區(qū)域完全沒有支撐,因此很可能整個(gè)橋立馬就垮了。所以有時(shí)候我們會(huì)綜合造價(jià)、成本等因素來考慮解決方案。
因此從加強(qiáng)安全性角度考慮可以使每個(gè)橋體的固定點(diǎn)都有2根鋼纜固定,且兩根鋼纜分別連接不同的立柱。再從造價(jià)和力學(xué)角度考慮讓每根鋼纜連接對(duì)應(yīng)的立柱中最短的一個(gè)點(diǎn),這樣可以在安全性和造價(jià)方面獲得一個(gè)不錯(cuò)的平衡。
因此這個(gè)設(shè)計(jì)的要求就是:
找出底部10個(gè)點(diǎn)的每個(gè)點(diǎn)分別跟兩個(gè)立柱連接的3根線中最短的一根。
這個(gè)設(shè)計(jì)從邏輯上來講其實(shí)和第二個(gè)方案比較接近,區(qū)別在于第二個(gè)設(shè)計(jì)僅僅要求找出每個(gè)點(diǎn)的6個(gè)連線中最短的一個(gè),而這個(gè)設(shè)計(jì)要求還需將每個(gè)點(diǎn)的6根線按照立柱的歸屬分成2組,然后再找出每一組中的最短的線。因此輸出的60根線應(yīng)該是按照如下的樹形結(jié)構(gòu)管理:

在明確希望得到的數(shù)據(jù)結(jié)構(gòu)后,來看程序:

首先在程序的立柱點(diǎn)輸入端輸入的數(shù)據(jù)必須按照立柱歸宿做樹形結(jié)構(gòu)的管理,兩個(gè)分支對(duì)應(yīng)兩個(gè)立柱,每個(gè)分支里面3個(gè)數(shù)據(jù)對(duì)應(yīng)每個(gè)立柱的三個(gè)固定點(diǎn)。
立柱的樹形數(shù)據(jù)結(jié)構(gòu)依賴于前端的程序?qū)?yīng)生成
在接下來的連線程序部分會(huì)遇到數(shù)據(jù)對(duì)應(yīng)方面的控制問題,當(dāng)前程序部分結(jié)構(gòu)如下:

現(xiàn)在A和B組數(shù)據(jù)的結(jié)構(gòu)與之前不同(并非單分支對(duì)單分支),按照GH的數(shù)據(jù)對(duì)規(guī)則來看,事實(shí)上這里無論怎么調(diào)整都不可能直接得到我們要的數(shù)據(jù)結(jié)構(gòu)。<想想為什么>
因此我們的考慮就是退而求其次:如果沒有辦法直接得到60根線的:10個(gè)點(diǎn)—2個(gè)立柱—-3根線 的樹形結(jié)構(gòu)方式,那么我也可以接受其他的樹形結(jié)構(gòu)管理方式,只要60跟線的數(shù)據(jù)沒有混在一起,我們就可以在后面做樹形結(jié)構(gòu)的的調(diào)整。
因此在這里我們的考慮變成:怎么樣處理程序讓得到的60根線的樹形結(jié)構(gòu)可以體現(xiàn)出:分別屬于橋體10個(gè)點(diǎn)、分別屬于2個(gè)立柱、分別屬于立柱的3個(gè)固定點(diǎn)的結(jié)構(gòu)?也即是樹形結(jié)構(gòu)中必須體現(xiàn)出:10,3,2的結(jié)構(gòu),無論順序如何。
這里根據(jù)排列原則有六種樹形結(jié)構(gòu)是符合要求的
當(dāng)前的程序從輸入數(shù)據(jù)的樹形結(jié)構(gòu)來分析唯一可以做到這個(gè)效果的方法就是:將A組的數(shù)據(jù)做Graft,用戶可以去思考為什么其他方式都不可以?如下圖所示。

讀一下輸出的數(shù)據(jù)接結(jié)構(gòu),我們看到目前的數(shù)據(jù)結(jié)構(gòu)是這樣管理的:

其數(shù)據(jù)管理邏輯是:
缺圖
這個(gè)樹形結(jié)構(gòu)可以體現(xiàn)2,3,10的結(jié)構(gòu),因此他是合理的。但我們希望樹形結(jié)構(gòu)管理是這樣:底部10個(gè)點(diǎn)中的每個(gè)點(diǎn)分別于兩個(gè)立柱的3條線中最短的一條。因此數(shù)據(jù)結(jié)構(gòu)應(yīng)該是:

?因此接下來我們需要在GH中把當(dāng)前的樹形結(jié)構(gòu)做對(duì)應(yīng)調(diào)整:

在這里為調(diào)整樹形結(jié)構(gòu)使到的工具是Path Mapper,Path Mapper在調(diào)整樹形結(jié)構(gòu)方面有非常多的用途,但是如何靈活運(yùn)用它依賴于用戶必須能看懂樹形結(jié)構(gòu),讀懂樹形結(jié)構(gòu)代表的數(shù)據(jù)管理邏輯,還必須明確自己需要的樹形結(jié)構(gòu)是什么樣,才能配合Path Mapper做對(duì)應(yīng)的調(diào)整。
一旦樹形結(jié)構(gòu)調(diào)整正確了,后面的部分就很容處理了,跟之前的部分完全一樣:對(duì)個(gè)分支中的三條線的長度做從小到大的排序,根據(jù)排序把對(duì)應(yīng)第一條線跳出來即可。完整程序如下。

可以看到,雖然整個(gè)程序編寫過程涉及的樹形管理的理解和控制需要非常多的思考,但是寫出來的程序是很簡單的。
效果如下圖所示:

因?yàn)槌绦虮旧砜梢蕴幚砹⒅c(diǎn)輸入端的多分枝數(shù)據(jù)結(jié)構(gòu),因此對(duì)于更加復(fù)雜的設(shè)計(jì),例如我們需要將立柱數(shù)量變成5個(gè),僅僅需要從輸入端將對(duì)應(yīng)的5個(gè)分支的數(shù)據(jù)輸入即可,程序不需要做任何修改,仍然是簡單的結(jié)構(gòu)但是可以處理復(fù)雜的數(shù)據(jù),如下圖所示:


題外話
該部分并不是這個(gè)范例中的教學(xué),而是花點(diǎn)篇幅解釋一種我們認(rèn)為不夠好的編程思路。雖然這也是一種方法。
例如剛才我們提到的第三種方案:
找出底部10個(gè)點(diǎn)的每個(gè)點(diǎn)分別跟兩個(gè)立柱連接的3根線中最短的一根。
遇到這種需要處理復(fù)雜的樹形結(jié)構(gòu)的程序的時(shí)候,我們經(jīng)常見到這種做法:
1. 程序僅考慮處理單根柱子的情況,這樣程序會(huì)較為簡單,程序如下:

效果如下:

這個(gè)程序幾乎可以沿用最簡化方案的程序,但輸入僅僅是3個(gè)點(diǎn)(第一根柱子)。
當(dāng)需要處理多根立柱的數(shù)據(jù)的時(shí)候,將整個(gè)程序復(fù)制一個(gè),輸入端接入另一根柱子的3個(gè)點(diǎn),最后再把數(shù)據(jù)合并在一起如下圖所示。

這種做法雖然也可以做到本例中的效果,但是其的本質(zhì)是用多個(gè)一模一樣的程序并排分別處理不同立柱中的數(shù)據(jù),然后再把每個(gè)程序得到的數(shù)據(jù)合并在一起。
這種做法如果要說好處,應(yīng)該是可以少費(fèi)一點(diǎn)腦力把。但是缺點(diǎn)是很明顯的,如果柱子數(shù)量較多,那么就需要對(duì)應(yīng)數(shù)量的完全一樣的程序來并排處理,程序會(huì)因此變得很復(fù)雜,不利于修改和管理程序,程序執(zhí)行效率也會(huì)變得比較低。例如前例中最后提到的:如果設(shè)計(jì)變動(dòng)成5跟立柱,那么程序就必須復(fù)制出5個(gè)一模一樣的,分別處理每根跟立足的數(shù)據(jù),如下圖所示:

另外這種方式還有一個(gè)致命缺點(diǎn):如果柱子數(shù)量本身是一個(gè)設(shè)計(jì)中考慮的變量,那么如果柱子數(shù)量發(fā)生變動(dòng),每次都必須手動(dòng)修改程序,否則程序運(yùn)行就會(huì)出錯(cuò)。
也即是說,這種方法是因?yàn)槌绦驘o法處理輸入端的樹形結(jié)構(gòu)數(shù)據(jù),因此把數(shù)據(jù)結(jié)構(gòu)拆開讓多個(gè)程序分別處理,因此這種程序往往顯得不夠“聰明”,它不能適應(yīng)輸入的數(shù)據(jù)分支結(jié)構(gòu)發(fā)生變化的情況。
我們希望學(xué)員可以掌握能夠處理復(fù)雜的樹形結(jié)構(gòu)的程序的方法,寫出高效而聰明的程序輔助設(shè)計(jì)。