From 3d3580fa65574193237adfae41f0950c6f1215e4 Mon Sep 17 00:00:00 2001 From: Emma Broman Date: Wed, 29 Jan 2025 16:11:47 +0100 Subject: [PATCH] Polish and docs for `RenderableDistanceLabel` and docs for `RenderableNodeLine` (#3485) * Update add add documentation for `RenderableDistanceLabel` * Move distancelabel to `base` module and remove now empty `vislab` module * Add examples for `RenderableNodeLine` and `RenderableDistanceLabel` * Fix faultily formatted documentation ID for `RenderableNodeLine` * Make `RenderableDistanceLabel` unit use units from distanceconversion file And simplify how the different names for a unit are specified * Use new distanceUnitList() function for other classes that uses the units * Change default unit to correct option according to documentation * Make the text property readonly for `RenderableDistanceLabel` * Add property to specify the precision of the number distance label precision to docs * Add examples with different units and descriptors * Add docs description to `RenderableNodeLine` * Update name in one of the examples * Remove redundant switch cases * Apply suggestions from code review Co-authored-by: Ylva Selling --------- Co-authored-by: Ylva Selling --- .../distancelabel.asset | 27 +++ .../distancelabel_unit.asset | 27 +++ .../distancelabel_unit_customdescriptor.asset | 29 +++ .../renderablenodeline/nodeline.asset | 35 +++ include/openspace/util/distanceconversion.h | 208 ++++++------------ modules/base/CMakeLists.txt | 2 + modules/base/basemodule.cpp | 3 + .../base/dashboard/dashboarditemdistance.cpp | 16 +- .../base/dashboard/dashboarditemvelocity.cpp | 16 +- .../rendering/renderabledistancelabel.cpp | 74 +++++-- .../rendering/renderabledistancelabel.h | 13 +- modules/base/rendering/renderablelabel.h | 4 +- modules/base/rendering/renderablemodel.cpp | 14 +- modules/base/rendering/renderablenodeline.cpp | 9 +- modules/vislab/CMakeLists.txt | 37 ---- modules/vislab/include.cmake | 1 - modules/vislab/vislabmodule.cpp | 51 ----- modules/vislab/vislabmodule.h | 47 ---- 18 files changed, 267 insertions(+), 346 deletions(-) create mode 100644 data/assets/examples/renderable/renderabledistancelabel/distancelabel.asset create mode 100644 data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit.asset create mode 100644 data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit_customdescriptor.asset create mode 100644 data/assets/examples/renderable/renderablenodeline/nodeline.asset rename modules/{vislab => base}/rendering/renderabledistancelabel.cpp (70%) rename modules/{vislab => base}/rendering/renderabledistancelabel.h (85%) delete mode 100644 modules/vislab/CMakeLists.txt delete mode 100644 modules/vislab/include.cmake delete mode 100644 modules/vislab/vislabmodule.cpp delete mode 100644 modules/vislab/vislabmodule.h diff --git a/data/assets/examples/renderable/renderabledistancelabel/distancelabel.asset b/data/assets/examples/renderable/renderabledistancelabel/distancelabel.asset new file mode 100644 index 0000000000..05d0ea6bc2 --- /dev/null +++ b/data/assets/examples/renderable/renderabledistancelabel/distancelabel.asset @@ -0,0 +1,27 @@ +-- Basic +-- This example adds a distance label between two nodes in the scene, based on an existing +-- [RenderableNodeLine](#base_renderable_nodeline). Note that the identifier of the +-- `RenderableNodeLine` is accessed by importing another example asset, which also adds +-- the node line to the scene. + +local nodelineAsset = asset.require("examples/renderable/renderablenodeline/nodeline") + +local Node = { + Identifier = "RenderableDistanceLabel_Example", + Renderable = { + Type = "RenderableDistanceLabel", + NodeLine = nodelineAsset.NodeLine.Identifier + }, + GUI = { + Name = "RenderableDistanceLabel - Basic", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit.asset b/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit.asset new file mode 100644 index 0000000000..57b067cf5b --- /dev/null +++ b/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit.asset @@ -0,0 +1,27 @@ +-- Set Unit +-- Per default, the distance is displayed in meters. This example shows how to specify a +-- specific unit, and how to set the precision of dislayed number. + +local nodelineAsset = asset.require("examples/renderable/renderablenodeline/nodeline") + +local Node = { + Identifier = "RenderableDistanceLabel_Example_Unit", + Renderable = { + Type = "RenderableDistanceLabel", + NodeLine = nodelineAsset.NodeLine.Identifier, + DistanceUnit = "AU", + Precision = 2 + }, + GUI = { + Name = "RenderableDistanceLabel - Unit", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit_customdescriptor.asset b/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit_customdescriptor.asset new file mode 100644 index 0000000000..4b1ba1686a --- /dev/null +++ b/data/assets/examples/renderable/renderabledistancelabel/distancelabel_unit_customdescriptor.asset @@ -0,0 +1,29 @@ +-- Custom Unit Descriptor +-- In addition to setting the unit, it is also possible to specify a custom unit +-- descriptor, i.e. a text that will de displayed for the unit instead of the default one. +-- Here, we write out "Astronomical Units" instead of using the default descriptor for AU. + +local nodelineAsset = asset.require("examples/renderable/renderablenodeline/nodeline") + +local Node = { + Identifier = "RenderableDistanceLabel_Example_CustomDescriptor", + Renderable = { + Type = "RenderableDistanceLabel", + NodeLine = nodelineAsset.NodeLine.Identifier, + DistanceUnit = "AU", + Precision = 2, + CustomUnitDescriptor = "Astronomical Units" + }, + GUI = { + Name = "RenderableDistanceLabel - Custom Unit Descriptor", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/renderable/renderablenodeline/nodeline.asset b/data/assets/examples/renderable/renderablenodeline/nodeline.asset new file mode 100644 index 0000000000..8bc0ead9f2 --- /dev/null +++ b/data/assets/examples/renderable/renderablenodeline/nodeline.asset @@ -0,0 +1,35 @@ +-- Basic +-- This example draws a line between two nodes in the scene, in this case the planets +-- Earth and Mars. +-- +-- Note that this example asset is used in another example, for +-- [RenderableDistanceLabel](#base_renderable_distancelabel). Due to this, we export the +-- `Node` table so we can access and refer to its identifier in the other example, the +-- same way as we do for Earth and Mars in this asset. + +local earth = asset.require("scene/solarsystem/planets/earth/earth") +local mars = asset.require("scene/solarsystem/planets/mars/mars") + +local Node = { + Identifier = "RenderableNodeLine_Example", + Renderable = { + Type = "RenderableNodeLine", + StartNode = earth.Earth.Identifier, + EndNode = mars.Mars.Identifier + }, + GUI = { + Name = "RenderableNodeLine - Basic", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) + +-- Export the Node table so it can be used in another example +asset.export("NodeLine", Node) diff --git a/include/openspace/util/distanceconversion.h b/include/openspace/util/distanceconversion.h index aba17dda6b..a0e51ea805 100644 --- a/include/openspace/util/distanceconversion.h +++ b/include/openspace/util/distanceconversion.h @@ -65,60 +65,11 @@ enum class DistanceUnit { League }; -// Assumption: Unit names are sequential in memory -constexpr std::string_view DistanceUnitNanometer = "Nanometer"; -constexpr std::string_view DistanceUnitMicrometer = "Micrometer"; -constexpr std::string_view DistanceUnitMillimeter = "Millimeter"; -constexpr std::string_view DistanceUnitCentimeter = "Centimeter"; -constexpr std::string_view DistanceUnitDecimeter = "Decimeter"; -constexpr std::string_view DistanceUnitMeter = "Meter"; -constexpr std::string_view DistanceUnitKilometer = "Kilometer"; -constexpr std::string_view DistanceUnitAU = "AU"; -constexpr std::string_view DistanceUnitLighthour = "Lighthour"; -constexpr std::string_view DistanceUnitLightday = "Lightday"; -constexpr std::string_view DistanceUnitLightmonth = "Lightmonth"; -constexpr std::string_view DistanceUnitLightyear = "Lightyear"; -constexpr std::string_view DistanceUnitParsec = "Parsec"; -constexpr std::string_view DistanceUnitKiloparsec = "Kiloparsec"; -constexpr std::string_view DistanceUnitMegaparsec = "Megaparsec"; -constexpr std::string_view DistanceUnitGigaparsec = "Gigaparsec"; -constexpr std::string_view DistanceUnitGigalightyear = "Gigalightyear"; -constexpr std::string_view DistanceUnitThou = "Thou"; -constexpr std::string_view DistanceUnitInch = "Inch"; -constexpr std::string_view DistanceUnitFoot = "Foot"; -constexpr std::string_view DistanceUnitYard = "Yard"; -constexpr std::string_view DistanceUnitChain = "Chain"; -constexpr std::string_view DistanceUnitFurlong = "Furlong"; -constexpr std::string_view DistanceUnitMile = "Mile"; -constexpr std::string_view DistanceUnitLeague = "League"; - - -// Assumption: Unit names are sequential in memory -constexpr std::string_view DistanceUnitNanometers = "Nanometers"; -constexpr std::string_view DistanceUnitMicrometers = "Micrometers"; -constexpr std::string_view DistanceUnitMillimeters = "Millimeters"; -constexpr std::string_view DistanceUnitCentimeters = "Centimeters"; -constexpr std::string_view DistanceUnitDecimeters = "Decimeters"; -constexpr std::string_view DistanceUnitMeters = "Meters"; -constexpr std::string_view DistanceUnitKilometers = "Kilometers"; -constexpr std::string_view DistanceUnitAUs = "AU"; -constexpr std::string_view DistanceUnitLighthours = "Lighthours"; -constexpr std::string_view DistanceUnitLightdays = "Lightdays"; -constexpr std::string_view DistanceUnitLightmonths = "Lightmonths"; -constexpr std::string_view DistanceUnitLightyears = "Lightyears"; -constexpr std::string_view DistanceUnitParsecs = "Parsecs"; -constexpr std::string_view DistanceUnitKiloparsecs = "Kiloparsecs"; -constexpr std::string_view DistanceUnitMegaparsecs = "Megaparsecs"; -constexpr std::string_view DistanceUnitGigaparsecs = "Gigaparsecs"; -constexpr std::string_view DistanceUnitGigalightyears = "Gigalightyears"; -constexpr std::string_view DistanceUnitThous = "Thou"; -constexpr std::string_view DistanceUnitInches = "Inches"; -constexpr std::string_view DistanceUnitFeet = "Feet"; -constexpr std::string_view DistanceUnitYards = "Yards"; -constexpr std::string_view DistanceUnitChains = "Chains"; -constexpr std::string_view DistanceUnitFurlongs = "Furlongs"; -constexpr std::string_view DistanceUnitMiles = "Miles"; -constexpr std::string_view DistanceUnitLeagues = "Leagues"; +struct DistanceUnitName { + std::string_view singular; + std::string_view plural; + std::string_view abbreviation; +}; constexpr std::array(DistanceUnit::League) + 1> DistanceUnits = { @@ -132,114 +83,85 @@ DistanceUnits = { DistanceUnit::Furlong, DistanceUnit::Mile, DistanceUnit::League }; -constexpr std::array(DistanceUnit::League) + 1> -DistanceUnitNamesSingular = { - DistanceUnitNanometer, DistanceUnitMicrometer, DistanceUnitMillimeter, - DistanceUnitCentimeter, DistanceUnitDecimeter, DistanceUnitMeter, - DistanceUnitKilometer, DistanceUnitAU, DistanceUnitLighthour, - DistanceUnitLightday, DistanceUnitLightmonth, DistanceUnitLightyear, - DistanceUnitParsec, DistanceUnitKiloparsec, DistanceUnitMegaparsec, - DistanceUnitGigaparsec, DistanceUnitGigalightyear, DistanceUnitThou, DistanceUnitInch, - DistanceUnitFoot, DistanceUnitYard, DistanceUnitChain, DistanceUnitFurlong, - DistanceUnitMile, DistanceUnitLeague -}; - -constexpr std::array(DistanceUnit::League) + 1> -DistanceUnitNamesPlural = { - DistanceUnitNanometers, DistanceUnitMicrometers, DistanceUnitMillimeters, - DistanceUnitCentimeters, DistanceUnitDecimeters, DistanceUnitMeters, - DistanceUnitKilometers, DistanceUnitAUs, DistanceUnitLighthours, - DistanceUnitLightdays, DistanceUnitLightmonths, DistanceUnitLightyears, - DistanceUnitParsecs, DistanceUnitKiloparsecs, DistanceUnitMegaparsecs, - DistanceUnitGigaparsecs, DistanceUnitGigalightyears, DistanceUnitThous, - DistanceUnitInches, DistanceUnitFeet, DistanceUnitYards, DistanceUnitChains, - DistanceUnitFurlongs, DistanceUnitMile, DistanceUnitLeague -}; +// Note that the syntax here is required when initializing constexpr std::arrays with structs +constexpr std::array(DistanceUnit::League) + 1> +DistanceUnitNames {{ + { "Nanometer", "Nanometers", "nm" }, + { "Micrometer", "Micrometers", "um" }, + { "Millimeter", "Millimeters", "mm" }, + { "Centimeter", "Centimeters", "cm" }, + { "Decimeter", "Decimeters", "dm" }, + { "Meter", "Meters", "m" }, + { "Kilometer", "Kilometers", "km" }, + { "AU", "AU", "au" }, + { "Lighthour", "Lighthours", "lh" }, + { "Lightday", "Lightdays", "ld" }, + { "Lightmonth", "Lightmonths", "lm" }, + { "Lightyear", "Lightyears", "ly" }, + { "Parsec", "Parsecs", "pc" }, + { "Kiloparsec", "Kiloparsecs", "kpc" }, + { "Megaparsec", "Megaparsecs", "Mpc" }, + { "Gigaparsec", "Gigaparsecs", "Gpc" }, + { "Gigalightyear", "Gigalightyears", "Gly" }, + { "Thou", "Thou", "th" }, + { "Inch", "Inches", "in" }, + { "Foot", "Feet", "ft" }, + { "Yard", "Yards", "yd" }, + { "Chain", "Chains", "ch" }, + { "Furlong", "Furlongs", "fur" }, + { "Mile", "Miles", "mi" }, + { "League", "Leagues", "league"} +}}; constexpr bool isValidDistanceUnitName(std::string_view name) { - for (std::string_view val : DistanceUnitNamesSingular) { - if (val == name) { - return true; - } - } - - for (std::string_view val : DistanceUnitNamesPlural) { - if (val == name) { + for (DistanceUnit unit : DistanceUnits) { + const DistanceUnitName unitName = DistanceUnitNames[static_cast(unit)]; + if (name == unitName.singular || name == unitName.plural || + name == unitName.abbreviation) + { return true; } } return false; } -constexpr std::string_view nameForDistanceUnit(DistanceUnit unit, bool pluralForm = false) +constexpr std::string_view nameForDistanceUnit(DistanceUnit unit, bool usePluralForm = false) { - switch (unit) { - case DistanceUnit::Nanometer: - case DistanceUnit::Micrometer: - case DistanceUnit::Millimeter: - case DistanceUnit::Centimeter: - case DistanceUnit::Decimeter: - case DistanceUnit::Meter: - case DistanceUnit::Kilometer: - case DistanceUnit::AU: - case DistanceUnit::Lighthour: - case DistanceUnit::Lightday: - case DistanceUnit::Lightmonth: - case DistanceUnit::Lightyear: - case DistanceUnit::Parsec: - case DistanceUnit::Kiloparsec: - case DistanceUnit::Megaparsec: - case DistanceUnit::Gigaparsec: - case DistanceUnit::Gigalightyear: - case DistanceUnit::Thou: - case DistanceUnit::Inch: - case DistanceUnit::Foot: - case DistanceUnit::Yard: - case DistanceUnit::Chain: - case DistanceUnit::Furlong: - case DistanceUnit::Mile: - case DistanceUnit::League: - if (pluralForm) { - return DistanceUnitNamesPlural[static_cast(unit)]; - } - else { - return DistanceUnitNamesSingular[static_cast(unit)]; - } - default: - throw ghoul::MissingCaseException(); - } + const DistanceUnitName unitName = DistanceUnitNames[static_cast(unit)]; + return usePluralForm ? unitName.plural : unitName.singular; +} + +constexpr std::string_view abbreviationForDistanceUnit(DistanceUnit unit) { + return DistanceUnitNames[static_cast(unit)].abbreviation; } constexpr DistanceUnit distanceUnitFromString(std::string_view unitName) { - int found = -1; int i = 0; - for (std::string_view val : DistanceUnitNamesSingular) { - if (val == unitName) { - found = i; - break; + for (DistanceUnit unit : DistanceUnits) { + const DistanceUnitName name = DistanceUnitNames[static_cast(unit)]; + if (name.singular == unitName || name.plural == unitName || + name.abbreviation == unitName) + { + return static_cast(i); } i++; } - i = 0; - for (std::string_view val : DistanceUnitNamesPlural) { - if (val == unitName) { - found = i; - break; - } - i++; - } - - - if (found != -1) { - return static_cast(found); - } - else { - throw ghoul::MissingCaseException(); - } + throw ghoul::MissingCaseException(); } - +constexpr std::vector distanceUnitList() { + std::vector res(DistanceUnits.size()); + std::transform( + DistanceUnits.begin(), + DistanceUnits.end(), + res.begin(), + [](DistanceUnit unit) { + return std::string(nameForDistanceUnit(unit)); + } + ); + return res; +} std::pair simplifyDistance(double meters, bool forceSingularForm = false); diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index 9f6c3ceeae..61be03a2d6 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -50,6 +50,7 @@ set(HEADER_FILES rendering/pointcloud/sizemappingcomponent.h rendering/renderablecartesianaxes.h rendering/renderabledisc.h + rendering/renderabledistancelabel.h rendering/renderablelabel.h rendering/renderablemodel.h rendering/renderablenodearrow.h @@ -113,6 +114,7 @@ set(SOURCE_FILES rendering/pointcloud/sizemappingcomponent.cpp rendering/renderablecartesianaxes.cpp rendering/renderabledisc.cpp + rendering/renderabledistancelabel.cpp rendering/renderablelabel.cpp rendering/renderablemodel.cpp rendering/renderablenodearrow.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 80f8aeefee..431df77e85 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,7 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) { fRenderable->registerClass("RenderableBoxGrid"); fRenderable->registerClass("RenderableCartesianAxes"); fRenderable->registerClass("RenderableDisc"); + fRenderable->registerClass("RenderableDistanceLabel"); fRenderable->registerClass("RenderableGrid"); fRenderable->registerClass("RenderableLabel"); fRenderable->registerClass("RenderableModel"); @@ -230,6 +232,7 @@ std::vector BaseModule::documentations() const { RenderableBoxGrid::Documentation(), RenderableCartesianAxes::Documentation(), RenderableDisc::Documentation(), + RenderableDistanceLabel::Documentation(), RenderableGrid::Documentation(), RenderableInterpolatedPoints::Documentation(), RenderableLabel::Documentation(), diff --git a/modules/base/dashboard/dashboarditemdistance.cpp b/modules/base/dashboard/dashboarditemdistance.cpp index c67d041e67..6fb3205e37 100644 --- a/modules/base/dashboard/dashboarditemdistance.cpp +++ b/modules/base/dashboard/dashboarditemdistance.cpp @@ -106,19 +106,6 @@ namespace { openspace::properties::Property::Visibility::AdvancedUser }; - std::vector unitList() { - std::vector res(openspace::DistanceUnits.size()); - std::transform( - openspace::DistanceUnits.begin(), - openspace::DistanceUnits.end(), - res.begin(), - [](openspace::DistanceUnit unit) { - return std::string(nameForDistanceUnit(unit)); - } - ); - return res; - } - struct [[codegen::Dictionary(DashboardItemDistance)]] Parameters { enum class [[codegen::map(Type)]] TypeInfo { Node, @@ -143,7 +130,8 @@ namespace { std::optional simplification; // [[codegen::verbatim(RequestedUnitInfo.description)]] - std::optional requestedUnit [[codegen::inlist(unitList())]]; + std::optional requestedUnit + [[codegen::inlist(openspace::distanceUnitList())]]; // [[codegen::verbatim(FormatStringInfo.description)]] std::optional formatString; diff --git a/modules/base/dashboard/dashboarditemvelocity.cpp b/modules/base/dashboard/dashboarditemvelocity.cpp index ac51ea2b6f..f76d2c8076 100644 --- a/modules/base/dashboard/dashboarditemvelocity.cpp +++ b/modules/base/dashboard/dashboarditemvelocity.cpp @@ -57,25 +57,13 @@ namespace { openspace::properties::Property::Visibility::User }; - std::vector unitList() { - std::vector res(openspace::DistanceUnits.size()); - std::transform( - openspace::DistanceUnits.begin(), - openspace::DistanceUnits.end(), - res.begin(), - [](openspace::DistanceUnit unit) { - return std::string(nameForDistanceUnit(unit)); - } - ); - return res; - } - struct [[codegen::Dictionary(DashboardItemVelocity)]] Parameters { // [[codegen::verbatim(SimplificationInfo.description)]] std::optional simplification; // [[codegen::verbatim(RequestedUnitInfo.description)]] - std::optional requestedUnit [[codegen::inlist(unitList())]]; + std::optional requestedUnit + [[codegen::inlist(openspace::distanceUnitList())]]; }; #include "dashboarditemvelocity_codegen.cpp" diff --git a/modules/vislab/rendering/renderabledistancelabel.cpp b/modules/base/rendering/renderabledistancelabel.cpp similarity index 70% rename from modules/vislab/rendering/renderabledistancelabel.cpp rename to modules/base/rendering/renderabledistancelabel.cpp index 9a49becdf1..7de7c4cf41 100644 --- a/modules/vislab/rendering/renderabledistancelabel.cpp +++ b/modules/base/rendering/renderabledistancelabel.cpp @@ -22,7 +22,7 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#include +#include #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -46,12 +47,9 @@ namespace { openspace::properties::Property::Visibility::AdvancedUser }; - // @TODO (2024-04-26, emmbr) The unit and custom unit descriptor are confusing and - // should be reimplemented. Why are we using an int value for the unit?? - constexpr openspace::properties::Property::PropertyInfo DistanceUnitInfo = { "DistanceUnit", - "Distance Unit", + "Display Distance Unit", "The unit in which the distance value should be displayed. Defaults to 'km' if " "not specified.", openspace::properties::Property::Visibility::User @@ -61,19 +59,40 @@ namespace { "CustomUnitDescriptor", "Custom Unit Descriptor", "Property to define a custom unit descriptor to use to describe the distance " - "value. Defaults to the units SI descriptor if not specified.", + "value. Defaults to the selected unit's SI descriptor if not specified.", openspace::properties::Property::Visibility::AdvancedUser }; + constexpr openspace::properties::Property::PropertyInfo PrecisionInfo = { + "Precision", + "Precision", + "The precision in which to to show the distance number, i.e. the number of " + "digits after the decimal point.", + openspace::properties::Property::Visibility::User + }; + + // This `Renderable` creates a label that shows the distance between two nodes, based + // on an existing [RenderableNodeLine](#base_renderable_nodeline). The label + // will be placed halfway between the two scene graph nodes that the line connects. + // + // The unit in which the distance is displayed can be customized, as well as the + // precision of the number. struct [[codegen::Dictionary(RenderableDistanceLabel)]] Parameters { - // [[codegen::verbatim(NodeLineInfo.description)]] + // The identifier of a scene graph node with a + // [RenderableNodeLine](#base_renderable_nodeline) that this label + // should track. The label text will be updating based on the distance from the + // node line's start and end. std::string nodeLine; // [[codegen::verbatim(DistanceUnitInfo.description)]] - std::optional distanceUnit; + std::optional distanceUnit + [[codegen::inlist(openspace::distanceUnitList())]]; // [[codegen::verbatim(CustomUnitDescriptorInfo.description)]] std::optional customUnitDescriptor; + + // [[codegen::verbatim(PrecisionInfo.description)]] + std::optional precision [[codegen::greaterequal(0)]]; }; #include "renderabledistancelabel_codegen.cpp" } // namespace @@ -81,25 +100,42 @@ namespace { namespace openspace { documentation::Documentation RenderableDistanceLabel::Documentation() { - return codegen::doc("vislab_renderable_distance_label"); + return codegen::doc("base_renderable_distancelabel"); } RenderableDistanceLabel::RenderableDistanceLabel(const ghoul::Dictionary& dictionary) : RenderableLabel(dictionary) , _nodelineId(NodeLineInfo) - , _distanceUnit(DistanceUnitInfo, 1, 0, 11) + , _distanceUnit(DistanceUnitInfo, properties::OptionProperty::DisplayType::Dropdown) , _customUnitDescriptor(CustomUnitDescriptorInfo) + , _precision(PrecisionInfo, 0, 0, 10) { const Parameters p = codegen::bake(dictionary); _nodelineId = p.nodeLine; addProperty(_nodelineId); - _distanceUnit = p.distanceUnit.value_or(_distanceUnit); + for (const DistanceUnit u : DistanceUnits) { + _distanceUnit.addOption( + static_cast(u), + std::string(nameForDistanceUnit(u)) + ); + } + _distanceUnit = static_cast(DistanceUnit::Kilometer); + if (p.distanceUnit.has_value()) { + const DistanceUnit unit = distanceUnitFromString(*p.distanceUnit); + _distanceUnit = static_cast(unit); + } addProperty(_distanceUnit); _customUnitDescriptor = p.customUnitDescriptor.value_or(_customUnitDescriptor); addProperty(_customUnitDescriptor); + + _precision = p.precision.value_or(_precision); + addProperty(_precision); + + // The text will be updated automatically, so set the property to readonly + _text.setReadOnly(true); } void RenderableDistanceLabel::update(const UpdateData&) { @@ -120,22 +156,18 @@ void RenderableDistanceLabel::update(const UpdateData&) { return; } - // Get used unit scale - const float scale = unit(_distanceUnit); + const DistanceUnit unit = static_cast(_distanceUnit.value()); // Get unit descriptor text - std::string_view unitDescriptor = toString(_distanceUnit); + std::string_view unitDescriptor = abbreviationForDistanceUnit(unit); if (!_customUnitDescriptor.value().empty()) { unitDescriptor = _customUnitDescriptor; } - // Get distance as string and remove fractional part - std::string distanceText = std::to_string( - std::round(nodeline->distance() / scale) - ); - const int pos = static_cast(distanceText.find('.')); - const std::string subStr = distanceText.substr(pos); - distanceText.erase(pos, subStr.size()); + // Get distance as string + const double convertedDistance = convertMeters(nodeline->distance(), unit); + + std::string distanceText = std::format("{:.{}f}", convertedDistance, _precision.value()); // Create final label text and set it const std::string finalText = std::format("{} {}", distanceText, unitDescriptor); diff --git a/modules/vislab/rendering/renderabledistancelabel.h b/modules/base/rendering/renderabledistancelabel.h similarity index 85% rename from modules/vislab/rendering/renderabledistancelabel.h rename to modules/base/rendering/renderabledistancelabel.h index 7bd48d8fa3..0f785b2da7 100644 --- a/modules/vislab/rendering/renderabledistancelabel.h +++ b/modules/base/rendering/renderabledistancelabel.h @@ -22,11 +22,15 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ -#ifndef __OPENSPACE_MODULE_VISLAB___RENDERABLEDISTANCELABEL___H__ -#define __OPENSPACE_MODULE_VISLAB___RENDERABLEDISTANCELABEL___H__ +#ifndef __OPENSPACE_MODULE_BASE___RENDERABLEDISTANCELABEL___H__ +#define __OPENSPACE_MODULE_BASE___RENDERABLEDISTANCELABEL___H__ #include +#include +#include +#include + namespace openspace { namespace documentation { struct Documentation; } @@ -40,11 +44,12 @@ public: private: properties::StringProperty _nodelineId; - properties::IntProperty _distanceUnit; + properties::OptionProperty _distanceUnit; properties::StringProperty _customUnitDescriptor; + properties::IntProperty _precision; bool _errorThrown = false; }; } // namespace openspace -#endif // __OPENSPACE_MODULE_VISLAB___RENDERABLEDISTANCELABEL___H__ +#endif // __OPENSPACE_MODULE_BASE___RENDERABLEDISTANCELABEL___H__ diff --git a/modules/base/rendering/renderablelabel.h b/modules/base/rendering/renderablelabel.h index 5708dd6198..c6684c8c60 100644 --- a/modules/base/rendering/renderablelabel.h +++ b/modules/base/rendering/renderablelabel.h @@ -73,6 +73,8 @@ public: protected: properties::OptionProperty _blendMode; + properties::StringProperty _text; + float unit(int unit) const; std::string_view toString(int unit) const; @@ -92,8 +94,6 @@ private: properties::FloatProperty _size; properties::IVec2Property _minMaxSize; - properties::StringProperty _text; - properties::BoolProperty _enableFadingEffect; properties::Vec2Property _fadeWidths; properties::Vec2Property _fadeDistances; diff --git a/modules/base/rendering/renderablemodel.cpp b/modules/base/rendering/renderablemodel.cpp index 7541f2b554..a22ddf579c 100644 --- a/modules/base/rendering/renderablemodel.cpp +++ b/modules/base/rendering/renderablemodel.cpp @@ -319,19 +319,11 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary) const std::string stringUnit = std::get(*p.modelScale); // Find matching unit name in list of supported unit names - DistanceUnit distanceUnit; - bool wasFound = false; - for (int i = 0; i < DistanceUnitNamesSingular.size(); ++i) { - if (stringUnit == DistanceUnitNamesSingular[i]) { - wasFound = true; - distanceUnit = DistanceUnits[i]; - } - } - - if (wasFound) { + try { + DistanceUnit distanceUnit = distanceUnitFromString(stringUnit); _modelScale = toMeter(distanceUnit); } - else { + catch (const ghoul::MissingCaseException& e) { std::string message = std::format("The given unit name '{}' does not " "match any currently supported unit names", stringUnit); LERROR(message); diff --git a/modules/base/rendering/renderablenodeline.cpp b/modules/base/rendering/renderablenodeline.cpp index 6d9642dec8..369da08cbc 100644 --- a/modules/base/rendering/renderablenodeline.cpp +++ b/modules/base/rendering/renderablenodeline.cpp @@ -114,6 +114,13 @@ namespace { return diffPos; } + // This `Renderable` connects two scene graph nodes by drawing a line between them. + // The line will update dynamically if the position of the nodes change. + // + // One use case for the `RenderableNodeLine` is to visualize the distance between two + // objects. For this, a [RenderableDistanceLabel](#base_renderable_distancelabel) can + // also be added to show the distance as a number. That renderable is designed to show + // the distance between the start and end node for a given `RenderableNodeLine`. struct [[codegen::Dictionary(RenderableNodeLine)]] Parameters { // [[codegen::verbatim(StartNodeInfo.description)]] std::optional startNode [[codegen::identifier()]]; @@ -142,7 +149,7 @@ namespace { namespace openspace { documentation::Documentation RenderableNodeLine::Documentation() { - return codegen::doc("base_renderable_renderablenodeline"); + return codegen::doc("base_renderable_nodeline"); } RenderableNodeLine::RenderableNodeLine(const ghoul::Dictionary& dictionary) diff --git a/modules/vislab/CMakeLists.txt b/modules/vislab/CMakeLists.txt deleted file mode 100644 index adf95601e7..0000000000 --- a/modules/vislab/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -########################################################################################## -# # -# OpenSpace # -# # -# Copyright (c) 2014-2025 # -# # -# 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(${PROJECT_SOURCE_DIR}/support/cmake/module_definition.cmake) - -set(HEADER_FILES - rendering/renderabledistancelabel.h -) -source_group("Header Files" FILES ${HEADER_FILES}) - -set(SOURCE_FILES - rendering/renderabledistancelabel.cpp -) -source_group("Source Files" FILES ${SOURCE_FILES}) - -create_new_module("VisLab" vislab_module ${HEADER_FILES} ${SOURCE_FILES}) diff --git a/modules/vislab/include.cmake b/modules/vislab/include.cmake deleted file mode 100644 index ffea0ac430..0000000000 --- a/modules/vislab/include.cmake +++ /dev/null @@ -1 +0,0 @@ -set(DEFAULT_MODULE ON) diff --git a/modules/vislab/vislabmodule.cpp b/modules/vislab/vislabmodule.cpp deleted file mode 100644 index d1f6a1b43c..0000000000 --- a/modules/vislab/vislabmodule.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2025 * - * * - * 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 - -namespace openspace { - -VisLabModule::VisLabModule() : OpenSpaceModule(Name) {} - -void VisLabModule::internalInitialize(const ghoul::Dictionary&) { - ghoul::TemplateFactory* renderableFactory = - FactoryManager::ref().factory(); - ghoul_assert(renderableFactory, "No renderable factory existed"); - - renderableFactory->registerClass("RenderableDistanceLabel"); -} - -std::vectorVisLabModule::documentations() const { - return { - RenderableDistanceLabel::Documentation() - }; -} - -} // namespace openspace diff --git a/modules/vislab/vislabmodule.h b/modules/vislab/vislabmodule.h deleted file mode 100644 index 48829ca8cc..0000000000 --- a/modules/vislab/vislabmodule.h +++ /dev/null @@ -1,47 +0,0 @@ -/***************************************************************************************** - * * - * OpenSpace * - * * - * Copyright (c) 2014-2025 * - * * - * 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_VISLAB___VISLABMODULE___H__ -#define __OPENSPACE_MODULE_VISLAB___VISLABMODULE___H__ - -#include - -namespace openspace { - -class VisLabModule : public OpenSpaceModule { -public: - constexpr static const char* Name = "VisLab"; - - VisLabModule(); - - std::vector documentations() const override; - - -private: - void internalInitialize(const ghoul::Dictionary&) override; -}; - -} // namespace openspace - -#endif // __OPENSPACE_MODULE_VISLAB___VISLABMODULE___H__