three-globe
Advanced tools
Comparing version 1.0.5 to 1.0.6
@@ -8,2 +8,3 @@ 'use strict'; | ||
var accessorFn = _interopDefault(require('accessor-fn')); | ||
var d3Geo = require('d3-geo'); | ||
var tinyColor = _interopDefault(require('tinycolor2')); | ||
@@ -19,2 +20,3 @@ | ||
BackSide: three.BackSide, | ||
BufferGeometry: three.BufferGeometry, | ||
Color: three.Color, | ||
@@ -25,2 +27,3 @@ CylinderGeometry: three.CylinderGeometry, | ||
Group: three.Group, | ||
Line: three.Line, | ||
Matrix4: three.Matrix4, | ||
@@ -99,7 +102,6 @@ Mesh: three.Mesh, | ||
globeImageUrl: { | ||
onChange(url) { | ||
this._loadGlobeImage(url); | ||
}, | ||
onChange(_, state) { | ||
state.globeNeedsUpdate = true; | ||
} | ||
triggerUpdate: false | ||
}, | ||
@@ -138,3 +140,3 @@ pointsData: { | ||
}, | ||
pointHeight: { | ||
pointAltitude: { | ||
default: 0.1, | ||
@@ -175,55 +177,53 @@ | ||
// boolean. Whether to merge all points into a single mesh for rendering performance | ||
linksData: { | ||
arcsData: { | ||
default: [], | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkStartLat: { | ||
arcStartLat: { | ||
default: 'startLat', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkStartLng: { | ||
default: 'endLng', | ||
arcStartLng: { | ||
default: 'startLng', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkEndLat: { | ||
arcEndLat: { | ||
default: 'endLat', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkEndLng: { | ||
arcEndLng: { | ||
default: 'endLng', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkColor: { | ||
arcColor: { | ||
default: () => '#ffffaa', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkHeight: { | ||
default: 0.4, | ||
arcAltitude: { | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -233,16 +233,23 @@ | ||
// in units of globe radius | ||
linkDiameter: { | ||
default: 0.2, | ||
arcAltitudeAutoScale: { | ||
default: 0.5, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// scale altitude proportional to great-arc distance between the two points | ||
arcStroke: { | ||
onChange(_, state) { | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// in deg | ||
linkCurveResolution: { | ||
arcCurveResolution: { | ||
default: 64, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -252,7 +259,7 @@ | ||
// how many slice segments in the tube's circumference | ||
linkCircularResolution: { | ||
arcCircularResolution: { | ||
default: 6, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -262,11 +269,11 @@ | ||
// how many slice segments in the tube's circumference | ||
linksMerge: { | ||
arcsMerge: { | ||
default: false, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// boolean. Whether to merge all links into a single mesh for rendering performance | ||
// boolean. Whether to merge all arcs into a single mesh for rendering performance | ||
customLayerData: { | ||
@@ -297,22 +304,9 @@ default: [], | ||
}; | ||
}, | ||
} | ||
_loadGlobeImage: function (state, imageUrl) { | ||
if (state.globeObj && imageUrl) { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(imageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
return this; | ||
} | ||
}, | ||
stateInit: () => ({ | ||
globeNeedsUpdate: true, | ||
pointsNeedsRepopulating: true, | ||
linksNeedsRepopulating: true, | ||
arcsNeedsRepopulating: true, | ||
customLayerNeedsRepopulating: true | ||
@@ -335,4 +329,3 @@ }), | ||
state.scene.add(globeObj); | ||
state.globeImageUrl && this._loadGlobeImage(state.globeImageUrl); // add atmosphere | ||
state.scene.add(globeObj); // add atmosphere | ||
@@ -357,5 +350,5 @@ { | ||
state.scene.add(state.pointsG = new THREE.Group()); // add links group | ||
state.scene.add(state.pointsG = new THREE.Group()); // add arcs group | ||
state.scene.add(state.linksG = new THREE.Group()); // add custom layer group | ||
state.scene.add(state.arcsG = new THREE.Group()); // add custom layer group | ||
@@ -368,4 +361,24 @@ state.scene.add(state.customLayerG = new THREE.Group()); | ||
if (state.globeNeedsUpdate) { | ||
state.globeNeedsUpdate = false; | ||
if (!state.globeImageUrl) { | ||
// Black globe | ||
state.globeObj.material = new THREE.MeshBasicMaterial({ | ||
color: 0x000000 | ||
}); | ||
} else { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(state.globeImageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
} | ||
if (state.pointsNeedsRepopulating) { | ||
state.pointsNeedRepopulating = false; // Clear the existing points | ||
state.pointsNeedsRepopulating = false; // Clear the existing points | ||
@@ -376,3 +389,3 @@ emptyObject(state.pointsG); // Data accessors | ||
const lngAccessor = accessorFn(state.pointLng); | ||
const heightAccessor = accessorFn(state.pointHeight); | ||
const altitudeAccessor = accessorFn(state.pointAltitude); | ||
const radiusAccessor = accessorFn(state.pointRadius); | ||
@@ -393,3 +406,3 @@ const colorAccessor = accessorFn(state.pointColor); // Add WebGL points | ||
obj.scale.x = obj.scale.y = Math.min(30, radiusAccessor(pnt)) * pxPerDeg; | ||
obj.scale.z = Math.max(heightAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
obj.scale.z = Math.max(altitudeAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
@@ -446,47 +459,59 @@ obj.__globeObjType = 'point'; // Add object type | ||
if (state.linksNeedsRepopulating) { | ||
state.linksNeedsRepopulating = false; // Clear the existing links | ||
if (state.arcsNeedsRepopulating) { | ||
state.arcsNeedsRepopulating = false; // Clear the existing arcs | ||
emptyObject(state.linksG); // Data accessors | ||
emptyObject(state.arcsG); // Data accessors | ||
const startLatAccessor = accessorFn(state.linkStartLat); | ||
const startLngAccessor = accessorFn(state.linkStartLng); | ||
const endLatAccessor = accessorFn(state.linkEndLat); | ||
const endLngAccessor = accessorFn(state.linkEndLng); | ||
const heightAccessor = accessorFn(state.linkHeight); | ||
const diameterAccessor = accessorFn(state.linkDiameter); | ||
const colorAccessor = accessorFn(state.linkColor); | ||
const linkObjs = []; | ||
state.linksData.forEach(link => { | ||
const startPnt = [...[startLatAccessor, startLngAccessor].map(fn => fn(link)), 0]; | ||
const endPnt = [...[endLatAccessor, endLngAccessor].map(fn => fn(link)), 0]; | ||
const startLatAccessor = accessorFn(state.arcStartLat); | ||
const startLngAccessor = accessorFn(state.arcStartLng); | ||
const endLatAccessor = accessorFn(state.arcEndLat); | ||
const endLngAccessor = accessorFn(state.arcEndLng); | ||
const altitudeAccessor = accessorFn(state.arcAltitude); | ||
const altitudeAutoScaleAccessor = accessorFn(state.arcAltitudeAutoScale); | ||
const strokeAccessor = accessorFn(state.arcStroke); | ||
const colorAccessor = accessorFn(state.arcColor); | ||
const arcObjs = []; | ||
state.arcsData.forEach(arc => { | ||
let curve; | ||
{ | ||
const getVec = ([lng, lat, alt]) => { | ||
const { | ||
x, | ||
y, | ||
z | ||
} = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(x, y, z); | ||
}; //calculate curve | ||
const getMiddle = (a, b) => a + (b - a) / 2; | ||
const middlePoint = [getMiddle(startPnt[0], endPnt[0]), getMiddle(startPnt[1], endPnt[1]), heightAccessor(link) * 2]; | ||
const curveVecs = [startPnt, middlePoint, endPnt].map(([lat, lng, alt]) => { | ||
const coords = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(coords.x, coords.y, coords.z); | ||
}); | ||
const path = new THREE.QuadraticBezierCurve3(...curveVecs); | ||
const linkGeometry = new THREE.TubeGeometry(path, state.linkCurveResolution, diameterAccessor(link) / 2, state.linkCircularResolution); | ||
const obj = new THREE.Mesh(linkGeometry); | ||
obj.__globeObjType = 'link'; // Add object type | ||
const startPnt = [startLngAccessor, startLatAccessor].map(fn => fn(arc)); | ||
const endPnt = [endLngAccessor, endLatAccessor].map(fn => fn(arc)); | ||
let altitude = altitudeAccessor(arc); | ||
(altitude === null || altitude === undefined) && ( // by default set altitude proportional to the great-arc distance | ||
altitude = d3Geo.geoDistance(startPnt, endPnt) / 2 * altitudeAutoScaleAccessor(arc)); | ||
const interpolate = d3Geo.geoInterpolate(startPnt, endPnt); | ||
const [m1Pnt, m2Pnt] = [0.25, 0.75].map(t => [...interpolate(t), altitude * 1.5]); | ||
curve = new THREE.CubicBezierCurve3(...[startPnt, m1Pnt, m2Pnt, endPnt].map(getVec)); //const mPnt = [...interpolate(0.5), altitude * 2]; | ||
//curve = new THREE.QuadraticBezierCurve3(...[startPnt, mPnt, endPnt].map(getVec)); | ||
} | ||
const stroke = strokeAccessor(arc); | ||
const obj = stroke === null || stroke === undefined ? new THREE.Line(new THREE.BufferGeometry().setFromPoints(curve.getPoints(state.arcCurveResolution))) : new THREE.Mesh(new THREE.TubeGeometry(curve, state.arcCurveResolution, stroke / 2, state.arcCircularResolution)); | ||
obj.__globeObjType = 'arc'; // Add object type | ||
obj.__data = link; // Attach point data | ||
obj.__data = arc; // Attach point data | ||
linkObjs.push(obj); | ||
arcObjs.push(obj); | ||
}); | ||
if (state.linksMerge) { | ||
// merge links into a single mesh | ||
const linksGeometry = new THREE.Geometry(); | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
const color = new THREE.Color(colorAccessor(link)); | ||
if (state.arcsMerge) { | ||
// merge arcs into a single mesh | ||
const arcsGeometry = new THREE.Geometry(); | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = new THREE.Color(colorAccessor(arc)); | ||
obj.geometry.faces.forEach(face => face.color = color); | ||
obj.updateMatrix(); | ||
linksGeometry.merge(obj.geometry, obj.matrix); | ||
arcsGeometry.merge(obj.geometry, obj.matrix); | ||
}); | ||
const links = new THREE.Mesh(linksGeometry, new THREE.MeshBasicMaterial({ | ||
const arcs = new THREE.Mesh(arcsGeometry, new THREE.MeshBasicMaterial({ | ||
color: 0xffffff, | ||
@@ -496,18 +521,18 @@ vertexColors: THREE.FaceColors, | ||
})); | ||
links.__globeObjType = 'links'; // Add object type | ||
arcs.__globeObjType = 'arcs'; // Add object type | ||
links.__data = state.linksData; // Attach obj data | ||
arcs.__data = state.arcsData; // Attach obj data | ||
state.linksG.add(links); | ||
state.arcsG.add(arcs); | ||
} else { | ||
// Add individual meshes per link | ||
const linkMaterials = {}; // indexed by color | ||
// Add individual meshes per arc | ||
const arcMaterials = {}; // indexed by color | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
const color = colorAccessor(link); | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = colorAccessor(arc); | ||
const opacity = colorAlpha(color); | ||
if (!linkMaterials.hasOwnProperty(color)) { | ||
linkMaterials[color] = new THREE.MeshLambertMaterial({ | ||
if (!arcMaterials.hasOwnProperty(color)) { | ||
arcMaterials[color] = new THREE.MeshLambertMaterial({ | ||
color: colorStr2Hex(color), | ||
@@ -519,4 +544,4 @@ transparent: opacity < 1, | ||
obj.material = linkMaterials[color]; | ||
state.linksG.add(link.__threeObj = obj); | ||
obj.material = arcMaterials[color]; | ||
state.arcsG.add(arc.__threeObj = obj); | ||
}); | ||
@@ -523,0 +548,0 @@ } |
@@ -1,5 +0,5 @@ | ||
// Version 1.0.5 three-globe - https://github.com/vasturiano/three-globe | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("three")):"function"==typeof define&&define.amd?define(["three"],t):(e=e||self).ThreeGlobe=t(e.THREE)}(this,function(e){"use strict";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function n(e,t){return e(t={exports:{}},t.exports),t.exports}var r=n(function(e,t){"undefined"!=typeof self&&self,e.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){var r,a,i,o;o=function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.stateInit,n=void 0===t?function(){return{}}:t,r=e.props,s=void 0===r?{}:r,l=e.methods,u=void 0===l?{}:l,f=e.aliases,c=void 0===f?{}:f,h=e.init,d=void 0===h?function(){}:h,g=e.update,p=void 0===g?function(){}:g,b=Object.keys(s).map(function(e){return new o(e,s[e])});return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=Object.assign({},n instanceof Function?n(e):n,{initialised:!1});function r(t){return o(t,e),s(),r}var o=function(e,n){d.call(r,e,t,n),t.initialised=!0},s=(0,a.default)(function(){t.initialised&&p.call(r,t)},1);return b.forEach(function(e){r[e.name]=function(e){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(e,t){};return function(i){var o=t[e];return arguments.length?(t[e]=i,a.call(r,i,t,o),n&&s(),r):o}}(e.name,e.triggerUpdate,e.onChange)}),Object.keys(u).forEach(function(e){r[e]=function(){for(var n,a=arguments.length,i=Array(a),o=0;o<a;o++)i[o]=arguments[o];return(n=u[e]).call.apply(n,[r,t].concat(i))}}),Object.entries(c).forEach(function(e){var t=i(e,2),n=t[0],a=t[1];return r[n]=r[a]}),r.resetProps=function(){return b.forEach(function(e){r[e.name](e.defaultVal)}),r},r.resetProps(),t._rerender=s,r}};var r,a=(r=n)&&r.__esModule?r:{default:r},i=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,a=!1,i=void 0;try{for(var o,s=e[Symbol.iterator]();!(r=(o=s.next()).done)&&(n.push(o.value),!t||n.length!==t);r=!0);}catch(e){a=!0,i=e}finally{try{!r&&s.return&&s.return()}finally{if(a)throw i}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},o=function e(t,n){var r=n.default,a=void 0===r?null:r,i=n.triggerUpdate,o=void 0===i||i,s=n.onChange,l=void 0===s?function(e,t){}:s;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.name=t,this.defaultVal=a,this.triggerUpdate=o,this.onChange=l};e.exports=t.default},a=[e,t,n(1)],void 0===(i="function"==typeof(r=o)?r.apply(t,a):r)||(e.exports=i)},function(e,t){e.exports=function(e,t,n){var r,a,i,o,s;function l(){var u=Date.now()-o;u<t&&u>=0?r=setTimeout(l,t-u):(r=null,n||(s=e.apply(i,a),i=a=null))}null==t&&(t=100);var u=function(){i=this,a=arguments,o=Date.now();var u=n&&!r;return r||(r=setTimeout(l,t)),u&&(s=e.apply(i,a),i=a=null),s};return u.clear=function(){r&&(clearTimeout(r),r=null)},u.flush=function(){r&&(s=e.apply(i,a),i=a=null,clearTimeout(r),r=null)},u}}])}),a=t(r),i=(r.Kapsule,n(function(e,t){e.exports=function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){var r,a,i;a=[e,t],void 0!==(i="function"==typeof(r=function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return e instanceof Function?e:"string"==typeof e?function(t){return t[e]}:function(t){return e}},e.exports=t.default})?r.apply(t,a):r)&&(e.exports=i)}])})),o=t(i),s=(i.accessorFn,n(function(e){!function(t){var n=/^\s+/,r=/\s+$/,a=0,i=t.round,o=t.min,s=t.max,l=t.random;function u(e,l){if(l=l||{},(e=e||"")instanceof u)return e;if(!(this instanceof u))return new u(e,l);var f=function(e){var a={r:0,g:0,b:0},i=1,l=null,u=null,f=null,c=!1,h=!1;"string"==typeof e&&(e=function(e){e=e.replace(n,"").replace(r,"").toLowerCase();var t,a=!1;if(R[e])e=R[e],a=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};if(t=U.rgb.exec(e))return{r:t[1],g:t[2],b:t[3]};if(t=U.rgba.exec(e))return{r:t[1],g:t[2],b:t[3],a:t[4]};if(t=U.hsl.exec(e))return{h:t[1],s:t[2],l:t[3]};if(t=U.hsla.exec(e))return{h:t[1],s:t[2],l:t[3],a:t[4]};if(t=U.hsv.exec(e))return{h:t[1],s:t[2],v:t[3]};if(t=U.hsva.exec(e))return{h:t[1],s:t[2],v:t[3],a:t[4]};if(t=U.hex8.exec(e))return{r:L(t[1]),g:L(t[2]),b:L(t[3]),a:E(t[4]),format:a?"name":"hex8"};if(t=U.hex6.exec(e))return{r:L(t[1]),g:L(t[2]),b:L(t[3]),format:a?"name":"hex"};if(t=U.hex4.exec(e))return{r:L(t[1]+""+t[1]),g:L(t[2]+""+t[2]),b:L(t[3]+""+t[3]),a:E(t[4]+""+t[4]),format:a?"name":"hex8"};if(t=U.hex3.exec(e))return{r:L(t[1]+""+t[1]),g:L(t[2]+""+t[2]),b:L(t[3]+""+t[3]),format:a?"name":"hex"};return!1}(e));"object"==typeof e&&(D(e.r)&&D(e.g)&&D(e.b)?(d=e.r,g=e.g,p=e.b,a={r:255*j(d,255),g:255*j(g,255),b:255*j(p,255)},c=!0,h="%"===String(e.r).substr(-1)?"prgb":"rgb"):D(e.h)&&D(e.s)&&D(e.v)?(l=H(e.s),u=H(e.v),a=function(e,n,r){e=6*j(e,360),n=j(n,100),r=j(r,100);var a=t.floor(e),i=e-a,o=r*(1-n),s=r*(1-i*n),l=r*(1-(1-i)*n),u=a%6;return{r:255*[r,s,o,o,l,r][u],g:255*[l,r,r,s,o,o][u],b:255*[o,o,l,r,r,s][u]}}(e.h,l,u),c=!0,h="hsv"):D(e.h)&&D(e.s)&&D(e.l)&&(l=H(e.s),f=H(e.l),a=function(e,t,n){var r,a,i;function o(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}if(e=j(e,360),t=j(t,100),n=j(n,100),0===t)r=a=i=n;else{var s=n<.5?n*(1+t):n+t-n*t,l=2*n-s;r=o(l,s,e+1/3),a=o(l,s,e),i=o(l,s,e-1/3)}return{r:255*r,g:255*a,b:255*i}}(e.h,l,f),c=!0,h="hsl"),e.hasOwnProperty("a")&&(i=e.a));var d,g,p;return i=N(i),{ok:c,format:e.format||h,r:o(255,s(a.r,0)),g:o(255,s(a.g,0)),b:o(255,s(a.b,0)),a:i}}(e);this._originalInput=e,this._r=f.r,this._g=f.g,this._b=f.b,this._a=f.a,this._roundA=i(100*this._a)/100,this._format=l.format||f.format,this._gradientType=l.gradientType,this._r<1&&(this._r=i(this._r)),this._g<1&&(this._g=i(this._g)),this._b<1&&(this._b=i(this._b)),this._ok=f.ok,this._tc_id=a++}function f(e,t,n){e=j(e,255),t=j(t,255),n=j(n,255);var r,a,i=s(e,t,n),l=o(e,t,n),u=(i+l)/2;if(i==l)r=a=0;else{var f=i-l;switch(a=u>.5?f/(2-i-l):f/(i+l),i){case e:r=(t-n)/f+(t<n?6:0);break;case t:r=(n-e)/f+2;break;case n:r=(e-t)/f+4}r/=6}return{h:r,s:a,l:u}}function c(e,t,n){e=j(e,255),t=j(t,255),n=j(n,255);var r,a,i=s(e,t,n),l=o(e,t,n),u=i,f=i-l;if(a=0===i?0:f/i,i==l)r=0;else{switch(i){case e:r=(t-n)/f+(t<n?6:0);break;case t:r=(n-e)/f+2;break;case n:r=(e-t)/f+4}r/=6}return{h:r,s:a,v:u}}function h(e,t,n,r){var a=[G(i(e).toString(16)),G(i(t).toString(16)),G(i(n).toString(16))];return r&&a[0].charAt(0)==a[0].charAt(1)&&a[1].charAt(0)==a[1].charAt(1)&&a[2].charAt(0)==a[2].charAt(1)?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0):a.join("")}function d(e,t,n,r){return[G(T(r)),G(i(e).toString(16)),G(i(t).toString(16)),G(i(n).toString(16))].join("")}function g(e,t){t=0===t?0:t||10;var n=u(e).toHsl();return n.s-=t/100,n.s=O(n.s),u(n)}function p(e,t){t=0===t?0:t||10;var n=u(e).toHsl();return n.s+=t/100,n.s=O(n.s),u(n)}function b(e){return u(e).desaturate(100)}function m(e,t){t=0===t?0:t||10;var n=u(e).toHsl();return n.l+=t/100,n.l=O(n.l),u(n)}function v(e,t){t=0===t?0:t||10;var n=u(e).toRgb();return n.r=s(0,o(255,n.r-i(-t/100*255))),n.g=s(0,o(255,n.g-i(-t/100*255))),n.b=s(0,o(255,n.b-i(-t/100*255))),u(n)}function _(e,t){t=0===t?0:t||10;var n=u(e).toHsl();return n.l-=t/100,n.l=O(n.l),u(n)}function y(e,t){var n=u(e).toHsl(),r=(n.h+t)%360;return n.h=r<0?360+r:r,u(n)}function x(e){var t=u(e).toHsl();return t.h=(t.h+180)%360,u(t)}function k(e){var t=u(e).toHsl(),n=t.h;return[u(e),u({h:(n+120)%360,s:t.s,l:t.l}),u({h:(n+240)%360,s:t.s,l:t.l})]}function w(e){var t=u(e).toHsl(),n=t.h;return[u(e),u({h:(n+90)%360,s:t.s,l:t.l}),u({h:(n+180)%360,s:t.s,l:t.l}),u({h:(n+270)%360,s:t.s,l:t.l})]}function M(e){var t=u(e).toHsl(),n=t.h;return[u(e),u({h:(n+72)%360,s:t.s,l:t.l}),u({h:(n+216)%360,s:t.s,l:t.l})]}function A(e,t,n){t=t||6,n=n||30;var r=u(e).toHsl(),a=360/n,i=[u(e)];for(r.h=(r.h-(a*t>>1)+720)%360;--t;)r.h=(r.h+a)%360,i.push(u(r));return i}function C(e,t){t=t||6;for(var n=u(e).toHsv(),r=n.h,a=n.s,i=n.v,o=[],s=1/t;t--;)o.push(u({h:r,s:a,v:i})),i=(i+s)%1;return o}u.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,n,r,a=this.toRgb();return e=a.r/255,n=a.g/255,r=a.b/255,.2126*(e<=.03928?e/12.92:t.pow((e+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:t.pow((n+.055)/1.055,2.4))+.0722*(r<=.03928?r/12.92:t.pow((r+.055)/1.055,2.4))},setAlpha:function(e){return this._a=N(e),this._roundA=i(100*this._a)/100,this},toHsv:function(){var e=c(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=c(this._r,this._g,this._b),t=i(360*e.h),n=i(100*e.s),r=i(100*e.v);return 1==this._a?"hsv("+t+", "+n+"%, "+r+"%)":"hsva("+t+", "+n+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var e=f(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=f(this._r,this._g,this._b),t=i(360*e.h),n=i(100*e.s),r=i(100*e.l);return 1==this._a?"hsl("+t+", "+n+"%, "+r+"%)":"hsla("+t+", "+n+"%, "+r+"%, "+this._roundA+")"},toHex:function(e){return h(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){return function(e,t,n,r,a){var o=[G(i(e).toString(16)),G(i(t).toString(16)),G(i(n).toString(16)),G(T(r))];if(a&&o[0].charAt(0)==o[0].charAt(1)&&o[1].charAt(0)==o[1].charAt(1)&&o[2].charAt(0)==o[2].charAt(1)&&o[3].charAt(0)==o[3].charAt(1))return o[0].charAt(0)+o[1].charAt(0)+o[2].charAt(0)+o[3].charAt(0);return o.join("")}(this._r,this._g,this._b,this._a,e)},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:i(this._r),g:i(this._g),b:i(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+i(this._r)+", "+i(this._g)+", "+i(this._b)+")":"rgba("+i(this._r)+", "+i(this._g)+", "+i(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:i(100*j(this._r,255))+"%",g:i(100*j(this._g,255))+"%",b:i(100*j(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+i(100*j(this._r,255))+"%, "+i(100*j(this._g,255))+"%, "+i(100*j(this._b,255))+"%)":"rgba("+i(100*j(this._r,255))+"%, "+i(100*j(this._g,255))+"%, "+i(100*j(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(S[h(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+d(this._r,this._g,this._b,this._a),n=t,r=this._gradientType?"GradientType = 1, ":"";if(e){var a=u(e);n="#"+d(a._r,a._g,a._b,a._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+t+",endColorstr="+n+")"},toString:function(e){var t=!!e;e=e||this._format;var n=!1,r=this._a<1&&this._a>=0;return t||!r||"hex"!==e&&"hex6"!==e&&"hex3"!==e&&"hex4"!==e&&"hex8"!==e&&"name"!==e?("rgb"===e&&(n=this.toRgbString()),"prgb"===e&&(n=this.toPercentageRgbString()),"hex"!==e&&"hex6"!==e||(n=this.toHexString()),"hex3"===e&&(n=this.toHexString(!0)),"hex4"===e&&(n=this.toHex8String(!0)),"hex8"===e&&(n=this.toHex8String()),"name"===e&&(n=this.toName()),"hsl"===e&&(n=this.toHslString()),"hsv"===e&&(n=this.toHsvString()),n||this.toHexString()):"name"===e&&0===this._a?this.toName():this.toRgbString()},clone:function(){return u(this.toString())},_applyModification:function(e,t){var n=e.apply(null,[this].concat([].slice.call(t)));return this._r=n._r,this._g=n._g,this._b=n._b,this.setAlpha(n._a),this},lighten:function(){return this._applyModification(m,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(_,arguments)},desaturate:function(){return this._applyModification(g,arguments)},saturate:function(){return this._applyModification(p,arguments)},greyscale:function(){return this._applyModification(b,arguments)},spin:function(){return this._applyModification(y,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(A,arguments)},complement:function(){return this._applyCombination(x,arguments)},monochromatic:function(){return this._applyCombination(C,arguments)},splitcomplement:function(){return this._applyCombination(M,arguments)},triad:function(){return this._applyCombination(k,arguments)},tetrad:function(){return this._applyCombination(w,arguments)}},u.fromRatio=function(e,t){if("object"==typeof e){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]="a"===r?e[r]:H(e[r]));e=n}return u(e,t)},u.equals=function(e,t){return!(!e||!t)&&u(e).toRgbString()==u(t).toRgbString()},u.random=function(){return u.fromRatio({r:l(),g:l(),b:l()})},u.mix=function(e,t,n){n=0===n?0:n||50;var r=u(e).toRgb(),a=u(t).toRgb(),i=n/100;return u({r:(a.r-r.r)*i+r.r,g:(a.g-r.g)*i+r.g,b:(a.b-r.b)*i+r.b,a:(a.a-r.a)*i+r.a})}, | ||
// Version 1.0.6 three-globe - https://github.com/vasturiano/three-globe | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("three")):"function"==typeof define&&define.amd?define(["three"],t):(e=e||self).ThreeGlobe=t(e.THREE)}(this,function(e){"use strict";"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function t(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function n(e,t){return e(t={exports:{}},t.exports),t.exports}var r=n(function(e,t){"undefined"!=typeof self&&self,e.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){var r,a,o,i;i=function(e,t,n){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.stateInit,n=void 0===t?function(){return{}}:t,r=e.props,s=void 0===r?{}:r,u=e.methods,l=void 0===u?{}:u,c=e.aliases,f=void 0===c?{}:c,h=e.init,d=void 0===h?function(){}:h,g=e.update,p=void 0===g?function(){}:g,b=Object.keys(s).map(function(e){return new i(e,s[e])});return function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=Object.assign({},n instanceof Function?n(e):n,{initialised:!1});function r(t){return i(t,e),s(),r}var i=function(e,n){d.call(r,e,t,n),t.initialised=!0},s=(0,a.default)(function(){t.initialised&&p.call(r,t)},1);return b.forEach(function(e){r[e.name]=function(e){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1],a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(e,t){};return function(o){var i=t[e];return arguments.length?(t[e]=o,a.call(r,o,t,i),n&&s(),r):i}}(e.name,e.triggerUpdate,e.onChange)}),Object.keys(l).forEach(function(e){r[e]=function(){for(var n,a=arguments.length,o=Array(a),i=0;i<a;i++)o[i]=arguments[i];return(n=l[e]).call.apply(n,[r,t].concat(o))}}),Object.entries(f).forEach(function(e){var t=o(e,2),n=t[0],a=t[1];return r[n]=r[a]}),r.resetProps=function(){return b.forEach(function(e){r[e.name](e.defaultVal)}),r},r.resetProps(),t._rerender=s,r}};var r,a=(r=n)&&r.__esModule?r:{default:r},o=function(e,t){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return function(e,t){var n=[],r=!0,a=!1,o=void 0;try{for(var i,s=e[Symbol.iterator]();!(r=(i=s.next()).done)&&(n.push(i.value),!t||n.length!==t);r=!0);}catch(e){a=!0,o=e}finally{try{!r&&s.return&&s.return()}finally{if(a)throw o}}return n}(e,t);throw new TypeError("Invalid attempt to destructure non-iterable instance")},i=function e(t,n){var r=n.default,a=void 0===r?null:r,o=n.triggerUpdate,i=void 0===o||o,s=n.onChange,u=void 0===s?function(e,t){}:s;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.name=t,this.defaultVal=a,this.triggerUpdate=i,this.onChange=u};e.exports=t.default},a=[e,t,n(1)],void 0===(o="function"==typeof(r=i)?r.apply(t,a):r)||(e.exports=o)},function(e,t){e.exports=function(e,t,n){var r,a,o,i,s;function u(){var l=Date.now()-i;l<t&&l>=0?r=setTimeout(u,t-l):(r=null,n||(s=e.apply(o,a),o=a=null))}null==t&&(t=100);var l=function(){o=this,a=arguments,i=Date.now();var l=n&&!r;return r||(r=setTimeout(u,t)),l&&(s=e.apply(o,a),o=a=null),s};return l.clear=function(){r&&(clearTimeout(r),r=null)},l.flush=function(){r&&(s=e.apply(o,a),o=a=null,clearTimeout(r),r=null)},l}}])}),a=t(r),o=(r.Kapsule,n(function(e,t){e.exports=function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=0)}([function(e,t,n){var r,a,o;a=[e,t],void 0!==(o="function"==typeof(r=function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){return e instanceof Function?e:"string"==typeof e?function(t){return t[e]}:function(t){return e}},e.exports=t.default})?r.apply(t,a):r)&&(e.exports=o)}])})),i=t(o);o.accessorFn;function s(){return new u}function u(){this.reset()}u.prototype={constructor:u,reset:function(){this.s=this.t=0},add:function(e){c(l,e,this.t),c(this,l.s,this.s),this.s?this.t+=l.t:this.s=l.t},valueOf:function(){return this.s}};var l=new u;function c(e,t,n){var r=e.s=t+n,a=r-t,o=r-a;e.t=t-o+(n-a)}var f=Math.PI,h=f/2,d=180/f,g=f/180,p=Math.abs,b=Math.atan2,m=Math.cos,v=Math.sin,y=Math.sqrt;function _(e){return(e=v(e/2))*e}function x(){}function w(e,t){e&&A.hasOwnProperty(e.type)&&A[e.type](e,t)}var M={Feature:function(e,t){w(e.geometry,t)},FeatureCollection:function(e,t){for(var n=e.features,r=-1,a=n.length;++r<a;)w(n[r].geometry,t)}},A={Sphere:function(e,t){t.sphere()},Point:function(e,t){e=e.coordinates,t.point(e[0],e[1],e[2])},MultiPoint:function(e,t){for(var n=e.coordinates,r=-1,a=n.length;++r<a;)e=n[r],t.point(e[0],e[1],e[2])},LineString:function(e,t){C(e.coordinates,t,0)},MultiLineString:function(e,t){for(var n=e.coordinates,r=-1,a=n.length;++r<a;)C(n[r],t,0)},Polygon:function(e,t){S(e.coordinates,t)},MultiPolygon:function(e,t){for(var n=e.coordinates,r=-1,a=n.length;++r<a;)S(n[r],t)},GeometryCollection:function(e,t){for(var n=e.geometries,r=-1,a=n.length;++r<a;)w(n[r],t)}};function C(e,t,n){var r,a=-1,o=e.length-n;for(t.lineStart();++a<o;)r=e[a],t.point(r[0],r[1],r[2]);t.lineEnd()}function S(e,t){var n=-1,r=e.length;for(t.polygonStart();++n<r;)C(e[n],t,1);t.polygonEnd()}s(),s(),s(),s();function R(e,t){return e<t?-1:e>t?1:e>=t?0:NaN}1===(k=R).length&&(N=k,k=function(e,t){return R(N(e),t)});var k,N,L,O,j,E=s(),G={sphere:x,point:x,lineStart:function(){G.point=F,G.lineEnd=T},lineEnd:x,polygonStart:x,polygonEnd:x};function T(){G.point=G.lineEnd=x}function F(e,t){L=e*=g,O=v(t*=g),j=m(t),G.point=P}function P(e,t){e*=g;var n=v(t*=g),r=m(t),a=p(e-L),o=m(a),i=r*v(a),s=j*n-O*r*o,u=O*n+j*r*o;E.add(b(y(i*i+s*s),u)),L=e,O=n,j=r}function H(e){return E.reset(),function(e,t){e&&M.hasOwnProperty(e.type)?M[e.type](e,t):w(e,t)}(e,G),+E}var U=[null,null],I={type:"LineString",coordinates:U};function B(e,t){var n,r=e[0]*g,a=e[1]*g,o=t[0]*g,i=t[1]*g,s=m(a),u=v(a),l=m(i),c=v(i),f=s*m(r),p=s*v(r),x=l*m(o),w=l*v(o),M=2*((n=y(_(i-a)+s*l*_(o-r)))>1?h:n<-1?-h:Math.asin(n)),A=v(M),C=M?function(e){var t=v(e*=M)/A,n=v(M-e)/A,r=n*f+t*x,a=n*p+t*w,o=n*u+t*c;return[b(a,r)*d,b(o,y(r*r+a*a))*d]}:function(){return[r*d,a*d]};return C.distance=M,C}s(),s(),s();var z=n(function(e){!function(t){var n=/^\s+/,r=/\s+$/,a=0,o=t.round,i=t.min,s=t.max,u=t.random;function l(e,u){if(u=u||{},(e=e||"")instanceof l)return e;if(!(this instanceof l))return new l(e,u);var c=function(e){var a={r:0,g:0,b:0},o=1,u=null,l=null,c=null,f=!1,h=!1;"string"==typeof e&&(e=function(e){e=e.replace(n,"").replace(r,"").toLowerCase();var t,a=!1;if(R[e])e=R[e],a=!0;else if("transparent"==e)return{r:0,g:0,b:0,a:0,format:"name"};if(t=I.rgb.exec(e))return{r:t[1],g:t[2],b:t[3]};if(t=I.rgba.exec(e))return{r:t[1],g:t[2],b:t[3],a:t[4]};if(t=I.hsl.exec(e))return{h:t[1],s:t[2],l:t[3]};if(t=I.hsla.exec(e))return{h:t[1],s:t[2],l:t[3],a:t[4]};if(t=I.hsv.exec(e))return{h:t[1],s:t[2],v:t[3]};if(t=I.hsva.exec(e))return{h:t[1],s:t[2],v:t[3],a:t[4]};if(t=I.hex8.exec(e))return{r:j(t[1]),g:j(t[2]),b:j(t[3]),a:F(t[4]),format:a?"name":"hex8"};if(t=I.hex6.exec(e))return{r:j(t[1]),g:j(t[2]),b:j(t[3]),format:a?"name":"hex"};if(t=I.hex4.exec(e))return{r:j(t[1]+""+t[1]),g:j(t[2]+""+t[2]),b:j(t[3]+""+t[3]),a:F(t[4]+""+t[4]),format:a?"name":"hex8"};if(t=I.hex3.exec(e))return{r:j(t[1]+""+t[1]),g:j(t[2]+""+t[2]),b:j(t[3]+""+t[3]),format:a?"name":"hex"};return!1}(e));"object"==typeof e&&(B(e.r)&&B(e.g)&&B(e.b)?(d=e.r,g=e.g,p=e.b,a={r:255*L(d,255),g:255*L(g,255),b:255*L(p,255)},f=!0,h="%"===String(e.r).substr(-1)?"prgb":"rgb"):B(e.h)&&B(e.s)&&B(e.v)?(u=G(e.s),l=G(e.v),a=function(e,n,r){e=6*L(e,360),n=L(n,100),r=L(r,100);var a=t.floor(e),o=e-a,i=r*(1-n),s=r*(1-o*n),u=r*(1-(1-o)*n),l=a%6;return{r:255*[r,s,i,i,u,r][l],g:255*[u,r,r,s,i,i][l],b:255*[i,i,u,r,r,s][l]}}(e.h,u,l),f=!0,h="hsv"):B(e.h)&&B(e.s)&&B(e.l)&&(u=G(e.s),c=G(e.l),a=function(e,t,n){var r,a,o;function i(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}if(e=L(e,360),t=L(t,100),n=L(n,100),0===t)r=a=o=n;else{var s=n<.5?n*(1+t):n+t-n*t,u=2*n-s;r=i(u,s,e+1/3),a=i(u,s,e),o=i(u,s,e-1/3)}return{r:255*r,g:255*a,b:255*o}}(e.h,u,c),f=!0,h="hsl"),e.hasOwnProperty("a")&&(o=e.a));var d,g,p;return o=N(o),{ok:f,format:e.format||h,r:i(255,s(a.r,0)),g:i(255,s(a.g,0)),b:i(255,s(a.b,0)),a:o}}(e);this._originalInput=e,this._r=c.r,this._g=c.g,this._b=c.b,this._a=c.a,this._roundA=o(100*this._a)/100,this._format=u.format||c.format,this._gradientType=u.gradientType,this._r<1&&(this._r=o(this._r)),this._g<1&&(this._g=o(this._g)),this._b<1&&(this._b=o(this._b)),this._ok=c.ok,this._tc_id=a++}function c(e,t,n){e=L(e,255),t=L(t,255),n=L(n,255);var r,a,o=s(e,t,n),u=i(e,t,n),l=(o+u)/2;if(o==u)r=a=0;else{var c=o-u;switch(a=l>.5?c/(2-o-u):c/(o+u),o){case e:r=(t-n)/c+(t<n?6:0);break;case t:r=(n-e)/c+2;break;case n:r=(e-t)/c+4}r/=6}return{h:r,s:a,l:l}}function f(e,t,n){e=L(e,255),t=L(t,255),n=L(n,255);var r,a,o=s(e,t,n),u=i(e,t,n),l=o,c=o-u;if(a=0===o?0:c/o,o==u)r=0;else{switch(o){case e:r=(t-n)/c+(t<n?6:0);break;case t:r=(n-e)/c+2;break;case n:r=(e-t)/c+4}r/=6}return{h:r,s:a,v:l}}function h(e,t,n,r){var a=[E(o(e).toString(16)),E(o(t).toString(16)),E(o(n).toString(16))];return r&&a[0].charAt(0)==a[0].charAt(1)&&a[1].charAt(0)==a[1].charAt(1)&&a[2].charAt(0)==a[2].charAt(1)?a[0].charAt(0)+a[1].charAt(0)+a[2].charAt(0):a.join("")}function d(e,t,n,r){return[E(T(r)),E(o(e).toString(16)),E(o(t).toString(16)),E(o(n).toString(16))].join("")}function g(e,t){t=0===t?0:t||10;var n=l(e).toHsl();return n.s-=t/100,n.s=O(n.s),l(n)}function p(e,t){t=0===t?0:t||10;var n=l(e).toHsl();return n.s+=t/100,n.s=O(n.s),l(n)}function b(e){return l(e).desaturate(100)}function m(e,t){t=0===t?0:t||10;var n=l(e).toHsl();return n.l+=t/100,n.l=O(n.l),l(n)}function v(e,t){t=0===t?0:t||10;var n=l(e).toRgb();return n.r=s(0,i(255,n.r-o(-t/100*255))),n.g=s(0,i(255,n.g-o(-t/100*255))),n.b=s(0,i(255,n.b-o(-t/100*255))),l(n)}function y(e,t){t=0===t?0:t||10;var n=l(e).toHsl();return n.l-=t/100,n.l=O(n.l),l(n)}function _(e,t){var n=l(e).toHsl(),r=(n.h+t)%360;return n.h=r<0?360+r:r,l(n)}function x(e){var t=l(e).toHsl();return t.h=(t.h+180)%360,l(t)}function w(e){var t=l(e).toHsl(),n=t.h;return[l(e),l({h:(n+120)%360,s:t.s,l:t.l}),l({h:(n+240)%360,s:t.s,l:t.l})]}function M(e){var t=l(e).toHsl(),n=t.h;return[l(e),l({h:(n+90)%360,s:t.s,l:t.l}),l({h:(n+180)%360,s:t.s,l:t.l}),l({h:(n+270)%360,s:t.s,l:t.l})]}function A(e){var t=l(e).toHsl(),n=t.h;return[l(e),l({h:(n+72)%360,s:t.s,l:t.l}),l({h:(n+216)%360,s:t.s,l:t.l})]}function C(e,t,n){t=t||6,n=n||30;var r=l(e).toHsl(),a=360/n,o=[l(e)];for(r.h=(r.h-(a*t>>1)+720)%360;--t;)r.h=(r.h+a)%360,o.push(l(r));return o}function S(e,t){t=t||6;for(var n=l(e).toHsv(),r=n.h,a=n.s,o=n.v,i=[],s=1/t;t--;)i.push(l({h:r,s:a,v:o})),o=(o+s)%1;return i}l.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var e=this.toRgb();return(299*e.r+587*e.g+114*e.b)/1e3},getLuminance:function(){var e,n,r,a=this.toRgb();return e=a.r/255,n=a.g/255,r=a.b/255,.2126*(e<=.03928?e/12.92:t.pow((e+.055)/1.055,2.4))+.7152*(n<=.03928?n/12.92:t.pow((n+.055)/1.055,2.4))+.0722*(r<=.03928?r/12.92:t.pow((r+.055)/1.055,2.4))},setAlpha:function(e){return this._a=N(e),this._roundA=o(100*this._a)/100,this},toHsv:function(){var e=f(this._r,this._g,this._b);return{h:360*e.h,s:e.s,v:e.v,a:this._a}},toHsvString:function(){var e=f(this._r,this._g,this._b),t=o(360*e.h),n=o(100*e.s),r=o(100*e.v);return 1==this._a?"hsv("+t+", "+n+"%, "+r+"%)":"hsva("+t+", "+n+"%, "+r+"%, "+this._roundA+")"},toHsl:function(){var e=c(this._r,this._g,this._b);return{h:360*e.h,s:e.s,l:e.l,a:this._a}},toHslString:function(){var e=c(this._r,this._g,this._b),t=o(360*e.h),n=o(100*e.s),r=o(100*e.l);return 1==this._a?"hsl("+t+", "+n+"%, "+r+"%)":"hsla("+t+", "+n+"%, "+r+"%, "+this._roundA+")"},toHex:function(e){return h(this._r,this._g,this._b,e)},toHexString:function(e){return"#"+this.toHex(e)},toHex8:function(e){return function(e,t,n,r,a){var i=[E(o(e).toString(16)),E(o(t).toString(16)),E(o(n).toString(16)),E(T(r))];if(a&&i[0].charAt(0)==i[0].charAt(1)&&i[1].charAt(0)==i[1].charAt(1)&&i[2].charAt(0)==i[2].charAt(1)&&i[3].charAt(0)==i[3].charAt(1))return i[0].charAt(0)+i[1].charAt(0)+i[2].charAt(0)+i[3].charAt(0);return i.join("")}(this._r,this._g,this._b,this._a,e)},toHex8String:function(e){return"#"+this.toHex8(e)},toRgb:function(){return{r:o(this._r),g:o(this._g),b:o(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+o(this._r)+", "+o(this._g)+", "+o(this._b)+")":"rgba("+o(this._r)+", "+o(this._g)+", "+o(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:o(100*L(this._r,255))+"%",g:o(100*L(this._g,255))+"%",b:o(100*L(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+o(100*L(this._r,255))+"%, "+o(100*L(this._g,255))+"%, "+o(100*L(this._b,255))+"%)":"rgba("+o(100*L(this._r,255))+"%, "+o(100*L(this._g,255))+"%, "+o(100*L(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(k[h(this._r,this._g,this._b,!0)]||!1)},toFilter:function(e){var t="#"+d(this._r,this._g,this._b,this._a),n=t,r=this._gradientType?"GradientType = 1, ":"";if(e){var a=l(e);n="#"+d(a._r,a._g,a._b,a._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+t+",endColorstr="+n+")"},toString:function(e){var t=!!e;e=e||this._format;var n=!1,r=this._a<1&&this._a>=0;return t||!r||"hex"!==e&&"hex6"!==e&&"hex3"!==e&&"hex4"!==e&&"hex8"!==e&&"name"!==e?("rgb"===e&&(n=this.toRgbString()),"prgb"===e&&(n=this.toPercentageRgbString()),"hex"!==e&&"hex6"!==e||(n=this.toHexString()),"hex3"===e&&(n=this.toHexString(!0)),"hex4"===e&&(n=this.toHex8String(!0)),"hex8"===e&&(n=this.toHex8String()),"name"===e&&(n=this.toName()),"hsl"===e&&(n=this.toHslString()),"hsv"===e&&(n=this.toHsvString()),n||this.toHexString()):"name"===e&&0===this._a?this.toName():this.toRgbString()},clone:function(){return l(this.toString())},_applyModification:function(e,t){var n=e.apply(null,[this].concat([].slice.call(t)));return this._r=n._r,this._g=n._g,this._b=n._b,this.setAlpha(n._a),this},lighten:function(){return this._applyModification(m,arguments)},brighten:function(){return this._applyModification(v,arguments)},darken:function(){return this._applyModification(y,arguments)},desaturate:function(){return this._applyModification(g,arguments)},saturate:function(){return this._applyModification(p,arguments)},greyscale:function(){return this._applyModification(b,arguments)},spin:function(){return this._applyModification(_,arguments)},_applyCombination:function(e,t){return e.apply(null,[this].concat([].slice.call(t)))},analogous:function(){return this._applyCombination(C,arguments)},complement:function(){return this._applyCombination(x,arguments)},monochromatic:function(){return this._applyCombination(S,arguments)},splitcomplement:function(){return this._applyCombination(A,arguments)},triad:function(){return this._applyCombination(w,arguments)},tetrad:function(){return this._applyCombination(M,arguments)}},l.fromRatio=function(e,t){if("object"==typeof e){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]="a"===r?e[r]:G(e[r]));e=n}return l(e,t)},l.equals=function(e,t){return!(!e||!t)&&l(e).toRgbString()==l(t).toRgbString()},l.random=function(){return l.fromRatio({r:u(),g:u(),b:u()})},l.mix=function(e,t,n){n=0===n?0:n||50;var r=l(e).toRgb(),a=l(t).toRgb(),o=n/100;return l({r:(a.r-r.r)*o+r.r,g:(a.g-r.g)*o+r.g,b:(a.b-r.b)*o+r.b,a:(a.a-r.a)*o+r.a})}, | ||
// <http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef (WCAG Version 2) | ||
// Analyze the 2 colors and returns the color contrast defined by (WCAG Version 2) | ||
u.readability=function(e,n){var r=u(e),a=u(n);return(t.max(r.getLuminance(),a.getLuminance())+.05)/(t.min(r.getLuminance(),a.getLuminance())+.05)},u.isReadable=function(e,t,n){var r,a,i=u.readability(e,t);switch(a=!1,(r=function(e){var t,n;t=((e=e||{level:"AA",size:"small"}).level||"AA").toUpperCase(),n=(e.size||"small").toLowerCase(),"AA"!==t&&"AAA"!==t&&(t="AA");"small"!==n&&"large"!==n&&(n="small");return{level:t,size:n}}(n)).level+r.size){case"AAsmall":case"AAAlarge":a=i>=4.5;break;case"AAlarge":a=i>=3;break;case"AAAsmall":a=i>=7}return a},u.mostReadable=function(e,t,n){var r,a,i,o,s=null,l=0;a=(n=n||{}).includeFallbackColors,i=n.level,o=n.size;for(var f=0;f<t.length;f++)(r=u.readability(e,t[f]))>l&&(l=r,s=u(t[f]));return u.isReadable(e,s,{level:i,size:o})||!a?s:(n.includeFallbackColors=!1,u.mostReadable(e,["#fff","#000"],n))};var R=u.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},S=u.hexNames=function(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[e[n]]=n);return t}(R);function N(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function j(e,n){(function(e){return"string"==typeof e&&-1!=e.indexOf(".")&&1===parseFloat(e)})(e)&&(e="100%");var r=function(e){return"string"==typeof e&&-1!=e.indexOf("%")}(e);return e=o(n,s(0,parseFloat(e))),r&&(e=parseInt(e*n,10)/100),t.abs(e-n)<1e-6?1:e%n/parseFloat(n)}function O(e){return o(1,s(0,e))}function L(e){return parseInt(e,16)}function G(e){return 1==e.length?"0"+e:""+e}function H(e){return e<=1&&(e=100*e+"%"),e}function T(e){return t.round(255*parseFloat(e)).toString(16)}function E(e){return L(e)/255}var F,I,P,U=(I="[\\s|\\(]+("+(F="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+F+")[,|\\s]+("+F+")\\s*\\)?",P="[\\s|\\(]+("+F+")[,|\\s]+("+F+")[,|\\s]+("+F+")[,|\\s]+("+F+")\\s*\\)?",{CSS_UNIT:new RegExp(F),rgb:new RegExp("rgb"+I),rgba:new RegExp("rgba"+P),hsl:new RegExp("hsl"+I),hsla:new RegExp("hsla"+P),hsv:new RegExp("hsv"+I),hsva:new RegExp("hsva"+P),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function D(e){return!!U.CSS_UNIT.exec(e)}e.exports?e.exports=u:window.tinycolor=u}(Math)}));const l=e=>isNaN(e)?parseInt(s(e).toHex(),16):e,u=e=>isNaN(e)?s(e).getAlpha():1,f=window.THREE?window.THREE:{AdditiveBlending:e.AdditiveBlending,BackSide:e.BackSide,Color:e.Color,CylinderGeometry:e.CylinderGeometry,FaceColors:e.FaceColors,Geometry:e.Geometry,Group:e.Group,Matrix4:e.Matrix4,Mesh:e.Mesh,MeshBasicMaterial:e.MeshBasicMaterial,MeshLambertMaterial:e.MeshLambertMaterial,QuadraticBezierCurve3:e.QuadraticBezierCurve3,ShaderMaterial:e.ShaderMaterial,SphereGeometry:e.SphereGeometry,TextureLoader:e.TextureLoader,TubeGeometry:e.TubeGeometry,UniformsUtils:e.UniformsUtils,Vector3:e.Vector3},c=e=>{const t=e=>{e instanceof Array?e.forEach(t):(e.map&&e.map.dispose(),e.dispose())},n=e=>{e.geometry&&e.geometry.dispose(),e.material&&t(e.material),e.texture&&e.texture.dispose(),e.children&&e.children.forEach(n)};for(;e.children.length;){const e=state.pointsG.children[0];state.pointsG.remove(e),n(e)}},h={earth:{uniforms:{texture:{type:"t",value:null}},vertexShader:["varying vec3 vNormal;","varying vec2 vUv;","void main() {","gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );","vNormal = normalize( normalMatrix * normal );","vUv = uv;","}"].join("\n"),fragmentShader:["uniform sampler2D texture;","varying vec3 vNormal;","varying vec2 vUv;","void main() {","vec3 diffuse = texture2D( texture, vUv ).xyz;","float intensity = 1.05 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) );","vec3 atmosphere = vec3( 1.0, 1.0, 1.0 ) * pow( intensity, 3.0 );","gl_FragColor = vec4( diffuse + atmosphere, 1.0 );","}"].join("\n")},atmosphere:{uniforms:{},vertexShader:["varying vec3 vNormal;","void main() {","vNormal = normalize( normalMatrix * normal );","gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );","}"].join("\n"),fragmentShader:["varying vec3 vNormal;","void main() {","float intensity = pow( 0.8 - dot( vNormal, vec3( 0, 0, 1.0 ) ), 12.0 );","gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ) * intensity;","}"].join("\n")}};return function(e,t=Object,n=!1){class r extends t{constructor(...t){super(...t),this.__kapsuleInstance=e()(...n?[this]:[],...t)}}return Object.keys(e()).forEach(e=>r.prototype[e]=function(...t){const n=this.__kapsuleInstance[e](...t);return n===this.__kapsuleInstance?this:n}),r}(a({props:{globeImageUrl:{onChange(e){this._loadGlobeImage(e)},triggerUpdate:!1},pointsData:{default:[],onChange(e,t){t.pointsNeedsRepopulating=!0}},pointLat:{default:"lat",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointLng:{default:"lng",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointColor:{default:()=>"#ffffaa",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointHeight:{default:.1,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointRadius:{default:.25,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointResolution:{default:12,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointsMerge:{default:!1,onChange(e,t){t.pointsNeedsRepopulating=!0}},linksData:{default:[],onChange(e,t){t.linksNeedsRepopulating=!0}},linkStartLat:{default:"startLat",onChange(e,t){t.linksNeedsRepopulating=!0}},linkStartLng:{default:"endLng",onChange(e,t){t.linksNeedsRepopulating=!0}},linkEndLat:{default:"endLat",onChange(e,t){t.linksNeedsRepopulating=!0}},linkEndLng:{default:"endLng",onChange(e,t){t.linksNeedsRepopulating=!0}},linkColor:{default:()=>"#ffffaa",onChange(e,t){t.linksNeedsRepopulating=!0}},linkHeight:{default:.4,onChange(e,t){t.linksNeedsRepopulating=!0}},linkDiameter:{default:.2,onChange(e,t){t.linksNeedsRepopulating=!0}},linkCurveResolution:{default:64,onChange(e,t){t.linksNeedsRepopulating=!0}},linkCircularResolution:{default:6,onChange(e,t){t.linksNeedsRepopulating=!0}},linksMerge:{default:!1,onChange(e,t){t.linksNeedsRepopulating=!0}},customLayerData:{default:[],onChange(e,t){t.customLayerNeedsRepopulating=!0}},customThreeObject:{onChange(e,t){t.customLayerNeedsRepopulating=!0}}},methods:{getCoords(e,t,n,r=0){const a=(90-t)*Math.PI/180,i=(-45-n)*Math.PI/180,o=100*(1+r);return{x:o*Math.sin(a)*Math.cos(i),y:o*Math.cos(a),z:o*Math.sin(a)*Math.sin(i)}},_loadGlobeImage:function(e,t){if(e.globeObj&&t){const n=h.earth,r=f.UniformsUtils.clone(n.uniforms);r.texture.value=(new f.TextureLoader).load(t),e.globeObj.material=new f.ShaderMaterial({uniforms:r,vertexShader:n.vertexShader,fragmentShader:n.fragmentShader})}return this}},stateInit:()=>({pointsNeedsRepopulating:!0,linksNeedsRepopulating:!0,customLayerNeedsRepopulating:!0}),init(e,t){t.scene=e,c(t.scene);const n=new f.SphereGeometry(100,40,30),r=t.globeObj=new f.Mesh(n,new f.MeshBasicMaterial({color:0}));r.rotation.y=Math.PI/4,r.__globeObjType="globe",t.scene.add(r),t.globeImageUrl&&this._loadGlobeImage(t.globeImageUrl);{const e=h.atmosphere,r=f.UniformsUtils.clone(e.uniforms),a=new f.ShaderMaterial({uniforms:r,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,side:f.BackSide,blending:f.AdditiveBlending,transparent:!0}),i=new f.Mesh(n,a);i.scale.set(1.1,1.1,1.1),i.__globeObjType="atmosphere",t.scene.add(i)}t.scene.add(t.pointsG=new f.Group),t.scene.add(t.linksG=new f.Group),t.scene.add(t.customLayerG=new f.Group)},update(e){const t=2*Math.PI*100/360;if(e.pointsNeedsRepopulating){e.pointsNeedRepopulating=!1,c(e.pointsG);const n=o(e.pointLat),r=o(e.pointLng),a=o(e.pointHeight),i=o(e.pointRadius),s=o(e.pointColor),h=new f.CylinderGeometry(1,1,1,e.pointResolution);h.applyMatrix((new f.Matrix4).makeRotationX(Math.PI/2)),h.applyMatrix((new f.Matrix4).makeTranslation(0,0,-.5));const d=[];if(e.pointsData.forEach(o=>{const s=new f.Mesh(h);Object.assign(s.position,this.getCoords(n(o),r(o))),s.lookAt(e.globeObj.position),s.scale.x=s.scale.y=Math.min(30,i(o))*t,s.scale.z=Math.max(100*a(o),.1),s.__globeObjType="point",s.__data=o,d.push(s)}),e.pointsMerge){const t=new f.Geometry;d.forEach(e=>{const n=e.__data,r=new f.Color(s(n));e.geometry.faces.forEach(e=>e.color=r),e.updateMatrix(),t.merge(e.geometry,e.matrix)});const n=new f.Mesh(t,new f.MeshBasicMaterial({color:16777215,vertexColors:f.FaceColors,morphTargets:!1}));n.__globeObjType="points",n.__data=e.pointsData,e.pointsG.add(n)}else{const t={};d.forEach(n=>{const r=n.__data,a=s(r),i=u(a);t.hasOwnProperty(a)||(t[a]=new f.MeshLambertMaterial({color:l(a),transparent:i<1,opacity:i})),n.material=t[a],e.pointsG.add(r.__threeObj=n)})}}if(e.linksNeedsRepopulating){e.linksNeedsRepopulating=!1,c(e.linksG);const t=o(e.linkStartLat),n=o(e.linkStartLng),r=o(e.linkEndLat),a=o(e.linkEndLng),i=o(e.linkHeight),s=o(e.linkDiameter),h=o(e.linkColor),d=[];if(e.linksData.forEach(o=>{const l=[...[t,n].map(e=>e(o)),0],u=[...[r,a].map(e=>e(o)),0],c=(e,t)=>e+(t-e)/2,h=[l,[c(l[0],u[0]),c(l[1],u[1]),2*i(o)],u].map(([e,t,n])=>{const r=this.getCoords(e,t,n);return new f.Vector3(r.x,r.y,r.z)}),g=new f.QuadraticBezierCurve3(...h),p=new f.TubeGeometry(g,e.linkCurveResolution,s(o)/2,e.linkCircularResolution),b=new f.Mesh(p);b.__globeObjType="link",b.__data=o,d.push(b)}),e.linksMerge){const t=new f.Geometry;d.forEach(e=>{const n=e.__data,r=new f.Color(h(n));e.geometry.faces.forEach(e=>e.color=r),e.updateMatrix(),t.merge(e.geometry,e.matrix)});const n=new f.Mesh(t,new f.MeshBasicMaterial({color:16777215,vertexColors:f.FaceColors,morphTargets:!1}));n.__globeObjType="links",n.__data=e.linksData,e.linksG.add(n)}else{const t={};d.forEach(n=>{const r=n.__data,a=h(r),i=u(a);t.hasOwnProperty(a)||(t[a]=new f.MeshLambertMaterial({color:l(a),transparent:i<1,opacity:i})),n.material=t[a],e.linksG.add(r.__threeObj=n)})}}if(e.customLayerNeedsRepopulating){e.customLayerNeedsRepopulating=!1,c(e.customLayerG);const t=o(e.customThreeObject);e.customLayerData.forEach(n=>{let r=t(n,100);r&&(e.customThreeObject===r&&(r=r.clone()),r.__globeObjType="custom",r.__data=n,e.customLayerG.add(n.__threeObj=r))})}}}),e.Group,!0)}); | ||
l.readability=function(e,n){var r=l(e),a=l(n);return(t.max(r.getLuminance(),a.getLuminance())+.05)/(t.min(r.getLuminance(),a.getLuminance())+.05)},l.isReadable=function(e,t,n){var r,a,o=l.readability(e,t);switch(a=!1,(r=function(e){var t,n;t=((e=e||{level:"AA",size:"small"}).level||"AA").toUpperCase(),n=(e.size||"small").toLowerCase(),"AA"!==t&&"AAA"!==t&&(t="AA");"small"!==n&&"large"!==n&&(n="small");return{level:t,size:n}}(n)).level+r.size){case"AAsmall":case"AAAlarge":a=o>=4.5;break;case"AAlarge":a=o>=3;break;case"AAAsmall":a=o>=7}return a},l.mostReadable=function(e,t,n){var r,a,o,i,s=null,u=0;a=(n=n||{}).includeFallbackColors,o=n.level,i=n.size;for(var c=0;c<t.length;c++)(r=l.readability(e,t[c]))>u&&(u=r,s=l(t[c]));return l.isReadable(e,s,{level:o,size:i})||!a?s:(n.includeFallbackColors=!1,l.mostReadable(e,["#fff","#000"],n))};var R=l.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},k=l.hexNames=function(e){var t={};for(var n in e)e.hasOwnProperty(n)&&(t[e[n]]=n);return t}(R);function N(e){return e=parseFloat(e),(isNaN(e)||e<0||e>1)&&(e=1),e}function L(e,n){(function(e){return"string"==typeof e&&-1!=e.indexOf(".")&&1===parseFloat(e)})(e)&&(e="100%");var r=function(e){return"string"==typeof e&&-1!=e.indexOf("%")}(e);return e=i(n,s(0,parseFloat(e))),r&&(e=parseInt(e*n,10)/100),t.abs(e-n)<1e-6?1:e%n/parseFloat(n)}function O(e){return i(1,s(0,e))}function j(e){return parseInt(e,16)}function E(e){return 1==e.length?"0"+e:""+e}function G(e){return e<=1&&(e=100*e+"%"),e}function T(e){return t.round(255*parseFloat(e)).toString(16)}function F(e){return j(e)/255}var P,H,U,I=(H="[\\s|\\(]+("+(P="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)")+")[,|\\s]+("+P+")[,|\\s]+("+P+")\\s*\\)?",U="[\\s|\\(]+("+P+")[,|\\s]+("+P+")[,|\\s]+("+P+")[,|\\s]+("+P+")\\s*\\)?",{CSS_UNIT:new RegExp(P),rgb:new RegExp("rgb"+H),rgba:new RegExp("rgba"+U),hsl:new RegExp("hsl"+H),hsla:new RegExp("hsla"+U),hsv:new RegExp("hsv"+H),hsva:new RegExp("hsva"+U),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/});function B(e){return!!I.CSS_UNIT.exec(e)}e.exports?e.exports=l:window.tinycolor=l}(Math)});const D=e=>isNaN(e)?parseInt(z(e).toHex(),16):e,q=e=>isNaN(e)?z(e).getAlpha():1,V=window.THREE?window.THREE:{AdditiveBlending:e.AdditiveBlending,BackSide:e.BackSide,BufferGeometry:e.BufferGeometry,Color:e.Color,CylinderGeometry:e.CylinderGeometry,FaceColors:e.FaceColors,Geometry:e.Geometry,Group:e.Group,Line:e.Line,Matrix4:e.Matrix4,Mesh:e.Mesh,MeshBasicMaterial:e.MeshBasicMaterial,MeshLambertMaterial:e.MeshLambertMaterial,QuadraticBezierCurve3:e.QuadraticBezierCurve3,ShaderMaterial:e.ShaderMaterial,SphereGeometry:e.SphereGeometry,TextureLoader:e.TextureLoader,TubeGeometry:e.TubeGeometry,UniformsUtils:e.UniformsUtils,Vector3:e.Vector3},$=e=>{const t=e=>{e instanceof Array?e.forEach(t):(e.map&&e.map.dispose(),e.dispose())},n=e=>{e.geometry&&e.geometry.dispose(),e.material&&t(e.material),e.texture&&e.texture.dispose(),e.children&&e.children.forEach(n)};for(;e.children.length;){const e=state.pointsG.children[0];state.pointsG.remove(e),n(e)}},Q={earth:{uniforms:{texture:{type:"t",value:null}},vertexShader:["varying vec3 vNormal;","varying vec2 vUv;","void main() {","gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );","vNormal = normalize( normalMatrix * normal );","vUv = uv;","}"].join("\n"),fragmentShader:["uniform sampler2D texture;","varying vec3 vNormal;","varying vec2 vUv;","void main() {","vec3 diffuse = texture2D( texture, vUv ).xyz;","float intensity = 1.05 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) );","vec3 atmosphere = vec3( 1.0, 1.0, 1.0 ) * pow( intensity, 3.0 );","gl_FragColor = vec4( diffuse + atmosphere, 1.0 );","}"].join("\n")},atmosphere:{uniforms:{},vertexShader:["varying vec3 vNormal;","void main() {","vNormal = normalize( normalMatrix * normal );","gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );","}"].join("\n"),fragmentShader:["varying vec3 vNormal;","void main() {","float intensity = pow( 0.8 - dot( vNormal, vec3( 0, 0, 1.0 ) ), 12.0 );","gl_FragColor = vec4( 1.0, 1.0, 1.0, 1.0 ) * intensity;","}"].join("\n")}};return function(e,t=Object,n=!1){class r extends t{constructor(...t){super(...t),this.__kapsuleInstance=e()(...n?[this]:[],...t)}}return Object.keys(e()).forEach(e=>r.prototype[e]=function(...t){const n=this.__kapsuleInstance[e](...t);return n===this.__kapsuleInstance?this:n}),r}(a({props:{globeImageUrl:{onChange(e,t){t.globeNeedsUpdate=!0}},pointsData:{default:[],onChange(e,t){t.pointsNeedsRepopulating=!0}},pointLat:{default:"lat",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointLng:{default:"lng",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointColor:{default:()=>"#ffffaa",onChange(e,t){t.pointsNeedsRepopulating=!0}},pointAltitude:{default:.1,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointRadius:{default:.25,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointResolution:{default:12,onChange(e,t){t.pointsNeedsRepopulating=!0}},pointsMerge:{default:!1,onChange(e,t){t.pointsNeedsRepopulating=!0}},arcsData:{default:[],onChange(e,t){t.arcsNeedsRepopulating=!0}},arcStartLat:{default:"startLat",onChange(e,t){t.arcsNeedsRepopulating=!0}},arcStartLng:{default:"startLng",onChange(e,t){t.arcsNeedsRepopulating=!0}},arcEndLat:{default:"endLat",onChange(e,t){t.arcsNeedsRepopulating=!0}},arcEndLng:{default:"endLng",onChange(e,t){t.arcsNeedsRepopulating=!0}},arcColor:{default:()=>"#ffffaa",onChange(e,t){t.arcsNeedsRepopulating=!0}},arcAltitude:{onChange(e,t){t.arcsNeedsRepopulating=!0}},arcAltitudeAutoScale:{default:.5,onChange(e,t){t.arcsNeedsRepopulating=!0}},arcStroke:{onChange(e,t){t.arcsNeedsRepopulating=!0}},arcCurveResolution:{default:64,onChange(e,t){t.arcsNeedsRepopulating=!0}},arcCircularResolution:{default:6,onChange(e,t){t.arcsNeedsRepopulating=!0}},arcsMerge:{default:!1,onChange(e,t){t.arcsNeedsRepopulating=!0}},customLayerData:{default:[],onChange(e,t){t.customLayerNeedsRepopulating=!0}},customThreeObject:{onChange(e,t){t.customLayerNeedsRepopulating=!0}}},methods:{getCoords(e,t,n,r=0){const a=(90-t)*Math.PI/180,o=(-45-n)*Math.PI/180,i=100*(1+r);return{x:i*Math.sin(a)*Math.cos(o),y:i*Math.cos(a),z:i*Math.sin(a)*Math.sin(o)}}},stateInit:()=>({globeNeedsUpdate:!0,pointsNeedsRepopulating:!0,arcsNeedsRepopulating:!0,customLayerNeedsRepopulating:!0}),init(e,t){t.scene=e,$(t.scene);const n=new V.SphereGeometry(100,40,30),r=t.globeObj=new V.Mesh(n,new V.MeshBasicMaterial({color:0}));r.rotation.y=Math.PI/4,r.__globeObjType="globe",t.scene.add(r);{const e=Q.atmosphere,r=V.UniformsUtils.clone(e.uniforms),a=new V.ShaderMaterial({uniforms:r,vertexShader:e.vertexShader,fragmentShader:e.fragmentShader,side:V.BackSide,blending:V.AdditiveBlending,transparent:!0}),o=new V.Mesh(n,a);o.scale.set(1.1,1.1,1.1),o.__globeObjType="atmosphere",t.scene.add(o)}t.scene.add(t.pointsG=new V.Group),t.scene.add(t.arcsG=new V.Group),t.scene.add(t.customLayerG=new V.Group)},update(e){const t=2*Math.PI*100/360;if(e.globeNeedsUpdate)if(e.globeNeedsUpdate=!1,e.globeImageUrl){const t=Q.earth,n=V.UniformsUtils.clone(t.uniforms);n.texture.value=(new V.TextureLoader).load(e.globeImageUrl),e.globeObj.material=new V.ShaderMaterial({uniforms:n,vertexShader:t.vertexShader,fragmentShader:t.fragmentShader})}else e.globeObj.material=new V.MeshBasicMaterial({color:0});if(e.pointsNeedsRepopulating){e.pointsNeedsRepopulating=!1,$(e.pointsG);const n=i(e.pointLat),r=i(e.pointLng),a=i(e.pointAltitude),o=i(e.pointRadius),s=i(e.pointColor),u=new V.CylinderGeometry(1,1,1,e.pointResolution);u.applyMatrix((new V.Matrix4).makeRotationX(Math.PI/2)),u.applyMatrix((new V.Matrix4).makeTranslation(0,0,-.5));const l=[];if(e.pointsData.forEach(i=>{const s=new V.Mesh(u);Object.assign(s.position,this.getCoords(n(i),r(i))),s.lookAt(e.globeObj.position),s.scale.x=s.scale.y=Math.min(30,o(i))*t,s.scale.z=Math.max(100*a(i),.1),s.__globeObjType="point",s.__data=i,l.push(s)}),e.pointsMerge){const t=new V.Geometry;l.forEach(e=>{const n=e.__data,r=new V.Color(s(n));e.geometry.faces.forEach(e=>e.color=r),e.updateMatrix(),t.merge(e.geometry,e.matrix)});const n=new V.Mesh(t,new V.MeshBasicMaterial({color:16777215,vertexColors:V.FaceColors,morphTargets:!1}));n.__globeObjType="points",n.__data=e.pointsData,e.pointsG.add(n)}else{const t={};l.forEach(n=>{const r=n.__data,a=s(r),o=q(a);t.hasOwnProperty(a)||(t[a]=new V.MeshLambertMaterial({color:D(a),transparent:o<1,opacity:o})),n.material=t[a],e.pointsG.add(r.__threeObj=n)})}}if(e.arcsNeedsRepopulating){e.arcsNeedsRepopulating=!1,$(e.arcsG);const t=i(e.arcStartLat),n=i(e.arcStartLng),r=i(e.arcEndLat),a=i(e.arcEndLng),o=i(e.arcAltitude),s=i(e.arcAltitudeAutoScale),u=i(e.arcStroke),l=i(e.arcColor),c=[];if(e.arcsData.forEach(i=>{let l;{const e=([e,t,n])=>{const{x:r,y:a,z:o}=this.getCoords(t,e,n);return new V.Vector3(r,a,o)},u=[n,t].map(e=>e(i)),c=[a,r].map(e=>e(i));let f=o(i);null==f&&(f=function(e,t){return U[0]=e,U[1]=t,H(I)}(u,c)/2*s(i));const h=B(u,c),[d,g]=[.25,.75].map(e=>[...h(e),1.5*f]);l=new V.CubicBezierCurve3(...[u,d,g,c].map(e))}const f=u(i),h=null==f?new V.Line((new V.BufferGeometry).setFromPoints(l.getPoints(e.arcCurveResolution))):new V.Mesh(new V.TubeGeometry(l,e.arcCurveResolution,f/2,e.arcCircularResolution));h.__globeObjType="arc",h.__data=i,c.push(h)}),e.arcsMerge){const t=new V.Geometry;c.forEach(e=>{const n=e.__data,r=new V.Color(l(n));e.geometry.faces.forEach(e=>e.color=r),e.updateMatrix(),t.merge(e.geometry,e.matrix)});const n=new V.Mesh(t,new V.MeshBasicMaterial({color:16777215,vertexColors:V.FaceColors,morphTargets:!1}));n.__globeObjType="arcs",n.__data=e.arcsData,e.arcsG.add(n)}else{const t={};c.forEach(n=>{const r=n.__data,a=l(r),o=q(a);t.hasOwnProperty(a)||(t[a]=new V.MeshLambertMaterial({color:D(a),transparent:o<1,opacity:o})),n.material=t[a],e.arcsG.add(r.__threeObj=n)})}}if(e.customLayerNeedsRepopulating){e.customLayerNeedsRepopulating=!1,$(e.customLayerG);const t=i(e.customThreeObject);e.customLayerData.forEach(n=>{let r=t(n,100);r&&(e.customThreeObject===r&&(r=r.clone()),r.__globeObjType="custom",r.__data=n,e.customLayerG.add(n.__threeObj=r))})}}}),e.Group,!0)}); |
@@ -1,4 +0,5 @@ | ||
import { AdditiveBlending, BackSide, Color, CylinderGeometry, FaceColors, Geometry, Group, Matrix4, Mesh, MeshBasicMaterial, MeshLambertMaterial, QuadraticBezierCurve3, ShaderMaterial, SphereGeometry, TextureLoader, TubeGeometry, UniformsUtils, Vector3 } from 'three'; | ||
import { AdditiveBlending, BackSide, BufferGeometry, Color, CylinderGeometry, FaceColors, Geometry, Group, Line, Matrix4, Mesh, MeshBasicMaterial, MeshLambertMaterial, QuadraticBezierCurve3, ShaderMaterial, SphereGeometry, TextureLoader, TubeGeometry, UniformsUtils, Vector3 } from 'three'; | ||
import Kapsule from 'kapsule'; | ||
import accessorFn from 'accessor-fn'; | ||
import { geoDistance, geoInterpolate } from 'd3-geo'; | ||
import tinyColor from 'tinycolor2'; | ||
@@ -14,2 +15,3 @@ | ||
BackSide, | ||
BufferGeometry, | ||
Color, | ||
@@ -20,2 +22,3 @@ CylinderGeometry, | ||
Group, | ||
Line, | ||
Matrix4, | ||
@@ -94,7 +97,6 @@ Mesh, | ||
globeImageUrl: { | ||
onChange(url) { | ||
this._loadGlobeImage(url); | ||
}, | ||
onChange(_, state) { | ||
state.globeNeedsUpdate = true; | ||
} | ||
triggerUpdate: false | ||
}, | ||
@@ -133,3 +135,3 @@ pointsData: { | ||
}, | ||
pointHeight: { | ||
pointAltitude: { | ||
default: 0.1, | ||
@@ -170,55 +172,53 @@ | ||
// boolean. Whether to merge all points into a single mesh for rendering performance | ||
linksData: { | ||
arcsData: { | ||
default: [], | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkStartLat: { | ||
arcStartLat: { | ||
default: 'startLat', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkStartLng: { | ||
default: 'endLng', | ||
arcStartLng: { | ||
default: 'startLng', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkEndLat: { | ||
arcEndLat: { | ||
default: 'endLat', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkEndLng: { | ||
arcEndLng: { | ||
default: 'endLng', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkColor: { | ||
arcColor: { | ||
default: () => '#ffffaa', | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
linkHeight: { | ||
default: 0.4, | ||
arcAltitude: { | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -228,16 +228,23 @@ | ||
// in units of globe radius | ||
linkDiameter: { | ||
default: 0.2, | ||
arcAltitudeAutoScale: { | ||
default: 0.5, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// scale altitude proportional to great-arc distance between the two points | ||
arcStroke: { | ||
onChange(_, state) { | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// in deg | ||
linkCurveResolution: { | ||
arcCurveResolution: { | ||
default: 64, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -247,7 +254,7 @@ | ||
// how many slice segments in the tube's circumference | ||
linkCircularResolution: { | ||
arcCircularResolution: { | ||
default: 6, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
@@ -257,11 +264,11 @@ | ||
// how many slice segments in the tube's circumference | ||
linksMerge: { | ||
arcsMerge: { | ||
default: false, | ||
onChange(_, state) { | ||
state.linksNeedsRepopulating = true; | ||
state.arcsNeedsRepopulating = true; | ||
} | ||
}, | ||
// boolean. Whether to merge all links into a single mesh for rendering performance | ||
// boolean. Whether to merge all arcs into a single mesh for rendering performance | ||
customLayerData: { | ||
@@ -292,22 +299,9 @@ default: [], | ||
}; | ||
}, | ||
} | ||
_loadGlobeImage: function (state, imageUrl) { | ||
if (state.globeObj && imageUrl) { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(imageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
return this; | ||
} | ||
}, | ||
stateInit: () => ({ | ||
globeNeedsUpdate: true, | ||
pointsNeedsRepopulating: true, | ||
linksNeedsRepopulating: true, | ||
arcsNeedsRepopulating: true, | ||
customLayerNeedsRepopulating: true | ||
@@ -330,4 +324,3 @@ }), | ||
state.scene.add(globeObj); | ||
state.globeImageUrl && this._loadGlobeImage(state.globeImageUrl); // add atmosphere | ||
state.scene.add(globeObj); // add atmosphere | ||
@@ -352,5 +345,5 @@ { | ||
state.scene.add(state.pointsG = new THREE.Group()); // add links group | ||
state.scene.add(state.pointsG = new THREE.Group()); // add arcs group | ||
state.scene.add(state.linksG = new THREE.Group()); // add custom layer group | ||
state.scene.add(state.arcsG = new THREE.Group()); // add custom layer group | ||
@@ -363,4 +356,24 @@ state.scene.add(state.customLayerG = new THREE.Group()); | ||
if (state.globeNeedsUpdate) { | ||
state.globeNeedsUpdate = false; | ||
if (!state.globeImageUrl) { | ||
// Black globe | ||
state.globeObj.material = new THREE.MeshBasicMaterial({ | ||
color: 0x000000 | ||
}); | ||
} else { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(state.globeImageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
} | ||
if (state.pointsNeedsRepopulating) { | ||
state.pointsNeedRepopulating = false; // Clear the existing points | ||
state.pointsNeedsRepopulating = false; // Clear the existing points | ||
@@ -371,3 +384,3 @@ emptyObject(state.pointsG); // Data accessors | ||
const lngAccessor = accessorFn(state.pointLng); | ||
const heightAccessor = accessorFn(state.pointHeight); | ||
const altitudeAccessor = accessorFn(state.pointAltitude); | ||
const radiusAccessor = accessorFn(state.pointRadius); | ||
@@ -388,3 +401,3 @@ const colorAccessor = accessorFn(state.pointColor); // Add WebGL points | ||
obj.scale.x = obj.scale.y = Math.min(30, radiusAccessor(pnt)) * pxPerDeg; | ||
obj.scale.z = Math.max(heightAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
obj.scale.z = Math.max(altitudeAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
@@ -441,47 +454,59 @@ obj.__globeObjType = 'point'; // Add object type | ||
if (state.linksNeedsRepopulating) { | ||
state.linksNeedsRepopulating = false; // Clear the existing links | ||
if (state.arcsNeedsRepopulating) { | ||
state.arcsNeedsRepopulating = false; // Clear the existing arcs | ||
emptyObject(state.linksG); // Data accessors | ||
emptyObject(state.arcsG); // Data accessors | ||
const startLatAccessor = accessorFn(state.linkStartLat); | ||
const startLngAccessor = accessorFn(state.linkStartLng); | ||
const endLatAccessor = accessorFn(state.linkEndLat); | ||
const endLngAccessor = accessorFn(state.linkEndLng); | ||
const heightAccessor = accessorFn(state.linkHeight); | ||
const diameterAccessor = accessorFn(state.linkDiameter); | ||
const colorAccessor = accessorFn(state.linkColor); | ||
const linkObjs = []; | ||
state.linksData.forEach(link => { | ||
const startPnt = [...[startLatAccessor, startLngAccessor].map(fn => fn(link)), 0]; | ||
const endPnt = [...[endLatAccessor, endLngAccessor].map(fn => fn(link)), 0]; | ||
const startLatAccessor = accessorFn(state.arcStartLat); | ||
const startLngAccessor = accessorFn(state.arcStartLng); | ||
const endLatAccessor = accessorFn(state.arcEndLat); | ||
const endLngAccessor = accessorFn(state.arcEndLng); | ||
const altitudeAccessor = accessorFn(state.arcAltitude); | ||
const altitudeAutoScaleAccessor = accessorFn(state.arcAltitudeAutoScale); | ||
const strokeAccessor = accessorFn(state.arcStroke); | ||
const colorAccessor = accessorFn(state.arcColor); | ||
const arcObjs = []; | ||
state.arcsData.forEach(arc => { | ||
let curve; | ||
{ | ||
const getVec = ([lng, lat, alt]) => { | ||
const { | ||
x, | ||
y, | ||
z | ||
} = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(x, y, z); | ||
}; //calculate curve | ||
const getMiddle = (a, b) => a + (b - a) / 2; | ||
const middlePoint = [getMiddle(startPnt[0], endPnt[0]), getMiddle(startPnt[1], endPnt[1]), heightAccessor(link) * 2]; | ||
const curveVecs = [startPnt, middlePoint, endPnt].map(([lat, lng, alt]) => { | ||
const coords = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(coords.x, coords.y, coords.z); | ||
}); | ||
const path = new THREE.QuadraticBezierCurve3(...curveVecs); | ||
const linkGeometry = new THREE.TubeGeometry(path, state.linkCurveResolution, diameterAccessor(link) / 2, state.linkCircularResolution); | ||
const obj = new THREE.Mesh(linkGeometry); | ||
obj.__globeObjType = 'link'; // Add object type | ||
const startPnt = [startLngAccessor, startLatAccessor].map(fn => fn(arc)); | ||
const endPnt = [endLngAccessor, endLatAccessor].map(fn => fn(arc)); | ||
let altitude = altitudeAccessor(arc); | ||
(altitude === null || altitude === undefined) && ( // by default set altitude proportional to the great-arc distance | ||
altitude = geoDistance(startPnt, endPnt) / 2 * altitudeAutoScaleAccessor(arc)); | ||
const interpolate = geoInterpolate(startPnt, endPnt); | ||
const [m1Pnt, m2Pnt] = [0.25, 0.75].map(t => [...interpolate(t), altitude * 1.5]); | ||
curve = new THREE.CubicBezierCurve3(...[startPnt, m1Pnt, m2Pnt, endPnt].map(getVec)); //const mPnt = [...interpolate(0.5), altitude * 2]; | ||
//curve = new THREE.QuadraticBezierCurve3(...[startPnt, mPnt, endPnt].map(getVec)); | ||
} | ||
const stroke = strokeAccessor(arc); | ||
const obj = stroke === null || stroke === undefined ? new THREE.Line(new THREE.BufferGeometry().setFromPoints(curve.getPoints(state.arcCurveResolution))) : new THREE.Mesh(new THREE.TubeGeometry(curve, state.arcCurveResolution, stroke / 2, state.arcCircularResolution)); | ||
obj.__globeObjType = 'arc'; // Add object type | ||
obj.__data = link; // Attach point data | ||
obj.__data = arc; // Attach point data | ||
linkObjs.push(obj); | ||
arcObjs.push(obj); | ||
}); | ||
if (state.linksMerge) { | ||
// merge links into a single mesh | ||
const linksGeometry = new THREE.Geometry(); | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
const color = new THREE.Color(colorAccessor(link)); | ||
if (state.arcsMerge) { | ||
// merge arcs into a single mesh | ||
const arcsGeometry = new THREE.Geometry(); | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = new THREE.Color(colorAccessor(arc)); | ||
obj.geometry.faces.forEach(face => face.color = color); | ||
obj.updateMatrix(); | ||
linksGeometry.merge(obj.geometry, obj.matrix); | ||
arcsGeometry.merge(obj.geometry, obj.matrix); | ||
}); | ||
const links = new THREE.Mesh(linksGeometry, new THREE.MeshBasicMaterial({ | ||
const arcs = new THREE.Mesh(arcsGeometry, new THREE.MeshBasicMaterial({ | ||
color: 0xffffff, | ||
@@ -491,18 +516,18 @@ vertexColors: THREE.FaceColors, | ||
})); | ||
links.__globeObjType = 'links'; // Add object type | ||
arcs.__globeObjType = 'arcs'; // Add object type | ||
links.__data = state.linksData; // Attach obj data | ||
arcs.__data = state.arcsData; // Attach obj data | ||
state.linksG.add(links); | ||
state.arcsG.add(arcs); | ||
} else { | ||
// Add individual meshes per link | ||
const linkMaterials = {}; // indexed by color | ||
// Add individual meshes per arc | ||
const arcMaterials = {}; // indexed by color | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
const color = colorAccessor(link); | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = colorAccessor(arc); | ||
const opacity = colorAlpha(color); | ||
if (!linkMaterials.hasOwnProperty(color)) { | ||
linkMaterials[color] = new THREE.MeshLambertMaterial({ | ||
if (!arcMaterials.hasOwnProperty(color)) { | ||
arcMaterials[color] = new THREE.MeshLambertMaterial({ | ||
color: colorStr2Hex(color), | ||
@@ -514,4 +539,4 @@ transparent: opacity < 1, | ||
obj.material = linkMaterials[color]; | ||
state.linksG.add(link.__threeObj = obj); | ||
obj.material = arcMaterials[color]; | ||
state.arcsG.add(arc.__threeObj = obj); | ||
}); | ||
@@ -518,0 +543,0 @@ } |
{ | ||
"name": "three-globe", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "Globe data visualization as a ThreeJS reusable 3D object", | ||
@@ -41,2 +41,3 @@ "unpkg": "dist/three-globe.min.js", | ||
"accessor-fn": "^1.2.2", | ||
"d3-geo": "^1.11.3", | ||
"kapsule": "^1.10.0", | ||
@@ -43,0 +44,0 @@ "tinycolor2": "^1.4.1" |
@@ -9,3 +9,3 @@ # ThreeJS Globe Visualization | ||
Largely inspired by the [WebGL Globe](https://experiments.withgoogle.com/chrome/globe), this is a [ThreeJS](https://threejs.org/) WebGL class to represent data visualization layers on a globe, using spherical projection. | ||
Largely inspired by [WebGL Globe](https://experiments.withgoogle.com/chrome/globe), this is a [ThreeJS](https://threejs.org/) WebGL class to represent data visualization layers on a globe, using spherical projection. | ||
@@ -12,0 +12,0 @@ ## Quick start |
import { | ||
AdditiveBlending, | ||
BackSide, | ||
BufferGeometry, | ||
Color, | ||
@@ -9,2 +10,3 @@ CylinderGeometry, | ||
Group, | ||
Line, | ||
Matrix4, | ||
@@ -28,2 +30,3 @@ Mesh, | ||
BackSide, | ||
BufferGeometry, | ||
Color, | ||
@@ -34,2 +37,3 @@ CylinderGeometry, | ||
Group, | ||
Line, | ||
Matrix4, | ||
@@ -50,2 +54,3 @@ Mesh, | ||
import accessorFn from 'accessor-fn'; | ||
import { geoDistance, geoInterpolate } from 'd3-geo'; | ||
@@ -129,3 +134,3 @@ import { colorStr2Hex, colorAlpha } from './color-utils'; | ||
props: { | ||
globeImageUrl: { onChange(url) { this._loadGlobeImage(url)}, triggerUpdate: false}, | ||
globeImageUrl: { onChange(_, state) { state.globeNeedsUpdate = true }}, | ||
pointsData: { default: [], onChange(_, state) { state.pointsNeedsRepopulating = true }}, | ||
@@ -135,17 +140,18 @@ pointLat: { default: 'lat', onChange(_, state) { state.pointsNeedsRepopulating = true }}, | ||
pointColor: { default: () => '#ffffaa', onChange(_, state) { state.pointsNeedsRepopulating = true }}, | ||
pointHeight: { default: 0.1, onChange(_, state) { state.pointsNeedsRepopulating = true }}, // in units of globe radius | ||
pointAltitude: { default: 0.1, onChange(_, state) { state.pointsNeedsRepopulating = true }}, // in units of globe radius | ||
pointRadius: { default: 0.25, onChange(_, state) { state.pointsNeedsRepopulating = true }}, // in deg | ||
pointResolution: { default: 12, onChange(_, state) { state.pointsNeedsRepopulating = true }}, // how many slice segments in the cylinder's circumference | ||
pointsMerge: { default: false, onChange(_, state) { state.pointsNeedsRepopulating = true }}, // boolean. Whether to merge all points into a single mesh for rendering performance | ||
linksData: { default: [], onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkStartLat: { default: 'startLat', onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkStartLng: { default: 'endLng', onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkEndLat: { default: 'endLat', onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkEndLng: { default: 'endLng', onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkColor: { default: () => '#ffffaa', onChange(_, state) { state.linksNeedsRepopulating = true }}, | ||
linkHeight: { default: 0.4, onChange(_, state) { state.linksNeedsRepopulating = true }}, // in units of globe radius | ||
linkDiameter: { default: 0.2, onChange(_, state) { state.linksNeedsRepopulating = true }}, // in deg | ||
linkCurveResolution: { default: 64, onChange(_, state) { state.linksNeedsRepopulating = true }}, // how many slice segments in the tube's circumference | ||
linkCircularResolution: { default: 6, onChange(_, state) { state.linksNeedsRepopulating = true }}, // how many slice segments in the tube's circumference | ||
linksMerge: { default: false, onChange(_, state) { state.linksNeedsRepopulating = true }}, // boolean. Whether to merge all links into a single mesh for rendering performance | ||
arcsData: { default: [], onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcStartLat: { default: 'startLat', onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcStartLng: { default: 'startLng', onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcEndLat: { default: 'endLat', onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcEndLng: { default: 'endLng', onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcColor: { default: () => '#ffffaa', onChange(_, state) { state.arcsNeedsRepopulating = true }}, | ||
arcAltitude: { onChange(_, state) { state.arcsNeedsRepopulating = true }}, // in units of globe radius | ||
arcAltitudeAutoScale: { default: 0.5, onChange(_, state) { state.arcsNeedsRepopulating = true }}, // scale altitude proportional to great-arc distance between the two points | ||
arcStroke: { onChange(_, state) { state.arcsNeedsRepopulating = true }}, // in deg | ||
arcCurveResolution: { default: 64, onChange(_, state) { state.arcsNeedsRepopulating = true }}, // how many slice segments in the tube's circumference | ||
arcCircularResolution: { default: 6, onChange(_, state) { state.arcsNeedsRepopulating = true }}, // how many slice segments in the tube's circumference | ||
arcsMerge: { default: false, onChange(_, state) { state.arcsNeedsRepopulating = true }}, // boolean. Whether to merge all arcs into a single mesh for rendering performance | ||
customLayerData: { default: [], onChange(_, state) { state.customLayerNeedsRepopulating = true }}, | ||
@@ -165,16 +171,2 @@ customThreeObject: { onChange(_, state) { state.customLayerNeedsRepopulating = true }} | ||
}; | ||
}, | ||
_loadGlobeImage: function(state, imageUrl) { | ||
if (state.globeObj && imageUrl) { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(imageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
return this; | ||
} | ||
@@ -184,4 +176,5 @@ }, | ||
stateInit: () => ({ | ||
globeNeedsUpdate: true, | ||
pointsNeedsRepopulating: true, | ||
linksNeedsRepopulating: true, | ||
arcsNeedsRepopulating: true, | ||
customLayerNeedsRepopulating: true | ||
@@ -203,3 +196,2 @@ }), | ||
state.scene.add(globeObj); | ||
state.globeImageUrl && this._loadGlobeImage(state.globeImageUrl); | ||
@@ -228,4 +220,4 @@ // add atmosphere | ||
// add links group | ||
state.scene.add(state.linksG = new THREE.Group()); | ||
// add arcs group | ||
state.scene.add(state.arcsG = new THREE.Group()); | ||
@@ -239,4 +231,23 @@ // add custom layer group | ||
if (state.globeNeedsUpdate) { | ||
state.globeNeedsUpdate = false; | ||
if (!state.globeImageUrl) { | ||
// Black globe | ||
state.globeObj.material = new THREE.MeshBasicMaterial({ color: 0x000000 }); | ||
} else { | ||
const shader = Shaders.earth; | ||
const uniforms = THREE.UniformsUtils.clone(shader.uniforms); | ||
uniforms.texture.value = new THREE.TextureLoader().load(state.globeImageUrl); | ||
state.globeObj.material = new THREE.ShaderMaterial({ | ||
uniforms: uniforms, | ||
vertexShader: shader.vertexShader, | ||
fragmentShader: shader.fragmentShader | ||
}); | ||
} | ||
} | ||
if (state.pointsNeedsRepopulating) { | ||
state.pointsNeedRepopulating = false; | ||
state.pointsNeedsRepopulating = false; | ||
@@ -249,3 +260,3 @@ // Clear the existing points | ||
const lngAccessor = accessorFn(state.pointLng); | ||
const heightAccessor = accessorFn(state.pointHeight); | ||
const altitudeAccessor = accessorFn(state.pointAltitude); | ||
const radiusAccessor = accessorFn(state.pointRadius); | ||
@@ -272,3 +283,3 @@ const colorAccessor = accessorFn(state.pointColor); | ||
obj.scale.x = obj.scale.y = Math.min(30, radiusAccessor(pnt)) * pxPerDeg; | ||
obj.scale.z = Math.max(heightAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
obj.scale.z = Math.max(altitudeAccessor(pnt) * GLOBE_RADIUS, 0.1); // avoid non-invertible matrix | ||
@@ -329,50 +340,68 @@ obj.__globeObjType = 'point'; // Add object type | ||
if (state.linksNeedsRepopulating) { | ||
state.linksNeedsRepopulating = false; | ||
if (state.arcsNeedsRepopulating) { | ||
state.arcsNeedsRepopulating = false; | ||
// Clear the existing links | ||
emptyObject(state.linksG); | ||
// Clear the existing arcs | ||
emptyObject(state.arcsG); | ||
// Data accessors | ||
const startLatAccessor = accessorFn(state.linkStartLat); | ||
const startLngAccessor = accessorFn(state.linkStartLng); | ||
const endLatAccessor = accessorFn(state.linkEndLat); | ||
const endLngAccessor = accessorFn(state.linkEndLng); | ||
const heightAccessor = accessorFn(state.linkHeight); | ||
const diameterAccessor = accessorFn(state.linkDiameter); | ||
const colorAccessor = accessorFn(state.linkColor); | ||
const startLatAccessor = accessorFn(state.arcStartLat); | ||
const startLngAccessor = accessorFn(state.arcStartLng); | ||
const endLatAccessor = accessorFn(state.arcEndLat); | ||
const endLngAccessor = accessorFn(state.arcEndLng); | ||
const altitudeAccessor = accessorFn(state.arcAltitude); | ||
const altitudeAutoScaleAccessor = accessorFn(state.arcAltitudeAutoScale); | ||
const strokeAccessor = accessorFn(state.arcStroke); | ||
const colorAccessor = accessorFn(state.arcColor); | ||
const linkObjs = []; | ||
const arcObjs = []; | ||
state.linksData.forEach(link => { | ||
const startPnt = [...[startLatAccessor, startLngAccessor].map(fn => fn(link)), 0]; | ||
const endPnt = [...[endLatAccessor, endLngAccessor].map(fn => fn(link)), 0]; | ||
state.arcsData.forEach(arc => { | ||
let curve; | ||
{ | ||
const getVec = ([lng, lat, alt]) => { | ||
const { x, y, z } = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(x, y, z); | ||
}; | ||
const getMiddle = (a, b) => a + (b-a) / 2; | ||
const middlePoint = [getMiddle(startPnt[0], endPnt[0]), getMiddle(startPnt[1], endPnt[1]), heightAccessor(link) * 2]; | ||
//calculate curve | ||
const startPnt = [startLngAccessor, startLatAccessor].map(fn => fn(arc)); | ||
const endPnt = [endLngAccessor, endLatAccessor].map(fn => fn(arc)); | ||
const curveVecs = [startPnt, middlePoint, endPnt].map(([lat, lng, alt]) => { | ||
const coords = this.getCoords(lat, lng, alt); | ||
return new THREE.Vector3(coords.x, coords.y, coords.z); | ||
}); | ||
let altitude = altitudeAccessor(arc); | ||
(altitude === null || altitude === undefined) && | ||
// by default set altitude proportional to the great-arc distance | ||
(altitude = geoDistance(startPnt, endPnt) / 2 * altitudeAutoScaleAccessor(arc)); | ||
const path = new THREE.QuadraticBezierCurve3(...curveVecs); | ||
const interpolate = geoInterpolate(startPnt, endPnt); | ||
const [m1Pnt, m2Pnt] = [0.25, 0.75].map(t => [...interpolate(t), altitude * 1.5]); | ||
curve = new THREE.CubicBezierCurve3(...[startPnt, m1Pnt, m2Pnt, endPnt].map(getVec)); | ||
const linkGeometry = new THREE.TubeGeometry(path, state.linkCurveResolution, diameterAccessor(link) / 2, state.linkCircularResolution); | ||
//const mPnt = [...interpolate(0.5), altitude * 2]; | ||
//curve = new THREE.QuadraticBezierCurve3(...[startPnt, mPnt, endPnt].map(getVec)); | ||
} | ||
const obj = new THREE.Mesh(linkGeometry); | ||
const stroke = strokeAccessor(arc); | ||
obj.__globeObjType = 'link'; // Add object type | ||
obj.__data = link; // Attach point data | ||
const obj = (stroke === null || stroke === undefined) | ||
? new THREE.Line( | ||
new THREE.BufferGeometry().setFromPoints(curve.getPoints(state.arcCurveResolution)) | ||
) | ||
: new THREE.Mesh( | ||
new THREE.TubeGeometry(curve, state.arcCurveResolution, stroke / 2, state.arcCircularResolution) | ||
); | ||
linkObjs.push(obj); | ||
obj.__globeObjType = 'arc'; // Add object type | ||
obj.__data = arc; // Attach point data | ||
arcObjs.push(obj); | ||
}); | ||
if (state.linksMerge) { // merge links into a single mesh | ||
const linksGeometry = new THREE.Geometry(); | ||
if (state.arcsMerge) { // merge arcs into a single mesh | ||
const arcsGeometry = new THREE.Geometry(); | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = new THREE.Color(colorAccessor(link)); | ||
const color = new THREE.Color(colorAccessor(arc)); | ||
obj.geometry.faces.forEach(face => face.color = color); | ||
@@ -382,6 +411,6 @@ | ||
linksGeometry.merge(obj.geometry, obj.matrix); | ||
arcsGeometry.merge(obj.geometry, obj.matrix); | ||
}); | ||
const links = new THREE.Mesh(linksGeometry, new THREE.MeshBasicMaterial({ | ||
const arcs = new THREE.Mesh(arcsGeometry, new THREE.MeshBasicMaterial({ | ||
color: 0xffffff, | ||
@@ -392,17 +421,17 @@ vertexColors: THREE.FaceColors, | ||
links.__globeObjType = 'links'; // Add object type | ||
links.__data = state.linksData; // Attach obj data | ||
arcs.__globeObjType = 'arcs'; // Add object type | ||
arcs.__data = state.arcsData; // Attach obj data | ||
state.linksG.add(links); | ||
state.arcsG.add(arcs); | ||
} else { // Add individual meshes per link | ||
} else { // Add individual meshes per arc | ||
const linkMaterials = {}; // indexed by color | ||
const arcMaterials = {}; // indexed by color | ||
linkObjs.forEach(obj => { | ||
const link = obj.__data; | ||
const color = colorAccessor(link); | ||
arcObjs.forEach(obj => { | ||
const arc = obj.__data; | ||
const color = colorAccessor(arc); | ||
const opacity = colorAlpha(color); | ||
if (!linkMaterials.hasOwnProperty(color)) { | ||
linkMaterials[color] = new THREE.MeshLambertMaterial({ | ||
if (!arcMaterials.hasOwnProperty(color)) { | ||
arcMaterials[color] = new THREE.MeshLambertMaterial({ | ||
color: colorStr2Hex(color), | ||
@@ -414,5 +443,5 @@ transparent: opacity < 1, | ||
obj.material = linkMaterials[color]; | ||
obj.material = arcMaterials[color]; | ||
state.linksG.add(link.__threeObj = obj); | ||
state.arcsG.add(arc.__threeObj = obj); | ||
}); | ||
@@ -419,0 +448,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1085579
18
3195
5
+ Addedd3-geo@^1.11.3
+ Addedd3-array@1.2.4(transitive)
+ Addedd3-geo@1.12.1(transitive)