• 校园地图


    1.项目描述

      趁课余时间做了一个小作品,项目是校园地图,主要目的是练习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();
    
    }
    查看代码

      经过实验该算法还是很可靠的 ;) 

      效果图:

      另外鼠标悬停在某个地点时,还会展示该地点的图片信息(亲自把所有地点拍了一遍 ;)

    -----------------------------------------------------------------------------------------------

    ------------ 转载请注明出处 ------------
  • 相关阅读:
    The resource identified by this request is only capable of generating responses with characteristics
    javaweb写的在线聊天应用
    JavaScript写一个拼图游戏
    jQ插件--时间线插件和拖拽API
    Javascript写俄罗斯方块游戏
    详解jQ的support模块
    磁盘IO的性能指标 阻塞与非阻塞、同步与异步 I/O模型
    Airflow Python工作流引擎的重要概念介绍
    DEVOPS 运维开发系列
    MYSQL 两表 排除 重复记录
  • 原文地址:https://www.cnblogs.com/whlook/p/6533642.html
Copyright © 2020-2023  润新知