From 7bc9e99b87983dd79d982e932954f2042e025f49 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 2 Aug 2022 13:11:50 +0200 Subject: [PATCH] Feature/satellites (#2185) * Remove planet geometry and simplespheregeometry * Only use a single TLE loading implementation * Add caching to the satellite loader; Add Lua function to load kepler file * Fix RenderablePlanetProjection specification * Add OMM loading funtion; Remove mean motion from Kepler parameters * Replace TLETranslation class with GPTranslation and support OMM files * Support loading SMDB files in kepler functions * Merge RenderableSatellites and RenderableSmallBody with RenderableOrbitalKepler * Update submodules * Adapt existing satellites to new OMM file type * Remove TLE helper * Remove SSSB shared file and adapt sssb assets --- .../ext/launcher/src/filesystemaccess.cpp | 2 +- .../launcher/src/profile/propertiesdialog.cpp | 2 +- .../satellites/communications/amateur.asset | 47 +- .../communications/experimental.asset | 46 +- .../communications/geostationary.asset | 49 +- .../communications/globalstar.asset | 43 +- .../satellites/communications/gorizont.asset | 43 +- .../satellites/communications/intelsat.asset | 43 +- .../satellites/communications/iridium.asset | 43 +- .../communications/iridium_next.asset | 43 +- .../satellites/communications/molniya.asset | 43 +- .../satellites/communications/orbcomm.asset | 43 +- .../communications/other_comm.asset | 43 +- .../satellites/communications/raduga.asset | 43 +- .../earth/satellites/communications/ses.asset | 43 +- .../satellites/communications/starlink.asset | 47 +- .../earth/satellites/debris/debris_asat.asset | 43 +- .../satellites/debris/debris_breezem.asset | 45 +- .../satellites/debris/debris_fengyun.asset | 43 +- .../satellites/debris/debris_iridium33.asset | 43 +- .../satellites/debris/debris_kosmos2251.asset | 43 +- .../earth/satellites/misc/active.asset | 45 +- .../earth/satellites/misc/brightest.asset | 47 +- .../earth/satellites/misc/cubesats.asset | 43 +- .../earth/satellites/misc/hubble_trail.asset | 121 ++- .../planets/earth/satellites/misc/iss.asset | 227 +++--- .../earth/satellites/misc/military.asset | 43 +- .../planets/earth/satellites/misc/other.asset | 43 +- .../planets/earth/satellites/misc/radar.asset | 43 +- .../earth/satellites/misc/spacestations.asset | 49 +- .../earth/satellites/misc/tle-new.asset | 45 +- .../earth/satellites/navigation/beidou.asset | 43 +- .../earth/satellites/navigation/galileo.asset | 43 +- .../satellites/navigation/glosnass.asset | 43 +- .../earth/satellites/navigation/gps.asset | 45 +- .../earth/satellites/navigation/musson.asset | 43 +- .../earth/satellites/navigation/nnss.asset | 44 +- .../earth/satellites/navigation/sbas.asset | 43 +- .../earth/satellites/science/education.asset | 43 +- .../satellites/science/engineering.asset | 43 +- .../earth/satellites/science/geodetic.asset | 43 +- .../earth/satellites/science/spaceearth.asset | 46 +- .../earth/satellites/weather/aqua.asset | 188 +++-- .../earth/satellites/weather/argos.asset | 43 +- .../earth/satellites/weather/dmc.asset | 46 +- .../satellites/weather/earth_resources.asset | 43 +- .../earth/satellites/weather/goes.asset | 43 +- .../earth/satellites/weather/noaa.asset | 43 +- .../earth/satellites/weather/planet.asset | 43 +- .../earth/satellites/weather/sarsat.asset | 43 +- .../earth/satellites/weather/snpp.asset | 186 +++-- .../earth/satellites/weather/spire.asset | 43 +- .../earth/satellites/weather/tdrss.asset | 43 +- .../earth/satellites/weather/terra.asset | 173 ++-- .../earth/satellites/weather/weather.asset | 43 +- .../solarsystem/sssb/amor_asteroid.asset | 37 +- .../solarsystem/sssb/apollo_asteroid.asset | 36 +- .../solarsystem/sssb/aten_asteroid.asset | 37 +- .../solarsystem/sssb/atira_asteroid.asset | 37 +- .../scene/solarsystem/sssb/c2019y4atlas.asset | 2 +- .../solarsystem/sssb/centaur_asteroid.asset | 37 +- .../solarsystem/sssb/chiron-type_comet.asset | 37 +- .../solarsystem/sssb/encke-type_comet.asset | 37 +- .../solarsystem/sssb/halley-type_comet.asset | 35 +- .../sssb/inner_main_belt_asteroid.asset | 37 +- .../scene/solarsystem/sssb/itokawa.asset | 2 +- .../sssb/jupiter-family_comet.asset | 37 +- .../sssb/jupiter_trojan_asteroid.asset | 37 +- .../solarsystem/sssb/main_belt_asteroid.asset | 39 +- .../sssb/mars-crossing_asteroid.asset | 37 +- .../sssb/outer_main_belt_asteroid.asset | 41 +- data/assets/scene/solarsystem/sssb/pha.asset | 43 +- .../scene/solarsystem/sssb/sssb_shared.asset | 50 -- .../sssb/transneptunian_object_asteroid.asset | 43 +- data/assets/util/tle_helper.asset | 124 --- modules/fitsfilereader/ext/CCfits | 2 +- modules/fitsfilereader/ext/cfitsio | 2 +- modules/kameleon/ext/kameleon | 2 +- modules/space/CMakeLists.txt | 10 +- modules/space/kepler.cpp | 751 ++++++++++++++++++ modules/space/kepler.h | 110 +++ .../rendering/renderableorbitalkepler.cpp | 412 ++++------ .../space/rendering/renderableorbitalkepler.h | 60 +- .../space/rendering/renderablesatellites.cpp | 253 ------ .../space/rendering/renderablesmallbody.cpp | 424 ---------- modules/space/spacemodule.cpp | 18 +- modules/space/spacemodule_lua.inl | 39 + .../space/tasks/generatedebrisvolumetask.h | 4 +- .../gptranslation.cpp} | 95 ++- .../gptranslation.h} | 47 +- modules/space/translation/keplertranslation.h | 2 +- modules/space/translation/tletranslation.cpp | 364 --------- modules/space/translation/tletranslation.h | 83 -- src/interaction/sessionrecording.cpp | 12 +- 94 files changed, 3757 insertions(+), 2723 deletions(-) delete mode 100644 data/assets/scene/solarsystem/sssb/sssb_shared.asset delete mode 100644 data/assets/util/tle_helper.asset create mode 100644 modules/space/kepler.cpp create mode 100644 modules/space/kepler.h delete mode 100644 modules/space/rendering/renderablesatellites.cpp delete mode 100644 modules/space/rendering/renderablesmallbody.cpp rename modules/space/{rendering/renderablesmallbody.h => translation/gptranslation.cpp} (50%) rename modules/space/{rendering/renderablesatellites.h => translation/gptranslation.h} (68%) delete mode 100644 modules/space/translation/tletranslation.cpp delete mode 100644 modules/space/translation/tletranslation.h diff --git a/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp b/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp index 08b1da4890..db4ef759f6 100644 --- a/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp +++ b/apps/OpenSpace/ext/launcher/src/filesystemaccess.cpp @@ -87,7 +87,7 @@ void FileSystemAccess::parseChildFile(std::string filename, bool& hasDirHeaderBe else { std::string extension = filename.substr(filename.length() - _fileExtension.length()); - if (extension.compare(_fileExtension) != 0) { + if (extension != _fileExtension) { return; } } diff --git a/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp index af2543e870..17b56745cb 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/propertiesdialog.cpp @@ -352,7 +352,7 @@ void PropertiesDialog::editBoxDisabled(bool disabled) { void PropertiesDialog::parseSelections() { // Handle case with only one remaining but empty line - if ((_propertyData.size() == 1) && (_propertyData.at(0).name.compare("") == 0)) { + if ((_propertyData.size() == 1) && _propertyData.at(0).name.empty()) { _propertyData.clear(); } *_properties = std::move(_propertyData); diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/amateur.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/amateur.asset index bc96ff5b4b..e7c819d288 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/amateur.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/amateur.asset @@ -1,21 +1,50 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Amateur Radio", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Amateur Radio)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_amateur_radio", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=amateur&FORMAT=kvn", Filename = "amateur.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=amateur&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "amateur", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "amateur.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Amateur Radio", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { Name = "Satellites Communications - Amateur Radio", Version = "1.0", - Description = [[Satellites asset for Communications - Amateur Radio. Data from - Celestrak]], + Description = [[Satellites asset for Communications - Amateur Radio. Data from + Celestrak]], Author = "OpenSpace Team", URL = "https://celestrak.com/NORAD/elements/", License = "Celestrak" diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/experimental.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/experimental.asset index 029e39a8e3..821998714b 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/experimental.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/experimental.asset @@ -1,21 +1,49 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Experimental", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Experimental)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_x-comm", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=x-comm&FORMAT=kvn", Filename = "x-comm.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=x-comm&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "x-comm", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "x-comm.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Experimental", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { Name = "Satellites Communications - Experimental", Version = "1.0", - Description = [[Satellites asset for Communications - Experimental. Data from - Celestrak]], + Description = "Satellites asset for Communications - Experimental. Data from Celestrak", Author = "OpenSpace Team", URL = "https://celestrak.com/NORAD/elements/", License = "Celestrak" diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/geostationary.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/geostationary.asset index b7f6737b90..51dd695a2c 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/geostationary.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/geostationary.asset @@ -1,22 +1,51 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Geostationary", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Geostationary)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_geo", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geo&FORMAT=kvn", Filename = "geo.txt", - Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=geo&FORMAT=TLE", - TrailColor = { 0.9, 0.9, 0.0 }, - Description = [[Satellites that are currently active and in a Geosynchronous orbit, meaning - their orbital period matches Earth's rotation]] + Override = true +}) + +local satellites = { + Identifier = "geo", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "geo.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.9, 0.9, 0.0 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Geostationary", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[Satellites that are currently active and in a Geosynchronous orbit, + meaning their orbital period matches Earth's rotation.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { Name = "Satellites Communications - Geostationary", Version = "1.0", - Description = [[Satellites asset for Communications - Geostationary. Data from + Description = [[Satellites asset for Communications - Geostationary. Data from Celestrak]], Author = "OpenSpace Team", URL = "https://celestrak.com/NORAD/elements/", diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/globalstar.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/globalstar.asset index bb7a8d0f5e..f315cb2e27 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/globalstar.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/globalstar.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "GlobalStar", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (GlobalStar)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_globalstar", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=globalstar&FORMAT=kvn", Filename = "globalstar.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=globalstar&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "globalstar", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "globalstar.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "GlobalStar", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/gorizont.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/gorizont.asset index 852f12a2bb..35db7638ef 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/gorizont.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/gorizont.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Gorizont", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Gorizont)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_gorizont", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gorizont&FORMAT=kvn", Filename = "gorizont.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gorizont&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "gorizont", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "gorizont.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Gorizont", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/intelsat.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/intelsat.asset index a817df5ad7..bd0f22605c 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/intelsat.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/intelsat.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Intelsat", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Intelsat)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_intelsat", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=intelsat&FORMAT=kvn", Filename = "intelsat.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=intelsat&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "intelsat", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "intelsat.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Intelsat", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium.asset index 905ce90d16..c42222bd9f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Iridium", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Iridium)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_iridium", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium&FORMAT=kvn", Filename = "iridium.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "iridium", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "iridium.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Iridium", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium_next.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium_next.asset index 0e4f4a760a..d926d17700 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium_next.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/iridium_next.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Iridium NEXT", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Iridium NEXT)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_iridium-NEXT", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-NEXT&FORMAT=kvn", Filename = "iridium-NEXT.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-NEXT&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "iridium-NEXT", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "iridium-NEXT.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Iridium NEXT", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/molniya.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/molniya.asset index eaf318a501..066a2059d4 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/molniya.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/molniya.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Molniya", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Molniya)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_molniya", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=molniya&FORMAT=kvn", Filename = "molniya.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=molniya&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "molniya", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "molniya.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Molniya", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/orbcomm.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/orbcomm.asset index f0292bf64d..d4537a33d4 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/orbcomm.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/orbcomm.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Orbcomm", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Orbcomm)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_orbcomm", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=orbcomm&FORMAT=kvn", Filename = "orbcomm.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=orbcomm&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "orbcomm", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "orbcomm.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Orbcomm", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/other_comm.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/other_comm.asset index 27aad6d3a4..27a8d42e62 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/other_comm.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/other_comm.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Other comm", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Other comm)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_other-comm", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other-comm&FORMAT=kvn", Filename = "other-comm.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other-comm&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "other-comm", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "other-comm.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Other comm", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/raduga.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/raduga.asset index 5e6edbd691..49a24e591a 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/raduga.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/raduga.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Raduga", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Raduga)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_raduga", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=raduga&FORMAT=kvn", Filename = "raduga.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=raduga&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "raduga", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "raduga.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Raduga", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/ses.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/ses.asset index cc8a74517d..801bef5795 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/ses.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/ses.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "SES", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (SES)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_ses", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=ses&FORMAT=kvn", Filename = "ses.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=ses&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "ses", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "ses.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "SES", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/communications/starlink.asset b/data/assets/scene/solarsystem/planets/earth/satellites/communications/starlink.asset index e368c302d9..09be6c2938 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/communications/starlink.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/communications/starlink.asset @@ -1,16 +1,45 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Starlink", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Starlink)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_starlink", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=starlink&FORMAT=kvn", Filename = "starlink.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=starlink&FORMAT=TLE", - TrailColor = { 0.65, 0.55, 0.55 }, - Description = [[LEO satellite constellation launched by SpaceX to provide - broadband internet access]] + Override = true +}) + +local satellites = { + Identifier = "starlink", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "starlink.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.65, 0.55, 0.55 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Starlink", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[LEO satellite constellation launched by SpaceX to provide broadband + internet access.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_asat.asset b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_asat.asset index 60fd1f4dfe..2b4b2cf976 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_asat.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_asat.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Indian ASAT test Debris", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Indian ASAT test Debris)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_2019-006", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2019-006&FORMAT=kvn", Filename = "2019-006.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2019-006&FORMAT=TLE", - TrailColor = { 0.25, 0.35, 0.45 } + Override = true +}) + +local satellites = { + Identifier = "2019-006", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "2019-006.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.25, 0.35, 0.45 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Indian ASAT test Debris", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_breezem.asset b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_breezem.asset index f2433c58a2..9d7111aef4 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_breezem.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_breezem.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Breeze-M Breakup", - Filename = "2021-044.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2012-044&FORMAT=TLE", - TrailColor = { 0.25, 0.35, 0.45 } +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Breeze-M Breakup)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_2012-044", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=2012-044&FORMAT=kvn", + Filename = "2012-044.txt", + Override = true +}) + +local satellites = { + Identifier = "2012-044", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "2012-044.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.25, 0.35, 0.45 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Breeze-M Breakup", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_fengyun.asset b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_fengyun.asset index c59a51cc27..0140b10623 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_fengyun.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_fengyun.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Fengyun Debris", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Fengyun Debris)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_1999-025", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=1999-025&FORMAT=kvn", Filename = "1999-025.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?INTDES=1999-025&FORMAT=TLE", - TrailColor = { 0.784, 1.0, 0.737 } + Override = true +}) + +local satellites = { + Identifier = "1999-025", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "1999-025.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.784, 1.0, 0.737 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Fengyun Debris", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_iridium33.asset b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_iridium33.asset index 1551e3fd96..455c6d6bf7 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_iridium33.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_iridium33.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Iridium 33 Debris", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Iridium 33 Debris)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_iridium-33-debris", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-33-debris&FORMAT=kvn", Filename = "iridium-33-debris.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=iridium-33-debris&FORMAT=TLE", - TrailColor = { 0.8, 0.0, 0.3 } + Override = true +}) + +local satellites = { + Identifier = "iridium-33-debris", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "iridium-33-debris.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.8, 0.0, 0.3 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Iridium 33 Debris", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_kosmos2251.asset b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_kosmos2251.asset index 4ac9eef903..2f0aa87a4f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_kosmos2251.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/debris/debris_kosmos2251.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Kosmos 2251 Debris", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Kosmos 2251 Debris)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_cosmos-2251-debris", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cosmos-2251-debris&FORMAT=kvn", Filename = "cosmos-2251-debris.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cosmos-2251-debris&FORMAT=TLE", - TrailColor = { 0.66, 0.8, 0.5 } + Override = true +}) + +local satellites = { + Identifier = "cosmos-2251-debris", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "cosmos-2251-debris.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.66, 0.8, 0.5 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Kosmos 2251 Debris", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/active.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/active.asset index dd1bea3c74..6d99a34e44 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/active.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/active.asset @@ -1,15 +1,44 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Active", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Active)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_active", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=kvn", Filename = "active.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=active&FORMAT=TLE", - TrailColor = { 0.45, 0.25, 0.45 }, - Description = "Satellites that employ active communication" + Override = true +}) + +local satellites = { + Identifier = "active", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "active.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.45, 0.25, 0.45 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Active", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[Satellites that employ active communication.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/brightest.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/brightest.asset index f936d31184..1d2ab326be 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/brightest.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/brightest.asset @@ -1,16 +1,45 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "100 Brightest", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (100 Brightest)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_visual", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=visual&FORMAT=kvn", Filename = "visual.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=visual&FORMAT=TLE", - TrailColor = { 0.55, 0.25, 0.65 }, - Description = [[The 100 (or so) satellites that will appear brightest when viewed - from Earth]] + Override = true +}) + +local satellites = { + Identifier = "visual", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "visual.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.55, 0.25, 0.65 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "100 Brightest", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[The 100 (or so) satellites that will appear brightest when viewed + from Earth.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/cubesats.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/cubesats.asset index 70ca3d1c9e..aed63787f7 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/cubesats.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/cubesats.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "CubeSat", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (CubeSat)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_cubesat", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cubesat&FORMAT=kvn", Filename = "cubesat.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=cubesat&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "cubesat", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "cubesat.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "CubeSat", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/hubble_trail.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/hubble_trail.asset index 6ceb27ca5c..c4f0081243 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/hubble_trail.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/hubble_trail.asset @@ -1,83 +1,78 @@ local transforms = asset.require('scene/solarsystem/planets/earth/transforms') -local satelliteHelper = asset.require('util/tle_helper') -local url = "https://celestrak.com/NORAD/elements/gp.php?CATNR=20580" -local identifier = "HST" -local filename = "HST.txt" -local nodes = {} -local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename) +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Hubble)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_hst", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=20580&FORMAT=kvn", + Filename = "hst.txt", + Override = true +}) -local initializeAndAddNodes = function() - local lineElement = satelliteHelper.makeSingleLineElement(tle, filename) - local period = satelliteHelper.getPeriodFromElement(lineElement) - local path = tle .. "/" .. filename - local HubblePosition = { - Identifier = "HubblePosition", - Parent = transforms.EarthInertial.Identifier, - Transform = { - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - Rotation = { - Type = "SpiceRotation", - SourceFrame = "GALACTIC", - DestinationFrame = "J2000", - } +local HubblePosition = { + Identifier = "HubblePosition", + Parent = transforms.EarthInertial.Identifier, + Transform = { + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "hst.txt", + Format = "OMM" }, - Tag = { "earth_satellite", "hubble" }, - GUI = { - Name = "Hubble Position", - Path = "/Solar System/Planets/Earth/Satellites/Hubble", - Hidden = true + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GALACTIC", + DestinationFrame = "J2000", } + }, + Tag = { "earth_satellite", "hubble" }, + GUI = { + Name = "Hubble Position", + Path = "/Solar System/Planets/Earth/Satellites/Hubble", + Hidden = true } +} - local HubbleTrail = { - Identifier = "HubbleTrail", - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - RenderBinMode = "PostDeferredTransparent", - Color = { 0.0, 0.902, 0.6}, - Fade = 1.5, - Period = period, - Resolution = 320 +local HubbleTrail = { + Identifier = "HubbleTrail", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "hst.txt", + Format = "OMM" }, - Tag = { "earth_satellite", "hubble" }, - GUI = { - Name = "Hubble Trail", - Path = "/Solar System/Planets/Earth/Satellites/Hubble" - } + RenderBinMode = "PostDeferredTransparent", + Color = { 0.0, 0.902, 0.6}, + Fade = 1.5, + Resolution = 320 + }, + Tag = { "earth_satellite", "hubble" }, + GUI = { + Name = "Hubble Trail", + Path = "/Solar System/Planets/Earth/Satellites/Hubble" } - - return { HubblePosition, HubbleTrail } -end +} asset.onInitialize(function () - nodes = initializeAndAddNodes() - for _, node in ipairs(nodes) do - openspace.addSceneGraphNode(node) - end + local hubble = openspace.space.readKeplerFile(omm .. "hst.txt", "OMM") + HubbleTrail.Renderable.Period = hubble[0].Period / (60 * 60 * 24) + + openspace.addSceneGraphNode(HubblePosition) + openspace.addSceneGraphNode(HubbleTrail) end) asset.onDeinitialize(function () - for i=1, #nodes do - openspace.removeSceneGraphNode(nodes[#nodes + 1 - i].Identifier) - end + openspace.removeSceneGraphNode(HubbleTrail) + openspace.removeSceneGraphNode(HubblePosition) end) +asset.export(HubblePosition) +asset.export(HubbleTrail) + asset.meta = { Name = "Hubble Space Telescope Trail", Version = "1.0", diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/iss.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/iss.asset index e2356aafcd..1e1b41dea0 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/iss.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/iss.asset @@ -1,145 +1,142 @@ -local satelliteHelper = asset.require("util/tle_helper") local transforms = asset.require("scene/solarsystem/planets/earth/transforms") local sun = asset.require("scene/solarsystem/sun/sun") -local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=25544" -local identifier = "ISS" -local filename = "ISS.txt" -local nodes = {} -local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename) - local models = asset.syncedResource({ - Name = "ISS Models", - Type = "HttpSynchronization", - Identifier = "iss_model", - Version = 3 + Name = "ISS Models", + Type = "HttpSynchronization", + Identifier = "iss_model", + Version = 3 }) -local initializeAndAddNodes = function() - local lineElement = satelliteHelper.makeSingleLineElement(tle, filename) - local period = satelliteHelper.getPeriodFromElement(lineElement) - local path = tle .. filename +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (ISS)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_iss", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=25544&FORMAT=kvn", + Filename = "ISS.txt", + Override = true +}) - local iss = { - Identifier = "ISS", - Parent = transforms.EarthInertial.Identifier, - BoundingSphere = 54.5, -- half the width - InteractionSphere = 30, - Transform = { - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - Rotation = { - Type = "SpiceRotation", - SourceFrame = "GALACTIC", - DestinationFrame = "J2000", - } +local iss = { + Identifier = "ISS", + Parent = transforms.EarthInertial.Identifier, + BoundingSphere = 54.5, -- half the width + InteractionSphere = 30, + Transform = { + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "ISS.txt", + Format = "OMM" }, - Tag = { "earth_satellite", "ISS" }, - GUI = { - Path = "/Solar System/Planets/Earth/Satellites/ISS" + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GALACTIC", + DestinationFrame = "J2000", } + }, + Tag = { "earth_satellite", "ISS" }, + GUI = { + Name = "ISS", + Path = "/Solar System/Planets/Earth/Satellites/ISS" } +} - local parentNode = { - Identifier = "ISSModel", - Parent = iss.Identifier, - Transform = { - Rotation = { - Type = "FixedRotation", - Attached = "ISSModel", - XAxis = { 0.01, -1.0, 0.56 }, - XAxisOrthogonal = true, - YAxis = transforms.EarthInertial.Identifier - } - }, - Renderable = { - Type = "RenderableModel", - GeometryFile = models .. "ISS.fbx", - ModelScale = "Centimeter", - LightSources = { - sun.LightSource - }, - PerformShading = true, - DisableFaceCulling = true - }, - GUI = { - Name = "ISS Model", - Path = "/Solar System/Planets/Earth/Satellites/ISS" +local parentNode = { + Identifier = "ISSModel", + Parent = iss.Identifier, + Transform = { + Rotation = { + Type = "FixedRotation", + Attached = "ISSModel", + XAxis = { 0.01, -1.0, 0.56 }, + XAxisOrthogonal = true, + YAxis = transforms.EarthInertial.Identifier } - } - - local issTrail = { - Identifier = identifier .. "_trail", - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1, - }, - RenderBinMode = "PostDeferredTransparent", - Color = { 0.9, 0.6715, 0.0 }, - Fade = 1.5, - Period = period, - Resolution = 320 + }, + Renderable = { + Type = "RenderableModel", + GeometryFile = models .. "ISS.fbx", + ModelScale = "Centimeter", + LightSources = { + sun.LightSource }, - Tag = { "earth_satellite", "ISS" }, - GUI = { - Name = "ISS Trail", - Path = "/Solar System/Planets/Earth/Satellites/ISS" - } + PerformShading = true, + DisableFaceCulling = true + }, + GUI = { + Name = "ISS Model", + Path = "/Solar System/Planets/Earth/Satellites/ISS" } +} - -- @TODO (emmbr, 2021-05-27) add to scene when label rendering issues have been fixed - local IssLabel = { - Identifier = "IssLabel", - Parent = iss.Identifier, - Renderable = { - Enabled = false, - Type = "RenderableLabels", - Text = "ISS", - FontSize = 70.0, - Size = 3.4, - MinMaxSize = { 1, 100 }, - OrientationOption = "Camera View Direction", - BlendMode = "Additive", - EnableFading = true, - FadeDistances = { 0.15, 15.0 }, - FadeWidths = { 1.0, 25.0 } +local issTrail = { + Identifier = "ISS_trail", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "ISS.txt", + Format = "OMM" }, - Tag = { "solarsystem_labels" }, - GUI = { - Name = "ISS Label", - Path = "/Solar System/Planets/Earth/Satellites" - } + RenderBinMode = "PostDeferredTransparent", + Color = { 0.9, 0.6715, 0.0 }, + Fade = 1.5, + Resolution = 320 + }, + Tag = { "earth_satellite", "ISS" }, + GUI = { + Name = "ISS Trail", + Path = "/Solar System/Planets/Earth/Satellites/ISS" } +} - return { iss, parentNode, issTrail } -end +-- @TODO (emmbr, 2021-05-27) add to scene when label rendering issues have been fixed +local IssLabel = { + Identifier = "IssLabel", + Parent = iss.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + Text = "ISS", + FontSize = 70.0, + Size = 3.4, + MinMaxSize = { 1, 100 }, + OrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeDistances = { 0.15, 15.0 }, + FadeWidths = { 1.0, 25.0 } + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "ISS Label", + Path = "/Solar System/Planets/Earth/Satellites" + } +} asset.onInitialize(function () - nodes = initializeAndAddNodes() - for _, node in ipairs(nodes) do - openspace.addSceneGraphNode(node) - end + local i = openspace.space.readKeplerFile(omm .. "ISS.txt", "OMM") + issTrail.Renderable.Period = i[0].Period / (60 * 60 * 24) + + openspace.addSceneGraphNode(iss) + openspace.addSceneGraphNode(parentNode) openspace.setPropertyValueSingle("Scene.ISSModel.Rotation.yAxisInvertObject", true) + openspace.addSceneGraphNode(issTrail) end) asset.onDeinitialize(function () - for i=1, #nodes do - openspace.removeSceneGraphNode(nodes[#nodes + 1 - i].Identifier) - end + openspace.removeSceneGraphNode(issTrail) + openspace.removeSceneGraphNode(parentNode) + openspace.removeSceneGraphNode(iss) end) +asset.export(issTrail) +asset.export(parentNode) +asset.export(iss) asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/military.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/military.asset index 9b2072efe7..f9b316466a 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/military.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/military.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Military", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Military)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_military", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=military&FORMAT=kvn", Filename = "military.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=military&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "military", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "military.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Military", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/other.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/other.asset index ecbef9aedb..9026efc730 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/other.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/other.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Other", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Other)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_other", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other&FORMAT=kvn", Filename = "other.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=other&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "other", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "other.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Other", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/radar.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/radar.asset index 6c84bd6de5..9e9aa8040a 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/radar.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/radar.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Radar Calibration", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Radar Calibration)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_radar", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=radar&FORMAT=kvn", Filename = "radar.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=radar&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "radar", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "radar.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Radar Calibration", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/spacestations.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/spacestations.asset index 1b8166f83b..ab30c6340d 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/spacestations.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/spacestations.asset @@ -1,17 +1,46 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "SpaceStations", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (SpaceStations)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_stations", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=stations&FORMAT=kvn", Filename = "stations.txt", - Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=stations&FORMAT=TLE", - TrailColor = { 0.9, 0.1, 0.0 }, - Description = [[A collection of space stations (including the ISS and China's - Tiangong), along with certain cubesats and satellite constellations from space - agencies]] + Override = true +}) + +local satellites = { + Identifier = "stations", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "stations.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.9, 0.1, 0.0 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "SpaceStations", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[A collection of space stations (including the ISS and China's + Tiangong), along with certain cubesats and satellite constellations from space + agencies.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/misc/tle-new.asset b/data/assets/scene/solarsystem/planets/earth/satellites/misc/tle-new.asset index b2b93189d0..0e6c02ee79 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/misc/tle-new.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/misc/tle-new.asset @@ -1,15 +1,44 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Last 30 Days", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Last 30 Days)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_tle-new", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=kvn", Filename = "tle-new.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=last-30-days&FORMAT=TLE", - TrailColor = { 0.65, 0.25, 0.45 }, - Description = [[All the satellites that have been launched in the last 30 days]] + Override = true +}) + +local satellites = { + Identifier = "tle-new", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "tle-new.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.65, 0.25, 0.45 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Last 30 Days", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[All the satellites that have been launched in the last 30 days.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/beidou.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/beidou.asset index 8bb732b8a6..c0df39d21c 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/beidou.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/beidou.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Beidou", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Beidou)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_beidou", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=beidou&FORMAT=kvn", Filename = "beidou.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=beidou&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "beidou", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "beidou.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Beidou", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/galileo.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/galileo.asset index fd33f0c75a..327082c42c 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/galileo.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/galileo.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Galileo", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Galileo)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_galileo", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=galileo&FORMAT=kvn", Filename = "galileo.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=galileo&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local galileo = { + Identifier = "galileo", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "galileo.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Galileo", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(galileo) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(galileo) +end) + +asset.export(galileo) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/glosnass.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/glosnass.asset index 709afd10f9..b0bd56d86f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/glosnass.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/glosnass.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Glosnass", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Glosnass)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_glo-ops", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=glo-ops&FORMAT=kvn", Filename = "glo-ops.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=glo-ops&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "glo-ops", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "glo-ops.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Glosnass", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/gps.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/gps.asset index 703d9694de..10c40b32ca 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/gps.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/gps.asset @@ -1,15 +1,44 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "GPS", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (GPS)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_gps-ops", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=gps-ops&FORMAT=kvn", Filename = "gps-ops.txt", - Url = "https://celestrak.com/NORAD/elements/gp.php?GROUP=gps-ops&FORMAT=TLE", - TrailColor = { 0.9, 0.5, 0.0 }, - Description = "The GPS satellites that give us our precise locations back here on Earth" + Override = true +}) + +local satellites = { + Identifier = "gps-ops", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "gps-ops.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.9, 0.5, 0.0 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "GPS", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[The GPS satellites that give us our precise locations back on Earth.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/musson.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/musson.asset index 66d855c44b..a3dae75647 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/musson.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/musson.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Russian LEO Navigation", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Russian LEO Navigation)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_musson", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=musson&FORMAT=kvn", Filename = "musson.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=musson&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "musson", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "musson.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Russian LEO Navigation", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/nnss.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/nnss.asset index e41d42c2ec..c9793110eb 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/nnss.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/nnss.asset @@ -1,14 +1,44 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Navy Navigation Satellite System", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Navy Navigation Satellite System)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_nnss", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=nnss&FORMAT=kvn", Filename = "nnss.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=nnss&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "nnss", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "nnss.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Navy Navigation Satellite System", + Path = "/Solar System/Planets/Earth/Satellites", + Description = [[The first satellite navigation system to be used operationally.]] + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/sbas.asset b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/sbas.asset index 46b8d416cc..6f9e213258 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/navigation/sbas.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/navigation/sbas.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Satellite Based Augmentation System", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Satellite Based Augmentation System)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_sbas", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sbas&FORMAT=kvn", Filename = "sbas.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sbas&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "sbas", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "sbas.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Satellite Based Augmentation System", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/science/education.asset b/data/assets/scene/solarsystem/planets/earth/satellites/science/education.asset index 4fff51fad5..a15709b6d4 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/science/education.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/science/education.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Education", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Education)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_education", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=education&FORMAT=kvn", Filename = "education.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=education&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "education", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "education.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Education", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/science/engineering.asset b/data/assets/scene/solarsystem/planets/earth/satellites/science/engineering.asset index ff18399024..f16025753f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/science/engineering.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/science/engineering.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Engineering", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Engineering)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_engineering", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=engineering&FORMAT=kvn", Filename = "engineering.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=engineering&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "engineering", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "engineering.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Engineering", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/science/geodetic.asset b/data/assets/scene/solarsystem/planets/earth/satellites/science/geodetic.asset index 41ebd84e6a..36b05a8833 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/science/geodetic.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/science/geodetic.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Geodect", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Geodetic)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_geodetic", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geodetic&FORMAT=kvn", Filename = "geodetic.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=geodetic&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "geodetic", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "geodetic.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Geodetic", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/science/spaceearth.asset b/data/assets/scene/solarsystem/planets/earth/satellites/science/spaceearth.asset index 4c66fdfe04..3ae5b96d7a 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/science/spaceearth.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/science/spaceearth.asset @@ -1,21 +1,49 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Space & Earth Science", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Space & Earth Science)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_science", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=science&FORMAT=kvn", Filename = "science.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=science&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "science", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "science.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Space & Earth Science", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { Name = "Satellites Science Space & Earth Science", Version = "1.0", - Description = [[Satellites asset for Science Space & Earth Science. Data from - Celestrak]], + Description = "Satellites asset for Science Space & Earth Science. Data from Celestrak", Author = "OpenSpace Team", URL = "https://celestrak.com/NORAD/elements/", License = "Celestrak" diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/aqua.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/aqua.asset index 1dce9889d4..ef88079ea2 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/aqua.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/aqua.asset @@ -1,111 +1,105 @@ -local satelliteHelper = asset.require("util/tle_helper") local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local sunTransforms = asset.require("scene/solarsystem/sun/transforms") -local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=27424" -local identifier = "Aqua" -local filename = "Aqua.txt" -local nodes = {} -local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename) +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Aqua)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_aqua", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=27424&FORMAT=kvn", + Filename = "Aqua.txt", + Override = true +}) +local Aqua = { + Identifier = "Aqua", + Parent = transforms.EarthInertial.Identifier, + InteractionSphere = 30, + Transform = { + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "Aqua.txt", + Format = "OMM" + }, + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GALACTIC", + DestinationFrame = "J2000", + } + }, + Tag = { "earth_satellite", "Aqua" }, + GUI = { + Name = "Aqua", + Path = "/Solar System/Planets/Earth/Satellites/Aqua" + } +} + +local AquaTrail = { + Identifier = "Aqua_trail", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "Aqua.txt", + Format = "OMM", + RenderBinMode = "PostDeferredTransparent" + }, + Color = { 0.9, 0.6715, 0.0 }, + Fade = 1.5, + Resolution = 320 + }, + Tag = { "earth_satellite", "Aqua" }, + GUI = { + Name = "Aqua Trail", + Path = "/Solar System/Planets/Earth/Satellites/Aqua" + } +} + +-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances? +-- Might also be affected by the rendering issues for labels +local AquaLabel = { + Identifier = "AquaLabel", + Parent = Aqua.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + Text = "Aqua", + FontSize = 70.0, + Size = 4.0, + MinMaxSize = { 1, 100 }, + OrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeUnit = "au", + FadeDistances = { 1.5, 15.0 }, + FadeWidths = { 1.0, 25.0 } + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Aqua Label", + Path = "/Solar System/Planets/Earth" + } +} asset.onInitialize(function () - local lineElement = satelliteHelper.makeSingleLineElement(tle, filename) - local period = satelliteHelper.getPeriodFromElement(lineElement) - local path = tle .. "/" .. filename + local a = openspace.space.readKeplerFile(omm .. "Aqua.txt", "OMM") + AquaTrail.Renderable.Period = a[0].Period / (60 * 60 * 24) - local Aqua = { - Identifier = "Aqua", - Parent = transforms.EarthInertial.Identifier, - InteractionSphere = 30, - Transform = { - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - Rotation = { - Type = "SpiceRotation", - SourceFrame = "GALACTIC", - DestinationFrame = "J2000", - } - }, - Tag = { "earth_satellite", "Aqua" }, - GUI = { - Path = "/Solar System/Planets/Earth/Satellites/Aqua" - } - } - - local AquaTrail = { - Identifier = identifier .. "_trail", - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1, - RenderBinMode = "PostDeferredTransparent" - }, - Color = { 0.9, 0.6715, 0.0 }, - Fade = 1.5, - Period = period, - Resolution = 320 - }, - Tag = { "earth_satellite", "Aqua" }, - GUI = { - Name = "Aqua Trail", - Path = "/Solar System/Planets/Earth/Satellites/Aqua" - } - } - - -- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances? - -- Might also be affected by the rendering issues for labels - local AquaLabel = { - Identifier = "AquaLabel", - Parent = Aqua.Identifier, - Renderable = { - Enabled = false, - Type = "RenderableLabels", - Text = "Aqua", - FontSize = 70.0, - Size = 4.0, - MinMaxSize = { 1, 100 }, - OrientationOption = "Camera View Direction", - BlendMode = "Additive", - EnableFading = true, - FadeUnit = "au", - FadeDistances = { 1.5, 15.0 }, - FadeWidths = { 1.0, 25.0 } - }, - Tag = { "solarsystem_labels" }, - GUI = { - Name = "Aqua Label", - Path = "/Solar System/Planets/Earth" - } - } - - table.insert(nodes, Aqua) - table.insert(nodes, AquaTrail) - table.insert(nodes, AquaLabel) - for _, node in ipairs(nodes) do - openspace.addSceneGraphNode(node) - end + openspace.addSceneGraphNode(Aqua) + openspace.addSceneGraphNode(AquaTrail) + openspace.addSceneGraphNode(AquaLabel) end) asset.onDeinitialize(function () - for _, node in ipairs(nodes) do - openspace.removeSceneGraphNode(node) - end + openspace.removeSceneGraphNode(AquaLabel) + openspace.removeSceneGraphNode(AquaTrail) + openspace.removeSceneGraphNode(Aqua) end) -for _, node in ipairs(nodes) do - asset.export(node) -end +asset.export(Aqua) +asset.export(AquaTrail) +asset.export(AquaLabel) asset.meta = { Name = "Aqua", diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/argos.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/argos.asset index f06309e5f3..8540e1f396 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/argos.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/argos.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "ARGOS", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (ARGOS)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_argos", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=argos&FORMAT=kvn", Filename = "argos.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=argos&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "argos", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "argos.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "ARGOS", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/dmc.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/dmc.asset index 1a520c399f..7ce666f433 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/dmc.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/dmc.asset @@ -1,21 +1,49 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Disaster Monitoring", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Disaster Monitoring)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_dmc", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=dmc&FORMAT=kvn", Filename = "dmc.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=dmc&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "dmc", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "dmc.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Disaster Monitoring", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { Name = "Satellites Weather - Disaster Monitoring", Version = "1.0", - Description = [[Satellites asset for Weather - Disaster Monitoring. Data from - Celestrak]], + Description = "Satellites asset for Weather - Disaster Monitoring. Data from Celestrak", Author = "OpenSpace Team", URL = "https://celestrak.com/NORAD/elements/", License = "Celestrak" diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/earth_resources.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/earth_resources.asset index c63991ad64..73dcb42271 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/earth_resources.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/earth_resources.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Earth Resources", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Earth Resources)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_resource", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=resource&FORMAT=kvn", Filename = "resource.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=resource&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "resource", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "resource.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Earth Resources", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/goes.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/goes.asset index d7e1386c12..70d6d6a350 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/goes.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/goes.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "GOES", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (GOES)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_goes", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=goes&FORMAT=kvn", Filename = "goes.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=goes&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "goes", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "goes.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "GOES", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/noaa.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/noaa.asset index 9e5b411435..1b7d99ffb0 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/noaa.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/noaa.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "NOAA", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (NOAA)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_noaa", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=noaa&FORMAT=kvn", Filename = "noaa.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=noaa&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "noaa", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "noaa.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "NOAA", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/planet.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/planet.asset index 037509071a..c30bf8ab6f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/planet.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/planet.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Planet", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Planet)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_planet", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=planet&FORMAT=kvn", Filename = "planet.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=planet&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "planet", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "planet.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Planet", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/sarsat.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/sarsat.asset index c5129910aa..d2ad0e7056 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/sarsat.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/sarsat.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Search & Rescue (SARSAT)", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Search & Rescue (SARSAT))", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_sarsat", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sarsat&FORMAT=kvn", Filename = "sarsat.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=sarsat&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "sarsat", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "sarsat.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Search & Rescue (SARSAT)", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/snpp.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/snpp.asset index 35bd126b15..6d53c08c0f 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/snpp.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/snpp.asset @@ -1,110 +1,104 @@ -local satelliteHelper = asset.require("util/tle_helper") local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local sunTransforms = asset.require("scene/solarsystem/sun/transforms") -local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=37849" -local identifier = "SNPP" -local filename = "SNPP.txt" -local nodes = {} -local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename) +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (SNPP)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_snpp", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=37849&FORMAT=kvn", + Filename = "SNPP.txt", + Override = true +}) +local SNPP = { + Identifier = "SNPP", + Parent = transforms.EarthInertial.Identifier, + InteractionSphere = 30, + Transform = { + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "SNPP.txt", + Format = "OMM" + }, + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GALACTIC", + DestinationFrame = "J2000", + } + }, + Tag = { "earth_satellite", "SNPP" }, + GUI = { + Name = "SNPP", + Path = "/Solar System/Planets/Earth/Satellites/SNPP" + } +} + +local SNPPTrail = { + Identifier = "SNPP_trail", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "SNPP.txt", + Format = "OMM", + RenderBinMode = "PostDeferredTransparent" + }, + Color = { 0.9, 0.6715, 0.0 }, + Fade = 1.5, + Resolution = 320 + }, + Tag = { "earth_satellite", "SNPP" }, + GUI = { + Name = "SNPP Trail", + Path = "/Solar System/Planets/Earth/Satellites/SNPP" + } +} + +local SNPPLabel = { + Identifier = "SNPPLabel", + Parent = SNPP.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + Text = "SNPP", + FontSize = 70.0, + Size = 4.0, + MinMaxSize = { 1, 100 }, + OrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeUnit = "au", + FadeDistances = { 1.5, 15.0 }, + FadeWidths = { 1.0, 25.0 } + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "SNPP Label", + Path = "/Solar System/Planets/Earth" + } +} asset.onInitialize(function () - local lineElement = satelliteHelper.makeSingleLineElement(tle, filename) - local period = satelliteHelper.getPeriodFromElement(lineElement) - local path = tle .. "/" .. filename - - local SNPP = { - Identifier = "SNPP", - Parent = transforms.EarthInertial.Identifier, - InteractionSphere = 30, - Transform = { - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - Rotation = { - Type = "SpiceRotation", - SourceFrame = "GALACTIC", - DestinationFrame = "J2000", - } - }, - Tag = { "earth_satellite", "SNPP" }, - GUI = { - Path = "/Solar System/Planets/Earth/Satellites/SNPP" - } - } - - - local SNPPTrail = { - Identifier = identifier .. "_trail", - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1, - RenderBinMode = "PostDeferredTransparent" - }, - Color = { 0.9, 0.6715, 0.0 }, - Fade = 1.5, - Period = period, - Resolution = 320 - }, - Tag = { "earth_satellite", "SNPP" }, - GUI = { - Name = "SNPP Trail", - Path = "/Solar System/Planets/Earth/Satellites/SNPP" - } - } - - local SNPPLabel = { - Identifier = "SNPPLabel", - Parent = SNPP.Identifier, - - Renderable = { - Enabled = false, - Type = "RenderableLabels", - Text = "SNPP", - FontSize = 70.0, - Size = 4.0, - MinMaxSize = { 1, 100 }, - OrientationOption = "Camera View Direction", - BlendMode = "Additive", - EnableFading = true, - FadeUnit = "au", - FadeDistances = { 1.5, 15.0 }, - FadeWidths = { 1.0, 25.0 } - }, - Tag = { "solarsystem_labels" }, - GUI = { - Name = "SNPP Label", - Path = "/Solar System/Planets/Earth" - } - } - - table.insert(nodes, SNPP) - table.insert(nodes, SNPPTrail) - table.insert(nodes, SNPPLabel) - for _, node in ipairs(nodes) do - openspace.addSceneGraphNode(node) - end + local s = openspace.space.readKeplerFile(omm .. "SNPP.txt", "OMM") + SNPPTrail.Renderable.Period = s[0].Period / (60 * 60 * 24) + openspace.addSceneGraphNode(SNPP) + openspace.addSceneGraphNode(SNPPTrail) + openspace.addSceneGraphNode(SNPPLabel) end) - asset.onDeinitialize(function () - for _, node in ipairs(nodes) do - openspace.removeSceneGraphNode(node) - end + openspace.removeSceneGraphNode(SNPPLabel) + openspace.removeSceneGraphNode(SNPPTrail) + openspace.removeSceneGraphNode(SNPP) end) +asset.export(SNPP) +asset.export(SNPPTrail) +asset.export(SNPPLabel) + asset.meta = { Name = "SNPP", diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/spire.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/spire.asset index 8bae8bd82e..d2a89c12d8 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/spire.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/spire.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Spire", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Spire)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_spire", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=spire&FORMAT=kvn", Filename = "spire.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=spire&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "spire", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "spire.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Spire", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/tdrss.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/tdrss.asset index c20f949738..cc39b62f47 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/tdrss.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/tdrss.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Tracking and Data Relay Satellite System (TDRSS)", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Tracking and Data Relay Satellite System (TDRSS))", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_tdrss", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=tdrss&FORMAT=kvn", Filename = "tdrss.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=tdrss&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "tdrss", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "tdrss.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Tracking and Data Relay Satellite System (TDRSS)", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/terra.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/terra.asset index aa546bf337..4c256885b8 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/terra.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/terra.asset @@ -1,110 +1,107 @@ -local satelliteHelper = asset.require("util/tle_helper") local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local sunTransforms = asset.require("scene/solarsystem/sun/transforms") -local url = "http://celestrak.com/NORAD/elements/gp.php?CATNR=25994" -local identifier = "Terra" -local filename = "Terra.txt" -local nodes = {} -local tle = satelliteHelper.downloadTLEFile(asset, url, identifier, filename) +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Terra)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_terra", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?CATNR=25994&FORMAT=kvn", + Filename = "Terra.txt", + Override = true +}) - -asset.onInitialize(function () - local lineElement = satelliteHelper.makeSingleLineElement(tle, filename) - local period = satelliteHelper.getPeriodFromElement(lineElement) - local path = tle .. "/" .. filename - - local Terra = { - Identifier = "Terra", - Parent = transforms.EarthInertial.Identifier, - InteractionSphere = 30, - Transform = { - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1 - }, - Rotation = { - Type = "SpiceRotation", - SourceFrame = "GALACTIC", - DestinationFrame = "J2000", - } +local Terra = { + Identifier = "Terra", + Parent = transforms.EarthInertial.Identifier, + InteractionSphere = 30, + Transform = { + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "Terra.txt", + Format = "OMM" }, - Tag = { "earth_satellite", "Terra" }, - GUI = { - Path = "/Solar System/Planets/Earth/Satellites/Terra" + Rotation = { + Type = "SpiceRotation", + SourceFrame = "GALACTIC", + DestinationFrame = "J2000", } + }, + Tag = { "earth_satellite", "Terra" }, + GUI = { + Name = "Terra", + Path = "/Solar System/Planets/Earth/Satellites/Terra" } +} - local TerraTrail = { - Identifier = identifier .. "_trail", - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableTrailOrbit", - Translation = { - Type = "TLETranslation", - Body = identifier, - Observer = transforms.EarthInertial.Identifier, - File = path, - LineNumber = 1, - RenderBinMode = "PostDeferredTransparent" - }, - Color = { 0.9, 0.6715, 0.0 }, - Fade = 1.5, - Period = period, - Resolution = 320 +local TerraTrail = { + Identifier = "Terra_trail", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableTrailOrbit", + Translation = { + Type = "GPTranslation", + Observer = transforms.EarthInertial.Identifier, + File = omm .. "Terra.txt", + Format = "OMM", + RenderBinMode = "PostDeferredTransparent" }, - Tag = { "earth_satellite", "Terra" }, - GUI = { - Name = "Terra Trail", - Path = "/Solar System/Planets/Earth/Satellites/Terra" - } + Color = { 0.9, 0.6715, 0.0 }, + Fade = 1.5, + Resolution = 320 + }, + Tag = { "earth_satellite", "Terra" }, + GUI = { + Name = "Terra Trail", + Path = "/Solar System/Planets/Earth/Satellites/Terra" } +} - -- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances? - -- Might also be affected by the rendering issues for labels - local TerraLabel = { - Identifier = "TerraLabel", - Parent = Terra.Identifier, - Renderable = { - Enabled = false, - Type = "RenderableLabels", - Text = "Terra", - FontSize = 70.0, - Size = 4.0, - MinMaxSize = { 1, 100 }, - OrientationOption = "Camera View Direction", - BlendMode = "Additive", - EnableFading = true, - FadeUnit = "au", - FadeDistances = { 1.5, 15.0 }, - FadeWidths = { 1.0, 25.0 } - }, - Tag = { "solarsystem_labels" }, - GUI = { - Name = "Terra Label", - Path = "/Solar System/Planets/Earth" - } +-- @TODO (emmbr, 2021-05-27) this label is not visible. Too large fade distances? +-- Might also be affected by the rendering issues for labels +local TerraLabel = { + Identifier = "TerraLabel", + Parent = Terra.Identifier, + Renderable = { + Enabled = false, + Type = "RenderableLabels", + Text = "Terra", + FontSize = 70.0, + Size = 4.0, + MinMaxSize = { 1, 100 }, + OrientationOption = "Camera View Direction", + BlendMode = "Additive", + EnableFading = true, + FadeUnit = "au", + FadeDistances = { 1.5, 15.0 }, + FadeWidths = { 1.0, 25.0 } + }, + Tag = { "solarsystem_labels" }, + GUI = { + Name = "Terra Label", + Path = "/Solar System/Planets/Earth" } +} - table.insert(nodes, Terra) - table.insert(nodes, TerraTrail) - table.insert(nodes, TerraLabel) - for _, node in ipairs(nodes) do - openspace.addSceneGraphNode(node) - end +asset.onInitialize(function() + local t = openspace.space.readKeplerFile(omm .. "Terra.txt", "OMM") + TerraTrail.Renderable.Period = t[0].Period / (60 * 60 * 24) + openspace.addSceneGraphNode(Terra) + openspace.addSceneGraphNode(TerraTrail) + openspace.addSceneGraphNode(TerraLabel) end) asset.onDeinitialize(function () - for _, node in ipairs(nodes) do - openspace.removeSceneGraphNode(node) - end + openspace.removeSceneGraphNode(TerraLabel) + openspace.removeSceneGraphNode(TerraTrail) + openspace.removeSceneGraphNode(Terra) end) +asset.export(Terra) +asset.export(TerraTrail) +asset.export(TerraLabel) + asset.meta = { Name = "Terra", diff --git a/data/assets/scene/solarsystem/planets/earth/satellites/weather/weather.asset b/data/assets/scene/solarsystem/planets/earth/satellites/weather/weather.asset index 80afc7a097..7c3525c960 100644 --- a/data/assets/scene/solarsystem/planets/earth/satellites/weather/weather.asset +++ b/data/assets/scene/solarsystem/planets/earth/satellites/weather/weather.asset @@ -1,14 +1,43 @@ -local shared = asset.require("util/tle_helper") +local transforms = asset.require("scene/solarsystem/planets/earth/transforms") -local group = { - Title = "Weather", +local omm = asset.syncedResource({ + Name = "Satellite OMM Data (Weather)", + Type = "UrlSynchronization", + Identifier = "satellite_omm_data_weather", + Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=weather&FORMAT=kvn", Filename = "weather.txt", - Url = "https://www.celestrak.com/NORAD/elements/gp.php?GROUP=weather&FORMAT=TLE", - TrailColor = { 0.75, 0.75, 0.35 } + Override = true +}) + +local satellites = { + Identifier = "weather", + Parent = transforms.EarthInertial.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = omm .. "weather.txt", + Format = "OMM", + SegmentQuality = 3, + Color = { 0.75, 0.75, 0.35 }, + Fade = 1.5, + RenderBinMode = "PostDeferredTransparent" + }, + Tag = { "earth_satellites" }, + GUI = { + Name = "Weather", + Path = "/Solar System/Planets/Earth/Satellites" + } } -local tle = shared.downloadTLEFile(asset, group.Url, group.Title, group.Filename) -shared.registerSatelliteGroupObjects(asset, group, tle, true) +asset.onInitialize(function() + openspace.addSceneGraphNode(satellites) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(satellites) +end) + +asset.export(satellites) + asset.meta = { diff --git a/data/assets/scene/solarsystem/sssb/amor_asteroid.asset b/data/assets/scene/solarsystem/sssb/amor_asteroid.asset index 86ba6ac74d..d8f0fb6cf7 100644 --- a/data/assets/scene/solarsystem/sssb/amor_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/amor_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "amor_asteroid", -"sssb_data_amor_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_amor_asteroid.csv", - "Amor Asteroids", filepath, { 1.0, 1.0, 1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 4 -object.Renderable.TrailFade = 11 - -object.GUI.Description = [[Earth-approaching Near-Earth-Asteroids with orbits exterior to - Earth's but interior to Mars']] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Amor Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_amor_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_amor_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_amor_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 4, + Color = { 1.0, 1.0, 1.0 }, + TrailFade = 11 + }, + GUI = { + Name = "Amor Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Earth-approaching Near-Earth-Asteroids with orbits exterior to + Earth's but interior to Mars'.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/apollo_asteroid.asset b/data/assets/scene/solarsystem/sssb/apollo_asteroid.asset index 4cdacd04f2..8959b3fc01 100644 --- a/data/assets/scene/solarsystem/sssb/apollo_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/apollo_asteroid.asset @@ -1,15 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "apollo_asteroid", - "sssb_data_apollo_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_apollo_asteroid.csv", - "Apollo Asteroids", filepath, { 0.7, 0.7, 1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 6 -object.Renderable.TrailFade = 10 +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Apollo Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_apollo_asteroid", + Version = 1 +}) -object.GUI.Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes - larger than Earth's. ]] +local object = { + Identifier = "sssb_apollo_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_apollo_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 6, + Color = { 0.7, 0.7, 1.0 }, + TrailFade = 10 + }, + GUI = { + Name = "Apollo Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes larger than + Earth's.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/aten_asteroid.asset b/data/assets/scene/solarsystem/sssb/aten_asteroid.asset index b62e9140f8..bde6a0cd97 100644 --- a/data/assets/scene/solarsystem/sssb/aten_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/aten_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "aten_asteroid", - "sssb_data_aten_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_aten_asteroid.csv", - "Aten Asteroids", filepath, { 0.15, 0.15, 1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 2 -object.Renderable.TrailFade = 18 - -object.GUI.Description = [[ Earth-crossing Near-Earth-Asteroids with semi-major axes - smaller than Earth's. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Aten Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_aten_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_aten_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_aten_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 2, + Color = { 0.15, 0.15, 1.0 }, + TrailFade = 18 + }, + GUI = { + Name = "Aten Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Earth-crossing Near-Earth-Asteroids with semi-major axes smaller than + Earth's.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/atira_asteroid.asset b/data/assets/scene/solarsystem/sssb/atira_asteroid.asset index fecc5b8803..31e6221811 100644 --- a/data/assets/scene/solarsystem/sssb/atira_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/atira_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "atira_asteroid", - "sssb_data_atira_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_atira_asteroid.csv", - "Atira Asteroids", filepath, { 0.5, 0.8, 1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 2 -object.Renderable.TrailFade = 25 - -object.GUI.Description = [[ Near-Earth-Asteroids whose orbits are contained entirely - within the orbit of the Earth. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Atira Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_atira_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_atira_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_atira_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 2, + Color = { 0.5, 0.8, 1.0 }, + TrailFade = 25 + }, + GUI = { + Name = "Atira Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Near-Earth-Asteroids whose orbits are contained entirely within the + orbit of the Earth.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/c2019y4atlas.asset b/data/assets/scene/solarsystem/sssb/c2019y4atlas.asset index d4c4418a65..61847df142 100644 --- a/data/assets/scene/solarsystem/sssb/c2019y4atlas.asset +++ b/data/assets/scene/solarsystem/sssb/c2019y4atlas.asset @@ -68,7 +68,7 @@ asset.export(C2019Y4AtlasTrail) asset.meta = { Name = "C/2019 Y4 Atlas", Version = "1.2", - Description = [[This asset contains the trail and position of C/2019 Y4 Atlas from + Description = [[This asset contains the trail and position of C/2019 Y4 Atlas from 1950 JAN 01 00:00:00 to 2100 JAN 01 00:00:00. Data from JPL Horizons]], Author = "OpenSpace Team", URL = "https://ssd.jpl.nasa.gov/horizons.cgi", diff --git a/data/assets/scene/solarsystem/sssb/centaur_asteroid.asset b/data/assets/scene/solarsystem/sssb/centaur_asteroid.asset index d11e1e925e..c86a9f5ebb 100644 --- a/data/assets/scene/solarsystem/sssb/centaur_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/centaur_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "centaur_asteroid", - "sssb_data_centaur_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_centaur_asteroid.csv", - "Centaur Asteroids", filepath, { 0.94, 0.96, 0.94 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 6 -object.Renderable.TrailFade = 18 - -object.GUI.Description = [[ Asteroids with either a perihelion or a semi-major axis - between those of the four outer planets. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Centaur Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_centaur_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_centaur_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_centaur_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 6, + Color = { 0.94, 0.96, 0.94 }, + TrailFade = 18 + }, + GUI = { + Name = "Centaur Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids with either a perihelion or a semi-major axis between those + of the four outer planets.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/chiron-type_comet.asset b/data/assets/scene/solarsystem/sssb/chiron-type_comet.asset index 9513a71d94..45693cd7e7 100644 --- a/data/assets/scene/solarsystem/sssb/chiron-type_comet.asset +++ b/data/assets/scene/solarsystem/sssb/chiron-type_comet.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "chiron-type_comet", - "sssb_data_chiron-type_comet") -local object = sharedSssb.createSssbGroupObject("sssb_data_chiron-type_comet.csv", - "Chiron-type Comets", filepath, { 0.15 ,0.1 ,1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 10 -object.Renderable.TrailFade = 25 - -object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of - greater than 3 and a semi-major axis greater than that of Jupiter. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Chiron-type Comet)", + Type = "HttpSynchronization", + Identifier = "sssb_data_chiron-type_comet", + Version = 1 +}) +local object = { + Identifier = "sssb_chiron-type_comet", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_chiron-type_comet.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 10, + Color = { 0.15, 0.1, 1.0 }, + TrailFade = 25 + }, + GUI = { + Name = "Chiron-type Comets", + Path = "/Solar System/Small Bodies", + Description = [[Comets with a Tisserand's parameter with respect to Jupiter of + greater than 3 and a semi-major axis greater than that of Jupiter.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/encke-type_comet.asset b/data/assets/scene/solarsystem/sssb/encke-type_comet.asset index 2e4da53952..011f588df5 100644 --- a/data/assets/scene/solarsystem/sssb/encke-type_comet.asset +++ b/data/assets/scene/solarsystem/sssb/encke-type_comet.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "encke-type_comet", - "sssb_data_encke-type_comet") -local object = sharedSssb.createSssbGroupObject("sssb_data_encke-type_comet.csv", - "Encke-type Comets", filepath, { 0.8, 0.34, 1.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 2 -object.Renderable.TrailFade = 23 - -object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of - greater than 3 and a semi-major axis less than that of Jupiter. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Encke-type Comet)", + Type = "HttpSynchronization", + Identifier = "sssb_data_encke-type_comet", + Version = 1 +}) +local object = { + Identifier = "sssb_encke-type_comet", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_encke-type_comet.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 2, + Color = { 0.8, 0.34, 1.0 }, + TrailFade = 23 + }, + GUI = { + Name = "Encke-type Comets", + Path = "/Solar System/Small Bodies", + Description = [[Comets with a Tisserand's parameter with respect to Jupiter of + greater than 3 and a semi-major axis less than that of Jupiter.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/halley-type_comet.asset b/data/assets/scene/solarsystem/sssb/halley-type_comet.asset index b86aaa0277..2eb3f87ac2 100644 --- a/data/assets/scene/solarsystem/sssb/halley-type_comet.asset +++ b/data/assets/scene/solarsystem/sssb/halley-type_comet.asset @@ -1,15 +1,30 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "halley-type_comet", - "sssb_data_halley-type_comet") -local object = sharedSssb.createSssbGroupObject("sssb_data_halley-type_comet.csv", - "Halley-type Comets", filepath, { 0.66, 0.66, 0.66 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 9 -object.Renderable.TrailFade = 18 +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Halley-type Comet)", + Type = "HttpSynchronization", + Identifier = "sssb_data_halley-type_comet", + Version = 1 +}) -object.GUI.Description = [[ Periodic comets with an orbital period between 20 and 200 - years. ]] +local object = { + Identifier = "sssb_halley-type_comet", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_halley-type_comet.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 9, + Color = { 0.66, 0.66, 0.66 }, + TrailFade = 18 + }, + GUI = { + Name = "Halley-type Comets", + Path = "/Solar System/Small Bodies", + Description = "Periodic comets with an orbital period between 20 and 200 years." + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/inner_main_belt_asteroid.asset b/data/assets/scene/solarsystem/sssb/inner_main_belt_asteroid.asset index 9e71e2dccd..7bd30ffefa 100644 --- a/data/assets/scene/solarsystem/sssb/inner_main_belt_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/inner_main_belt_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "inner_main_belt_asteroid", - "sssb_data_inner_main_belt_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_inner_main_belt_asteroid.csv", - "Inner Main Asteroid Belt", filepath, { 1.0, 1.0, 0.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 1 -object.Renderable.TrailFade = 0.5 - -object.GUI.Description = [[ Asteroids with a semi-major axis less than 2.0 au and a - perihelion distance greater than 1.666 au. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Inner Main Belt Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_inner_main_belt_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_inner_main_belt_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_inner_main_belt_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 1, + Color = { 1.0, 1.0, 0.0 }, + TrailFade = 0.5 + }, + GUI = { + Name = "Inner Main Asteroid Belt", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids with a semi-major axis less than 2.0 AU and a perihelion + distance greater than 1.666 AU.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/itokawa.asset b/data/assets/scene/solarsystem/sssb/itokawa.asset index 7e97485226..e53c6466b1 100644 --- a/data/assets/scene/solarsystem/sssb/itokawa.asset +++ b/data/assets/scene/solarsystem/sssb/itokawa.asset @@ -75,7 +75,7 @@ local ItokawaModel = { Name = "Itokawa Model", Path = "/Solar System/SSSB/Itokawa", Description = [[Model of asteroid 25143 Itokawa. 3D model from - https://solarsystem.nasa.gov/resources/2377/asteroid-itokawa-3d-model/]] + https://solarsystem.nasa.gov/resources/2377/asteroid-itokawa-3d-model]] } } diff --git a/data/assets/scene/solarsystem/sssb/jupiter-family_comet.asset b/data/assets/scene/solarsystem/sssb/jupiter-family_comet.asset index ab6b0e89b0..64e79450f4 100644 --- a/data/assets/scene/solarsystem/sssb/jupiter-family_comet.asset +++ b/data/assets/scene/solarsystem/sssb/jupiter-family_comet.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "jupiter-family_comet", - "sssb_data_jupiter-family_comet") -local object = sharedSssb.createSssbGroupObject("sssb_data_jupiter-family_comet.csv", - "Jupiter-family Comets", filepath, { 0.2, 0.8, 0.2 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 10 -object.Renderable.TrailFade = 28 - -object.GUI.Description = [[ Comets with a Tisserand's parameter with respect to Jupiter of - between 2 and 3. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Jupiter Family Comet)", + Type = "HttpSynchronization", + Identifier = "sssb_data_jupiter-family_comet", + Version = 1 +}) +local object = { + Identifier = "sssb_jupiter-family_comet", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_jupiter-family_comet.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 10, + Color = { 0.2, 0.8, 0.2 }, + TrailFade = 28 + }, + GUI = { + Name = "Jupiter-family Comets", + Path = "/Solar System/Small Bodies", + Description = [[Comets with a Tisserand's parameter with respect to Jupiter of between + 2 and 3.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/jupiter_trojan_asteroid.asset b/data/assets/scene/solarsystem/sssb/jupiter_trojan_asteroid.asset index 59d3eec17c..282cc1cc41 100644 --- a/data/assets/scene/solarsystem/sssb/jupiter_trojan_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/jupiter_trojan_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "jupiter_trojan_asteroid", - "sssb_data_jupiter_trojan_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_jupiter_trojan_asteroid.csv", - "Jupiter Trojan Asteroids", filepath, { 0.5, 0.8, 0.5 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 1 -object.Renderable.TrailFade = 5 - -object.GUI.Description = [[ Asteroids trapped in Jupiter's L4/L5 Lagrange points - (semimajor axis of between 4.6 and 5.5 au), with an eccentricity of less than 0.3. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Jupiter Trojan Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_jupiter_trojan_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_jupiter_trojan_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_jupiter_trojan_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 1, + Color = { 0.5, 0.8, 0.5 }, + TrailFade = 5 + }, + GUI = { + Name = "Jupiter Trojan Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids trapped in Jupiter's L4/L5 Lagrange points (semimajor axis + of between 4.6 and 5.5 AU), with an eccentricity of less than 0.3.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/main_belt_asteroid.asset b/data/assets/scene/solarsystem/sssb/main_belt_asteroid.asset index e291b95043..442ccbf0b8 100644 --- a/data/assets/scene/solarsystem/sssb/main_belt_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/main_belt_asteroid.asset @@ -1,17 +1,32 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "main_belt_asteroid", - "sssb_data_main_belt_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_main_belt_asteroid.csv", - "Main Asteroid Belt", filepath, { 0.0, 0.5, 0.0 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 1 -object.Renderable.TrailFade = 0.1 -object.Renderable.UpperLimit = 50000 - -object.GUI.Description = [[ Asteroids with a semi-major axis of between 2.0 and 3.2 au, - and a perihelion distance greater than 1.666 au. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Main Belt Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_main_belt_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_main_belt_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_main_belt_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 1, + Color = { 0.0, 0.5, 0.0 }, + TrailFade = 0.1, + RenderSize = 50000 + }, + GUI = { + Name = "Main Asteroid Belt", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids with a semi-major axis of between 2.0 and 3.2 AU, + and a perihelion distance greater than 1.666 AU.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/mars-crossing_asteroid.asset b/data/assets/scene/solarsystem/sssb/mars-crossing_asteroid.asset index 1ebf5adad6..b840a15e07 100644 --- a/data/assets/scene/solarsystem/sssb/mars-crossing_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/mars-crossing_asteroid.asset @@ -1,16 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "mars-crossing_asteroid", - "sssb_data_mars-crossing_asteroid") -local object = sharedSssb.createSssbGroupObject("sssb_data_mars-crossing_asteroid.csv", - "Mars-crossing Asteroids", filepath, { 0.814, 0.305, 0.220 }) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 1 -object.Renderable.TrailFade = 13 - -object.GUI.Description = [[ Asteroids that cross the orbit of Mars, with a semi-major axis - of less than 3.2 au, and a perihelion distance of between 1.3 and 1.666 au. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Mars-Crossing Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_mars-crossing_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_mars-crossing_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_mars-crossing_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 1, + Color = { 0.814, 0.305, 0.22 }, + TrailFade = 13 + }, + GUI = { + Name = "Mars-crossing Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids that cross the orbit of Mars, with a semi-major axis + of less than 3.2 AU, and a perihelion distance of between 1.3 and 1.666 AU.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/outer_main_belt_asteroid.asset b/data/assets/scene/solarsystem/sssb/outer_main_belt_asteroid.asset index 14b46f2fd6..7fb79168eb 100644 --- a/data/assets/scene/solarsystem/sssb/outer_main_belt_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/outer_main_belt_asteroid.asset @@ -1,21 +1,30 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile( - asset, - "outer_main_belt_asteroid", - "sssb_data_outer_main_belt_asteroid" -) -local object = sharedSssb.createSssbGroupObject( - "sssb_data_outer_main_belt_asteroid.csv", - "Outer Main Asteroid Belt", - filepath, - { 0.4, 0.4, 1.0 } -) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 1 -object.Renderable.TrailFade = 2 +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Outer Main Belt Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_outer_main_belt_asteroid", + Version = 1 +}) -object.GUI.Description = [[ Asteroids with a semi-major axis of between 3.2 and 4.6 au. ]] +local object = { + Identifier = "sssb_outer_main_belt_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_outer_main_belt_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 1, + Color = { 0.4, 0.4, 1.0 }, + TrailFade = 2 + }, + GUI = { + Name = "Outer Main Asteroid Belt", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids with a semi-major axis of between 3.2 and 4.6 AU.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/pha.asset b/data/assets/scene/solarsystem/sssb/pha.asset index 3f90b193b9..e5ae832015 100644 --- a/data/assets/scene/solarsystem/sssb/pha.asset +++ b/data/assets/scene/solarsystem/sssb/pha.asset @@ -1,20 +1,33 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, "pha", "sssb_data_pha") -local object = sharedSssb.createSssbGroupObject("sssb_data_pha.csv", - "Potentially Hazardous Asteroids", - filepath, - { 0.98, 0.09, 0.06 } -) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 3 -object.Renderable.TrailFade = 17 - -object.GUI.Description = [[ Asteroids that are deemed potentially hazardous to Earth - based on their close approaches. All asteroids with an Earth Minimum Orbit - Intersection Distance (MOID) of 0.05 au or less, and with an absolute magnitude (H) - of 22.0 or less. ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Potentially hazardous Asteroids)", + Type = "HttpSynchronization", + Identifier = "sssb_data_pha", + Version = 1 +}) +local object = { + Identifier = "sssb_pha", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_pha.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 3, + Color = { 0.98, 0.09, 0.06 }, + TrailFade = 17 + }, + GUI = { + Name = "Potentially Hazardous Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Asteroids that are deemed potentially hazardous to Earth based on + their close approaches. All asteroids with an Earth Minimum Orbit Intersection + Distance (MOID) of 0.05 AU or less, and with an absolute magnitude (H) of 22.0 or + less.]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/scene/solarsystem/sssb/sssb_shared.asset b/data/assets/scene/solarsystem/sssb/sssb_shared.asset deleted file mode 100644 index fdc22450d1..0000000000 --- a/data/assets/scene/solarsystem/sssb/sssb_shared.asset +++ /dev/null @@ -1,50 +0,0 @@ -local transforms = asset.require("scene/solarsystem/sun/transforms") - -function downloadSssbDatabaseFile(sceneAsset, name, identifier) - assert(sceneAsset, "'asset' needs to be provided") - assert(name, "'name' needs to be provided") - assert(identifier, "'identifier'needs to be provided") - - return sceneAsset.syncedResource({ - Name = "Small SolarSystem Body Data (" .. name .. ")", - Type = "HttpSynchronization", - Identifier = identifier, - Version = 1 - }) -end - -local createSssbGroupObject = function(filename, guiName, sssbFolder, trailColor) - assert(filename, "'filename' needs to be provided") - assert(sssbFolder, "'sssbFolder' needs to be provided") - trailColor = trailColor or { 0.75, 0.1, 0.1 } - - local filenameSansExt = filename:gsub(filename:match("(%.%w+)$"), "") - return { - Identifier = "sssb_" .. filenameSansExt, - Parent = transforms.SunECLIPJ2000.Identifier, - Renderable = { - Type = "RenderableSmallBody", - Path = sssbFolder .. filename, - Segments = 200, - Color = trailColor, - TrailFade = 0.5, - }, - GUI = { - Path = "/Solar System/Small Bodies", - Name = guiName - } - } -end - -asset.export("downloadSssbDatabaseFile", downloadSssbDatabaseFile) -asset.export("createSssbGroupObject", createSssbGroupObject) - - -asset.meta = { - Name = "SSSB shared", - Version = "1.0", - Description = [[ UTILITY ASSET; This asset is for builders and coders]], - Author = "OpenSpace Team", - URL = "http://openspaceproject.com", - License = "MIT license" -} diff --git a/data/assets/scene/solarsystem/sssb/transneptunian_object_asteroid.asset b/data/assets/scene/solarsystem/sssb/transneptunian_object_asteroid.asset index 02cf9993db..2bf8dd14fb 100644 --- a/data/assets/scene/solarsystem/sssb/transneptunian_object_asteroid.asset +++ b/data/assets/scene/solarsystem/sssb/transneptunian_object_asteroid.asset @@ -1,22 +1,31 @@ -local sharedSssb = asset.require("./sssb_shared") +local transforms = asset.require("scene/solarsystem/sun/transforms") -local filepath = sharedSssb.downloadSssbDatabaseFile(asset, - "transneptunian_object_asteroid", - "sssb_data_transneptunian_object_asteroid" -) -local object = sharedSssb.createSssbGroupObject( - "sssb_data_transneptunian_object_asteroid.csv", - "Transneptunian Object Asteroids", - filepath, - { 0.56, 0.64, 0.95 } -) -object.Renderable.Enabled = false -object.Renderable.SegmentQuality = 8 -object.Renderable.TrailFade = 10 - -object.GUI.Description = [[ Any minor or dwarf planets in the solar system that orbit - the Sun at a greater average distance than Neptune (semi-major axis of 30.1 AU). ]] +local sssb = asset.syncedResource({ + Name = "Small SolarSystem Body Data (Trans-Neptunian Object Asteroid)", + Type = "HttpSynchronization", + Identifier = "sssb_data_transneptunian_object_asteroid", + Version = 1 +}) +local object = { + Identifier = "sssb_transneptunian_object_asteroid", + Parent = transforms.SunECLIPJ2000.Identifier, + Renderable = { + Type = "RenderableOrbitalKepler", + Path = sssb .. "sssb_data_transneptunian_object_asteroid.csv", + Format = "SBDB", + Segments = 200, + SegmentQuality = 8, + Color = { 0.56, 0.64, 0.95 }, + TrailFade = 10 + }, + GUI = { + Name = "Transneptunian Object Asteroids", + Path = "/Solar System/Small Bodies", + Description = [[Any minor or dwarf planets in the solar system that orbit the Sun at a + greater average distance than Neptune (semi-major axis of 30.1 AU).]] + } +} asset.onInitialize(function() openspace.addSceneGraphNode(object) diff --git a/data/assets/util/tle_helper.asset b/data/assets/util/tle_helper.asset deleted file mode 100644 index 2676ebd824..0000000000 --- a/data/assets/util/tle_helper.asset +++ /dev/null @@ -1,124 +0,0 @@ -local transforms = asset.require("scene/solarsystem/planets/earth/transforms") - -function downloadTLEFile(sceneAsset, url, name, filename) - local identifier = name - identifier = identifier:gsub(" ", "") - identifier = identifier:gsub("&", "") - identifier = identifier:gsub("-", "") - - local urlSyncTable = { - Name = "Satellite TLE Data (" .. name .. ")", - Type = "UrlSynchronization", - Identifier = "satellite_tle_data_" .. identifier, - Url = url, - Override = true - } - - if (filename ~= "") then - urlSyncTable.Filename = filename - end - - return sceneAsset.syncedResource(urlSyncTable) -end - --- Check format of a set of 3 TLE file lines and return nonzero if there is a format error -function isValidTLEFileFormat(lineArr) - local function isEmpty(s) return s == nil or s == "" end - - if isEmpty(lineArr[1]) or isEmpty(lineArr[2]) or isEmpty(lineArr[3]) then - return false - end - if string.sub(lineArr[2], 1, 2) ~= "1 " then - return false - end - if string.sub(lineArr[3], 1, 2) ~= "2 " then - return false - end - return true -end - -local makeSingleLineElement = function(tle, filename) - local path = tle .. "/" .. filename - local file = io.open(path, "r") - assert(file, "File not found: " .. path) - - local line = { - file:read("*l"), --title line - file:read("*l"), - file:read("*l") - } - - assert(isValidTLEFileFormat(line), "TLE file syntax error on line " .. 1 .. ": " .. path) - - -- Trim string - line[1] = line[1]:gsub("^%s*(.-)%s*$", "%1") - line[1] = line[1]:gsub("%s+", "_") - line[1] = line[1]:gsub("[%-()]", "") - --local title = line[1] - - return line -end - -function numLinesInFile(filename) - local ctr = 0 - for _ in io.lines(filename) do ctr = ctr + 1 end - return ctr -end - -local getPeriodFromElement = function(element) - -- Get period from correct location of the string - local per = tonumber(string.sub(element[3], 53, 63)) - -- Trail for 2x a single revolution - per = 1.0 / per - - return per -end - -function satellites(title, file, color, group) - return { - Identifier = title, - Parent = transforms.EarthInertial.Identifier, - Renderable = { - Type = "RenderableSatellites", - Path = file, - SegmentQuality = 3, - Color = color, - Fade = 1.5, - RenderBinMode = "PostDeferredTransparent", - StartRenderIdx = group.StartRenderIdx, - RenderSize = group.RenderSize - }, - Tag = { "earth_satellites" }, - GUI = { - Name = group.Title, - Path = "/Solar System/Planets/Earth/Satellites", - Description = group.Description - } - } -end - -local registerSatelliteGroupObjects = function(containingAsset, group, tleFolder, shouldAddDuplicates) - local filename = group.Filename - local filenameSansExt = filename:gsub(filename:match("(%.%w+)$"), "") - - local path = tleFolder .. "/" .. filename - - local SatelliteBatch = satellites(filenameSansExt, path, group.TrailColor, group) - - containingAsset.onInitialize(function() - openspace.addSceneGraphNode(SatelliteBatch) - end) - - containingAsset.onDeinitialize(function() - openspace.removeSceneGraphNode(SatelliteBatch) - end) - - containingAsset.export(SatelliteBatch) -end - -asset.export("downloadTLEFile", downloadTLEFile) -asset.export("isValidTLEFileFormat", isValidTLEFileFormat) -asset.export("numLinesInFile", numLinesInFile) -asset.export("makeSingleLineElement", makeSingleLineElement) -asset.export("getPeriodFromElement", getPeriodFromElement) -asset.export("registerSatelliteGroupObjects", registerSatelliteGroupObjects) diff --git a/modules/fitsfilereader/ext/CCfits b/modules/fitsfilereader/ext/CCfits index 27f655a80f..3c16ca3f1e 160000 --- a/modules/fitsfilereader/ext/CCfits +++ b/modules/fitsfilereader/ext/CCfits @@ -1 +1 @@ -Subproject commit 27f655a80febd04a1921edc8894ebbe326137355 +Subproject commit 3c16ca3f1e9a405be7fdbd0db363151eca96629f diff --git a/modules/fitsfilereader/ext/cfitsio b/modules/fitsfilereader/ext/cfitsio index e8fc91cc4b..8d98f1495b 160000 --- a/modules/fitsfilereader/ext/cfitsio +++ b/modules/fitsfilereader/ext/cfitsio @@ -1 +1 @@ -Subproject commit e8fc91cc4b4cb22236d94429202175b7043bf36f +Subproject commit 8d98f1495b8c762f1c56e79da33cbd3c7d623d80 diff --git a/modules/kameleon/ext/kameleon b/modules/kameleon/ext/kameleon index e6978911c5..606edb945b 160000 --- a/modules/kameleon/ext/kameleon +++ b/modules/kameleon/ext/kameleon @@ -1 +1 @@ -Subproject commit e6978911c51560457ca1738517ff3cf5290febd4 +Subproject commit 606edb945b62d0151f20270ddb2db4a9f558aaa1 diff --git a/modules/space/CMakeLists.txt b/modules/space/CMakeLists.txt index dc8f0ddfd2..3337872afe 100644 --- a/modules/space/CMakeLists.txt +++ b/modules/space/CMakeLists.txt @@ -26,19 +26,18 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES horizonsfile.h + kepler.h speckloader.h rendering/renderableconstellationbounds.h rendering/renderablefluxnodes.h rendering/renderablehabitablezone.h rendering/renderablerings.h rendering/renderableorbitalkepler.h - rendering/renderablesatellites.h - rendering/renderablesmallbody.h rendering/renderablestars.h rendering/renderabletravelspeed.h + translation/gptranslation.h translation/keplertranslation.h translation/spicetranslation.h - translation/tletranslation.h translation/horizonstranslation.h rotation/spicerotation.h ) @@ -46,6 +45,7 @@ source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES horizonsfile.cpp + kepler.cpp spacemodule_lua.inl speckloader.cpp rendering/renderableconstellationbounds.cpp @@ -53,13 +53,11 @@ set(SOURCE_FILES rendering/renderablehabitablezone.cpp rendering/renderablerings.cpp rendering/renderableorbitalkepler.cpp - rendering/renderablesatellites.cpp - rendering/renderablesmallbody.cpp rendering/renderablestars.cpp rendering/renderabletravelspeed.cpp + translation/gptranslation.cpp translation/keplertranslation.cpp translation/spicetranslation.cpp - translation/tletranslation.cpp translation/horizonstranslation.cpp rotation/spicerotation.cpp ) diff --git a/modules/space/kepler.cpp b/modules/space/kepler.cpp new file mode 100644 index 0000000000..32b2c67769 --- /dev/null +++ b/modules/space/kepler.cpp @@ -0,0 +1,751 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + constexpr std::string_view _loggerCat = "Kepler"; + constexpr int8_t CurrentCacheVersion = 1; + + // The list of leap years only goes until 2056 as we need to touch this file then + // again anyway ;) + constexpr const std::array LeapYears = { + 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, + 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, + 2044, 2048, 2052, 2056 + }; + constexpr const std::array DaysOfMonths = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + + // Count the number of full days since the beginning of 2000 to the beginning of + // the parameter 'year' + int countDays(int year) { + // Find the position of the current year in the vector, the difference + // between its position and the position of 2000 (for J2000) gives the + // number of leap years + constexpr const int Epoch = 2000; + constexpr const int DaysRegularYear = 365; + constexpr const int DaysLeapYear = 366; + + if (year == Epoch) { + return 0; + } + + // Get the position of the most recent leap year + const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year); + + // Get the position of the epoch + const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch); + + // The distance between the two iterators gives us the number of leap years + const int nLeapYears = static_cast(std::abs(std::distance(y2000, lb))); + + const int nYears = std::abs(year - Epoch); + const int nRegularYears = nYears - nLeapYears; + + // Get the total number of days as the sum of leap years + non leap years + const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear; + return result; + } + + // Returns the number of leap seconds that lie between the {year, dayOfYear} + // time point and { 2000, 1 } + int countLeapSeconds(int year, int dayOfYear) { + // Find the position of the current year in the vector; its position in the vector + // gives the number of leap seconds + struct LeapSecond { + int year; + int dayOfYear; + bool operator<(const LeapSecond& rhs) const { + return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear); + } + }; + + constexpr const LeapSecond LeapEpoch = { 2000, 1 }; + + // List taken from: https://www.ietf.org/timezones/data/leap-seconds.list + constexpr const std::array LeapSeconds = { + LeapSecond{ 1972, 1 }, + LeapSecond{ 1972, 183 }, + LeapSecond{ 1973, 1 }, + LeapSecond{ 1974, 1 }, + LeapSecond{ 1975, 1 }, + LeapSecond{ 1976, 1 }, + LeapSecond{ 1977, 1 }, + LeapSecond{ 1978, 1 }, + LeapSecond{ 1979, 1 }, + LeapSecond{ 1980, 1 }, + LeapSecond{ 1981, 182 }, + LeapSecond{ 1982, 182 }, + LeapSecond{ 1983, 182 }, + LeapSecond{ 1985, 182 }, + LeapSecond{ 1988, 1 }, + LeapSecond{ 1990, 1 }, + LeapSecond{ 1991, 1 }, + LeapSecond{ 1992, 183 }, + LeapSecond{ 1993, 182 }, + LeapSecond{ 1994, 182 }, + LeapSecond{ 1996, 1 }, + LeapSecond{ 1997, 182 }, + LeapSecond{ 1999, 1 }, + LeapSecond{ 2006, 1 }, + LeapSecond{ 2009, 1 }, + LeapSecond{ 2012, 183 }, + LeapSecond{ 2015, 182 }, + LeapSecond{ 2017, 1 } + }; + // Get the position of the last leap second before the desired date + LeapSecond date{ year, dayOfYear }; + const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date); + + // Get the position of the Epoch + const auto y2000 = std::lower_bound( + LeapSeconds.begin(), + LeapSeconds.end(), + LeapEpoch + ); + + // The distance between the two iterators gives us the number of leap years + const int nLeapSeconds = static_cast(std::abs(std::distance(y2000, it))); + return nLeapSeconds; + } + + int daysIntoGivenYear(int year, int month, int dayOfMonth) { + // month and dayCount are zero-based. + month -= 1; + int dayCount = dayOfMonth - 1; + constexpr int February = 1; + const bool isInLeapYear = + std::find(LeapYears.begin(), LeapYears.end(), year) != LeapYears.end(); + + for (int m = 0; m < month; ++m) { + dayCount += DaysOfMonths[m]; + if (m == February && isInLeapYear) { + dayCount += 1; + } + } + return dayCount; + } + + double calculateSemiMajorAxis(double meanMotion) { + constexpr const double GravitationalConstant = 6.6740831e-11; + constexpr const double MassEarth = 5.9721986e24; + constexpr const double muEarth = GravitationalConstant * MassEarth; + + // Use Kepler's 3rd law to calculate semimajor axis + // a^3 / P^2 = mu / (2pi)^2 + // <=> a = ((mu * P^2) / (2pi^2))^(1/3) + // with a = semimajor axis + // P = period in seconds + // mu = G*M_earth + const double period = + std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; + + constexpr const double pisq = glm::pi() * glm::pi(); + const double semiMajorAxis = pow( + (muEarth * period * period) / (4 * pisq), + 1.0 / 3.0 + ); + + // We need the semi major axis in km instead of m + return semiMajorAxis / 1000.0; + } + + + double epochFromSubstring(const std::string& epoch) { + // The epochString is in the form: + // YYDDD.DDDDDDDD + // With YY being the last two years of the launch epoch, the first DDD the day of + // the year and the remaning a fractional part of the day + + // The main overview of this function: + // 1. Reconstruct the full year from the YY part + // 2. Calculate the number of days since the beginning of the year + // 3. Convert the number of days to a number of seconds + // 4. Get the number of leap seconds since January 1st, 2000 and remove them + // 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not + // midnight + + // According to https://celestrak.com/columns/v04n03/ + // Apparently, US Space Command sees no need to change the two-line element set + // format yet since no artificial earth satellites existed prior to 1957. By their + // reasoning, two-digit years from 57-99 correspond to 1957-1999 and those from + // 00-56 correspond to 2000-2056. We'll see each other again in 2057! + + // 1,2. Get the full year and days + auto [res, year, daysInYear] = scn::scan_tuple(epoch, "{:2}{}"); + if (!res) { + throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch)); + } + year += year > 57 ? 1900 : 2000; + const int daysSince2000 = countDays(year); + + // 3 + using namespace std::chrono; + const int SecondsPerDay = static_cast(seconds(hours(24)).count()); + //Need to subtract 1 from daysInYear since it is not a zero-based count + const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; + + // 4 + // We need to remove additional leap seconds past 2000 and add them prior to + // 2000 to sync up the time zones + const double nLeapSecondsOffset = countLeapSeconds( + year, + static_cast(std::floor(daysInYear)) + ); + + // 5 + const double nSecondsEpochOffset = + static_cast(seconds(hours(12)).count()); + + // Combine all of the values + return nSecondsSince2000 - nLeapSecondsOffset - nSecondsEpochOffset; + } + + double epochFromYMDdSubstring(const std::string& epoch) { + // The epochString is in the form: + // YYYYMMDD.ddddddd + // With YYYY as the year, MM the month (1 - 12), DD the day of month (1-31), + // and dddd the fraction of that day. + + // The main overview of this function: + // 1. Read the year value + // 2. Calculate the number of days since the beginning of the year + // 3. Convert the number of days to a number of seconds + // 4. Get the number of leap seconds since January 1st, 2000 and remove them + // 5. Adjust for the fact the epoch starts on 1st January at 12:00:00, not + // midnight + + // 1, 2 + auto [res, year, monthNum, dayOfMonthNum, fractionOfDay] = + scn::scan_tuple(epoch, "{:4}{:2}{:2}{}"); + if (!res) { + throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch)); + } + const int daysSince2000 = countDays(year); + int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum); + double daysInYear = static_cast(wholeDaysInto) + fractionOfDay; + + // 3 + using namespace std::chrono; + const int SecondsPerDay = static_cast(seconds(hours(24)).count()); + //Need to subtract 1 from daysInYear since it is not a zero-based count + const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; + + // 4 + // We need to remove additional leap seconds past 2000 and add them prior to + // 2000 to sync up the time zones + const double nLeapSecondsOffset = -countLeapSeconds( + year, + static_cast(std::floor(daysInYear)) + ); + + // 5 + const double offset = static_cast(seconds(hours(12)).count()); + + // Combine all of the values + return nSecondsSince2000 + nLeapSecondsOffset - offset; + } + + double epochFromOmmString(const std::string& epoch) { + // The epochString is in the form: + // YYYY-MM-DDThh:mm:ss[.d->d][Z] + // or + // YYYY-DDDThh:mm:ss[.d->d][Z] + + // The main overview of this function: + // 0. Determine which type it is + // 1. Read the year value + // 2. Calculate the number of days since the beginning of the year + // 3. Convert the number of days to a number of seconds + // 4. Get the number of leap seconds since January 1st, 2000 and remove them + // 5. Add the hh:mm:ss component + // 6. Adjust for the fact the epoch starts on 1st January at 12:00:00, not + // midnight + + std::string e = epoch; + if (e.back() == 'Z') { + e.pop_back(); + } + + struct { + int year; + int nDays; + int hours; + int minutes; + double seconds; + } date; + + // 1, 2 + const size_t pos = epoch.find('T'); + if (pos == 10) { + // We have the first form + + int month; + int days; + auto res = scn::scan( + epoch, "{:4}-{:2}-{:2}T{:2}:{:2}:{}", + date.year, month, days, date.hours, date.minutes, date.seconds + ); + if (!res) { + throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch)); + } + date.nDays = daysIntoGivenYear(date.year, month, days); + } + else if (pos == 8) { + // We have the second form + + auto res = scn::scan( + epoch, "{:4}-{:3}T{:2}:{:2}:{}", + date.year, date.nDays, date.hours, date.minutes, date.seconds + ); + if (!res) { + throw ghoul::RuntimeError(fmt::format("Error parsing epoch '{}'", epoch)); + } + } + else { + throw ghoul::RuntimeError(fmt::format("Malformed epoch string '{}'", epoch)); + } + + const int daysSince2000 = countDays(date.year); + + // 3 + using namespace std::chrono; + const int SecondsPerDay = static_cast(seconds(hours(24)).count()); + const double nSecondsSince2000 = (daysSince2000 + date.nDays) * SecondsPerDay; + + // 4 + // We need to remove additional leap seconds past 2000 and add them prior to + // 2000 to sync up the time zones + const double nLeapSecondsOffset = -countLeapSeconds( + date.year, + static_cast(std::floor(date.nDays)) + ); + + // 5 + const long long totalSeconds = + std::chrono::seconds(std::chrono::hours(date.hours)).count() + + std::chrono::seconds(std::chrono::minutes(date.minutes)).count(); + + // 6 + const long long offset = std::chrono::seconds(std::chrono::hours(12)).count(); + + // Combine all of the values + return + nSecondsSince2000 + totalSeconds + nLeapSecondsOffset - offset + date.seconds; + } +} // namespace + +namespace openspace::kepler { + +std::vector readTleFile(std::filesystem::path file) { + ghoul_assert(std::filesystem::is_regular_file(file), "File must exist"); + + std::vector result; + + std::ifstream f; + f.open(file); + + int lineNum = 1; + + std::string header; + while (std::getline(f, header)) { + Parameters p; + + // Header + p.name = header; + + // First line + // Field Columns Content + // 1 01-01 Line number + // 2 03-07 Satellite number + // 3 08-08 Classification (U = Unclassified) + // 4 10-11 International Designator (Last two digits of launch year) + // 5 12-14 International Designator (Launch number of the year) + // 6 15-17 International Designator(piece of the launch) A + // 7 19-20 Epoch Year(last two digits of year) + // 8 21-32 Epoch(day of the year and fractional portion of the day) + // 9 34-43 First Time Derivative of the Mean Motion divided by two + // 10 45-52 Second Time Derivative of Mean Motion divided by six + // 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4 + // 12 63-63 The "Ephemeris type" + // 13 65-68 Element set number.Incremented when a new TLE is generated + // 14 69-69 Checksum (modulo 10) + std::string firstLine; + std::getline(f, firstLine); + if (f.bad() || firstLine[0] != '1') { + throw ghoul::RuntimeError(fmt::format( + "Malformed TLE file '{}' at line {}", file, lineNum + 1 + )); + } + // The id only contains the last two digits of the launch year, so we have to + // patch it to the full year + { + std::string id = firstLine.substr(9, 6); + std::string prefix = [y = id.substr(0, 2)](){ + int year = std::atoi(y.c_str()); + return year >= 57 ? "19" : "20"; + }(); + p.id = fmt::format("{}{}-{}", prefix, id.substr(0, 2), id.substr(3)); + } + p.epoch = epochFromSubstring(firstLine.substr(18, 14)); // should be 13? + + + // Second line + // Field Columns Content + // 1 01-01 Line number + // 2 03-07 Satellite number + // 3 09-16 Inclination (degrees) + // 4 18-25 Right ascension of the ascending node (degrees) + // 5 27-33 Eccentricity (decimal point assumed) + // 6 35-42 Argument of perigee (degrees) + // 7 44-51 Mean Anomaly (degrees) + // 8 53-63 Mean Motion (revolutions per day) + // 9 64-68 Revolution number at epoch (revolutions) + // 10 69-69 Checksum (modulo 10) + std::string secondLine; + std::getline(f, secondLine); + if (f.bad() || secondLine[0] != '2') { + throw ghoul::RuntimeError(fmt::format( + "Malformed TLE file '{}' at line {}", file, lineNum + 1 + )); + } + + std::stringstream stream; + stream.exceptions(std::ios::failbit); + + // Get inclination + stream.str(secondLine.substr(8, 8)); + stream >> p.inclination; + stream.clear(); + + // Get Right ascension of the ascending node + stream.str(secondLine.substr(17, 8)); + stream >> p.ascendingNode; + stream.clear(); + + // Get Eccentricity + stream.str("0." + secondLine.substr(26, 7)); + stream >> p.eccentricity; + stream.clear(); + + // Get argument of periapsis + stream.str(secondLine.substr(34, 8)); + stream >> p.argumentOfPeriapsis; + stream.clear(); + + // Get mean anomaly + stream.str(secondLine.substr(43, 8)); + stream >> p.meanAnomaly; + stream.clear(); + + // Get mean motion + stream.str(secondLine.substr(52, 11)); + float meanMotion; + stream >> meanMotion; + + p.semiMajorAxis = calculateSemiMajorAxis(meanMotion); + p.period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; + + result.push_back(p); + + lineNum = lineNum + 3; + } + + return result; +} + +std::vector readOmmFile(std::filesystem::path file) { + ghoul_assert(std::filesystem::is_regular_file(file), "File must exist"); + + std::vector result; + + std::ifstream f; + f.open(file); + + int lineNum = 1; + std::optional current = std::nullopt; + std::string line; + while (std::getline(f, line)) { + if (line.empty()) { + continue; + } + + // Tokenize the line + std::vector parts = ghoul::tokenizeString(line, '='); + for (std::string& p : parts) { + ghoul::trimWhitespace(p); + } + + if (parts.size() != 2) { + throw ghoul::RuntimeError(fmt::format( + "Malformed line '{}' at {}", line, lineNum + )); + } + + if (parts[0] == "CCSDS_OMM_VERS") { + if (parts[1] != "2.0") { + LWARNINGC( + "OMM", + fmt::format( + "Only version 2.0 is currently supported but found {}. " + "Parsing might fail", + parts[1] + ) + ); + } + + // We start a new value so we need to store the last one... + if (current.has_value()) { + result.push_back(*current); + } + + // ... and start a new one + current = Parameters(); + } + + ghoul_assert(current.has_value(), "No current element"); + + if (parts[0] == "OBJECT_NAME") { + current->name = parts[1]; + } + else if (parts[0] == "OBJECT_ID") { + current->id = parts[1]; + } + else if (parts[0] == "EPOCH") { + current->epoch = epochFromOmmString(parts[1]); + } + else if (parts[0] == "MEAN_MOTION") { + float mm = std::stof(parts[1]); + current->semiMajorAxis = calculateSemiMajorAxis(mm); + current->period = std::chrono::seconds(std::chrono::hours(24)).count() / mm; + } + else if (parts[0] == "SEMI_MAJOR_AXIS") { + + } + else if (parts[0] == "ECCENTRICITY") { + current->eccentricity = std::stof(parts[1]); + } + else if (parts[0] == "INCLINATION") { + current->inclination = std::stof(parts[1]); + } + else if (parts[0] == "RA_OF_ASC_NODE") { + current->ascendingNode = std::stof(parts[1]); + } + else if (parts[0] == "ARG_OF_PERICENTER") { + current->argumentOfPeriapsis = std::stof(parts[1]); + } + else if (parts[0] == "MEAN_ANOMALY") { + current->meanAnomaly = std::stof(parts[1]); + } + } + + if (current.has_value()) { + result.push_back(*current); + } + + return result; +} + +std::vector readSbdbFile(std::filesystem::path file) { + constexpr int NDataFields = 9; + constexpr std::string_view ExpectedHeader = "full_name,epoch_cal,e,a,i,om,w,ma,per"; + + ghoul_assert(std::filesystem::is_regular_file(file), "File must exist"); + + std::ifstream f; + f.open(file); + + std::string line; + std::getline(f, line); + if (line != ExpectedHeader) { + throw ghoul::RuntimeError(fmt::format( + "Expected JPL SBDB file to start with '{}' but found '{}' instead", + ExpectedHeader, line + )); + } + + std::vector result; + while (std::getline(f, line)) { + constexpr double AuToKm = 1.496e8; + + std::vector parts = ghoul::tokenizeString(line, ','); + if (parts.size() != NDataFields) { + throw ghoul::RuntimeError(fmt::format( + "Malformed line {}, expected 8 data fields, got {}", line, parts.size() + )); + } + Parameters p; + + ghoul::trimWhitespace(parts[0]); + p.name = parts[0]; + + p.epoch = epochFromYMDdSubstring(parts[1]); + p.eccentricity = std::stod(parts[2]); + p.semiMajorAxis = std::stod(parts[3]) * AuToKm; + + auto importAngleValue = [](const std::string& angle) { + if (angle.empty()) { + return 0.0; + } + + double output = std::stod(angle); + output = std::fmod(output, 360.0); + if (output < 0.0) { + output += 360.0; + } + return output; + }; + + p.inclination = importAngleValue(parts[4]); + p.ascendingNode = importAngleValue(parts[5]); + p.argumentOfPeriapsis = importAngleValue(parts[6]); + p.meanAnomaly = importAngleValue(parts[7]); + p.period = + std::stod(parts[8]) * std::chrono::seconds(std::chrono::hours(24)).count(); + + result.push_back(std::move(p)); + } + return result; +} + +void saveCache(const std::vector& params, std::filesystem::path file) { + std::ofstream stream(file, std::ofstream::binary); + + stream.write(reinterpret_cast(&CurrentCacheVersion), sizeof(int8_t)); + + uint32_t size = static_cast(params.size()); + stream.write(reinterpret_cast(&size), sizeof(uint32_t)); + for (const Parameters& param : params) { + uint32_t nameLength = static_cast(param.name.size()); + stream.write(reinterpret_cast(&nameLength), sizeof(uint32_t)); + stream.write(param.name.data(), nameLength * sizeof(char)); + + uint32_t idLength = static_cast(param.id.size()); + stream.write(reinterpret_cast(&idLength), sizeof(uint32_t)); + stream.write(param.id.data(), idLength * sizeof(char)); + + stream.write(reinterpret_cast(¶m.inclination), sizeof(double)); + stream.write(reinterpret_cast(¶m.semiMajorAxis), sizeof(double)); + stream.write(reinterpret_cast(¶m.ascendingNode), sizeof(double)); + stream.write(reinterpret_cast(¶m.eccentricity), sizeof(double)); + stream.write( + reinterpret_cast(¶m.argumentOfPeriapsis), + sizeof(double) + ); + stream.write(reinterpret_cast(¶m.meanAnomaly), sizeof(double)); + stream.write(reinterpret_cast(¶m.epoch), sizeof(double)); + stream.write(reinterpret_cast(¶m.period), sizeof(double)); + } +} + +std::optional> loadCache(std::filesystem::path file) { + std::ifstream stream(file, std::ifstream::binary); + + int8_t version = 0; + stream.read(reinterpret_cast(&version), sizeof(int8_t)); + if (version != CurrentCacheVersion) { + LINFO("The format of the cached file has changed"); + return std::nullopt; + } + + uint32_t size = 0; + stream.read(reinterpret_cast(&size), sizeof(uint32_t)); + std::vector res; + res.reserve(size); + for (uint32_t i = 0; i < size; i++) { + Parameters param; + + uint32_t nameLength = 0; + stream.read(reinterpret_cast(&nameLength), sizeof(uint32_t)); + param.name.resize(nameLength); + stream.read(param.name.data(), nameLength * sizeof(char)); + + uint32_t idLength = 0; + stream.read(reinterpret_cast(&idLength), sizeof(uint32_t)); + param.id.resize(idLength); + stream.read(param.id.data(), idLength * sizeof(char)); + + stream.read(reinterpret_cast(¶m.inclination), sizeof(double)); + stream.read(reinterpret_cast(¶m.semiMajorAxis), sizeof(double)); + stream.read(reinterpret_cast(¶m.ascendingNode), sizeof(double)); + stream.read(reinterpret_cast(¶m.eccentricity), sizeof(double)); + stream.read(reinterpret_cast(¶m.argumentOfPeriapsis), sizeof(double)); + stream.read(reinterpret_cast(¶m.meanAnomaly), sizeof(double)); + stream.read(reinterpret_cast(¶m.epoch), sizeof(double)); + stream.read(reinterpret_cast(¶m.period), sizeof(double)); + + res.push_back(std::move(param)); + } + + return res; +} + +std::vector readFile(std::filesystem::path file, Format format) { + std::filesystem::path cachedFile = FileSys.cacheManager()->cachedFilename(file); + if (std::filesystem::is_regular_file(cachedFile)) { + LINFO(fmt::format( + "Cached file {} used for Kepler file {}", cachedFile, file + )); + + std::optional> res = loadCache(cachedFile); + if (res.has_value()) { + return *res; + } + + // If there is no value in the optional, the cached loading failed + } + + std::vector res; + switch (format) { + case Format::TLE: + res = readTleFile(file); + break; + case Format::OMM: + res = readOmmFile(file); + break; + case Format::SBDB: + res = readSbdbFile(file); + break; + default: + throw ghoul::MissingCaseException(); + } + + LINFO(fmt::format("Saving cache {} for Kepler file {}", cachedFile, file)); + saveCache(res, cachedFile); + return res; +} + +} // namespace openspace::kepler diff --git a/modules/space/kepler.h b/modules/space/kepler.h new file mode 100644 index 0000000000..d67dad8566 --- /dev/null +++ b/modules/space/kepler.h @@ -0,0 +1,110 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2022 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_SPACE___KEPLER___H__ +#define __OPENSPACE_MODULE_SPACE___KEPLER___H__ + +#include +#include +#include + +namespace openspace::kepler { + +struct Parameters { + // Some human-readable name for the object represented by this kepler parameter set + std::string name; + + // Some form of unique identifier for the object represented by this data + std::string id; + + double inclination = 0.0; + double semiMajorAxis = 0.0; + double ascendingNode = 0.0; + double eccentricity = 0.0; + double argumentOfPeriapsis = 0.0; + double meanAnomaly = 0.0; + double epoch = 0.0; + double period = 0.0; +}; + +/** + * Reads the object information from the provided \p file and returns them as individual + * values. + * + * \param file The file to the TLE file. This file must be a valid file + * \return Information about all of the contained objects in the \p file + * + * \pre \p file must be a file and must exist + * \throw ghoul::RuntimeError If the provided \p file is not a valid TLE file + */ +std::vector readTleFile(std::filesystem::path file); + +/** + * Reads the object information from the provided \p file and returns them as individual + * values. + * + * \param file The file to the OMM file. This file must be a valid file + * \return Information about all of the contained objects in the \p file + * + * \pre \p file must be a file and must exist + * \throw ghoul::RuntimeError If the provided \p file is not a valid OMM file + */ +std::vector readOmmFile(std::filesystem::path file); + +/** + * Reads the object information from a CSV file following JPL's Small Body Database + * format, which provides the Epoch, eccentricity, semi-major axis (in AU), inclination, + * ascending node, argument of periapsis, mean anomaly, and period in that order. + * + * \param file The CSV file containing the information about the objects + * \return Information about all of the contained objects in the \p file + * + * \pre \p file must be a file and must exist + * \throw ghoul::RuntimeError If the provided \p is not a valid JPL SBDB CSV format + */ +std::vector readSbdbFile(std::filesystem::path file); + +/** + * The different formats that the #readFile function is capable of loading + */ +enum class Format { + TLE, + OMM, + SBDB +}; +/** + * Reads the object information from the provided file. + * + * \param file The file containing the information about the objects + * \param format The format of the provided \p file + * \return Information about all of the contained objects in the \p file + * + * \pre \p file must be a file and must exist + * \throw ghoul::RuntimeError If the provided \p is not in the provided file + */ +std::vector readFile(std::filesystem::path file, Format format); + +} // namespace openspace::kepler + +#endif // __OPENSPACE_MODULE_SPACE___KEPLER___H__ diff --git a/modules/space/rendering/renderableorbitalkepler.cpp b/modules/space/rendering/renderableorbitalkepler.cpp index 5a9a7d7011..0baecf37dd 100644 --- a/modules/space/rendering/renderableorbitalkepler.cpp +++ b/modules/space/rendering/renderableorbitalkepler.cpp @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -42,130 +41,10 @@ #include #include #include +#include #include namespace { - constexpr std::array LeapYears = { - 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, - 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, - 2044, 2048, 2052, 2056 - }; - constexpr std::array DaysOfMonths = { - 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 - }; - - // Find the position of the current year in the vector; its position in - // the vector gives the number of leap seconds - struct LeapSecond { - int year; - int dayOfYear; - bool operator<(const LeapSecond& rhs) const { - return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear); - } - }; - - constexpr LeapSecond LeapEpoch = { 2000, 1 }; - - // List taken from: https://www.ietf.org/timezones/data/leap-seconds.list - constexpr std::array LeapSeconds = { - LeapSecond{ 1972, 1 }, - LeapSecond{ 1972, 183 }, - LeapSecond{ 1973, 1 }, - LeapSecond{ 1974, 1 }, - LeapSecond{ 1975, 1 }, - LeapSecond{ 1976, 1 }, - LeapSecond{ 1977, 1 }, - LeapSecond{ 1978, 1 }, - LeapSecond{ 1979, 1 }, - LeapSecond{ 1980, 1 }, - LeapSecond{ 1981, 182 }, - LeapSecond{ 1982, 182 }, - LeapSecond{ 1983, 182 }, - LeapSecond{ 1985, 182 }, - LeapSecond{ 1988, 1 }, - LeapSecond{ 1990, 1 }, - LeapSecond{ 1991, 1 }, - LeapSecond{ 1992, 183 }, - LeapSecond{ 1993, 182 }, - LeapSecond{ 1994, 182 }, - LeapSecond{ 1996, 1 }, - LeapSecond{ 1997, 182 }, - LeapSecond{ 1999, 1 }, - LeapSecond{ 2006, 1 }, - LeapSecond{ 2009, 1 }, - LeapSecond{ 2012, 183 }, - LeapSecond{ 2015, 182 }, - LeapSecond{ 2017, 1 } - }; - - // Count the number of full days since the beginning of 2000 to the beginning of - // the parameter 'year' - int countDays(int year) { - // Find the position of the current year in the vector, the difference - // between its position and the position of 2000 (for J2000) gives the - // number of leap years - constexpr int Epoch = 2000; - constexpr int DaysRegularYear = 365; - constexpr int DaysLeapYear = 366; - - if (year == Epoch) { - return 0; - } - - // Get the position of the most recent leap year - const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year); - - // Get the position of the epoch - const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch); - - // The distance between the two iterators gives us the number of leap years - const int nLeapYears = static_cast(std::abs(std::distance(y2000, lb))); - - const int nYears = std::abs(year - Epoch); - const int nRegularYears = nYears - nLeapYears; - - // Get the total number of days as the sum of leap years + non leap years - const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear; - return result; - } - - // Returns the number of leap seconds that lie between the {year, dayOfYear} - // time point and { 2000, 1 } - int countLeapSeconds(int year, int dayOfYear) { - // Get the position of the last leap second before the desired date - LeapSecond date{ year, dayOfYear }; - const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date); - - // Get the position of the Epoch - const auto y2000 = std::lower_bound( - LeapSeconds.begin(), - LeapSeconds.end(), - LeapEpoch - ); - - // The distance between the two iterators gives us the number of leap years - const int nLeapSeconds = static_cast(std::abs(std::distance(y2000, it))); - return nLeapSeconds; - } - - int daysIntoGivenYear(int year, int month, int dayOfMonth) { - //month and dayCount are zero-based. - month -= 1; - int dayCount = dayOfMonth - 1; - const int February = 1; - const bool isInLeapYear = - std::find(LeapYears.begin(), LeapYears.end(), year) - != LeapYears.end(); - - for (int m = 0; m < month; ++m) { - dayCount += DaysOfMonths[m]; - if (m == February && isInLeapYear) { - dayCount += 1; - } - } - return dayCount; - } - constexpr openspace::properties::Property::PropertyInfo PathInfo = { "Path", "Path", @@ -213,10 +92,30 @@ namespace { "Contiguous Size of Render Block", "Number of objects to render sequentially from StartRenderIdx" }; + + constexpr openspace::properties::Property::PropertyInfo ContiguousModeInfo = { + "ContiguousMode", + "Contiguous Mode", + "If enabled, then the contiguous set of objects starting from StartRenderIdx " + "of size RenderSize will be rendered. If disabled, then the number of objects " + "defined by UpperLimit will rendered from an evenly dispersed sample of the " + "full length of the data file." + }; struct [[codegen::Dictionary(RenderableOrbitalKepler)]] Parameters { // [[codegen::verbatim(PathInfo.description)]] - std::string path; + std::filesystem::path path; + + enum class [[codegen::map(openspace::kepler::Format)]] Format { + // A NORAD-style Two-Line element + TLE, + // Orbit Mean-Elements Message in the KVN notation + OMM, + // JPL's Small Bodies Database + SBDB + }; + // The file format that is contained in the file + Format format; // [[codegen::verbatim(SegmentQualityInfo.description)]] int segmentQuality; @@ -235,6 +134,9 @@ namespace { // [[codegen::verbatim(RenderSizeInfo.description)]] std::optional renderSize; + + // [[codegen::verbatim(ContiguousModeInfo.description)]] + std::optional contiguousMode; }; #include "renderableorbitalkepler_codegen.cpp" } // namespace @@ -245,140 +147,20 @@ documentation::Documentation RenderableOrbitalKepler::Documentation() { return codegen::doc("space_renderableorbitalkepler"); } -double RenderableOrbitalKepler::calculateSemiMajorAxis(double meanMotion) const { - constexpr double GravitationalConstant = 6.6740831e-11; - constexpr double MassEarth = 5.9721986e24; - constexpr double muEarth = GravitationalConstant * MassEarth; - - // Use Kepler's 3rd law to calculate semimajor axis - // a^3 / P^2 = mu / (2pi)^2 - // <=> a = ((mu * P^2) / (2pi^2))^(1/3) - // with a = semimajor axis - // P = period in seconds - // mu = G*M_earth - const double period = - std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; - - constexpr double pisq = glm::pi() * glm::pi(); - const double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0); - - // We need the semi major axis in km instead of m - return semiMajorAxis / 1000.0; -} - -double RenderableOrbitalKepler::epochFromSubstring(const std::string& epochString) const { - // The epochString is in the form: - // YYDDD.DDDDDDDD - // With YY being the last two years of the launch epoch, the first DDD the day - // of the year and the remaning a fractional part of the day - - // The main overview of this function: - // 1. Reconstruct the full year from the YY part - // 2. Calculate the number of days since the beginning of the year - // 3. Convert the number of days to a number of seconds - // 4. Get the number of leap seconds since January 1st, 2000 and remove them - // 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not - // midnight - - // According to https://celestrak.com/columns/v04n03/ - // Apparently, US Space Command sees no need to change the two-line element - // set format yet since no artificial earth satellites existed prior to 1957. - // By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and - // those from 00-56 correspond to 2000-2056. We'll see each other again in 057! - - // 1. Get the full year - std::string yearPrefix = - std::atoi(epochString.substr(0, 2).c_str()) > 57 ? "19" : "20"; - const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str()); - const int daysSince2000 = countDays(year); - - // 2. - double daysInYear = std::atof(epochString.substr(2).c_str()); - - // 3 - using namespace std::chrono; - const int SecondsPerDay = static_cast(seconds(hours(24)).count()); - //Need to subtract 1 from daysInYear since it is not a zero-based count - const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; - - // 4 - // We need to remove additional leap seconds past 2000 and add them prior to - // 2000 to sync up the time zones - const double nLeapSecondsOffset = -countLeapSeconds( - year, - static_cast(std::floor(daysInYear)) - ); - - // 5 - const double nSecondsEpochOffset = static_cast(seconds(hours(12)).count()); - - // Combine all of the values - const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset; - return epoch; -} - -double RenderableOrbitalKepler::epochFromYMDdSubstring(const std::string& epochString) { - // The epochString is in the form: - // YYYYMMDD.ddddddd - // With YYYY as the year, MM the month (1 - 12), DD the day of month (1-31), - // and dddd the fraction of that day. - - // The main overview of this function: - // 1. Read the year value - // 2. Calculate the number of days since the beginning of the year - // 3. Convert the number of days to a number of seconds - // 4. Get the number of leap seconds since January 1st, 2000 and remove them - // 5. Adjust for the fact the epoch starts on 1st January at 12:00:00, not - // midnight - - // 1 - int year = std::atoi(epochString.substr(0, 4).c_str()); - const int daysSince2000 = countDays(year); - - // 2. - int monthNum = std::atoi(epochString.substr(4, 2).c_str()); - int dayOfMonthNum = std::atoi(epochString.substr(6, 2).c_str()); - int wholeDaysInto = daysIntoGivenYear(year, monthNum, dayOfMonthNum); - double fractionOfDay = std::atof(epochString.substr(9, 7).c_str()); - double daysInYear = static_cast(wholeDaysInto) + fractionOfDay; - - // 3 - using namespace std::chrono; - const int SecondsPerDay = static_cast(seconds(hours(24)).count()); - //Need to subtract 1 from daysInYear since it is not a zero-based count - const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; - - // 4 - // We need to remove additional leap seconds past 2000 and add them prior to - // 2000 to sync up the time zones - const double nLeapSecondsOffset = -countLeapSeconds( - year, - static_cast(std::floor(daysInYear)) - ); - - // 5 - const double nSecondsEpochOffset = static_cast(seconds(hours(12)).count()); - - // Combine all of the values - const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset; - return epoch; -} - RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict) : Renderable(dict) , _segmentQuality(SegmentQualityInfo, 2, 1, 10) , _startRenderIdx(StartRenderIdxInfo, 0, 0, 1) , _sizeRender(RenderSizeInfo, 1, 1, 2) , _path(PathInfo) + , _contiguousMode(ContiguousModeInfo, false) { - _reinitializeTrailBuffers = std::function([this] { initializeGL(); }); - const Parameters p = codegen::bake(dict); addProperty(_opacity); _segmentQuality = static_cast(p.segmentQuality); - _segmentQuality.onChange(_reinitializeTrailBuffers); + _segmentQuality.onChange([this]() { initializeGL(); }); addProperty(_segmentQuality); _appearance.lineColor = p.color; @@ -386,13 +168,37 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict) _appearance.lineWidth = p.lineWidth.value_or(2.f); addPropertySubOwner(_appearance); - _path = p.path; - _path.onChange(_reinitializeTrailBuffers); + _path = p.path.string(); + _path.onChange([this]() { initializeGL(); }); addProperty(_path); + _format = codegen::map(p.format); + _startRenderIdx = p.startRenderIdx.value_or(0); + _startRenderIdx.onChange([this]() { + if (_contiguousMode) { + if ((_numObjects - _startRenderIdx) < _sizeRender) { + _sizeRender = static_cast(_numObjects - _startRenderIdx); + } + _updateDataBuffersAtNextRender = true; + } + }); + addProperty(_startRenderIdx); _sizeRender = p.renderSize.value_or(0u); + _sizeRender.onChange([this]() { + if (_contiguousMode) { + if (_sizeRender > (_numObjects - _startRenderIdx)) { + _startRenderIdx = static_cast(_numObjects - _sizeRender); + } + } + _updateDataBuffersAtNextRender = true; + }); + addProperty(_sizeRender); + + _contiguousMode = p.contiguousMode.value_or(false); + _contiguousMode.onChange([this]() { _updateDataBuffersAtNextRender = true; }); + addProperty(_contiguousMode); } void RenderableOrbitalKepler::initializeGL() { @@ -420,14 +226,6 @@ void RenderableOrbitalKepler::initializeGL() { _uniformCache.opacity = _programObject->uniformLocation("opacity"); updateBuffers(); - - double maxSemiMajorAxis = 0.0; - for (const KeplerParameters& kp : _data) { - if (kp.semiMajorAxis > maxSemiMajorAxis) { - maxSemiMajorAxis = kp.semiMajorAxis; - } - } - setBoundingSphere(maxSemiMajorAxis * 1000); } void RenderableOrbitalKepler::deinitializeGL() { @@ -447,14 +245,16 @@ bool RenderableOrbitalKepler::isReady() const { return _programObject != nullptr; } -void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) { - if (_data.empty()) { - return; - } - +void RenderableOrbitalKepler::update(const UpdateData&) { if (_updateDataBuffersAtNextRender) { _updateDataBuffersAtNextRender = false; - initializeGL(); + updateBuffers(); + } +} + +void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) { + if (_vertexBufferData.empty()) { + return; } _programObject->activate(); @@ -472,9 +272,7 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) { ); // Because we want the property to work similar to the planet trails - const float fade = static_cast( - pow(_appearance.lineFade.maxValue() - _appearance.lineFade, 2.0) - ); + const float fade = pow(_appearance.lineFade.maxValue() - _appearance.lineFade, 2.f); _programObject->setUniform(_uniformCache.projection, data.camera.projectionMatrix()); _programObject->setUniform(_uniformCache.color, _appearance.lineColor); @@ -482,7 +280,7 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) { glLineWidth(_appearance.lineWidth); - const size_t nrOrbits = _data.size(); + const size_t nrOrbits = _segmentSize.size(); gl::GLint vertices = 0; //glDepthMask(false); @@ -499,21 +297,83 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) { } void RenderableOrbitalKepler::updateBuffers() { - readDataFile(_path); + std::vector parameters = kepler::readFile( + _path.value(), + _format + ); + + _numObjects = parameters.size(); + + if (_startRenderIdx < 0 || _startRenderIdx >= _numObjects) { + throw ghoul::RuntimeError(fmt::format( + "Start index {} out of range [0, {}]", _startRenderIdx, _numObjects + )); + } + + long long endElement = _startRenderIdx + _sizeRender - 1; + endElement = (endElement >= _numObjects) ? _numObjects - 1 : endElement; + if (endElement < 0 || endElement >= _numObjects) { + throw ghoul::RuntimeError(fmt::format( + "End index {} out of range [0, {}]", endElement, _numObjects + )); + } + + _startRenderIdx.setMaxValue(static_cast(_numObjects - 1)); + _sizeRender.setMaxValue(static_cast(_numObjects)); + if (_sizeRender == 0u) { + _sizeRender = static_cast(_numObjects); + } + + if (_contiguousMode) { + if (_startRenderIdx >= parameters.size() || + (_startRenderIdx + _sizeRender) >= parameters.size()) + { + throw ghoul::RuntimeError(fmt::format( + "Tried to load {} objects but only {} are available", + _startRenderIdx + _sizeRender, parameters.size() + )); + } + + // Extract subset that starts at _startRenderIdx and contains _sizeRender obejcts + parameters = std::vector( + parameters.begin() + _startRenderIdx, + parameters.begin() + _startRenderIdx + _sizeRender + ); + } + else { + // First shuffle the whole array + std::default_random_engine rng; + std::shuffle(parameters.begin(), parameters.end(), rng); + + // Then take the first _sizeRender values + parameters = std::vector( + parameters.begin(), + parameters.begin() + _sizeRender + ); + } + + _segmentSize.clear(); + for (const kepler::Parameters& p : parameters) { + const double scale = static_cast(_segmentQuality) * 10.0; + _segmentSize.push_back( + static_cast(scale + (scale / pow(1 - p.eccentricity, 1.2))) + ); + } size_t nVerticesTotal = 0; - int numOrbits = static_cast(_data.size()); + int numOrbits = static_cast(parameters.size()); for (int i = 0; i < numOrbits; ++i) { nVerticesTotal += _segmentSize[i] + 1; } _vertexBufferData.resize(nVerticesTotal); size_t vertexBufIdx = 0; + KeplerTranslation keplerTranslator; for (int orbitIdx = 0; orbitIdx < numOrbits; ++orbitIdx) { - const KeplerParameters& orbit = _data[orbitIdx]; + const kepler::Parameters& orbit = parameters[orbitIdx]; - _keplerTranslator.setKeplerElements( + keplerTranslator.setKeplerElements( orbit.eccentricity, orbit.semiMajorAxis, orbit.inclination, @@ -526,9 +386,9 @@ void RenderableOrbitalKepler::updateBuffers() { for (size_t j = 0 ; j < (_segmentSize[orbitIdx] + 1); ++j) { double timeOffset = orbit.period * - static_cast(j)/ static_cast(_segmentSize[orbitIdx]); + static_cast(j) / static_cast(_segmentSize[orbitIdx]); - glm::dvec3 position = _keplerTranslator.position({ + glm::dvec3 position = keplerTranslator.position({ {}, Time(timeOffset + orbit.epoch), Time(0.0) @@ -556,7 +416,7 @@ void RenderableOrbitalKepler::updateBuffers() { ); glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(TrailVBOLayout), nullptr); glEnableVertexAttribArray(1); glVertexAttribPointer( @@ -569,6 +429,14 @@ void RenderableOrbitalKepler::updateBuffers() { ); glBindVertexArray(0); + + double maxSemiMajorAxis = 0.0; + for (const kepler::Parameters& kp : parameters) { + if (kp.semiMajorAxis > maxSemiMajorAxis) { + maxSemiMajorAxis = kp.semiMajorAxis; + } + } + setBoundingSphere(maxSemiMajorAxis * 1000); } } // namespace opensapce diff --git a/modules/space/rendering/renderableorbitalkepler.h b/modules/space/rendering/renderableorbitalkepler.h index 0b37d604c6..b0e97beef7 100644 --- a/modules/space/rendering/renderableorbitalkepler.h +++ b/modules/space/rendering/renderableorbitalkepler.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -47,65 +48,21 @@ public: void deinitializeGL() override; bool isReady() const override; + void update(const UpdateData& data) override; void render(const RenderData& data, RendererTasks& rendererTask) override; - /** - * Reads the provided data file and calls the KeplerTranslation::setKeplerElments - * method with the correct values. If \p filename is a valid data file but contains - * disallowed values (see KeplerTranslation::setKeplerElements), a - * KeplerTranslation::RangeError is thrown. - * - * \param filename The path to the file that contains the data file. - * - * \throw ghoul::RuntimeError if the data file does not exist or there is a - * problem with its format. - * \pre The \p filename must exist - */ - virtual void readDataFile(const std::string& filename) = 0; - -protected: static documentation::Documentation Documentation(); - double calculateSemiMajorAxis(double meanMotion) const; - double epochFromSubstring(const std::string& epochString) const; - double epochFromYMDdSubstring(const std::string& epochString); +private: void updateBuffers(); - std::function _reinitializeTrailBuffers; - std::function _updateStartRenderIdxSelect; - std::function _updateRenderSizeSelect; - - struct KeplerParameters { - double inclination = 0.0; - double semiMajorAxis = 0.0; - double ascendingNode = 0.0; - double eccentricity = 0.0; - double argumentOfPeriapsis = 0.0; - double meanAnomaly = 0.0; - double meanMotion = 0.0; - double epoch = 0.0; - double period = 0.0; - }; - bool _updateDataBuffersAtNextRender = false; - std::streamoff _numObjects; bool _isFileReadinitialized = false; - inline static constexpr double convertAuToKm = 1.496e8; - inline static constexpr double convertDaysToSecs = 86400.0; - std::vector _data; + std::streamoff _numObjects; std::vector _segmentSize; properties::UIntProperty _segmentQuality; properties::UIntProperty _startRenderIdx; properties::UIntProperty _sizeRender; - properties::Property::OnChangeHandle _startRenderIdxCallbackHandle; - properties::Property::OnChangeHandle _sizeRenderCallbackHandle; - -private: - struct Vertex { - glm::vec3 position = glm::vec3(0.f); - glm::vec3 color = glm::vec3(0.f); - glm::vec2 texcoord = glm::vec2(0.f); - }; /// The layout of the VBOs struct TrailVBOLayout { @@ -117,20 +74,17 @@ private: double period = 0.0; }; - KeplerTranslation _keplerTranslator; - - /// The backend storage for the vertex buffer object containing all points for this - /// trail. + /// The backend storage for the vertex buffer object containing all points std::vector _vertexBufferData; GLuint _vertexArray; GLuint _vertexBuffer; - ghoul::opengl::ProgramObject* _programObject; properties::StringProperty _path; + properties::BoolProperty _contiguousMode; + kepler::Format _format; RenderableTrail::Appearance _appearance; - glm::vec3 _position = glm::vec3(0.f); UniformCache(modelView, projection, lineFade, inGameTime, color, opacity, numberOfSegments) _uniformCache; diff --git a/modules/space/rendering/renderablesatellites.cpp b/modules/space/rendering/renderablesatellites.cpp deleted file mode 100644 index bc3636fbc3..0000000000 --- a/modules/space/rendering/renderablesatellites.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2022 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - constexpr std::string_view _loggerCat = "Satellites"; - - constexpr openspace::properties::Property::PropertyInfo SegmentsInfo = { - "Segments", - "Segments", - "The number of segments to use for each orbit ellipse" - }; - - struct [[codegen::Dictionary(RenderableSatellites)]] Parameters { - // [[codegen::verbatim(SegmentsInfo.description)]] - double segments; - }; -#include "renderablesatellites_codegen.cpp" -} - -namespace openspace { - -documentation::Documentation RenderableSatellites::Documentation() { - return codegen::doc( - "space_renderablesatellites", - RenderableOrbitalKepler::Documentation() - ); -} - -RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary) - : RenderableOrbitalKepler(dictionary) -{ - // Commented out right now as its not super clear how it works with inheritance. We'd - // probably want a codegen::check function that only does the checking without - // actually creating a Parameter objects - // codegen::bake(dictionary); - addProperty(_startRenderIdx); - addProperty(_sizeRender); - - _updateStartRenderIdxSelect = [this]() { - if ((_numObjects - _startRenderIdx) < _sizeRender) { - _sizeRender = static_cast(_numObjects - _startRenderIdx); - } - updateBuffers(); - }; - _updateRenderSizeSelect = [this]() { - if (_sizeRender > (_numObjects - _startRenderIdx)) { - _startRenderIdx = static_cast(_numObjects - _sizeRender); - } - updateBuffers(); - }; - _startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect); - _sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect); -} - -void RenderableSatellites::readDataFile(const std::string& filename) { - if (!std::filesystem::is_regular_file(filename)) { - throw ghoul::RuntimeError(fmt::format( - "Satellite TLE file {} does not exist", filename - )); - } - _data.clear(); - _segmentSize.clear(); - - std::ifstream file; - file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - file.open(filename); - - std::streamoff numberOfLines = std::count( - std::istreambuf_iterator(file), - std::istreambuf_iterator(), - '\n' - ); - file.seekg(std::ios_base::beg); // reset iterator to beginning of file - - _numObjects = numberOfLines / nLineEntriesPerSatellite; - - if (!_isFileReadinitialized) { - _isFileReadinitialized = true; - initializeFileReading(); - } - - std::string line = "-"; - std::string name; - long long endElement = _startRenderIdx + _sizeRender - 1; - endElement = (endElement >= _numObjects) ? _numObjects - 1 : endElement; - //Burn lines if not starting at first element - for (unsigned int k = 0; k < _startRenderIdx; ++k) { - skipSingleEntryInFile(file); - } - for (std::streamoff i = _startRenderIdx; i <= endElement; i++) { - //Read title line - std::getline(file, name); - KeplerParameters keplerElements; - - std::getline(file, line); - if (line[0] == '1') { - // First line - // Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 08-08 Classification (U = Unclassified) - // 4 10-11 International Designator (Last two digits of launch year) - // 5 12-14 International Designator (Launch number of the year) - // 6 15-17 International Designator(piece of the launch) A - name += " " + line.substr(2, 15); - if (_startRenderIdx == i && _sizeRender == 1) { - LINFO(fmt::format( - "Set render block to start at object {}", - name - )); - } - // 7 19-20 Epoch Year(last two digits of year) - // 8 21-32 Epoch(day of the year and fractional portion of the day) - // 9 34-43 First Time Derivative of the Mean Motion divided by two - // 10 45-52 Second Time Derivative of Mean Motion divided by six - // 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4 - // 12 63-63 The "Ephemeris type" - // 13 65-68 Element set number.Incremented when a new TLE is generated - // 14 69-69 Checksum (modulo 10) - keplerElements.epoch = epochFromSubstring(line.substr(18, 14)); - } - else { - throw ghoul::RuntimeError(fmt::format( - "File {} entry {} does not have '1' header", filename, i + 1 - )); - } - - std::getline(file, line); - if (line[0] == '2') { - // Second line - // Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 09-16 Inclination (degrees) - // 4 18-25 Right ascension of the ascending node (degrees) - // 5 27-33 Eccentricity (decimal point assumed) - // 6 35-42 Argument of perigee (degrees) - // 7 44-51 Mean Anomaly (degrees) - // 8 53-63 Mean Motion (revolutions per day) - // 9 64-68 Revolution number at epoch (revolutions) - // 10 69-69 Checksum (modulo 10) - - std::stringstream stream; - stream.exceptions(std::ios::failbit); - - // Get inclination - stream.str(line.substr(8, 8)); - stream >> keplerElements.inclination; - stream.clear(); - - // Get Right ascension of the ascending node - stream.str(line.substr(17, 8)); - stream >> keplerElements.ascendingNode; - stream.clear(); - - // Get Eccentricity - stream.str("0." + line.substr(26, 7)); - stream >> keplerElements.eccentricity; - stream.clear(); - - // Get argument of periapsis - stream.str(line.substr(34, 8)); - stream >> keplerElements.argumentOfPeriapsis; - stream.clear(); - - // Get mean anomaly - stream.str(line.substr(43, 8)); - stream >> keplerElements.meanAnomaly; - stream.clear(); - - // Get mean motion - stream.str(line.substr(52, 11)); - stream >> keplerElements.meanMotion; - } - else { - throw ghoul::RuntimeError(fmt::format( - "File {} entry {} does not have '2' header", filename, i + 1 - )); - } - - // Calculate the semi major axis based on the mean motion using kepler's laws - keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion); - - using namespace std::chrono; - double period = seconds(hours(24)).count() / keplerElements.meanMotion; - keplerElements.period = period; - - _data.push_back(keplerElements); - _segmentSize.push_back(_segmentQuality * 16); - } - file.close(); -} - -void RenderableSatellites::initializeFileReading() { - _startRenderIdx.setMaxValue(static_cast(_numObjects - 1)); - _sizeRender.setMaxValue(static_cast(_numObjects)); - if (_sizeRender == 0u) { - _sizeRender = static_cast(_numObjects); - } -} - -void RenderableSatellites::skipSingleEntryInFile(std::ifstream& file) { - std::string line; - for (unsigned int i = 0; i < nLineEntriesPerSatellite; i++) { - std::getline(file, line); - } -} - -} diff --git a/modules/space/rendering/renderablesmallbody.cpp b/modules/space/rendering/renderablesmallbody.cpp deleted file mode 100644 index 98a2a9738d..0000000000 --- a/modules/space/rendering/renderablesmallbody.cpp +++ /dev/null @@ -1,424 +0,0 @@ -/**************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2022 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - constexpr std::string_view _loggerCat = "SmallSolarSystemBody"; - - constexpr openspace::properties::Property::PropertyInfo ContiguousModeInfo = { - "ContiguousMode", - "Contiguous Mode", - "If enabled, then the contiguous set of objects starting from StartRenderIdx " - "of size RenderSize will be rendered. If disabled, then the number of objects " - "defined by UpperLimit will rendered from an evenly dispersed sample of the " - "full length of the data file" - }; - - constexpr openspace::properties::Property::PropertyInfo UpperLimitInfo = { - "UpperLimit", - "Upper Limit", - "Upper limit on the number of objects for this renderable, regardless of " - "how many objects are contained in the data file. Produces an evenly-distributed" - "sample from the data file" - }; - - double importAngleValue(const std::string& angle) { - if (angle.empty()) { - return 0.0; - } - - double output = std::stod(angle); - output = std::fmod(output, 360.0); - if (output < 0.0) { - output += 360.0; - } - return output; - } - - std::string& formatObjectName(std::string& name) { - const std::string trimChars = "\t\n\v\f\r\" "; - name.erase(0, name.find_first_not_of(trimChars)); - name.erase(name.find_last_not_of(trimChars) + 1); - return name; - } - - struct [[codegen::Dictionary(RenderableSmallBody)]] Parameters { - // [[codegen::verbatim(ContiguousModeInfo.description)]] - std::optional contiguousMode; - - // [[codegen::verbatim(UpperLimitInfo.description)]] - std::optional upperLimit; - }; -#include "renderablesmallbody_codegen.cpp" -} // namespace - -namespace openspace { - -documentation::Documentation RenderableSmallBody::Documentation() { - return codegen::doc( - "space_renderablesmallbody", - RenderableOrbitalKepler::Documentation() - ); -} - -RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary) - : RenderableOrbitalKepler(dictionary) - , _contiguousMode(ContiguousModeInfo, false) - , _upperLimit(UpperLimitInfo, 1000, 1, 1000000) -{ - codegen::bake(dictionary); - - addProperty(_startRenderIdx); - addProperty(_sizeRender); - addProperty(_contiguousMode); - addProperty(_upperLimit); - - if (dictionary.hasValue(UpperLimitInfo.identifier)) { - _upperLimit = static_cast( - dictionary.value(UpperLimitInfo.identifier)); - } - else { - _upperLimit = 0u; - } - - if (dictionary.hasValue(ContiguousModeInfo.identifier)) { - _contiguousMode = dictionary.value(ContiguousModeInfo.identifier); - } - else { - _contiguousMode = false; - } - - _updateStartRenderIdxSelect = std::function([this] { - if (_contiguousMode) { - if ((_numObjects - _startRenderIdx) < _sizeRender) { - _sizeRender = static_cast(_numObjects - _startRenderIdx); - } - _updateDataBuffersAtNextRender = true; - } - }); - _updateRenderSizeSelect = std::function([this] { - if (_contiguousMode) { - if (_sizeRender > (_numObjects - _startRenderIdx)) { - _startRenderIdx = static_cast(_numObjects - _sizeRender); - } - _updateDataBuffersAtNextRender = true; - } - }); - _updateRenderUpperLimitSelect = std::function([this] { - if (!_contiguousMode) { - _updateDataBuffersAtNextRender = true; - } - }); - _updateContiguousModeSelect = std::function([this] { - _updateDataBuffersAtNextRender = true; - }); - - _startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect); - _sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect); - _upperLimitCallbackHandle = _upperLimit.onChange(_updateRenderUpperLimitSelect); - _contiguousModeCallbackhandle = - _contiguousMode.onChange(_updateContiguousModeSelect); -} - -void RenderableSmallBody::readDataFile(const std::string& filename) { - if (!std::filesystem::is_regular_file(filename)) { - throw ghoul::RuntimeError(fmt::format( - "JPL SBDB file {} does not exist", filename - )); - } - - std::ifstream file; - file.exceptions(std::ifstream::failbit | std::ifstream::badbit); - file.open(filename); - - std::streamoff numberOfLines = std::count( - std::istreambuf_iterator(file), - std::istreambuf_iterator(), - '\n' - ); - file.seekg(std::ios_base::beg); // reset iterator to beginning of file - _data.clear(); - _sbNames.clear(); - _segmentSize.clear(); - - std::string line; - unsigned int csvLine = 0; - int fieldCount = 0; - const std::string expectedHeaderLine = "full_name,epoch_cal,e,a,i,om,w,ma,per"; - - try { - std::getline(file, line); // get rid of first line (header) - numberOfLines -= 1; - if (_numObjects != numberOfLines) { - _isFileReadinitialized = false; - } - _numObjects = numberOfLines; - - float lineSkipFraction = 1.0; - if (!_isFileReadinitialized) { - _isFileReadinitialized = true; - initializeFileReading(); - } - - unsigned int startElement = 0; - unsigned int endElement; - if (_contiguousMode) { - lineSkipFraction = 1.0; - startElement = _startRenderIdx; - endElement = _startRenderIdx + _sizeRender - 1; - } - else { - lineSkipFraction = static_cast(_upperLimit) - / static_cast(_numObjects); - endElement = static_cast(_numObjects - 1); - } - - if (line.compare(expectedHeaderLine) != 0) { - LERROR(fmt::format( - "File {} does not have the appropriate JPL SBDB header at line 1", - filename - )); - return; - } - - unsigned int sequentialLineErrors = 0; - endElement = - (endElement >= _numObjects) ? - static_cast(_numObjects - 1) : - endElement; - // Burn lines if not starting at first element - for (unsigned int k = 0; k < startElement; ++k) { - skipSingleLineInFile(file); - } - bool firstDataLine = true; - int lastLineCount = -1; - for (csvLine = startElement + 1; - csvLine <= endElement + 1; - csvLine++, sequentialLineErrors++) - { - float currLineFraction = static_cast(csvLine - 1) * lineSkipFraction; - int currLineCount = static_cast(currLineFraction); - if (currLineCount > lastLineCount) { - try { - readOrbitalParamsFromThisLine(firstDataLine, fieldCount, csvLine, - file); - sequentialLineErrors = 0; - } - catch (std::invalid_argument&) { - constexpr std::string_view errMsg = "Unable to convert field {} to " - "double value (invalid_argument exception). Ignoring line {}/{} " - "of {}"; - LINFO(fmt::format( - errMsg, - fieldCount, csvLine + 1, numberOfLines, filename - )); - } - catch (std::out_of_range&) { - constexpr std::string_view errMsg = "Unable to convert field {} to " - "double value (out_of_range exception). Ignoring line {}/{} of " - "{}"; - LINFO(fmt::format( - errMsg, - fieldCount, csvLine + 1, numberOfLines, filename - )); - } - catch (std::ios_base::failure&) { - throw; - } - - if (sequentialLineErrors == 4) { - _data.clear(); - _sbNames.clear(); - LERROR(fmt::format( - "Abandoning data file {} (too many sequential line errors)", - filename - )); - break; - } - } - else { - skipSingleLineInFile(file); - } - lastLineCount = currLineCount; - firstDataLine = false; - } - } - catch (const std::ios_base::failure&) { - LERROR(fmt::format( - "File read exception (ios_base::failure) while trying to read field {} at " - "line {}/{} of {}", - fieldCount, csvLine + 1, numberOfLines, filename - )); - } -} - -void RenderableSmallBody::initializeFileReading() { - _startRenderIdx.setMaxValue(static_cast(_numObjects - 1)); - _sizeRender.setMaxValue(static_cast(_numObjects)); - if (_sizeRender == 0u) { - _sizeRender = static_cast(_numObjects); - } - - _upperLimit.setMaxValue(static_cast(_numObjects)); - if (_upperLimit == 0u) { - _upperLimit = static_cast(_numObjects); - } -} - -void RenderableSmallBody::skipSingleLineInFile(std::ifstream& file) { - std::string line; - std::getline(file, line); -} - -void RenderableSmallBody::readOrbitalParamsFromThisLine(bool firstDataLine, - int& fieldCount, - unsigned int& csvLine, - std::ifstream& file) -{ - const int numDataFields = 8; - std::string name; - std::string field; - KeplerParameters keplerElements; - - //If there was a read/conversion error in the previous line, then read the remainder - // of that line and throw it out first before proceeding with the next line. - if (fieldCount != (numDataFields + 1) && !firstDataLine) { - std::getline(file, field); - } - fieldCount = 0; - - // Object designator string - std::getline(file, name, ','); - if (_startRenderIdx > 0 && _startRenderIdx == (csvLine - 1) && _sizeRender == 1) { - formatObjectName(name); - LINFO(fmt::format("Set render block to start at object {}", name)); - } - fieldCount++; - - // Epoch - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read epoch from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.epoch = epochFromYMDdSubstring(field); - fieldCount++; - - // Eccentricity (unit-less) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read eccentricity from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.eccentricity = std::stod(field); - fieldCount++; - - // Semi-major axis (astronomical units - au) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read semi-major axis from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.semiMajorAxis = std::stod(field); - keplerElements.semiMajorAxis *= convertAuToKm; - fieldCount++; - - // Inclination (degrees) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read inclination from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.inclination = importAngleValue(field); - fieldCount++; - - // Longitude of ascending node (degrees) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read ascending node from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.ascendingNode = importAngleValue(field); - fieldCount++; - - // Argument of Periapsis (degrees) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read arg of periapsis from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.argumentOfPeriapsis = importAngleValue(field); - fieldCount++; - - // Mean Anomaly (degrees) - if (!std::getline(file, field, ',')) { - throw std::invalid_argument( - "Unable to read mean anomaly from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.meanAnomaly = importAngleValue(field); - fieldCount++; - - // Period (days) - if (!std::getline(file, field)) { - throw std::invalid_argument( - "Unable to read period from line" + std::to_string(csvLine + 1) - ); - } - keplerElements.period = std::stod(field); - keplerElements.period *= convertDaysToSecs; - fieldCount++; - - _data.push_back(keplerElements); - _sbNames.push_back(name); - const double scale = static_cast(_segmentQuality) * 10.0; - _segmentSize.push_back( - static_cast(scale + (scale / pow(1 - keplerElements.eccentricity, 1.2))) - ); -} - -} // namespace openspace diff --git a/modules/space/spacemodule.cpp b/modules/space/spacemodule.cpp index 6bf6ec7c20..23ecd700f4 100644 --- a/modules/space/spacemodule.cpp +++ b/modules/space/spacemodule.cpp @@ -27,14 +27,13 @@ #include #include #include +#include #include -#include -#include #include #include #include #include -#include +#include #include #include #include @@ -83,8 +82,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) { fRenderable->registerClass("RenderableFluxNodes"); fRenderable->registerClass("RenderableHabitableZone"); fRenderable->registerClass("RenderableRings"); - fRenderable->registerClass("RenderableSatellites"); - fRenderable->registerClass("RenderableSmallBody"); + fRenderable->registerClass("RenderableOrbitalKepler"); fRenderable->registerClass("RenderableStars"); fRenderable->registerClass("RenderableTravelSpeed"); @@ -94,7 +92,7 @@ void SpaceModule::internalInitialize(const ghoul::Dictionary& dictionary) { fTranslation->registerClass("KeplerTranslation"); fTranslation->registerClass("SpiceTranslation"); - fTranslation->registerClass("TLETranslation"); + fTranslation->registerClass("GPTranslation"); fTranslation->registerClass("HorizonsTranslation"); ghoul::TemplateFactory* fRotation = @@ -120,13 +118,12 @@ std::vector SpaceModule::documentations() const { RenderableFluxNodes::Documentation(), RenderableHabitableZone::Documentation(), RenderableRings::Documentation(), - RenderableSatellites::Documentation(), - RenderableSmallBody::Documentation(), + RenderableOrbitalKepler::Documentation(), RenderableStars::Documentation(), RenderableTravelSpeed::Documentation(), SpiceRotation::Documentation(), SpiceTranslation::Documentation(), - TLETranslation::Documentation() + GPTranslation::Documentation() }; } @@ -135,7 +132,8 @@ scripting::LuaLibrary SpaceModule::luaLibrary() const { "space", { codegen::lua::ConvertFromRaDec, - codegen::lua::ConvertToRaDec + codegen::lua::ConvertToRaDec, + codegen::lua::ReadKeplerFile } }; } diff --git a/modules/space/spacemodule_lua.inl b/modules/space/spacemodule_lua.inl index c83cf8209d..c7999a163d 100644 --- a/modules/space/spacemodule_lua.inl +++ b/modules/space/spacemodule_lua.inl @@ -22,6 +22,8 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include "kepler.h" + namespace { /** @@ -77,6 +79,43 @@ namespace { return { raDecPair.first, raDecPair.second, deg.z }; } +[[codegen::luawrap]] +std::vector readKeplerFile(std::filesystem::path p, std::string type) +{ + openspace::kepler::Format f; + if (type == "TLE") { + f = openspace::kepler::Format::TLE; + } + else if (type == "OMM") { + f = openspace::kepler::Format::OMM; + } + else if (type == "SBDB") { + f = openspace::kepler::Format::SBDB; + } + else { + throw ghoul::lua::LuaError(fmt::format("Unsupported format '{}'", type)); + } + + std::vector params = openspace::kepler::readFile(p, f); + std::vector res; + res.reserve(params.size()); + for (const openspace::kepler::Parameters& param : params) { + ghoul::Dictionary d; + d.setValue("Name", param.name); + d.setValue("ID", param.id); + d.setValue("inclination", param.inclination); + d.setValue("SemiMajorAxis", param.semiMajorAxis); + d.setValue("AscendingNode", param.ascendingNode); + d.setValue("Eccentricity", param.eccentricity); + d.setValue("ArgumentOfPeriapsis", param.argumentOfPeriapsis); + d.setValue("MeanAnomaly", param.meanAnomaly); + d.setValue("Epoch", param.epoch); + d.setValue("Period", param.period); + res.push_back(d); + } + return res; +} + #include "spacemodule_lua_codegen.cpp" } // namespace diff --git a/modules/space/tasks/generatedebrisvolumetask.h b/modules/space/tasks/generatedebrisvolumetask.h index 7ea6926a01..a02d60ce38 100644 --- a/modules/space/tasks/generatedebrisvolumetask.h +++ b/modules/space/tasks/generatedebrisvolumetask.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include @@ -50,8 +50,6 @@ public: std::string _gridType; -protected: - private: std::string _rawVolumeOutputPath; std::string _dictionaryOutputPath; diff --git a/modules/space/rendering/renderablesmallbody.h b/modules/space/translation/gptranslation.cpp similarity index 50% rename from modules/space/rendering/renderablesmallbody.h rename to modules/space/translation/gptranslation.cpp index 00f0b7b47a..2ea8f79d8e 100644 --- a/modules/space/rendering/renderablesmallbody.h +++ b/modules/space/translation/gptranslation.cpp @@ -1,4 +1,4 @@ -/**************************************************************************************** +/***************************************************************************************** * * * OpenSpace * * * @@ -22,50 +22,71 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__ -#define __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__ +#include -#include -#include +#include +#include +#include +#include -#include -#include -#include -#include -#include -#include -#include +namespace { + struct [[codegen::Dictionary(GPTranslation)]] Parameters { + // Specifies the filename of the general pertubation file + std::filesystem::path file; + + enum class [[codegen::map(openspace::kepler::Format)]] Format { + // A NORAD-style Two-Line element + TLE, + // Orbit Mean-Elements Message in the KVN notation + OMM, + // JPL's Small Bodies Database + SBDB + }; + // The file format that is contained in the file + Format format; + + // Specifies the element within the file that should be used in case the file + // provides multiple general pertubation elements. Defaults to 1. + std::optional element [[codegen::greater(0)]]; + }; +#include "gptranslation_codegen.cpp" +} // namespace namespace openspace { -namespace documentation { struct Documentation; } +documentation::Documentation GPTranslation::Documentation() { + return codegen::doc("space_transform_gp"); +} -class RenderableSmallBody : public RenderableOrbitalKepler { -public: - RenderableSmallBody(const ghoul::Dictionary& dictionary); - static documentation::Documentation Documentation(); +GPTranslation::GPTranslation(const ghoul::Dictionary& dictionary) { + const Parameters p = codegen::bake(dictionary); + if (!std::filesystem::is_regular_file(p.file)) { + throw ghoul::RuntimeError("The provided TLE file must exist"); + } -private: - void readOrbitalParamsFromThisLine(bool firstDataLine, int& fieldCount, - unsigned int& csvLine, std::ifstream& file); - virtual void readDataFile(const std::string& filename) override; - void initializeFileReading(); - void skipSingleLineInFile(std::ifstream& file); + int element = p.element.value_or(1); - std::vector _sbNames; - std::function _updateContiguousModeSelect; - std::function _updateRenderUpperLimitSelect; + std::vector parameters = kepler::readFile( + p.file, + codegen::map(p.format) + ); + if (parameters.size() < element) { + throw ghoul::RuntimeError(fmt::format( + "Requested element {} but only {} are available", element, parameters.size() + )); + } - /// The index array that is potentially used in the draw call. If this is empty, no - /// element draw call is used. - std::vector _indexBufferData; - properties::BoolProperty _contiguousMode; - properties::UIntProperty _upperLimit; - properties::Property::OnChangeHandle _contiguousModeCallbackhandle; - properties::Property::OnChangeHandle _upperLimitCallbackHandle; -}; + kepler::Parameters param = parameters[element - 1]; + setKeplerElements( + param.eccentricity, + param.semiMajorAxis, + param.inclination, + param.ascendingNode, + param.argumentOfPeriapsis, + param.meanAnomaly, + param.period, + param.epoch + ); +} } // namespace openspace - -#endif // __OPENSPACE_MODULE_SPACE___RENDERABLESMALLBODY___H__ - diff --git a/modules/space/rendering/renderablesatellites.h b/modules/space/translation/gptranslation.h similarity index 68% rename from modules/space/rendering/renderablesatellites.h rename to modules/space/translation/gptranslation.h index 7dc9b93323..47c37cda60 100644 --- a/modules/space/rendering/renderablesatellites.h +++ b/modules/space/translation/gptranslation.h @@ -22,37 +22,38 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__ -#define __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__ +#ifndef __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__ +#define __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__ -#include -#include - -#include #include -#include -#include -#include -#include -#include namespace openspace { -namespace documentation { struct Documentation; } - -class RenderableSatellites : public RenderableOrbitalKepler { +/** + * A specialization of the KeplerTranslation that utilizes general pertubation file + * formats to extracts the Keplerian elements + */ +class GPTranslation : public KeplerTranslation { public: - RenderableSatellites(const ghoul::Dictionary& dictionary); - virtual void readDataFile(const std::string& filename) override; - static documentation::Documentation Documentation(); - void initializeFileReading(); + /** + * Constructor for the GPTranslation class. The \p dictionary must contain a key for + * the file that contains the general pertubation information as well as the file + * format that is to be used. + * + * \param The ghoul::Dictionary that contains the information for this TLETranslation + */ + explicit GPTranslation(const ghoul::Dictionary& dictionary); -private: - void skipSingleEntryInFile(std::ifstream& file); - const unsigned int nLineEntriesPerSatellite = 3; + /** + * Method returning the openspace::Documentation that describes the ghoul::Dictionary + * that can be passed to the constructor. + * + * \return The openspace::Documentation that describes the ghoul::Dicitonary that can + * be passed to the constructor + */ + static documentation::Documentation Documentation(); }; } // namespace openspace -#endif // __OPENSPACE_MODULE_SPACE___RENDERABLESATELLITES___H__ - +#endif // __OPENSPACE_MODULE_SPACE___GPTRANSLATION___H__ diff --git a/modules/space/translation/keplertranslation.h b/modules/space/translation/keplertranslation.h index 4813319c5b..9f1556c4a9 100644 --- a/modules/space/translation/keplertranslation.h +++ b/modules/space/translation/keplertranslation.h @@ -71,7 +71,7 @@ public: glm::dvec3 position(const UpdateData& data) const override; /** - * Method returning the openspace::Documentation that describes the ghoul::Dictinoary + * Method returning the openspace::Documentation that describes the ghoul::Dictionary * that can be passed to the constructor. * * \return The openspace::Documentation that describes the ghoul::Dicitonary that can diff --git a/modules/space/translation/tletranslation.cpp b/modules/space/translation/tletranslation.cpp deleted file mode 100644 index 4be0386007..0000000000 --- a/modules/space/translation/tletranslation.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2022 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace { - // The list of leap years only goes until 2056 as we need to touch this file then - // again anyway ;) - const std::vector LeapYears = { - 1956, 1960, 1964, 1968, 1972, 1976, 1980, 1984, 1988, 1992, 1996, - 2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028, 2032, 2036, 2040, - 2044, 2048, 2052, 2056 - }; - - // Count the number of full days since the beginning of 2000 to the beginning of - // the parameter 'year' - int countDays(int year) { - // Find the position of the current year in the vector, the difference - // between its position and the position of 2000 (for J2000) gives the - // number of leap years - constexpr int Epoch = 2000; - constexpr int DaysRegularYear = 365; - constexpr int DaysLeapYear = 366; - - if (year == Epoch) { - return 0; - } - - // Get the position of the most recent leap year - const auto lb = std::lower_bound(LeapYears.begin(), LeapYears.end(), year); - - // Get the position of the epoch - const auto y2000 = std::find(LeapYears.begin(), LeapYears.end(), Epoch); - - // The distance between the two iterators gives us the number of leap years - const int nLeapYears = static_cast(std::abs(std::distance(y2000, lb))); - - const int nYears = std::abs(year - Epoch); - const int nRegularYears = nYears - nLeapYears; - - // Get the total number of days as the sum of leap years + non leap years - const int result = nRegularYears * DaysRegularYear + nLeapYears * DaysLeapYear; - return result; - } - - // Returns the number of leap seconds that lie between the {year, dayOfYear} - // time point and { 2000, 1 } - int countLeapSeconds(int year, int dayOfYear) { - // Find the position of the current year in the vector; its position in - // the vector gives the number of leap seconds - struct LeapSecond { - int year; - int dayOfYear; - bool operator<(const LeapSecond& rhs) const { - return std::tie(year, dayOfYear) < std::tie(rhs.year, rhs.dayOfYear); - } - }; - - const LeapSecond Epoch = { 2000, 1 }; - - // List taken from: https://www.ietf.org/timezones/data/leap-seconds.list - static const std::vector LeapSeconds = { - { 1972, 1 }, - { 1972, 183 }, - { 1973, 1 }, - { 1974, 1 }, - { 1975, 1 }, - { 1976, 1 }, - { 1977, 1 }, - { 1978, 1 }, - { 1979, 1 }, - { 1980, 1 }, - { 1981, 182 }, - { 1982, 182 }, - { 1983, 182 }, - { 1985, 182 }, - { 1988, 1 }, - { 1990, 1 }, - { 1991, 1 }, - { 1992, 183 }, - { 1993, 182 }, - { 1994, 182 }, - { 1996, 1 }, - { 1997, 182 }, - { 1999, 1 }, - { 2006, 1 }, - { 2009, 1 }, - { 2012, 183 }, - { 2015, 182 }, - { 2017, 1 } - }; - - // Get the position of the last leap second before the desired date - LeapSecond date { year, dayOfYear }; - const auto it = std::lower_bound(LeapSeconds.begin(), LeapSeconds.end(), date); - - // Get the position of the Epoch - const auto y2000 = std::lower_bound( - LeapSeconds.begin(), - LeapSeconds.end(), - Epoch - ); - - // The distance between the two iterators gives us the number of leap years - const int nLeapSeconds = static_cast(std::abs(std::distance(y2000, it))); - return nLeapSeconds; - } - - double epochFromSubstring(const std::string& epochString) { - // The epochString is in the form: - // YYDDD.DDDDDDDD - // With YY being the last two years of the launch epoch, the first DDD the day - // of the year and the remaning a fractional part of the day - - // The main overview of this function: - // 1. Reconstruct the full year from the YY part - // 2. Calculate the number of days since the beginning of the year - // 3. Convert the number of days to a number of seconds - // 4. Get the number of leap seconds since January 1st, 2000 and remove them - // 5. Adjust for the fact the epoch starts on 1st Januaray at 12:00:00, not - // midnight - - // According to https://celestrak.com/columns/v04n03/ - // Apparently, US Space Command sees no need to change the two-line element - // set format yet since no artificial earth satellites existed prior to 1957. - // By their reasoning, two-digit years from 57-99 correspond to 1957-1999 and - // those from 00-56 correspond to 2000-2056. We'll see each other again in 2057! - - // 1. Get the full year - std::string yearPrefix = [y = epochString.substr(0, 2)](){ - int year = std::atoi(y.c_str()); - return year >= 57 ? "19" : "20"; - }(); - const int year = std::atoi((yearPrefix + epochString.substr(0, 2)).c_str()); - const int daysSince2000 = countDays(year); - - // 2. - double daysInYear = std::atof(epochString.substr(2).c_str()); - - // 3 - using namespace std::chrono; - const int SecondsPerDay = static_cast(seconds(hours(24)).count()); - //Need to subtract 1 from daysInYear since it is not a zero-based count - const double nSecondsSince2000 = (daysSince2000 + daysInYear - 1) * SecondsPerDay; - - // 4 - // We need to remove additionbal leap seconds past 2000 and add them prior to - // 2000 to sync up the time zones - const double nLeapSecondsOffset = -countLeapSeconds( - year, - static_cast(std::floor(daysInYear)) - ); - - // 5 - const double nSecondsEpochOffset = static_cast( - seconds(hours(12)).count() - ); - - // Combine all of the values - const double epoch = nSecondsSince2000 + nLeapSecondsOffset - nSecondsEpochOffset; - return epoch; - } - - double calculateSemiMajorAxis(double meanMotion) { - constexpr double GravitationalConstant = 6.6740831e-11; - constexpr double MassEarth = 5.9721986e24; - constexpr double muEarth = GravitationalConstant * MassEarth; - - // Use Kepler's 3rd law to calculate semimajor axis - // a^3 / P^2 = mu / (2pi)^2 - // <=> a = ((mu * P^2) / (2pi^2))^(1/3) - // with a = semimajor axis - // P = period in seconds - // mu = G*M_earth - double period = std::chrono::seconds(std::chrono::hours(24)).count() / meanMotion; - - constexpr double pisq = glm::pi() * glm::pi(); - double semiMajorAxis = pow((muEarth * period*period) / (4 * pisq), 1.0 / 3.0); - - // We need the semi major axis in km instead of m - return semiMajorAxis / 1000.0; - } - - struct [[codegen::Dictionary(TLETranslation)]] Parameters { - // Specifies the filename of the Two-Line-Element file - std::string file; - - // Specifies the line number within the file where the group of 3 TLE lines begins - // (1-based). Defaults to 1 - std::optional lineNumber [[codegen::greater(0)]]; - }; -#include "tletranslation_codegen.cpp" -} // namespace - -namespace openspace { - -documentation::Documentation TLETranslation::Documentation() { - return codegen::doc("space_transform_tle"); -} - -TLETranslation::TLETranslation(const ghoul::Dictionary& dictionary) { - const Parameters p = codegen::bake(dictionary); - - - int lineNum = p.lineNumber.value_or(1); - readTLEFile(p.file, lineNum); -} - -void TLETranslation::readTLEFile(const std::string& filename, int lineNum) { - ghoul_assert(std::filesystem::is_regular_file(filename), "The filename must exist"); - - std::ifstream file; - file.exceptions(std::ofstream::failbit | std::ofstream::badbit); - file.open(filename); - - // All of the Kepler element information - struct { - double inclination = 0.0; - double semiMajorAxis = 0.0; - double ascendingNode = 0.0; - double eccentricity = 0.0; - double argumentOfPeriapsis = 0.0; - double meanAnomaly = 0.0; - double meanMotion = 0.0; - double epoch = 0.0; - } keplerElements; - - std::string line; - // Loop through and throw out lines until getting to the linNum of interest - for (int i = 1; i < lineNum; ++i) { - std::getline(file, line); - } - std::getline(file, line); // Throw out the TLE title line (1st) - - std::getline(file, line); // Get line 1 of TLE format - if (line[0] == '1') { - // First line - // Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 08-08 Classification (U = Unclassified) - // 4 10-11 International Designator (Last two digits of launch year) - // 5 12-14 International Designator (Launch number of the year) - // 6 15-17 International Designator(piece of the launch) A - // 7 19-20 Epoch Year(last two digits of year) - // 8 21-32 Epoch(day of the year and fractional portion of the day) - // 9 34-43 First Time Derivative of the Mean Motion divided by two - // 10 45-52 Second Time Derivative of Mean Motion divided by six - // 11 54-61 BSTAR drag term(decimal point assumed)[10] - 11606 - 4 - // 12 63-63 The "Ephemeris type" - // 13 65-68 Element set number.Incremented when a new TLE is generated - // 14 69-69 Checksum (modulo 10) - keplerElements.epoch = epochFromSubstring(line.substr(18, 14)); - } - else { - throw ghoul::RuntimeError(fmt::format( - "File {} @ line {} does not have '1' header", filename, lineNum + 1 - )); - } - - std::getline(file, line); // Get line 2 of TLE format - if (line[0] == '2') { - // Second line - // Field Columns Content - // 1 01-01 Line number - // 2 03-07 Satellite number - // 3 09-16 Inclination (degrees) - // 4 18-25 Right ascension of the ascending node (degrees) - // 5 27-33 Eccentricity (decimal point assumed) - // 6 35-42 Argument of perigee (degrees) - // 7 44-51 Mean Anomaly (degrees) - // 8 53-63 Mean Motion (revolutions per day) - // 9 64-68 Revolution number at epoch (revolutions) - // 10 69-69 Checksum (modulo 10) - - std::stringstream stream; - stream.exceptions(std::ios::failbit); - - // Get inclination - stream.str(line.substr(8, 8)); - stream >> keplerElements.inclination; - stream.clear(); - - // Get Right ascension of the ascending node - stream.str(line.substr(17, 8)); - stream >> keplerElements.ascendingNode; - stream.clear(); - - // Get Eccentricity - stream.str("0." + line.substr(26, 7)); - stream >> keplerElements.eccentricity; - stream.clear(); - - // Get argument of periapsis - stream.str(line.substr(34, 8)); - stream >> keplerElements.argumentOfPeriapsis; - stream.clear(); - - // Get mean anomaly - stream.str(line.substr(43, 8)); - stream >> keplerElements.meanAnomaly; - stream.clear(); - - // Get mean motion - stream.str(line.substr(52, 11)); - stream >> keplerElements.meanMotion; - } - else { - throw ghoul::RuntimeError(fmt::format( - "File {} @ line {} does not have '2' header", filename, lineNum + 2 - )); - } - file.close(); - - // Calculate the semi major axis based on the mean motion using kepler's laws - keplerElements.semiMajorAxis = calculateSemiMajorAxis(keplerElements.meanMotion); - - // Converting the mean motion (revolutions per day) to period (seconds per revolution) - using namespace std::chrono; - double period = seconds(hours(24)).count() / keplerElements.meanMotion; - - setKeplerElements( - keplerElements.eccentricity, - keplerElements.semiMajorAxis, - keplerElements.inclination, - keplerElements.ascendingNode, - keplerElements.argumentOfPeriapsis, - keplerElements.meanAnomaly, - period, - keplerElements.epoch - ); -} - -} // namespace openspace diff --git a/modules/space/translation/tletranslation.h b/modules/space/translation/tletranslation.h deleted file mode 100644 index be689a3314..0000000000 --- a/modules/space/translation/tletranslation.h +++ /dev/null @@ -1,83 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2022 * - * * - * Permission is hereby granted, free of charge, to any person obtaining a copy of this * - * software and associated documentation files (the "Software"), to deal in the Software * - * without restriction, including without limitation the rights to use, copy, modify, * - * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * - * permit persons to whom the Software is furnished to do so, subject to the following * - * conditions: * - * * - * The above copyright notice and this permission notice shall be included in all copies * - * or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * - * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - ****************************************************************************************/ - -#ifndef __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__ -#define __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__ - -#include - -namespace openspace { - -/** - * A specialization of the KeplerTranslation that extracts the Keplerian elements from a - * two-line element as described by the US Space Command - * https://celestrak.com/columns/v04n03 - * The ghoul::Dictionary passed to the constructor must contain the pointer to a file that - * will be read. - */ -class TLETranslation : public KeplerTranslation { -public: - struct FileFormatError : public ghoul::RuntimeError { - explicit FileFormatError(std::string offense); - std::string offense; - }; - - /** - * Constructor for the TLETranslation class. The \p dictionary must contain a key for - * the file that contains the TLE information. The ghoul::Dictionary will be tested - * against the openspace::Documentation returned by Documentation. - * \param The ghoul::Dictionary that contains the information for this TLETranslation - (*/ - TLETranslation(const ghoul::Dictionary& dictionary = ghoul::Dictionary()); - - /** - * Method returning the openspace::Documentation that describes the ghoul::Dictinoary - * that can be passed to the constructor. - * \return The openspace::Documentation that describes the ghoul::Dicitonary that can - * be passed to the constructor - */ - static documentation::Documentation Documentation(); - -private: - /** - * Reads the provided TLE file and calles the KeplerTranslation::setKeplerElments - * method with the correct values. If \p filename is a valid TLE file but contains - * disallowed values (see KeplerTranslation::setKeplerElements), a - * KeplerTranslation::RangeError is thrown. - * - * \param filename The path to the file that contains the TLE file. - * \param lineNum The line number in the file where the set of 3 TLE lines starts - * - * \throw std::system_error if the TLE file is malformed (does not contain at least - * two lines that start with \c 1 and \c 2. - * \throw KeplerTranslation::RangeError If the Keplerian elements are outside of - * the valid range supported by Kepler::setKeplerElements - * \pre The \p filename must exist - */ - void readTLEFile(const std::string& filename, int lineNum); -}; - -} // namespace openspace - -#endif // __OPENSPACE_MODULE_SPACE___TLETRANSLATION___H__ diff --git a/src/interaction/sessionrecording.cpp b/src/interaction/sessionrecording.cpp index 0aac845fe1..070d6a60fd 100644 --- a/src/interaction/sessionrecording.cpp +++ b/src/interaction/sessionrecording.cpp @@ -875,14 +875,14 @@ void SessionRecording::saveScriptKeyframeToTimeline(std::string script) { bool SessionRecording::doesStartWithSubstring(const std::string& s, const std::string& matchSubstr) { - return (s.substr(0, matchSubstr.length()).compare(matchSubstr) == 0); + return s.substr(0, matchSubstr.length()) == matchSubstr; } void SessionRecording::saveScriptKeyframeToPropertiesBaseline(std::string script) { - Timestamps times - = generateCurrentTimestamp3(global::windowDelegate->applicationTime()); - size_t indexIntoScriptKeyframesFromMainTimeline - = _keyframesSavePropertiesBaseline_scripts.size(); + Timestamps times = + generateCurrentTimestamp3(global::windowDelegate->applicationTime()); + size_t indexIntoScriptKeyframesFromMainTimeline = + _keyframesSavePropertiesBaseline_scripts.size(); _keyframesSavePropertiesBaseline_scripts.push_back(std::move(script)); addKeyframeToTimeline( _keyframesSavePropertiesBaseline_timeline, @@ -2327,7 +2327,7 @@ std::string SessionRecording::convertFile(std::string filename, int depth) { // correct version of the file to be converted, then call getLegacy() to recurse // to the next level down in the legacy subclasses until we get the right // version, then proceed with conversion from there. - if (fileVersion.compare(fileFormatVersion()) != 0) { + if (fileVersion != fileFormatVersion()) { //conversionInStream.seekg(conversionInStream.beg); newFilename = getLegacyConversionResult(filename, depth + 1); removeTrailingPathSlashes(newFilename);