QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsmeshlayerrenderer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshlayerrenderer.cpp
3 ------------------------
4 begin : April 2018
5 copyright : (C) 2018 by Peter Petrik
6 email : zilolv at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include <memory>
19#include <QSet>
20#include <QPair>
21#include <QLinearGradient>
22#include <QBrush>
23#include <QPointer>
24#include <algorithm>
25
27
28#include "qgsfield.h"
29#include "qgslogger.h"
30#include "qgsmeshlayer.h"
31#include "qgspointxy.h"
32#include "qgsrenderer.h"
34#include "qgsrastershader.h"
36#include "qgsmeshlayerutils.h"
39#include "qgsfillsymbollayer.h"
40#include "qgssettings.h"
41#include "qgsstyle.h"
43#include "qgsmapclippingutils.h"
44#include "qgscolorrampshader.h"
45
47 QgsMeshLayer *layer,
48 QgsRenderContext &context )
49 : QgsMapLayerRenderer( layer->id(), &context )
50 , mIsEditable( layer->isEditable() )
51 , mFeedback( new QgsMeshLayerRendererFeedback )
52 , mRendererSettings( layer->rendererSettings() )
53 , mLayerOpacity( layer->opacity() )
54{
55 // make copies for mesh data
56 // cppcheck-suppress assertWithSideEffect
57 Q_ASSERT( layer->nativeMesh() );
58 // cppcheck-suppress assertWithSideEffect
59 Q_ASSERT( layer->triangularMesh() );
60 // cppcheck-suppress assertWithSideEffect
61 Q_ASSERT( layer->rendererCache() );
62 // cppcheck-suppress assertWithSideEffect
63 Q_ASSERT( layer->dataProvider() );
64
65 mReadyToCompose = false;
66
67 // copy native mesh
68 mNativeMesh = *( layer->nativeMesh() );
69 mLayerExtent = layer->extent();
70
71 // copy triangular mesh
72 copyTriangularMeshes( layer, context );
73
74 // copy datasets
75 copyScalarDatasetValues( layer );
76 copyVectorDatasetValues( layer );
77
78 calculateOutputSize();
79
81}
82
83void QgsMeshLayerRenderer::copyTriangularMeshes( QgsMeshLayer *layer, QgsRenderContext &context )
84{
85 // handle level of details of mesh
86 const QgsMeshSimplificationSettings simplificationSettings = layer->meshSimplificationSettings();
87 if ( simplificationSettings.isEnabled() )
88 {
89 const double triangleSize = simplificationSettings.meshResolution() * context.mapToPixel().mapUnitsPerPixel();
90 mTriangularMesh = *( layer->triangularMesh( triangleSize ) );
91 mIsMeshSimplificationActive = true;
92 }
93 else
94 {
95 mTriangularMesh = *( layer->triangularMesh() );
96 }
97}
98
100{
101 return mFeedback.get();
102}
103
104void QgsMeshLayerRenderer::calculateOutputSize()
105{
106 // figure out image size
107 const QgsRenderContext &context = *renderContext();
108 const QgsRectangle extent = context.mapExtent();
109 const QgsMapToPixel mapToPixel = context.mapToPixel();
110 const QgsRectangle screenBBox = QgsMeshLayerUtils::boundingBoxToScreenRectangle( mapToPixel, extent );
111 const int width = int( screenBBox.width() );
112 const int height = int( screenBBox.height() );
113 mOutputSize = QSize( width, height );
114}
115
116void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
117{
118 QgsMeshDatasetIndex datasetIndex;
119 if ( renderContext()->isTemporal() )
120 datasetIndex = layer->activeScalarDatasetAtTime( renderContext()->temporalRange() );
121 else
122 datasetIndex = layer->staticScalarDatasetIndex();
123
124 // Find out if we can use cache up to date. If yes, use it and return
125 const int datasetGroupCount = layer->datasetGroupCount();
127 QgsMeshLayerRendererCache *cache = layer->rendererCache();
128 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
129 ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
130 ( cache->mDataInterpolationMethod == method ) &&
131 ( QgsMesh3dAveragingMethod::equals( cache->mScalarAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
132 )
133 {
134 mScalarDatasetValues = cache->mScalarDatasetValues;
135 mScalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
136 mScalarDataType = cache->mScalarDataType;
137 mScalarDatasetMinimum = cache->mScalarDatasetMinimum;
138 mScalarDatasetMaximum = cache->mScalarDatasetMaximum;
139 return;
140 }
141
142 // Cache is not up-to-date, gather data
143 if ( datasetIndex.isValid() )
144 {
145 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex.group() );
146 mScalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
147
148 // populate scalar values
149 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mScalarDataType );
150 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
151 layer,
152 datasetIndex,
153 0,
154 count );
155
156 if ( vals.isValid() )
157 {
158 // vals could be scalar or vectors, for contour rendering we want always magnitude
159 mScalarDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
160 }
161 else
162 {
163 mScalarDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
164 }
165
166 // populate face active flag, always defined on faces
168 datasetIndex,
169 0,
170 mNativeMesh.faces.count() );
171
172 // for data on faces, there could be request to interpolate the data to vertices
174 {
175 if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces )
176 {
177 mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnVertices;
178 mScalarDatasetValues = QgsMeshLayerUtils::interpolateFromFacesData(
183 method
184 );
185 }
186 else if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
187 {
188 mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnFaces;
189 mScalarDatasetValues = QgsMeshLayerUtils::resampleFromVerticesToFaces(
194 method
195 );
196 }
197 }
198
199 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
200 mScalarDatasetMinimum = datasetMetadata.minimum();
201 mScalarDatasetMaximum = datasetMetadata.maximum();
202 }
203
204 // update cache
205 cache->mDatasetGroupsCount = datasetGroupCount;
206 cache->mActiveScalarDatasetIndex = datasetIndex;
207 cache->mDataInterpolationMethod = method;
208 cache->mScalarDatasetValues = mScalarDatasetValues;
209 cache->mScalarActiveFaceFlagValues = mScalarActiveFaceFlagValues;
210 cache->mScalarDataType = mScalarDataType;
211 cache->mScalarDatasetMinimum = mScalarDatasetMinimum;
212 cache->mScalarDatasetMaximum = mScalarDatasetMaximum;
213 cache->mScalarAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
214}
215
216
217void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
218{
219 QgsMeshDatasetIndex datasetIndex;
220 if ( renderContext()->isTemporal() )
221 datasetIndex = layer->activeVectorDatasetAtTime( renderContext()->temporalRange() );
222 else
223 datasetIndex = layer->staticVectorDatasetIndex();
224
225 // Find out if we can use cache up to date. If yes, use it and return
226 const int datasetGroupCount = layer->datasetGroupCount();
227 QgsMeshLayerRendererCache *cache = layer->rendererCache();
228 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
229 ( cache->mActiveVectorDatasetIndex == datasetIndex ) &&
230 ( QgsMesh3dAveragingMethod::equals( cache->mVectorAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
231 )
232 {
233 mVectorDatasetValues = cache->mVectorDatasetValues;
234 mVectorDatasetValuesMag = cache->mVectorDatasetValuesMag;
235 mVectorDatasetMagMinimum = cache->mVectorDatasetMagMinimum;
236 mVectorDatasetMagMaximum = cache->mVectorDatasetMagMaximum;
237 mVectorDatasetGroupMagMinimum = cache->mVectorDatasetMagMinimum;
238 mVectorDatasetGroupMagMaximum = cache->mVectorDatasetMagMaximum;
239 mVectorDataType = cache->mVectorDataType;
240 return;
241 }
242
243 // Cache is not up-to-date, gather data
244 if ( datasetIndex.isValid() )
245 {
246 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex );
247
248 const bool isScalar = metadata.isScalar();
249 if ( isScalar )
250 {
251 QgsDebugMsg( QStringLiteral( "Dataset has no vector values" ) );
252 }
253 else
254 {
255 mVectorDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
256
259
260 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mVectorDataType );
261 mVectorDatasetValues = QgsMeshLayerUtils::datasetValues(
262 layer,
263 datasetIndex,
264 0,
265 count );
266
268 mVectorDatasetValuesMag = QgsMeshLayerUtils::calculateMagnitudes( mVectorDatasetValues );
269 else
270 mVectorDatasetValuesMag = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
271
272 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
273 mVectorDatasetMagMinimum = datasetMetadata.minimum();
274 mVectorDatasetMagMaximum = datasetMetadata.maximum();
275 }
276 }
277
278 // update cache
279 cache->mDatasetGroupsCount = datasetGroupCount;
280 cache->mActiveVectorDatasetIndex = datasetIndex;
281 cache->mVectorDatasetValues = mVectorDatasetValues;
282 cache->mVectorDatasetValuesMag = mVectorDatasetValuesMag;
283 cache->mVectorDatasetMagMinimum = mVectorDatasetMagMinimum;
284 cache->mVectorDatasetMagMaximum = mVectorDatasetMagMaximum;
285 cache->mVectorDatasetGroupMagMinimum = mVectorDatasetMagMinimum;
286 cache->mVectorDatasetGroupMagMaximum = mVectorDatasetMagMaximum;
287 cache->mVectorDataType = mVectorDataType;
288 cache->mVectorAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
289}
290
292{
293 mReadyToCompose = false;
294 const QgsScopedQPainterState painterState( renderContext()->painter() );
295 if ( !mClippingRegions.empty() )
296 {
297 bool needsPainterClipPath = false;
299 if ( needsPainterClipPath )
300 renderContext()->painter()->setClipPath( path, Qt::IntersectClip );
301 }
302
303 renderScalarDataset();
304 mReadyToCompose = true;
305 renderMesh();
306 renderVectorDataset();
307
308 return !renderContext()->renderingStopped();
309}
310
312{
313 return renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
314}
315
316void QgsMeshLayerRenderer::renderMesh()
317{
318 if ( !mRendererSettings.nativeMeshSettings().isEnabled() && !mIsEditable &&
321 return;
322
323 // triangular mesh
324 const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( renderContext()->mapExtent() );
326 {
327 renderFaceMesh(
330 trianglesInExtent );
331 }
332
333 // native mesh
334 if ( ( mRendererSettings.nativeMeshSettings().isEnabled() || mIsEditable ) &&
336 {
337 const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
339
340 renderFaceMesh(
343 nativeFacesInExtent.values() );
344 }
345
346 // edge mesh
348 {
349 const QList<int> edgesInExtent = mTriangularMesh.edgeIndexesForRectangle( renderContext()->mapExtent() );
350 renderEdgeMesh( mRendererSettings.edgeMeshSettings(), edgesInExtent );
351 }
352}
353
354static QPainter *_painterForMeshFrame( QgsRenderContext &context, const QgsMeshRendererMeshSettings &settings )
355{
356 // Set up the render configuration options
357 QPainter *painter = context.painter();
358
359 painter->save();
360 context.setPainterFlagsUsingContext( painter );
361
362 QPen pen = painter->pen();
363 pen.setCapStyle( Qt::FlatCap );
364 pen.setJoinStyle( Qt::MiterJoin );
365
366 const double penWidth = context.convertToPainterUnits( settings.lineWidth(), settings.lineWidthUnit() );
367 pen.setWidthF( penWidth );
368 pen.setColor( settings.color() );
369 painter->setPen( pen );
370 return painter;
371}
372
373void QgsMeshLayerRenderer::renderEdgeMesh( const QgsMeshRendererMeshSettings &settings, const QList<int> &edgesInExtent )
374{
375 Q_ASSERT( settings.isEnabled() );
376
377 if ( !mTriangularMesh.contains( QgsMesh::ElementType::Edge ) )
378 return;
379
380 QgsRenderContext &context = *renderContext();
381 QPainter *painter = _painterForMeshFrame( context, settings );
382
383 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
384 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
385
386 for ( const int i : edgesInExtent )
387 {
388 if ( context.renderingStopped() )
389 break;
390
391 if ( i >= edges.size() )
392 continue;
393
394 const QgsMeshEdge &edge = edges[i];
395 const int startVertexIndex = edge.first;
396 const int endVertexIndex = edge.second;
397
398 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
399 continue;
400
401 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
402 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
403 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
404 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
405 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
406 }
407 painter->restore();
408};
409
410void QgsMeshLayerRenderer::renderFaceMesh(
411 const QgsMeshRendererMeshSettings &settings,
412 const QVector<QgsMeshFace> &faces,
413 const QList<int> &facesInExtent )
414{
415 Q_ASSERT( settings.isEnabled() || mIsEditable );
416
417 if ( !mTriangularMesh.contains( QgsMesh::ElementType::Face ) )
418 return;
419
420 QgsRenderContext &context = *renderContext();
421 QPainter *painter = _painterForMeshFrame( context, settings );
422
423 const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
424 QSet<QPair<int, int>> drawnEdges;
425
426 for ( const int i : facesInExtent )
427 {
428 if ( context.renderingStopped() )
429 break;
430
431 if ( i < 0 || i >= faces.count() )
432 continue;
433
434 const QgsMeshFace &face = faces[i];
435 if ( face.size() < 2 )
436 continue;
437
438 for ( int j = 0; j < face.size(); ++j )
439 {
440 const int startVertexId = face[j];
441 const int endVertexId = face[( j + 1 ) % face.size()];
442 const QPair<int, int> thisEdge( startVertexId, endVertexId );
443 const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
444 if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
445 continue;
446 drawnEdges.insert( thisEdge );
447 drawnEdges.insert( thisEdgeReversed );
448
449 const QgsMeshVertex &startVertex = vertices[startVertexId];
450 const QgsMeshVertex &endVertex = vertices[endVertexId];
451 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
452 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
453 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
454 }
455 }
456
457 painter->restore();
458}
459
460void QgsMeshLayerRenderer::renderScalarDataset()
461{
462 if ( mScalarDatasetValues.isEmpty() )
463 return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET
464
465 if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
466 return; // only NODATA values
467
468 const int groupIndex = mRendererSettings.activeScalarDatasetGroup();
469 if ( groupIndex < 0 )
470 return; // no shader
471
472 const QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( groupIndex );
473
474 if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Face ) ) &&
475 ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnEdges ) )
476 {
477 renderScalarDatasetOnFaces( scalarSettings );
478 }
479
480 if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Edge ) ) &&
481 ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnFaces ) )
482 {
483 renderScalarDatasetOnEdges( scalarSettings );
484 }
485}
486
487void QgsMeshLayerRenderer::renderScalarDatasetOnEdges( const QgsMeshRendererScalarSettings &scalarSettings )
488{
489 QgsRenderContext &context = *renderContext();
490 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
491 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
492 const QList<int> egdesInExtent = mTriangularMesh.edgeIndexesForRectangle( context.mapExtent() );
493
494 QgsInterpolatedLineRenderer edgePlotter;
495 edgePlotter.setInterpolatedColor( QgsInterpolatedLineColor( scalarSettings.colorRampShader() ) );
496 edgePlotter.setInterpolatedWidth( QgsInterpolatedLineWidth( scalarSettings.edgeStrokeWidth() ) );
497 edgePlotter.setWidthUnit( scalarSettings.edgeStrokeWidthUnit() );
498
499 for ( const int i : egdesInExtent )
500 {
501 if ( context.renderingStopped() )
502 break;
503
504 if ( i >= edges.size() )
505 continue;
506
507 const QgsMeshEdge &edge = edges[i];
508 const int startVertexIndex = edge.first;
509 const int endVertexIndex = edge.second;
510
511 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
512 continue;
513
514 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
515 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
516
517 if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnEdges )
518 {
519 edgePlotter.render( mScalarDatasetValues[i], mScalarDatasetValues[i], startVertex, endVertex, context );
520 }
521 else
522 {
523 edgePlotter.render( mScalarDatasetValues[startVertexIndex], mScalarDatasetValues[endVertexIndex], startVertex, endVertex, context );
524 }
525 }
526}
527
528QColor QgsMeshLayerRenderer::colorAt( QgsColorRampShader *shader, double val ) const
529{
530 int r, g, b, a;
531 if ( shader->shade( val, &r, &g, &b, &a ) )
532 {
533 return QColor( r, g, b, a );
534 }
535 return QColor();
536}
537
538QgsPointXY QgsMeshLayerRenderer::fractionPoint( const QgsPointXY &p1, const QgsPointXY &p2, double fraction ) const
539{
540 const QgsPointXY pt( p1.x() + fraction * ( p2.x() - p1.x() ),
541 p1.y() + fraction * ( p2.y() - p1.y() ) );
542 return pt;
543}
544
545void QgsMeshLayerRenderer::renderScalarDatasetOnFaces( const QgsMeshRendererScalarSettings &scalarSettings )
546{
547 QgsRenderContext &context = *renderContext();
548
549 QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() );
551 sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
552 QgsMeshLayerInterpolator interpolator( mTriangularMesh,
556 context,
557 mOutputSize );
558 interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
559 QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
560 renderer.setClassificationMin( scalarSettings.classificationMinimum() );
561 renderer.setClassificationMax( scalarSettings.classificationMaximum() );
562 renderer.setOpacity( scalarSettings.opacity() );
563
564 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, context.mapExtent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
565 const QImage img = bl->image();
566
567 context.painter()->drawImage( 0, 0, img );
568}
569
570void QgsMeshLayerRenderer::renderVectorDataset()
571{
572 const int groupIndex = mRendererSettings.activeVectorDatasetGroup();
573 if ( groupIndex < 0 )
574 return;
575
577 return; // no data at all
578
579 if ( std::isnan( mVectorDatasetMagMinimum ) || std::isnan( mVectorDatasetMagMaximum ) )
580 return; // only NODATA values
581
582 if ( !( mVectorDatasetMagMaximum > 0 ) )
583 return; //all vector are null vector
584
585 std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
593 mRendererSettings.vectorSettings( groupIndex ),
594 *renderContext(),
596 mOutputSize ) );
597
598 if ( renderer )
599 renderer->draw();
600}
601
@ UseAdvancedEffects
Enable layer opacity and blending effects.
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 and new RGB value based on one input value.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
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(QgsUnitTypes::RenderUnit strokeWidthUnit)
Sets the unit of the stroke width.
Represents a width than can vary depending on values.
static QList< QgsMapClippingRegion > collectClippingRegionsForLayer(const QgsRenderContext &context, const QgsMapLayer *layer)
Collects the list of map clipping regions from a context which apply to a map layer.
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > &regions, const QgsRenderContext &context, QgsMapLayerType layerType, bool &shouldClip)
Returns a QPainterPath representing the intersection of clipping regions from context which should be...
Base class for utility classes that encapsulate information necessary for rendering of map layers.
bool mReadyToCompose
The flag must be set to false in renderer's constructor if wants to use the smarter map redraws funct...
QgsRenderContext * renderContext()
Returns the render context associated with the renderer.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
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.
Definition: qgsmaptopixel.h:90
virtual QgsMesh3dAveragingMethod * clone() const =0
Clone the instance.
static bool equals(const QgsMesh3dAveragingMethod *a, const QgsMesh3dAveragingMethod *b)
Returns whether two methods equal.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
bool isValid() const
Whether the block is valid.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
bool isScalar() const
Returns whether dataset group has scalar data.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
double minimum() const
Returns minimum scalar value/vector magnitude present for whole dataset group.
double maximum() const
Returns maximum scalar value/vector magnitude present for whole dataset group.
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.
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
double maximum() const
Returns maximum scalar value/vector magnitude present for the dataset.
double minimum() const
Returns minimum scalar value/vector magnitude present for the dataset.
QgsMeshDatasetGroupMetadata::DataType mScalarDataType
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).
QVector< double > mVectorDatasetValuesMag
QgsMeshRendererSettings mRendererSettings
bool forceRasterRender() const override
Returns true if the renderer must be rendered to a raster paint device (e.g.
QgsMeshDatasetGroupMetadata::DataType mVectorDataType
QList< QgsMapClippingRegion > mClippingRegions
QgsFeedback * feedback() const override
Access to feedback object of the layer renderer (may be nullptr)
QgsMeshDataBlock mVectorDatasetValues
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:100
QgsRectangle extent() const override
Returns the extent of the layer.
int datasetGroupCount() const
Returns the dataset groups count handle by the layer.
QgsMeshDatasetIndex activeScalarDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active scalar group depending on the time range.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QgsMeshDatasetIndex staticVectorDatasetIndex() const
Returns the static vector dataset index that is rendered if the temporal properties is not active.
QgsMeshSimplificationSettings meshSimplificationSettings() const
Returns mesh simplification settings.
QgsMeshDatasetIndex activeVectorDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active vector group depending on the time range If the temporal properties...
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether the faces are active for particular dataset.
QgsMeshDatasetIndex staticScalarDatasetIndex() const
Returns the static scalar dataset index that is rendered if the temporal properties is not active.
QgsMeshDatasetMetadata datasetMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset metadata.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
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.
QgsUnitTypes::RenderUnit lineWidthUnit() const
Returns units of the width of the mesh frame.
double lineWidth() const
Returns line width used for rendering (in millimeters)
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.
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.
QgsUnitTypes::RenderUnit edgeStrokeWidthUnit() const
Returns the stroke width unit used to render edges scalar dataset.
QgsInterpolatedLineWidth edgeStrokeWidth() const
Returns the stroke width used to render edges scalar dataset.
QgsMeshRendererScalarSettings scalarSettings(int groupIndex) const
Returns renderer settings.
int activeVectorDatasetGroup() const
Returns the active vector dataset group.
int activeScalarDatasetGroup() const
Returns the active scalar dataset group.
QgsMesh3dAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
QgsMeshRendererVectorSettings vectorSettings(int groupIndex) const
Returns renderer settings.
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.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:169
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
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.
Definition: qgsrectangle.h:42
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
Contains information about the context of a rendering operation.
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 ...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
bool testFlag(Qgis::RenderContextFlag flag) const
Check whether a particular flag is enabled.
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...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
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.
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
CORE_EXPORT QSet< int > nativeFacesFromTriangles(const QList< int > &triangleIndexes, const QVector< int > &trianglesToNativeFaces)
Returns unique native faces indexes from list of triangle indexes.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2527
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QVector< int > QgsMeshFace
List of vertex indexes.
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
QVector< QgsMeshFace > faces