// mandel.cpp #include #include "colors.h" #include "mandel.h" MpzPoint::MpzPoint() : x(), y() {} MpzPoint::MpzPoint(mpz_class x, mpz_class y) : x(x), y(y) {} MpzPoint::MpzPoint(const MpzPoint &other) : x(other.x), y(other.y) {} MandelResultCell::MandelResultCell() {} MandelResultCell::MandelResultCell(size_t iter, MpzPoint 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); } } static inline mpz_class get_one(const QSize size) { int one = std::min(size.width() / 3, size.height() / 3) / 2; one--; one |= one >> 1; one |= one >> 2; one |= one >> 4; one |= one >> 8; one |= one >> 16; return mpz_class(one + 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)), one(::get_one(size)) { QVector::iterator i; QPointF c(size.width() / 2., size.height() / 2.); QPoint pos; center_f = MpzPoint(one * -3 / 4, 0); 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::iterator i; MpzPoint p = cells[img.width() * pos.y() + pos.x()].get_rpos0(); center_f = MpzPoint(p.get_x() * 8, p.get_y() * 8); one *= 8; 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() { MpzPoint center_f = meta->get_center_f(); rpos0 = MpzPoint( center_f.get_x() + (pos.x() - meta->get_width() / 2.), center_f.get_y() + (pos.y() - meta->get_height() / 2.) ); } 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 MpzPoint &rpos) { this->iter = iter; this->rpos = rpos; return pos; } void MandelCell::reset_iter_and_rpos() { iter = 0; rpos = MpzPoint(); 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 { MpzPoint rpos = this->rpos, sq; mpz_class one = meta->get_one(), four = one * one * 4; mpz_class sqx, sqy; size_t iter = this->iter; for (; iter < meta->get_max_iter(); iter++) { sqx = rpos.get_x() * rpos.get_x(); sqy = rpos.get_y() * rpos.get_y(); if (sqx + sqy > four) break; rpos = MpzPoint( (sqx - sqy) / one + rpos0.get_x(), rpos.get_x() * rpos.get_y() * 2 / one + rpos0.get_y() ); } return MandelResultCell(iter, rpos); }