mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 19:00:04 +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,
|
||||
timelineManager_.get(),
|
||||
&manager::TimelineManager::SetLoopSpeed);
|
||||
connect(animationDockWidget_,
|
||||
&ui::AnimationDockWidget::LoopDelayChanged,
|
||||
timelineManager_.get(),
|
||||
&manager::TimelineManager::SetLoopDelay);
|
||||
connect(animationDockWidget_,
|
||||
&ui::AnimationDockWidget::AnimationStepBeginSelected,
|
||||
timelineManager_.get(),
|
||||
|
|
|
|||
|
|
@ -210,7 +210,8 @@ public:
|
|||
static void
|
||||
LoadNexradFile(CreateNexradFileFunction load,
|
||||
std::shared_ptr<request::NexradFileRequest> request,
|
||||
std::mutex& mutex);
|
||||
std::mutex& mutex,
|
||||
std::chrono::system_clock::time_point time = {});
|
||||
|
||||
const std::string radarId_;
|
||||
bool initialized_;
|
||||
|
|
@ -801,7 +802,8 @@ void RadarProductManagerImpl::LoadProviderData(
|
|||
return nexradFile;
|
||||
},
|
||||
request,
|
||||
loadDataMutex);
|
||||
loadDataMutex,
|
||||
time);
|
||||
}
|
||||
|
||||
void RadarProductManager::LoadLevel2Data(
|
||||
|
|
@ -912,7 +914,8 @@ void RadarProductManager::LoadFile(
|
|||
void RadarProductManagerImpl::LoadNexradFile(
|
||||
CreateNexradFileFunction load,
|
||||
std::shared_ptr<request::NexradFileRequest> request,
|
||||
std::mutex& mutex)
|
||||
std::mutex& mutex,
|
||||
std::chrono::system_clock::time_point time)
|
||||
{
|
||||
scwx::util::async(
|
||||
[=, &mutex]()
|
||||
|
|
@ -929,6 +932,15 @@ void RadarProductManagerImpl::LoadNexradFile(
|
|||
{
|
||||
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 =
|
||||
RadarProductManager::Instance(record->radar_id());
|
||||
|
||||
|
|
@ -1192,15 +1204,17 @@ void RadarProductManagerImpl::UpdateRecentRecords(
|
|||
std::shared_ptr<types::RadarProductRecord> record)
|
||||
{
|
||||
const std::size_t recentListMaxSize {cacheLimit_};
|
||||
bool iteratorErased = false;
|
||||
|
||||
auto it = std::find(recentList.cbegin(), recentList.cend(), record);
|
||||
if (it != recentList.cbegin() && it != recentList.cend())
|
||||
{
|
||||
// If the record exists beyond the front of the list, remove 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
|
||||
recentList.push_front(record);
|
||||
|
|
|
|||
|
|
@ -59,8 +59,11 @@ public:
|
|||
|
||||
void Pause();
|
||||
void Play();
|
||||
void SelectTime(std::chrono::system_clock::time_point selectedTime = {});
|
||||
void Step(Direction direction);
|
||||
void
|
||||
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::string radarSite_ {"?"};
|
||||
|
|
@ -71,6 +74,7 @@ public:
|
|||
types::MapTime viewType_ {types::MapTime::Live};
|
||||
std::chrono::minutes loopTime_ {30};
|
||||
double loopSpeed_ {5.0};
|
||||
std::chrono::milliseconds loopDelay_ {2500};
|
||||
|
||||
bool radarSweepMonitorActive_ {false};
|
||||
std::mutex radarSweepMonitorMutex_ {};
|
||||
|
|
@ -113,7 +117,7 @@ void TimelineManager::SetRadarSite(const std::string& radarSite)
|
|||
else
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// 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
|
||||
|
|
@ -147,7 +151,7 @@ void TimelineManager::SetViewType(types::MapTime viewType)
|
|||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
void TimelineManager::SetLoopDelay(std::chrono::milliseconds loopDelay)
|
||||
{
|
||||
logger_->debug("SetLoopDelay: {}", loopDelay);
|
||||
|
||||
p->loopDelay_ = loopDelay;
|
||||
}
|
||||
|
||||
void TimelineManager::AnimationStepBegin()
|
||||
{
|
||||
logger_->debug("AnimationStepBegin");
|
||||
|
|
@ -180,12 +191,12 @@ void TimelineManager::AnimationStepBegin()
|
|||
p->pinnedTime_ == std::chrono::system_clock::time_point {})
|
||||
{
|
||||
// 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
|
||||
{
|
||||
// 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");
|
||||
|
||||
p->Pause();
|
||||
p->Step(Direction::Back);
|
||||
p->StepAsync(Direction::Back);
|
||||
}
|
||||
|
||||
void TimelineManager::AnimationPlayPause()
|
||||
|
|
@ -216,7 +227,7 @@ void TimelineManager::AnimationStepNext()
|
|||
logger_->debug("AnimationStepNext");
|
||||
|
||||
p->Pause();
|
||||
p->Step(Direction::Next);
|
||||
p->StepAsync(Direction::Next);
|
||||
}
|
||||
|
||||
void TimelineManager::AnimationStepEnd()
|
||||
|
|
@ -233,7 +244,7 @@ void TimelineManager::AnimationStepEnd()
|
|||
else
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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
|
||||
std::chrono::milliseconds interval;
|
||||
if (newTime != endTime)
|
||||
{
|
||||
// Determine repeat interval (speed of 1.0 is 1 minute per second)
|
||||
interval =
|
||||
std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_));
|
||||
interval = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_)) -
|
||||
elapsedTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Pause for 2.5 seconds at the end of the loop
|
||||
interval = std::chrono::milliseconds(2500);
|
||||
// Pause at the end of the loop
|
||||
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_};
|
||||
|
||||
animationTimer_.expires_after(interval);
|
||||
animationTimer_.async_wait(
|
||||
[this](const boost::system::error_code& e)
|
||||
{
|
||||
|
|
@ -453,118 +484,94 @@ void TimelineManager::Impl::Play()
|
|||
});
|
||||
}
|
||||
|
||||
void TimelineManager::Impl::SelectTime(
|
||||
void TimelineManager::Impl::SelectTimeAsync(
|
||||
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_)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||
}
|
||||
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
|
||||
selectedTime_ = selectedTime;
|
||||
adjustedTime_ = selectedTime;
|
||||
previousRadarSite_ = radarSite_;
|
||||
|
||||
// If a default time point is given, reset to a live view
|
||||
selectedTime_ = selectedTime;
|
||||
adjustedTime_ = selectedTime;
|
||||
logger_->debug("Time updated: Live");
|
||||
|
||||
logger_->debug("Time updated: Live");
|
||||
Q_EMIT self_->LiveStateUpdated(true);
|
||||
Q_EMIT self_->VolumeTimeUpdated(selectedTime);
|
||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||
|
||||
std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_};
|
||||
volumeTimeUpdated = true;
|
||||
selectedTimeUpdated = true;
|
||||
|
||||
// Reset radar sweep monitor in preparation for update
|
||||
RadarSweepMonitorReset();
|
||||
|
||||
Q_EMIT self_->LiveStateUpdated(true);
|
||||
Q_EMIT self_->VolumeTimeUpdated(selectedTime);
|
||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||
|
||||
// Wait for radar sweeps to update
|
||||
RadarSweepMonitorWait(radarSweepMonitorLock);
|
||||
});
|
||||
|
||||
return;
|
||||
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||
}
|
||||
|
||||
scwx::util::async(
|
||||
[=, this]()
|
||||
// Take a lock for time selection
|
||||
std::unique_lock lock {selectTimeMutex_};
|
||||
|
||||
// Request active volume times
|
||||
auto radarProductManager =
|
||||
manager::RadarProductManager::Instance(radarSite_);
|
||||
auto volumeTimes = radarProductManager->GetActiveVolumeTimes(selectedTime);
|
||||
|
||||
// Dynamically update maximum cached volume scans
|
||||
UpdateCacheLimit(radarProductManager, volumeTimes);
|
||||
|
||||
// Find the best match bounded time
|
||||
auto elementPtr = util::GetBoundedElementPointer(volumeTimes, selectedTime);
|
||||
|
||||
// The timeline is no longer live
|
||||
Q_EMIT self_->LiveStateUpdated(false);
|
||||
|
||||
if (elementPtr != nullptr)
|
||||
{
|
||||
// If the adjusted time changed, or if a new radar site has been selected
|
||||
if (adjustedTime_ != *elementPtr || radarSite_ != previousRadarSite_)
|
||||
{
|
||||
// Take a lock for time selection
|
||||
std::unique_lock lock {selectTimeMutex_};
|
||||
// If the time was found, select it
|
||||
adjustedTime_ = *elementPtr;
|
||||
|
||||
// Request active volume times
|
||||
auto radarProductManager =
|
||||
manager::RadarProductManager::Instance(radarSite_);
|
||||
auto volumeTimes =
|
||||
radarProductManager->GetActiveVolumeTimes(selectedTime);
|
||||
logger_->debug("Volume time updated: {}",
|
||||
scwx::util::TimeString(adjustedTime_));
|
||||
|
||||
// Dynamically update maximum cached volume scans
|
||||
UpdateCacheLimit(radarProductManager, volumeTimes);
|
||||
volumeTimeUpdated = true;
|
||||
Q_EMIT self_->VolumeTimeUpdated(adjustedTime_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No volume time was found
|
||||
logger_->info("No volume scan found for {}",
|
||||
scwx::util::TimeString(selectedTime));
|
||||
}
|
||||
|
||||
// Find the best match bounded time
|
||||
auto elementPtr =
|
||||
util::GetBoundedElementPointer(volumeTimes, selectedTime);
|
||||
logger_->trace("Selected time updated: {}",
|
||||
scwx::util::TimeString(selectedTime));
|
||||
|
||||
// The timeline is no longer live
|
||||
Q_EMIT self_->LiveStateUpdated(false);
|
||||
selectedTime_ = selectedTime;
|
||||
selectedTimeUpdated = true;
|
||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||
|
||||
bool volumeTimeUpdated = false;
|
||||
previousRadarSite_ = radarSite_;
|
||||
|
||||
std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_};
|
||||
|
||||
// Reset radar sweep monitor in preparation for update
|
||||
RadarSweepMonitorReset();
|
||||
|
||||
if (elementPtr != nullptr)
|
||||
{
|
||||
// If the adjusted time changed, or if a new radar site has been
|
||||
// selected
|
||||
if (adjustedTime_ != *elementPtr ||
|
||||
radarSite_ != previousRadarSite_)
|
||||
{
|
||||
// If the time was found, select it
|
||||
adjustedTime_ = *elementPtr;
|
||||
|
||||
logger_->debug("Volume time updated: {}",
|
||||
scwx::util::TimeString(adjustedTime_));
|
||||
|
||||
volumeTimeUpdated = true;
|
||||
Q_EMIT self_->VolumeTimeUpdated(adjustedTime_);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No volume time was found
|
||||
logger_->info("No volume scan found for {}",
|
||||
scwx::util::TimeString(selectedTime));
|
||||
}
|
||||
|
||||
logger_->trace("Selected time updated: {}",
|
||||
scwx::util::TimeString(selectedTime));
|
||||
|
||||
selectedTime_ = selectedTime;
|
||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||
|
||||
previousRadarSite_ = radarSite_;
|
||||
|
||||
if (volumeTimeUpdated)
|
||||
{
|
||||
// Wait for radar sweeps to update
|
||||
RadarSweepMonitorWait(radarSweepMonitorLock);
|
||||
}
|
||||
else
|
||||
{
|
||||
RadarSweepMonitorDisable();
|
||||
}
|
||||
});
|
||||
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||
}
|
||||
|
||||
void TimelineManager::Impl::Step(Direction direction)
|
||||
void TimelineManager::Impl::StepAsync(Direction direction)
|
||||
{
|
||||
scwx::util::async(
|
||||
[=, this]()
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public slots:
|
|||
|
||||
void SetLoopTime(std::chrono::minutes loopTime);
|
||||
void SetLoopSpeed(double loopSpeed);
|
||||
void SetLoopDelay(std::chrono::milliseconds loopDelay);
|
||||
|
||||
void AnimationStepBegin();
|
||||
void AnimationStepBack();
|
||||
|
|
|
|||
|
|
@ -1053,6 +1053,9 @@ void MapWidgetImpl::SetRadarSite(const std::string& radarSite)
|
|||
// Set new RadarProductManager
|
||||
radarProductManager_ = manager::RadarProductManager::Instance(radarSite);
|
||||
|
||||
// Re-enable auto-update
|
||||
autoUpdateEnabled_ = true;
|
||||
|
||||
// Connect signals to new RadarProductManager
|
||||
RadarProductManagerConnect();
|
||||
|
||||
|
|
|
|||
|
|
@ -133,6 +133,11 @@ std::chrono::system_clock::time_point RadarProductRecord::time() const
|
|||
return p->time_;
|
||||
}
|
||||
|
||||
void RadarProductRecord::set_time(std::chrono::system_clock::time_point time)
|
||||
{
|
||||
p->time_ = time;
|
||||
}
|
||||
|
||||
std::shared_ptr<RadarProductRecord>
|
||||
RadarProductRecord::Create(std::shared_ptr<wsr88d::NexradFile> nexradFile)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public:
|
|||
explicit RadarProductRecord(std::shared_ptr<wsr88d::NexradFile> nexradFile);
|
||||
~RadarProductRecord();
|
||||
|
||||
RadarProductRecord(const RadarProductRecord&) = delete;
|
||||
RadarProductRecord(const RadarProductRecord&) = delete;
|
||||
RadarProductRecord& operator=(const RadarProductRecord&) = delete;
|
||||
|
||||
RadarProductRecord(RadarProductRecord&&) noexcept;
|
||||
|
|
@ -38,6 +38,8 @@ public:
|
|||
std::string site_id() const;
|
||||
std::chrono::system_clock::time_point time() const;
|
||||
|
||||
void set_time(std::chrono::system_clock::time_point time);
|
||||
|
||||
static std::shared_ptr<RadarProductRecord>
|
||||
Create(std::shared_ptr<wsr88d::NexradFile> nexradFile);
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) :
|
|||
// Set loop defaults
|
||||
ui->loopTimeSpinBox->setValue(30);
|
||||
ui->loopSpeedSpinBox->setValue(5.0);
|
||||
ui->loopDelaySpinBox->setValue(2.5);
|
||||
|
||||
// Connect widget signals
|
||||
p->ConnectSignals();
|
||||
|
|
@ -161,6 +162,15 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
&QDoubleSpinBox::valueChanged,
|
||||
self_,
|
||||
[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
|
||||
QObject::connect(self_->ui->beginButton,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ signals:
|
|||
|
||||
void LoopTimeChanged(std::chrono::minutes loopTime);
|
||||
void LoopSpeedChanged(double loopSpeed);
|
||||
void LoopDelayChanged(std::chrono::milliseconds loopDelay);
|
||||
|
||||
void AnimationStepBeginSelected();
|
||||
void AnimationStepBackSelected();
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>200</width>
|
||||
<height>337</height>
|
||||
<height>348</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
|
@ -130,13 +130,6 @@
|
|||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</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">
|
||||
<widget class="QSpinBox" name="loopTimeSpinBox">
|
||||
<property name="correctionMode">
|
||||
|
|
@ -156,6 +149,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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">
|
||||
<widget class="QLabel" name="loopSpeedLabel">
|
||||
<property name="text">
|
||||
|
|
@ -179,6 +179,32 @@
|
|||
</property>
|
||||
</widget>
|
||||
</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>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -725,7 +725,8 @@ void Level2ProductViewImpl::ComputeCoordinates(
|
|||
const std::uint16_t numRadials =
|
||||
static_cast<std::uint16_t>(radarData->size());
|
||||
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 gates = boost::irange<std::uint32_t>(0u, numRangeBins);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue