#include "Data/DataSeriesUtils.h" Q_LOGGING_CATEGORY(LOG_DataSeriesUtils, "DataSeriesUtils") void DataSeriesUtils::fillDataHoles(std::vector &xAxisData, std::vector &valuesData, double resolution, double fillValue, double minBound, double maxBound) { if (resolution == 0. || std::isnan(resolution)) { qCWarning(LOG_DataSeriesUtils()) << "Can't fill data holes with a null resolution, no changes will be made"; return; } if (xAxisData.empty()) { qCWarning(LOG_DataSeriesUtils()) << "Can't fill data holes for empty data, no changes will be made"; return; } // Gets the number of values per x-axis data auto nbComponents = valuesData.size() / xAxisData.size(); // Generates fill values that will be used to complete values data std::vector fillValues(nbComponents, fillValue); // Checks if there are data holes on the beginning of the data and generates the hole at the // extremity if it's the case auto minXAxisData = xAxisData.front(); if (!std::isnan(minBound) && minBound < minXAxisData) { auto holeSize = static_cast((minXAxisData - minBound) / resolution); if (holeSize > 0) { xAxisData.insert(xAxisData.begin(), minXAxisData - holeSize * resolution); valuesData.insert(valuesData.begin(), fillValues.begin(), fillValues.end()); } } // Same for the end of the data auto maxXAxisData = xAxisData.back(); if (!std::isnan(maxBound) && maxBound > maxXAxisData) { auto holeSize = static_cast((maxBound - maxXAxisData) / resolution); if (holeSize > 0) { xAxisData.insert(xAxisData.end(), maxXAxisData + holeSize * resolution); valuesData.insert(valuesData.end(), fillValues.begin(), fillValues.end()); } } // Generates other data holes auto xAxisIt = xAxisData.begin(); while (xAxisIt != xAxisData.end()) { // Stops at first value which has a gap greater than resolution with the value next to it xAxisIt = std::adjacent_find( xAxisIt, xAxisData.end(), [resolution](const auto &a, const auto &b) { return (b - a) > resolution; }); if (xAxisIt != xAxisData.end()) { auto nextXAxisIt = xAxisIt + 1; // Gets the values that has a gap greater than resolution between them auto lowValue = *xAxisIt; auto highValue = *nextXAxisIt; // Completes holes between the two values by creating new values (according to the // resolution) for (auto i = lowValue + resolution; i < highValue; i += resolution) { // Gets the iterator of values data from which to insert fill values auto nextValuesIt = valuesData.begin() + std::distance(xAxisData.begin(), nextXAxisIt) * nbComponents; // New value is inserted before nextXAxisIt nextXAxisIt = xAxisData.insert(nextXAxisIt, i) + 1; // New values are inserted before nextValuesIt valuesData.insert(nextValuesIt, fillValues.begin(), fillValues.end()); } // Moves to the next value to continue loop on the x-axis data xAxisIt = nextXAxisIt; } } }