Уроки, алгоритмы, программы, примеры

Вход на сайт

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

dobryj den, popytalas otkryt prikreplionnyj fail ctoby posmotret kak rabotaet, no mne ego ne pokazyvaet vydajet osibku. Pochemu?
Очень интересно! ии сайт крутой жалко что умирает(
У Вас число превысит максимальное число int. Можно использовать в Вашем случае uint, но лучше все переписать на double.
Добавление к программе строки glutReshapeFunc(changeSize); приводит к тому, что треугольник перестаёт совсем отрисовываться.
Выдаёт ошибку glut32.dll не найден! При том, что он лежит в System32! Всё решил) Нужно отправить не в System32, а в System.

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Скриншот к примеру
Среда программирования: 
Qt
Статья по теме: 

Детали фрактала

Изначально есть лишь буква Н, затем к каждому из концов этой буквы пририсовывается точно такая же буква Н, но в два раза меньше, и так далее.
Известно, что Н-фрактал заполняет свой квадрат и его фрактальная размерность равна двум.

Принцип построения данного фрактала используется в проектировании микросхем.
Если рисовать толстые буквы Н, то получается дерево Мандельброта.
Принцип построения Н-фрактала очень похож на пострение Т-фрактала.

Детали реализации

Чтобы запоминать точки в которых надо рисовать буквы H будем использовать очередь, так как данная структура данных лучше всего подходит для наших целей. На каждой итерации построения букв H мы будем использовать рандомные цвета.
Все остальные детали будут описаны в комментариях в коде.

Конкретно данный пример кода был написан на Qt/C++, из-за удобств работы с ui интерфейсом.

Код программы: 

// widget.h
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QPair>
#include <QPainter>
#include <queue>
#include <time.h>
#include <stdlib.h>
using namespace std;
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    void drawH(int size, QPair<int,int> coord, QPainter *paint); // функция для отрисовки Н в какой-то точке coord с длиной линий size
    int getSize(int depth); // в зависимости от глубины узнаем длину линии, она равна начальной длине, деленной на два в степени глубина минус один (в 1-индексации)
    void drawHDepth(int depth); // отрисовка всех Н до глубины depth
    QColor getRandColor(); // функция, возвращающая рандомный цвет
 
private slots:
    void on_drawButton_clicked(); // метод клика по кнопке
 
private:
    Ui::Widget *ui; // форма
    int oX,oY; // начальные координаты центра
    int sizeMin; // начальная длина
    queue<QPair<int,int> > coords; // очередь, используемая для запоминания точек в которых надо рисовать Н
};
 
#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
 
// в конструкторе проинициализируем начальные значения координат и длины
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    oX = 290;
    oY = 255;
    sizeMin = 200;
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::drawH(int size, QPair<int,int> coord, QPainter *paint)
{
    // в данном методы мы просто рисуем три линии, которые и являются буквой Н
    // *paint нужен для отрисовки
    paint->drawLine(coord.first-(size/2),coord.second,coord.first+(size/2),coord.second);
    paint->drawLine(coord.first-(size/2),coord.second-(size/2),coord.first-(size/2),coord.second+(size/2));
    paint->drawLine(coord.first+(size/2),coord.second-(size/2),coord.first+(size/2),coord.second+(size/2));
 
    return;
}
 
int Widget::getSize(int depth)
{
    // функция, возвращающая длину линий на каждом шаге
    return sizeMin/(1<<(depth-1));
}
 
// так как на i-том шаге у нас будет ровно четыре в степени i-1 точек из которых надо рисовать Н, напишем рекурсивную функцию бинарного возведения в степень, которая за логарифмическую асимптотику позволяет вычислять степень числа
int binPow(int a, int b) {
    if(!b)
        return 1;
    if(b%2)
        return binPow(a,b-1)*a;
    int tmp = binPow(a,b/2);
    return tmp*tmp;
}
 
// в данном методе мы лишь задаем рандомные значения RGB для класса QColor
QColor Widget::getRandColor()
{
    int r = rand()%255;
    int g = rand()%255;
    int b = rand()%255;
    return QColor(r,g,b);
}
 
void Widget::drawHDepth(int depth)
{
    srand(time(NULL)); // для начала инициализируем рандомные значения
 
    QPixmap H(580,510); // далее создадим область рисования
    QPainter paint;
    paint.begin(&H);
    paint.eraseRect(0,0,580,510); // и закрасим её белым цветом
 
    while(!coords.empty()) // чтобы при каждой новой отрисовке не было конфузов, очистим очередь вершин
        coords.pop();
 
    QPair<int,int> a(oX,oY),tmp;
    int size;
    coords.push(a); // изначально в очередь поместим только центральную точку
    for(int i=1;i<=depth;++i) { // и последовательно пройдемся по всем глубинам
 
        size = getSize(i); // узнаем размер линии на каждом шаге глубины
 
        paint.setPen(QPen(getRandColor(),1)); // задаем кисть рандомного цвета толщиной 1
 
        for(int j=1;j<=binPow(4,i-1);j++) { // т.к. вершин на данном шаге будет 4 в степени i-1, проходимся только по 4 в степени i-1 первым значениям в очереди
 
            a = coords.front(); // узнаем координату очередной вершины
            coords.pop(); // удаляем её из очереди
            drawH(size,a,&paint); // и рисуем
 
            // далее просто добавляем 4 новые вершины в стек
            tmp.first = a.first-(size/2);
            tmp.second = a.second-(size/2);
            coords.push(tmp);
 
            tmp.first = a.first-(size/2);
            tmp.second = a.second+(size/2);
            coords.push(tmp);
 
            tmp.first = a.first+(size/2);
            tmp.second = a.second-(size/2);
            coords.push(tmp);
 
            tmp.first = a.first+(size/2);
            tmp.second = a.second+(size/2);
            coords.push(tmp);
        }
    }
 
    paint.end(); // заканчиваем рисование
    ui->output->setPixmap(H); // и выводим картинку на экран
}
 
void Widget::on_drawButton_clicked()
{
    QString tmp = ui->depthEdit->text(); // получаем глубину, которую пользователь вводит в форме
    int depth;
    if(tmp=="") // если строка пуста
        depth = 1; // то считаем, что глубина равна 1
    else // иначе
        depth = tmp.toInt(); // преобразовываем строку в число
    drawHDepth(depth); // и запускаем отрисовку фрактала до глубины depth
}

Прикрепленный файлРазмер
Kish_Hfrac.zip2.47 кб