C# 城市路网地图生成与运动模拟(一)-数据的获取

雪影工作室版权所有,转载请注明【http://blog.csdn.net/lina791211】


1、前言

这段时间一直在研究城市路网,某一天受不可告人的启发,决定把城市路网的地图做出来,然后模拟移动对象在路网上的运动,故本人开始了模拟地图生成的不归路。

  任务要求:

    (1)通过一组城市路网街道的数据(图的格式存储,demo数据下面给),把城市路网数据转换成坐标数据(其实这一步,我拿到的数据已经转换完成了,也就是说我拿到了的是平面坐标数据,而不是球面经纬度数据);

    (2)根据平面坐标数据,使用Java Swing或者Visual Studio(C# WinForm)生成城市路网;

    (3)支持点击某点,以此点放大;

    (4)支持按中心缩小

    (5)不用考虑剪枝(城市路网地图放大是存在剪枝的,那是因为附加数据太多,我的demo中只有1W多个街道,内存完全无压力)

    (6)经度不考虑(这个是因为winform坐标只能是整数,无法用浮点数表示)

    (7)根据移动对象的移动数据,模拟移动对象的运动。

 

2、数据demo

通过特殊途径拿到了一组城市路网街道的demo数据,如何拿到我就不讲了。但是可以提供另外一种获取途径。

  城市路网数据获取:来点我啊,来点我啊

  然后过几天就会拿到数据了。

  由于我这边通过其他途径得到数据的,所以还是简要介绍一下我这边数据的格式:

    (1)街道数据

0,50,8209,8769,8293,8768
1,50,8293,8768,8594,8773
2,50,8594,8773,8982,8781
3,50,8982,8781,9222,8787
4,30,8982,8781,9057,8936
5,30,9057,8936,9106,9038
6,30,9106,9038,9163,9209
7,30,9163,9209,9211,9354
8,70,9222,8787,9227,8890
9,70,9227,8890,9248,9350
10,70,9248,9350,9280,9476
11,70,9280,9476,9334,9670
12,70,9334,9670,9387,9804
13,70,9387,9804,9444,9919
14,70,9395,10233,9401,10199
15,70,9401,10199,9444,10000
16,70,9444,9919,9444,10000
17,50,8594,8773,8598,9061
18,50,8595,9495,8598,9256

  简要介绍下每行的含义

    street编号,限速,Start
X,Start Y,End X,End Y。

    (2)移动对象数据

1	1	39:22.6	39:24.6	15537	3850	15537	3850	0	0
1	2	39:24.6	39:26.6	15537	3850	15541.5	3857	8.321658489	14.97898528
1	2	39:26.6	39:28.6	15541.5	3857	15550.3	3870.65	16.24076661	29.23337989
1	2	39:28.6	39:30.6	15550.3	3870.65	15559.4	3884.65	16.69760462	30.05568831
1	2	39:30.6	39:32.6	15559.4	3884.65	15565.5	3894.21	11.34035273	20.41263491
1	2	39:32.6	39:34.6	15565.5	3894.21	15574.4	3907.99	16.40421897	29.52759415
1	2	39:34.6	39:36.6	15574.4	3907.99	15583.5	3921.99	16.69760462	30.05568831
1	2	39:36.6	39:38.6	15583.5	3921.99	15592.5	3935.99	16.64331698	29.95797056
1	2	39:38.6	39:40.6	15592.5	3935.99	15601.6	3949.99	16.69760462	30.05568831
1	2	39:40.6	39:42.6	15601.6	3949.99	15610.6	3964	16.65172964	29.97311335
1	2	39:42.6	39:44.6	15610.6	3964	15619	3977.01	15.48612605	27.87502689
1	2	39:44.6	39:46.6	15619	3977.01	15625.7	3987.33	12.3041619	22.14749142
1	2	39:46.6	39:48.6	15625.7	3987.33	15634.7	4001.33	16.64331698	29.95797056
1	2	39:48.6	39:50.6	15634.7	4001.33	15643.7	4015.33	16.64331698	29.95797056
1	2	39:50.6	39:52.6	15643.7	4015.33	15652.8	4029.34	16.70598994	30.0707819
1	2	39:52.6	39:54.6	15652.8	4029.34	15661.8	4043.34	16.64331698	29.95797056
1	2	39:54.6	39:56.4	15661.8	4043.34	15670	4056	15.08362026	27.15051646
1	2	39:56.4	39:58.4	15670	4056	15663.1	4060.69	8.343027029	15.01744865
1	2	39:58.4	40:00.4	15663.1	4060.69	15649.7	4069.83	16.22034525	29.19662145

  简要介绍下每行的含义

    移动对象编号,暂无意义,开始时间,结束时间,Start X,Start Y,End X,End Y,暂无意义(其实是行驶路程),暂无意义(其实是平均速度)

3、先上demo

讲了这么久,先把路网的demo拿出来看一下。(放大两倍后的,不敢把原图搞出来,不知道是否涉密)

4、数据处理

手里拿到的路网数据,是平面坐标数据,而且起始范围特别大,用1366这样的范围根本不能忍。故要读取样本,获取X、Y的最大值、最小值,并获取区间范围,然后缩放坐标范围到1000以内就行。

  (一)获取最大值最小值

    实现机制很简单,读取文件,转换数据,比较大小,分别获取X与Y的最大值和最小值;

 /// <summary>
        /// 测试使用
        /// 获取坐标集合中X 、Y的最大值和最小值
        /// </summary>
        /// <param name="strs"></param>
        private void getMax_Min_XY(string[] strs)
        {
            int xMin = 0;
            int xMax = 0;
            int yMin = 0;
            int yMax = 0;
            string[] s = strs[0].Split(',');
            xMin = Convert.ToInt32(s[2]);
            xMax = Convert.ToInt32(s[4]);
            yMin = Convert.ToInt32(s[3]);
            yMax = Convert.ToInt32(s[5]);
            if (xMin < xMax)
            {
                int temp = xMin; xMin = xMax; xMax = temp;
            }
            if (yMin < yMax)
            {
                int temp = yMin; yMin = yMax; yMax = temp;
            }
           // Console.WriteLine("\txMax \txMin \tyMax \tyMin");
            for (int i = 1; i < strs.Length; i++)
            {
                Console.Write("\n"+i);
                string[] s1 = strs[i].Split(',');
                int _xMin = Convert.ToInt32(s1[2].Contains(".") ? s1[2].Substring(0, s1[2].IndexOf('.')) : s1[2]);
                int _xMax = Convert.ToInt32(s1[4].Contains(".") ? s1[4].Substring(0, s1[4].IndexOf('.')) : s1[4]);
                int _yMin = Convert.ToInt32(s1[3].Contains(".") ? s1[3].Substring(0, s1[3].IndexOf('.')) : s1[3]);
                int _yMax = Convert.ToInt32(s1[5].Contains(".") ? s1[5].Substring(0, s1[5].IndexOf('.')) : s1[5]);

                if (_xMin < xMin)  xMin = _xMin;
                else if (_xMin > xMax) xMax = _xMin;

                if (_xMax < xMin) xMin = _xMax;
                else if (_xMax > xMax) xMax = _xMax;

                if (_yMin < yMin) yMin = _yMin;
                else if (_yMin > yMax) yMax = _yMin;

                if (_yMax < yMin) yMin = _yMax;
                else if (_yMax > yMax) yMax = _yMax;

                Console.Write("\t" + xMax);
                Console.Write("\t" + xMin);
                Console.Write("\t" + yMax);
                Console.Write("\t" + yMin);
            }
            Console.WriteLine("xMax:" + xMax);
            Console.WriteLine("xMin:" + xMin);
            Console.WriteLine("yMax:" + yMax);
            Console.WriteLine("yMin:" + yMin);
        }

  使用Convert.ToInt32(s1[2].Contains(".") ? s1[2].Substring(0, s1[2].IndexOf(‘.‘)) : s1[2]);的原因是:数据中有浮点数,,在粗粒度处理下,我就暴力的舍弃了。

  从而得到XY的最大和最小值:

        // private int xMax =33575;
        // private int xMin=-10836;
        // private int yMax=28095;
        // private int yMin = -6686;

  通过计算,xMax-xMin,yMax-yMin,离他们最近的最大整数分别是 90000和70000。

  因此,我选择了form页面大小为900*700的。中心点是(450,350),xmin取-11000,ymin取-6800,坐标转换后需要的缩放倍率是50

        private static int xmin = -11000;
        private static int ymin = -6800;
        private static int rate = 50;
        private int _Xc = 450;
        private int _Yc = 350;

  这些数据都作为固定值保存下来。不能每次加载地图的时候都去处理一遍啊,是不?处理数据很慢的。

  (二)转换坐标,并保存文件

  转换坐标好理解,保存文件是为了下次启动的时候可以直接读转换后的数据,而不用重新转换坐标了。其实这些都是数据的预处理。

        /// <summary>
        /// 测试使用的,根据城市路网坐标数据,生成符合当前坐标的路网坐标
        /// </summary>
        private void ConvertStreetPoints()
        {
            string[] strs = System.IO.File.ReadAllLines("c://streets_seg.csv");
            FileStream fs = new FileStream("C:\\A.txt", FileMode.Append);
            StreamWriter sw = new StreamWriter(fs, Encoding.Default);
            //Graphics g = this.pictureBox1.CreateGraphics();
            for (int i = 1; i < strs.Length; i++)
            {
                string[] s1 = strs[i].Split(',');
                //Console.Write("\n");
               // Console.WriteLine(getX(s1[2]));
               // Console.WriteLine(getX(s1[4]) );
               // Console.WriteLine(getY(s1[3]) );
               // Console.WriteLine(getY(s1[5]));

                //sw.Write(text);

                sw.Write(getX(s1[2]) + "\n");
                sw.Write(getX(s1[4]) + "\n");
                sw.Write(getY(s1[3]) + "\n");
                sw.Write(getY(s1[5]) + "\n");
               // Pen p = new Pen(Color.Red);
               // Point a = new Point(getX(s1[2]), getY(s1[3]));
               // Point b = new Point(getX(s1[4]), getY(s1[5]));
               // g.DrawLine(p, a, b);
            }
            sw.Close();
            fs.Close();
        }

  里面涉及了坐标的转换,方法如下:

        /// <summary>
        /// 转换路网坐标
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        private int getX(String x)
        {
            int tmp = Convert.ToInt32(x.Contains(".") ? x.Substring(0, x.IndexOf('.')) : x);
            return (tmp - xmin) / rate;
        }
        /// <summary>
        /// 转换路网坐标
        /// </summary>
        /// <param name="y"></param>
        /// <returns></returns>
        private int getY(String y)
        {
            int tmp = Convert.ToInt32(y.Contains(".") ? y.Substring(0, y.IndexOf('.')) : y);
            return (tmp - ymin) / rate;
        }

  处理后的坐标样式如下,每行一个数据,按照start X,end X,Start Y,End Y 进行保存的。当初脑子有点抽

385
391
311
311
391
399
311
311

  okay,路网的数据就这样基本处理完成了,下面开始进行地图绘制操作了。

5、地图绘制

系统启动的时候,首先要把转换后的路网坐标数据存到内存中,(不要跟我说存神马R树啊之类的,内容太少,没必要)

        private int[] ax = new int[MAX];
        private int[] ay = new int[MAX];
        private int[] bx = new int[MAX];
        private int[] by = new int[MAX];
        /// <summary>
        /// 初始化路网路口坐标
        /// </summary>
        private void initPoints()
        {
            string[] strs = System.IO.File.ReadAllLines("C:\\A.txt");
            for (int i = 0; i < strs.Length/4; i++) {
                //Console.WriteLine(strs[i]);
                ax[i] = Convert.ToInt32(strs[i * 4]);

                bx[i] = Convert.ToInt32(strs[i * 4 + 1]);

                ay[i] = Convert.ToInt32(strs[i * 4 + 2]);

                by[i] = Convert.ToInt32(strs[i * 4 + 3]);
            }
        }

  然后剩下的就是A-B这样进行划线啦。so easy的!(给form添加一个paint事件)

        /// <summary>
        /// 绘制地图主方法
        /// </summary>
        private void repaint()
        {

            Graphics g = this.CreateGraphics();
            for (int i = 1; i < ax.Length; i++)
            {
                Pen p = new Pen(Color.Red);
                Point a = new Point(ax[i], ay[i]);
                Point b = new Point(bx[i], by[i]);
                g.DrawLine(p, a, b);
            }

        }
        /// <summary>
        /// 绘制地图(Form的paint事件)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            repaint();

        }

  Form1_Load方法中直接调用对应的方法就行。

        private void Form1_Load(object sender, EventArgs e)
        {
            string[] strs = System.IO.File.ReadAllLines("c://streets_seg.csv");
            //Console.WriteLine(strs.Length);
            //ConvertStreetPoints();
            //ConvertTripPoint();
            initPoints();
           // initTripPoints();
            //getMax_Min_XY(strs);
            //
        }

6、地图出现

系统启动后会在1S左右把数据加载进来,然后绘制地图的图形,速度还是不错的。如果直接拿原始数据,先切割,再转换数据类型,然后缩放坐标点,这一套流程下来要耗费1分多的。

  下一章讲述如何放大和缩小。

  okay,本章结束!

C# 城市路网地图生成与运动模拟(一)-数据的获取,布布扣,bubuko.com

时间: 2024-11-10 13:11:06

C# 城市路网地图生成与运动模拟(一)-数据的获取的相关文章

使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图.下面就来看看本文实现的功能: Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发

植物风场运动模拟(Wind Animations for Trees)

提要 植物的运动模拟是图形学中的一个方向,今天就来讨论下怎么模拟出一个在风中荷叶. 植物力学模型 由于植物的模型在风中会有大变形的情况存在,这里采用的是有限元模拟的方法来实现. 关于基于有限元的物理模拟,可以参考: 有限单元法(The Finite Element Method) 专注网格剖分 - TetGen,NETGEN,Steller 在基于有限元物理模拟中,速度是最大的缺点,特别在四面体特别多的情况下,现在的配置比较不错的电脑(i7+GTX680)加上GPU计算的代码,可以接受的情况是小

经验分享:三套简单的迷宫地图生成方案

转自:http://www.gameres.com/754927.html 概述:文章基于一种基础的地图,来讨论三套不同的地图生成方案. 文章不会出现跟代码相关的内容,会以较为通俗的语句和不少简单的示意图来表示迷宫的生成方案.其中不少方法来自于游戏界前辈,我根据自己的基础地图做了不少修正(毕竟迷宫和地图的形式多种多样,适合自己游戏的才是最好的). 根据方案生成地图之后,还可以加上一些静态分布来丰富地图表现,大家就自行发挥啦! 地图基础 地图的形式很多,这里我使用的地图是以tile块为单位分割的地

js学习之地图生成

首先,上地图图片 接着,js,我们可以把图片看成一块块32*32像素的 var i; var j; window.onload = function () { gamemap(15, 10, 10, "map.jpg"); } var mapimg = new Image(); var map = [ [18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 55, 55, 18], [18, 18, 18, 17, 17, 17, 17, 17

iBase4j前端01_bootstrap-suggest json-server模拟后台数据、bootstrap-suggest环境搭建、开启bootstrap-suggest的post和put请求

1 准备 1.1 模拟的json数据 { "info": [ { "message": "信息", "value": [ { "userName": "淳芸", "shortAccount": "chunyun", "userId": 20001 }, { "userName": "orion-01

使用RAP2模拟假数据实现前后端分离

一.为什么使用RAP2 在一个项目的开发中,在页面需要使用大量数据进行渲染生成前,后端开发人员的接口可能还没有写完, 当前端没有后端数据支持的情况下,我们使用mock.js(mock.js用于生成随机数据,拦截ajax请求)模拟假数据,实现前后端分离.开发中我们也可以使用RAP2(这里面生成的数据基于mock.js)在线模拟假数据. 原文:https://www.jianshu.com/p/f11948877151 原文地址:https://www.cnblogs.com/cuiqq/p/113

//随机生成 10到20条数据 数据包含 用户名(5-10位的字母) 性别 年龄(1-100岁)

//随机生成 10到20条数据 数据包含 用户名(5-10位的字母) 性别 年龄(1-100岁)/*生成随机数的方法*/function random(min, max) { if (min < 0 || max < 0) { console.log("请输入大于0的数据"); return false } if (max == null) {//判断如果只传入一个参数 var max = min;//将参数设置为最大值 min = 0;//将最小值设置为零 } retur

App开发:模拟服务器数据接口 - MockApi

App开发:模拟服务器数据接口 - MockApi 为了方便app开发过程中,不受服务器接口的限制,便于客户端功能的快速测试,可以在客户端实现一个模拟服务器数据接口的MockApi模块.本篇文章就尝试为使用gradle的android项目设计实现MockApi. 需求概述 在app开发过程中,在和服务器人员协作时,一般会第一时间确定数据接口的请求参数和返回数据格式,然后服务器人员会尽快提供给客户端可调试的假数据接口.不过有时候就算是假数据接口也来不及提供,或者是接口数据格式来回变动--很可能是客

VC模拟发送数据包-百度关键词查找

VC模拟发送数据包-百度关键词查找 逗比汪星人2009-09-06上传 VC模拟发送数据包-百度关键词abcdef查找 详情 http://blog.csdn.net/wangningyu http://download.csdn.net/detail/wangningyu/1637723