L-SYSTEM
์ ํด์ง ๊ท์น์ ์ํด ํน์ ๋ฌธ์์ด์ ๋ฐ๋ณตํ์ฌ ์ ๊ฐํ ํ ์ ๊ฐ๋ ๋ฌธ์์ด์ ์๊ฑฐํ์ฌ ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๋ ๊ฒ์ L-์์คํ ์ด๋ผ ํ๋ค. 1986๋ ๋ฆฐ๋ด๋ง์ด์ด(Lindenmayer)๊ฐ ์ํ๊ณ์ ์ฑ์ฅ ๋ชจํ, ํนํ ๋๋ฌด์ ๋ถ๊ธฐ ๋ชจํ์ ์ฐ๊ตฌํ๋ ๋ชฉ์ ์ผ๋ก ๊ณ ์ํ์๋ค.
L-SYSTEM ๊ฐ์
F, +, -
L-์์คํ ์์๋ ๊ฑฐ๋ถ์ด ๊ทธ๋ํฝ๊ณผ ๋ฌธ์์ด์ ์๊ฑฐํ์ฌ ํ๋ํ์ ๊ทธ๋ฆฌ๋๋ฐ, ๋ฌธ์์ด์ ๋ฌธ์ ์ค ๋ค์์ ๋ฌธ์๋ฅผ ๋ง๋๋ฉด ๊ฑฐ๋ถ์ด ๊ทธ๋ํฝ์ ์ํํ์ฌ ์ ์ ๊ทธ๋ฆฌ๊ณ ํ์ ์ ํ๋ค.
F : ์ผ์ ํ ๊ธธ์ด์ ์ ์ ๊ทธ๋ฆฌ๊ณ ํ์ฌ์ ์ ์ ์ ์ ๋์ ์ผ๋ก ์ด๋
: ์ผ์ชฝ ๋ฐฉํฅ์ผ๋ก angle ๋งํผ ํ์
: ์ค๋ฅธ์ชฝ ๋ฐฉํฅ์ผ๋ก angle ๋งํผ ํ์
๋ณํ๊ท์น
์๋์ ๊ฐ์ ์ฝํธ ๊ณก์ ์ ๊ทธ๋ฆฌ๋ ๊ฒฝ์ฐ๋ฅผ ์๊ฐํด ๋ณด์.

์ ์ ๊ทธ๋ฆฐ๋ค ( F )
60 ๋ ์ขํ์ ํ๋ค ( + )
์ ์ ๊ทธ๋ฆฐ๋ค ( F )
60 ๋ ์ฐํ์ ํ๋ค ( - )
60 ๋ ์ฐํ์ ํ๋ค ( - )
์ ์ ๊ทธ๋ฆฐ๋ค ( F )
60 ๋ ์ขํ์ ํ๋ค ( + )
์ ์ ๊ทธ๋ฆฐ๋ค ( F )
์ด์ ํด๋นํ๋ ๋ฌธ์์ด์ ๋ค์๊ณผ ๊ฐ๋ค.
1์ฐจ ๋ณํ : F+F--F+F
์๋ 1 ์ฐจ์์ ์ฝํธ ๊ณก์ ์ ๊ทธ๋ฆฐ ๊ฒ์ด๋ค. ๊ทธ๋ ๋ค๋ฉด ์๋์ 2 ์ฐจ์์ ์ฝํธ ๊ณก์ ์ ์ด๋ป๊ฒ ๊ทธ๋ฆด๊น? 1 ์ฐจ ์ฝํธ ๊ณก์ ์ ๊ทธ๋ฆฌ๋ ๊ท์น์ A๋ผ ํ๋ค๋ฉด A ๋ ๋ค์๊ณผ ๊ฐ์ด ๋๋ค. A( F+F--F+F)

A ๋ฅผ ๊ทธ๋ฆฐ๋ค
60 ๋ ์ขํ์ ํ๋ค ( + )
A ๋ฅผ ๊ทธ๋ฆฐ๋ค
60 ๋ ์ฐํ์ ํ๋ค ( - )
60 ๋ ์ฐํ์ ํ๋ค ( - )
A ๋ฅผ ๊ทธ๋ฆฐ๋ค
60 ๋ ์ขํ์ ํ๋ค ( + )
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-์์คํ ์ ํ์ฉํ ์ฌ๋ฌ๊ฐ์ง ํ๋ํ์ ๊ทธ๋ ค๋ณด์.
Last updated
Was this helpful?