QGIS API Documentation 4.3.0-Master (16eddb2670e)
Loading...
Searching...
No Matches
qgssnaptogridcanvasitem.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgssnaptogridcanvasitem.cpp
3 ----------------------
4 begin : August 2018
5 copyright : (C) Matthias Kuhn
6 email : matthias@opengis.ch
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include "qgsmapcanvas.h"
19#include "qgspainting.h"
20#include "qgsrendercontext.h"
21
22#include "moc_qgssnaptogridcanvasitem.cpp"
23
25 : QgsMapCanvasItem( mapCanvas )
26{
27 updateMapCanvasCrs();
28 connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsSnapToGridCanvasItem::updateZoomFactor );
29 connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsSnapToGridCanvasItem::updateMapCanvasCrs );
30}
31
32void QgsSnapToGridCanvasItem::paint( QPainter *painter )
33{
34 if ( !mEnabled || !mAvailableByZoomFactor )
35 return;
36
37 const QgsScopedQPainterState painterState( painter );
38 const QgsRectangle mapRect = mMapCanvas->extent();
39
40 painter->setRenderHints( QPainter::Antialiasing );
41 painter->setCompositionMode( QPainter::CompositionMode_Difference );
42
43 const double scaleFactor = painter->fontMetrics().xHeight() * .2;
44
45 mGridPen.setWidth( scaleFactor );
46 mCurrentPointPen.setWidth( scaleFactor * 3 );
47 const int gridMarkerLength = scaleFactor * 3;
48
49 try
50 {
51 QgsCoordinateTransform extentTransform = mTransform;
52 extentTransform.setBallparkTransformsAreAppropriate( true );
53 const QgsRectangle layerExtent = extentTransform.transformBoundingBox( mapRect, Qgis::TransformDirection::Reverse );
54 const QgsPointXY layerPt = mTransform.transform( mPoint, Qgis::TransformDirection::Reverse );
55
56 const double gridXMin = std::ceil( layerExtent.xMinimum() / mPrecision ) * mPrecision;
57 const double gridXMax = std::ceil( layerExtent.xMaximum() / mPrecision ) * mPrecision;
58 const double gridYMin = std::ceil( layerExtent.yMinimum() / mPrecision ) * mPrecision;
59 const double gridYMax = std::ceil( layerExtent.yMaximum() / mPrecision ) * mPrecision;
60
61 for ( double x = gridXMin; x < gridXMax; x += mPrecision )
62 {
63 for ( double y = gridYMin; y < gridYMax; y += mPrecision )
64 {
65 const QgsPointXY pt = mTransform.transform( x, y );
66 const QPointF canvasPt = toCanvasCoordinates( pt );
67
68 if ( qgsDoubleNear( layerPt.x(), x, mPrecision / 2 ) && qgsDoubleNear( layerPt.y(), y, mPrecision / 2 ) )
69 {
70 painter->setPen( mCurrentPointPen );
71 }
72 else
73 {
74 painter->setPen( mGridPen );
75 }
76 painter->drawLine( canvasPt.x() - gridMarkerLength, canvasPt.y(), canvasPt.x() + gridMarkerLength, canvasPt.y() );
77 painter->drawLine( canvasPt.x(), canvasPt.y() - gridMarkerLength, canvasPt.x(), canvasPt.y() + gridMarkerLength );
78 }
79 }
80 }
81 catch ( QgsCsException &e )
82 {
83 Q_UNUSED( e )
84 mAvailableByZoomFactor = false;
85 }
86}
87
89{
90 return mPoint;
91}
92
94{
95 mPoint = point;
96 update();
97}
98
100{
101 return mPrecision;
102}
103
105{
106 mPrecision = precision;
107 updateZoomFactor();
108}
109
111{
112 return mTransform.sourceCrs();
113}
114
116{
117 mTransform.setSourceCrs( crs );
118 updateZoomFactor();
119}
120
122{
123 return mEnabled;
124}
125
127{
128 mEnabled = enabled;
129 update();
130}
131
132void QgsSnapToGridCanvasItem::updateMapCanvasCrs()
133{
136 update();
137}
138
139
140void QgsSnapToGridCanvasItem::updateZoomFactor()
141{
142 if ( !isVisible() )
143 return;
144
145 try
146 {
147 const int threshold = 5;
148
149 const QgsRectangle extent = mMapCanvas->extent();
150 if ( extent != rect() )
151 setRect( extent );
152
153 const QgsPointXY centerPoint = mMapCanvas->extent().center();
154 const QPointF canvasCenter = toCanvasCoordinates( centerPoint );
155
156 const QgsPointXY pt1 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() - threshold ), static_cast<int>( canvasCenter.y() - threshold ) );
157 const QgsPointXY pt2 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() + threshold ), static_cast<int>( canvasCenter.y() + threshold ) );
158
159 const QgsPointXY layerPt1 = mTransform.transform( pt1, Qgis::TransformDirection::Reverse );
160 const QgsPointXY layerPt2 = mTransform.transform( pt2, Qgis::TransformDirection::Reverse );
161
162 const double dist = layerPt1.distance( layerPt2 );
163
164 if ( dist < mPrecision )
165 mAvailableByZoomFactor = true;
166 else
167 mAvailableByZoomFactor = false;
168 }
169 catch ( QgsCsException & )
170 {
171 // transform errors?
172 // you've probably got worse problems than the grid with your digitizing operations in the current projection.
173 mAvailableByZoomFactor = false;
174 }
175}
@ Reverse
Reverse/inverse transform (from destination to source).
Definition qgis.h:2884
Represents a coordinate reference system (CRS).
Handles coordinate transforms between two coordinate systems.
void setContext(const QgsCoordinateTransformContext &context)
Sets the context in which the coordinate transform should be calculated.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination coordinate reference system.
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const
Transforms a rectangle from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
QgsRectangle rect() const
returns canvas item rectangle in map units
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
QgsMapCanvas * mMapCanvas
pointer to map canvas
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
QgsMapCanvasItem(QgsMapCanvas *mapCanvas)
protected constructor: cannot be constructed directly
Map canvas is a class for displaying all GIS data types on a canvas.
void extentsChanged()
Emitted when the extents of the map change.
void destinationCrsChanged()
Emitted when map CRS has changed.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Represents a 2D point.
Definition qgspointxy.h:62
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
Definition qgspointxy.h:209
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
A rectangle specified with double values.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
Scoped object for saving and restoring a QPainter object's state.
bool enabled() const
Enable this item.
double precision() const
The resolution of the grid in map units.
void setCrs(const QgsCoordinateReferenceSystem &crs)
The CRS in which the grid should be calculated.
void setPoint(const QgsPointXY &point)
A point that will be highlighted on the map canvas.
void setEnabled(bool enabled)
Enable this item.
QgsSnapToGridCanvasItem(QgsMapCanvas *mapCanvas)
Will automatically be added to the mapCanvas.
void paint(QPainter *painter) override
function to be implemented by derived classes
QgsCoordinateReferenceSystem crs() const
The CRS in which the grid should be calculated.
void setPrecision(double precision)
The resolution of the grid in map units.
QgsPointXY point() const
A point that will be highlighted on the map canvas.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:7743