QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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 "qgslogger.h"
29#include "qgsmeshlayer.h"
30#include "qgspointxy.h"
32#include "qgsrastershader.h"
34#include "qgsmeshlayerutils.h"
36#include "qgsmapclippingutils.h"
37#include "qgscolorrampshader.h"
39
41 QgsMeshLayer *layer,
42 QgsRenderContext &context )
43 : QgsMapLayerRenderer( layer->id(), &context )
44 , mIsEditable( layer->isEditable() )
45 , mFeedback( new QgsMeshLayerRendererFeedback )
46 , mRendererSettings( layer->rendererSettings() )
47 , mLayerOpacity( layer->opacity() )
48{
49 // make copies for mesh data
50 // cppcheck-suppress assertWithSideEffect
51 Q_ASSERT( layer->nativeMesh() );
52 // cppcheck-suppress assertWithSideEffect
53 Q_ASSERT( layer->triangularMesh() );
54 // cppcheck-suppress assertWithSideEffect
55 Q_ASSERT( layer->rendererCache() );
56 // cppcheck-suppress assertWithSideEffect
57 Q_ASSERT( layer->dataProvider() );
58
59 mReadyToCompose = false;
60
61 // copy native mesh
62 mNativeMesh = *( layer->nativeMesh() );
63 mLayerExtent = layer->extent();
64
65 // copy triangular mesh
66 copyTriangularMeshes( layer, context );
67
68 // copy datasets
69 copyScalarDatasetValues( layer );
70 copyVectorDatasetValues( layer );
71
72 calculateOutputSize();
73
75
76 if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() )
77 {
81 }
82}
83
84void QgsMeshLayerRenderer::copyTriangularMeshes( QgsMeshLayer *layer, QgsRenderContext &context )
85{
86 // handle level of details of mesh
87 const QgsMeshSimplificationSettings simplificationSettings = layer->meshSimplificationSettings();
88 if ( simplificationSettings.isEnabled() )
89 {
90 const double triangleSize = simplificationSettings.meshResolution() * context.mapToPixel().mapUnitsPerPixel();
91 mTriangularMesh = *( layer->triangularMesh( triangleSize ) );
92 mIsMeshSimplificationActive = true;
93 }
94 else
95 {
96 mTriangularMesh = *( layer->triangularMesh() );
97 }
98}
99
101{
102 return mFeedback.get();
103}
104
105void QgsMeshLayerRenderer::calculateOutputSize()
106{
107 // figure out image size
108 const QgsRenderContext &context = *renderContext();
109 const QgsRectangle extent = context.mapExtent();
110 const QgsMapToPixel mapToPixel = context.mapToPixel();
111 const QgsRectangle screenBBox = QgsMeshLayerUtils::boundingBoxToScreenRectangle( mapToPixel, extent );
112 const int width = int( screenBBox.width() );
113 const int height = int( screenBBox.height() );
114 mOutputSize = QSize( width, height );
115}
116
117void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
118{
119 QgsMeshDatasetIndex datasetIndex;
120 if ( renderContext()->isTemporal() )
121 datasetIndex = layer->activeScalarDatasetAtTime( renderContext()->temporalRange() );
122 else
123 datasetIndex = layer->staticScalarDatasetIndex();
124
125 // Find out if we can use cache up to date. If yes, use it and return
126 const int datasetGroupCount = layer->datasetGroupCount();
128 QgsMeshLayerRendererCache *cache = layer->rendererCache();
129 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
130 ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
131 ( cache->mDataInterpolationMethod == method ) &&
132 ( QgsMesh3dAveragingMethod::equals( cache->mScalarAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
133 )
134 {
135 mScalarDatasetValues = cache->mScalarDatasetValues;
136 mScalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
137 mScalarDataType = cache->mScalarDataType;
138 mScalarDatasetMinimum = cache->mScalarDatasetMinimum;
139 mScalarDatasetMaximum = cache->mScalarDatasetMaximum;
140 return;
141 }
142
143 // Cache is not up-to-date, gather data
144 if ( datasetIndex.isValid() )
145 {
146 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex.group() );
147 mScalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
148
149 // populate scalar values
150 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mScalarDataType );
151 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
152 layer,
153 datasetIndex,
154 0,
155 count );
156
157 if ( vals.isValid() )
158 {
159 // vals could be scalar or vectors, for contour rendering we want always magnitude
160 mScalarDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
161 }
162 else
163 {
164 mScalarDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
165 }
166
167 // populate face active flag, always defined on faces
169 datasetIndex,
170 0,
171 mNativeMesh.faces.count() );
172
173 // for data on faces, there could be request to interpolate the data to vertices
175 {
176 if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces )
177 {
178 mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnVertices;
179 mScalarDatasetValues = QgsMeshLayerUtils::interpolateFromFacesData(
184 method
185 );
186 }
187 else if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
188 {
189 mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnFaces;
190 mScalarDatasetValues = QgsMeshLayerUtils::resampleFromVerticesToFaces(
195 method
196 );
197 }
198 }
199
200 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
201 mScalarDatasetMinimum = datasetMetadata.minimum();
202 mScalarDatasetMaximum = datasetMetadata.maximum();
203 }
204
205 // update cache
206 cache->mDatasetGroupsCount = datasetGroupCount;
207 cache->mActiveScalarDatasetIndex = datasetIndex;
208 cache->mDataInterpolationMethod = method;
209 cache->mScalarDatasetValues = mScalarDatasetValues;
210 cache->mScalarActiveFaceFlagValues = mScalarActiveFaceFlagValues;
211 cache->mScalarDataType = mScalarDataType;
212 cache->mScalarDatasetMinimum = mScalarDatasetMinimum;
213 cache->mScalarDatasetMaximum = mScalarDatasetMaximum;
214 cache->mScalarAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
215}
216
217
218void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
219{
220 QgsMeshDatasetIndex datasetIndex;
221 if ( renderContext()->isTemporal() )
222 datasetIndex = layer->activeVectorDatasetAtTime( renderContext()->temporalRange() );
223 else
224 datasetIndex = layer->staticVectorDatasetIndex();
225
226 // Find out if we can use cache up to date. If yes, use it and return
227 const int datasetGroupCount = layer->datasetGroupCount();
228 QgsMeshLayerRendererCache *cache = layer->rendererCache();
229 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
230 ( cache->mActiveVectorDatasetIndex == datasetIndex ) &&
231 ( QgsMesh3dAveragingMethod::equals( cache->mVectorAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
232 )
233 {
234 mVectorDatasetValues = cache->mVectorDatasetValues;
235 mVectorDatasetValuesMag = cache->mVectorDatasetValuesMag;
236 mVectorDatasetMagMinimum = cache->mVectorDatasetMagMinimum;
237 mVectorDatasetMagMaximum = cache->mVectorDatasetMagMaximum;
238 mVectorDatasetGroupMagMinimum = cache->mVectorDatasetMagMinimum;
239 mVectorDatasetGroupMagMaximum = cache->mVectorDatasetMagMaximum;
240 mVectorActiveFaceFlagValues = cache->mVectorActiveFaceFlagValues;
241 mVectorDataType = cache->mVectorDataType;
242 return;
243 }
244
245 // Cache is not up-to-date, gather data
246 if ( datasetIndex.isValid() )
247 {
248 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex );
249
250 const bool isScalar = metadata.isScalar();
251 if ( isScalar )
252 {
253 QgsDebugMsg( QStringLiteral( "Dataset has no vector values" ) );
254 }
255 else
256 {
257 mVectorDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
258
261
262 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mVectorDataType );
263 mVectorDatasetValues = QgsMeshLayerUtils::datasetValues(
264 layer,
265 datasetIndex,
266 0,
267 count );
268
270 mVectorDatasetValuesMag = QgsMeshLayerUtils::calculateMagnitudes( mVectorDatasetValues );
271 else
272 mVectorDatasetValuesMag = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
273
274 // populate face active flag
275 mVectorActiveFaceFlagValues = layer->areFacesActive( datasetIndex, 0, mNativeMesh.faces.count() );
276
277 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
278 mVectorDatasetMagMinimum = datasetMetadata.minimum();
279 mVectorDatasetMagMaximum = datasetMetadata.maximum();
280 }
281 }
282
283 // update cache
284 cache->mDatasetGroupsCount = datasetGroupCount;
285 cache->mActiveVectorDatasetIndex = datasetIndex;
286 cache->mVectorDatasetValues = mVectorDatasetValues;
287 cache->mVectorDatasetValuesMag = mVectorDatasetValuesMag;
288 cache->mVectorDatasetMagMinimum = mVectorDatasetMagMinimum;
289 cache->mVectorDatasetMagMaximum = mVectorDatasetMagMaximum;
290 cache->mVectorDatasetGroupMagMinimum = mVectorDatasetMagMinimum;
291 cache->mVectorDatasetGroupMagMaximum = mVectorDatasetMagMaximum;
292 cache->mVectorActiveFaceFlagValues = mVectorActiveFaceFlagValues;
293 cache->mVectorDataType = mVectorDataType;
294 cache->mVectorAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
295}
296
298{
299 mReadyToCompose = false;
300 const QgsScopedQPainterState painterState( renderContext()->painter() );
301 if ( !mClippingRegions.empty() )
302 {
303 bool needsPainterClipPath = false;
304 const QPainterPath path = QgsMapClippingUtils::calculatePainterClipRegion( mClippingRegions, *renderContext(), Qgis::LayerType::Mesh, needsPainterClipPath );
305 if ( needsPainterClipPath )
306 renderContext()->painter()->setClipPath( path, Qt::IntersectClip );
307 }
308
309 renderScalarDataset();
310 mReadyToCompose = true;
311 renderMesh();
312 renderVectorDataset();
313
314 return !renderContext()->renderingStopped();
315}
316
318{
319 return renderContext()->testFlag( Qgis::RenderContextFlag::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
320}
321
322void QgsMeshLayerRenderer::renderMesh()
323{
324 if ( !mRendererSettings.nativeMeshSettings().isEnabled() && !mIsEditable &&
327 return;
328
329 // triangular mesh
330 const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( renderContext()->mapExtent() );
332 {
333 renderFaceMesh(
336 trianglesInExtent );
337 }
338
339 // native mesh
340 if ( ( mRendererSettings.nativeMeshSettings().isEnabled() || mIsEditable ) &&
342 {
343 const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
345
346 renderFaceMesh(
349 nativeFacesInExtent.values() );
350 }
351
352 // edge mesh
354 {
355 const QList<int> edgesInExtent = mTriangularMesh.edgeIndexesForRectangle( renderContext()->mapExtent() );
356 renderEdgeMesh( mRendererSettings.edgeMeshSettings(), edgesInExtent );
357 }
358}
359
360static QPainter *_painterForMeshFrame( QgsRenderContext &context, const QgsMeshRendererMeshSettings &settings )
361{
362 // Set up the render configuration options
363 QPainter *painter = context.painter();
364
365 painter->save();
366 context.setPainterFlagsUsingContext( painter );
367
368 QPen pen = painter->pen();
369 pen.setCapStyle( Qt::FlatCap );
370 pen.setJoinStyle( Qt::MiterJoin );
371
372 const double penWidth = context.convertToPainterUnits( settings.lineWidth(), settings.lineWidthUnit() );
373 pen.setWidthF( penWidth );
374 pen.setColor( settings.color() );
375 painter->setPen( pen );
376 return painter;
377}
378
379void QgsMeshLayerRenderer::renderEdgeMesh( const QgsMeshRendererMeshSettings &settings, const QList<int> &edgesInExtent )
380{
381 Q_ASSERT( settings.isEnabled() );
382
383 if ( !mTriangularMesh.contains( QgsMesh::ElementType::Edge ) )
384 return;
385
386 QgsRenderContext &context = *renderContext();
387 QPainter *painter = _painterForMeshFrame( context, settings );
388
389 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
390 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
391
392 for ( const int i : edgesInExtent )
393 {
394 if ( context.renderingStopped() )
395 break;
396
397 if ( i >= edges.size() )
398 continue;
399
400 const QgsMeshEdge &edge = edges[i];
401 const int startVertexIndex = edge.first;
402 const int endVertexIndex = edge.second;
403
404 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
405 continue;
406
407 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
408 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
409 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
410 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
411 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
412 }
413 painter->restore();
414};
415
416void QgsMeshLayerRenderer::renderFaceMesh(
417 const QgsMeshRendererMeshSettings &settings,
418 const QVector<QgsMeshFace> &faces,
419 const QList<int> &facesInExtent )
420{
421 Q_ASSERT( settings.isEnabled() || mIsEditable );
422
423 if ( !mTriangularMesh.contains( QgsMesh::ElementType::Face ) )
424 return;
425
426 QgsRenderContext &context = *renderContext();
427 QPainter *painter = _painterForMeshFrame( context, settings );
428
429 const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
430 QSet<QPair<int, int>> drawnEdges;
431
432 for ( const int i : facesInExtent )
433 {
434 if ( context.renderingStopped() )
435 break;
436
437 if ( i < 0 || i >= faces.count() )
438 continue;
439
440 const QgsMeshFace &face = faces[i];
441 if ( face.size() < 2 )
442 continue;
443
444 for ( int j = 0; j < face.size(); ++j )
445 {
446 const int startVertexId = face[j];
447 const int endVertexId = face[( j + 1 ) % face.size()];
448 const QPair<int, int> thisEdge( startVertexId, endVertexId );
449 const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
450 if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
451 continue;
452 drawnEdges.insert( thisEdge );
453 drawnEdges.insert( thisEdgeReversed );
454
455 const QgsMeshVertex &startVertex = vertices[startVertexId];
456 const QgsMeshVertex &endVertex = vertices[endVertexId];
457 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
458 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
459 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
460 }
461 }
462
463 painter->restore();
464}
465
466void QgsMeshLayerRenderer::renderScalarDataset()
467{
468 if ( mScalarDatasetValues.isEmpty() )
469 return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET
470
471 if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
472 return; // only NODATA values
473
474 const int groupIndex = mRendererSettings.activeScalarDatasetGroup();
475 if ( groupIndex < 0 )
476 return; // no shader
477
478 const QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( groupIndex );
479
480 if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Face ) ) &&
481 ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnEdges ) )
482 {
483 renderScalarDatasetOnFaces( scalarSettings );
484 }
485
486 if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Edge ) ) &&
487 ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnFaces ) )
488 {
489 renderScalarDatasetOnEdges( scalarSettings );
490 }
491}
492
493void QgsMeshLayerRenderer::renderScalarDatasetOnEdges( const QgsMeshRendererScalarSettings &scalarSettings )
494{
495 QgsRenderContext &context = *renderContext();
496 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
497 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
498 const QList<int> egdesInExtent = mTriangularMesh.edgeIndexesForRectangle( context.mapExtent() );
499
500 QgsInterpolatedLineRenderer edgePlotter;
501 edgePlotter.setInterpolatedColor( QgsInterpolatedLineColor( scalarSettings.colorRampShader() ) );
502 edgePlotter.setInterpolatedWidth( QgsInterpolatedLineWidth( scalarSettings.edgeStrokeWidth() ) );
503 edgePlotter.setWidthUnit( scalarSettings.edgeStrokeWidthUnit() );
504
505 for ( const int i : egdesInExtent )
506 {
507 if ( context.renderingStopped() )
508 break;
509
510 if ( i >= edges.size() )
511 continue;
512
513 const QgsMeshEdge &edge = edges[i];
514 const int startVertexIndex = edge.first;
515 const int endVertexIndex = edge.second;
516
517 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
518 continue;
519
520 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
521 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
522
523 if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnEdges )
524 {
525 edgePlotter.render( mScalarDatasetValues[i], mScalarDatasetValues[i], startVertex, endVertex, context );
526 }
527 else
528 {
529 edgePlotter.render( mScalarDatasetValues[startVertexIndex], mScalarDatasetValues[endVertexIndex], startVertex, endVertex, context );
530 }
531 }
532}
533
534QColor QgsMeshLayerRenderer::colorAt( QgsColorRampShader *shader, double val ) const
535{
536 int r, g, b, a;
537 if ( shader->shade( val, &r, &g, &b, &a ) )
538 {
539 return QColor( r, g, b, a );
540 }
541 return QColor();
542}
543
544QgsPointXY QgsMeshLayerRenderer::fractionPoint( const QgsPointXY &p1, const QgsPointXY &p2, double fraction ) const
545{
546 const QgsPointXY pt( p1.x() + fraction * ( p2.x() - p1.x() ),
547 p1.y() + fraction * ( p2.y() - p1.y() ) );
548 return pt;
549}
550
551void QgsMeshLayerRenderer::renderScalarDatasetOnFaces( const QgsMeshRendererScalarSettings &scalarSettings )
552{
553 QgsRenderContext &context = *renderContext();
554
555 QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() );
557 sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
558 QgsMeshLayerInterpolator interpolator( mTriangularMesh,
562 context,
563 mOutputSize );
564 interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
565 interpolator.setElevationMapSettings( mRenderElevationMap, mElevationScale, mElevationOffset );
566 QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
567 renderer.setClassificationMin( scalarSettings.classificationMinimum() );
568 renderer.setClassificationMax( scalarSettings.classificationMaximum() );
569 renderer.setOpacity( scalarSettings.opacity() );
570
571 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, context.mapExtent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
572 const QImage img = bl->image();
573
574 context.painter()->drawImage( 0, 0, img );
575}
576
577void QgsMeshLayerRenderer::renderVectorDataset()
578{
579 const int groupIndex = mRendererSettings.activeVectorDatasetGroup();
580 if ( groupIndex < 0 )
581 return;
582
584 return; // no data at all
585
586 if ( std::isnan( mVectorDatasetMagMinimum ) || std::isnan( mVectorDatasetMagMaximum ) )
587 return; // only NODATA values
588
589 if ( !( mVectorDatasetMagMaximum > 0 ) )
590 return; //all vector are null vector
591
592 std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
600 mRendererSettings.vectorSettings( groupIndex ),
601 *renderContext(),
603 mFeedback.get(),
604 mOutputSize ) );
605
606 if ( renderer )
607 renderer->draw();
608}
609
@ 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(Qgis::RenderUnit strokeWidthUnit)
Sets the unit of the stroke width.
Represents a width than can vary depending on values.
static QPainterPath calculatePainterClipRegion(const QList< QgsMapClippingRegion > &regions, 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...
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 mVectorActiveFaceFlagValues
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)
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
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.
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.
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.
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.
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 ...
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.
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:3509
#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