需求背景: 模拟台风运动情况,包含绘制台风路径,预测线,台风风圈,台风警戒线等。
效果图
台风的绘制分为两部分,静态图形的绘制与动态图形的绘制。其中静态图形是,台风的主线,台风的预测线与预警线。这部分用polyline做绘制。图形的动画,主要是风圈与风圈点,用availability去实现动画。
绘制台风圈
接口数据:radius7: "200|180|180|150"(台风圈四个方向上的半径,按照顺时针方向旋转。)
/**
* 计算风圈
* @param lng
* @param lat
* @param radius
* @param start
* @param end
* @returns
*/
private computeCirclularFlight(lng: string, lat: string, radius: string, start: number, end: number) {
let Ea = 6378137 // 赤道半径
let Eb = 6356725 // 极半径
let positionArr = []
for (let i = start; i <= end; i = i + 2) {
let dx = Number(radius) * Math.sin((i * Math.PI) / 180.0)
let dy = Number(radius) * Math.cos((i * Math.PI) / 180.0)
let ec = Eb + ((Ea - Eb) * (90.0 - Number(lat))) / 90.0
let ed = ec * Math.cos((Number(lat) * Math.PI) / 180)
let BJD = Number(lng) + ((dx / ed) * 180.0) / Math.PI
let BWD = Number(lat) + ((dy / ec) * 180.0) / Math.PI
positionArr.push(BJD)
positionArr.push(BWD)
}
return positionArr
}
/**
* 获取台风风圈,返回的是风圈点集数组
* @param {object} circle
*/
private getWindCircle(circle: { lng: any; lat: any; radius: any; direct: any }) {
// 90°的扇形,四分之一圆,顺时针
let start = 0
let end = 90
switch (circle.direct) {
case 'EN':
start = 0
end = 90
break
case 'ES':
start = 90
end = 180
break
case 'WS':
start = 180
end = 270
break
case 'WN':
start = 270
end = 360
break
}
let pointArr = []
pointArr = this.computeCirclularFlight(circle.lng, circle.lat, circle.radius, start, end)
return pointArr
}
在二维的平面里,已知半径与夹角求对边与邻边。得到点坐标。
Ea 表示赤道半径,Eb表示极半径,地球是一个近似球体,Ea与Eb稍微有点差距。ec的作用就是修正因为纬度不断变化的球半径长度。如果在GLAT=0,即在赤道上的时候,ec=Eb+(Ea-Eb)(90-0)/90=Ea,那ec就刚好是赤道半径Ea;如果在极点GLAT=90,ec=Eb+(Ea-Eb)(90-90)/90=Eb,那ec 就刚好是极半径Eb。
参看上图,那dx / ed 就相当于是在GLAT这个纬度上dx长度与总长度的占比,算出来应该是个经度跨度。如果这个经度跨度加上起始给定的经度就是最终的经度。
同理 dy/R就是在GLON这个经度上的dy长度与地球平均半径R的占比,算出来应该是一个纬度跨度。如果这个纬度跨度加上起始给定的纬度就是最终的纬度。这里使用了R,取地球平均半径。
dy/ec 就是用不断修正的ec半径替代了平均半径R。
(dy / ec + GLAT * Math.PI / 180.0) 就是起始纬度加上distance距离的最终纬度,同时需要将该结果转换为角度。 转换角度方法是:弧度* 180.0 / Math.PI。
BWD = (dy / ec + GLAT * Math.PI / 180.0) * 180.0 / Math.PI;
(dx / ed + GLON * Math.PI / 180.0)就是起始经度加上distance距离的最终经度,同时需要将该结果转换为角度。
BJD = (dx / ed + GLON * Math.PI / 180.0) * 180.0 / Math.PI;
参考资料