diff --git a/src/Algorithm/include/GraphPath.h b/src/Algorithm/include/GraphPath.h index 1541043..d2eca80 100644 --- a/src/Algorithm/include/GraphPath.h +++ b/src/Algorithm/include/GraphPath.h @@ -28,11 +28,14 @@ class GraphPath final : public QObject { void DFSRecursiveVersion(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end); - void GBFS(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end); + void GBFS(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end, + bool useManhattan = false); - void Dijkstra(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end); + void Dijkstra(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end, + bool useManhattan = false); - void aStar(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end); + void aStar(std::vector &points, const QPixmap &pixmap, QPoint start, QPoint end, + bool useManhattan = false); private: static GraphPath *instance; diff --git a/src/Algorithm/src/GraphPath.cpp b/src/Algorithm/src/GraphPath.cpp index f79e934..cfdbb1a 100644 --- a/src/Algorithm/src/GraphPath.cpp +++ b/src/Algorithm/src/GraphPath.cpp @@ -27,21 +27,19 @@ static constexpr auto visitPoint = [](const QRgb color) { return color == Config::getInstance()->getConfigField(WALL_COLOR); }; static constexpr auto getManhattanDistance = [](const QPoint &start, const QPoint &end) { - return abs(start.x() - end.x()) + std::abs(start.y() - end.y()); + return sc_double(abs(start.x() - end.x()) + std::abs(start.y() - end.y())); }; static constexpr auto getEuclideanDistance = [](const QPoint &start, const QPoint &end) { return sqrt(std::pow(start.x() - end.x(), 2) + std::pow(start.y() - end.y(), 2)); }; -template struct StorePoint { QPoint point{invalidPoint}; - T distance{-1}; + double distance{-1}; }; -template struct StorePointCmp { - bool operator()(const StorePoint &first, const StorePoint &second) { + bool operator()(const StorePoint &first, const StorePoint &second) const { return first.distance > second.distance; } }; @@ -177,8 +175,7 @@ void GraphPath::DFSRecursiveVersion(std::vector &points, const QPixmap &p } void GraphPath::_DFSRecursiveVersion(std::vector &points, std::vector &path, QImage &image, - const QPoint start, - const QPoint end, + const QPoint start, const QPoint end, std::vector > &vis) { if (returnFlag) return; if (start.x() == end.x() && start.y() == end.y()) { @@ -201,17 +198,21 @@ void GraphPath::_DFSRecursiveVersion(std::vector &points, std::vector &points, const QPixmap &pixmap, const QPoint start, const QPoint end) { +void GraphPath::GBFS(std::vector &points, const QPixmap &pixmap, const QPoint start, + const QPoint end, const bool useManhattan) { LOG(INFO) << "GBFS search start"; const QImage image = pixmap.toImage(); - using Point = StorePoint; - std::priority_queue, StorePointCmp > queue; + double (*opt)(const QPoint &, const QPoint &) = getEuclideanDistance; + if (useManhattan) { + opt = getManhattanDistance; + } + std::priority_queue, StorePointCmp> queue; std::vector vis(pixmap.width(), std::vector(pixmap.height(), invalidPoint)); TIMER_START if (visitPoint(image.pixel(start))) { goto EndFunc; } - queue.emplace(start, getEuclideanDistance(start, end)); + queue.emplace(start, opt(start, end)); while (!queue.empty()) { const QPoint temp = queue.top().point; queue.pop(); @@ -228,7 +229,7 @@ void GraphPath::GBFS(std::vector &points, const QPixmap &pixmap, const QP continue; } points.emplace_back(tmp, SEARCHING_POINT_COLOR); - queue.emplace(tmp, getEuclideanDistance(tmp, end)); + queue.emplace(tmp, opt(tmp, end)); } } } @@ -249,12 +250,16 @@ void GraphPath::GBFS(std::vector &points, const QPixmap &pixmap, const QP updateTime(time); } -void GraphPath::Dijkstra(std::vector &points, const QPixmap &pixmap, const QPoint start, const QPoint end) { +void GraphPath::Dijkstra(std::vector &points, const QPixmap &pixmap, const QPoint start, + const QPoint end, const bool useManhattan) { LOG(INFO) << "Dijkstra search start"; const QImage image = pixmap.toImage(); - using DijkstraPoint = StorePoint; - std::priority_queue, StorePointCmp > queue; - std::vector vis(pixmap.width(), std::vector(pixmap.height())); + double (*opt)(const QPoint &, const QPoint &) = getEuclideanDistance; + if (useManhattan) { + opt = getManhattanDistance; + } + std::priority_queue, StorePointCmp> queue; + std::vector vis(pixmap.width(), std::vector(pixmap.height())); std::vector startVis(pixmap.width(), std::vector(pixmap.height(), false)); TIMER_START if (visitPoint(image.pixel(start))) { @@ -279,9 +284,9 @@ void GraphPath::Dijkstra(std::vector &points, const QPixmap &pixmap, cons if (tmp.x() < 0 || tmp.x() >= image.width() || tmp.y() < 0 || tmp.y() >= image.height()) continue; if (!visitPoint(image.pixel(tmp)) && (vis[tmp.x()][tmp.y()].point == invalidPoint || - vis[tmp.x()][tmp.y()].distance > vis[temp.x()][temp.y()].distance + getEuclideanDistance(temp, tmp))) { + vis[tmp.x()][tmp.y()].distance > vis[temp.x()][temp.y()].distance + opt(temp, tmp))) { vis[tmp.x()][tmp.y()].point = temp; - vis[tmp.x()][tmp.y()].distance = vis[temp.x()][temp.y()].distance + getEuclideanDistance(temp, tmp); + vis[tmp.x()][tmp.y()].distance = vis[temp.x()][temp.y()].distance + opt(temp, tmp); points.emplace_back(tmp, SEARCHING_POINT_COLOR); queue.emplace(tmp, vis[tmp.x()][tmp.y()].distance); } @@ -304,4 +309,5 @@ void GraphPath::Dijkstra(std::vector &points, const QPixmap &pixmap, cons updateTime(time); } -void GraphPath::aStar(std::vector &points, const QPixmap &pixmap, const QPoint start, const QPoint end) {} +void GraphPath::aStar(std::vector &points, const QPixmap &pixmap, const QPoint start, const QPoint end, + const bool useManhattan) {} diff --git a/src/Qt/include/ImageDisplay.h b/src/Qt/include/ImageDisplay.h index 5d98726..60cec4c 100644 --- a/src/Qt/include/ImageDisplay.h +++ b/src/Qt/include/ImageDisplay.h @@ -36,6 +36,8 @@ namespace QT { public slots: void setSearchSequential(bool); + void setUseManhattan(bool); + void searchPath(PathSearchMethod); void dealDestroy() const; @@ -99,6 +101,7 @@ namespace QT { QTimer *timer = nullptr; int step = 0; bool searchSequential = true; + bool useManhattan = false; }; } diff --git a/src/Qt/src/ImageDisplay.cpp b/src/Qt/src/ImageDisplay.cpp index 1d2dcde..aedf71d 100644 --- a/src/Qt/src/ImageDisplay.cpp +++ b/src/Qt/src/ImageDisplay.cpp @@ -82,6 +82,10 @@ namespace QT { this->searchSequential = searchSequential; } + void ImageDisplay::setUseManhattan(const bool useManhattan) { + this->useManhattan = useManhattan; + } + void ImageDisplay::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.drawPixmap(startPoint.x(), startPoint.y(), @@ -228,7 +232,7 @@ namespace QT { void ImageDisplay::searchPath(const PathSearchMethod searchMethod) { thread = new SearchThread(searchMethod, currentImage, {sc_int(start.x()), sc_int(start.y())}, - {sc_int(end.x()), sc_int(end.y())}); + {sc_int(end.x()), sc_int(end.y())}, useManhattan); connect(thread, &SearchThread::threadFinishSignal, [this] { points.clear(); points = std::move(thread->getResult()); diff --git a/src/Qt/src/MainWindow.cpp b/src/Qt/src/MainWindow.cpp index 28e5f11..dc46543 100644 --- a/src/Qt/src/MainWindow.cpp +++ b/src/Qt/src/MainWindow.cpp @@ -23,6 +23,7 @@ namespace QT { connect(this, SIGNAL(searchPathSignal(PathSearchMethod)), ui->image, SLOT(searchPath(PathSearchMethod))); connect(this, SIGNAL(destroyThread()), ui->image, SLOT(dealDestroy())); connect(ui->showSearchPathCheckBox, SIGNAL(clicked(bool)), ui->image, SLOT(setSearchSequential(bool))); + connect(ui->useManhattanCheckBox, SIGNAL(clicked(bool)), ui->image, SLOT(setUseManhattan(bool))); connect(ui->searchDelaySlider, &QSlider::valueChanged, [this](const int value) { ui->searchDelaySpinBox->setValue(value); ui->image->setInterval(value); diff --git a/src/Qt/ui/MainWindow.ui b/src/Qt/ui/MainWindow.ui index f4c2e1c..31da9a2 100644 --- a/src/Qt/ui/MainWindow.ui +++ b/src/Qt/ui/MainWindow.ui @@ -20,37 +20,58 @@ QLayout::SetDefaultConstraint - - + + + + + 2 + 0 + + - 150 + 0 0 - 清空坐标 + (0, 0) - - - - 开始寻路 + + + + 1 + + + 1000 + + + 1 - - + + - 寻路算法 + 按搜索顺序绘制路径 + + + true - - + + + + + 150 + 0 + + - 重绘路径 + 清空坐标 @@ -86,53 +107,89 @@ - - + + - 按搜索顺序绘制路径 + 开始寻路 - - true + + + + + + 0s + + + + + + + 寻路算法 + + + + + + + 重绘路径 + + + + + + + 绘制延迟: - + 寻路耗时: - - + + - 1 + 2 0 - - - 0 - 23 - - - 开始坐标: + (0, 0) - - - - 0s + + + + 1 - - - - - - 清空路径 + + 1000 + + + 1 + + + 100 + + + Qt::Horizontal + + + false + + + false + + + QSlider::TicksBelow + + + 100 @@ -170,118 +227,68 @@ - - + + + + 清空路径 + + + + + - 2 + 1 0 0 - 0 - - - - (0, 0) - - - - - - - - 150 23 - 打开图片 - - - - - - - 绘制延迟: - - - - - - - 1 - - - 1000 - - - 1 + 结束坐标: - - + + - 2 + 1 0 - - (0, 0) - - - - - - - 1 - - - 1000 - - - 1 - - - 100 - - - Qt::Horizontal - - - false - - - false - - - QSlider::TicksBelow + + + 0 + 23 + - - 100 + + 开始坐标: - - - - - 1 - 0 - - + + - 0 + 150 23 - 结束坐标: + 打开图片 + + + + + + + 使用霍夫曼距离 @@ -452,8 +459,8 @@ findPath() - 139 - 331 + 149 + 362 166 @@ -468,8 +475,8 @@ clearPath() - 97 - 352 + 107 + 391 167 @@ -484,8 +491,8 @@ repaintPath() - 115 - 381 + 125 + 420 216 diff --git a/src/Thread/include/SearchThread.h b/src/Thread/include/SearchThread.h index e6777a4..2da0e0a 100644 --- a/src/Thread/include/SearchThread.h +++ b/src/Thread/include/SearchThread.h @@ -15,7 +15,7 @@ class SearchThread final : public Thread { public: SearchThread(const PathSearchMethod &method, const QPixmap &pixmap, const QPoint &start, - const QPoint &end, QObject *parent = nullptr); + const QPoint &end, bool useManhattan = false, QObject *parent = nullptr); [[nodiscard]] std::vector &getResult(); @@ -36,6 +36,7 @@ class SearchThread final : public Thread { const QPixmap &pixmap; QPoint start; QPoint end; + bool useManhattan; }; #endif diff --git a/src/Thread/src/SearchThread.cpp b/src/Thread/src/SearchThread.cpp index 416ce67..66f7033 100644 --- a/src/Thread/src/SearchThread.cpp +++ b/src/Thread/src/SearchThread.cpp @@ -13,8 +13,8 @@ #include SearchThread::SearchThread(const PathSearchMethod &method, const QPixmap &pixmap, const QPoint &start, - const QPoint &end, QObject *const parent): - Thread{parent}, searchMethod{method}, pixmap{pixmap}, start{start}, end{end} {} + const QPoint &end, const bool useManhattan, QObject *const parent): + Thread{parent}, searchMethod{method}, pixmap{pixmap}, start{start}, end{end}, useManhattan{useManhattan} {} std::vector &SearchThread::getResult() { return result; @@ -28,9 +28,9 @@ void SearchThread::execute() { break; case BFS: GraphPath::getInstance()->BFS(result, pixmap, start, end); break; - case GBFS: GraphPath::getInstance()->GBFS(result, pixmap, start, end); + case GBFS: GraphPath::getInstance()->GBFS(result, pixmap, start, end, useManhattan); break; - case DIJKSTRA: GraphPath::getInstance()->Dijkstra(result, pixmap, start, end); + case DIJKSTRA: GraphPath::getInstance()->Dijkstra(result, pixmap, start, end, useManhattan); break; case A_STAR: break; default: break;