校园地图

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();

}

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

  效果图:

时间: 2024-10-12 13:47:04

校园地图的相关文章

校园地图导航、图的裁剪和最短路径的的使用

最近接学校项目,做了个地图导航,图上标示十几个坐标点,进行了图的裁剪,并对点与点之间的联通做了最短路径的设置. 采用c#编程实现,实现了网格线. 如图:

【高德地图API】从零开始学高德JS API(一)地图展现

摘要:关于地图的显示,我想大家最关心的就是麻点图,自定义底图的解决方案了吧.在过去,marker大于500之后,浏览器开始逐渐卡死,大家都开始寻找解决方案,比如聚合marker啊,比如麻点图啊.聚合marker里面还有一些复杂的算法,而麻点图,最让大家头疼的,就是如何生成麻点图,如何切图,如何把图片贴到地图上,还有如何定位图片的位置吧.以前那么复杂的一系列操作,居然让云图的可视化操作一下子解决了.现在只要点一点鼠标,麻点图就自动生成了.真是广大LBS开发者的福音. 以前写过从零开始学百度地图AP

自定义地图开发(一)

前言: oh my lord,憋了好久了.纷纷扰扰的闹剧算是结束了,关于这个项目的任务也暂停一段时间.趁现在,好好的把地图模块整理一下. 要做的项目中,有一个功能是校园地图.但是不希望用现有的地图SDK来展示,故此,我只好自己写一个简单的模块来展示一张平面图. 先放一张效果图吧,当时匆忙,很多地方未完善,但最终的效果应该是这个样子的: 至于地图上那个图片,是用来做定位时的准星的--不要在意这些细节. 正文 好的,现在,咱们的教程,正式开始: 在本章教程中,我需要一个组件,可以用来监听不规则形状的

校园网络TV云平台

一.校园网络TV云平台 "校园网络TV云平台"是深圳矽伟智(sewise)基于"流媒体云技术"面向高校推出的一套'视频校园'网络TV门户网站资源共享平台应用方案,把高校原有的一些视频教学资源.教育行业网络电台音视频文件信息与流媒体软件服务器进行二次开发和全新的规划,通过后期的整合,以视频校园全媒体网络平台统一推送到在校学生的手机.PC.PAD.TV等端口.在校园网络公开课程板块中,老师可以录播网络课程进行在线直播和点播.学生可以自由选择和学习自己喜欢的线上课程.在校

校园知网使用体验及改进建议

一.使用体验: 校园知网是一个网页,点开之后首先要注册:用户名.密码.确认密码.邮箱,主要的应该是邮箱吧.进去之后先是校园新闻,有一些学校发生的事情,但感觉新闻的种类和数量不多,时事性还可以.课程中心可以观看一些老师的视频,但感觉种类少点,如果能加入一些选修的课程会更好.资源下载方面是真的很实用,因为总是出现考试前想找以前的考试题目而找不到或者找不全的问题,有这个网站就可以直接下载往年的一些题目,不过希望能够增加一些老师讲课用的ppt和一些科目的重要知识点集锦.互动交流方面是一个不错的创意,同时

Android和Linux应用综合对比分析

公开发布的序言: 这篇文章是作于2012年7月12日,也就是自己刚从大学校园迈向工作岗位的时候遇到的第一个题目"请你针对我们公司目前的应用行业场景做一下调研:在终端做应用程序开发的平台是选择Linux好还是Android好"而写的. 在踏出校园之前,自己从来没有接触过安卓的开发领域(除了在2010年下半年买了一部分安卓的智能手机外).接到这个题目后,自己也没有退缩,硬着头皮接下来了,然后凭借自己在学校时候学的一点检索信息写学术论文的小功底,三天之内写下了这篇长达1万4千多字的调研报告,

桂电在线-php-提取菜单到配置文件

新建存储菜单的配置文件 menus.php,并配置菜单 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); /*菜单配置*/ $config['menus'] = array(); // 校园生活 $config['menus']['life'] = array('name' => '学校生活', 'submenu' => array( 'news/official_news' =>

A*寻路算法的探寻与改良(二)

A*寻路算法的探寻与改良(二) by:田宇轩                                                     第二部分:这部分内容主要是使用C语言编程实现A*,想了解A*算法的优化内容的朋友们可以跳过这部分并阅读稍后更新的其他内容 2.1 回顾 在我的上一篇文章中,我们通过抽象的思维方式得出了A*算法的概念和原理,这一章内容中主要探讨如何用编程实现A*算法. 在数据结构与算法的学习中,每个算法都应该结合一定的数据结构在计算机中存储,然后用对应的函数操控这些

【移动开发】安卓Lab2(01)

本次Lab需要用到Google Map的API,分享学习一下Google Map的知识 需求: 界面: 1. 主界面(map界面): 提供了指定的学校校园地图图片,不能用Google的API生成图片 2. 楼体信息界面(building detail界面): 显示用户选中的building的detail信息 3. 街景界面(street view界面) 显示在building detail界面中的street view 功能: 1. map: 必须只用提供的campus map图片 2. bui