@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
119 lines (118 loc) • 3.86 kB
JavaScript
;
import { Vector3, Matrix4 } from "three";
import { CoreMapboxConstants } from "./Constants";
const Constants = CoreMapboxConstants;
export class CoreMapboxUtils {
static verticalNearLngLatPoints(map) {
const canvas = map.getCanvas();
const x = canvas.clientWidth;
const y = canvas.clientHeight;
return [map.unproject([0, y]), map.unproject([x, y])];
}
static verticalFarLngLatPoints(map) {
const canvas = map.getCanvas();
const x = canvas.clientWidth;
const y = 0;
return [map.unproject([0, y]), map.unproject([x, y])];
}
static horizontalLngLatPoints(map) {
const canvas = map.getCanvas();
const y = canvas.clientHeight / 2;
return [map.unproject([0, y]), map.unproject([100, y])];
}
static makePerspectiveMatrix(fovy, aspect, near, far) {
const out = new Matrix4();
const f = 1 / Math.tan(fovy / 2);
const nf = 1 / (near - far);
const newMatrix = [
f / aspect,
0,
0,
0,
0,
f,
0,
0,
0,
0,
(far + near) * nf,
-1,
0,
0,
2 * far * near * nf,
0
];
out.elements = newMatrix;
return out;
}
// #gimme radians
// function radify(deg){
// if (typeof deg === 'object'){
// return deg.map(function(degree){
// return Math.PI*2*degree/360
// })
// }
// else return Math.PI*2*deg/360
// }
// #gimme degrees
// function degreeify(rad){
// return 360*rad/(Math.PI*2)
// }
static projectToWorld(lnglat) {
const projected = [
-Constants.MERCATOR_A * lnglat[0] * Constants.DEG2RAD * Constants.PROJECTION_WORLD_SIZE,
-Constants.MERCATOR_A * Math.log(Math.tan(Math.PI * 0.25 + 0.5 * lnglat[1] * Constants.DEG2RAD)) * Constants.PROJECTION_WORLD_SIZE
];
const pixelsPerMeter = this.projectedUnitsPerMeter(lnglat[1]);
let height = lnglat[2];
if (height == null) {
height = 0;
}
projected.push(height * pixelsPerMeter);
return new Vector3(projected[0], projected[1], projected[2]);
}
static projectedUnitsPerMeter(latitude) {
return Math.abs(
Constants.WORLD_SIZE * (1 / Math.cos(latitude * Math.PI / 180)) / Constants.EARTH_CIRCUMFERENCE
);
}
static fromLL(lon, lat) {
const extent = 2003750834e-2;
const x = lon * extent / 180;
let y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
y = y * extent / 180;
return [(x + extent) / (2 * extent), 1 - (y + extent) / (2 * extent)];
}
static fromLLv(position) {
const ll = this.fromLL(position.x, position.z);
return new Vector3(ll[0], position.y, ll[1]);
}
// https://github.com/mapbox/mapbox-gl-js/blob/5bebe1cd725e9af0c6be25928bdbde468bebdf61/src/ui/control/scale_control.js#L61-L127
static get_distance(latlng1, latlng2) {
const R = 6371e3;
const rad = Math.PI / 180, lat1 = latlng1.lat * rad, lat2 = latlng2.lat * rad, a = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos((latlng2.lng - latlng1.lng) * rad);
const maxMeters = R * Math.acos(Math.min(a, 1));
return maxMeters;
}
// https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#Lon..2Flat._to_tile_numbers_3
static lnglatToTileNumber(latDeg, lngDeg, zoom) {
const latRad = latDeg / 180 * Math.PI;
const n = 2 ** zoom;
const x = Math.floor((lngDeg + 180) / 360 * n);
const y = Math.floor((1 - Math.log(Math.tan(latRad) + 1 / Math.cos(latRad)) / Math.PI) / 2 * n);
return {
x,
y
};
}
static tile_number_to_lnglat(xtile, ytile, zoom) {
const n = 2 ** zoom;
const lon_deg = xtile / n * 360 - 180;
const lat_rad = Math.atan(Math.sinh(Math.PI * (1 - 2 * ytile / n)));
const lat_deg = 180 * (lat_rad / Math.PI);
return {
lat: lat_deg,
lng: lon_deg
};
}
}