another version of tracing across buses
This commit is contained in:
@@ -1264,14 +1264,17 @@ void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem
|
||||
double signx = (p1.x() >= p0.x() ? 1. : -1.), signy = (p1.y() >= p0.y() ? 1. : -1.);
|
||||
int steps(0);
|
||||
if ((dx + dy) < grid_step) continue;
|
||||
BlockViewWavetrace::CellState cs = BlockViewWavetrace::Blocked;
|
||||
if (dx >= dy) { // by x
|
||||
sx = grid_step;
|
||||
sy = sx * dy / dx;
|
||||
steps = qRound(dx / grid_step);
|
||||
cs = BlockViewWavetrace::HorizontalBus;
|
||||
} else {
|
||||
sy = grid_step;
|
||||
sx = sy * dx / dy;
|
||||
steps = qRound(dy / grid_step);
|
||||
cs = BlockViewWavetrace::VerticalBus;
|
||||
}
|
||||
sx *= signx;
|
||||
sy *= signy;
|
||||
@@ -1279,7 +1282,7 @@ void BlockView::trace(QPointF scene_pos_from, QPointF scene_pos_to, BlockBusItem
|
||||
for (int j = 0; j < steps; ++j) {
|
||||
QPoint tp = quantize(cp, grid_step).toPoint() / grid_step + dp;
|
||||
if (tp != qpt)
|
||||
wavetrace.fill(tp, BlockViewWavetrace::Jump);
|
||||
wavetrace.fill(tp, cs);
|
||||
//qDebug() << " set" << cp;
|
||||
cp += QPointF(sx, sy);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "blockviewwavetrace.h"
|
||||
#include <QTime>
|
||||
|
||||
|
||||
BlockViewWavetrace::BlockViewWavetrace(int width, int height) {
|
||||
@@ -17,14 +16,13 @@ void BlockViewWavetrace::resize(int width, int height) {
|
||||
for (int i = 0; i < wid; ++i) {
|
||||
if (field[i].size() != hei) {
|
||||
field[i].resize(hei);
|
||||
field[i].fill(-1);
|
||||
field[i].fill(Cell());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BlockViewWavetrace::fill(short val) {
|
||||
QTime tm; tm.restart();
|
||||
for (int i = 0; i < wid; ++i) {
|
||||
if (i == 0)
|
||||
field[i].fill(val);
|
||||
@@ -37,11 +35,18 @@ void BlockViewWavetrace::fill(short val) {
|
||||
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;
|
||||
field[i][j].value = field[i][j].direction = val;
|
||||
}
|
||||
|
||||
|
||||
void BlockViewWavetrace::fill(int px, int py, short val) {
|
||||
field[px][py] = val;
|
||||
short p = field[px][py].value;
|
||||
if ((val == HorizontalBus && p == VerticalBus ) ||
|
||||
(val == VerticalBus && p == HorizontalBus))
|
||||
field[px][py].value = Blocked;
|
||||
else
|
||||
field[px][py].value = val;
|
||||
field[px][py].direction = field[px][py].value;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,44 +56,33 @@ bool BlockViewWavetrace::trace(const QPoint & start, const QPoint & finish) {
|
||||
if (dir_ == NoTrace) return true;
|
||||
//qDebug() << "trace" << start << finish;
|
||||
//return true;
|
||||
int cx, cy;
|
||||
short cl = 0;
|
||||
QRect frect(0, 0, wid - 1, hei - 1);
|
||||
QVector<QPoint> cpnts, npnts;
|
||||
fill(st, cl);
|
||||
jumps.clear();
|
||||
cpnts.append(st);
|
||||
auto checkAndFill = [this, &npnts, &frect](int x, int y, short c) {
|
||||
cpnts.push_back(st);
|
||||
if (field[fn.x()][fn.y()].value == (short)Blocked)
|
||||
return false;
|
||||
auto checkAndFill = [this, &npnts, &frect](int x, int y, short acc_dir, short c) {
|
||||
if (!frect.contains(x, y)) return;
|
||||
short p = field[x][y];
|
||||
if (p == (short)Empty || p == (short)Jump) {
|
||||
npnts.append(QPoint(x, y));
|
||||
fill(x, y, c);
|
||||
}
|
||||
if (p == (short)Jump) {
|
||||
jumps.append(QPoint(x, y));
|
||||
short p = field[x][y].value;
|
||||
if (p == (short)Empty || p == acc_dir) {
|
||||
npnts.push_back(QPoint(x, y));
|
||||
field[x][y].value = c;
|
||||
}
|
||||
};
|
||||
if (field[fn.x()][fn.y()] < (short)Empty)
|
||||
return false;
|
||||
while (cpnts.size() > 0) {
|
||||
npnts.clear();
|
||||
cl++;
|
||||
if (cl >= max_steps) return false;
|
||||
if (cl >= max_steps)
|
||||
return false;
|
||||
for (int i = 0; i < cpnts.size(); ++i) {
|
||||
if (cpnts[i] == fn) {
|
||||
if (cpnts[i] == fn)
|
||||
return true;
|
||||
}
|
||||
cx = cpnts[i].x() - 1;
|
||||
cy = cpnts[i].y();
|
||||
checkAndFill(cx, cy, cl);
|
||||
cx = cpnts[i].x() + 1;
|
||||
checkAndFill(cx, cy, cl);
|
||||
cx = cpnts[i].x();
|
||||
cy = cpnts[i].y() - 1;
|
||||
checkAndFill(cx, cy, cl);
|
||||
cy = cpnts[i].y() + 1;
|
||||
checkAndFill(cx, cy, cl);
|
||||
checkAndFill(cpnts[i].x() - 1, cpnts[i].y() , (short)VerticalBus , cl);
|
||||
checkAndFill(cpnts[i].x() + 1, cpnts[i].y() , (short)VerticalBus , cl);
|
||||
checkAndFill(cpnts[i].x() , cpnts[i].y() - 1, (short)HorizontalBus, cl);
|
||||
checkAndFill(cpnts[i].x() , cpnts[i].y() + 1, (short)HorizontalBus, cl);
|
||||
}
|
||||
cpnts = npnts;
|
||||
//qDebug() << cl << ": " << cpnts.size();
|
||||
@@ -106,27 +100,21 @@ void BlockViewWavetrace::gatherPath() {
|
||||
}
|
||||
int pa = -1, ca = -1;
|
||||
bool first = true;
|
||||
short cl = field[fn.x()][fn.y()];
|
||||
short cl = field[fn.x()][fn.y()].value;
|
||||
QRect frect(0, 0, wid, hei);
|
||||
QPoint cpnt = fn;
|
||||
//cout << "start from " << cl << endl;
|
||||
auto checkAndStep = [this, &cpnt, &first, &frect] (int & dir, short c, int & ca_, int pa_)->bool {
|
||||
auto checkAndStep = [this, &cpnt, &first, &frect] (int dir, short c, int & ca_, int pa_)->bool {
|
||||
int cx = cpnt.x() + dps[dir].x();
|
||||
int cy = cpnt.y() + dps[dir].y();
|
||||
dir++;
|
||||
if (frect.contains(cx, cy)) {
|
||||
if (field[cx][cy] == c) {
|
||||
if (jumps.contains(QPoint(cx, cy))) {
|
||||
int jx = cx - 1;
|
||||
int jy = cy;
|
||||
if (jumps.contains(QPoint(jx, jy))) fill(jx, jy, (short)Jump);
|
||||
jx = cx + 1;
|
||||
if (jumps.contains(QPoint(jx, jy))) fill(jx, jy, (short)Jump);
|
||||
jx = cx;
|
||||
jy = cy - 1;
|
||||
if (jumps.contains(QPoint(jx, jy))) fill(jx, jy, (short)Jump);
|
||||
jy = cy + 1;
|
||||
if (jumps.contains(QPoint(jx, jy))) fill(jx, jy, (short)Jump);
|
||||
const Cell & cell(field[cx][cy]);
|
||||
if (cell.value == c) {
|
||||
if (cell.direction == HorizontalBus || cell.direction == VerticalBus) {
|
||||
if (dps[dir].x() == 0 && cell.direction == VerticalBus)
|
||||
return false;
|
||||
if (dps[dir].y() == 0 && cell.direction == HorizontalBus)
|
||||
return false;
|
||||
}
|
||||
ca_ = QLineF(QPointF(cx, cy), cpnt).angle();
|
||||
if (ca_ != pa_ && !first)
|
||||
@@ -141,11 +129,12 @@ void BlockViewWavetrace::gatherPath() {
|
||||
while (cl > 0) {
|
||||
cl--;
|
||||
pa = ca;
|
||||
int dir = 0;
|
||||
if (checkAndStep(dir, cl, ca, pa)) continue;
|
||||
if (checkAndStep(dir, cl, ca, pa)) continue;
|
||||
if (checkAndStep(dir, cl, ca, pa)) continue;
|
||||
if (checkAndStep(dir, cl, ca, pa)) continue;
|
||||
|
||||
if (checkAndStep(0, cl, ca, pa)) continue;
|
||||
if (checkAndStep(1, cl, ca, pa)) continue;
|
||||
if (checkAndStep(2, cl, ca, pa)) continue;
|
||||
if (checkAndStep(3, cl, ca, pa)) continue;
|
||||
|
||||
}
|
||||
path_.push_front(st);
|
||||
//cout << path_.size() << endl;
|
||||
@@ -154,13 +143,13 @@ void BlockViewWavetrace::gatherPath() {
|
||||
|
||||
void BlockViewWavetrace::setPreferredDirection(BlockViewWavetrace::Direction dir) {
|
||||
dir_ = dir;
|
||||
if (dir == Horizontal) {
|
||||
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 == Vertical) {
|
||||
if (dir == BlockViewWavetrace::Vertical) {
|
||||
dps[2] = QPoint(0, -1);
|
||||
dps[3] = QPoint(0, 1);
|
||||
dps[0] = QPoint(-1, 0);
|
||||
|
||||
@@ -27,7 +27,7 @@ class QAD_EXPORT BlockViewWavetrace {
|
||||
public:
|
||||
BlockViewWavetrace(int width = 1, int height = 1);
|
||||
|
||||
enum CellState {Empty = -1, Blocked = -2, Jump = -3};
|
||||
enum CellState {Empty = -1, Blocked = -2, HorizontalBus = -3, VerticalBus = -4};
|
||||
enum Direction {NoTrace, Horizontal, Vertical};
|
||||
|
||||
int width() const {return wid;}
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
void resize(const QSize & sz) {resize(sz.width(), sz.height());}
|
||||
void fill(short val = -1);
|
||||
void fill(const QRect & rect, short val = -1);
|
||||
void fill(const QPoint & point, short val = -1) {field[point.x()][point.y()] = val;}
|
||||
void fill(const QPoint & point, short val = -1) {fill(point.x(), point.y(), val);}
|
||||
void fill(int px, int py, short val);
|
||||
void fill(BlockViewWavetrace::CellState val = Empty) {fill((short)val);}
|
||||
void fill(const QRect & rect, BlockViewWavetrace::CellState val = Empty) {fill(rect, (short)val);}
|
||||
@@ -52,9 +52,15 @@ public:
|
||||
const QVector<QPoint> & path() const;
|
||||
|
||||
private:
|
||||
struct Cell {
|
||||
Cell(short v = Empty): value(v), direction(0) {}
|
||||
short value;
|
||||
short direction;
|
||||
};
|
||||
|
||||
int wid, hei, max_steps;
|
||||
Direction dir_;
|
||||
QVector<QVector<short> > field;
|
||||
QVector<QVector<Cell> > field;
|
||||
QVector<QPoint> path_;
|
||||
QVector<QPoint> jumps;
|
||||
QPoint dps[4], st, fn;
|
||||
|
||||
Reference in New Issue
Block a user