cesium 圖層構(gòu)建的那些事 (十九)

我們之前構(gòu)建過arcgis 的風(fēng)場(chǎng)圖層 這次我們切換構(gòu)建cesium的風(fēng)場(chǎng)圖層

我們先設(shè)計(jì)一下風(fēng)場(chǎng)的工具類

vector類定義

class?Vector {

public u:number;

public v:number;

public m:number;

constructor(u:number, v:number) {

this.u = u

this.v = v

this.m =?this.magnitude()

}

/**

* the vector value

* @returns {Number}

*/

magnitude() {

return?Math.sqrt(this.u *?this.u +?this.v *?this.v)

}

/**

* Angle in degrees (0 to 360o) --> Towards

* N is 0o and E is 90o

* @returns {Number}

*/

directionTo() {

let verticalAngle =?Math.atan2(this.u,?this.v)

let inDegrees = verticalAngle * (180.0 /?Math.PI)

if (inDegrees <?0) {

inDegrees +=?360.0

}

return inDegrees

}


/**

* Angle in degrees (0 to 360o) From x-->

* N is 0o and E is 90o

* @returns {Number}

*/

directionFrom() {

let a =?this.directionTo()

return (a +?180.0) %?360.0

}

}


export?default Vector

Filed類定義

```

import Vector from './Vector'

class Field {

public grid:any = null;

public xmin:any = null;

public xmax:any= null;

public ymin:any= null;

public ymax:any= null;

public rows:any= null;

public cols:any= null;

public us:any= null;

public vs:any= null;

public deltaX:any= null;

public deltaY:any= null;

public isFields:any= null;

public isContinuous:any= null;

public wrappedX:any= null;

public range:any= null;

constructor(params:any) {

this.grid = []

this.xmin = params.xmin

this.xmax = params.xmax

this.ymin = params.ymin

this.ymax = params.ymax

this.cols = params.cols // 列數(shù)

this.rows = params.rows // 行數(shù)

this.us = params.us //

this.vs = params.vs

this.deltaX = params.deltaX // x 方向增量

this.deltaY = params.deltaY // y方向增量

if (this.deltaY < 0 && this.ymin < this.ymax) { // eslint-disable-next-line no-console console.warn('[wind-core]: The data is flipY') } else { this.ymin = Math.min(params.ymax, params.ymin) this.ymax = Math.max(params.ymax, params.ymin) } this.isFields = true let cols = Math.ceil((this.xmax - this.xmin) / params.deltaX) // 列 let rows = Math.ceil((this.ymax - this.ymin) / params.deltaY) // 行 if (cols !== this.cols || rows !== this.rows) { // eslint-disable-next-line no-console console.warn('[wind-core]: The data grid not equal') } // Math.floor(ni * Δλ) >= 360;

this.isContinuous = Math.floor(this.cols * params.deltaX) >= 360

this.wrappedX = 'wrappedX' in params ? params.wrappedX : this.xmax > 180 // [0, 360] --> [-180, 180];

this.grid = this.buildGrid()

this.range = this.calculateRange()

}

// fromhttps://github.com/sakitam-fdd/wind-layer/blob/95368f9433/src/windy/windy.js#L110

buildGrid() {

let grid = []

let p = 0

let _a = this,

rows = _a.rows,

cols = _a.cols,

us = _a.us,

vs = _a.vs

for (let j = 0; j < rows; j++) {

let row = []

for (let i = 0; i < cols; i++, p++) {

let u = us[p]

let v = vs[p]

let valid = this.isValid(u) && this.isValid(v)

row[i] = valid ? new Vector(u, v) : null

}

if (this.isContinuous) {

row.push(row[0])

}

grid[j] = row

}

return grid

}

/**

*

*/

release() {

this.grid = []

}

/***

*

@returns{(*)[]}

*/

extent() {

return [this.xmin, this.ymin, this.xmax, this.ymax]

}

/**

Bilinear interpolation for Vector

https://en.wikipedia.org/wiki/Bilinear_interpolation

@param{Number} x

@param{Number} y

@param{Number[]} g00

@param{Number[]} g10

@param{Number[]} g01

@param{Number[]} g11

@returns{Vector}

*/

bilinearInterpolateVector(x:any, y:any, g00:any, g10:any, g01:any, g11:any) {

let rx = 1 - x

let ry = 1 - y

let a = rx * ry

let b = x * ry

let c = rx * y

let d = x * y

let u = g00.u * a + g10.u * b + g01.u * c + g11.u * d

let v = g00.v * a + g10.v * b + g01.v * c + g11.v * d

return new Vector(u, v)

}

/**

calculate vector value range

/ calculateRange() { if (!this.grid || !this.grid[0]) { return } let rows = this.grid.length let cols = this.grid[0].length // const vectors = []; let min let max // @from:https://stackoverflow.com/questions/13544476/how-to-find-max-and-min-in-array-using-minimum-comparisonsfor (let j = 0; j < rows; j++) { for (let i = 0; i < cols; i++) { let vec = this.grid[j][i] if (vec !== null) { let val = vec.m || vec.magnitude() // vectors.push(); if (min === undefined) { min = val } else if (max === undefined) { max = val // update min max // 1. Pick 2 elements(a, b), compare them. (say a > b) min = Math.min(min, max) max = Math.max(min, max) } else { // 2. Update min by comparing (min, b) // 3. Update max by comparing (max, a) min = Math.min(val, min) max = Math.max(val, max) } } } } return [min, max] } /*

*

@paramx

@private

*/

isValid(x:any) {

return x !== null && x !== undefined

}

getWrappedLongitudes() {

let xmin = this.xmin

let xmax = this.xmax

if (this.wrappedX) {

if (this.isContinuous) {

xmin = -180

xmax = 180

} else {

xmax = this.xmax - 360

xmin = this.xmin - 360

}

}

return [xmin, xmax]

}

contains(lon:any, lat:any) {

let _a = this.getWrappedLongitudes(),

xmin = _a[0],

xmax = _a[1]

let longitudeIn = lon >= xmin && lon <= xmax let latitudeIn if (this.deltaY >= 0) {

latitudeIn = lat >= this.ymin && lat <= this.ymax } else { latitudeIn = lat >= this.ymax && lat <= this.ymin

}

return longitudeIn && latitudeIn

}

/**

*

@parama

@paramn

@returns{number}

*/

floorMod(a:any, n:any) {

return a - n * Math.floor(a / n)

}

/**

*

@paramlon

@paramlat

*/

getDecimalIndexes(lon:any, lat:any) {

let i = this.floorMod(lon - this.xmin, 360) / this.deltaX // calculate longitude index in wrapped range [0, 360)

let j = (this.ymax - lat) / this.deltaY // calculate latitude index in direction +90 to -90

return [i, j]

}

/**

Nearest value at lon-lat coordinates

*

@paramlon

@paramlat

/ valueAt(lon:any, lat:any) { if (!this.contains(lon, lat)) { return null } let indexes = this.getDecimalIndexes(lon, lat) let ii = Math.floor(indexes[0]) let jj = Math.floor(indexes[1]) let ci = this.clampColumnIndex(ii) let cj = this.clampRowIndex(jj) return this.valueAtIndexes(ci, cj) } /*

Get interpolated grid value lon-lat coordinates

@paramlon

@paramlat

*/

interpolatedValueAt(lon:any, lat:any) {

if (!this.contains(lon, lat)) {

return null

}

let _a = this.getDecimalIndexes(lon, lat),

i = _a[0],

j = _a[1]

return this.interpolatePoint(i, j)

}

hasValueAt(lon:any, lat:any) {

let value = this.valueAt(lon, lat)

return value !== null

}

/**

*

@parami

@paramj

/ interpolatePoint(i:any, j:any) { // 1 2 After converting λ and φ to fractional grid indexes i and j, we find the // fi i ci four points 'G' that enclose point (i, j). These points are at the four // | =1.4 | corners specified by the floor and ceiling of i and j. For example, given // ---G--|---G--- fj 8 i = 1.4 and j = 8.3, the four surrounding grid points are (1, 8), (2, 8), // j ___|_ . | (1, 9) and (2, 9). // =8.3 | | // ---G------G--- cj 9 Note that for wrapped grids, the first column is duplicated as the last // | | column, so the index ci can be used without taking a modulo. let indexes = this.getFourSurroundingIndexes(i, j) let fi = indexes[0], ci = indexes[1], fj = indexes[2], cj = indexes[3] let values = this.getFourSurroundingValues(fi, ci, fj, cj) if (values) { let g00 = values[0], g10 = values[1], g01 = values[2], g11 = values[3] //@ts-ignorereturn this.bilinearInterpolateVector(i - fi, j - fj, g00, g10, g01, g11) } return null } /*

Check the column index is inside the field,

adjusting to min or max when needed

@private

@param{Number} ii - index

@returns{Number} i - inside the allowed indexes

*/

clampColumnIndex(ii:any) {

let i = ii

if (ii < 0) { i = 0 } let maxCol = this.cols - 1 if (ii > maxCol) {

i = maxCol

}

return i

}

/**

Check the row index is inside the field,

adjusting to min or max when needed

@private

@param{Number} jj index

@returns{Number} j - inside the allowed indexes

*/

clampRowIndex(jj:any) {

let j = jj

if (jj < 0) { j = 0 } let maxRow = this.rows - 1 if (jj > maxRow) {

j = maxRow

}

return j

}

/**

from:https://github.com/IHCantabria/Leaflet.CanvasLayer.Field/blob/master/src/Field.js#L252

@private

@param{Number} i - decimal index

@param{Number} j - decimal index

@returns{Array} [fi, ci, fj, cj]

*/

getFourSurroundingIndexes(i:any, j:any) {

let fi = Math.floor(i) // 左

let ci = fi + 1 // 右

// duplicate colum to simplify interpolation logic (wrapped value)

if (this.isContinuous && ci >= this.cols) {

ci = 0

}

ci = this.clampColumnIndex(ci)

let fj = this.clampRowIndex(Math.floor(j)) // 上 緯度方向索引(取整)

let cj = this.clampRowIndex(fj + 1) // 下

return [fi, ci, fj, cj]

}

/**

fromhttps://github.com/IHCantabria/Leaflet.CanvasLayer.Field/blob/master/src/Field.js#L277

Get four surrounding values or null if not available,

from 4 integer indexes

@private

@param{Number} fi

@param{Number} ci

@param{Number} fj

@param{Number} cj

@returns{Array}

*/

getFourSurroundingValues(fi:any, ci:any, fj:any, cj:any) {

let row

if ((row = this.grid[fj])) {

let g00 = row[fi] // << left let g10 = row[ci] // right >>

if (this.isValid(g00) && this.isValid(g10) && (row = this.grid[cj])) {

// lower row vv

let g01 = row[fi] // << left let g11 = row[ci] // right >>

if (this.isValid(g01) && this.isValid(g11)) {

return [g00, g10, g01, g11] // 4 values found!

}

}

}

return null

}

/**

Value for grid indexes

@param{Number} i - column index (integer)

@param{Number} j - row index (integer)

@returns{Vector|Number}

*/

valueAtIndexes(i:any, j:any) {

return this.grid[j][i] // <-- j,i !!

}

/**

Lon-Lat for grid indexes

@param{Number} i - column index (integer)

@param{Number} j - row index (integer)

@returns{Number[]} [lon, lat]

*/

lonLatAtIndexes(i:any, j:any) {

let lon = this.longitudeAtX(i)

?更多參考?https://xiaozhuanlan.com/topic/1648735092

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酝蜒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贱傀,更是在濱河造成了極大的恐慌跑芳,老刑警劉巖亏较,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袄友,死亡現(xiàn)場(chǎng)離奇詭異捉貌,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暖侨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門椭住,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人字逗,你說我怎么就攤上這事京郑。” “怎么了葫掉?”我有些...
    開封第一講書人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵些举,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我俭厚,道長(zhǎng)户魏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任套腹,我火速辦了婚禮绪抛,結(jié)果婚禮上资铡,老公的妹妹穿的比我還像新娘电禀。我一直安慰自己,他們只是感情好笤休,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開白布尖飞。 她就那樣靜靜地躺著,像睡著了一般店雅。 火紅的嫁衣襯著肌膚如雪政基。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,821評(píng)論 1 314
  • 那天闹啦,我揣著相機(jī)與錄音沮明,去河邊找鬼。 笑死窍奋,一個(gè)胖子當(dāng)著我的面吹牛荐健,可吹牛的內(nèi)容都是我干的酱畅。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼江场,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼纺酸!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起址否,我...
    開封第一講書人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤餐蔬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后佑附,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體樊诺,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年帮匾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了啄骇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瘟斜,死狀恐怖缸夹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情螺句,我是刑警寧澤虽惭,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蛇尚,受9級(jí)特大地震影響芽唇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜取劫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一匆笤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧谱邪,春花似錦炮捧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扯俱,卻和暖如春书蚪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迅栅。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工殊校, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人读存。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓为流,卻偏偏與公主長(zhǎng)得像窜醉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艺谆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容