//-----------------------------------------------------------------------------
// Fraktaly v pocitacove grafice
// Demonstracni priklad 54.3
// Autor: Pavel Tisnovsky
//
// Vykresleni Hilbertovy krivky pomoci rekurzivniho algoritmu.
// Po prekladu a spusteni programu se rekurzivne vykresli Hilbertova krivka,
// jejiz velikost je zvolena tak, aby se presne vlezla do nastavene
// velikosti okna.
// Ukonceni aplikace se provede klavesou [Esc] nebo klavesou [Q].
//-----------------------------------------------------------------------------
#ifdef __BORLANDC__
#include <windows.h>
#endif
#include <GL/glut.h> // hlavickovy soubor funkci GLUTu a OpenGL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define WINDOW_TITLE "Fraktaly 54.3" // titulek okna
#define WINDOW_WIDTH 512 // pocatecni velikost okna
#define WINDOW_HEIGHT 512
#define MAX_LENGTH 500000 // maximalni delka retezce
// hlavicky funkci
void hilbertA(int level);
void hilbertB(int level);
void hilbertC(int level);
void hilbertD(int level);
void gotoXY(int x, int y);
void lineRel(int deltaX, int deltaY);
int itersCount=1; // pocet aplikaci prepisovaciho pravidla
int dist0=WINDOW_WIDTH;
int dist=WINDOW_WIDTH;
int xx, yy; // pozice grafickeho kurzoru
//-----------------------------------------------------------------------------
// Vykresleni casti 'A' Hilbertovy krivky
//-----------------------------------------------------------------------------
void hilbertA(int level)
{
if (level>0) {
hilbertB(level-1); lineRel(0,dist);
hilbertA(level-1); lineRel(dist,0);
hilbertA(level-1); lineRel(0,-dist);
hilbertC(level-1);
}
}
//-----------------------------------------------------------------------------
// Vykresleni casti 'B' Hilbertovy krivky
//-----------------------------------------------------------------------------
void hilbertB(int level)
{
if (level > 0) {
hilbertA(level-1); lineRel(dist,0);
hilbertB(level-1); lineRel(0,dist);
hilbertB(level-1); lineRel(-dist,0);
hilbertD(level-1);
}
}
//-----------------------------------------------------------------------------
// Vykresleni casti 'C' Hilbertovy krivky
//-----------------------------------------------------------------------------
void hilbertC(int level)
{
if (level>0) {
hilbertD(level-1); lineRel(-dist,0);
hilbertC(level-1); lineRel(0,-dist);
hilbertC(level-1); lineRel(dist,0);
hilbertA(level-1);
}
}
//-----------------------------------------------------------------------------
// Vykresleni casti 'D' Hilbertovy krivky
//-----------------------------------------------------------------------------
void hilbertD(int level) {
if (level > 0) {
hilbertC(level-1); lineRel(0,-dist);
hilbertD(level-1); lineRel(-dist,0);
hilbertD(level-1); lineRel(0,dist);
hilbertB(level-1);
}
}
//-----------------------------------------------------------------------------
// Presun grafickeho kurzoru na souradnice [x, y]
//-----------------------------------------------------------------------------
void gotoXY(int x, int y)
{
xx=x;
yy=y;
}
//-----------------------------------------------------------------------------
// Presun grafickeho kurzoru o vektor [deltaX, deltaY] s kreslenim
//-----------------------------------------------------------------------------
void lineRel(int deltaX, int deltaY)
{
glVertex2i(xx, yy);
xx+=deltaX;
yy+=deltaY;
glVertex2i(xx, yy);
}
//-----------------------------------------------------------------------------
// Prekresleni Hilbertovy krivky
//-----------------------------------------------------------------------------
void recalcHilbert(void)
{
int i;
int level=5;
xx=yy=0;
dist=dist0;
// ziskat krok pro zadany pocet iteraci
for (i=level; i>0; i--)
dist/=2;
// prvni uroven kresleni
glColor3f(1.0f, 1.0f, 1.0f);
glBegin(GL_LINES);
gotoXY(dist/2, dist/2);
hilbertA(level);
glEnd();
}
//-----------------------------------------------------------------------------
// Funkce volana pro inicializaci vykreslovani
//-----------------------------------------------------------------------------
void onInit(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // barva pozadi
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // mod ulozeni pixelu
}
//-----------------------------------------------------------------------------
// Nastaveni souradneho systemu v zavislosti na velikosti okna
//-----------------------------------------------------------------------------
void onResize(int w, int h) // argumenty w a h reprezentuji novou velikost okna
{
glViewport(0, 0, w, h); // viditelna oblast pres cele okno
glMatrixMode(GL_PROJECTION); // zacatek modifikace projekcni matice
glLoadIdentity(); // vymazani projekcni matice (=identita)
glOrtho(0, w, 0, h, -1, 1); // mapovani abstraktnich souradnic do souradnic okna
}
//-----------------------------------------------------------------------------
// Tato callback funkce je zavolana pri kazdem prekresleni okna
//-----------------------------------------------------------------------------
void onDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT); // vymazani vsech bitovych rovin barvoveho bufferu
glDrawBuffer(GL_BACK); // pixmapa se bude kreslit do zadniho barvoveho bufferu
recalcHilbert(); // prekresleni Hilbertovy krivky
glFlush(); // provedeni a vykresleni vsech zmen
glutSwapBuffers();
}
//-----------------------------------------------------------------------------
// Tato callback funkce je zavolana pri stlaceni ASCII klavesy
//-----------------------------------------------------------------------------
#ifdef __BORLANDC__
#pragma option -w-par
#endif
void onKeyboard(unsigned char key, int x, int y)
{
key=(key>='A' && key<='Z') ? key-'A'+'a': key;
switch (key) {
case 27: // pokud byla stlacena klavesa ESC, konec programu
case 'q': exit(0); break; // totez co klavesa ESC
default: break;
}
}
#ifdef __BORLANDC__
#pragma option -w+par
#endif
//-----------------------------------------------------------------------------
// Hlavni funkce konzolove aplikace
//-----------------------------------------------------------------------------
int main(int argc, char **argv)
{
glutInit(&argc, argv); // inicializace knihovny GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(WINDOW_TITLE); // vytvoreni okna pro kresleni
glutReshapeWindow(WINDOW_WIDTH, WINDOW_HEIGHT);// zmena velikosti okna
glutPositionWindow(100, 100); // pozice leveho horniho rohu okna
glutDisplayFunc(onDisplay); // registrace funkce volane pri prekreslovani okna
glutReshapeFunc(onResize); // registrace funkce volane pri zmene velikosti okna
glutKeyboardFunc(onKeyboard); // registrace funkce volane pri stlaceni klavesy
onInit(); // inicializace vykreslovani
glutMainLoop(); // nekonecna smycka, kde se volaji zaregistrovane funkce
return 0; // navratova hodnota vracena operacnimu systemu
}
//-----------------------------------------------------------------------------
// finito
//-----------------------------------------------------------------------------