js/Mobilizing/input/GPSUtils.js
import * as _Math from '../core/util/Math';
const _STATICS = {};
_STATICS.zoom = 1;
_STATICS.worldSize = 512 * (Math.pow(2, _STATICS.zoom));
/**
* Some GPS coordinates convertion tools to use maps in Mobilizing.js
*/
export default class GPSUtils {
/**
* Converts longitude and latitude coords (from an OpenStreetMap map) into absolute pixels coords. This method don't calculate the pixels coords within a given map bound's! Use getCoordinateInMap for this.
* @static
*
* @param {Number} longitute longitute
* @param {Number} latitude latitude
* @param {Number} zoom the zoom factor fo this map
*/
static getPixelsCoordsFromOSMLngLat(longitute, latitude, zoom) {
if (zoom) {
_STATICS.zoom = zoom;
_STATICS.worldSize = 512 * (Math.pow(2, _STATICS.zoom));
}
return { x: GPSUtils.lngX(longitute), y: GPSUtils.latY(latitude) };
}
/**
* Compute GPS coordinates into pixels x, y coordinates in a map. Here, we adopt the OSM standard for mappinp. Therefore, you should generate your bitmap earth map with a tool using OSM tiles (like MapBox, TileMill). You should give the zoom factor and the map bounds (in lognititude and latitude) to this method for the calculation to be effective
* @static
*
* @param {Number} longitute
* @param {Number} latitude
* @param {Number} zoom zoom factor fo this map
* @param {Array} mapCoord MapBox/TileMill map coords array, like [-180,-85.0511,180,85.0511]
* @param {Number} mapWidth the map width in pixels
* @param {Number} mapHeight the map height in pixels
*/
static getCoordinateInMap(longitute, latitude, mapCoord, mapWidth, mapHeight, zoom) {
if (zoom) {
_STATICS.zoom = zoom;
}
//construct local variable to simplify expressions writing
const leftLong = mapCoord[0];
const bottomLat = mapCoord[1];
const rightLong = mapCoord[2];
const topLat = mapCoord[3];
//construct the corners pixel coordinates
const topRight = GPSUtils.getPixelsCoordsFromOSMLngLat(rightLong, topLat);
const topLeft = GPSUtils.getPixelsCoordsFromOSMLngLat(leftLong, topLat);
const bottomRight = GPSUtils.getPixelsCoordsFromOSMLngLat(rightLong, bottomLat);
// let bottomLeft = GPSUtils.getPixelsCoordsFromOSMLngLat(leftLong, bottomLat);
const absCoord = GPSUtils.getPixelsCoordsFromOSMLngLat(longitute, latitude);
const coords = {
x: _Math.map(absCoord.x, topRight.x, topLeft.x, mapWidth / 2, -mapHeight / 2),
y: _Math.map(absCoord.y, topRight.y, bottomRight.y, mapWidth / 2, -mapHeight / 2)
};
return coords;
}
/**
* latitude to absolute x coord
* @static
*
* @param {Number} lon
* @return {Number} pixel coordinate
*/
static lngX(lng) {
return (180 + lng) * _STATICS.worldSize / 360;
}
/**
* latitude to absolute y coord
* @static
* @method latY
* @param {Number} lat
* @return {Number} pixel coordinate
*/
static latY(lat) {
const y = 180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
return (180 - y) * _STATICS.worldSize / 360;
}
static xLng(x) {
return x * 360 / _STATICS.worldSize - 180;
}
static yLat(y) {
const y2 = 180 - y * 360 / _STATICS.worldSize;
return 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90;
}
/**
* Convert GPS coords to cartesian coords. NB : this algorithm is adapted to three.js geoms!
* @static
*
* @param {Number} longitude
* @param {Number} latitude
* @param {Number} radius
* @return {Object} {x, y, z} coordinates
*/
static getPolarFromLngLat(longitude, latitude, radius) {
const lng = _Math.degToRad(longitude + 180);
const lat = _Math.degToRad(90 - latitude);
const x = -(radius * Math.cos(lng) * Math.sin(lat));
const y = radius * Math.cos(lat);
const z = radius * Math.sin(lat) * Math.sin(lng);
return { x, y, z };
}
}