44#include <QElapsedTimer>
45#include <QLinearGradient>
51#include "moc_qgsmeshlayerrenderer.cpp"
53using namespace Qt::StringLiterals;
59 , mIsEditable( layer->isEditable() )
61 ,
mFeedback( new QgsMeshLayerRendererFeedback )
64 , mLayerOpacity( layer->opacity() )
95 switch ( elevProp->
mode() )
111 int currentMatchingVectorGroup = -1;
112 int currentMatchingScalarGroup = -1;
118 const int activeVectorDatasetGroup =
mRendererSettings.activeVectorDatasetGroup();
119 const int activeScalarDatasetGroup =
mRendererSettings.activeScalarDatasetGroup();
121 for (
auto it = rangePerGroup.constBegin(); it != rangePerGroup.constEnd(); ++it )
123 if ( it.value().overlaps( context.
zRange() ) )
128 if ( matchesVectorParentGroup && (
130 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingVectorRange.
upper() )
131 || ( !currentMatchingVectorRange.
includeUpper() && it.value().upper() >= currentMatchingVectorRange.
upper() ) ) )
133 currentMatchingVectorGroup = it.key();
134 currentMatchingVectorRange = it.value();
137 if ( matchesScalarParentGroup && (
139 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingScalarRange.
upper() )
140 || ( !currentMatchingScalarRange.
includeUpper() && it.value().upper() >= currentMatchingScalarRange.
upper() ) ) )
142 currentMatchingScalarGroup = it.key();
143 currentMatchingScalarRange = it.value();
147 if ( currentMatchingVectorGroup >= 0 )
149 if ( currentMatchingScalarGroup >= 0 )
157 copyTriangularMeshes( layer, context );
160 copyScalarDatasetValues( layer );
161 copyVectorDatasetValues( layer );
163 calculateOutputSize();
166 prepareLabeling( layer, attrs );
175 if ( activeDatasetIndex.
isValid() )
190 if ( previousMin != min || previousMax != max )
216 if ( simplificationSettings.
isEnabled() )
220 mIsMeshSimplificationActive =
true;
233void QgsMeshLayerRenderer::calculateOutputSize()
240 const int width = int( screenBBox.
width() );
241 const int height = int( screenBBox.
height() );
245void QgsMeshLayerRenderer::copyScalarDatasetValues(
QgsMeshLayer *layer )
247 QgsMeshDatasetIndex datasetIndex;
257 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
258 ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
259 ( cache->mDataInterpolationMethod == method ) &&
279 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
328 const QgsMeshDatasetMetadata datasetMetadata = layer->
datasetMetadata( datasetIndex );
334 cache->mDatasetGroupsCount = datasetGroupCount;
335 cache->mActiveScalarDatasetIndex = datasetIndex;
336 cache->mDataInterpolationMethod = method;
346void QgsMeshLayerRenderer::copyVectorDatasetValues(
QgsMeshLayer *layer )
348 QgsMeshDatasetIndex datasetIndex;
357 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
358 ( cache->mActiveVectorDatasetIndex == datasetIndex ) &&
378 const bool isScalar = metadata.
isScalar();
405 const QgsMeshDatasetMetadata datasetMetadata = layer->
datasetMetadata( datasetIndex );
412 cache->mDatasetGroupsCount = datasetGroupCount;
413 cache->mActiveVectorDatasetIndex = datasetIndex;
429 std::unique_ptr< QgsScopedRuntimeProfile > profile;
430 std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
433 profile = std::make_unique< QgsScopedRuntimeProfile >(
mLayerName, u
"rendering"_s,
layerId() );
436 preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Preparing render" ), u
"rendering"_s );
443 bool needsPainterClipPath =
false;
445 if ( needsPainterClipPath )
449 preparingProfile.reset();
451 renderScalarDataset();
454 renderVectorDataset();
456 registerLabelFeatures();
476void QgsMeshLayerRenderer::renderMesh()
483 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
486 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering mesh" ), u
"rendering"_s );
509 nativeFacesInExtent.values() );
523 QPainter *painter = context.
painter();
528 QPen pen = painter->pen();
529 pen.setCapStyle( Qt::FlatCap );
530 pen.setJoinStyle( Qt::MiterJoin );
533 pen.setWidthF( penWidth );
534 pen.setColor( settings.
color() );
535 painter->setPen( pen );
547 QPainter *painter = _painterForMeshFrame( context, settings );
552 for (
const int i : edgesInExtent )
557 if ( i >= edges.size() )
561 const int startVertexIndex = edge.first;
562 const int endVertexIndex = edge.second;
564 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
567 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
576void QgsMeshLayerRenderer::renderFaceMesh(
578 const QVector<QgsMeshFace> &faces,
579 const QList<int> &facesInExtent )
581 Q_ASSERT( settings.
isEnabled() || mIsEditable );
587 QPainter *painter = _painterForMeshFrame( context, settings );
590 QSet<QPair<int, int>> drawnEdges;
592 for (
const int i : facesInExtent )
597 if ( i < 0 || i >= faces.count() )
601 if ( face.size() < 2 )
604 for (
int j = 0; j < face.size(); ++j )
606 const int startVertexId = face[j];
607 const int endVertexId = face[( j + 1 ) % face.size()];
608 const QPair<int, int> thisEdge( startVertexId, endVertexId );
609 const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
610 if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
612 drawnEdges.insert( thisEdge );
613 drawnEdges.insert( thisEdgeReversed );
626void QgsMeshLayerRenderer::renderScalarDataset()
635 if ( groupIndex < 0 )
638 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
641 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering scalar datasets" ), u
"rendering"_s );
644 const QgsMeshRendererScalarSettings scalarSettings =
mRendererSettings.scalarSettings( groupIndex );
649 renderScalarDatasetOnFaces( scalarSettings );
655 renderScalarDatasetOnEdges( scalarSettings );
666 QgsInterpolatedLineRenderer edgePlotter;
671 for (
const int i : edgesInExtent )
676 if ( i >= edges.size() )
680 const int startVertexIndex = edge.first;
681 const int endVertexIndex = edge.second;
683 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
686 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
703 if ( shader->
shade( val, &r, &g, &b, &a ) )
705 return QColor( r, g, b, a );
712 const QgsPointXY pt( p1.
x() + fraction * ( p2.
x() - p1.
x() ),
713 p1.
y() + fraction * ( p2.
y() - p1.
y() ) );
721 QgsColorRampShader *fcn =
new QgsColorRampShader( scalarSettings.
colorRampShader() );
722 QgsRasterShader *sh =
new QgsRasterShader();
730 interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
732 QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh );
735 renderer.setOpacity( scalarSettings.
opacity() );
738 QImage img = bl->image();
741 context.
painter()->drawImage( 0, 0, img );
744void QgsMeshLayerRenderer::renderVectorDataset()
747 if ( groupIndex < 0 )
759 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
762 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering vector datasets" ), u
"rendering"_s );
765 std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
783void QgsMeshLayerRenderer::prepareLabeling(
QgsMeshLayer *layer, QSet<QString> &attributeNames )
792 if ( mLabelProvider )
797 c.lastScope()->setVariable( u
"_native_mesh"_s, QVariant::fromValue(
mNativeMesh ) );
800 engine->addProvider( mLabelProvider );
801 if ( !mLabelProvider->prepare( context, attributeNames ) )
803 engine->removeProvider( mLabelProvider );
804 mLabelProvider =
nullptr;
811void QgsMeshLayerRenderer::registerLabelFeatures()
813 if ( !mLabelProvider )
822 if ( mLabelProvider->labelFaces() )
829 for (
const int i : nativeFacesInExtent )
837 scope->
setVariable( u
"_mesh_face_index"_s, i,
false );
841 f.setGeometry( geom );
842 mLabelProvider->registerFeature( f, context );
852 for (
const int i : nativeVerticesInExtent )
860 scope->
setVariable( u
"_mesh_vertex_index"_s, i,
false );
863 QgsGeometry geom = QgsGeometry(
new QgsPoint(
mNativeMesh.vertex( i ) ) );
864 f.setGeometry( geom );
865 mLabelProvider->registerFeature( f, context );
Provides global constants and enumerations for use throughout the application.
@ Default
Allow raster-based rendering in situations where it is required for correct rendering or where it wil...
@ PreferVector
Prefer vector-based rendering, when the result will still be visually near-identical to a raster-base...
@ ForceVector
Always force vector-based rendering, even when the result will be visually different to a raster-base...
@ MinimumMaximum
Real min-max values.
@ UpdatedCanvas
Constantly updated extent of the canvas is used to compute statistics.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ RenderPreviewJob
Render is a 'canvas preview' render, and shortcuts should be taken to ensure fast rendering.
@ Render3DMap
Render is for a 3D map.
@ FromVertices
Elevation should be taken from mesh vertices.
@ FixedRangePerGroup
Layer has a fixed (manually specified) elevation range per group.
@ FixedElevationRange
Layer has a fixed elevation range.
virtual QgsMeshLayerLabelProvider * provider(QgsMeshLayer *layer) const
Factory for label provider implementation.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
bool shade(double value, int *returnRedValue, int *returnGreenValue, int *returnBlueValue, int *returnAlphaValue) const override
Generates an new RGBA value based on one input value.
QgsRange which stores a range of double values.
bool isInfinite() const
Returns true if the range consists of all possible values.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QgsExpressionContextScope * meshExpressionScope(QgsMesh::ElementType elementType)
Creates a new scope which contains functions relating to mesh layer element elementType.
QgsExpressionContextScope * activeScopeForVariable(const QString &name)
Returns the currently active scope from the context for a specified variable name.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
void setInterpolatedColor(const QgsInterpolatedLineColor &strokeColoring)
Sets the stroke color used to render.
void setInterpolatedWidth(const QgsInterpolatedLineWidth &strokeWidth)
Sets the stroke width used to render.
void render(double value1, double value2, const QgsPointXY &point1, const QgsPointXY &point2, QgsRenderContext &context) const
Renders a line in the context between point1 and point2 with color and width that vary depending on v...
void setWidthUnit(Qgis::RenderUnit strokeWidthUnit)
Sets the unit of the stroke width.
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.
double zScale() const
Returns the z scale, which is a scaling factor which should be applied to z values from the layer.
virtual bool hasElevation() const
Returns true if the layer has an elevation or z component.
double zOffset() const
Returns the z offset, which is a fixed offset amount which should be added to z values from the layer...
bool mReadyToCompose
The flag must be set to false in renderer's constructor if wants to use the smarter map redraws funct...
QString layerId() const
Gets access to the ID of the layer rendered by this class.
void appendRenderedItemDetails(QgsRenderedItemDetails *details)
Appends the details of a rendered item to the renderer.
virtual Qgis::MapLayerRendererFlags flags() const
Returns flags which control how the map layer rendering behaves.
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.
Perform transforms between map coordinates and device coordinates.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
QgsPointXY transform(const QgsPointXY &p) const
Transforms a point p from map (world) coordinates to device coordinates.
static bool equals(const QgsMesh3DAveragingMethod *a, const QgsMesh3DAveragingMethod *b)
Returns whether two methods equal.
bool isValid() const
Whether the block is valid.
An index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
Mesh layer specific subclass of QgsMapLayerElevationProperties.
Qgis::MeshElevationMode mode() const
Returns the elevation mode.
QMap< int, QgsDoubleRange > fixedRangePerGroup() const
Returns the fixed elevation range for each group.
double mScalarDatasetMaximum
QgsMeshDatasetGroupMetadata::DataType mScalarDataType
double mVectorDatasetMagMinimum
double mScalarDatasetMinimum
QgsTriangularMesh mTriangularMesh
QgsMeshLayerRenderer(QgsMeshLayer *layer, QgsRenderContext &context)
Ctor.
QVector< double > mScalarDatasetValues
std::unique_ptr< QgsMeshLayerRendererFeedback > mFeedback
feedback class for cancellation
QgsMeshDataBlock mScalarActiveFaceFlagValues
bool render() override
Do the rendering (based on data stored in the class).
double mVectorDatasetMagMaximum
QgsRectangle mLayerExtent
QVector< double > mVectorDatasetValuesMag
double mVectorDatasetGroupMagMaximum
QgsMeshRendererSettings mRendererSettings
bool forceRasterRender() const override
Returns true if the renderer must be rendered to a raster paint device (e.g.
QgsMeshDatasetGroupMetadata::DataType mVectorDataType
double mVectorDatasetGroupMagMinimum
QList< QgsMapClippingRegion > mClippingRegions
QgsFeedback * feedback() const override
Access to feedback object of the layer renderer (may be nullptr).
QgsMeshDataBlock mVectorActiveFaceFlagValues
QgsMeshDataBlock mVectorDatasetValues
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsRectangle extent() const override
Returns the extent of the layer.
QgsMeshDatasetIndex activeScalarDatasetIndex(QgsRenderContext &rendererContext)
Returns current active scalar dataset index for current renderer context.
QgsMeshDatasetIndex activeVectorDatasetAtTime(const QgsDateTimeRange &timeRange, int group=-1) const
Returns dataset index from active vector group depending on the time range If the temporal properties...
int datasetGroupCount() const
Returns the dataset groups count handle by the layer.
const QgsAbstractMeshLayerLabeling * labeling() const
Access to const labeling configuration.
QgsMeshDatasetIndex staticVectorDatasetIndex(int group=-1) const
Returns the static vector dataset index that is rendered if the temporal properties is not active.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh).
bool minimumMaximumActiveScalarDataset(const QgsRectangle &extent, const QgsMeshDatasetIndex &datasetIndex, double &min, double &max)
Extracts minimum and maximum value for active scalar dataset on mesh faces.
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
QgsMeshSimplificationSettings meshSimplificationSettings() const
Returns mesh simplification settings.
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether the faces are active for particular dataset.
QgsMeshDatasetMetadata datasetMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset metadata.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
QgsMeshDatasetIndex activeScalarDatasetAtTime(const QgsDateTimeRange &timeRange, int group=-1) const
Returns dataset index from active scalar group depending on the time range.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
QgsMeshDatasetIndex staticScalarDatasetIndex(int group=-1) const
Returns the static scalar dataset index that is rendered if the temporal properties is not active.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
QgsMeshLayerRendererCache * rendererCache()
Returns native mesh (nullptr before rendering).
Represents a mesh renderer settings for mesh objects.
QColor color() const
Returns color used for rendering.
double lineWidth() const
Returns line width used for rendering (in millimeters).
Qgis::RenderUnit lineWidthUnit() const
Returns units of the width of the mesh frame.
bool isEnabled() const
Returns whether mesh structure rendering is enabled.
Represents a mesh renderer settings for scalar datasets.
void setClassificationMinimumMaximum(double minimum, double maximum)
Sets min/max values used for creation of the color ramp shader.
Qgis::MeshRangeExtent extent() const
Returns the mesh extent for minimum maximum calculation.
double opacity() const
Returns opacity.
Qgis::MeshRangeLimit limits() const
Returns the range limits type for minimum maximum calculation.
QgsColorRampShader colorRampShader() const
Returns color ramp shader function.
double classificationMinimum() const
Returns min value used for creation of the color ramp shader.
DataResamplingMethod
Resampling of value from dataset.
@ NoResampling
Does not use resampling.
Qgis::RenderUnit edgeStrokeWidthUnit() const
Returns the stroke width unit used to render edges scalar dataset.
double classificationMaximum() const
Returns max value used for creation of the color ramp shader.
QgsInterpolatedLineWidth edgeStrokeWidth() const
Returns the stroke width used to render edges scalar dataset.
QgsMeshRendererMeshSettings edgeMeshSettings() const
Returns edge mesh renderer settings.
QgsMeshRendererMeshSettings nativeMeshSettings() const
Returns native mesh renderer settings.
QgsMeshRendererMeshSettings triangularMeshSettings() const
Returns triangular mesh renderer settings.
Represents an overview renderer settings.
bool isEnabled() const
Returns if the overview is active.
int meshResolution() const
Returns the mesh resolution i.e., the minimum size (average) of triangles in pixels.
static QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
static QSet< int > nativeVerticesFromTriangles(const QList< int > &triangleIndexes, const QVector< QgsMeshFace > &triangles)
Returns unique native vertex indexes from list of vertices of triangles.
static QSet< int > nativeFacesFromTriangles(const QList< int > &triangleIndexes, const QVector< int > &trianglesToNativeFaces)
Returns unique native faces indexes from list of triangle indexes.
QPointF toQPointF() const
Converts a point to a QPointF.
bool includeUpper() const
Returns true if the upper bound is inclusive, or false if the upper bound is exclusive.
T upper() const
Returns the upper bound of the range.
void setRasterShaderFunction(QgsRasterShaderFunction *function)
A public method that allows the user to set their own shader function.
A rectangle specified with double values.
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 ...
QgsExpressionContext & expressionContext()
Gets the expression context.
const QgsRectangle & extent() const
When rendering a map layer, calling this method returns the "clipping" extent for the layer (in the l...
bool testFlag(Qgis::RenderContextFlag flag) const
Check whether a particular flag is enabled.
float devicePixelRatio() const
Returns the device pixel ratio.
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
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...
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
QgsLabelingEngine * labelingEngine() const
Gets access to new labeling engine (may be nullptr).
Qgis::RenderContextFlags flags() const
Returns combination of flags used for rendering.
void setBoundingBox(const QgsRectangle &bounds)
Sets the bounding box of the item (in map units).
Contains computed statistics for a layer render.
void setMaximum(QList< double > &maximum)
Sets the maximum values of the computed statistics.
void setMinimum(QList< double > &minimum)
Sets the minimum values of the computed statistics.
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.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
#define QgsDebugError(str)
QVector< int > QgsMeshFace
List of vertex indexes.
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
QgsPoint QgsMeshVertex
xyz coords of vertex