Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsmeshvectorrenderer.cpp
3 : : -------------------------
4 : : begin : May 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 "qgsmeshvectorrenderer.h"
19 : : #include "qgsrendercontext.h"
20 : : #include "qgscoordinatetransform.h"
21 : : #include "qgsmaptopixel.h"
22 : : #include "qgsunittypes.h"
23 : : #include "qgsmeshlayerutils.h"
24 : : #include "qgsmeshtracerenderer.h"
25 : :
26 : : #include <cstdlib>
27 : : #include <ctime>
28 : : #include <algorithm>
29 : : #include <QPen>
30 : : #include <QPainter>
31 : : #include <cmath>
32 : :
33 : : ///@cond PRIVATE
34 : :
35 : : #ifndef M_DEG2RAD
36 : : #define M_DEG2RAD 0.0174532925
37 : : #endif
38 : :
39 : 0 : inline double mag( double input )
40 : : {
41 : 0 : if ( input < 0.0 )
42 : : {
43 : 0 : return -1.0;
44 : : }
45 : 0 : return 1.0;
46 : 0 : }
47 : :
48 : 0 : inline bool nodataValue( double x, double y )
49 : : {
50 : 0 : return ( std::isnan( x ) || std::isnan( y ) );
51 : : }
52 : :
53 : 0 : QgsMeshVectorArrowRenderer::QgsMeshVectorArrowRenderer(
54 : : const QgsTriangularMesh &m,
55 : : const QgsMeshDataBlock &datasetValues,
56 : : const QVector<double> &datasetValuesMag,
57 : : double datasetMagMaximumValue, double datasetMagMinimumValue,
58 : : QgsMeshDatasetGroupMetadata::DataType dataType,
59 : : const QgsMeshRendererVectorSettings &settings,
60 : : QgsRenderContext &context,
61 : : QSize size ) :
62 : 0 : mTriangularMesh( m )
63 : 0 : , mDatasetValues( datasetValues )
64 : 0 : , mDatasetValuesMag( datasetValuesMag )
65 : 0 : , mMinMag( datasetMagMinimumValue )
66 : 0 : , mMaxMag( datasetMagMaximumValue )
67 : 0 : , mContext( context )
68 : 0 : , mCfg( settings )
69 : 0 : , mDataType( dataType )
70 : 0 : , mOutputSize( size )
71 : 0 : , mBufferedExtent( context.mapExtent() )
72 : 0 : {
73 : : // should be checked in caller
74 : : Q_ASSERT( !mDatasetValuesMag.empty() );
75 : : Q_ASSERT( !std::isnan( mMinMag ) );
76 : : Q_ASSERT( !std::isnan( mMaxMag ) );
77 : : Q_ASSERT( mDatasetValues.isValid() );
78 : : Q_ASSERT( QgsMeshDataBlock::Vector2DDouble == mDatasetValues.type() );
79 : :
80 : : // we need to expand out the extent so that it includes
81 : : // arrows which start or end up outside of the
82 : : // actual visible extent
83 : 0 : double extension = context.convertToMapUnits( calcExtentBufferSize(), QgsUnitTypes::RenderPixels );
84 : 0 : mBufferedExtent.setXMinimum( mBufferedExtent.xMinimum() - extension );
85 : 0 : mBufferedExtent.setXMaximum( mBufferedExtent.xMaximum() + extension );
86 : 0 : mBufferedExtent.setYMinimum( mBufferedExtent.yMinimum() - extension );
87 : 0 : mBufferedExtent.setYMaximum( mBufferedExtent.yMaximum() + extension );
88 : :
89 : 0 : mVectorColoring = settings.vectorStrokeColoring();
90 : 0 : }
91 : :
92 : 0 : QgsMeshVectorArrowRenderer::~QgsMeshVectorArrowRenderer() = default;
93 : :
94 : 0 : void QgsMeshVectorArrowRenderer::draw()
95 : : {
96 : : // Set up the render configuration options
97 : 0 : QPainter *painter = mContext.painter();
98 : :
99 : 0 : QgsScopedQPainterState painterState( painter );
100 : 0 : mContext.setPainterFlagsUsingContext( painter );
101 : :
102 : 0 : QPen pen = painter->pen();
103 : 0 : pen.setCapStyle( Qt::FlatCap );
104 : 0 : pen.setJoinStyle( Qt::MiterJoin );
105 : :
106 : 0 : double penWidth = mContext.convertToPainterUnits( mCfg.lineWidth(),
107 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
108 : 0 : pen.setWidthF( penWidth );
109 : 0 : painter->setPen( pen );
110 : :
111 : 0 : if ( mCfg.isOnUserDefinedGrid() )
112 : : {
113 : 0 : drawVectorDataOnGrid( );
114 : 0 : }
115 : 0 : else if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
116 : : {
117 : 0 : drawVectorDataOnVertices( );
118 : 0 : }
119 : 0 : else if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces )
120 : : {
121 : 0 : drawVectorDataOnFaces( );
122 : 0 : }
123 : 0 : else if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnEdges )
124 : : {
125 : 0 : drawVectorDataOnEdges( );
126 : 0 : }
127 : 0 : }
128 : :
129 : 0 : bool QgsMeshVectorArrowRenderer::calcVectorLineEnd(
130 : : QgsPointXY &lineEnd,
131 : : double &vectorLength,
132 : : double &cosAlpha,
133 : : double &sinAlpha, //out
134 : : const QgsPointXY &lineStart,
135 : : double xVal,
136 : : double yVal,
137 : : double magnitude //in
138 : : )
139 : : {
140 : : // return true on error
141 : :
142 : 0 : if ( xVal == 0.0 && yVal == 0.0 )
143 : 0 : return true;
144 : :
145 : : // do not render if magnitude is outside of the filtered range (if filtering is enabled)
146 : 0 : if ( mCfg.filterMin() >= 0 && magnitude < mCfg.filterMin() )
147 : 0 : return true;
148 : 0 : if ( mCfg.filterMax() >= 0 && magnitude > mCfg.filterMax() )
149 : 0 : return true;
150 : :
151 : : // Determine the angle of the vector, counter-clockwise, from east
152 : : // (and associated trigs)
153 : 0 : double vectorAngle = -1.0 * atan( ( -1.0 * yVal ) / xVal ) - mContext.mapToPixel().mapRotation() * M_DEG2RAD;
154 : :
155 : 0 : cosAlpha = cos( vectorAngle ) * mag( xVal );
156 : 0 : sinAlpha = sin( vectorAngle ) * mag( xVal );
157 : :
158 : : // Now determine the X and Y distances of the end of the line from the start
159 : 0 : double xDist = 0.0;
160 : 0 : double yDist = 0.0;
161 : 0 : switch ( mCfg.arrowSettings().shaftLengthMethod() )
162 : : {
163 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::MinMax:
164 : : {
165 : 0 : double minShaftLength = mContext.convertToPainterUnits( mCfg.arrowSettings().minShaftLength(),
166 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
167 : 0 : double maxShaftLength = mContext.convertToPainterUnits( mCfg.arrowSettings().maxShaftLength(),
168 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
169 : 0 : double minVal = mMinMag;
170 : 0 : double maxVal = mMaxMag;
171 : 0 : double k = ( magnitude - minVal ) / ( maxVal - minVal );
172 : 0 : double L = minShaftLength + k * ( maxShaftLength - minShaftLength );
173 : 0 : xDist = cosAlpha * L;
174 : 0 : yDist = sinAlpha * L;
175 : 0 : break;
176 : : }
177 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::Scaled:
178 : : {
179 : 0 : double scaleFactor = mCfg.arrowSettings().scaleFactor();
180 : 0 : xDist = scaleFactor * xVal;
181 : 0 : yDist = scaleFactor * yVal;
182 : 0 : break;
183 : : }
184 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::Fixed:
185 : : {
186 : : // We must be using a fixed length
187 : 0 : double fixedShaftLength = mContext.convertToPainterUnits( mCfg.arrowSettings().fixedShaftLength(),
188 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
189 : 0 : xDist = cosAlpha * fixedShaftLength;
190 : 0 : yDist = sinAlpha * fixedShaftLength;
191 : 0 : break;
192 : : }
193 : : }
194 : :
195 : : // Flip the Y axis (pixel vs real-world axis)
196 : 0 : yDist *= -1.0;
197 : :
198 : 0 : if ( std::abs( xDist ) < 1 && std::abs( yDist ) < 1 )
199 : 0 : return true;
200 : :
201 : : // Determine the line coords
202 : 0 : lineEnd = QgsPointXY( lineStart.x() + xDist,
203 : 0 : lineStart.y() + yDist );
204 : :
205 : 0 : vectorLength = sqrt( xDist * xDist + yDist * yDist );
206 : :
207 : : // Check to see if both of the coords are outside the QImage area, if so, skip the whole vector
208 : 0 : if ( ( lineStart.x() < 0 || lineStart.x() > mOutputSize.width() ||
209 : 0 : lineStart.y() < 0 || lineStart.y() > mOutputSize.height() ) &&
210 : 0 : ( lineEnd.x() < 0 || lineEnd.x() > mOutputSize.width() ||
211 : 0 : lineEnd.y() < 0 || lineEnd.y() > mOutputSize.height() ) )
212 : 0 : return true;
213 : :
214 : 0 : return false; //success
215 : 0 : }
216 : :
217 : 0 : double QgsMeshVectorArrowRenderer::calcExtentBufferSize() const
218 : : {
219 : 0 : double buffer = 0;
220 : 0 : switch ( mCfg.arrowSettings().shaftLengthMethod() )
221 : : {
222 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::MinMax:
223 : : {
224 : 0 : buffer = mContext.convertToPainterUnits( mCfg.arrowSettings().maxShaftLength(),
225 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
226 : 0 : break;
227 : : }
228 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::Scaled:
229 : : {
230 : 0 : buffer = mCfg.arrowSettings().scaleFactor() * mMaxMag;
231 : 0 : break;
232 : : }
233 : : case QgsMeshRendererVectorArrowSettings::ArrowScalingMethod::Fixed:
234 : : {
235 : 0 : buffer = mContext.convertToPainterUnits( mCfg.arrowSettings().fixedShaftLength(),
236 : : QgsUnitTypes::RenderUnit::RenderMillimeters );
237 : 0 : break;
238 : : }
239 : : }
240 : :
241 : 0 : if ( mCfg.filterMax() >= 0 && buffer > mCfg.filterMax() )
242 : 0 : buffer = mCfg.filterMax();
243 : :
244 : 0 : if ( buffer < 0.0 )
245 : 0 : buffer = 0.0;
246 : :
247 : 0 : return buffer;
248 : : }
249 : :
250 : :
251 : 0 : void QgsMeshVectorArrowRenderer::drawVectorDataOnVertices()
252 : : {
253 : 0 : const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
254 : 0 : QSet<int> verticesToDraw;
255 : :
256 : : // currently expecting that triangulation does not add any new extra vertices on the way
257 : : Q_ASSERT( mDatasetValuesMag.count() == vertices.count() );
258 : :
259 : : // find all vertices from faces to render
260 : : {
261 : 0 : const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mBufferedExtent );
262 : 0 : const QVector<QgsMeshFace> &triangles = mTriangularMesh.triangles();
263 : 0 : verticesToDraw.unite( QgsMeshUtils::nativeVerticesFromTriangles( trianglesInExtent, triangles ) );
264 : 0 : }
265 : :
266 : : // find all vertices from edges to render
267 : : {
268 : 0 : const QList<int> edgesInExtent = mTriangularMesh.edgeIndexesForRectangle( mBufferedExtent );
269 : 0 : const QVector<QgsMeshEdge> &edges = mTriangularMesh.edges();
270 : 0 : verticesToDraw.unite( QgsMeshUtils::nativeVerticesFromEdges( edgesInExtent, edges ) );
271 : 0 : }
272 : :
273 : : // render
274 : 0 : drawVectorDataOnPoints( verticesToDraw, vertices );
275 : 0 : }
276 : :
277 : 0 : void QgsMeshVectorArrowRenderer::drawVectorDataOnPoints( const QSet<int> indexesToRender, const QVector<QgsMeshVertex> &points )
278 : : {
279 : 0 : for ( int i : indexesToRender )
280 : : {
281 : 0 : if ( mContext.renderingStopped() )
282 : 0 : break;
283 : :
284 : 0 : QgsPointXY center = points.at( i );
285 : 0 : if ( !mBufferedExtent.contains( center ) )
286 : 0 : continue;
287 : :
288 : 0 : const QgsMeshDatasetValue val = mDatasetValues.value( i );
289 : 0 : double xVal = val.x();
290 : 0 : double yVal = val.y();
291 : 0 : if ( nodataValue( xVal, yVal ) )
292 : 0 : continue;
293 : :
294 : 0 : double V = mDatasetValuesMag[i]; // pre-calculated magnitude
295 : 0 : QgsPointXY lineStart = mContext.mapToPixel().transform( center.x(), center.y() );
296 : :
297 : 0 : drawVectorArrow( lineStart, xVal, yVal, V );
298 : : }
299 : 0 : }
300 : :
301 : 0 : void QgsMeshVectorArrowRenderer::drawVectorDataOnFaces( )
302 : : {
303 : 0 : const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mBufferedExtent );
304 : 0 : const QVector<QgsMeshVertex> ¢roids = mTriangularMesh.faceCentroids();
305 : 0 : const QSet<int> nativeFacesInExtent = QgsMeshUtils::nativeFacesFromTriangles( trianglesInExtent,
306 : 0 : mTriangularMesh.trianglesToNativeFaces() );
307 : 0 : drawVectorDataOnPoints( nativeFacesInExtent, centroids );
308 : 0 : }
309 : :
310 : 0 : void QgsMeshVectorArrowRenderer::drawVectorDataOnEdges()
311 : : {
312 : 0 : const QList<int> egdesInExtent = mTriangularMesh.edgeIndexesForRectangle( mBufferedExtent );
313 : 0 : const QVector<QgsMeshVertex> ¢roids = mTriangularMesh.edgeCentroids();
314 : 0 : const QSet<int> nativeEdgesInExtent = QgsMeshUtils::nativeEdgesFromEdges( egdesInExtent,
315 : 0 : mTriangularMesh.edgesToNativeEdges() );
316 : 0 : drawVectorDataOnPoints( nativeEdgesInExtent, centroids );
317 : 0 : }
318 : :
319 : 0 : void QgsMeshVectorArrowRenderer::drawVectorDataOnGrid( )
320 : : {
321 : 0 : if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnEdges ||
322 : 0 : mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
323 : 0 : return;
324 : :
325 : 0 : const QList<int> trianglesInExtent = mTriangularMesh.faceIndexesForRectangle( mBufferedExtent );
326 : 0 : int cellx = mCfg.userGridCellWidth();
327 : 0 : int celly = mCfg.userGridCellHeight();
328 : :
329 : 0 : const QVector<QgsMeshFace> &triangles = mTriangularMesh.triangles();
330 : 0 : const QVector<QgsMeshVertex> &vertices = mTriangularMesh.vertices();
331 : :
332 : 0 : for ( const int i : trianglesInExtent )
333 : : {
334 : 0 : if ( mContext.renderingStopped() )
335 : 0 : break;
336 : :
337 : 0 : const QgsMeshFace &face = triangles[i];
338 : :
339 : 0 : const int v1 = face[0], v2 = face[1], v3 = face[2];
340 : 0 : const QgsPoint p1 = vertices[v1], p2 = vertices[v2], p3 = vertices[v3];
341 : :
342 : 0 : const int nativeFaceIndex = mTriangularMesh.trianglesToNativeFaces()[i];
343 : :
344 : : // Get the BBox of the element in pixels
345 : 0 : QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( p1, p2, p3 );
346 : : int left, right, top, bottom;
347 : 0 : QgsMeshLayerUtils::boundingBoxToScreenRectangle( mContext.mapToPixel(), mOutputSize, bbox, left, right, top, bottom );
348 : :
349 : : // Align rect to the grid (e.g. interval <13, 36> with grid cell 10 will be trimmed to <20,30>
350 : 0 : if ( left % cellx != 0 )
351 : 0 : left += cellx - ( left % cellx );
352 : 0 : if ( right % cellx != 0 )
353 : 0 : right -= ( right % cellx );
354 : 0 : if ( top % celly != 0 )
355 : 0 : top += celly - ( top % celly );
356 : 0 : if ( bottom % celly != 0 )
357 : 0 : bottom -= ( bottom % celly );
358 : :
359 : 0 : for ( int y = top; y <= bottom; y += celly )
360 : : {
361 : 0 : for ( int x = left; x <= right; x += cellx )
362 : : {
363 : 0 : QgsMeshDatasetValue val;
364 : 0 : const QgsPointXY p = mContext.mapToPixel().toMapCoordinates( x, y );
365 : :
366 : 0 : if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices )
367 : : {
368 : 0 : const auto val1 = mDatasetValues.value( v1 );
369 : 0 : const auto val2 = mDatasetValues.value( v2 );
370 : 0 : const auto val3 = mDatasetValues.value( v3 );
371 : 0 : val.setX(
372 : 0 : QgsMeshLayerUtils::interpolateFromVerticesData(
373 : 0 : p1, p2, p3,
374 : 0 : val1.x(),
375 : 0 : val2.x(),
376 : 0 : val3.x(),
377 : : p )
378 : : );
379 : 0 : val.setY(
380 : 0 : QgsMeshLayerUtils::interpolateFromVerticesData(
381 : 0 : p1, p2, p3,
382 : 0 : val1.y(),
383 : 0 : val2.y(),
384 : 0 : val3.y(),
385 : : p )
386 : : );
387 : 0 : }
388 : 0 : else if ( mDataType == QgsMeshDatasetGroupMetadata::DataType::DataOnFaces )
389 : : {
390 : 0 : const auto val1 = mDatasetValues.value( nativeFaceIndex );
391 : 0 : val.setX(
392 : 0 : QgsMeshLayerUtils::interpolateFromFacesData(
393 : 0 : p1, p2, p3,
394 : 0 : val1.x(),
395 : : p
396 : : )
397 : : );
398 : 0 : val.setY(
399 : 0 : QgsMeshLayerUtils::interpolateFromFacesData(
400 : 0 : p1, p2, p3,
401 : 0 : val1.y(),
402 : : p
403 : : )
404 : : );
405 : 0 : }
406 : 0 : if ( nodataValue( val.x(), val.y() ) )
407 : 0 : continue;
408 : :
409 : 0 : QgsPointXY lineStart( x, y );
410 : 0 : drawVectorArrow( lineStart, val.x(), val.y(), val.scalar() );
411 : 0 : }
412 : 0 : }
413 : 0 : }
414 : 0 : }
415 : :
416 : 0 : void QgsMeshVectorArrowRenderer::drawVectorArrow( const QgsPointXY &lineStart, double xVal, double yVal, double magnitude )
417 : : {
418 : 0 : QgsPointXY lineEnd;
419 : : double vectorLength;
420 : : double cosAlpha, sinAlpha;
421 : 0 : if ( calcVectorLineEnd( lineEnd, vectorLength, cosAlpha, sinAlpha,
422 : 0 : lineStart, xVal, yVal, magnitude ) )
423 : 0 : return;
424 : :
425 : : // Make a set of vector head coordinates that we will place at the end of each vector,
426 : : // scale, translate and rotate.
427 : 0 : QgsPointXY vectorHeadPoints[3];
428 : 0 : QVector<QPointF> finalVectorHeadPoints( 3 );
429 : :
430 : 0 : double vectorHeadWidthRatio = mCfg.arrowSettings().arrowHeadWidthRatio();
431 : 0 : double vectorHeadLengthRatio = mCfg.arrowSettings().arrowHeadLengthRatio();
432 : :
433 : : // First head point: top of ->
434 : 0 : vectorHeadPoints[0].setX( -1.0 * vectorHeadLengthRatio );
435 : 0 : vectorHeadPoints[0].setY( vectorHeadWidthRatio * 0.5 );
436 : :
437 : : // Second head point: right of ->
438 : 0 : vectorHeadPoints[1].setX( 0.0 );
439 : 0 : vectorHeadPoints[1].setY( 0.0 );
440 : :
441 : : // Third head point: bottom of ->
442 : 0 : vectorHeadPoints[2].setX( -1.0 * vectorHeadLengthRatio );
443 : 0 : vectorHeadPoints[2].setY( -1.0 * vectorHeadWidthRatio * 0.5 );
444 : :
445 : : // Determine the arrow head coords
446 : 0 : for ( int j = 0; j < 3; j++ )
447 : : {
448 : 0 : finalVectorHeadPoints[j].setX( lineEnd.x()
449 : 0 : + ( vectorHeadPoints[j].x() * cosAlpha * vectorLength )
450 : 0 : - ( vectorHeadPoints[j].y() * sinAlpha * vectorLength )
451 : : );
452 : :
453 : 0 : finalVectorHeadPoints[j].setY( lineEnd.y()
454 : 0 : - ( vectorHeadPoints[j].x() * sinAlpha * vectorLength )
455 : 0 : - ( vectorHeadPoints[j].y() * cosAlpha * vectorLength )
456 : : );
457 : 0 : }
458 : :
459 : : // Now actually draw the vector
460 : 0 : QPen pen( mContext.painter()->pen() );
461 : 0 : pen.setColor( mVectorColoring.color( magnitude ) );
462 : 0 : mContext.painter()->setPen( pen );
463 : 0 : mContext.painter()->drawLine( lineStart.toQPointF(), lineEnd.toQPointF() );
464 : 0 : mContext.painter()->drawPolygon( finalVectorHeadPoints );
465 : 0 : }
466 : :
467 : 0 : QgsMeshVectorRenderer::~QgsMeshVectorRenderer() = default;
468 : :
469 : 0 : QgsMeshVectorRenderer *QgsMeshVectorRenderer::makeVectorRenderer(
470 : : const QgsTriangularMesh &m,
471 : : const QgsMeshDataBlock &datasetVectorValues,
472 : : const QgsMeshDataBlock &scalarActiveFaceFlagValues,
473 : : const QVector<double> &datasetValuesMag,
474 : : double datasetMagMaximumValue,
475 : : double datasetMagMinimumValue,
476 : : QgsMeshDatasetGroupMetadata::DataType dataType,
477 : : const QgsMeshRendererVectorSettings &settings,
478 : : QgsRenderContext &context,
479 : : const QgsRectangle &layerExtent,
480 : : QSize size )
481 : : {
482 : 0 : QgsMeshVectorRenderer *renderer = nullptr;
483 : :
484 : 0 : switch ( settings.symbology() )
485 : : {
486 : : case QgsMeshRendererVectorSettings::Arrows:
487 : 0 : renderer = new QgsMeshVectorArrowRenderer(
488 : 0 : m,
489 : 0 : datasetVectorValues,
490 : 0 : datasetValuesMag,
491 : 0 : datasetMagMaximumValue,
492 : 0 : datasetMagMinimumValue,
493 : 0 : dataType,
494 : 0 : settings,
495 : 0 : context,
496 : 0 : size );
497 : 0 : break;
498 : : case QgsMeshRendererVectorSettings::Streamlines:
499 : 0 : renderer = new QgsMeshVectorStreamlineRenderer(
500 : 0 : m,
501 : 0 : datasetVectorValues,
502 : 0 : scalarActiveFaceFlagValues,
503 : 0 : dataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices,
504 : 0 : settings,
505 : 0 : context,
506 : 0 : layerExtent,
507 : 0 : datasetMagMaximumValue );
508 : 0 : break;
509 : : case QgsMeshRendererVectorSettings::Traces:
510 : 0 : renderer = new QgsMeshVectorTraceRenderer(
511 : 0 : m,
512 : 0 : datasetVectorValues,
513 : 0 : scalarActiveFaceFlagValues,
514 : 0 : dataType == QgsMeshDatasetGroupMetadata::DataType::DataOnVertices,
515 : 0 : settings,
516 : 0 : context,
517 : 0 : layerExtent,
518 : 0 : datasetMagMaximumValue );
519 : 0 : break;
520 : : }
521 : :
522 : 0 : return renderer;
523 : 0 : }
524 : :
525 : :
526 : : ///@endcond
|