@@ -3,6 +3,8 | |||
|
3 | 3 | |
|
4 | 4 | #include "CoreGlobal.h" |
|
5 | 5 | |
|
6 | #include <Data/DataSeriesIterator.h> | |
|
7 | ||
|
6 | 8 | #include <QLoggingCategory> |
|
7 | 9 | |
|
8 | 10 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils) |
@@ -154,6 +156,46 struct SCIQLOP_CORE_EXPORT DataSeriesUtils { | |||
|
154 | 156 | */ |
|
155 | 157 | template <typename Iterator> |
|
156 | 158 | static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false); |
|
159 | ||
|
160 | /** | |
|
161 | * Computes a regular mesh for a data series, according to resolutions for x-axis and y-axis | |
|
162 | * passed as parameters. | |
|
163 | * | |
|
164 | * The mesh is created from the resolutions in x and y and the boundaries delimiting the data | |
|
165 | * series. If the resolutions do not allow to obtain a regular mesh, they are recalculated. | |
|
166 | * | |
|
167 | * For example : | |
|
168 | * Let x-axis data = [0, 1, 3, 5, 9], its associated values = [0, 10, 30, 50, 90] and | |
|
169 | * xResolution = 2. | |
|
170 | * Based on the resolution, the mesh would be [0, 2, 4, 6, 8, 10] and would be invalid because | |
|
171 | * it exceeds the maximum bound of the data. The resolution is thus recalculated so that the | |
|
172 | * mesh holds between the data terminals. | |
|
173 | * So => resolution is 1.8 and the mesh is [0, 1.8, 3.6, 5.4, 7.2, 9]. | |
|
174 | * | |
|
175 | * Once the mesh is generated in x and y, the values are associated with each mesh point, | |
|
176 | * based on the data in the series, finding the existing data at which the mesh point would be | |
|
177 | * or would be closest to, without exceeding it. | |
|
178 | * | |
|
179 | * In the example, we determine the value of each mesh point: | |
|
180 | * - x = 0 => value = 0 (existing x in the data series) | |
|
181 | * - x = 1.8 => value = 10 (the closest existing x: 1) | |
|
182 | * - x = 3.6 => value = 30 (the closest existing x: 3) | |
|
183 | * - x = 5.4 => value = 50 (the closest existing x: 5) | |
|
184 | * - x = 7.2 => value = 50 (the closest existing x: 5) | |
|
185 | * - x = 9 => value = 90 (existing x in the data series) | |
|
186 | * | |
|
187 | * Same algorithm is applied for y-axis. | |
|
188 | * | |
|
189 | * @param begin the iterator pointing to the beginning of the data series | |
|
190 | * @param end the iterator pointing to the end of the data series | |
|
191 | * @param xResolution the resolution expected for the mesh's x-axis | |
|
192 | * @param yResolution the resolution expected for the mesh's y-axis | |
|
193 | * @return the mesh created, an empty mesh if the input data do not allow to generate a regular | |
|
194 | * mesh (empty data, null resolutions, logarithmic x-axis) | |
|
195 | * @warning the method considers the dataset as sorted and doesn't control it. | |
|
196 | */ | |
|
197 | static Mesh regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |
|
198 | Resolution xResolution, Resolution yResolution); | |
|
157 | 199 | }; |
|
158 | 200 | |
|
159 | 201 | template <typename Iterator> |
@@ -1,5 +1,7 | |||
|
1 | 1 | #include "Data/DataSeriesUtils.h" |
|
2 | 2 | |
|
3 | #include <cmath> | |
|
4 | ||
|
3 | 5 | Q_LOGGING_CATEGORY(LOG_DataSeriesUtils, "DataSeriesUtils") |
|
4 | 6 | |
|
5 | 7 | void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData, |
@@ -79,3 +81,36 void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector< | |||
|
79 | 81 | } |
|
80 | 82 | } |
|
81 | 83 | } |
|
84 | DataSeriesUtils::Mesh DataSeriesUtils::regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |
|
85 | Resolution xResolution, Resolution yResolution) | |
|
86 | { | |
|
87 | // Checks preconditions | |
|
88 | if (xResolution.m_Val == 0. || std::isnan(xResolution.m_Val) || yResolution.m_Val == 0. | |
|
89 | || std::isnan(yResolution.m_Val)) { | |
|
90 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh with a null resolution"; | |
|
91 | return Mesh{}; | |
|
92 | } | |
|
93 | ||
|
94 | if (xResolution.m_Logarithmic) { | |
|
95 | qCWarning(LOG_DataSeriesUtils()) | |
|
96 | << "Can't generate mesh with a logarithmic x-axis resolution"; | |
|
97 | return Mesh{}; | |
|
98 | } | |
|
99 | ||
|
100 | if (std::distance(begin, end) == 0) { | |
|
101 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for empty data"; | |
|
102 | return Mesh{}; | |
|
103 | } | |
|
104 | ||
|
105 | auto yData = begin->y(); | |
|
106 | if (yData.empty()) { | |
|
107 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for data with no y-axis"; | |
|
108 | return Mesh{}; | |
|
109 | } | |
|
110 | ||
|
111 | // Converts y-axis and its resolution to logarithmic values | |
|
112 | if (yResolution.m_Logarithmic) { | |
|
113 | std::for_each(yData.begin(), yData.end(), [](auto &val) { val = std::log10(val); }); | |
|
114 | } | |
|
115 | ||
|
116 | } |
General Comments 0
You need to be logged in to leave comments.
Login now