QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 
26 #include "qgsmeshlayerrenderer.h"
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"
37 #include "qgsmeshvectorrenderer.h"
38 #include "qgsmeshtracerenderer.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  , mFeedback( new QgsMeshLayerRendererFeedback )
51  , mRendererSettings( layer->rendererSettings() )
52  , mLayerOpacity( layer->opacity() )
53 {
54  // make copies for mesh data
55  // cppcheck-suppress assertWithSideEffect
56  Q_ASSERT( layer->nativeMesh() );
57  // cppcheck-suppress assertWithSideEffect
58  Q_ASSERT( layer->triangularMesh() );
59  // cppcheck-suppress assertWithSideEffect
60  Q_ASSERT( layer->rendererCache() );
61  // cppcheck-suppress assertWithSideEffect
62  Q_ASSERT( layer->dataProvider() );
63 
64  mReadyToCompose = false;
65 
66  // copy native mesh
67  mNativeMesh = *( layer->nativeMesh() );
68  mLayerExtent = layer->extent();
69 
70  // copy triangular mesh
71  copyTriangularMeshes( layer, context );
72 
73  // copy datasets
74  copyScalarDatasetValues( layer );
75  copyVectorDatasetValues( layer );
76 
77  calculateOutputSize();
78 
80 }
81 
82 void QgsMeshLayerRenderer::copyTriangularMeshes( QgsMeshLayer *layer, QgsRenderContext &context )
83 {
84  // handle level of details of mesh
85  QgsMeshSimplificationSettings simplificationSettings = layer->meshSimplificationSettings();
86  if ( simplificationSettings.isEnabled() )
87  {
88  double triangleSize = simplificationSettings.meshResolution() * context.mapToPixel().mapUnitsPerPixel();
89  mTriangularMesh = *( layer->triangularMesh( triangleSize ) );
90  mIsMeshSimplificationActive = true;
91  }
92  else
93  {
94  mTriangularMesh = *( layer->triangularMesh() );
95  }
96 }
97 
99 {
100  return mFeedback.get();
101 }
102 
103 void QgsMeshLayerRenderer::calculateOutputSize()
104 {
105  // figure out image size
106  QgsRenderContext &context = *renderContext();
107  const QgsRectangle extent = context.mapExtent();
108  const QgsMapToPixel mapToPixel = context.mapToPixel();
109  const QgsRectangle screenBBox = QgsMeshLayerUtils::boundingBoxToScreenRectangle( mapToPixel, extent );
110  int width = int( screenBBox.width() );
111  int height = int( screenBBox.height() );
112  mOutputSize = QSize( width, height );
113 }
114 
115 void QgsMeshLayerRenderer::copyScalarDatasetValues( QgsMeshLayer *layer )
116 {
117  QgsMeshDatasetIndex datasetIndex;
118  if ( renderContext()->isTemporal() )
119  datasetIndex = layer->activeScalarDatasetAtTime( renderContext()->temporalRange() );
120  else
121  datasetIndex = layer->staticScalarDatasetIndex();
122 
123  // Find out if we can use cache up to date. If yes, use it and return
124  const int datasetGroupCount = layer->datasetGroupCount();
126  QgsMeshLayerRendererCache *cache = layer->rendererCache();
127  if ( ( cache->mDatasetGroupsCount == datasetGroupCount ) &&
128  ( cache->mActiveScalarDatasetIndex == datasetIndex ) &&
129  ( cache->mDataInterpolationMethod == method ) &&
130  ( QgsMesh3dAveragingMethod::equals( cache->mScalarAveragingMethod.get(), mRendererSettings.averagingMethod() ) )
131  )
132  {
133  mScalarDatasetValues = cache->mScalarDatasetValues;
134  mScalarActiveFaceFlagValues = cache->mScalarActiveFaceFlagValues;
135  mScalarDataType = cache->mScalarDataType;
136  mScalarDatasetMinimum = cache->mScalarDatasetMinimum;
137  mScalarDatasetMaximum = cache->mScalarDatasetMaximum;
138  return;
139  }
140 
141  // Cache is not up-to-date, gather data
142  if ( datasetIndex.isValid() )
143  {
144  const QgsMeshDatasetGroupMetadata metadata = layer->datasetGroupMetadata( datasetIndex.group() );
145  mScalarDataType = QgsMeshLayerUtils::datasetValuesType( metadata.dataType() );
146 
147  // populate scalar values
148  const int count = QgsMeshLayerUtils::datasetValuesCount( &mNativeMesh, mScalarDataType );
149  QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
150  layer,
151  datasetIndex,
152  0,
153  count );
154 
155  if ( vals.isValid() )
156  {
157  // vals could be scalar or vectors, for contour rendering we want always magnitude
158  mScalarDatasetValues = QgsMeshLayerUtils::calculateMagnitudes( vals );
159  }
160  else
161  {
162  mScalarDatasetValues = QVector<double>( count, std::numeric_limits<double>::quiet_NaN() );
163  }
164 
165  // populate face active flag, always defined on faces
167  datasetIndex,
168  0,
169  mNativeMesh.faces.count() );
170 
171  // for data on faces, there could be request to interpolate the data to vertices
172  if ( method != QgsMeshRendererScalarSettings::None )
173  {
174  if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces )
175  {
176  mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnVertices;
177  mScalarDatasetValues = QgsMeshLayerUtils::interpolateFromFacesData(
179  &mNativeMesh,
182  method
183  );
184  }
185  else if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
186  {
187  mScalarDataType = QgsMeshDatasetGroupMetadata::DataType::DataOnFaces;
188  mScalarDatasetValues = QgsMeshLayerUtils::resampleFromVerticesToFaces(
190  &mNativeMesh,
193  method
194  );
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 
217 void 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  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  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  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( QgsRenderContext::UseAdvancedEffects ) && ( !qgsDoubleNear( mLayerOpacity, 1.0 ) );
314 }
315 
316 void QgsMeshLayerRenderer::renderMesh()
317 {
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
335  {
336  const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
338 
339  renderFaceMesh(
342  nativeFacesInExtent.values() );
343  }
344 
345  // edge mesh
347  {
348  const QList<int> edgesInExtent = mTriangularMesh.edgeIndexesForRectangle( renderContext()->mapExtent() );
349  renderEdgeMesh( mRendererSettings.edgeMeshSettings(), edgesInExtent );
350  }
351 }
352 
353 static QPainter *_painterForMeshFrame( QgsRenderContext &context, const QgsMeshRendererMeshSettings &settings )
354 {
355  // Set up the render configuration options
356  QPainter *painter = context.painter();
357 
358  painter->save();
359  context.setPainterFlagsUsingContext( painter );
360 
361  QPen pen = painter->pen();
362  pen.setCapStyle( Qt::FlatCap );
363  pen.setJoinStyle( Qt::MiterJoin );
364 
365  double penWidth = context.convertToPainterUnits( settings.lineWidth(), settings.lineWidthUnit() );
366  pen.setWidthF( penWidth );
367  pen.setColor( settings.color() );
368  painter->setPen( pen );
369  return painter;
370 }
371 
372 void QgsMeshLayerRenderer::renderEdgeMesh( const QgsMeshRendererMeshSettings &settings, const QList<int> &edgesInExtent )
373 {
374  Q_ASSERT( settings.isEnabled() );
375 
376  if ( !mTriangularMesh.contains( QgsMesh::ElementType::Edge ) )
377  return;
378 
379  QgsRenderContext &context = *renderContext();
380  QPainter *painter = _painterForMeshFrame( context, settings );
381 
382  const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
383  const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
384 
385  for ( const int i : edgesInExtent )
386  {
387  if ( context.renderingStopped() )
388  break;
389 
390  if ( i >= edges.size() )
391  continue;
392 
393  const QgsMeshEdge &edge = edges[i];
394  const int startVertexIndex = edge.first;
395  const int endVertexIndex = edge.second;
396 
397  if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
398  continue;
399 
400  const QgsMeshVertex &startVertex = vertices[startVertexIndex];
401  const QgsMeshVertex &endVertex = vertices[endVertexIndex];
402  const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
403  const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
404  painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
405  }
406  painter->restore();
407 };
408 
409 void QgsMeshLayerRenderer::renderFaceMesh(
410  const QgsMeshRendererMeshSettings &settings,
411  const QVector<QgsMeshFace> &faces,
412  const QList<int> &facesInExtent )
413 {
414  Q_ASSERT( settings.isEnabled() );
415 
416  if ( !mTriangularMesh.contains( QgsMesh::ElementType::Face ) )
417  return;
418 
419  QgsRenderContext &context = *renderContext();
420  QPainter *painter = _painterForMeshFrame( context, settings );
421 
422  const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices(); //Triangular mesh vertices contains also native mesh vertices
423  QSet<QPair<int, int>> drawnEdges;
424 
425  for ( const int i : facesInExtent )
426  {
427  if ( context.renderingStopped() )
428  break;
429 
430  const QgsMeshFace &face = faces[i];
431  if ( face.size() < 2 )
432  continue;
433 
434  for ( int j = 0; j < face.size(); ++j )
435  {
436  const int startVertexId = face[j];
437  const int endVertexId = face[( j + 1 ) % face.size()];
438  const QPair<int, int> thisEdge( startVertexId, endVertexId );
439  const QPair<int, int> thisEdgeReversed( endVertexId, startVertexId );
440  if ( drawnEdges.contains( thisEdge ) || drawnEdges.contains( thisEdgeReversed ) )
441  continue;
442  drawnEdges.insert( thisEdge );
443  drawnEdges.insert( thisEdgeReversed );
444 
445  const QgsMeshVertex &startVertex = vertices[startVertexId];
446  const QgsMeshVertex &endVertex = vertices[endVertexId];
447  const QgsPointXY lineStart = context.mapToPixel().transform( startVertex.x(), startVertex.y() );
448  const QgsPointXY lineEnd = context.mapToPixel().transform( endVertex.x(), endVertex.y() );
449  painter->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
450  }
451  }
452 
453  painter->restore();
454 }
455 
456 void QgsMeshLayerRenderer::renderScalarDataset()
457 {
458  if ( mScalarDatasetValues.isEmpty() )
459  return; // activeScalarDataset == NO_ACTIVE_MESH_DATASET
460 
461  if ( std::isnan( mScalarDatasetMinimum ) || std::isnan( mScalarDatasetMaximum ) )
462  return; // only NODATA values
463 
464  int groupIndex = mRendererSettings.activeScalarDatasetGroup();
465  if ( groupIndex < 0 )
466  return; // no shader
467 
468  const QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( groupIndex );
469 
470  if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Face ) ) &&
471  ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnEdges ) )
472  {
473  renderScalarDatasetOnFaces( scalarSettings );
474  }
475 
476  if ( ( mTriangularMesh.contains( QgsMesh::ElementType::Edge ) ) &&
477  ( mScalarDataType != QgsMeshDatasetGroupMetadata::DataType::DataOnFaces ) )
478  {
479  renderScalarDatasetOnEdges( scalarSettings );
480  }
481 }
482 
483 void QgsMeshLayerRenderer::renderScalarDatasetOnEdges( const QgsMeshRendererScalarSettings &scalarSettings )
484 {
485  QgsRenderContext &context = *renderContext();
486  const QVector<QgsMeshEdge> edges = mTriangularMesh.edges();
487  const QVector<QgsMeshVertex> vertices = mTriangularMesh.vertices();
488  const QList<int> egdesInExtent = mTriangularMesh.edgeIndexesForRectangle( context.mapExtent() );
489  const QSet<int> nativeEdgesInExtent = QgsMeshUtils::nativeEdgesFromEdges( egdesInExtent,
491 
492  QgsInterpolatedLineRenderer edgePlotter;
493  edgePlotter.setInterpolatedColor( QgsInterpolatedLineColor( scalarSettings.colorRampShader() ) );
494  edgePlotter.setInterpolatedWidth( QgsInterpolatedLineWidth( scalarSettings.edgeStrokeWidth() ) );
495  edgePlotter.setWidthUnit( scalarSettings.edgeStrokeWidthUnit() );
496 
497  for ( const int i : egdesInExtent )
498  {
499  if ( context.renderingStopped() )
500  break;
501 
502  if ( i >= edges.size() )
503  continue;
504 
505  const QgsMeshEdge &edge = edges[i];
506  const int startVertexIndex = edge.first;
507  const int endVertexIndex = edge.second;
508 
509  if ( ( startVertexIndex >= vertices.size() ) || endVertexIndex >= vertices.size() )
510  continue;
511 
512  const QgsMeshVertex &startVertex = vertices[startVertexIndex];
513  const QgsMeshVertex &endVertex = vertices[endVertexIndex];
514 
515  if ( mScalarDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnEdges )
516  {
517  edgePlotter.render( mScalarDatasetValues[i], mScalarDatasetValues[i], startVertex, endVertex, context );
518  }
519  else
520  {
521  edgePlotter.render( mScalarDatasetValues[startVertexIndex], mScalarDatasetValues[endVertexIndex], startVertex, endVertex, context );
522  }
523  }
524 }
525 
526 QColor QgsMeshLayerRenderer::colorAt( QgsColorRampShader *shader, double val ) const
527 {
528  int r, g, b, a;
529  if ( shader->shade( val, &r, &g, &b, &a ) )
530  {
531  return QColor( r, g, b, a );
532  }
533  return QColor();
534 }
535 
536 QgsPointXY QgsMeshLayerRenderer::fractionPoint( const QgsPointXY &p1, const QgsPointXY &p2, double fraction ) const
537 {
538  const QgsPointXY pt( p1.x() + fraction * ( p2.x() - p1.x() ),
539  p1.y() + fraction * ( p2.y() - p1.y() ) );
540  return pt;
541 }
542 
543 void QgsMeshLayerRenderer::renderScalarDatasetOnFaces( const QgsMeshRendererScalarSettings &scalarSettings )
544 {
545  QgsRenderContext &context = *renderContext();
546 
547  QgsColorRampShader *fcn = new QgsColorRampShader( scalarSettings.colorRampShader() );
548  QgsRasterShader *sh = new QgsRasterShader();
549  sh->setRasterShaderFunction( fcn ); // takes ownership of fcn
550  QgsMeshLayerInterpolator interpolator( mTriangularMesh,
554  context,
555  mOutputSize );
556  interpolator.setSpatialIndexActive( mIsMeshSimplificationActive );
557  QgsSingleBandPseudoColorRenderer renderer( &interpolator, 0, sh ); // takes ownership of sh
558  renderer.setClassificationMin( scalarSettings.classificationMinimum() );
559  renderer.setClassificationMax( scalarSettings.classificationMaximum() );
560  renderer.setOpacity( scalarSettings.opacity() );
561 
562  std::unique_ptr<QgsRasterBlock> bl( renderer.block( 0, context.mapExtent(), mOutputSize.width(), mOutputSize.height(), mFeedback.get() ) );
563  QImage img = bl->image();
564 
565  context.painter()->drawImage( 0, 0, img );
566 }
567 
568 void QgsMeshLayerRenderer::renderVectorDataset()
569 {
570  int groupIndex = mRendererSettings.activeVectorDatasetGroup();
571  if ( groupIndex < 0 )
572  return;
573 
574  if ( !mVectorDatasetValues.isValid() )
575  return; // no data at all
576 
577  if ( std::isnan( mVectorDatasetMagMinimum ) || std::isnan( mVectorDatasetMagMaximum ) )
578  return; // only NODATA values
579 
580  if ( !( mVectorDatasetMagMaximum > 0 ) )
581  return; //all vector are null vector
582 
583  std::unique_ptr<QgsMeshVectorRenderer> renderer( QgsMeshVectorRenderer::makeVectorRenderer(
591  mRendererSettings.vectorSettings( groupIndex ),
592  *renderContext(),
593  mLayerExtent,
594  mOutputSize ) );
595 
596  if ( renderer )
597  renderer->draw();
598 }
599 
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 setWidthUnit(const QgsUnitTypes::RenderUnit &strokeWidthUnit)
Sets the unit of the stroke width.
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...
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 current map units per pixel.
QgsPointXY transform(const QgsPointXY &p) const
Transform the point p from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.h:82
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:95
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 a overview renderer settings.
bool isEnabled() const
Returns if the overview is active.
int meshResolution() const
Returns the mesh resolution e.i., 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.
const QgsMapToPixel & mapToPixel() const
Returns the context's map to pixel transform, which transforms between map coordinates and device coo...
void setPainterFlagsUsingContext(QPainter *painter=nullptr) const
Sets relevant flags on a destination painter, using the flags and settings currently defined for the ...
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
@ UseAdvancedEffects
Enable layer opacity and blending effects.
bool renderingStopped() const
Returns true if the rendering operation has been stopped and any ongoing rendering should be canceled...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
bool testFlag(Flag flag) const
Check whether a particular flag is enabled.
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 at mesh elements of given type.
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
const QVector< int > & edgesToNativeEdges() const
Returns mapping between edges and original edges.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
@ MeshLayer
Added in 3.2.
CORE_EXPORT QSet< int > nativeEdgesFromEdges(const QList< int > &edgesIndexes, const QVector< int > &edgesToNativeEdges)
Returns unique native faces indexes from list of triangle indexes.
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:598
#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