QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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> class QgsRange
48{
49 public:
54 QgsRange( T lower, T upper, bool includeLower = true, bool includeUpper = true )
55 : mLower( lower )
56 , mUpper( upper )
59 {}
60
68 : mLower( lower )
69 , mUpper( upper )
70 , mIncludeLower( limits == Qgis::RangeLimits::IncludeLowerExcludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
71 , mIncludeUpper( limits == Qgis::RangeLimits::ExcludeLowerIncludeUpper || limits == Qgis::RangeLimits::IncludeBoth )
72 {}
73
79 T lower() const { return mLower; }
80
86 T upper() const { return mUpper; }
87
94 bool includeLower() const { return mIncludeLower; }
95
102 bool includeUpper() const { return mIncludeUpper; }
103
120
126 bool isEmpty() const { return mLower > mUpper || ( mUpper == mLower && !( mIncludeLower || mIncludeUpper ) ); }
127
132 bool isSingleton() const { return mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
133
138 bool contains( const QgsRange<T> &other ) const
139 {
140 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
141 if ( !lowerOk )
142 return false;
143
144 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
145 if ( !upperOk )
146 return false;
147
148 return true;
149 }
150
154 bool contains( T element ) const
155 {
156 const bool lowerOk = ( mIncludeLower && mLower <= element ) || ( !mIncludeLower && mLower < element );
157 if ( !lowerOk )
158 return false;
159
160 const bool upperOk = ( mIncludeUpper && mUpper >= element ) || ( !mIncludeUpper && mUpper > element );
161 if ( !upperOk )
162 return false;
163
164 return true;
165 }
166
171 bool overlaps( const QgsRange<T> &other ) const
172 {
173 // other range is completely before or completely after self range
174 if ( other.mUpper < mLower || other.mLower > mUpper )
175 return false;
176
177 // other overlaps self for sure
178 if ( other.mUpper > mLower && other.mLower < mUpper )
179 return true;
180
181 if ( other.mUpper == mLower )
182 return other.mIncludeUpper && mIncludeLower;
183
184 if ( other.mLower == mUpper )
185 return other.mIncludeLower && mIncludeUpper;
186
187 // UNREACHABLE CODE
188 return false;
189 }
190
191 bool operator==( const QgsRange<T> &other ) const { return mLower == other.mLower && mUpper == other.mUpper && mIncludeLower == other.includeLower() && mIncludeUpper == other.includeUpper(); }
192
193 bool operator!=( const QgsRange<T> &other ) const { return ( !operator==( other ) ); }
194
195 protected:
198 bool mIncludeLower = true;
199 bool mIncludeUpper = true;
200};
201
202// These typedefs are in place to work around a SIP bug:
203// https://github.com/Python-SIP/sip/issues/66
204#ifndef SIP_RUN
207#endif
208
216class CORE_EXPORT QgsDoubleRange : public QgsRange< double >
217{
218 public:
225 QgsDoubleRange( double lower, double upper, Qgis::RangeLimits limits )
226 : QgsRange( lower, upper, limits )
227 {}
228
229#ifndef SIP_RUN
230
239 QgsDoubleRange( double lower = std::numeric_limits< double >::lowest(), double upper = std::numeric_limits< double >::max(), bool includeLower = true, bool includeUpper = true )
241 {}
242#else
243
248 QgsDoubleRange( double lower, double upper, bool includeLower = true, bool includeUpper = true )
249 : QgsRange( lower, upper, includeLower, includeUpper )
250 {}
251
257 QgsDoubleRange()
258 : QgsRange( std::numeric_limits< double >::lowest(), std::numeric_limits< double >::max(), true, true )
259 {}
260#endif
261
266 bool isInfinite() const { return lower() == std::numeric_limits< double >::lowest() && upper() == std::numeric_limits< double >::max(); }
267
268#ifdef SIP_RUN
269 // clang-format off
270 SIP_PYOBJECT __repr__();
271 % MethodCode
272 QString str = u"<QgsDoubleRange: %1%2, %3%4>"_s.arg( sipCpp->includeLower() ? u"["_s : u"("_s )
273 .arg( sipCpp->lower() )
274 .arg( sipCpp->upper() )
275 .arg( sipCpp->includeUpper() ? u"]"_s : u")"_s );
276 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
277 % End
278// clang-format on
279#endif
280
281 bool operator==( const QgsDoubleRange &other ) const
282 {
283 return qgsDoubleNear( mLower, other.mLower ) && qgsDoubleNear( mUpper, other.mUpper ) && mIncludeLower == other.includeLower() && mIncludeUpper == other.includeUpper();
284 }
285
286 bool operator!=( const QgsDoubleRange &other ) const { return ( !operator==( other ) ); }
287};
288
290
291
292
299class CORE_EXPORT QgsIntRange : public QgsRange< int >
300{
301 public:
309 : QgsRange( lower, upper, limits )
310 {}
311
312#ifndef SIP_RUN
313
322 QgsIntRange( int lower = std::numeric_limits< int >::lowest(), int upper = std::numeric_limits< int >::max(), bool includeLower = true, bool includeUpper = true )
324 {}
325#else
326
331 QgsIntRange( int lower, int upper, bool includeLower = true, bool includeUpper = true )
332 : QgsRange( lower, upper, includeLower, includeUpper )
333 {}
334
341 : QgsRange( std::numeric_limits< int >::lowest(), std::numeric_limits< int >::max(), true, true )
342 {}
343#endif
344
349 bool isInfinite() const { return lower() == std::numeric_limits< int >::lowest() && upper() == std::numeric_limits< int >::max(); }
350
351#ifdef SIP_RUN
352 // clang-format off
353 SIP_PYOBJECT __repr__();
354 % MethodCode
355 QString str = u"<QgsIntRange: %1%2, %3%4>"_s.arg( sipCpp->includeLower() ? u"["_s : u"("_s )
356 .arg( sipCpp->lower() )
357 .arg( sipCpp->upper() )
358 .arg( sipCpp->includeUpper() ? u"]"_s : u")"_s );
359 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
360 % End
361// clang-format on
362#endif
363};
364
366
367
368
383template<typename T> class QgsTemporalRange
384{
385 public:
391#ifndef SIP_RUN
392 QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
393 : mLower( begin )
394 , mUpper( end )
395 , mIncludeLower( includeBeginning )
396 , mIncludeUpper( includeEnd )
397 {}
398#else
399 QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
400 // default constructor as default value for templates is not handled in SIP
401#endif
402
408 T begin() const { return mLower; }
409
415 T end() const { return mUpper; }
416
423 bool includeBeginning() const { return mIncludeLower; }
424
430 bool includeEnd() const { return mIncludeUpper; }
431
437 bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
438
444 bool isInfinite() const { return !mLower.isValid() && !mUpper.isValid(); }
445
451 bool isEmpty() const
452 {
453 if ( !mLower.isValid() && !mUpper.isValid() )
454 return false;
455
456 if ( mLower.isValid() != mUpper.isValid() )
457 return false;
458
459 if ( mLower > mUpper )
460 return true;
461
462 if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
463 return true;
464
465 return false;
466 }
467
471 bool contains( const QgsTemporalRange<T> &other ) const
472 {
473 if ( !other.mLower.isValid() && mLower.isValid() )
474 return false;
475
476 if ( mLower.isValid() )
477 {
478 const bool lowerOk = ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
479 if ( !lowerOk )
480 return false;
481 }
482
483 if ( !other.mUpper.isValid() && mUpper.isValid() )
484 return false;
485
486 if ( mUpper.isValid() )
487 {
488 const bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
489 if ( !upperOk )
490 return false;
491 }
492
493 return true;
494 }
495
499 bool contains( const T &element ) const
500 {
501 if ( !element.isValid() )
502 return false;
503
504 if ( mLower.isValid() )
505 {
506 const bool lowerOk = ( mIncludeLower && mLower <= element ) || ( !mIncludeLower && mLower < element );
507 if ( !lowerOk )
508 return false;
509 }
510
511 if ( mUpper.isValid() )
512 {
513 const bool upperOk = ( mIncludeUpper && mUpper >= element ) || ( !mIncludeUpper && mUpper > element );
514 if ( !upperOk )
515 return false;
516 }
517
518 return true;
519 }
520
525 bool overlaps( const QgsTemporalRange<T> &other ) const
526 {
527 // one or both range is infinite
528 if ( isInfinite() || other.isInfinite() )
529 return true;
530
531 // all bounds are fixed
532 if ( mLower.isValid() && mUpper.isValid() && other.mLower.isValid() && other.mUpper.isValid() )
533 {
534 // other range is completely before or completely after self range
535 if ( other.mUpper < mLower || other.mLower > mUpper )
536 return false;
537
538 // other overlaps self for sure
539 if ( other.mUpper > mLower && other.mLower < mUpper )
540 return true;
541 }
542
543 // other is just before and has a bound in common
544 if ( other.mUpper == mLower && mLower.isValid() )
545 return other.mIncludeUpper && mIncludeLower;
546
547 // other is just after and has a bound in common
548 if ( other.mLower == mUpper && mUpper.isValid() )
549 return other.mIncludeLower && mIncludeUpper;
550
551 if ( !mLower.isValid() )
552 return other.mLower < mUpper || !other.mLower.isValid();
553
554 if ( !mUpper.isValid() )
555 return other.mUpper > mLower || !other.mUpper.isValid();
556
557 if ( !other.mLower.isValid() )
558 return other.mUpper > mLower || !mLower.isValid();
559
560 if ( !other.mUpper.isValid() )
561 return other.mLower < mUpper || !mUpper.isValid();
562
563 // UNREACHABLE CODE
564 return false;
565 }
566
575 bool extend( const QgsTemporalRange<T> &other )
576 {
577 if ( other.isEmpty() )
578 {
579 return false;
580 }
581 else if ( isEmpty() )
582 {
583 mLower = other.begin();
584 mUpper = other.end();
585 mIncludeLower = other.includeBeginning();
586 mIncludeUpper = other.includeEnd();
587 return true;
588 }
589
590 // Both not empty, do some math
591 bool changed { false };
592
593 // Lower
594 if ( !other.begin().isValid() || ( begin().isValid() && other.begin() < mLower ) )
595 {
596 mLower = other.begin();
597 mIncludeLower = other.includeBeginning();
598 changed = true;
599 }
600 else if ( other.begin() == mLower && other.includeBeginning() && !mIncludeLower )
601 {
602 mIncludeLower = true;
603 changed = true;
604 }
605
606 // Upper
607 if ( !other.end().isValid() || ( end().isValid() && other.end() > mUpper ) )
608 {
609 mUpper = other.end();
610 mIncludeUpper = other.includeEnd();
611 changed = true;
612 }
613 else if ( other.end() == mUpper && other.includeEnd() && !mIncludeUpper )
614 {
615 mIncludeUpper = true;
616 changed = true;
617 }
618 return changed;
619 }
620
621#ifndef SIP_RUN
622
636 static QList< QgsTemporalRange<T> > mergeRanges( const QList< QgsTemporalRange<T> > &ranges )
637 {
638 if ( ranges.empty() )
639 return {};
640
641 QList< QgsTemporalRange<T > > sortedRanges = ranges;
642 // cppcheck-suppress mismatchingContainerExpression
643 std::sort( sortedRanges.begin(), sortedRanges.end(), []( const QgsTemporalRange< T > &a, const QgsTemporalRange< T > &b ) -> bool { return a.begin() < b.begin(); } );
644 QList< QgsTemporalRange<T>> res;
645 res.reserve( sortedRanges.size() );
646
647 QgsTemporalRange<T> prevRange;
648 auto it = sortedRanges.constBegin();
649 prevRange = *it++;
650 for ( ; it != sortedRanges.constEnd(); ++it )
651 {
652 if ( prevRange.overlaps( *it ) )
653 {
654 prevRange.extend( *it );
655 }
656 else
657 {
658 res << prevRange;
659 prevRange = *it;
660 }
661 }
662 res << prevRange;
663 return res;
664 }
665#endif
666
667 bool operator==( const QgsTemporalRange<T> &other ) const
668 {
669 return mLower == other.mLower && mUpper == other.mUpper && mIncludeLower == other.includeBeginning() && mIncludeUpper == other.includeEnd();
670 }
671
672 bool operator!=( const QgsTemporalRange<T> &other ) const { return ( !operator==( other ) ); }
673
674 private:
675 T mLower;
676 T mUpper;
677 bool mIncludeLower = true;
678 bool mIncludeUpper = true;
679};
680
681
692// NOTE -- Python docstrings for QgsDateRange are patched in python/core/__init__.py
693
695
696
706// NOTE -- Python docstrings for QgsDateTimeRange are patched in python/core/__init__.py
707
709
710#endif // QGSRANGE_H
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:62
RangeLimits
Describes how the limits of a range are handled.
Definition qgis.h:4124
@ ExcludeLowerIncludeUpper
Lower value is excluded from the range, upper value in inccluded.
Definition qgis.h:4127
@ IncludeBoth
Both lower and upper values are included in the range.
Definition qgis.h:4125
@ ExcludeBoth
Both lower and upper values are excluded from the range.
Definition qgis.h:4128
@ IncludeLowerExcludeUpper
Lower value is included in the range, upper value is excluded.
Definition qgis.h:4126
QgsRange which stores a range of double values.
Definition qgsrange.h:217
QgsDoubleRange(double lower, double upper, Qgis::RangeLimits limits)
Constructor for QgsDoubleRange.
Definition qgsrange.h:225
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:239
bool operator==(const QgsDoubleRange &other) const
Definition qgsrange.h:281
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:266
bool operator!=(const QgsDoubleRange &other) const
Definition qgsrange.h:286
QgsRange which stores a range of integer values.
Definition qgsrange.h:300
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:349
QgsIntRange(int lower, int upper, Qgis::RangeLimits limits)
Constructor for QgsIntRange.
Definition qgsrange.h:308
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:322
A template based class for storing ranges (lower to upper values).
Definition qgsrange.h:48
QgsRange(T lower, T upper, Qgis::RangeLimits limits)
Constructor for QgsRange.
Definition qgsrange.h:67
bool includeUpper() const
Definition qgsrange.h:102
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:171
Qgis::RangeLimits rangeLimits() const
Returns the limit handling of the range.
Definition qgsrange.h:109
QgsRange(T lower, T upper, bool includeLower=true, bool includeUpper=true)
Constructor for QgsRange.
Definition qgsrange.h:54
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:138
double lower() const
Definition qgsrange.h:79
bool includeLower() const
Definition qgsrange.h:94
double upper() const
Definition qgsrange.h:86
bool isSingleton() const
Returns true if the range consists only of a single value or instant.
Definition qgsrange.h:132
bool operator!=(const QgsRange< T > &other) const
Definition qgsrange.h:193
bool contains(T element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:154
bool operator==(const QgsRange< T > &other) const
Definition qgsrange.h:191
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:126
A template based class for storing temporal ranges (beginning to end values).
Definition qgsrange.h:384
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition qgsrange.h:499
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition qgsrange.h:471
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition qgsrange.h:575
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition qgsrange.h:437
bool operator!=(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:672
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition qgsrange.h:392
bool operator==(const QgsTemporalRange< T > &other) const
Definition qgsrange.h:667
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition qgsrange.h:525
bool includeEnd() const
Definition qgsrange.h:430
bool includeBeginning() const
Definition qgsrange.h:423
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:451
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition qgsrange.h:636
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition qgsrange.h:444
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6975
#define SIP_DOC_TEMPLATE
Definition qgis_sip.h:231
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QgsTemporalRange< QDate > QgsDateRange
QgsRange which stores a range of dates.
Definition qgsrange.h:691
QgsTemporalRange< QDateTime > QgsDateTimeRange
QgsRange which stores a range of date times.
Definition qgsrange.h:705
QgsRange< double > QgsRangedoubleBase
Definition qgsrange.h:205
QgsRange< int > QgsRangeintBase
Definition qgsrange.h:206