e-civ-planet
Version:
A WebGL virtual globe and map engine based on webglobe
1,267 lines (1,243 loc) • 375 kB
JavaScript
(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