18 #include <QElapsedTimer>
41 , mLayerAttributes( layer->attributes() )
59 mZOffset = elevationProps->zOffset();
60 mZScale = elevationProps->zScale();
80 if ( !mClippingRegions.empty() )
82 bool needsPainterClipPath =
false;
84 if ( needsPainterClipPath )
88 if ( mRenderer->type() == QLatin1String(
"extent" ) )
91 mRenderer->startRender( context );
93 mRenderer->stopRender( context );
110 mBlockRenderUpdates =
true;
111 mElapsedTimer.start();
114 mRenderer->startRender( context );
120 QSet< QString > rendererAttributes = mRenderer->usedAttributes( context );
123 rendererAttributes.insert( QStringLiteral(
"Z" ) );
125 for (
const QString &attribute : std::as_const( rendererAttributes ) )
127 if ( mAttributes.
indexOf( attribute ) >= 0 )
130 const int layerIndex = mLayerAttributes.
indexOf( attribute );
131 if ( layerIndex < 0 )
133 QgsMessageLog::logMessage( QObject::tr(
"Required attribute %1 not found in layer" ).arg( attribute ), QObject::tr(
"Point Cloud" ) );
137 mAttributes.
push_back( mLayerAttributes.
at( layerIndex ) );
163 QgsDebugMsg( QStringLiteral(
"Could not transform node extent to map CRS" ) );
164 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
169 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
172 const double rootErrorInMapCoordinates = rootNodeExtentMapCoords.
width() / pc->
span();
175 if ( ( rootErrorInMapCoordinates < 0.0 ) || ( mapUnitsPerPixel < 0.0 ) || ( maximumError < 0.0 ) )
177 QgsDebugMsg( QStringLiteral(
"invalid screen error" ) );
181 double rootErrorPixels = rootErrorInMapCoordinates / mapUnitsPerPixel;
182 const QVector<IndexedPointCloudNode> nodes = traverseTree( pc, context.
renderContext(), pc->
root(), maximumError, rootErrorPixels );
189 bool canceled =
false;
191 if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Local )
193 nodesDrawn += renderNodesSync( nodes, pc, context, request, canceled );
195 else if ( pc->
accessType() == QgsPointCloudIndex::AccessType::Remote )
197 nodesDrawn += renderNodesAsync( nodes, pc, context, request, canceled );
201 QgsDebugMsgLevel( QStringLiteral(
"totals: %1 nodes | %2 points | %3ms" ).arg( nodesDrawn )
203 .arg( t.elapsed() ), 2 );
208 mRenderer->stopRender( context );
225 std::unique_ptr<QgsPointCloudBlock> block( pc->
nodeData( n, request ) );
238 mRenderer->renderBlock( block.get(), context );
260 QElapsedTimer downloadTimer;
261 downloadTimer.start();
267 const int groupSize = 4;
268 for (
int groupIndex = 0; groupIndex < nodes.size(); groupIndex += groupSize )
273 const int currentGroupSize = std::min< size_t >( std::max< size_t >( nodes.size() - groupIndex, 0 ), groupSize );
274 QVector<QgsPointCloudBlockRequest *> blockRequests( currentGroupSize,
nullptr );
275 QVector<bool> finishedLoadingBlock( currentGroupSize,
false );
280 for (
int i = 0; i < blockRequests.size(); ++i )
282 int nodeIndex = groupIndex + i;
286 blockRequests[ i ] = blockRequest;
289 if ( !blockRequest->
block() )
291 QgsDebugMsg( QStringLiteral(
"Unable to load node %1, error: %2" ).arg( nStr, blockRequest->errorStr() ) );
293 finishedLoadingBlock[ i ] =
true;
295 if ( !finishedLoadingBlock.contains(
false ) ) loop.exit();
301 QgsDebugMsg( QStringLiteral(
"Downloaded in : %1ms" ).arg( downloadTimer.elapsed() ) );
305 for (
int i = 0; i < blockRequests.size(); ++i )
314 if ( !blockRequests[ i ]->block() )
320 context.
setScale( blockRequests[ i ]->block()->scale() );
321 context.
setOffset( blockRequests[ i ]->block()->offset() );
323 context.
setAttributes( blockRequests[ i ]->block()->attributes() );
325 mRenderer->renderBlock( blockRequests[ i ]->block(), context );
342 for (
int i = 0; i < blockRequests.size(); ++i )
344 if ( blockRequests[ i ] )
346 if ( blockRequests[ i ]->block() )
347 delete blockRequests[ i ]->block();
348 blockRequests[ i ]->deleteLater();
360 return mRenderer ? mRenderer->type() != QLatin1String(
"extent" ) :
false;
365 mRenderTimeHint = time;
368 QVector<IndexedPointCloudNode> QgsPointCloudLayerRenderer::traverseTree(
const QgsPointCloudIndex *pc,
371 double maxErrorPixels,
372 double nodeErrorPixels )
374 QVector<IndexedPointCloudNode> nodes;
392 double childrenErrorPixels = nodeErrorPixels / 2.0;
393 if ( childrenErrorPixels < maxErrorPixels )
396 const QList<IndexedPointCloudNode> children = pc->
nodeChildren( n );
399 nodes += traverseTree( pc, context, nn, maxErrorPixels, childrenErrorPixels );
Represents a indexed point cloud node in octree.
QString toString() const
Encode node to string.
Custom exception class for Coordinate Reference System related exceptions.
QgsRange which stores a range of double values.
bool isInfinite() const
Returns true if the range consists of all possible values.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
void canceled()
Internal routines can connect to this signal if they use event loop.
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
static QList< QgsMapClippingRegion > collectClippingRegionsForLayer(const QgsRenderContext &context, const QgsMapLayer *layer)
Collects the list of map clipping regions from a context which apply to a map layer.
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > ®ions, const QgsRenderContext &context, QgsMapLayerType layerType, bool &shouldClip)
Returns a QPainterPath representing the intersection of clipping regions from context which should be...
Base class for utility classes that encapsulate information necessary for rendering of map layers.
bool mReadyToCompose
The flag must be set to false in renderer's constructor if wants to use the smarter map redraws funct...
static constexpr int MAX_TIME_TO_USE_CACHED_PREVIEW_IMAGE
Maximum time (in ms) to allow display of a previously cached preview image while rendering layers,...
QgsRenderContext * renderContext()
Returns the render context associated with the renderer.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
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).
void push_back(const QgsPointCloudAttribute &attribute)
Adds extra attribute.
const QgsPointCloudAttribute & at(int index) const
Returns the attribute at the specified index.
int indexOf(const QString &name) const
Returns the index of the attribute with the specified name.
Attribute for point cloud data pair of name and size in bytes.
Base class for handling loading QgsPointCloudBlock asynchronously.
QgsPointCloudBlock * block()
Returns the requested block.
void finished()
Emitted when the request processing has finished.
Represents packaged data bounds.
virtual QgsPointCloudIndex * index() const
Returns the point cloud index associated with the provider.
virtual QgsGeometry polygonBounds() const
Returns the polygon bounds of the layer.
A renderer for 2d visualisation of point clouds which shows the dataset's extents using a fill symbol...
Represents a indexed point clouds data in octree.
int span() const
Returns the number of points in one direction in a single node.
QgsRectangle nodeMapExtent(const IndexedPointCloudNode &node) const
Returns the extent of a node in map coordinates.
virtual QList< IndexedPointCloudNode > nodeChildren(const IndexedPointCloudNode &n) const
Returns all children of node.
QgsVector3D offset() const
Returns offset.
QgsVector3D scale() const
Returns scale.
virtual QgsPointCloudBlock * nodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns node data block.
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...
virtual bool isValid() const =0
Returns whether index is loaded and valid.
IndexedPointCloudNode root()
Returns root node of the index.
QgsDoubleRange nodeZRange(const IndexedPointCloudNode &node) const
Returns the z range of a node.
virtual QgsPointCloudBlockRequest * asyncNodeData(const IndexedPointCloudNode &n, const QgsPointCloudRequest &request)=0
Returns a handle responsible for loading a node data block.
Point cloud layer specific subclass of QgsMapLayerElevationProperties.
~QgsPointCloudLayerRenderer()
bool forceRasterRender() const override
Returns true if the renderer must be rendered to a raster paint device (e.g.
QgsPointCloudLayerRenderer(QgsPointCloudLayer *layer, QgsRenderContext &context)
Ctor.
void setLayerRenderingTimeHint(int time) override
Sets approximate render time (in ms) for the layer to render.
bool render() override
Do the rendering (based on data stored in the class).
Represents a map layer supporting display of point clouds.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
QgsPointCloudRenderer * renderer()
Returns the 2D renderer for the point cloud.
QgsPointCloudDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Encapsulates the render context for a 2D point cloud rendering operation.
QgsVector3D offset() const
Returns the offset of the layer's int32 coordinates compared to CRS coords.
long pointsRendered() const
Returns the total number of points rendered.
void setOffset(const QgsVector3D &offset)
Sets the offset of the layer's int32 coordinates compared to CRS coords.
void setScale(const QgsVector3D &scale)
Sets the scale of the layer's int32 coordinates compared to CRS coords.
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering.
QgsVector3D scale() const
Returns the scale of the layer's int32 coordinates compared to CRS coords.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Sets the attributes associated with the rendered block.
virtual QgsPointCloudRenderer * clone() const =0
Create a deep copy of this renderer.
Point cloud data request.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Set attributes filter in the request.
bool overlaps(const QgsRange< T > &other) const
Returns true if this range overlaps another range.
T lower() const
Returns the lower bound of the range.
T upper() const
Returns the upper bound of the range.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle intersects with other rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
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).
QgsDoubleRange zRange() const
Returns the range of z-values which should be rendered.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
Scoped object for saving and restoring a QPainter object's state.
@ VectorTileLayer
Added in 3.14.
#define QgsDebugMsgLevel(str, level)