校园地图
来源:互联网 发布:mac电脑excel指数幂 编辑:程序博客网 时间:2024/06/08 16:34
趁课余时间做了一个小作品,项目是校园地图,主要目的是练习Qt和一些基本的数据结构和算法。该项目的主要功能是从下拉列表中选择出发地和目的地,然后地图上可以显示路线。主要的显示方法是通过贴图来显示。时间久远才想起来整理,当时也是经历了一个星期的断断续续的修补,最后形成了一个比较完善的小地图软件。
2.基本思路
01.首先需要构建路网(很重要),我首先写了一个该版本,然后把路网标记后保存。具体用来储存的数据结构是一个具有节点信息的结构体,然后借用C++的 vector (vector真的太好用了)来记录所有的路网节点。
typedef struct road_dot{ int i; // 该节点的id int vistable; //该节点是否可访问 cv::Point self; //该节点在地图上的位置 std::vector<size_t> others_id; // 保存与该节点相连的节点的id }Road_node;
下面是我用来标记路网并自动储存的模块:
/************************************************************************************************ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * These under codes construct a tool to get the road nodes infomation * * <2016-10-29><wuhui> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ void MainWindow::mousePressEvent(QMouseEvent *event){ if(0<x&&x<1480&&0<y&&y<800) // if on the pic { Road_node new_node; new_node.self = Point(x,y); new_node.i = 200; // not a pos cv::circle(img,Point(x,y),6,cv::Scalar(255,0,255),-1); qimg = Mat2QImage(img); ui->pic->setPixmap(QPixmap::fromImage(qimg)); if(!first_node) {start_node = new_node;start_set_flag = 1; first_node =2;pre_nodes_id = 0;} for(int i = 0;i<point.size();i++) { if((abs(x-point[i].x) <10 )&& (abs(y-point[i].y)<10)) // if at pos { new_node.i = i; qDebug()<<"this is pos "<<i; break; } } road.push_back(new_node);// record this new node ; for(int i = 0;i<road.size()-1;i++) { if((abs(x-road[i].self.x) <10 )&& (abs(y-road[i].self.y)<10)) // if at node { // yes road.pop_back(); // drop this node if(event->button() == Qt::LeftButton) // if leftButton { start_node = road[i]; // set start node start_set_flag = 1; pre_nodes_id = i; } else if(event->button() == Qt::RightButton) { start_node = road[pre_nodes_id]; // this is start start_set_flag = 1; end_node = road[i]; end_set_flag = 1; road[i].others_id.push_back(pre_nodes_id); road[pre_nodes_id].others_id.push_back(i); pre_nodes_id = i; } qDebug()<<"this node's others.size = "<<road[i].others_id.size(); break; } else if(i == road.size() - 2) { // no if(!start_set_flag) // if have no start_node { start_node = road[pre_nodes_id]; start_set_flag = 1; } if(!end_set_flag) { end_node = road[road.size()-1]; end_set_flag = 1; } road[pre_nodes_id].others_id.push_back(road.size()-1); // push now node road[road.size()-1].others_id.push_back(pre_nodes_id); qDebug()<<"this node's others.size = "<<road[road.size()-1].others_id.size(); pre_nodes_id = road.size()-1; break; } } if(end_set_flag && start_set_flag) { end_set_flag = 0; start_set_flag = 0; cv::line(img,start_node.self,end_node.self,cv::Scalar(0,0,0),3); qimg = Mat2QImage(img); ui->pic->setPixmap(QPixmap::fromImage(qimg)); // flush the pic } qDebug()<<"road.size"<<road.size(); }} // :)
该代码主要通过在地图上点击来标记,右键表示一个连续段的结束,每个节点会记录与之相连的其它节点的id号。结果示意图:(另外,地图图片是Google截图并精心修改而成)
02.标记完了路网后就是设计一个找路算法了,想过深度或广度搜索,但是做过一个demo后觉得稍显复杂并且速度不理想,后来根据地图的形状设计了一个看似很low却很有效的算法:
首先设立两个哨兵,一个在当前出发节点(哨兵A),另一个在下一个目标出发点(哨兵 B),下一个目标出发点由所有子节点中距离目的地最近的节点确定。
当B所在的节点具有可走子节点(不是死胡同)并且还未达到目的地时,A走到B(所有走过的路压栈,方便后退),B继续探路,若走到死胡同就后退,走其他的最近子节点。
该寻路算法如下:
int start_id = ui->comboBox->currentIndex(); // get start and end node's id / int end_id = ui->comboBox_2->currentIndex(); for(int i = 0;i<road.size();i++) { road[i].vistable = 0; // set all nodes are visitable; } // Road_node start_node_temp,end_node_temp; // temp node int road_start_i,road_end_i; int road_start_i_temp,road_end_i_temp; for(int i = 0;i<road.size();i++) // search which node is on the start/end point; { if(road[i].i == start_id) { qDebug()<<"start"<<i; start_node = road[i]; road_start_i = i; // get the id of start roadnode; qDebug()<<"i = "<<start_node.i; } else if(road[i].i == end_id) { qDebug()<<"end"<<i; end_node = road[i]; road_end_i = i; // get the id of end roadnode; qDebug()<<"i = "<<end_node.i; } } /***********/ road_start_i_temp = road_start_i; road_end_i_temp = road_start_i; // start_node_temp = start_node; //end_node_temp = start_node_temp; std::vector<int> road_temp; int pre_distance = 9000000; while(road[road_end_i_temp].i!= end_id) //for(int xx = 0;xx<10;xx++) { int useable_flag = 0; for(int i = 0;i<road[road_end_i_temp].others_id.size();i++) // if the current endpoint to have next point { if(road[road[road_end_i_temp].others_id[i]].vistable == 0) useable_flag = 1; // have useable point } if(useable_flag) // have useable next node { // start_node_temp = end_node_temp; road_start_i_temp = road_end_i_temp; road[road_start_i_temp].vistable = 1; // have visited it; //start_node_temp.vistable = 1; // have visited it; road_temp.push_back(road_start_i_temp); // record the walked node int temp_min_id; for(int i = 0;i<road[road_start_i_temp].others_id.size();i++) // find the min dis node // int these next points { if(road[road[road_start_i_temp].others_id[i]].vistable == 0 ) // if this node have not visited; { int tempx,tempy; tempx = (road[road[road_start_i_temp].others_id[i]].self.x- end_node.self.x)*(road[road[road_start_i_temp].others_id[i]].self.x - end_node.self.x); tempy = (road[road[road_start_i_temp].others_id[i]].self.y- end_node.self.y)*(road[road[road_start_i_temp].others_id[i]].self.y - end_node.self.y); if(pre_distance<(tempx+tempy)) { qDebug()<<"pre_distance = "<<pre_distance; qDebug()<<"now distance = "<<tempx+tempy; // end_node_temp = road[road[road_start_i_temp].others_id[i-1]]; road_end_i_temp = road[road_start_i_temp].others_id[temp_min_id]; } else { //end_node_temp = road[start_node_temp.others_id[i]]; road_end_i_temp = road[road_start_i_temp].others_id[i]; temp_min_id = i; pre_distance = tempx+tempy; } } } pre_distance = 9000000; } else // have no useable next node { road[road_end_i_temp].vistable = 1; loop: for(int i = 0;i<road[road_start_i_temp].others_id.size();i++) // if have other useable nodes { if(road[road[road_start_i_temp].others_id[i]].vistable == 0) useable_flag = 1; // have useable point } if(useable_flag) { int temp_min_id; for(int i = 0;i<road[road_start_i_temp].others_id.size();i++) // fine the min dis node { if(road[road[road_start_i_temp].others_id[i]].vistable == 0 ) // if this node have not visited; { int tempx,tempy; tempx = (road[road[road_start_i_temp].others_id[i]].self.x- end_node.self.x)*(road[road[road_start_i_temp].others_id[i]].self.x - end_node.self.x); tempy = (road[road[road_start_i_temp].others_id[i]].self.y- end_node.self.y)*(road[road[road_start_i_temp].others_id[i]].self.y - end_node.self.y); if(pre_distance<(tempx+tempy)) { //end_node_temp = road[road[road_start_i_temp].others_id[i-1]]; road_end_i_temp = road[road_start_i_temp].others_id[temp_min_id]; } else { //end_node_temp = road[start_node_temp.others_id[i]]; road_end_i_temp = road[road_start_i_temp].others_id[i]; temp_min_id = i; pre_distance = tempx+tempy; } } } pre_distance = 9000000; } else { road_temp.pop_back(); // drop this start_temp node road_start_i_temp = road_temp[road_temp.size()-1]; goto loop; } } /* int pre_distance = 90000000; for(int i = 0;i<start_node_temp.others_id.size();i++) // { int tempx,tempy; tempx = (road[start_node_temp.others_id[i]].self.x- end_node.self.x)*(road[start_node_temp.others_id[i]].self.x - end_node.self.x); tempy = (road[start_node_temp.others_id[i]].self.y- end_node.self.y)*(road[start_node_temp.others_id[i]].self.y - end_node.self.y); if(pre_distance<(tempx+tempy)) { end_node_temp = road[start_node_temp.others_id[i-1]]; } else { end_node_temp = road[start_node_temp.others_id[i]]; pre_distance = tempx+tempy; } } cv::line(img,start_node_temp.self,end_node_temp.self,cv::Scalar(0,0,0),3); qimg = Mat2QImage(img); ui->pic->setPixmap(QPixmap::fromImage(qimg)); // flush the pic start_node_temp = end_node_temp; xx++;*/ } road_temp.push_back(road_end_i_temp); for(int i = 0;i<road_temp.size()-1;i++) { cv::line(img,road[road_temp[i]].self,road[road_temp[i+1]].self,cv::Scalar(0,0,0),3); qimg = Mat2QImage(img); ui->pic->setPixmap(QPixmap::fromImage(qimg)); // flush the pic } qDebug()<<road_temp.size();}
经过实验该算法还是很可靠的 ;)
效果图:
另外鼠标悬停在某个地点时,还会展示该地点的图片信息(亲自把所有地点拍了一遍 ;)
-----------------------------------------------------------------------------------------------
- 校园地图
- 校园地图
- 校园地图
- 校园地图
- 校园地图
- 校园地图
- 校园地图框架设计
- HTML5实现3D校园地图思路
- #WEBGIS#校园地图系统开发-地图数据发布
- 使用百度地图API来完成交大校园巴士时刻表
- #WEBGIS#校园地图系统开发-6、多图层发布方案
- 校园
- 校园助手APP--腾讯地图的集成使用(含街景)
- jquery mobile + 百度地图 + phonegap 写的一个"校园助手"的app
- 微信小程序——校园活动地图后端开发日志(1)
- 微信小程序——校园活动地图后端开发日志(2)
- #WEBGIS#校园地图系统开发-2、postgresql+postgis+geoserver搭建WEBGIS
- #WEBGIS#校园地图系统开发- 4、制作并发布叠加层(矢量)
- C++:类和对象
- 函数指针
- main函数的参数:argc和argv
- mac osx Apache 服务器架设
- C++:栈(stack)的模板类实现
- 校园地图
- 安装VMware Tools:Ubuntu
- 链表
- GLES2.0初识——API
- GitHub:Git的使用
- C++:线程(std::thread)
- 产品经理成长经历感悟
- bootstrap兼容ie8+
- 转——quartz_jobs.xml配置文件样例