프랙탈이란

특정 도형패턴 무한 반복되는 구조를 말합니다.

 

프랙탈이 중요하고 유용한 이유는 특히 자기자신을 호출하는 재귀(recursive)구조때문입니다.

재귀구조는 거의 무한히 반복할 수 있어서 오늘날의 인공지능 계산에 있어서도 그 근간이자 뿌리가 되는 중요한 프로그래밍 기술입니다. 또한 뫼비우스의 띠, 무한증식, 블랙홀 그리고 LK99 초전도체 심지어 생명체의 영생 등과도 개념적으로 연결되는 원리입니다.

 

가장 최초이자 유명한 프랙탈 도형 중의 하나가 Sierpinsky 삼각형입니다.

 

삼각형의 각 선분을 2등분하는 점을 연결하여 뒤집어진 이등변삼각형을 삼각형 안에 만들고

다시 만들어지 각 삼각형들안에 역삼각형을 계속 무한히 만들어 갑니다.

갈수록 삼각형이 줄어들어서 눈에 보이지 않을 정도로 무한히 만들기는 어렵습니다.

 

 

먼저 삼각형 도형으로 내부 역삼각형을 3개씩 만드는 방식입니다. 너무 많은 단계를 거치면 시간이 오래 걸리고 보이지도 않으므로 현재는 6단계만 그립니다.

이등변 삼각형을 그릴 때 왼쪽 위 좌표와 넓이와 높이를 구해서 삼각형을 그리고 뒤집는 방식입니다.

그래서 내부의 삼각형이 뒤집어져 있습니다.

더보기
Option Explicit

Const PI = 3.141592
Const rad = 0.0174532925
Const ROOF = 6                      '반복회수

Sub DrawSierpinsky()

    Dim sld As Slide
    Dim shp As Shape
    Dim SW!, SH!, x!, y!, w!, h!
    Dim i%
    Dim arr() As Long
    
    With ActivePresentation.PageSetup
        SW = .SlideWidth
        SH = .SlideHeight
    End With
    
    Set sld = ActiveWindow.View.Slide
    
    h = SH
    w = h / Sin(60 * rad)
    x = SW / 2 - w / 2
    y = 0
    Set shp = sld.Shapes.AddShape(msoShapeIsoscelesTriangle, x, y, w, h)
    shp.Name = "S_s"
    shp.Fill.ForeColor.RGB = rgbLightGray
    shp.Line.ForeColor.RGB = rgbBlack
    shp.Line.Weight = 2
    
    'x번 재귀호출
    Call Sierpinsky(sld, x, y, w, h, ROOF, ROOF)
    
    '그룹
    For Each shp In sld.Shapes
        If shp.Name Like "S_*" Then
            i = i + 1
            ReDim Preserve arr(1 To i)
            arr(i) = shp.ZOrderPosition
        End If
    Next shp
    sld.Shapes.Range(arr).Group.Name = "Sierpinsky" & ROOF
    
End Sub

Function Sierpinsky(oSld As Slide, l!, t!, ww!, hh!, o%, tt%)
    Dim x!, y!, w!, h!
    Dim s As Shape
    
    If o > 0 Then
        x = l + ww / 4
        y = t + hh / 2
        w = ww / 2
        h = hh / 2
        Set s = oSld.Shapes.AddShape(msoShapeIsoscelesTriangle, x, y, w, h)
        s.Name = "S_" & tt - o + 1 & "_" & s.ZOrderPosition
        s.Fill.ForeColor.RGB = rgbWhite
        s.Line.ForeColor.RGB = rgbDarkGray
        s.Line.Weight = 1
        s.Rotation = 180
  
        Call Sierpinsky(oSld, x, t, w, h, o - 1, tt)
         
        Call Sierpinsky(oSld, l, y, w, h, o - 1, tt)
 
        Call Sierpinsky(oSld, l + w, y, w, h, o - 1, tt)
        
    End If
    
End Function

 

이번에는 Freeform 즉 좌표를 구해서 역삼각형을 그리는 방식입니다.

각 삼각형의 꼭지점의 좌표를 계산해서 세 점을 잇는 방식입니다. 

그래서 내부의 삼각형이 뒤집어지지 않았습니다.

더보기
Sub DrawSierpinsky2()

    Dim sld As Slide
    Dim shp As Shape
    Dim SW!, SH!, x!, y!, w!, h!
    Dim i%
    Dim arr() As Long
    
    With ActivePresentation.PageSetup
        SW = .SlideWidth
        SH = .SlideHeight
    End With
    
    Set sld = ActiveWindow.View.Slide
    
    h = SH
    w = h / Sin(60 * rad)
    x = SW / 2 - w / 2
    y = 0
    With sld.Shapes.BuildFreeform(msoEditingAuto, x + w / 2, y)
        .AddNodes msoSegmentLine, msoEditingAuto, x + w, y + h
        .AddNodes msoSegmentLine, msoEditingAuto, x, y + h
        .AddNodes msoSegmentLine, msoEditingAuto, x + w / 2, y
        Set shp = .ConvertToShape
    End With
    
    shp.Name = "S_s"
    shp.Fill.ForeColor.RGB = rgbLightGray
    shp.Line.ForeColor.RGB = rgbBlack
    shp.Line.Weight = 2
    
    'x번 재귀호출
    Call Sierpinsky2(sld, x, y, w, h, ROOF, ROOF)
    
    '그룹
    For Each shp In sld.Shapes
        If shp.Name Like "S_*" Then
            i = i + 1
            ReDim Preserve arr(1 To i)
            arr(i) = shp.ZOrderPosition
        End If
    Next shp
    sld.Shapes.Range(arr).Group.Name = "Sierpinsky2_" & ROOF
    
End Sub

Function Sierpinsky2(oSld As Slide, l!, t!, ww!, hh!, o%, tt%)
    Dim x!, y!, w!, h!
    Dim s As Shape
    
    If o > 0 Then
        x = l + ww / 4
        y = t + hh / 2
        w = ww / 2
        h = hh / 2
 
        With oSld.Shapes.BuildFreeform(msoEditingAuto, x, y)
            .AddNodes msoSegmentLine, msoEditingAuto, x + w, y
            .AddNodes msoSegmentLine, msoEditingAuto, x + w / 2, y + h
            .AddNodes msoSegmentLine, msoEditingAuto, x, y
            Set s = .ConvertToShape
        End With
    
        s.Name = "S_" & tt - o + 1 & "_" & s.ZOrderPosition
        s.Fill.ForeColor.RGB = rgbWhite
        s.Line.ForeColor.RGB = rgbDarkGray
        s.Line.Weight = 1
         
  
        Call Sierpinsky2(oSld, x, t, w, h, o - 1, tt)
         
        Call Sierpinsky2(oSld, l, y, w, h, o - 1, tt)
 
        Call Sierpinsky2(oSld, l + w, y, w, h, o - 1, tt)
        
    End If
    
End Function

여기서 msoSegmentLine이 아니라 msoSegmentCurve 로 그려주면 모서리가 둥그런 부드러운 삼각형이 됩니다.

또한 각 점마다 Bezier handle node가 2개씩 추가됩니다.

 

Sierpinsky 삼각형을 응용해서 사각형을 그리기도 하고 다른 다각형을 그릴 수도 있습니다.