QGIS API Documentation 3.36.0-Maidenhead (09951dc0acf)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
65 T lower() const { return mLower; }
66
72 T upper() const { return mUpper; }
73
80 bool includeLower() const { return mIncludeLower; }
81
88 bool includeUpper() const { return mIncludeUpper; }
89
95 bool isEmpty() const { return mLower > mUpper || ( mUpper == mLower && !( mIncludeLower || mIncludeUpper ) ); }
96
101 bool isSingleton() const { return mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
102
107 bool contains( const QgsRange<T> &other ) const
108 {
109 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
110 || ( !mIncludeLower && mLower < other.mLower )
111 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
112 if ( !lowerOk )
113 return false;
114
115 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
116 || ( !mIncludeUpper && mUpper > other.mUpper )
117 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
118 if ( !upperOk )
119 return false;
120
121 return true;
122 }
123
127 bool contains( T element ) const
128 {
129 const bool lowerOk = ( mIncludeLower && mLower <= element )
130 || ( !mIncludeLower && mLower < element );
131 if ( !lowerOk )
132 return false;
133
134 const bool upperOk = ( mIncludeUpper && mUpper >= element )
135 || ( !mIncludeUpper && mUpper > element );
136 if ( !upperOk )
137 return false;
138
139 return true;
140 }
141
146 bool overlaps( const QgsRange<T> &other ) const
147 {
148 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
149 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
150 return true;
151
152 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
153 && ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
154 return true;
155
156 if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
157 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
158 return true;
159
160 if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
161 && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
162 return true;
163
164 if ( mLower == other.mLower && mUpper == other.mUpper )
165 return true;
166
167 return false;
168 }
169
170 bool operator==( const QgsRange<T> &other ) const
171 {
172 return mLower == other.mLower &&
173 mUpper == other.mUpper &&
174 mIncludeLower == other.includeLower() &&
175 mIncludeUpper == other.includeUpper();
176 }
177
178 bool operator!=( const QgsRange<T> &other ) const
179 {
180 return ( ! operator==( other ) );
181 }
182
183 protected:
184
187 bool mIncludeLower = true;
188 bool mIncludeUpper = true;
189
190};
191
192
200class CORE_EXPORT QgsDoubleRange : public QgsRange< double >
201{
202 public:
203
204#ifndef SIP_RUN
205
214 QgsDoubleRange( double lower = std::numeric_limits< double >::lowest(),
215 double upper = std::numeric_limits< double >::max(),
216 bool includeLower = true, bool includeUpper = true )
217 : QgsRange( lower, upper, includeLower, includeUpper )
218 {}
219#else
220
225 QgsDoubleRange( double lower,
226 double upper,
227 bool includeLower = true, bool includeUpper = true )
228 : QgsRange( lower, upper, includeLower, includeUpper )
229 {}
230
237 : QgsRange( std::numeric_limits< double >::lowest(), std::numeric_limits< double >::max(), true, true )
238 {}
239#endif
240
245 bool isInfinite() const
246 {
247 return lower() == std::numeric_limits< double >::lowest() && upper() == std::numeric_limits< double >::max();
248 }
249
250#ifdef SIP_RUN
251 SIP_PYOBJECT __repr__();
252 % MethodCode
253 QString str = QStringLiteral( "<QgsDoubleRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
254 .arg( sipCpp->lower() )
255 .arg( sipCpp->upper() )
256 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
257 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
258 % End
259#endif
260
261 bool operator==( const QgsDoubleRange &other ) const
262 {
263 return qgsDoubleNear( mLower, other.mLower ) &&
264 qgsDoubleNear( mUpper, other.mUpper ) &&
265 mIncludeLower == other.includeLower() &&
266 mIncludeUpper == other.includeUpper();
267 }
268
269 bool operator!=( const QgsDoubleRange &other ) const
270 {
271 return ( ! operator==( other ) );
272 }
273
274};
275
276
284class CORE_EXPORT QgsIntRange : public QgsRange< int >
285{
286 public:
287
288#ifndef SIP_RUN
289
298 QgsIntRange( int lower = std::numeric_limits< int >::lowest(),
299 int upper = std::numeric_limits< int >::max(),
300 bool includeLower = true, bool includeUpper = true )
301 : QgsRange( lower, upper, includeLower, includeUpper )
302 {}
303#else
304
309 QgsIntRange( int lower,
310 int upper,
311 bool includeLower = true, bool includeUpper = true )
312 : QgsRange( lower, upper, includeLower, includeUpper )
313 {}
314
321 : QgsRange( std::numeric_limits< int >::lowest(), std::numeric_limits< int >::max(), true, true )
322 {}
323#endif
324
329 bool isInfinite() const
330 {
331 return lower() == std::numeric_limits< int >::lowest() && upper() == std::numeric_limits< int >::max();
332 }
333
334#ifdef SIP_RUN
335 SIP_PYOBJECT __repr__();
336 % MethodCode
337 QString str = QStringLiteral( "<QgsIntRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
338 .arg( sipCpp->lower() )
339 .arg( sipCpp->upper() )
340 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
341 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
342 % End
343#endif
344
345};
346
347
363template <typename T>
365{
366 public:
367
373#ifndef SIP_RUN
374 QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
375 : mLower( begin )
376 , mUpper( end )
377 , mIncludeLower( includeBeginning )
378 , mIncludeUpper( includeEnd )
379 {}
380#else
381 QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
382 // default constructor as default value for templates is not handled in SIP
383#endif
384
390 T begin() const { return mLower; }
391
397 T end() const { return mUpper; }
398
405 bool includeBeginning() const { return mIncludeLower; }
406
412 bool includeEnd() const { return mIncludeUpper; }
413
419 bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
420
426 bool isInfinite() const
427 {
428 return !mLower.isValid() && !mUpper.isValid();
429 }
430
436 bool isEmpty() const
437 {
438 if ( !mLower.isValid() && !mUpper.isValid() )
439 return false;
440
441 if ( mLower.isValid() != mUpper.isValid() )
442 return false;
443
444 if ( mLower > mUpper )
445 return true;
446
447 if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
448 return true;
449
450 return false;
451 }
452
456 bool contains( const QgsTemporalRange<T> &other ) const
457 {
458 if ( !other.mLower.isValid() && mLower.isValid() )
459 return false;
460
461 if ( mLower.isValid() )
462 {
463 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
464 || ( !mIncludeLower && mLower < other.mLower )
465 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
466 if ( !lowerOk )
467 return false;
468 }
469
470 if ( !other.mUpper.isValid() && mUpper.isValid() )
471 return false;
472
473 if ( mUpper.isValid() )
474 {
475 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
476 || ( !mIncludeUpper && mUpper > other.mUpper )
477 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
478 if ( !upperOk )
479 return false;
480 }
481
482 return true;
483 }
484
488 bool contains( const T &element ) const
489 {
490 if ( !element.isValid() )
491 return false;
492
493 if ( mLower.isValid() )
494 {
495 const bool lowerOk = ( mIncludeLower && mLower <= element )
496 || ( !mIncludeLower && mLower < element );
497 if ( !lowerOk )
498 return false;
499 }
500
501 if ( mUpper.isValid() )
502 {
503 const bool upperOk = ( mIncludeUpper && mUpper >= element )
504 || ( !mIncludeUpper && mUpper > element );
505 if ( !upperOk )
506 return false;
507 }
508
509 return true;
510 }
511
515 bool overlaps( const QgsTemporalRange<T> &other ) const
516 {
517 if ( !mUpper.isValid() && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
518 return true;
519
520 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
521 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
522 return true;
523
524 if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
525 && ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
526 return true;
527
528 if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
529 && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
530 return true;
531
532 if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
533 && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
534 return true;
535
536 if ( mLower == other.mLower && mUpper == other.mUpper )
537 return true;
538
539 return false;
540 }
541
550 bool extend( const QgsTemporalRange<T> &other )
551 {
552 if ( other.isEmpty() )
553 {
554 return false;
555 }
556 else if ( isEmpty() )
557 {
558 mLower = other.begin();
559 mUpper = other.end();
560 mIncludeLower = other.includeBeginning();
561 mIncludeUpper = other.includeEnd();
562 return true;
563 }
564
565 // Both not empty, do some math
566 bool changed { false };
567
568 // Lower
569 if ( ! other.begin().isValid()
570 || ( begin().isValid() && other.begin() < mLower ) )
571 {
572 mLower = other.begin();
573 mIncludeLower = other.includeBeginning();
574 changed = true;
575 }
576 else if ( other.begin() == mLower && other.includeBeginning() && ! mIncludeLower )
577 {
578 mIncludeLower = true;
579 changed = true;
580 }
581
582 // Upper
583 if ( ! other.end().isValid()
584 || ( end().isValid() && other.end() > mUpper ) )
585 {
586 mUpper = other.end();
587 mIncludeUpper = other.includeEnd();
588 changed = true;
589 }
590 else if ( other.end() == mUpper && other.includeEnd() && ! mIncludeUpper )
591 {
592 mIncludeUpper = true;
593 changed = true;
594 }
595 return changed;
596 }
597
598#ifndef SIP_RUN
599
613 static QList< QgsTemporalRange<T> > mergeRanges( const QList< QgsTemporalRange<T> > &ranges )
614 {
615 if ( ranges.empty() )
616 return {};
617
618 QList< QgsTemporalRange<T > > sortedRanges = ranges;
619 // cppcheck-suppress mismatchingContainerExpression
620 std::sort( sortedRanges.begin(), sortedRanges.end(), []( const QgsTemporalRange< T > &a, const QgsTemporalRange< T > &b ) -> bool { return a.begin() < b.begin(); } );
621 QList< QgsTemporalRange<T>> res;
622 res.reserve( sortedRanges.size() );
623
624 QgsTemporalRange<T> prevRange;
625 auto it = sortedRanges.constBegin();
626 prevRange = *it++;
627 for ( ; it != sortedRanges.constEnd(); ++it )
628 {
629 if ( prevRange.overlaps( *it ) )
630 {
631 prevRange.extend( *it );
632 }
633 else
634 {
635 res << prevRange;
636 prevRange = *it;
637 }
638 }
639 res << prevRange;
640 return res;
641 }
642#endif
643
644 bool operator==( const QgsTemporalRange<T> &other ) const
645 {
646 return mLower == other.mLower &&
647 mUpper == other.mUpper &&
648 mIncludeLower == other.includeBeginning() &&
649 mIncludeUpper == other.includeEnd();
650 }
651
652 bool operator!=( const QgsTemporalRange<T> &other ) const
653 {
654 return ( ! operator==( other ) );
655 }
656
657 private:
658
659 T mLower;
660 T mUpper;
661 bool mIncludeLower = true;
662 bool mIncludeUpper = true;
663};
664
665
676
678
679
689
691
692#endif // QGSRANGE_H
QgsRange which stores a range of double values.
Definition qgsrange.h:201
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:214
bool operator==(const QgsDoubleRange &other) const
Definition qgsrange.h:261
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:245
bool operator!=(const QgsDoubleRange &other) const
Definition qgsrange.h:269
QgsRange which stores a range of integer values.
Definition qgsrange.h:285
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:329
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:298
A template based class for storing ranges (lower to upper values).
Definition qgsrange.h:46
bool mIncludeLower
Definition qgsrange.h:187
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
Definition qgsrange.h:88
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:146
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:107
T lower() const
Returns the lower bound of the range.
Definition qgsrange.h:65
bool includeLower() const
Returns true if the lower bound is inclusive, or false if the lower bound is exclusive.
Definition qgsrange.h:80
bool mIncludeUpper
Definition qgsrange.h:188
T upper() const
Returns the upper bound of the range.
Definition qgsrange.h:72
bool isSingleton() const
Returns true if the range consists only of a single value or instant.
Definition qgsrange.h:101
bool operator!=(const QgsRange< T > &other) const
Definition qgsrange.h:178
bool contains(T element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:127
bool operator==(const QgsRange< T > &other) const
Definition qgsrange.h:170
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:95
A template based class for storing temporal ranges (beginning to end values).
Definition qgsrange.h:365
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:488
T begin() const
Returns the beginning of the range.
Definition qgsrange.h:390
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:456
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition qgsrange.h:550
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:397
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition qgsrange.h:419
bool operator!=(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:652
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition qgsrange.h:374
bool operator==(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:644
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:515
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:412
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition qgsrange.h:405
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:436
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition qgsrange.h:613
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:426
#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:5144
#define SIP_DOC_TEMPLATE
Definition qgis_sip.h:224
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QgsTemporalRange< QDate > QgsDateRange
QgsRange which stores a range of dates.
Definition qgsrange.h:675