##// END OF EJS Templates
Add satic method to compute vector of in or not in ranges between...
perrinel -
r816:97f935302b90
parent child
Show More
@@ -1,83 +1,89
1 1 #ifndef SCIQLOP_VARIABLE_H
2 2 #define SCIQLOP_VARIABLE_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/DataSeriesIterator.h>
7 7 #include <Data/SqpRange.h>
8 8
9 9 #include <QLoggingCategory>
10 10 #include <QObject>
11 11
12 12 #include <Common/MetaTypes.h>
13 13 #include <Common/spimpl.h>
14 14
15 15 Q_DECLARE_LOGGING_CATEGORY(LOG_Variable)
16 16
17 17 class IDataSeries;
18 18 class QString;
19 19
20 20 /**
21 21 * @brief The Variable class represents a variable in SciQlop.
22 22 */
23 23 class SCIQLOP_CORE_EXPORT Variable : public QObject {
24 24
25 25 Q_OBJECT
26 26
27 27 public:
28 28 explicit Variable(const QString &name, const QVariantHash &metadata = {});
29 29
30 30 /// Copy ctor
31 31 explicit Variable(const Variable &other);
32 32
33 33 std::shared_ptr<Variable> clone() const;
34 34
35 35 QString name() const noexcept;
36 36 void setName(const QString &name) noexcept;
37 37 SqpRange range() const noexcept;
38 38 void setRange(const SqpRange &range) noexcept;
39 39 SqpRange cacheRange() const noexcept;
40 40 void setCacheRange(const SqpRange &cacheRange) noexcept;
41 41
42 42 /// @return the number of points hold by the variable. The number of points is updated each time
43 43 /// the data series changes
44 44 int nbPoints() const noexcept;
45 45
46 46 /// Returns the real range of the variable, i.e. the min and max x-axis values of the data
47 47 /// series between the range of the variable. The real range is updated each time the variable
48 48 /// range or the data series changed
49 49 /// @return the real range, invalid range if the data series is null or empty
50 50 /// @sa setDataSeries()
51 51 /// @sa setRange()
52 52 SqpRange realRange() const noexcept;
53 53
54 54 /// @return the data of the variable, nullptr if there is no data
55 55 std::shared_ptr<IDataSeries> dataSeries() const noexcept;
56 56
57 57 QVariantHash metadata() const noexcept;
58 58
59 59 bool contains(const SqpRange &range) const noexcept;
60 60 bool intersect(const SqpRange &range) const noexcept;
61 61 bool isInside(const SqpRange &range) const noexcept;
62 62
63 63 bool cacheContains(const SqpRange &range) const noexcept;
64 64 bool cacheIntersect(const SqpRange &range) const noexcept;
65 65 bool cacheIsInside(const SqpRange &range) const noexcept;
66 66
67 67 QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &range) const noexcept;
68 68 QVector<SqpRange> provideInCacheRangeList(const SqpRange &range) const noexcept;
69 69 void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept;
70 70
71 static QVector<SqpRange> provideNotInCacheRangeList(const SqpRange &oldRange,
72 const SqpRange &nextRange);
73
74 static QVector<SqpRange> provideInCacheRangeList(const SqpRange &oldRange,
75 const SqpRange &nextRange);
76
71 77 signals:
72 78 void updated();
73 79
74 80 private:
75 81 class VariablePrivate;
76 82 spimpl::unique_impl_ptr<VariablePrivate> impl;
77 83 };
78 84
79 85 // Required for using shared_ptr in signals/slots
80 86 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>)
81 87 SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >)
82 88
83 89 #endif // SCIQLOP_VARIABLE_H
@@ -1,315 +1,388
1 1 #include "Variable/Variable.h"
2 2
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpRange.h>
5 5
6 6 #include <QMutex>
7 7 #include <QReadWriteLock>
8 8 #include <QThread>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
11 11
12 12 struct Variable::VariablePrivate {
13 13 explicit VariablePrivate(const QString &name, const QVariantHash &metadata)
14 14 : m_Name{name},
15 15 m_Range{INVALID_RANGE},
16 16 m_CacheRange{INVALID_RANGE},
17 17 m_Metadata{metadata},
18 18 m_DataSeries{nullptr},
19 19 m_RealRange{INVALID_RANGE},
20 20 m_NbPoints{0}
21 21 {
22 22 }
23 23
24 24 VariablePrivate(const VariablePrivate &other)
25 25 : m_Name{other.m_Name},
26 26 m_Range{other.m_Range},
27 27 m_CacheRange{other.m_CacheRange},
28 28 m_Metadata{other.m_Metadata},
29 29 m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr},
30 30 m_RealRange{other.m_RealRange},
31 31 m_NbPoints{other.m_NbPoints}
32 32 {
33 33 }
34 34
35 35 void lockRead() { m_Lock.lockForRead(); }
36 36 void lockWrite() { m_Lock.lockForWrite(); }
37 37 void unlock() { m_Lock.unlock(); }
38 38
39 39 void purgeDataSeries()
40 40 {
41 41 if (m_DataSeries) {
42 42 m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd);
43 43 }
44 44 updateRealRange();
45 45 updateNbPoints();
46 46 }
47 47
48 48 void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; }
49 49
50 50 /// Updates real range according to current variable range and data series
51 51 void updateRealRange()
52 52 {
53 53 if (m_DataSeries) {
54 54 m_DataSeries->lockRead();
55 55 auto end = m_DataSeries->cend();
56 56 auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart);
57 57 auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd);
58 58
59 59 m_RealRange
60 60 = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x())
61 61 ? SqpRange{minXAxisIt->x(), maxXAxisIt->x()}
62 62 : INVALID_RANGE;
63 63 m_DataSeries->unlock();
64 64 }
65 65 else {
66 66 m_RealRange = INVALID_RANGE;
67 67 }
68 68 }
69 69
70 70 QString m_Name;
71 71
72 72 SqpRange m_Range;
73 73 SqpRange m_CacheRange;
74 74 QVariantHash m_Metadata;
75 75 std::shared_ptr<IDataSeries> m_DataSeries;
76 76 SqpRange m_RealRange;
77 77 int m_NbPoints;
78 78
79 79 QReadWriteLock m_Lock;
80 80 };
81 81
82 82 Variable::Variable(const QString &name, const QVariantHash &metadata)
83 83 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)}
84 84 {
85 85 }
86 86
87 87 Variable::Variable(const Variable &other)
88 88 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)}
89 89 {
90 90 }
91 91
92 92 std::shared_ptr<Variable> Variable::clone() const
93 93 {
94 94 return std::make_shared<Variable>(*this);
95 95 }
96 96
97 97 QString Variable::name() const noexcept
98 98 {
99 99 impl->lockRead();
100 100 auto name = impl->m_Name;
101 101 impl->unlock();
102 102 return name;
103 103 }
104 104
105 105 void Variable::setName(const QString &name) noexcept
106 106 {
107 107 impl->lockWrite();
108 108 impl->m_Name = name;
109 109 impl->unlock();
110 110 }
111 111
112 112 SqpRange Variable::range() const noexcept
113 113 {
114 114 impl->lockRead();
115 115 auto range = impl->m_Range;
116 116 impl->unlock();
117 117 return range;
118 118 }
119 119
120 120 void Variable::setRange(const SqpRange &range) noexcept
121 121 {
122 122 impl->lockWrite();
123 123 impl->m_Range = range;
124 124 impl->updateRealRange();
125 125 impl->unlock();
126 126 }
127 127
128 128 SqpRange Variable::cacheRange() const noexcept
129 129 {
130 130 impl->lockRead();
131 131 auto cacheRange = impl->m_CacheRange;
132 132 impl->unlock();
133 133 return cacheRange;
134 134 }
135 135
136 136 void Variable::setCacheRange(const SqpRange &cacheRange) noexcept
137 137 {
138 138 impl->lockWrite();
139 139 if (cacheRange != impl->m_CacheRange) {
140 140 impl->m_CacheRange = cacheRange;
141 impl->purgeDataSeries();
142 141 }
143 142 impl->unlock();
144 143 }
145 144
146 145 int Variable::nbPoints() const noexcept
147 146 {
148 147 return impl->m_NbPoints;
149 148 }
150 149
151 150 SqpRange Variable::realRange() const noexcept
152 151 {
153 152 return impl->m_RealRange;
154 153 }
155 154
156 155 void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
157 156 {
158 157 qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries"
159 158 << QThread::currentThread()->objectName();
160 159 if (!dataSeries) {
161 160 /// @todo ALX : log
162 161 return;
163 162 }
164 163
165 164 // Add or merge the data
166 165 impl->lockWrite();
167 166 if (!impl->m_DataSeries) {
168 167 impl->m_DataSeries = dataSeries->clone();
169 168 }
170 169 else {
171 170 impl->m_DataSeries->merge(dataSeries.get());
172 171 }
173 172 impl->purgeDataSeries();
174 173 impl->unlock();
175 174 }
176 175
176
177 177 std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept
178 178 {
179 179 impl->lockRead();
180 180 auto dataSeries = impl->m_DataSeries;
181 181 impl->unlock();
182 182
183 183 return dataSeries;
184 184 }
185 185
186 186 QVariantHash Variable::metadata() const noexcept
187 187 {
188 188 impl->lockRead();
189 189 auto metadata = impl->m_Metadata;
190 190 impl->unlock();
191 191 return metadata;
192 192 }
193 193
194 194 bool Variable::contains(const SqpRange &range) const noexcept
195 195 {
196 196 impl->lockRead();
197 197 auto res = impl->m_Range.contains(range);
198 198 impl->unlock();
199 199 return res;
200 200 }
201 201
202 202 bool Variable::intersect(const SqpRange &range) const noexcept
203 203 {
204 204
205 205 impl->lockRead();
206 206 auto res = impl->m_Range.intersect(range);
207 207 impl->unlock();
208 208 return res;
209 209 }
210 210
211 211 bool Variable::isInside(const SqpRange &range) const noexcept
212 212 {
213 213 impl->lockRead();
214 214 auto res = range.contains(SqpRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd});
215 215 impl->unlock();
216 216 return res;
217 217 }
218 218
219 219 bool Variable::cacheContains(const SqpRange &range) const noexcept
220 220 {
221 221 impl->lockRead();
222 222 auto res = impl->m_CacheRange.contains(range);
223 223 impl->unlock();
224 224 return res;
225 225 }
226 226
227 227 bool Variable::cacheIntersect(const SqpRange &range) const noexcept
228 228 {
229 229 impl->lockRead();
230 230 auto res = impl->m_CacheRange.intersect(range);
231 231 impl->unlock();
232 232 return res;
233 233 }
234 234
235 235 bool Variable::cacheIsInside(const SqpRange &range) const noexcept
236 236 {
237 237 impl->lockRead();
238 238 auto res = range.contains(SqpRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd});
239 239 impl->unlock();
240 240 return res;
241 241 }
242 242
243 243
244 244 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &range) const noexcept
245 245 {
246 246 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
247 247 auto notInCache = QVector<SqpRange>{};
248 248 if (impl->m_CacheRange != INVALID_RANGE) {
249 249
250 250 if (!this->cacheContains(range)) {
251 251 if (range.m_TEnd <= impl->m_CacheRange.m_TStart
252 252 || range.m_TStart >= impl->m_CacheRange.m_TEnd) {
253 253 notInCache << range;
254 254 }
255 255 else if (range.m_TStart < impl->m_CacheRange.m_TStart
256 256 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
257 257 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart};
258 258 }
259 259 else if (range.m_TStart < impl->m_CacheRange.m_TStart
260 260 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
261 261 notInCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TStart}
262 262 << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
263 263 }
264 264 else if (range.m_TStart < impl->m_CacheRange.m_TEnd) {
265 265 notInCache << SqpRange{impl->m_CacheRange.m_TEnd, range.m_TEnd};
266 266 }
267 267 else {
268 268 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
269 269 << QThread::currentThread();
270 270 }
271 271 }
272 272 }
273 273 else {
274 274 notInCache << range;
275 275 }
276 276
277 277 return notInCache;
278 278 }
279 279
280 280 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &range) const noexcept
281 281 {
282 282 // This code assume that cach in contigue. Can return 0 or 1 SqpRange
283 283
284 284 auto inCache = QVector<SqpRange>{};
285 285
286 286 if (impl->m_CacheRange != INVALID_RANGE) {
287 287
288 if (this->intersect(range)) {
288 if (this->cacheIntersect(range)) {
289 289 if (range.m_TStart <= impl->m_CacheRange.m_TStart
290 290 && range.m_TEnd >= impl->m_CacheRange.m_TStart
291 291 && range.m_TEnd < impl->m_CacheRange.m_TEnd) {
292 292 inCache << SqpRange{impl->m_CacheRange.m_TStart, range.m_TEnd};
293 293 }
294 294
295 295 else if (range.m_TStart >= impl->m_CacheRange.m_TStart
296 296 && range.m_TEnd <= impl->m_CacheRange.m_TEnd) {
297 297 inCache << range;
298 298 }
299 299 else if (range.m_TStart > impl->m_CacheRange.m_TStart
300 300 && range.m_TEnd > impl->m_CacheRange.m_TEnd) {
301 301 inCache << SqpRange{range.m_TStart, impl->m_CacheRange.m_TEnd};
302 302 }
303 303 else if (range.m_TStart <= impl->m_CacheRange.m_TStart
304 304 && range.m_TEnd >= impl->m_CacheRange.m_TEnd) {
305 305 inCache << impl->m_CacheRange;
306 306 }
307 307 else {
308 308 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
309 309 << QThread::currentThread();
310 310 }
311 311 }
312 312 }
313 313
314 314 return inCache;
315 315 }
316
317
318 QVector<SqpRange> Variable::provideNotInCacheRangeList(const SqpRange &oldRange,
319 const SqpRange &nextRange)
320 {
321
322 // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange
323 auto notInCache = QVector<SqpRange>{};
324 if (oldRange != INVALID_RANGE) {
325
326 if (!oldRange.contains(nextRange)) {
327 if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) {
328 notInCache << nextRange;
329 }
330 else if (nextRange.m_TStart < oldRange.m_TStart
331 && nextRange.m_TEnd <= oldRange.m_TEnd) {
332 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart};
333 }
334 else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
335 notInCache << SqpRange{nextRange.m_TStart, oldRange.m_TStart}
336 << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
337 }
338 else if (nextRange.m_TStart < oldRange.m_TEnd) {
339 notInCache << SqpRange{oldRange.m_TEnd, nextRange.m_TEnd};
340 }
341 else {
342 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
343 << QThread::currentThread();
344 }
345 }
346 }
347 else {
348 notInCache << nextRange;
349 }
350
351 return notInCache;
352 }
353
354 QVector<SqpRange> Variable::provideInCacheRangeList(const SqpRange &oldRange,
355 const SqpRange &nextRange)
356 {
357 // This code assume that cach is contigue. Can return 0 or 1 SqpRange
358
359 auto inCache = QVector<SqpRange>{};
360
361 if (oldRange != INVALID_RANGE) {
362
363 if (oldRange.intersect(nextRange)) {
364 if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart
365 && nextRange.m_TEnd < oldRange.m_TEnd) {
366 inCache << SqpRange{oldRange.m_TStart, nextRange.m_TEnd};
367 }
368
369 else if (nextRange.m_TStart >= oldRange.m_TStart
370 && nextRange.m_TEnd <= oldRange.m_TEnd) {
371 inCache << nextRange;
372 }
373 else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) {
374 inCache << SqpRange{nextRange.m_TStart, oldRange.m_TEnd};
375 }
376 else if (nextRange.m_TStart <= oldRange.m_TStart
377 && nextRange.m_TEnd >= oldRange.m_TEnd) {
378 inCache << oldRange;
379 }
380 else {
381 qCCritical(LOG_Variable()) << tr("Detection of unknown case.")
382 << QThread::currentThread();
383 }
384 }
385 }
386
387 return inCache;
388 }
General Comments 0
You need to be logged in to leave comments. Login now