基于cesium+canvas构建小区内部风场图
1、应用说明
去年项目中用到了风场显示,最近回顾了一下,重拾了一下记忆,也记录一下。当时需求就是比如在某城市一个小区的真实动态风场进行模拟显示,主要模拟小区内不同季节、不同高度下的主导风的走向,和不同高度建筑周围的环流效果,因为建筑物会影响风向的走势变化,所以风场显示要突出建筑物的影响等。风场图的和洋流图的流动效果大差不差,两个如果实现,也是如出一辙。
2、风场图原理
关于风场效果可视化的博客文章也很多,有leaflet、openlayer、cesium等常见webgis地图框架的都有。查阅了许多关于风场图可视化的原理、代码实现的文章,初步了解风场实现的基本原理。关于原理部分,非常感谢这位大佬的文章里的介绍:数据可视化之风向图。感兴趣的可以查看一下,
那位大佬的文章里面形象的把需要显示的风场区域形象的比喻成一个棋盘:棋盘(风场范围)就是由多个小方格组成的,你随手拿一个棋子(风的起点),随机放在一个格子上,这就是当做风的起点,然后如果每个小格子上都定义了这个棋子该怎么走(风的风向),那么当棋子落在小格子里时,已经确定了下一次移动棋子的位置,棋子不停的跟着小格子里的指定方向移动,那么这个棋子就动了起来,对比风的显示效果,如果棋盘足够大,每次有很多个棋子随机的落在棋盘内的某个小格子里,然后都按照格内的方向一次接一次的移动,这个风就刮起来了。这里面当然也需要考虑很多细节的问题,大佬文章里也指出了,比如棋子移动到了边界怎么处理,棋子的生命周期的设置,老棋子的消亡,新棋子的诞生等等。这些问题其实都是可以自定义处理的,如果使用代码来实现,完全可以自由发挥,例如棋子到了边界,可以让它消亡,重新在随机产生一个棋子,也可以让它回归原始位置,从新在执行自己的运动轨迹。
3、准备风向数据
风向数据的准备和处理很重要,因为它最终影响着风场的显示效果。风场数据就和向量一样,分为南北方向(U)、东西方向(V);要有具体的格式供前端调用,那无非就是构造成json数据了。参考文章:气象数据之风向数据展示原理和气象数据之风向数据json格式解析。我使用的风场源数据不是上面文章中所说的netcdf数据或grib2数据;所以我转换的时候用到了其他办法,不过最终定义的数据类型是他那种。
其实我在准备数据的时候,还要贴合我的实际使用需求,得到风场数据源还要进一步处理,源数据风场还分为了不同高度下的风场要进行纠正和精细化处理,这里说一下精细化处理,精细化处理是要更细致的表现风场的分布,拿到的数据一般不是很精细,需要结合楼宇数据等其他辅助数据进行精细化,直接点就像栅格把分辨率缩小,因为从风场的原理可知道,风在运动的时候是按照指定的‘格子’进行变化,如果‘格子’的范围太大,比楼宇之间的距离还大,那么就没办法保障风场在局部范围的细节展示了,所以要做精细化处理,最起码楼宇之间可以多放几个格子,精细化后比较头疼的是区域不大,但最终结果数据很大,精细化不够显示效果不好。
其中包括了插值处理,插值过的风场在小区内每个位置都是有风向的,那么我要尽量保证在风场高度不超过小区楼层高度的时候,风场显示的时候尽量不能覆盖超过它的楼层,这么一来对坐标要求就很苛刻了,要确定建筑边界的位置,在处理风场数据时候要把在建筑区域内的风进行标识处理(0,0),意思就是风到这里就没了,实际情况也是如此,因为建筑会挡住风,改变风的走向,模拟的时候如果风到了建筑边界,要把它消亡,这样就不会覆盖小区建筑了(其实最终的结果处理看,还是因为坐标精确的问题,导致了一部分低于建筑高度的5米和10米高度下的风会显示在建筑区域上面,可能是三维显示的原因,在转动动地图时,感觉有一部分风就是在建筑上面,如果把视角垂直90度成二维地图的视角,那就好很多,风穿梭在楼宇之间的效果还是有的)。一些必要操作处理完后,直接转成json格式就作为模拟风场的真正数据了。
风向数据json格式实例,具体可以参考上面文章链接:
1、参数含义:
parameterCategory
配置了数据记录内容,风力数据默认为2
parameterCategoryName
风向数据默认:Momentum
parameterNumber
记录了数据方向:U向为2,V向为3
parameterNumberName
U-component_of_wind/V-component_of_wind
numberPoints
数据点数量
nx
横向划分栅格数量
ny
纵向划分栅格数量
dx
横向步长
dy
纵向步长
lo1
横向起点,全球默认为0
la1
纵向起点,全球默认为-90
lo2
横向终点,全球默认359.5,根据步长有所不同
la2
纵向终点,全球默认-902、json格式示例
[{"header": {"discipline": 0,"disciplineName": "Meteorological products","gribEdition": 2,"gribLength": 251674,"center": 7,"centerName": "US National Weather Service - NCEP(WMC)","subcenter": 0,"refTime": "2017-12-27T00:00:00.000Z","significanceOfRT": 1,"significanceOfRTName": "Start of forecast","productStatus": 0,"productStatusName": "Operational products","productType": 1,"productTypeName": "Forecast products","productDefinitionTemplate": 0,"productDefinitionTemplateName": "Analysis/forecast at horizontal level/layer at a point in time","parameterCategory": 2,"parameterCategoryName": "Momentum","parameterNumber": 2,"parameterNumberName": "U-component_of_wind","parameterUnit": "m.s-1","genProcessType": 2,"genProcessTypeName": "Forecast","forecastTime": 0,"surface1Type": 103,"surface1TypeName": "Specified height level above ground","surface1Value": 10,"surface2Type": 255,"surface2TypeName": "Missing","surface2Value": 0,"gridDefinitionTemplate": 0,"gridDefinitionTemplateName": "Latitude_Longitude","numberPoints": 259920,"shape": 6,"shapeName": "Earth spherical with radius of 6,371,229.0 m","gridUnits": "degrees","resolution": 48,"winds": "true","scanMode": 0,"nx": 720,"ny": 361,"basicAngle": 0,"lo1": 0,"la1": 90,"lo2": 359.5,"la2": -90,"dx": 0.5,"dy": 0.5},"data": [2.3011596,2.3011596,2.3011596,2.2811596,......1.1211597,1.1511596,1.1711596]},{"header": {"discipline": 0,"disciplineName": "Meteorological products","gribEdition": 2,"gribLength": 245626,"center": 7,"centerName": "US National Weather Service - NCEP(WMC)","subcenter": 0,"refTime": "2017-12-27T00:00:00.000Z","significanceOfRT": 1,"significanceOfRTName": "Start of forecast","productStatus": 0,"productStatusName": "Operational products","productType": 1,"productTypeName": "Forecast products","productDefinitionTemplate": 0,"productDefinitionTemplateName": "Analysis/forecast at horizontal level/layer at a point in time","parameterCategory": 2,"parameterCategoryName": "Momentum","parameterNumber": 3,"parameterNumberName": "V-component_of_wind","parameterUnit": "m.s-1","genProcessType": 2,"genProcessTypeName": "Forecast","forecastTime": 0,"surface1Type": 103,"surface1TypeName": "Specified height level above ground","surface1Value": 10,"surface2Type": 255,"surface2TypeName": "Missing","surface2Value": 0,"gridDefinitionTemplate": 0,"gridDefinitionTemplateName": "Latitude_Longitude","numberPoints": 259920,"shape": 6,"shapeName": "Earth spherical with radius of 6,371,229.0 m","gridUnits": "degrees","resolution": 48,"winds": "true","scanMode": 0,"nx": 720,"ny": 361,"basicAngle": 0,"lo1": 0,"la1": 90,"lo2": 359.5,"la2": -90,"dx": 0.5,"dy": 0.5},"data": [-0.12500733,-0.14500733,-0.16500732,......-2.9750073,-2.9650073]}
]
4、代码思路
知道了风场原理和数据后,接下来就可以整理编码思路了,看了大部分的代码都是在绘制风的时候用的canvas 2d画线,试验证明这种方式是不错的,canvas 3d绘图没试过,以后有时间可以试一下,虽然不能有效表达风场的高度,但绘制的效率很高,因为我试验过通过cesium中添加Entity实体或者Primitive的方式进行显示,目的就是想突出风场的高度,毕竟是三维地图,建筑物也是三维模型,但是显示效果不太好,风场动起来效率很慢,尤其是Entity,超过三百个点浏览器就已经卡半天不能动了,感兴趣的可以尝试一下。最终还是用了canvas绘制,原理明白后,代码思路就简单了,在前人的基础上总结一下代码思路,总的来说分四步:
1、创建风场区域网格
风场网格区域(棋盘)的创建要根据所输入的数据范围来创建,棋盘的行列数据就是输入风场数据的行列,棋盘里每个格子里的信息就是风场的uv方向上的风速。
2、初始化风场粒子
风场粒子就是棋子,这个可以自定义个数,让它随机的分布在棋盘里,在随机放入棋盘里时,要初始化它的基本信息。基本信息主要包括当前坐标和要移动位置的坐标已经运动速度,其他的比如生命周期这个东西其实可要可不要,很多风场实现代码里都有。
3、绘制风场
绘制的话就是使用canvas来绘制,风场流动是线来表示的,绘制时利用粒子的当前坐标和目标坐标确定这条线,同时可以加入线条的粗细颜色等。
4、更新粒子运动
更新粒子运动就是为了使风动起来,可以使用requestAnimationFrame函数来进行每一帧的重绘,重绘的间隔可以自定义,只要保证效率和画面的流程就ok了,重绘的内容就是更新粒子的位置信息,粒子会在棋盘里安装指定速度进行运动,你重绘的时间越短,画面就越细腻,当然也增加了浏览器的负担。
5、代码
链接:https://pan.baidu.com/s/10vCmogCVz-WQmCUWaEjFGw
提取码:1234
6 风场效果图
最终的效果图,虽然可以大概显示小区区域内风场的流动情况以及楼宇之间导致的风向环流效果;但总归是基于canvas2d画图显示,也就是这个风场不是真3d的,而地图和建筑是三维的,要想做到很好的显示还需要继续研究:1是从数据处理上,数据是一切的入口;2是从渲染加载方式上。以后有时间再慢慢研究一下。
基于cesium+canvas构建小区内部风场图相关推荐
- 分享一个基于Vue3+TS构建Cesium组件库
分享一个基于Vue3+TS构建Cesium组件库 点击进入 Vue Cesium官网 //vc-navigation <template><el-row ref="view ...
- 基于html5 Canvas图表库 : ECharts
基于html5 Canvas图表库 : ECharts 分类 编程技术 ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生 ...
- echart图片库_基于html5 Canvas图表库 : ECharts
ECharts开源来自百度商业前端数据可视化团队,基于html5 Canvas,是一个纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表.创新的拖拽重计算.数据视图.值 ...
- 基于JAVA人才库构建研究计算机毕业设计源码+系统+mysql数据库+lw文档+部署
基于JAVA人才库构建研究计算机毕业设计源码+系统+mysql数据库+lw文档+部署 基于JAVA人才库构建研究计算机毕业设计源码+系统+mysql数据库+lw文档+部署 本源码技术栈: 项目架构:B ...
- 把canvas放在盒子内_如何将您的专业知识放在盒子中并出售
把canvas放在盒子内 At RISE Conf in Hong Kong, Gary Vaynerchuk was asked: 在香港的RISE Conf会议上, 加里·韦纳楚克被问到: H ...
- ajax+lucene pdf,基于Ajax/Lucene的站内搜索技术研究
摘要: 站内搜索引擎是找出网站重要信息的必要工具,高效的站内搜索将有助于提升网站的价值,发挥网站应有的作用.虽然现在一些网络巨头已开始研究并应用这类工具,但整个互联网行业中,受制于技术的门槛,真正的站 ...
- MATLAB在温室中的应用,基于MATLAB的日光温室内气温的图形显示方法与流程
本发明涉及日光温室温度检测 技术领域: ,具体涉及一种基于MATLAB的日光温室内气温的图形显示方法. 背景技术: :日光温室极大丰富了人们的菜篮子,丰富了人们的生活,各地日光温室的墙体材料不尽相同, ...
- Demo:基于 Flink SQL 构建流式应用
摘要:上周四在 Flink 中文社区钉钉群中直播分享了<Demo:基于 Flink SQL 构建流式应用>,直播内容偏向实战演示.这篇文章是对直播内容的一个总结,并且改善了部分内容,比如除 ...
- 一直在构建工作空间_基于用户场景构建的建筑工程弱电设计工作设想
[摘要]因为弱电产品更新速度快,功能差异变化大,往往会出现设计成果同预期有所区别的情况.针对类似情形,文章提出借鉴发展变化更加迅速的互联网行业中产品设计的理念,通过业主方或者设计方构建用户场景的手段, ...
最新文章
- mvc if 显示html,asp.net mvc - 在MVC3 Razor中,如何在动作中获取渲染视图的html?
- js实现线路流动_52期:实现redux与reactredux
- Spring Boot - 修改Tomcat默认的8080端口
- 腾讯视频中如何把视频进行收藏
- 第20章 TCP的成块数据流
- Linux学习总结(四)-两种模式修复系统,单用户,救援模式
- Oracle中connect by...start with...的使用
- 律师总结二手房买卖中的八大陷阱
- oracle区分度公式,区分度越大的列,作为主导列,索引效果越好?
- 冈萨雷斯 数字图像处理 插图 打包下载 原tif版 + png版
- Cookies的SameSite属性
- CentOS7安装Hadoop-3.3.0集群
- 蚂蚁全媒体中心总编刘鑫炜解答:「李子柒说时代给了我一阵风」,成就自媒体网红需要哪些助力?
- 【IT互联网系列】什么是网关?网关的作用是什么?看完不懂,你捶我
- Linux远程访问的方法
- C# 定时关机小应用
- ubuntu server 安全模式磁盘检查修复
- 【c++/c】C语言“小小计算器”基本功能实现(包含12个实验一篇足以)【期末大作业】
- Unity TextMeshpro创建中文字体
- 达人评测 机械革命Z3 Air怎么样
热门文章
- COB--COF--COG--TAB--TCP
- 嵌入式linux 竖屏,嵌入式Linux下竖屏显示配置
- java街边熟食店卤菜网上商城系统springboot+vue
- Docker/Podman使用入门---从容器构建镜像 提交镜像到服务器UCloud dockerhub
- MySQL创建用户,授权
- 我用这个画3d图和电路图、上网,防止鼠标手
- 网易云信第三方接口调用超详细Demo
- hiveserver2 和beeline_Beeline连接Hiveserver2错误
- JSFL批量删除fla文件中超出某个宽度的原件
- css制作聊天气泡android,css实现聊天气泡效果