22#include "delaunator.hpp"
41#include "qgsvirtualpointcloudprovider.h"
43#include <QElapsedTimer>
48 , mLayerName( layer->name() )
49 , mLayerAttributes( layer->attributes() )
50 , mSubIndexes( layer->dataProvider() ? layer->dataProvider()->subIndexes() : QVector<QgsPointCloudSubIndex>() )
52 , mEnableProfile( context.
flags() &
Qgis::RenderContextFlag::RecordProfile )
57 mIndex = layer->
index();
63 if ( !mSubIndexes.isEmpty() )
65 mSubIndexExtentRenderer = std::make_unique<QgsPointCloudExtentRenderer>( );
66 mSubIndexExtentRenderer->setShowLabels( mRenderer->showLabels() );
67 mSubIndexExtentRenderer->setLabelTextFormat( mRenderer->labelTextFormat() );
72 mScale = mIndex.scale();
73 mOffset = mIndex.offset();
78 mZOffset = elevationProps->zOffset();
79 mZScale = elevationProps->zScale();
82 if (
const QgsVirtualPointCloudProvider *vpcProvider =
dynamic_cast<QgsVirtualPointCloudProvider *
>( layer->
dataProvider() ) )
85 mAverageSubIndexWidth = vpcProvider->averageSubIndexWidth();
86 mAverageSubIndexHeight = vpcProvider->averageSubIndexHeight();
87 mOverviewIndex = vpcProvider->overview();
96 mPreparationTime = timer.elapsed();
103 std::unique_ptr< QgsScopedRuntimeProfile > profile;
104 if ( mEnableProfile )
106 profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral(
"rendering" ),
layerId() );
107 if ( mPreparationTime > 0 )
111 std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
112 if ( mEnableProfile )
114 preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Preparing render" ), QStringLiteral(
"rendering" ) );
125 if ( !mClippingRegions.empty() )
127 bool needsPainterClipPath =
false;
129 if ( needsPainterClipPath )
133 if ( mRenderer->type() == QLatin1String(
"extent" ) )
136 mRenderer->startRender( context );
138 mRenderer->stopRender( context );
143 if ( mSubIndexes.isEmpty() && ( !mIndex || !mIndex.isValid() ) )
153 mBlockRenderUpdates =
true;
154 mElapsedTimer.start();
157 mRenderer->startRender( context );
169 QSet< QString > rendererAttributes = mRenderer->usedAttributes( context );
172 for (
const QString &attribute : std::as_const( rendererAttributes ) )
174 if ( mAttributes.indexOf( attribute ) >= 0 )
177 const int layerIndex = mLayerAttributes.indexOf( attribute );
178 if ( layerIndex < 0 )
180 QgsMessageLog::logMessage( QObject::tr(
"Required attribute %1 not found in layer" ).arg( attribute ), QObject::tr(
"Point Cloud" ) );
184 mAttributes.push_back( mLayerAttributes.at( layerIndex ) );
194 QgsDebugError( QStringLiteral(
"Transformation of extent failed!" ) );
197 preparingProfile.reset();
198 std::unique_ptr< QgsScopedRuntimeProfile > renderingProfile;
199 if ( mEnableProfile )
201 renderingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering" ), QStringLiteral(
"rendering" ) );
204 bool canceled =
false;
205 if ( mSubIndexes.isEmpty() )
207 canceled = !renderIndex( mIndex );
211 QVector< QgsPointCloudSubIndex > visibleIndexes;
212 for (
const QgsPointCloudSubIndex &si : mSubIndexes )
216 visibleIndexes.append( si );
219 const bool zoomedOut = renderExtent.
width() > mAverageSubIndexWidth ||
220 renderExtent.
height() > mAverageSubIndexHeight;
222 if ( mOverviewIndex && mOverviewIndex->isValid() && zoomedOut &&
225 renderIndex( *mOverviewIndex );
231 if ( mOverviewIndex && mOverviewIndex->isValid() && zoomedOut &&
234 renderIndex( *mOverviewIndex );
236 mSubIndexExtentRenderer->startRender( context );
237 for (
const QgsPointCloudSubIndex &si : visibleIndexes )
247 mSubIndexExtentRenderer->renderExtent( si.polygonBounds(), context );
248 if ( mSubIndexExtentRenderer->showLabels() )
250 mSubIndexExtentRenderer->renderLabel(
252 si.uri().section(
"/", -1 ).section(
".", 0, 0 ),
259 canceled = !renderIndex( pc );
262 mSubIndexExtentRenderer->stopRender( context );
266 mRenderer->stopRender( context );
288 const double maximumError = context.renderContext().convertToPainterUnits( mRenderer->maximumScreenError(), mRenderer->maximumScreenErrorUnit() );
293 if ( !context.renderContext().coordinateTransform().isShortCircuited() )
301 catch ( QgsCsException & )
303 QgsDebugError( QStringLiteral(
"Could not transform node extent to map CRS" ) );
304 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
309 rootNodeExtentMapCoords = rootNodeExtentLayerCoords;
312 const double rootErrorInMapCoordinates = rootNodeExtentMapCoords.
width() / pc.
span();
314 double mapUnitsPerPixel = context.renderContext().mapToPixel().mapUnitsPerPixel();
315 if ( ( rootErrorInMapCoordinates < 0.0 ) || ( mapUnitsPerPixel < 0.0 ) || ( maximumError < 0.0 ) )
320 double rootErrorPixels = rootErrorInMapCoordinates / mapUnitsPerPixel;
321 const QVector<QgsPointCloudNodeId> nodes = traverseTree( pc, context.renderContext(), pc.
root(), maximumError, rootErrorPixels );
323 QgsPointCloudRequest request;
328 bool canceled =
false;
331 if ( mRenderer->renderAsTriangles() )
343 nodesDrawn += renderNodesSorted( nodes, pc, context, request, canceled, mRenderer->drawOrder2d() );
352 nodesDrawn += renderNodesSync( nodes, pc, context, request, canceled );
357 nodesDrawn += renderNodesAsync( nodes, pc, context, request, canceled );
365 QgsDebugMsgLevel( QStringLiteral(
"totals: %1 nodes | %2 points | %3ms" ).arg( nodesDrawn )
366 .arg( context.pointsRendered() )
367 .arg( t.elapsed() ), 2 );
386 for (
const QgsPointCloudNodeId &n : nodes )
394 std::unique_ptr<QgsPointCloudBlock> block( pc.
nodeData( n, request ) );
399 QgsVector3D contextScale = context.
scale();
400 QgsVector3D contextOffset = context.
offset();
407 mRenderer->renderBlock( block.get(), context );
423 if ( mRenderer->renderAsTriangles() )
427 renderTriangulatedSurface( context );
435 if ( nodes.isEmpty() )
452 QVector<QgsPointCloudBlockRequest *> blockRequests;
457 for (
int i = 0; i < nodes.size(); ++i )
459 const QgsPointCloudNodeId &n = nodes[i];
461 QgsPointCloudBlockRequest *blockRequest = pc.
asyncNodeData( n, request );
462 blockRequests.append( blockRequest );
464 [
this, &canceled, &nodesDrawn, &loop, &blockRequests, &context, nStr, blockRequest ]()
466 blockRequests.removeOne( blockRequest );
469 if ( blockRequests.isEmpty() )
472 std::unique_ptr<QgsPointCloudBlock> block( blockRequest->
takeBlock() );
474 blockRequest->deleteLater();
484 QgsDebugError( QStringLiteral(
"Unable to load node %1, error: %2" ).arg( nStr, blockRequest->
errorStr() ) );
488 QgsVector3D contextScale = context.
scale();
489 QgsVector3D contextOffset = context.
offset();
495 mRenderer->renderBlock( block.get(), context );
514 if ( !blockRequests.isEmpty() )
519 for ( QgsPointCloudBlockRequest *blockRequest : std::as_const( blockRequests ) )
521 std::unique_ptr<QgsPointCloudBlock> block = blockRequest->
takeBlock();
524 blockRequest->deleteLater();
527 if ( mRenderer->renderAsTriangles() )
531 renderTriangulatedSurface( context );
542 QgsVector3D blockScale;
543 QgsVector3D blockOffset;
544 QgsPointCloudAttributeCollection blockAttributes;
548 QByteArray allByteArrays;
550 QVector<QPair<int, double>> allPairs;
552 for (
const QgsPointCloudNodeId &n : nodes )
560 std::unique_ptr<QgsPointCloudBlock> block( pc.
nodeData( n, request ) );
567 QgsVector3D offsetDifference = QgsVector3D( 0, 0, 0 );
568 if ( blockCount == 0 )
570 blockScale = block->scale();
571 blockOffset = block->offset();
572 blockAttributes = block->attributes();
576 offsetDifference = blockOffset - block->offset();
579 const char *ptr = block->data();
587 for (
int i = 0; i < block->pointCount(); ++i )
589 allByteArrays.append( ptr + i * recordSize, recordSize );
592 if ( offsetDifference.
x() != 0 )
594 qint32 ix = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
xOffset() );
595 ix -= std::lround( offsetDifference.
x() / context.
scale().
x() );
596 const char *xPtr =
reinterpret_cast< const char *
>( &ix );
597 allByteArrays.replace( pointCount * recordSize + context.
xOffset(), 4, QByteArray( xPtr, 4 ) );
599 if ( offsetDifference.
y() != 0 )
601 qint32 iy = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
yOffset() );
602 iy -= std::lround( offsetDifference.
y() / context.
scale().
y() );
603 const char *yPtr =
reinterpret_cast< const char *
>( &iy );
604 allByteArrays.replace( pointCount * recordSize + context.
yOffset(), 4, QByteArray( yPtr, 4 ) );
607 qint32 iz = *
reinterpret_cast< const qint32 *
>( ptr + i * recordSize + context.
zOffset() );
608 if ( offsetDifference.
z() != 0 )
610 iz -= std::lround( offsetDifference.
z() / context.
scale().
z() );
611 const char *zPtr =
reinterpret_cast< const char *
>( &iz );
612 allByteArrays.replace( pointCount * recordSize + context.
zOffset(), 4, QByteArray( zPtr, 4 ) );
614 allPairs.append( qMakePair( pointCount,
double( iz ) + block->offset().z() ) );
621 if ( pointCount == 0 )
627 std::sort( allPairs.begin(), allPairs.end(), []( QPair<int, double> a, QPair<int, double> b ) { return a.second < b.second; } );
630 std::sort( allPairs.begin(), allPairs.end(), []( QPair<int, double> a, QPair<int, double> b ) { return a.second > b.second; } );
637 QByteArray sortedByteArray;
638 sortedByteArray.reserve( allPairs.size() );
639 for ( QPair<int, double> pair : allPairs )
640 sortedByteArray.append( allByteArrays.mid( pair.first * recordSize, recordSize ) );
642 std::unique_ptr<QgsPointCloudBlock> bigBlock {
new QgsPointCloudBlock( pointCount,
648 QgsVector3D contextScale = context.
scale();
649 QgsVector3D contextOffset = context.
offset();
651 context.
setScale( bigBlock->scale() );
655 mRenderer->renderBlock( bigBlock.get(), context );
663inline bool isEdgeTooLong(
const QPointF &p1,
const QPointF &p2,
float length )
666 return p.x() * p.x() + p.y() * p.y() > length;
669static void renderTriangle( QImage &img, QPointF *pts, QRgb c0, QRgb c1, QRgb c2,
float horizontalFilter,
float *elev,
QgsElevationMap *elevationMap )
671 if ( horizontalFilter > 0 )
673 float filterThreshold2 = horizontalFilter * horizontalFilter;
680 QgsRectangle screenBBox = QgsMeshLayerUtils::triangleBoundingBox( pts[0], pts[1], pts[2] );
682 QSize outputSize = img.size();
684 int topLim = std::max(
int( screenBBox.
yMinimum() ), 0 );
685 int bottomLim = std::min(
int( screenBBox.
yMaximum() ), outputSize.height() - 1 );
686 int leftLim = std::max(
int( screenBBox.
xMinimum() ), 0 );
687 int rightLim = std::min(
int( screenBBox.
xMaximum() ), outputSize.width() - 1 );
689 int red0 = qRed( c0 ), green0 = qGreen( c0 ), blue0 = qBlue( c0 );
690 int red1 = qRed( c1 ), green1 = qGreen( c1 ), blue1 = qBlue( c1 );
691 int red2 = qRed( c2 ), green2 = qGreen( c2 ), blue2 = qBlue( c2 );
695 for (
int j = topLim; j <= bottomLim; j++ )
697 QRgb *scanLine = ( QRgb * ) img.scanLine( j );
698 QRgb *elevScanLine = elevData ? elevData +
static_cast<size_t>( outputSize.width() * j ) : nullptr;
699 for (
int k = leftLim; k <= rightLim; k++ )
702 double lam1, lam2, lam3;
703 if ( !QgsMeshLayerUtils::calculateBarycentricCoordinates( pts[0], pts[1], pts[2], pt, lam3, lam2, lam1 ) )
707 int r =
static_cast<int>( red0 * lam1 + red1 * lam2 + red2 * lam3 );
708 int g =
static_cast<int>( green0 * lam1 + green1 * lam2 + green2 * lam3 );
709 int b =
static_cast<int>( blue0 * lam1 + blue1 * lam2 + blue2 * lam3 );
710 scanLine[k] = qRgb( r, g, b );
715 float z =
static_cast<float>( elev[0] * lam1 + elev[1] * lam2 + elev[2] * lam3 );
724 const QgsPointCloudRenderContext::TriangulationData &triangulation = context.
triangulationData();
725 const std::vector<double> &points = triangulation.
points;
728 if ( points.size() < 3 )
730 QgsDebugMsgLevel( QStringLiteral(
"Need at least 3 points to triangulate" ), 4 );
734 std::unique_ptr<delaunator::Delaunator> delaunator;
737 delaunator = std::make_unique<delaunator::Delaunator>( points );
739 catch ( std::exception & )
746 float horizontalFilter = 0;
747 if ( mRenderer->horizontalTriangleFilter() )
750 mRenderer->horizontalTriangleFilterThreshold(), mRenderer->horizontalTriangleFilterUnit() ) );
757 const std::vector<size_t> &triangleIndexes = delaunator->triangles;
761 float elev[3] {0, 0, 0};
762 for (
size_t i = 0; i < triangleIndexes.size(); i += 3 )
764 size_t v0 = triangleIndexes[i], v1 = triangleIndexes[i + 1], v2 = triangleIndexes[i + 2];
765 triangle[0].rx() = points[v0 * 2];
766 triangle[0].ry() = points[v0 * 2 + 1];
767 triangle[1].rx() = points[v1 * 2];
768 triangle[1].ry() = points[v1 * 2 + 1];
769 triangle[2].rx() = points[v2 * 2];
770 triangle[2].ry() = points[v2 * 2 + 1];
779 QRgb c0 = triangulation.
colors[v0], c1 = triangulation.
colors[v1], c2 = triangulation.
colors[v2];
780 renderTriangle( img, triangle, c0, c1, c2, horizontalFilter, elev, elevationMap );
783 painter->drawImage( 0, 0, img );
791 if ( mRenderer->renderAsTriangles() )
801 return mRenderer ? mRenderer->type() != QLatin1String(
"extent" ) :
false;
806 mRenderTimeHint = time;
811 QVector<QgsPointCloudNodeId> nodes;
819 QgsPointCloudNode node = pc.
getNode( n );
820 QgsBox3D nodeExtent = node.
bounds();
825 const QgsDoubleRange nodeZRange( nodeExtent.
zMinimum(), nodeExtent.
zMaximum() );
826 const QgsDoubleRange adjustedNodeZRange = QgsDoubleRange( nodeZRange.lower() + mZOffset, nodeZRange.upper() + mZOffset );
833 double childrenErrorPixels = nodeErrorPixels / 2.0;
834 if ( childrenErrorPixels < maxErrorPixels )
837 for (
const QgsPointCloudNodeId &nn : node.
children() )
839 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.
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.
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())
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.
QgsVector3D offset() const
Returns offset of data from CRS.
QgsVector3D scale() const
Returns scale of data relative to CRS.
QgsPointCloudBlockRequest * asyncNodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns a handle responsible for loading a node data block.
bool isValid() const
Returns whether index is loaded and valid.
QgsRectangle extent() const
Returns extent of the data.
std::unique_ptr< QgsPointCloudBlock > nodeData(const QgsPointCloudNodeId &n, const QgsPointCloudRequest &request)
Returns node data block.
QgsPointCloudNodeId root() const
Returns root node of the index.
QgsPointCloudNode getNode(const QgsPointCloudNodeId &id) const
Returns object for a given node.
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.
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 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)
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...