diff --git a/src/keepTrackApi.ts b/src/keepTrackApi.ts index b583232a7..b5d3edd7f 100644 --- a/src/keepTrackApi.ts +++ b/src/keepTrackApi.ts @@ -21,7 +21,6 @@ import type { InputManager } from './singletons/input-manager'; import { PanTouchEvent, TapTouchEvent } from './singletons/input-manager/touch-input'; import type { OrbitManager } from './singletons/orbitManager'; import { Scene } from './singletons/scene'; -import { StarManager } from './singletons/starManager'; import type { TimeManager } from './singletons/time-manager'; import type { UiManager } from './singletons/uiManager'; import { WebGLRenderer } from './singletons/webgl-renderer'; @@ -82,7 +81,7 @@ type KeepTrackApiEventArguments = { [KeepTrackApiEvents.resize]: []; [KeepTrackApiEvents.altCanvasResize]: []; [KeepTrackApiEvents.endOfDraw]: [Milliseconds]; - [KeepTrackApiEvents.onWatchlistUpdated]: [number[]]; + [KeepTrackApiEvents.onWatchlistUpdated]: [{ id: number, inView: boolean }[]]; [KeepTrackApiEvents.staticOffsetChange]: [number]; [KeepTrackApiEvents.onLineAdded]: [LineManager]; [KeepTrackApiEvents.sensorDotSelected]: [DetailedSensor]; @@ -266,7 +265,6 @@ export class KeepTrackApi { } getSoundManager = () => keepTrackContainer.get(Singletons.SoundManager); - getStarManager = () => keepTrackContainer.get(Singletons.StarManager); getRenderer = () => keepTrackContainer.get(Singletons.WebGLRenderer); getScene = () => keepTrackContainer.get(Singletons.Scene); getCatalogManager = () => keepTrackContainer.get(Singletons.CatalogManager); diff --git a/src/plugins/astronomy/astronomy.ts b/src/plugins/astronomy/astronomy.ts index 5b264709b..357fef418 100644 --- a/src/plugins/astronomy/astronomy.ts +++ b/src/plugins/astronomy/astronomy.ts @@ -41,7 +41,6 @@ export class Astronomy extends KeepTrackPlugin { isIconDisabledOnLoad = true; isIconDisabled = true; bottomIconCallback = (): void => { - const catalogManagerInstance = keepTrackApi.getCatalogManager(); const orbitManagerInstance = keepTrackApi.getOrbitManager(); const drawManagerInstance = keepTrackApi.getRenderer(); const uiManagerInstance = keepTrackApi.getUiManager(); @@ -51,13 +50,6 @@ export class Astronomy extends KeepTrackPlugin { return; } - if (catalogManagerInstance.isStarManagerLoaded) { - /* - * TODO: This takes way too long trying to find the star's - * satellite id from its name. The ids should be predetermined. - */ - keepTrackApi.getStarManager().drawAllConstellations(); - } orbitManagerInstance.clearInViewOrbit(); keepTrackApi.getMainCamera().cameraType = CameraType.ASTRONOMY; // Activate Astronomy Camera Mode // getEl('fov-text').innerHTML = ('FOV: ' + (settingsManager.fieldOfView * 100).toFixed(2) + ' deg'); @@ -72,9 +64,6 @@ export class Astronomy extends KeepTrackPlugin { uiManagerInstance.hideSideMenus(); keepTrackApi.getMainCamera().cameraType = CameraType.DEFAULT; // Back to normal Camera Mode LegendManager.change('default'); - if (catalogManagerInstance.isStarManagerLoaded) { - keepTrackApi.getStarManager().clearConstellations(); - } // getEl('fov-text').innerHTML = (''); getEl(this.bottomIconElementName).classList.remove('bmenu-item-selected'); } diff --git a/src/plugins/debug/debug.ts b/src/plugins/debug/debug.ts index 842bcc089..0fef3c4e8 100644 --- a/src/plugins/debug/debug.ts +++ b/src/plugins/debug/debug.ts @@ -6,7 +6,8 @@ import { KeepTrackApiEvents } from '@app/interfaces'; import { keepTrackApi } from '@app/keepTrackApi'; import debugPng from '@public/img/icons/debug.png'; -import { LineTypes, lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; +import { lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; +import { LineColors } from '@app/singletons/draw-manager/line-manager/line'; import eruda from 'eruda'; import { Milliseconds } from 'ootk'; import { KeepTrackPlugin, clickDragOptions } from '../KeepTrackPlugin'; @@ -126,9 +127,9 @@ export class DebugMenuPlugin extends KeepTrackPlugin { if (sat) { const offsetFromSat = keepTrackApi.getMainCamera().getCameraPosition(sat.position, keepTrackApi.getMainCamera().getCameraOrientation()); - const position = [sat.position.x + offsetFromSat[0], sat.position.y + offsetFromSat[1], sat.position.z + offsetFromSat[2]]; + const camPos = [sat.position.x + offsetFromSat[0], sat.position.y + offsetFromSat[1], sat.position.z + offsetFromSat[2]]; - lineManagerInstance.create(LineTypes.REF_TO_SAT, [selectedSat, position[0], position[1], position[2]], 'o'); + lineManagerInstance.createRef2Ref([camPos[0], camPos[1], camPos[2]], [sat.position.x, sat.position.y, sat.position.z], LineColors.PURPLE); } } }); @@ -139,7 +140,7 @@ export class DebugMenuPlugin extends KeepTrackPlugin { if (camera) { const position = camera.getCameraPosition(); - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_REF, [position[0], position[1], position[2]], 'r'); + lineManagerInstance.createRef2Ref(position, [0, 0, 0], LineColors.PURPLE); } }); }, diff --git a/src/plugins/planetarium/planetarium.ts b/src/plugins/planetarium/planetarium.ts index 6b8127790..ad3b49cd3 100644 --- a/src/plugins/planetarium/planetarium.ts +++ b/src/plugins/planetarium/planetarium.ts @@ -78,11 +78,6 @@ export class Planetarium extends KeepTrackPlugin { * getEl('fov-text').innerHTML = ('FOV: ' + (settingsManager.fieldOfView * 100).toFixed(2) + ' deg'); */ LegendManager.change('planetarium'); - const catalogManagerInstance = keepTrackApi.getCatalogManager(); - - if (catalogManagerInstance.isStarManagerLoaded) { - keepTrackApi.getStarManager().clearConstellations(); - } keepTrackApi.getPlugin(Astronomy)?.setBottomIconToUnselected(); } else { diff --git a/src/plugins/sensor-list/sensor-list.ts b/src/plugins/sensor-list/sensor-list.ts index 724fee58e..36a6226a1 100644 --- a/src/plugins/sensor-list/sensor-list.ts +++ b/src/plugins/sensor-list/sensor-list.ts @@ -3,7 +3,6 @@ import { KeepTrackApiEvents } from '@app/interfaces'; import { getClass } from '@app/lib/get-class'; import { getEl } from '@app/lib/get-el'; import { CameraType } from '@app/singletons/camera'; -import { LineTypes } from '@app/singletons/draw-manager/line-manager'; import { errorManagerInstance } from '@app/singletons/errorManager'; import { PersistenceManager, StorageKey } from '@app/singletons/persistence-manager'; import { LegendManager } from '@app/static/legend-manager'; @@ -187,18 +186,11 @@ export class SensorListPlugin extends KeepTrackPlugin { const sat = selectSatManagerInstance.getSelectedSat(); - if (sat.isMissile()) { + if (!sat.isSatellite()) { return; } - Object.keys(sensors).forEach((key) => { - const sensor = sensors[key]; - const isInView = sensor.isSatInFov(sat as DetailedSatellite, keepTrackApi.getTimeManager().simulationTimeObj); - - if (isInView) { - keepTrackApi.getLineManager().create(LineTypes.MULTI_SENSORS_TO_SAT, [sat.id, keepTrackApi.getCatalogManager().getSensorFromSensorName(sensor.name)], 'g'); - } - }); + keepTrackApi.getLineManager().createSensorsToSatFovOnly(sat as DetailedSatellite); }); this.isSensorLinksAdded = true; } diff --git a/src/plugins/sensor/sensor-info-plugin.ts b/src/plugins/sensor/sensor-info-plugin.ts index 8e8f526ec..487175917 100644 --- a/src/plugins/sensor/sensor-info-plugin.ts +++ b/src/plugins/sensor/sensor-info-plugin.ts @@ -1,7 +1,9 @@ import { KeepTrackApiEvents, ToastMsgType } from '@app/interfaces'; import { keepTrackApi } from '@app/keepTrackApi'; import { getEl, hideEl, showEl } from '@app/lib/get-el'; -import { LineManager, LineTypes } from '@app/singletons/draw-manager/line-manager'; +import { LineManager } from '@app/singletons/draw-manager/line-manager'; +import { SensorToMoonLine } from '@app/singletons/draw-manager/line-manager/sensor-to-moon-line'; +import { SensorToSunLine } from '@app/singletons/draw-manager/line-manager/sensor-to-sun-line'; import radioTowerPng from '@public/img/icons/radio-tower.png'; import { RfSensor, SpaceObjectType } from 'ootk'; import { KeepTrackPlugin, clickDragOptions } from '../KeepTrackPlugin'; @@ -142,8 +144,8 @@ export class SensorInfoPlugin extends KeepTrackPlugin { } private checkIfLinesVisible_(lineManager: LineManager) { - this.isSunLineVisible_ = lineManager.drawLineList.some((line) => { - if (line.type === LineTypes.SENSOR_TO_SUN) { + this.isSunLineVisible_ = lineManager.lines.some((line) => { + if (line instanceof SensorToSunLine) { return true; } @@ -158,8 +160,8 @@ export class SensorInfoPlugin extends KeepTrackPlugin { this.isSunLineVisible_ = false; } - this.isMonnLineVisible_ = lineManager.drawLineList.some((line) => { - if (line.type === LineTypes.SENSOR_TO_MOON) { + this.isMonnLineVisible_ = lineManager.lines.some((line) => { + if (line instanceof SensorToMoonLine) { return true; } @@ -180,9 +182,9 @@ export class SensorInfoPlugin extends KeepTrackPlugin { if (this.isMonnLineVisible_) { const lineManager = keepTrackApi.getLineManager(); - for (const line of lineManager.drawLineList) { - if (line.type === LineTypes.SENSOR_TO_MOON) { - lineManager.drawLineList.splice(lineManager.drawLineList.indexOf(line), 1); + for (const line of lineManager.lines) { + if (line instanceof SensorToMoonLine) { + line.isGarbage = true; getEl('sensor-moon-btn').textContent = 'Add Line to Moon \u25B6'; this.isMonnLineVisible_ = false; keepTrackApi.getSoundManager().play(SoundNames.TOGGLE_OFF); @@ -198,17 +200,9 @@ export class SensorInfoPlugin extends KeepTrackPlugin { keepTrackApi.getUiManager().toast('Please Select Only One Sensor', ToastMsgType.caution); } - // Draw Line to Sun from Sensor - const scene = keepTrackApi.getScene(); - const now = keepTrackApi.getTimeManager().simulationTimeObj; - keepTrackApi .getLineManager() - .create( - LineTypes.SENSOR_TO_MOON, - [sensors[0].eci(now).x, sensors[0].eci(now).y, sensors[0].eci(now).z, scene.moon.position[0], scene.moon.position[1], scene.moon.position[2]], - 'w', - ); + .createSensorToMoon(keepTrackApi.getSensorManager().currentSensors[0]); // Change Button Text getEl('sensor-moon-btn').textContent = 'Remove Line to Moon \u25B6'; @@ -223,9 +217,9 @@ export class SensorInfoPlugin extends KeepTrackPlugin { if (this.isSunLineVisible_) { const lineManager = keepTrackApi.getLineManager(); - for (const line of lineManager.drawLineList) { - if (line.type === LineTypes.SENSOR_TO_SUN) { - lineManager.drawLineList.splice(lineManager.drawLineList.indexOf(line), 1); + for (const line of lineManager.lines) { + if (line instanceof SensorToSunLine) { + line.isGarbage = true; getEl('sensor-sun-btn').textContent = 'Add Line to Sun \u25B6'; this.isSunLineVisible_ = false; keepTrackApi.getSoundManager().play(SoundNames.TOGGLE_OFF); @@ -241,17 +235,9 @@ export class SensorInfoPlugin extends KeepTrackPlugin { keepTrackApi.getUiManager().toast('Please Select Only One Sensor', ToastMsgType.caution); } - // Draw Line to Sun from Sensor - const scene = keepTrackApi.getScene(); - const now = keepTrackApi.getTimeManager().simulationTimeObj; - keepTrackApi .getLineManager() - .create( - LineTypes.SENSOR_TO_SUN, - [sensors[0].eci(now).x, sensors[0].eci(now).y, sensors[0].eci(now).z, scene.sun.position[0], scene.sun.position[1], scene.sun.position[2]], - 'o', - ); + .createSensorToSun(keepTrackApi.getSensorManager().currentSensors[0]); // Change Button Text getEl('sensor-sun-btn').textContent = 'Remove Line to Sun \u25B6'; diff --git a/src/plugins/sensor/sensorManager.ts b/src/plugins/sensor/sensorManager.ts index 28059f72e..209a4fa1c 100644 --- a/src/plugins/sensor/sensorManager.ts +++ b/src/plugins/sensor/sensorManager.ts @@ -32,7 +32,7 @@ import { errorManagerInstance } from '@app/singletons/errorManager'; import { KeepTrackApiEvents } from '@app/interfaces'; import { lat2pitch, lon2yaw } from '@app/lib/transforms'; import { waitForCruncher } from '@app/lib/waitForCruncher'; -import { LineTypes, lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; +import { lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; import { PersistenceManager, StorageKey } from '@app/singletons/persistence-manager'; import { LegendManager } from '@app/static/legend-manager'; import { SatMath } from '@app/static/sat-math'; @@ -146,18 +146,16 @@ export class SensorManager { case 'BLEAFB': case 'CLRSFS': case 'THLSFB': - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, sensor.minAz, sensor.minAz + 120, sensor.minEl, sensor.maxRng], 'c'); - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, sensor.minAz + 120, sensor.maxAz, sensor.minEl, sensor.maxRng], 'c'); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 1, 2); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 2, 2); break; case 'RAFFYL': - // TODO: Find actual face directions - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, 300, 60, sensor.minEl, sensor.maxRng], 'c'); - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, 60, 180, sensor.minEl, sensor.maxRng], 'c'); - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, 180, 300, sensor.minEl, sensor.maxRng], 'c'); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 1, 3); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 2, 3); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 3, 3); break; case 'COBRADANE': - // NOTE: This will be a bit more complicated later - lineManagerInstance.create(LineTypes.SENSOR_SCAN_HORIZON, [sensorId, sensor.minAz, sensor.maxAz, sensor.minEl, sensor.maxRng], 'c'); + lineManagerInstance.createSensorScanHorizon(keepTrackApi.getSensorManager().getSensorById(sensorId), 1, 1); break; default: errorManagerInstance.warn('Sensor not found'); @@ -562,6 +560,10 @@ export class SensorManager { return this.currentSensors.concat(this.secondarySensors).concat(this.stfSensors); } + getAllSensors(): DetailedSensor[] { + return Object.values(sensors); + } + public calculateSensorPos(now: Date, sensors?: DetailedSensor[]): { x: number; y: number; z: number; lat: number; lon: number; gmst: GreenwichMeanSiderealTime } { sensors = this.verifySensors(sensors); const sensor = sensors[0]; diff --git a/src/plugins/watchlist/watchlist-overlay.ts b/src/plugins/watchlist/watchlist-overlay.ts index c1b1f557e..8c78b906c 100644 --- a/src/plugins/watchlist/watchlist-overlay.ts +++ b/src/plugins/watchlist/watchlist-overlay.ts @@ -4,11 +4,11 @@ import { dateFormat } from '@app/lib/dateFormat'; import { getEl } from '@app/lib/get-el'; import { shake } from '@app/lib/shake'; import { showLoading } from '@app/lib/showLoading'; -import { LineTypes, lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; -import { SatMath } from '@app/static/sat-math'; +import { lineManagerInstance } from '@app/singletons/draw-manager/line-manager'; +import { LineColors } from '@app/singletons/draw-manager/line-manager/line'; import { SensorMath } from '@app/static/sensor-math'; import infoPng from '@public/img/icons/info.png'; -import { DetailedSatellite, MILLISECONDS_PER_DAY, Sgp4 } from 'ootk'; +import { DetailedSatellite, MILLISECONDS_PER_DAY } from 'ootk'; import { KeepTrackPlugin } from '../KeepTrackPlugin'; import { SelectSatManager } from '../select-sat-manager/select-sat-manager'; import { WatchlistPlugin } from './watchlist'; @@ -129,48 +129,35 @@ export class WatchlistOverlay extends KeepTrackPlugin { return; } this.updateFovLines_(); - - for (const element of this.watchlistPlugin_.watchlistInViewList) { - if (element === true) { - return; - } - } } - private updateFovLinesMulti_(sat: DetailedSatellite, i: number) { - keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistPlugin_.watchlistList[i]); - for (const sensor of keepTrackApi.getSensorManager().currentSensors) { - const satrec = Sgp4.createSatrec(sat.tle1, sat.tle2); // perform and store sat init calcs - const rae = SatMath.getRae(keepTrackApi.getTimeManager().simulationTimeObj, satrec, sensor); - const isInFov = SatMath.checkIsInView(sensor, rae); + private updateFovLinesMulti_(sat: DetailedSatellite) { + const idx = this.watchlistPlugin_.watchlistList.findIndex((el) => el.id === sat.id); - if (!isInFov) { - continue; - } - lineManagerInstance.create(LineTypes.SELECTED_SENSOR_TO_SAT_IF_IN_FOV, [sat.id, keepTrackApi.getCatalogManager().getSensorFromSensorName(sensor.name)], 'g'); + keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistPlugin_.watchlistList[idx].id); + for (const sensor of keepTrackApi.getSensorManager().currentSensors) { + lineManagerInstance.createSensorToSatFovOnly(sensor, sat, LineColors.GREEN); } } - private updateFovLinesSingle_(sat: DetailedSatellite, i: number) { + private updateFovLinesSingle_(sat: DetailedSatellite) { const inView = keepTrackApi.getDotsManager().inViewData[sat.id]; const uiManagerInstance = keepTrackApi.getUiManager(); + const idx = this.watchlistPlugin_.watchlistList.findIndex((el) => el.id === sat.id); + const inViewListVal = this.watchlistPlugin_.watchlistList[idx].inView; - if (inView === 1 && this.watchlistPlugin_.watchlistInViewList[i] === false) { + if (inView === 1 && inViewListVal === false) { // Is inview and wasn't previously - this.watchlistPlugin_.watchlistInViewList[i] = true; + this.watchlistPlugin_.watchlistList[idx].inView = true; uiManagerInstance.toast(`Satellite ${sat.sccNum} is In Field of View!`, ToastMsgType.normal); - lineManagerInstance.create( - LineTypes.SELECTED_SENSOR_TO_SAT_IF_IN_FOV, - [sat.id, keepTrackApi.getCatalogManager().getSensorFromSensorName(keepTrackApi.getSensorManager().currentSensors[0].name)], - 'g', - ); - keepTrackApi.getOrbitManager().addInViewOrbit(this.watchlistPlugin_.watchlistList[i]); + lineManagerInstance.createSensorToSatFovOnly(keepTrackApi.getSensorManager().currentSensors[0], sat, LineColors.GREEN); + keepTrackApi.getOrbitManager().addInViewOrbit(this.watchlistPlugin_.watchlistList[idx].id); } - if (inView === 0 && this.watchlistPlugin_.watchlistInViewList[i] === true) { + if (inView === 0 && inViewListVal === true) { // Isn't inview and was previously - this.watchlistPlugin_.watchlistInViewList[i] = false; + this.watchlistPlugin_.watchlistList[idx].inView = false; uiManagerInstance.toast(`Satellite ${sat.sccNum} left Field of View!`, ToastMsgType.standby); - keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistPlugin_.watchlistList[i]); + keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistPlugin_.watchlistList[idx].id); } } @@ -178,13 +165,13 @@ export class WatchlistOverlay extends KeepTrackPlugin { const catalogManagerInstance = keepTrackApi.getCatalogManager(); const sensorManagerInstance = keepTrackApi.getSensorManager(); - for (let i = 0; i < this.watchlistPlugin_.watchlistList.length; i++) { - const sat = catalogManagerInstance.getSat(this.watchlistPlugin_.watchlistList[i]); + for (const obj of this.watchlistPlugin_.watchlistList) { + const sat = catalogManagerInstance.getSat(obj.id); if (sensorManagerInstance.currentSensors.length > 1) { - this.updateFovLinesMulti_(sat, i); + this.updateFovLinesMulti_(sat); } else { - this.updateFovLinesSingle_(sat, i); + this.updateFovLinesSingle_(sat); } } } @@ -213,8 +200,8 @@ export class WatchlistOverlay extends KeepTrackPlugin { const satArray: DetailedSatellite[] = []; - for (const id of this.watchlistPlugin_.watchlistList) { - satArray.push(catalogManagerInstance.getSat(id, GetSatType.EXTRA_ONLY)); + for (const obj of this.watchlistPlugin_.watchlistList) { + satArray.push(catalogManagerInstance.getSat(obj.id, GetSatType.EXTRA_ONLY)); } this.nextPassArray = SensorMath.nextpassList(satArray, sensorManagerInstance.currentSensors, 1, this.OVERLAY_CALC_LENGTH_IN_DAYS); diff --git a/src/plugins/watchlist/watchlist.ts b/src/plugins/watchlist/watchlist.ts index 5b52367dc..cdeccbdf4 100644 --- a/src/plugins/watchlist/watchlist.ts +++ b/src/plugins/watchlist/watchlist.ts @@ -27,7 +27,7 @@ import { GetSatType, KeepTrackApiEvents, ToastMsgType } from '@app/interfaces'; import { keepTrackApi } from '@app/keepTrackApi'; import { clickAndDragWidth } from '@app/lib/click-and-drag'; import { getEl } from '@app/lib/get-el'; -import { LineTypes } from '@app/singletons/draw-manager/line-manager'; +import { SensorToSatLine } from '@app/singletons/draw-manager/line-manager/sensor-to-sat-line'; import { errorManagerInstance } from '@app/singletons/errorManager'; import { PersistenceManager, StorageKey } from '@app/singletons/persistence-manager'; import { isThisNode } from '@app/static/isThisNode'; @@ -40,8 +40,7 @@ import { KeepTrackPlugin } from '../KeepTrackPlugin'; import { SoundNames } from '../sounds/SoundNames'; interface UpdateWatchlistParams { - updateWatchlistList?: number[]; - updateWatchlistInViewList?: boolean[]; + updateWatchlistList?: { id: number, inView: boolean }[]; isSkipSearch?: boolean; } @@ -108,9 +107,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { `; sideMenuElementName: string = 'watchlist-menu'; - watchlistInViewList: boolean[] = []; - /** List of ids (not scc numbers) */ - watchlistList: number[] = []; + watchlistList: { id: number, inView: boolean }[] = []; constructor() { super(WatchlistPlugin.PLUGIN_NAME); @@ -147,16 +144,25 @@ export class WatchlistPlugin extends KeepTrackPlugin { } } if (watchlistString !== null && watchlistString !== '[]' && watchlistString.length > 0) { - const newWatchlist = JSON.parse(watchlistString); + let newWatchlist: { id: number, inView: boolean }[]; + // We save it as an array of sccNums + const savedSatList: string[] = JSON.parse(watchlistString); + + if (savedSatList.length > 0) { + // We need to convert it to an array of objects + newWatchlist = savedSatList.map((sccNum: string) => ({ id: parseInt(sccNum), inView: false })); + } else { + newWatchlist = []; + } + const catalogManagerInstance = keepTrackApi.getCatalogManager(); - const _watchlistInViewList = []; - for (let i = 0; i < newWatchlist.length; i++) { - const sat = catalogManagerInstance.getObject(catalogManagerInstance.sccNum2Id(newWatchlist[i]), GetSatType.EXTRA_ONLY); + for (const obj of newWatchlist) { + const sat = catalogManagerInstance.getObject(catalogManagerInstance.sccNum2Id(obj.id), GetSatType.EXTRA_ONLY); if (sat !== null) { - newWatchlist[i] = sat.id; - _watchlistInViewList.push(false); + obj.id = sat.id; + obj.inView = false; } else { errorManagerInstance.warn('Watchlist File Format Incorret'); @@ -167,7 +173,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { keepTrackApi.getUiManager().toast(`Watchlist Loaded with ${newWatchlist.length} Satellites`, ToastMsgType.normal); } - this.updateWatchlist({ updateWatchlistList: newWatchlist, updateWatchlistInViewList: _watchlistInViewList, isSkipSearch: true }); + this.updateWatchlist({ updateWatchlistList: newWatchlist, isSkipSearch: true }); } } @@ -243,15 +249,12 @@ export class WatchlistPlugin extends KeepTrackPlugin { * @param updateWatchlistInViewList - An optional array of booleans indicating whether each item in the watchlist should be displayed. * @param isSkipSearch - A boolean indicating whether to skip the search operation. */ - updateWatchlist({ updateWatchlistList, updateWatchlistInViewList, isSkipSearch = false }: UpdateWatchlistParams = {}) { + updateWatchlist({ updateWatchlistList, isSkipSearch = false }: UpdateWatchlistParams = {}) { const settingsManager: any = window.settingsManager; if (typeof updateWatchlistList !== 'undefined') { this.watchlistList = updateWatchlistList; } - if (typeof updateWatchlistInViewList !== 'undefined') { - this.watchlistInViewList = updateWatchlistInViewList; - } if (!this.watchlistList) { return; @@ -264,7 +267,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { const catalogManagerInstance = keepTrackApi.getCatalogManager(); for (let i = 0; i < this.watchlistList.length; i++) { - sat = catalogManagerInstance.getSat(this.watchlistList[i], GetSatType.EXTRA_ONLY); + sat = catalogManagerInstance.getSat(this.watchlistList[i].id, GetSatType.EXTRA_ONLY); if (sat == null) { this.watchlistList.splice(i, 1); } else { @@ -288,7 +291,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { for (let i = 0; i < this.watchlistList.length; i++) { // No duplicates - watchlistString += catalogManagerInstance.getSat(this.watchlistList[i], GetSatType.EXTRA_ONLY).sccNum; + watchlistString += catalogManagerInstance.getSat(this.watchlistList[i].id, GetSatType.EXTRA_ONLY).sccNum; if (i !== this.watchlistList.length - 1) { watchlistString += ','; } @@ -302,7 +305,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { const saveWatchlist = []; for (let i = 0; i < this.watchlistList.length; i++) { - sat = catalogManagerInstance.getSat(this.watchlistList[i], GetSatType.EXTRA_ONLY); + sat = catalogManagerInstance.getSat(this.watchlistList[i].id, GetSatType.EXTRA_ONLY); saveWatchlist[i] = sat.sccNum; } @@ -313,20 +316,21 @@ export class WatchlistPlugin extends KeepTrackPlugin { * Removes the satellite with the specified id from the watchlist. */ removeSat(id: number) { - for (let i = 0; i < this.watchlistList.length; i++) { - if (this.watchlistList[i] === id) { - keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistList[i]); - this.watchlistList.splice(i, 1); - this.watchlistInViewList.splice(i, 1); + const idxMatch = this.watchlistList.findIndex(({ id: id_ }) => id === id_); - keepTrackApi.getLineManager().drawLineList.forEach((line, idx) => { - if (line.type === LineTypes.SELECTED_SENSOR_TO_SAT_IF_IN_FOV && line.sat.id === id) { - keepTrackApi.getLineManager().drawLineList.splice(idx, 1); - } - }); - } + if (idxMatch === -1) { + return; } + keepTrackApi.getOrbitManager().removeInViewOrbit(this.watchlistList[idxMatch].id); + this.watchlistList.splice(idxMatch, 1); + + keepTrackApi.getLineManager().lines.forEach((line) => { + if (line instanceof SensorToSatLine && line.sat.id === id) { + line.isGarbage = true; + } + }); + this.updateWatchlist(); const uiManagerInstance = keepTrackApi.getUiManager(); @@ -340,11 +344,10 @@ export class WatchlistPlugin extends KeepTrackPlugin { } addSat(id: number, isMultiAdd = false) { - const isDuplicate = this.watchlistList.some((id_: number) => id_ === id); + const isDuplicate = this.watchlistList.some(({ id: id_ }) => id_ === id); if (!isDuplicate) { - this.watchlistList.push(id); - this.watchlistInViewList.push(false); + this.watchlistList.push({ id, inView: false }); } else { const sat = keepTrackApi.getCatalogManager().getSat(id); @@ -358,7 +361,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { } if (!isMultiAdd) { - this.watchlistList.sort((a: number, b: number) => { + this.watchlistList.sort(({ id: a }, { id: b }) => { const satA = keepTrackApi.getCatalogManager().getSat(a); const satB = keepTrackApi.getCatalogManager().getSat(b); @@ -377,11 +380,17 @@ export class WatchlistPlugin extends KeepTrackPlugin { return false; } - return this.watchlistList.some((satId_: number) => satId_ === id); + return this.watchlistList.some(({ id: id_ }) => id_ === id); } getSatellites() { - return this.watchlistList; + return this.watchlistList.map(({ + id, + }) => id); + } + + hasAnyInView() { + return this.watchlistList.some(({ inView }) => inView); } /** @@ -402,7 +411,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { this.addSat(id, true); }); - this.watchlistList.sort((a: number, b: number) => { + this.watchlistList.sort(({ id: a }, { id: b }) => { const satA = keepTrackApi.getCatalogManager().getSat(a); const satB = keepTrackApi.getCatalogManager().getSat(b); @@ -424,11 +433,11 @@ export class WatchlistPlugin extends KeepTrackPlugin { keepTrackApi.getSoundManager().play(SoundNames.MENU_BUTTON); const orbitManagerInstance = keepTrackApi.getOrbitManager(); - for (const id of this.watchlistList) { - orbitManagerInstance.removeInViewOrbit(id); + for (const obj of this.watchlistList) { + orbitManagerInstance.removeInViewOrbit(obj.id); } // TODO: Clear lines from sensors to satellites - this.updateWatchlist({ updateWatchlistList: [], updateWatchlistInViewList: [], isSkipSearch: true }); + this.updateWatchlist({ updateWatchlistList: [], isSkipSearch: true }); } /** @@ -446,10 +455,18 @@ export class WatchlistPlugin extends KeepTrackPlugin { return; } - let newWatchlist: number[]; + let newWatchlist: { id: number, inView: boolean }[]; try { - newWatchlist = JSON.parse(evt.target.result); + // We save it as an array of sccNums + const savedSatList: string[] = JSON.parse(evt.target.result); + + if (savedSatList.length > 0) { + // We need to convert it to an array of objects + newWatchlist = savedSatList.map((sccNum: string) => ({ id: parseInt(sccNum), inView: false })); + } else { + newWatchlist = []; + } } catch { errorManagerInstance.warn('Watchlist File Format Incorret'); @@ -462,20 +479,18 @@ export class WatchlistPlugin extends KeepTrackPlugin { return; } - this.watchlistInViewList = []; + this.watchlistList = []; const catalogManagerInstance = keepTrackApi.getCatalogManager(); - for (let i = 0; i < newWatchlist.length; i++) { - const sat = catalogManagerInstance.getObject(catalogManagerInstance.sccNum2Id(newWatchlist[i]), GetSatType.EXTRA_ONLY); + for (const obj of newWatchlist) { + const sat = catalogManagerInstance.getObject(catalogManagerInstance.sccNum2Id(obj.id), GetSatType.EXTRA_ONLY); if (sat !== null && sat.id > 0) { - newWatchlist[i] = sat.id; - this.watchlistInViewList.push(false); + this.watchlistList.push({ id: sat.id, inView: false }); } else { - errorManagerInstance.warn(`Sat ${newWatchlist[i]} not found!`); + errorManagerInstance.warn(`Sat ${obj} not found!`); } } - this.watchlistList = newWatchlist; this.updateWatchlist(); } @@ -489,7 +504,7 @@ export class WatchlistPlugin extends KeepTrackPlugin { const satIds = []; for (let i = 0; i < this.watchlistList.length; i++) { - const sat = keepTrackApi.getCatalogManager().getSat(this.watchlistList[i], GetSatType.EXTRA_ONLY); + const sat = keepTrackApi.getCatalogManager().getSat(this.watchlistList[i].id, GetSatType.EXTRA_ONLY); satIds[i] = sat.sccNum; } diff --git a/src/settings/versionDate.js b/src/settings/versionDate.js index 2d66317b0..f4e24ab4a 100644 --- a/src/settings/versionDate.js +++ b/src/settings/versionDate.js @@ -1,2 +1,2 @@ // THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -export const VERSION_DATE = 'August 14, 2024'; +export const VERSION_DATE = 'August 16, 2024'; diff --git a/src/singletons/camera.ts b/src/singletons/camera.ts index 611fd7ed8..53f9521a5 100644 --- a/src/singletons/camera.ts +++ b/src/singletons/camera.ts @@ -33,7 +33,6 @@ import { SettingsManager } from '../settings/settings'; import { LegendManager } from '../static/legend-manager'; import { SatMath } from '../static/sat-math'; import { MissileObject } from './catalog-manager/MissileObject'; -import { LineTypes } from './draw-manager/line-manager'; import { errorManagerInstance } from './errorManager'; import type { OrbitManager } from './orbitManager'; @@ -1029,11 +1028,6 @@ export class Camera { } lineManagerInstance.clear(); - if (catalogManagerInstance.isStarManagerLoaded) { - keepTrackApi.getStarManager().isAllConstellationVisible = false; - } - - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_REF, [sat.position.x, sat.position.y, sat.position.z], [1, 0.4, 0, 1]); this.cameraType = CameraType.DEFAULT; // Earth will block the view of the star this.lookAtPosition(sat.position, false, timeManagerInstance.selectedDate); } diff --git a/src/singletons/catalog-manager/satLinkManager.ts b/src/singletons/catalog-manager/satLinkManager.ts index 80898c2ad..ee58912a5 100644 --- a/src/singletons/catalog-manager/satLinkManager.ts +++ b/src/singletons/catalog-manager/satLinkManager.ts @@ -4,7 +4,7 @@ import { keepTrackApi } from '@app/keepTrackApi'; import { SensorMath } from '@app/static/sensor-math'; import numeric from 'numeric'; import { DetailedSatellite, DetailedSensor, RAD2DEG } from 'ootk'; -import { LineManager, LineTypes } from '../draw-manager/line-manager'; +import { LineManager } from '../draw-manager/line-manager'; import { errorManagerInstance } from '../errorManager'; import { TimeManager } from '../time-manager'; import { ControlSite } from './ControlSite'; @@ -205,8 +205,8 @@ export class SatLinkManager { for (let j = 0; j < satlist.length; j++) { if (i !== j) { const catalogManagerInstance = keepTrackApi.getCatalogManager(); - const sat1 = catalogManagerInstance.getObject(satlist[i]); - const sat2 = catalogManagerInstance.getObject(satlist[j]); + const sat1 = catalogManagerInstance.getSat(satlist[i]); + const sat2 = catalogManagerInstance.getSat(satlist[j]); /* * * Debug for finding decayed satellites @@ -225,16 +225,16 @@ export class SatLinkManager { [-sat1.position.x + sat2.position.x, -sat1.position.y + sat2.position.y, -sat1.position.z + sat2.position.z], ) ) / - (Math.sqrt((-sat1.position.x) ** 2 + (-sat1.position.y) ** 2 + (-sat1.position.z) ** 2) * - Math.sqrt( - (-sat1.position.x + sat2.position.x) ** 2 + (-sat1.position.y + sat2.position.y) ** 2 + (-sat1.position.z + sat2.position.z) ** 2, - )), + (Math.sqrt((-sat1.position.x) ** 2 + (-sat1.position.y) ** 2 + (-sat1.position.z) ** 2) * + Math.sqrt( + (-sat1.position.x + sat2.position.x) ** 2 + (-sat1.position.y + sat2.position.y) ** 2 + (-sat1.position.z + sat2.position.z) ** 2, + )), ) * RAD2DEG; if (theta < minTheta) { // Intentional } else { - lineManager.create(LineTypes.SENSOR_TO_SAT, [sat1.id, sat2.id], [0, 0.6, 1, 1]); + lineManager.createObjToObj(sat1, sat2, [0, 0.6, 1, 1]); } } } @@ -259,7 +259,7 @@ export class SatLinkManager { } } if (bestSat) { - lineManager.create(LineTypes.SENSOR_TO_SAT, [bestSat.id, id], [0, 1.0, 0.6, 1.0]); + lineManager.createSensorToSat(keepTrackApi.getSensorManager().getSensor(), bestSat, [0, 1.0, 0.6, 1.0]); } } } catch (e) { @@ -313,7 +313,7 @@ export class SatLinkManager { } } // Draw a line from the user to the satellite - lineManager.create(LineTypes.SENSOR_TO_SAT, [bestSat.id, catalogManagerInstance.getSensorFromSensorName(user.name)], [0, 1.0, 0.6, 1.0]); + lineManager.createSensorToSat(keepTrackApi.getSensorManager().getSensor(), bestSat, [0, 1.0, 0.6, 1.0]); } } catch (e) { errorManagerInstance.info(e); diff --git a/src/singletons/draw-manager/line-manager.ts b/src/singletons/draw-manager/line-manager.ts index 3cb26e7b1..29d8a43c8 100644 --- a/src/singletons/draw-manager/line-manager.ts +++ b/src/singletons/draw-manager/line-manager.ts @@ -1,63 +1,29 @@ /* eslint-disable max-depth */ /* eslint-disable complexity */ /* eslint-disable camelcase */ -import { EciArr3, GetSatType, KeepTrackApiEvents, Singletons } from '@app/interfaces'; -import { BaseObject, Degrees, DetailedSatellite, Kilometers, SpaceObjectType, Star, ecf2eci, ecf2rae, eci2ecf, lla2ecf, rae2ecf } from 'ootk'; +import { KeepTrackApiEvents, Singletons } from '@app/interfaces'; +import { BaseObject, DetailedSatellite, DetailedSensor } from 'ootk'; import { keepTrackApi } from '@app/keepTrackApi'; import { BufferAttribute } from '@app/static/buffer-attribute'; import { WebGlProgramHelper } from '@app/static/webgl-program'; -import { mat4, vec4 } from 'gl-matrix'; +import { mat4, vec3, vec4 } from 'gl-matrix'; import { keepTrackContainer } from '../../container'; -import { SensorMath } from '../../static/sensor-math'; -import { WebGLRenderer } from '../webgl-renderer'; -import { Line } from './line-manager/line'; - -export enum LineTypes { - CENTER_OF_EARTH_TO_SAT = 'sat', - REF_TO_SAT = 'sat2', - SELECTED_SENSOR_TO_SAT_IF_IN_FOV = 'sat3', - SELECTED_SENSOR_TO_SELECTED_SAT_IF_IN_FOV = 'sat4', - SENSOR_TO_SAT = 'sat5', - MULTI_SENSORS_TO_SAT = 'sat6', - SAT_SCAN_EARTH = 'scan', - SENSOR_SCAN_HORIZON = 'scan2', - SAT_TO_MISL = 'misl', - CENTER_OF_EARTH_TO_REF = 'ref', - REF_TO_REF = 'ref2', - SENSOR_TO_SUN = 'SENSOR_TO_SUN', - SENSOR_TO_MOON = 'SENSOR_TO_MOON', -} -export type LineColors = 'r' | 'o' | 'y' | 'g' | 'b' | 'c' | 'p' | 'w' | [number, number, number, number]; - -export type LineTask = { - line: Line; - sat?: DetailedSatellite; - sat2?: DetailedSatellite; - star1?: string; - star2?: string; - star1ID?: number; - star2ID?: number; - ref?: EciArr3; - ref2?: EciArr3; - color?: [number, number, number, number]; - isOnlyInFOV?: boolean; - isDrawWhenSelected?: boolean; - isCalculateIfInFOV?: boolean; - isScan?: boolean; - isScan2?: boolean; - lat?: Degrees; - lon?: Degrees; - az?: Degrees; - minAz?: Degrees; - maxAz?: Degrees; - minEl?: Degrees; - maxRng?: Kilometers; - type: LineTypes; -}; +import { MissileObject } from '../catalog-manager/MissileObject'; +import { Line, LineColor, LineColors } from './line-manager/line'; +import { ObjToObjLine } from './line-manager/obj-to-obj-line'; +import { RefToRefLine } from './line-manager/ref-to-ref-line'; +import { SatRicLine } from './line-manager/sat-ric-line'; +import { SatScanEarthLine } from './line-manager/sat-scan-earth-line'; +import { SatToRefLine } from './line-manager/sat-to-ref-line'; +import { SatToSunLine } from './line-manager/sat-to-sun-line'; +import { SensorScanHorizonLine } from './line-manager/sensor-scan-horizon-line'; +import { SensorToMoonLine } from './line-manager/sensor-to-moon-line'; +import { SensorToSatLine } from './line-manager/sensor-to-sat-line'; +import { SensorToSunLine } from './line-manager/sensor-to-sun-line'; export class LineManager { - private attribs_ = { + attribs = { a_position: new BufferAttribute({ location: 0, vertices: 4, @@ -65,375 +31,138 @@ export class LineManager { stride: 0, }), }; - - private gl_: WebGL2RenderingContext; - private tempStar1_: Star; - private tempStar2_: Star; - private uniforms_ = { + uniforms_ = { u_color: null, u_camMatrix: null, u_pMatrix: null, }; - - drawLineList = []; program: WebGLProgram; - static getColor(color?: LineColors): [number, number, number, number] { - color ??= [1.0, 0, 1.0, 1.0]; - switch (color) { - case 'r': - color = [1.0, 0.0, 0.0, 1.0]; - break; - case 'o': - color = [1.0, 0.5, 0.0, 1.0]; - break; - case 'y': - color = [1.0, 1.0, 0.0, 1.0]; - break; - case 'g': - color = [0.0, 1.0, 0.0, 1.0]; - break; - case 'b': - color = [0.0, 0.0, 1.0, 1.0]; - break; - case 'c': - color = [0.0, 1.0, 1.0, 1.0]; - break; - case 'p': - color = [1.0, 0.0, 1.0, 1.0]; - break; - case 'w': - color = [1.0, 1.0, 1.0, 1.0]; - break; - default: - // If color not a letter than assume its been set - if (color.length !== 4) { - throw new Error('Color must be a 4 element array or a valid string!'); - } - break; - } - - return color; - } + lines = []; clear(): void { - this.drawLineList = []; + this.lines = []; + keepTrackApi.runEvent(KeepTrackApiEvents.onLineAdded, keepTrackApi.getLineManager()); } - create(type: LineTypes, value: number[], inputColor?: LineColors): void { - const color = LineManager.getColor(inputColor); - - switch (type) { - case LineTypes.CENTER_OF_EARTH_TO_SAT: - this.createSat_(value as [number], color); - break; - case LineTypes.REF_TO_SAT: - this.createSat2_(value as [number, number, number, number], color); - break; - case LineTypes.SELECTED_SENSOR_TO_SAT_IF_IN_FOV: - this.createSat3_(value as [number, number], color); - break; - case LineTypes.SELECTED_SENSOR_TO_SELECTED_SAT_IF_IN_FOV: - this.createSat4_(value as [number, number], color); - break; - case LineTypes.SENSOR_TO_SAT: - this.createSat5_(value as [number, number], color); - break; - case LineTypes.MULTI_SENSORS_TO_SAT: - this.createSat6_(value as [number, number], color); - break; - case LineTypes.SAT_SCAN_EARTH: - this.createScan_(value as [number], color); - break; - case LineTypes.SENSOR_SCAN_HORIZON: - this.createScan2_(value as [number, Degrees, Degrees, Degrees, Kilometers], color); - break; - case LineTypes.SAT_TO_MISL: - this.createMisl_(value as [number, number], color); - break; - case LineTypes.CENTER_OF_EARTH_TO_REF: - this.createRef_(value as [number, number, number], color); - break; - case LineTypes.SENSOR_TO_SUN: - case LineTypes.SENSOR_TO_MOON: - case LineTypes.REF_TO_REF: - this.createRef2_(value as [number, number, number, number, number, number], color, type); - break; - default: - break; - } - + add(line: Line): void { + this.lines.push(line); keepTrackApi.runEvent(KeepTrackApiEvents.onLineAdded, this); } - /** - * Reference Point to Reference Point - */ - private createRef2_(value: [number, number, number, number, number, number], color: [number, number, number, number], type = LineTypes.REF_TO_REF) { - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [value[0], value[1], value[2]], - ref2: [value[3], value[4], value[5]], - color, - type, - }); - } + createSatRicFrame(sat: DetailedSatellite | MissileObject | null): void { + if (!sat || sat instanceof MissileObject) { + return; + } - /** - * Center of the Earth to the Reference Point - */ - private createRef_(value: [number, number, number], color: [number, number, number, number]) { - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [0, 0, 0], - ref2: [value[0], value[1], value[2]], - color, - type: LineTypes.CENTER_OF_EARTH_TO_REF, - }); + this.add(new SatRicLine(sat, 'I', LineColors.GREEN)); + this.add(new SatRicLine(sat, 'R', LineColors.RED)); + this.add(new SatRicLine(sat, 'C', LineColors.BLUE)); } - /** - * Satellite to Missile - */ - private createMisl_(value: [number, number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - const sat2 = keepTrackApi.getCatalogManager().getObject(value[1]) as DetailedSatellite; + createSatToRef(sat: DetailedSatellite | MissileObject | null, ref: vec3, color?: vec4): void { + if (!sat || sat instanceof MissileObject) { + return; + } - if (!sat || !sat2 || !sat.position || !sat.position.x || !sat2.position || !sat2.position.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - console.debug(sat2); + this.add(new SatToRefLine(sat, ref, color)); + } + createSat2Sun(sat: DetailedSatellite | MissileObject | null): void { + if (!sat || sat instanceof MissileObject) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - sat2, - ref: [sat.position.x, sat.position.y, sat.position.z], - ref2: [sat2.position.x, sat2.position.y, sat2.position.z], - color, - type: LineTypes.SAT_TO_MISL, - }); - } - /** - * Center of the Earth to the Satellite - */ - private createSat_(value: [number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; + this.add(new SatToSunLine(sat)); + } - if (!sat?.position?.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); + createRef2Ref(ref1: vec3, ref2: vec3, color: vec4): void { + this.add(new RefToRefLine(ref1, ref2, color)); + } + createSensorToSun(sensor: DetailedSensor | null): void { + if (!sensor) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - ref: [0, 0, 0], - ref2: [sat.position.x, sat.position.y, sat.position.z], - color, - type: LineTypes.CENTER_OF_EARTH_TO_SAT, - }); + this.add(new SensorToSunLine(sensor)); } - /** - * Reference Point to Satellite - */ - private createSat2_(value: [number, number, number, number], color: [number, number, number, number], type: LineTypes = LineTypes.REF_TO_SAT) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - - if (!sat?.position?.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - + createSensorToMoon(sensor: DetailedSensor | null): void { + if (!sensor) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - ref: [value[1], value[2], value[3]], - ref2: [sat.position.x, sat.position.y, sat.position.z], - color, - type, - }); + this.add(new SensorToMoonLine(sensor)); } - /** - * Sensor to Satellite When in View of Currently Selected Sensor - */ - private createSat3_(value: [number, number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - const sat2 = keepTrackApi.getCatalogManager().getObject(value[1]) as DetailedSatellite; - - if (!sat || !sat2 || !sat.position || !sat.position.x || !sat2.position || !sat2.position.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - console.debug(sat2); - + createSatScanEarth(sat: DetailedSatellite | null, color?: vec4): void { + if (!sat) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - sat2, - ref: [sat.position.x, sat.position.y, sat.position.z], - ref2: [sat2.position.x, sat2.position.y, sat2.position.z], - color, - isOnlyInFOV: true, - isDrawWhenSelected: false, - type: LineTypes.SELECTED_SENSOR_TO_SAT_IF_IN_FOV, - }); + this.add(new SatScanEarthLine(sat, color)); } - /** - * Sensor to Satellite When in View of Currently Selected Sensor and Satellite Selected - */ - private createSat4_(value: [number, number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - const sat2 = keepTrackApi.getCatalogManager().getObject(value[1]) as DetailedSatellite; - - if (!sat || !sat2 || !sat.position || !sat.position.x || !sat2.position || !sat2.position.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - console.debug(sat2); - + createSensorScanHorizon(sensor: DetailedSensor | null, face = 1, faces = 2, color = LineColors.CYAN): void { + if (!sensor) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - sat2, - ref: [sat.position.x, sat.position.y, sat.position.z], - ref2: [sat2.position.x, sat2.position.y, sat2.position.z], - color, - isOnlyInFOV: true, - isDrawWhenSelected: true, - type: LineTypes.SELECTED_SENSOR_TO_SELECTED_SAT_IF_IN_FOV, - }); + + this.add(new SensorScanHorizonLine(sensor, face, faces, color)); } - /** - * One Sensor to Satellite - */ - private createSat5_(value: [number, number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - const sat2 = keepTrackApi.getCatalogManager().getObject(value[1]) as DetailedSatellite; + createSensorToSat(sensor: DetailedSensor | null, sat: DetailedSatellite | MissileObject | null, color?: vec4): void { + if (!sensor || !sat || sat instanceof MissileObject) { + return; + } - if (!sat || !sat2 || !sat.position || !sat.position.x || !sat2.position || !sat2.position.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - console.debug(sat2); + this.add(new SensorToSatLine(sensor, sat, color)); + } + createObjToObj(obj1: DetailedSatellite | MissileObject | null, obj2: DetailedSatellite | MissileObject | null, color?: vec4): void { + if (!obj1 || !obj2) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - sat2, - ref: [sat.position.x, sat.position.y, sat.position.z], - ref2: [sat2.position.x, sat2.position.y, sat2.position.z], - color, - isOnlyInFOV: false, - isDrawWhenSelected: false, - type: LineTypes.SENSOR_TO_SAT, - }); + this.add(new ObjToObjLine(obj1, obj2, color)); } - /** - * Multiple Sensors to Satellite - */ - private createSat6_(value: [number, number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; - const sat2 = keepTrackApi.getCatalogManager().getObject(value[1]) as DetailedSatellite; - - if (!sat || !sat2 || !sat.position || !sat.position.x || !sat2.position || !sat2.position.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); - console.debug(sat2); - + createSensorToSatFovOnly(sensor: DetailedSensor | null, sat: DetailedSatellite | null, color?: vec4): void { + if (!sensor || !sat) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - sat2, - ref: [sat.position.x, sat.position.y, sat.position.z], - ref2: [sat2.position.x, sat2.position.y, sat2.position.z], - color, - isOnlyInFOV: true, - isDrawWhenSelected: false, - isCalculateIfInFOV: true, - type: LineTypes.MULTI_SENSORS_TO_SAT, - }); - } - /** - * Scanning Satellite to Reference Points on Earth in FOV - */ - private createScan_(value: [number], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; + const line = new SensorToSatLine(sensor, sat, color); - if (!sat?.position?.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); + line.setDrawFovOnly(true); + this.add(line); + } + createSensorToSatFovAndSelectedOnly(sensor: DetailedSensor | null, sat: DetailedSatellite | null, color?: vec4): void { + if (!sensor || !sat) { return; } - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - ref: [0, 0, 0], - ref2: [sat.position.x, sat.position.y, sat.position.z], - color, - isScan: true, - lat: -90, - lon: 0, - type: LineTypes.SAT_SCAN_EARTH, - }); + const line = new SensorToSatLine(sensor, sat, color); + + line.setDrawFovOnly(true); + line.setDrawSelectedOnly(true); + this.add(line); } - /** - * Scanning Satellite to Reference Points on Earth in FOV - */ - private createScan2_(value: [number, Degrees, Degrees, Degrees, Kilometers], color: [number, number, number, number]) { - const sat = keepTrackApi.getCatalogManager().getObject(value[0]) as DetailedSatellite; + createSensorsToSatFovOnly(sat: DetailedSatellite, color?: vec4): void { + const sensorManagerInstance = keepTrackApi.getSensorManager(); - if (!sat?.position?.x) { - console.debug('No Satellite Position Available for Line'); - console.debug(sat); + for (const sensor of sensorManagerInstance.getAllSensors()) { + const line = new SensorToSatLine(sensor, sat, color); - return; + line.setDrawFovOnly(true); + this.add(line); } - - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - sat, - ref: [0, 0, 0], - ref2: [sat.position.x, sat.position.y, sat.position.z], - color, - isScan2: true, - az: value[1], - minAz: value[1], - maxAz: value[2], - minEl: value[3], - maxRng: value[4], - type: LineTypes.SENSOR_SCAN_HORIZON, - }); } - createGrid(type: 'x' | 'y' | 'z', inputColor?: LineColors, scalar?: number): void { + createGrid(type: 'x' | 'y' | 'z', color?: LineColor, scalar = 1): void { if (type !== 'x' && type !== 'y' && type !== 'z') { throw new Error('Invalid type'); } - const color = LineManager.getColor(inputColor); - - scalar ??= 1; - const num1 = 10000 / scalar; const num2 = num1 * 7 * scalar; const min = -7 * scalar; @@ -442,56 +171,20 @@ export class LineManager { switch (type) { case 'x': for (let i = min; i <= max; i++) { - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [num2, i * num1, 0], - ref2: [-num2, i * num1, 0], - color, - type: LineTypes.REF_TO_REF, - }); - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [i * num1, num2, 0], - ref2: [i * num1, -num2, 0], - color, - type: LineTypes.REF_TO_REF, - }); + this.add(new RefToRefLine([num2, i * num1, 0], [-num2, i * num1, 0], color)); + this.add(new RefToRefLine([i * num1, num2, 0], [i * num1, -num2, 0], color)); } break; case 'y': for (let i = min; i <= max; i++) { - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [num2, 0, i * num1], - ref2: [-num2, 0, i * num1], - color, - type: LineTypes.REF_TO_REF, - }); - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [i * num1, 0, num2], - ref2: [i * num1, 0, -num2], - color, - type: LineTypes.REF_TO_REF, - }); + this.add(new RefToRefLine([0, num2, i * num1], [0, -num2, i * num1], color)); + this.add(new RefToRefLine([0, i * num1, num2], [0, i * num1, -num2], color)); } break; case 'z': for (let i = min; i <= max; i++) { - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [0, num2, i * num1], - ref2: [0, -num2, i * num1], - color, - type: LineTypes.REF_TO_REF, - }); - this.drawLineList.push({ - line: new Line(this.gl_, this.attribs_, this.uniforms_), - ref: [0, i * num1, num2], - ref2: [0, i * num1, -num2], - color, - type: LineTypes.REF_TO_REF, - }); + this.add(new RefToRefLine([num2, 0, i * num1], [-num2, 0, i * num1], color)); + this.add(new RefToRefLine([i * num1, num2, 0], [i * num1, -num2, 0], color)); } break; default: @@ -499,291 +192,91 @@ export class LineManager { } } - draw(renderer: WebGLRenderer, inViewData: Int8Array, camMatrix: mat4, tgtBuffer: WebGLFramebuffer = null): void { - const gl = this.gl_; - const { gmst, projectionMatrix } = renderer; + draw(tgtBuffer: WebGLFramebuffer = null): void { + if (this.lines.length === 0) { + return; + } - gl.bindFramebuffer(gl.FRAMEBUFFER, tgtBuffer); - gl.useProgram(this.program); + this.runBeforeDraw(tgtBuffer); - gl.uniformMatrix4fv(this.uniforms_.u_camMatrix, false, camMatrix); - gl.uniformMatrix4fv(this.uniforms_.u_pMatrix, false, projectionMatrix); + for (let i = this.lines.length - 1; i >= 0; i--) { + if (this.lines[i].isGarbage) { + this.lines.splice(i, 1); + } + } - gl.enableVertexAttribArray(this.attribs_.a_position.location); // Enable + for (const line of this.lines) { + line.draw(this); + } - if (this.drawLineList.length == 0) { - return; + this.runAfterDraw(); + } + + update(): void { + for (const line of this.lines) { + line.update(); } - const catalogManagerInstance = keepTrackApi.getCatalogManager(); - - for (let i = 0; i < this.drawLineList.length; i++) { - try { - if (typeof this.drawLineList[i].sat !== 'undefined' && this.drawLineList[i].sat != null && typeof this.drawLineList[i].sat.id !== 'undefined') { - // At least One Satellite - this.drawLineList[i].sat = catalogManagerInstance.getObject(this.drawLineList[i].sat.id, GetSatType.POSITION_ONLY) as DetailedSatellite; - if (typeof this.drawLineList[i].sat2 !== 'undefined' && this.drawLineList[i].sat2 != null) { - // Satellite and Static - if (typeof this.drawLineList[i].sat2.name !== 'undefined') { - if (typeof this.drawLineList[i].sat2.id === 'undefined' && this.drawLineList[i].sat2 != null) { - this.drawLineList[i].sat2.id = catalogManagerInstance.getSensorFromSensorName(this.drawLineList[i].sat2.name); - } - this.drawLineList[i].sat2 = catalogManagerInstance.getObject(this.drawLineList[i].sat2.id) as DetailedSatellite; - if ( - (!this.drawLineList[i].isCalculateIfInFOV && this.drawLineList[i].isOnlyInFOV && !inViewData[this.drawLineList[i].sat.id]) || - !settingsManager.isDrawInCoverageLines - ) { - this.drawLineList.splice(i, 1); - continue; - } - if (this.drawLineList[i].isCalculateIfInFOV && this.drawLineList[i].isOnlyInFOV) { - const staticSet = keepTrackApi.getCatalogManager().staticSet; - - Object.keys(staticSet).forEach((key) => { - const sensor = staticSet[key]; - - if (sensor.name == this.drawLineList[i].sat2.name) { - const tearr = SensorMath.getTearr(this.drawLineList[i].sat, [sensor]); - - if (!tearr.inView || !settingsManager.isDrawInCoverageLines) { - this.drawLineList.splice(i, 1); - } - } - }); - } - this.drawLineList[i].line.update( - [this.drawLineList[i].sat.position.x, this.drawLineList[i].sat.position.y, this.drawLineList[i].sat.position.z], - [this.drawLineList[i].sat2.position.x, this.drawLineList[i].sat2.position.y, this.drawLineList[i].sat2.position.z], - ); - } else { - // Two Satellites - this.drawLineList[i].sat2 = catalogManagerInstance.getObject(this.drawLineList[i].sat2.id, GetSatType.POSITION_ONLY) as DetailedSatellite; - this.drawLineList[i].line.update( - [this.drawLineList[i].sat.position.x, this.drawLineList[i].sat.position.y, this.drawLineList[i].sat.position.z], - [this.drawLineList[i].sat2.position.x, this.drawLineList[i].sat2.position.y, this.drawLineList[i].sat2.position.z], - ); - } - } else if (this.drawLineList[i].isScan) { - let t = 0; - - while (t < 1000) { - this.drawLineList[i].lon = (this.drawLineList[i].lon + settingsManager.lineScanSpeedSat); - if (this.drawLineList[i].lon > 180) { - this.drawLineList[i].lon = -180; - } - if (this.drawLineList[i].lon >= 0 && this.drawLineList[i].lon < settingsManager.lineScanSpeedSat) { - this.drawLineList[i].lat = (this.drawLineList[i].lat + settingsManager.lineScanSpeedSat); - } - if (this.drawLineList[i].lat > 90) { - this.drawLineList[i].lat = -90; - } - - const lla = { lat: this.drawLineList[i].lat, lon: this.drawLineList[i].lon, alt: 0.05 }; - const ecf = eci2ecf(this.drawLineList[i].sat.position, 0); - const rae = ecf2rae(lla, ecf); - const el = rae.el; - - if (el > settingsManager.lineScanMinEl) { - const pos = lla2ecf(lla); - - this.drawLineList[i].line.update( - [pos.x, pos.y, pos.z], - [this.drawLineList[i].sat.position.x, this.drawLineList[i].sat.position.y, this.drawLineList[i].sat.position.z], - ); - break; - } - - if (this.drawLineList[i].lat === -90) { - this.drawLineList[i].lat = (this.drawLineList[i].lat + settingsManager.lineScanSpeedSat); - } - if (this.drawLineList[i].lat === 90) { - this.drawLineList[i].lat = -90; - } - - t++; - } - } else if (this.drawLineList[i].isScan2) { - this.drawLineList[i].az = (this.drawLineList[i].az + settingsManager.lineScanSpeedRadar); - // Normalize azimuth - if (this.drawLineList[i].az > 360) { - this.drawLineList[i].az = 0; - } - // Is azimuth outside of FOV? - if ( - (this.drawLineList[i].maxAz > this.drawLineList[i].minAz && this.drawLineList[i].az > this.drawLineList[i].maxAz) || - (this.drawLineList[i].maxAz < this.drawLineList[i].minAz && - this.drawLineList[i].az > this.drawLineList[i].maxAz && - this.drawLineList[i].az < this.drawLineList[i].minAz) - ) { - // Reset it - this.drawLineList[i].az = this.drawLineList[i].minAz; - } - /* - * Calculate ECI for that RAE coordinate - * Adding 30km to altitude to avoid clipping the earth - */ - const lla = this.drawLineList[i].sat.lla(keepTrackApi.getTimeManager().simulationTimeObj); - const pos = ecf2eci( - rae2ecf( - { - rng: this.drawLineList[i].maxRng, - az: this.drawLineList[i].az, - el: this.drawLineList[i].minEl, - }, - { - lat: lla.lat, - lon: lla.lon, - alt: lla.alt + 30, - }, - ), - gmst, - ); - // Update the line - - this.drawLineList[i].line.update( - [pos.x, pos.y, pos.z], - [this.drawLineList[i].sat.position.x, this.drawLineList[i].sat.position.y, this.drawLineList[i].sat.position.z], - ); - } else { - // Just One Satellite - this.drawLineList[i].line.update(this.drawLineList[i].ref, [ - this.drawLineList[i].sat.position.x, - this.drawLineList[i].sat.position.y, - this.drawLineList[i].sat.position.z, - ]); - } - } else if ( - typeof this.drawLineList[i].star1 !== 'undefined' && - typeof this.drawLineList[i].star2 !== 'undefined' && - this.drawLineList[i].star1 != null && - this.drawLineList[i].star2 != null - ) { - // Constellation - const dotsManagerInstance = keepTrackApi.getDotsManager(); - const starIdx1 = dotsManagerInstance.starIndex1; - const starIdx2 = dotsManagerInstance.starIndex2; - - if (typeof this.drawLineList[i].star1ID === 'undefined') { - this.drawLineList[i].star1ID = catalogManagerInstance.starName2Id(this.drawLineList[i].star1, starIdx1, starIdx2); - } - if (typeof this.drawLineList[i].star2ID === 'undefined') { - this.drawLineList[i].star2ID = catalogManagerInstance.starName2Id(this.drawLineList[i].star2, starIdx1, starIdx2); - } - this.tempStar1_ = catalogManagerInstance.getObject(this.drawLineList[i].star1ID, GetSatType.POSITION_ONLY) as Star; - this.tempStar2_ = catalogManagerInstance.getObject(this.drawLineList[i].star2ID, GetSatType.POSITION_ONLY) as Star; - this.drawLineList[i].line.update( - [this.tempStar1_.position.x, this.tempStar1_.position.y, this.tempStar1_.position.z], - [this.tempStar2_.position.x, this.tempStar2_.position.y, this.tempStar2_.position.z], - ); - } else { - // Arbitrary Lines - this.drawLineList[i].line.update(this.drawLineList[i].ref, this.drawLineList[i].ref2); - } + } - this.drawLineList[i].line.draw(this.drawLineList[i].color); - } catch (error) { - /* - * DEBUG: - * console.warn(error); - */ - } + runBeforeDraw(tgtBuffer: WebGLFramebuffer) { + const { projectionMatrix, gl } = keepTrackApi.getRenderer(); - // When multiple sensors are selected it will keep creating new lines so we have to purge them - const sensorManagerInstance = keepTrackApi.getSensorManager(); + gl.bindFramebuffer(gl.FRAMEBUFFER, tgtBuffer); + gl.useProgram(this.program); - if (sensorManagerInstance.currentSensors.length > 1 && this.drawLineList[i].isOnlyInFOV && !this.drawLineList[i].isDrawWhenSelected) { - this.drawLineList.splice(i, 1); - } - } + gl.uniformMatrix4fv(this.uniforms_.u_camMatrix, false, keepTrackApi.getMainCamera().camMatrix); + gl.uniformMatrix4fv(this.uniforms_.u_pMatrix, false, projectionMatrix); - gl.disableVertexAttribArray(this.attribs_.a_position.location); // Reset + gl.enableVertexAttribArray(this.attribs.a_position.location); // Enable } - drawWhenSelected(): void { - for (let i = 0; i < this.drawLineList.length; i++) { - if (this.drawLineList[i].isDrawWhenSelected) { - this.drawLineList.splice(i, 1); - } - } + runAfterDraw() { + const gl = keepTrackApi.getRenderer().gl; + + gl.disableVertexAttribArray(this.attribs.a_position.location); // Disable } init() { - this.gl_ = keepTrackApi.getRenderer().gl; - this.program = new WebGlProgramHelper(this.gl_, this.shaders_.vert, this.shaders_.frag, this.attribs_, this.uniforms_).program; + const gl = keepTrackApi.getRenderer().gl; + + this.program = new WebGlProgramHelper(gl, this.shaders_.vert, this.shaders_.frag, this.attribs, this.uniforms_).program; keepTrackApi.register({ event: KeepTrackApiEvents.selectSatData, cbName: 'LineManager', cb: (sat: BaseObject) => { if (sat) { - const sensorManagerInstance = keepTrackApi.getSensorManager(); - - keepTrackApi.getOrbitManager().setSelectOrbit(sat.id); - if (sensorManagerInstance.isSensorSelected() && keepTrackApi.getDotsManager().inViewData?.[sat.id] === 1) { - this.drawWhenSelected(); - this.updateLineToSat(sat.id, keepTrackApi.getCatalogManager().getSensorFromSensorName(sensorManagerInstance.currentSensors[0].name)); - } - } else { - this.drawWhenSelected(); + const sensor = keepTrackApi.getSensorManager().getSensor(); + + this.createSensorToSatFovAndSelectedOnly(sensor, sat as DetailedSatellite); } }, }); } - removeStars(): boolean { - let starFound = false; - - for (let i = 0; i < this.drawLineList.length; i++) { - if ( - (typeof this.drawLineList[i].sat !== 'undefined' && this.drawLineList[i].sat.type === SpaceObjectType.STAR) || - (typeof this.drawLineList[i].sat2 !== 'undefined' && this.drawLineList[i].sat2.type === SpaceObjectType.STAR) - ) { - this.drawLineList.splice(i, 1); - starFound = true; - } - } - - return starFound; - } - setAttribsAndDrawLineStrip(buffer: WebGLBuffer, segments: number) { - const gl = this.gl_; + const gl = keepTrackApi.getRenderer().gl; gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.vertexAttribPointer(this.attribs_.a_position.location, 4, gl.FLOAT, false, 0, 0); - gl.enableVertexAttribArray(this.attribs_.a_position.location); + gl.vertexAttribPointer(this.attribs.a_position.location, 4, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(this.attribs.a_position.location); gl.drawArrays(gl.LINE_STRIP, 0, segments); - gl.disableVertexAttribArray(this.attribs_.a_position.location); + gl.disableVertexAttribArray(this.attribs.a_position.location); } setColorUniforms(color: vec4) { - this.gl_.uniform4fv(this.uniforms_.u_color, color); + const gl = keepTrackApi.getRenderer().gl; + + gl.uniform4fv(this.uniforms_.u_color, color); } setWorldUniforms(camMatrix: mat4, pMatrix: mat4) { - const gl = this.gl_; + const gl = keepTrackApi.getRenderer().gl; gl.uniformMatrix4fv(this.uniforms_.u_camMatrix, false, camMatrix); gl.uniformMatrix4fv(this.uniforms_.u_pMatrix, false, pMatrix); } - updateLineToSat(satId: number, sensorId: number) { - let isLineDrawnToSat = false; - - for (const line of this.drawLineList) { - if (typeof line.sat === 'undefined') { - continue; - } - - if (line.sat.id == satId) { - isLineDrawnToSat = true; - } - } - - if (!isLineDrawnToSat) { - this.create(LineTypes.SELECTED_SENSOR_TO_SELECTED_SAT_IF_IN_FOV, [satId, sensorId], 'g'); - } - } - private shaders_ = { frag: keepTrackApi.glsl`#version 300 es precision mediump float; diff --git a/src/singletons/draw-manager/line-manager/line.ts b/src/singletons/draw-manager/line-manager/line.ts index a07ae353a..799174285 100644 --- a/src/singletons/draw-manager/line-manager/line.ts +++ b/src/singletons/draw-manager/line-manager/line.ts @@ -1,35 +1,36 @@ /* eslint-disable camelcase */ import { EciArr3 } from '@app/interfaces'; -import { BufferAttribute } from '@app/static/buffer-attribute'; +import { keepTrackApi } from '@app/keepTrackApi'; import { vec4 } from 'gl-matrix'; import { GlUtils } from '../../../static/gl-utils'; +import { LineManager } from '../line-manager'; + +export type LineColor = typeof LineColors[keyof typeof LineColors] | vec4; + +export const LineColors = { + RED: [1.0, 0.0, 0.0, 1.0] as vec4, + ORANGE: [1.0, 0.5, 0.0, 1.0] as vec4, + YELLOW: [1.0, 1.0, 0.0, 1.0] as vec4, + GREEN: [0.0, 1.0, 0.0, 1.0] as vec4, + BLUE: [0.0, 0.0, 1.0, 1.0] as vec4, + CYAN: [0.0, 1.0, 1.0, 1.0] as vec4, + PURPLE: [1.0, 0.0, 1.0, 1.0] as vec4, + WHITE: [1.0, 1.0, 1.0, 1.0] as vec4, +}; /** * A line with a start and end point. * * It requires a precompiled shader program and its attributes to work. */ -export class Line { - private attribs_: { a_position: BufferAttribute }; - - private gl_: WebGL2RenderingContext; - private uniforms_: { u_color: WebGLUniformLocation; u_camMatrix: WebGLUniformLocation; u_pMatrix: WebGLUniformLocation }; +export abstract class Line { private vertBuf_: WebGLBuffer; + protected color_: vec4; + protected isDraw_: boolean = true; + isGarbage: boolean = false; - constructor( - gl: WebGL2RenderingContext, - attribs: { - a_position: BufferAttribute; - }, - uniforms: { - u_color: WebGLUniformLocation; - u_camMatrix: WebGLUniformLocation; - u_pMatrix: WebGLUniformLocation; - }, - ) { - this.gl_ = gl; - this.attribs_ = attribs; - this.uniforms_ = uniforms; + constructor() { + const gl = keepTrackApi.getRenderer().gl; this.vertBuf_ = gl.createBuffer(); GlUtils.bindBufferStreamDraw(gl, this.vertBuf_, new Float32Array(6)); @@ -38,22 +39,32 @@ export class Line { /** * This assumes that LineManager.drawFirst has already run and LineManager.drawLast will run after all lines are drawn. */ - draw(color = [1.0, 1.0, 1.0, 1.0]) { - if (color[0] < 0 || color[0] > 1 || color[1] < 0 || color[1] > 1 || color[2] < 0 || color[2] > 1 || color[3] < 0 || color[3] > 1) { - throw new Error('Invalid color'); + draw(lineManager: LineManager): void { + if (!this.isDraw_) { + return; } - const gl = this.gl_; + const gl = keepTrackApi.getRenderer().gl; - gl.uniform4fv(this.uniforms_.u_color, color); + gl.uniform4fv(lineManager.uniforms_.u_color, this.color_); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertBuf_); - gl.vertexAttribPointer(this.attribs_.a_position.location, 3, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(lineManager.attribs.a_position.location, 3, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.LINES, 0, 2); } - update(pt1: EciArr3, pt2: EciArr3) { - GlUtils.bindBufferStreamDraw(this.gl_, this.vertBuf_, new Float32Array([pt1[0], pt1[1], pt1[2], pt2[0], pt2[1], pt2[2]])); + abstract update(): void; + + updateVertBuf(pt1: EciArr3, pt2: EciArr3) { + const gl = keepTrackApi.getRenderer().gl; + + GlUtils.bindBufferStreamDraw(gl, this.vertBuf_, new Float32Array([pt1[0], pt1[1], pt1[2], pt2[0], pt2[1], pt2[2]])); + } + + protected validateColor(color: vec4): void { + if (color[0] < 0 || color[0] > 1 || color[1] < 0 || color[1] > 1 || color[2] < 0 || color[2] > 1 || color[3] < 0 || color[3] > 1) { + throw new Error('Invalid color'); + } } } diff --git a/src/singletons/draw-manager/line-manager/obj-to-obj-line.ts b/src/singletons/draw-manager/line-manager/obj-to-obj-line.ts new file mode 100644 index 000000000..1f17b5c0e --- /dev/null +++ b/src/singletons/draw-manager/line-manager/obj-to-obj-line.ts @@ -0,0 +1,44 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { MissileObject } from '@app/singletons/catalog-manager/MissileObject'; +import { DetailedSatellite } from 'ootk'; +import { Line, LineColors } from './line'; + +export class ObjToObjLine extends Line { + obj: DetailedSatellite | MissileObject; + obj2: DetailedSatellite | MissileObject; + + constructor(obj: DetailedSatellite | MissileObject, obj2: DetailedSatellite | MissileObject, color = LineColors.ORANGE) { + super(); + this.obj = obj; + this.obj2 = obj2; + this.color_ = color; + } + + update(): void { + let eciArr: EciArr3; + let eciArr2: EciArr3; + + if (this.obj instanceof MissileObject) { + eciArr = [this.obj.position.x, this.obj.position.y, this.obj.position.z] as EciArr3; + } else if (this.obj instanceof DetailedSatellite) { + const eci = this.obj.eci(keepTrackApi.getTimeManager().simulationTimeObj); + + eciArr = [eci.position.x, eci.position.y, eci.position.z] as EciArr3; + } else { + throw new Error('Invalid type'); + } + + if (this.obj2 instanceof MissileObject) { + eciArr2 = [this.obj2.position.x, this.obj2.position.y, this.obj2.position.z] as EciArr3; + } else if (this.obj2 instanceof DetailedSatellite) { + const eci = this.obj2.eci(keepTrackApi.getTimeManager().simulationTimeObj); + + eciArr2 = [eci.position.x, eci.position.y, eci.position.z] as EciArr3; + } else { + throw new Error('Invalid type'); + } + + this.updateVertBuf(eciArr, eciArr2); + } +} diff --git a/src/singletons/draw-manager/line-manager/ref-to-ref-line.ts b/src/singletons/draw-manager/line-manager/ref-to-ref-line.ts new file mode 100644 index 000000000..31c2653db --- /dev/null +++ b/src/singletons/draw-manager/line-manager/ref-to-ref-line.ts @@ -0,0 +1,24 @@ +import { EciArr3 } from '@app/interfaces'; +import { vec3, vec4 } from 'gl-matrix'; +import { Line } from './line'; + +export class RefToRefLine extends Line { + private ref1_: vec3; + private ref2_: vec3; + color: vec4; + + constructor(ref1: vec3, ref2: vec3, color: vec4) { + super(); + this.ref1_ = ref1; + this.ref2_ = ref2; + + this.validateColor(color); + this.color_ = color; + + this.updateVertBuf(this.ref1_ as EciArr3, this.ref2_ as EciArr3); + } + + update(): void { + // Do nothing + } +} diff --git a/src/singletons/draw-manager/line-manager/sat-ric-line.ts b/src/singletons/draw-manager/line-manager/sat-ric-line.ts new file mode 100644 index 000000000..51b63016c --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sat-ric-line.ts @@ -0,0 +1,97 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { DetailedSatellite, Kilometers } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SatRicLine extends Line { + sat: DetailedSatellite; + private coordinate_: 'R' | 'I' | 'C'; + + private readonly lineLength = 500; + + constructor(sat: DetailedSatellite, coordinate: 'R' | 'I' | 'C', color = LineColors.ORANGE) { + super(); + this.sat = sat; + this.coordinate_ = coordinate; + this.color_ = color; + } + + update(): void { + const posData = keepTrackApi.getDotsManager().positionData; + const position = { + x: posData[this.sat.id * 3], + y: posData[this.sat.id * 3 + 1], + z: posData[this.sat.id * 3 + 2], + }; + const satArr = [position.x, position.y, position.z] as EciArr3; + + // Create In-Track Vector First + const inTrack = { ...this.sat.velocity }; // Duplicate the velocity vector to avoid modifying the original + // Normalize the velocity vector + const inTrackMag = Math.sqrt(inTrack.x * inTrack.x + inTrack.y * inTrack.y + inTrack.z * inTrack.z); + + inTrack.x = inTrack.x / inTrackMag as Kilometers; + inTrack.y = inTrack.y / inTrackMag as Kilometers; + inTrack.z = inTrack.z / inTrackMag as Kilometers; + + // Now Create the Cross Track Vector (Cross Product of In-Track and Satellite Position) + const r = position; + const crossTrack = { + x: r.y * inTrack.z - r.z * inTrack.y, + y: r.z * inTrack.x - r.x * inTrack.z, + z: r.x * inTrack.y - r.y * inTrack.x, + }; + + // Normalize the cross track vector + const crossTrackMag = Math.sqrt(crossTrack.x * crossTrack.x + crossTrack.y * crossTrack.y + crossTrack.z * crossTrack.z); + + crossTrack.x = crossTrack.x / crossTrackMag as Kilometers; + crossTrack.y = crossTrack.y / crossTrackMag as Kilometers; + crossTrack.z = crossTrack.z / crossTrackMag as Kilometers; + + // Create the Radial Vector (Cross Product of In-Track and Cross-Track) + const radial = { + x: inTrack.y * crossTrack.z - inTrack.z * crossTrack.y, + y: inTrack.z * crossTrack.x - inTrack.x * crossTrack.z, + z: inTrack.x * crossTrack.y - inTrack.y * crossTrack.x, + }; + + // Normalize the radial vector + const radialMag = Math.sqrt(radial.x * radial.x + radial.y * radial.y + radial.z * radial.z); + + radial.x = radial.x / radialMag as Kilometers; + radial.y = radial.y / radialMag as Kilometers; + radial.z = radial.z / radialMag as Kilometers; + + // Calculate a point this.lineLength in each direction from the satellite's position + inTrack.x = position.x + inTrack.x * this.lineLength as Kilometers; + inTrack.y = position.y + inTrack.y * this.lineLength as Kilometers; + inTrack.z = position.z + inTrack.z * this.lineLength as Kilometers; + + crossTrack.x = position.x + crossTrack.x * this.lineLength as Kilometers; + crossTrack.y = position.y + crossTrack.y * this.lineLength as Kilometers; + crossTrack.z = position.z + crossTrack.z * this.lineLength as Kilometers; + + radial.x = position.x + radial.x * this.lineLength as Kilometers; + radial.y = position.y + radial.y * this.lineLength as Kilometers; + radial.z = position.z + radial.z * this.lineLength as Kilometers; + + let eciArr: EciArr3; + + switch (this.coordinate_) { + case 'C': + eciArr = [crossTrack.x, crossTrack.y, crossTrack.z] as EciArr3; + break; + case 'I': + eciArr = [inTrack.x, inTrack.y, inTrack.z] as EciArr3; + break; + case 'R': + eciArr = [radial.x, radial.y, radial.z] as EciArr3; + break; + default: + throw new Error('Invalid type'); + } + + this.updateVertBuf(eciArr, satArr); + } +} diff --git a/src/singletons/draw-manager/line-manager/sat-scan-earth-line.ts b/src/singletons/draw-manager/line-manager/sat-scan-earth-line.ts new file mode 100644 index 000000000..ddc1bec28 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sat-scan-earth-line.ts @@ -0,0 +1,73 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { vec4 } from 'gl-matrix'; +import { Degrees, DetailedSatellite, ecf2rae, eci2ecf, Kilometers, lla2ecf } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SatScanEarthLine extends Line { + private sat: DetailedSatellite; + private lat_: Degrees = -90 as Degrees; + private lon_: Degrees = 0 as Degrees; + + constructor(sat: DetailedSatellite, color: vec4 = LineColors.GREEN) { + super(); + this.sat = sat; + + this.validateColor(color); + this.color_ = color; + } + + update(): void { + const eci = this.sat.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.position.x, eci.position.y, eci.position.z] as EciArr3; + + let t = 0; + + while (t < 1000) { + this.updateLongitude_(); + this.updateLatitude_(); + + const lla = { lat: this.lat_, lon: this.lon_, alt: 0.05 }; + const ecf = eci2ecf(this.sat.position, 0); + const rae = ecf2rae(lla, ecf); + const el = rae.el; + + if (el > settingsManager.lineScanMinEl) { + const pos = lla2ecf(lla); + const eciArr2 = [pos.x, pos.y, pos.z] as EciArr3; + + this.updateVertBuf(eciArr, eciArr2); + break; + } + + this.adjustLatitude_(); + + t++; + } + } + + private updateLongitude_(): void { + this.lon_ = (this.lon_ + settingsManager.lineScanSpeedSat); + if (this.lon_ > 180) { + this.lon_ = -180; + } + } + + private updateLatitude_(): void { + if (this.lon_ >= 0 && this.lon_ < settingsManager.lineScanSpeedSat) { + this.lat_ = (this.lat_ + settingsManager.lineScanSpeedSat); + } + if (this.lat_ > 90) { + this.lat_ = -90; + } + } + + private adjustLatitude_(): void { + if (this.lat_ === -90) { + this.lat_ = (this.lat_ + settingsManager.lineScanSpeedSat); + } + if (this.lat_ === 90) { + this.lat_ = -90; + } + } +} diff --git a/src/singletons/draw-manager/line-manager/sat-to-ref-line.ts b/src/singletons/draw-manager/line-manager/sat-to-ref-line.ts new file mode 100644 index 000000000..6292b5a10 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sat-to-ref-line.ts @@ -0,0 +1,26 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { vec3, vec4 } from 'gl-matrix'; +import { DetailedSatellite } from 'ootk'; +import { Line } from './line'; + +export class SatToRefLine extends Line { + private sat: DetailedSatellite; + private ref2_: vec3; + + constructor(sat: DetailedSatellite, ref2: vec3, color: vec4) { + super(); + this.sat = sat; + this.ref2_ = ref2; + + this.validateColor(color); + this.color_ = color; + } + + update(): void { + const eci = this.sat.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.position.x, eci.position.y, eci.position.z] as EciArr3; + + this.updateVertBuf(eciArr, this.ref2_ as EciArr3); + } +} diff --git a/src/singletons/draw-manager/line-manager/sat-to-sun-line.ts b/src/singletons/draw-manager/line-manager/sat-to-sun-line.ts new file mode 100644 index 000000000..0f3fcfc54 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sat-to-sun-line.ts @@ -0,0 +1,21 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { DetailedSatellite } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SatToSunLine extends Line { + private sat: DetailedSatellite; + + constructor(sat: DetailedSatellite) { + super(); + this.sat = sat; + this.color_ = LineColors.ORANGE; + } + + update(): void { + const eci = this.sat.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.position.x, eci.position.y, eci.position.z] as EciArr3; + + this.updateVertBuf(eciArr, keepTrackApi.getScene().sun.position as EciArr3); + } +} diff --git a/src/singletons/draw-manager/line-manager/sensor-scan-horizon-line.ts b/src/singletons/draw-manager/line-manager/sensor-scan-horizon-line.ts new file mode 100644 index 000000000..95d0fa995 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sensor-scan-horizon-line.ts @@ -0,0 +1,80 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { SatMath } from '@app/static/sat-math'; +import { vec4 } from 'gl-matrix'; +import { Degrees, DetailedSensor, ecf2eci, rae2ecf } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SensorScanHorizonLine extends Line { + private sensor: DetailedSensor; + private az_: Degrees = -90 as Degrees; + private minAz_: Degrees; + private maxAz_: Degrees; + + constructor(sensor: DetailedSensor, face = 1, faces = 2, color: vec4 = LineColors.CYAN) { + super(); + this.sensor = sensor; + this.az_ = sensor.minAz; + + const maxAz = sensor.maxAz > sensor.minAz ? sensor.maxAz : sensor.maxAz - 360; + const minAz = sensor.minAz; + const azRange = maxAz - minAz; + + this.minAz_ = minAz + (azRange / faces) * (face - 1) as Degrees; + this.maxAz_ = minAz + (azRange / faces) * (face) as Degrees; + + this.validateColor(color); + this.color_ = color; + } + + update(): void { + const eci = this.sensor.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.x, eci.y, eci.z] as EciArr3; + + this.updateAzimuth_(); + const eciArr2 = this.calculateEciPosition_(); + + this.updateVertBuf(eciArr, eciArr2); + } + + private updateAzimuth_(): void { + this.az_ = (this.az_ + settingsManager.lineScanSpeedRadar); + // Normalize azimuth + if (this.az_ > 360) { + this.az_ = 0; + } + // Is azimuth outside of FOV? + if ( + (this.maxAz_ > this.minAz_ && this.az_ > this.maxAz_) || + (this.maxAz_ < this.minAz_ && + this.az_ > this.maxAz_ && + this.az_ < this.minAz_) + ) { + // Reset it + this.az_ = this.minAz_; + } + } + + private calculateEciPosition_(): EciArr3 { + const lla = this.sensor.lla(); + + + const eci = ecf2eci( + rae2ecf( + { + rng: this.sensor.maxRng, + az: this.az_, + el: this.sensor.minEl, + }, + { + lat: lla.lat, + lon: lla.lon, + alt: lla.alt + 30, + }, + ), + SatMath.calculateTimeVariables(keepTrackApi.getTimeManager().simulationTimeObj).gmst, + ); + + return [eci.x, eci.y, eci.z] as EciArr3; + } +} diff --git a/src/singletons/draw-manager/line-manager/sensor-to-moon-line.ts b/src/singletons/draw-manager/line-manager/sensor-to-moon-line.ts new file mode 100644 index 000000000..f23ebe9dd --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sensor-to-moon-line.ts @@ -0,0 +1,22 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { DetailedSensor } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SensorToMoonLine extends Line { + private sensor_: DetailedSensor; + + constructor(sensor: DetailedSensor) { + super(); + this.sensor_ = sensor; + + this.color_ = LineColors.WHITE; + } + + update(): void { + const eci = this.sensor_.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.x, eci.y, eci.z] as EciArr3; + + this.updateVertBuf(eciArr, keepTrackApi.getScene().moon.position as EciArr3); + } +} diff --git a/src/singletons/draw-manager/line-manager/sensor-to-sat-line.ts b/src/singletons/draw-manager/line-manager/sensor-to-sat-line.ts new file mode 100644 index 000000000..7978773f8 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sensor-to-sat-line.ts @@ -0,0 +1,57 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { SelectSatManager } from '@app/plugins/select-sat-manager/select-sat-manager'; +import { vec4 } from 'gl-matrix'; +import { DetailedSatellite, DetailedSensor } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SensorToSatLine extends Line { + sat: DetailedSatellite; + sensor: DetailedSensor; + private isDrawFovOnly_: boolean = false; + private isDrawSelectedOnly_: boolean = false; + + constructor(sensor: DetailedSensor, sat: DetailedSatellite, color?: vec4) { + super(); + this.sat = sat; + this.sensor = sensor; + this.color_ = color || LineColors.GREEN; + } + + setDrawFovOnly(drawFovOnly: boolean): void { + this.isDrawFovOnly_ = drawFovOnly; + } + + setDrawSelectedOnly(drawSelectedOnly: boolean): void { + this.isDrawSelectedOnly_ = drawSelectedOnly; + } + + update(): void { + const posData = keepTrackApi.getDotsManager().positionData; + const id = this.sat.id; + const eciArr = [posData[id * 3], posData[id * 3 + 1], posData[id * 3 + 2]] as EciArr3; + + const sensorEci = this.sensor.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const sensorEciArr = [sensorEci.x, sensorEci.y, sensorEci.z] as EciArr3; + + this.isDraw_ = true; + + if (this.isDrawFovOnly_) { + const isInFov = this.sensor.isSatInFov(this.sat, keepTrackApi.getTimeManager().simulationTimeObj); + + if (!isInFov) { + this.isDraw_ = false; + this.isGarbage = true; + } + } + + if (this.isDrawSelectedOnly_) { + if (this.sat.id !== keepTrackApi.getPlugin(SelectSatManager).selectedSat) { + this.isDraw_ = false; + this.isGarbage = true; + } + } + + this.updateVertBuf(eciArr, sensorEciArr); + } +} diff --git a/src/singletons/draw-manager/line-manager/sensor-to-sun-line.ts b/src/singletons/draw-manager/line-manager/sensor-to-sun-line.ts new file mode 100644 index 000000000..8afa5ad59 --- /dev/null +++ b/src/singletons/draw-manager/line-manager/sensor-to-sun-line.ts @@ -0,0 +1,22 @@ +import { EciArr3 } from '@app/interfaces'; +import { keepTrackApi } from '@app/keepTrackApi'; +import { DetailedSensor } from 'ootk'; +import { Line, LineColors } from './line'; + +export class SensorToSunLine extends Line { + private sensor_: DetailedSensor; + + constructor(sensor: DetailedSensor) { + super(); + this.sensor_ = sensor; + + this.color_ = LineColors.ORANGE; + } + + update(): void { + const eci = this.sensor_.eci(keepTrackApi.getTimeManager().simulationTimeObj); + const eciArr = [eci.x, eci.y, eci.z] as EciArr3; + + this.updateVertBuf(eciArr, keepTrackApi.getScene().sun.position as EciArr3); + } +} diff --git a/src/singletons/hover-manager.ts b/src/singletons/hover-manager.ts index 73f66b89d..4b8d955cd 100644 --- a/src/singletons/hover-manager.ts +++ b/src/singletons/hover-manager.ts @@ -72,17 +72,8 @@ export class HoverManager { if (this.satHoverBoxDOM.style.display === 'none' || !settingsManager.enableHoverOverlay) { return false; } - const catalogManagerInstance = keepTrackApi.getCatalogManager(); const renderer = keepTrackApi.getRenderer(); - if (catalogManagerInstance.isStarManagerLoaded) { - const starManager = keepTrackApi.getStarManager(); - - if (starManager.isConstellationVisible === true && !starManager.isAllConstellationVisible) { - starManager.clearConstellations(); - } - } - this.satHoverBoxDOM.style.display = 'none'; renderer.setCursor('default'); @@ -329,29 +320,13 @@ export class HoverManager { } } - private star_(sat: Star) { - const constellationName = keepTrackApi.getStarManager().findStarsConstellation(sat.name); - - if (constellationName !== null) { - this.satHoverBoxNode1.innerHTML = sat.name + constellationName; - } else { - this.satHoverBoxNode1.textContent = sat.name; - } - this.satHoverBoxNode2.innerHTML = 'Star'; - this.satHoverBoxNode3.innerHTML = `RA: ${sat.ra.toFixed(3)} deg DEC: ${sat.dec.toFixed(3)} deg`; - - if (this.lasthoveringSat !== sat.id && typeof sat !== 'undefined' && constellationName !== null) { - keepTrackApi.getStarManager().drawConstellations(constellationName); - } - } - private staticObj_(obj: DetailedSensor | LandObject | Star) { if (obj.type === SpaceObjectType.LAUNCH_FACILITY) { this.launchFacility_(obj as LandObject); } else if (obj.type === SpaceObjectType.CONTROL_FACILITY) { this.controlFacility_(obj as LandObject); } else if (obj.type === SpaceObjectType.STAR) { - this.star_(obj as Star); + // Do nothing } else { // It is a Sensor at this point const sensor = obj as DetailedSensor; diff --git a/src/singletons/input-manager.ts b/src/singletons/input-manager.ts index 2eef6150f..e5168e0ac 100644 --- a/src/singletons/input-manager.ts +++ b/src/singletons/input-manager.ts @@ -421,7 +421,7 @@ export class InputManager { hideEl('earth-vec-rmb'); hideEl('earth-political-rmb'); - if (lineManagerInstance.drawLineList.length > 0) { + if (lineManagerInstance.lines.length > 0) { getEl('clear-lines-rmb').style.display = 'block'; numMenuItems++; } diff --git a/src/singletons/input-manager/mouse-input.ts b/src/singletons/input-manager/mouse-input.ts index f261ff0be..2b4ab974f 100644 --- a/src/singletons/input-manager/mouse-input.ts +++ b/src/singletons/input-manager/mouse-input.ts @@ -8,16 +8,17 @@ import { TimeMachine } from '@app/plugins/time-machine/time-machine'; import { Camera, CameraType } from '@app/singletons/camera'; import { SatMath } from '@app/static/sat-math'; import { UrlManager } from '@app/static/url-manager'; -import { Kilometers, eci2lla } from 'ootk'; +import { DetailedSatellite, Kilometers, eci2lla } from 'ootk'; import { closeColorbox } from '../../lib/colorbox'; import { getEl } from '../../lib/get-el'; import { showLoading } from '../../lib/showLoading'; import { LegendManager } from '../../static/legend-manager'; -import { LineTypes, lineManagerInstance } from '../draw-manager/line-manager'; +import { MissileObject } from '../catalog-manager/MissileObject'; +import { lineManagerInstance } from '../draw-manager/line-manager'; +import { LineColors } from '../draw-manager/line-manager/line'; import { errorManagerInstance } from '../errorManager'; import { InputManager, LatLon } from '../input-manager'; import { PersistenceManager, StorageKey } from '../persistence-manager'; -import { starManager } from '../starManager'; import { KeyboardInput } from './keyboard-input'; export class MouseInput { @@ -416,7 +417,6 @@ export class MouseInput { const catalogManagerInstance = keepTrackApi.getCatalogManager(); const timeManagerInstance = keepTrackApi.getTimeManager(); - const sensorManagerInstance = keepTrackApi.getSensorManager(); const uiManagerInstance = keepTrackApi.getUiManager(); const colorSchemeManagerInstance = keepTrackApi.getColorSchemeManager(); @@ -430,6 +430,16 @@ export class MouseInput { targetId = (target.firstChild).id; } + let clickSatObj: DetailedSatellite | MissileObject | null = null; + + if (this.clickedSat === -1) { + const obj = catalogManagerInstance.getObject(this.mouseSat); + + if ((obj instanceof DetailedSatellite) || (obj instanceof MissileObject)) { + clickSatObj = obj; + } + } + switch (targetId) { case 'view-info-rmb': if (typeof this.latLon === 'undefined' || isNaN(this.latLon.lat) || isNaN(this.latLon.lon)) { @@ -467,14 +477,11 @@ export class MouseInput { break; case 'clear-lines-rmb': lineManagerInstance.clear(); - if (catalogManagerInstance.isStarManagerLoaded) { - starManager.isAllConstellationVisible = false; - } break; case 'line-eci-axis-rmb': - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_REF, [25000, 0, 0], 'r'); - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_REF, [0, 25000, 0], 'g'); - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_REF, [0, 0, 25000], 'b'); + lineManagerInstance.createRef2Ref([0, 0, 0], [25000, 0, 0], LineColors.RED); + lineManagerInstance.createRef2Ref([0, 0, 0], [0, 25000, 0], LineColors.GREEN); + lineManagerInstance.createRef2Ref([0, 0, 0], [0, 0, 25000], LineColors.BLUE); break; case 'line-eci-xgrid-rmb': lineManagerInstance.createGrid('x', [0.6, 0.2, 0.2, 1], 1); @@ -486,21 +493,16 @@ export class MouseInput { lineManagerInstance.createGrid('z', [0.2, 0.2, 0.6, 1], 1); break; case 'line-earth-sat-rmb': - lineManagerInstance.create(LineTypes.CENTER_OF_EARTH_TO_SAT, [this.clickedSat], 'p'); + lineManagerInstance.createSatToRef(keepTrackApi.getPlugin(SelectSatManager)?.primarySatObj, [0, 0, 0], LineColors.PURPLE); break; case 'line-sensor-sat-rmb': - // Sensor always has to be #2 - lineManagerInstance.create(LineTypes.SENSOR_TO_SAT, [this.clickedSat, catalogManagerInstance.getSensorFromSensorName(sensorManagerInstance.currentSensors[0].name)], 'p'); + lineManagerInstance.createSensorToSat(keepTrackApi.getSensorManager().getSensor(), clickSatObj, LineColors.GREEN); break; case 'line-sat-sat-rmb': - lineManagerInstance.create(LineTypes.SENSOR_TO_SAT, [this.clickedSat, keepTrackApi.getPlugin(SelectSatManager)?.selectedSat], 'b'); + lineManagerInstance.createObjToObj(clickSatObj, keepTrackApi.getPlugin(SelectSatManager)?.primarySatObj, LineColors.BLUE); break; case 'line-sat-sun-rmb': - lineManagerInstance.create( - LineTypes.REF_TO_SAT, - [this.clickedSat, keepTrackApi.getScene().sun.position[0], keepTrackApi.getScene().sun.position[1], keepTrackApi.getScene().sun.position[2]], - 'o', - ); + lineManagerInstance.createSat2Sun(clickSatObj); break; case 'earth-blue-rmb': MouseInput.resetCurrentEarthTexture(); diff --git a/src/singletons/scene.ts b/src/singletons/scene.ts index 4220b4f12..facb99d2f 100644 --- a/src/singletons/scene.ts +++ b/src/singletons/scene.ts @@ -64,6 +64,8 @@ export class Scene { this.moon.update(simulationTime); this.skybox.update(); + keepTrackApi.getLineManager().update(); + this.sensorFovFactory.updateAll(gmst); this.coneFactory.updateAll(); } @@ -169,7 +171,7 @@ export class Scene { orbitManagerInstance.draw(renderer.projectionMatrix, camera.camMatrix, renderer.postProcessingManager.curBuffer, hoverManagerInstance, colorSchemeManagerInstance, camera); - keepTrackApi.getLineManager().draw(renderer, dotsManagerInstance.inViewData, camera.camMatrix, null); + keepTrackApi.getLineManager().draw(null); // Draw Satellite Model if a satellite is selected and meshManager is loaded if (keepTrackApi.getPlugin(SelectSatManager)?.selectedSat > -1) { diff --git a/src/singletons/starManager.ts b/src/singletons/starManager.ts deleted file mode 100644 index b4f406ce2..000000000 --- a/src/singletons/starManager.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * ///////////////////////////////////////////////////////////////////////////// - * - * (c) 2016-2023, Theodore Kruczek - * http://keeptrack.space - * - * All code is Copyright © 2016-2023 by Theodore Kruczek. All rights reserved. - * No part of this web site may be reproduced, published, distributed, displayed, - * performed, copied or stored for or private use, without written - * permission of the author. - * - * No part of this code may be modified or changed or exploited in any way used - * for derivative works, or offered for sale, or used to construct any kind of database - * or mirrored at any other location without the express written permission of the author. - * - * ///////////////////////////////////////////////////////////////////////////// - */ - -import { keepTrackApi } from '@app/keepTrackApi'; -import { constellations } from '../catalogs/constellations'; -import { isThisNode } from '../static/isThisNode'; -import { LineTypes, lineManagerInstance } from './draw-manager/line-manager'; - -export class StarManager { - isConstellationVisible = false; - isAllConstellationVisible = false; - constellations = constellations; - private currentConstellationName_ = null; - - findStarsConstellation(starName: string) { - for (const constellation of this.constellations) { - for (const starPair of constellation.stars) { - if (starPair[0] === starName) { - return constellation.name; - } - if (starPair[1] === starName) { - return constellation.name; - } - } - } - - return null; - } - - drawAllConstellations() { - const catalogManagerInstance = keepTrackApi.getCatalogManager(); - - for (let i = 0; i < this.constellations.length; i++) { - for (let s = 0; s < this.constellations[i].stars.length; s++) { - // Verify Stars Exist - let star1, star2; - - try { - const dotsManagerInstance = keepTrackApi.getDotsManager(); - const starIdx1 = dotsManagerInstance.starIndex1; - const starIdx2 = dotsManagerInstance.starIndex2; - - star1 = catalogManagerInstance.starName2Id(this.constellations[i].stars[s][0], starIdx1, starIdx2); - star2 = catalogManagerInstance.starName2Id(this.constellations[i].stars[s][1], starIdx1, starIdx2); - if (star1 == null || star2 == null) { - continue; - } - } catch (e) { - // IF this isn't Jest testing, then throw a warning - /* istanbul ignore next */ - if (isThisNode()) { - console.warn(`Constellation/Star error - i: ${i} - s: ${s}`); - } - continue; - } - lineManagerInstance.create(LineTypes.SENSOR_TO_SAT, [star1, star2], 'p'); - this.isConstellationVisible = true; - this.isAllConstellationVisible = true; - } - } - } - - drawConstellations(C: string) { - const catalogManagerInstance = keepTrackApi.getCatalogManager(); - - if (typeof C === 'undefined') { - return; - } - if (this.currentConstellationName_ === C) { - return; - } - for (const constellation of this.constellations) { - if (constellation.name === C) { - for (const starPair of constellation.stars) { - // Verify Stars Exist - const dotsManagerInstance = keepTrackApi.getDotsManager(); - const starIdx1 = dotsManagerInstance.starIndex1; - const starIdx2 = dotsManagerInstance.starIndex2; - const star1 = catalogManagerInstance.starName2Id(starPair[0], starIdx1, starIdx2); - const star2 = catalogManagerInstance.starName2Id(starPair[1], starIdx1, starIdx2); - - if (star1 == null && star2 == null) { - return; - } // TODO: Not all constellations are ready yet - /* istanbul ignore next */ - if (typeof star1 === 'undefined' || star1 == null || typeof star2 === 'undefined' || star2 == null) { - continue; - } - lineManagerInstance.create(LineTypes.SENSOR_TO_SAT, [star1, star2], 'p'); - this.isConstellationVisible = true; - } - - return; - } - } - } - - clearConstellations() { - this.isConstellationVisible = false; - this.currentConstellationName_ = null; - let isFoundStar = true; - let attempts = 0; - // No idea why this took 3 tries -- maybe unnecessary now? - - while (isFoundStar && attempts < 30) { - isFoundStar = lineManagerInstance.removeStars(); - attempts++; - } - } -} - -export const starManager = new StarManager(); diff --git a/src/singletons/webgl-renderer.ts b/src/singletons/webgl-renderer.ts index 7aab0fa64..bc33de2c9 100644 --- a/src/singletons/webgl-renderer.ts +++ b/src/singletons/webgl-renderer.ts @@ -229,7 +229,7 @@ export class WebGLRenderer { if ( keepTrackApi.getMainCamera().cameraType === CameraType.ASTRONOMY || keepTrackApi.getMainCamera().cameraType === CameraType.PLANETARIUM || - watchlistPluginInstance?.watchlistInViewList?.length > 0 + watchlistPluginInstance?.hasAnyInView() ) { // Catch race condition where sensor has been reset but camera hasn't been updated try { @@ -251,7 +251,7 @@ export class WebGLRenderer { return; } // Previously called showOrbitsAbove(); - if (!settingsManager.isSatLabelModeOn || (keepTrackApi.getMainCamera().cameraType !== CameraType.PLANETARIUM && watchlistPluginInstance?.watchlistInViewList?.length === 0)) { + if (!settingsManager.isSatLabelModeOn || (keepTrackApi.getMainCamera().cameraType !== CameraType.PLANETARIUM && !watchlistPluginInstance?.hasAnyInView())) { if (this.isSatMiniBoxInUse_) { this.hoverBoxOnSatMiniElements_ = getEl('sat-minibox'); this.hoverBoxOnSatMiniElements_.innerHTML = ''; @@ -353,7 +353,7 @@ export class WebGLRenderer { return; } - watchlistPluginInstance?.watchlistList.forEach((id: number) => { + watchlistPluginInstance?.watchlistList.forEach(({ id }) => { const obj = catalogManagerInstance.getObject(id, GetSatType.POSITION_ONLY) as DetailedSatellite; if (dotsManagerInstance.inViewData[id] === 0) { @@ -406,7 +406,7 @@ export class WebGLRenderer { } // Hide satMiniBoxes When Not in Use - if (!settingsManager.isSatLabelModeOn || (keepTrackApi.getMainCamera().cameraType !== CameraType.PLANETARIUM && watchlistPluginInstance?.watchlistInViewList?.length === 0)) { + if (!settingsManager.isSatLabelModeOn || (keepTrackApi.getMainCamera().cameraType !== CameraType.PLANETARIUM && !watchlistPluginInstance?.hasAnyInView())) { if (this.isSatMiniBoxInUse_) { this.satMiniBox_ = (getEl('sat-minibox')); this.satMiniBox_.innerHTML = ''; diff --git a/test/line.test.ts b/test/line.test.ts index 8651124bc..d6358bf90 100644 --- a/test/line.test.ts +++ b/test/line.test.ts @@ -65,7 +65,7 @@ describe('Line_class', () => { }; const line = new Line(gl, attribs, uniforms); - line.update([0, 0, 0], [1, 1, 1]); + line.updateVertBuf([0, 0, 0], [1, 1, 1]); expect(line).toBeInstanceOf(Line); });