UNPKG

e-civ-planet

Version:

A WebGL virtual globe and map engine based on webglobe

1,267 lines (1,243 loc) 375 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["e-civ-planet"] = factory(); else root["e-civ-planet"] = factory(); })(this, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ exports: {}, /******/ id: moduleId, /******/ loaded: false /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.loaded = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(0); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Kernel_1 = __webpack_require__(1); var Utils_1 = __webpack_require__(2); var Renderer_1 = __webpack_require__(3); var Camera_1 = __webpack_require__(4); var Scene_1 = __webpack_require__(15); var Image_1 = __webpack_require__(17); var EventHandler_1 = __webpack_require__(18); var Google_1 = __webpack_require__(19); var Atmosphere_1 = __webpack_require__(35); var LocationGraphic_1 = __webpack_require__(38); var PoiLayer_1 = __webpack_require__(42); var RouteLayer_1 = __webpack_require__(45); var Extent_1 = __webpack_require__(14); var Service_1 = __webpack_require__(43); var initLevel = Utils_1.default.isMobile() ? 11 : 3; var initLonlat = [116.3975, 39.9085]; var GlobeOptions = (function () { function GlobeOptions() { this.pauseRendering = false; this.satellite = true; this.level = 'auto'; this.lonlat = 'auto'; this.key = ""; } return GlobeOptions; }()); exports.GlobeOptions = GlobeOptions; var Globe = (function () { function Globe(canvas, options) { var _this = this; this.canvas = canvas; this.options = options; this.renderer = null; this.scene = null; this.camera = null; this.tiledLayer = null; this.labelLayer = null; this.poiLayer = null; this.routeLayer = null; this.locationGraphic = null; this.debugStopRefreshTiles = false; this.REFRESH_INTERVAL = 150; this.lastRefreshTimestamp = -1; this.lastRefreshCameraCore = null; this.eventHandler = null; this.allRefreshCount = 0; this.realRefreshCount = 0; this.afterRenderCallbacks = []; this.gl = null; if (!this.options) { this.options = new GlobeOptions(); } this.renderer = new Renderer_1.default(canvas, this._onBeforeRender.bind(this), this._onAfterRender.bind(this)); this.gl = this.renderer.gl; this.scene = new Scene_1.default(); var radio = canvas.width / canvas.height; var level = this.options.level >= 0 ? this.options.level : initLevel; var lonlat = (this.options.lonlat && this.options.lonlat.length === 2) ? this.options.lonlat : initLonlat; this.camera = new Camera_1.default(canvas, 30, radio, 1, Kernel_1.default.EARTH_RADIUS * 2, level, lonlat, options.resolutionFactor); this.renderer.setScene(this.scene); this.renderer.setCamera(this.camera); this._setTiledLayer(new Google_1.GoogleTiledLayer("Road"), this.options.pauseRendering); var atmosphere = Atmosphere_1.default.getInstance(); this.scene.add(atmosphere); this.routeLayer = RouteLayer_1.default.getInstance(this.camera, this.options.key); this.scene.add(this.routeLayer); this.poiLayer = PoiLayer_1.default.getInstance(); this.poiLayer.globe = this; this.scene.add(this.poiLayer); this.locationGraphic = LocationGraphic_1.default.getInstance(this); this.scene.add(this.locationGraphic); this.eventHandler = new EventHandler_1.default(this); if (this.options.pauseRendering !== true) { this.renderer.resumeRendering(); } var locationCallback = function (location) { if (location) { _this.afterRenderCallbacks.push(function () { _this.updateUserLocation(location); }); } }; Service_1.default.getCurrentPosition().then(locationCallback); } Globe.getInstance = function (options) { if (!this.globe) { var canvas = document.createElement("canvas"); canvas.width = document.documentElement.clientWidth; canvas.height = document.documentElement.clientHeight; this.globe = new Globe(canvas, options); } return this.globe; }; Globe.prototype.placeAt = function (container) { if (this.canvas.parentNode) { if (this.canvas.parentNode !== container) { container.appendChild(this.canvas); } } else { container.appendChild(this.canvas); } }; Globe.prototype.resize = function (width, height) { this.canvas.width = width; this.canvas.height = height; this.camera.setAspect(this.canvas.width / this.canvas.height); Utils_1.default.publish("extent-change"); }; Globe.prototype.updateUserLocation = function (location) { this.locationGraphic.setLonLat(location.lon, location.lat); var _a = this.camera.getLonlat(), lon = _a[0], lat = _a[1]; if (this.options.lonlat === 'auto') { lon = location.lon; lat = location.lat; } var level = this.getLevel(); if (this.options.level === 'auto') { level = 8; if (location.accuracy <= 100) { level = 16; } else if (location.accuracy <= 1000) { level = 13; } else { level = 11; } } this.centerTo(lon, lat, level); }; Globe.prototype.showPositions = function (positions) { this.poiLayer.showMapPositions(positions); }; Globe.prototype.getLonlat = function () { return this.camera.getLonlat(); }; Globe.prototype.isRenderingPaused = function () { return this.renderer.isRenderingPaused(); }; Globe.prototype.pauseRendering = function () { this.renderer.pauseRendering(); }; Globe.prototype.resumeRendering = function () { this.renderer.resumeRendering(); this.refresh(true); }; Globe.prototype._setTiledLayer = function (tiledLayer, dontRefresh) { if (dontRefresh === void 0) { dontRefresh = false; } Image_1.default.clear(); if (this.tiledLayer) { var b = this.scene.remove(this.tiledLayer); if (!b) { console.error("this.scene.remove(this.tiledLayer)失败"); } this.scene.tiledLayer = null; } tiledLayer.globe = this; this.tiledLayer = tiledLayer; this.scene.add(this.tiledLayer, true); if (!dontRefresh) { this.refresh(true); } }; Globe.prototype.showLabelLayer = function () { if (this.labelLayer) { this.labelLayer.visible = true; } }; Globe.prototype.hideLabelLayer = function () { if (this.labelLayer) { this.labelLayer.visible = false; } }; Globe.prototype.getLevel = function () { return this.camera.getLevel(); }; Globe.prototype.zoomIn = function () { this.setLevel(this.getLevel() + 1); }; Globe.prototype.setLevel = function (level) { if (this.camera) { this.camera.setLevel(level); } }; Globe.prototype.centerTo = function (lon, lat, level) { if (level === void 0) { level = this.getLevel(); } return this.camera.centerTo(lon, lat, level); }; Globe.prototype.animateTo = function (newLon, newLat, newLevel, duration) { if (newLevel === void 0) { newLevel = this.getLevel(); } if (duration === void 0) { duration = 1000; } return this.camera.animateTo(newLon, newLat, newLevel, duration); }; Globe.prototype.setExtent = function (extent) { return this.camera.setExtent(extent); }; Globe.prototype.animateToExtent = function (extent, duration) { if (duration === void 0) { duration = 1000; } return this.camera.animateToExtent(extent, duration); }; Globe.prototype.isAnimating = function () { return this.camera.isAnimating(); }; Globe.prototype.animateToLevel = function (level, cb) { if (!this.isAnimating()) { if (level < Kernel_1.default.MIN_LEVEL) { level = Kernel_1.default.MIN_LEVEL; } if (level > Kernel_1.default.MAX_LEVEL) { level = Kernel_1.default.MAX_LEVEL; } if (level !== this.getLevel()) { this.camera.animateToLevel(level, cb); } } }; Globe.prototype.animateOut = function (cb) { this.animateToLevel(this.getLevel() - 1, cb); }; Globe.prototype.animateIn = function (cb) { this.animateToLevel(this.getLevel() + 1, cb); }; Globe.prototype._onBeforeRender = function (renderer) { this.refresh(); }; Globe.prototype._onAfterRender = function (render) { this.afterRenderCallbacks.forEach(function (callback) { return callback(); }); this.afterRenderCallbacks = []; }; Globe.prototype.logRefreshInfo = function () { console.log(this.realRefreshCount, this.allRefreshCount, this.realRefreshCount / this.allRefreshCount); }; Globe.prototype.refresh = function (force) { if (force === void 0) { force = false; } this.allRefreshCount++; var timestamp = Date.now(); this.camera.update(force); if (!this.tiledLayer || !this.scene || !this.camera) { return; } if (this.debugStopRefreshTiles) { return; } var newCameraCore = this.camera.getCameraCore(); var isNeedRefresh = false; if (force) { isNeedRefresh = true; } else { if (this.isRenderingPaused()) { isNeedRefresh = false; } else { if (newCameraCore.equals(this.lastRefreshCameraCore)) { isNeedRefresh = false; } else { isNeedRefresh = timestamp - this.lastRefreshTimestamp >= this.REFRESH_INTERVAL; } } } this.tiledLayer.updateSubLayerCount(); if (isNeedRefresh) { this.realRefreshCount++; this.lastRefreshTimestamp = timestamp; this.lastRefreshCameraCore = newCameraCore; this.tiledLayer.refresh(); } this.tiledLayer.updateTileVisibility(); if (!this.isRenderingPaused()) { var a = !!(this.labelLayer && this.labelLayer.visible); if (a) { var lastLevelTileGrids = this.tiledLayer.getLastLevelVisibleTileGrids(); this.labelLayer.updateTiles(this.getLevel(), lastLevelTileGrids); } } }; Globe.prototype.getExtent = function () { var extents = []; var layerExtent = this.tiledLayer.getExtent(); if (layerExtent) { extents.push(layerExtent); } var cameraExtent = this.camera.getExtent(); if (cameraExtent) { extents.push(cameraExtent); } if (extents.length === 0) { return null; } else if (extents.length === 1) { return extents[0]; } else { return Extent_1.default.intersect(extents); } }; Globe.prototype.pick = function (canvasX, canvasY) { var pickInfo = this.camera.getPickInfoByCanvas(canvasX, canvasY, false); var line = pickInfo.line; this.scene.pickByWorldLine(line); }; Globe.prototype.test = function () { this.debugStopRefreshTiles = true; this.labelLayer.hideAllTiles(); this.tiledLayer.children.forEach(function (subLayer) { return subLayer.hideAllTiles(); }); var subLayer = this.tiledLayer.children[this.tiledLayer.children.length - 1]; subLayer.visible = true; subLayer.children[0].visible = true; return subLayer; }; Globe.globe = null; return Globe; }()); exports.default = Globe; ; /***/ }), /* 1 */ /***/ (function(module, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var REAL_EARTH_RADIUS = 6378137; var EARTH_RADIUS = 500; var SCALE_FACTOR = EARTH_RADIUS / REAL_EARTH_RADIUS; var MAX_PROJECTED_COORD = Math.PI * EARTH_RADIUS; var MAX_REAL_RESOLUTION = 156543.03392800014; var MAX_RESOLUTION = MAX_REAL_RESOLUTION * SCALE_FACTOR; var Kernel = (function () { function Kernel() { } Kernel.gl = null; Kernel.idCounter = 0; Kernel.version = "0.0.1"; Kernel.SCALE_FACTOR = SCALE_FACTOR; Kernel.REAL_EARTH_RADIUS = REAL_EARTH_RADIUS; Kernel.EARTH_RADIUS = EARTH_RADIUS; Kernel.MAX_RESOLUTION = MAX_RESOLUTION; Kernel.MAX_REAL_RESOLUTION = MAX_REAL_RESOLUTION; Kernel.MAX_PROJECTED_COORD = MAX_PROJECTED_COORD; Kernel.BASE_LEVEL = 6; Kernel.MAX_LEVEL = 16; Kernel.MIN_LEVEL = 2; Kernel.MIN_PITCH_LEVEL = 8; Kernel.proxy = ""; return Kernel; }()); exports.default = Kernel; ; /***/ }), /* 2 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Kernel_1 = __webpack_require__(1); var topic = {}; var Utils = (function () { function Utils() { } Utils.isNumber = function (v) { return typeof v === "number"; }; Utils.isInteger = function (v) { var isInt = false; var isNum = this.isNumber(v); if (isNum) { var numFloat = parseFloat(v); var numInt = parseInt(v); if (numFloat === numInt) { isInt = true; } else { isInt = false; } } else { isInt = false; } return isInt; }; Utils.isPositive = function (v) { return v > 0; }; Utils.isNegative = function (v) { return v < 0; }; Utils.isNonNegative = function (v) { return v >= 0; }; Utils.isNonPositive = function (v) { return v <= 0; }; Utils.isPositiveInteger = function (v) { return this.isPositive(v) && this.isInteger(v); }; Utils.isNonNegativeInteger = function (v) { return this.isNonNegative(v) && this.isInteger(v); }; Utils.isArray = function (v) { return Object.prototype.toString.call(v) === '[object Array]'; }; Utils.isFunction = function (v) { return typeof v === 'function'; }; Utils.forEach = function (arr, func) { return this.isFunction(arr.forEach) ? arr.forEach(func) : Array.prototype.forEach.call(arr, func); }; Utils.filter = function (arr, func) { return this.isFunction(arr.filter) ? arr.filter(func) : Array.prototype.filter.call(arr, func); }; Utils.map = function (arr, func) { return this.isFunction(arr.map) ? arr.map(func) : Array.prototype.map.call(arr, func); }; Utils.some = function (arr, func) { return this.isFunction(arr.some) ? arr.some(func) : Array.prototype.some.call(arr, func); }; Utils.every = function (arr, func) { return this.isFunction(arr.every) ? arr.every(func) : Array.prototype.every.call(arr, func); }; Utils.filterRepeatArray = function (arr) { var cloneArray = arr.map(function (item) { return item; }); var simplifyArray = []; while (cloneArray.length > 0) { var e = cloneArray[0]; var exist = simplifyArray.some(function (item) { return e.equals(item); }); if (!exist) { simplifyArray.push(e); } cloneArray.splice(0, 1); } return simplifyArray; }; Utils.isMobile = function () { return !!window.navigator.userAgent.match(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone|IEMobile|Opera Mini/i); }; Utils.isWindows = function () { var platform = window.navigator.platform; return platform.toLowerCase().indexOf('win') === 0; }; Utils.wrapUrlWithProxy = function (url) { if (Kernel_1.default.proxy) { return Kernel_1.default.proxy + "?" + url; } return url; }; Utils.subscribe = function (topicName, callback) { if (!topic[topicName]) { topic[topicName] = []; } topic[topicName].push(callback); }; Utils.publish = function (topicName, data) { var callbacks = topic[topicName]; if (callbacks && callbacks.length > 0) { callbacks.forEach(function (callback) { callback(data); }); } }; return Utils; }()); exports.default = Utils; ; /***/ }), /* 3 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var Kernel_1 = __webpack_require__(1); var Renderer = (function () { function Renderer(canvas, onBeforeRender, onAfterRender) { this.canvas = canvas; this.onBeforeRender = onBeforeRender; this.onAfterRender = onAfterRender; this.scene = null; this.camera = null; this.renderingPaused = true; this.gl = null; this.gl = this._getWebGLContext(this.canvas); Kernel_1.default.gl = this.gl; if (!this.gl) { console.debug("浏览器不支持WebGL或将WebGL禁用!"); } var gl = this.gl; gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.clearColor(0, 0, 0, 1); gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); gl.depthMask(true); gl.enable(gl.CULL_FACE); gl.frontFace(gl.CCW); gl.cullFace(gl.BACK); } Renderer.prototype._getWebGLContext = function (canvas) { var gl = null; try { var contextList = [ "webgl", "experimental-webgl", "webkit-3d", "moz-webgl" ]; for (var i = 0; i < contextList.length; i++) { gl = canvas.getContext(contextList[i], { antialias: true }); if (gl) { break; } } } catch (e) { console.error(e); } return gl; }; Renderer.prototype.render = function (scene, camera) { var gl = this.gl; gl.viewport(0, 0, this.canvas.width, this.canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.clearColor(0, 0, 0, 1); try { camera.update(); } catch (e) { console.error(e); } try { if (this.onBeforeRender) { this.onBeforeRender(this); } } catch (e) { console.error(e); } try { if (!this.renderingPaused) { scene.draw(camera); } } catch (e) { console.error(e); } try { if (this.onAfterRender) { this.onAfterRender(this); } } catch (e) { console.error(e); } }; Renderer.prototype.setScene = function (scene) { this.scene = scene; }; Renderer.prototype.setCamera = function (camera) { this.camera = camera; }; Renderer.prototype._tick = function () { if (this.scene && this.camera) { this.render(this.scene, this.camera); } window.requestAnimationFrame(this._tick.bind(this)); }; Renderer.prototype.isRenderingPaused = function () { return this.renderingPaused; }; Renderer.prototype.pauseRendering = function () { this.renderingPaused = true; }; Renderer.prototype.resumeRendering = function () { this.renderingPaused = false; this._tick(); }; return Renderer; }()); exports.default = Renderer; /***/ }), /* 4 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); var Kernel_1 = __webpack_require__(1); var Utils_1 = __webpack_require__(2); var Events_1 = __webpack_require__(5); var Utils_2 = __webpack_require__(6); var Vertice_1 = __webpack_require__(7); var Vector_1 = __webpack_require__(8); var Line_1 = __webpack_require__(9); var TileGrid_1 = __webpack_require__(11); var Matrix_1 = __webpack_require__(12); var Object3D_1 = __webpack_require__(13); var Extent_1 = __webpack_require__(14); var CameraCore = (function () { function CameraCore(fov, aspect, near, far, floatLevel, matrix) { this.fov = fov; this.aspect = aspect; this.near = near; this.far = far; this.floatLevel = floatLevel; this.matrix = matrix; } CameraCore.prototype.getFov = function () { return this.fov; }; CameraCore.prototype.getAspect = function () { return this.aspect; }; CameraCore.prototype.getNear = function () { return this.near; }; CameraCore.prototype.getFar = function () { return this.far; }; CameraCore.prototype.getFloatLevel = function () { return this.floatLevel; }; CameraCore.prototype.getMatrix = function () { return this.matrix; }; CameraCore.prototype.equals = function (other) { if (!other) { return false; } return (this.fov === other.getFov() && this.aspect === other.getAspect() && this.near === other.getNear() && this.far === other.getFar() && this.floatLevel === other.getFloatLevel() && this.matrix.equals(other.getMatrix())); }; return CameraCore; }()); exports.CameraCore = CameraCore; var realResolutionCache = {}; (function () { for (var i = 0; i <= Kernel_1.default.MAX_LEVEL; i++) { realResolutionCache[i] = Kernel_1.default.MAX_REAL_RESOLUTION / Math.pow(2, i); } })(); var Camera = (function (_super) { __extends(Camera, _super); function Camera(canvas, fov, aspect, near, far, level, lonlat, resolutionFactor) { if (fov === void 0) { fov = 45; } if (aspect === void 0) { aspect = 1; } if (near === void 0) { near = 1; } if (far === void 0) { far = 100; } if (level === void 0) { level = 3; } if (lonlat === void 0) { lonlat = [0, 0]; } if (resolutionFactor === void 0) { resolutionFactor = Math.pow(2, 0.375295); } var _this = _super.call(this) || this; _this.canvas = canvas; _this.fov = fov; _this.aspect = aspect; _this.near = near; _this.far = far; _this.animationDuration = 200; _this.nearFactor = 0.6; _this.maxPitch = 40; _this.isZeroPitch = true; _this.level = -1; _this.floatLevel = -2; _this.lastFloatLevel = -3; _this.lastFov = -1; _this.lastAspect = -1; _this.lastNear = -1; _this.lastFar = -1; _this.lonlatsOfBoundary = null; _this.animating = false; _this.eventEmitter = null; if (!(resolutionFactor > 0)) { resolutionFactor = Math.pow(2, 0.375295); } _this.resolutionFactor1 = resolutionFactor; _this.resolutionFactor2 = _this.resolutionFactor1 * 2; _this.eventEmitter = new Events_1.EventEmitter(); _this.lonlatsOfBoundary = []; _this.initFov = _this.fov; _this.lastMatrix = new Matrix_1.default(); _this.lastMatrix.setUniqueValue(0); _this.projMatrix = new Matrix_1.default(); _this._rawSetPerspectiveMatrix(_this.fov, _this.aspect, _this.near, _this.far); _this._initCameraPosition(level, lonlat[0], lonlat[1]); _this.update(true); return _this; } Camera.prototype.getExtent = function () { var extent = null; if (this.isEarthFullOverlapScreen()) { var lons = []; var lats = []; this.lonlatsOfBoundary.forEach(function (lonlat) { lons.push(lonlat[0]); lats.push(lonlat[1]); }); var minLon = Math.min.apply(Math, lons); var maxLon = Math.max.apply(Math, lons); var minLat = Math.min.apply(Math, lats); var maxLat = Math.max.apply(Math, lats); extent = new Extent_1.default(minLon, minLat, maxLon, maxLat); } return extent; }; Camera.prototype.getEventEmitter = function () { return this.eventEmitter; }; Camera.prototype.isEarthFullOverlapScreen = function () { return this.lonlatsOfBoundary.length === 8; }; Camera.prototype.getTileGridsOfBoundary = function (level, filterRepeat) { var tileGridsOfBoundary = this.lonlatsOfBoundary.map(function (lonlat) { return TileGrid_1.default.getTileGridByGeo(lonlat[0], lonlat[1], level); }); return filterRepeat ? Utils_1.default.filterRepeatArray(tileGridsOfBoundary) : tileGridsOfBoundary; }; Camera.prototype.toJson = function () { function matrixToJson(mat) { return mat ? mat.toJson() : null; } var json = { matrix: matrixToJson(this.matrix), isZeroPitch: this.isZeroPitch, level: this.level, floatLevel: this.floatLevel, lastFloatLevel: this.lastFloatLevel, lastMatrix: matrixToJson(this.lastMatrix), lastFov: this.lastFov, lastAspect: this.lastAspect, lastNear: this.lastNear, lastFar: this.lastFar, viewMatrix: matrixToJson(this.viewMatrix), projMatrix: matrixToJson(this.projMatrix), projViewMatrix: matrixToJson(this.projViewMatrix), matrixForDraw: matrixToJson(this.matrixForDraw), viewMatrixForDraw: matrixToJson(this.viewMatrixForDraw), projMatrixForDraw: matrixToJson(this.projMatrixForDraw), projViewMatrixForDraw: matrixToJson(this.projViewMatrixForDraw), animating: this.animating }; return json; }; Camera.prototype.toJsonString = function () { return JSON.stringify(this.toJson()); }; Camera.prototype.fromJson = function (json) { this.matrix = Matrix_1.default.fromJson(json.matrix); this.isZeroPitch = json.isZeroPitch; this.level = json.level; this.floatLevel = json.floatLevel; this.lastFloatLevel = json.lastFloatLevel; this.lastMatrix = Matrix_1.default.fromJson(json.lastMatrix); this.lastFov = json.lastFov; this.lastAspect = json.lastAspect; this.lastNear = json.lastNear; this.lastFar = json.lastFar; this.viewMatrix = Matrix_1.default.fromJson(json.viewMatrix); this.projMatrix = Matrix_1.default.fromJson(json.projMatrix); this.projViewMatrix = Matrix_1.default.fromJson(json.projViewMatrix); this.matrixForDraw = Matrix_1.default.fromJson(json.matrixForDraw); this.viewMatrixForDraw = Matrix_1.default.fromJson(json.viewMatrixForDraw); this.projMatrixForDraw = Matrix_1.default.fromJson(json.projMatrixForDraw); this.projViewMatrixForDraw = Matrix_1.default.fromJson(json.projViewMatrixForDraw); this.animating = json.animating; this.update(true); }; Camera.prototype.fromJsonString = function (jsonStr) { this.fromJson(JSON.parse(jsonStr)); }; Camera.prototype._setPerspectiveMatrix = function (fov, aspect, near, far) { this._rawSetPerspectiveMatrix(fov, aspect, near, far); this._updateFar(); }; Camera.prototype._rawSetPerspectiveMatrix = function (fov, aspect, near, far, projMatrix) { if (projMatrix === void 0) { projMatrix = this.projMatrix; } if (this.projMatrix === projMatrix) { this.fov = fov; this.aspect = aspect; this.near = near; this.far = far; } var mat = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]; var halfFov = fov * Math.PI / 180 / 2; var f = 1 / Math.tan(halfFov); var nf = 1 / (near - far); mat[0] = f / aspect; mat[5] = f; mat[10] = (far + near) * nf; mat[11] = -1; mat[14] = 2 * near * far * nf; mat[15] = 0; projMatrix.setElements(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5], mat[6], mat[7], mat[8], mat[9], mat[10], mat[11], mat[12], mat[13], mat[14], mat[15]); }; Camera.prototype._setFov = function (fov) { if (!(fov > 0)) { throw "invalid fov:" + fov; } this._setPerspectiveMatrix(fov, this.aspect, this.near, this.far); }; Camera.prototype.setAspect = function (aspect) { if (!(aspect > 0)) { throw "invalid aspect:" + aspect; } this._setPerspectiveMatrix(this.fov, aspect, this.near, this.far); this.setLevel(this.level, true); }; Camera.prototype._updateFar = function () { }; Camera.prototype._getMinimalFar = function (cameraPosition) { var distance2EarthOrigin = Vector_1.default.fromVertice(cameraPosition).getLength(); var far = Math.sqrt(distance2EarthOrigin * distance2EarthOrigin - Kernel_1.default.EARTH_RADIUS * Kernel_1.default.EARTH_RADIUS); far *= 1.05; return far; }; Camera.prototype.update = function (force) { if (force === void 0) { force = false; } var shouldUpdate = this._updateCore(force); if (shouldUpdate) { this._updateTileGridsOfBoundary(); } return shouldUpdate; }; Camera.prototype._updateCore = function (force) { if (force === void 0) { force = false; } var shouldUpdate = force || this._isNeedUpdate(); if (shouldUpdate) { this._normalUpdate(); this._updateProjViewMatrixForDraw(); } this.lastFov = this.fov; this.lastAspect = this.aspect; this.lastNear = this.near; this.lastFar = this.far; this.lastFloatLevel = this.floatLevel; this.lastMatrix.setMatrixByOther(this.matrix); return shouldUpdate; }; Camera.prototype._updateTileGridsOfBoundary = function () { var _this = this; var lonlatsOfBoundary = []; var ndcs = [ [-1, 1], [-1, 0], [-1, -1], [1, 1], [1, 0], [1, -1], [0, 1], [0, -1] ]; ndcs.forEach(function (ndcXY) { var lonlat = _this._getPickLonLatByNDC(ndcXY[0], ndcXY[1]); if (lonlat && lonlat.length > 0) { lonlatsOfBoundary.push(lonlat); } }); this.lonlatsOfBoundary = lonlatsOfBoundary; }; Camera.prototype.getCameraCore = function () { return new CameraCore(this.fov, this.aspect, this.near, this.far, this.floatLevel, this.matrix.clone()); }; Camera.prototype._isNeedUpdate = function () { return (this.fov !== this.lastFov || this.aspect !== this.lastAspect || this.near !== this.lastNear || this.far !== this.lastFar || this.floatLevel !== this.lastFloatLevel || !this.matrix.equals(this.lastMatrix)); }; Camera.prototype.getProjViewMatrixForDraw = function () { return this.projViewMatrixForDraw; }; Camera.prototype._normalUpdate = function () { this.viewMatrix = this.matrix.getInverseMatrix(); this._updateFar(); this.projViewMatrix = this.projMatrix.multiplyMatrix(this.viewMatrix); }; Camera.prototype._updateProjViewMatrixForDraw = function () { this.matrixForDraw = this.matrix.clone(); var newFov = this._updatePositionAndFov(this.matrixForDraw); var aspect = this.aspect; var near = this.near; var newFar = this.far; this.projMatrixForDraw = new Matrix_1.default(); this._rawSetPerspectiveMatrix(newFov, aspect, near, newFar, this.projMatrixForDraw); this.viewMatrixForDraw = this.matrixForDraw.getInverseMatrix(); this.projViewMatrixForDraw = this.projMatrixForDraw.multiplyMatrix(this.viewMatrixForDraw); }; Camera.prototype._updatePositionAndFov = function (cameraMatrix) { var currentLevel = this.animating ? this.floatLevel : this.level; var safeLevel = this._getSafeThresholdLevelForNear(); if (currentLevel > safeLevel) { this._updatePositionByLevel(safeLevel, cameraMatrix); var deltaLevel = currentLevel - safeLevel; var newFov = this._calculateFovByDeltaLevel(this.initFov, deltaLevel); return newFov; } else { this._updatePositionByLevel(currentLevel, cameraMatrix); return this.initFov; } }; Camera.prototype._getSafeThresholdLevelForNear = function () { var thresholdNear = this.near * this.nearFactor; var result = this._calculateResolutionAndBestDisplayLevelByDistance2EarthSurface(thresholdNear); var level = result[1]; return level; }; Camera.prototype._calculateDeltaLevelByFov = function (oldFov, newFov) { var radianOldFov = Utils_2.default.degreeToRadian(oldFov); var halfRadianOldFov = radianOldFov / 2; var tanOld = Math.tan(halfRadianOldFov); var radianNewFov = Utils_2.default.degreeToRadian(newFov); var halfRadianNewFov = radianNewFov / 2; var tanNew = Math.tan(halfRadianNewFov); var deltaLevel = Utils_2.default.log2(tanOld / tanNew); return deltaLevel; }; Camera.prototype._calculateFovByDeltaLevel = function (oldFov, deltaLevel) { var radianOldFov = Utils_2.default.degreeToRadian(oldFov); var halfRadianOldFov = radianOldFov / 2; var tanOld = Math.tan(halfRadianOldFov); var tanNew = tanOld / Math.pow(2, deltaLevel); var halfRadianNewFov = Math.atan(tanNew); var radianNewFov = halfRadianNewFov * 2; var newFov = Utils_2.default.radianToDegree(radianNewFov); return newFov; }; Camera.prototype.getResolution = function () { var _a = this.measureXYResolutionAndBestDisplayLevel(), resolutionX = _a.resolutionX, bestDisplayLevelFloatX = _a.bestDisplayLevelFloatX, resolutionY = _a.resolutionY, bestDisplayLevelFloatY = _a.bestDisplayLevelFloatY; return (resolutionX + resolutionY) / 2 / this.resolutionFactor1; }; Camera.prototype.getResolutionInWorld = function () { return this.getResolution() / Kernel_1.default.SCALE_FACTOR; }; Camera.prototype.getResolutionInWorld2 = function () { if (realResolutionCache.hasOwnProperty(this.level)) { return realResolutionCache[this.level]; } else { return Kernel_1.default.MAX_REAL_RESOLUTION / Math.pow(2, this.level); } }; Camera.prototype.measureXYResolutionAndBestDisplayLevel = function () { var p = this.matrix.getPosition(); var dir = Vector_1.default.fromVertice(p); var line = new Line_1.default(p, dir); var pickResult1 = this._getPickCartesianCoordInEarthByLine(line); var p1 = pickResult1[0]; var ndc1 = this._convertVerticeFromWorldToNDC(p1); var canvasXY1 = Utils_2.default.convertPointFromNdcToCanvas(this.canvas.width, this.canvas.height, ndc1.x, ndc1.y); var centerX = canvasXY1[0]; var centerY = canvasXY1[1]; var offsetPixel = 10; var leftPickResult = this.getPickCartesianCoordInEarthByCanvas(centerX - offsetPixel, centerY); var vLeft = Vector_1.default.fromVertice(leftPickResult[0]); var rightPickResult = this.getPickCartesianCoordInEarthByCanvas(centerX + offsetPixel, centerY); var vRight = Vector_1.default.fromVertice(rightPickResult[0]); var α = Vector_1.default.getRadianOfTwoVectors(vLeft, vRight); var resolutionX = α * Kernel_1.default.EARTH_RADIUS / (2 * offsetPixel) * this.resolutionFactor1; var bestDisplayLevelFloatX = this._calculateLevelByResolution(resolutionX); var topPickResult = this.getPickCartesianCoordInEarthByCanvas(centerX, centerY + offsetPixel); var vTop = Vector_1.default.fromVertice(topPickResult[0]); var bottomPickResult = this.getPickCartesianCoordInEarthByCanvas(centerX, centerY - offsetPixel); var vBottom = Vector_1.default.fromVertice(bottomPickResult[0]); var β = Vector_1.default.getRadianOfTwoVectors(vTop, vBottom); var resolutionY = β * Kernel_1.default.EARTH_RADIUS / (2 * offsetPixel) * this.resolutionFactor1; var bestDisplayLevelFloatY = this._calculateLevelByResolution(resolutionY); return { resolutionX: resolutionX, bestDisplayLevelFloatX: bestDisplayLevelFloatX, resolutionY: resolutionY, bestDisplayLevelFloatY: bestDisplayLevelFloatY }; }; Camera.prototype.calculateCurrentResolutionAndBestDisplayLevel = function () { var distance2EarthOrigin = this.getDistance2EarthOrigin(); return this._calculateResolutionAndBestDisplayLevelByDistance2EarthOrigin(distance2EarthOrigin); }; Camera.prototype._calculateResolutionAndBestDisplayLevelByDistance2EarthOrigin = function (distance2EarthOrigin) { var α2 = Utils_2.default.degreeToRadian(this.fov / 2); var α1 = Math.atan(2 / this.canvas.height * Math.tan(α2)); var δ = Math.asin(distance2EarthOrigin * Math.sin(α1) / Kernel_1.default.EARTH_RADIUS); var β = δ - α1; var resolution = β * Kernel_1.default.EARTH_RADIUS * this.resolutionFactor2; var bestDisplayLevelFloat = this._calculateLevelByResolution(resolution); return [resolution, bestDisplayLevelFloat]; }; Camera.prototype._calculateResolutionAndBestDisplayLevelByDistance2EarthSurface = function (distance2EarthSurface) { var distance2EarthOrigin = distance2EarthSurface + Kernel_1.default.EARTH_RADIUS; return this._calculateResolutionAndBestDisplayLevelByDistance2EarthOrigin(distance2EarthOrigin); }; Camera.prototype._calculateDistance2EarthSurfaceByBestDisplayLevel = function (level) { return (this._calculateDistance2EarthOriginByBestDisplayLevel(level) - Kernel_1.default.EARTH_RADIUS); }; Camera.prototype._calculateDistance2EarthOriginByBestDisplayLevel = function (level) { var resolution = this._calculateResolutionByLevel(level); return this._calculateDistance2EarthOriginByResolution(resolution); }; Camera.prototype._calculateDistance2EarthOriginByResolution = function (resolution) { resolution /= this.resolutionFactor2; var α2 = Utils_2.default.degreeToRadian(this.fov / 2); var α1 = Math.atan(2 / this.canvas.height * Math.tan(α2)); var β = resolution / Kernel_1.default.EARTH_RADIUS; var δ = α1 + β; var distance2EarthOrigin = Kernel_1.default.EARTH_RADIUS * Math.sin(δ) / Math.sin(α1); return distance2EarthOrigin; }; Camera.prototype._calculateLevelByResolution = function (resolution) { var pow2value = Kernel_1.default.MAX_RESOLUTION / resolution; var bestDisplayLevelFloat = Utils_2.default.log2(pow2value); return bestDisplayLevelFloat; }; Camera.prototype._calculateResolutionByLevel = function (level) { return Kernel_1.default.MAX_RESOLUTION / Math.pow(2, level); }; Camera.prototype.getVertice = function () { var origin2PositionVector = Vector_1.default.fromVertice(this.getPosition()); origin2PositionVector.setLength(Kernel_1.default.EARTH_RADIUS); var p = origin2PositionVector.getVertice(); return p; }; Camera.prototype.getLonlat = function () { var p = this.getVertice(); var lonlat = Utils_2.default.cartesianCoordToGeographic(p); return lonlat; }; Camera.prototype.getLevel = function () { return this.level; }; Camera.prototype.setLevel = function (level, force) { if (force === void 0) { force = false; } if (!Utils_1.default.isNonNegativeInteger(level)) { throw "invalid level:" + level; } if (level < Kernel_1.default.MIN_LEVEL) { level = Kernel_1.default.MIN_LEVEL; } if (level > Kernel_1.default.MAX_LEVEL) { level = Kernel_1.default.MAX_LEVEL; } var oldLevel = this.level; var levelChanged = level !== this.level; if (levelChanged || force) { this._updatePositionByLevel(level, this.matrix); this.level = level; this.floatLevel = level; } if (levelChanged) { Utils_1.default.publish("level-change", { oldLevel: oldLevel, newLevel: this.level }); } }; Camera.prototype._initCameraPosition = function (level, lon, lat) { var initDistanceToOrigin = this._calculateDistance2EarthOriginByBestDisplayLevel(level); var initPosition = Utils_2.default.geographicToCartesianCoord(lon, lat, initDistanceToOrigin); var origin = new Vertice_1.default(0, 0, 0); var vector = this.getLightDirection().getOpposite(); vector.setLength(initDistanceToOrigin); this._look(initPosition, origin); this.setLevel(level); }; Camera.prototype._updatePositionByLevel = function (level, cameraMatrix) { var intersects = this._getDirectionIntersectPointWithEarth(cameraMatrix); if (intersects.length === 0) { throw "no intersect"; } var intersect = intersects[0]; var theoryDistance2Interscet = this._calculateDistance2EarthSurfaceByBestDisplayLevel(level); var vector = cameraMatrix.getVectorZ(); vector.setLength(theoryDistance2Interscet); var newCameraPosition = Vector_1.default.verticePlusVector(intersect, vector); cameraMatrix.setPosition(newCameraPosition); }; Camera.prototype.setDeltaPitch = function (deltaPitch) { if (this.level < Kernel_1.default.MIN_PITCH_LEVEL || !this.isEarthFullOverlapScreen()) { return; } var currentPitch = this.getPitch(); var newPitch = currentPitch + deltaPitch; if (newPitch > this.maxPitch) { return; } if (newPitch < 0) { newPitch = 0; } deltaPitch = newPitch - currentPitch; if (deltaPitch === 0) { return; } var intersects = this._getDirectionIntersectPointWithEarth(this.matrix); if (intersects.length === 0) { throw "no intersects"; } var intersect = intersects[0]; var deltaRadian = Utils_2.default.degreeToRadian(deltaPitch); var matrix = this.matrix.clone(); matrix.setPosition(intersect); matrix.localRotateX(deltaRadian); this._updatePositionByLevel(this.level, matrix); this.isZeroPitch = newPitch === 0; this.matrix = matrix; }; Camera.prototype.getPitch = function () { if (this.isZeroPitch) { return 0; } var intersects = this._getDirectionIntersectPointWithEarth(this.matrix); if (intersects.length === 0) { throw "no intersects"; } var intersect = intersects[0]; var vectorOrigin2Intersect = Vector_1.default.fromVertice(intersect); var length1 = vectorOrigin2Intersect.getLength(); var vectorIntersect2Camera = Vector_1.default.verticeMinusVertice(this.getPosition(), intersect); var length2 = vectorIntersect2Camera.getLength(); var cosθ = vectorOrigin2Intersect.dot(vectorIntersect2Camera) / (length1 * length2); var radian = Utils_2.default.acosSafely(cosθ); var crossVector = vectorOrigin2Intersect.cross(vectorIntersect2Camera); var xAxisDirection = this.matrix.getVectorX(); if (crossVector.dot(xAxisDirection)) { radian = Math.abs(radian); } else { radian = -Math.abs(radian); } var pitch = Utils_2.default.radianToDegree(radian); if (pitch >= 90) { throw "Invalid pitch: " + pitch; } return pitch; }; Camera.prototype.getPickInfoByCanvas = function (canvasX, canvasY, verticesResult) { if (verticesResult === void 0) { verticesResult = false; } var result = { line: null, vertices: [] }; this._updateCore(); var matrix = this.matrix; var viewMatrix = this.viewMatrix; var projMatrix = this.projMatrix; var projViewMatrix = this.projViewMatrix; this.matrix = this.matrixForDraw; this.viewMatrix = this.viewMatrixForDraw; this.projMatrix = this.projMatrixForDraw; this.projViewMatrix = this.projViewMatrixForDraw; var pickDirection = this._getPickDirectionByCanvas(canvasX, canvasY); var p = this.getPosition(); result.line = new Line_1.default(p, pickDirection); if (verticesResult) { result.vertices = this._getPickCartesianCoordInEarthByLine(result.line); } this.matrix = matrix; this.viewMatrix = viewMatrix; this.projMatrix = projMatrix; this.projViewMatrix = projViewMatrix; return result; }; Camera.prototype.getPickCartesianCoordInEarthByCanvas = function (canvasX, canvasY) { var pickInfo = this.getPickInfoByCanvas(canvasX, canvasY, true); return pickInfo.vertices; }; Camera.prototype.getLightDirection = function () { var dirVertice = this.matrix.getVectorZ(); var direction = new Vector_1.default(-dirVertice.x, -dirVertice.y, -dirVertice.z); direction.normalize(); return direction; }; Camera.prototype.getDistance2EarthSurface = function () { var position = this.getPosition(); var length2EarthSurface = Vector_1.default.fromVertice(position).getLength() - Kernel_1.default.EARTH_RADIUS; return length2EarthSurface; }; Camera.prototype.getDistance2EarthOrigin = function () { var position = this.getPosition(); return Vector_1.default.fromVertice(positio