QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsmaptoolidentify.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaptoolidentify.cpp - map tool for identifying features
3  ---------------------
4  begin : January 2006
5  copyright : (C) 2006 by Martin Dobias
6  email : wonder.sk at gmail dot com
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 
16 #include "qgsapplication.h"
17 #include "qgsdistancearea.h"
18 #include "qgsfeature.h"
19 #include "qgsfeatureiterator.h"
20 #include "qgsfeaturestore.h"
21 #include "qgsfields.h"
22 #include "qgsgeometry.h"
23 #include "qgsgeometryengine.h"
24 #include "qgsidentifymenu.h"
25 #include "qgslogger.h"
26 #include "qgsmapcanvas.h"
27 #include "qgsmaptoolidentify.h"
28 #include "qgsmaptopixel.h"
29 #include "qgsmessageviewer.h"
30 #include "qgsmaplayer.h"
31 #include "qgsrasterdataprovider.h"
32 #include "qgsrasterlayer.h"
35 #include "qgsvectordataprovider.h"
36 #include "qgsvectorlayer.h"
37 #include "qgsproject.h"
38 #include "qgsrenderer.h"
39 #include "qgsgeometryutils.h"
40 #include "qgsgeometrycollection.h"
41 #include "qgscurve.h"
42 #include "qgscoordinateutils.h"
43 #include "qgsexception.h"
44 #include "qgssettings.h"
45 
46 #include <QMouseEvent>
47 #include <QCursor>
48 #include <QPixmap>
49 #include <QStatusBar>
50 #include <QVariant>
51 #include <QMenu>
52 
54  : QgsMapTool( canvas )
55  , mIdentifyMenu( new QgsIdentifyMenu( mCanvas ) )
56  , mLastMapUnitsPerPixel( -1.0 )
57  , mCoordinatePrecision( 6 )
58 {
59  setCursor( QgsApplication::getThemeCursor( QgsApplication::Cursor::Identify ) );
60 }
61 
63 {
64  delete mIdentifyMenu;
65 }
66 
68 {
69  Q_UNUSED( e );
70 }
71 
73 {
74  Q_UNUSED( e );
75 }
76 
78 {
79  Q_UNUSED( e );
80 }
81 
82 QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( int x, int y, const QList<QgsMapLayer *> &layerList, IdentifyMode mode )
83 {
84  return identify( x, y, mode, layerList, AllLayers );
85 }
86 
87 QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( int x, int y, IdentifyMode mode, LayerType layerType )
88 {
89  return identify( x, y, mode, QList<QgsMapLayer *>(), layerType );
90 }
91 
92 QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( int x, int y, IdentifyMode mode, const QList<QgsMapLayer *> &layerList, LayerType layerType )
93 {
94  return identify( QgsGeometry::fromPointXY( toMapCoordinates( QPoint( x, y ) ) ), mode, layerList, layerType );
95 }
96 
97 QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( const QgsGeometry &geometry, IdentifyMode mode, LayerType layerType )
98 {
99  return identify( geometry, mode, QList<QgsMapLayer *>(), layerType );
100 }
101 
102 QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( const QgsGeometry &geometry, IdentifyMode mode, const QList<QgsMapLayer *> &layerList, LayerType layerType )
103 {
104  QList<IdentifyResult> results;
105 
106  mLastGeometry = geometry;
107  mLastExtent = mCanvas->extent();
108  mLastMapUnitsPerPixel = mCanvas->mapUnitsPerPixel();
109 
110  mCoordinatePrecision = QgsCoordinateUtils::calculateCoordinatePrecision( mLastMapUnitsPerPixel, mCanvas->mapSettings().destinationCrs() );
111 
112  if ( mode == DefaultQgsSetting )
113  {
114  QgsSettings settings;
115  mode = settings.enumValue( QStringLiteral( "Map/identifyMode" ), ActiveLayer );
116  }
117 
118  if ( mode == LayerSelection )
119  {
120  QPoint canvasPt = toCanvasCoordinates( geometry.asPoint() );
121  int x = canvasPt.x(), y = canvasPt.y();
122  QList<IdentifyResult> results = identify( x, y, TopDownAll, layerList, layerType );
123  QPoint globalPos = mCanvas->mapToGlobal( QPoint( x + 5, y + 5 ) );
124  return mIdentifyMenu->exec( results, globalPos );
125  }
126  else if ( mode == ActiveLayer && layerList.isEmpty() )
127  {
128  QgsMapLayer *layer = mCanvas->currentLayer();
129 
130  if ( !layer )
131  {
132  emit identifyMessage( tr( "No active layer. To identify features, you must choose an active layer." ) );
133  return results;
134  }
135 
136  QApplication::setOverrideCursor( Qt::WaitCursor );
137 
138  identifyLayer( &results, layer, mLastGeometry, mLastExtent, mLastMapUnitsPerPixel, layerType );
139  }
140  else
141  {
142  QApplication::setOverrideCursor( Qt::WaitCursor );
143 
144  int layerCount;
145  if ( layerList.isEmpty() )
146  layerCount = mCanvas->layerCount();
147  else
148  layerCount = layerList.count();
149 
150 
151  for ( int i = 0; i < layerCount; i++ )
152  {
153 
154  QgsMapLayer *layer = nullptr;
155  if ( layerList.isEmpty() )
156  layer = mCanvas->layer( i );
157  else
158  layer = layerList.value( i );
159 
160  emit identifyProgress( i, mCanvas->layerCount() );
161  emit identifyMessage( tr( "Identifying on %1…" ).arg( layer->name() ) );
162 
163  if ( !layer->flags().testFlag( QgsMapLayer::Identifiable ) )
164  continue;
165 
166  if ( identifyLayer( &results, layer, mLastGeometry, mLastExtent, mLastMapUnitsPerPixel, layerType ) )
167  {
168  if ( mode == TopDownStopAtFirst )
169  break;
170  }
171  }
172 
174  emit identifyMessage( tr( "Identifying done." ) );
175  }
176 
177  QApplication::restoreOverrideCursor();
178 
179  return results;
180 }
181 
182 void QgsMapToolIdentify::setCanvasPropertiesOverrides( double searchRadiusMapUnits )
183 {
184  mOverrideCanvasSearchRadius = searchRadiusMapUnits;
185 }
186 
188 {
189  mOverrideCanvasSearchRadius = -1;
190 }
191 
193 {
195 }
196 
198 {
200 }
201 
202 bool QgsMapToolIdentify::identifyLayer( QList<IdentifyResult> *results, QgsMapLayer *layer, const QgsPointXY &point, const QgsRectangle &viewExtent, double mapUnitsPerPixel, QgsMapToolIdentify::LayerType layerType )
203 {
204  return identifyLayer( results, layer, QgsGeometry::fromPointXY( point ), viewExtent, mapUnitsPerPixel, layerType );
205 }
206 
207 bool QgsMapToolIdentify::identifyLayer( QList<IdentifyResult> *results, QgsMapLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel, QgsMapToolIdentify::LayerType layerType )
208 {
209  if ( layer->type() == QgsMapLayer::RasterLayer && layerType.testFlag( RasterLayer ) )
210  {
211  return identifyRasterLayer( results, qobject_cast<QgsRasterLayer *>( layer ), geometry, viewExtent, mapUnitsPerPixel );
212  }
213  else if ( layer->type() == QgsMapLayer::VectorLayer && layerType.testFlag( VectorLayer ) )
214  {
215  return identifyVectorLayer( results, qobject_cast<QgsVectorLayer *>( layer ), geometry );
216  }
217  else
218  {
219  return false;
220  }
221 }
222 
223 bool QgsMapToolIdentify::identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsPointXY &point )
224 {
225  return identifyVectorLayer( results, layer, QgsGeometry::fromPointXY( point ) );
226 }
227 
228 QMap<QString, QString> QgsMapToolIdentify::derivedAttributesForPoint( const QgsPoint &point )
229 {
230  QMap< QString, QString > derivedAttributes;
231  derivedAttributes.insert( tr( "(clicked coordinate X)" ), formatXCoordinate( point ) );
232  derivedAttributes.insert( tr( "(clicked coordinate Y)" ), formatYCoordinate( point ) );
233  if ( point.is3D() )
234  derivedAttributes.insert( tr( "(clicked coordinate Z)" ), QString::number( point.z(), 'f' ) );
235  return derivedAttributes;
236 }
237 
238 bool QgsMapToolIdentify::identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsGeometry &geometry )
239 {
240  if ( !layer || !layer->isSpatial() )
241  return false;
242 
243  if ( !layer->isInScaleRange( mCanvas->mapSettings().scale() ) )
244  {
245  QgsDebugMsg( QStringLiteral( "Out of scale limits" ) );
246  return false;
247  }
248 
249  QApplication::setOverrideCursor( Qt::WaitCursor );
250 
251  QMap< QString, QString > commonDerivedAttributes;
252 
253  QgsGeometry selectionGeom = geometry;
254  bool isPointOrRectangle;
255  QgsPointXY point;
256  bool isSingleClick = selectionGeom.type() == QgsWkbTypes::PointGeometry;
257  if ( isSingleClick )
258  {
259  isPointOrRectangle = true;
260  point = selectionGeom.asPoint();
261 
262  commonDerivedAttributes = derivedAttributesForPoint( QgsPoint( point ) );
263  }
264  else
265  {
266  // we have a polygon - maybe it is a rectangle - in such case we can avoid costly insterestion tests later
267  isPointOrRectangle = QgsGeometry::fromRect( selectionGeom.boundingBox() ).isGeosEqual( selectionGeom );
268  }
269 
270  int featureCount = 0;
271 
272  QgsFeatureList featureList;
273  std::unique_ptr<QgsGeometryEngine> selectionGeomPrepared;
274 
275  // toLayerCoordinates will throw an exception for an 'invalid' point.
276  // For example, if you project a world map onto a globe using EPSG 2163
277  // and then click somewhere off the globe, an exception will be thrown.
278  try
279  {
280  QgsRectangle r;
281  if ( isSingleClick )
282  {
283  double sr = mOverrideCanvasSearchRadius < 0 ? searchRadiusMU( mCanvas ) : mOverrideCanvasSearchRadius;
284  r = toLayerCoordinates( layer, QgsRectangle( point.x() - sr, point.y() - sr, point.x() + sr, point.y() + sr ) );
285  }
286  else
287  {
288  r = toLayerCoordinates( layer, selectionGeom.boundingBox() );
289 
290  if ( !isPointOrRectangle )
291  {
293  if ( ct.isValid() )
294  selectionGeom.transform( ct );
295 
296  // use prepared geometry for faster intersection test
297  selectionGeomPrepared.reset( QgsGeometry::createGeometryEngine( selectionGeom.constGet() ) );
298  }
299  }
300 
301  QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFilterRect( r ).setFlags( QgsFeatureRequest::ExactIntersect ) );
302  QgsFeature f;
303  while ( fit.nextFeature( f ) )
304  {
305  if ( !selectionGeomPrepared || selectionGeomPrepared->intersects( f.geometry().constGet() ) )
306  featureList << QgsFeature( f );
307  }
308  }
309  catch ( QgsCsException &cse )
310  {
311  Q_UNUSED( cse );
312  // catch exception for 'invalid' point and proceed with no features found
313  QgsDebugMsg( QStringLiteral( "Caught CRS exception %1" ).arg( cse.what() ) );
314  }
315 
316  bool filter = false;
317 
320  std::unique_ptr< QgsFeatureRenderer > renderer( layer->renderer() ? layer->renderer()->clone() : nullptr );
321  if ( renderer )
322  {
323  // setup scale for scale dependent visibility (rule based)
324  renderer->startRender( context, layer->fields() );
325  filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
326  }
327 
328  for ( const QgsFeature &feature : qgis::as_const( featureList ) )
329  {
330  QMap< QString, QString > derivedAttributes = commonDerivedAttributes;
331 
332  QgsFeatureId fid = feature.id();
333  context.expressionContext().setFeature( feature );
334 
335  if ( filter && !renderer->willRenderFeature( feature, context ) )
336  continue;
337 
338  featureCount++;
339 
340  if ( isSingleClick )
341  derivedAttributes.unite( featureDerivedAttributes( feature, layer, toLayerCoordinates( layer, point ) ) );
342 
343  derivedAttributes.insert( tr( "Feature ID" ), fid < 0 ? tr( "new feature" ) : FID_TO_STRING( fid ) );
344 
345  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), feature, derivedAttributes ) );
346  }
347 
348  if ( renderer )
349  {
350  renderer->stopRender( context );
351  }
352 
353  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );
354 
355  QApplication::restoreOverrideCursor();
356  return featureCount > 0;
357 }
358 
359 void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString > &derivedAttributes )
360 {
361  QString str = QLocale().toString( vId.vertex + 1 );
362  derivedAttributes.insert( tr( "Closest vertex number" ), str );
363 
364  QgsPoint closestPoint = geometry.vertexAt( vId );
365 
366  QgsPointXY closestPointMapCoords = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( closestPoint.x(), closestPoint.y() ) );
367  derivedAttributes.insert( tr( "Closest vertex X" ), formatXCoordinate( closestPointMapCoords ) );
368  derivedAttributes.insert( tr( "Closest vertex Y" ), formatYCoordinate( closestPointMapCoords ) );
369 
370  if ( closestPoint.is3D() )
371  {
372  str = QLocale().toString( closestPoint.z(), 'g', 10 );
373  derivedAttributes.insert( tr( "Closest vertex Z" ), str );
374  }
375  if ( closestPoint.isMeasure() )
376  {
377  str = QLocale().toString( closestPoint.m(), 'g', 10 );
378  derivedAttributes.insert( tr( "Closest vertex M" ), str );
379  }
380 
381  if ( vId.type == QgsVertexId::CurveVertex )
382  {
383  double radius, centerX, centerY;
384  QgsVertexId vIdBefore = vId;
385  --vIdBefore.vertex;
386  QgsVertexId vIdAfter = vId;
387  ++vIdAfter.vertex;
388  QgsGeometryUtils::circleCenterRadius( geometry.vertexAt( vIdBefore ), geometry.vertexAt( vId ),
389  geometry.vertexAt( vIdAfter ), radius, centerX, centerY );
390  derivedAttributes.insert( QStringLiteral( "Closest vertex radius" ), QLocale().toString( radius ) );
391  }
392 }
393 
394 void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geometry, const QgsPointXY &layerPoint, QMap<QString, QString> &derivedAttributes )
395 {
396  QgsPoint closestPoint = QgsGeometryUtils::closestPoint( geometry, QgsPoint( layerPoint ) );
397 
398  derivedAttributes.insert( tr( "Closest X" ), formatXCoordinate( closestPoint ) );
399  derivedAttributes.insert( tr( "Closest Y" ), formatYCoordinate( closestPoint ) );
400 
401  if ( closestPoint.is3D() )
402  {
403  const QString str = QLocale().toString( closestPoint.z(), 'g', 10 );
404  derivedAttributes.insert( tr( "Interpolated Z" ), str );
405  }
406  if ( closestPoint.isMeasure() )
407  {
408  const QString str = QLocale().toString( closestPoint.m(), 'g', 10 );
409  derivedAttributes.insert( tr( "Interpolated M" ), str );
410  }
411 }
412 
413 QString QgsMapToolIdentify::formatCoordinate( const QgsPointXY &canvasPoint ) const
414 {
415  return QgsCoordinateUtils::formatCoordinateForProject( QgsProject::instance(), canvasPoint, mCanvas->mapSettings().destinationCrs(),
416  mCoordinatePrecision );
417 }
418 
419 QString QgsMapToolIdentify::formatXCoordinate( const QgsPointXY &canvasPoint ) const
420 {
421  QString coordinate = formatCoordinate( canvasPoint );
422  return coordinate.split( ',' ).at( 0 );
423 }
424 
425 QString QgsMapToolIdentify::formatYCoordinate( const QgsPointXY &canvasPoint ) const
426 {
427  QString coordinate = formatCoordinate( canvasPoint );
428  return coordinate.split( ',' ).at( 1 );
429 }
430 
431 QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( const QgsFeature &feature, QgsMapLayer *layer, const QgsPointXY &layerPoint )
432 {
433  // Calculate derived attributes and insert:
434  // measure distance or area depending on geometry type
435  QMap< QString, QString > derivedAttributes;
436 
437  // init distance/area calculator
438  QString ellipsoid = QgsProject::instance()->ellipsoid();
439  QgsDistanceArea calc;
440  calc.setEllipsoid( ellipsoid );
441  calc.setSourceCrs( layer->crs(), QgsProject::instance()->transformContext() );
442 
445 
446  QgsVertexId vId;
447  QgsPoint closestPoint;
448  if ( feature.hasGeometry() )
449  {
450  geometryType = feature.geometry().type();
451  wkbType = feature.geometry().wkbType();
452  //find closest vertex to clicked point
453  closestPoint = QgsGeometryUtils::closestVertex( *feature.geometry().constGet(), QgsPoint( layerPoint ), vId );
454  }
455 
456  if ( QgsWkbTypes::isMultiType( wkbType ) )
457  {
458  QString str = QLocale().toString( static_cast<const QgsGeometryCollection *>( feature.geometry().constGet() )->numGeometries() );
459  derivedAttributes.insert( tr( "Parts" ), str );
460  str = QLocale().toString( vId.part + 1 );
461  derivedAttributes.insert( tr( "Part number" ), str );
462  }
463 
464  QgsUnitTypes::DistanceUnit cartesianDistanceUnits = QgsUnitTypes::unitType( layer->crs().mapUnits() ) == QgsUnitTypes::unitType( displayDistanceUnits() )
465  ? displayDistanceUnits() : layer->crs().mapUnits();
466  QgsUnitTypes::AreaUnit cartesianAreaUnits = QgsUnitTypes::unitType( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ) ) == QgsUnitTypes::unitType( displayAreaUnits() )
467  ? displayAreaUnits() : QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() );
468 
469  if ( geometryType == QgsWkbTypes::LineGeometry )
470  {
471  double dist = calc.measureLength( feature.geometry() );
472  dist = calc.convertLengthMeasurement( dist, displayDistanceUnits() );
473  QString str;
474  if ( ellipsoid != GEO_NONE )
475  {
476  str = formatDistance( dist );
477  derivedAttributes.insert( tr( "Length (Ellipsoidal, %1)" ).arg( ellipsoid ), str );
478  }
479  str = formatDistance( feature.geometry().constGet()->length()
480  * QgsUnitTypes::fromUnitToUnitFactor( layer->crs().mapUnits(), cartesianDistanceUnits ), cartesianDistanceUnits );
481  derivedAttributes.insert( tr( "Length (Cartesian)" ), str );
482 
483  const QgsAbstractGeometry *geom = feature.geometry().constGet();
484  if ( geom )
485  {
486  str = QLocale().toString( geom->nCoordinates() );
487  derivedAttributes.insert( tr( "Vertices" ), str );
488  //add details of closest vertex to identify point
489  closestVertexAttributes( *geom, vId, layer, derivedAttributes );
490  closestPointAttributes( *geom, layerPoint, derivedAttributes );
491 
492  if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
493  {
494  // Add the start and end points in as derived attributes
495  QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) );
496  str = formatXCoordinate( pnt );
497  derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
498  str = formatYCoordinate( pnt );
499  derivedAttributes.insert( tr( "firstY" ), str );
500  pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->endPoint().x(), curve->endPoint().y() ) );
501  str = formatXCoordinate( pnt );
502  derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
503  str = formatYCoordinate( pnt );
504  derivedAttributes.insert( tr( "lastY" ), str );
505  }
506  }
507  }
508  else if ( geometryType == QgsWkbTypes::PolygonGeometry )
509  {
510  double area = calc.measureArea( feature.geometry() );
511  area = calc.convertAreaMeasurement( area, displayAreaUnits() );
512  QString str;
513  if ( ellipsoid != GEO_NONE )
514  {
515  str = formatArea( area );
516  derivedAttributes.insert( tr( "Area (Ellipsoidal, %1)" ).arg( ellipsoid ), str );
517  }
518  str = formatArea( feature.geometry().area()
519  * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ), cartesianAreaUnits ), cartesianAreaUnits );
520  derivedAttributes.insert( tr( "Area (Cartesian)" ), str );
521 
522  if ( ellipsoid != GEO_NONE )
523  {
524  double perimeter = calc.measurePerimeter( feature.geometry() );
525  perimeter = calc.convertLengthMeasurement( perimeter, displayDistanceUnits() );
526  str = formatDistance( perimeter );
527  derivedAttributes.insert( tr( "Perimeter (Ellipsoidal, %1)" ).arg( ellipsoid ), str );
528  }
529  str = formatDistance( feature.geometry().constGet()->perimeter()
530  * QgsUnitTypes::fromUnitToUnitFactor( layer->crs().mapUnits(), cartesianDistanceUnits ), cartesianDistanceUnits );
531  derivedAttributes.insert( tr( "Perimeter (Cartesian)" ), str );
532 
533  str = QLocale().toString( feature.geometry().constGet()->nCoordinates() );
534  derivedAttributes.insert( tr( "Vertices" ), str );
535 
536  //add details of closest vertex to identify point
537  closestVertexAttributes( *feature.geometry().constGet(), vId, layer, derivedAttributes );
538  closestPointAttributes( *feature.geometry().constGet(), layerPoint, derivedAttributes );
539  }
540  else if ( geometryType == QgsWkbTypes::PointGeometry )
541  {
542  if ( QgsWkbTypes::flatType( wkbType ) == QgsWkbTypes::Point )
543  {
544  // Include the x and y coordinates of the point as a derived attribute
545  QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature.geometry().asPoint() );
546  QString str = formatXCoordinate( pnt );
547  derivedAttributes.insert( tr( "X" ), str );
548  str = formatYCoordinate( pnt );
549  derivedAttributes.insert( tr( "Y" ), str );
550 
551  if ( QgsWkbTypes::hasZ( wkbType ) )
552  {
553  str = QLocale().toString( static_cast<const QgsPoint *>( feature.geometry().constGet() )->z(), 'g', 10 );
554  derivedAttributes.insert( tr( "Z" ), str );
555  }
556  if ( QgsWkbTypes::hasM( wkbType ) )
557  {
558  str = QLocale().toString( static_cast<const QgsPoint *>( feature.geometry().constGet() )->m(), 'g', 10 );
559  derivedAttributes.insert( tr( "M" ), str );
560  }
561  }
562  else
563  {
564  //multipart
565 
566  //add details of closest vertex to identify point
567  const QgsAbstractGeometry *geom = feature.geometry().constGet();
568  {
569  closestVertexAttributes( *geom, vId, layer, derivedAttributes );
570  }
571  }
572  }
573 
574  return derivedAttributes;
575 }
576 
577 bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel )
578 {
579  QgsPointXY point = geometry.asPoint(); // raster layers currently only support identification by point
580  return identifyRasterLayer( results, layer, point, viewExtent, mapUnitsPerPixel );
581 }
582 
583 bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, QgsPointXY point, const QgsRectangle &viewExtent, double mapUnitsPerPixel )
584 {
585  QgsDebugMsg( "point = " + point.toString() );
586  if ( !layer )
587  return false;
588 
589  QgsRasterDataProvider *dprovider = layer->dataProvider();
590  if ( !dprovider )
591  return false;
592 
593  int capabilities = dprovider->capabilities();
594  if ( !( capabilities & QgsRasterDataProvider::Identify ) )
595  return false;
596 
597  QgsPointXY pointInCanvasCrs = point;
598  try
599  {
600  point = toLayerCoordinates( layer, point );
601  }
602  catch ( QgsCsException &cse )
603  {
604  Q_UNUSED( cse );
605  QgsDebugMsg( QStringLiteral( "coordinate not reprojectable: %1" ).arg( cse.what() ) );
606  return false;
607  }
608  QgsDebugMsg( QStringLiteral( "point = %1 %2" ).arg( point.x() ).arg( point.y() ) );
609 
610  if ( !layer->extent().contains( point ) )
611  return false;
612 
613  QMap< QString, QString > attributes, derivedAttributes;
614 
615  QgsRaster::IdentifyFormat format = QgsRasterDataProvider::identifyFormatFromName( layer->customProperty( QStringLiteral( "identify/format" ) ).toString() );
616 
617  // check if the format is really supported otherwise use first supported format
618  if ( !( QgsRasterDataProvider::identifyFormatToCapability( format ) & capabilities ) )
619  {
621  else if ( capabilities & QgsRasterInterface::IdentifyValue ) format = QgsRaster::IdentifyFormatValue;
622  else if ( capabilities & QgsRasterInterface::IdentifyHtml ) format = QgsRaster::IdentifyFormatHtml;
623  else if ( capabilities & QgsRasterInterface::IdentifyText ) format = QgsRaster::IdentifyFormatText;
624  else return false;
625  }
626 
627  QgsRasterIdentifyResult identifyResult;
628  // We can only use current map canvas context (extent, width, height) if layer is not reprojected,
629  if ( dprovider->crs() != mCanvas->mapSettings().destinationCrs() )
630  {
631  // To get some reasonable response for point/line WMS vector layers we must
632  // use a context with approximately a resolution in layer CRS units
633  // corresponding to current map canvas resolution (for examplei UMN Mapserver
634  // in msWMSFeatureInfo() -> msQueryByRect() is using requested pixel
635  // + TOLERANCE (layer param) for feature selection)
636  //
637  QgsRectangle r;
638  r.setXMinimum( pointInCanvasCrs.x() - mapUnitsPerPixel / 2. );
639  r.setXMaximum( pointInCanvasCrs.x() + mapUnitsPerPixel / 2. );
640  r.setYMinimum( pointInCanvasCrs.y() - mapUnitsPerPixel / 2. );
641  r.setYMaximum( pointInCanvasCrs.y() + mapUnitsPerPixel / 2. );
642  r = toLayerCoordinates( layer, r ); // will be a bit larger
643  // Mapserver (6.0.3, for example) does not work with 1x1 pixel box
644  // but that is fixed (the rect is enlarged) in the WMS provider
645  identifyResult = dprovider->identify( point, format, r, 1, 1 );
646  }
647  else
648  {
649  // It would be nice to use the same extent and size which was used for drawing,
650  // so that WCS can use cache from last draw, unfortunately QgsRasterLayer::draw()
651  // is doing some tricks with extent and size to align raster to output which
652  // would be difficult to replicate here.
653  // Note: cutting the extent may result in slightly different x and y resolutions
654  // and thus shifted point calculated back in QGIS WMS (using average resolution)
655  //viewExtent = dprovider->extent().intersect( &viewExtent );
656 
657  // Width and height are calculated from not projected extent and we hope that
658  // are similar to source width and height used to reproject layer for drawing.
659  // TODO: may be very dangerous, because it may result in different resolutions
660  // in source CRS, and WMS server (QGIS server) calcs wrong coor using average resolution.
661  int width = static_cast< int >( std::round( viewExtent.width() / mapUnitsPerPixel ) );
662  int height = static_cast< int >( std::round( viewExtent.height() / mapUnitsPerPixel ) );
663 
664  QgsDebugMsg( QStringLiteral( "viewExtent.width = %1 viewExtent.height = %2" ).arg( viewExtent.width() ).arg( viewExtent.height() ) );
665  QgsDebugMsg( QStringLiteral( "width = %1 height = %2" ).arg( width ).arg( height ) );
666  QgsDebugMsg( QStringLiteral( "xRes = %1 yRes = %2 mapUnitsPerPixel = %3" ).arg( viewExtent.width() / width ).arg( viewExtent.height() / height ).arg( mapUnitsPerPixel ) );
667 
668  identifyResult = dprovider->identify( point, format, viewExtent, width, height );
669  }
670 
671  derivedAttributes.unite( derivedAttributesForPoint( QgsPoint( pointInCanvasCrs ) ) );
672 
673  if ( identifyResult.isValid() )
674  {
675  QMap<int, QVariant> values = identifyResult.results();
676  QgsGeometry geometry;
677  if ( format == QgsRaster::IdentifyFormatValue )
678  {
679  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
680  {
681  QString valueString;
682  if ( it.value().isNull() )
683  {
684  valueString = tr( "no data" );
685  }
686  else
687  {
688  QVariant value( it.value() );
689  // The cast is legit. Quoting QT doc :
690  // "Although this function is declared as returning QVariant::Type,
691  // the return value should be interpreted as QMetaType::Type"
692  if ( static_cast<QMetaType::Type>( value.type() ) == QMetaType::Float )
693  {
694  valueString = QgsRasterBlock::printValue( value.toFloat() );
695  }
696  else
697  {
698  valueString = QgsRasterBlock::printValue( value.toDouble() );
699  }
700  }
701  attributes.insert( dprovider->generateBandName( it.key() ), valueString );
702  }
703  QString label = layer->name();
704  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
705  }
706  else if ( format == QgsRaster::IdentifyFormatFeature )
707  {
708  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
709  {
710  QVariant value = it.value();
711  if ( value.type() == QVariant::Bool && !value.toBool() )
712  {
713  // sublayer not visible or not queryable
714  continue;
715  }
716 
717  if ( value.type() == QVariant::String )
718  {
719  // error
720  // TODO: better error reporting
721  QString label = layer->subLayers().value( it.key() );
722  attributes.clear();
723  attributes.insert( tr( "Error" ), value.toString() );
724 
725  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
726  continue;
727  }
728 
729  // list of feature stores for a single sublayer
730  const QgsFeatureStoreList featureStoreList = it.value().value<QgsFeatureStoreList>();
731 
732  for ( const QgsFeatureStore &featureStore : featureStoreList )
733  {
734  const QgsFeatureList storeFeatures = featureStore.features();
735  for ( const QgsFeature &feature : storeFeatures )
736  {
737  attributes.clear();
738  // WMS sublayer and feature type, a sublayer may contain multiple feature types.
739  // Sublayer name may be the same as layer name and feature type name
740  // may be the same as sublayer. We try to avoid duplicities in label.
741  QString sublayer = featureStore.params().value( QStringLiteral( "sublayer" ) ).toString();
742  QString featureType = featureStore.params().value( QStringLiteral( "featureType" ) ).toString();
743  // Strip UMN MapServer '_feature'
744  featureType.remove( QStringLiteral( "_feature" ) );
745  QStringList labels;
746  if ( sublayer.compare( layer->name(), Qt::CaseInsensitive ) != 0 )
747  {
748  labels << sublayer;
749  }
750  if ( featureType.compare( sublayer, Qt::CaseInsensitive ) != 0 || labels.isEmpty() )
751  {
752  labels << featureType;
753  }
754 
755  QMap< QString, QString > derAttributes = derivedAttributes;
756  derAttributes.unite( featureDerivedAttributes( feature, layer ) );
757 
758  IdentifyResult identifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( QStringLiteral( " / " ) ), featureStore.fields(), feature, derAttributes );
759 
760  identifyResult.mParams.insert( QStringLiteral( "getFeatureInfoUrl" ), featureStore.params().value( QStringLiteral( "getFeatureInfoUrl" ) ) );
761  results->append( identifyResult );
762  }
763  }
764  }
765  }
766  else // text or html
767  {
768  QgsDebugMsg( QStringLiteral( "%1 HTML or text values" ).arg( values.size() ) );
769  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
770  {
771  QString value = it.value().toString();
772  attributes.clear();
773  attributes.insert( QString(), value );
774 
775  QString label = layer->subLayers().value( it.key() );
776  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
777  }
778  }
779  }
780  else
781  {
782  attributes.clear();
783  QString value = identifyResult.error().message( QgsErrorMessage::Text );
784  attributes.insert( tr( "Error" ), value );
785  QString label = tr( "Identify error" );
786  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
787  }
788 
789  return true;
790 }
791 
792 QgsUnitTypes::DistanceUnit QgsMapToolIdentify::displayDistanceUnits() const
793 {
794  return mCanvas->mapUnits();
795 }
796 
797 QgsUnitTypes::AreaUnit QgsMapToolIdentify::displayAreaUnits() const
798 {
800 }
801 
802 QString QgsMapToolIdentify::formatDistance( double distance ) const
803 {
804  return formatDistance( distance, displayDistanceUnits() );
805 }
806 
807 QString QgsMapToolIdentify::formatArea( double area ) const
808 {
809  return formatArea( area, displayAreaUnits() );
810 }
811 
812 QString QgsMapToolIdentify::formatDistance( double distance, QgsUnitTypes::DistanceUnit unit ) const
813 {
814  QgsSettings settings;
815  bool baseUnit = settings.value( QStringLiteral( "qgis/measure/keepbaseunit" ), true ).toBool();
816 
817  return QgsDistanceArea::formatDistance( distance, 3, unit, baseUnit );
818 }
819 
820 QString QgsMapToolIdentify::formatArea( double area, QgsUnitTypes::AreaUnit unit ) const
821 {
822  QgsSettings settings;
823  bool baseUnit = settings.value( QStringLiteral( "qgis/measure/keepbaseunit" ), true ).toBool();
824 
825  return QgsDistanceArea::formatArea( area, 3, unit, baseUnit );
826 }
827 
829 {
830  QList<IdentifyResult> results;
831  if ( identifyRasterLayer( &results, layer, mLastGeometry, mLastExtent, mLastMapUnitsPerPixel ) )
832  {
833  emit changedRasterResults( results );
834  }
835 }
836 
double measureLength(const QgsGeometry &geometry) const
Measures the length of a geometry.
bool isValid() const
Returns true if valid.
Wrapper for iterator of features from vector data provider or vector layer.
A container for features with the same fields and crs.
IdentifyFormat
Definition: qgsraster.h:57
A rectangle specified with double values.
Definition: qgsrectangle.h:40
Base class for all map layer types.
Definition: qgsmaplayer.h:63
double y
Definition: qgspoint.h:42
void changedRasterResults(QList< QgsMapToolIdentify::IdentifyResult > &)
QStringList subLayers() const override
Returns the sublayers of this layer.
QgsMapLayer::LayerType type() const
Returns the type of the layer.
static QString printValue(double value)
Print double value with all necessary significant digits.
static double searchRadiusMU(const QgsRenderContext &context)
Gets search radius in map units for given context.
Definition: qgsmaptool.cpp:215
double scale() const
Returns the calculated map scale.
double mapUnitsPerPixel() const
Returns the mapUnitsPerPixel (map units per pixel) for the canvas.
int layerCount() const
Returns number of layers on the map.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
void activate() override
called when set as currently active map tool
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:134
Use exact geometry intersection (slower) instead of bounding boxes.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer&#39;s CRS to output CRS
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:695
void identifyProgress(int, int)
bool identifyLayer(QList< QgsMapToolIdentify::IdentifyResult > *results, QgsMapLayer *layer, const QgsPointXY &point, const QgsRectangle &viewExtent, double mapUnitsPerPixel, QgsMapToolIdentify::LayerType layerType=AllLayers)
Call the right method depending on layer type.
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
This class provides qgis with the ability to render raster datasets onto the mapcanvas.
Features may be filtered, i.e. some features may not be rendered (categorized, rule based ...
Definition: qgsrenderer.h:244
QList< QgsFeatureStore > QgsFeatureStoreList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
double y
Definition: qgspointxy.h:48
A class to represent a 2D point.
Definition: qgspointxy.h:43
QString message(QgsErrorMessage::Format format=QgsErrorMessage::Html) const
Full error messages description.
Definition: qgserror.cpp:49
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
Definition: qgsrectangle.h:341
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
double convertLengthMeasurement(double length, QgsUnitTypes::DistanceUnit toUnits) const
Takes a length measurement calculated by this QgsDistanceArea object and converts it to a different d...
A QgsMapMouseEvent is the result of a user interaction with the mouse on a QgsMapCanvas.
void canvasMoveEvent(QgsMapMouseEvent *e) override
Mouse move event for overriding. Default implementation does nothing.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static Capability identifyFormatToCapability(QgsRaster::IdentifyFormat format)
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
void canvasReleaseEvent(QgsMapMouseEvent *e) override
Mouse release event for overriding. Default implementation does nothing.
QgsPointXY toMapCoordinates(QPoint point)
transformation from screen coordinates to map coordinates
Definition: qgsmaptool.cpp:42
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
bool identifyRasterLayer(QList< QgsMapToolIdentify::IdentifyResult > *results, QgsRasterLayer *layer, QgsPointXY point, const QgsRectangle &viewExtent, double mapUnitsPerPixel)
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
static QgsPoint closestVertex(const QgsAbstractGeometry &geom, const QgsPoint &pt, QgsVertexId &id)
Returns the closest vertex to a geometry for a specified point.
QString ellipsoid
Definition: qgsproject.h:97
void identifyMessage(const QString &)
QString toString(int precision=-1) const
Returns a string representation of the point (x, y) with a preset precision.
Definition: qgspointxy.cpp:40
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
QgsMapToolIdentify(QgsMapCanvas *canvas)
constructor
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:906
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:74
QMap< int, QVariant > results() const
Returns the identify results.
QList< QgsMapToolIdentify::IdentifyResult > identify(int x, int y, const QList< QgsMapLayer * > &layerList=QList< QgsMapLayer * >(), IdentifyMode mode=DefaultQgsSetting)
Performs the identification.
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:71
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
QgsCoordinateReferenceSystem destinationCrs() const
returns CRS of destination coordinate reference system
Raster identify results container.
virtual void activate()
called when set as currently active map tool
Definition: qgsmaptool.cpp:83
QgsMapCanvas * mCanvas
pointer to map canvas
Definition: qgsmaptool.h:241
QgsIdentifyMenu * mIdentifyMenu
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
QgsRasterDataProvider * dataProvider() override
Returns the layer&#39;s data provider.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
void formatChanged(QgsRasterLayer *layer)
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
bool isMeasure() const
Returns true if the geometry contains m values.
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
QList< QgsMapToolIdentify::IdentifyResult > exec(const QList< QgsMapToolIdentify::IdentifyResult > &idResults, QPoint pos)
exec
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
void deactivate() override
called when map tool is being deactivated
Utility class for identifying a unique vertex within a geometry.
virtual QgsRectangle extent() const
Returns the extent of the layer.
static QgsRaster::IdentifyFormat identifyFormatFromName(const QString &formatName)
double convertAreaMeasurement(double area, QgsUnitTypes::AreaUnit toUnits) const
Takes an area measurement calculated by this QgsDistanceArea object and converts it to a different ar...
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:139
This class wraps a request for features to a vector layer (or directly its vector data provider)...
double measurePerimeter(const QgsGeometry &geometry) const
Measures the perimeter of a polygon geometry.
QgsFeatureRenderer * renderer()
Returns renderer.
The QgsIdentifyMenu class builds a menu to be used with identify results (.
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
virtual void deactivate()
called when map tool is being deactivated
Definition: qgsmaptool.cpp:99
QVariant customProperty(const QString &value, const QVariant &defaultValue=QVariant()) const
Read a custom property from layer.
Abstract base class for all geometries.
bool identifyVectorLayer(QList< QgsMapToolIdentify::IdentifyResult > *results, QgsVectorLayer *layer, const QgsPointXY &point)
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QMap< QString, QString > derivedAttributesForPoint(const QgsPoint &point)
Returns derived attributes map for a clicked point in map coordinates. May be 2D or 3D point...
double x
Definition: qgspointxy.h:47
virtual int capabilities() const
Returns a bitmask containing the supported capabilities.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine.
QgsMapLayer * currentLayer()
returns current layer (set by legend widget)
virtual double length() const
Returns the length of the geometry.
QgsExpressionContext & expressionContext()
Gets the expression context.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:53
static Q_INVOKABLE DistanceUnitType unitType(QgsUnitTypes::DistanceUnit unit)
Returns the type for a distance unit.
virtual QString generateBandName(int bandNumber) const
helper function to create zero padded band names
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:96
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:138
Abstract base class for all map tools.
Definition: qgsmaptool.h:62
A general purpose distance and area calculator, capable of performing ellipsoid based calculations...
QString what() const
Definition: qgsexception.h:48
Contains information about the context of a rendering operation.
QgsPointXY toLayerCoordinates(const QgsMapLayer *layer, QPoint point)
transformation from screen coordinates to layer&#39;s coordinates
Definition: qgsmaptool.cpp:54
#define FID_TO_STRING(fid)
Definition: qgsfeatureid.h:30
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void canvasPressEvent(QgsMapMouseEvent *e) override
Mouse press event for overriding. Default implementation does nothing.
virtual double perimeter() const
Returns the perimeter of the geometry.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:144
static QgsRenderContext fromMapSettings(const QgsMapSettings &mapSettings)
create initialized QgsRenderContext instance from given QgsMapSettings
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:411
void setCanvasPropertiesOverrides(double searchRadiusMapUnits)
Overrides some map canvas properties inside the map tool for the upcoming identify requests...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
virtual QgsRasterIdentifyResult identify(const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox=QgsRectangle(), int width=0, int height=0, int dpi=96)
Identify raster value(s) found on the point position.
static void circleCenterRadius(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double &radius, double &centerX, double &centerY)
Returns radius and center of the circle through pt1, pt2, pt3.
static QString formatArea(double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit=false)
Returns an area formatted as a friendly string.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Class for doing transforms between two map coordinate systems.
T enumValue(const QString &key, const T &defaultValue, const Section section=NoSection)
Returns the setting value for a setting based on an enum.
Definition: qgssettings.h:235
QgsUnitTypes::DistanceUnit mapUnits() const
Convenience function for returning the current canvas map units.
double z
Definition: qgspoint.h:43
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Query the layer for features specified in request.
virtual void setCursor(const QCursor &cursor)
Sets a user defined cursor.
Definition: qgsmaptool.cpp:149
QString name
Definition: qgsmaplayer.h:67
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:956
static QCursor getThemeCursor(Cursor cursor)
Helper to get a theme cursor.
void setSourceCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets source spatial reference system crs.
QgsRectangle extent() const
Returns the current zoom extent of the map canvas.
QgsGeometry geometry
Definition: qgsfeature.h:67
void restoreCanvasPropertiesOverrides()
Clears canvas properties overrides previously set with setCanvasPropertiesOverrides() ...
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
static QgsPoint closestPoint(const QgsAbstractGeometry &geometry, const QgsPoint &point)
Returns the nearest point on a segment of a geometry for the specified point.
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer.
bool nextFeature(QgsFeature &f)
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
double width() const
Returns the width of the rectangle.
Definition: qgsrectangle.h:201
virtual QgsPoint vertexAt(QgsVertexId id) const =0
Returns the point corresponding to a specified vertex id.
QgsError error() const
Returns the last error.
Represents a vector layer which manages a vector based data sets.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:565
QgsWkbTypes::GeometryType type() const
Returns type of the geometry as a QgsWkbTypes::GeometryType.
QgsWkbTypes::Type wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static Q_INVOKABLE QgsUnitTypes::AreaUnit distanceToAreaUnit(QgsUnitTypes::DistanceUnit distanceUnit)
Converts a distance unit to its corresponding area unit, e.g., meters to square meters.
double measureArea(const QgsGeometry &geometry) const
Measures the area of a geometry.
QPoint toCanvasCoordinates(const QgsPointXY &point)
transformation from map coordinates to screen coordinates
Definition: qgsmaptool.cpp:75
AreaUnit
Units of area.
Definition: qgsunittypes.h:79
If the layer is identifiable using the identify map tool and as a WMS layer.
Definition: qgsmaplayer.h:130
QgsMapLayer * layer(int index)
Returns the map layer at position index in the layer stack.
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
double area() const
Returns the area of the geometry using GEOS.
static QgsGeometry fromPointXY(const QgsPointXY &point)
Creates a new geometry from a QgsPointXY object.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:129
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:70
double height() const
Returns the height of the rectangle.
Definition: qgsrectangle.h:208
double m
Definition: qgspoint.h:44
Base class for raster data providers.
static QString formatDistance(double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit=false)
Returns an distance formatted as a friendly string.
double x
Definition: qgspoint.h:41