This repository has been archived on 2020-09-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
libs/qad/blockview/blockviewwavetrace.cpp
andrey 3e0ec72e7d Blockview changes:
1) Теперь для создания сегмента не надо держать Shift, а перемешение шины теперь с нажатой клавишей Shift
2) Режим трассировки шин теперь пытается проложить маршрут с возможностью пересечения шины под прямым углом
3) Теперь рисуются точки соединения сегментов если их больше 2х
4) Обновлена подсказка в tooltip

p.s. update pip)
2020-08-11 17:35:18 +03:00

179 lines
4.1 KiB
C++

#include "blockviewwavetrace.h"
#include <QTime>
BlockViewWavetrace::BlockViewWavetrace(int width, int height) {
max_steps = 512;
resize(width, height);
setPreferredDirection(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;
}
void BlockViewWavetrace::fill(int px, int py, short val) {
field[px][py] = val;
}
bool BlockViewWavetrace::trace(const QPoint & start, const QPoint & finish) {
st = start;
fn = 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) {
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));
}
};
if (field[fn.x()][fn.y()] < (short)Empty)
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();
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);
}
cpnts = npnts;
//qDebug() << cl << ": " << cpnts.size();
}
return false;
}
void BlockViewWavetrace::gatherPath() {
path_.clear();
path_.push_back(fn);
if (dir_ == NoTrace) {
path_.push_front(st);
return;
}
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;
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);
}
ca_ = QLineF(QPointF(cx, cy), cpnt).angle();
if (ca_ != pa_ && !first)
path_.push_front(cpnt);
cpnt = QPoint(cx, cy);
first = false;
return true;
}
}
return false;
};
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;
}
path_.push_front(st);
//cout << path_.size() << endl;
}
void BlockViewWavetrace::setPreferredDirection(BlockViewWavetrace::Direction dir) {
dir_ = dir;
if (dir == Horizontal) {
dps[0] = QPoint(0, -1);
dps[1] = QPoint(0, 1);
dps[2] = QPoint(-1, 0);
dps[3] = QPoint(1, 0);
}
if (dir == 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_;
}