QGIS API Documentation 3.99.0-Master (d270888f95f)
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.h"
22#include "qgis_core.h"
23#include "qgis_sip.h"
24
25#include <QDate>
26#include <QDateTime>
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
47template <typename T>
49{
50 public:
51
56 QgsRange( T lower, T upper, bool includeLower = true, bool includeUpper = true )
57 : mLower( lower )
58 , mUpper( upper )
61 {}
62
70 : mLower( lower )
71 , mUpper( upper )
72 , mIncludeLower( limits == Qgis::RangeLimits::IncludeLowerExcludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
73 , mIncludeUpper( limits == Qgis::RangeLimits::ExcludeLowerIncludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
74 {}
75
81 T lower() const { return mLower; }
82
88 T upper() const { return mUpper; }
89
96 bool includeLower() const { return mIncludeLower; }
97
104 bool includeUpper() const { return mIncludeUpper; }
105
122
128 bool isEmpty() const { return mLower > mUpper || ( mUpper == mLower && !( mIncludeLower || mIncludeUpper ) ); }
129
134 bool isSingleton() const { return mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
135
140 bool contains( const QgsRange<T> &other ) const
141 {
142 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
143 || ( !mIncludeLower && mLower < other.mLower )
144 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
145 if ( !lowerOk )
146 return false;
147
148 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
149 || ( !mIncludeUpper && mUpper > other.mUpper )
150 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
151 if ( !upperOk )
152 return false;
153
154 return true;
155 }
156
160 bool contains( T element ) const
161 {
162 const bool lowerOk = ( mIncludeLower && mLower <= element )
163 || ( !mIncludeLower && mLower < element );
164 if ( !lowerOk )
165 return false;
166
167 const bool upperOk = ( mIncludeUpper && mUpper >= element )
168 || ( !mIncludeUpper && mUpper > element );
169 if ( !upperOk )
170 return false;
171
172 return true;
173 }
174
179 bool overlaps( const QgsRange<T> &other ) const
180 {
181 // other range is completely before or completely after self range
182 if ( other.mUpper < mLower || other.mLower > mUpper )
183 return false;
184
185 // other overlaps self for sure
186 if ( other.mUpper > mLower && other.mLower < mUpper )
187 return true;
188
189 if ( other.mUpper == mLower )
190 return other.mIncludeUpper && mIncludeLower;
191
192 if ( other.mLower == mUpper )
193 return other.mIncludeLower && mIncludeUpper;
194
195 // UNREACHABLE CODE
196 return false;
197 }
198
199 bool operator==( const QgsRange<T> &other ) const
200 {
201 return mLower == other.mLower &&
202 mUpper == other.mUpper &&
203 mIncludeLower == other.includeLower() &&
204 mIncludeUpper == other.includeUpper();
205 }
206
207 bool operator!=( const QgsRange<T> &other ) const
208 {
209 return ( ! operator==( other ) );
210 }
211
212 protected:
213
216 bool mIncludeLower = true;
217 bool mIncludeUpper = true;
218
219};
220
221// These typedefs are in place to work around a SIP bug:
222// https://github.com/Python-SIP/sip/issues/66
223#ifndef SIP_RUN
226#endif
227
235class CORE_EXPORT QgsDoubleRange : public QgsRange< double >
236{
237 public:
238
245 QgsDoubleRange( double lower, double upper, Qgis::RangeLimits limits )
246 : QgsRange( lower, upper, limits )
247 {}
248
249#ifndef SIP_RUN
250
259 QgsDoubleRange( double lower = std::numeric_limits< double >::lowest(),
260 double upper = std::numeric_limits< double >::max(),
261 bool includeLower = true, bool includeUpper = true )
263 {}
264#else
265
270 QgsDoubleRange( double lower,
271 double upper,
272 bool includeLower = true, bool includeUpper = true )
273 : QgsRange( lower, upper, includeLower, includeUpper )
274 {}
275
281 QgsDoubleRange()
282 : QgsRange( std::numeric_limits< double >::lowest(), std::numeric_limits< double >::max(), true, true )
283 {}
284#endif
285
290 bool isInfinite() const
291 {
292 return lower() == std::numeric_limits< double >::lowest() && upper() == std::numeric_limits< double >::max();
293 }
294
295#ifdef SIP_RUN
296 SIP_PYOBJECT __repr__();
297 % MethodCode
298 QString str = u"<QgsDoubleRange: %1%2, %3%4>"_s.arg( sipCpp->includeLower() ? u"["_s : u"("_s )
299 .arg( sipCpp->lower() )
300 .arg( sipCpp->upper() )
301 .arg( sipCpp->includeUpper() ? u"]"_s : u")"_s );
302 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
303 % End
304#endif
305
306 bool operator==( const QgsDoubleRange &other ) const
307 {
308 return qgsDoubleNear( mLower, other.mLower ) &&
309 qgsDoubleNear( mUpper, other.mUpper ) &&
310 mIncludeLower == other.includeLower() &&
311 mIncludeUpper == other.includeUpper();
312 }
313
314 bool operator!=( const QgsDoubleRange &other ) const
315 {
316 return ( ! operator==( other ) );
317 }
318
319};
320
322
323
324
331class CORE_EXPORT QgsIntRange : public QgsRange< int >
332{
333 public:
334
342 : QgsRange( lower, upper, limits )
343 {}
344
345#ifndef SIP_RUN
346
355 QgsIntRange( int lower = std::numeric_limits< int >::lowest(),
356 int upper = std::numeric_limits< int >::max(),
357 bool includeLower = true, bool includeUpper = true )
359 {}
360#else
361
366 QgsIntRange( int lower,
367 int upper,
368 bool includeLower = true, bool includeUpper = true )
369 : QgsRange( lower, upper, includeLower, includeUpper )
370 {}
371
378 : QgsRange( std::numeric_limits< int >::lowest(), std::numeric_limits< int >::max(), true, true )
379 {}
380#endif
381
386 bool isInfinite() const
387 {
388 return lower() == std::numeric_limits< int >::lowest() && upper() == std::numeric_limits< int >::max();
389 }
390
391#ifdef SIP_RUN
392 SIP_PYOBJECT __repr__();
393 % MethodCode
394 QString str = u"<QgsIntRange: %1%2, %3%4>"_s.arg( sipCpp->includeLower() ? u"["_s : u"("_s )
395 .arg( sipCpp->lower() )
396 .arg( sipCpp->upper() )
397 .arg( sipCpp->includeUpper() ? u"]"_s : u")"_s );
398 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
399 % End
400#endif
401
402};
403
405
406
407
422template <typename T>
424{
425 public:
426
432#ifndef SIP_RUN
433 QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
434 : mLower( begin )
435 , mUpper( end )
436 , mIncludeLower( includeBeginning )
437 , mIncludeUpper( includeEnd )
438 {}
439#else
440 QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
441 // default constructor as default value for templates is not handled in SIP
442#endif
443
449 T begin() const { return mLower; }
450
456 T end() const { return mUpper; }
457
464 bool includeBeginning() const { return mIncludeLower; }
465
471 bool includeEnd() const { return mIncludeUpper; }
472
478 bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
479
485 bool isInfinite() const
486 {
487 return !mLower.isValid() && !mUpper.isValid();
488 }
489
495 bool isEmpty() const
496 {
497 if ( !mLower.isValid() && !mUpper.isValid() )
498 return false;
499
500 if ( mLower.isValid() != mUpper.isValid() )
501 return false;
502
503 if ( mLower > mUpper )
504 return true;
505
506 if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
507 return true;
508
509 return false;
510 }
511
515 bool contains( const QgsTemporalRange<T> &other ) const
516 {
517 if ( !other.mLower.isValid() && mLower.isValid() )
518 return false;
519
520 if ( mLower.isValid() )
521 {
522 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
523 || ( !mIncludeLower && mLower < other.mLower )
524 || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
525 if ( !lowerOk )
526 return false;
527 }
528
529 if ( !other.mUpper.isValid() && mUpper.isValid() )
530 return false;
531
532 if ( mUpper.isValid() )
533 {
534 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
535 || ( !mIncludeUpper && mUpper > other.mUpper )
536 || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
537 if ( !upperOk )
538 return false;
539 }
540
541 return true;
542 }
543
547 bool contains( const T &element ) const
548 {
549 if ( !element.isValid() )
550 return false;
551
552 if ( mLower.isValid() )
553 {
554 const bool lowerOk = ( mIncludeLower && mLower <= element )
555 || ( !mIncludeLower && mLower < element );
556 if ( !lowerOk )
557 return false;
558 }
559
560 if ( mUpper.isValid() )
561 {
562 const bool upperOk = ( mIncludeUpper && mUpper >= element )
563 || ( !mIncludeUpper && mUpper > element );
564 if ( !upperOk )
565 return false;
566 }
567
568 return true;
569 }
570
575 bool overlaps( const QgsTemporalRange<T> &other ) const
576 {
577 // one or both range is infinite
578 if ( isInfinite() || other.isInfinite() )
579 return true;
580
581 // all bounds are fixed
582 if ( mLower.isValid() && mUpper.isValid() && other.mLower.isValid() && other.mUpper.isValid() )
583 {
584 // other range is completely before or completely after self range
585 if ( other.mUpper < mLower || other.mLower > mUpper )
586 return false;
587
588 // other overlaps self for sure
589 if ( other.mUpper > mLower && other.mLower < mUpper )
590 return true;
591 }
592
593 // other is just before and has a bound in common
594 if ( other.mUpper == mLower && mLower.isValid() )
595 return other.mIncludeUpper && mIncludeLower;
596
597 // other is just after and has a bound in common
598 if ( other.mLower == mUpper && mUpper.isValid() )
599 return other.mIncludeLower && mIncludeUpper;
600
601 if ( !mLower.isValid() )
602 return other.mLower < mUpper || !other.mLower.isValid();
603
604 if ( !mUpper.isValid() )
605 return other.mUpper > mLower || !other.mUpper.isValid();
606
607 if ( !other.mLower.isValid() )
608 return other.mUpper > mLower || !mLower.isValid();
609
610 if ( !other.mUpper.isValid() )
611 return other.mLower < mUpper || !mUpper.isValid();
612
613 // UNREACHABLE CODE
614 return false;
615 }
616
625 bool extend( const QgsTemporalRange<T> &other )
626 {
627 if ( other.isEmpty() )
628 {
629 return false;
630 }
631 else if ( isEmpty() )
632 {
633 mLower = other.begin();
634 mUpper = other.end();
635 mIncludeLower = other.includeBeginning();
636 mIncludeUpper = other.includeEnd();
637 return true;
638 }
639
640 // Both not empty, do some math
641 bool changed { false };
642
643 // Lower
644 if ( ! other.begin().isValid()
645 || ( begin().isValid() && other.begin() < mLower ) )
646 {
647 mLower = other.begin();
648 mIncludeLower = other.includeBeginning();
649 changed = true;
650 }
651 else if ( other.begin() == mLower && other.includeBeginning() && ! mIncludeLower )
652 {
653 mIncludeLower = true;
654 changed = true;
655 }
656
657 // Upper
658 if ( ! other.end().isValid()
659 || ( end().isValid() && other.end() > mUpper ) )
660 {
661 mUpper = other.end();
662 mIncludeUpper = other.includeEnd();
663 changed = true;
664 }
665 else if ( other.end() == mUpper && other.includeEnd() && ! mIncludeUpper )
666 {
667 mIncludeUpper = true;
668 changed = true;
669 }
670 return changed;
671 }
672
673#ifndef SIP_RUN
674
688 static QList< QgsTemporalRange<T> > mergeRanges( const QList< QgsTemporalRange<T> > &ranges )
689 {
690 if ( ranges.empty() )
691 return {};
692
693 QList< QgsTemporalRange<T > > sortedRanges = ranges;
694 // cppcheck-suppress mismatchingContainerExpression
695 std::sort( sortedRanges.begin(), sortedRanges.end(), []( const QgsTemporalRange< T > &a, const QgsTemporalRange< T > &b ) -> bool { return a.begin() < b.begin(); } );
696 QList< QgsTemporalRange<T>> res;
697 res.reserve( sortedRanges.size() );
698
699 QgsTemporalRange<T> prevRange;
700 auto it = sortedRanges.constBegin();
701 prevRange = *it++;
702 for ( ; it != sortedRanges.constEnd(); ++it )
703 {
704 if ( prevRange.overlaps( *it ) )
705 {
706 prevRange.extend( *it );
707 }
708 else
709 {
710 res << prevRange;
711 prevRange = *it;
712 }
713 }
714 res << prevRange;
715 return res;
716 }
717#endif
718
719 bool operator==( const QgsTemporalRange<T> &other ) const
720 {
721 return mLower == other.mLower &&
722 mUpper == other.mUpper &&
723 mIncludeLower == other.includeBeginning() &&
724 mIncludeUpper == other.includeEnd();
725 }
726
727 bool operator!=( const QgsTemporalRange<T> &other ) const
728 {
729 return ( ! operator==( other ) );
730 }
731
732 private:
733
734 T mLower;
735 T mUpper;
736 bool mIncludeLower = true;
737 bool mIncludeUpper = true;
738};
739
740
751// NOTE -- Python docstrings for QgsDateRange are patched in python/core/__init__.py
752
754
755
765// NOTE -- Python docstrings for QgsDateTimeRange are patched in python/core/__init__.py
766
768
769#endif // QGSRANGE_H
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
RangeLimits
Describes how the limits of a range are handled.
Definition qgis.h:4066
@ ExcludeLowerIncludeUpper
Lower value is excluded from the range, upper value in inccluded.
Definition qgis.h:4069
@ IncludeBoth
Both lower and upper values are included in the range.
Definition qgis.h:4067
@ ExcludeBoth
Both lower and upper values are excluded from the range.
Definition qgis.h:4070
@ IncludeLowerExcludeUpper
Lower value is included in the range, upper value is excluded.
Definition qgis.h:4068
QgsRange which stores a range of double values.
Definition qgsrange.h:236
QgsDoubleRange(double lower, double upper, Qgis::RangeLimits limits)
Constructor for QgsDoubleRange.
Definition qgsrange.h:245
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:259
bool operator==(const QgsDoubleRange &other) const
Definition qgsrange.h:306
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:290
bool operator!=(const QgsDoubleRange &other) const
Definition qgsrange.h:314
QgsRange which stores a range of integer values.
Definition qgsrange.h:332
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:386
QgsIntRange(int lower, int upper, Qgis::RangeLimits limits)
Constructor for QgsIntRange.
Definition qgsrange.h:341
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:355
A template based class for storing ranges (lower to upper values).
Definition qgsrange.h:49
QgsRange(T lower, T upper, Qgis::RangeLimits limits)
Constructor for QgsRange.
Definition qgsrange.h:69
bool includeUpper() const
Definition qgsrange.h:104
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:179
Qgis::RangeLimits rangeLimits() const
Returns the limit handling of the range.
Definition qgsrange.h:111
QgsRange(T lower, T upper, bool includeLower=true, bool includeUpper=true)
Constructor for QgsRange.
Definition qgsrange.h:56
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:140
double lower() const
Definition qgsrange.h:81
bool includeLower() const
Definition qgsrange.h:96
double upper() const
Definition qgsrange.h:88
bool isSingleton() const
Returns true if the range consists only of a single value or instant.
Definition qgsrange.h:134
bool operator!=(const QgsRange< T > &other) const
Definition qgsrange.h:207
bool contains(T element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:160
bool operator==(const QgsRange< T > &other) const
Definition qgsrange.h:199
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:128
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:547
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:515
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition qgsrange.h:625
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition qgsrange.h:478
bool operator!=(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:727
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition qgsrange.h:433
bool operator==(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:719
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:575
bool includeEnd() const
Definition qgsrange.h:471
bool includeBeginning() const
Definition qgsrange.h:464
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:495
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition qgsrange.h:688
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:485
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6900
#define SIP_DOC_TEMPLATE
Definition qgis_sip.h:232
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QgsTemporalRange< QDate > QgsDateRange
QgsRange which stores a range of dates.
Definition qgsrange.h:750
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:764
QgsRange< double > QgsRangedoubleBase
Definition qgsrange.h:224
QgsRange< int > QgsRangeintBase
Definition qgsrange.h:225