utils/PlainSegmentWorker.worker.jsjavascript
"use strict";
let model = null;
let cached_ix = null;
let cached_iy = null;
let v00 = null;
let v01 = null;
let v10 = null;
let v11 = null;
//let t = null;
function rawval(ix, iy) {
if (iy < 0) {
iy = -iy;
ix += model.width / 2;
} else if (iy >= model.height) {
iy = 2 * (model.height - 1) - iy;
ix += model.width / 2;
}
if (ix < 0) {
ix += model.width;
} else if (ix >= model.width) {
ix -= model.width;
}
var k = (iy * model.width + ix) * 2 + model.i;
return (model.rawfile[k] << 8) | model.rawfile[k + 1];
}
function getHeightMSL(lon, lat) {
if (!model) return 0;
if (lon < 0) lon += 360.0;
var fy = (90 - lat) * model.rlatres;
var fx = lon * model.rlonres;
var iy = Math.floor(fy);
var ix = Math.floor(fx);
fx -= ix;
fy -= iy;
if (iy === model.height - 1) {
iy--;
}
if (cached_ix !== ix || cached_iy !== iy) {
cached_ix = ix;
cached_iy = iy;
v00 = rawval(ix, iy);
v01 = rawval(ix + 1, iy);
v10 = rawval(ix, iy + 1);
v11 = rawval(ix + 1, iy + 1);
}
let h = null;
var a = (1 - fx) * v00 + fx * v01;
var b = (1 - fx) * v10 + fx * v11;
h = (1 - fy) * a + fy * b;
return model.offset + model.scale * h;
}
const HALF_PI = Math.PI * 0.5;
const POLE = 20037508.34;
const PI_BY_POLE = Math.PI / POLE;
const INV_POLE_BY_180 = 180.0 / POLE;
const INV_PI_BY_180 = 180.0 / Math.PI;
const INV_PI_BY_180_HALF_PI = INV_PI_BY_180 * HALF_PI;
const RADIANS = Math.PI / 180.0;
const INV_PI_BY_360 = INV_PI_BY_180 * 2.0;
let E2 = 0.0,
A = 0.0;
let _projFunc = null;
const Vec3 = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
var geodeticToCartesian = function (lon, lat, heightFactor, res) {
let h = getHeightMSL(lon, lat) * heightFactor;
let latrad = RADIANS * lat,
lonrad = RADIANS * lon;
let slt = Math.sin(latrad);
let N = A / Math.sqrt(1.0 - E2 * slt * slt);
let nc = (N + h) * Math.cos(latrad);
res.x = nc * Math.cos(lonrad);
res.y = nc * Math.sin(lonrad);
res.z = (N * (1 - E2) + h) * slt;
};
var geodeticToCartesianInverse = function (lon, lat, heightFactor, res) {
geodeticToCartesian(
lon * INV_POLE_BY_180,
INV_PI_BY_360 * Math.atan(Math.exp(lat * PI_BY_POLE)) - INV_PI_BY_180_HALF_PI,
heightFactor,
res
);
};
var worldPos = new Vec3(0.0, 0.0, 0.0);
var rtcPos = new Vec3(0.0, 0.0, 0.0);
var _tempHigh = new Vec3(0.0, 0.0, 0.0);
var _tempLow = new Vec3(0.0, 0.0, 0.0);
var doubleToTwoFloats = function (v, high, low) {
let x = v.x,
y = v.y,
z = v.z;
var doubleHigh;
if (x >= 0.0) {
doubleHigh = Math.floor(x / 65536.0) * 65536.0;
high.x = Math.fround(doubleHigh);
low.x = Math.fround(x - doubleHigh);
} else {
doubleHigh = Math.floor(-x / 65536.0) * 65536.0;
high.x = Math.fround(-doubleHigh);
low.x = Math.fround(x + doubleHigh);
}
if (y >= 0.0) {
doubleHigh = Math.floor(y / 65536.0) * 65536.0;
high.y = Math.fround(doubleHigh);
low.y = Math.fround(y - doubleHigh);
} else {
doubleHigh = Math.floor(-y / 65536.0) * 65536.0;
high.y = Math.fround(-doubleHigh);
low.y = Math.fround(y + doubleHigh);
}
if (z >= 0.0) {
doubleHigh = Math.floor(z / 65536.0) * 65536.0;
high.z = Math.fround(doubleHigh);
low.z = Math.fround(z - doubleHigh);
} else {
doubleHigh = Math.floor(-z / 65536.0) * 65536.0;
high.z = Math.fround(-doubleHigh);
low.z = Math.fround(z + doubleHigh);
}
};
self.onmessage = function (msg) {
if (msg.data.model) {
model = msg.data.model;
model.rawfile = msg.data.rawfile;
} else if (msg.data.params) {
let rtc_x = msg.data.params[14];
let rtc_y = msg.data.params[15];
let rtc_z = msg.data.params[16];
let xmin = 549755748352.0,
xmax = -549755748352.0,
ymin = 549755748352.0,
ymax = -549755748352.0,
zmin = 549755748352.0,
zmax = -549755748352.0;
E2 = msg.data.params[8];
A = msg.data.params[9];
let gridSize = msg.data.params[2],
fgs = msg.data.params[3],
r2_x = msg.data.params[10],
r2_y = msg.data.params[11],
r2_z = msg.data.params[12];
let heightFactor = msg.data.params[13];
if (msg.data.params[1] === 0.0) {
_projFunc = geodeticToCartesianInverse;
} else {
_projFunc = geodeticToCartesian;
}
let maxFgs = Math.max(fgs, gridSize);
let llStep = (msg.data.params[6] - msg.data.params[4]) / maxFgs;
let ltStep = (msg.data.params[7] - msg.data.params[5]) / maxFgs;
let esw_lon = msg.data.params[4],
ene_lat = msg.data.params[7];
let dg = Math.max(fgs / gridSize, 1.0),
gs = maxFgs + 1;
const gsgs = gs * gs;
const gridSize3 = (gridSize + 1) * (gridSize + 1) * 3;
let plainNormals = new Float32Array(gridSize3);
let plainVertices = new Float64Array(gridSize3);
let plainVerticesHigh = new Float32Array(gridSize3);
let plainVerticesLow = new Float32Array(gridSize3);
let normalMapNormals = new Float32Array(gsgs * 3);
let normalMapVertices = new Float64Array(gsgs * 3);
let ind = 0,
nmInd = 0;
for (let k = 0; k < gsgs; k++) {
let j = k % gs,
i = ~~(k / gs);
_projFunc(esw_lon + j * llStep, ene_lat - i * ltStep, heightFactor, worldPos);
let nx = worldPos.x * r2_x,
ny = worldPos.y * r2_y,
nz = worldPos.z * r2_z;
let l = 1.0 / Math.sqrt(nx * nx + ny * ny + nz * nz);
let nxl = nx * l,
nyl = ny * l,
nzl = nz * l;
rtcPos.x = worldPos.x - rtc_x;
rtcPos.y = worldPos.y - rtc_y;
rtcPos.z = worldPos.z - rtc_z;
normalMapVertices[nmInd] = rtcPos.x;
normalMapNormals[nmInd++] = nxl;
normalMapVertices[nmInd] = rtcPos.y;
normalMapNormals[nmInd++] = nyl;
normalMapVertices[nmInd] = rtcPos.z;
normalMapNormals[nmInd++] = nzl;
if (i % dg === 0 && j % dg === 0) {
doubleToTwoFloats(rtcPos, _tempHigh, _tempLow);
plainVertices[ind] = rtcPos.x;
plainVerticesHigh[ind] = _tempHigh.x;
plainVerticesLow[ind] = _tempLow.x;
plainNormals[ind++] = nxl;
plainVertices[ind] = rtcPos.y;
plainVerticesHigh[ind] = _tempHigh.y;
plainVerticesLow[ind] = _tempLow.y;
plainNormals[ind++] = nyl;
plainVertices[ind] = rtcPos.z;
plainVerticesHigh[ind] = _tempHigh.z;
plainVerticesLow[ind] = _tempLow.z;
plainNormals[ind++] = nzl;
if (worldPos.x < xmin) xmin = worldPos.x;
if (worldPos.x > xmax) xmax = worldPos.x;
if (worldPos.y < ymin) ymin = worldPos.y;
if (worldPos.y > ymax) ymax = worldPos.y;
if (worldPos.z < zmin) zmin = worldPos.z;
if (worldPos.z > zmax) zmax = worldPos.z;
}
}
let x = (xmax - xmin) * 0.5,
y = (ymax - ymin) * 0.5,
z = (zmax - zmin) * 0.5;
let plainRadius = Math.sqrt(x * x + y * y + z * z);
self.postMessage(
{
id: msg.data.params[0],
plainVertices: plainVertices,
plainVerticesHigh: plainVerticesHigh,
plainVerticesLow: plainVerticesLow,
plainNormals: plainNormals,
normalMapNormals: normalMapNormals,
normalMapVertices: normalMapVertices,
plainRadius: plainRadius,
relativeCenter: [rtc_x, rtc_y, rtc_z]
},
[
plainVertices.buffer,
plainVerticesHigh.buffer,
plainVerticesLow.buffer,
plainNormals.buffer,
normalMapNormals.buffer,
normalMapVertices.buffer
]
);
}
};