mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 13:20:06 +00:00 
			
		
		
		
	Merge pull request #61 from dpaulat/feature/timeline-part-2
Timeline Animation Continued
This commit is contained in:
		
						commit
						31319076c1
					
				
					 12 changed files with 206 additions and 126 deletions
				
			
		|  | @ -672,6 +672,10 @@ void MainWindowImpl::ConnectAnimationSignals() | ||||||
|            &ui::AnimationDockWidget::LoopSpeedChanged, |            &ui::AnimationDockWidget::LoopSpeedChanged, | ||||||
|            timelineManager_.get(), |            timelineManager_.get(), | ||||||
|            &manager::TimelineManager::SetLoopSpeed); |            &manager::TimelineManager::SetLoopSpeed); | ||||||
|  |    connect(animationDockWidget_, | ||||||
|  |            &ui::AnimationDockWidget::LoopDelayChanged, | ||||||
|  |            timelineManager_.get(), | ||||||
|  |            &manager::TimelineManager::SetLoopDelay); | ||||||
|    connect(animationDockWidget_, |    connect(animationDockWidget_, | ||||||
|            &ui::AnimationDockWidget::AnimationStepBeginSelected, |            &ui::AnimationDockWidget::AnimationStepBeginSelected, | ||||||
|            timelineManager_.get(), |            timelineManager_.get(), | ||||||
|  |  | ||||||
|  | @ -210,7 +210,8 @@ public: | ||||||
|    static void |    static void | ||||||
|    LoadNexradFile(CreateNexradFileFunction                    load, |    LoadNexradFile(CreateNexradFileFunction                    load, | ||||||
|                   std::shared_ptr<request::NexradFileRequest> request, |                   std::shared_ptr<request::NexradFileRequest> request, | ||||||
|                   std::mutex&                                 mutex); |                   std::mutex&                                 mutex, | ||||||
|  |                   std::chrono::system_clock::time_point       time = {}); | ||||||
| 
 | 
 | ||||||
|    const std::string radarId_; |    const std::string radarId_; | ||||||
|    bool              initialized_; |    bool              initialized_; | ||||||
|  | @ -801,7 +802,8 @@ void RadarProductManagerImpl::LoadProviderData( | ||||||
|          return nexradFile; |          return nexradFile; | ||||||
|       }, |       }, | ||||||
|       request, |       request, | ||||||
|       loadDataMutex); |       loadDataMutex, | ||||||
|  |       time); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RadarProductManager::LoadLevel2Data( | void RadarProductManager::LoadLevel2Data( | ||||||
|  | @ -912,7 +914,8 @@ void RadarProductManager::LoadFile( | ||||||
| void RadarProductManagerImpl::LoadNexradFile( | void RadarProductManagerImpl::LoadNexradFile( | ||||||
|    CreateNexradFileFunction                    load, |    CreateNexradFileFunction                    load, | ||||||
|    std::shared_ptr<request::NexradFileRequest> request, |    std::shared_ptr<request::NexradFileRequest> request, | ||||||
|    std::mutex&                                 mutex) |    std::mutex&                                 mutex, | ||||||
|  |    std::chrono::system_clock::time_point       time) | ||||||
| { | { | ||||||
|    scwx::util::async( |    scwx::util::async( | ||||||
|       [=, &mutex]() |       [=, &mutex]() | ||||||
|  | @ -929,6 +932,15 @@ void RadarProductManagerImpl::LoadNexradFile( | ||||||
|          { |          { | ||||||
|             record = types::RadarProductRecord::Create(nexradFile); |             record = types::RadarProductRecord::Create(nexradFile); | ||||||
| 
 | 
 | ||||||
|  |             // If the time is already determined, override the time in the file.
 | ||||||
|  |             // Sometimes, level 2 data has been seen to be a few seconds off
 | ||||||
|  |             // between filename and file data. Overriding this can help prevent
 | ||||||
|  |             // issues with locating and storing the correct records.
 | ||||||
|  |             if (time != std::chrono::system_clock::time_point {}) | ||||||
|  |             { | ||||||
|  |                record->set_time(time); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             std::shared_ptr<RadarProductManager> manager = |             std::shared_ptr<RadarProductManager> manager = | ||||||
|                RadarProductManager::Instance(record->radar_id()); |                RadarProductManager::Instance(record->radar_id()); | ||||||
| 
 | 
 | ||||||
|  | @ -1192,15 +1204,17 @@ void RadarProductManagerImpl::UpdateRecentRecords( | ||||||
|    std::shared_ptr<types::RadarProductRecord> record) |    std::shared_ptr<types::RadarProductRecord> record) | ||||||
| { | { | ||||||
|    const std::size_t recentListMaxSize {cacheLimit_}; |    const std::size_t recentListMaxSize {cacheLimit_}; | ||||||
|  |    bool              iteratorErased = false; | ||||||
| 
 | 
 | ||||||
|    auto it = std::find(recentList.cbegin(), recentList.cend(), record); |    auto it = std::find(recentList.cbegin(), recentList.cend(), record); | ||||||
|    if (it != recentList.cbegin() && it != recentList.cend()) |    if (it != recentList.cbegin() && it != recentList.cend()) | ||||||
|    { |    { | ||||||
|       // If the record exists beyond the front of the list, remove it
 |       // If the record exists beyond the front of the list, remove it
 | ||||||
|       recentList.erase(it); |       recentList.erase(it); | ||||||
|  |       iteratorErased = true; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    if (recentList.size() == 0 || it != recentList.cbegin()) |    if (iteratorErased || recentList.size() == 0 || it != recentList.cbegin()) | ||||||
|    { |    { | ||||||
|       // Add the record to the front of the list, unless it's already there
 |       // Add the record to the front of the list, unless it's already there
 | ||||||
|       recentList.push_front(record); |       recentList.push_front(record); | ||||||
|  |  | ||||||
|  | @ -59,8 +59,11 @@ public: | ||||||
| 
 | 
 | ||||||
|    void Pause(); |    void Pause(); | ||||||
|    void Play(); |    void Play(); | ||||||
|    void SelectTime(std::chrono::system_clock::time_point selectedTime = {}); |    void | ||||||
|    void Step(Direction direction); |    SelectTimeAsync(std::chrono::system_clock::time_point selectedTime = {}); | ||||||
|  |    std::pair<bool, bool> | ||||||
|  |         SelectTime(std::chrono::system_clock::time_point selectedTime = {}); | ||||||
|  |    void StepAsync(Direction direction); | ||||||
| 
 | 
 | ||||||
|    std::size_t                           mapCount_ {0}; |    std::size_t                           mapCount_ {0}; | ||||||
|    std::string                           radarSite_ {"?"}; |    std::string                           radarSite_ {"?"}; | ||||||
|  | @ -71,6 +74,7 @@ public: | ||||||
|    types::MapTime                        viewType_ {types::MapTime::Live}; |    types::MapTime                        viewType_ {types::MapTime::Live}; | ||||||
|    std::chrono::minutes                  loopTime_ {30}; |    std::chrono::minutes                  loopTime_ {30}; | ||||||
|    double                                loopSpeed_ {5.0}; |    double                                loopSpeed_ {5.0}; | ||||||
|  |    std::chrono::milliseconds             loopDelay_ {2500}; | ||||||
| 
 | 
 | ||||||
|    bool                    radarSweepMonitorActive_ {false}; |    bool                    radarSweepMonitorActive_ {false}; | ||||||
|    std::mutex              radarSweepMonitorMutex_ {}; |    std::mutex              radarSweepMonitorMutex_ {}; | ||||||
|  | @ -113,7 +117,7 @@ void TimelineManager::SetRadarSite(const std::string& radarSite) | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       // If the selected view type is archive, select using the selected time
 |       // If the selected view type is archive, select using the selected time
 | ||||||
|       p->SelectTime(p->selectedTime_); |       p->SelectTimeAsync(p->selectedTime_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -127,7 +131,7 @@ void TimelineManager::SetDateTime( | ||||||
|    if (p->viewType_ == types::MapTime::Archive) |    if (p->viewType_ == types::MapTime::Archive) | ||||||
|    { |    { | ||||||
|       // Only select if the view type is archive
 |       // Only select if the view type is archive
 | ||||||
|       p->SelectTime(dateTime); |       p->SelectTimeAsync(dateTime); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    // Ignore a date/time selection if the view type is live
 |    // Ignore a date/time selection if the view type is live
 | ||||||
|  | @ -147,7 +151,7 @@ void TimelineManager::SetViewType(types::MapTime viewType) | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       // If the selected view type is archive, select using the pinned time
 |       // If the selected view type is archive, select using the pinned time
 | ||||||
|       p->SelectTime(p->pinnedTime_); |       p->SelectTimeAsync(p->pinnedTime_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -170,6 +174,13 @@ void TimelineManager::SetLoopSpeed(double loopSpeed) | ||||||
|    p->loopSpeed_ = loopSpeed; |    p->loopSpeed_ = loopSpeed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void TimelineManager::SetLoopDelay(std::chrono::milliseconds loopDelay) | ||||||
|  | { | ||||||
|  |    logger_->debug("SetLoopDelay: {}", loopDelay); | ||||||
|  | 
 | ||||||
|  |    p->loopDelay_ = loopDelay; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void TimelineManager::AnimationStepBegin() | void TimelineManager::AnimationStepBegin() | ||||||
| { | { | ||||||
|    logger_->debug("AnimationStepBegin"); |    logger_->debug("AnimationStepBegin"); | ||||||
|  | @ -180,12 +191,12 @@ void TimelineManager::AnimationStepBegin() | ||||||
|        p->pinnedTime_ == std::chrono::system_clock::time_point {}) |        p->pinnedTime_ == std::chrono::system_clock::time_point {}) | ||||||
|    { |    { | ||||||
|       // If the selected view type is live, select the current products
 |       // If the selected view type is live, select the current products
 | ||||||
|       p->SelectTime(std::chrono::system_clock::now() - p->loopTime_); |       p->SelectTimeAsync(std::chrono::system_clock::now() - p->loopTime_); | ||||||
|    } |    } | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       // If the selected view type is archive, select using the pinned time
 |       // If the selected view type is archive, select using the pinned time
 | ||||||
|       p->SelectTime(p->pinnedTime_ - p->loopTime_); |       p->SelectTimeAsync(p->pinnedTime_ - p->loopTime_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -194,7 +205,7 @@ void TimelineManager::AnimationStepBack() | ||||||
|    logger_->debug("AnimationStepBack"); |    logger_->debug("AnimationStepBack"); | ||||||
| 
 | 
 | ||||||
|    p->Pause(); |    p->Pause(); | ||||||
|    p->Step(Direction::Back); |    p->StepAsync(Direction::Back); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TimelineManager::AnimationPlayPause() | void TimelineManager::AnimationPlayPause() | ||||||
|  | @ -216,7 +227,7 @@ void TimelineManager::AnimationStepNext() | ||||||
|    logger_->debug("AnimationStepNext"); |    logger_->debug("AnimationStepNext"); | ||||||
| 
 | 
 | ||||||
|    p->Pause(); |    p->Pause(); | ||||||
|    p->Step(Direction::Next); |    p->StepAsync(Direction::Next); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TimelineManager::AnimationStepEnd() | void TimelineManager::AnimationStepEnd() | ||||||
|  | @ -233,7 +244,7 @@ void TimelineManager::AnimationStepEnd() | ||||||
|    else |    else | ||||||
|    { |    { | ||||||
|       // If the selected view type is archive, select using the pinned time
 |       // If the selected view type is archive, select using the pinned time
 | ||||||
|       p->SelectTime(p->pinnedTime_); |       p->SelectTimeAsync(p->pinnedTime_); | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -407,30 +418,50 @@ void TimelineManager::Impl::Play() | ||||||
|             newTime = currentTime + 1min; |             newTime = currentTime + 1min; | ||||||
|          } |          } | ||||||
| 
 | 
 | ||||||
|  |          // Unlock prior to selecting time
 | ||||||
|  |          lock.unlock(); | ||||||
|  | 
 | ||||||
|  |          // Lock radar sweep monitor
 | ||||||
|  |          std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_}; | ||||||
|  | 
 | ||||||
|  |          // Reset radar sweep monitor in preparation for update
 | ||||||
|  |          RadarSweepMonitorReset(); | ||||||
|  | 
 | ||||||
|  |          // Select the time
 | ||||||
|  |          auto selectTimeStart = std::chrono::steady_clock::now(); | ||||||
|  |          auto [volumeTimeUpdated, selectedTimeUpdated] = SelectTime(newTime); | ||||||
|  |          auto selectTimeEnd = std::chrono::steady_clock::now(); | ||||||
|  |          auto elapsedTime   = selectTimeEnd - selectTimeStart; | ||||||
|  | 
 | ||||||
|  |          if (volumeTimeUpdated) | ||||||
|  |          { | ||||||
|  |             // Wait for radar sweeps to update
 | ||||||
|  |             RadarSweepMonitorWait(radarSweepMonitorLock); | ||||||
|  |          } | ||||||
|  |          else | ||||||
|  |          { | ||||||
|  |             // Disable radar sweep monitor
 | ||||||
|  |             RadarSweepMonitorDisable(); | ||||||
|  |          } | ||||||
|  | 
 | ||||||
|          // Calculate the interval until the next update, prior to selecting
 |          // Calculate the interval until the next update, prior to selecting
 | ||||||
|          std::chrono::milliseconds interval; |          std::chrono::milliseconds interval; | ||||||
|          if (newTime != endTime) |          if (newTime != endTime) | ||||||
|          { |          { | ||||||
|             // Determine repeat interval (speed of 1.0 is 1 minute per second)
 |             // Determine repeat interval (speed of 1.0 is 1 minute per second)
 | ||||||
|             interval = |             interval = std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|                std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_)); |                std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_)) - | ||||||
|  |                elapsedTime); | ||||||
|          } |          } | ||||||
|          else |          else | ||||||
|          { |          { | ||||||
|             // Pause for 2.5 seconds at the end of the loop
 |             // Pause at the end of the loop
 | ||||||
|             interval = std::chrono::milliseconds(2500); |             interval = std::chrono::duration_cast<std::chrono::milliseconds>( | ||||||
|  |                loopDelay_ - elapsedTime); | ||||||
|          } |          } | ||||||
| 
 | 
 | ||||||
|          animationTimer_.expires_after(interval); |  | ||||||
| 
 |  | ||||||
|          // Unlock prior to selecting time
 |  | ||||||
|          lock.unlock(); |  | ||||||
| 
 |  | ||||||
|          // Select the time
 |  | ||||||
|          SelectTime(newTime); |  | ||||||
| 
 |  | ||||||
|          std::unique_lock animationTimerLock {animationTimerMutex_}; |          std::unique_lock animationTimerLock {animationTimerMutex_}; | ||||||
| 
 |          animationTimer_.expires_after(interval); | ||||||
|          animationTimer_.async_wait( |          animationTimer_.async_wait( | ||||||
|             [this](const boost::system::error_code& e) |             [this](const boost::system::error_code& e) | ||||||
|             { |             { | ||||||
|  | @ -453,79 +484,63 @@ void TimelineManager::Impl::Play() | ||||||
|       }); |       }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TimelineManager::Impl::SelectTime( | void TimelineManager::Impl::SelectTimeAsync( | ||||||
|    std::chrono::system_clock::time_point selectedTime) |    std::chrono::system_clock::time_point selectedTime) | ||||||
| { | { | ||||||
|  |    scwx::util::async([=, this]() { SelectTime(selectedTime); }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::pair<bool, bool> TimelineManager::Impl::SelectTime( | ||||||
|  |    std::chrono::system_clock::time_point selectedTime) | ||||||
|  | { | ||||||
|  |    bool volumeTimeUpdated   = false; | ||||||
|  |    bool selectedTimeUpdated = false; | ||||||
|  | 
 | ||||||
|    if (selectedTime_ == selectedTime && radarSite_ == previousRadarSite_) |    if (selectedTime_ == selectedTime && radarSite_ == previousRadarSite_) | ||||||
|    { |    { | ||||||
|       // Nothing to do
 |       // Nothing to do
 | ||||||
|       return; |       return {volumeTimeUpdated, selectedTimeUpdated}; | ||||||
|    } |    } | ||||||
|    else if (selectedTime == std::chrono::system_clock::time_point {}) |    else if (selectedTime == std::chrono::system_clock::time_point {}) | ||||||
|    { |    { | ||||||
|       scwx::util::async( |  | ||||||
|          [=, this]() |  | ||||||
|          { |  | ||||||
|             // Take a lock for time selection
 |  | ||||||
|             std::unique_lock lock {selectTimeMutex_}; |  | ||||||
| 
 |  | ||||||
|       // If a default time point is given, reset to a live view
 |       // If a default time point is given, reset to a live view
 | ||||||
|       selectedTime_      = selectedTime; |       selectedTime_      = selectedTime; | ||||||
|       adjustedTime_      = selectedTime; |       adjustedTime_      = selectedTime; | ||||||
|  |       previousRadarSite_ = radarSite_; | ||||||
| 
 | 
 | ||||||
|       logger_->debug("Time updated: Live"); |       logger_->debug("Time updated: Live"); | ||||||
| 
 | 
 | ||||||
|             std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_}; |  | ||||||
| 
 |  | ||||||
|             // Reset radar sweep monitor in preparation for update
 |  | ||||||
|             RadarSweepMonitorReset(); |  | ||||||
| 
 |  | ||||||
|       Q_EMIT self_->LiveStateUpdated(true); |       Q_EMIT self_->LiveStateUpdated(true); | ||||||
|       Q_EMIT self_->VolumeTimeUpdated(selectedTime); |       Q_EMIT self_->VolumeTimeUpdated(selectedTime); | ||||||
|       Q_EMIT self_->SelectedTimeUpdated(selectedTime); |       Q_EMIT self_->SelectedTimeUpdated(selectedTime); | ||||||
| 
 | 
 | ||||||
|             // Wait for radar sweeps to update
 |       volumeTimeUpdated   = true; | ||||||
|             RadarSweepMonitorWait(radarSweepMonitorLock); |       selectedTimeUpdated = true; | ||||||
|          }); |  | ||||||
| 
 | 
 | ||||||
|       return; |       return {volumeTimeUpdated, selectedTimeUpdated}; | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    scwx::util::async( |  | ||||||
|       [=, this]() |  | ||||||
|       { |  | ||||||
|    // Take a lock for time selection
 |    // Take a lock for time selection
 | ||||||
|    std::unique_lock lock {selectTimeMutex_}; |    std::unique_lock lock {selectTimeMutex_}; | ||||||
| 
 | 
 | ||||||
|    // Request active volume times
 |    // Request active volume times
 | ||||||
|    auto radarProductManager = |    auto radarProductManager = | ||||||
|       manager::RadarProductManager::Instance(radarSite_); |       manager::RadarProductManager::Instance(radarSite_); | ||||||
|          auto volumeTimes = |    auto volumeTimes = radarProductManager->GetActiveVolumeTimes(selectedTime); | ||||||
|             radarProductManager->GetActiveVolumeTimes(selectedTime); |  | ||||||
| 
 | 
 | ||||||
|    // Dynamically update maximum cached volume scans
 |    // Dynamically update maximum cached volume scans
 | ||||||
|    UpdateCacheLimit(radarProductManager, volumeTimes); |    UpdateCacheLimit(radarProductManager, volumeTimes); | ||||||
| 
 | 
 | ||||||
|    // Find the best match bounded time
 |    // Find the best match bounded time
 | ||||||
|          auto elementPtr = |    auto elementPtr = util::GetBoundedElementPointer(volumeTimes, selectedTime); | ||||||
|             util::GetBoundedElementPointer(volumeTimes, selectedTime); |  | ||||||
| 
 | 
 | ||||||
|    // The timeline is no longer live
 |    // The timeline is no longer live
 | ||||||
|    Q_EMIT self_->LiveStateUpdated(false); |    Q_EMIT self_->LiveStateUpdated(false); | ||||||
| 
 | 
 | ||||||
|          bool volumeTimeUpdated = false; |  | ||||||
| 
 |  | ||||||
|          std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_}; |  | ||||||
| 
 |  | ||||||
|          // Reset radar sweep monitor in preparation for update
 |  | ||||||
|          RadarSweepMonitorReset(); |  | ||||||
| 
 |  | ||||||
|    if (elementPtr != nullptr) |    if (elementPtr != nullptr) | ||||||
|    { |    { | ||||||
|             // If the adjusted time changed, or if a new radar site has been
 |       // If the adjusted time changed, or if a new radar site has been selected
 | ||||||
|             // selected
 |       if (adjustedTime_ != *elementPtr || radarSite_ != previousRadarSite_) | ||||||
|             if (adjustedTime_ != *elementPtr || |  | ||||||
|                 radarSite_ != previousRadarSite_) |  | ||||||
|       { |       { | ||||||
|          // If the time was found, select it
 |          // If the time was found, select it
 | ||||||
|          adjustedTime_ = *elementPtr; |          adjustedTime_ = *elementPtr; | ||||||
|  | @ -548,23 +563,15 @@ void TimelineManager::Impl::SelectTime( | ||||||
|                   scwx::util::TimeString(selectedTime)); |                   scwx::util::TimeString(selectedTime)); | ||||||
| 
 | 
 | ||||||
|    selectedTime_       = selectedTime; |    selectedTime_       = selectedTime; | ||||||
|  |    selectedTimeUpdated = true; | ||||||
|    Q_EMIT self_->SelectedTimeUpdated(selectedTime); |    Q_EMIT self_->SelectedTimeUpdated(selectedTime); | ||||||
| 
 | 
 | ||||||
|    previousRadarSite_ = radarSite_; |    previousRadarSite_ = radarSite_; | ||||||
| 
 | 
 | ||||||
|          if (volumeTimeUpdated) |    return {volumeTimeUpdated, selectedTimeUpdated}; | ||||||
|          { |  | ||||||
|             // Wait for radar sweeps to update
 |  | ||||||
|             RadarSweepMonitorWait(radarSweepMonitorLock); |  | ||||||
|          } |  | ||||||
|          else |  | ||||||
|          { |  | ||||||
|             RadarSweepMonitorDisable(); |  | ||||||
|          } |  | ||||||
|       }); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TimelineManager::Impl::Step(Direction direction) | void TimelineManager::Impl::StepAsync(Direction direction) | ||||||
| { | { | ||||||
|    scwx::util::async( |    scwx::util::async( | ||||||
|       [=, this]() |       [=, this]() | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ public slots: | ||||||
| 
 | 
 | ||||||
|    void SetLoopTime(std::chrono::minutes loopTime); |    void SetLoopTime(std::chrono::minutes loopTime); | ||||||
|    void SetLoopSpeed(double loopSpeed); |    void SetLoopSpeed(double loopSpeed); | ||||||
|  |    void SetLoopDelay(std::chrono::milliseconds loopDelay); | ||||||
| 
 | 
 | ||||||
|    void AnimationStepBegin(); |    void AnimationStepBegin(); | ||||||
|    void AnimationStepBack(); |    void AnimationStepBack(); | ||||||
|  |  | ||||||
|  | @ -1053,6 +1053,9 @@ void MapWidgetImpl::SetRadarSite(const std::string& radarSite) | ||||||
|       // Set new RadarProductManager
 |       // Set new RadarProductManager
 | ||||||
|       radarProductManager_ = manager::RadarProductManager::Instance(radarSite); |       radarProductManager_ = manager::RadarProductManager::Instance(radarSite); | ||||||
| 
 | 
 | ||||||
|  |       // Re-enable auto-update
 | ||||||
|  |       autoUpdateEnabled_ = true; | ||||||
|  | 
 | ||||||
|       // Connect signals to new RadarProductManager
 |       // Connect signals to new RadarProductManager
 | ||||||
|       RadarProductManagerConnect(); |       RadarProductManagerConnect(); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -133,6 +133,11 @@ std::chrono::system_clock::time_point RadarProductRecord::time() const | ||||||
|    return p->time_; |    return p->time_; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void RadarProductRecord::set_time(std::chrono::system_clock::time_point time) | ||||||
|  | { | ||||||
|  |    p->time_ = time; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::shared_ptr<RadarProductRecord> | std::shared_ptr<RadarProductRecord> | ||||||
| RadarProductRecord::Create(std::shared_ptr<wsr88d::NexradFile> nexradFile) | RadarProductRecord::Create(std::shared_ptr<wsr88d::NexradFile> nexradFile) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -38,6 +38,8 @@ public: | ||||||
|    std::string                           site_id() const; |    std::string                           site_id() const; | ||||||
|    std::chrono::system_clock::time_point time() const; |    std::chrono::system_clock::time_point time() const; | ||||||
| 
 | 
 | ||||||
|  |    void set_time(std::chrono::system_clock::time_point time); | ||||||
|  | 
 | ||||||
|    static std::shared_ptr<RadarProductRecord> |    static std::shared_ptr<RadarProductRecord> | ||||||
|    Create(std::shared_ptr<wsr88d::NexradFile> nexradFile); |    Create(std::shared_ptr<wsr88d::NexradFile> nexradFile); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -88,6 +88,7 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) : | ||||||
|    // Set loop defaults
 |    // Set loop defaults
 | ||||||
|    ui->loopTimeSpinBox->setValue(30); |    ui->loopTimeSpinBox->setValue(30); | ||||||
|    ui->loopSpeedSpinBox->setValue(5.0); |    ui->loopSpeedSpinBox->setValue(5.0); | ||||||
|  |    ui->loopDelaySpinBox->setValue(2.5); | ||||||
| 
 | 
 | ||||||
|    // Connect widget signals
 |    // Connect widget signals
 | ||||||
|    p->ConnectSignals(); |    p->ConnectSignals(); | ||||||
|  | @ -161,6 +162,15 @@ void AnimationDockWidgetImpl::ConnectSignals() | ||||||
|                     &QDoubleSpinBox::valueChanged, |                     &QDoubleSpinBox::valueChanged, | ||||||
|                     self_, |                     self_, | ||||||
|                     [this](double d) { Q_EMIT self_->LoopSpeedChanged(d); }); |                     [this](double d) { Q_EMIT self_->LoopSpeedChanged(d); }); | ||||||
|  |    QObject::connect( | ||||||
|  |       self_->ui->loopDelaySpinBox, | ||||||
|  |       &QDoubleSpinBox::valueChanged, | ||||||
|  |       self_, | ||||||
|  |       [this](double d) | ||||||
|  |       { | ||||||
|  |          Q_EMIT self_->LoopDelayChanged(std::chrono::milliseconds( | ||||||
|  |             static_cast<typename std::chrono::milliseconds::rep>(d * 1000.0))); | ||||||
|  |       }); | ||||||
| 
 | 
 | ||||||
|    // Animation controls
 |    // Animation controls
 | ||||||
|    QObject::connect(self_->ui->beginButton, |    QObject::connect(self_->ui->beginButton, | ||||||
|  |  | ||||||
|  | @ -38,6 +38,7 @@ signals: | ||||||
| 
 | 
 | ||||||
|    void LoopTimeChanged(std::chrono::minutes loopTime); |    void LoopTimeChanged(std::chrono::minutes loopTime); | ||||||
|    void LoopSpeedChanged(double loopSpeed); |    void LoopSpeedChanged(double loopSpeed); | ||||||
|  |    void LoopDelayChanged(std::chrono::milliseconds loopDelay); | ||||||
| 
 | 
 | ||||||
|    void AnimationStepBeginSelected(); |    void AnimationStepBeginSelected(); | ||||||
|    void AnimationStepBackSelected(); |    void AnimationStepBackSelected(); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
|     <x>0</x> |     <x>0</x> | ||||||
|     <y>0</y> |     <y>0</y> | ||||||
|     <width>200</width> |     <width>200</width> | ||||||
|     <height>337</height> |     <height>348</height> | ||||||
|    </rect> |    </rect> | ||||||
|   </property> |   </property> | ||||||
|   <property name="windowTitle"> |   <property name="windowTitle"> | ||||||
|  | @ -130,13 +130,6 @@ | ||||||
|           <property name="bottomMargin"> |           <property name="bottomMargin"> | ||||||
|            <number>0</number> |            <number>0</number> | ||||||
|           </property> |           </property> | ||||||
|           <item row="0" column="0"> |  | ||||||
|            <widget class="QLabel" name="loopTimeLabel"> |  | ||||||
|             <property name="text"> |  | ||||||
|              <string>Loop Time</string> |  | ||||||
|             </property> |  | ||||||
|            </widget> |  | ||||||
|           </item> |  | ||||||
|           <item row="0" column="1"> |           <item row="0" column="1"> | ||||||
|            <widget class="QSpinBox" name="loopTimeSpinBox"> |            <widget class="QSpinBox" name="loopTimeSpinBox"> | ||||||
|             <property name="correctionMode"> |             <property name="correctionMode"> | ||||||
|  | @ -156,6 +149,13 @@ | ||||||
|             </property> |             </property> | ||||||
|            </widget> |            </widget> | ||||||
|           </item> |           </item> | ||||||
|  |           <item row="0" column="0"> | ||||||
|  |            <widget class="QLabel" name="loopTimeLabel"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Loop Time</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|           <item row="1" column="0"> |           <item row="1" column="0"> | ||||||
|            <widget class="QLabel" name="loopSpeedLabel"> |            <widget class="QLabel" name="loopSpeedLabel"> | ||||||
|             <property name="text"> |             <property name="text"> | ||||||
|  | @ -179,6 +179,32 @@ | ||||||
|             </property> |             </property> | ||||||
|            </widget> |            </widget> | ||||||
|           </item> |           </item> | ||||||
|  |           <item row="2" column="0"> | ||||||
|  |            <widget class="QLabel" name="loopDelayLabel"> | ||||||
|  |             <property name="text"> | ||||||
|  |              <string>Loop Delay</string> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|  |           <item row="2" column="1"> | ||||||
|  |            <widget class="QDoubleSpinBox" name="loopDelaySpinBox"> | ||||||
|  |             <property name="suffix"> | ||||||
|  |              <string> sec</string> | ||||||
|  |             </property> | ||||||
|  |             <property name="decimals"> | ||||||
|  |              <number>1</number> | ||||||
|  |             </property> | ||||||
|  |             <property name="maximum"> | ||||||
|  |              <double>15.000000000000000</double> | ||||||
|  |             </property> | ||||||
|  |             <property name="singleStep"> | ||||||
|  |              <double>0.100000000000000</double> | ||||||
|  |             </property> | ||||||
|  |             <property name="value"> | ||||||
|  |              <double>2.500000000000000</double> | ||||||
|  |             </property> | ||||||
|  |            </widget> | ||||||
|  |           </item> | ||||||
|          </layout> |          </layout> | ||||||
|         </widget> |         </widget> | ||||||
|        </item> |        </item> | ||||||
|  |  | ||||||
|  | @ -725,7 +725,8 @@ void Level2ProductViewImpl::ComputeCoordinates( | ||||||
|    const std::uint16_t numRadials = |    const std::uint16_t numRadials = | ||||||
|       static_cast<std::uint16_t>(radarData->size()); |       static_cast<std::uint16_t>(radarData->size()); | ||||||
|    const std::uint16_t numRangeBins = |    const std::uint16_t numRangeBins = | ||||||
|       momentData0->number_of_data_moment_gates(); |       std::max(momentData0->number_of_data_moment_gates() + 1u, | ||||||
|  |                common::MAX_DATA_MOMENT_GATES); | ||||||
| 
 | 
 | ||||||
|    auto radials = boost::irange<std::uint32_t>(0u, numRadials); |    auto radials = boost::irange<std::uint32_t>(0u, numRadials); | ||||||
|    auto gates   = boost::irange<std::uint32_t>(0u, numRangeBins); |    auto gates   = boost::irange<std::uint32_t>(0u, numRangeBins); | ||||||
|  |  | ||||||
|  | @ -422,6 +422,12 @@ void Ar2vFileImpl::IndexFile() | ||||||
|       std::shared_ptr<rda::DigitalRadarData> radial0 = |       std::shared_ptr<rda::DigitalRadarData> radial0 = | ||||||
|          (*elevationCut.second)[0]; |          (*elevationCut.second)[0]; | ||||||
| 
 | 
 | ||||||
|  |       if (radial0 == nullptr) | ||||||
|  |       { | ||||||
|  |          logger_->warn("Empty radial data"); | ||||||
|  |          continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|       for (rda::DataBlockType dataBlockType : |       for (rda::DataBlockType dataBlockType : | ||||||
|            rda::MomentDataBlockTypeIterator()) |            rda::MomentDataBlockTypeIterator()) | ||||||
|       { |       { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat