UNPKG

earthtrek-core

Version:

Global Nominee NASA Space Apps Challenge 2017 Buenos Aires - Global Finalist (Best Use of Data) NASA Space Apps Challenge 2017 - 1D, 2D, 3D, Go! Challenge

324 lines (291 loc) 11.3 kB
/** * @class EarthTrek * @module EarthTrek * @author SATrek * @author Alejandro Sanchez <alejandro.sanchez.trek@gmail.com> * @description EarthTrek - NASA Space Apps 2017 23 APR 2017. */ /**EXTERNAL */ import events from 'events'; import Cesium from './utils/cesium'; import _ from 'underscore'; /***/ import EarthTrekEntity from './earthtrek-entity'; import earthTrekData from './earthtrek-data'; import earthTrekSatellite from './earthtrek-satellite'; import EarthTrekLayerCollection from './earthtrek-layer-collection'; import earthTrekUtils from './utils/earthtrek-utils'; let instance = null; /** * * @returns {*} */ export function earthTrekInstance() { return instance; } export default class EarthTrekCore { /** * Constructor * @param options */ constructor(options) { window.CESIUM_BASE_URL = './'; require('cesium/Build/Cesium/Widgets/widgets.css'); require('../../src/css/main.css'); require('../../src/css/left-toolbar.css'); if(!instance){ instance = this; } if (!options.mainContainer) { throw new Error('Invalid Main Container'); } if (!options.startTime) { throw new Error('Invalid Start Time'); } if (!options.endTime) { throw new Error('Invalid End Time'); } if (!options.initialTime) { this.initialTime = Cesium.JulianDate.fromDate( new Date(options.endTime)); } if (!options.maxDistanceCamera) { options.maxDistanceCamera = 10000000000; //10,000,000,000 meters } if (!options.enableLighting) { options.enableLighting = false; } if (!options.showFeatures) { options.showFeatures = true; } if (!options.orbitalDataUpdateTime) { options.orbitalDataUpdateTime = 10; } if (!options.multiplier) { options.multiplier = 10; //intervals } if (!options.orbitDuration) { options.orbitDuration = 7200; //seconds } if (!options.frequency) { options.frequency = 50; //intervals } if (!options.entities) { options.entities = { orbitDuration: options.orbitDuration, frequency: options.frequency }; } if (!options.env) { options.env = 'dev'; } this.startTime = Cesium.JulianDate.fromDate( new Date(options.startTime)); this.endTime = Cesium.JulianDate.fromDate( new Date(options.endTime)); this.initialTime = Cesium.JulianDate.fromDate( new Date(options.initialTime)); if (options.imageryProvider != undefined) { this.imageryProvider = options.imageryProvider; } this.previousTime = earthTrekUtils.isoDate(this.initialTime.toString()); this.lastPropagationTime = this.initialTime; this.multiplier = options.multiplier; this.mainContainerId = options.mainContainer; this.maxDistanceCamera = options.maxDistanceCamera; this.enableLighting = options.enableLighting; this.orbitalDataUpdateTime = options.orbitalDataUpdateTime; this.orbitDuration = options.orbitDuration; this.frequency = options.frequency; if (options.env == 'dev') { this.debugMode = true; } this.options = options; this.entities = []; this.layers = new EarthTrekLayerCollection(); this.eventEmitter = new events.EventEmitter(); this.createViewer(); return instance; } getLayers() { return this.layers; } /** * * @returns {events.EventEmitter} */ getEventEmitter() { return this.eventEmitter; } /** * getClock * @returns {Cesium.Clock|*} */ getClock() { if (this.clock === undefined) { this.clock = new Cesium.Clock({ startTime: this.startTime, endTime: this.endTime, currentTime: this.initialTime, multiplier: this.multiplier, clockStep: Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER }); } return this.clock; } /** * Create Viewer * @param mainContainer * @returns {Cesium.Viewer|*} */ createViewer() { if (this.viewer === undefined) { const viewerOptions = { clock: this.getClock(), baseLayerPicker: false, requestWaterMask: true, automaticallyTrackDataSourceClocks: false, navigationHelpButton: false, infoBox: false, creditContainer: "credit", terrainExaggeration: 10 } if (this.imageryProvider) { viewerOptions.imageryProvider = this.imageryProvider; } this.viewer = new Cesium.Viewer(this.mainContainerId, viewerOptions); this.viewer.scene.globe.tileCacheSize = 1000; this.viewer.scene.globe.enableLighting = this.enableLighting; this.getClock().onTick.addEventListener(this.onClockUpdate, this); this.viewer.timeline.zoomTo(this.startTime, this.endTime); this.viewer.camera.frustum.far = this.maxDistanceCamera; this.viewer.camera.defaultZoomAmount = 500000.0; if (this.debugMode == true) { this.viewer.scene.debugShowFramesPerSecond = true; } } this.lastOrbitalDataUpdated = this.clock.currentTime; return this.viewer; } /** * Get Viewer * @returns {Cesium.Viewer} */ getViewer() { return this.viewer; } pullSatellitesData(callback) { earthTrekData.getFullData({getCache: this.options.getCache}, (satellites) => { satellites.forEach((satelliteData) => { const entity = this.viewer.entities.getById(satelliteData.satId); callback(satelliteData, entity); }); this.getEventEmitter().emit('entities-added', {entities: this.entities}); }); } /** * Add Entity * @param satelliteData */ addEntity(satelliteData) { const earthTrekEntity = new EarthTrekEntity(satelliteData, this.getClock().currentTime, this.options.entities); const entity = this.viewer.entities.add(earthTrekEntity.getEntityData()); this.entities.push(entity); this.getEventEmitter().emit('entity-added', {entity: entity, satelliteData: satelliteData, earthTrekEntity: earthTrekEntity}); } /** * on Clock Update * @param clock */ onClockUpdate(clock) { const isoDateTime = clock.currentTime.toString(); const time = earthTrekUtils.isoDate(isoDateTime); if (time !== this.previousTime) { this.getEventEmitter().emit('date-updated', {time: time}); // updateLayers(); } this.updateEntities(time); if (this.viewer.selectedEntity != null && (Cesium.JulianDate.secondsDifference(this.clock.currentTime, this.lastOrbitalDataUpdated) > this.orbitalDataUpdateTime || Cesium.JulianDate.secondsDifference(this.lastOrbitalDataUpdated, this.clock.currentTime) > this.orbitalDataUpdateTime)) { this.getEventEmitter().emit('update-orbital-data', {entity: this.viewer.selectedEntity}); this.lastOrbitalDataUpdated = this.clock.currentTime; } }; /** * Register events * @param event * @param callback */ on(event, callback) { this.getEventEmitter().on(event, callback); } /** * Raise Event events * @param event * @param params */ raise(event, params = {}) { this.getEventEmitter().emit(event, params); } /** * Update Entities * @param isoTime */ updateEntities(isoTime) { const currentTime = this.getClock().currentTime; if (Cesium.JulianDate.secondsDifference(this.getClock().currentTime, this.lastPropagationTime) > this.orbitDuration || Cesium.JulianDate.secondsDifference(this.lastPropagationTime, this.getClock().currentTime) > this.orbitDuration) { const p1 = new Promise( (resolve, reject) => { if (isoTime !== this.previousTime) { this.previousTime = isoTime; this.lastPropagationTime = currentTime; const startDate = new Date(isoTime); startDate.setDate(startDate.getDate()); const endDate = new Date(isoTime); endDate.setDate(endDate.getDate() + 1); return resolve(earthTrekData.getTLEs(earthTrekData.getSatelliteIds(), { startDate: startDate, endDate: endDate })); } else { reject(time); } } ); p1.then((tles) => { tles.data.forEach( (tle) =>{ const entity = this.viewer.entities.getById(tle.satId); if (entity != null) { entity.properties.tle.setValue(tle.tle); entity.properties.data.setValue(_.extend(entity.properties.data.getValue(), tle.data)); } }); return new Promise(propagation).then(() => { this.getEventEmitter().emit('entities-updated'); }); }, (isoTime) => { return new Promise(propagation).then(() => { this.getEventEmitter().emit('entities-updated'); }); }); var that = this; var propagation = function(resolve) { that.entities.forEach( (entity) => { const newStart = that.clock.currentTime; const tle1 = entity.properties.getValue(newStart).tle[0]; const tle2 = entity.properties.getValue(newStart).tle[1]; const samples = earthTrekSatellite.getSamples(tle1, tle2, newStart, that.orbitDuration, that.frequency); entity.position = samples.positions entity.velocity = samples.velocities; entity.altitude = samples.heights; that.getEventEmitter().emit('entity-updated', {entity: entity, newStart: newStart}); }); that.lastPropagationTime = that.clock.currentTime; return resolve(); }; } } }