QT、C++实现地图导航系统(mapSystem)

news2024/11/26 4:27:28

文章目录

    • 地图导航系统
      • 项目应用背景
      • 技术栈选择
      • 数据处理
      • 算法实现
      • 界面实现
      • 源码展示
      • 成果展示
      • 源码下载 (免费)

地图导航系统

项目应用背景

电子地图导航系统的主要目的是为用户提供精确、实时的导航和位置信息,以帮助他们在城市或地区内轻松找到目的地。
①提供用户友好的界面,使用户能够轻松输入起点和目的地,并获取最佳的导航路线。
②支持用户个性化设置,例如选择不同的地图样式、导航偏好和关注的兴趣点,以满足不同用户的需求。
③提供可靠的地图数据,包括道路、建筑物、公共设施和兴趣点的详细信息,以帮助用户更好地理解其周围环境。
在这里插入图片描述

技术栈选择

用哈希map以及设置类进行数据的存储

对于地图导航系统,我们需要考虑到数据的存储防止内存的溢出,地图中的数据多并且杂需要进行数据清洗。对于我们需要的数据提取出来并存储下来。这样我们需要考虑数据的存储方式而且需要在数据调用时可以更快的将某条数据进行处理。

Floyd路径算法计算最短路径

考虑到该算法可以实现全局最短路径的搜索;既适用于有向图又适用于无向图;采用动态规划思想,通过逐步优化子问题的解决方案来找到整体的最优解;适用性广泛, Floyd算法适用于各种类型的图,包括稠密图和稀疏图,它不依赖于特定的图结构,因此可以用于多种应用领域。

QT实现图形界面开发

QT的图形界面实现简单容易;模块化,可扩展,QT的模块化架构允许你仅包含你需要的模块,从而减小应用程序的大小。

数据处理

Openstreetmap 数据osm数据的格式的特点,虽然是osm数据格式但是获取的数据格式xml可以通过解析xml数据格式的方式进行解析。
数据解析: 使用QT中的xml解析库函数进行数据的解析。读取其中的数据挑选出其中的ID 号,Lat维度,Lon经度。

算法实现

真实经纬度坐标结构体类型
在这里插入图片描述

经纬度坐标转换函数
在这里插入图片描述

构造解析OSM(XMl)类
在这里插入图片描述

数据类型转化
在这里插入图片描述
根据经纬度计算点与点之间距离
在这里插入图片描述
画出道路图
在这里插入图片描述

构造Floyd算法函数
在这里插入图片描述

界面实现

在Widget标出村落
在这里插入图片描述

共54个村落标注点,接收起点终点,进行画线
在这里插入图片描述

构造放大和缩小地图功能槽函数
在这里插入图片描述

源码展示

.pro文件

#-------------------------------------------------
#
# Project created by QtCreator 2023-09-22T10:19:55
#
#-------------------------------------------------

QT       += core gui
QT += xml
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = cheshi
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

RESOURCES += \
    resourcefile.qrc

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QXmlStreamReader>
#include <QFile>
#include <unordered_map>
#include <QDebug>
#include <cmath>
#include <vector>
#include <QString>
#include <set>
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsTextItem>

const int INF = 10000000;
int ressssssssss(int x);

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    //void on_InButton_clicked();
    //void on_OutButton_clicked();
    void showComBox();
    void zoomInOut();
    void floyd(int n);
    void initDist();
    void getPath(int start, int end);
    void initMap();
    void click();
private slots:
    void InButton_clicked();
    void OutButton_clicked();
    void showShortPath();
    void shortBtnclicked();

protected:
    void paintEvent(QPaintEvent *event) override;
private:
    Ui::MainWindow *ui;

};
struct coordinates  //对应的经纬度坐标(double)
{
    int id;
    double lon;
    double lat;
};
struct coordinatesStr  //对应的经纬度坐标(QString)
{
    QString id;
    QString lon;
    QString lat;
};
struct coordinatesInt //对应的经纬度坐标(int)
{
    QString id;
    int x;
    int y;
};

class resolve_xml
{
public:
    double degreesToRadians(double degrees);
    double radiansToDegrees(double radians);
    double calculateDistance(coordinates node1, coordinates node2);
    void saveNode(int id,coordinates node);
    void strChangeDouble(coordinatesStr node);
    void findCommonNode();
    void changeCoor(QString strId);
    int imortant();
    std::map<QString,coordinatesInt>doubleCoorMap;
    std::vector<coordinatesInt>doubleCoor;
    std::vector<coordinatesInt>doubleWay;
    double minLat;     //最小纬度
    double maxLat;     //最大经度
    double minLon;
    double maxLon;
};
class Graph {
public:
    int vertices = 54;
    std::vector<int>result;
    std::vector<std::vector<int>> distance;
    std::vector<std::vector<int>> next;
    void addEdge(int source, int destination, int weight) {
        distance[source][destination] = weight;
        next[source][destination] = destination;
    }

    void floydWarshall() {
    //distance.assign(54, std::vector<int>(54, INF));
    next.assign(54, std::vector<int>(54, -1));
        for (int k = 0; k < vertices; ++k) {
            for (int i = 0; i < vertices; ++i) {
                for (int j = 0; j < vertices; ++j) {
                    if (distance[i][k] != INF && distance[k][j] != INF && distance[i][k] + distance[k][j] < distance[i][j]) {
                        distance[i][j] = distance[i][k] + distance[k][j];
                        next[i][j] = next[i][k];
                    }
                }
            }
        }
    }

    void printShortestPath(int start, int end) {
        if (distance[start][end] == INF) {
            //cout << "No path exists from Node " << start << " to Node " << end << endl;
            return;
        }

        //cout << "Shortest Path from Node " << start << " to Node " << end << ": ";
        result.push_back(start);

        while (start != end) {
            start = next[start][end];
            //cout << " -> " << start;
            result.push_back(start);
        }

    }
};


#endif // MAINWINDOW_H

mainwindow.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <map>
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsTextItem>

const int MAXN = 10000000;

Graph grap;
int n = 54;
//std::vector<std::vector<int>> prev(n, std::vector<int>(n, -1));
std::map<QString,coordinatesStr>mp;
std::map<QString,coordinates>doubleMap;
std::vector<QString>commonNode;
std::map<QString,QString>mapVillage;
std::map<QString,std::vector<QString>>mapWay;
std::map<QString,int>villageToInt;
std::map<int,QString>villageToString;
std::vector<QString>nodeVillage;

//ui->graphicsView->setScene(scene);

int dist[54][54];  // 保存点与点之间的距离
int prev[100][100];  // 保存路径上的前一个点
std::vector<int> path;  // 存储最短路径上的点
int Matrix[54][54] = {0};
resolve_xml Xml;

double resolve_xml::degreesToRadians(double degrees) {
    return degrees * M_PI / 180;
}
double resolve_xml::radiansToDegrees(double radians) {
    return radians * 180 / M_PI;
}
double resolve_xml::calculateDistance(coordinates node1, coordinates node2) { //经纬度坐标
    double dLat = degreesToRadians(node2.lat - node1.lat);   //Haversine公式
    double dLon = degreesToRadians(node2.lon - node1.lon);
    double a = std::sin(dLat / 2) * std::sin(dLat / 2) +
               std::cos(degreesToRadians(node1.lat)) * std::cos(degreesToRadians(node2.lat)) *
               std::sin(dLon / 2) * std::sin(dLon / 2);
    double c = 2 * std::atan2(std::sqrt(a), std::sqrt(1 - a));
    double distance = 6378137 * c;
    return distance;
}

void resolve_xml::strChangeDouble(coordinatesStr node)
{
    coordinates coor;
    coor.id = node.id.toInt();
    coor.lat = node.lat.toDouble();
    coor.lon = node.lon.toDouble();
    doubleMap[node.id] = coor;
}

void resolve_xml::findCommonNode() //查找公共交点
{
    QFile file(":/qrc/map.osm");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
            qDebug() << "无法打开XML文件.";
            //exit(0);
    }
    QXmlStreamReader xml(&file);

    std::set<QString> wayNodes;

    int wayCount = 0;
    bool flag = false;

    while (!xml.atEnd() && !xml.hasError()) {
        QXmlStreamReader::TokenType token = xml.readNext();
        if (token == QXmlStreamReader::StartElement) {
            if (xml.name() == "way") {
                flag = true;
            }
            else if (xml.name() == "nd" && flag == true) {
                QString ndRef = xml.attributes().value("ref").toString();
                if (wayNodes.find(ndRef) != wayNodes.end()) {
                    commonNode.push_back(ndRef);
                }
                else {
                    wayNodes.insert(ndRef);
                }
            }
            else if(xml.name() == "relation"){
                flag = false;
            }
            else if(xml.name() == "member"){
                flag = false;
            }
        }
    }
    file.close();
}

void resolve_xml::changeCoor(QString strId)
{
    coordinates coo = doubleMap[strId];
    coordinatesInt cooint ;
    int width = (maxLon - minLon) * 10000;
    int length = (maxLat - minLat) * 10000;
    int x = (maxLat - coo.lat ) * 10000 ;
    int y = (coo.lon - minLon) * 10000 ;
    cooint.id = strId;
    cooint.x = y;
    cooint.y = x;
    Xml.doubleCoor.push_back(cooint);
    Xml.doubleCoorMap[strId] = cooint;
}
/*void resolve_xml::saveNode(int id,coordinates node)
{
    mp[id] = node;
}*/
int resolve_xml::  imortant()
{

    std::vector<QString>strNode;
    std::vector<QString>strWay;
    coordinatesStr coorStr;   //QString类型经纬度的结构体
    QString wayId;      //way的Id
    QString tagKey;
    QString tagValue;
    QString nodeId;     //node的ID
    QString nodeLon;    //node的经度
    QString nodeLat;    //node的纬度
    QFile fileName(":/qrc/map.osm");
    if (!fileName.open(QIODevice::ReadOnly | QIODevice::Text))
    {
            qDebug() << "无法打开XML文件.";
            return 1;
    }
    QXmlStreamReader xml(&fileName);
        while (!xml.atEnd() && !xml.hasError()) {
            QXmlStreamReader::TokenType token = xml.readNext();

            if (token == QXmlStreamReader::StartElement) {
                if(xml.name() == "node"){
                    nodeId = xml.attributes().value("id").toString();
                    nodeLon = xml.attributes().value("lon").toString();
                    nodeLat = xml.attributes().value("lat").toString();
                    coorStr.id = nodeId;
                    coorStr.lat = nodeLat;
                    coorStr.lon = nodeLon;
                    mp[nodeId] = coorStr;
                    strNode.push_back(nodeId);
                }
                else if (xml.name() == "way") {
                    // 提取way元素的id属性值
                    strWay.clear();
                    wayId = xml.attributes().value("id").toString();
                    //qDebug() << "Way ID:" << wayId;
                } else if (xml.name() == "nd") {
                    // 提取nd元素的ref属性值
                    QString ndRef = xml.attributes().value("ref").toString();
                    strWay.push_back(ndRef);
                    mapWay[wayId] = strWay;
                    //qDebug() << "ND Ref:" << ndRef;
                } else if (xml.name() == "tag") {
                    // 提取tag元素的k和v属性值
                    QString str1 = tagKey;
                    QString str2 = tagValue;
                    tagKey = xml.attributes().value("k").toString();
                    tagValue = xml.attributes().value("v").toString();
                    if(tagValue == "village")
                    {
                        nodeVillage.push_back(str2);
                        mapVillage[str2] = nodeId;
                    }
                    //qDebug() << "Tag Key:" << tagKey << ", Value:" << tagValue;
                }
                else if(xml.name() == "bounds")
                {
                    //提取数据中的最大最小经纬度
                    Xml.minLat = xml.attributes().value("minlat").toString().toDouble();
                    Xml.minLon = xml.attributes().value("minlon").toString().toDouble();
                    Xml.maxLat = xml.attributes().value("maxlat").toString().toDouble();
                    Xml.maxLon = xml.attributes().value("maxlon").toString().toDouble();
                }
            }
        }
       if (xml.hasError())
       {
           qDebug() << "XML解析错误: " << xml.errorString();
           return 1;
       }
      for(auto it = mp.begin();it != mp.end();it++) //将QString的经纬度转化成double类型的经纬度
      {
          QString Id = it->first;
          coordinatesStr jw = it->second;
          Xml.strChangeDouble(jw);
          Xml.changeCoor(Id);
          //qDebug()<<Id;
          //qDebug()<<jw.lat<<" "<<jw.lon;
      }
      for(auto it = mapWay.begin();it != mapWay.end();it++)
      {
          std::vector<QString> Strway = it->second;
          for(int i = 0;i < Strway.size();i++)
          {
                QString Qstr = Strway[i];
                double x = doubleMap[Qstr].lat;
                double y = doubleMap[Qstr].lon;
                minLat = std::min(minLat,x);
                minLon = std::min(minLon,y);
                maxLat = std::max(maxLat,x);
                maxLon = std::max(maxLon,y);
          }
      }
     // qDebug()<<"xxxx"<<minLat<<minLon<<maxLat<<maxLon; //输出最大最小经纬度
      for(auto it = mapWay.begin();it != mapWay.end();it++) //保存所有way的点
      {
          QString way = it->first;
          std::vector<QString> Strway = it->second;
          for(int i = 0;i < Strway.size();i++)
          {
                QString Qstr = Strway[i];
                //Xml.changeCoor(Qstr);
          }
      }
      for(auto it = mapWay.begin();it != mapWay.end();it++) //根据经纬度计算点与点之间距离,连接成路
      {
          QString way = it->first;
          //qDebug()<<way;
          std::vector<QString> Strway = it->second;
          //qDebug()<<"way nodeNumber:"<<Strway.size();
          int distanceWay = 0;
          for(int i = 1;i < Strway.size();i++)
          {
                QString Qstr1 = Strway[i-1];
                QString Qstr2 = Strway[i];
                coordinates node1 = doubleMap[Qstr1];
                coordinates node2 = doubleMap[Qstr2];
                distanceWay += (int)Xml.calculateDistance(node1,node2);
          }
          //qDebug()<<"way distance:"<<distanceWay;
      }
      for(auto it = mapVillage.begin();it != mapVillage.end();it++)
      {
          //qDebug()<<"village: "<<it->first<<"village nodeId: "<<it->second;
      }
      for(int i = 0;i < nodeVillage.size();i++)
      {
          QString sst = nodeVillage[i];
          villageToInt[sst] = i;
          villageToString[i] = sst;
          //qDebug()<<sst<<i;
      }
      /*QString str = "121.1458065";
      bool ok;
      double value = str.toDouble(&ok);
      if (ok) {
          qDebug() << "Converted value:" << value;
      } else {
          qDebug() << "Conversion failed.";
      }*/
      Xml.findCommonNode();
      for(int i = 0;i < commonNode.size();i++)
      {
          //qDebug()<<"commonNode"<<commonNode[i];
      }
      //qDebug()<<"commonNode size"<<commonNode.size()<<"way size:"<<mapWay.size()<<"village size"<<mapVillage.size();
      //qDebug()<<"---"<<Xml.doubleCoor.size();
      fileName.close();
      return 0;
}


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::showComBox()
{
    for(auto it = mapVillage.begin();it != mapVillage.end();it++)
    {
        QString stt = it->first;
        ui->startBox->addItem(stt);
    }
    for(auto it = mapVillage.begin();it != mapVillage.end();it++)
    {
        QString stt = it->first;
        ui->endBox->addItem(stt);
    }
    qDebug()<<mapVillage.size();
}

void MainWindow::zoomInOut()
{
    // 连接放大按钮
    connect(ui->InButton, &QPushButton::clicked, this, &MainWindow::InButton_clicked);

    // 连接缩小按钮
    connect(ui->outButton, &QPushButton::clicked, this, &MainWindow::OutButton_clicked);

    //连接最短路径按钮
    connect(ui->shortBtn, &QPushButton::clicked, this, &MainWindow::shortBtnclicked);
}

void MainWindow::InButton_clicked()
{
    qDebug() << "InButton was clicked or triggered!";
    double scaleFactor = 1.15;
    ui->graphicsView->scale(scaleFactor, scaleFactor);
}

void MainWindow::OutButton_clicked()
{
    double scaleFactor = 1.15;
    ui->graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
}

void MainWindow::showShortPath()
{

    QGraphicsScene *scene = ui->graphicsView->scene();
    ui->graphicsView->setRenderHint(QPainter::Antialiasing);  //抗锯齿功能,画的线更润换
   // ui->graphicsView->setScene(scene);
    std::vector<QPointF>shortPath;
    QPainterPath pathVillage;
    for(int i = 0;i < path.size();i++)
    {
        int  intId = path[i];
        QString StrID = villageToString[intId];
        coordinatesInt coorvillage = Xml.doubleCoorMap[mapVillage[StrID]];
        QPointF points;
        points.setX(coorvillage.x);
        points.setY(coorvillage.y);
        shortPath.push_back(points);
    }
    qDebug()<<shortPath.size();
    int distance;
    for(int i = 1;i < path.size();i++)
    {
        int  intId1 = path[i-1];
        int  intId2 = path[i];
        QString StrID1 = villageToString[intId1];
        QString StrID2 = villageToString[intId2];
        coordinates node1 = doubleMap[mapVillage[StrID1]];
        coordinates node2 = doubleMap[mapVillage[StrID2]];
        distance = Xml.calculateDistance(node1,node2);
    }
    QString setdist = QString::number(distance);
    setdist += " meter";
    ui->showDist->setText(setdist);
    /*if(shortPath.size() != 0)
    {

        pathVillage.moveTo(shortPath[0]);
        for(int i = 1;i <shortPath.size();i++)
        {
            pathVillage.lineTo(shortPath[i]);
        }
        QGraphicsPathItem *pathItems = new QGraphicsPathItem(pathVillage);
        scene->addItem(pathItems);

        // 可选:设置道路的样式
        QPen roadPenVillage(Qt::green, 2);  // 示例:绿色,线宽为3
        pathItems->setPen(roadPenVillage);
    }*/
    if(!scene) {
        scene = new QGraphicsScene(this);
        ui->graphicsView->setScene(scene);
    }
    for( int i = 1; i < shortPath.size();i++)
    {
        QPen pen(Qt::red);
        pen.setWidth(3);
        QPointF point1 = shortPath[i-1];
        QPointF point2 = shortPath[i];
        scene->addLine(point1.x(), point1.y(), point2.x(), point2.y(), pen);  // 这里使用红色画笔
    }
}

void MainWindow::floyd(int n)
{
    for(int k = 0; k < n; k++) {
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(dist[i][k] != INT_MAX && dist[k][j] != INT_MAX && dist[i][j] > dist[i][k] + dist[k][j]) {
                    dist[i][j] = dist[i][k] + dist[k][j];
                    prev[i][j] = k;
                }
            }
        }
    }
}

void MainWindow::initDist()
{
    n = 54;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            if(i == j) dist[i][j] = 0;
            else  if ( j % 2 == 0)
            {
                QString s1 = villageToString[i];
                QString s2 = villageToString[j];
                coordinates node1 = doubleMap[mapVillage[s1]];
                coordinates node2 = doubleMap[mapVillage[s2]];
                int distancesss = Xml.calculateDistance(node1,node2);
                qDebug()<<"s="<<distancesss;
                dist[i][j] = distancesss;
            }
            /*else if (Matrix[i][j] == 0)
            {
                dist[i][j] = INT_MAX;
            }*/
            prev[i][j] = i;
        }
    }
}

void MainWindow::getPath(int start, int end)
{
    //if(start != end) getPath(start, prev[start][end]);
    //path.push_back(end);
    //path.clear();
    /*QString cur1 = ui->startBox->currentText();
    QString cur2 = ui->endBox->currentText();
    int current1 = villageToInt[cur1];
    int current2 = villageToInt[cur2];
    path.push_back(current1);
    while (current1 != current2) {
        current1 = prev[current1][current2];
        path.push_back(current1);
    }*//*
    if (prev[start][end] == -1) {
            return ;
        }

        path.push_back(start);
        while (start != end) {
            start = prev[start][end];
            path.push_back(start);
        }*/
    /*if (start == end || prev[start][end] == -1) {
            // 如果已经到达终点或者无法到达,返回包含起点的路径
            return {start};
        } else {
            // 递归调用,将路径从起点到 next[start][end] 和从 next[start][end] 到终点连接起来
            std::vector<int> path1 = getPath(start, prev[start][end]);
            std::vector<int> path2 = getPath(prev[start][end], end);

            // 合并两个路径
            path1.insert(path1.end(), path2.begin() + 1, path2.end());
            return path1;
        }*/
    if(start != end) getPath(start, prev[start][end]);
        path.push_back(end);
}

void MainWindow::initMap()
{
    Matrix[0][32] = Matrix[32][0] = 1;
    Matrix[0][53] = Matrix[53][0] = 1;
    Matrix[0][48] = Matrix[48][0] = 1;
    Matrix[0][47] = Matrix[47][0] = 1;
    Matrix[0][49] = Matrix[49][0] = 1;
    Matrix[0][50] = Matrix[50][0] = 1;
    Matrix[0][51] = Matrix[51][0] = 1;
    Matrix[0][36] = Matrix[36][0] = 1;
    Matrix[0][35] = Matrix[35][0] = 1;
    Matrix[0][34] = Matrix[34][0] = 1;
    Matrix[0][37] = Matrix[37][0] = 1;
    Matrix[0][40] = Matrix[40][0] = 1;
    Matrix[0][50] = Matrix[50][0] = 1;
    Matrix[2][33] = Matrix[33][2] = 1;
    Matrix[2][3] = Matrix[3][2] = 1;
    Matrix[2][4] = Matrix[4][2] = 1;
    Matrix[4][3] = Matrix[3][4] = 1;
    Matrix[4][33] = Matrix[33][4] = 1;
    Matrix[5][8] = Matrix[8][5] = 1;
    Matrix[5][9] = Matrix[9][5] = 1;
    Matrix[5][10] = Matrix[10][5] = 1;
    Matrix[7][6] = Matrix[6][7] = 1;
    Matrix[7][4] = Matrix[4][7] = 1;
    Matrix[11][43] = Matrix[43][11] = 1;
    Matrix[11][45] = Matrix[45][11] = 1;
    Matrix[11][42] = Matrix[42][11] = 1;
    Matrix[12][13] = Matrix[13][12] = 1;
    Matrix[12][14] = Matrix[14][12] = 1;
    Matrix[12][15] = Matrix[15][12] = 1;
    Matrix[16][20] = Matrix[20][16] = 1;
    Matrix[17][19] = Matrix[19][17] = 1;
    Matrix[17][18] = Matrix[18][17] = 1;
    Matrix[20][17] = Matrix[17][20] = 1;
    Matrix[20][18] = Matrix[18][20] = 1;
    Matrix[20][19] = Matrix[19][20] = 1;
    Matrix[21][22] = Matrix[22][21] = 1;
    Matrix[21][23] = Matrix[23][21] = 1;
    Matrix[21][26] = Matrix[26][21] = 1;
    Matrix[26][27] = Matrix[27][26] = 1;
    Matrix[26][24] = Matrix[24][26] = 1;
    Matrix[24][25] = Matrix[25][24] = 1;
    Matrix[25][31] = Matrix[31][25] = 1;
    Matrix[28][29] = Matrix[29][28] = 1;
    Matrix[28][30] = Matrix[30][28] = 1;
    Matrix[34][36] = Matrix[36][34] = 1;
    Matrix[35][36] = Matrix[36][35] = 1;
    Matrix[40][34] = Matrix[34][40] = 1;
    Matrix[40][37] = Matrix[37][40] = 1;
    Matrix[41][37] = Matrix[37][41] = 1;
    Matrix[41][34] = Matrix[34][41] = 1;

    Matrix[44][39] = Matrix[39][44] = 1;

    Matrix[39][38] = Matrix[38][39] = 1;
}

void MainWindow::click()
{
    test newobj(this);
    newobj.useMainWindowUI();

}
void MainWindow::paintEvent(QPaintEvent *event)
{
    QMainWindow::paintEvent(event);  // 调用父类的 paintEvent 以确保其他部分绘制正确
    /*QPainter painter(this);
    QPen pen;
    pen.setWidth(2);
    painter.setPen(pen);
    qDebug()<<"   "<<Xml.doubleCoor.size();
    for(int i = 0;i <Xml.doubleCoor.size();i++)
    {
        coordinatesInt it = Xml.doubleCoor[i];
        pen.setColor(Qt::red); // 设置画笔颜色
        painter.drawPoint(it.x, it.y);     // 在坐标 (50, 50) 上绘制一个点
    }*/

    QGraphicsScene *scene = new QGraphicsScene(this);
    ui->graphicsView->setScene(scene);
    ui->graphicsView->setRenderHint(QPainter::Antialiasing); //抗锯齿

    // 示例点位和名字
    /*int len = nodeVillage.size();
    QList<QPointF> points;
    for(int i = 0;i < len;i++)
    {
        QString villageNode = mapVillage[nodeVillage[i]];
        QPoint ppp;
        coordinatesInt coo = Xml.doubleCoorMap[villageNode];
        ppp.setX(coo.x);
        ppp.setY(coo.y);
        points.push_back(ppp);
        //qDebug()<<points.size();
    }

    for(int i = 0; i < nodeVillage.size(); ++i)
    {
        // 为每个点位创建一个小的椭圆
        QGraphicsEllipseItem *ellipse = scene->addEllipse(points[i].x() - 5, points[i].y() - 5, 10, 10, QPen(Qt::black), QBrush(Qt::red));

        // 创建一个文本项以显示名字
        QGraphicsTextItem *text = scene->addText(nodeVillage[i]);
        text->setPos(points[i].x() + 10, points[i].y() - text->boundingRect().height() / 2);
    }*/

    std::vector<std::vector<QPointF>>roads;
    for(auto it = mapWay.begin();it != mapWay.end();it++)
    {
        std::vector<QString> vectorStr = it->second;
        std::vector<QPointF>roadWay;
        for(int i = 0;i < vectorStr.size();i++)
        {
            QString wayStr = vectorStr[i];
            coordinatesInt coorWay;
            coorWay = Xml.doubleCoorMap[wayStr];
            QPoint pointWay;
            pointWay.setX(coorWay.x);
            pointWay.setY(coorWay.y);
            roadWay.push_back(pointWay);
        }
        roads.push_back(roadWay);
        roadWay.clear();
    }

    for (const std::vector<QPointF> &road : roads) {
        QPainterPath pathsss;
        pathsss.moveTo(road[0]);
        for (int i = 1; i < road.size(); ++i)
        {
            pathsss.lineTo(road[i]);
        }
        QGraphicsPathItem *pathItem = new QGraphicsPathItem(pathsss);
        scene->addItem(pathItem);

        // 可选:设置道路的样式
        QPen roadPen(Qt::blue, 2);  // 示例:蓝色,线宽为2
        pathItem->setPen(roadPen);
    }

    // 示例点位和名字
    int len = nodeVillage.size();
    QList<QPointF> points;
    for(int i = 0;i < len;i++)
    {
        QString villageNode = mapVillage[nodeVillage[i]];
        QPoint ppp;
        coordinatesInt coo = Xml.doubleCoorMap[villageNode];
        ppp.setX(coo.x);
        ppp.setY(coo.y);
        points.push_back(ppp);
        //qDebug()<<points.size();
    }

    for(int i = 0; i < nodeVillage.size(); ++i)
    {
        // 为每个点位创建一个小的椭圆
        QGraphicsEllipseItem *ellipse = scene->addEllipse(points[i].x() - 5, points[i].y() - 5, 10, 10, QPen(Qt::black), QBrush(Qt::red));

        // 创建一个文本项以显示名字
        QGraphicsTextItem *text = scene->addText(nodeVillage[i]);
        text->setPos(points[i].x() + 10, points[i].y() - text->boundingRect().height() / 2);
    }
}
class CustomGraphicsView : public QGraphicsView //放大缩小只能点击,不能使用滚轮
{
    Q_OBJECT
public:
    explicit CustomGraphicsView(QWidget* parent = nullptr)
        : QGraphicsView(parent) {}

protected:
    void wheelEvent(QWheelEvent* event) override
    {

    }
};


void MainWindow::shortBtnclicked()
{
    //initMap();
    /*for(int i = 0;i < 54;i++)
    {
        for(int j = 0;j < 54;j++)
        {
            if(i == j)
            {
                grap.addEdge(i,j,0);
            }
            else
            {
                if(Matrix[i][j] == 1)
                {
                    QString s1 = villageToString[i];
                    QString s2 = villageToString[j];
                    coordinates node1 = doubleMap[mapVillage[s1]];
                    coordinates node2 = doubleMap[mapVillage[s2]];
                    int distancesss = Xml.calculateDistance(node1,node2);
                    qDebug()<<"s="<<distancesss;
                    //dist[i][j] = distancesss;
                    grap.addEdge(i,j,distancesss);
                }
                else
                {
                    grap.addEdge(i,j,MAXN);
                }
            }
        }
    }
    grap.floydWarshall();
    qDebug()<<grap.result.size();
    path = grap.result;*/
    initDist();
    floyd(54);
    QString textBox1 = ui->startBox->currentText();
    QString textBox2 = ui->endBox->currentText();
    int idx1 = villageToInt[textBox1];
    int idx2 = villageToInt[textBox2];
    //grap.printShortestPath(idx1,idx2);
    getPath(idx1,idx2);
    showShortPath();
    //path.clear();
}

成果展示

在这里插入图片描述

源码下载 (免费)

链接: https://pan.baidu.com/s/1Ai4m-X6GwLmkpbQpESRRDw
提取码: 0703


更多资料尽在 GitHub 欢迎各位读者去Star

⭐学术交流群Q 754410389 持续更新中~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1056443.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ - 封装 unordered_set 和 unordered_map - 哈希桶的迭代器实现

前言 unordered_set 和 unordered_map 两个容器的底层是哈希表实现的&#xff0c;此处的封装使用的 上篇博客当中的哈希桶来进行封装&#xff0c;相当于是在 哈希桶之上在套上了 unordered_set 和 unordered_map 。 哈希桶的逻辑实现&#xff1a; C - 开散列的拉链法&…

Java环境配置无效

Java环境配置无效 老是使用1.8版本&#xff0c;象牛皮癣。 查找java来源 where java 打开C:\Windows\System32 删掉java.exe javaaw.exe javaaws.exe 正常

【超强图解Docker常见命令与实战】

目录 一、镜像容器基础&#xff08;一&#xff09;基本概念&#xff08;二&#xff09;镜像&#xff08;三&#xff09;容器&#xff08;四&#xff09;运行的容器&#xff08;五&#xff09; 镜像层(image layer) 二、常用命令&#xff08;一&#xff09;docker create <im…

XWiki Platform 安全漏洞RCE:CVE-2023-37462

2023年7月14日&#xff0c;美国国家标准与技术研究院&#xff08;NIST&#xff09;维护的综合性漏洞数据库&#xff08;NVD&#xff09;第一次记录了这个漏洞&#xff0c;这个漏洞影响版本是从7.0到14.48&#xff08;不包括&#xff09;和从14.5到14.10.4&#xff08;不包括&am…

BGP服务器租用价格表_腾讯云PK阿里云

BGP云服务器像阿里云和腾讯云均是BGP多线网络&#xff0c;速度更快延迟更低&#xff0c;阿里云BGP服务器2核2G3M带宽优惠价格108元一年起&#xff0c;腾讯云BGP服务器2核2G3M带宽95元一年起&#xff0c;阿腾云分享更多云服务器配置如2核4G、4核8G、8核16G等配置价格表如下&…

A*搜索算法(含Java源代码)

前言 本来是想写一块的&#xff0c;但是为了这个国庆的专属勋章就分开写了&#xff0c;这个侧重还是对作业题目要求的实现。 课题目的 理解 A Star 算法设计流程。 理解 A Star 算法的启发式函数的作用。 掌握 A Start 解决搜索问题的过程&#xff0c;能够应用 A Star 算法…

凉鞋的 Godot 笔记 101. Hello Godot!

101. Hello Godot 学习任何一门技术&#xff0c;第一件事就是先完成 Hello World&#xff01;的输出 所以我们也来先完成 Godot 的 Hello World。 我们所使用的 Godot 版本是 4.x 版本。 安装的过程就不给大家展示了&#xff0c;笔者更推荐初学者用 Steam 版本的 Godot&…

Scala第十八章节

Scala第十八章节 scala总目录 文档资料下载 章节目标 掌握Iterable集合相关内容.掌握Seq集合相关内容.掌握Set集合相关内容.掌握Map集合相关内容.掌握统计字符个数案例. 1. Iterable 1.1 概述 Iterable代表一个可以迭代的集合, 它继承了Traversable特质, 同时也是其他集合…

学习开发一个RISC-V上的操作系统(汪辰老师) — 环境配置

前言 &#xff08;1&#xff09;此系列文章是跟着汪辰老师的RISC-V课程所记录的学习笔记。 &#xff08;2&#xff09;该课程相关代码gitee链接&#xff1b; &#xff08;3&#xff09;PLCT实验室实习生长期招聘&#xff1a;招聘信息链接 &#xff08;4&#xff09;在学习汪辰老…

正则表达式验证和跨域postmessage

1.用正则表达式验证用户名 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

msvcp120.dll放在哪个文件夹?msvcp120.dll丢失解决方法详细分析

Msvcp120.dll 丢失可能会导致一些基于 Microsoft Visual C 编写的程序和游戏无法正常运行。Msvcp120.dll 是 Microsoft Visual C Redistributable 的一个组件&#xff0c;它包含了 C 运行时库&#xff0c;这些库在运行程序时会被加载到内存中。如果该文件丢失或损坏&#xff0c…

多目标平衡黏菌算法(MOEOSMA)求解八个现实世界受约束的工程问题

目录 1 受约束的工程问题 1.1 减速器设计问题(Speed reducer design problem) 1.2 弹簧设计问题(Spring design problem) 1.3 静压推力轴承设计问题(Hydrostatic thrust bearing design problem) 1.4 振动平台设计问题(Vibrating platform design problem) 1.5 汽车侧面碰…

18.示例程序(编码器接口测速)

STM32标准库开发-各章节笔记-查阅传送门_Archie_IT的博客-CSDN博客https://blog.csdn.net/m0_61712829/article/details/132434192?spm1001.2014.3001.5501 main.c #include "stm32f10x.h" // Device header #include "Delay.h" #incl…

数据结构:KMP算法的原理图解和代码解析

文章目录 应用场景算法方案算法原理完整代码 本篇总结的是关于串中的KMP算法解析 应用场景 现给定两个串&#xff0c;现在要看较短的一个串是不是较长的串的子串&#xff0c;如果是就输出子串后面的内容&#xff0c;如果不是则输出Not Found 能匹配到&#xff1a; 长串&…

基于SSM的连锁经营商业管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

JavaSE | 初识Java(五) | 方法的使用

方法就是一个代码片段&#xff0c; 类似于 C 语言中的 " 函数 "。 方法可以是我们代码逻辑更清晰&#xff0c;并且可以服用方法使代码更简洁 方法语法格式 // 方法定义 修饰符 返回值类型 方法名称([参数类型 形参 ...]){ 方法体代码; [return 返回值]; } 实例&…

自媒体文章改写工具-自媒体文章改写软件

自媒体时代已然来临&#xff0c;每个人都有机会成为自己的内容创作者&#xff0c;分享自己的观点和故事。在竞争激烈的自媒体领域&#xff0c;如何让自己的文章脱颖而出&#xff0c;吸引更多读者成为了一个重要的问题。 自媒体文章改写是一项旨在提高文章原创性和吸引力的关键任…

Arcgis打开影像分析窗口没反应

Arcgis打开影像分析窗口没反应 问题描述 做NDVI计算的时候&#xff0c;一直点击窗口-影像分析&#xff0c;发现影像分析的小界面一直不跳出来。 原因 后来发现是被内容列表给遮住了&#xff0c;其实是已经出来了的。。 拖动内容列表就能找到。 解决方案 内容列表和影像分…

热点文章采集-热点资讯采集工具免费

在信息时代&#xff0c;掌握热点资讯、了解热门时事、采集热门文章是许多自媒体从业者和信息追踪者的重要任务。然而&#xff0c;这并不是一项容易的任务。信息的海洋庞大而繁杂&#xff0c;要从中捞取有价值的热点和文章需要耗费大量时间和精力。 热点资讯采集&#xff1a;信息…

[Linux 基础] 一篇带你了解linux权限问题

文章目录 1、Linux下的两种用户2、文件类型和访问权限&#xff08;事物属性&#xff09;2.1 Linux下的文件类型2.2 基本权限2.3 文件权限值的表示方法&#xff08;1&#xff09;字符表示方法&#xff08;2&#xff09;8进制数值表示方法 2.4 文件访问权限的相关设置方法(1) chm…