##// END OF EJS Templates
Adds "number of operations" and "number of variables" properties for the tests
Adds "number of operations" and "number of variables" properties for the tests

File last commit:

r1110:0e96e473601d
r1170:3da18e6983d5
Show More
AxisRenderingUtils.cpp
177 lines | 5.8 KiB | text/x-c | CppLexer
#include "Visualization/AxisRenderingUtils.h"
#include <Data/ScalarSeries.h>
#include <Data/SpectrogramSeries.h>
#include <Data/VectorSeries.h>
#include <Visualization/SqpColorScale.h>
#include <Visualization/qcustomplot.h>
Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
namespace {
const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
/// Format for datetimes on a axis
const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
const auto NUMBER_FORMAT = 'g';
const auto NUMBER_PRECISION = 9;
/// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
/// non-time data
QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
{
if (isTimeAxis) {
auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
dateTicker->setDateTimeSpec(Qt::UTC);
return dateTicker;
}
else if (scaleType == QCPAxis::stLogarithmic) {
return QSharedPointer<QCPAxisTickerLog>::create();
}
else {
// default ticker
return QSharedPointer<QCPAxisTicker>::create();
}
}
/**
* Sets properties of the axis passed as parameter
* @param axis the axis to set
* @param unit the unit to set for the axis
* @param scaleType the scale type to set for the axis
*/
void setAxisProperties(QCPAxis &axis, const Unit &unit,
QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
{
// label (unit name)
axis.setLabel(unit.m_Name);
// scale type
axis.setScaleType(scaleType);
if (scaleType == QCPAxis::stLogarithmic) {
// Scientific notation
axis.setNumberPrecision(0);
axis.setNumberFormat("eb");
}
// ticker (depending on the type of unit)
axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
}
/**
* Delegate used to set axes properties
*/
template <typename T, typename Enabled = void>
struct AxisSetter {
static void setProperties(T &, QCustomPlot &, SqpColorScale &)
{
// Default implementation does nothing
qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
}
};
/**
* Specialization of AxisSetter for scalars and vectors
* @sa ScalarSeries
* @sa VectorSeries
*/
template <typename T>
struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
or std::is_base_of<VectorSeries, T>::value> > {
static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
{
dataSeries.lockRead();
auto xAxisUnit = dataSeries.xAxisUnit();
auto valuesUnit = dataSeries.valuesUnit();
dataSeries.unlock();
setAxisProperties(*plot.xAxis, xAxisUnit);
setAxisProperties(*plot.yAxis, valuesUnit);
}
};
/**
* Specialization of AxisSetter for spectrograms
* @sa SpectrogramSeries
*/
template <typename T>
struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
{
dataSeries.lockRead();
auto xAxisUnit = dataSeries.xAxisUnit();
auto yAxisUnit = dataSeries.yAxisUnit();
auto valuesUnit = dataSeries.valuesUnit();
dataSeries.unlock();
setAxisProperties(*plot.xAxis, xAxisUnit);
setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
// Displays color scale in plot
plot.plotLayout()->insertRow(0);
plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
colorScale.m_Scale->setType(QCPAxis::atTop);
colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
// Aligns color scale with axes
auto marginGroups = plot.axisRect()->marginGroups();
for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
colorScale.m_Scale->setMarginGroup(it.key(), it.value());
}
// Set color scale properties
setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
colorScale.m_AutomaticThreshold = true;
}
};
/**
* Default implementation of IAxisHelper, which takes data series to set axes properties
* @tparam T the data series' type
*/
template <typename T>
struct AxisHelper : public IAxisHelper {
explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
{
AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
}
T &m_DataSeries;
};
} // namespace
QString formatValue(double value, const QCPAxis &axis)
{
// If the axis is a time axis, formats the value as a date
if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
}
else {
return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
}
}
std::unique_ptr<IAxisHelper>
IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
{
if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
}
else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
}
else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
}
else {
return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
}
}