diff --git a/qad/blockview/blockview.cpp b/qad/blockview/blockview.cpp index 418c5f7..db628a0 100644 --- a/qad/blockview/blockview.cpp +++ b/qad/blockview/blockview.cpp @@ -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); } diff --git a/qad/blockview/blockviewwavetrace.cpp b/qad/blockview/blockviewwavetrace.cpp index 72b597c..79be7fd 100644 --- a/qad/blockview/blockviewwavetrace.cpp +++ b/qad/blockview/blockviewwavetrace.cpp @@ -1,5 +1,4 @@ #include "blockviewwavetrace.h" -#include 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 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); diff --git a/qad/blockview/blockviewwavetrace.h b/qad/blockview/blockviewwavetrace.h index f95a8c7..c8d0f90 100644 --- a/qad/blockview/blockviewwavetrace.h +++ b/qad/blockview/blockviewwavetrace.h @@ -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 & 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 > field; + QVector > field; QVector path_; QVector jumps; QPoint dps[4], st, fn;