Add QgsSnapToGridCanvasItem

This commit is contained in:
Matthias Kuhn 2018-08-25 15:49:00 +02:00
parent fff743bed8
commit 1e81e03a18
5 changed files with 334 additions and 0 deletions

View File

@ -0,0 +1,91 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgssnaptogridcanvasitem.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsSnapToGridCanvasItem : QObject, QgsMapCanvasItem
{
%Docstring
Shows a grid on the map canvas given a spatial resolution.
.. versionadded:: 3.4
%End
%TypeHeaderCode
#include "qgssnaptogridcanvasitem.h"
%End
public:
QgsSnapToGridCanvasItem( QgsMapCanvas *mapCanvas );
%Docstring
Will automatically be added to the ``mapCanvas``.
%End
virtual void paint( QPainter *painter );
QgsPointXY point() const;
%Docstring
A point that will be highlighted on the map canvas.
The point needs to be in map coordinates. The closest point on the
grid will be highlighted.
%End
void setPoint( const QgsPointXY &point );
%Docstring
A point that will be highlighted on the map canvas.
The point needs to be in map coordinates. The closest point on the
grid will be highlighted.
%End
double precision() const;
%Docstring
The resolution of the grid in map units.
If a crs has been specified it will be in CRS units.
%End
void setPrecision( double precision );
%Docstring
The resolution of the grid in map units.
If a crs has been specified it will be in CRS units.
%End
QgsCoordinateReferenceSystem crs() const;
%Docstring
The CRS in which the grid should be calculated.
By default will be an invalid QgsCoordinateReferenceSystem and
as such equal to the CRS of the map canvas.
%End
void setCrs( const QgsCoordinateReferenceSystem &crs );
%Docstring
The CRS in which the grid should be calculated.
By default will be an invalid QgsCoordinateReferenceSystem and
as such equal to the CRS of the map canvas.
%End
bool enabled() const;
%Docstring
Enable this item. It will be hidden if disabled.
%End
void setEnabled( bool enabled );
%Docstring
Enable this item. It will be hidden if disabled.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgssnaptogridcanvasitem.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -192,6 +192,7 @@
%Include auto_generated/qgssearchquerybuilder.sip
%Include auto_generated/qgsshortcutsmanager.sip
%Include auto_generated/qgsslider.sip
%Include auto_generated/qgssnaptogridcanvasitem.sip
%Include auto_generated/qgsstatusbar.sip
%Include auto_generated/qgssublayersdialog.sip
%Include auto_generated/qgssubstitutionlistwidget.sip

View File

@ -355,6 +355,7 @@ SET(QGIS_GUI_SRCS
qgsshortcutsmanager.cpp
qgsslider.cpp
qgssnapindicator.cpp
qgssnaptogridcanvasitem.cpp
qgssublayersdialog.cpp
qgssubstitutionlistwidget.cpp
qgssqlcomposerdialog.cpp
@ -524,6 +525,7 @@ SET(QGIS_GUI_MOC_HDRS
qgssearchquerybuilder.h
qgsshortcutsmanager.h
qgsslider.h
qgssnaptogridcanvasitem.h
qgssqlcomposerdialog.h
qgsstatusbar.h
qgssublayersdialog.h

View File

@ -0,0 +1,142 @@
#include "qgssnaptogridcanvasitem.h"
#include "qgsmapcanvas.h"
QgsSnapToGridCanvasItem::QgsSnapToGridCanvasItem( QgsMapCanvas *mapCanvas )
: QgsMapCanvasItem( mapCanvas )
, mGridPen( QPen( QColor( 127, 127, 127, 150 ), 1 ) )
, mCurrentPointPen( QPen( QColor( 200, 200, 200, 150 ), 3 ) )
{
updateMapCanvasCrs();
connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsSnapToGridCanvasItem::updateZoomFactor );
connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsSnapToGridCanvasItem::updateMapCanvasCrs );
}
void QgsSnapToGridCanvasItem::paint( QPainter *painter )
{
painter->save();
QgsRectangle mapRect = mMapCanvas->extent();
if ( rect() != mapRect )
setRect( mapRect );
painter->setRenderHints( QPainter::Antialiasing );
painter->setCompositionMode( QPainter::CompositionMode_Difference );
if ( mEnabled && mAvailableByZoomFactor )
{
const QgsRectangle layerExtent = mTransform.transformBoundingBox( mapRect, QgsCoordinateTransform::ReverseTransform );
const QgsPointXY layerPt = mTransform.transform( mPoint, QgsCoordinateTransform::ReverseTransform );
const double gridXMin = std::ceil( layerExtent.xMinimum() / mPrecision ) * mPrecision;
const double gridXMax = std::ceil( layerExtent.xMaximum() / mPrecision ) * mPrecision;
const double gridYMin = std::ceil( layerExtent.yMinimum() / mPrecision ) * mPrecision;
const double gridYMax = std::ceil( layerExtent.yMaximum() / mPrecision ) * mPrecision;
for ( int x = gridXMin ; x < gridXMax; x += mPrecision )
{
for ( int y = gridYMin ; y < gridYMax; y += mPrecision )
{
const QgsPointXY pt = mTransform.transform( x, y );
const QPointF canvasPt = toCanvasCoordinates( pt );
if ( qgsDoubleNear( layerPt.x(), x, mPrecision / 3 ) && qgsDoubleNear( layerPt.y(), y, mPrecision / 3 ) )
{
painter->setPen( mCurrentPointPen );
}
else
{
painter->setPen( mGridPen );
}
painter->drawLine( canvasPt.x() - 3, canvasPt.y(), canvasPt.x() + 3, canvasPt.y() );
painter->drawLine( canvasPt.x(), canvasPt.y() - 3, canvasPt.x(), canvasPt.y() + 3 );
}
}
}
painter->restore();
}
QgsPointXY QgsSnapToGridCanvasItem::point() const
{
return mPoint;
}
void QgsSnapToGridCanvasItem::setPoint( const QgsPointXY &point )
{
mPoint = point;
update();
}
double QgsSnapToGridCanvasItem::precision() const
{
return mPrecision;
}
void QgsSnapToGridCanvasItem::setPrecision( double precision )
{
mPrecision = precision;
updateZoomFactor();
}
QgsCoordinateReferenceSystem QgsSnapToGridCanvasItem::crs() const
{
return mTransform.sourceCrs();
}
void QgsSnapToGridCanvasItem::setCrs( const QgsCoordinateReferenceSystem &crs )
{
mTransform.setSourceCrs( crs );
updateZoomFactor();
}
bool QgsSnapToGridCanvasItem::enabled() const
{
return mEnabled;
}
void QgsSnapToGridCanvasItem::setEnabled( bool enabled )
{
mEnabled = enabled;
update();
}
void QgsSnapToGridCanvasItem::updateMapCanvasCrs()
{
mTransform.setContext( mMapCanvas->mapSettings().transformContext() );
mTransform.setDestinationCrs( mMapCanvas->mapSettings().destinationCrs() );
update();
}
void QgsSnapToGridCanvasItem::updateZoomFactor()
{
if ( !isVisible() )
return;
try
{
const int threshold = 5;
const QgsPointXY centerPoint = mMapCanvas->extent().center();
const QPointF canvasCenter = toCanvasCoordinates( centerPoint );
const QgsPointXY pt1 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( canvasCenter.x() - threshold, canvasCenter.y() - threshold );
const QgsPointXY pt2 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( canvasCenter.x() + threshold, canvasCenter.y() + threshold );
const QgsPointXY layerPt1 = mTransform.transform( pt1, QgsCoordinateTransform::ReverseTransform );
const QgsPointXY layerPt2 = mTransform.transform( pt2, QgsCoordinateTransform::ReverseTransform );
const double dist = layerPt1.distance( layerPt2 );
if ( dist < mPrecision )
mAvailableByZoomFactor = true;
else
mAvailableByZoomFactor = false;
}
catch ( QgsCsException &e )
{
// transform errors?
// you've probably got worse problems than the grid with your digitizing operations in the current projection.
mAvailableByZoomFactor = false;
}
}

View File

@ -0,0 +1,98 @@
#ifndef QGSSNAPTOGRIDCANVASITEM_H
#define QGSSNAPTOGRIDCANVASITEM_H
#include <QObject>
#include <QPen>
#include "qgscoordinatereferencesystem.h"
#include "qgsmapcanvasitem.h"
#include "qgscoordinatetransform.h"
/**
* \ingroup gui
*
* Shows a grid on the map canvas given a spatial resolution.
*
* \since QGIS 3.4
*/
class GUI_EXPORT QgsSnapToGridCanvasItem : public QObject, public QgsMapCanvasItem
{
Q_OBJECT
public:
/**
* Will automatically be added to the \a mapCanvas.
*/
QgsSnapToGridCanvasItem( QgsMapCanvas *mapCanvas );
void paint( QPainter *painter ) override;
/**
* A point that will be highlighted on the map canvas.
* The point needs to be in map coordinates. The closest point on the
* grid will be highlighted.
*/
QgsPointXY point() const;
/**
* A point that will be highlighted on the map canvas.
* The point needs to be in map coordinates. The closest point on the
* grid will be highlighted.
*/
void setPoint( const QgsPointXY &point );
/**
* The resolution of the grid in map units.
* If a crs has been specified it will be in CRS units.
*/
double precision() const;
/**
* The resolution of the grid in map units.
* If a crs has been specified it will be in CRS units.
*/
void setPrecision( double precision );
/**
* The CRS in which the grid should be calculated.
* By default will be an invalid QgsCoordinateReferenceSystem and
* as such equal to the CRS of the map canvas.
*/
QgsCoordinateReferenceSystem crs() const;
/**
* The CRS in which the grid should be calculated.
* By default will be an invalid QgsCoordinateReferenceSystem and
* as such equal to the CRS of the map canvas.
*/
void setCrs( const QgsCoordinateReferenceSystem &crs );
/**
* Enable this item. It will be hidden if disabled.
*/
bool enabled() const;
/**
* Enable this item. It will be hidden if disabled.
*/
void setEnabled( bool enabled );
private slots:
void updateMapCanvasCrs();
void updateZoomFactor();
private:
QPen mGridPen;
QPen mCurrentPointPen;
bool mEnabled = true;
bool mAvailableByZoomFactor = false;
double mPrecision = 0.0;
QgsCoordinateTransform mTransform;
QgsPointXY mPoint;
};
#endif // QGSSNAPTOGRIDCANVASITEM_H