아래와 같은 하나의 줄기에 두개의 가지만 있는 나무 모양의 프랙탈을 이진 나무(Binary Tree)라 한다. 쉽게 짐작할 수 있듯이 많은 자연의 성장 과정이 위와 유사한 구조로 되어 있다. 나무와 하천의 흐름이 가장 쉽게 찾아 볼 수 있는 예이다.
알고리즘
위의 차수가 3 인 이진 나무를 유심히 관찰하자. 구조가 완벽한 재귀적(순환적) 구조이다. 줄기에서 가지를 쳐 나가는 작업을 0 차 가지(잎)에 도달할 때까지 재귀적으로 반복하면 된다. 기본적인 알고리즘은 잡혔다. 이어서는 어떻게 가지를 쳐 나갈 것인가를 결정한다.
길이가 length 인 a 가지를 그린다.
왼쪽으로 30 도 회전하여 길이가 length*0.8 인 b 가지를 그린다.
오른쪽으로 60 도 회전하여 길이가 length*0.8 인 c 가지를 그린다.
3 번 과정을 마친 후 왼쪽으로 30 도 회전하여 진행 방향을 원래대로 환원시킨다.
예를 들어 차수 n = 3 인 경우 위와 같은 처리를 n 을 1 씩 줄여 나가면서 n = 0 이 될때까지 재귀적으로 반복시키면 위의 오른쪽의 나무가 그려진다. 이 때 주의할 점은 예를 들어 b 가지를 그린 후에는 선을 그리는 시작 위치를 b 가지의 시작점인 CP 로 환원시켜야 한다는 점이다. 그래야 위 알고리즘은 c 가지를 정확히 그린다. 이를 위해서 거북이 그래픽 클래스에 현재 거북이의 위치를 저장하는 스택을 포함하였다. 아래 부분은 거북이 클래스에 새로 추가된 함수의 코드이다.
// Header Filetypedef stack<Point3D> pstack;classTurtle{private: ... pstack PointStack; //위치를 저장할 스택 ...public: ... voidMarkCurrentPoint(void); //현재의 위치에 점을 그린다.voidPush(void); //현재의 위치를 저장한다.voidPop(void); //저장한 위치로 돌아간다.};
// Source FileTurtle::Turtle(void){ //스택 포인터 모두 제거while(PointStack.size()) {PointStack.pop(); } ...}void Turtle::SetStartPoint(float x,float y,float z){ //스택 포인터 모두 제거while(PointStack.size()) {PointStack.pop(); } ... } void Turtle::MarkCurrentPoint(void){glPointSize(5.0f);glBegin(GL_POINTS);glColor3f(1.0f,0.0f,0.0f);glVertex3f(PointList[PointList.size()-1].x,PointList[PointList.size()-1].y,PointList[PointList.size()-1].z);glColor3f(1.0f,1.0f,1.0f);glEnd();}void Turtle::Push(void){int index =PointList.size()-1; Point3D pt(PointList[index].x,PointList[index].y,PointList[index].z); //포인트 리스트에 저장되어 있는 마지막 점을 push 한다.PointStack.push(pt);}void Turtle::Pop(void){if(PointStack.size()) { Point3D pt(PointStack.top());PointStack.pop();PointList.push_back(pt); }}