OpenLayers学习笔记(十一)— 飞机速度矢量线预测
在机场使用的空管系统中,飞机的速度矢量线差不多是这样的:
模拟飞机飞行时的速度矢量线,这里就大概做个类似效果:
什么叫速度矢量线呢,个人理解就是根据飞机当前速度和航向预测它在未来一段时间内的飞机轨迹,以此来监测飞机是否偏离。
如何运行代码已经在上一篇博客《动态加载JSON数据模拟航迹线》讲过了。
在这个模拟DEMO中,主要存在四个图层,分别为地图底图、航迹线图层、速度矢量线图层、飞机图层(我用的点代替飞机图标),因为我自身有一个需求就是控制航迹和速度矢量线的显示与隐藏,这跟本文没多大关系。
技术准备
常规的数学公式都知道,路程 = 速度 * 时间,在地图上的一些相关计算,查阅了一些资料,并翻译了相关的计算博文《(译)计算距离、方位以及更多经纬度之间的点》,并Google到了一个相关的技术博客,只不过这是基于OL 2的一些例子,但是我从中得到了一些灵感。
1.实现
在上一篇博文的代码基础上添加,相关都做了详细注释
2.图层以及样式
/**
* @name: 相关样式和图层:点 航迹线 飞机 标牌
* @test: test font
* @msg:
* @param {type}
* @return:
*/
//样式
let point_style = new ol.style.Style({//预测点
image:new ol.style.Circle({
radius:2,
snapToPixel:false,
fill:new ol.style.Fill({
color:'#333'
}),
stroke:new ol.style.Stroke({
color:"#333",
})
})
})
let route_style = new ol.style.Style({//航迹线
stroke:new ol.style.Stroke({
width:2,
color: 'yellow'
}),
zIndex:2
});
let vel_style = new ol.style.Style({//速度矢量线
stroke:new ol.style.Stroke({
color: '#333',
width: 1,
})
});
//创建轨迹线
let trackLine = new ol.geom.LineString([]);
//速度矢量线
let velLine = new ol.geom.LineString([]);
//矢量图层层
let aircfaftLayer = new ol.layer.Vector({//飞机图层
source:new ol.source.Vector(),
updateWhileInteracting: true,
updateWhileAnimating: true
})
let flightTrackLayer = new ol.layer.Vector({//航迹线图层
source:new ol.source.Vector({
features:[
new ol.Feature({
geometry:trackLine
})
]
}),
style:route_style,
updateWhileInteracting: true
});
let velLayer = new ol.layer.Vector({//速度矢量线图层
3.初始化地图
/*
* @name: 初始化地图
* @description:
* @param {type} none
* @return: */
let center = new ol.proj.fromLonLat([104.06250000000001, 30.65681556429287]);
//地图
let map = new ol.Map({
//图层顺序自下而上
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({ })
}),flightTrackLayer,velLayer,aircfaftLayer,
],
renderer: 'canvas',
target: 'map',
view: new ol.View({
center: center,
zoom: 6
})
}); /**
* @name: 飞机 标牌 样式
* @description:
* @param {type} none
* @return:
*/
//标牌叠加层 + 指引线
let markerEl = document.getElementById('geo-marker');//标牌
let marker = new ol.Overlay({
positioning: 'bottom-center',
stopEvent: false,
dragging: false,
offset: [0, -10],
element: markerEl,
stopEvent: false
});
map.addOverlay(marker); //飞机样式 以点代替飞机图片
function createGoodStyle() {
return new ol.style.Style({
image:new ol.style.Circle({//点状模拟飞机
radius:6,
snapToPixel:false,
fill:new ol.style.Fill({
color:'yellow'
}),
stroke:new ol.style.Stroke({
color:"#333",
width:2
})
}) });
}
//设置地图中心
let centerAir = val => {
map.getView().setCenter(val);
}
4.加载数据
/**
* @name: 加载数据
* @description:
* @param {type} none
* @return:
*/
//添加飞机 + 更新位置 const KTS2KPH = 1.85200;//1 knot (kt) = 1.85200 kilometer per hour (kph)
const NM2KM = 1.852;
const pred_secs = 5 * 60; //5分钟
const bearing = 90; //航向
let coords = [], speedMH = [], flightData, intervalId, interval = 1000, i = 0;
let from , to, distance_whole, tiem_whole, distance_cur, point_cur, point_next;
const url = './data/openflights/vel.json';
let theAirplane = new ol.Feature([]); $('.startAnimate').click(() => {
//加载坐标数据
$.ajax({
url: url,
dataType: 'json',
success: function (response) {
console.log("飞行开始");
flightData = response.data;
coords = flightData.map(obj => {//坐标集合
return obj[0];
})
speedMH = flightData.map(obj => {//速度集合
return obj[1];
})
//飞机
theAirplane.setId(response.aircraftNum);
theAirplane.setStyle(createGoodStyle());
aircfaftLayer.getSource().addFeature(theAirplane); //预测点
let vel_point = new ol.Feature([]);
vel_point.setStyle(point_style);
velLayer.getSource().addFeature(vel_point); //模拟飞行
intervalId = setInterval(() => {
let position;
position = ol.proj.fromLonLat(coords[i]); //标牌
marker.setPosition(position);
markerEl.innerHTML = response.aircraftNum;//简标牌 //飞机
theAirplane.setGeometry(new ol.geom.Point(position)); //航迹
let point = new ol.proj.transform(coords[i], 'EPSG:4326', 'EPSG:3857');
trackLine.appendCoordinate(point); //以飞机当前位置为地图中心
centerAir(position); //速度矢量线
from = new LatLon(coords[0][1], coords[0][0]);//起点
to = new LatLon(coords[coords.length - 1][1], coords[coords.length - 1][0]);//终点
// console.log(from, to); distance_whole = from.distanceTo(to) / 1000;// km 总里程
tiem_whole = distance_whole / speedMH[i] / KTS2KPH;// hour 总耗时
// console.log(distance_whole, tiem_whole); point_cur = new LatLon(coords[i][1], coords[i][0]);//当前坐标
distance_cur = KTS2KPH * speedMH[i] * ( pred_secs * interval / 3600); //已经过里程
point_next = point_cur.destinationPoint(distance_cur, bearing); //预测5分钟后所在的坐标点
// console.log( distance_whole, tiem_whole, distance_cur, point_next);
let pointCur = ol.proj.fromLonLat([point_cur._lon, point_cur._lat]);
let pointNext = ol.proj.fromLonLat([point_next._lon, point_next._lat]); let pointNextArray = Array();
pointNextArray.push(pointNext);
console.log(pointNextArray); //预测点
vel_point.setGeometry(new ol.geom.Point(pointNext)); //速度矢量线
let velFeature = new ol.Feature(velLine);
velFeature.setStyle(vel_style);
velLine.setCoordinates([pointCur, pointNext]); //绘制速度矢量线
velLayer.getSource().addFeature(velFeature); i++;
if (i === flightData.length) {
clearInterval(intervalId);
console.log("飞行结束");
} }, interval); }
})
})
5.json数据
json数据来源于arc.js,该例子选取的是成都—上海的坐标数据,速度是我自己随意添加的:
{ "ID": "1",
"aircraftNum": "B000",
"data": [
[[104.06250000000001, 30.65681556429287], "284"],
[[104.23659653944907, 30.67396833485058], "285"],
[[104.4107544999246, 30.690888911014596], "285"],
[[104.58497310591778, 30.70757705503652], "286"],
[[104.75925157857333, 30.724032532190993], "284"],
[[104.93358913572729, 30.740255110788784], "286"],
[[105.10798499194534, 30.75624456218971], "287"],
[[105.28243835856125, 30.772000660815337], "288"],
[[105.45694844371592, 30.787523184161603], "288"],
[[105.63151445239656, 30.80281191281125], "287"],
[[105.80613558647657, 30.817866630446186], "288"],
[[105.98081104475536, 30.8326871238596], "287"],
[[106.15554002299895, 30.847273182967992], "287"],
[[106.33032171398055, 30.861624600823], "286"],
[[106.50515530752187, 30.875741173623137], "285"],
[[106.68003999053437, 30.889622700725297], "287"],
[[106.85497494706121, 30.90326898465615], "285"],
[[107.02995935831927, 30.916679831123393], "288"],
[[107.20499240274177, 30.929855049026738], "287"],
[[107.38007325602092, 30.942794450468945], "286"],
[[107.55520109115115, 30.95549785076639], "285"],
[[107.73037507847249, 30.967965068459744], "287"],
[[107.90559438571445, 30.98019592532436], "286"],
[[108.08085817803996, 30.992190246380456], "288"],
[[108.25616561808987, 31.003947859903253], "287"],
[[108.43151586602752, 31.01546859743276], "285"],
[[108.60690807958395, 31.026752293783623], "286"],
[[108.7823414141029, 31.0377987870545], "285"],
[[108.9578150225866, 31.0486079186376], "287"],
[[109.13332805574153, 31.059179533227734], "285"],
[[109.30887966202457, 31.069513478831404], "286"],
[[109.48446898768944, 31.079609606775563], "285"],
[[109.66009517683327, 31.089467771716325], "287"],
[[109.83575737144373, 31.099087831647413], "285"],
[[110.011454711446, 31.108469647908397], "287"],
[[110.18718633475038, 31.11761308519283], "288"],
[[110.36295137729994, 31.126518011556165], "289"],
[[110.53874897311843, 31.135184298423425], "287"],
[[110.7145782543585, 31.14361182059676], "286"],
[[110.89043835135004, 31.151800456262833], "285"],
[[111.06632839264884, 31.1597500869999], "286"],
[[111.24224750508553, 31.16746059778481], "287"],
[[111.4181948138144, 31.17493187699975], "288"],
[[111.5941694423629, 31.182163816438862], "289"],
[[111.77017051268102, 31.18915631131456], "290"],
[[111.94619714519094, 31.195909260263747], "288"],
[[112.1222484588369, 31.202422565353807], "288"],
[[112.29832357113521, 31.208696132088367], "288"],
[[112.47442159822452, 31.21472986941292], "288"],
[[112.65054165491617, 31.220523689720157], "287"],
[[112.82668285474469, 31.226077508855244], "287"],
[[113.00284431001862, 31.231391246120737], "288"],
[[113.17902513187131, 31.236464824281384], "287"],
[[113.35522443031194, 31.241298169568736], "286"],
[[113.53144131427662, 31.245891211685535], "285"],
[[113.70767489167979, 31.250243883809823], "285"],
[[113.88392426946552, 31.254356122599024], "285"],
[[114.0601885536591, 31.258227868193615], "286"],
[[114.23646684941869, 31.26185906422076], "285"],
[[114.41275826108706, 31.265249657797618], "287"],
[[114.58906189224348, 31.268399599534526], "287"],
[[114.76537684575561, 31.271308843537938], "286"],
[[114.94170222383167, 31.27397734741316], "287"],
[[115.11803712807243, 31.276405072266883], "288"],
[[115.2943806595235, 31.27859198270948], "288"],
[[115.47073191872758, 31.28053804685718], "288"],
[[115.64709000577683, 31.282243236333912], "288"],
[[115.82345402036526, 31.28370752627301], "288"],
[[115.99982306184107, 31.284930895318737], "288"],
[[116.17619622925929, 31.285913325627515], "288"],
[[116.35257262143426, 31.28665480286904], "288"],
[[116.52895133699217, 31.28715531622708], "288"],
[[116.70533147442355, 31.28741485840016], "287"],
[[116.8817121321361, 31.28743342560202], "288"],
[[117.0580924085071, 31.28721101756178], "288"],
[[117.23447140193603, 31.286747637524012], "287"],
[[117.41084821089731, 31.286043292248515], "287"],
[[117.58722193399282, 31.285097992009906], "287"],
[[117.76359167000443, 31.283911750597046], "287"],
[[117.93995651794664, 31.282484585312172], "286"],
[[118.11631557711907, 31.280816516969885], "286"],
[[118.29266794715906, 31.278907569895903], "286"],
[[118.46901272809394, 31.276757771925578], "286"],
[[118.64534902039362, 31.27436715440231], "286"],
[[118.82167592502275, 31.271735752175562], "286"],
[[118.99799254349321, 31.268863603598895], "286"],
[[119.17429797791613, 31.26575075052759], "285"],
[[119.35059133105422, 31.262397238316204], "285"],
[[119.52687170637368, 31.258803115815805], "285"],
[[119.70313820809623, 31.254968435371172], "285"],
[[119.87938994125103, 31.250893252817523], "285"],
[[120.05562601172639, 31.2465776274773], "285"],
[[120.2318455263214, 31.242021622156606], "285"],
[[120.40804759279759, 31.237225303141468], "285"],
[[120.58423131993031, 31.232188740193873], "285"],
[[120.76039581756008, 31.226912006547636], "285"],
[[120.93654019664363, 31.221395178904057], "284"],
[[121.11266356930511, 31.215638337427364], "284"],
[[121.28876504888679, 31.20964156573994], "284"],
[[121.46484375, 31.203404950917395], "283"]
] }
后续要完成的就是拖拽飞机标牌以及控制图层的显示与隐藏
查看源码:GitHub
OpenLayers学习笔记(十一)— 飞机速度矢量线预测的更多相关文章
- OpenLayers学习笔记(十二)— 飞机速度矢量线预测(二)
根据计算公式实现预测线 作者:狐狸家的鱼 GitHub:八至 之前有一篇博客简单写了一个模拟demo,根据物体当前的速度和方向预测多少时间后所在的位置,具体计算是参考<(译)计算距离.方位以及更 ...
- python3.4学习笔记(十一) 列表、数组实例
python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...
- Go语言学习笔记十一: 切片(slice)
Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...
- OpenLayers学习笔记(十)— 动态加载JSON数据模拟航迹线
在openlayers 3 上,加载本地json数据,动态绘制航迹线,以飞机当前位置为地图中心,此例子是模拟DEMO 本文链接:动态加载JSON数据模拟航迹线 作者:狐狸家的鱼 GitHub:八至 前 ...
- SharpGL学习笔记(十一) 光源创建的综合例子:光源参数可调节的测试场景
灯光的测试例子:光源参数可以调节的测试场景 先看一下测试场景和效果. 场景中可以切换视图, 以方便观察三维体和灯光的位置.环境光,漫射光,镜面反射光都可以在四种颜色间切换. 灯光位置和摄像机位置(Lo ...
- JavaScript权威设计--JavaScript函数(简要学习笔记十一)
1.函数调用的四种方式 第三种:构造函数调用 如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内.这和函数调用和方法调用是一致的.但如果构造函数没有形参,JavaScri ...
- OpenLayers学习笔记4——使用jQuery UI实现測量对话框
OpenLayers学习最好的方式就是跟着其自带的演示样例进行学习,另外对web前端的开发设计要了解,慢慢积累,这样在一般的小项目中应该是足够用了. 本篇參照量測demo实现对话框形式的量測,抛砖引玉 ...
- openlayers学习笔记(十三)— 异步调用JSON数据画点、文字标注与连线
使用Openlayers 3实现调用本地json数据在地图上添加点.文字标注以及连线. 生成底图地图 首先得有一个地图作为底图,代码如下: let vectorSource = new ol.sour ...
- java jvm学习笔记十一(访问控制器)
欢迎装载请说明出处: http://blog.csdn.net/yfqnihao/article/details/8271665 这一节,我们要学习的是访问控制器,在阅读本节之前,如果没有前面几节的 ...
随机推荐
- 多线程之Thread
Thread类可以创建和控制线程,Thread类的构造函数重载为接受ThreadStart和ParameterizedThreadStart类型的委托参数. Thread类默认创建的是前台线程,所以我 ...
- 读书笔记之_Win10 与Jmeter5.1.1界面兼容:
读书笔记之win10 与jmeter5.1.1界面兼容: 调整前:
- 业务与IT技术
最近听一个同事又再次提问关于业务比技术重要,是真的吗? 今天我们再来看一下. 一,什么是业务? 业务意指某种有目的的工作或工作项目.技术可以指人类对机器.硬件或人造器皿的运用,但它也可以包含 ...
- C#图片添加文字水印
/// <summary> /// 给图片添加文字水印 /// </summary> /// <param name="img">图片</ ...
- JavaScript调试总结
一.vs调试 1.设置断点 2.设置浏览模式:一定要设置IE浏览器 3.设置起始页 4.运行 二.谷歌浏览器调试 1.运行项目,进入后F12,找到Sources
- js常用写法
遍历数组 ES5 写法 arr.forEach(function(value,index){ console.log(index+'--'+value); }) 遍历数组 ES6 写法 for( l ...
- 网页控制脚本修改系统信息 C语言调用uci
0 交叉编译生成程序 http://tuntuntun.net/%E5%9C%A8OpenWrt%E4%B8%8A%E8%BF%90%E8%A1%8C%E7%AC%AC%E4%B8%80%E4%B8% ...
- Pandas 数据清洗常用篇
一.缺失值 sklearn中的preprocessing下有imputer,可进官方文档参考.这里主讲pandas. 拿到数据,一般先检查是否有缺失值,用isnul()或notnull(). 再决定d ...
- VMware Workstation14 安装Ubuntu18.04
1 下载Vmware Workstations14破解版 百度网盘链接:https://pan.baidu.com/s/12yVxoPCJUAmdts4SUdzndg 提取码:bs0g 2 下载Ubu ...
- rpm安装查看卸载软件
1.安装 rpm -i 需要安装的包文件名 举例如下: rpm -i example.rpm 安装 example.rpm 包: rpm -iv example.rpm 安装 example.rpm ...