]> git.mar77i.info Git - bigintmandel/blob - mandel.cpp
make zoom_factor part of MandelSettings
[bigintmandel] / mandel.cpp
1
2 // mandel.cpp
3
4 #include <QFile>
5 #include <QJsonArray>
6 #include <QJsonDocument>
7
8 #include "colors.h"
9 #include "mandel.h"
10
11 MandelParams::MandelParams() {}
12 MandelParams::MandelParams(
13 size_t max_iter,
14 QSize size,
15 MpzPoint center_f,
16 mpz_class one
17 ) : max_iter(max_iter),
18 size(size),
19 center_f(center_f),
20 one(one),
21 left(center_f.get_x() - size.width() / 2.),
22 top(center_f.get_y() + size.height() / 2.) {}
23 MandelParams::MandelParams(const MandelParams &other)
24 : max_iter(other.max_iter),
25 size(other.size),
26 center_f(other.center_f),
27 one(other.one),
28 left(center_f.get_x() - size.width() / 2.),
29 top(center_f.get_y() + size.height() / 2.) {}
30
31 MandelParams MandelParams::from_json(const QJsonObject &json) {
32 return MandelParams(
33 json["max_iter"].toString().toULongLong(),
34 QSize(json["size_w"].toInt(), json["size_h"].toInt()),
35 MpzPoint(
36 mpz_class(json["center_f_x"].toString().toStdString()),
37 mpz_class(json["center_f_y"].toString().toStdString())
38 ),
39 mpz_class(json["one"].toString().toStdString())
40 );
41 }
42
43 QJsonObject MandelParams::to_json() const {
44 QJsonObject json;
45 json["max_iter"] = QString::number(max_iter);
46 json["size_w"] = size.width();
47 json["size_h"] = size.height();
48 json["center_f_x"] = QString::fromStdString(center_f.get_x().get_str());
49 json["center_f_y"] = QString::fromStdString(center_f.get_y().get_str());
50 json["one"] = QString::fromStdString(one.get_str());
51 return json;
52 }
53
54 static inline void incrpos(QPoint &pos, const int width) {
55 pos.setX(pos.x() + 1);
56 if (pos.x() == width) {
57 pos.setX(0);
58 pos.setY(pos.y() + 1);
59 }
60 }
61
62 static inline void setup_cells(
63 QVector<MandelCell> &cells, const MandelParams *current
64 ) {
65 QSize size = current->get_size();
66 QVector<MandelCell>::iterator i;
67 QPoint pos;
68
69 cells.resize(size.width() * size.height(), MandelCell(current));
70 for (i = cells.begin(); i != cells.end(); incrpos(pos, size.width()), i++)
71 i->setup(pos);
72 }
73
74 static inline QImage *setup_image(QImage *img, const QSize &size) {
75 if(!img || img->size() != size) {
76 delete img;
77 img = new QImage(size, QImage::Format_RGB888);
78 }
79 img->fill(Qt::GlobalColor::black);
80 return img;
81 }
82
83 MandelSettings::MandelSettings(size_t max_iter, const QSize size)
84 : img(nullptr) {
85 reset(max_iter, size);
86 }
87
88 void MandelSettings::zoom(const QSize size, int zoom_factor, const QPoint pos) {
89 MpzPoint p = cells[img->width() * pos.y() + pos.x()].get_rpos0();
90 params = MandelParams(
91 params.get_max_iter(),
92 size,
93 MpzPoint(p.get_x() * zoom_factor, p.get_y() * zoom_factor),
94 params.get_one() * zoom_factor
95 );
96 img = setup_image(img, size);
97 img->fill(Qt::GlobalColor::black);
98 setup_cells(cells, &params);
99 }
100
101 void MandelSettings::finished_cell(int num, const MandelResultCell &result) {
102 cells[num].set_result(result);
103 if (!img)
104 return;
105 img->setPixelColor(cells[num].get_pos(), cells[num].get_color());
106 return;
107 (void)colors;
108 }
109
110 void MandelSettings::save_img(QString file_name) {
111 if (img)
112 img->save(file_name);
113 }
114
115 void MandelSettings::reset(size_t max_iter, const QSize size) {
116 mpz_class one;
117 MpzPoint center_f;
118 int ione = std::min(size.width(), size.height()) / 3;
119 ione--;
120 ione |= ione >> 1;
121 ione |= ione >> 2;
122 ione |= ione >> 4;
123 ione |= ione >> 8;
124 ione |= ione >> 16;
125 one = mpz_class(ione + 1);
126 center_f = MpzPoint(one * -3 / 4, 0);
127 params = MandelParams(max_iter, size, center_f, one);
128 img = setup_image(img, size);
129 setup_cells(cells, &params);
130 }
131
132 void MandelSettings::from_json(const QJsonObject &json) {
133 QJsonArray json_array;
134 int i;
135 params = MandelParams::from_json(json["params"].toObject());
136 json_array = json["cells"].toArray();
137 cells.resize(json_array.size(), MandelCell(&params));
138 img = setup_image(img, params.get_size());
139 for (i = 0; i < json_array.size(); i++)
140 finished_cell(i, cells[i].from_json(json_array[i].toObject()));
141 }
142
143 QJsonObject MandelSettings::to_json() {
144 QJsonArray c;
145 QJsonObject json;
146 QVector<MandelCell>::iterator i;
147 json["params"] = params.to_json();
148 for (i = cells.begin(); i != cells.end(); i++)
149 c.append(i->to_json());
150 json["cells"] = c;
151 return json;
152 }
153
154 MandelCell::MandelCell(const MandelParams *params) : params(params) {}
155 MandelCell::MandelCell(const MandelCell &cell)
156 : params(cell.params),
157 pos(cell.pos),
158 result(cell.result),
159 rpos0(cell.rpos0) {}
160
161 void MandelCell::setup(const QPoint pos) {
162 this->pos = pos;
163 rpos0 = MpzPoint(params->get_left() + pos.x(), params->get_top() - pos.y());
164 result = MandelResultCell();
165 }
166
167 MandelResultCell MandelCell::iterate() const {
168 MpzPoint rpos = result.get_rpos(), sq;
169 mpz_class one = params->get_one(), four = one * one * 4;
170 mpz_class sqx, sqy;
171 size_t iter = result.get_iter();
172 for (; iter < params->get_max_iter(); iter++) {
173 sqx = rpos.get_x() * rpos.get_x();
174 sqy = rpos.get_y() * rpos.get_y();
175 if (sqx + sqy > four)
176 break;
177 rpos = MpzPoint(
178 (sqx - sqy) / one + rpos0.get_x(),
179 rpos.get_x() * rpos.get_y() * 2 / one + rpos0.get_y()
180 );
181 }
182 return MandelResultCell(iter, rpos);
183 }
184
185 MandelResultCell MandelCell::from_json(const QJsonObject &json) {
186 this->pos = QPoint(json["pos_x"].toInt(), json["pos_y"].toInt());
187 this->rpos0 = MpzPoint(
188 mpz_class(json["rpos0_x"].toString().toStdString()),
189 mpz_class(json["rpos0_y"].toString().toStdString())
190 );
191 return MandelResultCell(
192 json["iter"].toString().toULongLong(),
193 MpzPoint(
194 mpz_class(json["rpos_x"].toString().toStdString()),
195 mpz_class(json["rpos_y"].toString().toStdString())
196 )
197 );
198 }
199
200 QJsonObject MandelCell::to_json() const {
201 const MpzPoint rpos(result.get_rpos());
202 QJsonObject json;
203 json["pos_x"] = pos.x();
204 json["pos_y"] = pos.y();
205 json["rpos0_x"] = QString::fromStdString(rpos0.get_x().get_str());
206 json["rpos0_y"] = QString::fromStdString(rpos0.get_y().get_str());
207 json["iter"] = QString::number(result.get_iter());
208 json["rpos_x"] = QString::fromStdString(rpos.get_x().get_str());
209 json["rpos_y"] = QString::fromStdString(rpos.get_y().get_str());
210 return json;
211 }