VisualizationGraphHelper.cpp
163 lines
| 5.7 KiB
| text/x-c
|
CppLexer
r243 | #include "Visualization/VisualizationGraphHelper.h" | |||
|
r181 | #include "Visualization/qcustomplot.h" | ||
|
r182 | #include <Data/ScalarSeries.h> | ||
|
r181 | #include <Variable/Variable.h> | ||
r243 | Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper") | |||
|
r181 | |||
|
r182 | namespace { | ||
r364 | class SqpDataContainer : public QCPGraphDataContainer { | |||
public: | ||||
|
r453 | void appendGraphData(const QCPGraphData &data) { mData.append(data); } | ||
r364 | }; | |||
|
r183 | /// 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); | ||||
|
r490 | dateTicker->setDateTimeSpec(Qt::UTC); | ||
|
r183 | |||
return dateTicker; | ||||
} | ||||
else { | ||||
// default ticker | ||||
return QSharedPointer<QCPAxisTicker>::create(); | ||||
} | ||||
} | ||||
|
r182 | |||
r542 | void updateScalarData(QCPAbstractPlottable *component, std::shared_ptr<ScalarSeries> scalarSeries, | |||
r512 | const SqpRange &dateTime) | |||
r235 | { | |||
r367 | qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData" | |||
<< QThread::currentThread()->objectName(); | ||||
r235 | if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) { | |||
r542 | scalarSeries->lockRead(); | |||
r364 | { | |||
r542 | const auto &xData = scalarSeries->xAxisData()->cdata(); | |||
const auto &valuesData = scalarSeries->valuesData()->cdata(); | ||||
|
r453 | |||
auto xDataBegin = xData.cbegin(); | ||||
auto xDataEnd = xData.cend(); | ||||
r542 | qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points in cache" | |||
r471 | << xData.count(); | |||
|
r453 | |||
r364 | auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create(); | |||
qcpGraph->setData(sqpDataContainer); | ||||
|
r453 | auto lowerIt = std::lower_bound(xDataBegin, xDataEnd, dateTime.m_TStart); | ||
auto upperIt = std::upper_bound(xDataBegin, xDataEnd, dateTime.m_TEnd); | ||||
auto distance = std::distance(xDataBegin, lowerIt); | ||||
auto valuesDataIt = valuesData.cbegin() + distance; | ||||
for (auto xAxisDataIt = lowerIt; xAxisDataIt != upperIt; | ||||
++xAxisDataIt, ++valuesDataIt) { | ||||
sqpDataContainer->appendGraphData(QCPGraphData(*xAxisDataIt, *valuesDataIt)); | ||||
r235 | } | |||
|
r453 | |||
r542 | qCInfo(LOG_VisualizationGraphHelper()) << "TODEBUG: Current points displayed" | |||
r471 | << sqpDataContainer->size(); | |||
r235 | } | |||
r542 | scalarSeries->unlock(); | |||
r235 | ||||
r315 | ||||
// Display all data | ||||
component->parentPlot()->replot(); | ||||
r235 | } | |||
else { | ||||
/// @todo DEBUG | ||||
} | ||||
} | ||||
r542 | QCPAbstractPlottable *createScalarSeriesComponent(std::shared_ptr<ScalarSeries> scalarSeries, | |||
QCustomPlot &plot, const SqpRange &dateTime) | ||||
|
r182 | { | ||
auto component = plot.addGraph(); | ||||
if (component) { | ||||
r235 | // // Graph data | |||
r542 | component->setData(scalarSeries->xAxisData()->data(), scalarSeries->valuesData()->data(), | |||
|
r182 | true); | ||
r235 | updateScalarData(component, scalarSeries, dateTime); | |||
|
r183 | // Axes properties | ||
/// @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)); | ||||
}; | ||||
r542 | setAxisProperties(plot.xAxis, scalarSeries->xAxisUnit()); | |||
setAxisProperties(plot.yAxis, scalarSeries->valuesUnit()); | ||||
|
r183 | |||
|
r182 | // Display all data | ||
component->rescaleAxes(); | ||||
plot.replot(); | ||||
} | ||||
else { | ||||
r243 | qCDebug(LOG_VisualizationGraphHelper()) | |||
|
r182 | << QObject::tr("Can't create graph for the scalar series"); | ||
} | ||||
return component; | ||||
} | ||||
} // namespace | ||||
r243 | QVector<QCPAbstractPlottable *> VisualizationGraphHelper::create(std::shared_ptr<Variable> variable, | |||
QCustomPlot &plot) noexcept | ||||
|
r181 | { | ||
auto result = QVector<QCPAbstractPlottable *>{}; | ||||
if (variable) { | ||||
|
r182 | // Gets the data series of the variable to call the creation of the right components | ||
// according to its type | ||||
r542 | if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(variable->dataSeries())) { | |||
result.append(createScalarSeriesComponent(scalarSeries, plot, variable->range())); | ||||
|
r182 | } | ||
else { | ||||
r243 | qCDebug(LOG_VisualizationGraphHelper()) | |||
|
r182 | << QObject::tr("Can't create graph plottables : unmanaged data series type"); | ||
} | ||||
|
r181 | } | ||
else { | ||||
r243 | qCDebug(LOG_VisualizationGraphHelper()) | |||
|
r181 | << QObject::tr("Can't create graph plottables : the variable is null"); | ||
} | ||||
return result; | ||||
} | ||||
r235 | ||||
r243 | void VisualizationGraphHelper::updateData(QVector<QCPAbstractPlottable *> plotableVect, | |||
r542 | std::shared_ptr<IDataSeries> dataSeries, | |||
const SqpRange &dateTime) | ||||
r235 | { | |||
r542 | if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) { | |||
r235 | if (plotableVect.size() == 1) { | |||
r542 | updateScalarData(plotableVect.at(0), scalarSeries, dateTime); | |||
r235 | } | |||
else { | ||||
r243 | qCCritical(LOG_VisualizationGraphHelper()) << QObject::tr( | |||
r235 | "Can't update Data of a scalarSeries because there is not only one component " | |||
"associated"); | ||||
} | ||||
} | ||||
else { | ||||
/// @todo DEBUG | ||||
} | ||||
} | ||||