zoukankan      html  css  js  c++  java
  • 校园地图

    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();
    
    }
    查看代码

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

      效果图:

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

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

    ------------ 转载请注明出处 ------------
  • 相关阅读:
    Java的静态块与实例块(转)
    Programming Ability Test学习 1031. Hello World for U (20)
    Programming Ability Test学习 1011. World Cup Betting (20)
    Programming Ability Test学习 1027. Colors in Mars (20)
    Programming Ability Test学习 1064. Complete Binary Search Tree (30)
    Programming Ability Test学习 1008. Elevator (20)
    【maven详解-生命周期】Maven的生命周期和插件
    【maven详解-插件】maven插件学习之源码插件Source Xref
    $(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别
    你还没真的努力过,就轻易输给了懒惰
  • 原文地址:https://www.cnblogs.com/whlook/p/6533642.html
Copyright © 2011-2022 走看看