From 6b629e199e92fac0ffc2dd54307bb588012b21c3 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 17 Oct 2017 17:13:54 +1000 Subject: [PATCH] Port snappedAngle from composer --- python/core/layout/qgslayoututils.sip | 7 ++++ src/core/layout/qgslayoututils.cpp | 40 +++++++++++++++++++++ src/core/layout/qgslayoututils.h | 6 ++++ tests/src/core/testqgslayoututils.cpp | 50 +++++++++++++++++++++++++++ 4 files changed, 103 insertions(+) diff --git a/python/core/layout/qgslayoututils.sip b/python/core/layout/qgslayoututils.sip index 205c81caff47..37940211b9fe 100644 --- a/python/core/layout/qgslayoututils.sip +++ b/python/core/layout/qgslayoututils.sip @@ -29,6 +29,13 @@ class QgsLayoutUtils :rtype: float %End + static double snappedAngle( double angle ); +%Docstring + Snaps an ``angle`` (in degrees) to its closest 45 degree angle. + :return: angle snapped to 0, 45/90/135/180/225/270 or 315 degrees + :rtype: float +%End + static QgsRenderContext createRenderContextForMap( QgsLayoutItemMap *map, QPainter *painter, double dpi = -1 ); %Docstring Creates a render context suitable for the specified layout ``map`` and ``painter`` destination. diff --git a/src/core/layout/qgslayoututils.cpp b/src/core/layout/qgslayoututils.cpp index 004f78a50e74..f854cdde0ef3 100644 --- a/src/core/layout/qgslayoututils.cpp +++ b/src/core/layout/qgslayoututils.cpp @@ -36,6 +36,46 @@ double QgsLayoutUtils::normalizedAngle( const double angle, const bool allowNega return clippedAngle; } +double QgsLayoutUtils::snappedAngle( double angle ) +{ + //normalize angle to 0-360 degrees + double clippedAngle = normalizedAngle( angle ); + + //snap angle to 45 degree + if ( clippedAngle >= 22.5 && clippedAngle < 67.5 ) + { + return 45.0; + } + else if ( clippedAngle >= 67.5 && clippedAngle < 112.5 ) + { + return 90.0; + } + else if ( clippedAngle >= 112.5 && clippedAngle < 157.5 ) + { + return 135.0; + } + else if ( clippedAngle >= 157.5 && clippedAngle < 202.5 ) + { + return 180.0; + } + else if ( clippedAngle >= 202.5 && clippedAngle < 247.5 ) + { + return 225.0; + } + else if ( clippedAngle >= 247.5 && clippedAngle < 292.5 ) + { + return 270.0; + } + else if ( clippedAngle >= 292.5 && clippedAngle < 337.5 ) + { + return 315.0; + } + else + { + return 0.0; + } +} + QgsRenderContext QgsLayoutUtils::createRenderContextForMap( QgsLayoutItemMap *map, QPainter *painter, double dpi ) { if ( !map ) diff --git a/src/core/layout/qgslayoututils.h b/src/core/layout/qgslayoututils.h index 25c98a5e4d7f..38698f408a18 100644 --- a/src/core/layout/qgslayoututils.h +++ b/src/core/layout/qgslayoututils.h @@ -41,6 +41,12 @@ class CORE_EXPORT QgsLayoutUtils */ static double normalizedAngle( const double angle, const bool allowNegative = false ); + /** + * Snaps an \a angle (in degrees) to its closest 45 degree angle. + * \returns angle snapped to 0, 45/90/135/180/225/270 or 315 degrees + */ + static double snappedAngle( double angle ); + /** * Creates a render context suitable for the specified layout \a map and \a painter destination. * This method returns a new QgsRenderContext which matches the scale and settings of the diff --git a/tests/src/core/testqgslayoututils.cpp b/tests/src/core/testqgslayoututils.cpp index ad3f483ac6cf..d420d12ac89d 100644 --- a/tests/src/core/testqgslayoututils.cpp +++ b/tests/src/core/testqgslayoututils.cpp @@ -31,6 +31,7 @@ class TestQgsLayoutUtils: public QObject void init();// will be called before each testfunction is executed. void cleanup();// will be called after every testfunction. void normalizedAngle(); //test normalised angle function + void snappedAngle(); void createRenderContextFromLayout(); void createRenderContextFromMap(); void relativePosition(); @@ -117,6 +118,55 @@ void TestQgsLayoutUtils::normalizedAngle() } } +void TestQgsLayoutUtils::snappedAngle() +{ + QList< QPair< double, double > > testVals; + testVals << qMakePair( 0.0, 0.0 ); + testVals << qMakePair( 10.0, 0.0 ); + testVals << qMakePair( 20.0, 0.0 ); + testVals << qMakePair( 30.0, 45.0 ); + testVals << qMakePair( 40.0, 45.0 ); + testVals << qMakePair( 50.0, 45.0 ); + testVals << qMakePair( 60.0, 45.0 ); + testVals << qMakePair( 70.0, 90.0 ); + testVals << qMakePair( 80.0, 90.0 ); + testVals << qMakePair( 90.0, 90.0 ); + testVals << qMakePair( 100.0, 90.0 ); + testVals << qMakePair( 110.0, 90.0 ); + testVals << qMakePair( 120.0, 135.0 ); + testVals << qMakePair( 130.0, 135.0 ); + testVals << qMakePair( 140.0, 135.0 ); + testVals << qMakePair( 150.0, 135.0 ); + testVals << qMakePair( 160.0, 180.0 ); + testVals << qMakePair( 170.0, 180.0 ); + testVals << qMakePair( 180.0, 180.0 ); + testVals << qMakePair( 190.0, 180.0 ); + testVals << qMakePair( 200.0, 180.0 ); + testVals << qMakePair( 210.0, 225.0 ); + testVals << qMakePair( 220.0, 225.0 ); + testVals << qMakePair( 230.0, 225.0 ); + testVals << qMakePair( 240.0, 225.0 ); + testVals << qMakePair( 250.0, 270.0 ); + testVals << qMakePair( 260.0, 270.0 ); + testVals << qMakePair( 270.0, 270.0 ); + testVals << qMakePair( 280.0, 270.0 ); + testVals << qMakePair( 290.0, 270.0 ); + testVals << qMakePair( 300.0, 315.0 ); + testVals << qMakePair( 310.0, 315.0 ); + testVals << qMakePair( 320.0, 315.0 ); + testVals << qMakePair( 330.0, 315.0 ); + testVals << qMakePair( 340.0, 0.0 ); + testVals << qMakePair( 350.0, 0.0 ); + testVals << qMakePair( 360.0, 0.0 ); + + //test snapped angle helper function + QList< QPair< double, double > >::const_iterator it = testVals.constBegin(); + for ( ; it != testVals.constEnd(); ++it ) + { + QGSCOMPARENEAR( QgsLayoutUtils::snappedAngle( ( *it ).first ), ( *it ).second, 4 * DBL_EPSILON ); + } +} + void TestQgsLayoutUtils::createRenderContextFromLayout() {