mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
New QgsRange template based class for storing interval ranges
QgsRange classes represent a range of values of some element type. For instance, ranges of QDateTime might be used to represent the ranges of timestamp ranges. Ranges can indicate whether the upper and lower values are inclusive or exclusive. The inclusivity or exclusivity of bounds is considered when determining things like whether ranges overlap or during calculation of range intersections. Includes typedefs for QgsDoubleRange, QgsIntRange, QgsDateRange.
This commit is contained in:
parent
33b6c41dd2
commit
c4ea048e5b
@ -94,6 +94,7 @@ core/qgspropertycollection.sip
|
||||
core/qgsprovidermetadata.sip
|
||||
core/qgsproviderregistry.sip
|
||||
core/qgspythonrunner.sip
|
||||
core/qgsrange.sip
|
||||
core/qgsrelation.sip
|
||||
core/qgsrelationmanager.sip
|
||||
core/qgsrenderchecker.sip
|
||||
|
@ -127,6 +127,7 @@
|
||||
%Include qgsprovidermetadata.sip
|
||||
%Include qgsproviderregistry.sip
|
||||
%Include qgspythonrunner.sip
|
||||
%Include qgsrange.sip
|
||||
%Include qgsrelation.sip
|
||||
%Include qgsrelationmanager.sip
|
||||
%Include qgsrenderchecker.sip
|
||||
|
57
python/core/qgsrange.sip
Normal file
57
python/core/qgsrange.sip
Normal file
@ -0,0 +1,57 @@
|
||||
class QgsDoubleRange
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsrange.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
QgsDoubleRange( double lower, double upper, bool includeLower = true, bool includeUpper = true );
|
||||
double lower() const;
|
||||
double upper() const;
|
||||
bool includeLower() const;
|
||||
bool includeUpper() const;
|
||||
bool isEmpty() const;
|
||||
bool contains( const QgsDoubleRange &other ) const;
|
||||
bool contains( double element ) const;
|
||||
bool overlaps( const QgsDoubleRange &other ) const;
|
||||
};
|
||||
|
||||
class QgsIntRange
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsrange.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
QgsIntRange( int lower, int upper, bool includeLower = true, bool includeUpper = true );
|
||||
int lower() const;
|
||||
int upper() const;
|
||||
bool includeLower() const;
|
||||
bool includeUpper() const;
|
||||
bool isEmpty() const;
|
||||
bool contains( const QgsIntRange &other ) const;
|
||||
bool contains( int element ) const;
|
||||
bool overlaps( const QgsIntRange &other ) const;
|
||||
};
|
||||
|
||||
class QgsDateRange
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsrange.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
QgsDateRange( QDate lower, QDate upper, bool includeLower = true, bool includeUpper = true );
|
||||
QDate lower() const;
|
||||
QDate upper() const;
|
||||
bool includeLower() const;
|
||||
bool includeUpper() const;
|
||||
bool isEmpty() const;
|
||||
bool contains( const QgsDateRange &other ) const;
|
||||
bool contains( QDate element ) const;
|
||||
bool overlaps( const QgsDateRange &other ) const;
|
||||
};
|
||||
|
@ -762,6 +762,7 @@ SET(QGIS_CORE_HDRS
|
||||
qgsprovidermetadata.h
|
||||
qgsproviderregistry.h
|
||||
qgspythonrunner.h
|
||||
qgsrange.h
|
||||
qgsrenderchecker.h
|
||||
qgsrendercontext.h
|
||||
qgsruntimeprofiler.h
|
||||
|
307
src/core/qgsrange.h
Normal file
307
src/core/qgsrange.h
Normal file
@ -0,0 +1,307 @@
|
||||
/***************************************************************************
|
||||
qgsrange.h
|
||||
----------
|
||||
begin : April 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSRANGE_H
|
||||
#define QGSRANGE_H
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgis_core.h"
|
||||
|
||||
/**
|
||||
* \class QgsRange
|
||||
* \ingroup core
|
||||
* A template based class for storing ranges (lower to upper values).
|
||||
*
|
||||
* QgsRange classes represent a range of values of some element type. For instance,
|
||||
* ranges of QDateTime might be used to represent the ranges of timestamp ranges.
|
||||
*
|
||||
* Ranges can indicate whether the upper and lower values are inclusive or exclusive.
|
||||
* The inclusivity or exclusivity of bounds is considered when determining things like
|
||||
* whether ranges overlap or during calculation of range intersections.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
* \see QgsDoubleRange
|
||||
* \see QgsIntRange
|
||||
* \note not available in Python bindings
|
||||
*/
|
||||
template <class T> class CORE_EXPORT QgsRange
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor for QgsRange. The \a lower and \a upper bounds are specified,
|
||||
* and optionally whether or not these bounds are included in the range.
|
||||
*/
|
||||
QgsRange( T lower, T upper, bool includeLower = true, bool includeUpper = true )
|
||||
: mLower( lower )
|
||||
, mUpper( upper )
|
||||
, mIncludeLower( includeLower )
|
||||
, mIncludeUpper( includeUpper )
|
||||
{}
|
||||
|
||||
/**
|
||||
* Returns the lower bound of the range.
|
||||
* \see upper()
|
||||
* \see includeLower()
|
||||
*/
|
||||
T lower() const { return mLower; }
|
||||
|
||||
/**
|
||||
* Returns the upper bound of the range.
|
||||
* \see lower()
|
||||
* \see includeUpper()
|
||||
*/
|
||||
T upper() const { return mUpper; }
|
||||
|
||||
/**
|
||||
* Returns true if the lower bound is inclusive, or false if the lower
|
||||
* bound is exclusive.
|
||||
* \see lower()
|
||||
* \see includeUpper()
|
||||
*/
|
||||
bool includeLower() const { return mIncludeLower; }
|
||||
|
||||
/**
|
||||
* Returns true if the upper bound is inclusive, or false if the upper
|
||||
* bound is exclusive.
|
||||
* \see upper()
|
||||
* \see includeLower()
|
||||
*/
|
||||
bool includeUpper() const { return mIncludeUpper; }
|
||||
|
||||
/**
|
||||
* Returns true if the range is empty, ie the lower bound equals (or exceeds) the upper bound
|
||||
* and either the bounds are exclusive.
|
||||
*/
|
||||
bool isEmpty() const { return mLower > mUpper || ( mUpper == mLower && !( mIncludeLower || mIncludeUpper ) ); }
|
||||
|
||||
/**
|
||||
* Returns true if this range contains another range.
|
||||
* \see overlaps()
|
||||
*/
|
||||
bool contains( const QgsRange<T> &other ) const
|
||||
{
|
||||
bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
|
||||
|| ( !mIncludeLower && mLower < other.mLower )
|
||||
|| ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
|
||||
if ( !lowerOk )
|
||||
return false;
|
||||
|
||||
bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
|
||||
|| ( !mIncludeUpper && mUpper > other.mUpper )
|
||||
|| ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
|
||||
if ( !upperOk )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this range contains a specified \a element.
|
||||
*/
|
||||
bool contains( T element ) const
|
||||
{
|
||||
bool lowerOk = ( mIncludeLower && mLower <= element )
|
||||
|| ( !mIncludeLower && mLower < element );
|
||||
if ( !lowerOk )
|
||||
return false;
|
||||
|
||||
bool upperOk = ( mIncludeUpper && mUpper >= element )
|
||||
|| ( !mIncludeUpper && mUpper > element );
|
||||
if ( !upperOk )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this range overlaps another range.
|
||||
* \see contains()
|
||||
*/
|
||||
bool overlaps( const QgsRange<T> &other ) const
|
||||
{
|
||||
if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
|
||||
&& ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( mLower == other.mLower && mUpper == other.mUpper )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
T mLower;
|
||||
T mUpper;
|
||||
bool mIncludeLower = true;
|
||||
bool mIncludeUpper = true;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* QgsRange which stores a range of double values.
|
||||
* \since QGIS 3.0
|
||||
* \see QgsIntRange
|
||||
* \see QgsDateRange
|
||||
* \see QgsDateTimeRange
|
||||
*/
|
||||
typedef QgsRange< double > QgsDoubleRange;
|
||||
|
||||
/**
|
||||
* QgsRange which stores a range of integer values.
|
||||
* \since QGIS 3.0
|
||||
* \see QgsDoubleRange
|
||||
* \see QgsDateRange
|
||||
* \see QgsDateTimeRange
|
||||
*/
|
||||
typedef QgsRange< int > QgsIntRange;
|
||||
|
||||
|
||||
// specialization required to handle invalid QDate bounds
|
||||
template<>
|
||||
bool QgsRange<QDate>::isEmpty() const
|
||||
{
|
||||
if ( !mLower.isValid() && !mUpper.isValid() )
|
||||
return true;
|
||||
|
||||
if ( mLower.isValid() != mUpper.isValid() )
|
||||
return false;
|
||||
|
||||
if ( mLower > mUpper )
|
||||
return true;
|
||||
|
||||
if ( mLower == mUpper && !( mIncludeLower || mIncludeUpper ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool QgsRange<QDate>::contains( const QgsRange<QDate> &other ) const
|
||||
{
|
||||
if ( !other.mLower.isValid() && mLower.isValid() )
|
||||
return false;
|
||||
|
||||
if ( mLower.isValid() )
|
||||
{
|
||||
bool lowerOk = ( mIncludeLower && mLower <= other.mLower )
|
||||
|| ( !mIncludeLower && mLower < other.mLower )
|
||||
|| ( !mIncludeLower && !other.mIncludeLower && mLower <= other.mLower );
|
||||
if ( !lowerOk )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !other.mUpper.isValid() && mUpper.isValid() )
|
||||
return false;
|
||||
|
||||
if ( mUpper.isValid() )
|
||||
{
|
||||
bool upperOk = ( mIncludeUpper && mUpper >= other.mUpper )
|
||||
|| ( !mIncludeUpper && mUpper > other.mUpper )
|
||||
|| ( !mIncludeUpper && !other.mIncludeUpper && mUpper >= other.mUpper );
|
||||
if ( !upperOk )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool QgsRange<QDate>::contains( QDate element ) const
|
||||
{
|
||||
if ( !element.isValid() )
|
||||
return false;
|
||||
|
||||
if ( mLower.isValid() )
|
||||
{
|
||||
bool lowerOk = ( mIncludeLower && mLower <= element )
|
||||
|| ( !mIncludeLower && mLower < element );
|
||||
if ( !lowerOk )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( mUpper.isValid() )
|
||||
{
|
||||
bool upperOk = ( mIncludeUpper && mUpper >= element )
|
||||
|| ( !mIncludeUpper && mUpper > element );
|
||||
if ( !upperOk )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool QgsRange<QDate>::overlaps( const QgsRange<QDate> &other ) const
|
||||
{
|
||||
if ( !mUpper.isValid() && ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower <= other.mLower ) || ( !mIncludeLower && mLower < other.mLower ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mLower ) || ( !mIncludeUpper && mUpper > other.mLower ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) )
|
||||
&& ( ( mIncludeUpper && mUpper >= other.mUpper ) || ( !mIncludeUpper && mUpper > other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( ( ( mIncludeLower && mLower >= other.mLower ) || ( !mIncludeLower && mLower > other.mLower ) )
|
||||
&& ( ( mIncludeLower && mLower <= other.mUpper ) || ( !mIncludeLower && mLower < other.mUpper ) ) )
|
||||
return true;
|
||||
|
||||
if ( mLower == other.mLower && mUpper == other.mUpper )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* QgsRange which stores a range of dates.
|
||||
*
|
||||
* Invalid QDates as the lower or upper bound are permitted. In this case,
|
||||
* the bound is considered to be infinite. E.g. QgsDateRange(QDate(),QDate(2017,1,1))
|
||||
* is treated as a range containing all dates before 2017-1-1.
|
||||
* QgsDateRange(QDate(2017,1,1),QDate()) is treated as a range containing all dates after 2017-1-1.
|
||||
* \since QGIS 3.0
|
||||
* \see QgsIntRange
|
||||
* \see QgsDoubleRange
|
||||
* \see QgsDateTimeRange
|
||||
*/
|
||||
typedef QgsRange< QDate > QgsDateRange;
|
||||
|
||||
|
||||
|
||||
#endif // QGSRANGE_H
|
@ -98,6 +98,7 @@ ADD_PYTHON_TEST(PyQgsPoint test_qgspoint.py)
|
||||
ADD_PYTHON_TEST(PyQgsPointClusterRenderer test_qgspointclusterrenderer.py)
|
||||
ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer.py)
|
||||
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
|
||||
ADD_PYTHON_TEST(PyQgsRange test_qgsrange.py)
|
||||
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
|
||||
ADD_PYTHON_TEST(PyQgsRasterFileWriter test_qgsrasterfilewriter.py)
|
||||
ADD_PYTHON_TEST(PyQgsRasterFileWriterTask test_qgsrasterfilewritertask.py)
|
||||
|
319
tests/src/python/test_qgsrange.py
Normal file
319
tests/src/python/test_qgsrange.py
Normal file
@ -0,0 +1,319 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsRange
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
"""
|
||||
__author__ = 'Nyall Dawson'
|
||||
__date__ = '11.04.2017'
|
||||
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.testing import unittest
|
||||
from qgis.core import (QgsIntRange,
|
||||
QgsDateRange)
|
||||
from qgis.PyQt.QtCore import QDate
|
||||
|
||||
|
||||
class TestQgsIntRange(unittest.TestCase):
|
||||
|
||||
def testGetters(self):
|
||||
range = QgsIntRange(1, 11)
|
||||
self.assertEqual(range.lower(), 1)
|
||||
self.assertEqual(range.upper(), 11)
|
||||
self.assertTrue(range.includeLower())
|
||||
self.assertTrue(range.includeUpper())
|
||||
|
||||
range = QgsIntRange(-1, 3, False, False)
|
||||
self.assertEqual(range.lower(), -1)
|
||||
self.assertEqual(range.upper(), 3)
|
||||
self.assertFalse(range.includeLower())
|
||||
self.assertFalse(range.includeUpper())
|
||||
|
||||
def testIsEmpty(self):
|
||||
range = QgsIntRange(1, 1)
|
||||
# should not be empty because 1 is included
|
||||
self.assertFalse(range.isEmpty())
|
||||
|
||||
range = QgsIntRange(1, 1, False, False)
|
||||
# should be empty because 1 is NOT included
|
||||
self.assertTrue(range.isEmpty())
|
||||
|
||||
# invalid range is empty
|
||||
range = QgsIntRange(1, -1)
|
||||
self.assertTrue(range.isEmpty())
|
||||
|
||||
def testContains(self):
|
||||
# includes both ends
|
||||
range = QgsIntRange(0, 10)
|
||||
self.assertTrue(range.contains(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.contains(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.contains(QgsIntRange(0, 9)))
|
||||
self.assertTrue(range.contains(QgsIntRange(0, 10)))
|
||||
self.assertFalse(range.contains(QgsIntRange(-1, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(1, 11)))
|
||||
|
||||
# does not include left end
|
||||
range = QgsIntRange(0, 10, False, True)
|
||||
self.assertTrue(range.contains(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.contains(QgsIntRange(1, 10)))
|
||||
self.assertFalse(range.contains(QgsIntRange(0, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(0, 10)))
|
||||
self.assertFalse(range.contains(QgsIntRange(-1, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(1, 11)))
|
||||
|
||||
# does not include right end
|
||||
range = QgsIntRange(0, 10, True, False)
|
||||
self.assertTrue(range.contains(QgsIntRange(1, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.contains(QgsIntRange(0, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(0, 10)))
|
||||
self.assertFalse(range.contains(QgsIntRange(-1, 9)))
|
||||
self.assertFalse(range.contains(QgsIntRange(1, 11)))
|
||||
|
||||
def testContainsElement(self):
|
||||
# includes both ends
|
||||
range = QgsIntRange(0, 10)
|
||||
self.assertTrue(range.contains(0))
|
||||
self.assertTrue(range.contains(5))
|
||||
self.assertTrue(range.contains(10))
|
||||
self.assertFalse(range.contains(-1))
|
||||
self.assertFalse(range.contains(11))
|
||||
|
||||
# includes left end
|
||||
range = QgsIntRange(0, 10, True, False)
|
||||
self.assertTrue(range.contains(0))
|
||||
self.assertTrue(range.contains(5))
|
||||
self.assertFalse(range.contains(10))
|
||||
self.assertFalse(range.contains(-1))
|
||||
self.assertFalse(range.contains(11))
|
||||
|
||||
# includes right end
|
||||
range = QgsIntRange(0, 10, False, True)
|
||||
self.assertFalse(range.contains(0))
|
||||
self.assertTrue(range.contains(5))
|
||||
self.assertTrue(range.contains(10))
|
||||
self.assertFalse(range.contains(-1))
|
||||
self.assertFalse(range.contains(11))
|
||||
|
||||
# includes neither end
|
||||
range = QgsIntRange(0, 10, False, False)
|
||||
self.assertFalse(range.contains(0))
|
||||
self.assertTrue(range.contains(5))
|
||||
self.assertFalse(range.contains(10))
|
||||
self.assertFalse(range.contains(-1))
|
||||
self.assertFalse(range.contains(11))
|
||||
|
||||
def testOverlaps(self):
|
||||
# includes both ends
|
||||
range = QgsIntRange(0, 10)
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(10, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 0)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-10, -1)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(11, 12)))
|
||||
|
||||
# includes left end
|
||||
range = QgsIntRange(0, 10, True, False)
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 11)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(10, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 0)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-10, -1)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(11, 12)))
|
||||
|
||||
# includes right end
|
||||
range = QgsIntRange(0, 10, False, True)
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(10, 11)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-1, 0)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-10, -1)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(11, 12)))
|
||||
|
||||
# includes neither end
|
||||
range = QgsIntRange(0, 10, False, False)
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(0, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 10)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 9)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(1, 11)))
|
||||
self.assertTrue(range.overlaps(QgsIntRange(-1, 11)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(10, 11)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-1, 0)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(-10, -1)))
|
||||
self.assertFalse(range.overlaps(QgsIntRange(11, 12)))
|
||||
|
||||
|
||||
class TestQgsDateRange(unittest.TestCase):
|
||||
|
||||
def testGetters(self):
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertEqual(range.lower(), QDate(2010, 3, 1))
|
||||
self.assertEqual(range.upper(), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.includeLower())
|
||||
self.assertTrue(range.includeUpper())
|
||||
|
||||
range = QgsDateRange(QDate(), QDate(2010, 6, 2))
|
||||
self.assertFalse(range.lower().isValid())
|
||||
self.assertEqual(range.upper(), QDate(2010, 6, 2))
|
||||
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate())
|
||||
self.assertEqual(range.lower(), QDate(2010, 3, 1))
|
||||
self.assertFalse(range.upper().isValid())
|
||||
|
||||
def testIsEmpty(self):
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertFalse(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(), QDate(2010, 6, 2))
|
||||
self.assertFalse(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate())
|
||||
self.assertFalse(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(), QDate())
|
||||
self.assertTrue(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(2017, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 3, 1))
|
||||
self.assertFalse(range.isEmpty())
|
||||
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 3, 1), False, False)
|
||||
self.assertTrue(range.isEmpty())
|
||||
|
||||
def testContains(self):
|
||||
# includes both ends
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
|
||||
# infinite left end
|
||||
range = QgsDateRange(QDate(), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
|
||||
# infinite right end
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate())
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertTrue(range.contains(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertFalse(range.contains(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
|
||||
def testContainsElement(self):
|
||||
# includes both ends
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.contains(QDate(2010, 3, 1)))
|
||||
self.assertTrue(range.contains(QDate(2010, 5, 2)))
|
||||
self.assertTrue(range.contains(QDate(2010, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate(2009, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate(2017, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate()))
|
||||
|
||||
# infinite left end
|
||||
range = QgsDateRange(QDate(), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.contains(QDate(2010, 3, 1)))
|
||||
self.assertTrue(range.contains(QDate(2010, 5, 2)))
|
||||
self.assertTrue(range.contains(QDate(2010, 6, 2)))
|
||||
self.assertTrue(range.contains(QDate(2009, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate(2017, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate()))
|
||||
|
||||
# infinite right end
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate())
|
||||
self.assertTrue(range.contains(QDate(2010, 3, 1)))
|
||||
self.assertTrue(range.contains(QDate(2010, 5, 2)))
|
||||
self.assertTrue(range.contains(QDate(2010, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate(2009, 6, 2)))
|
||||
self.assertTrue(range.contains(QDate(2017, 6, 2)))
|
||||
self.assertFalse(range.contains(QDate()))
|
||||
|
||||
def testOverlaps(self):
|
||||
# includes both ends
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
self.assertFalse(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2009, 8, 5))))
|
||||
self.assertFalse(range.overlaps(QgsDateRange(QDate(2019, 4, 1), QDate(2019, 8, 5))))
|
||||
|
||||
range = QgsDateRange(QDate(), QDate(2010, 6, 2))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2009, 8, 5))))
|
||||
self.assertFalse(range.overlaps(QgsDateRange(QDate(2019, 4, 1), QDate(2019, 8, 5))))
|
||||
|
||||
range = QgsDateRange(QDate(2010, 3, 1), QDate())
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 3, 1), QDate(2010, 6, 2))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2010, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate(2017, 4, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2010, 4, 1), QDate())))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(), QDate(2010, 4, 1))))
|
||||
self.assertFalse(range.overlaps(QgsDateRange(QDate(2009, 4, 1), QDate(2009, 8, 5))))
|
||||
self.assertTrue(range.overlaps(QgsDateRange(QDate(2019, 4, 1), QDate(2019, 8, 5))))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user