新文章

Tuesday, June 19, 2012

Grasshopper中的資料控制

【為了讓不同程度的使用者包括初學者也可以閱讀這篇文章。本文使用的範例程式結構簡單但足夠典型。著重于介紹思路的分析,反映設計過程中遇到的資料處理及如何解決問題的思維過程。對涉及的工具就使用不做細緻的介紹,敬請見諒】--by McNeelAsia Dixon SUN

在使用參數化設計工具輔助設計的過程中使用者需要解決兩個階段的問題:

  • 根據設計要求規劃合理的程式設計邏輯順序。(程式設計思維過程)
  • 使用參數化設計工具實現設計功能。(技術處理過程)

在這幾年接觸學習參數化設計的學員的過程中,我們發現大部分學員會在這兩個階段遇到不同的問題。

其中,第一個階段屬於使用者程式設計思維方式主導的部分。由於大部分設計背景的學員之前並沒有接受過系統的程式設計課程的訓練,因此普偏在程式設計邏輯思維方面較為欠缺。本文的範例中對實際的設計要求有簡單的程式設計邏輯思維方法的解釋可作為參考。

第二個階段屬於技術細節的部分。我們注意到大部分Grasshopper(以下簡稱GH)用戶遇到的技術細節問題可以歸類於以下三方面:

1.對GH的工具的運行原理和使用方法不夠理解。這是比較初級的問題。

2對GH工具涉及到的曲面造型技術缺乏足夠瞭解。具體為:對NURBS的幾何特性、NURBS資料的程式設計控制方法和曲面造型思路缺乏瞭解。因此程式中涉及曲線曲面控制處理的部分較難深入和靈活運用。這部分較為欠缺的使用者建議可以參加Rhino原廠開設的曲面造型課程的短期學習班做系統的補充。

3.除了以上兩個參見的問題之外,大部分學員都會在學習到一個階段後遇到GH樹形據結構資料管理的理解和控制方面的困難。這通常是所有學習GH者都需要跨過的一道門檻。

和其他的參數化設計軟體和程式設計軟體不同,GH採用的樹形據結構的資料管理是很特別的,它可以讓用戶更容易的管理和控制龐大和複雜的資料,以實現用參數化控制複雜的功能甚至是系統的設計(如:一整棟建築),但前提是使用者必須對這種資料管理和控制的原理有對應的瞭解,才能對其進行合理和靈活的控制。這部分是很多人學習中遇到的難點或者難以深入到的部分。

為了説明GH使用者GH的理解樹形資料結構在參數化設計過程中起到的作用,以及如何配合設計需求處理和控制它,我們使用GH原廠課程中的一個範例來做介紹。

範例

我要設計一座懸掛結構的橋!

這是一個懸掛結構的橋,如圖是整個橋的側面結構。黑色矩形方框是橋體。橋體上10個紅色點橋體的固定點。用鋼絲懸掛固定。頂上的兩個藍色矩形代表懸掛橋的兩個立柱,每個立柱上各有3個鋼絲固定點。我們需要解決的問題就是如何在橋體和柱子的固定點之間拉鋼絲。

這個設計中遇到的實際問題可以被簡化為點連線的問題,即:

如何在下面10個點和上面6個點(2*3結構)之間做各種連線方式的設計。

為了理清設計思路,我們先看兩種最極端的連線方式:

1.最穩固的方式(連線最複雜)

2.最省材料的方式(連線最簡單)


最穩固的連線方式(連線最複雜)

所謂最穩固的方式(並且是合理的),也即是:

橋體的每個點(地下的10個)都和柱子上的每個點(頂上的6個)都做連線。

這個連線方式題就可以簡化為:10個點和6個點之間的連線組合,很明顯會有60條線(10*6)。

雖說是最複雜的連線方式,但是在程式設計邏輯中卻是最簡單的,程式如下圖:

為了集中表述問題的關鍵部分,圖片中去掉了點生成的程式部分。

在程式處理細節方面注意line工具的內部必須切換成cross的資料對應方式,這在程式外部看不出來。

連接效果如圖:


雖然這是最穩固的連接方式,邏輯上來講很簡單,程式處理也很容易。但連接的視覺效果卻不夠好,因為橋體每個點都有6跟連線,因此連線過於密集(60根連線),造價也較貴(很多更多鋼纜)。

最省材料的方式(連線最簡單)

再來看最省材料的連接方式:

即:橋體上的每個點(10個點)只使用一根鋼絲做固定。從連接的角度可以理解為:

底部的10個點每個點都和上面的6個點的其中之一做連接。

那麼具體和頂部的哪一個點做連接呢?我認為和最近的一個點連接是最合理的,因為最省材料而且鋼纜牽引的角度也更趨近于垂直向上,力學上來說較為合理。 所以整個連線的邏輯就是:

底部的10個點中每個點與頂上的6個點中最近的一個點做連線。

這個邏輯就稍微複雜一點了,從程式設計邏輯考慮實現這個效果可以分為兩個步驟實現:

1.首先分別做出底部的每個點和頂上6個點的連線。

2.然後從每個底部點的6個連線中挑選出最短的一根。

在這個程式設計邏輯中要特別注意:第一步驟的程式輸出的資料是有結構分支做管理的,因為第一步實際上仍然是得到60根線(10個點其中每個點6根線),但是如果這60根線是混在一起的,那麼在第二步驟中就無法找出屬於某一點的6根連線,因此也無法完成第二個步驟中規劃的邏輯效果。因此這60跟線應該是依據底部的10個點來做分支處理的,也即是:第一步輸出的資料結構應該包含有10個分支,對應的是底部的10個點,而每個分支裡面有6個資料,代表連接到某個點的6根線。這種資料結構可以反映60跟線中那些線是連接那個點的,資料結構圖和GH中的Param Viewer觀察輸出結構應該如下圖所示:


Param Viewer是用於檢查樹形結構常用的工具,使用者應該熟悉如何去閱讀它

第一個步驟的程式如下圖所示:

程式處理細節:為了保證輸出結果是分組樹形結構,因此根據GH的資料對應法則,必須把B端的資料做Graft處理,這樣資料的對應方式就變成每個點和頂部的六個點做資料對應連接線。

< 用戶應該瞭解:做Graft之後資料產生什麼樣的結構變化?為什麼要把B端做Graft,而不是把A端做Graft?如果對A端做Graft會變成什麼樣的資料結構?為什麼需要這樣的資料結構?>

接下來的程式實現第二個步驟:從得到的60根條線中,找出連接每個點的6條線中最短的一根。

這個功能從程式設計邏輯角度思考可以這樣解決:首先對每個點的六條線的長度做從小到大的排序,然後從中挑第一條線,因為第一條線必定是每個點的六條線中最短的一根。這部分並不涉及資料結構的處理,理解工具運作的原理就可以做出來,程式如下。


效果如下圖,每條線都是底部的每個點與頂部6個點中最近的一個點的連線:


在這個例子中,如何控制程式將輸出的60根線使用樹形結構做正確的歸屬管理是程式實現正確連線效果的關鍵。

綜合優化的方案

在實際設計中,很多時候採用的解決方案都不是那麼極端的,例如第一個方案安全性自然是最好,但是因為連線很多意味著實際項目中鋼纜也必須使用很多因此造價很貴。而第二種方案雖然造假最便宜,但是因為每個橋體上的固定點子只有一根鋼纜固定,因此安全性最差。而且可以試想如果其中有一根柱子斷了,那麼整個橋就有一半的區域完全沒有支撐,因此很可能整個橋馬上就垮了。所以有時候我們會綜合造價、成本等因素來考慮解決方案。

因此從加強安全性角度考慮可以使每個橋體的固定點都有2根鋼纜固定,且兩根鋼纜分別連接不同的立柱。再從造價和力學角度考慮讓每根鋼纜連接對應的立柱中最短的一個點,這樣可以在安全性和造價方面獲得一個不錯的平衡。

因此這個設計的要求就是:

找出底部10個點的每個點分別跟兩個立柱連接的3根線中最短的一根。

這個設計從邏輯上來講其實和第二個方案比較接近,區別在於第二個設計僅僅要求找出每個點的6個連線中最短的一個,而這個設計要求還需將每個點的6根線按照立柱的歸屬分成2組,然後再找出每一組中的最短的線。因此輸出的60根線應該是按照如下的樹形結構管理:

在明確希望得到的資料結構後,來看程式:


首先在程式的立柱點輸入端輸入的資料必須按照立柱歸宿做樹形結構的管理,兩個分支對應兩個立柱,每個分支裡面3個資料對應每個立柱的三個固定點。

<立柱的樹形資料結構依賴於前端的程式對應生成>

在接下來的連線程式部分會遇到資料對應方面的控制問題,當前程式部分結構如下:


現在A和B組資料的結構與之前不同(並非單分支對單分支),按照GH的資料對規則來看,事實上這裡無論怎麼調整都不可能直接得到我們要的資料結構。<想想為什麼>

因此我們的考慮就是退而求其次:如果沒有辦法直接得到60根線的:10個點—2個立柱—-3根線 的樹形結構方式,那麼我也可以接受其他的樹形結構管理方式,只要60跟線的資料沒有混在一起,我們就可以在後面做樹形結構的的調整。

因此在這裡我們的考慮變成:怎麼樣處理常式讓得到的60根線的樹形結構可以體現出:分別屬於橋體10個點、分別屬於2個立柱、分別屬於立柱的3個固定點的結構?也即是樹形結構中必須體現出:10,3,2的結構,無論順序如何。

<這裡根據排列原則有六種樹形結構是符合要求的>

當前的程式從輸入資料的樹形結構來分析唯一可以做到這個效果的方法就是:將A組的資料做Graft , <使用者可以去思考為什麼其他方式都不可以?>如下圖所示。


讀一下輸出的資料接結構,我們看到目前的資料結構是這樣管理的:


其資料管理邏輯是:


這個樹形結構可以體現2,3,10的結構,因此他是合理的。但我們希望樹形結構管理是這樣:底部10個點中的每個點分別于兩個立柱的3條線中最短的一條。因此資料結構應該是:


因此接下來我們需要在GH中把當前的樹形結構做對應調整:


<在這裡為調整樹形結構使到的工具是Path Mapper,Path Mapper在調整樹形結構方面有非常多的用途,但是如何靈活運用它依賴於用戶必須能看懂樹形結構,讀懂樹形結構代表的資料管理邏輯,還必須明確自己需要的樹形結構是什麼樣,才能配合Path Mapper做對應的調整。>

一旦樹形結構調整正確了,後面的部分就很容易處理了,跟之前的部分完全一樣:對個分支中的三條線的長度做從小到大的排序,根據排序把對應第一條線跳出來即可。完整程式如下:


可以看到,雖然整個程式編寫過程涉及的樹形管理的理解和控制需要非常多的思考,但是寫出來的程式是很簡單的。

效果如下圖所示:


因為程式本身可以處理立柱點輸入端的多分枝資料結構,因此對於更加複雜的設計,例如我們需要將立柱數量變成5個,僅僅需要從輸入端將對應的5個分支的資料登錄即可,程式不需要做任何修改,仍然是簡單的結構但是可以處理複雜的資料,如下圖所示:




題外話

該部分並不是這個範例中的教學,而是花點篇幅解釋一種我們認為不夠好的程式設計思路。雖然這也是一種方法。

例如剛才我們提到的第三種方案:

找出底部10個點的每個點分別跟兩個立柱連接的3根線中最短的一根。

遇到這種需要處理複雜的樹形結構的程式的時候,我們經常見到這種做法:

1,程式僅考慮處理單根柱子的情況,這樣程式會較為簡單,程式如下:


效果如下:


這個程式幾乎可以沿用最簡化方案的程式,但輸入僅僅是3個點(第一根柱子)。

當需要處理多根立柱的資料的時候,將整個程式複製一個,輸入端接入另一根柱子的3個點,最後再把資料合併在一起如下圖所示:


這種做法雖然也可以做到本例中的效果,但是其的本質是用多個一模一樣的程式並排分別處理不同立柱中的資料,然後再把每個程式得到的資料合併在一起。

這種做法如果要說好處,應該是可以少費一點腦力把。但是缺點是很明顯的,如果柱子數量較多,那麼就需要對應數量的完全一樣的程式來並排處理,程式會因此變得很複雜,不利於修改和管理程式,程式執行效率也會變得比較低。例如前例中最後提到的:如果設計變動成5跟立柱,那麼程式就必須複製出5個一模一樣的,分別處理每根跟立足的資料,如下圖所示:



另外這種方式還有一個致命缺點:如果柱子數量本身是一個設計中考慮的變數,那麼如果柱子數量發生變動,每次都必須手動修改程式,否則程式運行就會出錯。

也即是說,這種方法是因為程式無法處理輸入端的樹形結構資料,因此把資料結構拆開讓多個程式分別處理,因此這種程式往往顯得不夠“聰明”,它不能適應輸入的資料分支結構發生變化的情況。

我們希望學員可以掌握能夠處理複雜的樹形結構的程式的方法,寫出高效而聰明的程式輔助設計。