爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 13671|回复: 20

迁移到MeteoInfo的一些心得

[复制链接]

新浪微博达人勋

发表于 2012-12-9 22:47:50 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 luckycomcn 于 2012-12-9 22:51 编辑

    之前开发一个项目用于显示一些气象实况以及预报数据,主要就是显示一些数值以及部分图形。本来是想转到DotSpatial或者是SharpMap上的,不过国内相关资料基本没有,而个人技术有限,一直没有去做。最近发现MeteoInfo已经能很好的实现这些功能,于是将整个项目迁移到MeoteoInfo上。
    由于其他功能之前都已经完成,所以只要把显示部分转移即可。在把王老师的 MeteoInfo二次开发教程 前十一讲都试了一遍、对照demo程序看一下,然后再通过VC#的对象浏览器查看MeteoInfoC.dll,对MeteoInfo算是有了个大致的了解。
    因为工作量不大,利用空余时间开发,大约10天左右完成。功能实现比较简单,但是优化上就比较麻烦。优化上的问题主要就是图像的显示速度。比如项目中有雷达数据的显示,数据大约是500×500的栅格。本来是绘制色块图的,用CreateContourLayer实现,但是这样的速度太慢了。于是把绘制方式改变成绘制栅格数据,用CreateRasterLayer,但是速度还是不够理想。当栅格较大时,绘制速度会变得很慢。因为项目中不需要投影转换,最后直接使用CreateImageLayer方法实现,这样速度就能提升很多。另外有些底图比较大,于是直接转成png,添加pgw文件后直接加载。所有的地图都添加到MIP文件中,并设置好样式色标,程序启动的时候只要简单几句代码就可以了。
  1. string aFile =  "map.mip";
  2. XmlDocument doc = new XmlDocument();
  3. doc.Load(aFile);XmlElement root = doc.DocumentElement;
  4. this.aLayersLegend.ActiveMapFrame.ImportProjectXML(root);



wrf数据显示

wrf数据显示

雷达回波数据显示

雷达回波数据显示

地图数据显示

地图数据显示

根据数据绘制的色块图

根据数据绘制的色块图

地图选择

地图选择

评分

参与人数 1威望 +5 金钱 +30 贡献 +10 体力 +80 收起 理由
MeteoInfo + 5 + 30 + 10 + 80 很好的开发实例和心得体会!

查看全部评分

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-12-10 10:19:05 | 显示全部楼层
本帖最后由 MeteoInfo 于 2012-12-10 10:23 编辑

很高兴能看到这样的帖子!

RasterLayer和ImageLayer都是以Image显示的,显示过程RasterLayer不会比ImageLayer慢,但是在创建过程中可能会比较慢。

CreateRasterLayer方法有两种重载:CreateRasterLayer(GridData GridData, string LName, string paletteFile), CreateRasterLayer(GridData GridData, string LName, LegendScheme aLS),区别在于如何给RasterLayer创建调色板,第一种方法直接给出了调色板,速度应该和CreateImageLayer是一样的。第二种方法用LegendScheme来间接创建调色板,如果格点数多且这个LegendScheme比较复杂(颜色比较丰富),RasterLayer的创建过程会比较慢,这是因为需要遍历每个格点,读取格点数据,再根据LegendScheme设置确定该格点在调色板中应该是什么值。

因此你可以试试CreateRasterLayer(GridData GridData, string LName, string paletteFile),比较一下和CreateImageLayer的差别。需要注意的是用这种创建RasterLayer方法参数中的GridData数据必须在调色板的范围内(1 - 256)。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2012-12-10 12:20:13 | 显示全部楼层

    谢谢王老师!
    测试得不够多,目前使用结果来看,RasterLayer是支持投影转换的,而ImageLayer好像是不支持。
    关于RasterLayer和ImageLayer确实是我没写清楚,主要是创建过程时间有差异。不过由于雨量数据都是浮点型的,如果直接转换的话,转换后数据超过256,所以我觉得没法直接用调色板的方法。
    现在我是先生成GridData,然后根据GridData创建Image,然后自己对GridData历遍,根据LegendScheme确定颜色,最后用返回的Image创建ImageLayer。比起直接用GridData和LegendScheme创建RasterLayer要快。经老师指点我倒是觉得可以根据数据生成的GridData和调色板生成一个新的GridData,然后用新的GridData来创建RasterLayer。
    至于地图底图这块,把数据转换成图像的好处是能压缩文件的大小,原来的文件超过10M,转成图片之后不到500K;坏处就是显示上完全不能改,数值也不可查询了。在学习上确实意义不大,不过对于实际应用来说,我觉得还是有点价值的。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2012-12-10 12:36:56 | 显示全部楼层
从GridData创建Image的代码,没有把LegendScheme独立成另外一个方法,是因为我觉得那样会多次调用和创建一些对象,可能相对会慢一点(没有经过具体测试)

  1. /// <summary>
  2.         /// 从Grid创建图像
  3.         /// </summary>
  4.         /// <param name="gdata">GridData</param>
  5.         /// <param name="als">色标</param>
  6.         /// <returns></returns>
  7.         public static Image getImageFromGridData(GridData gdata, LegendScheme als)
  8.         {
  9.             int width,height,breakNum;
  10.             width = gdata.XNum;
  11.             height = gdata.YNum;
  12.             breakNum = als.BreakNum;
  13.             double[] breakValue = new double[breakNum];
  14.             Color[] breakColor = new Color[breakNum];
  15.             for (int i = 0; i < breakNum; i++)
  16.             {
  17.                 breakValue = Convert.ToDouble(als.LegendBreaks.EndValue);
  18.                 breakColor = als.LegendBreaks.Color;
  19.             }
  20.             Color defaultColor = breakColor[breakNum-1];    //默认颜色为最后一个颜色
  21.             Bitmap aBitmap = new Bitmap(width, height);
  22.             aBitmap.MakeTransparent();
  23.             for (int i = 0; i < height; i++)
  24.             {
  25.                 for (int j = 0; j < width; j++)
  26.                 {
  27.                     double oneValue = gdata.Data[i, j];
  28.                     Color oneColor = defaultColor;
  29.                     //循环只到breakNum-1 是因为最后一个LegendBreaks的EndValue和StartValue是一样的
  30.                     for (int k = 0; k < breakNum - 1; k++)   
  31.                     {
  32.                         if (oneValue < breakValue[k])
  33.                         {
  34.                             oneColor = breakColor[k];
  35.                             break;
  36.                         }
  37.                     }
  38.                     aBitmap.SetPixel(j, height-i-1, oneColor);
  39.                 }
  40.             }
  41.             Image aImage = (Image)aBitmap;
  42.             return aImage;
  43.         }
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-12-10 13:05:59 | 显示全部楼层
luckycomcn 发表于 2012-12-10 12:36
从GridData创建Image的代码,没有把LegendScheme独立成另外一个方法,是因为我觉得那样会多次调用和创建一些 ...

你这个方法效率是比较高,赞一个!

我已经利用这个方法更新了RasterLayer的创建方法。你可以用最新的类库文件测试一下(见置顶帖子)。

感谢你所做的贡献!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

 楼主| 发表于 2012-12-10 14:05:31 | 显示全部楼层
MeteoInfo 发表于 2012-12-10 13:05
你这个方法效率是比较高,赞一个!

我已经利用这个方法更新了RasterLayer的创建方法。你可以 ...

    测试过了,现在速度是一样了。

    另外我觉得王老师可以把一些想做而没空做的写个清单,如果刚好有人做这个事情的话,可以顺便去完成一下。我最近刚好在忙一些其他事情,忙完之后可能顺便尝试一下GeoTiff文件的支持。代码经审定之后再加进去也能确保库的稳定性和可靠性。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-12-10 14:34:34 | 显示全部楼层
图很漂亮!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-12-10 16:19:04 | 显示全部楼层
两位牛人,学习了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-12-11 09:17:57 | 显示全部楼层
luckycomcn 发表于 2012-12-10 14:05
测试过了,现在速度是一样了。

    另外我觉得王老师可以把一些想做而没空做的写个清单,如果刚好 ...

谢谢你的建议,也欢迎你这样热心的高手参与MeteoInfo的开发。
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2013-5-3 21:23:09 | 显示全部楼层
感谢lz提供的Raster更新方法,刚用CreateRasterLayer测试了自己的数据,速度是快!
想请教一下:Raster 和 Shaded 的绘图区别,毕竟还是想追求Shaded的画质。
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表