21#include <QLinearGradient>
25#include <QElapsedTimer>
28#include "moc_qgsmeshlayerrenderer.cpp"
52 , mIsEditable( layer->isEditable() )
53 , mLayerName( layer->name() )
54 , mFeedback( new QgsMeshLayerRendererFeedback )
55 , mRendererSettings( layer->rendererSettings() )
56 , mEnableProfile( context.flags() &
Qgis::RenderContextFlag::RecordProfile )
57 , mLayerOpacity( layer->opacity() )
88 switch ( elevProp->
mode() )
104 int currentMatchingVectorGroup = -1;
105 int currentMatchingScalarGroup = -1;
114 for (
auto it = rangePerGroup.constBegin(); it != rangePerGroup.constEnd(); ++it )
116 if ( it.value().overlaps( context.
zRange() ) )
121 if ( matchesVectorParentGroup && (
123 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingVectorRange.
upper() )
124 || ( !currentMatchingVectorRange.
includeUpper() && it.value().upper() >= currentMatchingVectorRange.
upper() ) ) )
126 currentMatchingVectorGroup = it.key();
127 currentMatchingVectorRange = it.value();
130 if ( matchesScalarParentGroup && (
132 || ( it.value().includeUpper() && it.value().upper() >= currentMatchingScalarRange.
upper() )
133 || ( !currentMatchingScalarRange.
includeUpper() && it.value().upper() >= currentMatchingScalarRange.
upper() ) ) )
135 currentMatchingScalarGroup = it.key();
136 currentMatchingScalarRange = it.value();
140 if ( currentMatchingVectorGroup >= 0 )
142 if ( currentMatchingScalarGroup >= 0 )
150 copyTriangularMeshes( layer, context );
153 copyScalarDatasetValues( layer );
154 copyVectorDatasetValues( layer );
156 calculateOutputSize();
159 prepareLabeling( layer, attrs );
170 if ( simplificationSettings.
isEnabled() )
174 mIsMeshSimplificationActive =
true;
187void QgsMeshLayerRenderer::calculateOutputSize()
194 const int width = int( screenBBox.
width() );
195 const int height = int( screenBBox.
height() );
199void QgsMeshLayerRenderer::copyScalarDatasetValues(
QgsMeshLayer *layer )
211 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
212 ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
213 ( cache->mDataInterpolationMethod == method ) &&
288 cache->mDatasetGroupsCount = datasetGroupCount;
289 cache->mActiveScalarDatasetIndex = datasetIndex;
290 cache->mDataInterpolationMethod = method;
300void QgsMeshLayerRenderer::copyVectorDatasetValues(
QgsMeshLayer *layer )
311 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
312 ( cache->mActiveVectorDatasetIndex == datasetIndex ) &&
332 const bool isScalar = metadata.
isScalar();
335 QgsDebugError( QStringLiteral(
"Dataset has no vector values" ) );
366 cache->mDatasetGroupsCount = datasetGroupCount;
367 cache->mActiveVectorDatasetIndex = datasetIndex;
381 std::unique_ptr< QgsScopedRuntimeProfile > profile;
382 std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
385 profile = std::make_unique< QgsScopedRuntimeProfile >(
mLayerName, QStringLiteral(
"rendering" ),
layerId() );
388 preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Preparing render" ), QStringLiteral(
"rendering" ) );
395 bool needsPainterClipPath =
false;
397 if ( needsPainterClipPath )
401 preparingProfile.reset();
403 renderScalarDataset();
406 renderVectorDataset();
408 registerLabelFeatures();
418void QgsMeshLayerRenderer::renderMesh()
425 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
428 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering mesh" ), QStringLiteral(
"rendering" ) );
445 const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
451 nativeFacesInExtent.values() );
465 QPainter *painter = context.
painter();
470 QPen pen = painter->pen();
471 pen.setCapStyle( Qt::FlatCap );
472 pen.setJoinStyle( Qt::MiterJoin );
475 pen.setWidthF( penWidth );
476 pen.setColor( settings.
color() );
477 painter->setPen( pen );
489 QPainter *painter = _painterForMeshFrame( context, settings );
494 for (
const int i : edgesInExtent )
499 if ( i >= edges.size() )
503 const int startVertexIndex = edge.first;
504 const int endVertexIndex = edge.second;
506 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
509 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
518void QgsMeshLayerRenderer::renderFaceMesh(
520 const QVector<QgsMeshFace> &faces,
521 const QList<int> &facesInExtent )
523 Q_ASSERT( settings.
isEnabled() || mIsEditable );
529 QPainter *painter = _painterForMeshFrame( context, settings );
532 QSet<QPair<int, int>> drawnEdges;
534 for (
const int i : facesInExtent )
539 if ( i < 0 || i >= faces.count() )
543 if ( face.size() < 2 )
546 for (
int j = 0; j < face.size(); ++j )
548 const int startVertexId = face[j];
549 const int endVertexId = face[( j + 1 ) % face.size()];
550 const QPair<int, int> thisEdge( startVertexId, endVertexId );
551 const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
552 if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
554 drawnEdges.insert( thisEdge );
555 drawnEdges.insert( thisEdgeReversed );
568void QgsMeshLayerRenderer::renderScalarDataset()
577 if ( groupIndex < 0 )
580 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
583 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering scalar datasets" ), QStringLiteral(
"rendering" ) );
591 renderScalarDatasetOnFaces( scalarSettings );
597 renderScalarDatasetOnEdges( scalarSettings );
613 for (
const int i : edgesInExtent )
618 if ( i >= edges.size() )
622 const int startVertexIndex = edge.first;
623 const int endVertexIndex = edge.second;
625 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
628 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
645 if ( shader->
shade( val, &r, &g, &b, &a ) )
647 return QColor( r, g, b, a );
654 const QgsPointXY pt( p1.
x() + fraction * ( p2.
x() - p1.
x() ),
655 p1.
y() + fraction * ( p2.
y() - p1.
y() ) );
672 interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
677 renderer.setOpacity( scalarSettings.
opacity() );
680 QImage img = bl->image();
683 context.
painter()->drawImage( 0, 0, img );
686void QgsMeshLayerRenderer::renderVectorDataset()
689 if ( groupIndex < 0 )
701 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
704 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr(
"Rendering vector datasets" ), QStringLiteral(
"rendering" ) );
707 std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
725void QgsMeshLayerRenderer::prepareLabeling(
QgsMeshLayer *layer, QSet<QString> &attributeNames )
734 if ( mLabelProvider )
739 c.lastScope()->setVariable( QStringLiteral(
"_native_mesh" ), QVariant::fromValue(
mNativeMesh ) );
742 engine->addProvider( mLabelProvider );
743 if ( !mLabelProvider->
prepare( context, attributeNames ) )
745 engine->removeProvider( mLabelProvider );
746 mLabelProvider =
nullptr;
753void QgsMeshLayerRenderer::registerLabelFeatures()
755 if ( !mLabelProvider )
768 const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
771 for (
const int i : nativeFacesInExtent )
779 scope->
setVariable( QStringLiteral(
"_mesh_face_index" ), i,
false );
783 f.setGeometry( geom );
791 const QSet<int> nativeVerticesInExtent = QgsMeshUtils::nativeVerticesFromTriangles( trianglesInExtent,
794 for (
const int i : nativeVerticesInExtent )
802 scope->
setVariable( QStringLiteral(
"_mesh_vertex_index" ), i,
false );
806 f.setGeometry( geom );
The Qgis class provides global constants for use throughout the application.
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ UseAdvancedEffects
Enable layer opacity and blending effects.
@ 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.
Single scope for storing variables and functions for use within a QgsExpressionContext.
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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Base class for feedback objects to be used for cancellation of something running in a worker thread.
A geometry is the spatial representation of a feature.
Class defining color to render mesh datasets.
Represents a simple line renderer with width and color varying depending on values.
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.
Represents a width than can vary depending on values.
The QgsLabelingEngine class provides map labeling functionality.
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...
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...
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.
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.
virtual QgsMesh3DAveragingMethod * clone() const =0
Clone the instance.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
bool isValid() const
Whether the block is valid.
QgsMeshDatasetIndex is 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.
bool labelFaces() const
Returns false if labeling mesh vertices, true if labeling mesh faces.
virtual QList< QgsLabelFeature * > registerFeature(const QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry=QgsGeometry(), const QgsSymbol *symbol=nullptr)
Register a feature for labeling as one or more QgsLabelFeature objects stored into mLabels.
virtual bool prepare(QgsRenderContext &context, QSet< QString > &attributeNames)
Prepare for registration of features.
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 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)
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 object.
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.
double opacity() const
Returns opacity.
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.
DataResamplingMethod dataResamplingMethod() const
Returns the type of interpolation to use to convert face defined datasets to values on vertices.
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.
void setActiveVectorDatasetGroup(int activeVectorDatasetGroup)
Sets the active vector dataset group.
QgsMeshRendererScalarSettings scalarSettings(int groupIndex) const
Returns renderer settings.
int activeVectorDatasetGroup() const
Returns the active vector dataset group.
QgsMesh3DAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
int activeScalarDatasetGroup() const
Returns the active scalar dataset group.
QgsMeshRendererVectorSettings vectorSettings(int groupIndex) const
Returns renderer settings.
void setActiveScalarDatasetGroup(int activeScalarDatasetGroup)
Sets the active scalar dataset group.
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.
A class to represent a 2D point.
QPointF toQPointF() const
Converts a point to a QPointF.
Point geometry type, with support for z-dimension and m-values.
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.
Interface for all raster shaders.
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.
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).
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.
Raster renderer pipe for single band pseudocolor.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
int levelOfDetail() const
Returns the corresponding index of level of detail on which this mesh is associated.
QList< int > edgeIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of edges intersecting given bounding box It uses spatial indexing.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
const QVector< QgsMeshEdge > & edges() const
Returns edges.
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains mesh elements of given type.
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
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.
Mesh - vertices, edges and faces.
int vertexCount() const
Returns number of vertices.
QVector< QgsMeshVertex > vertices
QgsMeshFace face(int index) const
Returns a face at the index.
QVector< QgsMeshFace > faces
QgsMeshVertex vertex(int index) const
Returns a vertex at the index.