]> git.mar77i.info Git - bigintmandel/commitdiff
initial commit
authormar77i <mar77i@protonmail.ch>
Sun, 31 Mar 2024 14:41:36 +0000 (16:41 +0200)
committermar77i <mar77i@protonmail.ch>
Mon, 1 Apr 2024 01:31:32 +0000 (03:31 +0200)
.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0644]
bigintwidget.cpp [new file with mode: 0644]
bigintwidget.h [new file with mode: 0644]
colors.h [new file with mode: 0644]
main.cpp [new file with mode: 0644]
mandel.cpp [new file with mode: 0644]
mandel.h [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..0c9e5c7
--- /dev/null
@@ -0,0 +1,77 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+CMakeLists.txt.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
+# Build directories
+# -----------------
+build-*/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644 (file)
index 0000000..243407b
--- /dev/null
@@ -0,0 +1,76 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(bigintmandel VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOUIC ON)
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Concurrent)
+find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Concurrent)
+
+set(PROJECT_SOURCES
+        main.cpp
+        bigintwidget.cpp
+        bigintwidget.h
+        mandel.cpp
+        mandel.h
+)
+
+if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
+    qt_add_executable(bigintmandel
+        MANUAL_FINALIZATION
+        ${PROJECT_SOURCES}
+    )
+# Define target properties for Android with Qt 6 as:
+#    set_property(TARGET bigintmandel APPEND PROPERTY QT_ANDROID_PACKAGE_SOURCE_DIR
+#                 ${CMAKE_CURRENT_SOURCE_DIR}/android)
+# For more information, see https://doc.qt.io/qt-6/qt-add-executable.html#target-creation
+else()
+    if(ANDROID)
+        add_library(bigintmandel SHARED
+            ${PROJECT_SOURCES}
+        )
+# Define properties for Android with Qt 5 after find_package() calls as:
+#    set(ANDROID_PACKAGE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/android")
+    else()
+        add_executable(bigintmandel
+            ${PROJECT_SOURCES}
+        )
+    endif()
+endif()
+
+target_link_libraries(
+    bigintmandel
+    PRIVATE
+    Qt${QT_VERSION_MAJOR}::Widgets
+    Qt${QT_VERSION_MAJOR}::Concurrent
+)
+
+# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
+# If you are developing for iOS or macOS you should consider setting an
+# explicit, fixed bundle identifier manually though.
+if(${QT_VERSION} VERSION_LESS 6.1.0)
+  set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.bigintmandel)
+endif()
+set_target_properties(bigintmandel PROPERTIES
+    ${BUNDLE_ID_OPTION}
+    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+    MACOSX_BUNDLE TRUE
+    WIN32_EXECUTABLE TRUE
+)
+
+include(GNUInstallDirs)
+install(TARGETS bigintmandel
+    BUNDLE DESTINATION .
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)
+
+if(QT_VERSION_MAJOR EQUAL 6)
+    qt_finalize_executable(bigintmandel)
+endif()
diff --git a/bigintwidget.cpp b/bigintwidget.cpp
new file mode 100644 (file)
index 0000000..c965e0f
--- /dev/null
@@ -0,0 +1,69 @@
+
+// bigintwidget.cpp
+
+#include <QLayout>
+#include <QMouseEvent>
+#include <QtConcurrent/QtConcurrent>
+
+#include "bigintwidget.h"
+
+BigintWidget::BigintWidget(QWidget *parent)
+:   QWidget(parent),
+    fw(new QFutureWatcher<MandelResultCell>(this)),
+    meta(1024, QSize(1800, 1000)),
+    img_label(new QLabel(this)),
+    img_dirty(true)
+{
+    connect(
+        fw,
+        &QFutureWatcher<MandelResultCell>::resultReadyAt,
+        this,
+        &BigintWidget::finished_cell
+    );
+    connect(
+        fw,
+        &QFutureWatcher<MandelResultCell>::finished,
+        this,
+        &BigintWidget::finished
+    );
+    fw->setFuture(QtConcurrent::mapped(meta.get_cells(), MandelMeta::iterate));
+    setLayout(new QVBoxLayout());
+    layout()->addWidget(img_label);
+    img_label->setMinimumSize(meta.get_size());
+}
+
+BigintWidget::~BigintWidget() {
+    fw->cancel();
+    fw->waitForFinished();
+}
+
+void BigintWidget::finished_cell(int num) {
+    meta.finished_cell(num, fw->resultAt(num));
+    img_dirty = true;
+    update();
+}
+
+void BigintWidget::finished() {
+    img_dirty = true;
+    update();
+}
+
+void BigintWidget::paintEvent(QPaintEvent *event) {
+    if (img_dirty) {
+        img_label->setPixmap(meta.get_pixmap());
+        img_dirty = false;
+    }
+}
+
+void BigintWidget::mousePressEvent(QMouseEvent *event) {
+    if (!fw->isFinished() || event->button() != Qt::MouseButton::LeftButton)
+        return;
+    QPoint pos = img_label->mapFromParent(event->pos());
+    if (pos.x() < 0 || pos.x() >= meta.get_width()
+            || pos.y() < 0 || pos.y() >= meta.get_height())
+        return;
+    meta.zoom2x(pos);
+    fw->setFuture(QtConcurrent::mapped(meta.get_cells(), MandelMeta::iterate));
+    img_dirty = true;
+    update();
+}
diff --git a/bigintwidget.h b/bigintwidget.h
new file mode 100644 (file)
index 0000000..5d1964b
--- /dev/null
@@ -0,0 +1,30 @@
+
+// bigintwidget.h
+
+#ifndef BIGINTWIDGET_H
+#define BIGINTWIDGET_H
+
+#include <QFutureWatcher>
+#include <QLabel>
+#include <QWidget>
+
+#include "mandel.h"
+
+class BigintWidget : public QWidget {
+    Q_OBJECT
+
+    QFutureWatcher<MandelResultCell> *fw;
+    MandelMeta meta;
+    QLabel *img_label;
+    bool img_dirty;
+
+public:
+    BigintWidget(QWidget *parent = nullptr);
+    ~BigintWidget();
+    void finished_cell(int num);
+    void finished();
+    void paintEvent(QPaintEvent *event);
+    void mousePressEvent(QMouseEvent *event);
+};
+
+#endif // BIGINTWIDGET_H
diff --git a/colors.h b/colors.h
new file mode 100644 (file)
index 0000000..b6f8724
--- /dev/null
+++ b/colors.h
@@ -0,0 +1,269 @@
+
+// colors.h
+
+#ifndef COLORS_H
+#define COLORS_H
+
+#include <QVector>
+#include <QColor>
+
+static QVector<QColor> colors = {
+    "#3868b8",
+    "#3468b4",
+    "#3468b4",
+    "#3468b0",
+    "#3468b0",
+    "#3068ac",
+    "#3068ac",
+    "#3064a8",
+    "#3064a8",
+    "#2c64a4",
+    "#2c64a4",
+    "#2c64a4",
+    "#2c64a0",
+    "#2c64a0",
+    "#28649c",
+    "#28649c",
+    "#286098",
+    "#286098",
+    "#246094",
+    "#246094",
+    "#246090",
+    "#246090",
+    "#20608c",
+    "#20608c",
+    "#206088",
+    "#205c88",
+    "#1c5c84",
+    "#1c5c84",
+    "#1c5c80",
+    "#1c5c80",
+    "#185c7c",
+    "#185c7c",
+    "#185c78",
+    "#185c78",
+    "#185c78",
+    "#3c6c70",
+    "#607868",
+    "#808464",
+    "#a4945c",
+    "#c8a054",
+    "#e8ac50",
+    "#e4a854",
+    "#e4a458",
+    "#e0a058",
+    "#e09c5c",
+    "#e0985c",
+    "#dc9460",
+    "#dc9060",
+    "#dc9064",
+    "#d88c64",
+    "#d88868",
+    "#d88468",
+    "#d4806c",
+    "#d47c70",
+    "#d07870",
+    "#d07874",
+    "#d07474",
+    "#cc7078",
+    "#cc6c78",
+    "#cc687c",
+    "#c8647c",
+    "#c86080",
+    "#c86080",
+    "#c4647c",
+    "#c0687c",
+    "#bc6c7c",
+    "#b8707c",
+    "#4cc470",
+    "#48c870",
+    "#40cc6c",
+    "#3cd06c",
+    "#38d06c",
+    "#3ccc70",
+    "#40cc70",
+    "#40cc74",
+    "#44c874",
+    "#44c878",
+    "#48c878",
+    "#4cc87c",
+    "#4cc47c",
+    "#50c480",
+    "#50c480",
+    "#54c484",
+    "#58c084",
+    "#58c084",
+    "#5cc088",
+    "#5cc088",
+    "#60bc8c",
+    "#64bc8c",
+    "#64bc90",
+    "#68bc90",
+    "#68b894",
+    "#6cb894",
+    "#70b898",
+    "#70b498",
+    "#74b49c",
+    "#74b49c",
+    "#78b49c",
+    "#78b0a0",
+    "#7cb0a0",
+    "#80b0a4",
+    "#80b0a4",
+    "#84aca8",
+    "#84aca8",
+    "#88acac",
+    "#8cacac",
+    "#8ca8b0",
+    "#90a8b0",
+    "#90a8b4",
+    "#94a8b4",
+    "#98a4b4",
+    "#98a4b8",
+    "#9ca4b8",
+    "#9ca0bc",
+    "#a0a0bc",
+    "#a4a0c0",
+    "#a4a0c0",
+    "#a89cc4",
+    "#a89cc4",
+    "#ac9cc8",
+    "#b09cc8",
+    "#b098cc",
+    "#b498cc",
+    "#b498cc",
+    "#b898d0",
+    "#b894d0",
+    "#bc94d4",
+    "#c094d4",
+    "#c094d8",
+    "#c490d8",
+    "#c490dc",
+    "#c890dc",
+    "#cc8ce0",
+    "#cc8ce0",
+    "#d08ce4",
+    "#d08ce4",
+    "#d488e4",
+    "#d888e8",
+    "#d888e8",
+    "#dc88ec",
+    "#dc84ec",
+    "#e084f0",
+    "#e484f0",
+    "#e484f4",
+    "#e880f4",
+    "#e880f8",
+    "#ec80f8",
+    "#ec80f8",
+    "#e87cf0",
+    "#e47cec",
+    "#e07ce8",
+    "#dc78e0",
+    "#d878dc",
+    "#d478d8",
+    "#d474d4",
+    "#d074cc",
+    "#cc74c8",
+    "#c870c4",
+    "#c470c0",
+    "#c070b8",
+    "#bc6cb4",
+    "#bc6cb0",
+    "#b86ca8",
+    "#b468a4",
+    "#b068a0",
+    "#ac689c",
+    "#a86494",
+    "#a46490",
+    "#a4648c",
+    "#a06488",
+    "#9c6080",
+    "#98607c",
+    "#946078",
+    "#905c74",
+    "#8c5c6c",
+    "#8c5c68",
+    "#885864",
+    "#84585c",
+    "#805858",
+    "#7c5454",
+    "#785450",
+    "#745448",
+    "#745044",
+    "#705040",
+    "#6c503c",
+    "#684c34",
+    "#644c30",
+    "#604c2c",
+    "#604c28",
+    "#5c502c",
+    "#5c5030",
+    "#5c5034",
+    "#5c5038",
+    "#5c5038",
+    "#5c503c",
+    "#5c5440",
+    "#585444",
+    "#585444",
+    "#585448",
+    "#58544c",
+    "#585450",
+    "#585850",
+    "#585854",
+    "#585858",
+    "#54585c",
+    "#54585c",
+    "#545860",
+    "#545c64",
+    "#545c68",
+    "#545c6c",
+    "#545c6c",
+    "#545c70",
+    "#505c74",
+    "#506078",
+    "#506078",
+    "#50607c",
+    "#506080",
+    "#506084",
+    "#506084",
+    "#506488",
+    "#4c648c",
+    "#4c6490",
+    "#4c6490",
+    "#4c6494",
+    "#4c6498",
+    "#4c689c",
+    "#4c68a0",
+    "#4c68a0",
+    "#4868a4",
+    "#4868a8",
+    "#4868ac",
+    "#486cac",
+    "#486cb0",
+    "#486cb4",
+    "#486cb8",
+    "#486cb8",
+    "#446cbc",
+    "#4470c0",
+    "#4470c4",
+    "#4470c4",
+    "#4470c8",
+    "#4470cc",
+    "#4470d0",
+    "#4470d0",
+    "#406ccc",
+    "#406ccc",
+    "#406cc8",
+    "#406cc8",
+    "#3c6cc4",
+    "#3c6cc4",
+    "#3c6cc0",
+    "#3c6cc0",
+    "#386cbc",
+    "#3868bc",
+    "#3868b8",
+    "#3868b8",
+};
+
+#endif // COLORS_H
diff --git a/main.cpp b/main.cpp
new file mode 100644 (file)
index 0000000..07cdecd
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,14 @@
+
+// main.cpp
+
+#include <QApplication>
+
+#include "bigintwidget.h"
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    BigintWidget w;
+    w.show();
+    return a.exec();
+}
diff --git a/mandel.cpp b/mandel.cpp
new file mode 100644 (file)
index 0000000..e633fb0
--- /dev/null
@@ -0,0 +1,109 @@
+
+// mandel.cpp
+
+#include "colors.h"
+#include "mandel.h"
+
+MandelResultCell::MandelResultCell() {}
+
+MandelResultCell::MandelResultCell(size_t iter, QPointF rpos)
+:   iter(iter), rpos(rpos) {}
+
+static inline void incrpos(QPoint &pos, const int width) {
+    pos.setX(pos.x() + 1);
+    if (pos.x() == width) {
+        pos.setX(0);
+        pos.setY(pos.y() + 1);
+    }
+}
+
+MandelMeta::MandelMeta(size_t max_iter, const QSize size)
+:   max_iter(max_iter),
+    img(size, QImage::Format_RGB888),
+    cells(size.width() * size.height(), MandelCell(this)),
+    center_f(qreal(-3) / 4, 0),
+    one(1),
+    four(4),
+    scale(std::max(qreal(3) / size.width(), qreal(3) / size.height()))
+{
+    QVector<MandelCell>::iterator i;
+    QPointF c(size.width() / 2., size.height() / 2.);
+    QPoint pos;
+
+    for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++) {
+        i->set_meta(this);
+        i->set_pos(pos);
+    }
+}
+
+void MandelMeta::zoom2x(QPoint pos) {
+    QVector<MandelCell>::iterator i;
+    center_f = cells[img.width() * pos.y() + pos.x()].get_rpos0();
+    scale /= 2;
+    img.fill(Qt::GlobalColor::black);
+    for (i = cells.begin(); i != cells.end(); i++)
+        i->reset_iter_and_rpos();
+}
+
+void MandelMeta::finished_cell(int num, const MandelResultCell &cell) {
+    img.setPixelColor(
+        cells[num].update_result(cell.iter, cell.rpos),
+        cell.iter < max_iter
+        ? colors[cell.iter % colors.size()]
+        : Qt::GlobalColor::black
+    );
+}
+
+MandelResultCell MandelMeta::iterate(const MandelCell &cell) {
+    return cell.iterate();
+}
+
+void MandelCell::reset_rpos0() {
+    QPointF center_f = meta->get_center_f();
+    rpos0 = QPointF(
+        center_f.x() + (pos.x() - meta->get_width() / 2.) * meta->get_scale(),
+        center_f.y() + (pos.y() - meta->get_height() / 2.) * meta->get_scale()
+    );
+}
+
+MandelCell::MandelCell(MandelMeta *meta) : meta(meta), iter(0) {}
+
+MandelCell::MandelCell(const MandelCell &cell)
+:   meta(cell.meta), pos(cell.pos), iter(cell.iter),
+    rpos(cell.rpos), rpos0(cell.rpos0) {}
+
+QPoint MandelCell::update_result(size_t iter, const QPointF &rpos) {
+    this->iter = iter;
+    this->rpos = rpos;
+    return pos;
+}
+
+void MandelCell::reset_iter_and_rpos() {
+    iter = 0;
+    rpos = QPointF();
+    reset_rpos0();
+}
+
+void MandelCell::set_meta(MandelMeta *meta) {
+    this->meta = meta;
+}
+
+void MandelCell::set_pos(QPoint pos) {
+    this->pos = pos;
+    reset_rpos0();
+}
+
+MandelResultCell MandelCell::iterate() const {
+    size_t iter = this->iter;
+    QPointF rpos = this->rpos, sq;
+    for (; iter < this->meta->get_max_iter(); iter++) {
+        sq = QPointF(rpos.x() * rpos.x(), rpos.y() * rpos.y());
+        if (sq.x() + sq.y() > meta->get_four())
+            break;
+        rpos = QPointF(
+            sq.x() - sq.y() + rpos0.x(),
+            2 * rpos.x() * rpos.y() + rpos0.y()
+        );
+    }
+    return MandelResultCell(iter, rpos);
+}
diff --git a/mandel.h b/mandel.h
new file mode 100644 (file)
index 0000000..487dd0b
--- /dev/null
+++ b/mandel.h
@@ -0,0 +1,69 @@
+
+// mandel.h
+
+#ifndef MANDEL_H
+#define MANDEL_H
+
+#include <QPixmap>
+#include <QPoint>
+#include <QVector>
+
+class MandelCell;
+
+class MandelResultCell {
+    friend class MandelMeta;
+
+    size_t iter;
+    QPointF rpos;
+public:
+    MandelResultCell();
+    MandelResultCell(size_t iter, QPointF rpos);
+};
+
+class MandelMeta {
+    size_t max_iter;
+    QImage img;
+    QVector<MandelCell> cells;
+    QPointF center_f;
+    qreal one, four, scale;
+
+public:
+    MandelMeta(size_t max_iter, QSize size);
+    const size_t get_max_iter() const { return max_iter; }
+    const QPixmap get_pixmap() const { return QPixmap::fromImage(img); }
+    const int get_width() const { return img.width(); }
+    const int get_height() const { return img.height(); }
+    const QSize get_size() const { return img.size(); }
+    const QVector<MandelCell> get_cells() const { return cells; }
+    const QPointF get_center_f() const { return center_f; }
+    const qreal get_four() const { return four; }
+    const qreal get_scale() const { return scale; }
+
+    void zoom2x(QPoint pos);
+    void finished_cell(int num, const MandelResultCell &cell);
+    static MandelResultCell iterate(const MandelCell &cell);
+};
+
+class MandelCell {
+    MandelMeta *meta;
+    QPoint pos;
+    size_t iter;
+    QPointF rpos, rpos0;
+
+protected:
+    void reset_rpos0();
+
+public:
+    MandelCell(MandelMeta *meta);
+    MandelCell(const MandelCell &cell);
+    inline const size_t get_iter() const { return iter; }
+    inline const QPointF get_rpos0() const { return rpos0; }
+
+    QPoint update_result(size_t iter, const QPointF &rpos);
+    void reset_iter_and_rpos();
+    void set_meta(MandelMeta *meta);
+    void set_pos(const QPoint pos);
+    MandelResultCell iterate() const;
+};
+
+#endif // MANDEL_H