QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsrange.h
Go to the documentation of this file.
1/***************************************************************************
2 qgsrange.h
3 ----------
4 begin : April 2017
5 copyright : (C) 2017 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#ifndef QGSRANGE_H
19#define QGSRANGE_H
20
21#include "qgis_sip.h"
22#include "qgis_core.h"
23#include "qgis.h"
24
25#include <QDate>
26#include <QDateTime>
27
44template <typename T>
46{
47 public:
48
53 QgsRange( T lower, T upper, bool includeLower = true, bool includeUpper = true )
54 : mLower( lower )
55 , mUpper( upper )
58 {}
59
67 : mLower( lower )
68 , mUpper( upper )
69 , mIncludeLower( limits == Qgis::RangeLimits::IncludeLowerExcludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
70 , mIncludeUpper( limits == Qgis::RangeLimits::ExcludeLowerIncludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
71 {}
72
78 T lower() const { return mLower; }
79
85 T upper() const { return mUpper; }
86
93 bool includeLower() const { return mIncludeLower; }
94
101 bool includeUpper() const { return mIncludeUpper; }
102
109 {
112 else if ( mIncludeLower && !mIncludeUpper )
114 else if ( !mIncludeLower && mIncludeUpper )
116 else
118 }
119
125 bool isEmpty() const { return mLower > mUpper || ( mUpper == mLower && !( mIncludeLower || mIncludeUpper ) ); }
126
131 bool isSingleton() const { return mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
132
137 bool contains( const QgsRange<T> &other ) const
138 {
139 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
140 || ( !mIncludeLower && mLower < other.mLower )
141 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
142 if ( !lowerOk )
143 return false;
144
145 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
146 || ( !mIncludeUpper && mUpper > other.mUpper )
147 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
148 if ( !upperOk )
149 return false;
150
151 return true;
152 }
153
157 bool contains( T element ) const
158 {
159 const bool lowerOk = ( mIncludeLower && mLower <= element )
160 || ( !mIncludeLower && mLower < element );
161 if ( !lowerOk )
162 return false;
163
164 const bool upperOk = ( mIncludeUpper && mUpper >= element )
165 || ( !mIncludeUpper && mUpper > element );
166 if ( !upperOk )
167 return false;
168
169 return true;
170 }
171
176 bool overlaps( const QgsRange<T> &other ) const
177 {
178 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
179 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
180 return true;
181
182 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
183 && ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
184 return true;
185
186 if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
187 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
188 return true;
189
190 if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
191 && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
192 return true;
193
194 if ( mLower == other.mLower && mUpper == other.mUpper )
195 return true;
196
197 return false;
198 }
199
200 bool operator==( const QgsRange<T> &other ) const
201 {
202 return mLower == other.mLower &&
203 mUpper == other.mUpper &&
204 mIncludeLower == other.includeLower() &&
205 mIncludeUpper == other.includeUpper();
206 }
207
208 bool operator!=( const QgsRange<T> &other ) const
209 {
210 return ( ! operator==( other ) );
211 }
212
213 protected:
214
217 bool mIncludeLower = true;
218 bool mIncludeUpper = true;
219
220};
221
222
230class CORE_EXPORT QgsDoubleRange : public QgsRange< double >
231{
232 public:
233
240 QgsDoubleRange( double lower, double upper, Qgis::RangeLimits limits )
241 : QgsRange( lower, upper, limits )
242 {}
243
244#ifndef SIP_RUN
245
254 QgsDoubleRange( double lower = std::numeric_limits< double >::lowest(),
255 double upper = std::numeric_limits< double >::max(),
256 bool includeLower = true, bool includeUpper = true )
257 : QgsRange( lower, upper, includeLower, includeUpper )
258 {}
259#else
260
265 QgsDoubleRange( double lower,
266 double upper,
267 bool includeLower = true, bool includeUpper = true )
268 : QgsRange( lower, upper, includeLower, includeUpper )
269 {}
270
277 : QgsRange( std::numeric_limits< double >::lowest(), std::numeric_limits< double >::max(), true, true )
278 {}
279#endif
280
285 bool isInfinite() const
286 {
287 return lower() == std::numeric_limits< double >::lowest() && upper() == std::numeric_limits< double >::max();
288 }
289
290#ifdef SIP_RUN
291 SIP_PYOBJECT __repr__();
292 % MethodCode
293 QString str = QStringLiteral( "<QgsDoubleRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
294 .arg( sipCpp->lower() )
295 .arg( sipCpp->upper() )
296 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
297 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
298 % End
299#endif
300
301 bool operator==( const QgsDoubleRange &other ) const
302 {
303 return qgsDoubleNear( mLower, other.mLower ) &&
304 qgsDoubleNear( mUpper, other.mUpper ) &&
305 mIncludeLower == other.includeLower() &&
306 mIncludeUpper == other.includeUpper();
307 }
308
309 bool operator!=( const QgsDoubleRange &other ) const
310 {
311 return ( ! operator==( other ) );
312 }
313
314};
315
317
318
319
326class CORE_EXPORT QgsIntRange : public QgsRange< int >
327{
328 public:
329
336 QgsIntRange( int lower, int upper, Qgis::RangeLimits limits )
337 : QgsRange( lower, upper, limits )
338 {}
339
340#ifndef SIP_RUN
341
350 QgsIntRange( int lower = std::numeric_limits< int >::lowest(),
351 int upper = std::numeric_limits< int >::max(),
352 bool includeLower = true, bool includeUpper = true )
353 : QgsRange( lower, upper, includeLower, includeUpper )
354 {}
355#else
356
361 QgsIntRange( int lower,
362 int upper,
363 bool includeLower = true, bool includeUpper = true )
364 : QgsRange( lower, upper, includeLower, includeUpper )
365 {}
366
373 : QgsRange( std::numeric_limits< int >::lowest(), std::numeric_limits< int >::max(), true, true )
374 {}
375#endif
376
381 bool isInfinite() const
382 {
383 return lower() == std::numeric_limits< int >::lowest() && upper() == std::numeric_limits< int >::max();
384 }
385
386#ifdef SIP_RUN
387 SIP_PYOBJECT __repr__();
388 % MethodCode
389 QString str = QStringLiteral( "<QgsIntRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
390 .arg( sipCpp->lower() )
391 .arg( sipCpp->upper() )
392 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
393 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
394 % End
395#endif
396
397};
398
400
401
402
417template <typename T>
419{
420 public:
421
427#ifndef SIP_RUN
428 QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
429 : mLower( begin )
430 , mUpper( end )
431 , mIncludeLower( includeBeginning )
432 , mIncludeUpper( includeEnd )
433 {}
434#else
435 QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
436 // default constructor as default value for templates is not handled in SIP
437#endif
438
444 T begin() const { return mLower; }
445
451 T end() const { return mUpper; }
452
459 bool includeBeginning() const { return mIncludeLower; }
460
466 bool includeEnd() const { return mIncludeUpper; }
467
473 bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
474
480 bool isInfinite() const
481 {
482 return !mLower.isValid() && !mUpper.isValid();
483 }
484
490 bool isEmpty() const
491 {
492 if ( !mLower.isValid() && !mUpper.isValid() )
493 return false;
494
495 if ( mLower.isValid() != mUpper.isValid() )
496 return false;
497
498 if ( mLower > mUpper )
499 return true;
500
501 if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
502 return true;
503
504 return false;
505 }
506
510 bool contains( const QgsTemporalRange<T> &other ) const
511 {
512 if ( !other.mLower.isValid() && mLower.isValid() )
513 return false;
514
515 if ( mLower.isValid() )
516 {
517 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
518 || ( !mIncludeLower && mLower < other.mLower )
519 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
520 if ( !lowerOk )
521 return false;
522 }
523
524 if ( !other.mUpper.isValid() && mUpper.isValid() )
525 return false;
526
527 if ( mUpper.isValid() )
528 {
529 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
530 || ( !mIncludeUpper && mUpper > other.mUpper )
531 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
532 if ( !upperOk )
533 return false;
534 }
535
536 return true;
537 }
538
542 bool contains( const T &element ) const
543 {
544 if ( !element.isValid() )
545 return false;
546
547 if ( mLower.isValid() )
548 {
549 const bool lowerOk = ( mIncludeLower && mLower <= element )
550 || ( !mIncludeLower && mLower < element );
551 if ( !lowerOk )
552 return false;
553 }
554
555 if ( mUpper.isValid() )
556 {
557 const bool upperOk = ( mIncludeUpper && mUpper >= element )
558 || ( !mIncludeUpper && mUpper > element );
559 if ( !upperOk )
560 return false;
561 }
562
563 return true;
564 }
565
569 bool overlaps( const QgsTemporalRange<T> &other ) const
570 {
571 if ( !mUpper.isValid() && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
572 return true;
573
574 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
575 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
576 return true;
577
578 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
579 && ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
580 return true;
581
582 if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
583 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
584 return true;
585
586 if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
587 && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
588 return true;
589
590 if ( mLower == other.mLower && mUpper == other.mUpper )
591 return true;
592
593 return false;
594 }
595
604 bool extend( const QgsTemporalRange<T> &other )
605 {
606 if ( other.isEmpty() )
607 {
608 return false;
609 }
610 else if ( isEmpty() )
611 {
612 mLower = other.begin();
613 mUpper = other.end();
614 mIncludeLower = other.includeBeginning();
615 mIncludeUpper = other.includeEnd();
616 return true;
617 }
618
619 // Both not empty, do some math
620 bool changed { false };
621
622 // Lower
623 if ( ! other.begin().isValid()
624 || ( begin().isValid() && other.begin() < mLower ) )
625 {
626 mLower = other.begin();
627 mIncludeLower = other.includeBeginning();
628 changed = true;
629 }
630 else if ( other.begin() == mLower && other.includeBeginning() && ! mIncludeLower )
631 {
632 mIncludeLower = true;
633 changed = true;
634 }
635
636 // Upper
637 if ( ! other.end().isValid()
638 || ( end().isValid() && other.end() > mUpper ) )
639 {
640 mUpper = other.end();
641 mIncludeUpper = other.includeEnd();
642 changed = true;
643 }
644 else if ( other.end() == mUpper && other.includeEnd() && ! mIncludeUpper )
645 {
646 mIncludeUpper = true;
647 changed = true;
648 }
649 return changed;
650 }
651
652#ifndef SIP_RUN
653
667 static QList< QgsTemporalRange<T> > mergeRanges( const QList< QgsTemporalRange<T> > &ranges )
668 {
669 if ( ranges.empty() )
670 return {};
671
672 QList< QgsTemporalRange<T > > sortedRanges = ranges;
673 // cppcheck-suppress mismatchingContainerExpression
674 std::sort( sortedRanges.begin(), sortedRanges.end(), []( const QgsTemporalRange< T > &a, const QgsTemporalRange< T > &b ) -> bool { return a.begin() < b.begin(); } );
675 QList< QgsTemporalRange<T>> res;
676 res.reserve( sortedRanges.size() );
677
678 QgsTemporalRange<T> prevRange;
679 auto it = sortedRanges.constBegin();
680 prevRange = *it++;
681 for ( ; it != sortedRanges.constEnd(); ++it )
682 {
683 if ( prevRange.overlaps( *it ) )
684 {
685 prevRange.extend( *it );
686 }
687 else
688 {
689 res << prevRange;
690 prevRange = *it;
691 }
692 }
693 res << prevRange;
694 return res;
695 }
696#endif
697
698 bool operator==( const QgsTemporalRange<T> &other ) const
699 {
700 return mLower == other.mLower &&
701 mUpper == other.mUpper &&
702 mIncludeLower == other.includeBeginning() &&
703 mIncludeUpper == other.includeEnd();
704 }
705
706 bool operator!=( const QgsTemporalRange<T> &other ) const
707 {
708 return ( ! operator==( other ) );
709 }
710
711 private:
712
713 T mLower;
714 T mUpper;
715 bool mIncludeLower = true;
716 bool mIncludeUpper = true;
717};
718
719
730
732
733
743
745
746#endif // QGSRANGE_H
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:54
RangeLimits
Describes how the limits of a range are handled.
Definition: qgis.h:3263
@ ExcludeLowerIncludeUpper
Lower value is excluded from the range, upper value in inccluded.
@ IncludeBoth
Both lower and upper values are included in the range.
@ ExcludeBoth
Both lower and upper values are excluded from the range.
@ IncludeLowerExcludeUpper
Lower value is included in the range, upper value is excluded.
QgsRange which stores a range of double values.
Definition: qgsrange.h:231
QgsDoubleRange(double lower, double upper, Qgis::RangeLimits limits)
Constructor for QgsDoubleRange.
Definition: qgsrange.h:240
QgsDoubleRange(double lower=std::numeric_limits< double >::lowest(), double upper=std::numeric_limits< double >::max(), bool includeLower=true, bool includeUpper=true)
Constructor for QgsDoubleRange.
Definition: qgsrange.h:254
bool operator==(const QgsDoubleRange &other) const
Definition: qgsrange.h:301
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:285
bool operator!=(const QgsDoubleRange &other) const
Definition: qgsrange.h:309
QgsRange which stores a range of integer values.
Definition: qgsrange.h:327
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:381
QgsIntRange(int lower, int upper, Qgis::RangeLimits limits)
Constructor for QgsIntRange.
Definition: qgsrange.h:336
QgsIntRange(int lower=std::numeric_limits< int >::lowest(), int upper=std::numeric_limits< int >::max(), bool includeLower=true, bool includeUpper=true)
Constructor for QgsIntRange.
Definition: qgsrange.h:350
A template based class for storing ranges (lower to upper values).
Definition: qgsrange.h:46
bool mIncludeLower
Definition: qgsrange.h:217
QgsRange(T lower, T upper, Qgis::RangeLimits limits)
Constructor for QgsRange.
Definition: qgsrange.h:66
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
Definition: qgsrange.h:101
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:176
Qgis::RangeLimits rangeLimits() const
Returns the limit handling of the range.
Definition: qgsrange.h:108
QgsRange(T lower, T upper, bool includeLower=true, bool includeUpper=true)
Constructor for QgsRange.
Definition: qgsrange.h:53
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:137
T lower() const
Returns the lower bound of the range.
Definition: qgsrange.h:78
bool includeLower() const
Returns true if the lower bound is inclusive, or false if the lower bound is exclusive.
Definition: qgsrange.h:93
bool mIncludeUpper
Definition: qgsrange.h:218
T upper() const
Returns the upper bound of the range.
Definition: qgsrange.h:85
bool isSingleton() const
Returns true if the range consists only of a single value or instant.
Definition: qgsrange.h:131
T mUpper
Definition: qgsrange.h:216
bool operator!=(const QgsRange< T > &other) const
Definition: qgsrange.h:208
bool contains(T element) const
Returns true if this range contains a specified element.
Definition: qgsrange.h:157
bool operator==(const QgsRange< T > &other) const
Definition: qgsrange.h:200
bool isEmpty() const
Returns true if the range is empty, ie the lower bound equals (or exceeds) the upper bound and either...
Definition: qgsrange.h:125
T mLower
Definition: qgsrange.h:215
A template based class for storing temporal ranges (beginning to end values).
Definition: qgsrange.h:419
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition: qgsrange.h:542
T begin() const
Returns the beginning of the range.
Definition: qgsrange.h:444
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:510
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition: qgsrange.h:604
T end() const
Returns the upper bound of the range.
Definition: qgsrange.h:451
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition: qgsrange.h:473
bool operator!=(const QgsTemporalRange< T > &other) const
Definition: qgsrange.h:706
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition: qgsrange.h:428
bool operator==(const QgsTemporalRange< T > &other) const
Definition: qgsrange.h:698
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:569
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition: qgsrange.h:466
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition: qgsrange.h:459
bool isEmpty() const
Returns true if the range is empty, ie the beginning equals (or exceeds) the end and either of the bo...
Definition: qgsrange.h:490
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition: qgsrange.h:667
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:480
int ANALYSIS_EXPORT lower(int n, int i)
Lower function.
Definition: MathUtils.cpp:337
#define str(x)
Definition: qgis.cpp:38
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5207
#define SIP_DOC_TEMPLATE
Definition: qgis_sip.h:224
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)