Загрузка данных
#include <windows.h>
#include <GL/glut.h>
#include <cmath>
#include <vector>
#include <string>
// Структура для хранения точки
struct Point {
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
};
// Глобальные переменные для кривой дракона
std::vector<Point> dragonPoints;
int dragonLevel = 12; // уровень детализации (оптимально 10-14)
double dragonStartX = -0.3; // начальная позиция
double dragonStartY = 0.0;
double dragonSize = 0.8; // масштаб кривой
// Шаг черепашьей графики для кривой дракона (L-система)
void dragonTurtle(std::vector<Point>& points, double& x, double& y,
double& angle, double step, const std::string& str) {
for (char c : str) {
if (c == 'F') {
// Двигаемся вперёд и добавляем точку
double rad = angle * M_PI / 180.0;
x += step * cos(rad);
y += step * sin(rad);
points.push_back(Point(x, y));
} else if (c == '+') {
// Поворот вправо на 90°
angle += 90.0;
} else if (c == '-') {
// Поворот влево на 90°
angle -= 90.0;
}
// Символы X и Y игнорируются при отрисовке — они только для рекурсии
}
}
// Рекурсивное построение L-строки для кривой дракона
// Аксиома: FX
// Правила: X -> X+YF+
// Y -> -FX-Y
std::string generateDragonLSystem(int level) {
std::string current = "FX";
for (int i = 0; i < level; i++) {
std::string next;
for (char c : current) {
if (c == 'X') {
next += "X+YF+";
} else if (c == 'Y') {
next += "-FX-Y";
} else {
next += c; // F, +, - копируем как есть
}
}
current = next;
}
return current;
}
// Построение массива точек кривой дракона
void buildDragonCurve() {
dragonPoints.clear();
std::string lstring = generateDragonLSystem(dragonLevel);
double x = dragonStartX;
double y = dragonStartY;
double angle = 0.0; // начальный угол (в градусах)
// Длина шага уменьшается с ростом уровня, чтобы кривая помещалась в окно
double step = dragonSize / pow(sqrt(2.0), dragonLevel);
dragonPoints.push_back(Point(x, y));
dragonTurtle(dragonPoints, x, y, angle, step, lstring);
}
// Функция отрисовки
void display() {
glClear(GL_COLOR_BUFFER_BIT);
// Рисуем координатные оси (серые)
glColor3f(0.3f, 0.3f, 0.3f);
glBegin(GL_LINES);
glVertex2f(-1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
glVertex2f(0.0f, -1.0f); glVertex2f(0.0f, 1.0f);
glEnd();
// Рисуем кривую дракона
if (!dragonPoints.empty()) {
glColor3f(0.2f, 0.8f, 1.0f); // голубой цвет
glLineWidth(1.5f);
glBegin(GL_LINE_STRIP);
for (const Point& p : dragonPoints) {
glVertex2d(p.x, p.y);
}
glEnd();
}
glFlush();
}
// Обработка изменения размеров окна
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double aspect = (double)w / h;
if (aspect >= 1.0) {
gluOrtho2D(-aspect, aspect, -1.0, 1.0);
} else {
gluOrtho2D(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect);
}
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Обработка клавиатуры
void keyboard(unsigned char key, int x, int y) {
switch (key) {
case '1': dragonLevel = 8; buildDragonCurve(); break;
case '2': dragonLevel = 10; buildDragonCurve(); break;
case '3': dragonLevel = 12; buildDragonCurve(); break;
case '4': dragonLevel = 14; buildDragonCurve(); break;
case '+':
if (dragonLevel < 16) {
dragonLevel++;
buildDragonCurve();
}
break;
case '-':
if (dragonLevel > 1) {
dragonLevel--;
buildDragonCurve();
}
break;
case 27: // Esc
exit(0);
}
glutPostRedisplay();
}
// Инициализация
void init() {
glClearColor(0.05f, 0.05f, 0.1f, 1.0f); // тёмно-синий фон
buildDragonCurve();
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(900, 900);
glutInitWindowPosition(100, 50);
glutCreateWindow("Dragon Curve - Harter-Heighway");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
printf("Dragon Curve Controls:\n");
printf(" 1-4 : preset levels (8, 10, 12, 14)\n");
printf(" +/- : increase/decrease detail level\n");
printf(" ESC : exit\n");
glutMainLoop();
return 0;
}