22#include "delaunator.hpp"
43#include "qgsvirtualpointcloudprovider.h"
45#include <QElapsedTimer>
49using namespace Qt::StringLiterals;
53 , mLayerName( layer->name() )
54 , mLayerAttributes( layer->attributes() )
55 , mSubIndexes( layer->subIndexes() )
57 , mEnableProfile( context.
flags() &
Qgis::RenderContextFlag::RecordProfile )
62 mIndex = layer->
index();
68 if ( !mSubIndexes.isEmpty() )
70 mSubIndexExtentRenderer = std::make_unique<QgsPointCloudExtentRenderer>();
71 mSubIndexExtentRenderer->setShowLabels( mRenderer->showLabels() );
72 mSubIndexExtentRenderer->setLabelTextFormat( mRenderer->labelTextFormat() );
77 mScale = mIndex.scale();
78 mOffset = mIndex.offset();
83 mZOffset = elevationProps->zOffset();
84 mZScale = elevationProps->zScale();
87 if (
const QgsVirtualPointCloudProvider *vpcProvider =
dynamic_cast<QgsVirtualPointCloudProvider *
>( layer->
dataProvider() ) )
90 mAverageSubIndexWidth = vpcProvider->averageSubIndexWidth();
91 mAverageSubIndexHeight = vpcProvider->averageSubIndexHeight();
92 mOverviewIndexes = vpcProvider->overviews();
101 mPreparationTime = timer.elapsed();
108 std::unique_ptr< QgsScopedRuntimeProfile > profile;
109 if ( mEnableProfile )
111 profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, u
"rendering"_s,
layerId() );
112 if ( mPreparationTime > 0 )
116 std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
117 if ( mEnableProfile )
119 preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Preparing render" ), u
"rendering"_s );
130 if ( !mClippingRegions.empty() )
132 bool needsPainterClipPath =
false;
134 if ( needsPainterClipPath )
138 double topoLat = 0.0, topoLon = 0.0;
139 if (
renderContext()->coordinateTransform().destinationCrs().topocentricOrigin( topoLat, topoLon ) )
144 const double a = ellipsoidParams.
semiMajor;
145 const double b = ellipsoidParams.
semiMinor;
146 const double latRad = topoLat * M_PI / 180.0;
148 const double beta = std::atan2( b * std::sin( latRad ), a * std::cos( latRad ) );
149 const double xa = a * std::cos( beta );
150 const double zb = b * std::sin( beta );
151 const double originRadius = std::sqrt( xa * xa + zb * zb );
153 mMapCrsZFilter =
QgsDoubleRange( -originRadius, std::numeric_limits< double >::max() );
157 if ( mRenderer->type() ==
"extent"_L1 )
160 mRenderer->startRender( context );
162 mRenderer->stopRender( context );
167 if ( mSubIndexes.isEmpty() && ( !mIndex || !mIndex.isValid() ) )
177 mBlockRenderUpdates =
true;
178 mElapsedTimer.start();
182 if ( elevationShadingRenderer.
isActive() )
184 auto elevationMap = std::make_unique<QgsElevationMap>(
renderContext()->deviceOutputSize(),
renderContext()->devicePixelRatio() );
188 mRenderer->startRender( context );
197 || !mMapCrsZFilter.isInfinite() )
201 QSet< QString > rendererAttributes = mRenderer->usedAttributes( context );
204 for (
const QString &attribute : std::as_const( rendererAttributes ) )
206 if ( mAttributes.indexOf( attribute ) >= 0 )
209 const int layerIndex = mLayerAttributes.indexOf( attribute );
210 if ( layerIndex < 0 )
212 QgsMessageLog::logMessage( QObject::tr(
"Required attribute %1 not found in layer" ).arg( attribute ), QObject::tr(
"Point Cloud" ) );
216 mAttributes.push_back( mLayerAttributes.at( layerIndex ) );
229 preparingProfile.reset();
230 std::unique_ptr< QgsScopedRuntimeProfile > renderingProfile;
231 if ( mEnableProfile )
233 renderingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering" ), u
"rendering"_s );
236 bool canceled =
false;
237 if ( mSubIndexes.isEmpty() )
239 canceled = !renderIndex( mIndex );
243 QVector< QgsPointCloudSubIndex > visibleIndexes;
244 for (
const QgsPointCloudSubIndex &si : mSubIndexes )
248 visibleIndexes.append( si );
252 const double overviewSwitchingScale = mRenderer->overviewSwitchingScale();
253 const bool zoomedOut = renderExtent.
width() > mAverageSubIndexWidth * overviewSwitchingScale || renderExtent.
height() > mAverageSubIndexHeight * overviewSwitchingScale;
255 bool shouldRenderOverviews =
false, shouldRenderExtents =
false;
256 switch ( mRenderer->zoomOutBehavior() )
259 shouldRenderOverviews =
true;
260 shouldRenderExtents =
false;
263 shouldRenderOverviews =
true;
264 shouldRenderExtents =
true;
267 shouldRenderOverviews =
false;
268 shouldRenderExtents =
true;
272 if ( zoomedOut && shouldRenderOverviews )
276 if ( ovIdx.isValid() && renderExtent.
intersects( ovIdx.extent() ) )
277 renderIndex( ovIdx );
281 mSubIndexExtentRenderer->startRender( context );
282 for (
const QgsPointCloudSubIndex &si : visibleIndexes )
289 if ( ( zoomedOut && shouldRenderExtents ) || ( !zoomedOut && ( !pc || !pc.
isValid() ) ) )
291 mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context );
292 if ( mSubIndexExtentRenderer->showLabels() )
301 QgsDebugError( u
"Could not reproject virtual point cloud sub index extent to map crs"_s );
307 if ( pc && pc.
isValid() && !zoomedOut )
309 canceled = !renderIndex( pc );
312 mSubIndexExtentRenderer->stopRender( context );
315 if ( elevationShadingRenderer.
isActive() )
317 QImage *img =
dynamic_cast< QImage *
>( painter->device() );
322 mRenderer->elevationShadingRenderer().renderShading( *elevationMap, *img, *
renderContext() );
326 mRenderer->stopRender( context );
334 context.setMapCrsZFilter( mMapCrsZFilter );
343 const double maximumError = context.renderContext().convertToPainterUnits( mRenderer->maximumScreenError(), mRenderer->maximumScreenErrorUnit() );
348 if ( !context.renderContext().coordinateTransform().isShortCircuited() )
356 catch ( QgsCsException & )
358 QgsDebugError( u
"Could not transform node extent to map CRS"_s );
359 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
364 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
367 const double rootErrorInMapCoordinates = rootNodeExtentMapCoords.
width() / pc.
span();
369 double mapUnitsPerPixel = context.renderContext().mapToPixel().mapUnitsPerPixel();
370 if ( ( rootErrorInMapCoordinates < 0.0 ) || ( mapUnitsPerPixel < 0.0 ) || ( maximumError < 0.0 ) )
375 double rootErrorPixels = rootErrorInMapCoordinates / mapUnitsPerPixel;
376 const QVector<QgsPointCloudNodeId> nodes = traverseTree( pc, context.renderContext(), pc.
root(), maximumError, rootErrorPixels );
378 QgsPointCloudRequest request;
383 bool canceled =
false;
386 if ( mRenderer->renderAsTriangles() )
398 nodesDrawn += renderNodesSorted( nodes, pc, context, request, canceled, mRenderer->drawOrder2d() );
407 nodesDrawn += renderNodesSync( nodes, pc, context, request, canceled );
412 nodesDrawn += renderNodesAsync( nodes, pc, context, request, canceled );
420 QgsDebugMsgLevel( u
"totals: %1 nodes | %2 points | %3ms"_s.arg( nodesDrawn ).arg( context.pointsRendered() ).arg( t.elapsed() ), 2 );
439 for ( QgsPointCloudNodeId n : nodes )
447 std::unique_ptr<QgsPointCloudBlock> block( pc.
nodeData( n, request ) );
452 QgsVector3D contextScale = context.
scale();
453 QgsVector3D contextOffset = context.
offset();
460 mRenderer->renderBlock( block.get(), context );
476 if ( mRenderer->renderAsTriangles() )
480 renderTriangulatedSurface( context );
488 if ( nodes.isEmpty() )
505 QVector<QgsPointCloudBlockRequest *> blockRequests;
510 for (
int i = 0; i < nodes.size(); ++i )
512 QgsPointCloudNodeId n = nodes[i];
514 QgsPointCloudBlockRequest *blockRequest = pc.
asyncNodeData( n, request );
515 blockRequests.append( blockRequest );
516 QObject::connect( blockRequest, &
QgsPointCloudBlockRequest::finished, &loop, [
this, &canceled, &nodesDrawn, &loop, &blockRequests, &context, nStr, blockRequest]() {
517 blockRequests.removeOne( blockRequest );
520 if ( blockRequests.isEmpty() )
523 std::unique_ptr<QgsPointCloudBlock> block( blockRequest->
takeBlock() );
525 blockRequest->deleteLater();
539 QgsVector3D contextScale = context.
scale();
540 QgsVector3D contextOffset = context.
offset();
546 mRenderer->renderBlock( block.get(), context );
564 if ( !blockRequests.isEmpty() )
569 for ( QgsPointCloudBlockRequest *blockRequest : std::as_const( blockRequests ) )
571 std::unique_ptr<QgsPointCloudBlock> block = blockRequest->
takeBlock();
574 blockRequest->deleteLater();
577 if ( mRenderer->renderAsTriangles() )
581 renderTriangulatedSurface( context );
587int QgsPointCloudLayerRenderer::renderNodesSorted(
594 QgsVector3D blockScale;
595 QgsVector3D blockOffset;
596 QgsPointCloudAttributeCollection blockAttributes;
600 QByteArray allByteArrays;
602 QVector<QPair<int, double>> allPairs;
604 for ( QgsPointCloudNodeId n : nodes )
612 std::unique_ptr<QgsPointCloudBlock> block( pc.
nodeData( n, request ) );
619 QgsVector3D offsetDifference = QgsVector3D( 0, 0, 0 );
620 if ( blockCount == 0 )
622 blockScale = block->scale();
623 blockOffset = block->offset();
624 blockAttributes = block->attributes();
628 offsetDifference = blockOffset - block->offset();
631 const char *ptr = block->data();
639 for (
int i = 0; i < block->pointCount(); ++i )
641 allByteArrays.append( ptr + i * recordSize, recordSize );
644 if ( offsetDifference.
x() != 0 )
646 qint32 ix = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
xOffset() );
647 ix -= std::lround( offsetDifference.
x() / context.
scale().
x() );
648 const char *xPtr =
reinterpret_cast< const char *
>( &ix );
649 allByteArrays.replace( pointCount * recordSize + context.
xOffset(), 4, QByteArray( xPtr, 4 ) );
651 if ( offsetDifference.
y() != 0 )
653 qint32 iy = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
yOffset() );
654 iy -= std::lround( offsetDifference.
y() / context.
scale().
y() );
655 const char *yPtr =
reinterpret_cast< const char *
>( &iy );
656 allByteArrays.replace( pointCount * recordSize + context.
yOffset(), 4, QByteArray( yPtr, 4 ) );
659 qint32 iz = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
zOffset() );
660 if ( offsetDifference.
z() != 0 )
662 iz -= std::lround( offsetDifference.
z() / context.
scale().
z() );
663 const char *zPtr =
reinterpret_cast< const char *
>( &iz );
664 allByteArrays.replace( pointCount * recordSize + context.
zOffset(), 4, QByteArray( zPtr, 4 ) );
666 allPairs.append( qMakePair( pointCount,
double( iz ) + block->offset().z() ) );
673 if ( pointCount == 0 )
679 std::sort( allPairs.begin(), allPairs.end(), []( QPair<int, double> a, QPair<int, double> b ) { return a.second < b.second; } );
682 std::sort( allPairs.begin(), allPairs.end(), []( QPair<int, double> a, QPair<int, double> b ) { return a.second > b.second; } );
689 QByteArray sortedByteArray;
690 sortedByteArray.reserve( allPairs.size() );
691 for ( QPair<int, double> pair : allPairs )
692 sortedByteArray.append( allByteArrays.mid( pair.first * recordSize, recordSize ) );
694 std::unique_ptr<QgsPointCloudBlock> bigBlock {
new QgsPointCloudBlock( pointCount, blockAttributes, sortedByteArray, blockScale, blockOffset ) };
696 QgsVector3D contextScale = context.
scale();
697 QgsVector3D contextOffset = context.
offset();
699 context.
setScale( bigBlock->scale() );
703 mRenderer->renderBlock( bigBlock.get(), context );
711inline bool isEdgeTooLong(
const QPointF &p1,
const QPointF &p2,
float length )
714 return p.x() * p.x() + p.y() * p.y() > length;
717static void renderTriangle( QImage &img, QPointF *pts, QRgb c0, QRgb c1, QRgb c2,
float horizontalFilter,
float *elev,
QgsElevationMap *elevationMap )
719 if ( horizontalFilter > 0 )
721 float filterThreshold2 = horizontalFilter * horizontalFilter;
726 QgsRectangle screenBBox = QgsMeshLayerUtils::triangleBoundingBox( pts[0], pts[1], pts[2] );
728 QSize outputSize = img.size();
730 int topLim = std::max(
int( screenBBox.
yMinimum() ), 0 );
731 int bottomLim = std::min(
int( screenBBox.
yMaximum() ), outputSize.height() - 1 );
732 int leftLim = std::max(
int( screenBBox.
xMinimum() ), 0 );
733 int rightLim = std::min(
int( screenBBox.
xMaximum() ), outputSize.width() - 1 );
735 int red0 = qRed( c0 ), green0 = qGreen( c0 ), blue0 = qBlue( c0 );
736 int red1 = qRed( c1 ), green1 = qGreen( c1 ), blue1 = qBlue( c1 );
737 int red2 = qRed( c2 ), green2 = qGreen( c2 ), blue2 = qBlue( c2 );
741 for (
int j = topLim; j <= bottomLim; j++ )
743 QRgb *scanLine = ( QRgb * ) img.scanLine( j );
744 QRgb *elevScanLine = elevData ? elevData +
static_cast<size_t>( outputSize.width() * j ) : nullptr;
745 for (
int k = leftLim; k <= rightLim; k++ )
748 double lam1, lam2, lam3;
749 if ( !QgsMeshLayerUtils::calculateBarycentricCoordinates( pts[0], pts[1], pts[2], pt, lam3, lam2, lam1 ) )
753 int r =
static_cast<int>( red0 * lam1 + red1 * lam2 + red2 * lam3 );
754 int g =
static_cast<int>( green0 * lam1 + green1 * lam2 + green2 * lam3 );
755 int b =
static_cast<int>( blue0 * lam1 + blue1 * lam2 + blue2 * lam3 );
756 scanLine[k] = qRgb( r, g, b );
761 float z =
static_cast<float>( elev[0] * lam1 + elev[1] * lam2 + elev[2] * lam3 );
770 const QgsPointCloudRenderContext::TriangulationData &triangulation = context.
triangulationData();
771 const std::vector<double> &points = triangulation.
points;
774 if ( points.size() < 3 )
780 std::unique_ptr<delaunator::Delaunator> delaunator;
783 delaunator = std::make_unique<delaunator::Delaunator>( points );
785 catch ( std::exception & )
792 float horizontalFilter = 0;
793 if ( mRenderer->horizontalTriangleFilter() )
795 horizontalFilter =
static_cast<float>(
renderContext()->
convertToPainterUnits( mRenderer->horizontalTriangleFilterThreshold(), mRenderer->horizontalTriangleFilterUnit() ) );
802 const std::vector<size_t> &triangleIndexes = delaunator->triangles;
806 float elev[3] { 0, 0, 0 };
807 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
809 size_t v0 = triangleIndexes[i], v1 = triangleIndexes[i + 1], v2 = triangleIndexes[i + 2];
810 triangle[0].rx() = points[v0 * 2];
811 triangle[0].ry() = points[v0 * 2 + 1];
812 triangle[1].rx() = points[v1 * 2];
813 triangle[1].ry() = points[v1 * 2 + 1];
814 triangle[2].rx() = points[v2 * 2];
815 triangle[2].ry() = points[v2 * 2 + 1];
824 QRgb c0 = triangulation.
colors[v0], c1 = triangulation.
colors[v1], c2 = triangulation.
colors[v2];
825 renderTriangle( img, triangle, c0, c1, c2, horizontalFilter, elev, elevationMap );
828 painter->drawImage( 0, 0, img );
836 if ( mRenderer->renderAsTriangles() )
846 return mRenderer ? mRenderer->type() !=
"extent"_L1 :
false;
851 mRenderTimeHint = time;
856 QVector<QgsPointCloudNodeId> nodes;
864 QgsPointCloudNode node = pc.
getNode( n );
865 QgsBox3D nodeExtent = node.
bounds();
870 const QgsDoubleRange nodeZRange( nodeExtent.
zMinimum(), nodeExtent.
zMaximum() );
871 const QgsDoubleRange adjustedNodeZRange = QgsDoubleRange( nodeZRange.lower() + mZOffset, nodeZRange.upper() + mZOffset );
878 double childrenErrorPixels = nodeErrorPixels / 2.0;
879 if ( childrenErrorPixels < maxErrorPixels )
882 for ( QgsPointCloudNodeId nn : node.
children() )
884 nodes += traverseTree( pc, context, nn, maxErrorPixels, childrenErrorPixels );
Provides global constants and enumerations for use throughout the application.
QFlags< MapLayerRendererFlag > MapLayerRendererFlags
Flags which control how map layer renderers behave.
PointCloudDrawOrder
Pointcloud rendering order for 2d views.
@ BottomToTop
Draw points with larger Z values last.
@ Default
Draw points in the order they are stored.
@ TopToBottom
Draw points with larger Z values first.
@ RenderOverviewAndExtents
Render point cloud extents over overview point cloud.
@ RenderExtents
Render only point cloud extents when zoomed out.
@ RenderOverview
Render overview point cloud when zoomed out.
@ VectorTile
Vector tile layer. Added in QGIS 3.14.
@ RenderPartialOutputOverPreviousCachedImage
When rendering temporary in-progress preview renders, these preview renders can be drawn over any pre...
@ RenderPartialOutputs
The renderer benefits from rendering temporary in-progress preview renders. These are temporary resul...
@ Local
Local means the source is a local file on the machine.
@ Remote
Remote means it's loaded through a protocol like HTTP.
@ Reverse
Reverse/inverse transform (from destination to source).
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
double zMaximum() const
Returns the maximum z value.
QgsRectangle toRectangle() const
Converts the box to a 2D rectangle.
double zMinimum() const
Returns the minimum z value.
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.
Stores a digital elevation model in a raster image which may get updated as a part of the map layer r...
static QRgb encodeElevation(float z)
Converts elevation value to an actual color.
QRgb * rawElevationImageData()
Returns pointer to the actual elevation image data.
Renders elevation shading on an image with different methods (eye dome lighting, hillshading,...
bool isActive() const
Returns whether this shading renderer is active.
static EllipsoidParameters ellipsoidParameters(const QString &ellipsoid)
Returns the parameters for the specified ellipsoid.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
Tells whether the operation has been canceled already.
void canceled()
Internal routines can connect to this signal if they use event loop.
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > ®ions, const QgsRenderContext &context, Qgis::LayerType layerType, bool &shouldClip)
Returns a QPainterPath representing the intersection of clipping regions from context which should be...
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.
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,...
QString layerId() const
Gets access to the ID of the layer rendered by this class.
QgsRenderContext * renderContext()
Returns the render context associated with the renderer.
QgsMapLayerRenderer(const QString &layerID, QgsRenderContext *context=nullptr)
Constructor for QgsMapLayerRenderer, with the associated layerID and render context.
QRectF transformBounds(const QRectF &bounds) const
Transforms a bounding box from map coordinates to device coordinates.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
Attribute for point cloud data pair of name and size in bytes.
QString errorStr() const
Returns the error message string of the request.
void finished()
Emitted when the request processing has finished.
std::unique_ptr< QgsPointCloudBlock > takeBlock()
Returns the requested block.
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...
void renderExtent(const QgsGeometry &extent, QgsPointCloudRenderContext &context)
Renders a polygon extent geometry to the specified render context.
Smart pointer for QgsAbstractPointCloudIndex.
int span() const
Returns the number of points in one direction in a single node.
std::unique_ptr< QgsPointCloudBlock > nodeData(QgsPointCloudNodeId n, const QgsPointCloudRequest &request)
Returns node data block.
QgsVector3D offset() const
Returns offset of data from CRS.
QgsVector3D scale() const
Returns scale of data relative to CRS.
QgsPointCloudNode getNode(QgsPointCloudNodeId id) const
Returns object for a given node.
bool isValid() const
Returns whether index is loaded and valid.
QgsRectangle extent() const
Returns extent of the data.
QgsPointCloudNodeId root() const
Returns root node of the index.
QgsPointCloudBlockRequest * asyncNodeData(QgsPointCloudNodeId n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
Qgis::PointCloudAccessType accessType() const
Returns the access type of the data If the access type is Remote, data will be fetched from an HTTP s...
Point cloud layer specific subclass of QgsMapLayerElevationProperties.
~QgsPointCloudLayerRenderer() override
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).
Qgis::MapLayerRendererFlags flags() const override
Returns flags which control how the map layer rendering behaves.
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.
QgsPointCloudIndex index() const
Returns the point cloud index associated with the layer.
QgsPointCloudDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
Represents an indexed point cloud node's position in octree.
QString toString() const
Encode node to string.
Keeps metadata for an indexed point cloud node.
QList< QgsPointCloudNodeId > children() const
Returns IDs of child nodes.
qint64 pointCount() const
Returns number of points contained in node data.
QgsBox3D bounds() const
Returns node's bounding cube in CRS coords.
Encapsulates the render context for a 2D point cloud rendering operation.
int yOffset() const
Returns the offset for the y value in a point record.
QgsVector3D offset() const
Returns the offset of the layer's int32 coordinates compared to CRS coords.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
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.
int pointRecordSize() const
Returns the size of a single point record.
int xOffset() const
Returns the offset for the x value in a point record.
QgsVector3D scale() const
Returns the scale of the layer's int32 coordinates compared to CRS coords.
TriangulationData & triangulationData()
Returns reference to the triangulation data structure (only used when rendering as triangles is enabl...
int zOffset() const
Returns the offset for the y value in a point record.
QgsFeedback * feedback() const
Returns the feedback object used to cancel rendering.
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.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
QRectF toRectF() const
Returns a QRectF with same coordinates as the rectangle.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsElevationMap * elevationMap() const
Returns the destination elevation map for the render operation.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
float devicePixelRatio() const
Returns the device pixel ratio.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainter(QPainter *p)
Sets the destination QPainter for the render operation.
QgsDoubleRange zRange() const
Returns the range of z-values which should be rendered.
QSize deviceOutputSize() const
Returns the device output size of the render.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
QPainter * previewRenderPainter()
Returns the const destination QPainter for temporary in-progress preview renders.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
void setElevationMap(QgsElevationMap *map)
Sets the destination elevation map for the render operation.
void record(const QString &name, double time, const QString &group="startup", const QString &id=QString())
Manually adds a profile event with the given name and total time (in seconds).
Scoped object for saving and restoring a QPainter object's state.
Scoped object for setting the current thread name.
double y() const
Returns Y coordinate.
double z() const
Returns Z coordinate.
double x() const
Returns X coordinate.
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
bool isEdgeTooLong(const QPointF &p1, const QPointF &p2, float length)
Contains parameters for an ellipsoid.
double semiMajor
Semi-major axis, in meters.
bool valid
Whether ellipsoid parameters are valid.
double semiMinor
Semi-minor axis, in meters.
std::vector< QRgb > colors
RGB color for each point.
std::vector< float > elevations
Z value for each point (only used when global map shading is enabled).
std::vector< double > points
X,Y for each point - kept in this structure so that we can use it without further conversions in Dela...