QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 
20  : QgsMapCanvasItem( mapCanvas )
21 {
22  updateMapCanvasCrs();
23  connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsSnapToGridCanvasItem::updateZoomFactor );
24  connect( mMapCanvas, &QgsMapCanvas::destinationCrsChanged, this, &QgsSnapToGridCanvasItem::updateMapCanvasCrs );
25 }
26 
27 void QgsSnapToGridCanvasItem::paint( QPainter *painter )
28 {
29  if ( !mEnabled || !mAvailableByZoomFactor )
30  return;
31 
32  QgsScopedQPainterState painterState( painter );
33  QgsRectangle mapRect = mMapCanvas->extent();
34 
35  painter->setRenderHints( QPainter::Antialiasing );
36  painter->setCompositionMode( QPainter::CompositionMode_Difference );
37 
38  double scaleFactor = painter->fontMetrics().xHeight() * .2;
39 
40  mGridPen.setWidth( scaleFactor );
41  mCurrentPointPen.setWidth( scaleFactor * 3 );
42  const int gridMarkerLength = scaleFactor * 3;
43 
44  try
45  {
46  const QgsRectangle layerExtent = mTransform.transformBoundingBox( mapRect, QgsCoordinateTransform::ReverseTransform );
47  const QgsPointXY layerPt = mTransform.transform( mPoint, QgsCoordinateTransform::ReverseTransform );
48 
49  const double gridXMin = std::ceil( layerExtent.xMinimum() / mPrecision ) * mPrecision;
50  const double gridXMax = std::ceil( layerExtent.xMaximum() / mPrecision ) * mPrecision;
51  const double gridYMin = std::ceil( layerExtent.yMinimum() / mPrecision ) * mPrecision;
52  const double gridYMax = std::ceil( layerExtent.yMaximum() / mPrecision ) * mPrecision;
53 
54  for ( double x = gridXMin ; x < gridXMax; x += mPrecision )
55  {
56  for ( double y = gridYMin ; y < gridYMax; y += mPrecision )
57  {
58  const QgsPointXY pt = mTransform.transform( x, y );
59  const QPointF canvasPt = toCanvasCoordinates( pt );
60 
61  if ( qgsDoubleNear( layerPt.x(), x, mPrecision / 2 ) && qgsDoubleNear( layerPt.y(), y, mPrecision / 2 ) )
62  {
63  painter->setPen( mCurrentPointPen );
64  }
65  else
66  {
67  painter->setPen( mGridPen );
68  }
69  painter->drawLine( canvasPt.x() - gridMarkerLength, canvasPt.y(), canvasPt.x() + gridMarkerLength, canvasPt.y() );
70  painter->drawLine( canvasPt.x(), canvasPt.y() - gridMarkerLength, canvasPt.x(), canvasPt.y() + gridMarkerLength );
71 
72  }
73  }
74  }
75  catch ( QgsCsException &e )
76  {
77  Q_UNUSED( e )
78  mAvailableByZoomFactor = false;
79  }
80 }
81 
83 {
84  return mPoint;
85 }
86 
88 {
89  mPoint = point;
90  update();
91 }
92 
94 {
95  return mPrecision;
96 }
97 
99 {
100  mPrecision = precision;
101  updateZoomFactor();
102 }
103 
105 {
106  return mTransform.sourceCrs();
107 }
108 
110 {
111  mTransform.setSourceCrs( crs );
112  updateZoomFactor();
113 }
114 
116 {
117  return mEnabled;
118 }
119 
121 {
122  mEnabled = enabled;
123  update();
124 }
125 
126 void QgsSnapToGridCanvasItem::updateMapCanvasCrs()
127 {
130  update();
131 }
132 
133 
134 
135 void QgsSnapToGridCanvasItem::updateZoomFactor()
136 {
137  if ( !isVisible() )
138  return;
139 
140  try
141  {
142  const int threshold = 5;
143 
144  const QgsRectangle extent = mMapCanvas->extent();
145  if ( extent != rect() )
146  setRect( extent );
147 
148  const QgsPointXY centerPoint = mMapCanvas->extent().center();
149  const QPointF canvasCenter = toCanvasCoordinates( centerPoint );
150 
151  const QgsPointXY pt1 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() - threshold ),
152  static_cast<int>( canvasCenter.y() - threshold ) );
153  const QgsPointXY pt2 = mMapCanvas->mapSettings().mapToPixel().toMapCoordinates( static_cast<int>( canvasCenter.x() + threshold ),
154  static_cast<int>( canvasCenter.y() + threshold ) );
155 
156  const QgsPointXY layerPt1 = mTransform.transform( pt1, QgsCoordinateTransform::ReverseTransform );
157  const QgsPointXY layerPt2 = mTransform.transform( pt2, QgsCoordinateTransform::ReverseTransform );
158 
159  const double dist = layerPt1.distance( layerPt2 );
160 
161  if ( dist < mPrecision )
162  mAvailableByZoomFactor = true;
163  else
164  mAvailableByZoomFactor = false;
165  }
166  catch ( QgsCsException & )
167  {
168  // transform errors?
169  // you've probably got worse problems than the grid with your digitizing operations in the current projection.
170  mAvailableByZoomFactor = false;
171  }
172 }
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:196
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsMapCanvas::extent
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
Definition: qgsmapcanvas.cpp:1056
QgsSnapToGridCanvasItem::QgsSnapToGridCanvasItem
QgsSnapToGridCanvasItem(QgsMapCanvas *mapCanvas)
Will automatically be added to the mapCanvas.
Definition: qgssnaptogridcanvasitem.cpp:19
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:391
QgsRectangle::center
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:230
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
QgsCoordinateTransform::setContext
void setContext(const QgsCoordinateTransformContext &context)
Sets the context in which the coordinate transform should be calculated.
Definition: qgscoordinatetransform.cpp:200
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsMapCanvas
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:85
QgsCoordinateTransform::setSourceCrs
void setSourceCrs(const QgsCoordinateReferenceSystem &crs)
Sets the source coordinate reference system.
Definition: qgscoordinatetransform.cpp:159
QgsMapToPixel::toMapCoordinates
QgsPointXY toMapCoordinates(int x, int y) const
Transform device coordinates to map (world) coordinates.
Definition: qgsmaptopixel.cpp:108
QgsCoordinateTransform::transform
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:239
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsCoordinateTransform::ReverseTransform
@ ReverseTransform
Transform from destination to source CRS.
Definition: qgscoordinatetransform.h:61
QgsSnapToGridCanvasItem::setPrecision
void setPrecision(double precision)
The resolution of the grid in map units.
Definition: qgssnaptogridcanvasitem.cpp:98
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, TransformDirection direction=ForwardTransform, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:511
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:104
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
QgsCoordinateTransform::sourceCrs
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source coordinate reference system, which the transform will transform coordinates from.
Definition: qgscoordinatetransform.cpp:229
precision
int precision
Definition: qgswfsgetfeature.cpp:49
qgssnaptogridcanvasitem.h
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
QgsMapCanvasItem
An abstract class for items that can be placed on the map canvas.
Definition: qgsmapcanvasitem.h:34
QgsMapSettings::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Definition: qgsmapsettings.cpp:401
QgsSnapToGridCanvasItem::enabled
bool enabled() const
Enable this item.
Definition: qgssnaptogridcanvasitem.cpp:115
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:179
QgsSnapToGridCanvasItem::setEnabled
void setEnabled(bool enabled)
Enable this item.
Definition: qgssnaptogridcanvasitem.cpp:120
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:315
QgsSnapToGridCanvasItem::point
QgsPointXY point() const
A point that will be highlighted on the map canvas.
Definition: qgssnaptogridcanvasitem.cpp:82
QgsMapCanvas::extentsChanged
void extentsChanged()
Emitted when the extents of the map change.
QgsSnapToGridCanvasItem::paint
void paint(QPainter *painter) override
function to be implemented by derived classes
Definition: qgssnaptogridcanvasitem.cpp:27
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1120
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:206
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsMapSettings::destinationCrs
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Definition: qgsmapsettings.cpp:318
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsMapCanvasItem::rect
QgsRectangle rect() const
returns canvas item rectangle in map units
Definition: qgsmapcanvasitem.cpp:68
QgsSnapToGridCanvasItem::precision
double precision() const
The resolution of the grid in map units.
Definition: qgssnaptogridcanvasitem.cpp:93
QgsSnapToGridCanvasItem::setPoint
void setPoint(const QgsPointXY &point)
A point that will be highlighted on the map canvas.
Definition: qgssnaptogridcanvasitem.cpp:87
QgsMapSettings::mapToPixel
const QgsMapToPixel & mapToPixel() const
Definition: qgsmapsettings.h:436
QgsSnapToGridCanvasItem::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
The CRS in which the grid should be calculated.
Definition: qgssnaptogridcanvasitem.cpp:109