-
Notifications
You must be signed in to change notification settings - Fork 372
/
EarthGravityModel1996.js
136 lines (117 loc) · 4.14 KB
/
EarthGravityModel1996.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
"use strict";
/*global require,Int16Array,Uint8Array,Int16Array*/
var CesiumMath = require("terriajs-cesium/Source/Core/Math").default;
var defined = require("terriajs-cesium/Source/Core/defined").default;
var loadArrayBuffer = require("../Core/loadArrayBuffer");
var when = require("terriajs-cesium/Source/ThirdParty/when").default;
/**
* The Earth Gravity Model 1996 (EGM96) geoid.
* @param {String} gridFileUrl The URL of the WW15MGH.DAC file.
*/
var EarthGravityModel1996 = function(gridFileUrl) {
this.gridFileUrl = gridFileUrl;
this.data = undefined;
// These values were determined by inspecting the WW15MGH.DAC file. We hard-code them here because
// we need them available before that file finishes loading.
this.minimumHeight = -106.99;
this.maximumHeight = 85.39;
};
/**
* Determines if this class will work in the current environment. It will return false on older browsers without support
* for typed arrays.
* @return {Boolean} True if this class may be used in this environment; otherwise, false.
*/
EarthGravityModel1996.isSupported = function() {
return typeof Int16Array !== "undefined" && typeof Uint8Array !== "undefined";
};
/**
* Gets the height of EGM96 above the surface of the ellipsoid.
* @param {String} baseUrl The base URL for TerriaJS resources.
* @param {Number} longitude The longitude.
* @param {Number} latitude The latitude
* @return {Promise|Number} A promise, that, when it results The height of mean sea level above the ellipsoid at the specified location. Negative numbers indicate that mean sea level
* is below the ellipsoid.
*/
EarthGravityModel1996.prototype.getHeight = function(longitude, latitude) {
return getHeightData(this).then(function(data) {
return getHeightFromData(data, longitude, latitude);
});
};
EarthGravityModel1996.prototype.getHeights = function(cartographicArray) {
return getHeightData(this).then(function(data) {
for (var i = 0; i < cartographicArray.length; ++i) {
var cartographic = cartographicArray[i];
cartographic.height = getHeightFromData(
data,
cartographic.longitude,
cartographic.latitude
);
}
return cartographicArray;
});
};
function getHeightData(model) {
if (!defined(model.data)) {
model.data = loadArrayBuffer(model.gridFileUrl);
}
return when(model.data, function(data) {
if (!(model.data instanceof Int16Array)) {
// Data file is big-endian, all relevant platforms are little endian, so swap the byte order.
var byteView = new Uint8Array(data);
for (var k = 0; k < byteView.length; k += 2) {
var tmp = byteView[k];
byteView[k] = byteView[k + 1];
byteView[k + 1] = tmp;
}
model.data = new Int16Array(data);
}
return model.data;
});
}
function getHeightFromData(data, longitude, latitude) {
var recordIndex = (720 * (CesiumMath.PI_OVER_TWO - latitude)) / Math.PI;
if (recordIndex < 0) {
recordIndex = 0;
} else if (recordIndex > 720) {
recordIndex = 720;
}
longitude = CesiumMath.zeroToTwoPi(longitude);
var heightIndex = (1440 * longitude) / CesiumMath.TWO_PI;
if (heightIndex < 0) {
heightIndex = 0;
} else if (heightIndex > 1440) {
heightIndex = 1440;
}
var i = heightIndex | 0;
var j = recordIndex | 0;
var xMinusX1 = heightIndex - i;
var yMinusY1 = recordIndex - j;
var x2MinusX = 1.0 - xMinusX1;
var y2MinusY = 1.0 - yMinusY1;
var f11 = getHeightValue(data, j, i);
var f21 = getHeightValue(data, j, i + 1);
var f12 = getHeightValue(data, j + 1, i);
var f22 = getHeightValue(data, j + 1, i + 1);
return (
(f11 * x2MinusX * y2MinusY +
f21 * xMinusX1 * y2MinusY +
f12 * x2MinusX * yMinusY1 +
f22 * xMinusX1 * yMinusY1) /
100.0
);
}
// Heights returned by this function are in centimeters.
function getHeightValue(data, recordIndex, heightIndex) {
if (recordIndex > 720) {
recordIndex = 720;
} else if (recordIndex < 0) {
recordIndex = 0;
}
if (heightIndex > 1439) {
heightIndex -= 1440;
} else if (heightIndex < 0) {
heightIndex += 1440;
}
return data[recordIndex * 1440 + heightIndex];
}
module.exports = EarthGravityModel1996;