QGIS API Documentation 3.43.0-Master (ebb4087afc0)
Loading...
Searching...
No Matches
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
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 // other range is completely before or completely after self range
179 if ( other.mUpper < mLower || other.mLower > mUpper )
180 return false;
181
182 // other overlaps self for sure
183 if ( other.mUpper > mLower && other.mLower < mUpper )
184 return true;
185
186 if ( other.mUpper == mLower )
187 return other.mIncludeUpper && mIncludeLower;
188
189 if ( other.mLower == mUpper )
190 return other.mIncludeLower && mIncludeUpper;
191
192 // UNREACHABLE CODE
193 return false;
194 }
195
196 bool operator==( const QgsRange<T> &other ) const
197 {
198 return mLower == other.mLower &&
199 mUpper == other.mUpper &&
200 mIncludeLower == other.includeLower() &&
201 mIncludeUpper == other.includeUpper();
202 }
203
204 bool operator!=( const QgsRange<T> &other ) const
205 {
206 return ( ! operator==( other ) );
207 }
208
209 protected:
210
213 bool mIncludeLower = true;
214 bool mIncludeUpper = true;
215
216};
217
218// These typedefs are in place to work around a SIP bug:
219// https://github.com/Python-SIP/sip/issues/66
220#ifndef SIP_RUN
223#endif
224
232class CORE_EXPORT QgsDoubleRange : public QgsRange< double >
233{
234 public:
235
242 QgsDoubleRange( double lower, double upper, Qgis::RangeLimits limits )
243 : QgsRange( lower, upper, limits )
244 {}
245
246#ifndef SIP_RUN
247
256 QgsDoubleRange( double lower = std::numeric_limits< double >::lowest(),
257 double upper = std::numeric_limits< double >::max(),
258 bool includeLower = true, bool includeUpper = true )
259 : QgsRange( lower, upper, includeLower, includeUpper )
260 {}
261#else
262
267 QgsDoubleRange( double lower,
268 double upper,
269 bool includeLower = true, bool includeUpper = true )
270 : QgsRange( lower, upper, includeLower, includeUpper )
271 {}
272
279 : QgsRange( std::numeric_limits< double >::lowest(), std::numeric_limits< double >::max(), true, true )
280 {}
281#endif
282
287 bool isInfinite() const
288 {
289 return lower() == std::numeric_limits< double >::lowest() && upper() == std::numeric_limits< double >::max();
290 }
291
292#ifdef SIP_RUN
293 SIP_PYOBJECT __repr__();
294 % MethodCode
295 QString str = QStringLiteral( "<QgsDoubleRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
296 .arg( sipCpp->lower() )
297 .arg( sipCpp->upper() )
298 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
299 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
300 % End
301#endif
302
303 bool operator==( const QgsDoubleRange &other ) const
304 {
305 return qgsDoubleNear( mLower, other.mLower ) &&
306 qgsDoubleNear( mUpper, other.mUpper ) &&
307 mIncludeLower == other.includeLower() &&
308 mIncludeUpper == other.includeUpper();
309 }
310
311 bool operator!=( const QgsDoubleRange &other ) const
312 {
313 return ( ! operator==( other ) );
314 }
315
316};
317
319
320
321
328class CORE_EXPORT QgsIntRange : public QgsRange< int >
329{
330 public:
331
338 QgsIntRange( int lower, int upper, Qgis::RangeLimits limits )
339 : QgsRange( lower, upper, limits )
340 {}
341
342#ifndef SIP_RUN
343
352 QgsIntRange( int lower = std::numeric_limits< int >::lowest(),
353 int upper = std::numeric_limits< int >::max(),
354 bool includeLower = true, bool includeUpper = true )
355 : QgsRange( lower, upper, includeLower, includeUpper )
356 {}
357#else
358
363 QgsIntRange( int lower,
364 int upper,
365 bool includeLower = true, bool includeUpper = true )
366 : QgsRange( lower, upper, includeLower, includeUpper )
367 {}
368
375 : QgsRange( std::numeric_limits< int >::lowest(), std::numeric_limits< int >::max(), true, true )
376 {}
377#endif
378
383 bool isInfinite() const
384 {
385 return lower() == std::numeric_limits< int >::lowest() && upper() == std::numeric_limits< int >::max();
386 }
387
388#ifdef SIP_RUN
389 SIP_PYOBJECT __repr__();
390 % MethodCode
391 QString str = QStringLiteral( "<QgsIntRange: %1%2, %3%4>" ).arg( sipCpp->includeLower() ? QStringLiteral( "[" ) : QStringLiteral( "(" ) )
392 .arg( sipCpp->lower() )
393 .arg( sipCpp->upper() )
394 .arg( sipCpp->includeUpper() ? QStringLiteral( "]" ) : QStringLiteral( ")" ) );
395 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
396 % End
397#endif
398
399};
400
402
403
404
419template <typename T>
421{
422 public:
423
429#ifndef SIP_RUN
430 QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
431 : mLower( begin )
432 , mUpper( end )
433 , mIncludeLower( includeBeginning )
434 , mIncludeUpper( includeEnd )
435 {}
436#else
437 QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
438 // default constructor as default value for templates is not handled in SIP
439#endif
440
446 T begin() const { return mLower; }
447
453 T end() const { return mUpper; }
454
461 bool includeBeginning() const { return mIncludeLower; }
462
468 bool includeEnd() const { return mIncludeUpper; }
469
475 bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
476
482 bool isInfinite() const
483 {
484 return !mLower.isValid() && !mUpper.isValid();
485 }
486
492 bool isEmpty() const
493 {
494 if ( !mLower.isValid() && !mUpper.isValid() )
495 return false;
496
497 if ( mLower.isValid() != mUpper.isValid() )
498 return false;
499
500 if ( mLower > mUpper )
501 return true;
502
503 if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
504 return true;
505
506 return false;
507 }
508
512 bool contains( const QgsTemporalRange<T> &other ) const
513 {
514 if ( !other.mLower.isValid() && mLower.isValid() )
515 return false;
516
517 if ( mLower.isValid() )
518 {
519 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
520 || ( !mIncludeLower && mLower < other.mLower )
521 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
522 if ( !lowerOk )
523 return false;
524 }
525
526 if ( !other.mUpper.isValid() && mUpper.isValid() )
527 return false;
528
529 if ( mUpper.isValid() )
530 {
531 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
532 || ( !mIncludeUpper && mUpper > other.mUpper )
533 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
534 if ( !upperOk )
535 return false;
536 }
537
538 return true;
539 }
540
544 bool contains( const T &element ) const
545 {
546 if ( !element.isValid() )
547 return false;
548
549 if ( mLower.isValid() )
550 {
551 const bool lowerOk = ( mIncludeLower && mLower <= element )
552 || ( !mIncludeLower && mLower < element );
553 if ( !lowerOk )
554 return false;
555 }
556
557 if ( mUpper.isValid() )
558 {
559 const bool upperOk = ( mIncludeUpper && mUpper >= element )
560 || ( !mIncludeUpper && mUpper > element );
561 if ( !upperOk )
562 return false;
563 }
564
565 return true;
566 }
567
572 bool overlaps( const QgsTemporalRange<T> &other ) const
573 {
574 // one or both range is infinite
575 if ( isInfinite() || other.isInfinite() )
576 return true;
577
578 // all bounds are fixed
579 if ( mLower.isValid() && mUpper.isValid() && other.mLower.isValid() && other.mUpper.isValid() )
580 {
581 // other range is completely before or completely after self range
582 if ( other.mUpper < mLower || other.mLower > mUpper )
583 return false;
584
585 // other overlaps self for sure
586 if ( other.mUpper > mLower && other.mLower < mUpper )
587 return true;
588 }
589
590 // other is just before and has a bound in common
591 if ( other.mUpper == mLower && mLower.isValid() )
592 return other.mIncludeUpper && mIncludeLower;
593
594 // other is just after and has a bound in common
595 if ( other.mLower == mUpper && mUpper.isValid() )
596 return other.mIncludeLower && mIncludeUpper;
597
598 if ( !mLower.isValid() )
599 return other.mLower < mUpper || !other.mLower.isValid();
600
601 if ( !mUpper.isValid() )
602 return other.mUpper > mLower || !other.mUpper.isValid();
603
604 if ( !other.mLower.isValid() )
605 return other.mUpper > mLower || !mLower.isValid();
606
607 if ( !other.mUpper.isValid() )
608 return other.mLower < mUpper || !mUpper.isValid();
609
610 // UNREACHABLE CODE
611 return false;
612 }
613
622 bool extend( const QgsTemporalRange<T> &other )
623 {
624 if ( other.isEmpty() )
625 {
626 return false;
627 }
628 else if ( isEmpty() )
629 {
630 mLower = other.begin();
631 mUpper = other.end();
632 mIncludeLower = other.includeBeginning();
633 mIncludeUpper = other.includeEnd();
634 return true;
635 }
636
637 // Both not empty, do some math
638 bool changed { false };
639
640 // Lower
641 if ( ! other.begin().isValid()
642 || ( begin().isValid() && other.begin() < mLower ) )
643 {
644 mLower = other.begin();
645 mIncludeLower = other.includeBeginning();
646 changed = true;
647 }
648 else if ( other.begin() == mLower && other.includeBeginning() && ! mIncludeLower )
649 {
650 mIncludeLower = true;
651 changed = true;
652 }
653
654 // Upper
655 if ( ! other.end().isValid()
656 || ( end().isValid() && other.end() > mUpper ) )
657 {
658 mUpper = other.end();
659 mIncludeUpper = other.includeEnd();
660 changed = true;
661 }
662 else if ( other.end() == mUpper && other.includeEnd() && ! mIncludeUpper )
663 {
664 mIncludeUpper = true;
665 changed = true;
666 }
667 return changed;
668 }
669
670#ifndef SIP_RUN
671
685 static QList< QgsTemporalRange<T> > mergeRanges( const QList< QgsTemporalRange<T> > &ranges )
686 {
687 if ( ranges.empty() )
688 return {};
689
690 QList< QgsTemporalRange<T > > sortedRanges = ranges;
691 // cppcheck-suppress mismatchingContainerExpression
692 std::sort( sortedRanges.begin(), sortedRanges.end(), []( const QgsTemporalRange< T > &a, const QgsTemporalRange< T > &b ) -> bool { return a.begin() < b.begin(); } );
693 QList< QgsTemporalRange<T>> res;
694 res.reserve( sortedRanges.size() );
695
696 QgsTemporalRange<T> prevRange;
697 auto it = sortedRanges.constBegin();
698 prevRange = *it++;
699 for ( ; it != sortedRanges.constEnd(); ++it )
700 {
701 if ( prevRange.overlaps( *it ) )
702 {
703 prevRange.extend( *it );
704 }
705 else
706 {
707 res << prevRange;
708 prevRange = *it;
709 }
710 }
711 res << prevRange;
712 return res;
713 }
714#endif
715
716 bool operator==( const QgsTemporalRange<T> &other ) const
717 {
718 return mLower == other.mLower &&
719 mUpper == other.mUpper &&
720 mIncludeLower == other.includeBeginning() &&
721 mIncludeUpper == other.includeEnd();
722 }
723
724 bool operator!=( const QgsTemporalRange<T> &other ) const
725 {
726 return ( ! operator==( other ) );
727 }
728
729 private:
730
731 T mLower;
732 T mUpper;
733 bool mIncludeLower = true;
734 bool mIncludeUpper = true;
735};
736
737
748
750
751
761
763
764#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:3849
@ 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:233
QgsDoubleRange(double lower, double upper, Qgis::RangeLimits limits)
Constructor for QgsDoubleRange.
Definition qgsrange.h:242
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:256
bool operator==(const QgsDoubleRange &other) const
Definition qgsrange.h:303
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:287
bool operator!=(const QgsDoubleRange &other) const
Definition qgsrange.h:311
QgsRange which stores a range of integer values.
Definition qgsrange.h:329
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:383
QgsIntRange(int lower, int upper, Qgis::RangeLimits limits)
Constructor for QgsIntRange.
Definition qgsrange.h:338
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:352
A template based class for storing ranges (lower to upper values).
Definition qgsrange.h:46
bool mIncludeLower
Definition qgsrange.h:213
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:214
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
bool operator!=(const QgsRange< T > &other) const
Definition qgsrange.h:204
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:196
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
A template based class for storing temporal ranges (beginning to end values).
Definition qgsrange.h:421
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:544
T begin() const
Returns the beginning of the range.
Definition qgsrange.h:446
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:512
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition qgsrange.h:622
T end() const
Returns the upper bound of the range.
Definition qgsrange.h:453
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition qgsrange.h:475
bool operator!=(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:724
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition qgsrange.h:430
bool operator==(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:716
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:572
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition qgsrange.h:468
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition qgsrange.h:461
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:492
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition qgsrange.h:685
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:482
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6186
#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:747
QgsRange< double > QgsRangedoubleBase
Definition qgsrange.h:221
QgsRange< int > QgsRangeintBase
Definition qgsrange.h:222