QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspointcloudlayerprofilegenerator.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudlayerprofilegenerator.cpp
3  ---------------
4  begin : April 2022
5  copyright : (C) 2022 by Nyall Dawson
6  email : nyall dot dawson at gmail dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
18 #include "qgsprofilerequest.h"
19 #include "qgscurve.h"
20 #include "qgspointcloudlayer.h"
21 #include "qgscoordinatetransform.h"
22 #include "qgsgeos.h"
23 #include "qgsterrainprovider.h"
24 #include "qgslinesymbol.h"
26 #include "qgsprofilesnapping.h"
27 #include "qgsprofilepoint.h"
28 #include "qgspointcloudrenderer.h"
29 #include "qgspointcloudrequest.h"
31 #include "qgsmarkersymbol.h"
32 #include "qgsmessagelog.h"
33 
34 //
35 // QgsPointCloudLayerProfileGenerator
36 //
37 
39 {
40  mPointIndex = GEOSSTRtree_create_r( QgsGeos::getGEOSHandler(), ( size_t )10 );
41 }
42 
44 {
45  GEOSSTRtree_destroy_r( QgsGeos::getGEOSHandler(), mPointIndex );
46  mPointIndex = nullptr;
47 }
48 
50 {
51  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
52 
53  const std::size_t size = results.size();
54  PointResult *pointData = results.data();
55  for ( std::size_t i = 0; i < size; ++i, ++pointData )
56  {
57  if ( feedback->isCanceled() )
58  break;
59 
60 #if GEOS_VERSION_MAJOR>3 || GEOS_VERSION_MINOR>=8
61  geos::unique_ptr geosPoint( GEOSGeom_createPointFromXY_r( geosctxt, pointData->distanceAlongCurve, pointData->z ) );
62 #else
63  GEOSCoordSequence *seq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
64  GEOSCoordSeq_setX_r( geosctxt, seq, 0, point.distanceAlongCurve );
65  GEOSCoordSeq_setY_r( geosctxt, seq, 0, point.z );
66  geos::unique_ptr geosPoint( GEOSGeom_createPoint_r( geosctxt, seq ) );
67 #endif
68 
69  GEOSSTRtree_insert_r( geosctxt, mPointIndex, geosPoint.get(), pointData );
70  // only required for GEOS < 3.9
71 #if GEOS_VERSION_MAJOR<4 && GEOS_VERSION_MINOR<9
72  mSTRTreeItems.emplace_back( std::move( geosPoint ) );
73 #endif
74  }
75 }
76 
78 {
79  return QStringLiteral( "pointcloud" );
80 }
81 
83 {
84  // TODO -- cache?
85  QMap< double, double > res;
86  for ( const PointResult &point : results )
87  {
88  res.insert( point.distanceAlongCurve, point.z );
89  }
90  return res;
91 }
92 
94 {
95  // TODO -- cache?
96  QgsPointSequence res;
97  res.reserve( results.size() );
98  for ( const PointResult &point : results )
99  {
100  res.append( QgsPoint( point.x, point.y, point.z ) );
101  }
102  return res;
103 }
104 
106 {
107  // TODO -- cache?
108  QVector< QgsGeometry > res;
109  res.reserve( results.size() );
110  for ( const PointResult &point : results )
111  {
112  res.append( QgsGeometry( new QgsPoint( point.x, point.y, point.z ) ) );
113  }
114  return res;
115 }
116 
118 {
119  return QgsDoubleRange( minZ, maxZ );
120 }
121 
123 {
124  QPainter *painter = context.renderContext().painter();
125  if ( !painter )
126  return;
127 
128  const QgsScopedQPainterState painterState( painter );
129 
130  painter->setBrush( Qt::NoBrush );
131  painter->setPen( Qt::NoPen );
132 
133  switch ( pointSymbol )
134  {
136  // for square point we always disable antialiasing -- it's not critical here and we benefit from the performance boost disabling it gives
137  context.renderContext().painter()->setRenderHint( QPainter::Antialiasing, false );
138  break;
139 
141  break;
142  }
143 
144  const double minDistance = context.distanceRange().lower();
145  const double maxDistance = context.distanceRange().upper();
146  const double minZ = context.elevationRange().lower();
147  const double maxZ = context.elevationRange().upper();
148 
149  const QRectF visibleRegion( minDistance, minZ, maxDistance - minDistance, maxZ - minZ );
150  QPainterPath clipPath;
151  clipPath.addPolygon( context.worldTransform().map( visibleRegion ) );
152  painter->setClipPath( clipPath, Qt::ClipOperation::IntersectClip );
153 
154  const double penWidth = context.renderContext().convertToPainterUnits( pointSize, pointSizeUnit );
155 
156  for ( const PointResult &point : std::as_const( results ) )
157  {
158  QPointF p = context.worldTransform().map( QPointF( point.distanceAlongCurve, point.z ) );
159  QColor color = respectLayerColors ? point.color : pointColor;
161  color.setAlphaF( color.alphaF() * ( 1.0 - std::pow( point.distanceFromCurve / tolerance, 0.5 ) ) );
162 
163  switch ( pointSymbol )
164  {
166  painter->fillRect( QRectF( p.x() - penWidth * 0.5,
167  p.y() - penWidth * 0.5,
168  penWidth, penWidth ), color );
169  break;
170 
172  painter->setBrush( QBrush( color ) );
173  painter->setPen( Qt::NoPen );
174  painter->drawEllipse( QRectF( p.x() - penWidth * 0.5,
175  p.y() - penWidth * 0.5,
176  penWidth, penWidth ) );
177  break;
178  }
179  }
180 }
181 
183 {
184  QList< const QgsPointCloudLayerProfileResults::PointResult * > *list;
185 };
186 void _GEOSQueryCallback( void *item, void *userdata )
187 {
188  reinterpret_cast<_GEOSQueryCallbackData *>( userdata )->list->append( reinterpret_cast<const QgsPointCloudLayerProfileResults::PointResult *>( item ) );
189 }
190 
192 {
193  QgsProfileSnapResult result;
194 
195  GEOSContextHandle_t geosctxt = QgsGeos::getGEOSHandler();
196 
197  const double minDistance = point.distance() - context.maximumPointDistanceDelta;
198  const double maxDistance = point.distance() + context.maximumPointDistanceDelta;
199  const double minElevation = point.elevation() - context.maximumPointElevationDelta;
200  const double maxElevation = point.elevation() + context.maximumPointElevationDelta;
201 
202  GEOSCoordSequence *coord = GEOSCoordSeq_create_r( geosctxt, 2, 2 );
203 #if GEOS_VERSION_MAJOR<4 && GEOS_VERSION_MINOR<9
204  GEOSCoordSeq_setXY_r( geosctxt, coord, 0, minDistance, minElevation );
205  GEOSCoordSeq_setXY_r( geosctxt, coord, 1, maxDistance, maxElevation );
206 #else
207  GEOSCoordSeq_setX_r( geosctxt, coord, 0, minDistance );
208  GEOSCoordSeq_setY_r( geosctxt, coord, 0, minElevation );
209  GEOSCoordSeq_setX_r( geosctxt, coord, 1, maxDistance );
210  GEOSCoordSeq_setY_r( geosctxt, coord, 1, maxElevation );
211 #endif
212  geos::unique_ptr searchDiagonal( GEOSGeom_createLineString_r( geosctxt, coord ) );
213 
214  QList<const PointResult *> items;
215  struct _GEOSQueryCallbackData callbackData;
216  callbackData.list = &items;
217  GEOSSTRtree_query_r( geosctxt, mPointIndex, searchDiagonal.get(), _GEOSQueryCallback, &callbackData );
218  if ( items.empty() )
219  return result;
220 
221  double bestMatchDistance = std::numeric_limits< double >::max();
222  const PointResult *bestMatch = nullptr;
223  for ( const PointResult *candidate : std::as_const( items ) )
224  {
225  const double distance = std::sqrt( std::pow( candidate->distanceAlongCurve - point.distance(), 2 )
226  + std::pow( ( candidate->z - point.elevation() ) / context.displayRatioElevationVsDistance, 2 ) );
227  if ( distance < bestMatchDistance )
228  {
229  bestMatchDistance = distance;
230  bestMatch = candidate;
231  }
232  }
233  if ( !bestMatch )
234  return result;
235 
236  result.snappedPoint = QgsProfilePoint( bestMatch->distanceAlongCurve, bestMatch->z );
237  return result;
238 }
239 
240 QVector<QgsProfileIdentifyResults> QgsPointCloudLayerProfileResults::identify( const QgsProfilePoint &point, const QgsProfileIdentifyContext &context )
241 {
242  return identify( QgsDoubleRange( point.distance() - context.maximumPointDistanceDelta, point.distance() + context.maximumPointDistanceDelta ),
243  QgsDoubleRange( point.elevation() - context.maximumPointElevationDelta, point.elevation() + context.maximumPointElevationDelta ), context );
244 }
245 
246 QVector<QgsProfileIdentifyResults> QgsPointCloudLayerProfileResults::identify( const QgsDoubleRange &distanceRange, const QgsDoubleRange &elevationRange, const QgsProfileIdentifyContext &context )
247 {
248  if ( !mLayer )
249  return {};
250 
251  std::unique_ptr< QgsCurve > substring( mProfileCurve->curveSubstring( distanceRange.lower(), distanceRange.upper() ) );
252  QgsGeos substringGeos( substring.get() );
253  std::unique_ptr< QgsAbstractGeometry > searchGeometry( substringGeos.buffer( mTolerance, 8, Qgis::EndCapStyle::Flat, Qgis::JoinStyle::Round, 2 ) );
254  if ( !searchGeometry )
255  return {};
256 
257  const QgsCoordinateTransform curveToLayerTransform = QgsCoordinateTransform( mCurveCrs, mLayer->crs(), context.project ? context.project->transformContext() : QgsCoordinateTransformContext() );
258  try
259  {
260  searchGeometry->transform( curveToLayerTransform );
261  }
262  catch ( QgsCsException & )
263  {
264  return {};
265  }
266 
267  // we have to adjust the elevation range to "undo" the z offset/z scale before we can hand to the provider
268  const QgsDoubleRange providerElevationRange( ( elevationRange.lower() - mZOffset ) / mZScale, ( elevationRange.upper() - mZOffset ) / mZScale );
269 
270  const QgsGeometry pointCloudSearchGeometry( std::move( searchGeometry ) );
271  const QVector<QVariantMap> pointAttributes = mLayer->dataProvider()->identify( mMaxErrorInLayerCoordinates, pointCloudSearchGeometry, providerElevationRange );
272  if ( pointAttributes.empty() )
273  return {};
274 
275  return { QgsProfileIdentifyResults( mLayer, pointAttributes )};
276 }
277 
279 {
280  const QgsPointCloudLayerProfileGenerator *pcGenerator = qgis::down_cast< const QgsPointCloudLayerProfileGenerator *>( generator );
281  tolerance = pcGenerator->mTolerance;
282  pointSize = pcGenerator->mPointSize;
283  pointSizeUnit = pcGenerator->mPointSizeUnit;
284  pointSymbol = pcGenerator->mPointSymbol;
285  pointColor = pcGenerator->mPointColor;
286  respectLayerColors = static_cast< bool >( pcGenerator->mRenderer );
287  opacityByDistanceEffect = pcGenerator->mOpacityByDistanceEffect;
288 
289  mLayer = pcGenerator->mLayer;
290  mCurveCrs = pcGenerator->mTargetCrs;
291  mProfileCurve.reset( pcGenerator->mProfileCurve->clone() );
292  mTolerance = pcGenerator->mTolerance;
293 
294  mZOffset = pcGenerator->mZOffset;
295  mZScale = pcGenerator->mZScale;
296 }
297 
298 //
299 // QgsPointCloudLayerProfileGenerator
300 //
301 
303  : mLayer( layer )
304  , mLayerAttributes( layer->attributes() )
305  , mRenderer( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->respectLayerColors() && mLayer->renderer() ? mLayer->renderer()->clone() : nullptr )
306  , mMaximumScreenError( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->maximumScreenError() )
307  , mMaximumScreenErrorUnit( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->maximumScreenErrorUnit() )
308  , mPointSize( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->pointSize() )
309  , mPointSizeUnit( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->pointSizeUnit() )
310  , mPointSymbol( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->pointSymbol() )
311  , mPointColor( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->pointColor() )
312  , mOpacityByDistanceEffect( qgis::down_cast< QgsPointCloudLayerElevationProperties* >( layer->elevationProperties() )->applyOpacityByDistanceEffect() )
313  , mId( layer->id() )
314  , mFeedback( std::make_unique< QgsFeedback >() )
315  , mProfileCurve( request.profileCurve() ? request.profileCurve()->clone() : nullptr )
316  , mTolerance( request.tolerance() )
317  , mSourceCrs( layer->crs() )
318  , mTargetCrs( request.crs() )
319  , mTransformContext( request.transformContext() )
320  , mZOffset( layer->elevationProperties()->zOffset() )
321  , mZScale( layer->elevationProperties()->zScale() )
322  , mStepDistance( request.stepDistance() )
323 {
324  if ( mLayer->dataProvider()->index() )
325  {
326  mScale = mLayer->dataProvider()->index()->scale();
327  mOffset = mLayer->dataProvider()->index()->offset();
328  }
329 }
330 
332 {
333  return mId;
334 }
335 
336 Qgis::ProfileGeneratorFlags QgsPointCloudLayerProfileGenerator::flags() const
337 {
339 }
340 
342 
344 {
345  mGatheredPoints.clear();
346  if ( !mLayer || !mProfileCurve || mFeedback->isCanceled() )
347  return false;
348 
349  // this is not AT ALL thread safe, but it's what QgsPointCloudLayerRenderer does !
350  // TODO: fix when QgsPointCloudLayerRenderer is made thread safe to use same approach
351 
352  QgsPointCloudIndex *pc = mLayer->dataProvider()->index();
353  if ( !pc || !pc->isValid() )
354  {
355  return false;
356  }
357 
358  const double startDistanceOffset = std::max( !context.distanceRange().isInfinite() ? context.distanceRange().lower() : 0, 0.0 );
359  const double endDistance = context.distanceRange().upper();
360 
361  std::unique_ptr< QgsCurve > trimmedCurve;
362  QgsCurve *sourceCurve = nullptr;
363  if ( startDistanceOffset > 0 || endDistance < mProfileCurve->length() )
364  {
365  trimmedCurve.reset( mProfileCurve->curveSubstring( startDistanceOffset, endDistance ) );
366  sourceCurve = trimmedCurve.get();
367  }
368  else
369  {
370  sourceCurve = mProfileCurve.get();
371  }
372 
373  // we need to transform the profile curve and max search extent to the layer's CRS
374  QgsGeos originalCurveGeos( sourceCurve );
375  originalCurveGeos.prepareGeometry();
376  mSearchGeometryInLayerCrs.reset( originalCurveGeos.buffer( mTolerance, 8, Qgis::EndCapStyle::Flat, Qgis::JoinStyle::Round, 2 ) );
377  mLayerToTargetTransform = QgsCoordinateTransform( mSourceCrs, mTargetCrs, mTransformContext );
378 
379  try
380  {
381  mSearchGeometryInLayerCrs->transform( mLayerToTargetTransform, Qgis::TransformDirection::Reverse );
382  }
383  catch ( QgsCsException & )
384  {
385  QgsDebugMsg( QStringLiteral( "Error transforming profile line to layer CRS" ) );
386  return false;
387  }
388 
389  if ( mFeedback->isCanceled() )
390  return false;
391 
392  mSearchGeometryInLayerCrsGeometryEngine = std::make_unique< QgsGeos >( mSearchGeometryInLayerCrs.get() );
393  mSearchGeometryInLayerCrsGeometryEngine->prepareGeometry();
394  mMaxSearchExtentInLayerCrs = mSearchGeometryInLayerCrs->boundingBox();
395 
396  const IndexedPointCloudNode root = pc->root();
397 
398  double maximumErrorPixels = context.convertDistanceToPixels( mMaximumScreenError, mMaximumScreenErrorUnit );
399  const double toleranceInPixels = context.convertDistanceToPixels( mTolerance, QgsUnitTypes::RenderMapUnits );
400  // ensure that the maximum error is compatible with the tolerance size -- otherwise if the tolerance size
401  // is much smaller than the maximum error, we don't dig deep enough into the point cloud nodes to find
402  // points which are inside the tolerance.
403  // "4" is a magic number here, based purely on what "looks good" in the profile results!
404  if ( toleranceInPixels / 4 < maximumErrorPixels )
405  maximumErrorPixels = toleranceInPixels / 4;
406 
407  const QgsRectangle rootNodeExtentLayerCoords = pc->nodeMapExtent( root );
408  QgsRectangle rootNodeExtentInCurveCrs;
409  try
410  {
411  QgsCoordinateTransform extentTransform = mLayerToTargetTransform;
412  extentTransform.setBallparkTransformsAreAppropriate( true );
413  rootNodeExtentInCurveCrs = extentTransform.transformBoundingBox( rootNodeExtentLayerCoords );
414  }
415  catch ( QgsCsException & )
416  {
417  QgsDebugMsg( QStringLiteral( "Could not transform node extent to curve CRS" ) );
418  rootNodeExtentInCurveCrs = rootNodeExtentLayerCoords;
419  }
420 
421  const double rootErrorInMapCoordinates = rootNodeExtentInCurveCrs.width() / pc->span(); // in curve coords
422 
423  const double mapUnitsPerPixel = context.mapUnitsPerDistancePixel();
424  if ( ( rootErrorInMapCoordinates < 0.0 ) || ( mapUnitsPerPixel < 0.0 ) || ( maximumErrorPixels < 0.0 ) )
425  {
426  QgsDebugMsg( QStringLiteral( "invalid screen error" ) );
427  return false;
428  }
429  double rootErrorPixels = rootErrorInMapCoordinates / mapUnitsPerPixel; // in pixels
430  const QVector<IndexedPointCloudNode> nodes = traverseTree( pc, pc->root(), maximumErrorPixels, rootErrorPixels, context.elevationRange() );
431 
432  const double rootErrorInLayerCoordinates = rootNodeExtentLayerCoords.width() / pc->span();
433  const double maxErrorInMapCoordinates = maximumErrorPixels * mapUnitsPerPixel;
434 
435  mResults = std::make_unique< QgsPointCloudLayerProfileResults >();
436  mResults->copyPropertiesFromGenerator( this );
437  mResults->mMaxErrorInLayerCoordinates = maxErrorInMapCoordinates * rootErrorInLayerCoordinates / rootErrorInMapCoordinates;
438 
439  QgsPointCloudRequest request;
441  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "X" ), QgsPointCloudAttribute::Int32 ) );
442  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Y" ), QgsPointCloudAttribute::Int32 ) );
443  attributes.push_back( QgsPointCloudAttribute( QStringLiteral( "Z" ), QgsPointCloudAttribute::Int32 ) );
444 
445  if ( mRenderer )
446  {
447  mPreparedRendererData = mRenderer->prepare();
448  if ( mPreparedRendererData )
449  {
450  const QSet< QString > rendererAttributes = mPreparedRendererData->usedAttributes();
451  for ( const QString &attribute : std::as_const( rendererAttributes ) )
452  {
453  if ( attributes.indexOf( attribute ) >= 0 )
454  continue; // don't re-add attributes we are already going to fetch
455 
456  const int layerIndex = mLayerAttributes.indexOf( attribute );
457  if ( layerIndex < 0 )
458  {
459  QgsMessageLog::logMessage( QObject::tr( "Required attribute %1 not found in layer" ).arg( attribute ), QObject::tr( "Point Cloud" ) );
460  continue;
461  }
462 
463  attributes.push_back( mLayerAttributes.at( layerIndex ) );
464  }
465  }
466  }
467  else
468  {
469  mPreparedRendererData.reset();
470  }
471 
472  request.setAttributes( attributes );
473 
474  switch ( pc->accessType() )
475  {
476  case QgsPointCloudIndex::AccessType::Local:
477  {
478  visitNodesSync( nodes, pc, request, context.elevationRange() );
479  break;
480  }
481  case QgsPointCloudIndex::AccessType::Remote:
482  {
483  visitNodesAsync( nodes, pc, request, context.elevationRange() );
484  break;
485  }
486  }
487 
488  if ( mFeedback->isCanceled() )
489  return false;
490 
491  // convert x/y values back to distance/height values
492 
493  QString lastError;
494  const QgsPointCloudLayerProfileResults::PointResult *pointData = mGatheredPoints.constData();
495  const int size = mGatheredPoints.size();
496  mResults->results.resize( size );
497  QgsPointCloudLayerProfileResults::PointResult *destData = mResults->results.data();
498  for ( int i = 0; i < size; ++i, ++pointData, ++destData )
499  {
500  if ( mFeedback->isCanceled() )
501  return false;
502 
503  *destData = *pointData;
504  destData->distanceAlongCurve = startDistanceOffset + originalCurveGeos.lineLocatePoint( destData->x, destData->y, &lastError );
505  if ( mOpacityByDistanceEffect ) // don't calculate this if we don't need it
506  destData->distanceFromCurve = originalCurveGeos.distance( destData->x, destData->y );
507 
508  mResults->minZ = std::min( destData->z, mResults->minZ );
509  mResults->maxZ = std::max( destData->z, mResults->maxZ );
510  }
511  mResults->finalize( mFeedback.get() );
512 
513  return true;
514 }
515 
517 {
518  return mResults.release();
519 }
520 
522 {
523  return mFeedback.get();
524 }
525 
526 QVector<IndexedPointCloudNode> QgsPointCloudLayerProfileGenerator::traverseTree( const QgsPointCloudIndex *pc, IndexedPointCloudNode n, double maxErrorPixels, double nodeErrorPixels, const QgsDoubleRange &zRange )
527 {
528  QVector<IndexedPointCloudNode> nodes;
529 
530  if ( mFeedback->isCanceled() )
531  {
532  return nodes;
533  }
534 
535  const QgsDoubleRange nodeZRange = pc->nodeZRange( n );
536  const QgsDoubleRange adjustedNodeZRange = QgsDoubleRange( nodeZRange.lower() * mZScale + mZOffset, nodeZRange.upper() * mZScale + mZOffset );
537  if ( !zRange.isInfinite() && !zRange.overlaps( adjustedNodeZRange ) )
538  return nodes;
539 
540  const QgsRectangle nodeMapExtent = pc->nodeMapExtent( n );
541  if ( !mMaxSearchExtentInLayerCrs.intersects( nodeMapExtent ) )
542  return nodes;
543 
544  const QgsGeometry nodeMapGeometry = QgsGeometry::fromRect( nodeMapExtent );
545  if ( !mSearchGeometryInLayerCrsGeometryEngine->intersects( nodeMapGeometry.constGet() ) )
546  return nodes;
547 
548  nodes.append( n );
549 
550  double childrenErrorPixels = nodeErrorPixels / 2.0;
551  if ( childrenErrorPixels < maxErrorPixels )
552  return nodes;
553 
554  const QList<IndexedPointCloudNode> children = pc->nodeChildren( n );
555  for ( const IndexedPointCloudNode &nn : children )
556  {
557  nodes += traverseTree( pc, nn, maxErrorPixels, childrenErrorPixels, zRange );
558  }
559 
560  return nodes;
561 }
562 
563 int QgsPointCloudLayerProfileGenerator::visitNodesSync( const QVector<IndexedPointCloudNode> &nodes, QgsPointCloudIndex *pc, QgsPointCloudRequest &request, const QgsDoubleRange &zRange )
564 {
565  int nodesDrawn = 0;
566  for ( const IndexedPointCloudNode &n : nodes )
567  {
568  if ( mFeedback->isCanceled() )
569  break;
570 
571  std::unique_ptr<QgsPointCloudBlock> block( pc->nodeData( n, request ) );
572 
573  if ( !block )
574  continue;
575 
576  visitBlock( block.get(), zRange );
577 
578  ++nodesDrawn;
579  }
580  return nodesDrawn;
581 }
582 
583 int QgsPointCloudLayerProfileGenerator::visitNodesAsync( const QVector<IndexedPointCloudNode> &nodes, QgsPointCloudIndex *pc, QgsPointCloudRequest &request, const QgsDoubleRange &zRange )
584 {
585  int nodesDrawn = 0;
586 
587  // see notes about this logic in QgsPointCloudLayerRenderer::renderNodesAsync
588 
589  // Async loading of nodes
590  QVector<QgsPointCloudBlockRequest *> blockRequests;
591  QEventLoop loop;
592  QObject::connect( mFeedback.get(), &QgsFeedback::canceled, &loop, &QEventLoop::quit );
593 
594  for ( int i = 0; i < nodes.size(); ++i )
595  {
596  const IndexedPointCloudNode &n = nodes[i];
597  const QString nStr = n.toString();
598  QgsPointCloudBlockRequest *blockRequest = pc->asyncNodeData( n, request );
599  blockRequests.append( blockRequest );
600  QObject::connect( blockRequest, &QgsPointCloudBlockRequest::finished, &loop,
601  [ this, &nodesDrawn, &loop, &blockRequests, &zRange, nStr, blockRequest ]()
602  {
603  blockRequests.removeOne( blockRequest );
604 
605  // If all blocks are loaded, exit the event loop
606  if ( blockRequests.isEmpty() )
607  loop.exit();
608 
609  std::unique_ptr<QgsPointCloudBlock> block( blockRequest->block() );
610 
611  blockRequest->deleteLater();
612 
613  if ( mFeedback->isCanceled() )
614  {
615  return;
616  }
617 
618  if ( !block )
619  {
620  QgsDebugMsg( QStringLiteral( "Unable to load node %1, error: %2" ).arg( nStr, blockRequest->errorStr() ) );
621  return;
622  }
623 
624  visitBlock( block.get(), zRange );
625  ++nodesDrawn;
626  } );
627  }
628 
629  // Wait for all point cloud nodes to finish loading
630  loop.exec();
631 
632  // Generation may have got canceled and the event loop exited before finished()
633  // was called for all blocks, so let's clean up anything that is left
634  for ( QgsPointCloudBlockRequest *blockRequest : std::as_const( blockRequests ) )
635  {
636  delete blockRequest->block();
637  blockRequest->deleteLater();
638  }
639 
640  return nodesDrawn;
641 }
642 
643 void QgsPointCloudLayerProfileGenerator::visitBlock( const QgsPointCloudBlock *block, const QgsDoubleRange &zRange )
644 {
645  const char *ptr = block->data();
646  int count = block->pointCount();
647 
648  const QgsPointCloudAttributeCollection request = block->attributes();
649 
650  const std::size_t recordSize = request.pointRecordSize();
651 
652  const QgsPointCloudAttributeCollection blockAttributes = block->attributes();
653  int xOffset = 0, yOffset = 0, zOffset = 0;
654  const QgsPointCloudAttribute::DataType xType = blockAttributes.find( QStringLiteral( "X" ), xOffset )->type();
655  const QgsPointCloudAttribute::DataType yType = blockAttributes.find( QStringLiteral( "Y" ), yOffset )->type();
656  const QgsPointCloudAttribute::DataType zType = blockAttributes.find( QStringLiteral( "Z" ), zOffset )->type();
657 
658  bool useRenderer = false;
659  if ( mPreparedRendererData )
660  {
661  useRenderer = mPreparedRendererData->prepareBlock( block );
662  }
663 
664  QColor color;
665  const bool reproject = !mLayerToTargetTransform.isShortCircuited();
666  for ( int i = 0; i < count; ++i )
667  {
668  if ( mFeedback->isCanceled() )
669  {
670  break;
671  }
672 
674  QgsPointCloudAttribute::getPointXYZ( ptr, i, recordSize, xOffset, xType, yOffset, yType, zOffset, zType, block->scale(), block->offset(), res.x, res.y, res.z );
675 
676  res.z = res.z * mZScale + mZOffset;
677  if ( !zRange.contains( res.z ) )
678  continue;
679 
680  if ( useRenderer )
681  {
682  color = mPreparedRendererData->pointColor( block, i, res.z );
683  if ( !color.isValid() )
684  continue;
685 
686  res.color = color.rgba();
687  }
688  else
689  {
690  res.color = mPointColor.rgba();
691  }
692 
693  if ( mSearchGeometryInLayerCrsGeometryEngine->contains( res.x, res.y ) )
694  {
695  if ( reproject )
696  {
697  try
698  {
699  mLayerToTargetTransform.transformInPlace( res.x, res.y, res.z );
700  }
701  catch ( QgsCsException & )
702  {
703  continue;
704  }
705  }
706 
707  mGatheredPoints.append( res );
708  }
709  }
710 }
711 
712 
QgsRectangle::intersects
bool intersects(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle intersects with other rectangle.
Definition: qgsrectangle.h:349
QgsProfileIdentifyContext
Encapsulates the context of identifying profile results.
Definition: qgsabstractprofilegenerator.h:125
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsPointCloudLayerProfileResults::minZ
double minZ
Definition: qgspointcloudlayerprofilegenerator.h:83
QgsPointCloudIndex::nodeMapExtent
QgsRectangle nodeMapExtent(const IndexedPointCloudNode &node) const
Returns the extent of a node in map coordinates.
Definition: qgspointcloudindex.cpp:216
QgsPointCloudLayerProfileResults::PointResult::y
double y
Definition: qgspointcloudlayerprofilegenerator.h:68
QgsGeos::distance
double distance(const QgsAbstractGeometry *geom, QString *errorMsg=nullptr) const override
Calculates the distance between this and geom.
Definition: qgsgeos.cpp:444
QgsPointCloudLayerProfileResults::pointColor
QColor pointColor
Definition: qgspointcloudlayerprofilegenerator.h:90
QgsCoordinateTransform::transformInPlace
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
Definition: qgscoordinatetransform.cpp:364
_GEOSQueryCallbackData
Definition: qgspointcloudlayerprofilegenerator.cpp:182
QgsPointCloudLayerProfileResults::pointSymbol
Qgis::PointCloudSymbol pointSymbol
Definition: qgspointcloudlayerprofilegenerator.h:88
QgsProfileIdentifyContext::maximumPointElevationDelta
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when identifying a point.
Definition: qgsabstractprofilegenerator.h:139
QgsPointCloudBlockRequest::block
QgsPointCloudBlock * block()
Returns the requested block.
QgsCoordinateTransformContext
Contains information about the context in which a coordinate transform is executed.
Definition: qgscoordinatetransformcontext.h:57
QgsProfileRenderContext::distanceRange
QgsDoubleRange distanceRange() const
Returns the range of distances to include in the render.
Definition: qgsabstractprofilegenerator.cpp:37
_GEOSQueryCallback
void _GEOSQueryCallback(void *item, void *userdata)
Definition: qgspointcloudlayerprofilegenerator.cpp:186
QgsPointCloudAttribute::DataType
DataType
Systems of unit measurement.
Definition: qgspointcloudattribute.h:44
QgsPointCloudAttributeCollection::find
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Definition: qgspointcloudattribute.cpp:168
QgsProfileSnapContext::maximumPointElevationDelta
double maximumPointElevationDelta
Maximum allowed snapping delta for the elevation values when snapping to a point.
Definition: qgsprofilesnapping.h:57
QgsPointCloudIndex::nodeData
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
QgsRange::overlaps
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
Definition: qgsrange.h:147
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
qgspointcloudblockrequest.h
QgsPointCloudLayerProfileResults::copyPropertiesFromGenerator
void copyPropertiesFromGenerator(const QgsAbstractProfileGenerator *generator) override
Copies properties from specified generator to the results object.
Definition: qgspointcloudlayerprofilegenerator.cpp:278
QgsPointCloudLayerElevationProperties
Point cloud layer specific subclass of QgsMapLayerElevationProperties.
Definition: qgspointcloudlayerelevationproperties.h:33
QgsPointCloudLayer
Represents a map layer supporting display of point clouds.
Definition: qgspointcloudlayer.h:45
QgsPointCloudBlock::data
const char * data() const
Returns raw pointer to data.
Definition: qgspointcloudblock.cpp:37
QgsProfileSnapResult
Encapsulates results of snapping a profile point.
Definition: qgsprofilesnapping.h:56
QgsFeedback::canceled
void canceled()
Internal routines can connect to this signal if they use event loop.
QgsPointCloudLayerProfileResults::PointResult
Definition: qgspointcloudlayerprofilegenerator.h:65
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsPointCloudBlock::attributes
QgsPointCloudAttributeCollection attributes() const
Returns the attributes that are stored in the data block, along with their size.
Definition: qgspointcloudblock.cpp:47
QgsPointCloudIndex::nodeChildren
virtual QList< IndexedPointCloudNode > nodeChildren(const IndexedPointCloudNode &n) const
Returns all children of node.
Definition: qgspointcloudindex.cpp:172
QgsPointCloudLayerProfileResults::zRange
QgsDoubleRange zRange() const override
Returns the range of the retrieved elevation values.
Definition: qgspointcloudlayerprofilegenerator.cpp:117
QgsCoordinateTransform::transformBoundingBox
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
Definition: qgscoordinatetransform.cpp:560
QgsPointCloudAttributeCollection::at
const QgsPointCloudAttribute & at(int index) const
Returns the attribute at the specified index.
Definition: qgspointcloudattribute.h:170
QgsPointCloudLayerProfileGenerator
Implementation of QgsAbstractProfileGenerator for point cloud layers.
Definition: qgspointcloudlayerprofilegenerator.h:131
QgsAbstractProfileGenerator
Abstract base class for objects which generate elevation profiles.
Definition: qgsabstractprofilegenerator.h:392
QgsProject::transformContext
QgsCoordinateTransformContext transformContext
Definition: qgsproject.h:110
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:67
QgsProfileRenderContext
Abstract base class for storage of elevation profiles.
Definition: qgsabstractprofilegenerator.h:40
QgsPointCloudLayerProfileResults::respectLayerColors
bool respectLayerColors
Definition: qgspointcloudlayerprofilegenerator.h:89
QgsPointCloudLayerProfileResults::type
QString type() const override
Returns the unique string identifier for the results type.
Definition: qgspointcloudlayerprofilegenerator.cpp:77
QgsPointCloudBlock
Base class for storing raw data from point cloud nodes.
Definition: qgspointcloudblock.h:38
QgsGeos::buffer
QgsAbstractGeometry * buffer(double distance, int segments, QString *errorMsg=nullptr) const override
Definition: qgsgeos.cpp:1802
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
Qgis::ProfileGeneratorFlag::RespectsMaximumErrorMapUnit
@ RespectsMaximumErrorMapUnit
Generated profile respects the QgsProfileGenerationContext::maximumErrorMapUnits() property.
QgsPointCloudIndex::isValid
virtual bool isValid() const =0
Returns whether index is loaded and valid.
QgsPointCloudLayerProfileResults::~QgsPointCloudLayerProfileResults
~QgsPointCloudLayerProfileResults() override
Definition: qgspointcloudlayerprofilegenerator.cpp:43
QgsProfileSnapContext
Encapsulates the context of snapping a profile point.
Definition: qgsprofilesnapping.h:30
QgsProfileIdentifyContext::maximumPointDistanceDelta
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when identifying a point.
Definition: qgsabstractprofilegenerator.h:136
QgsProfileGenerationContext::elevationRange
QgsDoubleRange elevationRange() const
Returns the range of elevations to include in the generation.
Definition: qgsabstractprofilegenerator.h:325
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsPointCloudIndex::accessType
virtual AccessType accessType() const =0
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
QgsPointCloudLayerProfileGenerator::generateProfile
bool generateProfile(const QgsProfileGenerationContext &context=QgsProfileGenerationContext()) override
Generate the profile (based on data stored in the class).
Definition: qgspointcloudlayerprofilegenerator.cpp:343
QgsProfilePoint
Encapsulates a point on a distance-elevation profile.
Definition: qgsprofilepoint.h:30
QgsPointCloudBlock::pointCount
int pointCount() const
Returns number of points that are stored in the block.
Definition: qgspointcloudblock.cpp:42
QgsPointCloudLayerProfileResults::finalize
void finalize(QgsFeedback *feedback)
Finalizes results – should be called after last point is added.
Definition: qgspointcloudlayerprofilegenerator.cpp:49
QgsPointCloudRequest
Point cloud data request.
Definition: qgspointcloudrequest.h:39
QgsPointCloudLayerProfileResults::opacityByDistanceEffect
bool opacityByDistanceEffect
Definition: qgspointcloudlayerprofilegenerator.h:91
QgsPointCloudLayerProfileResults::results
std::vector< PointResult > results
Definition: qgspointcloudlayerprofilegenerator.h:80
QgsProfileGenerationContext
Encapsulates the context in which an elevation profile is to be generated.
Definition: qgsabstractprofilegenerator.h:262
geos::unique_ptr
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Definition: qgsgeos.h:79
QgsProfileIdentifyResults
Stores identify results generated by a QgsAbstractProfileResults object.
Definition: qgsabstractprofilegenerator.h:158
IndexedPointCloudNode
Represents a indexed point cloud node in octree.
Definition: qgspointcloudindex.h:57
QgsPointCloudLayerProfileGenerator::QgsPointCloudLayerProfileGenerator
QgsPointCloudLayerProfileGenerator(QgsPointCloudLayer *layer, const QgsProfileRequest &request)
Constructor for QgsPointCloudLayerProfileGenerator.
Definition: qgspointcloudlayerprofilegenerator.cpp:302
QgsProfileRenderContext::renderContext
QgsRenderContext & renderContext()
Returns a reference to the component QgsRenderContext.
Definition: qgsabstractprofilegenerator.h:52
QgsCsException
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
QgsRange::lower
T lower() const
Returns the lower bound of the range.
Definition: qgsrange.h:66
qgsprofilesnapping.h
QgsCoordinateTransform::isShortCircuited
bool isShortCircuited() const
Returns true if the transform short circuits because the source and destination are equivalent.
Definition: qgscoordinatetransform.cpp:905
qgsprofilepoint.h
qgspointcloudlayer.h
QgsPointCloudAttribute::Int32
@ Int32
Int32 4 bytes.
Definition: qgspointcloudattribute.h:50
QgsPointCloudAttributeCollection::pointRecordSize
int pointRecordSize() const
Returns total size of record.
Definition: qgspointcloudattribute.h:187
QgsPointCloudLayerProfileGenerator::feedback
QgsFeedback * feedback() const override
Access to feedback object of the generator (may be nullptr)
Definition: qgspointcloudlayerprofilegenerator.cpp:521
QgsCoordinateTransform::setBallparkTransformsAreAppropriate
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
Definition: qgscoordinatetransform.cpp:939
QgsProfileGenerationContext::convertDistanceToPixels
double convertDistanceToPixels(double size, QgsUnitTypes::RenderUnit unit) const
Converts a distance size from the specified units to pixels.
Definition: qgsabstractprofilegenerator.cpp:89
QgsFeedback
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
QgsRange::upper
T upper() const
Returns the upper bound of the range.
Definition: qgsrange.h:73
qgsprofilerequest.h
QgsPointCloudAttributeCollection
Collection of point cloud attributes.
Definition: qgspointcloudattribute.h:141
QgsProfileGenerationContext::distanceRange
QgsDoubleRange distanceRange() const
Returns the range of distances to include in the generation.
Definition: qgsabstractprofilegenerator.h:307
QgsGeos
Does vector analysis using the geos library and handles import, export, exception handling*.
Definition: qgsgeos.h:103
Qgis::PointCloudSymbol::Square
@ Square
Renders points as squares.
qgspointcloudlayerprofilegenerator.h
QgsPointCloudLayerProfileResults::asGeometries
QVector< QgsGeometry > asGeometries() const override
Returns a list of geometries representing the calculated elevation results.
Definition: qgspointcloudlayerprofilegenerator.cpp:105
QgsPointCloudBlockRequest::errorStr
QString errorStr()
Returns the error message string of the request.
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsProfileRequest
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
Definition: qgsprofilerequest.h:37
QgsPointCloudLayerProfileGenerator::flags
Qgis::ProfileGeneratorFlags flags() const override
Returns flags which reflect how the profile generator operates.
Definition: qgspointcloudlayerprofilegenerator.cpp:336
qgscoordinatetransform.h
QgsPointCloudIndex::root
IndexedPointCloudNode root()
Returns root node of the index.
Definition: qgspointcloudindex.h:227
QgsProfileSnapResult::snappedPoint
QgsProfilePoint snappedPoint
Snapped point.
Definition: qgsprofilesnapping.h:61
QgsPointCloudAttribute
Attribute for point cloud data pair of name and size in bytes.
Definition: qgspointcloudattribute.h:40
QgsProfilePoint::distance
double distance() const SIP_HOLDGIL
Returns the distance of the point.
Definition: qgsprofilepoint.h:88
QgsScopedQPainterState
Scoped object for saving and restoring a QPainter object's state.
Definition: qgsrendercontext.h:1336
QgsPointCloudLayerProfileResults::pointSize
double pointSize
Definition: qgspointcloudlayerprofilegenerator.h:86
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsProfileGenerationContext::mapUnitsPerDistancePixel
double mapUnitsPerDistancePixel() const
Returns the number of map units per pixel in the distance dimension.
Definition: qgsabstractprofilegenerator.h:291
QgsPointCloudLayerProfileResults::QgsPointCloudLayerProfileResults
QgsPointCloudLayerProfileResults()
Definition: qgspointcloudlayerprofilegenerator.cpp:38
QgsPointCloudLayerProfileResults::distanceToHeightMap
QMap< double, double > distanceToHeightMap() const override
Returns the map of distance (chainage) to height.
Definition: qgspointcloudlayerprofilegenerator.cpp:82
Qgis::PointCloudSymbol::Circle
@ Circle
Renders points as circles.
QgsPointCloudLayerProfileResults::snapPoint
QgsProfileSnapResult snapPoint(const QgsProfilePoint &point, const QgsProfileSnapContext &context) override
Snaps a point to the generated elevation profile.
Definition: qgspointcloudlayerprofilegenerator.cpp:191
QgsGeos::getGEOSHandler
static GEOSContextHandle_t getGEOSHandler()
Definition: qgsgeos.cpp:3369
QgsPointCloudLayerProfileResults::identify
QVector< QgsProfileIdentifyResults > identify(const QgsProfilePoint &point, const QgsProfileIdentifyContext &context) override
Identify results visible at the specified profile point.
Definition: qgspointcloudlayerprofilegenerator.cpp:240
QgsDoubleRange::isInfinite
bool isInfinite() const
Returns true if the range consists of all possible values.
Definition: qgsrange.h:247
QgsPointCloudAttributeCollection::indexOf
int indexOf(const QString &name) const
Returns the index of the attribute with the specified name.
Definition: qgspointcloudattribute.cpp:181
QgsProfileIdentifyContext::project
QgsProject * project
Associated project.
Definition: qgsabstractprofilegenerator.h:145
QgsRenderContext::convertToPainterUnits
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
Definition: qgsrendercontext.cpp:367
QgsPointCloudLayerProfileGenerator::~QgsPointCloudLayerProfileGenerator
~QgsPointCloudLayerProfileGenerator() override
QgsPointCloudIndex::asyncNodeData
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
QgsDoubleRange
QgsRange which stores a range of double values.
Definition: qgsrange.h:202
QgsPointCloudLayerProfileResults::pointSizeUnit
QgsUnitTypes::RenderUnit pointSizeUnit
Definition: qgspointcloudlayerprofilegenerator.h:87
Qgis::ProfileGeneratorFlag::RespectsDistanceRange
@ RespectsDistanceRange
Generated profile respects the QgsProfileGenerationContext::distanceRange() property.
QgsPointSequence
QVector< QgsPoint > QgsPointSequence
Definition: qgsabstractgeometry.h:52
qgscurve.h
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsPointCloudBlockRequest
Base class for handling loading QgsPointCloudBlock asynchronously.
Definition: qgspointcloudblockrequest.h:36
QgsRectangle::width
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
qgsmarkersymbol.h
QgsPointCloudBlock::offset
QgsVector3D offset() const
Returns the custom offset of the block.
Definition: qgspointcloudblock.cpp:57
QgsPointCloudRequest::setAttributes
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
Definition: qgspointcloudrequest.cpp:29
QgsGeometry::fromRect
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
Definition: qgsgeometry.cpp:241
QgsProfileRenderContext::worldTransform
const QTransform & worldTransform() const
Returns the transform from world coordinates to painter coordinates.
Definition: qgsabstractprofilegenerator.cpp:27
_GEOSQueryCallbackData::list
QList< const QgsPointCloudLayerProfileResults::PointResult * > * list
Definition: qgspointcloudlayerprofilegenerator.cpp:184
QgsPointCloudLayerProfileResults::maxZ
double maxZ
Definition: qgspointcloudlayerprofilegenerator.h:84
QgsProfileSnapContext::maximumPointDistanceDelta
double maximumPointDistanceDelta
Maximum allowed snapping delta for the distance values when snapping to a point.
Definition: qgsprofilesnapping.h:54
QgsGeos::lineLocatePoint
double lineLocatePoint(const QgsPoint &point, QString *errorMsg=nullptr) const
Returns a distance representing the location along this linestring of the closest point on this lines...
Definition: qgsgeos.cpp:2733
QgsPointCloudBlockRequest::finished
void finished()
Emitted when the request processing has finished.
QgsPointCloudIndex::span
int span() const
Returns the number of points in one direction in a single node.
Definition: qgspointcloudindex.cpp:247
QgsPointCloudLayerProfileResults::PointResult::z
double z
Definition: qgspointcloudlayerprofilegenerator.h:69
qgsterrainprovider.h
QgsRange::contains
bool contains(const QgsRange< T > &other) const
Returns true if this range contains another range.
Definition: qgsrange.h:108
QgsProfileRenderContext::elevationRange
QgsDoubleRange elevationRange() const
Returns the range of elevations to include in the render.
Definition: qgsabstractprofilegenerator.cpp:47
QgsAbstractProfileResults
Abstract base class for storage of elevation profiles.
Definition: qgsabstractprofilegenerator.h:193
QgsPointCloudLayerProfileResults::PointResult::color
QRgb color
Definition: qgspointcloudlayerprofilegenerator.h:72
qgspointcloudlayerelevationproperties.h
QgsPointCloudIndex
Represents a indexed point clouds data in octree.
Definition: qgspointcloudindex.h:163
IndexedPointCloudNode::toString
QString toString() const
Encode node to string.
Definition: qgspointcloudindex.cpp:58
QgsRenderContext::painter
QPainter * painter()
Returns the destination QPainter for the render operation.
Definition: qgsrendercontext.h:112
QgsPointCloudAttributeCollection::push_back
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
Definition: qgspointcloudattribute.cpp:142
QgsPointCloudLayerProfileResults::PointResult::distanceAlongCurve
double distanceAlongCurve
Definition: qgspointcloudlayerprofilegenerator.h:70
qgspointcloudrequest.h
QgsCoordinateTransform
Class for doing transforms between two map coordinate systems.
Definition: qgscoordinatetransform.h:57
qgspointcloudrenderer.h
QgsPointCloudLayerProfileResults::renderResults
void renderResults(QgsProfileRenderContext &context) override
Renders the results to the specified context.
Definition: qgspointcloudlayerprofilegenerator.cpp:122
QgsPointCloudAttribute::getPointXYZ
static void getPointXYZ(const char *ptr, int i, std::size_t pointRecordSize, int xOffset, QgsPointCloudAttribute::DataType xType, int yOffset, QgsPointCloudAttribute::DataType yType, int zOffset, QgsPointCloudAttribute::DataType zType, const QgsVector3D &indexScale, const QgsVector3D &indexOffset, double &x, double &y, double &z)
Retrieves the x, y, z values for the point at index i.
Definition: qgspointcloudattribute.cpp:255
QgsPointCloudIndex::nodeZRange
QgsDoubleRange nodeZRange(const IndexedPointCloudNode &node) const
Returns the z range of a node.
Definition: qgspointcloudindex.cpp:221
QgsPointCloudLayerProfileGenerator::sourceId
QString sourceId() const override
Returns a unique identifier representing the source of the profile.
Definition: qgspointcloudlayerprofilegenerator.cpp:331
QgsPointCloudLayerProfileResults::PointResult::x
double x
Definition: qgspointcloudlayerprofilegenerator.h:67
QgsPointCloudLayerProfileResults::tolerance
double tolerance
Definition: qgspointcloudlayerprofilegenerator.h:81
QgsUnitTypes::RenderMapUnits
@ RenderMapUnits
Map units.
Definition: qgsunittypes.h:170
QgsGeos::prepareGeometry
void prepareGeometry() override
Prepares the geometry, so that subsequent calls to spatial relation methods are much faster.
Definition: qgsgeos.cpp:213
QgsPointCloudLayerProfileResults::sampledPoints
QgsPointSequence sampledPoints() const override
Returns a list of sampled points, with their calculated elevation as the point z value.
Definition: qgspointcloudlayerprofilegenerator.cpp:93
qgsgeos.h
QgsPointCloudBlock::scale
QgsVector3D scale() const
Returns the custom scale of the block.
Definition: qgspointcloudblock.cpp:52
QgsPointCloudAttribute::type
DataType type() const
Returns the data type.
Definition: qgspointcloudattribute.h:74
QgsPointCloudLayerProfileGenerator::takeResults
QgsAbstractProfileResults * takeResults() override
Takes results from the generator.
Definition: qgspointcloudlayerprofilegenerator.cpp:516
QgsProfilePoint::elevation
double elevation() const SIP_HOLDGIL
Returns the elevation of the point.
Definition: qgsprofilepoint.h:98
qgslinesymbol.h
qgsmessagelog.h
QgsProfileSnapContext::displayRatioElevationVsDistance
double displayRatioElevationVsDistance
Display ratio of elevation vs distance units.
Definition: qgsprofilesnapping.h:60
QgsPointCloudLayerProfileResults::PointResult::distanceFromCurve
double distanceFromCurve
Definition: qgspointcloudlayerprofilegenerator.h:71