cesium 繪制台風(附代碼)


台風的繪制,首要任務就是台風數據,沒有數據,一切白搭,技術難點就台風圈繪制較為復雜,數據格式在文末
let Viewer ;
function showTFLJ(viewer,data) {//顯示台風路徑,包括台風圈
Viewer = viewer;
data.forEach(function (t) {
const positions = [];
 const position = [];
//對台風數據進行時間排序
let typhoonPoints = t.typhoonPoints.sort(function (a,b) {
return a.time-b.time;
});
//封裝坐標點
typhoonPoints.forEach(function (p) {
positions.push(p.longitude*1);
positions.push(p.latitude*1);
positions.push(8000);
position.push(p);
})
//點畫線
viewer.entities.add({
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions),//[113.5,14.4,113.7,14.3,113.9,14.2,114.1,14.1,114.3,14.0,114.5,13.9,114.7,13.9,115.0,13.8,115.2,13.8,115.4,13.7,115.6,13.7,115.8,13.7,116.1,13.6,116.3,13.6,116.5,13.5,116.6,13.4,116.8,13.4,116.9,13.3,117.0,13.3,117.1,13.3,117.2,13.3,117.3,13.3,117.4,13.3,117.6,13.1,117.8,13.0,117.9,13.0,118.1,12.9,118.2,12.8,118.4,12.7]
width: 1,//new Cesium.CallbackProperty(changeR3, false),
height:8000,
material: Cesium.Color.WHEAT.withAlpha(0.5)
},
});
//核心代碼
position.forEach(function (p,index) {
const entity = viewer.entities.add({
describe:t.name+"_"+p.time+"_"+p.longitude+"/"+p.latitude+"_"
+p.speed+" 米/秒,"+p.power+"級("+p.strong+")"+"_"
+p.pressure+" 百帕"+"_"+p.moveSpeed+" 公里/小時,"+p.moveDir+"_"
+p.radius7+"|"+p.radius10+"|"+p.radius12+"_"+p.radius7Quad+"|"+p.radius10Quad+"|"+p.radius12Quad,//此處是為了展示明細信息,單擊點彈框顯示明細
position: Cesium.Cartesian3.fromDegrees(p.longitude*1,p.latitude*1,8001),
ellipse : {
semiMinorAxis : new Cesium.CallbackProperty(changeR1, false),//縮放按比例調整entity大小
semiMajorAxis : new Cesium.CallbackProperty(changeR1, false),//縮放按比例調整entity大小
height:8001,
material : Cesium.Color.BLUE.withAlpha(0.5)
}
});
//根據power 判斷風力,展示不同顏色點
if(p.power*1<=7)//熱帶低壓 TD
entity.ellipse.material = TD;
if(p.power*1>7 && p.power*1<=9)//熱帶風暴 TS
entity.ellipse.material = TS;
if(p.power*1>9 && p.power*1<=11)//強熱帶風暴 STS
entity.ellipse.material = STS;
if(p.power*1>11 && p.power*1<=13 )//台風 TY
entity.ellipse.material = TY;
if(p.power*1>13 && p.power*1<=15 )//強台風 STY
entity.ellipse.material = STY;
if(p.power*1>15 )//超強台風 SuperTY
entity.ellipse.material = SuperTY;

//核心,風圈的繪制
//畫台風風圈的原理如下:以圓心為原點,以正北方向為0度,順時針畫點,1度為1個點,並連成線,並最終回到正北方向,形成封閉的多邊形;然后再加以填充。由於台風半徑分為東北、東南、西南、西北四個方向,每個方向距離圓心可能長度不一,於是就形成了有四個鋸齒狀的風圈。
if(index==position.length-1){//判斷最后一個點,繪制 台風圈
let points = new Array();
if(p.radius7>0){//7級風圈
points = new Array();
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius7Quad).ne*1, 0);//東北方向
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius7Quad).se*1, 90);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius7Quad).sw*1, 180);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius7Quad).nw*1, 270);
if(points.length>0){
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(points),
material: new Cesium.Color(242/255,205/255,65/255).withAlpha(0.2),
extrudedHeight: 1000,
outline: true,
outlineColor:new Cesium.Color(242/255,205/255,65/255),
outlineWidth:10
}
});
}
}
if(p.radius10>0){//10級風圈
points = new Array();
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius10Quad).ne*1, 0);//東北方向
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius10Quad).se*1, 90);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius10Quad).sw*1, 180);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius10Quad).nw*1, 270);
if(points.length>0){
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(points),
material: new Cesium.Color(242/255,205/255,65/255).withAlpha(0.2),
extrudedHeight: 1000,
outline: true,
outlineColor:new Cesium.Color(242/255,205/255,65/255),
outlineWidth:20
}
});
}
}
if(p.radius12>0){//12級風圈
points = new Array();
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius12Quad).ne*1, 0);//東北方向
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius12Quad).se*1, 90);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius12Quad).sw*1, 180);
getPoints([p.longitude*1,p.latitude*1], JSON.parse(p.radius12Quad).nw*1, 270);
if(points.length>0){
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray(points),
material: new Cesium.Color(242/255,205/255,65/255).withAlpha(0.2),
extrudedHeight: 1000,
outline: true,
outlineColor:new Cesium.Color(242/255,205/255,65/255),
outlineWidth:10
}
});
}
}

function getPoints(center, cradius, startAngle) {
let radius = cradius / 100;
let pointNum = 90;
let endAngle = startAngle + 90;
let sin,cos,x,y,angle;
for (let i = 0; i <= pointNum; i++) {
angle = startAngle + (endAngle - startAngle) * i / pointNum;
sin = Math.sin(angle * Math.PI / 180);
cos = Math.cos(angle * Math.PI / 180);
x = center[0] + radius * sin;
y = center[1] + radius * cos;
points.push(x,y);
}
}
const entity1 = viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(p.longitude*1,p.latitude*1,8000),
ellipse : {
semiMinorAxis : new Cesium.CallbackProperty(changeR2, false),//根據高度 縮放entity
semiMajorAxis : new Cesium.CallbackProperty(changeR2, false),//根據高度 縮放entity
height:8000,
material : Cesium.Color.BLUE
}
});
entity1.ellipse.material = new Cesium.ImageMaterialProperty({
image: new Cesium.CallbackProperty(drawCanvasImage, false),//這里是一個旋轉的圖標回調,做一個動態旋轉效果
transparent: true
});
}
})
})

viewer.camera.flyTo({
destination: new Cesium.Cartesian3.fromDegrees(112.7383109598977, 25.658452600672697, 4200000),//相機飛入點
});
}

//展示台風明細,單擊台風路徑的點觸發
function showTFMX(obj) {
    let DOM = document.getElementById("ZY-QX-ICON")
let c = new Cesium.Cartesian2(obj.v.mousePosition.x, obj.v.mousePosition.y);
update(c);
function update(c) {
let x = c.x - (DOM.offsetWidth) / 2;
let y = c.y - (DOM.offsetHeight) ;
DOM.style.top = y + 'px';
DOM.style.left = x + 'px';
DOM.style.display = "block";
}
obj.viewer.scene.postRender.addEventListener(function () {
let p = new Cesium.Cartesian3(obj.v.pickedFeature.id._position._value.x, obj.v.pickedFeature.id._position._value.y,obj.v.pickedFeature.id._position._value.z);
let c = Cesium.SceneTransforms.wgs84ToWindowCoordinates(obj.viewer.scene, p);
if(getIsHide()){//因為這里一直在刷新,可以通過setIsHide 來設置是否展示
update(c);
}else{
DOM.style.display = "none";
}
});
}
//監聽單擊
Ewater.SetClickEvent(viewer, function (e, v) {
    const describe = v.pickedFeature.id.describe;//上面給的明細信息
if (describe) {
CesiumTF.showTFMX({
viewer, e, v,
CurrentEnableBrand: true,
describe
});
CesiumTF.setIsHide(true);
}
});
后台封裝:台風數據格式
public class TyphoonInfo {

@TableId(value="id")
String id;
@ApiModelProperty(value = "台風編碼")
@TableField(value = "code")
String code;
@ApiModelProperty(value = "台風名稱")
@TableField(value = "name")
String name;
@ApiModelProperty(value = "台風英文名稱")
@TableField(value = "ename")
String ename;
@ApiModelProperty(value = "開始時間")
@TableField(value = "begin_time")
Date beginTime;

@ApiModelProperty(value = "結束時間")
@TableField(value = "end_time")
Date endTime;

@ApiModelProperty(value = "年度")
@TableField(value = "year")
String year;
@ApiModelProperty(value = "是否是當前台風")
@TableField(value = "is_current")
String isCurrent;
@ApiModelProperty(value = "台風路徑列表")
@TableField(exist = false)
private List<TyphoonPoints> typhoonPoints;
}






public class TyphoonPoints {
@TableId(value = "id")
String id;
@ApiModelProperty(value = "台風編碼")
@TableField(value = "code")
String code;
@ApiModelProperty(value = "時間")
@TableField(value = "time")
Date time;
@ApiModelProperty(value = "經度")
@TableField(value = "longitude")
String longitude;
@ApiModelProperty(value = "緯度")
@TableField(value = "latitude")
String latitude;

@ApiModelProperty(value = "級別")
@TableField(value = "strong")
String strong;

@ApiModelProperty(value = "最大風力")
@TableField(value = "power")
String power;

@ApiModelProperty(value = "最大風速")
@TableField(value = "speed")
String speed;

@ApiModelProperty(value = "中心氣壓")
@TableField(value = "pressure")
String pressure;

@ApiModelProperty(value = "移動速度")
@TableField(value = "move_Speed")
String moveSpeed;

@ApiModelProperty(value = "移動方向")
@TableField(value = "move_Dir")
String moveDir;

@ApiModelProperty(value = "7級風圈最大半徑值")
@TableField(value = "radius7")
String radius7;

@ApiModelProperty(value = "10級風圈最大半徑值")
@TableField(value = "radius10")
String radius10;

@ApiModelProperty(value = "12級風圈最大半徑值")
@TableField(value = "radius12")
String radius12;

@ApiModelProperty(value = "7級風圈范圍")
@TableField(value = "radius7_Quad")
String radius7Quad;

@ApiModelProperty(value = "10級風圈范圍")
@TableField(value = "radius10_Quad")
String radius10Quad;

@ApiModelProperty(value = "12級風圈范圍")
@TableField(value ="radius12_Quad")
String radius12Quad;
}

台風數據的獲取,可以去網上抓取,網上很多台風數據,附最終效果圖:

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM