QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
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#include <QElapsedTimer>
26
28
29#include "qgslogger.h"
30#include "qgsmeshlayer.h"
31#include "qgspointxy.h"
33#include "qgsrastershader.h"
35#include "qgsmeshlayerutils.h"
37#include "qgsmapclippingutils.h"
38#include "qgscolorrampshader.h"
40#include "qgsapplication.h"
41#include "qgsruntimeprofiler.h"
42
44 QgsMeshLayer *layer,
45 QgsRenderContext &context )
46 : QgsMapLayerRenderer( layer->id(), &context )
47 , mIsEditable( layer->isEditable() )
48 , mLayerName( layer->name() )
49 , mFeedback( new QgsMeshLayerRendererFeedback )
50 , mRendererSettings( layer->rendererSettings() )
51 , mEnableProfile( context.flags() & Qgis::RenderContextFlag::RecordProfile )
52 , mLayerOpacity( layer->opacity() )
53{
54 QElapsedTimer timer;
55 timer.start();
56
57 // make copies for mesh data
58 // cppcheck-suppress assertWithSideEffect
59 Q_ASSERT( layer->nativeMesh() );
60 // cppcheck-suppress assertWithSideEffect
61 Q_ASSERT( layer->triangularMesh() );
62 // cppcheck-suppress assertWithSideEffect
63 Q_ASSERT( layer->rendererCache() );
64 // cppcheck-suppress assertWithSideEffect
65 Q_ASSERT( layer->dataProvider() );
66
67 mReadyToCompose = false;
68
69 // copy native mesh
70 mNativeMesh = *( layer->nativeMesh() );
71 mLayerExtent = layer->extent();
72
73 // copy triangular mesh
74 copyTriangularMeshes( layer, context );
75
76 // copy datasets
77 copyScalarDatasetValues( layer );
78 copyVectorDatasetValues( layer );
79
80 calculateOutputSize();
81
83
84 if ( layer->elevationProperties() && layer->elevationProperties()->hasElevation() )
85 {
89 }
90
91 mPreparationTime = timer.elapsed();
92}
93
94void QgsMeshLayerRenderer::copyTriangularMeshes( QgsMeshLayer *layer, QgsRenderContext &context )
95{
96 // handle level of details of mesh
97 const QgsMeshSimplificationSettings simplificationSettings = layer->meshSimplificationSettings();
98 if ( simplificationSettings.isEnabled() )
99 {
100 const double triangleSize = simplificationSettings.meshResolution() * context.mapToPixel().mapUnitsPerPixel();
101 mTriangularMesh = *( layer->triangularMesh( triangleSize ) );
102 mIsMeshSimplificationActive = true;
103 }
104 else
105 {
106 mTriangularMesh = *( layer->triangularMesh() );
107 }
108}
109
111{
112 return mFeedback.get();
113}
114
115void QgsMeshLayerRenderer::calculateOutputSize()
116{
117 // figure out image size
118 const QgsRenderContext &context = *renderContext();
119 const QgsRectangle extent = context.mapExtent();
120 const QgsMapToPixel mapToPixel = context.mapToPixel();
121 const QgsRectangle screenBBox = QgsMeshLayerUtils::boundingBoxToScreenRectangle( mapToPixel, extent, context.devicePixelRatio() );
122 const int width = int( screenBBox.width() );
123 const int height = int( screenBBox.height() );
124 mOutputSize = QSize( width, height );
125}
126
127void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
128{
129 QgsMeshDatasetIndex datasetIndex;
130 if ( renderContext()->isTemporal() )
131 datasetIndex = layer->activeScalarDatasetAtTime( renderContext()->temporalRange() );
132 else
133 datasetIndex = layer->staticScalarDatasetIndex();
134
135 // Find out if we can use cache up to date. If yes, use it and return
136 const int datasetGroupCount = layer->datasetGroupCount();
138 QgsMeshLayerRendererCache *cache = layer->rendererCache();
139 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
140 ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
141 ( cache->mDataInterpolationMethod == method ) &&
142 ( QgsMesh3DAveragingMethod::equals( cache->mScalarAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
143 )
144 {
145 mScalarDatasetValues = cache->mScalarDatasetValues;
146 mScalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
147 mScalarDataType = cache->mScalarDataType;
148 mScalarDatasetMinimum = cache->mScalarDatasetMinimum;
149 mScalarDatasetMaximum = cache->mScalarDatasetMaximum;
150 return;
151 }
152
153 // Cache is not up-to-date, gather data
154 if ( datasetIndex.isValid() )
155 {
156 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex.group() );
157 mScalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
158
159 // populate scalar values
160 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mScalarDataType );
161 const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
162 layer,
163 datasetIndex,
164 0,
165 count );
166
167 if ( vals.isValid() )
168 {
169 // vals could be scalar or vectors, for contour rendering we want always magnitude
170 mScalarDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
171 }
172 else
173 {
174 mScalarDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
175 }
176
177 // populate face active flag, always defined on faces
179 datasetIndex,
180 0,
181 mNativeMesh.faces.count() );
182
183 // for data on faces, there could be request to interpolate the data to vertices
185 {
187 {
189 mScalarDatasetValues = QgsMeshLayerUtils::interpolateFromFacesData(
194 method
195 );
196 }
198 {
200 mScalarDatasetValues = QgsMeshLayerUtils::resampleFromVerticesToFaces(
205 method
206 );
207 }
208 }
209
210 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
211 mScalarDatasetMinimum = datasetMetadata.minimum();
212 mScalarDatasetMaximum = datasetMetadata.maximum();
213 }
214
215 // update cache
216 cache->mDatasetGroupsCount = datasetGroupCount;
217 cache->mActiveScalarDatasetIndex = datasetIndex;
218 cache->mDataInterpolationMethod = method;
219 cache->mScalarDatasetValues = mScalarDatasetValues;
220 cache->mScalarActiveFaceFlagValues = mScalarActiveFaceFlagValues;
221 cache->mScalarDataType = mScalarDataType;
222 cache->mScalarDatasetMinimum = mScalarDatasetMinimum;
223 cache->mScalarDatasetMaximum = mScalarDatasetMaximum;
224 cache->mScalarAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
225}
226
227
228void QgsMeshLayerRenderer::copyVectorDatasetValues( QgsMeshLayer *layer )
229{
230 QgsMeshDatasetIndex datasetIndex;
231 if ( renderContext()->isTemporal() )
232 datasetIndex = layer->activeVectorDatasetAtTime( renderContext()->temporalRange() );
233 else
234 datasetIndex = layer->staticVectorDatasetIndex();
235
236 // Find out if we can use cache up to date. If yes, use it and return
237 const int datasetGroupCount = layer->datasetGroupCount();
238 QgsMeshLayerRendererCache *cache = layer->rendererCache();
239 if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
240 ( cache->mActiveVectorDatasetIndex == datasetIndex ) &&
241 ( QgsMesh3DAveragingMethod::equals( cache->mVectorAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
242 )
243 {
244 mVectorDatasetValues = cache->mVectorDatasetValues;
245 mVectorDatasetValuesMag = cache->mVectorDatasetValuesMag;
246 mVectorDatasetMagMinimum = cache->mVectorDatasetMagMinimum;
247 mVectorDatasetMagMaximum = cache->mVectorDatasetMagMaximum;
248 mVectorDatasetGroupMagMinimum = cache->mVectorDatasetMagMinimum;
249 mVectorDatasetGroupMagMaximum = cache->mVectorDatasetMagMaximum;
250 mVectorActiveFaceFlagValues = cache->mVectorActiveFaceFlagValues;
251 mVectorDataType = cache->mVectorDataType;
252 return;
253 }
254
255 // Cache is not up-to-date, gather data
256 if ( datasetIndex.isValid() )
257 {
258 const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex );
259
260 const bool isScalar = metadata.isScalar();
261 if ( isScalar )
262 {
263 QgsDebugError( QStringLiteral( "Dataset has no vector values" ) );
264 }
265 else
266 {
267 mVectorDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
268
271
272 const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mVectorDataType );
273 mVectorDatasetValues = QgsMeshLayerUtils::datasetValues(
274 layer,
275 datasetIndex,
276 0,
277 count );
278
280 mVectorDatasetValuesMag = QgsMeshLayerUtils::calculateMagnitudes( mVectorDatasetValues );
281 else
282 mVectorDatasetValuesMag = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
283
284 // populate face active flag
285 mVectorActiveFaceFlagValues = layer->areFacesActive( datasetIndex, 0, mNativeMesh.faces.count() );
286
287 const QgsMeshDatasetMetadata datasetMetadata = layer->datasetMetadata( datasetIndex );
288 mVectorDatasetMagMinimum = datasetMetadata.minimum();
289 mVectorDatasetMagMaximum = datasetMetadata.maximum();
290 }
291 }
292
293 // update cache
294 cache->mDatasetGroupsCount = datasetGroupCount;
295 cache->mActiveVectorDatasetIndex = datasetIndex;
296 cache->mVectorDatasetValues = mVectorDatasetValues;
297 cache->mVectorDatasetValuesMag = mVectorDatasetValuesMag;
298 cache->mVectorDatasetMagMinimum = mVectorDatasetMagMinimum;
299 cache->mVectorDatasetMagMaximum = mVectorDatasetMagMaximum;
300 cache->mVectorDatasetGroupMagMinimum = mVectorDatasetMagMinimum;
301 cache->mVectorDatasetGroupMagMaximum = mVectorDatasetMagMaximum;
302 cache->mVectorActiveFaceFlagValues = mVectorActiveFaceFlagValues;
303 cache->mVectorDataType = mVectorDataType;
304 cache->mVectorAveragingMethod.reset( mRendererSettings.averagingMethod() ? mRendererSettings.averagingMethod()->clone() : nullptr );
305}
306
308{
309 std::unique_ptr< QgsScopedRuntimeProfile > profile;
310 std::unique_ptr< QgsScopedRuntimeProfile > preparingProfile;
311 if ( mEnableProfile )
312 {
313 profile = std::make_unique< QgsScopedRuntimeProfile >( mLayerName, QStringLiteral( "rendering" ), layerId() );
314 if ( mPreparationTime > 0 )
315 QgsApplication::profiler()->record( QObject::tr( "Create renderer" ), mPreparationTime / 1000.0, QStringLiteral( "rendering" ) );
316 preparingProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr( "Preparing render" ), QStringLiteral( "rendering" ) );
317 }
318
319 mReadyToCompose = false;
320 const QgsScopedQPainterState painterState( renderContext()->painter() );
321 if ( !mClippingRegions.empty() )
322 {
323 bool needsPainterClipPath = false;
324 const QPainterPath path = QgsMapClippingUtils::calculatePainterClipRegion( mClippingRegions, *renderContext(), Qgis::LayerType::Mesh, needsPainterClipPath );
325 if ( needsPainterClipPath )
326 renderContext()->painter()->setClipPath( path, Qt::IntersectClip );
327 }
328
329 preparingProfile.reset();
330
331 renderScalarDataset();
332 mReadyToCompose = true;
333 renderMesh();
334 renderVectorDataset();
335
336 return !renderContext()->renderingStopped();
337}
338
343
344void QgsMeshLayerRenderer::renderMesh()
345{
346 if ( !mRendererSettings.nativeMeshSettings().isEnabled() && !mIsEditable &&
349 return;
350
351 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
352 if ( mEnableProfile )
353 {
354 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr( "Rendering mesh" ), QStringLiteral( "rendering" ) );
355 }
356
357 // triangular mesh
358 const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( renderContext()->mapExtent() );
360 {
361 renderFaceMesh(
364 trianglesInExtent );
365 }
366
367 // native mesh
368 if ( ( mRendererSettings.nativeMeshSettings().isEnabled() || mIsEditable ) &&
370 {
371 const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
373
374 renderFaceMesh(
377 nativeFacesInExtent.values() );
378 }
379
380 // edge mesh
382 {
383 const QList<int> edgesInExtent = mTriangularMesh.edgeIndexesForRectangle( renderContext()->mapExtent() );
384 renderEdgeMesh( mRendererSettings.edgeMeshSettings(), edgesInExtent );
385 }
386}
387
388static QPainter *_painterForMeshFrame( QgsRenderContext &context, const QgsMeshRendererMeshSettings &settings )
389{
390 // Set up the render configuration options
391 QPainter *painter = context.painter();
392
393 painter->save();
394 context.setPainterFlagsUsingContext( painter );
395
396 QPen pen = painter->pen();
397 pen.setCapStyle( Qt::FlatCap );
398 pen.setJoinStyle( Qt::MiterJoin );
399
400 const double penWidth = context.convertToPainterUnits( settings.lineWidth(), settings.lineWidthUnit() );
401 pen.setWidthF( penWidth );
402 pen.setColor( settings.color() );
403 painter->setPen( pen );
404 return painter;
405}
406
407void QgsMeshLayerRenderer::renderEdgeMesh( const QgsMeshRendererMeshSettings &settings, const QList<int> &edgesInExtent )
408{
409 Q_ASSERT( settings.isEnabled() );
410
412 return;
413
414 QgsRenderContext &context = *renderContext();
415 QPainter *painter = _painterForMeshFrame( context, settings );
416
417 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
418 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
419
420 for ( const int i : edgesInExtent )
421 {
422 if ( context.renderingStopped() )
423 break;
424
425 if ( i >= edges.size() )
426 continue;
427
428 const QgsMeshEdge &edge = edges[i];
429 const int startVertexIndex = edge.first;
430 const int endVertexIndex = edge.second;
431
432 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
433 continue;
434
435 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
436 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
437 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
438 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
439 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
440 }
441 painter->restore();
442};
443
444void QgsMeshLayerRenderer::renderFaceMesh(
445 const QgsMeshRendererMeshSettings &settings,
446 const QVector<QgsMeshFace> &faces,
447 const QList<int> &facesInExtent )
448{
449 Q_ASSERT( settings.isEnabled() || mIsEditable );
450
452 return;
453
454 QgsRenderContext &context = *renderContext();
455 QPainter *painter = _painterForMeshFrame( context, settings );
456
457 const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
458 QSet<QPair<int, int>> drawnEdges;
459
460 for ( const int i : facesInExtent )
461 {
462 if ( context.renderingStopped() )
463 break;
464
465 if ( i < 0 || i >= faces.count() )
466 continue;
467
468 const QgsMeshFace &face = faces[i];
469 if ( face.size() < 2 )
470 continue;
471
472 for ( int j = 0; j < face.size(); ++j )
473 {
474 const int startVertexId = face[j];
475 const int endVertexId = face[( j + 1 ) % face.size()];
476 const QPair<int, int> thisEdge( startVertexId, endVertexId );
477 const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
478 if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
479 continue;
480 drawnEdges.insert( thisEdge );
481 drawnEdges.insert( thisEdgeReversed );
482
483 const QgsMeshVertex &startVertex = vertices[startVertexId];
484 const QgsMeshVertex &endVertex = vertices[endVertexId];
485 const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
486 const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
487 painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
488 }
489 }
490
491 painter->restore();
492}
493
494void QgsMeshLayerRenderer::renderScalarDataset()
495{
496 if ( mScalarDatasetValues.isEmpty() )
497 return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET
498
499 if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
500 return; // only NODATA values
501
502 const int groupIndex = mRendererSettings.activeScalarDatasetGroup();
503 if ( groupIndex < 0 )
504 return; // no shader
505
506 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
507 if ( mEnableProfile )
508 {
509 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr( "Rendering scalar datasets" ), QStringLiteral( "rendering" ) );
510 }
511
512 const QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( groupIndex );
513
516 {
517 renderScalarDatasetOnFaces( scalarSettings );
518 }
519
522 {
523 renderScalarDatasetOnEdges( scalarSettings );
524 }
525}
526
527void QgsMeshLayerRenderer::renderScalarDatasetOnEdges( const QgsMeshRendererScalarSettings &scalarSettings )
528{
529 QgsRenderContext &context = *renderContext();
530 const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
531 const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
532 const QList<int> egdesInExtent = mTriangularMesh.edgeIndexesForRectangle( context.mapExtent() );
533
534 QgsInterpolatedLineRenderer edgePlotter;
535 edgePlotter.setInterpolatedColor( QgsInterpolatedLineColor( scalarSettings.colorRampShader() ) );
536 edgePlotter.setInterpolatedWidth( QgsInterpolatedLineWidth( scalarSettings.edgeStrokeWidth() ) );
537 edgePlotter.setWidthUnit( scalarSettings.edgeStrokeWidthUnit() );
538
539 for ( const int i : egdesInExtent )
540 {
541 if ( context.renderingStopped() )
542 break;
543
544 if ( i >= edges.size() )
545 continue;
546
547 const QgsMeshEdge &edge = edges[i];
548 const int startVertexIndex = edge.first;
549 const int endVertexIndex = edge.second;
550
551 if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
552 continue;
553
554 const QgsMeshVertex &startVertex = vertices[startVertexIndex];
555 const QgsMeshVertex &endVertex = vertices[endVertexIndex];
556
558 {
559 edgePlotter.render( mScalarDatasetValues[i], mScalarDatasetValues[i], startVertex, endVertex, context );
560 }
561 else
562 {
563 edgePlotter.render( mScalarDatasetValues[startVertexIndex], mScalarDatasetValues[endVertexIndex], startVertex, endVertex, context );
564 }
565 }
566}
567
568QColor QgsMeshLayerRenderer::colorAt( QgsColorRampShader *shader, double val ) const
569{
570 int r, g, b, a;
571 if ( shader->shade( val, &r, &g, &b, &a ) )
572 {
573 return QColor( r, g, b, a );
574 }
575 return QColor();
576}
577
578QgsPointXY QgsMeshLayerRenderer::fractionPoint( const QgsPointXY &p1, const QgsPointXY &p2, double fraction ) const
579{
580 const QgsPointXY pt( p1.x() + fraction * ( p2.x() - p1.x() ),
581 p1.y() + fraction * ( p2.y() - p1.y() ) );
582 return pt;
583}
584
585void QgsMeshLayerRenderer::renderScalarDatasetOnFaces( const QgsMeshRendererScalarSettings &scalarSettings )
586{
587 QgsRenderContext &context = *renderContext();
588
589 QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() );
591 sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
592 QgsMeshLayerInterpolator interpolator( mTriangularMesh,
596 context,
597 mOutputSize );
598 interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
599 interpolator.setElevationMapSettings( mRenderElevationMap, mElevationScale, mElevationOffset );
600 QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
601 renderer.setClassificationMin( scalarSettings.classificationMinimum() );
602 renderer.setClassificationMax( scalarSettings.classificationMaximum() );
603 renderer.setOpacity( scalarSettings.opacity() );
604
605 std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, context.mapExtent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
606 QImage img = bl->image();
607 img.setDevicePixelRatio( context.devicePixelRatio() );
608
609 context.painter()->drawImage( 0, 0, img );
610}
611
612void QgsMeshLayerRenderer::renderVectorDataset()
613{
614 const int groupIndex = mRendererSettings.activeVectorDatasetGroup();
615 if ( groupIndex < 0 )
616 return;
617
619 return; // no data at all
620
621 if ( std::isnan( mVectorDatasetMagMinimum ) || std::isnan( mVectorDatasetMagMaximum ) )
622 return; // only NODATA values
623
624 if ( !( mVectorDatasetMagMaximum > 0 ) )
625 return; //all vector are null vector
626
627 std::unique_ptr< QgsScopedRuntimeProfile > renderProfile;
628 if ( mEnableProfile )
629 {
630 renderProfile = std::make_unique< QgsScopedRuntimeProfile >( QObject::tr( "Rendering vector datasets" ), QStringLiteral( "rendering" ) );
631 }
632
633 std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
641 mRendererSettings.vectorSettings( groupIndex ),
642 *renderContext(),
644 mFeedback.get(),
645 mOutputSize ) );
646
647 if ( renderer )
648 renderer->draw();
649}
650
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ Mesh
Mesh layer. Added in QGIS 3.2.
@ UseAdvancedEffects
Enable layer opacity and blending effects.
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 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...
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.
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.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
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.
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.
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.
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
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
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.
double width() const
Returns the width of the rectangle.
double height() const
Returns the height of the rectangle.
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, Qgis::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale(), Qgis::RenderSubcomponentProperty property=Qgis::RenderSubcomponentProperty::Generic) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
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...
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
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.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:4332
#define QgsDebugError(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