QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsmeshlayerutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshlayerutils.cpp
3  --------------------------
4  begin : August 2018
5  copyright : (C) 2018 by Martin Dobias
6  email : wonder dot sk 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 <limits>
19 #include <QTime>
20 #include <QDateTime>
21 
22 #include "qgsmeshlayerutils.h"
23 #include "qgsmeshtimesettings.h"
24 #include "qgstriangularmesh.h"
25 #include "qgslogger.h"
26 #include "qgsmeshdataprovider.h"
27 #include "qgsmesh3daveraging.h"
28 #include "qgsmeshlayer.h"
29 
30 
32 
33 int QgsMeshLayerUtils::datasetValuesCount( const QgsMesh *mesh, QgsMeshDatasetGroupMetadata::DataType dataType )
34 {
35  if ( !mesh )
36  return 0;
37 
38  switch ( dataType )
39  {
40  case QgsMeshDatasetGroupMetadata::DataType::DataOnEdges:
41  return mesh->edgeCount();
42  case QgsMeshDatasetGroupMetadata::DataType::DataOnFaces:
43  return mesh->faceCount();
44  case QgsMeshDatasetGroupMetadata::DataType::DataOnVertices:
45  return mesh->vertexCount();
46  case QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes:
47  return mesh->faceCount(); // because they are averaged to faces
48  }
49  return 0;
50 }
51 
52 QgsMeshDatasetGroupMetadata::DataType QgsMeshLayerUtils::datasetValuesType( const QgsMeshDatasetGroupMetadata::DataType &type )
53 {
54  // data on volumes are averaged to 2D data on faces
55  if ( type == QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
56  return QgsMeshDatasetGroupMetadata::DataType::DataOnFaces;
57 
58  return type;
59 }
60 
61 QgsMeshDataBlock QgsMeshLayerUtils::datasetValues(
62  const QgsMeshLayer *meshLayer,
63  QgsMeshDatasetIndex index,
64  int valueIndex,
65  int count )
66 {
67  QgsMeshDataBlock block;
68  if ( !meshLayer )
69  return block;
70 
71 
72  if ( !meshLayer->datasetCount( index ) )
73  return block;
74 
75  if ( !index.isValid() )
76  return block;
77 
78  const QgsMeshDatasetGroupMetadata meta = meshLayer->datasetGroupMetadata( index.group() );
79  if ( meta.dataType() != QgsMeshDatasetGroupMetadata::DataType::DataOnVolumes )
80  {
81  block = meshLayer->datasetValues( index, valueIndex, count );
82  if ( block.isValid() )
83  return block;
84  }
85  else
86  {
87  const QgsMesh3dAveragingMethod *averagingMethod = meshLayer->rendererSettings().averagingMethod();
88  if ( !averagingMethod )
89  return block;
90 
91  QgsMesh3dDataBlock block3d = meshLayer->dataset3dValues( index, valueIndex, count );
92  if ( !block3d.isValid() )
93  return block;
94 
95  block = averagingMethod->calculate( block3d );
96  }
97  return block;
98 }
99 
100 QVector<QgsVector> QgsMeshLayerUtils::griddedVectorValues( const QgsMeshLayer *meshLayer,
101  const QgsMeshDatasetIndex index,
102  double xSpacing,
103  double ySpacing,
104  const QSize &size,
105  const QgsPointXY &minCorner )
106 {
107  QVector<QgsVector> vectors;
108 
109  if ( !meshLayer || !index.isValid() )
110  return vectors;
111 
112  const QgsTriangularMesh *triangularMesh = meshLayer->triangularMesh();
113  const QgsMesh *nativeMesh = meshLayer->nativeMesh();
114 
115  if ( !triangularMesh || !nativeMesh )
116  return vectors;
117 
118  QgsMeshDatasetGroupMetadata meta = meshLayer->datasetGroupMetadata( index );
119  if ( !meta.isVector() )
120  return vectors;
121 
122  // extract vector dataset
123  bool vectorDataOnVertices = meta.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
124  int datacount = vectorDataOnVertices ? nativeMesh->vertices.count() : nativeMesh->faces.count();
125  const QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues( meshLayer, index, 0, datacount );
126 
127  const QgsMeshDataBlock isFacesActive = meshLayer->areFacesActive( index, 0, nativeMesh->faceCount() );
128  const QgsMeshDatasetGroupMetadata::DataType dataType = meta.dataType();
129 
131  return vectors;
132 
133  try
134  {
135  vectors.reserve( size.height()*size.width() );
136  }
137  catch ( ... )
138  {
139  QgsDebugMsgLevel( "Unable to store the arrow grid in memory", 1 );
140  return QVector<QgsVector>();
141  }
142 
143  for ( int iy = 0; iy < size.height(); ++iy )
144  {
145  double y = minCorner.y() + iy * ySpacing;
146  for ( int ix = 0; ix < size.width(); ++ix )
147  {
148  double x = minCorner.x() + ix * xSpacing;
149  QgsPoint point( x, y );
150  int faceIndex = triangularMesh->faceIndexForPoint_v2( point );
151  int nativeFaceIndex = -1;
152  if ( faceIndex != -1 )
153  nativeFaceIndex = triangularMesh->trianglesToNativeFaces().at( faceIndex );
154  QgsMeshDatasetValue value;
155  if ( nativeFaceIndex != -1 && isFacesActive.active( nativeFaceIndex ) )
156  {
157  switch ( dataType )
158  {
161  value = vals.value( nativeFaceIndex );
162  break;
164  {
165  const QgsMeshFace &face = triangularMesh->triangles()[faceIndex];
166  const int v1 = face[0], v2 = face[1], v3 = face[2];
167  const QgsPoint p1 = triangularMesh->vertices()[v1], p2 = triangularMesh->vertices()[v2], p3 = triangularMesh->vertices()[v3];
168  const QgsMeshDatasetValue val1 = vals.value( v1 );
169  const QgsMeshDatasetValue val2 = vals.value( v2 );
170  const QgsMeshDatasetValue val3 = vals.value( v3 );
171  const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
172  const double y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
173  value = QgsMeshDatasetValue( x, y );
174  }
175  break;
177  break;
178  }
179  }
180  vectors.append( QgsVector( value.x(), value.y() ) );
181  }
182  }
183  return vectors;
184 }
185 
186 QVector<double> QgsMeshLayerUtils::calculateMagnitudes( const QgsMeshDataBlock &block )
187 {
188  Q_ASSERT( QgsMeshDataBlock::ActiveFlagInteger != block.type() );
189  int count = block.count();
190  QVector<double> ret( count );
191 
192  for ( int i = 0; i < count; ++i )
193  {
194  double mag = block.value( i ).scalar();
195  ret[i] = mag;
196  }
197  return ret;
198 }
199 
200 QgsRectangle QgsMeshLayerUtils::boundingBoxToScreenRectangle(
201  const QgsMapToPixel &mtp,
202  const QgsRectangle &bbox
203 )
204 {
205  const QgsPointXY topLeft = mtp.transform( bbox.xMinimum(), bbox.yMaximum() );
206  const QgsPointXY topRight = mtp.transform( bbox.xMaximum(), bbox.yMaximum() );
207  const QgsPointXY bottomLeft = mtp.transform( bbox.xMinimum(), bbox.yMinimum() );
208  const QgsPointXY bottomRight = mtp.transform( bbox.xMaximum(), bbox.yMinimum() );
209 
210  double xMin = std::min( {topLeft.x(), topRight.x(), bottomLeft.x(), bottomRight.x()} );
211  double xMax = std::max( {topLeft.x(), topRight.x(), bottomLeft.x(), bottomRight.x()} );
212  double yMin = std::min( {topLeft.y(), topRight.y(), bottomLeft.y(), bottomRight.y()} );
213  double yMax = std::max( {topLeft.y(), topRight.y(), bottomLeft.y(), bottomRight.y()} );
214 
215  QgsRectangle ret( xMin, yMin, xMax, yMax );
216  return ret;
217 }
218 
219 void QgsMeshLayerUtils::boundingBoxToScreenRectangle(
220  const QgsMapToPixel &mtp,
221  const QSize &outputSize,
222  const QgsRectangle &bbox,
223  int &leftLim,
224  int &rightLim,
225  int &bottomLim,
226  int &topLim )
227 {
228  const QgsRectangle screenBBox = boundingBoxToScreenRectangle( mtp, bbox );
229 
230  bottomLim = std::max( int( screenBBox.yMinimum() ), 0 );
231  topLim = std::min( int( screenBBox.yMaximum() ), outputSize.height() - 1 );
232  leftLim = std::max( int( screenBBox.xMinimum() ), 0 );
233  rightLim = std::min( int( screenBBox.xMaximum() ), outputSize.width() - 1 );
234 }
235 
236 static void lamTol( double &lam )
237 {
238  const static double eps = 1e-6;
239  if ( ( lam < 0.0 ) && ( lam > -eps ) )
240  {
241  lam = 0.0;
242  }
243 }
244 
245 static bool E3T_physicalToBarycentric( const QgsPointXY &pA, const QgsPointXY &pB, const QgsPointXY &pC, const QgsPointXY &pP,
246  double &lam1, double &lam2, double &lam3 )
247 {
248  if ( pA == pB || pA == pC || pB == pC )
249  return false; // this is not a valid triangle!
250 
251  // Compute vectors
252  QgsVector v0( pC - pA );
253  QgsVector v1( pB - pA );
254  QgsVector v2( pP - pA );
255 
256  // Compute dot products
257  double dot00 = v0 * v0;
258  double dot01 = v0 * v1;
259  double dot02 = v0 * v2;
260  double dot11 = v1 * v1;
261  double dot12 = v1 * v2;
262 
263  // Compute barycentric coordinates
264  double invDenom = 1.0 / ( dot00 * dot11 - dot01 * dot01 );
265  lam1 = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
266  lam2 = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
267  lam3 = 1.0 - lam1 - lam2;
268 
269  // Apply some tolerance to lam so we can detect correctly border points
270  lamTol( lam1 );
271  lamTol( lam2 );
272  lamTol( lam3 );
273 
274  // Return if POI is outside triangle
275  if ( ( lam1 < 0 ) || ( lam2 < 0 ) || ( lam3 < 0 ) )
276  {
277  return false;
278  }
279 
280  return true;
281 }
282 
283 double QgsMeshLayerUtils::interpolateFromVerticesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3,
284  double val1, double val2, double val3, const QgsPointXY &pt )
285 {
286  double lam1, lam2, lam3;
287  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
288  return std::numeric_limits<double>::quiet_NaN();
289 
290  return lam1 * val3 + lam2 * val2 + lam3 * val1;
291 }
292 
293 double QgsMeshLayerUtils::interpolateFromVerticesData( double fraction, double val1, double val2 )
294 {
295  if ( std::isnan( val1 ) || std::isnan( val2 ) || ( fraction < 0 ) || ( fraction > 1 ) )
296  {
297  return std::numeric_limits<double>::quiet_NaN();
298  }
299  return val1 + ( val2 - val1 ) * fraction;
300 }
301 
302 QgsMeshDatasetValue QgsMeshLayerUtils::interpolateFromVerticesData( double fraction, const QgsMeshDatasetValue &val1, const QgsMeshDatasetValue &val2 )
303 {
304  return QgsMeshDatasetValue( interpolateFromVerticesData( fraction, val1.x(), val2.x() ),
305  interpolateFromVerticesData( fraction, val1.y(), val2.y() ) );
306 }
307 
308 
309 QgsVector QgsMeshLayerUtils::interpolateVectorFromVerticesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3, QgsVector vect1, QgsVector vect2, QgsVector vect3, const QgsPointXY &pt )
310 {
311  double lam1, lam2, lam3;
312  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
313  return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
314 
315  return vect3 * lam1 + vect2 * lam2 + vect1 * lam3;
316 }
317 
318 double QgsMeshLayerUtils::interpolateFromFacesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3,
319  double val, const QgsPointXY &pt )
320 {
321  double lam1, lam2, lam3;
322  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
323  return std::numeric_limits<double>::quiet_NaN();
324 
325  return val;
326 }
327 
328 QgsVector QgsMeshLayerUtils::interpolateVectorFromFacesData( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3,
329  QgsVector vect, const QgsPointXY &pt )
330 {
331  double lam1, lam2, lam3;
332  if ( !E3T_physicalToBarycentric( p1, p2, p3, pt, lam1, lam2, lam3 ) )
333  return QgsVector( std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN() );
334 
335  return vect;
336 }
337 
338 
339 QVector<double> QgsMeshLayerUtils::interpolateFromFacesData(
340  QVector<double> valuesOnFaces,
341  const QgsMesh *nativeMesh,
342  const QgsTriangularMesh *triangularMesh,
343  QgsMeshDataBlock *active,
345 {
346  assert( nativeMesh );
347  Q_UNUSED( method );
349 
350  // assuming that native vertex count = triangular vertex count
351  assert( nativeMesh->vertices.size() == triangularMesh->vertices().size() );
352  int vertexCount = triangularMesh->vertices().size();
353 
354  QVector<double> res( vertexCount, 0.0 );
355  // for face datasets do simple average of the valid values of all faces that contains this vertex
356  QVector<int> count( vertexCount, 0 );
357 
358  for ( int i = 0; i < nativeMesh->faces.size(); ++i )
359  {
360  if ( !active || active->active( i ) )
361  {
362  double val = valuesOnFaces[ i ];
363  if ( !std::isnan( val ) )
364  {
365  // assign for all vertices
366  const QgsMeshFace &face = nativeMesh->faces.at( i );
367  for ( int j = 0; j < face.size(); ++j )
368  {
369  int vertexIndex = face[j];
370  res[vertexIndex] += val;
371  count[vertexIndex] += 1;
372  }
373  }
374  }
375  }
376 
377  for ( int i = 0; i < vertexCount; ++i )
378  {
379  if ( count.at( i ) > 0 )
380  {
381  res[i] = res[i] / double( count.at( i ) );
382  }
383  else
384  {
385  res[i] = std::numeric_limits<double>::quiet_NaN();
386  }
387  }
388 
389  return res;
390 }
391 
392 QVector<double> QgsMeshLayerUtils::resampleFromVerticesToFaces(
393  const QVector<double> valuesOnVertices,
394  const QgsMesh *nativeMesh,
395  const QgsTriangularMesh *triangularMesh,
396  const QgsMeshDataBlock *active,
398 {
399  assert( nativeMesh );
400  Q_UNUSED( method );
402 
403  // assuming that native vertex count = triangular vertex count
404  Q_UNUSED( triangularMesh );
405  assert( nativeMesh->vertices.size() == triangularMesh->vertices().size() );
406 
407  QVector<double> ret( nativeMesh->faceCount(), std::numeric_limits<double>::quiet_NaN() );
408 
409  for ( int i = 0; i < nativeMesh->faces.size(); ++i )
410  {
411  const QgsMeshFace face = nativeMesh->face( i );
412  if ( active->active( i ) && face.count() > 2 )
413  {
414  double value = 0;
415  for ( int j = 0; j < face.count(); ++j )
416  {
417  value += valuesOnVertices.at( face.at( j ) );
418  }
419  ret[i] = value / face.count();
420  }
421  }
422 
423  return ret;
424 }
425 
426 QVector<double> QgsMeshLayerUtils::calculateMagnitudeOnVertices( const QgsMeshLayer *meshLayer,
427  const QgsMeshDatasetIndex index,
428  QgsMeshDataBlock *activeFaceFlagValues,
430 {
431  QVector<double> ret;
432 
433  if ( !meshLayer && !index.isValid() )
434  return ret;
435 
436  const QgsTriangularMesh *triangularMesh = meshLayer->triangularMesh();
437  const QgsMesh *nativeMesh = meshLayer->nativeMesh();
438  if ( !triangularMesh || !nativeMesh )
439  return ret;
440 
441  const QgsMeshDatasetGroupMetadata metadata = meshLayer->datasetGroupMetadata( index );
442  bool scalarDataOnVertices = metadata.dataType() == QgsMeshDatasetGroupMetadata::DataOnVertices;
443 
444  // populate scalar values
445  int datacount = scalarDataOnVertices ? nativeMesh->vertices.count() : nativeMesh->faces.count();
446  QgsMeshDataBlock vals = QgsMeshLayerUtils::datasetValues(
447  meshLayer,
448  index,
449  0,
450  datacount );
451 
452  if ( vals.isValid() )
453  {
454  ret = QgsMeshLayerUtils::calculateMagnitudes( vals );
455 
456  if ( !scalarDataOnVertices )
457  {
458  //Need to interpolate data on vertices
459  ret = QgsMeshLayerUtils::interpolateFromFacesData(
460  ret,
461  nativeMesh,
462  triangularMesh,
463  activeFaceFlagValues,
464  method );
465  }
466  }
467  return ret;
468 }
469 
470 QgsRectangle QgsMeshLayerUtils::triangleBoundingBox( const QgsPointXY &p1, const QgsPointXY &p2, const QgsPointXY &p3 )
471 {
472  // p1
473  double xMin = p1.x();
474  double xMax = p1.x();
475  double yMin = p1.y();
476  double yMax = p1.y();
477 
478  //p2
479  xMin = ( ( xMin < p2.x() ) ? xMin : p2.x() );
480  xMax = ( ( xMax > p2.x() ) ? xMax : p2.x() );
481  yMin = ( ( yMin < p2.y() ) ? yMin : p2.y() );
482  yMax = ( ( yMax > p2.y() ) ? yMax : p2.y() );
483 
484  // p3
485  xMin = ( ( xMin < p3.x() ) ? xMin : p3.x() );
486  xMax = ( ( xMax > p3.x() ) ? xMax : p3.x() );
487  yMin = ( ( yMin < p3.y() ) ? yMin : p3.y() );
488  yMax = ( ( yMax > p3.y() ) ? yMax : p3.y() );
489 
490  QgsRectangle bbox( xMin, yMin, xMax, yMax );
491  return bbox;
492 }
493 
494 QString QgsMeshLayerUtils::formatTime( double hours, const QDateTime &referenceTime, const QgsMeshTimeSettings &settings )
495 {
496  QString ret;
497 
498  if ( referenceTime.isValid() )
499  {
500  QString format( settings.absoluteTimeFormat() );
501  QDateTime dateTime( referenceTime );
502  qint64 seconds = static_cast<qint64>( hours * 3600.0 );
503  dateTime = dateTime.addSecs( seconds );
504  ret = dateTime.toString( format );
505  if ( ret.isEmpty() ) // error
506  ret = dateTime.toString();
507  }
508  else
509  {
510  QString format( settings.relativeTimeFormat() );
511  format = format.trimmed();
512  int totalHours = static_cast<int>( hours );
513 
514  if ( format == QLatin1String( "hh:mm:ss.zzz" ) )
515  {
516  int ms = static_cast<int>( hours * 3600.0 * 1000 );
517  int seconds = ms / 1000;
518  int z = ms % 1000;
519  int m = seconds / 60;
520  int s = seconds % 60;
521  int h = m / 60;
522  m = m % 60;
523  ret = QStringLiteral( "%1:%2:%3.%4" ).
524  arg( h, 2, 10, QLatin1Char( '0' ) ).
525  arg( m, 2, 10, QLatin1Char( '0' ) ).
526  arg( s, 2, 10, QLatin1Char( '0' ) ).
527  arg( z, 3, 10, QLatin1Char( '0' ) );
528  }
529  else if ( format == QLatin1String( "hh:mm:ss" ) )
530  {
531  int seconds = static_cast<int>( hours * 3600.0 );
532  int m = seconds / 60;
533  int s = seconds % 60;
534  int h = m / 60;
535  m = m % 60;
536  ret = QStringLiteral( "%1:%2:%3" ).
537  arg( h, 2, 10, QLatin1Char( '0' ) ).
538  arg( m, 2, 10, QLatin1Char( '0' ) ).
539  arg( s, 2, 10, QLatin1Char( '0' ) );
540 
541  }
542  else if ( format == QLatin1String( "d hh:mm:ss" ) )
543  {
544  int seconds = static_cast<int>( hours * 3600.0 );
545  int m = seconds / 60;
546  int s = seconds % 60;
547  int h = m / 60;
548  m = m % 60;
549  int d = totalHours / 24;
550  h = totalHours % 24;
551  ret = QStringLiteral( "%1 d %2:%3:%4" ).
552  arg( d ).
553  arg( h, 2, 10, QLatin1Char( '0' ) ).
554  arg( m, 2, 10, QLatin1Char( '0' ) ).
555  arg( s, 2, 10, QLatin1Char( '0' ) );
556  }
557  else if ( format == QLatin1String( "d hh" ) )
558  {
559  int d = totalHours / 24;
560  int h = totalHours % 24;
561  ret = QStringLiteral( "%1 d %2" ).
562  arg( d ).
563  arg( h );
564  }
565  else if ( format == QLatin1String( "d" ) )
566  {
567  int d = totalHours / 24;
568  ret = QString::number( d );
569  }
570  else if ( format == QLatin1String( "ss" ) )
571  {
572  int seconds = static_cast<int>( hours * 3600.0 );
573  ret = QString::number( seconds );
574  }
575  else // "hh"
576  {
577  ret = QString::number( hours );
578  }
579  }
580  return ret;
581 }
582 
583 QVector<QVector3D> QgsMeshLayerUtils::calculateNormals( const QgsTriangularMesh &triangularMesh, const QVector<double> &verticalMagnitude, bool isRelative )
584 {
585  QVector<QVector3D> normals( triangularMesh.vertices().count() );
586  for ( const auto &face : triangularMesh.triangles() )
587  {
588  for ( int i = 0; i < 3; i++ )
589  {
590  int index( face.at( i ) );
591  int index1( face.at( ( i + 1 ) % 3 ) );
592  int index2( face.at( ( i + 2 ) % 3 ) );
593 
594  const QgsMeshVertex &vert( triangularMesh.vertices().at( index ) );
595  const QgsMeshVertex &otherVert1( triangularMesh.vertices().at( index1 ) );
596  const QgsMeshVertex &otherVert2( triangularMesh.vertices().at( index2 ) );
597 
598  float adjustRelative = 0;
599  float adjustRelative1 = 0;
600  float adjustRelative2 = 0;
601 
602  if ( isRelative )
603  {
604  adjustRelative = vert.z();
605  adjustRelative1 = otherVert1.z();
606  adjustRelative2 = otherVert2.z();
607  }
608 
609  QVector3D v1( float( otherVert1.x() - vert.x() ),
610  float( otherVert1.y() - vert.y() ),
611  float( verticalMagnitude[index1] - verticalMagnitude[index] + adjustRelative1 - adjustRelative ) );
612  QVector3D v2( float( otherVert2.x() - vert.x() ),
613  float( otherVert2.y() - vert.y() ),
614  float( verticalMagnitude[index2] - verticalMagnitude[index] + adjustRelative2 - adjustRelative ) );
615 
616  normals[index] += QVector3D::crossProduct( v1, v2 );
617  }
618  }
619 
620  return normals;
621 }
622 
qgsmeshlayerutils.h
qgsmesh3daveraging.h
QgsPointXY::y
double y
Definition: qgspointxy.h:48
QgsMeshDatasetGroupMetadata::DataOnVolumes
@ DataOnVolumes
Data is defined on volumes.
Definition: qgsmeshdataset.h:358
QgsTriangularMesh::vertices
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
Definition: qgstriangularmesh.cpp:287
QgsMeshTimeSettings
Represents a mesh time settings for mesh datasets.
Definition: qgsmeshtimesettings.h:36
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:38
QgsDebugMsgLevel
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QgsPointXY::x
Q_GADGET double x
Definition: qgspointxy.h:47
QgsMesh3dDataBlock::isValid
bool isValid() const
Whether the block is valid.
Definition: qgsmeshdataset.cpp:341
QgsMeshDatasetValue
QgsMeshDatasetValue represents single dataset value.
Definition: qgsmeshdataset.h:78
QgsRectangle::yMinimum
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:177
QgsTriangularMesh::triangles
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
Definition: qgstriangularmesh.cpp:292
QgsMesh
Mesh - vertices, edges and faces.
Definition: qgsmeshdataprovider.h:58
QgsMeshLayer::triangularMesh
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
Definition: qgsmeshlayer.cpp:248
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QgsMesh3dDataBlock
QgsMesh3dDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
Definition: qgsmeshdataset.h:245
QgsMeshDataBlock::type
DataType type() const
Type of data stored in the block.
Definition: qgsmeshdataset.cpp:251
QgsMeshLayer::rendererSettings
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
Definition: qgsmeshlayer.cpp:287
QgsMeshRendererScalarSettings::NeighbourAverage
@ NeighbourAverage
Does a simple average of values defined for all surrounding faces/vertices.
Definition: qgsmeshrenderersettings.h:116
qgstriangularmesh.h
QgsRectangle::xMaximum
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:162
qgsmeshtimesettings.h
QgsMeshDatasetGroupMetadata::DataOnFaces
@ DataOnFaces
Data is defined on faces.
Definition: qgsmeshdataset.h:356
QgsMeshDatasetGroupMetadata::DataOnVertices
@ DataOnVertices
Data is defined on vertices.
Definition: qgsmeshdataset.h:357
QgsMesh::faceCount
int faceCount() const
Returns number of faces.
Definition: qgsmeshdataprovider.cpp:174
QgsMeshDatasetIndex::group
int group() const
Returns a group index.
Definition: qgsmeshdataset.cpp:26
QgsMesh::vertexCount
int vertexCount() const
Returns number of vertices.
Definition: qgsmeshdataprovider.cpp:169
QgsMesh::faces
QVector< QgsMeshFace > faces
Definition: qgsmeshdataprovider.h:113
QgsMesh::edgeCount
int edgeCount() const
Returns number of edge.
Definition: qgsmeshdataprovider.cpp:179
QgsMeshLayer::dataset3dValues
QgsMesh3dDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
Definition: qgsmeshlayer.cpp:367
QgsMeshDatasetIndex
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
Definition: qgsmeshdataset.h:47
QgsMeshLayer
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:95
QgsMeshDataBlock::active
bool active(int index) const
Returns a value for active flag by the index For scalar and vector 2d the behavior is undefined.
Definition: qgsmeshdataset.cpp:282
QgsMeshDatasetIndex::isValid
bool isValid() const
Returns whether index is valid, ie at least groups is set.
Definition: qgsmeshdataset.cpp:36
QgsMeshTimeSettings::relativeTimeFormat
QString relativeTimeFormat() const
Returns format used for relative time.
Definition: qgsmeshtimesettings.cpp:39
QgsMeshDatasetValue::x
double x() const
Returns x value.
Definition: qgsmeshdataset.cpp:93
QgsMeshLayer::datasetCount
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
Definition: qgsmeshlayer.cpp:347
QgsMesh::face
QgsMeshFace face(int index) const
Returns a face at the index.
Definition: qgsmeshdataprovider.cpp:114
QgsMeshRendererScalarSettings::DataResamplingMethod
DataResamplingMethod
Resampling of value from dataset.
Definition: qgsmeshrenderersettings.h:106
QgsRectangle::xMinimum
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:167
QgsTriangularMesh::faceIndexForPoint_v2
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
Definition: qgstriangularmesh.cpp:340
QgsMeshDatasetGroupMetadata::DataOnEdges
@ DataOnEdges
Data is defined on edges.
Definition: qgsmeshdataset.h:359
QgsMeshFace
QVector< int > QgsMeshFace
List of vertex indexes.
Definition: qgsmeshdataprovider.h:41
QgsMeshTimeSettings::absoluteTimeFormat
QString absoluteTimeFormat() const
Returns format used for absolute time.
Definition: qgsmeshtimesettings.cpp:49
QgsMapToPixel::transform
QgsPointXY transform(const QgsPointXY &p) const
Transform the point from map (world) coordinates to device coordinates.
Definition: qgsmaptopixel.cpp:217
QgsMesh3dAveragingMethod
Abstract class to interpolate 3d stacked mesh data to 2d data.
Definition: qgsmesh3daveraging.h:40
qgsmeshlayer.h
QgsPointXY
A class to represent a 2D point.
Definition: qgspointxy.h:44
QgsMeshDatasetGroupMetadata::dataType
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
Definition: qgsmeshdataset.cpp:171
QgsMeshDatasetGroupMetadata
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
Definition: qgsmeshdataset.h:350
QgsRectangle::yMaximum
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:172
QgsMapToPixel
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:38
QgsMeshDatasetGroupMetadata::DataType
DataType
Location of where data is specified for datasets in the dataset group.
Definition: qgsmeshdataset.h:355
QgsMeshDataBlock::ActiveFlagInteger
@ ActiveFlagInteger
Integer boolean flag whether face is active.
Definition: qgsmeshdataset.h:141
QgsTriangularMesh::trianglesToNativeFaces
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
Definition: qgstriangularmesh.cpp:317
QgsVector
A class to represent a vector.
Definition: qgsvector.h:30
QgsMeshDatasetValue::y
double y() const
Returns y value.
Definition: qgsmeshdataset.cpp:98
QgsMesh::vertices
QVector< QgsMeshVertex > vertices
Definition: qgsmeshdataprovider.h:111
QgsMeshRendererSettings::averagingMethod
QgsMesh3dAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
Definition: qgsmeshrenderersettings.cpp:396
QgsMeshDataBlock
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
Definition: qgsmeshdataset.h:136
QgsMeshLayer::datasetGroupMetadata
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
Definition: qgsmeshlayer.cpp:342
QgsMeshLayer::nativeMesh
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
Definition: qgsmeshlayer.cpp:238
QgsTriangularMesh
Triangular/Derived Mesh is mesh with vertices in map coordinates.
Definition: qgstriangularmesh.h:50
QgsMeshLayer::datasetValues
QgsMeshDataBlock datasetValues(const QgsMeshDatasetIndex &index, int valueIndex, int count) const
Returns N vector/scalar values from the index from the dataset.
Definition: qgsmeshlayer.cpp:362
qgslogger.h
QgsMeshDatasetGroupMetadata::isVector
bool isVector() const
Returns whether dataset group has vector data.
Definition: qgsmeshdataset.cpp:151
QgsMeshDataBlock::value
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
Definition: qgsmeshdataset.cpp:266
QgsMeshDatasetValue::scalar
double scalar() const
Returns magnitude of vector for vector data or scalar value for scalar data.
Definition: qgsmeshdataset.cpp:62
QgsMesh3dAveragingMethod::calculate
QgsMeshDataBlock calculate(const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
Definition: qgsmesh3daveraging.cpp:57
QgsMeshLayer::areFacesActive
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether the faces are active for particular dataset.
Definition: qgsmeshlayer.cpp:372
qgsmeshdataprovider.h
QgsMeshDataBlock::isValid
bool isValid() const
Whether the block is valid.
Definition: qgsmeshdataset.cpp:261
QgsMeshDataBlock::count
int count() const
Number of items stored in the block.
Definition: qgsmeshdataset.cpp:256