globe.min.js 31 KB

12345678910111213141516171819202122
  1. /**
  2. * globe.js library - visualizes individual data on an interactive globe
  3. *
  4. * Based on webgl-globe hosted at the time of this writing at
  5. * http://code.google.com/p/webgl-globe/
  6. *
  7. * Copyright 2011 Data Arts Team, Google Creative Lab
  8. * Copyright 2013 Matthias Gazzari, Annemarie Mattmann, André Wolski
  9. *
  10. * Licensed under the Apache License, Version 2.0 (the "License");
  11. * you may not use this file except in compliance with the License.
  12. * You may obtain a copy of the License at
  13. *
  14. * http://www.apache.org/licenses/LICENSE-2.0
  15. *
  16. * Unless required by applicable law or agreed to in writing, software
  17. * distributed under the License is distributed on an "AS IS" BASIS,
  18. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  19. * See the License for the specific language governing permissions and
  20. * limitations under the License.
  21. */
  22. var GLOBE = GLOBE || {};GLOBE.Tooltip = function() {var element = document.createElement("div");element.className = "globe-tooltip";document.body.appendChild(element);this.hide = function() {element.style.display = "none";};this.show = function(label, x, y) {element.style.display = "inline";element.innerHTML = label;element.style.left = x + "px";element.style.top = y + "px";};};var GLOBE = GLOBE || {};GLOBE.Sphere = function(options) {var material;function init(obj) {options = options || {};var radius = options.radius || 200;var segments = options.segments || 40;var rings = options.rings || 20;var sphere = new THREE.SphereGeometry(radius, segments, rings);material = new THREE.MeshBasicMaterial();var mesh = new THREE.Mesh(sphere, material);mesh.matrixAutoUpdate = false;mesh.updateMatrix();obj.mesh = mesh;obj.setTexture = setTexture;}function setTexture(texture) {material.map = texture;}init(this);};var GLOBE = GLOBE || {};GLOBE.Atmosphere = function(options) {var material;function init(obj) {options = options || {};var radius = options.radius || 200;var segments = options.segments || 40;var rings = options.rings || 20;var scale = options.scale || 1.15;var sphere = new THREE.SphereGeometry(radius, segments, rings);var vertexShader = ["varying vec3 vNormal;","void main() {","vNormal = normalize(normalMatrix * normal);","gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);","}",].join("\n");var fragmentShader = ["varying vec3 vNormal;","void main() {","float intensity = (dot(vNormal, vec3(0, 0, 1.0)) + 0.7) * 1.6;","gl_FragColor = vec4(intensity, intensity, intensity, 1.0);","}",].join("\n");material = new THREE.ShaderMaterial({"vertexShader": vertexShader,"fragmentShader": fragmentShader,"side": THREE.BackSide,"visible": true,});var mesh = new THREE.Mesh(sphere, material);mesh.scale.multiplyScalar(scale);mesh.matrixAutoUpdate = false;mesh.updateMatrix();obj.mesh = mesh;obj.setVisibility = setVisibility;}function setVisibility(visbility) {material.visible = visbility;}init(this);};var GLOBE = GLOBE || {};GLOBE.Countries = function(options) {var bytes = 3;var code = ['A1', 'A2', 'O1', 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AP','AQ', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE','BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS','BT', 'BV', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI','CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ','DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'EH', 'ER', 'ES','ET', 'EU', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE','GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT','GU', 'GW', 'GY', 'HK', 'HM', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL','IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE','KG', 'KH', 'KI', 'KM', 'KN', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB','LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD','ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR','MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF','NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF','PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA','RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH','SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX','SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN','TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ','VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA','ZM', 'ZW', 'NULL', 'NULL'];var interpolator;var maxSaturation;var markers;var cpc;var markerPerCountry;var texture;function init(obj) {options = options || {};var defaultInterpolator = function(ratio) {return (1 - Math.pow(ratio, 1/3));};interpolator = options.interpolator || defaultInterpolator;maxSaturation = options.maxSaturation || 255;if (maxSaturation > 255) {maxSaturation = 255;}if (maxSaturation < 0) {maxSaturation = 0;}markerPerCountry = {};markers = 0;cpc = new Uint8Array(code.length * bytes);texture = new THREE.DataTexture(cpc,code.length,1,THREE.RGBFormat);texture.magFilter = THREE.NearestFilter;texture.minFilter = THREE.NearestMipMapNearestFilter;reset();obj.texture = texture;obj.inc = inc;obj.dec = dec;obj.reset = reset;obj.getCC = getCC;obj.getMarkers = getMarkers;obj.getAllMarkers = getAllMarkers;obj.hasMarker = hasMarker;}function hasMarker() {if (markers > 0) {return true;}return false;}function setColor(index, red, green, blue) {cpc[index * bytes + 0] = red;cpc[index * bytes + 1] = green;cpc[index * bytes + 2] = blue;}function updateCountries() {for (var i = 0; i < code.length ; i++) {if (markers <= 0) {setColor(i, maxSaturation, maxSaturation, maxSaturation);} else {var absolute = (markerPerCountry[code[i]] | 0);var ratio = absolute / markers;var value = interpolator(ratio) * maxSaturation;setColor(i, maxSaturation, value, value);}}texture.needsUpdate = true;}function inc(cc) {markers++;markerPerCountry[cc] = (markerPerCountry[cc] | 0) + 1;updateCountries();}function dec(cc) {if (markerPerCountry[cc] > 0) {markers--;markerPerCountry[cc] = markerPerCountry[cc] - 1;updateCountries();}}function reset() {for (key in markerPerCountry)markerPerCountry[key] = 0;markers = 0;updateCountries();}function getCC(index) {return code[index];}function getMarkers(index) {return (markerPerCountry[code[index]] | 0);}function getAllMarkers() {return markers;}init(this);};var GLOBE = GLOBE || {};GLOBE.Heatmap = function(width, height, heatTexture, gradientTexture) {var left = -width/2;var right = width/2;var top = height/2;var bottom = -height/2;var zNear = -10000;var zFar = 10000;var camera = new THREE.OrthographicCamera(left, right, top, bottom, zNear, zFar);camera.position.z = 100;var uniforms = {"heatTexture": {type: 't', value: heatTexture},"gradientTexture": {type: 't', value: gradientTexture}};var vertexShader = ["varying vec2 vUv;","void main() {","vUv = uv;","gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);","}",].join("\n");var fragmentShader = ["uniform sampler2D heatTexture;","uniform sampler2D gradientTexture;","varying vec2 vUv;","void main() {","vec4 heatTexel = texture2D(heatTexture, vUv);","if(heatTexel.a == 1.0) {","gl_FragColor = heatTexel;","}","else {","vec2 pos = vec2(1.0 - heatTexel.a, 0.0);","vec3 gradientTexel = texture2D(gradientTexture, pos).rgb;","gl_FragColor = vec4(gradientTexel, 1.0);","}","}",].join("\n");var plane = new THREE.PlaneGeometry(width, height);plane.dynamic = true;var planeMaterial = new THREE.ShaderMaterial({"uniforms": uniforms,"vertexShader": vertexShader,"fragmentShader": fragmentShader});var screen = new THREE.Mesh(plane, planeMaterial);var scene = new THREE.Scene();scene.add(screen);this.scene = scene;this.camera = camera;};var GLOBE = GLOBE || {};GLOBE.MapMode = 0;GLOBE.HeatMode = 1;GLOBE.PickMode = 2;GLOBE.main = function(container, imgPath, options) {var view;var renderer;var tooltip;var position;var countries;var res;var mouseDown = false;var intervalID;var pickBufferUpdate;var mapUpdate;var modifyMarkerLabel;var setCountryLabel;function init(obj) {options = options || {};modifyMarkerLabel = options.modifyMarkerLabel || function(label) {return label;};setCountryLabel = options.setCountryLabel || function(cc, markers, allMarkers) {return "CC: " + cc + " Markers: " + markers + " of " + allMarkers + " total";};var w = container.offsetWidth || window.innerWidth;var h = container.offsetHeight || window.innerHeight;countries = new GLOBE.Countries();tooltip = new GLOBE.Tooltip();var PI_HALF = Math.PI / 2;var INFINITY = Number.POSITIVE_INFINITY;position = new GLOBE.Position({"currentPos": new THREE.Vector3(10000, 0, 0),"targetPos": new THREE.Vector3(1000, PI_HALF * 1.3, PI_HALF * 0.25),"weights": new THREE.Vector3(0.3, 0.1, 0.1),"lowerLimit": new THREE.Vector3(250, -INFINITY, -PI_HALF),"upperLimit": new THREE.Vector3(1000, INFINITY, PI_HALF)});loadResources(function() {renderer = new GLOBE.Renderer(container, res.pickTexture, res.borderTexture, countries.texture, res.gradientTexture);renderer.updateMap();view = new GLOBE.View(renderer.mapTexture, res.pickTexture, res.borderTexture, res.markerTexture, res.heatTexture, res.animationTexture, {"aspectRatio": w/h,"offset": 10,"radius": 200,});pickBufferUpdate = new GLOBE.Update(function() {var previous = view.getMode();view.setMode(GLOBE.PickMode);renderer.updateColorPicking(view);view.setMode(previous);}, 300);mapUpdate = new GLOBE.Update(function() {renderer.updateMap();view.update();}, 100);obj.reset = reset;obj.removeMarker = removeMarker;obj.addMarker = addMarker;obj.zoom = zoom;obj.rotate = rotate;obj.toggleView = toggleView;obj.resize = resize;obj.hasMarker = countries.hasMarker;container.addEventListener('DOMMouseScroll', onMouseWheel, false);container.addEventListener('mousewheel', onMouseWheel, false);container.addEventListener('mousedown', onMouseDown, false);container.addEventListener('mousemove', onMouseMove, false);container.addEventListener('mouseout', onMouseOut, false);window.addEventListener('resize', resize, false);window.addEventListener('beforeunload', unloadResources);animate();});}function loadResources(callback) {var resCount = 0;var onLoad = function(texture) {resCount--;console.log(resCount + " textures left to be loaded (" + new Date() + ")");if (resCount == 0) {callback();}};var load = function(path, minFilter, magFilter) {resCount++;var texture = THREE.ImageUtils.loadTexture(path, {}, onLoad);if (minFilter !== undefined) {texture.minFilter = minFilter;}if (magFilter !== undefined) {texture.magFilter = magFilter;}return texture;};res = {"pickTexture": load(imgPath + 'countries_colored.png', THREE.NearestFilter, THREE.NearestFilter),"borderTexture": load(imgPath + 'borders_oceans_lakes.png', THREE.LinearFilter, THREE.LinearFilter),"markerTexture": load(imgPath + 'circle.png', THREE.LinearFilter, THREE.LinearFilter),"animationTexture": load(imgPath + 'animation.png', THREE.LinearFilter, THREE.LinearFilter),"heatTexture": load(imgPath + 'heat.png', THREE.NearestFilter, THREE.NearestFilter),"gradientTexture": load(imgPath + 'gradient.png', THREE.NearestFilter, THREE.NearestFilter)};}function unloadResources(event) {for (var key in res) {res[key].dispose();console.log("disposed " + key);}renderer.dispose();}function animate() {requestAnimationFrame(animate);var error = position.getError();if (error < 1e-4 && error > 1e-6) {pickBufferUpdate.execute();}render();}function render() {var pos = position.doStep();view.setCamera(pos.x, pos.y, pos.z);renderer.renderView(view);}function onMouseWheel(event) {event.preventDefault();if (event.wheelDeltaY) {zoom(event.wheelDeltaY * 0.7);} else {zoom(event.detail * -36);}return false;}function toggleView() {var mode = view.getMode();if (mode == GLOBE.HeatMode) {view.setMode(GLOBE.MapMode);} else {view.setMode(GLOBE.HeatMode);}}function resize() {if (container.style.display != "none") {renderer.resize(view);pickBufferUpdate.execute();}}function zoom(delta) {tooltip.hide();if (!mouseDown) {var pos = new THREE.Vector3(-delta, 0, 0);position.adjustTarget(pos);}}function rotate(horizAngle, vertAngle) {tooltip.hide();if (!mouseDown) {var pos = new THREE.Vector3(0, horizAngle, vertAngle);position.adjustTarget(pos);}}function onMouseOut(event) {tooltip.hide();mouseDown = false;document.removeEventListener('mouseup', onMouseUp, false);container.style.cursor = 'auto';}function onMouseDown(event) {mouseDown = true;event.preventDefault();document.addEventListener('mouseup', onMouseUp, false);var pos = new THREE.Vector3(0, -event.clientX, event.clientY);position.store(pos);container.style.cursor = 'move';tooltip.hide();}function onMouseUp(event) {mouseDown = false;document.removeEventListener('mouseup', onMouseUp, false);container.style.cursor = 'auto';}function onMouseMove(event) {if (mouseDown) {tooltip.hide();var pos = new THREE.Vector3(0, -event.clientX, event.clientY);position.adjustTargetRelative(pos, 0.000000005);} else {setLabel(event.clientX, event.clientY, event.pageX, event.pageY);mapUpdate.execute();}}function setLabel(posX, posY, screenPosX, screenPosY) {var color = renderer.getPixel(posX, posY);if (color.a == 255) {if (color.r == 0) {var hex = (color.r << 16) + (color.g << 8) + (color.b);var label = modifyMarkerLabel(view.getLabel(hex));tooltip.show(label, screenPosX, screenPosY);}if (color.r > 0 && color.r < 254) {var cc = countries.getCC(color.r);var markers = countries.getMarkers(color.r);var allMarkers = countries.getAllMarkers();var label = setCountryLabel(cc, markers, allMarkers);renderer.setPickIndex(color.r);tooltip.show(label, screenPosX, screenPosY);}}else {tooltip.hide();renderer.setPickIndex(-1.0);}}function addMarker(cc, latitude, longitude, sourceLabel) {var onOverflow = countries.dec;var returnMarker = view.addMarker(cc, latitude, longitude, sourceLabel, onOverflow);countries.inc(cc);pickBufferUpdate.execute();mapUpdate.execute();return returnMarker;}function removeMarker(key) {var cc = view.getCC(key);view.removeMarker(key);countries.dec(cc);pickBufferUpdate.execute();mapUpdate.execute();}function reset() {countries.reset();view.reset();pickBufferUpdate.execute();mapUpdate.execute();}init(this);};var GLOBE = GLOBE || {};GLOBE.Map = function(width, height, pickTexture, borderTexture, mpcTexture) {var left = -width/2;var right = width/2;var top = height/2;var bottom = -height/2;var zNear = -10000;var zFar = 10000;var camera = new THREE.OrthographicCamera(left, right, top, bottom, zNear, zFar);camera.position.z = 100;var target = new THREE.WebGLRenderTarget(width, height, {"format": THREE.RGBFormat});target.magFilter = THREE.LinearFilter;target.minFilter = THREE.LinearFilter;var uniforms = {"pickTexture": {type: 't', value: pickTexture},"borderTexture": {type: 't', value: borderTexture},"mpcTexture": {type: 't', value: mpcTexture},"pickIndex": {type: 'f', value: -1.0},"hoverColor": {type: 'v3', value: new THREE.Vector3(0.8, 0.8, 0.9)},};var vertexShader = ["varying vec2 vUv;","void main() {","gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);","vUv = uv;","}",].join("\n");var fragmentShader = ["uniform sampler2D pickTexture;","uniform sampler2D borderTexture;","uniform sampler2D mpcTexture;","uniform float pickIndex;","uniform vec3 hoverColor;","varying vec2 vUv;","const float allowedError = 1.0/1024.0;","void main() {","vec4 pickTexel = texture2D(pickTexture, vUv).rgba;","vec2 pos = vec2(pickTexel.r, 0.0);","vec3 mpcTexel = texture2D(mpcTexture, pos).rgb;","vec3 borderTexel = texture2D(borderTexture, vUv).rgb;","if (pickTexel.a == 0.0)","gl_FragColor = vec4(borderTexel, 1.0);","else if (pickTexel.r < (pickIndex + allowedError) && pickTexel.r > (pickIndex - allowedError))","gl_FragColor = vec4(hoverColor * mpcTexel * borderTexel, 1.0);","else","gl_FragColor = vec4(mpcTexel * borderTexel, 1.0);","}",].join("\n");var plane = new THREE.PlaneGeometry(width, height);var planeMaterial = new THREE.ShaderMaterial({"uniforms": uniforms,"vertexShader": vertexShader,"fragmentShader": fragmentShader});var screen = new THREE.Mesh(plane, planeMaterial);var scene = new THREE.Scene();scene.add(screen);this.scene = scene;this.camera = camera;this.target = target;this.setPickIndex = function(index) {screen.material.uniforms.pickIndex.value = index/255.0;};};var GLOBE = GLOBE || {};GLOBE.Renderer = function(container, pickTexture, borderTexture, mpcTexture, gradientTexture) {var renderer;var gl;var pickTarget;var pixelBuffer;var heatTexture;var map;var heatmap;function init(obj) {var w = container.offsetWidth || window.innerWidth;var h = container.offsetHeight || window.innerHeight;renderer = new THREE.WebGLRenderer();console.log(renderer.info);renderer.setSize(w, h);renderer.setClearColor(0xffffff, 1);container.appendChild(renderer.domElement);gl = renderer.getContext();pixelBuffer = new Uint8Array(w * h * 4);pickTarget = new THREE.WebGLRenderTarget(w, h, {"format": THREE.RGBAFormat});pickTarget.generateMipmaps = false;heatTexture = new THREE.WebGLRenderTarget(w, h, {"format": THREE.RGBAFormat});heatTexture.minFilter = THREE.LinearFilter;heatTexture.magFilter = THREE.LinearFilter;heatTexture.generateMipmaps = false;var textureWidth = pickTexture.image.width;var textureHeight = pickTexture.image.height;map = new GLOBE.Map(textureWidth, textureHeight, pickTexture, borderTexture, mpcTexture);heatmap = new GLOBE.Heatmap(w, h, heatTexture, gradientTexture);obj.mapTexture = map.target;obj.renderView = renderView;obj.updateMap = updateMap;obj.updateColorPicking = updateColorPicking;obj.resize = resize;obj.getPixel = getPixel;obj.setPickIndex = map.setPickIndex;obj.dispose = dispose;}function renderView(view) {var mode = view.getMode();if (mode == GLOBE.MapMode) {renderer.render(view.scene, view.camera);} else if (mode == GLOBE.HeatMode) {renderer.render(view.scene, view.camera, heatTexture);renderer.render(heatmap.scene, heatmap.camera);}}function updateMap() {renderer.render(map.scene, map.camera, map.target);}function updateColorPicking(view) {var w = container.offsetWidth || window.innerWidth;var h = container.offsetHeight || window.innerHeight;pickTarget.width = w;pickTarget.height = h;pixelBuffer = new Uint8Array(w * h * 4);renderer.render(view.scene, view.camera, pickTarget);gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixelBuffer);}function resize(view) {var w = container.offsetWidth || window.innerWidth;var h = container.offsetHeight || window.innerHeight;renderer.setSize(w, h);view.resize(w/h);if (heatTexture.width != w || heatTexture.height - h != 10) {heatTexture = new THREE.WebGLRenderTarget(w, h, {"format": THREE.RGBAFormat});heatTexture.minFilter = THREE.LinearFilter;heatTexture.magFilter = THREE.LinearFilter;heatTexture.generateMipmaps = false;heatmap = new GLOBE.Heatmap(w, h, heatTexture, gradientTexture);}}function getPixel(mouseX, mouseY) {var pos = mapMouseToCoord(mouseX, mouseY);var w = container.offsetWidth || window.innerWidth;var h = container.offsetHeight || window.innerHeight;var index = (pos.x + (h - pos.y + 1) * w) *4;return {"r": pixelBuffer[index + 0],"g": pixelBuffer[index + 1],"b": pixelBuffer[index + 2],"a": pixelBuffer[index + 3]}}function mapMouseToCoord(mouseX, mouseY) {var rect = container.getBoundingClientRect();var left = toInt(rect.left);var top = toInt(rect.top);return {'x': mouseX - left - 1,'y': mouseY - top,}}function toInt(value) {return value | 0;}function dispose() {pickTarget.dispose();console.log("disposed pickTarget");heatTexture.dispose();console.log("disposed heatTexture");}init(this);};var GLOBE = GLOBE || {};GLOBE.Update = function(f, t) {var timeoutInterval;var blocked;var waiting;var updateFunction;function init(obj) {updateFunction = f;timeoutInterval = t;blocked = false;enqueued = false;obj.execute = execute;}function execute() {if (!blocked) {blocked = true;updateFunction();startTimeout(false);}else {enqueued = true;}}function startTimeout(execute) {setTimeout(function() {if (execute) {updateFunction();}if (enqueued) {enqueued = false;startTimeout(true);} else {blocked = false;}}, timeoutInterval);}init(this);};var GLOBE = GLOBE || {};GLOBE.View = function(mapTexture, pickTexture, borderTexture, markerTexture, heatTexture, animationTexture, options) {var ORIGIN = new THREE.Vector3(0, 0, 0);var camera;var scene;var radius;var offset;var markers;var sphere;var atmosphere;var mode;var markerScale;function init(obj) {options = options || {};mode = options.mode || GLOBE.MapMode;markerScale = options.markerScale || 1;var fov = options.fov || 30;var aspectRatio = options.aspectRatio || 1;var zNear = options.zNear || 1;var zFar = options.zFar || 10000;var distance = options.distance || 1000;radius = options.radius || 200;offset = options.offset || 0;camera = new THREE.PerspectiveCamera(fov, aspectRatio, zNear, zFar);camera.position.z = distance;scene = new THREE.Scene();markers = new GLOBE.Markers(markerTexture, heatTexture, animationTexture, {"maxMarker": options.maxMarker,"markerSize": options.markerSize,});markers.setMode(mode);sphere = new GLOBE.Sphere({"radius": options.radius,"segments": options.segments,"rings": options.rings});sphere.setTexture(mapTexture);atmosphere = new GLOBE.Atmosphere({"radius": options.radius,"segments": options.segments,"rings": options.rings,"scale": options.scale});atmosphere.setVisibility(true);scene.add(markers.system);scene.add(markers.animation);scene.add(atmosphere.mesh);scene.add(sphere.mesh);obj.camera = camera;obj.scene = scene;obj.addMarker = addMarker;obj.removeMarker = removeMarker;obj.update = update;obj.getLabel = getLabel;obj.getCC = getCC;obj.setMode = setMode;obj.getMode = getMode;obj.resize = resize;obj.setCamera = setCamera;obj.reset = reset;}function addMarker(cc, latitude, longitude, sourceLabel, onOverflow) {return markers.add(cc, latitude, longitude - offset, radius * markerScale, sourceLabel, onOverflow);}function removeMarker(key) {markers.remove(key);}function update() {markers.update();}function getLabel(key) {return markers.getLabel(key);}function getCC(key) {return markers.getCC(key);}function setMode(m) {mode = m;markers.setMode(m);if (m == GLOBE.PickMode) {atmosphere.setVisibility(false);sphere.setTexture(pickTexture);} else if (m == GLOBE.HeatMode) {atmosphere.setVisibility(true);sphere.setTexture(borderTexture);} else {atmosphere.setVisibility(true);sphere.setTexture(mapTexture);}}function getMode() {return mode;}function resize(aspectRatio) {camera.aspect = aspectRatio;camera.updateProjectionMatrix();}function setCamera(distance, horizAngle, vertAngle) {camera.position.x = distance * Math.sin(horizAngle) * Math.cos(vertAngle);camera.position.y = distance * Math.sin(vertAngle);camera.position.z = distance * Math.cos(horizAngle) * Math.cos(vertAngle);camera.lookAt(ORIGIN);}function reset() {markers.reset();}init(this);};var GLOBE = GLOBE || {};GLOBE.Position = function(options) {var INFINITY = Number.POSITIVE_INFINITY;var ZEROS = new THREE.Vector3(0, 0, 0);var ONES = new THREE.Vector3(1, 1, 1);var MIN = new THREE.Vector3(-INFINITY, -INFINITY, -INFINITY);var MAX = new THREE.Vector3(INFINITY, INFINITY, INFINITY);var currentPos;var targetPos;var storedPos;var lastTarget;var lowerLimit;var upperLimit;var weights;var difference;function init(obj) {options = options || {};currentPos = options.currentPos || ZEROS.clone();targetPos = options.targetPos || ZEROS.clone();storedPos = currentPos.clone();lastTarget = targetPos.clone();lowerLimit = options.lowerLimit || MIN.clone();upperLimit = options.upperLimit || MAX.clone();weights = options.weights || ONES.clone();for (i = 0; i < 3; i++) {var component = weights.getComponent(i);if (component <= 0 || component > 1) {console.log("The " + i + "th element of initialWeights is not in the interval (0,1]");weights = ONES.clone();break;}}difference = new THREE.Vector3();clampTarget();updateDifference();obj.adjustTarget = adjustTarget;obj.store = store;obj.adjustTargetRelative = adjustTargetRelative;obj.doStep = doStep;obj.getError = getError;}function getZoomDamp() {return new THREE.Vector3(1, currentPos.x*currentPos.x, currentPos.x*currentPos.x);}function clampTarget() {targetPos.clamp(lowerLimit, upperLimit);}function adjustTarget(delta) {var zoomDamp = getZoomDamp();delta.multiply(zoomDamp);targetPos.add(delta);clampTarget();updateDifference();}function store(pos) {lastTarget.copy(targetPos);storedPos.copy(pos);}function adjustTargetRelative(pos, damp) {var damp = damp || 1;var zoomDamp = getZoomDamp();var vec = new THREE.Vector3();vec.subVectors(pos, storedPos);vec.multiplyScalar(damp);vec.multiply(zoomDamp);targetPos.addVectors(lastTarget, vec);clampTarget();updateDifference();}function doStep() {var intermediate = new THREE.Vector3();intermediate.multiplyVectors(difference, weights);currentPos.add(intermediate);updateDifference();return currentPos;}function getError() {return difference.length() / (targetPos.length() || 1);}function updateDifference() {difference.subVectors(targetPos, currentPos);}function debugVector(name, vec) {console.log(name, vec.x, vec.y, vec.z, vec.length());}init(this);};var GLOBE = GLOBE || {};GLOBE.Markers = function(markerTexture, heatTexture, animationTexture, options) {var INFINITY = Number.POSITIVE_INFINITY;var marker;var label;var countryCode;var nextMarker;var markerSystem;var maxMarker;var markerMaterial;var animation;var nextAnimation;var animationSystem;var maxAnimation;var animationMaterial;function init(obj) {options = options || {};maxMarker = options.maxMarker || 10000;maxAnimation = options.maxAnimation || 100;if (maxMarker < 1) {maxMarker = 1;}if (maxMarker > 16777216) {maxMarker = 16777216;}var markerSize = options.markerSize || 15;var heatSize = options.heatSize || 10;var animationSize = options.animationSize || 40;var animationDuration = options.animationDuration || 1.0;var heatColor = options.heatColor || new THREE.Vector4(1.0, 0.0, 0.0, 0.95);var circleColor = options.circleColor || new THREE.Vector4(0.8, 0.0, 0.0, 1.0);marker = [maxMarker];label = [maxMarker];countryCode = [maxMarker];animation = [maxAnimation];nextMarker = 0;nextAnimation = 0;var markerGeometry = new THREE.Geometry();for (var i = 0; i < maxMarker; i++) {marker[i] = new THREE.Vector3(INFINITY, INFINITY, INFINITY);markerGeometry.vertices.push(marker[i]);markerGeometry.colors[i] = new THREE.Color(i);}var animationGeometry = new THREE.Geometry();for (var i = 0; i < maxAnimation; i++) {animation[i] = new THREE.Vector3(INFINITY, INFINITY, INFINITY);animationGeometry.vertices.push(animation[i]);}var markerUniforms = {markerTexture: {type: "t", value: markerTexture},heatTexture: {type: "t", value: heatTexture},mode: {type: "i", value: GLOBE.MapMode},markerSize: {type: "f", value: markerSize},heatSize: {type: "f", value: heatSize},heatColor: {type: "v4", value: heatColor},circleColor: {type: "v4", value: circleColor}};var markerVertexShader = ["uniform float heatSize;","uniform float markerSize;","uniform float animationSize;","uniform int mode;","varying vec3 vColor;","void main() {","if(mode == 2) {","gl_PointSize = markerSize;","}","else if(mode == 1) {","gl_PointSize = heatSize;","}","else {","gl_PointSize = markerSize;","}","vColor = color;","gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);","}",].join("\n");var markerFragmentShader = ["uniform sampler2D markerTexture;","uniform sampler2D heatTexture;","uniform int mode;","uniform vec4 circleColor;","uniform vec4 heatColor;","varying vec3 vColor;","void main() {","if (mode == 2){","gl_FragColor = vec4(vColor, 1.0);","}","else if (mode == 1) {","vec4 heatTexel = texture2D(heatTexture, gl_PointCoord);","gl_FragColor = heatTexel - heatColor;","}","else {","vec4 markerTexel = texture2D(markerTexture, gl_PointCoord);","gl_FragColor = markerTexel * circleColor;","}","}",].join("\n");markerMaterial = new THREE.ShaderMaterial({"uniforms": markerUniforms,"vertexShader": markerVertexShader,"fragmentShader": markerFragmentShader,"transparent": true,"vertexColors": THREE.VertexColors,"blending": THREE.NormalBlending,"depthWrite": false,});var animationAttributes = {timeout: {type: "f", value: []}};var animationUniforms = {texture: {type: "t", value: animationTexture},mode: {type: "i", value: GLOBE.MapMode},time: {type: "f", value: 0.0},animationDuration: {type: "f", value: animationDuration},size: {type: "f", value: animationSize},circleColor: {type: "v4", value: circleColor}};var animationVertexShader = ["uniform float size;","uniform float time;","uniform float animationDuration;","attribute float timeout;","varying float relTime;","void main() {","gl_PointSize = size;","relTime = (timeout - time) / animationDuration;","gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);","}",].join("\n");var animationFragmentShader = ["uniform sampler2D texture;","uniform int mode;","uniform vec4 circleColor;","uniform vec4 heatColor;","varying float relTime;","void main() {","if (mode == 0) {","vec4 texel = texture2D(texture, gl_PointCoord);","vec4 ratio = vec4(1.0 , 1.0, 1.0, relTime);","gl_FragColor = texel * circleColor*ratio;","}","else {","gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);","}","}",].join("\n");animationMaterial = new THREE.ShaderMaterial({"attributes": animationAttributes,"uniforms": animationUniforms,"vertexShader": animationVertexShader,"fragmentShader": animationFragmentShader,"transparent": true,"blending": THREE.NormalBlending,"depthWrite": false,});markerSystem = new THREE.ParticleSystem(markerGeometry, markerMaterial);animationSystem = new THREE.ParticleSystem(animationGeometry, animationMaterial);setInterval(function() {animationMaterial.uniforms.time.value += 0.015625;}, 15.625);obj.system = markerSystem;obj.animation = animationSystem;obj.add = add;obj.remove = remove;obj.update = update;obj.setMode = setMode;obj.getLabel = getLabel;obj.getCC = getCC;obj.reset = reset;}function add(cc, latitude, longitude, radius, sourceLabel, onOverflow) {if (inUse(marker[nextMarker])) {onOverflow(countryCode[nextMarker]);}var cartesian = convert(latitude, longitude, radius);marker[nextMarker].set(cartesian.x, cartesian.y, cartesian.z);animation[nextAnimation].set(cartesian.x, cartesian.y, cartesian.z);label[nextMarker] = sourceLabel;countryCode[nextMarker] = cc;animationMaterial.attributes.timeout.value[nextAnimation] = animationMaterial.uniforms.time.value + 1.0;animationMaterial.attributes.timeout.needsUpdate = true;animationSystem.geometry.verticesNeedUpdate = true;var returnMarker = nextMarker;nextMarker = (nextMarker + 1) % maxMarker;nextAnimation = (nextAnimation + 1) % maxAnimation;return returnMarker;}function inUse(marker) {return !(marker.x == INFINITY && marker.y == INFINITY && marker.z ==INFINITY);}function remove(key) {marker[key].set(INFINITY, INFINITY, INFINITY);countryCode[key] = undefined;}function update() {markerSystem.geometry.verticesNeedUpdate = true;}function setMode(mode) {markerMaterial.uniforms.mode.value = mode;animationMaterial.uniforms.mode.value = mode;if (mode == GLOBE.HeatMode) {markerMaterial.blending = THREE.SubtractiveBlending;} else {markerMaterial.blending = THREE.NormalBlending;}}function getLabel(key) {return label[key];}function getCC(key) {return countryCode[key];}function reset() {for(i = 0; i < maxMarker; i++) {marker[i].set(INFINITY, INFINITY, INFINITY);countryCode[i] = undefined;}}function convert(latitude, longitude, radius) {var theta = latitude * Math.PI / 180;var phi = longitude * Math.PI / 180;var x = radius * Math.cos(phi) * Math.cos(theta);var y = radius * Math.sin(theta);var z = - radius * Math.sin(phi) * Math.cos(theta);return new THREE.Vector3(x, y, z);}init(this);};