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.rhkb.cn/news/147288.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

固定式工业RFID读写器有哪些特点?如何选型?

工业读写器可分为便携式读写器和固定式读写器&#xff0c;固定式读写器主要是将读写器固定在某一位置钟&#xff0c;常常应用在工位、生产、进入库等场景中。但是很多人并不了解固定式读写器都有哪些特点&#xff0c;具体应该怎么选型&#xff0c;下面我们就一起来了解一下。 固…

C语言数组和指针笔试题(五)(一定要看)

这里写目录标题 指针运算笔试题解析题目1解析结果 题目2解析结果 题目3解析结果 题目4解析结果 题目5解析结果 题目6解析结果 题目7解析结果 题目8解析结果 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412;个人主页 &a…

Jmeter+jenkins接口性能测试平台实践整理

最近两周在研究jmeter&#xff0b;Jenkin的性能测试平台测试dubbo接口&#xff0c;分别尝试使用maven&#xff0c;ant和Shell进行构建&#xff0c;jmeter相关设置略。 一、Jmeterjenkins&#xff0b;Shell&#xff0b;tomcat 安装Jenkins,JDK,tomcat,并设置环境变量&#xff0…

STM32之DMA

简介 • DMA &#xff08; Direct Memory Access &#xff09;直接存储器存取 &#xff08;可以直接访问STM32内部存储器&#xff0c;如SRAM、程序存储器Flash和寄存器等&#xff09; •DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&a…

在pycharm中出现下载软件包失败的解决方法

一. 一般情况下我们会选择在设置中下载软件包,过程如下. 1. 直接点击左上角的文件, 再点击设置, 再点击项目, 在右边选择python解释器,点击号,输入要下载的软件包, 在下面的一系列的包中选择相对应的包,点击安装就可以了,有的时候我们下载的是最新的版本,如果要下载固定的版本…

Spring的注解开发-注解方式整合MyBatis代码实现

之前使用xml方式整合了MyBatis&#xff0c;文章导航&#xff1a;Spring整合第三方框架-MyBatis整合Spring实现-CSDN博客 现在使用注解的方式无非是就是将xml标签替换为注解&#xff0c;将xml配置文件替换为配置类而已。 非自定义配置类 package com.example.Configure;import c…

SpringBoot banner 样式 自动生成

目录 SpringBoot banner 样式 自动生成 图案网站&#xff1a; 1.第一步创建banner.txt文件 2.访问网站Ascii艺术字实现个性化Spring Boot启动banner图案&#xff0c;轻松修改更换banner.txt文件内容&#xff0c;收集了丰富的banner艺术字和图&#xff0c;并且支持中文banner下…

基于体素场景的摄像机穿模处理

基于上一篇一种基于体素的射线检测 使用射线处理第三人称摄像头穿模问题 基于体素的第三人称摄像机拉近简单处理 摄像机移动至碰撞点处 简单的从角色身上发射一条射线到摄像机&#xff0c;中途遇到碰撞就把摄像机移动至该碰撞点 public void UpdateDistance(float defaultDist…

Unity实现设计模式——状态模式

Unity实现设计模式——状态模式 状态模式最核心的设计思路就是将对象的状态抽象出一个接口&#xff0c;然后根据它的不同状态封装其行为&#xff0c;这样就可以实现状态和行为的绑定&#xff0c;最终实现对象和状态的有效解耦。 在实际开发中一般用到FSM有限状态机的实现&…

Learning Invariant Representation for Unsupervised Image Restoration

Learning Invariant Representation for Unsupervised Image Restoration (Paper reading) Wenchao Du, Sichuan University, CVPR20, Cited:63, Code, Paper 1. 前言 近年来&#xff0c;跨域传输被应用于无监督图像恢复任务中。但是&#xff0c;直接应用已有的框架&#xf…

叶工好容6-自定义与扩展

本篇主要介绍扩展的本质以及CRD与Operator之间的区别&#xff0c;帮助大家理解相关的概念以及知道要进行扩展需要做哪些工作。 CRD&#xff08;CustomerResourceDefinition&#xff09; 自定义资源定义,代表某种自定义的配置或者独立运行的服务。 用户只定义了CRD没有任何意…

【Spring Cloud】深入探索统一网关 Gateway 的搭建,断言工厂,过滤器工厂,全局过滤器以及跨域问题

文章目录 前言为什么需要网关以及网关的作用网关的技术实现 一、Gateway 网关的搭建1.1 创建 Gateway 模块1.2 引入依赖1.3 配置网关1.4 验证网关是否搭建成功1.5 微服务结构分析 二、Gateway 断言工厂2.1 Spring 提供的断言工厂2.2 示例&#xff1a;设置断言工厂 三、Gateway …

从0手写两轮差速机器人urdf模型

文章目录 前言一、基本理论二、实现步骤1.创建一个机器人建模功能包2.使用圆柱体创建一个车体模型2.同理创建机器人其它构件3.机器人模型添加传感器 前言 最近为找到与自己课题应用场景相适应的机器人结构&#xff0c;对机器人建模方面的内容进行了了解和学习&#xff0c;计划…

【数组及指针经典笔试题解析】

1.数组和指针笔试题 题目1 int main(){int a[5] { 1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5};int * ptr (int * )(&a 1);printf("%d&#xff0c;%d"&#xff0c;*(a 1)&#xff0c;*(ptr - 1));return 0;}图文解析&#xff1a; int * ptr …

【JavaEE】JavaScript webAPI的基本知识

JavaScript Web API 文章目录 JavaScript Web APIwebAPI背景DOMDOM树 获取元素querySelectorquerySelectorAll 事件初识键盘事件onkeydownonkeypressonkeyup 操作元素获取/修改元素内容1.innerText2.innerHTML 获取/修改元素属性获取/修改表单元素属性获取/修改样式属性行内样式…

redis的简单使用

文章目录 环境安装与配置redis发布-订阅相关命令redis发布-订阅的客户端编程redis的订阅发布的例子 环境安装与配置 sudo apt-get install redis-server # ubuntu命令安装redis服务ubuntu通过上面命令安装完redis&#xff0c;会自动启动redis服务&#xff0c;通过ps命令确认&a…

用于YOLO格式分割的咖啡叶病害数据集。

下载链接&#xff1a;https://download.csdn.net/download/qq_40840797/88389334 数据集&#xff0c;一共1164张照片 随机选取几张照片及对应的目标标签 因为健康&#xff0c;所以标签为空

[BJDCTF2020]The mystery of ip

打开环境 点击flag&#xff0c;提示ip&#xff0c;这里确实就比较容易联想到x-forwarded-for 点击hint 这个好像没啥用 使用bp抓包 添加请求头 X-Forwarded-For:1 试一下 发现ip可控 后来查了发现 PHP可能存在Twig模版注入漏洞 参考https://www.cnblogs.com/zzjdbk/p/13…

【C语言】循环结构程序设计 (详细讲解)

前言&#xff1a;前面介绍了程序中常常用到的顺序结构和选择结构&#xff0c;但是只有这两种结构是不够的&#xff0c;还有用到循环结构(或者称为重复结构)。因为在日常生活中或是在程序所处理的问题中常常遇到需要重复处理的问题。 【卫卫卫的代码仓库】 【选择结构】 【专栏链…

HTML的相关知识

1.什么是HTML&#xff1f;基本语法 HTML: Hyper Text Markup Language &#xff08;超文本标记语言&#xff09; 超文本&#xff1f;超级文本&#xff0c;例如流媒体&#xff0c;声音、视频、图片等。 标记语言&#xff1f;这种语言是由大量的标签组成。HTML标签参考手…