##// END OF EJS Templates
Merge branch 'feature/ImprovePerf' into develop
Merge branch 'feature/ImprovePerf' into develop

File last commit:

r594:ad1efe843595
r615:4575ac2a0a6a merge
Show More
VisualizationGraphHelper.cpp
247 lines | 8.3 KiB | text/x-c | CppLexer
/ gui / src / Visualization / VisualizationGraphHelper.cpp
Correction for pull request
r227 #include "Visualization/VisualizationGraphHelper.h"
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 #include "Visualization/qcustomplot.h"
Alexandre Leroux
Sets differents colors for components of a vector
r548 #include <Common/ColorUtils.h>
Alexandre Leroux
Handles creations for scalar series
r169 #include <Data/ScalarSeries.h>
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 #include <Data/VectorSeries.h>
Alexandre Leroux
Handles creations for scalar series
r169
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 #include <Variable/Variable.h>
Correction for pull request
r227 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168
Alexandre Leroux
Handles creations for scalar series
r169 namespace {
Add current progression for thread fix
r336 class SqpDataContainer : public QCPGraphDataContainer {
public:
Alexandre Leroux
Updates UI to not call the sort method when update graphs, as data series are already sorted
r419 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
Add current progression for thread fix
r336 };
Alexandre Leroux
Handles axes properties
r170 /// Format for datetimes on a axis
const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
/// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
/// non-time data
QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
{
if (isTimeAxis) {
auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
Alexandre Leroux
Uses the same time spec (UTC) as axis for tooltips on graph
r452 dateTicker->setDateTimeSpec(Qt::UTC);
Alexandre Leroux
Handles axes properties
r170
return dateTicker;
}
else {
// default ticker
return QSharedPointer<QCPAxisTicker>::create();
}
}
Alexandre Leroux
Handles creations for scalar series
r169
Add thread protection for DataSeries...
r594 /// Sets axes properties according to the properties of a data series. Not thread safe
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 template <int Dim>
void setAxesProperties(const DataSeries<Dim> &dataSeries, QCustomPlot &plot) noexcept
The mock plugin can now create data with view operation
r219 {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
/// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
auto setAxisProperties = [](auto axis, const auto &unit) {
// label (unit name)
axis->setLabel(unit.m_Name);
// ticker (depending on the type of unit)
axis->setTicker(axisTicker(unit.m_TimeUnit));
};
setAxisProperties(plot.xAxis, dataSeries.xAxisUnit());
setAxisProperties(plot.yAxis, dataSeries.valuesUnit());
}
onRangeChanged is now based on the good range (the new one)...
r290
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /**
Add mofif for clang format
r554 * Struct used to create plottables, depending on the type of the data series from which to create
* them
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 * @tparam T the data series' type
* @remarks Default implementation can't create plottables
*/
template <typename T, typename Enabled = void>
struct PlottablesCreator {
static PlottablesMap createPlottables(T &, QCustomPlot &)
{
qCCritical(LOG_DataSeries())
<< QObject::tr("Can't create plottables: unmanaged data series type");
return {};
The mock plugin can now create data with view operation
r219 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 };
The mock plugin can now create data with view operation
r219
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /**
* Specialization of PlottablesCreator for scalars and vectors
* @sa ScalarSeries
* @sa VectorSeries
*/
template <typename T>
struct PlottablesCreator<T,
typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
or std::is_base_of<VectorSeries, T>::value> > {
static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
{
PlottablesMap result{};
// Gets the number of components of the data series
Add thread protection for DataSeries...
r594 dataSeries.lockRead();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 auto componentCount = dataSeries.valuesData()->componentCount();
Add thread protection for DataSeries...
r594 dataSeries.unlock();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547
Alexandre Leroux
Sets differents colors for components of a vector
r548 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 // For each component of the data series, creates a QCPGraph to add to the plot
for (auto i = 0; i < componentCount; ++i) {
auto graph = plot.addGraph();
Alexandre Leroux
Sets differents colors for components of a vector
r548 graph->setPen(QPen{colors.at(i)});
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547
result.insert({i, graph});
}
Initialisation of the graph range at creation in a new graphe, or inside...
r518
// Axes properties
Add thread protection for DataSeries...
r594 dataSeries.lockRead();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 setAxesProperties(dataSeries, plot);
Add thread protection for DataSeries...
r594 dataSeries.unlock();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547
plot.replot();
return result;
Initialisation of the graph range at creation in a new graphe, or inside...
r518 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 };
Initialisation of the graph range at creation in a new graphe, or inside...
r518
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /**
Add mofif for clang format
r554 * Struct used to update plottables, depending on the type of the data series from which to update
* them
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 * @tparam T the data series' type
* @remarks Default implementation can't update plottables
*/
template <typename T, typename Enabled = void>
struct PlottablesUpdater {
static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
{
qCCritical(LOG_DataSeries())
<< QObject::tr("Can't update plottables: unmanaged data series type");
}
};
Alexandre Leroux
Handles creations for scalar series
r169
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /**
* Specialization of PlottablesUpdater for scalars and vectors
* @sa ScalarSeries
* @sa VectorSeries
*/
template <typename T>
struct PlottablesUpdater<T,
typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
or std::is_base_of<VectorSeries, T>::value> > {
static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
bool rescaleAxes)
{
// For each plottable to update, resets its data
std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
for (const auto &plottable : plottables) {
if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
auto dataContainer = QSharedPointer<SqpDataContainer>::create();
graph->setData(dataContainer);
dataContainers.insert({plottable.first, dataContainer});
}
}
Add thread protection for DataSeries...
r594 dataSeries.lockRead();
Alexandre Leroux
Handles creations for scalar series
r169
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 // - Gets the data of the series included in the current range
Add mofif for clang format
r554 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
// and value data. The correct value is retrieved according to the index of the component
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r566 auto subDataIts = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
for (const auto &dataContainer : dataContainers) {
auto componentIndex = dataContainer.first;
dataContainer.second->appendGraphData(
QCPGraphData(it->x(), it->value(componentIndex)));
}
}
The mock plugin can now create data with view operation
r219
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 dataSeries.unlock();
Alexandre Leroux
Handles axes properties
r170
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 if (!plottables.empty()) {
auto plot = plottables.begin()->second->parentPlot();
Alexandre Leroux
Handles axes properties
r170
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 if (rescaleAxes) {
plot->rescaleAxes();
}
Alexandre Leroux
Handles axes properties
r170
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 plot->replot();
}
Alexandre Leroux
Handles creations for scalar series
r169 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 };
/**
* Helper used to create/update plottables
*/
struct IPlottablesHelper {
virtual ~IPlottablesHelper() noexcept = default;
virtual PlottablesMap create(QCustomPlot &plot) const = 0;
virtual void update(PlottablesMap &plottables, const SqpRange &range,
bool rescaleAxes = false) const = 0;
};
/**
* Default implementation of IPlottablesHelper, which takes data series to create/update plottables
* @tparam T the data series' type
*/
template <typename T>
struct PlottablesHelper : public IPlottablesHelper {
explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
PlottablesMap create(QCustomPlot &plot) const override
{
return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
Alexandre Leroux
Handles creations for scalar series
r169 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
{
PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
}
Alexandre Leroux
Handles creations for scalar series
r169
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 T &m_DataSeries;
};
Alexandre Leroux
Handles creations for scalar series
r169
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 /// Creates IPlottablesHelper according to a data series
Alexandre Leroux
Uses std::shared_ptr
r551 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
Initialisation of the graph range at creation in a new graphe, or inside...
r518 {
Alexandre Leroux
Uses std::shared_ptr
r551 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
}
Alexandre Leroux
Uses std::shared_ptr
r551 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
Initialisation of the graph range at creation in a new graphe, or inside...
r518 }
else {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
Initialisation of the graph range at creation in a new graphe, or inside...
r518 }
}
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 } // namespace
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
QCustomPlot &plot) noexcept
{
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 if (variable) {
Alexandre Leroux
Uses std::shared_ptr
r551 auto helper = createHelper(variable->dataSeries());
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 auto plottables = helper->create(plot);
return plottables;
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 }
else {
Correction for pull request
r227 qCDebug(LOG_VisualizationGraphHelper())
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 << QObject::tr("Can't create graph plottables : the variable is null");
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 return PlottablesMap{};
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r168 }
}
The mock plugin can now create data with view operation
r219
Alexandre Leroux
Uses std::shared_ptr
r551 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
std::shared_ptr<IDataSeries> dataSeries,
The dataSeries of a variable is now shared istead of uniq to avoid...
r513 const SqpRange &dateTime)
The mock plugin can now create data with view operation
r219 {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r547 auto helper = createHelper(dataSeries);
helper->update(plottables, dateTime);
The mock plugin can now create data with view operation
r219 }