diff --git a/data/assets/examples/scale/timedependentscale/timedependent.asset b/data/assets/examples/scale/timedependentscale/timedependent.asset new file mode 100644 index 0000000000..95da1ad3a8 --- /dev/null +++ b/data/assets/examples/scale/timedependentscale/timedependent.asset @@ -0,0 +1,29 @@ +-- This asset creates a SceneGraphNode that only displays coordinate axes, which grow at +-- a speed of 1 m/s starting on January 1st, 2000 00:00:00. This means that on +-- that date, the coordinate axes will disappear and, for example, on January 1st, 2000 +-- 12:00:00, the coordinate axes will be 43200 meters long. + +local Node = { + Identifier = "TimeDependentScale_Example", + Transform = { + Scale = { + Type = "TimeDependentScale", + ReferenceDate = "2000 JAN 01 00:00:00" + } + }, + Renderable = { + Type = "RenderableCartesianAxes" + }, + GUI = { + Name = "TimeDependentScale", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/data/assets/examples/scale/timedependentscale/timedependent_speed.asset b/data/assets/examples/scale/timedependentscale/timedependent_speed.asset new file mode 100644 index 0000000000..44fa04a63f --- /dev/null +++ b/data/assets/examples/scale/timedependentscale/timedependent_speed.asset @@ -0,0 +1,30 @@ +-- This asset creates a SceneGraphNode that only displays coordinate axes, which grow at +-- a speed of 12 km/s starting on August 8th, 1969 12:00:00. This means that on +-- that date, the coordinate axes will disappear and, for example, on August 8th, 1969 +-- 23:00:00, the coordinate axes will be 475200 km long. + +local Node = { + Identifier = "TimeDependentScale_Example_Speed", + Transform = { + Scale = { + Type = "TimeDependentScale", + ReferenceDate = "1969 AUG 08 12:00:00", + Speed = 12000 + } + }, + Renderable = { + Type = "RenderableCartesianAxes" + }, + GUI = { + Name = "TimeDependentScale (Speed)", + Path = "/Examples" + } +} + +asset.onInitialize(function() + openspace.addSceneGraphNode(Node) +end) + +asset.onDeinitialize(function() + openspace.removeSceneGraphNode(Node) +end) diff --git a/modules/base/scale/timedependentscale.cpp b/modules/base/scale/timedependentscale.cpp index a4ecf7da99..e70b077fa4 100644 --- a/modules/base/scale/timedependentscale.cpp +++ b/modules/base/scale/timedependentscale.cpp @@ -54,18 +54,27 @@ namespace { constexpr openspace::properties::Property::PropertyInfo ClampToPositiveInfo = { "ClampToPositive", "Clamp to Positive", - "If this value is true, the velocity computation will never result in any " - "negative values. This is useful for instantaneous events that only propagate " - "forwards. The default value is 'true'", + "If this value is true, the velocity computation will be clamped to a positive " + "value if the current simulation time is before the `ReferenceDate`. This is " + "useful for instantaneous events that only propagate forwards in time. The " + "default value is 'true'", openspace::properties::Property::Visibility::AdvancedUser }; + // This Scale type provides the ability to scale an object dynamically as time in the + // simulation passes. The provided `ReferenceDate`, specifies when the total scale + // should be equal to 0 and the scales grows by `Speed` meters for every second in the + // simulation. If `ClampToPositive` is specified as `true`, then the resulting scale + // will always be positive or 0 if the simulation time is before the `ReferenceDate`. + // + // A common use-case for this Scale type would be to represent the Radiosphere, which + // grows at the speed of light. struct [[codegen::Dictionary(TimeDependentScale)]] Parameters { // [[codegen::verbatim(ReferenceDateInfo.description)]] - std::string referenceDate; + std::string referenceDate [[codegen::datetime()]]; // [[codegen::verbatim(SpeedInfo.description)]] - std::optional speed; + std::optional speed [[codegen::greaterequal(0.0)]]; // [[codegen::verbatim(ClampToPositiveInfo.description)]] std::optional clampToPositive; @@ -93,8 +102,7 @@ TimeDependentScale::TimeDependentScale(const ghoul::Dictionary& dictionary) _speed = p.speed.value_or(_speed); addProperty(_speed); - // @TODO (abock, 2021-01-09) The clamp to positive value from the dictionary was never - // actually read. I think this should probably be done here? + _clampToPositive = p.clampToPositive.value_or(_clampToPositive); addProperty(_clampToPositive); } diff --git a/src/documentation/verifier.cpp b/src/documentation/verifier.cpp index ac8911163b..41a0b294dc 100644 --- a/src/documentation/verifier.cpp +++ b/src/documentation/verifier.cpp @@ -316,7 +316,8 @@ TestResult DateTimeVerifier::operator()(const ghoul::Dictionary& dict, } const std::string dateTime = dict.value(key); - const std::string format = "%Y %m %d %H:%M:%S"; // YYYY MM DD hh:mm:ss + const std::string format = "%Y %b %d %H:%M:%S"; // YYYY MMM DD hh:mm:ss + const std::string format2 = "%Y %m %d %H:%M:%S"; // YYYY MM DD hh:mm:ss std::tm t = {}; std::istringstream ss(dateTime); @@ -324,13 +325,22 @@ TestResult DateTimeVerifier::operator()(const ghoul::Dictionary& dict, // first check format (automatically checks if valid time) if (ss.fail()) { - res.success = false; - TestResult::Offense o = { - .offender = key, - .reason = TestResult::Offense::Reason::Verification, - .explanation = "Not a valid format, should be: YYYY MM DD hh:mm:ss" - }; - res.offenses.push_back(std::move(o)); + // The format might be of the type "YYYY MM DD hh:mm:ss" + std::istringstream ss2(dateTime); + ss2 >> std::get_time(&t, format2.c_str()); + + if (ss2.fail()) { + // It fails if it is neither of the two formats + res.success = false; + TestResult::Offense o = { + .offender = key, + .reason = TestResult::Offense::Reason::Verification, + .explanation = + "Not a valid format, should be: " + "YYYY MM DD hh:mm:ss or YYYY MMM DD hh:mm:ss" + }; + res.offenses.push_back(std::move(o)); + } } return res; }