Skip to content

Commit

Permalink
Add QgsMapCanvas::setZoomResolutions
Browse files Browse the repository at this point in the history
  • Loading branch information
manisandro authored and nyalldawson committed Jan 17, 2020
1 parent c658159 commit 8410ea7
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 4 deletions.
19 changes: 19 additions & 0 deletions python/gui/auto_generated/qgsmapcanvas.sip.in
Expand Up @@ -841,6 +841,25 @@ Zoom out with fixed factor
Zoom to the extent of the selected features of provided (vector) layer.

:param layer: optionally specify different than current layer
%End

void setZoomResolutions( const QList<double> &resolutions );
%Docstring
Set a list of resolutions (map units per pixel) to which to "snap to" when zooming the map

:param resolutions: A list of resolutions

.. versionadded:: 3.12
%End

const QList<double> &zoomResolutions() const;
%Docstring

:return: List of resolutions to which to "snap to" when zooming the map

.. seealso:: :py:func:`setZoomResolutions`

.. versionadded:: 3.12
%End

signals:
Expand Down
55 changes: 51 additions & 4 deletions src/gui/qgsmapcanvas.cpp
Expand Up @@ -1639,7 +1639,7 @@ void QgsMapCanvas::wheelEvent( QWheelEvent *e )
return;
}

double zoomFactor = mWheelZoomFactor;
double zoomFactor = e->angleDelta().y() > 0 ? 1. / zoomInFactor() : zoomOutFactor();

// "Normal" mouse have an angle delta of 120, precision mouses provide data faster, in smaller steps
zoomFactor = 1.0 + ( zoomFactor - 1.0 ) / 120.0 * std::fabs( e->angleDelta().y() );
Expand Down Expand Up @@ -1670,13 +1670,13 @@ void QgsMapCanvas::setWheelFactor( double factor )
void QgsMapCanvas::zoomIn()
{
// magnification is alreday handled in zoomByFactor
zoomByFactor( 1 / mWheelZoomFactor );
zoomByFactor( zoomInFactor() );
}

void QgsMapCanvas::zoomOut()
{
// magnification is alreday handled in zoomByFactor
zoomByFactor( mWheelZoomFactor );
zoomByFactor( zoomOutFactor() );
}

void QgsMapCanvas::zoomScale( double newScale )
Expand All @@ -1686,7 +1686,7 @@ void QgsMapCanvas::zoomScale( double newScale )

void QgsMapCanvas::zoomWithCenter( int x, int y, bool zoomIn )
{
double scaleFactor = ( zoomIn ? 1 / mWheelZoomFactor : mWheelZoomFactor );
double scaleFactor = ( zoomIn ? zoomInFactor() : zoomOutFactor() );

if ( mScaleLocked )
{
Expand Down Expand Up @@ -2522,3 +2522,50 @@ bool QgsMapCanvas::panOperationInProgress()

return false;
}

int QgsMapCanvas::nextZoomLevel( const QList<double> &resolutions, bool zoomIn ) const
{
int resolutionLevel = -1;
double currentResolution = mapUnitsPerPixel();

for ( int i = 0, n = resolutions.size(); i < n; ++i )
{
if ( qgsDoubleNear( resolutions[i], currentResolution, 0.0001 ) )
{
resolutionLevel = zoomIn ? ( i - 1 ) : ( i + 1 );
break;
}
else if ( currentResolution <= resolutions[i] )
{
resolutionLevel = zoomIn ? ( i - 1 ) : i;
break;
}
}
return ( resolutionLevel < 0 || resolutionLevel >= resolutions.size() ) ? -1 : resolutionLevel;
}

double QgsMapCanvas::zoomInFactor() const
{
if ( !mZoomResolutions.isEmpty() )
{
int zoomLevel = nextZoomLevel( mZoomResolutions, true );
if ( zoomLevel != -1 )
{
return mZoomResolutions.at( zoomLevel ) / mapUnitsPerPixel();
}
}
return 1 / mWheelZoomFactor;
}

double QgsMapCanvas::zoomOutFactor() const
{
if ( !mZoomResolutions.isEmpty() )
{
int zoomLevel = nextZoomLevel( mZoomResolutions, false );
if ( zoomLevel != -1 )
{
return mZoomResolutions.at( zoomLevel ) / mapUnitsPerPixel();
}
}
return mWheelZoomFactor;
}
19 changes: 19 additions & 0 deletions src/gui/qgsmapcanvas.h
Expand Up @@ -751,6 +751,20 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
*/
void zoomToSelected( QgsVectorLayer *layer = nullptr );

/**
* Set a list of resolutions (map units per pixel) to which to "snap to" when zooming the map
* \param resolutions A list of resolutions
* \since QGIS 3.12
*/
void setZoomResolutions( const QList<double> &resolutions ) { mZoomResolutions = resolutions; }

/**
* \returns List of resolutions to which to "snap to" when zooming the map
* \see setZoomResolutions()
* \since QGIS 3.12
*/
const QList<double> &zoomResolutions() const { return mZoomResolutions; }

private slots:
//! called when current maptool is destroyed
void mapToolDestroyed();
Expand Down Expand Up @@ -1055,6 +1069,7 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
QVector<QPointer<QgsCustomDropHandler >> mDropHandlers;

QgsDistanceArea mDa;
QList<double> mZoomResolutions;

/**
* Returns the last cursor position on the canvas in geographical coordinates
Expand Down Expand Up @@ -1102,6 +1117,10 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
*/
bool panOperationInProgress();

int nextZoomLevel( const QList<double> &resolutions, bool zoomIn = true ) const;
double zoomInFactor() const;
double zoomOutFactor() const;

friend class TestQgsMapCanvas;

}; // class QgsMapCanvas
Expand Down
22 changes: 22 additions & 0 deletions tests/src/gui/testqgsmapcanvas.cpp
Expand Up @@ -61,6 +61,7 @@ class TestQgsMapCanvas : public QObject
void testZoomByWheel();
void testShiftZoom();
void testDragDrop();
void testZoomResolutions();

private:
QgsMapCanvas *mCanvas = nullptr;
Expand Down Expand Up @@ -514,5 +515,26 @@ void TestQgsMapCanvas::testDragDrop()
QVERIFY( dropEvent->isAccepted() );
}

void TestQgsMapCanvas::testZoomResolutions()
{
mCanvas->setExtent( QgsRectangle( 0, 0, 10, 10 ) );
double resolution = mCanvas->mapSettings().mapUnitsPerPixel();

double nextResolution = qCeil( resolution ) + 1;
QList<double> resolutions = QList<double>() << nextResolution << ( 2.5 * nextResolution ) << ( 3.6 * nextResolution ) << ( 4.7 * nextResolution );
mCanvas->setZoomResolutions( resolutions );

mCanvas->zoomOut();
QGSCOMPARENEAR( mCanvas->mapSettings().mapUnitsPerPixel(), resolutions[0], 0.0001 );

mCanvas->zoomOut();
QGSCOMPARENEAR( mCanvas->mapSettings().mapUnitsPerPixel(), resolutions[1], 0.0001 );

mCanvas->zoomIn();
QGSCOMPARENEAR( mCanvas->mapSettings().mapUnitsPerPixel(), resolutions[0], 0.0001 );

QCOMPARE( mCanvas->zoomResolutions(), resolutions );
}

QGSTEST_MAIN( TestQgsMapCanvas )
#include "testqgsmapcanvas.moc"

0 comments on commit 8410ea7

Please sign in to comment.