From 1ccf5584974cffa389a2b68523a39013cf5ac054 Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Sat, 7 Feb 2015 15:05:00 +0100 Subject: [PATCH] Add a new visiblePolygon method to QgsMapSettings Centralizes code to return a possible rotated map area boundaries. Makes use of the new method from the grid decoration. Adds new testcase for QgsMapSettings, including test for visibleExtent, mapUnitsPerPixel and the new visiblePolygon method. --- python/core/qgsmapsettings.sip | 3 + src/app/qgsdecorationgrid.cpp | 10 +- src/core/qgsmapsettings.cpp | 15 +++ src/core/qgsmapsettings.h | 3 + tests/src/core/CMakeLists.txt | 1 + tests/src/core/testqgsmapsettings.cpp | 141 ++++++++++++++++++++++++++ 6 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 tests/src/core/testqgsmapsettings.cpp diff --git a/python/core/qgsmapsettings.sip b/python/core/qgsmapsettings.sip index e4e131b8d6b..f7af8766e31 100644 --- a/python/core/qgsmapsettings.sip +++ b/python/core/qgsmapsettings.sip @@ -110,6 +110,9 @@ class QgsMapSettings bool hasValidSettings() const; //! Return the actual extent derived from requested extent that takes takes output image size into account QgsRectangle visibleExtent() const; + //! Return the visible area as a polygon (may be rotated) + //! @note added in 2.8 + QPolygonF visiblePolygon() const; //! Return the distance in geographical coordinates that equals to one pixel in the map double mapUnitsPerPixel() const; //! Return the calculated scale of the map diff --git a/src/app/qgsdecorationgrid.cpp b/src/app/qgsdecorationgrid.cpp index 4847f4ce596..ae5551fa886 100644 --- a/src/app/qgsdecorationgrid.cpp +++ b/src/app/qgsdecorationgrid.cpp @@ -524,15 +524,7 @@ QPolygonF canvasPolygon() const QgsMapCanvas& mapCanvas = canvas(); const QgsMapSettings& mapSettings = mapCanvas.mapSettings(); - const QSize& sz = mapSettings.outputSize(); - const QgsMapToPixel& m2p = mapSettings.mapToPixel(); - - poly << m2p.toMapCoordinatesF( 0, 0 ).toQPointF(); - poly << m2p.toMapCoordinatesF( sz.width(), 0 ).toQPointF(); - poly << m2p.toMapCoordinatesF( sz.width(), sz.height() ).toQPointF(); - poly << m2p.toMapCoordinatesF( 0, sz.height() ).toQPointF(); - - return poly; + return mapSettings.visiblePolygon(); } bool clipByRect( QLineF& line, const QPolygonF& rect ) diff --git a/src/core/qgsmapsettings.cpp b/src/core/qgsmapsettings.cpp index 011b2818c3e..0d97a42f937 100644 --- a/src/core/qgsmapsettings.cpp +++ b/src/core/qgsmapsettings.cpp @@ -311,6 +311,21 @@ QgsRectangle QgsMapSettings::visibleExtent() const return mVisibleExtent; } +QPolygonF QgsMapSettings::visiblePolygon() const +{ + QPolygonF poly; + + const QSize& sz = outputSize(); + const QgsMapToPixel& m2p = mapToPixel(); + + poly << m2p.toMapCoordinatesF( 0, 0 ).toQPointF(); + poly << m2p.toMapCoordinatesF( sz.width(), 0 ).toQPointF(); + poly << m2p.toMapCoordinatesF( sz.width(), sz.height() ).toQPointF(); + poly << m2p.toMapCoordinatesF( 0, sz.height() ).toQPointF(); + + return poly; +} + double QgsMapSettings::mapUnitsPerPixel() const { return mMapUnitsPerPixel; diff --git a/src/core/qgsmapsettings.h b/src/core/qgsmapsettings.h index abda40ddb97..3873ed88e28 100644 --- a/src/core/qgsmapsettings.h +++ b/src/core/qgsmapsettings.h @@ -156,6 +156,9 @@ class CORE_EXPORT QgsMapSettings bool hasValidSettings() const; //! Return the actual extent derived from requested extent that takes takes output image size into account QgsRectangle visibleExtent() const; + //! Return the visible area as a polygon (may be rotated) + //! @note added in 2.8 + QPolygonF visiblePolygon() const; //! Return the distance in geographical coordinates that equals to one pixel in the map double mapUnitsPerPixel() const; //! Return the calculated scale of the map diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt index 6efc518dec2..c558d996cca 100644 --- a/tests/src/core/CMakeLists.txt +++ b/tests/src/core/CMakeLists.txt @@ -140,6 +140,7 @@ ADD_QGIS_TEST(invertedpolygontest testqgsinvertedpolygonrenderer.cpp ) ADD_QGIS_TEST(colorschemeregistry testqgscolorschemeregistry.cpp) ADD_QGIS_TEST(colorscheme testqgscolorscheme.cpp) ADD_QGIS_TEST(maptopixeltest testqgsmaptopixel.cpp) +ADD_QGIS_TEST(mapsettingstest testqgsmapsettings.cpp) ADD_QGIS_TEST(networkcontentfetcher testqgsnetworkcontentfetcher.cpp ) ADD_QGIS_TEST(legendrenderertest testqgslegendrenderer.cpp ) ADD_QGIS_TEST(vectorlayerjoinbuffer testqgsvectorlayerjoinbuffer.cpp ) diff --git a/tests/src/core/testqgsmapsettings.cpp b/tests/src/core/testqgsmapsettings.cpp new file mode 100644 index 00000000000..50c40ba4d73 --- /dev/null +++ b/tests/src/core/testqgsmapsettings.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + testqgsmapsettings.cpp + -------------------------------------- + Date : Tue 6 Feb 2015 + Copyright : (C) 2014 by Sandro Santilli + Email : strk@keybit.net + *************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#include +#include +#include +#include +//header for class being tested +#include +#include +#include +#include +#include "qgslogger.h" + +class TestQgsMapSettings: public QObject +{ + Q_OBJECT + private slots: + void visibleExtent(); + void mapUnitsPerPixel(); + void visiblePolygon(); + private: + QString toString( const QPolygonF& p, int decimalPlaces = 2 ) const; +}; + +QString TestQgsMapSettings::toString( const QPolygonF& p, int dec ) const +{ + QString s; + const char *sep = ""; + double r = pow( 10, dec ); + for ( int i = 0; i < p.size(); ++i ) + { + s += QString( "%1%2 %3" ).arg( sep ) + .arg( int( p[i].x() * r ) / r ) + .arg( int( p[i].y() * r ) / r ); + sep = ","; + } + + return s; +} + +void TestQgsMapSettings::visibleExtent() +{ + QgsMapSettings ms; + + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + ms.setOutputSize( QSize( 100, 50 ) ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-50,0 : 150,100" ) ); + + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + ms.setOutputSize( QSize( 100, 100 ) ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "0,0 : 100,100" ) ); + + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + ms.setOutputSize( QSize( 50, 100 ) ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "0,-50 : 100,150" ) ); + + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + ms.setOutputSize( QSize( 50, 100 ) ); + ms.setRotation( 90 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-50,0 : 150,100" ) ); + ms.setRotation( -90 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-50,0 : 150,100" ) ); + + ms.setExtent( QgsRectangle( 0, 0, 100, 50 ) ); + ms.setOutputSize( QSize( 50, 100 ) ); + ms.setRotation( 0 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "0,-75 : 100,125" ) ); + ms.setRotation( 90 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-50,-25 : 150,75" ) ); + ms.setRotation( -90 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-50,-25 : 150,75" ) ); + ms.setRotation( 45 ); + QCOMPARE( ms.visibleExtent().toString( 0 ), QString( "-56,-81 : 156,131" ) ); +} + +void TestQgsMapSettings::mapUnitsPerPixel() +{ + QgsMapSettings ms; + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + + ms.setOutputSize( QSize( 100, 50 ) ); + QCOMPARE( ms.mapUnitsPerPixel(), 2.0 ); + + ms.setOutputSize( QSize( 100, 100 ) ); + QCOMPARE( ms.mapUnitsPerPixel(), 1.0 ); + + ms.setOutputSize( QSize( 50, 100 ) ); + QCOMPARE( ms.mapUnitsPerPixel(), 2.0 ); + + ms.setOutputSize( QSize( 5000, 1000 ) ); + QCOMPARE( ms.mapUnitsPerPixel(), 0.1 ); + + ms.setOutputSize( QSize( 1000, 500 ) ); + QCOMPARE( ms.mapUnitsPerPixel(), 0.2 ); +} + +void TestQgsMapSettings::visiblePolygon() +{ + QgsMapSettings ms; + + ms.setExtent( QgsRectangle( 0, 0, 100, 100 ) ); + ms.setOutputSize( QSize( 100, 50 ) ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "-50 100,150 100,150 0,-50 0" ) ); + + ms.setExtent( QgsRectangle( 0, -50, 100, 0 ) ); + ms.setOutputSize( QSize( 100, 50 ) ); + ms.setRotation( 90 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "25 -75,25 25,75 25,75 -75" ) ); + ms.setRotation( -90 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "75 25,75 -75,25 -75,25 25" ) ); + ms.setRotation( 30 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "-5.8 -28.34,80.8 21.65,105.8 -21.65,19.19 -71.65" ) ); + ms.setRotation( -30 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "19.19 21.65,105.8 -28.34,80.8 -71.65,-5.8 -21.65" ) ); + ms.setRotation( 45 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "-3.03 -42.67,67.67 28.03,103.03 -7.32,32.32 -78.03" ) ); + ms.setRotation( -45 ); + QCOMPARE( toString( ms.visiblePolygon() ), + QString( "32.32 28.03,103.03 -42.67,67.67 -78.03,-3.03 -7.32" ) ); +} + +QTEST_MAIN( TestQgsMapSettings ) +#include "testqgsmapsettings.moc"