git-svn-id: svn://db.shs.com.ru/libs@1 a8b55f48-bf90-11e4-a774-851b48703e85
198 lines
4.3 KiB
C++
198 lines
4.3 KiB
C++
#include "blockviewwavetrace.h"
|
|
#include <QTime>
|
|
|
|
|
|
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<QPoint> 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;
|
|
//cout << cl << ": " << cpnts.size() << endl;
|
|
}
|
|
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<QPoint> & BlockViewWavetrace::path() const {
|
|
/*path_.resize(3);
|
|
path_[0] = st;
|
|
path_[1] = (st + fn) / 2;
|
|
path_[2] = fn;*/
|
|
return path_;
|
|
}
|