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

文章目录

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

地图导航系统

项目应用背景

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

技术栈选择

用哈希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 += widgetsTARGET = 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.0SOURCES += \main.cpp \mainwindow.cppHEADERS += \mainwindow.hFORMS += \mainwindow.uiRESOURCES += \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_OBJECTpublic: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的IdQString tagKey;QString tagValue;QString nodeId;     //node的IDQString 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);  // 示例:绿色,线宽为3pathItems->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);  // 示例:蓝色,线宽为2pathItem->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.xdnf.cn/news/148341.html

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

相关文章

Golang 中的调试技巧

掌握有效的策略和工具&#xff0c;实现顺畅的开发 调试是每位开发人员都必须掌握的关键技能。它是识别、隔离和解决代码库中问题的过程。在 Golang 的世界中&#xff0c;掌握有效的调试技巧可以显著提升您的开发工作流程&#xff0c;并帮助您创建更可靠和健壮的应用程序。在本…

【面试经典150 | 矩阵】矩阵置零

文章目录 写在前面Tag题目来源题目解读解题思路方法一&#xff1a; O ( m n ) O(mn) O(mn) 空间复杂度方法二&#xff1a; O ( m n ) O(mn) O(mn) 空间复杂度方法三&#xff1a;仅使用2个额外变量的常量空间复杂度 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算…

【Docker】Docker的应用包含Sandbox、PaaS、Open Solution以及IT运维概念的详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…

简单的考试系统

开发一个简单的考试系统&#xff0c;在HTML页面中建立一个表单&#xff0c;通过post方法传递参数。题目类型包括单选题、多选题和填空题&#xff0c;要求程序给出考试成绩。 <!DOCTYPE html> <html> <head><title>question.html</title><met…

C#餐饮收银系统

一、引言 餐饮收银系统是一种用于管理餐馆、咖啡厅、快餐店等餐饮业务的计算机化工具。它旨在简化点餐、结账、库存管理等任务&#xff0c;提高运营效率&#xff0c;增强客户体验&#xff0c;同时提供准确的财务记录。C# 餐饮收银系统是一种使用C#编程语言开发的餐饮业务管理软…

SG Former论文学习笔记

超越SWin和CSWin Transformer的新模型 代码地址&#xff1a;https://github.com/OliverRensu/SG-Former 论文地址&#xff1a;https://arxiv.org/pdf/2308.12216.pdf ViT在各种视觉任务中虽然成功&#xff0c;但它的计算成本随着Token序列长度的增加呈二次增长&#xff0c;这在…

Gurobi设置初始可行解

目录 1. 决策变量的Start属性直接设置变量的初始值 1.1 Start&#xff1a;MIP变量的起始值&#xff08;初值&#xff09;double类型&#xff0c;可更改 1.2 StartNodeLimit&#xff1a;限制了在完善一组输入部分变量的初始解时&#xff0c;MIP所探索的分支定界的节点的数量 …

【1】c++设计模式——>UML类图的画法

UML介绍 UML:unified modeling language 统一建模语言 面向对象设计主要就是使用UML类图&#xff0c;类图用于描述系统中所包含的类以及他们之间的相互关系&#xff0c;帮助人们简化对系统的理解&#xff0c;他是系统分析和设计阶段的重要产物&#xff0c;也是系统编码和测试的…

Python无废话-办公自动化Excel写入操作

Python 办公自动化-Excel写入 创建并保存Excel文件 import openpyxl workbookopenpyxl.Workbook() #创建空Excel文件 sheetworkbook.active #获取活动的工作表 sheet.title“测试“ #修改sheet工作表名称为测试 workbook.save(“data\input\Test.xlsx”) #保存Excel文件 …

SDK Vitis记录

文章目录 SDK记录SDK中报错“undefined reference to sqrt”的解决方法通过XML文件导入工程的include路径方法说明 其他设置编译选项设置某些文件/文件夹不编译单独设置文件的编译选项 向存储区中导入/导出数据通过GUI操作使用命令行操作 产生C代码的MAP文件在Xilinx SDK 工程的…

Flutter项目安装到Android手机一直显示在assembledebug

问题 Flutter项目安装到Android手机一直显示在assembledebug 原因 网络不好&#xff0c;gradle依赖下载不下来 解决方案 修改如下的文件 gradle-wrapper.properties 使用腾讯提供的gradle镜像下载 distributionUrlhttps://mirrors.cloud.tencent.com/gradle/gradle-7.5…

Mac安装Ecplise产品报错:dose not contain the JNI_CreateJavaVM symbol

1. 絮絮叨叨 工作中需要借助Ecplise Memory Analyzer (MAT)分析dump文件&#xff0c;直接下载、安装、运行MAT报错 询问同事后&#xff0c;同事说可以先安装Ecplise&#xff0c;再以插件的形式安装MAT下载、安装好Eclipse&#xff0c;点击运行仍然报错&#xff0c;且错误信息一…

【算法训练-二分查找 三】【特殊二分】寻找峰值

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【数组的二分查找】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为…

AcWing算法提高课-5.6.1同余方程

宣传一下 算法提高课整理 CSDN个人主页&#xff1a;更好的阅读体验 原题链接 题目描述 求关于 x x x 的同余方程 a x ≡ 1 ( m o d b ) ax ≡ 1 \pmod b ax≡1(modb) 的最小正整数解。 输入格式 输入只有一行&#xff0c;包含两个正整数 a , b a,b a,b&#xff0c;用一…

2023最新简易ChatGPT3.5小程序全开源源码+全新UI首发+实测可用可二开(带部署教程)

源码简介&#xff1a; 2023最新简易ChatGPT3.5小程序全开源源码全新UI首发&#xff0c;实测可以用&#xff0c;而且可以二次开发。这个是最新ChatGPT智能AI机器人微信小程序源码&#xff0c;同时也带部署教程。 这个全新版本的小界面设计相当漂亮&#xff0c;简单大方&#x…

2023/10/4 -- ARM

今日任务&#xff1a;QT实现TCP服务器客户端搭建的代码&#xff0c;现象 ser&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);server new QTcpSe…

订单型批发制造企业经营分析123个指标大全(ODOO15/16)

ODOO-ERP搭建完成之后&#xff0c;我们重点是帮客户建立经营分析能力&#xff0c;以下是针对订单型企业的经营分析指标&#xff0c;涵盖业务运营的监控、资产构成、利润、盈亏点计算、资产运营效率等各方面&#xff0c;并且持续完善​。 有些企业不重视&#xff0c;觉得自己企业…

ChatGPT启蒙之旅:弟弟妹妹的关键概念入门

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

项目进展(六)-继续学习32位ADC芯片ADS1285

一、数据手册学习 1.1时序图 SPI时序图&#xff0c;这是很重要的一个地方&#xff0c;一定要在代码中将SPI配置成对应的模式。 先放一堆截图在这吧&#xff0c;一些引脚的功能及特性还未看到&#xff0c;等具体了解之后再详细介绍下面几张截图的时序&#xff1a; 1.2 内…

集合-Map系列

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 4.数据结构-哈希表_喜欢吃animal milk的博客-CSDN博客 5.集合-set系列集合-CSDN博客 6.集合-Map系列-CSDN博客 文章目…