QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
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 
44 template <typename T>
45 class QgsRange
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  {
110  if ( mIncludeLower && mIncludeUpper )
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 
230 class 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 
326 class 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 
372  QgsIntRange()
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 
417 template <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:3243
@ 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
static QList< QgsTemporalRange< T > > mergeRanges(const QList< QgsTemporalRange< T > > &ranges)
Merges a list of temporal ranges.
Definition: qgsrange.h:667
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
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:5172
#define SIP_DOC_TEMPLATE
Definition: qgis_sip.h:224
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)