QGIS API Documentation  3.20.0-Odense (decaadbb31)
qgsmeshlayer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmeshlayer.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 <cstddef>
19 #include <limits>
20 
21 #include <QUuid>
22 #include <QUrl>
23 
24 #include "qgscolorramp.h"
25 #include "qgslogger.h"
26 #include "qgsmaplayerlegend.h"
27 #include "qgsmaplayerfactory.h"
28 #include "qgsmeshdataprovider.h"
30 #include "qgsmeshlayer.h"
31 #include "qgsmeshlayerrenderer.h"
33 #include "qgsmeshlayerutils.h"
34 #include "qgsmeshtimesettings.h"
35 #include "qgspainting.h"
36 #include "qgsproviderregistry.h"
37 #include "qgsreadwritecontext.h"
38 #include "qgsstyle.h"
39 #include "qgstriangularmesh.h"
40 #include "qgsmesh3daveraging.h"
42 
43 QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
44  const QString &baseName,
45  const QString &providerKey,
46  const QgsMeshLayer::LayerOptions &options )
47  : QgsMapLayer( QgsMapLayerType::MeshLayer, baseName, meshLayerPath ),
48  mDatasetGroupStore( new QgsMeshDatasetGroupStore( this ) ),
49  mTemporalProperties( new QgsMeshLayerTemporalProperties( this ) )
50 
51 {
53 
54  QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
55  QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
57  {
59  }
60  setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
63 
64  if ( isValid() )
65  setDefaultRendererSettings( mDatasetGroupStore->datasetGroupIndexes() );
66 
67  connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
68 }
69 
70 
71 void QgsMeshLayer::setDefaultRendererSettings( const QList<int> &groupIndexes )
72 {
73  QgsMeshRendererMeshSettings meshSettings;
74  if ( groupIndexes.count() > 0 )
75  {
76  // Show data from the first dataset group
77  mRendererSettings.setActiveScalarDatasetGroup( 0 );
78  // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
80  if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
81  meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
82  meshSettings.setEnabled( true );
83  }
84  else
85  {
86  // show at least the mesh by default
87  meshSettings.setEnabled( true );
88  return;
89  }
90  mRendererSettings.setNativeMeshSettings( meshSettings );
91 
92  // Sets default resample method for scalar dataset
93  for ( int i : groupIndexes )
94  {
96  QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
97  switch ( meta.dataType() )
98  {
100  case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
102  break;
105  break;
107  break;
108  }
109 
110  //override color ramp if the values in the dataset group are classified
111  applyClassificationOnScalarSettings( meta, scalarSettings );
112 
113  mRendererSettings.setScalarSettings( i, scalarSettings );
114  }
115 
116 }
117 
118 void QgsMeshLayer::createSimplifiedMeshes()
119 {
120  if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
121  {
122  double reductionFactor = mSimplificationSettings.reductionFactor();
123 
124  QVector<QgsTriangularMesh *> simplifyMeshes =
125  mTriangularMeshes[0]->simplifyMesh( reductionFactor );
126 
127  for ( int i = 0; i < simplifyMeshes.count() ; ++i )
128  {
129  mTriangularMeshes.emplace_back( simplifyMeshes[i] );
130  }
131  }
132 }
133 
134 bool QgsMeshLayer::hasSimplifiedMeshes() const
135 {
136  //First mesh is the base mesh, so if size>1, there is no simplified meshes
137  return ( mTriangularMeshes.size() > 1 );
138 }
139 
141 {
142  delete mDataProvider;
143 }
144 
146 {
147  return mDataProvider;
148 }
149 
151 {
152  return mDataProvider;
153 }
154 
156 {
158  if ( mDataProvider )
159  {
160  options.transformContext = mDataProvider->transformContext();
161  }
162  QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
163  QgsMapLayer::clone( layer );
164  return layer;
165 }
166 
168 {
169  if ( mDataProvider )
170  return mDataProvider->extent();
171  else
172  {
173  QgsRectangle rec;
174  rec.setMinimal();
175  return rec;
176  }
177 }
178 
180 {
181  return mProviderKey;
182 }
183 
184 bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
185 {
186  bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
187  if ( mDatasetGroupStore->addPersistentDatasets( path ) )
188  {
189  mExtraDatasetUri.append( path );
190  QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
191  if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
192  {
194  dataProvider()->temporalCapabilities() );
195 
196  if ( ! temporalProperties->referenceTime().isValid() )
197  {
198  QDateTime referenceTime = defaultReferenceTime;
199  if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
200  referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
201  temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
202  }
203 
204  mTemporalProperties->setIsActive( true );
205  }
206  emit dataSourceChanged();
207  return true;
208  }
209 
210  return false;
211 }
212 
214 {
215  if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
216  {
217  emit dataChanged();
218  return true;
219  }
220  return false;
221 }
222 
223 bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
224 {
225  return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
226 }
227 
229 {
230  return mNativeMesh.get();
231 }
232 
234 {
235  return mNativeMesh.get();
236 }
237 
238 QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
239 {
240  for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
241  {
242  if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
243  return lod.get();
244  }
245 
246  if ( !mTriangularMeshes.empty() )
247  return mTriangularMeshes.back().get();
248  else
249  return nullptr;
250 }
251 
253 {
254  return mTriangularMeshes.size();
255 }
256 
258 {
259  if ( mTriangularMeshes.empty() )
260  return nullptr;
261  if ( lodIndex < 0 )
262  return mTriangularMeshes.front().get();
263 
264  if ( lodIndex >= int( mTriangularMeshes.size() ) )
265  return mTriangularMeshes.back().get();
266 
267  return mTriangularMeshes.at( lodIndex ).get();
268 }
269 
271 {
272  // Native mesh
273  if ( !mNativeMesh )
274  {
275  // lazy loading of mesh data
276  fillNativeMesh();
277  }
278 
279  // Triangular mesh
280  if ( mTriangularMeshes.empty() )
281  {
282  QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
283  mTriangularMeshes.emplace_back( baseMesh );
284  }
285 
286  if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
287  mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
288 
289  createSimplifiedMeshes();
290 }
291 
292 QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
293 {
294  return mRendererCache.get();
295 }
296 
298 {
299  return mRendererSettings;
300 }
301 
303 {
304  int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
305  int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
306  mRendererSettings = settings;
307 
308  if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
309  emit activeScalarDatasetGroupChanged( mRendererSettings.activeScalarDatasetGroup() );
310 
311  if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
312  emit activeVectorDatasetGroupChanged( mRendererSettings.activeVectorDatasetGroup() );
313 
314  emit rendererChanged();
315  triggerRepaint();
316 }
317 
319 {
320  return mTimeSettings;
321 }
322 
324 {
325  mTimeSettings = settings;
326  emit timeSettingsChanged();
327 }
328 
329 QString QgsMeshLayer::formatTime( double hours )
330 {
331  if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
332  return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
333  else
334  return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
335 }
336 
338 {
339  return mDatasetGroupStore->datasetGroupCount();
340 }
341 
343 {
344  return mDatasetGroupStore->extraDatasetGroupCount();
345 }
346 
348 {
349  return mDatasetGroupStore->datasetGroupIndexes();
350 }
351 
353 {
354  return mDatasetGroupStore->enabledDatasetGroupIndexes();
355 }
356 
358 {
359  return mDatasetGroupStore->datasetGroupMetadata( index );
360 }
361 
363 {
364  return mDatasetGroupStore->datasetCount( index.group() );
365 }
366 
368 {
369  return mDatasetGroupStore->datasetMetadata( index );
370 }
371 
373 {
374  return mDatasetGroupStore->datasetValue( index, valueIndex );
375 }
376 
377 QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
378 {
379  return mDatasetGroupStore->datasetValues( index, valueIndex, count );
380 }
381 
382 QgsMesh3dDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
383 {
384  return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
385 }
386 
387 QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
388 {
389  return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
390 }
391 
392 bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
393 {
394  return mDatasetGroupStore->isFaceActive( index, faceIndex );
395 }
396 
397 QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
398 {
399  QgsMeshDatasetValue value;
400  const QgsTriangularMesh *mesh = triangularMesh();
401 
402  if ( mesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
403  {
404  if ( dataProvider()->contains( QgsMesh::ElementType::Edge ) )
405  {
406  QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
407  return dataset1dValue( index, point, searchRadius );
408  }
409  int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
410  if ( faceIndex >= 0 )
411  {
412  int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
414  if ( isFaceActive( index, nativeFaceIndex ) )
415  {
416  switch ( dataType )
417  {
419  {
420  value = datasetValue( index, nativeFaceIndex );
421  }
422  break;
423 
425  {
426  const QgsMeshFace &face = mesh->triangles()[faceIndex];
427  const int v1 = face[0], v2 = face[1], v3 = face[2];
428  const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
429  const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
430  const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
431  const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
432  const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
433  double y = std::numeric_limits<double>::quiet_NaN();
434  bool isVector = datasetGroupMetadata( index ).isVector();
435  if ( isVector )
436  y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
437 
438  value = QgsMeshDatasetValue( x, y );
439  }
440  break;
441 
443  {
444  const QgsMesh3dAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
445  if ( avgMethod )
446  {
447  const QgsMesh3dDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
448  const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
449  if ( block2d.isValid() )
450  {
451  value = block2d.value( 0 );
452  }
453  }
454  }
455  break;
456 
457  default:
458  break;
459  }
460  }
461  }
462  }
463 
464  return value;
465 }
466 
468 {
469  QgsMesh3dDataBlock block3d;
470 
471  const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
472 
473  if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
474  {
477  {
478  int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
479  if ( faceIndex >= 0 )
480  {
481  int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
482  block3d = dataset3dValues( index, nativeFaceIndex, 1 );
483  }
484  }
485  }
486  return block3d;
487 }
488 
489 QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
490 {
491  QgsMeshDatasetValue value;
492  QgsPointXY projectedPoint;
493  int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
494  const QgsTriangularMesh *mesh = triangularMesh();
495  if ( selectedIndex >= 0 )
496  {
498  switch ( dataType )
499  {
501  {
502  value = datasetValue( index, selectedIndex );
503  }
504  break;
505 
507  {
508  const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
509  const int v1 = edge.first, v2 = edge.second;
510  const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
511  const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
512  const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
513  double edgeLength = p1.distance( p2 );
514  double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
515  value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
516  }
517  break;
518  default:
519  break;
520  }
521  }
522 
523  return value;
524 }
525 
527 {
528  if ( mDataProvider )
529  mDataProvider->setTransformContext( transformContext );
531 }
532 
533 QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
534 {
535  if ( ! mTemporalProperties->isActive() )
536  return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
537 
538  const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
539  QDateTime utcTime = timeRange.begin();
540  if ( utcTime.timeSpec() != Qt::UTC )
541  utcTime.setTimeSpec( Qt::UTC );
542  qint64 startTime = layerReferenceTime.msecsTo( utcTime );
543 
544  return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
545 }
546 
547 QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
548 {
549  qint64 usedRelativeTime = relativeTime.seconds() * 1000;
550 
551  //adjust relative time if layer reference time is different from provider reference time
552  if ( mTemporalProperties->referenceTime().isValid() &&
553  mDataProvider &&
554  mDataProvider->isValid() &&
555  mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
556  usedRelativeTime = usedRelativeTime + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
557 
558  return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
559 }
560 
561 void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
562 {
563  if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
564  {
565  QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
566  QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
567  QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
568 
569  QString units;
570  if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
571  units = meta.extraOptions()[ QStringLiteral( "units" )];
572 
573  QVector<QVector<double>> bounds;
574  for ( const QString &classe : classes )
575  {
576  QStringList boundsStr = classe.split( ',' );
577  QVector<double> bound;
578  for ( const QString &boundStr : boundsStr )
579  bound.append( boundStr.toDouble() );
580  bounds.append( bound );
581  }
582 
583  if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
584  ( bounds.count() > 1 ) ) // or at least two classes
585  {
586  const QVector<double> firstClass = bounds.first();
587  const QVector<double> lastClass = bounds.last();
588  double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
589  double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
590  double diff = maxValue - minValue;
591  QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
592  for ( int i = 0; i < bounds.count(); ++i )
593  {
594  const QVector<double> &boundClass = bounds.at( i );
596  item.value = i + 1;
597  if ( !boundClass.isEmpty() )
598  {
599  double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
600  item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
601  if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
602  {
603  item.label = QString( ( "%1 - %2 %3" ) ).
604  arg( QString::number( boundClass.first() ) ).
605  arg( QString::number( boundClass.last() ) ).
606  arg( units );
607  }
608  }
609  colorRampItemlist.append( item );
610  }
611  //treat first and last labels
612  if ( firstClass.count() == 1 )
613  colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
614  arg( QString::number( firstClass.first() ) ).
615  arg( units );
616  else
617  {
618  colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
619  arg( QString::number( firstClass.first() ) ).
620  arg( QString::number( firstClass.last() ) ).
621  arg( units );
622  }
623 
624  if ( lastClass.count() == 1 )
625  colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
626  arg( QString::number( lastClass.first() ) ).
627  arg( units );
628  else
629  {
630  colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
631  arg( QString::number( lastClass.first() ) ).
632  arg( QString::number( lastClass.last() ) ).
633  arg( units );
634  }
635 
636  colorRampShader.setMinimumValue( 0 );
637  colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
638  scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
639  colorRampShader.setColorRampItemList( colorRampItemlist );
640  colorRampShader.setColorRampType( QgsColorRampShader::Exact );
642  }
643 
644  scalarSettings.setColorRampShader( colorRampShader );
646  }
647 }
648 
649 QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const
650 {
651  if ( mTemporalProperties->isActive() )
652  return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
653  else
654  return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
655 }
656 
657 QgsMeshDatasetIndex QgsMeshLayer::activeVectorDatasetAtTime( const QgsDateTimeRange &timeRange ) const
658 {
659  if ( mTemporalProperties->isActive() )
660  return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
661  else
662  return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
663 }
664 
665 void QgsMeshLayer::fillNativeMesh()
666 {
667  Q_ASSERT( !mNativeMesh );
668 
669  mNativeMesh.reset( new QgsMesh() );
670 
671  if ( !( dataProvider() && dataProvider()->isValid() ) )
672  return;
673 
674  dataProvider()->populateMesh( mNativeMesh.get() );
675 }
676 
677 void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
678 {
679  // assign default style to new dataset groups
680  for ( int i = 0; i < datasetGroupIndexes.count(); ++i )
681  assignDefaultStyleToDatasetGroup( datasetGroupIndexes.at( i ) );
682 
683  temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
684  emit rendererChanged();
685 }
686 
688 {
689  return mDatasetGroupStore->datasetGroupTreeItem();
690 }
691 
693 {
694  mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
695  updateActiveDatasetGroups();
696 }
697 
698 int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
699 {
700  QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
701  const QgsTriangularMesh *mesh = triangularMesh();
702  // search for the closest edge in search area from point
703  const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
704  int selectedIndex = -1;
705  if ( mesh->contains( QgsMesh::Edge ) &&
706  mDataProvider->isValid() )
707  {
708  double sqrMaxDistFromPoint = pow( searchRadius, 2 );
709  for ( const int edgeIndex : edgeIndexes )
710  {
711  const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
712  const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
713  const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
714  QgsPointXY projPoint;
715  double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint );
716  if ( sqrDist < sqrMaxDistFromPoint )
717  {
718  selectedIndex = edgeIndex;
719  projectedPoint = projPoint;
720  sqrMaxDistFromPoint = sqrDist;
721  }
722  }
723  }
724 
725  return selectedIndex;
726 }
727 
729 {
730  return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
731 }
732 
733 void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
734 {
735  if ( auto *lDataProvider = dataProvider() )
736  mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
737  else
738  mTemporalProperties->setReferenceTime( referenceTime, nullptr );
739 }
740 
742 {
743  mTemporalProperties->setMatchingMethod( matchingMethod );
744 }
745 
746 QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
747 {
748  const QgsTriangularMesh *mesh = triangularMesh();
749  QgsPointXY exactPosition;
750  if ( !mesh )
751  return exactPosition;
752  QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
753  double maxDistance = searchRadius;
754  //attempt to snap on edges's vertices
755  QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
756  for ( const int edgeIndex : edgeIndexes )
757  {
758  const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
759  const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
760  const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
761  double dist1 = point.distance( vertex1 );
762  double dist2 = point.distance( vertex2 );
763  if ( dist1 < maxDistance )
764  {
765  maxDistance = dist1;
766  exactPosition = vertex1;
767  }
768  if ( dist2 < maxDistance )
769  {
770  maxDistance = dist2;
771  exactPosition = vertex2;
772  }
773  }
774 
775  //attempt to snap on face's vertices
776  QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
777  for ( const int faceIndex : faceIndexes )
778  {
779  const QgsMeshFace &face = mesh->triangles().at( faceIndex );
780  for ( int i = 0; i < 3; ++i )
781  {
782  const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
783  double dist = point.distance( vertex );
784  if ( dist < maxDistance )
785  {
786  maxDistance = dist;
787  exactPosition = vertex;
788  }
789  }
790  }
791 
792  return exactPosition;
793 }
794 
795 QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
796 {
797  QgsPointXY projectedPoint;
798  closestEdge( point, searchRadius, projectedPoint );
799 
800  return projectedPoint;
801 }
802 
803 QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
804 {
805  const QgsTriangularMesh *mesh = triangularMesh();
806  QgsPointXY centroidPosition;
807  if ( !mesh )
808  return centroidPosition;
809  QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
810  double maxDistance = std::numeric_limits<double>::max();
811 
812  QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
813  for ( const int faceIndex : faceIndexes )
814  {
815  int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
816  if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
817  continue;
818  const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
819  double dist = point.distance( centroid );
820  if ( dist < maxDistance )
821  {
822  maxDistance = dist;
823  centroidPosition = centroid;
824  }
825  }
826 
827  return centroidPosition;
828 }
829 
831 {
832  mDatasetGroupStore->resetDatasetGroupTreeItem();
833  updateActiveDatasetGroups();
834 }
835 
837 {
838  if ( !mDataProvider )
839  return QgsInterval();
840  int groupCount = mDataProvider->datasetGroupCount();
841  for ( int i = 0; i < groupCount; ++i )
842  {
843  qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
844  if ( timeStep > 0 )
846  }
847 
848  return QgsInterval();
849 }
850 
852 {
853  qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
854 
855  if ( time == INVALID_MESHLAYER_TIME )
856  return QgsInterval();
857  else
859 }
860 
862 {
863  return mDatasetGroupStore->datasetRelativeTime( index );
864 }
865 
866 void QgsMeshLayer::updateActiveDatasetGroups()
867 {
868  QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
869 
870  if ( !mDatasetGroupStore->datasetGroupTreeItem() )
871  return;
872 
874  int oldActiveScalar = settings.activeScalarDatasetGroup();
875  int oldActiveVector = settings.activeVectorDatasetGroup();
876 
877  QgsMeshDatasetGroupTreeItem *activeScalarItem =
878  treeItem->childFromDatasetGroupIndex( oldActiveScalar );
879 
880  if ( !activeScalarItem && treeItem->childCount() > 0 )
881  activeScalarItem = treeItem->child( 0 );
882 
883  if ( activeScalarItem && !activeScalarItem->isEnabled() )
884  {
885  for ( int i = 0; i < treeItem->childCount(); ++i )
886  {
887  activeScalarItem = treeItem->child( i );
888  if ( activeScalarItem->isEnabled() )
889  break;
890  else
891  activeScalarItem = nullptr;
892  }
893  }
894 
895  if ( activeScalarItem )
896  settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
897  else
898  settings.setActiveScalarDatasetGroup( -1 );
899 
900  QgsMeshDatasetGroupTreeItem *activeVectorItem =
901  treeItem->childFromDatasetGroupIndex( oldActiveVector );
902 
903  if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
904  settings.setActiveVectorDatasetGroup( -1 );
905 
906  setRendererSettings( settings );
907 
908  if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
910  if ( oldActiveVector != settings.activeVectorDatasetGroup() )
912 }
913 
914 void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
915 {
916  mDataSource = dataSource;
917  mLayerName = baseName;
918  setProviderType( provider );
919 
920  // if we’re given a provider type, try to create and bind one to this layer
921  bool ok = false;
922  if ( !mDataSource.isEmpty() && !provider.isEmpty() )
923  {
924  ok = setDataProvider( provider, options, flags );
925  }
926 
927  if ( ok )
928  {
929  mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
930  }
931 }
932 
933 QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
934 {
935  switch ( elementType )
936  {
937  case QgsMesh::Vertex:
938  return snapOnVertex( point, searchRadius );
939  case QgsMesh::Edge:
940  return snapOnEdge( point, searchRadius );
941  case QgsMesh::Face:
942  return snapOnFace( point, searchRadius );
943  }
944  return QgsPointXY(); // avoid warnings
945 }
946 
948 {
949  return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
950 }
951 
952 void QgsMeshLayer::setStaticVectorDatasetIndex( const QgsMeshDatasetIndex &staticVectorDatasetIndex )
953 {
954  int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
955 
956  mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
958 
959  if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
960  emit activeVectorDatasetGroupChanged( mRendererSettings.activeVectorDatasetGroup() );
961 }
962 
963 void QgsMeshLayer::setStaticScalarDatasetIndex( const QgsMeshDatasetIndex &staticScalarDatasetIndex )
964 {
965  int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
966 
967  mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
969 
970  if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
971  emit activeScalarDatasetGroupChanged( mRendererSettings.activeScalarDatasetGroup() );
972 }
973 
975 {
976  return mSimplificationSettings;
977 }
978 
980 {
981  mSimplificationSettings = simplifySettings;
982 }
983 
984 static QgsColorRamp *_createDefaultColorRamp()
985 {
986  QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
987  if ( ramp )
988  return ramp;
989 
990  // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
991  QVariantMap props;
992  props["color1"] = "13,8,135,255";
993  props["color2"] = "240,249,33,255";
994  props["stops"] =
995  "0.0196078;27,6,141,255:0.0392157;38,5,145,255:0.0588235;47,5,150,255:0.0784314;56,4,154,255:0.0980392;65,4,157,255:"
996  "0.117647;73,3,160,255:0.137255;81,2,163,255:0.156863;89,1,165,255:0.176471;97,0,167,255:0.196078;105,0,168,255:"
997  "0.215686;113,0,168,255:0.235294;120,1,168,255:0.254902;128,4,168,255:0.27451;135,7,166,255:0.294118;142,12,164,255:"
998  "0.313725;149,17,161,255:0.333333;156,23,158,255:0.352941;162,29,154,255:0.372549;168,34,150,255:0.392157;174,40,146,255:"
999  "0.411765;180,46,141,255:0.431373;186,51,136,255:0.45098;191,57,132,255:0.470588;196,62,127,255:0.490196;201,68,122,255:"
1000  "0.509804;205,74,118,255:0.529412;210,79,113,255:0.54902;214,85,109,255:0.568627;218,91,105,255:0.588235;222,97,100,255:"
1001  "0.607843;226,102,96,255:0.627451;230,108,92,255:0.647059;233,114,87,255:0.666667;237,121,83,255:0.686275;240,127,79,255:"
1002  "0.705882;243,133,75,255:0.72549;245,140,70,255:0.745098;247,147,66,255:0.764706;249,154,62,255:0.784314;251,161,57,255:"
1003  "0.803922;252,168,53,255:0.823529;253,175,49,255:0.843137;254,183,45,255:0.862745;254,190,42,255:0.882353;253,198,39,255:"
1004  "0.901961;252,206,37,255:0.921569;251,215,36,255:0.941176;248,223,37,255:0.960784;246,232,38,255:0.980392;243,240,39,255";
1005  return QgsGradientColorRamp::create( props );
1006 }
1007 
1008 void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1009 {
1011  double groupMin = metadata.minimum();
1012  double groupMax = metadata.maximum();
1013 
1014  QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1015  fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1016 
1017  QgsMeshRendererScalarSettings scalarSettings;
1018  scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1019  scalarSettings.setColorRampShader( fcn );
1020  QgsInterpolatedLineWidth edgeStrokeWidth;
1021  edgeStrokeWidth.setMinimumValue( groupMin );
1022  edgeStrokeWidth.setMaximumValue( groupMax );
1023  QgsInterpolatedLineColor edgeStrokeColor( fcn );
1024  QgsInterpolatedLineRenderer edgeStrokePen;
1025  scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1026  mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1027 
1028  if ( metadata.isVector() )
1029  {
1030  QgsMeshRendererVectorSettings vectorSettings;
1031  vectorSettings.setColorRampShader( fcn );
1032  mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1033  }
1034 }
1035 
1037 {
1038  // Triangular mesh
1039  updateTriangularMesh( rendererContext.coordinateTransform() );
1040 
1041  // Build overview triangular meshes if needed
1042  createSimplifiedMeshes();
1043 
1044  // Cache
1045  if ( !mRendererCache )
1046  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1047 
1048  return new QgsMeshLayerRenderer( this, rendererContext );
1049 }
1050 
1051 bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1052  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1053 {
1054  Q_UNUSED( errorMessage )
1055  // TODO: implement categories for raster layer
1056 
1057  QDomElement elem = node.toElement();
1058 
1059  readCommonStyle( elem, context, categories );
1060 
1061  QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1062  if ( !elemRendererSettings.isNull() )
1063  mRendererSettings.readXml( elemRendererSettings, context );
1064 
1065  QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1066  if ( !elemSimplifySettings.isNull() )
1067  mSimplificationSettings.readXml( elemSimplifySettings, context );
1068 
1069  // get and set the blend mode if it exists
1070  QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1071  if ( !blendModeNode.isNull() )
1072  {
1073  QDomElement e = blendModeNode.toElement();
1074  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1075  }
1076 
1077  // get and set the layer transparency
1078  if ( categories.testFlag( Rendering ) )
1079  {
1080  QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1081  if ( !layerOpacityNode.isNull() )
1082  {
1083  QDomElement e = layerOpacityNode.toElement();
1084  setOpacity( e.text().toDouble() );
1085  }
1086  }
1087 
1088  return true;
1089 }
1090 
1091 bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1092  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1093 {
1094  Q_UNUSED( errorMessage )
1095  // TODO: implement categories for raster layer
1096 
1097  QDomElement elem = node.toElement();
1098 
1099  writeCommonStyle( elem, doc, context, categories );
1100 
1101  QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1102  elem.appendChild( elemRendererSettings );
1103 
1104  QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1105  elem.appendChild( elemSimplifySettings );
1106 
1107  // add blend mode node
1108  QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1109  QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1110  blendModeElement.appendChild( blendModeText );
1111  node.appendChild( blendModeElement );
1112 
1113  // add the layer opacity
1114  if ( categories.testFlag( Rendering ) )
1115  {
1116  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1117  QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1118  layerOpacityElem.appendChild( layerOpacityText );
1119  node.appendChild( layerOpacityElem );
1120  }
1121 
1122  return true;
1123 }
1124 
1125 bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1126 {
1127  return writeSymbology( node, doc, errorMessage, context, categories );
1128 }
1129 
1130 bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1131 {
1132  return readSymbology( node, errorMessage, context, categories );
1133 }
1134 
1135 QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1136 {
1137  QString src( source );
1138  if ( provider == QLatin1String( "mdal" ) )
1139  {
1140  src = context.pathResolver().readPath( src );
1141  }
1142  return src;
1143 }
1144 
1145 QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1146 {
1147  QString src( source );
1148  if ( providerType() == QLatin1String( "mdal" ) )
1149  {
1150  src = context.pathResolver().writePath( src );
1151  }
1152  return src;
1153 }
1154 
1155 bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1156 {
1157  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1158 
1159  //process provider key
1160  QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1161 
1162  if ( pkeyNode.isNull() )
1163  {
1164  mProviderKey.clear();
1165  }
1166  else
1167  {
1168  QDomElement pkeyElt = pkeyNode.toElement();
1169  mProviderKey = pkeyElt.text();
1170  }
1171 
1173  {
1174  return false;
1175  }
1176 
1177  QgsDataProvider::ProviderOptions providerOptions;
1178  QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
1180  {
1182  }
1183 
1184  QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1185  if ( !elemExtraDatasets.isNull() )
1186  {
1187  QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1188  while ( !elemUri.isNull() )
1189  {
1190  QString uri = context.pathResolver().readPath( elemUri.text() );
1191  mExtraDatasetUri.append( uri );
1192  elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1193  }
1194  }
1195 
1196  if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1197  mTemporalUnit = static_cast<QgsUnitTypes::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1198 
1199  // read dataset group store
1200  QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1201  if ( elemDatasetGroupsStore.isNull() )
1203  else
1204  mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1205 
1206  setDataProvider( mProviderKey, providerOptions, flags );
1207 
1208  QString errorMsg;
1209  readSymbology( layer_node, errorMsg, context );
1210 
1211  if ( !mTemporalProperties->timeExtent().begin().isValid() )
1213 
1214  // read static dataset
1215  QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1216  if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1217  {
1218  mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1219  }
1220  if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1221  {
1222  mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1223  }
1224 
1225  return isValid(); // should be true if read successfully
1226 }
1227 
1228 bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1229 {
1230  // first get the layer element so that we can append the type attribute
1231  QDomElement mapLayerNode = layer_node.toElement();
1232 
1233  if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1234  {
1235  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1236  return false;
1237  }
1238 
1239  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::MeshLayer ) );
1240 
1241  // add provider node
1242  if ( mDataProvider )
1243  {
1244  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1245  QDomText providerText = document.createTextNode( providerType() );
1246  provider.appendChild( providerText );
1247  layer_node.appendChild( provider );
1248  provider.setAttribute( QStringLiteral( "time-unit" ), mDataProvider->temporalCapabilities()->temporalUnit() );
1249 
1250  const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1251  QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1252  for ( const QString &uri : extraDatasetUris )
1253  {
1254  QString path = context.pathResolver().writePath( uri );
1255  QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1256  elemUri.appendChild( document.createTextNode( path ) );
1257  elemExtraDatasets.appendChild( elemUri );
1258  }
1259  layer_node.appendChild( elemExtraDatasets );
1260  }
1261 
1262  QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1263  elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1264  elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1265  layer_node.appendChild( elemStaticDataset );
1266 
1267  // write dataset group store
1268  layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1269 
1270  // renderer specific settings
1271  QString errorMsg;
1272  return writeSymbology( layer_node, document, errorMsg, context );
1273 }
1274 
1276 {
1277  if ( mDataProvider && mDataProvider->isValid() )
1278  {
1279  mDataProvider->reloadData();
1280 
1281  //reload the mesh structure
1282  if ( !mNativeMesh )
1283  mNativeMesh.reset( new QgsMesh );
1284 
1285  dataProvider()->populateMesh( mNativeMesh.get() );
1286 
1287  //clear the TriangularMeshes
1288  mTriangularMeshes.clear();
1289 
1290  //clear the rendererCache
1291  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1292  }
1293 }
1294 
1295 QStringList QgsMeshLayer::subLayers() const
1296 {
1297  if ( mDataProvider )
1298  return mDataProvider->subLayers();
1299  else
1300  return QStringList();
1301 }
1302 
1304 {
1305  QgsLayerMetadataFormatter htmlFormatter( metadata() );
1306  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1307 
1308  // Begin Provider section
1309  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1310  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1311 
1312  // name
1313  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Name" ) + QStringLiteral( "</td><td>" ) + name() + QStringLiteral( "</td></tr>\n" );
1314 
1315  // local path
1316  QVariantMap uriComponents = QgsProviderRegistry::instance()->decodeUri( mProviderKey, publicSource() );
1317  QString path;
1318  if ( uriComponents.contains( QStringLiteral( "path" ) ) )
1319  {
1320  path = uriComponents[QStringLiteral( "path" )].toString();
1321  if ( QFile::exists( path ) )
1322  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Path" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl::fromLocalFile( path ).toString(), QDir::toNativeSeparators( path ) ) ) + QStringLiteral( "</td></tr>\n" );
1323  }
1324  if ( uriComponents.contains( QStringLiteral( "url" ) ) )
1325  {
1326  const QString url = uriComponents[QStringLiteral( "url" )].toString();
1327  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "URL" ) + QStringLiteral( "</td><td>%1" ).arg( QStringLiteral( "<a href=\"%1\">%2</a>" ).arg( QUrl( url ).toString(), url ) ) + QStringLiteral( "</td></tr>\n" );
1328  }
1329 
1330  // data source
1331  if ( publicSource() != path )
1332  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Source" ) + QStringLiteral( "</td><td>%1" ).arg( publicSource() ) + QStringLiteral( "</td></tr>\n" );
1333 
1334  // Extent
1335  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1336 
1337  // feature count
1338  QLocale locale = QLocale();
1339  locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1340 
1341  if ( dataProvider() )
1342  {
1343  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1344  + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
1345  + ( locale.toString( static_cast<qlonglong>( dataProvider()->vertexCount() ) ) )
1346  + QStringLiteral( "</td></tr>\n" );
1347  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1348  + tr( "Face count" ) + QStringLiteral( "</td><td>" )
1349  + ( locale.toString( static_cast<qlonglong>( dataProvider()->faceCount() ) ) )
1350  + QStringLiteral( "</td></tr>\n" );
1351  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1352  + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
1353  + ( locale.toString( static_cast<qlonglong>( dataProvider()->edgeCount() ) ) )
1354  + QStringLiteral( "</td></tr>\n" );
1355  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1356  + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
1357  + ( locale.toString( static_cast<qlonglong>( dataProvider()->datasetGroupCount() ) ) )
1358  + QStringLiteral( "</td></tr>\n" );
1359  }
1360 
1361  // End Provider section
1362  myMetadata += QLatin1String( "</table>\n<br><br>" );
1363 
1364  // CRS
1365  myMetadata += crsHtmlMetadata();
1366 
1367  // identification section
1368  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
1369  myMetadata += htmlFormatter.identificationSectionHtml( );
1370  myMetadata += QLatin1String( "<br><br>\n" );
1371 
1372  // extent section
1373  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
1374  myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
1375  myMetadata += QLatin1String( "<br><br>\n" );
1376 
1377  // Start the Access section
1378  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
1379  myMetadata += htmlFormatter.accessSectionHtml( );
1380  myMetadata += QLatin1String( "<br><br>\n" );
1381 
1382  // Start the contacts section
1383  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
1384  myMetadata += htmlFormatter.contactsSectionHtml( );
1385  myMetadata += QLatin1String( "<br><br>\n" );
1386 
1387  // Start the links section
1388  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
1389  myMetadata += htmlFormatter.linksSectionHtml( );
1390  myMetadata += QLatin1String( "<br><br>\n" );
1391 
1392  // Start the history section
1393  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
1394  myMetadata += htmlFormatter.historySectionHtml( );
1395  myMetadata += QLatin1String( "<br><br>\n" );
1396 
1397  myMetadata += QLatin1String( "\n</body>\n</html>\n" );
1398  return myMetadata;
1399 }
1400 
1401 bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1402 {
1403  mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
1404 
1405  delete mDataProvider;
1406  mProviderKey = provider;
1407  QString dataSource = mDataSource;
1408 
1409  mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
1410 
1411  if ( !mDataProvider )
1412  {
1413  QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
1414  return false;
1415  }
1416 
1417  mDataProvider->setParent( this );
1418  QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
1419 
1420  setValid( mDataProvider->isValid() );
1421  if ( !isValid() )
1422  {
1423  QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1424  return false;
1425  }
1426 
1427  mDataProvider->setTemporalUnit( mTemporalUnit );
1428  mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
1429  setCrs( mDataProvider->crs() );
1430 
1431  if ( provider == QLatin1String( "mesh_memory" ) )
1432  {
1433  // required so that source differs between memory layers
1434  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1435  }
1436 
1437  for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
1438  assignDefaultStyleToDatasetGroup( i );
1439 
1440  connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
1441 
1442  return true;
1443 }
1444 
1446 {
1447  return mTemporalProperties;
1448 }
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
@ EqualInterval
Uses equal interval.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
Abstract base class for color ramps.
Definition: qgscolorramp.h:32
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
bool hasTemporalCapabilities() const
Returns true if the provider has temporal capabilities available.
@ FlagTrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
QgsCoordinateTransformContext transformContext() const
Returns data provider coordinate transform context.
virtual QgsCoordinateReferenceSystem crs() const =0
Returns the coordinate system for the data source.
void dataChanged()
Emitted whenever a change is made to the data provider which may have caused changes in the provider'...
virtual bool isValid() const =0
Returns true if this is a valid layer.
virtual QStringList subLayers() const
Sub-layers handled by this provider, in order from bottom to top.
virtual void reloadData()
Reloads the data from the source for providers with data caches to synchronize, changes in the data s...
virtual QgsRectangle extent() const =0
Returns the extent of the layer.
virtual void setTransformContext(const QgsCoordinateTransformContext &transformContext)
Sets data coordinate transform context to transformContext.
static QgsColorRamp * create(const QVariantMap &properties=QVariantMap())
Creates a new QgsColorRamp from a map of properties.
Class defining color to render mesh datasets.
Represents a simple line renderer with width and color varying depending on values.
Represents a width than can vary depending on values.
void setMaximumValue(double maximumValue)
Sets the maximum value used to defined the variable width.
void setMinimumValue(double minimumValue)
Sets the minimum value used to defined the variable width.
A representation of the interval between two datetime values.
Definition: qgsinterval.h:42
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:236
Class for metadata formatter.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
static QgsMapLayerLegend * defaultMeshLegend(QgsMeshLayer *ml)
Create new legend implementation for mesh layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
virtual void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities)=0
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Base class for all map layer types.
Definition: qgsmaplayer.h:70
QString name
Definition: qgsmaplayer.h:73
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
QString source() const
Returns the source for the layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QString publicSource() const
Gets a version of the internal layer definition that has sensitive bits removed (for example,...
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1668
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:75
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1711
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void rendererChanged()
Signal emitted when renderer is changed.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
void dataChanged()
Data of layer changed.
bool isValid
Definition: qgsmaplayer.h:78
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1665
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:581
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:580
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1716
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:79
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:164
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1723
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Abstract class to interpolate 3d stacked mesh data to 2d data.
QgsMeshDataBlock calculate(const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
QgsMesh3dDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
bool isValid() const
Whether the block is valid.
QgsUnitTypes::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
QDateTime referenceTime() const
Returns the reference time.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 firstTimeStepDuration(int group) const
Returns the duration of the first time step of the dataset group with index group.
Base class for providing data for QgsMeshLayer.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
void setTemporalUnit(QgsUnitTypes::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
QMap< QString, QString > extraOptions() const
Returns extra metadata options, for example description.
bool isVector() const
Returns whether dataset group has vector 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.
DataType
Location of where data is specified for datasets in the dataset group.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
Class used to register and access all the dataset groups related to a mesh layer.
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
Tree item for display of the mesh dataset groups.
int childCount() const
Returns the count of children.
QgsMeshDatasetGroupTreeItem * childFromDatasetGroupIndex(int index)
Returns the child with dataset group index Searches as depper as needed on the child hierarchy.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a 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.
int dataset() const
Returns a dataset index within group()
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
virtual QStringList extraDatasets() const =0
Returns list of additional dataset file URIs added using addDataset() calls.
QgsMeshDatasetValue represents single dataset value.
double y() const
Returns y value.
double x() const
Returns x value.
Implementation of threaded rendering for mesh layers.
Implementation of map layer temporal properties for mesh layers.
QDateTime referenceTime() const
Returns the reference time.
void setMatchingMethod(const QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod &matchingMethod)
Sets the method used to match dataset from temporal capabilities.
QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod matchingMethod() const
Returns the method used to match dataset from temporal capabilities.
void setReferenceTime(const QDateTime &referenceTime, const QgsDataProviderTemporalCapabilities *capabilities)
Sets the reference time and update the time extent from the temporal capabilities,...
void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities) override
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
QgsDateTimeRange timeExtent() const
Returns the time extent.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:95
~QgsMeshLayer() override
void setMeshSimplificationSettings(const QgsMeshSimplificationSettings &meshSimplificationSettings)
Sets mesh simplification settings.
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
QList< int > datasetGroupsIndexes() const
Returns the list of indexes of dataset groups handled by the layer.
QgsRectangle extent() const override
Returns the extent of the layer.
void setStaticVectorDatasetIndex(const QgsMeshDatasetIndex &staticVectorDatasetIndex)
Sets the static vector dataset index that is rendered if the temporal properties is not active.
void setStaticScalarDatasetIndex(const QgsMeshDatasetIndex &staticScalarDatasetIndex)
Sets the static scalar dataset index that is rendered if the temporal properties is not active.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
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.
void activeScalarDatasetGroupChanged(int index)
Emitted when active scalar group dataset is changed.
int datasetGroupCount() const
Returns the dataset groups count handle by the layer.
void updateTriangularMesh(const QgsCoordinateTransform &transform=QgsCoordinateTransform())
Gets native mesh and updates (creates if it doesn't exist) the base triangular mesh.
bool addDatasets(const QString &path, const QDateTime &defaultReferenceTime=QDateTime())
Adds datasets to the mesh from file with path.
void activeVectorDatasetGroupChanged(int index)
Emitted when active vector group dataset is changed.
void reload() override
Synchronises with changes in the datasource.
QgsMeshDatasetIndex activeScalarDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active scalar group depending on the time range.
QgsPointXY snapOnElement(QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius)
Returns the position of the snapped point on the mesh element closest to point intersecting with the ...
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
QStringList subLayers() const override
Returns the sublayers of this layer.
void setDatasetGroupTreeRootItem(QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root items of the dataset group tree item.
QgsMeshDatasetValue dataset1dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius) const
Returns the value of 1D mesh dataset defined on edge that are in the search area defined by point ans...
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QgsTriangularMesh * triangularMeshByLodIndex(int lodIndex) const
Returns triangular corresponding to the index of level of details.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
QgsMesh3dDataBlock dataset3dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point) const
Returns the 3d values of stacked 3d mesh defined by the given point.
QgsMeshLayer * clone() const override
Returns a new instance equivalent to this one except for the id which is still unique.
void timeSettingsChanged()
Emitted when time format is changed.
QList< int > enabledDatasetGroupsIndexes() const
Returns the list of indexes of enables dataset groups handled by the layer.
void resetDatasetGroupTreeItem()
Reset the dataset group tree item to default from provider.
int triangularMeshLevelOfDetailCount() const
Returns the count of levels of detail of the mesh simplification.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
QgsMeshDatasetIndex staticVectorDatasetIndex() const
Returns the static vector dataset index that is rendered if the temporal properties is not active.
QgsMeshDatasetIndex datasetIndexAtRelativeTime(const QgsInterval &relativeTime, int datasetGroupIndex) const
Returns dataset index from datasets group depending on the relative time from the layer reference tim...
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
QgsMeshDataBlock datasetValues(const QgsMeshDatasetIndex &index, int valueIndex, int count) const
Returns N vector/scalar values from the index from the dataset.
bool writeStyle(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const override
Write just the symbology information for the layer into the document.
void setTransformContext(const QgsCoordinateTransformContext &transformContext) override
Sets the coordinate transform context to transformContext.
QgsMeshSimplificationSettings meshSimplificationSettings() const
Returns mesh simplification settings.
QgsMapLayerRenderer * createMapRenderer(QgsRenderContext &rendererContext) override
Returns new instance of QgsMapLayerRenderer that will be used for rendering of given context.
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.
bool isFaceActive(const QgsMeshDatasetIndex &index, int faceIndex) const
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
QgsMeshDatasetMetadata datasetMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset metadata.
bool saveDataset(const QString &path, int datasetGroupIndex, QString driver)
Saves datasets group on file with the specified driver.
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
QgsInterval firstValidTimeStep() const
Returns the first valid time step of the dataset groups, invalid QgInterval if no time step is presen...
QgsInterval datasetRelativeTime(const QgsMeshDatasetIndex &index)
Returns the relative time of the dataset from the reference time of its group.
QgsMeshDatasetIndex datasetIndexAtTime(const QgsDateTimeRange &timeRange, int datasetGroupIndex) const
Returns dataset index from datasets group depending on the time range.
QgsMeshDatasetValue datasetValue(const QgsMeshDatasetIndex &index, int valueIndex) const
Returns vector/scalar value associated with the index from the dataset To read multiple continuous va...
QgsMeshTimeSettings timeSettings() const
Returns time format settings.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
void setReferenceTime(const QDateTime &referenceTime)
Sets the reference time of the layer.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) override
Read the style for the current layer from the DOM node supplied.
int extraDatasetGroupCount() const
Returns the extra dataset groups count handle by the layer.
void setRendererSettings(const QgsMeshRendererSettings &settings)
Sets new renderer settings.
qint64 datasetRelativeTimeInMilliseconds(const QgsMeshDatasetIndex &index)
Returns the relative time (in milliseconds) of the dataset from the reference time of its group.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
void setTemporalMatchingMethod(const QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod &matchingMethod)
Sets the method used to match the temporal dataset from a requested time, see activeVectorDatasetAtTi...
QgsMeshDatasetGroupTreeItem * datasetGroupTreeRootItem() const
Returns the root items of the dataset group tree item.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
QString providerType() const
Returns the provider type for this layer.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
QString formatTime(double hours)
Returns (date) time in hours formatted to human readable form.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
QgsMeshLayerRendererCache * rendererCache()
Returns native mesh (nullptr before rendering)
void setTimeSettings(const QgsMeshTimeSettings &settings)
Sets time format settings.
QgsMeshLayer(const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib=QStringLiteral("mesh_memory"), const QgsMeshLayer::LayerOptions &options=QgsMeshLayer::LayerOptions())
Constructor - creates a mesh layer.
Represents a mesh renderer settings for mesh object.
void setEnabled(bool enabled)
Sets whether mesh structure rendering is enabled.
Represents a mesh renderer settings for scalar datasets.
void setClassificationMinimumMaximum(double minimum, double maximum)
Sets min/max values used for creation of the color ramp shader.
void setColorRampShader(const QgsColorRampShader &shader)
Sets color ramp shader function.
QgsColorRampShader colorRampShader() const
Returns color ramp shader function.
@ NeighbourAverage
Does a simple average of values defined for all surrounding faces/vertices.
void setEdgeStrokeWidth(const QgsInterpolatedLineWidth &strokeWidth)
Sets the stroke width used to render edges scalar dataset.
void setDataResamplingMethod(const DataResamplingMethod &dataResamplingMethod)
Sets data interpolation method.
Represents all mesh renderer settings.
void setActiveVectorDatasetGroup(int activeVectorDatasetGroup)
Sets the active vector dataset group.
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.
void setActiveScalarDatasetGroup(int activeScalarDatasetGroup)
Sets the active scalar dataset group.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
void setVectorSettings(int groupIndex, const QgsMeshRendererVectorSettings &settings)
Sets new renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
void setScalarSettings(int groupIndex, const QgsMeshRendererScalarSettings &settings)
Sets new renderer settings.
void setNativeMeshSettings(const QgsMeshRendererMeshSettings &settings)
Sets new native mesh renderer settings, triggers repaint.
Represents a renderer settings for vector datasets.
void setColorRampShader(const QgsColorRampShader &colorRampShader)
Returns the color ramp shader used to render vector datasets.
Represents a overview renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
double reductionFactor() const
Returns the reduction factor used to build simplified mesh.
bool isEnabled() const
Returns if the overview is active.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from the given DOM element.
Represents a mesh time settings for mesh datasets.
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
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
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspointxy.h:211
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const SIP_HOLDGIL
Returns the minimum distance between this point and a segment.
Definition: qgspointxy.cpp:95
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:343
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
Contains information about the context of a rendering operation.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:131
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition: qgsstyle.cpp:446
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
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< QgsMeshVertex > & faceCentroids() const
Returns centroids of the native faces in map CRS.
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.
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.
TemporalUnit
Temporal units.
Definition: qgsunittypes.h:150
@ TemporalMilliseconds
Milliseconds.
Definition: qgsunittypes.h:151
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:46
@ MeshLayer
Added in 3.2.
#define SIP_SKIP
Definition: qgis_sip.h:126
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QVector< int > QgsMeshFace
List of vertex indexes.
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
Setting options for creating vector data providers.
Setting options for loading mesh layers.
Definition: qgsmeshlayer.h:103
QgsCoordinateTransformContext transformContext
Definition: qgsmeshlayer.h:113
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:128
Mesh - vertices, edges and faces.
ElementType
Defines type of mesh elements.