cesium-examples/map/3d/code/winds.js

334 lines
9.8 KiB
JavaScript
Raw Normal View History

2019-11-21 15:46:14 +08:00
/*
* @Descripttion:
* @version: 1.0
* @Author: zhangti
* @Date: 2019-10-22 16:29:22
* @LastEditors: sueRimn
* @LastEditTime: 2019-11-16 16:08:40
*/
/**
* 封装风场
* 洋流效果
*/
/**
* 粒子实体
*/
const Particle = class {
constructor(){
this.x = null;
this.dx = null;
this.dx = null;
this.y = null;
this.age = null;
this.birthAge = null;
this.path = null;
}
}
/**
* 风场实体
*/
const WindField = class {
constructor(obj){
this.west = null;
this.east = null;
this.south = null;
this.north = null;
this.rows = null;
this.cols = null;
this.dx = null;
this.dy = null;
this.unit = null;
this.date = null;
this.grid = null;
this._init(obj);
}
_init(obj) {
var header = obj.header,
uComponent = obj['uComponent'],
vComponent = obj['vComponent'];
this.west = +header['lo1'];
this.east = +header['lo2'];
this.south = +header['la2'];
this.north = +header['la1'];
this.rows = +header['ny'];
this.cols = +header['nx'];
this.dx = +header['dx'];
this.dy = +header['dy'];
this.unit = header['parameterUnit'];
this.date = header['refTime'];
this.grid = [];
var k = 0,
rows = null,
uv = null;
for (var j = 0; j < this.rows; j++) {
rows = [];
for (var i = 0; i < this.cols; i++, k++) {
uv = this._calcUV(uComponent[k], vComponent[k]);
rows.push(uv);
}
this.grid.push(rows);
}
}
_calcUV (u, v) {
return [+u, +v, Math.sqrt(u * u + v * v)];
}
_bilinearInterpolation (x, y, g00, g10, g01, g11) {
var rx = (1 - x);
var ry = (1 - y);
var a = rx * ry, b = x * ry, c = rx * y, d = x * y;
var u = g00[0] * a + g10[0] * b + g01[0] * c + g11[0] * d;
var v = g00[1] * a + g10[1] * b + g01[1] * c + g11[1] * d;
return this._calcUV(u, v);
}
getIn (x, y) {
var x0 = Math.floor(x),
y0 = Math.floor(y),
x1, y1;
if (x0 === x && y0 === y) return this.grid[y][x];
x1 = x0 + 1;
y1 = y0 + 1;
var g00 = this.getIn(x0, y0),
g10 = this.getIn(x1, y0),
g01 = this.getIn(x0, y1),
g11 = this.getIn(x1, y1);
return this._bilinearInterpolation(x - x0, y - y0, g00, g10, g01, g11);
}
isInBound (x, y) {
if ((x >= 0 && x < this.cols - 2) && (y >= 0 && y < this.rows - 2)) return true;
return false;
}
}
/**
* 风场接口
*/
const Windy = class{
constructor(param){
if(null === param || undefined === param)return;
var t = this;
for(var key in param){
t[key] = param[key];
}
this.windData = param.data;
this.windField = null;
this.particles = [];
this.lines = null;
this._primitives = this.viewer.scene.primitives;
this._init();
}
_init () {
// 创建风场网格
this.windField = this.createField();
// 创建风场粒子
for (var i = 0; i < this.PARTICLES_NUMBER; i++) {
this.particles.push(this.randomParticle(new Particle()));
}
}
createField () {
var data = this._parseWindJson();
return new WindField(data);
}
animate(){
try {
var self = this,
field = self.windField,
particles = self.particles,
SPEED_RATE = self.SPEED_RATE;
var instances = [],
nextX = null,
nextY = null,
xy = null,
uv = null;
particles.forEach(function (particle) {
if (particle.age <= 0) {
self.randomParticle(particle);
}
if (particle.age > 0) {
var x = particle.x,
y = particle.y;
if (!field.isInBound(x, y)) {
particle.age = 0;
} else {
uv = field.getIn(x, y);
nextX = x + SPEED_RATE * uv[0];
nextY = y + SPEED_RATE * uv[1];
particle.path.push(nextX, nextY);
particle.x = nextX;
particle.y = nextY;
instances.push(self._createLineInstance(self._map(particle.path), particle.age / particle.birthAge));
particle.age--;
}
}
});
if (instances.length <= 0)self.removeLines();
self._drawLines(instances);
} catch (error) {
console.log(error);
}
}
_parseWindJson () {
var uComponent = null,
vComponent = null,
header = null;
this.windData.forEach(function (record) {
var type = record.header.parameterCategory + "," + record.header.parameterNumber;
switch (type) {
case "2,2":
uComponent = record['data'];
header = record['header'];
break;
case "2,3":
vComponent = record['data'];
break;
default:
break;
}
});
return {
header: header,
uComponent: uComponent,
vComponent: vComponent
};
}
removeLines () {
if (this.lines) {
this._primitives.remove(this.lines);
this.lines.destroy();
}
}
//求路径上点
_map (arr) {
var length = arr.length,
field = this.windField,
dx = field.dx,
dy = field.dy,
west = field.west,
south = field.north,
newArr = [];
for (var i = 0; i <= length - 2; i += 2) {
newArr.push(
west + arr[i] * dx,
south - arr[i + 1] * dy
)
}
return newArr;
}
//后边配色需要能配置
_createLineInstance (positions, ageRate) {
var colors = [],$color = this.color,
length = positions.length,
count = length / 2;
for (var i = 0; i < length; i++) {
colors.push($color.withAlpha(i / count * ageRate * this.BRIGHTEN));
}
return new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray(positions),
colors: colors,
width: 1.5,
colorsPerVertex: true
})
});
}
_drawLines (lineInstances) {
this.removeLines();
var linePrimitive = new Cesium.Primitive({
appearance: new Cesium.PolylineColorAppearance({
translucent: true
}),
geometryInstances: lineInstances,
asynchronous: false
});
this.lines = this._primitives.add(linePrimitive);
}
randomParticle (particle) {
var safe = 30,x, y;
do {
x = Math.floor(Math.random() * (this.windField.cols - 2));
y = Math.floor(Math.random() * (this.windField.rows - 2));
} while (this.windField.getIn(x, y)[2] <= 0 && safe++ < 30);
particle.x = x;
particle.y = y;
particle.age = Math.round(Math.random() * this.MAX_AGE);
particle.birthAge = particle.age;
particle.path = [x, y];
return particle;
}
}
/**
* 外部接口
*/
export default class Winds{
constructor(param){
if(param == null){
console.log("没有获取到参数!");
return false;
};
var t = this;
for(var key in param){
t[key] = param[key];
}
//外部控制参数
this.WINDY = {
Color:{RED:Cesium.Color.RED,BLUE:Cesium.Color.BLUE
,ORANGE:Cesium.Color.ORANGE,WHITE:Cesium.Color.WHITE
,CHARTREUSE:Cesium.Color.CHARTREUSE},
Speed:{_1:0.1,_2:0.2,_3:0.3,_4:0.4,_1:0.5,_6:0.6,_7:0.7,_8:0.8}
}
//给默认值
this.ms = this.ms == undefined ? 300 : this.ms;
this.color = this.color == undefined ? Cesium.Color.CHARTREUSE : this.color;
this.BRIGHTEN = this.BRIGHTEN == undefined ? 1.5 : this.BRIGHTEN;
this.MAX_AGE = this.MAX_AGE == undefined ? 10 : this.MAX_AGE;
this.PARTICLES_NUMBER = this.PARTICLES_NUMBER == undefined ? 2000 : this.PARTICLES_NUMBER;
this.SPEED_RATE = this.SPEED_RATE == undefined ? 0.15 : this.SPEED_RATE;
this.url = this.url == undefined ? 'data/2017121300.json' : this.url; //current-temp-surface-level-gfs-1.0
}
load(){
let $this = this;
$.get($this.url,{},function(json){
if(json == "" && json == null){
console.log("没有获取到数据!");
return false;
};
$this.data = json;
$this.windy = new Windy($this,$this.viewer);
$this.windy.animate();
$this.task();
//viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(117, 30,20000000)});
});
}
//设置颜色
setColor(value){
this.windy.color = value;
}
//设置速度
setSpeed(value){
this.windy.SPEED_RATE = value;
}
//定时任务
task(){
var $this = this;
$this.timer = setInterval(function () {
// console.log(123456);
$this.windy.animate();
}, $this.ms);
}
remove(){
if(this.windy != undefined){
this.windy.removeLines();
window.clearInterval(this.timer);
}
}
}