QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 : [email protected]
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 #include "qgsmapcanvas.h"
18 #include "qgsrendercontext.h"
19 
21  : QgsMapCanvasItem( mapCanvas )
22 {
23  updateMapCanvasCrs();
24  connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsSnapToGridCanvasItem::updateZoomFactor );
25  connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsSnapToGridCanvasItem::updateMapCanvasCrs );
26 }
27 
28 void QgsSnapToGridCanvasItem::paint( QPainter *painter )
29 {
30  if ( !mEnabled || !mAvailableByZoomFactor )
31  return;
32 
33  const QgsScopedQPainterState painterState( painter );
34  const QgsRectangle mapRect = mMapCanvas->extent();
35 
36  painter->setRenderHints( QPainter::Antialiasing );
37  painter->setCompositionMode( QPainter::CompositionMode_Difference );
38 
39  const double scaleFactor = painter->fontMetrics().xHeight() * .2;
40 
41  mGridPen.setWidth( scaleFactor );
42  mCurrentPointPen.setWidth( scaleFactor * 3 );
43  const int gridMarkerLength = scaleFactor * 3;
44 
45  try
46  {
47  QgsCoordinateTransform extentTransform = mTransform;
48  extentTransform.setBallparkTransformsAreAppropriate( true );
49  const QgsRectangle layerExtent = extentTransform.transformBoundingBox( mapRect, Qgis::TransformDirection::Reverse );
50  const QgsPointXY layerPt = mTransform.transform( mPoint, Qgis::TransformDirection::Reverse );
51 
52  const double gridXMin = std::ceil( layerExtent.xMinimum() / mPrecision ) * mPrecision;
53  const double gridXMax = std::ceil( layerExtent.xMaximum() / mPrecision ) * mPrecision;
54  const double gridYMin = std::ceil( layerExtent.yMinimum() / mPrecision ) * mPrecision;
55  const double gridYMax = std::ceil( layerExtent.yMaximum() / mPrecision ) * mPrecision;
56 
57  for ( double x = gridXMin ; x < gridXMax; x += mPrecision )
58  {
59  for ( double y = gridYMin ; y < gridYMax; y += mPrecision )
60  {
61  const QgsPointXY pt = mTransform.transform( x, y );
62  const QPointF canvasPt = toCanvasCoordinates( pt );
63 
64  if ( qgsDoubleNear( layerPt.x(), x, mPrecision / 2 ) && qgsDoubleNear( layerPt.y(), y, mPrecision / 2 ) )
65  {
66  painter->setPen( mCurrentPointPen );
67  }
68  else
69  {
70  painter->setPen( mGridPen );
71  }
72  painter->drawLine( canvasPt.x() - gridMarkerLength, canvasPt.y(), canvasPt.x() + gridMarkerLength, canvasPt.y() );
73  painter->drawLine( canvasPt.x(), canvasPt.y() - gridMarkerLength, canvasPt.x(), canvasPt.y() + gridMarkerLength );
74 
75  }
76  }
77  }
78  catch ( QgsCsException &e )
79  {
80  Q_UNUSED( e )
81  mAvailableByZoomFactor = false;
82  }
83 }
84 
86 {
87  return mPoint;
88 }
89 
91 {
92  mPoint = point;
93  update();
94 }
95 
97 {
98  return mPrecision;
99 }
100 
102 {
103  mPrecision = precision;
104  updateZoomFactor();
105 }
106 
108 {
109  return mTransform.sourceCrs();
110 }
111 
113 {
114  mTransform.setSourceCrs( crs );
115  updateZoomFactor();
116 }
117 
119 {
120  return mEnabled;
121 }
122 
124 {
125  mEnabled = enabled;
126  update();
127 }
128 
129 void QgsSnapToGridCanvasItem::updateMapCanvasCrs()
130 {
133  update();
134 }
135 
136 
137 
138 void QgsSnapToGridCanvasItem::updateZoomFactor()
139 {
140  if ( !isVisible() )
141  return;
142 
143  try
144  {
145  const int threshold = 5;
146 
147  const QgsRectangle extent = mMapCanvas->extent();
148  if ( extent != rect() )
149  setRect( extent );
150 
151  const QgsPointXY centerPoint = mMapCanvas->extent().center();
152  const QPointF canvasCenter = toCanvasCoordinates( centerPoint );
153 
154  const QgsPointXY pt1 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() - threshold ),
155  static_cast<int>( canvasCenter.y() - threshold ) );
156  const QgsPointXY pt2 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() + threshold ),
157  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 }
QgsPointXY::distance
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspointxy.h:211
QgsPointXY::y
double y
Definition: qgspointxy.h:63
QgsMapCanvas::extent
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Definition: qgsmapcanvas.cpp:1331
QgsSnapToGridCanvasItem::QgsSnapToGridCanvasItem
QgsSnapToGridCanvasItem(QgsMapCanvas *mapCanvas)
Will automatically be added to the mapCanvas.
Definition: qgssnaptogridcanvasitem.cpp:20
QgsMapCanvas::destinationCrsChanged
void destinationCrsChanged()
Emitted when map CRS has changed.
qgsmapcanvas.h
QgsMapCanvasItem::mMapCanvas
QgsMapCanvas * mMapCanvas
pointer to map canvas
Definition: qgsmapcanvasitem.h:82
QgsMapCanvas::mapSettings
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
Definition: qgsmapcanvas.cpp:437
QgsRectangle::center
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsCoordinateTransform::setContext
void setContext(const QgsCoordinateTransformContext &context)
Sets the context in which the coordinate transform should be calculated.
Definition: qgscoordinatetransform.cpp:230
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:89
QgsCoordinateTransform::setSourceCrs
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source coordinate reference system.
Definition: qgscoordinatetransform.cpp:183
QgsMapToPixel::toMapCoordinates
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
Definition: qgsmaptopixel.h:173
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsSnapToGridCanvasItem::setPrecision
void setPrecision(double precision)
The resolution of the grid in map units.
Definition: qgssnaptogridcanvasitem.cpp:101
QgsMapCanvasItem::setRect
void setRect(const QgsRectangle &r, bool resetRotation=true)
sets canvas item rectangle in map units
Definition: qgsmapcanvasitem.cpp:74
QgsSnapToGridCanvasItem::crs
QgsCoordinateReferenceSystem crs() const
The CRS in which the grid should be calculated.
Definition: qgssnaptogridcanvasitem.cpp:107
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
QgsCoordinateTransform::sourceCrs
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source coordinate reference system, which the transform will transform coordinates from.
Definition: qgscoordinatetransform.cpp:262
precision
int precision
Definition: qgswfsgetfeature.cpp:103
qgssnaptogridcanvasitem.h
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsMapCanvasItem
An abstract class for items that can be placed on the map canvas.
Definition: qgsmapcanvasitem.h:33
QgsMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgsmapsettings.cpp:463
QgsSnapToGridCanvasItem::enabled
bool enabled() const
Enable this item.
Definition: qgssnaptogridcanvasitem.cpp:118
QgsMapCanvasItem::toCanvasCoordinates
QPointF toCanvasCoordinates(const QgsPointXY &point) const
transformation from map coordinates to screen coordinates
Definition: qgsmapcanvasitem.cpp:61
QgsCoordinateTransform::setDestinationCrs
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination coordinate reference system.
Definition: qgscoordinatetransform.cpp:206
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
QgsSnapToGridCanvasItem::setEnabled
void setEnabled(bool enabled)
Enable this item.
Definition: qgssnaptogridcanvasitem.cpp:123
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsSnapToGridCanvasItem::point
QgsPointXY point() const
A point that will be highlighted on the map canvas.
Definition: qgssnaptogridcanvasitem.cpp:85
QgsMapCanvas::extentsChanged
void extentsChanged()
Emitted when the extents of the map change.
qgsrendercontext.h
QgsSnapToGridCanvasItem::paint
void paint(QPainter *painter) override
function to be implemented by derived classes
Definition: qgssnaptogridcanvasitem.cpp:28
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:58
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
Definition: qgsmapsettings.cpp:358
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
QgsMapCanvasItem::rect
QgsRectangle rect() const
returns canvas item rectangle in map units
Definition: qgsmapcanvasitem.cpp:68
QgsPointXY::x
double x
Definition: qgspointxy.h:62
QgsSnapToGridCanvasItem::precision
double precision() const
The resolution of the grid in map units.
Definition: qgssnaptogridcanvasitem.cpp:96
QgsSnapToGridCanvasItem::setPoint
void setPoint(const QgsPointXY &point)
A point that will be highlighted on the map canvas.
Definition: qgssnaptogridcanvasitem.cpp:90
QgsCoordinateTransform::transform
QgsPointXY transform(const QgsPointXY &point, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:272
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:527
QgsSnapToGridCanvasItem::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
The CRS in which the grid should be calculated.
Definition: qgssnaptogridcanvasitem.cpp:112