QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
24 #include <QDate>
25 #include <QDateTime>
26 
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 )
56  , mIncludeLower( includeLower )
57  , mIncludeUpper( includeUpper )
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  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  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  bool lowerOk = ( mIncludeLower && mLower <= element )
130  || ( !mIncludeLower && mLower < element );
131  if ( !lowerOk )
132  return false;
133 
134  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  private:
171 
172  T mLower;
173  T mUpper;
174  bool mIncludeLower = true;
175  bool mIncludeUpper = true;
176 
177 };
178 
179 
188 
189 
190 
191 
200 
201 
218 template <typename T>
220 {
221  public:
222 
228 #ifndef SIP_RUN
229  QgsTemporalRange( const T &begin = T(), const T &end = T(), bool includeBeginning = true, bool includeEnd = true )
230  : mLower( begin )
231  , mUpper( end )
232  , mIncludeLower( includeBeginning )
233  , mIncludeUpper( includeEnd )
234  {}
235 #else
236  QgsTemporalRange( const T &begin, const T &end, bool includeBeginning = true, bool includeEnd = true );
237  // default constructor as default value for templates is not handled in SIP
238 #endif
239 
245  T begin() const { return mLower; }
246 
252  T end() const { return mUpper; }
253 
260  bool includeBeginning() const { return mIncludeLower; }
261 
267  bool includeEnd() const { return mIncludeUpper; }
268 
274  bool isInstant() const { return mLower.isValid() && mUpper.isValid() && mLower == mUpper && ( mIncludeLower || mIncludeUpper ); }
275 
281  bool isInfinite() const
282  {
283  return !mLower.isValid() && !mUpper.isValid();
284  }
285 
291  bool isEmpty() const
292  {
293  if ( !mLower.isValid() && !mUpper.isValid() )
294  return false;
295 
296  if ( mLower.isValid() != mUpper.isValid() )
297  return false;
298 
299  if ( mLower > mUpper )
300  return true;
301 
302  if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
303  return true;
304 
305  return false;
306  }
307 
311  bool contains( const QgsTemporalRange<T> &other ) const
312  {
313  if ( !other.mLower.isValid() && mLower.isValid() )
314  return false;
315 
316  if ( mLower.isValid() )
317  {
318  bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
319  || ( !mIncludeLower && mLower < other.mLower )
320  || ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
321  if ( !lowerOk )
322  return false;
323  }
324 
325  if ( !other.mUpper.isValid() && mUpper.isValid() )
326  return false;
327 
328  if ( mUpper.isValid() )
329  {
330  bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
331  || ( !mIncludeUpper && mUpper > other.mUpper )
332  || ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
333  if ( !upperOk )
334  return false;
335  }
336 
337  return true;
338  }
339 
343  bool contains( const T &element ) const
344  {
345  if ( !element.isValid() )
346  return false;
347 
348  if ( mLower.isValid() )
349  {
350  bool lowerOk = ( mIncludeLower && mLower <= element )
351  || ( !mIncludeLower && mLower < element );
352  if ( !lowerOk )
353  return false;
354  }
355 
356  if ( mUpper.isValid() )
357  {
358  bool upperOk = ( mIncludeUpper && mUpper >= element )
359  || ( !mIncludeUpper && mUpper > element );
360  if ( !upperOk )
361  return false;
362  }
363 
364  return true;
365  }
366 
370  bool overlaps( const QgsTemporalRange<T> &other ) const
371  {
372  if ( !mUpper.isValid() && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
373  return true;
374 
375  if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
376  && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
377  return true;
378 
379  if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
380  && ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
381  return true;
382 
383  if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
384  && ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
385  return true;
386 
387  if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
388  && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
389  return true;
390 
391  if ( mLower == other.mLower && mUpper == other.mUpper )
392  return true;
393 
394  return false;
395  }
396 
405  bool extend( const QgsTemporalRange<T> &other )
406  {
407  if ( other.isEmpty() )
408  {
409  return false;
410  }
411  else if ( isEmpty() )
412  {
413  mLower = other.begin();
414  mUpper = other.end();
415  mIncludeLower = other.includeBeginning();
416  mIncludeUpper = other.includeEnd();
417  return true;
418  }
419 
420  // Both not empty, do some math
421  bool changed { false };
422 
423  // Lower
424  if ( ! other.begin().isValid()
425  || ( begin().isValid() && other.begin() < mLower ) )
426  {
427  mLower = other.begin();
428  mIncludeLower = other.includeBeginning();
429  changed = true;
430  }
431  else if ( other.begin() == mLower && other.includeBeginning() && ! mIncludeLower )
432  {
433  mIncludeLower = true;
434  changed = true;
435  }
436 
437  // Upper
438  if ( ! other.end().isValid()
439  || ( end().isValid() && other.end() > mUpper ) )
440  {
441  mUpper = other.end();
442  mIncludeUpper = other.includeEnd();
443  changed = true;
444  }
445  else if ( other.end() == mUpper && other.includeEnd() && ! mIncludeUpper )
446  {
447  mIncludeUpper = true;
448  changed = true;
449  }
450  return changed;
451  }
452 
453  bool operator==( const QgsTemporalRange<T> &other ) const
454  {
455  return mLower == other.mLower &&
456  mUpper == other.mUpper &&
457  mIncludeLower == other.includeBeginning() &&
458  mIncludeUpper == other.includeEnd();
459  }
460 
461  bool operator!=( const QgsTemporalRange<T> &other ) const
462  {
463  return ( ! operator==( other ) );
464  }
465 
466  private:
467 
468  T mLower;
469  T mUpper;
470  bool mIncludeLower = true;
471  bool mIncludeUpper = true;
472 };
473 
474 
486 
497 typedef QgsTemporalRange< QDateTime > QgsDateTimeRange SIP_DOC_TEMPLATE;
498 
499 #endif // QGSRANGE_H
QgsRange::overlaps
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:146
QgsTemporalRange::isInstant
bool isInstant() const
Returns true if the range consists only of a single instant.
Definition: qgsrange.h:274
QgsIntRange
QgsRange< int > QgsIntRange
QgsRange which stores a range of integer values.
Definition: qgsrange.h:199
QgsRange::includeLower
bool includeLower() const
Returns true if the lower bound is inclusive, or false if the lower bound is exclusive.
Definition: qgsrange.h:80
QgsTemporalRange::includeBeginning
bool includeBeginning() const
Returns true if the beginning is inclusive, or false if the beginning is exclusive.
Definition: qgsrange.h:260
QgsTemporalRange
A template based class for storing temporal ranges (beginning to end values).
Definition: qgsrange.h:220
QgsTemporalRange::end
T end() const
Returns the upper bound of the range.
Definition: qgsrange.h:252
QgsRange::lower
T lower() const
Returns the lower bound of the range.
Definition: qgsrange.h:65
QgsRange
A template based class for storing ranges (lower to upper values).
Definition: qgsrange.h:46
QgsRange::upper
T upper() const
Returns the upper bound of the range.
Definition: qgsrange.h:72
qgis_sip.h
QgsTemporalRange::contains
bool contains(const T &element) const
Returns true if this range contains a specified element.
Definition: qgsrange.h:343
QgsTemporalRange::operator!=
bool operator!=(const QgsTemporalRange< T > &other) const
Definition: qgsrange.h:461
QgsTemporalRange::contains
bool contains(const QgsTemporalRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:311
QgsTemporalRange::includeEnd
bool includeEnd() const
Returns true if the end is inclusive, or false if the end is exclusive.
Definition: qgsrange.h:267
QgsTemporalRange::isInfinite
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:281
QgsRange::isEmpty
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
QgsTemporalRange::operator==
bool operator==(const QgsTemporalRange< T > &other) const
Definition: qgsrange.h:453
QgsTemporalRange::isEmpty
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:291
QgsTemporalRange::begin
T begin() const
Returns the beginning of the range.
Definition: qgsrange.h:245
QgsRange::isSingleton
bool isSingleton() const
Returns true if the range consists only of a single value or instant.
Definition: qgsrange.h:101
QgsRange::contains
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:107
SIP_DOC_TEMPLATE
QgsTemporalRange< QDate > QgsDateRange SIP_DOC_TEMPLATE
QgsRange which stores a range of dates.
Definition: qgsrange.h:485
QgsRange::contains
bool contains(T element) const
Returns true if this range contains a specified element.
Definition: qgsrange.h:127
QgsTemporalRange::extend
bool extend(const QgsTemporalRange< T > &other)
Extends the range in place by extending this range out to include an other range.
Definition: qgsrange.h:405
QgsTemporalRange::QgsTemporalRange
QgsTemporalRange(const T &begin=T(), const T &end=T(), bool includeBeginning=true, bool includeEnd=true)
Constructor for QgsTemporalRange.
Definition: qgsrange.h:229
QgsTemporalRange::overlaps
bool overlaps(const QgsTemporalRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:370
QgsDoubleRange
QgsRange< double > QgsDoubleRange
QgsRange which stores a range of double values.
Definition: qgsrange.h:187
QgsRange::QgsRange
QgsRange(T lower, T upper, bool includeLower=true, bool includeUpper=true)
Constructor for QgsRange.
Definition: qgsrange.h:53
QgsRange::includeUpper
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
Definition: qgsrange.h:88