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