2011/11/13

Square Fractal 方塊碎形 (rhinoscript教學)

為了讓大家更有些興趣來玩玩看rhinoscript,
所以讓我來把CCC的講義案例做簡單的白話文翻譯,

你就會知道程式碼就跟學任何語言一樣,由語法(邏輯順序)跟單字(指令)組成爾爾.
有鑑於CCC常說學長教學寫了寫就不寫了的事會發生在我身上,
因此我要非常不負責的告訴大家,林杯想寫什麼就寫什麼,
你要學什麼基礎就去把前面的processing教學給我看完,

因為我只會拿processing裡的指令跟rhinoscript做相似的比對,
這種東西就是要會舉一反三麻是不是?    速西ㄟ~~~~


...........................................  :-x


如果你有跟著我之前學processing一樣從零開始,
那我現在講得你應該一點就通,
如果你看得有點吃力,代表你之前不好好砸時間下去摸,
現在趕快回去把之前的processing教學看一看還來得及.

師父叫你蹲馬步跟挑水桶不是沒有道理滴!


好了,誠如CCC所說的,grasshopper在做for loop這種東西上是比較弱的,
(幹,for loop是什麼都不知道就趕快看這裡)
相對如果你只是做單純的遞歸,那grasshopper的確會比較方便.
簡單來說,如果你只是要做形,那就用grasshopper,
如果要做較偏向前因後果的空間關係演算法,那rhinoscript會比較吃香.
這篇要講的就是square fractal,方塊碎形,以下.


---------------------------------------------------------------------------------------------------------



















Call Rhino.EnableRedraw(False)
Call Fractal_01(0,0,30,2)
Call Rhino.EnableRedraw(True)



Sub Fractal_01(X,Y,L,n)
  Dim a,b,c,d,E
  a = Array(X+L/2,Y+L/2,0)
  b = Array(X-L/2,Y+L/2,0)
  c = Array(X-L/2,Y-L/2,0)
  d = Array(X+L/2,Y-L/2,0)
  If n > 0 Then
    Call Rhino.AddSrfPt(Array(a,b,c,d))
    E = 0.75 * L
    Call Fractal_01(X+E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y-E,L/2,n-1)
    Call Fractal_01(X+E,Y-E,L/2,n-1)
  End If
End Sub



基本上我們要將程式碼先拆成兩部份來看.




Call Rhino.EnableRedraw(False)
Call Fractal_01(0,0,30,2)
Call Rhino.EnableRedraw(True)

Sub Fractal_01(X,Y,L,n)
  Dim a,b,c,d,E
  a = Array(X+L/2,Y+L/2,0)
  b = Array(X-L/2,Y+L/2,0)
  c = Array(X-L/2,Y-L/2,0)
  d = Array(X+L/2,Y-L/2,0)
  If n > 0 Then
    Call Rhino.AddSrfPt(Array(a,b,c,d))
    E = 0.75 * L
    Call Fractal_01(X+E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y-E,L/2,n-1)
    Call Fractal_01(X+E,Y-E,L/2,n-1)
  End If
End Sub

黃色的部份那些call就是在叫指令的意思,
所以我們會說call taxi意思是叫計程車不是沒有道理的.


橘色的部份在processing中就是所謂的void,一種可撰寫指令的空集合.
(如果你忘了void是什麼請看這裡)
所以Sub ______ ()
的底線就是你集合的名稱,
括號內就就是你會在集合內用到的參數代號.


且讓我們先一行一行看橘色的部分,
噢對了,在processing裡//之後代表無效程式碼,在rhinoscript內則是在'之後.


Sub Fractal_01(X,Y,L,n)
'有一個叫做Fractal_01的集合,這集合內需要代入X,Y,L,n這四個數.

  Dim a,b,c,d,E
'dim就跟processing內一樣,你有什麼數需要被定義就需要先來個dim.

  a = Array(X+L/2,Y+L/2,0)

  b = Array(X-L/2,Y+L/2,0)
  c = Array(X-L/2,Y-L/2,0)
  d = Array(X+L/2,Y-L/2,0)

'這四行就是在到時有X,L等數被代入時,a,b,c,d就會有各自的值.

  If n > 0 Then
'當代入n的數大於零時則會啟動下面的三項事情

    Call Rhino.AddSrfPt(Array(a,b,c,d))
'當n>0時,執行AddSrfPt這指令,基本上就是一個需要三到四個點構成一個面的指令,
'如果你不知道這些指令是幹麻的,在rhinoscript editor > help > index下搜尋

    E = 0.75 * L
'當n>0時,E = 0.75 * L,這單純是演算碎形時的需要

    Call Fractal_01(X+E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y-E,L/2,n-1)
    Call Fractal_01(X+E,Y-E,L/2,n-1)

'當n>0時,分別call fractal_01四次,只是原本代入的X,Y,L,n會變
'你可以看到最後一項n-1,這就是為了呼應前面if n > 0所做的應對,
'所以我們知道總共在算過兩次之後n > 0就不成立了

  End If
'因為用到if就要end if

End Sub
'因為用到一個sub就要end sub


好,如果你到上面基本的理解都沒問題,
我們就可把黃色部份的數代入橘色內看看CCC到底在想什麼.


Call Rhino.EnableRedraw(False)
'我不太知道EnableRedraw這指令到底要怎麼用,但基本上不影響運算

Call Fractal_01(0,0,30,2)
'我們由此可知一開始代入X,Y,L,n這四個數的值是0,0,30,2

Call Rhino.EnableRedraw(True)
'等我了解這指令再解釋

讓我們看看電腦是怎麼看這些script的,
因為我們知道n一開始為2,所以會做兩次運算.

首先(0,0,30,2)代入(X,Y,L,n)後

  a = Array(X+L/2,Y+L/2,0)
  b = Array(X-L/2,Y+L/2,0)
  c = Array(X-L/2,Y-L/2,0)
  d = Array(X+L/2,Y-L/2,0)

會變成

  a = Array(0+30/2,0+30/2,0)
  b = Array(0-30/2,0+30/2,0)
  c = Array(0-30/2,0-30/2,0)
  d = Array(0+30/2,0-30/2,0)
也就是

  a = Array(15,15,0)
  b = Array(-15,15,0)
  c = Array(-15,-15,0)
  d = Array(15,-15,0)


而因為n=2是> 0的,因此會發動
Call Rhino.AddSrfPt(Array(a,b,c,d))
也因此我們知道這個分別在四象限的點會連成一個面,

一個邊長為30的正方形.















 同時,E = 0.75 * L一算即是E = 0.75 * 30 = 22.5


而之下的
    Call Fractal_01(X+E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y+E,L/2,n-1)
    Call Fractal_01(X-E,Y-E,L/2,n-1)
    Call Fractal_01(X+E,Y-E,L/2,n-1)
就變成

    Call Fractal_01(0+22.5,0+22.5,30/2,2-1)
    Call Fractal_01(0-22.5,0+22.5,30/2,2-1)
    Call Fractal_01(0-22.5,0-22.5,30/2,2-1)
    Call Fractal_01(0+22.5,0-22.5,30/2,2-1)

意即
    Call Fractal_01(22.5,22.5,15,1)
    Call Fractal_01(-22.5,22.5,15,1)
    Call Fractal_01(-22.5,-22.5,15,1)
    Call Fractal_01(22.5,-22.5,15,1)


因此這四個Call Fractal_01又會分別再去生產四個方形,
Call Fractal_01(22.5,22.5,15,1)的方形是
  a = Array(22.5+15/2,22.5+15/2,0)
  b = Array(22.5-15/2,22.5+15/2,0)
  c = Array(22.5-15/2,22.5-15/2,0)
  d = Array(22.5+15/2,22.5-15/2,0)

  a = Array(30,30,0)
  b = Array(15,30,0)
  c = Array(15,15,0)
  d = Array(30,15,0)
其他三個同理,之後分裂越來越多只是把n加大而已.


下圖則是Call Fractal_01(0,0,30,6)的結果


















但寫到此刻,我發現一個地方不對勁,
不合邏輯令我百思不得其解,你發現了嗎?

沒有留言:

張貼留言