diff --git a/modules/softwareintegration/network/messagehandler.cpp b/modules/softwareintegration/network/messagehandler.cpp index 334a12b441..d249c77045 100644 --- a/modules/softwareintegration/network/messagehandler.cpp +++ b/modules/softwareintegration/network/messagehandler.cpp @@ -609,6 +609,9 @@ void handleDataMessage(const std::vector& message, std::shared_ptr& message, std::shared_ptr #include + +const std::string STRING_NOT_SET = ""; + namespace { constexpr const char* _loggerCat = "PointsCloud"; @@ -77,6 +80,12 @@ namespace { "Point Unit", "The distance unit of the point data." }; + + constexpr openspace::properties::Property::PropertyInfo PositionCoordSystemInfo = { + "PositionCoordSystem", + "Position Coordinate System", + "The coordinate system of the point data." + }; constexpr openspace::properties::Property::PropertyInfo SizeOptionInfo = { "SizeOption", @@ -181,6 +190,9 @@ namespace { // [[codegen::verbatim(PointUnitInfo.description)]] std::optional pointUnit; + // [[codegen::verbatim(PositionCoordSystemInfo.description)]] + std::optional positionCoordSystem; + // [[codegen::verbatim(ColormapMinInfo.description)]] std::optional colormapMin; @@ -246,7 +258,8 @@ RenderablePointsCloud::RenderablePointsCloud(const ghoul::Dictionary& dictionary : Renderable(dictionary) , _color(ColorInfo, glm::vec4(glm::vec3(0.5f), 1.f), glm::vec4(0.f), glm::vec4(1.f), glm::vec4(.01f)) , _size(SizeInfo, 1.f, 0.f, 500.f, .1f) - , _pointUnit(PointUnitInfo, "") + , _pointUnit(PointUnitInfo, STRING_NOT_SET) + , _positionCoordSystem(PositionCoordSystemInfo, STRING_NOT_SET) , _sizeOption(SizeOptionInfo, properties::OptionProperty::DisplayType::Dropdown) , _colormapMin(ColormapMinInfo) , _colormapMax(ColormapMaxInfo) @@ -256,8 +269,8 @@ RenderablePointsCloud::RenderablePointsCloud(const ghoul::Dictionary& dictionary , _linearSizeMax(LinearSizeMinInfo) , _linearSizeMin(LinearSizeMaxInfo) , _linearSizeEnabled(LinearSizeEnabledInfo, false) - , _velocityDistanceUnit(VelocityDistanceUnitInfo, "") - , _velocityTimeUnit(VelocityTimeUnitInfo, "") + , _velocityDistanceUnit(VelocityDistanceUnitInfo, STRING_NOT_SET) + , _velocityTimeUnit(VelocityTimeUnitInfo, STRING_NOT_SET) , _velocityDateRecorded(VelocityDateRecordedInfo, glm::ivec3{ -1 }) , _velocityNanMode(VelocityNanModeInfo) , _name(NameInfo) @@ -299,6 +312,11 @@ RenderablePointsCloud::RenderablePointsCloud(const ghoul::Dictionary& dictionary _pointUnit.onChange([this] { _pointUnitIsDirty = true; }); addProperty(_pointUnit); + _positionCoordSystem = p.positionCoordSystem.value_or(_positionCoordSystem); + _positionCoordSystem.setVisibility(properties::Property::Visibility::Hidden); + _positionCoordSystem.onChange([this] { _positionCoordSystemIsDirty = true; }); + addProperty(_positionCoordSystem); + // =============== Colormap =============== _colormapMin = p.colormapMin.value_or(_colormapMin); _colormapMin.setVisibility(properties::Property::Visibility::Hidden); @@ -626,6 +644,7 @@ bool RenderablePointsCloud::checkDataStorage() { loadPointData(softwareIntegrationModule); updatedDataSlices = true; _pointUnitIsDirty = false; + _positionCoordSystemIsDirty = false; } if (shouldLoadColormap(softwareIntegrationModule)) { @@ -653,8 +672,33 @@ bool RenderablePointsCloud::checkDataStorage() { void RenderablePointsCloud::loadPointData(SoftwareIntegrationModule* softwareIntegrationModule) { // Fetch point data from module's centralized storage - std::vector pointData; - if (!softwareIntegrationModule->fetchData(_identifier.value(), storage::Key::DataPoints, pointData)) { + ghoul::Dictionary additionalInfo; + switch (simp::getCoordSystem(_positionCoordSystem)) { + case simp::CoordSystem::Cartesian: { + additionalInfo.setValue( + "CoordSystem", + simp::getStringFromCoordSystem(simp::CoordSystem::Cartesian) + ); + break; + } + case simp::CoordSystem::ICRS: { + additionalInfo.setValue( + "CoordSystem", + simp::getStringFromCoordSystem(simp::CoordSystem::ICRS) + ); + break; + } + default: { // Unknown + LERROR(fmt::format( + "Could not find any coordinate system '{}'", + _positionCoordSystem + )); + return; + } + } + + std::vector pointData; + if (!softwareIntegrationModule->fetchData(_identifier.value(), storage::Key::DataPoints, pointData, additionalInfo)) { LERROR("There was an issue trying to fetch the point data from the centralized storage."); return; } @@ -938,9 +982,11 @@ bool RenderablePointsCloud::shouldLoadPointData(SoftwareIntegrationModule* softw return ( ( _pointUnitIsDirty + || _positionCoordSystemIsDirty || softwareIntegrationModule->isDataDirty(_identifier.value(), storage::Key::DataPoints) ) - && _pointUnit.value() != "" + && _pointUnit.value() != STRING_NOT_SET + && _positionCoordSystem.value() != STRING_NOT_SET ); } @@ -950,8 +996,8 @@ bool RenderablePointsCloud::shouldLoadVelocityData(SoftwareIntegrationModule* so _velocityUnitsAreDirty || softwareIntegrationModule->isDataDirty(_identifier.value(), storage::Key::VelocityData) ) - && _velocityDistanceUnit.value() != "" - && _velocityTimeUnit.value() != "" + && _velocityDistanceUnit.value() != STRING_NOT_SET + && _velocityTimeUnit.value() != STRING_NOT_SET ); } diff --git a/modules/softwareintegration/rendering/renderablepointscloud.h b/modules/softwareintegration/rendering/renderablepointscloud.h index 12c53317aa..84a286521d 100644 --- a/modules/softwareintegration/rendering/renderablepointscloud.h +++ b/modules/softwareintegration/rendering/renderablepointscloud.h @@ -97,6 +97,7 @@ private: properties::FloatProperty _size; properties::Vec4Property _color; properties::StringProperty _pointUnit; + properties::StringProperty _positionCoordSystem; properties::OptionProperty _sizeOption; properties::BoolProperty _linearSizeEnabled; @@ -120,6 +121,7 @@ private: std::optional _identifier = std::nullopt; bool _pointUnitIsDirty = false; + bool _positionCoordSystemIsDirty = false; bool _hasLoadedColormapAttributeData = false; bool _hasLoadedColormap = false; diff --git a/modules/softwareintegration/simp/simp.cpp b/modules/softwareintegration/simp/simp.cpp index 709386bbe9..2a890a7fa9 100644 --- a/modules/softwareintegration/simp/simp.cpp +++ b/modules/softwareintegration/simp/simp.cpp @@ -49,7 +49,11 @@ const std::unordered_map _dataTypeFromString{ { "pos.x", DataKey::X }, { "pos.y", DataKey::Y }, { "pos.z", DataKey::Z }, + { "pos.ra", DataKey::RA }, + { "pos.dec", DataKey::Dec }, + { "pos.dist", DataKey::Distance }, { "pos.unit", DataKey::PointUnit }, + { "pos.coordsys", DataKey::PositionCoordSystem }, { "vel.u", DataKey::U }, { "vel.v", DataKey::V }, { "vel.w", DataKey::W }, @@ -85,6 +89,11 @@ const std::unordered_map _dataTypeFromString{ { "vis.val", DataKey::Visibility }, }; +const std::unordered_map _coordSystemFromString { + { "Cartesian", CoordSystem::Cartesian }, + { "ICRS", CoordSystem::ICRS }, +}; + const std::unordered_map _colormapNanRenderModeFromString { { "Hide", ColormapNanRenderMode::Hide }, { "FixedColor", ColormapNanRenderMode::FixedColor }, @@ -253,6 +262,29 @@ std::string getStringFromDataKey(const DataKey& key) { return it->first; } +bool hasCoordSystem(const std::string& key) { + return _coordSystemFromString.count(key) > 0; +} + +CoordSystem getCoordSystem(const std::string& key) { + if (hasCoordSystem(key)) { + return _coordSystemFromString.at(key); + } + return CoordSystem::Unknown; +} + +std::string getStringFromCoordSystem(const CoordSystem& key) { + auto it = std::find_if( + _coordSystemFromString.begin(), + _coordSystemFromString.end(), + [key](const std::pair& p) { + return key == p.second; + } + ); + if (it == _coordSystemFromString.end()) return ""; + return it->first; +} + ColormapNanRenderMode getColormapNanRenderMode(const std::string& type) { if (_colormapNanRenderModeFromString.count(type) == 0) return ColormapNanRenderMode::Unknown; return _colormapNanRenderModeFromString.at(type); diff --git a/modules/softwareintegration/simp/simp.h b/modules/softwareintegration/simp/simp.h index b397461cfb..6258130843 100644 --- a/modules/softwareintegration/simp/simp.h +++ b/modules/softwareintegration/simp/simp.h @@ -54,7 +54,11 @@ enum class DataKey : uint16_t { X = 0, Y, Z, + RA, + Dec, + Distance, PointUnit, + PositionCoordSystem, // Velocity U, V, @@ -97,6 +101,12 @@ enum class DataKey : uint16_t { Unknown }; +enum class CoordSystem : uint8_t { + Cartesian = 0, + ICRS, + Unknown +}; + enum class ColormapNanRenderMode { Hide = 0, FixedColor, @@ -135,6 +145,10 @@ DataKey getDataKey(const std::string& type); std::string getStringFromDataKey(const DataKey& type); +CoordSystem getCoordSystem(const std::string& type); + +std::string getStringFromCoordSystem(const CoordSystem& type); + ColormapNanRenderMode getColormapNanRenderMode(const std::string& type); VelocityNanRenderMode getVelocityNanRenderMode(const std::string& type); diff --git a/modules/softwareintegration/softwareintegrationmodule.cpp b/modules/softwareintegration/softwareintegrationmodule.cpp index fa15c754b6..c92c2144a0 100644 --- a/modules/softwareintegration/softwareintegrationmodule.cpp +++ b/modules/softwareintegration/softwareintegrationmodule.cpp @@ -66,9 +66,10 @@ void SoftwareIntegrationModule::storeData( bool SoftwareIntegrationModule::isDataDirty( const SyncableStorage::Identifier& identifier, - const storage::Key key + const storage::Key key, + const ghoul::Dictionary& additionalInfo ) { - return _syncableStorage.isDirty(identifier, key); + return _syncableStorage.isDirty(identifier, key, additionalInfo); } void SoftwareIntegrationModule::setDataLoaded( diff --git a/modules/softwareintegration/softwareintegrationmodule.h b/modules/softwareintegration/softwareintegrationmodule.h index 67dcf1647c..76856cd84b 100644 --- a/modules/softwareintegration/softwareintegrationmodule.h +++ b/modules/softwareintegration/softwareintegrationmodule.h @@ -56,11 +56,13 @@ public: bool fetchData( const SyncableStorage::Identifier& identifier, const storage::Key key, - T& resultingData + T& resultingData, + const ghoul::Dictionary& additionalInfo = {} ); bool isDataDirty( const SyncableStorage::Identifier& identifier, - const storage::Key key + const storage::Key key, + const ghoul::Dictionary& additionalInfo = {} ); void setDataLoaded( const SyncableStorage::Identifier& identifier, diff --git a/modules/softwareintegration/softwareintegrationmodule.inl b/modules/softwareintegration/softwareintegrationmodule.inl index dd827e9dd2..4d1ae267a1 100644 --- a/modules/softwareintegration/softwareintegrationmodule.inl +++ b/modules/softwareintegration/softwareintegrationmodule.inl @@ -28,9 +28,10 @@ template bool SoftwareIntegrationModule::fetchData( const SyncableStorage::Identifier& identifier, const storage::Key key, - T& resultingData + T& resultingData, + const ghoul::Dictionary& additionalInfo ) { - return _syncableStorage.fetch(identifier, key, resultingData); + return _syncableStorage.fetch(identifier, key, resultingData, additionalInfo); } } // namespace openspace diff --git a/modules/softwareintegration/utils/syncablestorage.cpp b/modules/softwareintegration/utils/syncablestorage.cpp index b93093fde2..c4dcfd7f4d 100644 --- a/modules/softwareintegration/utils/syncablestorage.cpp +++ b/modules/softwareintegration/utils/syncablestorage.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -244,6 +245,33 @@ void SyncableStorage::insertAssign(const Identifier& identifier, const simp::Dat } } +// ghoul::Dictionary getDataKeysAdditionalInfo(const storage::Key storageKey) { +// ghoul::Dictionary additionalInfo; +// switch () { +// case simp::CoordSystem::Cartesian: { +// additionalInfo.setValue( +// "CoordSystem", +// simp::getStringFromCoordSystem(simp::CoordSystem::Cartesian) +// ); +// break; +// } +// case simp::CoordSystem::ICRS: { +// additionalInfo.setValue( +// "CoordSystem", +// simp::getStringFromCoordSystem(simp::CoordSystem::ICRS) +// ); +// break; +// } +// default: { // Unknown +// LERROR(fmt::format( +// "Could not find any coordinate system '{}'", +// _positionCoordSystem +// )); +// return; +// } +// } +// } + size_t SyncableStorage::count(const Identifier& identifier) { return _storage.count(identifier); } @@ -255,10 +283,34 @@ size_t SyncableStorage::count(const Identifier& identifier, const simp::DataKey return sceneIt->second.count(key); } -std::vector SyncableStorage::simpDataKeysFromStorageKey(const storage::Key key) { +std::vector SyncableStorage::simpDataKeysFromStorageKey( + const storage::Key key, + const ghoul::Dictionary& additionalInfo +) { switch (key) { case storage::Key::DataPoints: { - return { simp::DataKey::X, simp::DataKey::Y, simp::DataKey::Z }; + if (!additionalInfo.hasKey("CoordSystem")) { + LERROR(fmt::format( + "A coordinate system is needed to load point data from syncable storage." + )); + return {}; + } + + std::string coordSystemString = additionalInfo.value("CoordSystem"); + simp::CoordSystem coordSystem = simp::getCoordSystem(coordSystemString); + switch (coordSystem) { + case simp::CoordSystem::Cartesian: + return { simp::DataKey::X, simp::DataKey::Y, simp::DataKey::Z }; + case simp::CoordSystem::ICRS: + return { simp::DataKey::RA, simp::DataKey::Dec, simp::DataKey::Distance }; + default: { // simp::CoordSystem::Unknown + LERROR(fmt::format( + "Could not find the coordinate system '{}'.", + coordSystemString + )); + return {}; + } + } } case storage::Key::VelocityData:{ return { simp::DataKey::U, simp::DataKey::V, simp::DataKey::W }; @@ -394,6 +446,52 @@ bool SyncableStorage::fetchDimFloatData( return true; } +bool SyncableStorage::fetchPositionData( + const Identifier& identifier, + const storage::Key storageKey, + std::vector& resultingData, + const ghoul::Dictionary& additionalInfo +) { + if (!additionalInfo.hasKey("CoordSystem")) { + LERROR(fmt::format( + "A coordinate system is needed to load point data from syncable storage." + )); + return false; + } + + std::string coordSystemString = additionalInfo.value("CoordSystem"); + simp::CoordSystem coordSystem = simp::getCoordSystem(coordSystemString); + bool success = fetchDimFloatData(identifier, simpDataKeysFromStorageKey(storageKey, additionalInfo), resultingData); + if (!success) return false; + + switch (coordSystem) { + case simp::CoordSystem::Cartesian: + return success; + case simp::CoordSystem::ICRS: { + // Convert (RA, Dec, Distance) => (X, Y, Z) + for (size_t i = 0; i < resultingData.size()/3; i += 3) { + double ra = resultingData[i]; + double dec = resultingData[i + 1]; + double dist = resultingData[i + 2]; + glm::dvec3 pos = icrsToGalacticCartesian(ra, dec, dist); + resultingData[i] = static_cast(pos.x); + resultingData[i + 1] = static_cast(pos.y); + resultingData[i + 2] = static_cast(pos.z); + } + + // TODO: Check for errors + return true; + } + default: { // simp::CoordSystem::Unknown + LERROR(fmt::format( + "Could not find the coordinate system '{}' when trying to fetch data from syncable storage", + coordSystemString + )); + return false; + } + } +} + /* ================================================== */ } // namespace openspace diff --git a/modules/softwareintegration/utils/syncablestorage.h b/modules/softwareintegration/utils/syncablestorage.h index 3e6e08c75e..0cd1aa1ad0 100644 --- a/modules/softwareintegration/utils/syncablestorage.h +++ b/modules/softwareintegration/utils/syncablestorage.h @@ -29,6 +29,8 @@ #include #include +#include + #include #include @@ -81,7 +83,8 @@ public: bool fetch( const Identifier& identifier, const storage::Key storageKey, - T& resultingData + T& resultingData, + const ghoul::Dictionary& additionalInfo ); void setLoaded(const Identifier& identifier, const storage::Key storageKey); bool hasLoaded(const Identifier& identifier, const storage::Key storageKey); @@ -97,14 +100,26 @@ public: private: /* =============== Utility functions ================ */ void insertAssign(const Identifier& identifier, const simp::DataKey key, const Value& value); + size_t count(const Identifier& identifier); size_t count(const Identifier& identifier, const simp::DataKey key); - std::vector simpDataKeysFromStorageKey(const storage::Key key); + + std::vector simpDataKeysFromStorageKey( + const storage::Key key, + const ghoul::Dictionary& additionalInfo = {} + ); bool fetchDimFloatData( const Identifier& identifier, const std::vector dimDataKeys, std::vector& resultingData ); + bool fetchPositionData( + const Identifier& identifier, + // const std::vector dimDataKeys, + const storage::Key key, + std::vector& resultingData, + const ghoul::Dictionary& additionalInfo + ); /* ================================================== */ std::mutex _mutex; diff --git a/modules/softwareintegration/utils/syncablestorage.inl b/modules/softwareintegration/utils/syncablestorage.inl index 73432eb06b..56ed6ad72f 100644 --- a/modules/softwareintegration/utils/syncablestorage.inl +++ b/modules/softwareintegration/utils/syncablestorage.inl @@ -30,7 +30,8 @@ template bool SyncableStorage::fetch( const Identifier& identifier, const storage::Key storageKey, - T& resultingData + T& resultingData, + const ghoul::Dictionary& additionalInfo ) { LDEBUGC("SyncableStorage", fmt::format("Loading data from float data storage: {}-{}", identifier, storage::getStorageKeyString(storageKey))); std::lock_guard guard(_mutex); @@ -42,8 +43,11 @@ bool SyncableStorage::fetch( return false; } + LERRORC("SyncableStorage", fmt::format("stroageKey={}", storage::getStorageKeyString(storageKey))); switch (storageKey) { - case storage::Key::DataPoints: + case storage::Key::DataPoints: { + return fetchPositionData(identifier, storageKey, resultingData, additionalInfo); + } case storage::Key::Colormap: case storage::Key::ColormapAttrData: case storage::Key::LinearSizeAttrData: @@ -55,7 +59,10 @@ bool SyncableStorage::fetch( )); return false; } - + // std::vector simpDataKeys = simpDataKeysFromStorageKey(storageKey, additionalInfo); + // if (simpDataKeys.size() < 1) { + // return false; + // } return fetchDimFloatData(identifier, simpDataKeysFromStorageKey(storageKey), resultingData); } default: {