QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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;
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  QgsDebugMsg( "Feature count on identify: " + QString::number( featureCount ) );
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 != GEO_NONE )
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  derivedAttributes.insert( tr( "Length (Cartesian)" ), str );
571 
572  const QgsAbstractGeometry *geom = feature.geometry().constGet();
573  if ( geom )
574  {
575  str = QLocale().toString( geom->nCoordinates() );
576  derivedAttributes.insert( tr( "Vertices" ), str );
577  //add details of closest vertex to identify point
578  closestVertexAttributes( *geom, vId, layer, derivedAttributes );
579  closestPointAttributes( *geom, layerPoint, derivedAttributes );
580 
581  if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
582  {
583  // Add the start and end points in as derived attributes
584  QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) );
585  str = formatXCoordinate( pnt );
586  derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
587  str = formatYCoordinate( pnt );
588  derivedAttributes.insert( tr( "firstY" ), str );
589  pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->endPoint().x(), curve->endPoint().y() ) );
590  str = formatXCoordinate( pnt );
591  derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
592  str = formatYCoordinate( pnt );
593  derivedAttributes.insert( tr( "lastY" ), str );
594  }
595  }
596  }
597  else if ( geometryType == QgsWkbTypes::PolygonGeometry )
598  {
599  double area = calc.measureArea( feature.geometry() );
600  area = calc.convertAreaMeasurement( area, displayAreaUnits() );
601  QString str;
602  if ( ellipsoid != GEO_NONE )
603  {
604  str = formatArea( area );
605  derivedAttributes.insert( tr( "Area (Ellipsoidal, %1)" ).arg( ellipsoid ), str );
606  }
607  str = formatArea( feature.geometry().area()
608  * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::distanceToAreaUnit( layer->crs().mapUnits() ), cartesianAreaUnits ), cartesianAreaUnits );
609  derivedAttributes.insert( tr( "Area (Cartesian)" ), str );
610 
611  if ( ellipsoid != GEO_NONE )
612  {
613  double perimeter = calc.measurePerimeter( feature.geometry() );
614  perimeter = calc.convertLengthMeasurement( perimeter, displayDistanceUnits() );
615  str = formatDistance( perimeter );
616  derivedAttributes.insert( tr( "Perimeter (Ellipsoidal, %1)" ).arg( ellipsoid ), str );
617  }
618  str = formatDistance( feature.geometry().constGet()->perimeter()
619  * QgsUnitTypes::fromUnitToUnitFactor( layer->crs().mapUnits(), cartesianDistanceUnits ), cartesianDistanceUnits );
620  derivedAttributes.insert( tr( "Perimeter (Cartesian)" ), str );
621 
622  str = QLocale().toString( feature.geometry().constGet()->nCoordinates() );
623  derivedAttributes.insert( tr( "Vertices" ), str );
624 
625  //add details of closest vertex to identify point
626  closestVertexAttributes( *feature.geometry().constGet(), vId, layer, derivedAttributes );
627  closestPointAttributes( *feature.geometry().constGet(), layerPoint, derivedAttributes );
628  }
629  else if ( geometryType == QgsWkbTypes::PointGeometry )
630  {
631  if ( QgsWkbTypes::flatType( wkbType ) == QgsWkbTypes::Point )
632  {
633  // Include the x and y coordinates of the point as a derived attribute
634  QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, feature.geometry().asPoint() );
635  QString str = formatXCoordinate( pnt );
636  derivedAttributes.insert( tr( "X" ), str );
637  str = formatYCoordinate( pnt );
638  derivedAttributes.insert( tr( "Y" ), str );
639 
640  if ( QgsWkbTypes::hasZ( wkbType ) )
641  {
642  str = QLocale().toString( static_cast<const QgsPoint *>( feature.geometry().constGet() )->z(), 'g', 10 );
643  derivedAttributes.insert( tr( "Z" ), str );
644  }
645  if ( QgsWkbTypes::hasM( wkbType ) )
646  {
647  str = QLocale().toString( static_cast<const QgsPoint *>( feature.geometry().constGet() )->m(), 'g', 10 );
648  derivedAttributes.insert( tr( "M" ), str );
649  }
650  }
651  else
652  {
653  //multipart
654 
655  //add details of closest vertex to identify point
656  const QgsAbstractGeometry *geom = feature.geometry().constGet();
657  {
658  closestVertexAttributes( *geom, vId, layer, derivedAttributes );
659  }
660  }
661  }
662 
663  return derivedAttributes;
664 }
665 
666 bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel )
667 {
668  QgsPointXY point = geometry.asPoint(); // raster layers currently only support identification by point
669  return identifyRasterLayer( results, layer, point, viewExtent, mapUnitsPerPixel );
670 }
671 
672 bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, QgsPointXY point, const QgsRectangle &viewExtent, double mapUnitsPerPixel )
673 {
674  QgsDebugMsg( "point = " + point.toString() );
675  if ( !layer )
676  return false;
677 
678  QgsRasterDataProvider *dprovider = layer->dataProvider();
679  if ( !dprovider )
680  return false;
681 
682  int capabilities = dprovider->capabilities();
683  if ( !( capabilities & QgsRasterDataProvider::Identify ) )
684  return false;
685 
686  QgsPointXY pointInCanvasCrs = point;
687  try
688  {
689  point = toLayerCoordinates( layer, point );
690  }
691  catch ( QgsCsException &cse )
692  {
693  Q_UNUSED( cse )
694  QgsDebugMsg( QStringLiteral( "coordinate not reprojectable: %1" ).arg( cse.what() ) );
695  return false;
696  }
697  QgsDebugMsg( QStringLiteral( "point = %1 %2" ).arg( point.x() ).arg( point.y() ) );
698 
699  if ( !layer->extent().contains( point ) )
700  return false;
701 
702  QMap< QString, QString > attributes, derivedAttributes;
703 
704  QgsRaster::IdentifyFormat format = QgsRasterDataProvider::identifyFormatFromName( layer->customProperty( QStringLiteral( "identify/format" ) ).toString() );
705 
706  // check if the format is really supported otherwise use first supported format
707  if ( !( QgsRasterDataProvider::identifyFormatToCapability( format ) & capabilities ) )
708  {
710  else if ( capabilities & QgsRasterInterface::IdentifyValue ) format = QgsRaster::IdentifyFormatValue;
711  else if ( capabilities & QgsRasterInterface::IdentifyHtml ) format = QgsRaster::IdentifyFormatHtml;
712  else if ( capabilities & QgsRasterInterface::IdentifyText ) format = QgsRaster::IdentifyFormatText;
713  else return false;
714  }
715 
716  QgsRasterIdentifyResult identifyResult;
717  // We can only use current map canvas context (extent, width, height) if layer is not reprojected,
718  if ( dprovider->crs() != mCanvas->mapSettings().destinationCrs() )
719  {
720  // To get some reasonable response for point/line WMS vector layers we must
721  // use a context with approximately a resolution in layer CRS units
722  // corresponding to current map canvas resolution (for examplei UMN Mapserver
723  // in msWMSFeatureInfo() -> msQueryByRect() is using requested pixel
724  // + TOLERANCE (layer param) for feature selection)
725  //
726  QgsRectangle r;
727  r.setXMinimum( pointInCanvasCrs.x() - mapUnitsPerPixel / 2. );
728  r.setXMaximum( pointInCanvasCrs.x() + mapUnitsPerPixel / 2. );
729  r.setYMinimum( pointInCanvasCrs.y() - mapUnitsPerPixel / 2. );
730  r.setYMaximum( pointInCanvasCrs.y() + mapUnitsPerPixel / 2. );
731  r = toLayerCoordinates( layer, r ); // will be a bit larger
732  // Mapserver (6.0.3, for example) does not work with 1x1 pixel box
733  // but that is fixed (the rect is enlarged) in the WMS provider
734  identifyResult = dprovider->identify( point, format, r, 1, 1 );
735  }
736  else
737  {
738  // It would be nice to use the same extent and size which was used for drawing,
739  // so that WCS can use cache from last draw, unfortunately QgsRasterLayer::draw()
740  // is doing some tricks with extent and size to align raster to output which
741  // would be difficult to replicate here.
742  // Note: cutting the extent may result in slightly different x and y resolutions
743  // and thus shifted point calculated back in QGIS WMS (using average resolution)
744  //viewExtent = dprovider->extent().intersect( &viewExtent );
745 
746  // Width and height are calculated from not projected extent and we hope that
747  // are similar to source width and height used to reproject layer for drawing.
748  // TODO: may be very dangerous, because it may result in different resolutions
749  // in source CRS, and WMS server (QGIS server) calcs wrong coor using average resolution.
750  int width = static_cast< int >( std::round( viewExtent.width() / mapUnitsPerPixel ) );
751  int height = static_cast< int >( std::round( viewExtent.height() / mapUnitsPerPixel ) );
752 
753  QgsDebugMsg( QStringLiteral( "viewExtent.width = %1 viewExtent.height = %2" ).arg( viewExtent.width() ).arg( viewExtent.height() ) );
754  QgsDebugMsg( QStringLiteral( "width = %1 height = %2" ).arg( width ).arg( height ) );
755  QgsDebugMsg( QStringLiteral( "xRes = %1 yRes = %2 mapUnitsPerPixel = %3" ).arg( viewExtent.width() / width ).arg( viewExtent.height() / height ).arg( mapUnitsPerPixel ) );
756 
757  identifyResult = dprovider->identify( point, format, viewExtent, width, height );
758  }
759 
760  derivedAttributes.unite( derivedAttributesForPoint( QgsPoint( pointInCanvasCrs ) ) );
761 
762  if ( identifyResult.isValid() )
763  {
764  QMap<int, QVariant> values = identifyResult.results();
765  QgsGeometry geometry;
766  if ( format == QgsRaster::IdentifyFormatValue )
767  {
768  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
769  {
770  QString valueString;
771  if ( it.value().isNull() )
772  {
773  valueString = tr( "no data" );
774  }
775  else
776  {
777  QVariant value( it.value() );
778  // The cast is legit. Quoting QT doc :
779  // "Although this function is declared as returning QVariant::Type,
780  // the return value should be interpreted as QMetaType::Type"
781  if ( static_cast<QMetaType::Type>( value.type() ) == QMetaType::Float )
782  {
783  valueString = QgsRasterBlock::printValue( value.toFloat() );
784  }
785  else
786  {
787  valueString = QgsRasterBlock::printValue( value.toDouble() );
788  }
789  }
790  attributes.insert( dprovider->generateBandName( it.key() ), valueString );
791  }
792  QString label = layer->name();
793  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
794  }
795  else if ( format == QgsRaster::IdentifyFormatFeature )
796  {
797  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
798  {
799  QVariant value = it.value();
800  if ( value.type() == QVariant::Bool && !value.toBool() )
801  {
802  // sublayer not visible or not queryable
803  continue;
804  }
805 
806  if ( value.type() == QVariant::String )
807  {
808  // error
809  // TODO: better error reporting
810  QString label = layer->subLayers().value( it.key() );
811  attributes.clear();
812  attributes.insert( tr( "Error" ), value.toString() );
813 
814  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
815  continue;
816  }
817 
818  // list of feature stores for a single sublayer
819  const QgsFeatureStoreList featureStoreList = it.value().value<QgsFeatureStoreList>();
820 
821  for ( const QgsFeatureStore &featureStore : featureStoreList )
822  {
823  const QgsFeatureList storeFeatures = featureStore.features();
824  for ( const QgsFeature &feature : storeFeatures )
825  {
826  attributes.clear();
827  // WMS sublayer and feature type, a sublayer may contain multiple feature types.
828  // Sublayer name may be the same as layer name and feature type name
829  // may be the same as sublayer. We try to avoid duplicities in label.
830  QString sublayer = featureStore.params().value( QStringLiteral( "sublayer" ) ).toString();
831  QString featureType = featureStore.params().value( QStringLiteral( "featureType" ) ).toString();
832  // Strip UMN MapServer '_feature'
833  featureType.remove( QStringLiteral( "_feature" ) );
834  QStringList labels;
835  if ( sublayer.compare( layer->name(), Qt::CaseInsensitive ) != 0 )
836  {
837  labels << sublayer;
838  }
839  if ( featureType.compare( sublayer, Qt::CaseInsensitive ) != 0 || labels.isEmpty() )
840  {
841  labels << featureType;
842  }
843 
844  QMap< QString, QString > derAttributes = derivedAttributes;
845  derAttributes.unite( featureDerivedAttributes( feature, layer ) );
846 
847  IdentifyResult identifyResult( qobject_cast<QgsMapLayer *>( layer ), labels.join( QStringLiteral( " / " ) ), featureStore.fields(), feature, derAttributes );
848 
849  identifyResult.mParams.insert( QStringLiteral( "getFeatureInfoUrl" ), featureStore.params().value( QStringLiteral( "getFeatureInfoUrl" ) ) );
850  results->append( identifyResult );
851  }
852  }
853  }
854  }
855  else // text or html
856  {
857  QgsDebugMsg( QStringLiteral( "%1 HTML or text values" ).arg( values.size() ) );
858  for ( auto it = values.constBegin(); it != values.constEnd(); ++it )
859  {
860  QString value = it.value().toString();
861  attributes.clear();
862  attributes.insert( QString(), value );
863 
864  QString label = layer->subLayers().value( it.key() );
865  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
866  }
867  }
868  }
869  else
870  {
871  attributes.clear();
872  QString value = identifyResult.error().message( QgsErrorMessage::Text );
873  attributes.insert( tr( "Error" ), value );
874  QString label = tr( "Identify error" );
875  results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) );
876  }
877 
878  return true;
879 }
880 
881 QgsUnitTypes::DistanceUnit QgsMapToolIdentify::displayDistanceUnits() const
882 {
883  return mCanvas->mapUnits();
884 }
885 
886 QgsUnitTypes::AreaUnit QgsMapToolIdentify::displayAreaUnits() const
887 {
889 }
890 
891 QString QgsMapToolIdentify::formatDistance( double distance ) const
892 {
893  return formatDistance( distance, displayDistanceUnits() );
894 }
895 
896 QString QgsMapToolIdentify::formatArea( double area ) const
897 {
898  return formatArea( area, displayAreaUnits() );
899 }
900 
901 QString QgsMapToolIdentify::formatDistance( double distance, QgsUnitTypes::DistanceUnit unit ) const
902 {
903  QgsSettings settings;
904  bool baseUnit = settings.value( QStringLiteral( "qgis/measure/keepbaseunit" ), true ).toBool();
905 
906  return QgsDistanceArea::formatDistance( distance, 3, unit, baseUnit );
907 }
908 
909 QString QgsMapToolIdentify::formatArea( double area, QgsUnitTypes::AreaUnit unit ) const
910 {
911  QgsSettings settings;
912  bool baseUnit = settings.value( QStringLiteral( "qgis/measure/keepbaseunit" ), true ).toBool();
913 
914  return QgsDistanceArea::formatArea( area, 3, unit, baseUnit );
915 }
916 
918 {
919  QList<IdentifyResult> results;
920  if ( identifyRasterLayer( &results, layer, mLastGeometry, mLastExtent, mLastMapUnitsPerPixel ) )
921  {
922  emit changedRasterResults( results );
923  }
924 }
925 
bool isMeasure() const
Returns true if the geometry contains m values.
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:78
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:58
static bool isMultiType(Type type)
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:560
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
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
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
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:111
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:40
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:97
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:771
Map canvas is a class for displaying all GIS data types on a canvas.
Definition: qgsmapcanvas.h:73
const QString GEO_NONE
Constant that holds the string representation for "No ellips/No CRS".
Definition: qgis.cpp:71
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 layer&#39;s data provider, it may be nullptr.
virtual double length() const
Returns the 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:54
static Q_INVOKABLE DistanceUnitType unitType(QgsUnitTypes::DistanceUnit unit)
Returns the type for a distance unit.
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:96
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:438
virtual double perimeter() const
Returns the 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:244
double z
Definition: qgspoint.h:43
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:90
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:82
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:821
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:115
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
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 area of the geometry using GEOS.
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:430
static Q_INVOKABLE QgsUnitTypes::AreaUnit distanceToAreaUnit(QgsUnitTypes::DistanceUnit distanceUnit)
Converts a distance unit to its corresponding area unit, e.g., meters to square meters.
QPoint toCanvasCoordinates(const QgsPointXY &point)
transformation from map coordinates to screen coordinates
Definition: qgsmaptool.cpp:75
AreaUnit
Units of area.
Definition: qgsunittypes.h:80
If the layer is identifiable using the identify map tool and as a WMS layer.
Definition: qgsmaplayer.h:136
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:85
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.