Skip to content

Commit 20cc7a7

Browse files
committed
Boost test coverage for QgsRectangle
1 parent d704163 commit 20cc7a7

File tree

3 files changed

+153
-10
lines changed

3 files changed

+153
-10
lines changed

src/core/geometry/qgsrectangle.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ QgsRectangle &QgsRectangle::operator+=( const QgsVector v )
254254

255255
bool QgsRectangle::isEmpty() const
256256
{
257-
return mXmax <= mXmin || mYmax <= mYmin;
257+
return mXmax < mXmin || mYmax < mYmin || qgsDoubleNear( mXmax, mXmin ) || qgsDoubleNear( mYmax, mYmin );
258258
}
259259

260260
bool QgsRectangle::isNull() const

tests/src/core/testqgsrectangle.cpp

+130
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,37 @@ class TestQgsRectangle: public QObject
2525
{
2626
Q_OBJECT
2727
private slots:
28+
void isEmpty();
2829
void manipulate();
2930
void regression6194();
3031
void operators();
3132
void asVariant();
3233
void referenced();
34+
void minimal();
35+
void grow();
36+
void include();
37+
void buffered();
38+
void isFinite();
39+
void dataStream();
3340
};
3441

42+
void TestQgsRectangle::isEmpty()
43+
{
44+
QVERIFY( QgsRectangle().isEmpty() );
45+
QVERIFY( QgsRectangle( 1, 2, 1, 4 ).isEmpty() );
46+
QVERIFY( QgsRectangle( 2, 1, 4, 1 ).isEmpty() );
47+
//constructor should normalize
48+
QVERIFY( !QgsRectangle( 2, 2, 1, 4 ).isEmpty() );
49+
QVERIFY( !QgsRectangle( 1, 2, 2, 1 ).isEmpty() );
50+
51+
QgsRectangle r( 2, 2, 3, 4 );
52+
r.setXMaximum( 1 );
53+
QVERIFY( r.isEmpty() );
54+
r = QgsRectangle( 2, 2, 3, 4 );
55+
r.setYMaximum( 1 );
56+
QVERIFY( r.isEmpty() );
57+
}
58+
3559
void TestQgsRectangle::manipulate()
3660
{
3761
// Set up two intersecting rectangles and normalize
@@ -155,5 +179,111 @@ void TestQgsRectangle::referenced()
155179
QCOMPARE( rect2.crs().authid(), QStringLiteral( "EPSG:28356" ) );
156180
}
157181

182+
void TestQgsRectangle::minimal()
183+
{
184+
QgsRectangle rect1 = QgsRectangle( 10.0, 20.0, 110.0, 220.0 );
185+
rect1.setMinimal();
186+
QVERIFY( rect1.isEmpty() );
187+
QVERIFY( rect1.isNull() );
188+
}
189+
190+
void TestQgsRectangle::grow()
191+
{
192+
QgsRectangle rect1 = QgsRectangle( 10.0, 20.0, 110.0, 220.0 );
193+
rect1.grow( 11 );
194+
QCOMPARE( rect1.xMinimum(), -1.0 );
195+
QCOMPARE( rect1.yMinimum(), 9.0 );
196+
QCOMPARE( rect1.xMaximum(), 121.0 );
197+
QCOMPARE( rect1.yMaximum(), 231.0 );
198+
199+
QgsRectangle rect2 = QgsRectangle( -110.0, -220.0, -10.0, -20.0 );
200+
rect2.grow( 11 );
201+
QCOMPARE( rect2.xMinimum(), -121.0 );
202+
QCOMPARE( rect2.yMinimum(), -231.0 );
203+
QCOMPARE( rect2.xMaximum(), 1.0 );
204+
QCOMPARE( rect2.yMaximum(), -9.0 );
205+
}
206+
207+
void TestQgsRectangle::include()
208+
{
209+
QgsRectangle rect1 = QgsRectangle( 10.0, 20.0, 110.0, 220.0 );
210+
// inside
211+
rect1.include( QgsPointXY( 15, 50 ) );
212+
QCOMPARE( rect1.xMinimum(), 10.0 );
213+
QCOMPARE( rect1.yMinimum(), 20.0 );
214+
QCOMPARE( rect1.xMaximum(), 110.0 );
215+
QCOMPARE( rect1.yMaximum(), 220.0 );
216+
217+
rect1.include( QgsPointXY( 5, 50 ) );
218+
QCOMPARE( rect1.xMinimum(), 5.0 );
219+
QCOMPARE( rect1.yMinimum(), 20.0 );
220+
QCOMPARE( rect1.xMaximum(), 110.0 );
221+
QCOMPARE( rect1.yMaximum(), 220.0 );
222+
223+
rect1.include( QgsPointXY( 15, 12 ) );
224+
QCOMPARE( rect1.xMinimum(), 5.0 );
225+
QCOMPARE( rect1.yMinimum(), 12.0 );
226+
QCOMPARE( rect1.xMaximum(), 110.0 );
227+
QCOMPARE( rect1.yMaximum(), 220.0 );
228+
229+
rect1.include( QgsPointXY( 115, 12 ) );
230+
QCOMPARE( rect1.xMinimum(), 5.0 );
231+
QCOMPARE( rect1.yMinimum(), 12.0 );
232+
QCOMPARE( rect1.xMaximum(), 115.0 );
233+
QCOMPARE( rect1.yMaximum(), 220.0 );
234+
235+
rect1.include( QgsPointXY( 115, 242 ) );
236+
QCOMPARE( rect1.xMinimum(), 5.0 );
237+
QCOMPARE( rect1.yMinimum(), 12.0 );
238+
QCOMPARE( rect1.xMaximum(), 115.0 );
239+
QCOMPARE( rect1.yMaximum(), 242.0 );
240+
241+
}
242+
243+
void TestQgsRectangle::buffered()
244+
{
245+
QgsRectangle rect = QgsRectangle( 10.0, 20.0, 110.0, 220.0 );
246+
QgsRectangle rect1 = rect.buffered( 11 );
247+
QCOMPARE( rect1.xMinimum(), -1.0 );
248+
QCOMPARE( rect1.yMinimum(), 9.0 );
249+
QCOMPARE( rect1.xMaximum(), 121.0 );
250+
QCOMPARE( rect1.yMaximum(), 231.0 );
251+
252+
rect = QgsRectangle( -110.0, -220.0, -10.0, -20.0 );
253+
QgsRectangle rect2 = rect.buffered( 11 );
254+
QCOMPARE( rect2.xMinimum(), -121.0 );
255+
QCOMPARE( rect2.yMinimum(), -231.0 );
256+
QCOMPARE( rect2.xMaximum(), 1.0 );
257+
QCOMPARE( rect2.yMaximum(), -9.0 );
258+
}
259+
260+
void TestQgsRectangle::isFinite()
261+
{
262+
QVERIFY( QgsRectangle( 1, 2, 3, 4 ).isFinite() );
263+
QVERIFY( !QgsRectangle( std::numeric_limits<double>::infinity(), 2, 3, 4 ).isFinite() );
264+
QVERIFY( !QgsRectangle( 1, std::numeric_limits<double>::infinity(), 3, 4 ).isFinite() );
265+
QVERIFY( !QgsRectangle( 1, 2, std::numeric_limits<double>::infinity(), 4 ).isFinite() );
266+
QVERIFY( !QgsRectangle( 1, 2, 3, std::numeric_limits<double>::infinity() ).isFinite() );
267+
QVERIFY( !QgsRectangle( std::numeric_limits<double>::quiet_NaN(), 2, 3, 4 ).isFinite() );
268+
QVERIFY( !QgsRectangle( 1, std::numeric_limits<double>::quiet_NaN(), 3, 4 ).isFinite() );
269+
QVERIFY( !QgsRectangle( 1, 2, std::numeric_limits<double>::quiet_NaN(), 4 ).isFinite() );
270+
QVERIFY( !QgsRectangle( 1, 2, 3, std::numeric_limits<double>::quiet_NaN() ).isFinite() );
271+
}
272+
273+
void TestQgsRectangle::dataStream()
274+
{
275+
QgsRectangle original( 10.1, 20.2, 110.3, 220.4 );
276+
277+
QByteArray ba;
278+
QDataStream ds( &ba, QIODevice::ReadWrite );
279+
ds << original;
280+
281+
QgsRectangle result;
282+
ds.device()->seek( 0 );
283+
ds >> result;
284+
285+
QCOMPARE( result, original );
286+
}
287+
158288
QGSTEST_MAIN( TestQgsRectangle )
159289
#include "testqgsrectangle.moc"

tests/src/python/test_qgsrectangle.py

+22-9
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,8 @@
2424

2525
class TestQgsRectangle(unittest.TestCase):
2626

27-
# Because isEmpty() is not returning expected result in 9b0fee3
28-
29-
@unittest.expectedFailure
3027
def testCtor(self):
3128
rect = QgsRectangle(5.0, 5.0, 10.0, 10.0)
32-
33-
myExpectedResult = True
34-
myResult = rect.isEmpty()
35-
myMessage = ('Expected: %s Got: %s' % (myExpectedResult, myResult))
36-
assert rect.isEmpty(), myMessage
37-
3829
myMessage = ('Expected: %s\nGot: %s\n' %
3930
(5.0, rect.xMinimum()))
4031
assert rect.xMinimum() == 5.0, myMessage
@@ -204,13 +195,22 @@ def testAsWktPolygon(self):
204195

205196
def testToString(self):
206197
"""Test the different string representations"""
198+
self.assertEqual(QgsRectangle().toString(), 'Empty')
207199
rect = QgsRectangle(0, 0.1, 0.2, 0.3)
208200
myExpectedString = '0.0000000000000000,0.1000000000000000 : 0.2000000000000000,0.3000000000000000'
209201
myString = rect.toString()
210202
myMessage = ('Expected: %s\nGot: %s\n' %
211203
(myExpectedString, myString))
212204
assert myString == myExpectedString, myMessage
213205

206+
# can't test the actual result here, because floating point inaccuracies mean the result is unpredictable
207+
# at this precision
208+
self.assertEqual(len(rect.toString(20)), 93)
209+
210+
myMessage = ('Expected: %s\nGot: %s\n' %
211+
(myExpectedString, myString))
212+
assert myString == myExpectedString, myMessage
213+
214214
myExpectedString = '0,0 : 0,0'
215215
myString = rect.toString(0)
216216
myMessage = ('Expected: %s\nGot: %s\n' %
@@ -242,6 +242,11 @@ def testToString(self):
242242
(myExpectedString, myString))
243243
assert myString == myExpectedString, myMessage
244244

245+
def testAsPolygon(self):
246+
"""Test string representation as polygon"""
247+
self.assertEqual(QgsRectangle().asPolygon(), '0.00000000 0.00000000, 0.00000000 0.00000000, 0.00000000 0.00000000, 0.00000000 0.00000000, 0.00000000 0.00000000')
248+
self.assertEqual(QgsRectangle(0, 0.1, 0.2, 0.3).asPolygon(), '0.00000000 0.10000000, 0.00000000 0.30000000, 0.20000000 0.30000000, 0.20000000 0.10000000, 0.00000000 0.10000000')
249+
245250
def testToBox3d(self):
246251
rect = QgsRectangle(0, 0.1, 0.2, 0.3)
247252
box = rect.toBox3d(0.4, 0.5)
@@ -261,6 +266,14 @@ def testOperators(self):
261266
rect1 -= rect1.center() - QgsPointXY(0, 0)
262267
assert rect1.center() == QgsPointXY(0, 0)
263268

269+
def testInvert(self):
270+
rect = QgsRectangle(0, 0.1, 0.2, 0.3)
271+
rect.invert()
272+
self.assertEqual(rect.xMinimum(), 0.1)
273+
self.assertEqual(rect.yMinimum(), 0)
274+
self.assertEqual(rect.xMaximum(), 0.3)
275+
self.assertEqual(rect.yMaximum(), 0.2)
276+
264277

265278
if __name__ == '__main__':
266279
unittest.main()

0 commit comments

Comments
 (0)