#include "blockviewwavetrace.h" #include BlockViewWavetrace::BlockViewWavetrace(int width, int height) { max_steps = 512; resize(width, height); setPreferredDirection(BlockViewWavetrace::Horizontal); } void BlockViewWavetrace::resize(int width, int height) { wid = width; hei = height; if (field.size() != wid) field.resize(wid); for (int i = 0; i < wid; ++i) { if (field[i].size() != hei) { field[i].resize(hei); field[i].fill(-1); } } } void BlockViewWavetrace::fill(short val) { QTime tm; tm.restart(); for (int i = 0; i < wid; ++i) { if (i == 0) field[i].fill(val); else memcpy(field[i].data(), field[0].constData(), hei * sizeof(field[0][0])); } } void BlockViewWavetrace::fill(const QRect & rect, short val) { for (int i = rect.left(); i <= rect.right(); ++i) for (int j = rect.top(); j <= rect.bottom(); ++j) field[i][j] = val; } bool BlockViewWavetrace::trace(const QPoint & start, const QPoint & finish) { st = start; fn = finish; //qDebug() << "trace" << start << finish; //return true; int cx, cy; short cl = 0, empty = (short)BlockViewWavetrace::Empty; QRect frect(0, 0, wid - 1, hei - 1); QVector cpnts, npnts; fill(st, cl); cpnts.push_back(st); if (field[fn.x()][fn.y()] == (short)BlockViewWavetrace::Blocked) return false; while (cpnts.size() > 0) { npnts.clear(); cl++; if (cl >= max_steps) return false; for (int i = 0; i < cpnts.size(); ++i) { if (cpnts[i] == fn) { return true; } cx = cpnts[i].x() - 1; cy = cpnts[i].y(); if (frect.contains(cx, cy)) { if (field[cx][cy] == empty) { npnts.push_back(QPoint(cx, cy)); fill(cx, cy, cl); } } cx = cpnts[i].x() + 1; if (frect.contains(cx, cy)) { if (field[cx][cy] == empty) { npnts.push_back(QPoint(cx, cy)); fill(cx, cy, cl); } } cx = cpnts[i].x(); cy = cpnts[i].y() - 1; if (frect.contains(cx, cy)) { if (field[cx][cy] == empty) { npnts.push_back(QPoint(cx, cy)); fill(cx, cy, cl); } } cy = cpnts[i].y() + 1; if (frect.contains(cx, cy)) { if (field[cx][cy] == empty) { npnts.push_back(QPoint(cx, cy)); fill(cx, cy, cl); } } } cpnts = npnts; //qDebug() << cl << ": " << cpnts.size(); } return false; } void BlockViewWavetrace::gatherPath() { path_.clear(); path_.push_back(fn); int cx, cy; int pa = -1, ca = -1; bool first = true; short cl = field[fn.x()][fn.y()]; QRect frect(0, 0, wid, hei); QPoint cpnt = fn; //cout << "start from " << cl << endl; while (cl > 0) { cl--; pa = ca; int dir = 0; cx = cpnt.x() + dps[dir].x(); cy = cpnt.y() + dps[dir].y(); dir++; if (frect.contains(cx, cy)) { if (field[cx][cy] == cl) { ca = QLineF(QPointF(cx, cy), cpnt).angle(); if (ca != pa && !first) path_.push_front(cpnt); cpnt = QPoint(cx, cy); first = false; continue; } } cx = cpnt.x() + dps[dir].x(); cy = cpnt.y() + dps[dir].y(); dir++; if (frect.contains(cx, cy)) { if (field[cx][cy] == cl) { ca = QLineF(QPointF(cx, cy), cpnt).angle(); if (ca != pa && !first) path_.push_front(cpnt); cpnt = QPoint(cx, cy); first = false; continue; } } cx = cpnt.x() + dps[dir].x(); cy = cpnt.y() + dps[dir].y(); dir++; if (frect.contains(cx, cy)) { if (field[cx][cy] == cl) { ca = QLineF(QPointF(cx, cy), cpnt).angle(); if (ca != pa && !first) path_.push_front(cpnt); cpnt = QPoint(cx, cy); first = false; continue; } } cx = cpnt.x() + dps[dir].x(); cy = cpnt.y() + dps[dir].y(); if (frect.contains(cx, cy)) { if (field[cx][cy] == cl) { ca = QLineF(QPointF(cx, cy), cpnt).angle(); if (ca != pa && !first) path_.push_front(cpnt); cpnt = QPoint(cx, cy); first = false; continue; } } } path_.push_front(st); //cout << path_.size() << endl; } void BlockViewWavetrace::setPreferredDirection(BlockViewWavetrace::Direction dir) { dir_ = dir; if (dir == BlockViewWavetrace::Horizontal) { dps[0] = QPoint(0, -1); dps[1] = QPoint(0, 1); dps[2] = QPoint(-1, 0); dps[3] = QPoint(1, 0); } if (dir == BlockViewWavetrace::Vertical) { dps[2] = QPoint(0, -1); dps[3] = QPoint(0, 1); dps[0] = QPoint(-1, 0); dps[1] = QPoint(1, 0); } } const QVector & BlockViewWavetrace::path() const { /*path_.resize(3); path_[0] = st; path_[1] = (st + fn) / 2; path_[2] = fn;*/ return path_; }