0%

GGB 碎形製作

在 GeoGeBra 內製作碎形並不是太困難的事情,但是 GGB 很容易當機,因此要注意隨時存檔喔:D

Outline

  • 二元樹
  • 謝爾賓斯基三角形

二元樹 Binary Tree

定義

二元樹是每個節點最多只有兩個分支的樹狀結構
分支具有左右次序,不能隨意顛倒
而本次製作的是完全二元樹

Outline

  • 做出初始線段
  • 線段集
  • 工具
  • 迭代

製作

首先做出任意兩點 A, B 以及 5 個滑桿:

  • n - 迭代次數
  • r1, r2 - 左右線段比例
  • a, b - 左右角度




請特別注意那個"度"


做完應該長這樣


接下來我們開始下幾個指令:

1
2
3
4
5
6
u = Vector(A, B)
B1 = Translate(B, u)
B2 = Dilate(B1, r1, B)
B3 = Rotate(B2, a, B)
B4 = Dilate(B1, r2, B)
B5 = Rotate(B4, -b, B) //特別注意中間那個"-b"
  • Vector 產生起點至終點的向量
  • Translate 由起點位置往向量方向延伸做新點
  • Dilate 將輸入的向量伸縮
  • Rotate 將物件旋轉
    1
    2
    3
    4
    5
    // 各參數意義
    Vector( <Start Point>, <End Point> )
    Translate( <Vector>, <Start Point> )
    Dilate( <Object>, <Dilation Factor>, <Dilation Center Point> )
    Rotate( <Object>, <Angle>, <Point> )
    最後我們把這些東西作成線段並存成串列
    1
    2
    list1 = {Segment(B, B3), Segment(B, B5)}
    // Segment[ <Point>, <Point> ]
    然後把 B1 到 B5 隱藏起來

接下來要自訂工具


輸出:


輸入: 順序請按照圖片上的標示


來測試一下:D
新增隨意點 C、 D
然後輸入指令:

1
branch(C, D, a, b, r1, r2)


接下來我們要一步步做出最終的式子:D

1
IterationList(Flatten(Sequence(branch(Vertex(Element(list1,i),1),Vertex(Element(list1,i),2),a,b,r1,r2),i, 1,Length(list1))),list1,{{Segment(A,B)}},n) 

怕豹
所以先準備這條:D

1
branch(Vertex(Element(list1,i),1),Vertex(Element(list1,i),2),a,b,r1,r2) 
  • Vertex - 將線段中的點取出
  • Element - 將串列中的元素取出
    1
    2
    Vertex( <Segment>, <Index> )
    Element( <List>, <Position of Element n> )
    所以剛剛那條是
    “將 list1 中的第 i 個線段取出,並得到那兩個點”,再拿那兩個點做新線。可是 GGB 不認識 “i” 是誰ㄚ

所以要來實現一個”迴圈”的功能,加上”Sequence”!

1
Sequence( <Expression>, <Variable k>, <Start Value a>, <End Value b> )

把這個套上剛剛的那式就變成:

1
Sequence(branch(Vertex(Element(list1,i),1),Vertex(Element(list1,i),2),a,b,r1,r2),i,1,Length(list1)) 

最後把產生的串列攤平:

1
Flatten(Sequence(branch(Vertex(Element(list1,i),1),Vertex(Element(list1,i),2),a,b,r1,r2),i,1,Length(list1))) 

今天的主角: IterationList

1
IterationList( <Expression>, <Variable Name>, ..., <Start Values>, <Number of Iterations> )

我們以 list1 作為迭代物件,點 A、B 作為初始值

1
IterationList( <Expression>, list1, {{Segment(A,B)}},n)

再把上面那一長串指令帶入 expression:

1
IterationList(Flatten(Sequence(branch(Vertex(Element(list1,i),1),Vertex(Element(list1,i),2),a,b,r1,r2),i,1,Length(list1))), list1, {{Segment(A,B)}},n)

就大功告成啦:D

:D


謝爾賓斯基三角形 Sierpinsky Triangle

Outline

  • 三角形
  • 往內縮放
  • 迭代

製作

首先做出任意兩點 A、B
並使用 polygon() 函數做出正三角形

1
poly1 = Polygon(A, B, 3) // 後面的 3 代表三邊的正多邊形

接下來使用剛剛有提到的 Dilate() 來縮放三角形
並使用 Zip() 各對三頂點縮放

  • Zip(): 將 expression 內的變數以 list 內的替換
    1
    2
    3
    4
    Zip( <Expression>, <Var1>, <List1>, <Var2>, <List2>, ...)
    Dilate(poly1,0.5,O) // 以 0.5 倍縮放 poly1
    Zip(Dilate(poly1,0.5,O),O,{Vertex(poly1)}) // 將 {vertex(poly1)} 中的點代進 O
    // 指令請輸入第三行的


接下來就可以來迭代啦
下一種迭代技巧: Iteration()

  • Iteration: 將上一層得出的結果輸入到下一層中
    1
    Iteration( <Expression>, <Variable Name>, ..., <Start Values>, <Number of Iterations> )


1
Iteration(Join(Zip(Zip(Dilate(poly1,0.5,O),O,{Vertex(poly1)}),poly1,p1)),p1,{{Polygon(A,B,3)}},n)

以上式子做的事:

  • {{Polygon(A, B, 3)}} 作為初值
  • Zip() 將大括號內的串列取出
  • 放入 expression

本文章同步發布於 HackMD