UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

278 lines (237 loc) 8.99 kB
import { geometry as g } from '@progress/kendo-drawing'; import { Class, setDefaultOptions, limitValue, rad, deg, deepExtend } from '../common'; import { Location } from './location'; import { datums } from './datums'; var math = Math, atan = math.atan, exp = math.exp, pow = math.pow, sin = math.sin, log = math.log, tan = math.tan, Point = g.Point; var PI = math.PI, PI_DIV_2 = PI / 2, PI_DIV_4 = PI / 4, DEG_TO_RAD = PI / 180; var WGS84 = datums.WGS84; // WGS 84 / World Mercator export var Mercator = (function (Class) { function Mercator(options) { Class.call(this); this.initProperties(); this._initOptions(options); } if ( Class ) Mercator.__proto__ = Class; Mercator.prototype = Object.create( Class && Class.prototype ); Mercator.prototype.constructor = Mercator; Mercator.prototype._initOptions = function _initOptions (options) { this.options = deepExtend({}, this.options, options); }; Mercator.prototype.initProperties = function initProperties () { // super.initProperties(); deepExtend(this, { MAX_LNG: 180, MAX_LAT: 85.0840590501, INVERSE_ITERATIONS: 15, INVERSE_CONVERGENCE: 1e-12 }); }; Mercator.prototype.forward = function forward (loc, clamp) { var proj = this, options = proj.options, datum = options.datum, r = datum.a, lng0 = options.centralMeridian, lat = limitValue(loc.lat, -proj.MAX_LAT, proj.MAX_LAT), lng = clamp ? limitValue(loc.lng, -proj.MAX_LNG, proj.MAX_LNG) : loc.lng, x = rad(lng - lng0) * r, y = proj._projectLat(lat); return new Point(x, y); }; Mercator.prototype._projectLat = function _projectLat (lat) { var datum = this.options.datum, ecc = datum.e, r = datum.a, y = rad(lat), ts = tan(PI_DIV_4 + y / 2), con = ecc * sin(y), p = pow((1 - con) / (1 + con), ecc / 2); // See: http://en.wikipedia.org/wiki/Mercator_projection#Generalization_to_the_ellipsoid return r * log(ts * p); }; Mercator.prototype.inverse = function inverse (point, clamp) { var proj = this, options = proj.options, datum = options.datum, r = datum.a, lng0 = options.centralMeridian, lng = point.x / (DEG_TO_RAD * r) + lng0, lat = limitValue(proj._inverseY(point.y), -proj.MAX_LAT, proj.MAX_LAT); if (clamp) { lng = limitValue(lng, -proj.MAX_LNG, proj.MAX_LNG); } return new Location(lat, lng); }; Mercator.prototype._inverseY = function _inverseY (y) { var proj = this, datum = proj.options.datum, r = datum.a, ecc = datum.e, ecch = ecc / 2, ts = exp(-y / r), phi = PI_DIV_2 - 2 * atan(ts), i; for (i = 0; i <= proj.INVERSE_ITERATIONS; i++) { var con = ecc * sin(phi), p = pow((1 - con) / (1 + con), ecch), dphi = PI_DIV_2 - 2 * atan(ts * p) - phi; phi += dphi; if (math.abs(dphi) <= proj.INVERSE_CONVERGENCE) { break; } } return deg(phi); }; return Mercator; }(Class)); setDefaultOptions(Mercator, { centralMeridian: 0, datum: WGS84 }); // WGS 84 / Pseudo-Mercator // Used by Google Maps, Bing, OSM, etc. // Spherical projection of ellipsoidal coordinates. export var SphericalMercator = (function (Mercator) { function SphericalMercator () { Mercator.apply(this, arguments); } if ( Mercator ) SphericalMercator.__proto__ = Mercator; SphericalMercator.prototype = Object.create( Mercator && Mercator.prototype ); SphericalMercator.prototype.constructor = SphericalMercator; SphericalMercator.prototype.initProperties = function initProperties () { Mercator.prototype.initProperties.call(this); deepExtend(this, { MAX_LAT: 85.0511287798 }); }; SphericalMercator.prototype._projectLat = function _projectLat (lat) { var r = this.options.datum.a, y = rad(lat), ts = tan(PI_DIV_4 + y / 2); return r * log(ts); }; SphericalMercator.prototype._inverseY = function _inverseY (y) { var r = this.options.datum.a, ts = exp(-y / r); return deg(PI_DIV_2 - 2 * atan(ts)); }; return SphericalMercator; }(Mercator)); export var Equirectangular = (function (Class) { function Equirectangular () { Class.apply(this, arguments); } if ( Class ) Equirectangular.__proto__ = Class; Equirectangular.prototype = Object.create( Class && Class.prototype ); Equirectangular.prototype.constructor = Equirectangular; Equirectangular.prototype.forward = function forward (loc) { return new Point(loc.lng, loc.lat); }; Equirectangular.prototype.inverse = function inverse (point) { return new Location(point.y, point.x); }; return Equirectangular; }(Class)); // This is the projected coordinate system used for rendering maps in Google Maps, OpenStreetMap, etc // Unit: metre // Geodetic CRS: WGS 84 // Scope: Certain Web mapping and visualisation applications. It is not a recognised geodetic system: for that see ellipsoidal Mercator CRS code 3395 (WGS 84 / World Mercator). // Remarks: Uses spherical development of ellipsoidal coordinates. Relative to WGS 84 / World Mercator (CRS code 3395) errors of 0.7 percent in scale and differences in northing of up to 43km in the map (equivalent to 21km on the ground) may arise. // Area of use: World between 85.06°S and 85.06°N. // Coordinate system: Cartesian 2D CS. Axes: easting, northing (X,Y). Orientations: east, north. UoM: m. // https://epsg.io/3857 export var EPSG3857 = (function (Class) { function EPSG3857() { Class.call(this); var crs = this, proj = crs._proj = new SphericalMercator(); var c = this.c = 2 * PI * proj.options.datum.a; // transfrom matrix // Scale circumference to 1, mirror Y and shift origin to top left this._tm = g.transform().translate(0.5, 0.5).scale(1 / c, -1 / c); // Inverse transform matrix this._itm = g.transform().scale(c, -c).translate(-0.5, -0.5); } if ( Class ) EPSG3857.__proto__ = Class; EPSG3857.prototype = Object.create( Class && Class.prototype ); EPSG3857.prototype.constructor = EPSG3857; // Location <-> Point (screen coordinates for a given scale) EPSG3857.prototype.toPoint = function toPoint (loc, scale, clamp) { var point = this._proj.forward(loc, clamp); return point.transform(this._tm).scale(scale || 1); }; EPSG3857.prototype.toLocation = function toLocation (point, scale, clamp) { var newPoint = point.clone().scale(1 / (scale || 1)).transform(this._itm); return this._proj.inverse(newPoint, clamp); }; return EPSG3857; }(Class)); // Unit: metre // Geodetic CRS: WGS 84 // Scope: Very small scale mapping. // Remarks: Euro-centric view of world excluding polar areas. // Area of use: World between 80°S and 84°N. // Coordinate system: Cartesian 2D CS. Axes: easting, northing (E,N). Orientations: east, north. UoM: m. // https://epsg.io/3395 export var EPSG3395 = (function (Class) { function EPSG3395() { Class.call(this); this._proj = new Mercator(); } if ( Class ) EPSG3395.__proto__ = Class; EPSG3395.prototype = Object.create( Class && Class.prototype ); EPSG3395.prototype.constructor = EPSG3395; EPSG3395.prototype.toPoint = function toPoint (loc) { return this._proj.forward(loc); }; EPSG3395.prototype.toLocation = function toLocation (point) { return this._proj.inverse(point); }; return EPSG3395; }(Class)); // Unit: degree // Geodetic CRS: WGS 84 // Scope: Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying. // Area of use: World. // Coordinate system: Ellipsoidal 2D CS. Axes: latitude, longitude. Orientations: north, east. UoM: degree // https://epsg.io/4326 export var EPSG4326 = (function (Class) { function EPSG4326() { Class.call(this); this._proj = new Equirectangular(); } if ( Class ) EPSG4326.__proto__ = Class; EPSG4326.prototype = Object.create( Class && Class.prototype ); EPSG4326.prototype.constructor = EPSG4326; EPSG4326.prototype.toPoint = function toPoint (loc) { return this._proj.forward(loc); }; EPSG4326.prototype.toLocation = function toLocation (point) { return this._proj.inverse(point); }; return EPSG4326; }(Class));