πŸ”Ί
Fractal Graphics With OpenGL
  • Introduction
  • μ €μž μ†Œκ°œ
  • Fractal에 λŒ€ν•˜μ—¬
  • μž¬κ·€μ  ν”„λž™νƒˆ
  • μΉΈν† μ–΄ λ¨Όμ§€
  • μ‹œμ–΄ν•€μŠ€ν‚€ μ–‘νƒ„μž
  • μ½”ν˜Έ 곑선
  • μ½”ν˜Έμ„¬
  • C곑선
  • λ“œλž˜κ³€ 곑선
  • 이진 λ‚˜λ¬΄
  • L-SYSTEM
  • L-SYSTEM 을 ν™œμš©ν•œ ν”„λž™νƒˆ
  • 뢀둝 : 거뢁이 κ·Έλž˜ν”½μŠ€μ˜ 이해
Powered by GitBook
On this page
  • L-SYSTEM κ°œμš”
  • F, +, -
  • λ³€ν™˜κ·œμΉ™
  • 곡리
  • L-SYSTEM κ΅¬ν˜„

Was this helpful?

L-SYSTEM

Previous이진 λ‚˜λ¬΄NextL-SYSTEM 을 ν™œμš©ν•œ ν”„λž™νƒˆ

Last updated 5 years ago

Was this helpful?

μ •ν•΄μ§„ κ·œμΉ™μ— μ˜ν•΄ νŠΉμ • λ¬Έμžμ—΄μ„ λ°˜λ³΅ν•˜μ—¬ μ „κ°œν•œ ν›„ μ „κ°œλœ λ¬Έμžμ—΄μ— μ˜κ±°ν•˜μ—¬ 그림을 κ·Έλ¦¬λŠ” 것을 L-μ‹œμŠ€ν…œμ΄λΌ ν•œλ‹€. 1986λ…„ λ¦°λ΄λ§ˆμ΄μ–΄(Lindenmayer)κ°€ μƒνƒœκ³„μ˜ μ„±μž₯ λͺ¨ν˜•, 특히 λ‚˜λ¬΄μ˜ λΆ„κΈ° λͺ¨ν˜•을 μ—°κ΅¬ν•˜λŠ” λͺ©μ μœΌλ‘œ κ³ μ•ˆν•˜μ˜€λ‹€.

L-SYSTEM κ°œμš”

F, +, -

L-μ‹œμŠ€ν…œμ—μ„œλŠ” 거뢁이 κ·Έλž˜ν”½κ³Ό λ¬Έμžμ—΄μ— μ˜κ±°ν•˜μ—¬ ν”„λž™νƒˆμ„ κ·Έλ¦¬λŠ”λ°, λ¬Έμžμ—΄μ˜ 문자 쀑 λ‹€μŒμ˜ 문자λ₯Ό λ§Œλ‚˜λ©΄ 거뢁이 κ·Έλž˜ν”½μ„ μˆ˜ν–‰ν•˜μ—¬ 선을 그리고 νšŒμ „μ„ ν•œλ‹€.

  • F : μΌμ •ν•œ 길이의 선을 그리고 ν˜„μž¬μ˜ 점을 μ„ μ˜ 끝점으둜 이동

    • : μ™Όμͺ½ λ°©ν–₯으둜 angle 만큼 νšŒμ „

    • : 였λ₯Έμͺ½ λ°©ν–₯으둜 angle 만큼 νšŒμ „

λ³€ν™˜κ·œμΉ™

μ•„λž˜μ™€ 같은 μ½”ν˜Έ 곑선을 κ·Έλ¦¬λŠ” 경우λ₯Ό 생각해 보자.

  1. 선을 κ·Έλ¦°λ‹€ ( F )

  2. 60 도 μ’ŒνšŒμ „ν•œλ‹€ ( + )

  3. 선을 κ·Έλ¦°λ‹€ ( F )

  4. 60 도 μš°νšŒμ „ν•œλ‹€ ( - )

  5. 60 도 μš°νšŒμ „ν•œλ‹€ ( - )

  6. 선을 κ·Έλ¦°λ‹€ ( F )

  7. 60 도 μ’ŒνšŒμ „ν•œλ‹€ ( + )

  8. 선을 κ·Έλ¦°λ‹€ ( F )

이에 ν•΄λ‹Ήν•˜λŠ” λ¬Έμžμ—΄μ€ λ‹€μŒκ³Ό κ°™λ‹€.

1μ°¨ λ³€ν™˜ : F+F--F+F

μœ„λŠ” 1 μ°¨μ›μ˜ μ½”ν˜Έ 곑선을 κ·Έλ¦° 것이닀. κ·Έλ ‡λ‹€λ©΄ μ•„λž˜μ˜ 2 μ°¨μ›μ˜ μ½”ν˜Έ 곑선은 μ–΄λ–»κ²Œ 그릴까? 1 μ°¨ μ½”ν˜Έ 곑선을 κ·Έλ¦¬λŠ” κ·œμΉ™μ„ A라 ν•œλ‹€λ©΄ A λŠ” λ‹€μŒκ³Ό 같이 λœλ‹€. A( F+F--F+F)

  1. A λ₯Ό κ·Έλ¦°λ‹€

  2. 60 도 μ’ŒνšŒμ „ν•œλ‹€ ( + )

  3. A λ₯Ό κ·Έλ¦°λ‹€

  4. 60 도 μš°νšŒμ „ν•œλ‹€ ( - )

  5. 60 도 μš°νšŒμ „ν•œλ‹€ ( - )

  6. A λ₯Ό κ·Έλ¦°λ‹€

  7. 60 도 μ’ŒνšŒμ „ν•œλ‹€ ( + )

  8. A λ₯Ό κ·Έλ¦°λ‹€.

이에 ν•΄λ‹Ήν•˜λŠ” λ¬Έμžμ—΄μ€ λ‹€μŒκ³Ό κ°™λ‹€.

A+A--A+A

μœ„μ˜ κ·œμΉ™μ„ A -> F + F - - F + F 둜 고쳐보면 λ‹€μŒκ³Ό κ°™λ‹€.

2μ°¨ λ³€ν™˜ : F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F

이λ₯Ό 3μ°¨ λ³€ν™˜ ν•΄ λ³Έλ‹€λ©΄ μ•„λž˜μ™€ 같이 λœλ‹€.

3μ°¨ λ³€ν™˜ : F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F+F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F+F+F--F+F+F+F--F+F--F+F--F+F+F+F--F+F

이와 같이 F -> F+F--F+F 둜 λ³€ν™˜ν•˜λŠ” κ·œμΉ™μ„ λ³€ν™˜κ·œμΉ™μ΄λΌκ³  ν•œλ‹€. 이 λ³€ν™˜ κ·œμΉ™μ„ 3번 λ³€ν™˜ν•˜λ©΄ μœ„μ˜ 3μ°¨ λ³€ν™˜μ΄ λ‚˜μ˜€κ²Œ λœλ‹€.

곡리

μˆ˜ν•™μ—μ„œ κ³΅λ¦¬λŠ” κ°€μž₯ 기본을 이룬닀. 예λ₯Ό λ“€μ–΄ 'μ‚Όκ°ν˜• λ‚΄κ°μ˜ 합은 180도이닀' κ°€ 곡리의 μ˜ˆμ΄λ‹€. μ΄λŸ¬ν•œ κ³΅λ¦¬μ—μ„œ λ§Žμ€ μˆ˜ν•™μ  정리듀이 λ§Œλ“€μ–΄μ‘Œλ‹€. 즉 κ³΅λ¦¬λŠ” κ°€μž₯ 기본적인 원칙이라고 ν•  수 μžˆλ‹€. 이 κ³΅λ¦¬λŠ” 마치 μœ μ „μžμ™€λ„ κ°™λ‹€. κ°„λ‹¨ν•œ μœ μ „μžκ°€ μƒλ¬Όμ²΄μ˜ μ—¬λŸ¬ κ°€μ§€ λ³΅μž‘ν•œ μ„±μž₯을 μ œμ–΄ν•œλ‹€. L-μ‹œμŠ€ν…œμ—μ„œλ„ κ³΅λ¦¬λŠ” 이와 λΉ„μŠ·ν•œ κ°œλ…μ„ κ°–λŠ”λ‹€. λ‹€μ‹œ λ§ν•˜μžλ©΄ L-μ‹œμŠ€ν…œμ—μ„œ κ³΅λ¦¬λŠ” λ³΅μž‘ν•œ ν”„λž™νƒˆμ•ˆμ— μˆ¨μ–΄ μžˆλŠ” μœ μ „μžλΌκ³  ν•  수 μžˆλ‹€.

L-SYSTEM κ΅¬ν˜„

μ§€κΈˆλΆ€ν„° κ΅¬ν˜„ν•΄λ³Ό L-μ‹œμŠ€ν…œμ€ λ‹€μŒκ³Ό 같은 κ·œμΉ™μ„ κ°–λŠ”λ‹€.

  • F : μ „μ§„

  • + : μ’ŒνšŒμ „

  • - : μš°νšŒμ „

  • @ : 점을 κ·Έλ¦°λ‹€.(μ—΄λ§€λ₯Ό κ·Έλ¦°λ‹€)

  • [ : ν˜„μž¬ μœ„μΉ˜μ™€ 각도λ₯Ό μŠ€νƒμ— μ €μž₯ν•œλ‹€.

  • ] : ν˜„μž¬ μœ„μΉ˜μ™€ 각도λ₯Ό μŠ€νƒμ˜ μ΅œμƒμœ„ μ•„μ΄ν…œμ˜ μœ„μΉ˜μ™€ κ°λ„λ‘œ μ„€μ •ν•œλ‹€.

  • { : ν˜„μž¬ μœ„μΉ˜λ§Œμ„ μŠ€νƒμ— μ €μž₯ν•œλ‹€.

  • } : ν˜„μž¬ μœ„μΉ˜λ₯Ό μŠ€νƒμ˜ μ΅œμƒμœ„ μ•„μ΄ν…œμ˜ μœ„μΉ˜μ™€ κ°λ„λ‘œ μ„€μ •ν•œλ‹€.

  • | : μ™Όμͺ½μœΌλ‘œ 180 도 νšŒμ „ν•œλ‹€.

이λ₯Ό μœ„ν•΄μ„œ 거뢁이 κ·Έλž˜ν”½ ν΄λž˜μŠ€κ°€ μ•½κ°„ λ³€ν˜•λ˜μ—ˆλ‹€. μŠ€νƒμ— μ €μž₯ν•˜λŠ” λ‚΄μš©κ³Ό Push() ν•¨μˆ˜μ— μƒˆλ‘œμš΄ μΈμžκ°€ μ„€μ •λœ 것이닀. μ†ŒμŠ€ μ½”λ“œλ₯Ό 보면 이해가 갈 것이닀.

struct StackItem
{
    Point3D cp;
    float angle;
    bool save_angle;
    StackItem() { cp.x=cp.y=cp.z=0.0f; angle=0.0f; save_angle=false; }
    StackItem(const Point3D& pt, float a, bool s)
    {
        cp.x = pt.x;
        cp.y = pt.y;
        cp.z = pt.z;
        angle = a;
        save_angle = s;
    }
    StackItem(const StackItem& i)
    {
        cp = i.cp;
        angle = i.angle;
        save_angle = i.save_angle;
    }
};

typedef stack<StackItem> pstack;

class Turtle
{
    ... 
    void Push(bool save_angle=true);
    void Pop(void);
    ... 
};
void Turtle::Push(bool save_angle)
{
    int index = PointList.size()-1;
    Point3D pt(PointList[index].x, PointList[index].y, PointList[index].z);
    //포인트 λ¦¬μŠ€νŠΈμ— μ €μž₯λ˜μ–΄ μžˆλŠ” λ§ˆμ§€λ§‰ 점을 push ν•œλ‹€.
     // save_angle 이 true 이면 pop μˆ˜ν–‰μ‹œ μ €μž₯된 각도가 ν˜„μž¬ 각도가 λœλ‹€.
    StackItem s(pt, angle, save_angle);
    PointStack.push(s);
}

void Turtle::Pop(void)
{
    if(PointStack.size())
    {
        StackItem s(PointStack.top());
        PointStack.pop();
        PointList.push_back(s.cp);
        if(s.save_angle)
        {
            angle = s.angle;
        }
    }
}

이제 L μ‹œμŠ€ν…œμ„ κ΅¬ν˜„ν•΄ 보자. μ•„λž˜λŠ” μ†ŒμŠ€ μ½”λ“œλ₯Ό λ‚˜νƒ€λ‚Έ 것이닀. λ”°λ‘œ μ„€λͺ…은 ν•˜μ§€ μ•Šκ³  주석을 λ‹¬μ•˜λ‹€.

/*******************************************************************************
{ LSystem Class
{ written by Sungcheol Kim
{ 2003.4.27
{
{ F : μ „μ§„
{ + : μ™Όμͺ½μœΌλ‘œ νšŒμ „
{ - : 였λ₯Έμͺ½μœΌλ‘œ νšŒμ „
{ | : μ™Όμͺ½μœΌλ‘œ 180 도 νšŒμ „
{ [ : ν˜„μž¬μ’Œν‘œ, ν˜„μž¬ 각도λ₯Ό μŠ€νƒμ—μ €μž₯
{ ] : ν˜„μž¬μ’Œν‘œ, ν˜„μž¬ 각도λ₯Ό μ €μž₯ν–ˆλ˜ μ’Œν‘œ,κ°λ„λ‘œ μ„€μ •
{ { : ν˜„μž¬μ’Œν‘œλ§Œ μ €μž₯
{ } : ν˜„μž¬μ’Œν‘œλ§Œ μ €μž₯ν–ˆλ˜ μ’Œν‘œλ‘œ μ„€μ •
{ @ : μ—΄λ§€λ₯Ό κ·Έλ¦°λ‹€.
*******************************************************************************/

#ifndef _LSYSTEM_H_
#define _LSYSTEM_H_

#pragma warning(disable : 4786)

#include <map>
#include <string>
#include "turtle.h"

using namespace std;

typedef map< char, string > trule_list;
typedef map< char, string >::iterator ai;

class LSystem
{
public:
    string TotalAxiom; //μ΅œμ’… 곡리
    trule_list TRuleList; //λ³€ν™˜κ·œμΉ™ 리슀트
    float angle; //νšŒμ „κ°λ„
    float length; //진행길이
    float factor; //길이의 배율
    Turtle *turtle; //거뢁이
public:
    LSystem();

    void SetAngle(float rotate_angle); //νšŒμ „ 각도λ₯Ό μ„€μ •ν•œλ‹€.
    void SetLength(float move_distance); //μ „μ§„ 거리λ₯Ό μ„€μ •ν•œλ‹€.
    void SetFactor(float magnification); //μ „μ§„ λΉ„μœ¨μ„ μ„€μ •ν•œλ‹€. μ΅œμ’… μ „μ§„ κ±°λ¦¬λŠ” length*factor 와 κ°™λ‹€.

    void SelectTurtle(Turtle *pturtle); //거뢁이λ₯Ό μ„ νƒν•œλ‹€.
    void AddTransRule(char name, string rule); //λ³€ν™˜ κ·œμΉ™μ„ 생성, μΆ”κ°€ν•œλ‹€.
    void MakeAxiom(string axiom, int n); //곡리λ₯Ό λ§Œλ“ λ‹€. n μ°¨κΉŒμ§€ 곡리 λ³€ν™˜
    void Draw(void); //곡리에 μ˜ν•œ L-μ‹œμŠ€ν…œμ„ κ·Έλ¦°λ‹€.
};

#endif
#include "LSystem.h"

LSystem::LSystem(void)
{
    angle = 0.0f;
    length = 1.0f;
    factor = 1.0f;
    turtle = NULL;
    TotalAxiom = "";
    TRuleList.clear();
}
void LSystem::SetAngle(float rotate_angle)
{
    angle = rotate_angle;
}
void LSystem::SetLength(float move_distance)
{
    length = move_distance;
}
void LSystem::SetFactor(float magnification)
{
    factor = magnification;
}
void LSystem::SelectTurtle(Turtle *pturtle)
{
    turtle = pturtle;
}
void LSystem::AddTransRule(char name, string rule)
{
    TRuleList[name] = rule;
}
void LSystem::MakeAxiom(string axiom, int n)
{
    ai fi;
    string buffer;
    TotalAxiom = axiom;
    for(int x=0; x<n; ++x) //nμ°¨κΉŒμ§€ λ³€ν™˜
    {
        buffer.erase(buffer.begin(), buffer.end());//곡리λ₯Ό 담을 버퍼
        for(int i=0; i<TotalAxiom.length(); ++i)
        {
            switch(TotalAxiom[i])
            {
                case 'F':
                    fi = TRuleList.find('F'); // F 에 λŒ€ν•΄μ„œ μ •μ˜λœ λ³€ν™˜ κ·œμΉ™μ΄ 있으면 κ·Έ κ·œμΉ™μ„ 버퍼에 λ„£κ³  μ•„λ‹ˆλ©΄ κ·Έλƒ₯ F(μ „μ§„) 자λ₯Ό λ„£λŠ”λ‹€.
                    if(fi!=TRuleList.end())
                    {
                        buffer += fi->second;
                    }
                    else
                    {
                        buffer += "F";
                    }
                    break;
                case '@':
                    buffer += "@";
                    break;
                case '+':
                    buffer += "+";
                    break;
                case '-':
                    buffer += "-";
                    break;
                case '[':
                    buffer += "[";
                    break;
                case ']':
                    buffer += "]";
                    break;
                case '{':
                    buffer += "{";
                    break;
                case '}':
                    buffer += "}";
                    break;
                case '|':
                    buffer += "|";
                    break;
                default: //μœ„μ˜ 문자 μ΄μ™Έμ˜ λ¬ΈμžλŠ” ν•΄λ‹Ή λ¬Έμžμ— ν•΄λ‹Ήν•˜λŠ” λ³€ν™˜κ·œμΉ™μ΄ 있으면 버퍼에 λ„£λŠ”λ‹€.
                    fi = TRuleList.find((char)(TotalAxiom[i]));
                    if(fi!=TRuleList.end())
                    {
                        buffer += fi->second;
                    }
                    break;
            }
        }
        TotalAxiom = buffer; //버퍼λ₯Ό μ΅œμ’… 곡리에 λ„£λŠ”λ‹€.
    }
}

void LSystem::Draw(void)
{
    for(string::iterator i = TotalAxiom.begin(); i!=TotalAxiom.end(); ++i)
    {
        switch((char)(*i))
        {
            case 'F':
                turtle->Forward(length*factor); //μ „μ§„
                break;
            case '@':
                turtle->MarkCurrentPoint(); //열맀그리기 
                break;
            case '+':
                turtle->Left(angle); //μ’ŒνšŒμ „ 
                break;
            case '-':
                turtle->Right(angle); //μš°νšŒμ „ 
                break;
            case '|':
                turtle->Left(180); //쒌둜 180 도 νšŒμ „
                break;
            case '[':
                turtle->Push(true); //μœ„μΉ˜, 각도 μ €μž₯
                break;
            case ']':
            case '}':
                turtle->Pop(); //μœ„μΉ˜ 또느 각도 화원
                break;
            case '{':
                turtle->Push(false); //μœ„μΉ˜ μ €μž₯
                break;
        }
    }
}

μ•„λž˜μ˜ μ½”λ“œλŠ” L-μ‹œμŠ€ν…œμ„ μ‚¬μš©ν•˜λŠ” 일련의 μ½”λ“œλ₯Ό 보여쀀닀.

#include "lib\egl.h"
#include "LSystem.h"

using namespace egl;

class RenderWindow : public Window
{
private:
    LSystem lsystem;
    Turtle turtle;
public:
    virtual BOOL InitGL(void);
    virtual void RenderGLScene(void);
};

BOOL RenderWindow::InitGL(void)
{
    Window::InitGL();

    lsystem.SelectTurtle(&turtle); //거뢁이 선택
    lsystem.SetAngle(60.0f); //νšŒμ „ 각도λ₯Ό 60 λ„λ‘œ μ„€μ •
    lsystem.SetLength(1.0f); //μ „μ§„ 거리λ₯Ό 1.0 으둜 μ„€μ •
    lsystem.SetFactor(1.0f); //μ „μ§„ λΉ„μœ¨μ„ 1.0 으둜 μ„€μ •
    lsystem.AddTransRule('F', "F+F--F+F"); //코흐 곑선을 κ·Έλ¦¬λŠ” λ³€ν™˜ κ·œμΉ™ F 생성 및 μΆ”κ°€
    lsystem.MakeAxiom("F", 3); //곡리 F λ₯Ό 3 차에 걸쳐 λ³€ν™˜ 

    return TRUE;
}

void RenderWindow::RenderGLScene(void)
{
    Window::RenderGLScene();
    turtle.SetStartPoint(-13.0f, 0.0f, -30.0f); //거뢁이의 μ‹œμž‘μœ„μΉ˜λ₯Ό μ •ν•˜κ³  
    lsystem.Draw(); //L-μ‹œμŠ€ν…œμ— μ˜ν•΄ μƒμ„±λœ ν”„λž™νƒˆμ„ κ·Έλ¦°λ‹€.
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    RenderWindow app;
    if(!app.Create(FALSE, "EDin's OpenGL - Texture2D"))
        return EXIT_FAILURE;
    return app.Run();
}

μ•„λž˜λŠ” μ‹€ν–‰ 결과이닀.

λ‹€μŒ μž₯μ—μ„œ L-μ‹œμŠ€ν…œμ„ ν™œμš©ν•œ μ—¬λŸ¬κ°€μ§€ ν”„λž™νƒˆμ„ 그렀보자.