QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 "qgscolorrampimpl.h"
25 #include "qgslogger.h"
26 #include "qgsmaplayerlegend.h"
27 #include "qgsmaplayerfactory.h"
28 #include "qgsmaplayerutils.h"
29 #include "qgsmeshdataprovider.h"
31 #include "qgsmeshlayer.h"
32 #include "qgsmeshlayerrenderer.h"
34 #include "qgsmeshlayerutils.h"
35 #include "qgsmeshtimesettings.h"
36 #include "qgspainting.h"
37 #include "qgsproviderregistry.h"
38 #include "qgsreadwritecontext.h"
39 #include "qgsstyle.h"
40 #include "qgstriangularmesh.h"
41 #include "qgsmesh3daveraging.h"
43 #include "qgsmesheditor.h"
44 #include "qgsmessagelog.h"
46 
47 QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
48  const QString &baseName,
49  const QString &providerKey,
50  const QgsMeshLayer::LayerOptions &options )
51  : QgsMapLayer( QgsMapLayerType::MeshLayer, baseName, meshLayerPath ),
52  mDatasetGroupStore( new QgsMeshDatasetGroupStore( this ) ),
53  mTemporalProperties( new QgsMeshLayerTemporalProperties( this ) )
54 {
56 
57  const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
58  QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
59  if ( options.loadDefaultStyle )
60  {
62  }
64  {
66  }
67  setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
70 
71  if ( isValid() && options.loadDefaultStyle )
72  setDefaultRendererSettings( mDatasetGroupStore->datasetGroupIndexes() );
73 
74  connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
75 }
76 
77 
78 void QgsMeshLayer::setDefaultRendererSettings( const QList<int> &groupIndexes )
79 {
80  QgsMeshRendererMeshSettings meshSettings;
81  if ( groupIndexes.count() > 0 )
82  {
83  // Show data from the first dataset group
84  mRendererSettings.setActiveScalarDatasetGroup( 0 );
85  // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
87  if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
88  meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
89  meshSettings.setEnabled( true );
90  }
91  else
92  {
93  // show at least the mesh by default
94  meshSettings.setEnabled( true );
95  return;
96  }
97  mRendererSettings.setNativeMeshSettings( meshSettings );
98 
99  // Sets default resample method for scalar dataset
100  for ( const int i : groupIndexes )
101  {
103  QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
104  switch ( meta.dataType() )
105  {
107  case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
109  break;
112  break;
114  break;
115  }
116 
117  //override color ramp if the values in the dataset group are classified
118  applyClassificationOnScalarSettings( meta, scalarSettings );
119 
120  mRendererSettings.setScalarSettings( i, scalarSettings );
121  }
122 
123 }
124 
125 void QgsMeshLayer::createSimplifiedMeshes()
126 {
127  if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
128  {
129  const double reductionFactor = mSimplificationSettings.reductionFactor();
130 
131  QVector<QgsTriangularMesh *> simplifyMeshes =
132  mTriangularMeshes[0]->simplifyMesh( reductionFactor );
133 
134  for ( int i = 0; i < simplifyMeshes.count() ; ++i )
135  {
136  mTriangularMeshes.emplace_back( simplifyMeshes[i] );
137  }
138  }
139 }
140 
141 bool QgsMeshLayer::hasSimplifiedMeshes() const
142 {
143  //First mesh is the base mesh, so if size>1, there is no simplified meshes
144  return ( mTriangularMeshes.size() > 1 );
145 }
146 
148 {
149  delete mDataProvider;
150 }
151 
153 {
154  return mDataProvider;
155 }
156 
158 {
159  return mDataProvider;
160 }
161 
163 {
165  if ( mDataProvider )
166  {
167  options.transformContext = mDataProvider->transformContext();
168  }
169  QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
170  QgsMapLayer::clone( layer );
171  return layer;
172 }
173 
175 {
176  if ( mMeshEditor )
177  return mMeshEditor->extent();
178 
179  if ( mDataProvider )
180  return mDataProvider->extent();
181  else
182  {
183  QgsRectangle rec;
184  rec.setMinimal();
185  return rec;
186  }
187 }
188 
190 {
191  return mProviderKey;
192 }
193 
195 {
196  if ( !mDataProvider )
197  return false;
198 
199  if ( mMeshEditor )
200  return true;
201 
202  const QgsMeshDriverMetadata driverMetadata = mDataProvider->driverMetadata();
203 
204  return driverMetadata.capabilities() & QgsMeshDriverMetadata::CanWriteMeshData;
205 }
206 
207 QString QgsMeshLayer::loadDefaultStyle( bool &resultFlag )
208 {
209  const QList<int> groupsList = datasetGroupsIndexes();
210 
211  for ( const int index : groupsList )
212  assignDefaultStyleToDatasetGroup( index );
213 
214  if ( !groupsList.isEmpty() )
215  {
216  emit rendererChanged();
218  }
219 
220  return QgsMapLayer::loadDefaultStyle( resultFlag );
221 }
222 
223 bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
224 {
225  const bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
226  if ( mDatasetGroupStore->addPersistentDatasets( path ) )
227  {
228  mExtraDatasetUri.append( path );
229  QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
230  if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
231  {
233  dataProvider()->temporalCapabilities() );
234 
235  if ( ! temporalProperties->referenceTime().isValid() )
236  {
237  QDateTime referenceTime = defaultReferenceTime;
238  if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
239  referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
240  temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
241  }
242 
243  mTemporalProperties->setIsActive( true );
244  }
245  emit dataSourceChanged();
246  return true;
247  }
248 
249  return false;
250 }
251 
253 {
254  if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
255  {
256  emit dataChanged();
257  return true;
258  }
259  return false;
260 }
261 
262 bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
263 {
264  return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
265 }
266 
268 {
269  return mNativeMesh.get();
270 }
271 
273 {
274  return mNativeMesh.get();
275 }
276 
277 QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
278 {
279  for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
280  {
281  if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
282  return lod.get();
283  }
284 
285  if ( !mTriangularMeshes.empty() )
286  return mTriangularMeshes.back().get();
287  else
288  return nullptr;
289 }
290 
292 {
293  return mTriangularMeshes.size();
294 }
295 
297 {
298  if ( mTriangularMeshes.empty() )
299  return nullptr;
300  if ( lodIndex < 0 )
301  return mTriangularMeshes.front().get();
302 
303  if ( lodIndex >= int( mTriangularMeshes.size() ) )
304  return mTriangularMeshes.back().get();
305 
306  return mTriangularMeshes.at( lodIndex ).get();
307 }
308 
310 {
311  // Native mesh
312  if ( !mNativeMesh )
313  {
314  // lazy loading of mesh data
315  fillNativeMesh();
316  }
317 
318  // Triangular mesh
319  if ( mTriangularMeshes.empty() )
320  {
321  QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
322  mTriangularMeshes.emplace_back( baseMesh );
323  }
324 
325  if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
326  mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
327 
328  createSimplifiedMeshes();
329 }
330 
331 QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
332 {
333  return mRendererCache.get();
334 }
335 
337 {
338  return mRendererSettings;
339 }
340 
342 {
343  const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
344  const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
345  mRendererSettings = settings;
346 
347  if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
348  emit activeScalarDatasetGroupChanged( mRendererSettings.activeScalarDatasetGroup() );
349 
350  if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
351  emit activeVectorDatasetGroupChanged( mRendererSettings.activeVectorDatasetGroup() );
352 
353  emit rendererChanged();
354  triggerRepaint();
355 }
356 
358 {
359  return mTimeSettings;
360 }
361 
363 {
364  mTimeSettings = settings;
365  emit timeSettingsChanged();
366 }
367 
368 QString QgsMeshLayer::formatTime( double hours )
369 {
370  if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
371  return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
372  else
373  return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
374 }
375 
377 {
378  return mDatasetGroupStore->datasetGroupCount();
379 }
380 
382 {
383  return mDatasetGroupStore->extraDatasetGroupCount();
384 }
385 
387 {
388  return mDatasetGroupStore->datasetGroupIndexes();
389 }
390 
392 {
393  return mDatasetGroupStore->enabledDatasetGroupIndexes();
394 }
395 
397 {
398  return mDatasetGroupStore->datasetGroupMetadata( index );
399 }
400 
402 {
403  return mDatasetGroupStore->datasetCount( index.group() );
404 }
405 
407 {
408  return mDatasetGroupStore->datasetMetadata( index );
409 }
410 
412 {
413  return mDatasetGroupStore->datasetValue( index, valueIndex );
414 }
415 
416 QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
417 {
418  return mDatasetGroupStore->datasetValues( index, valueIndex, count );
419 }
420 
421 QgsMesh3dDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
422 {
423  return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
424 }
425 
426 QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
427 {
428  return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
429 }
430 
431 bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
432 {
433  return mDatasetGroupStore->isFaceActive( index, faceIndex );
434 }
435 
436 QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
437 {
438  QgsMeshDatasetValue value;
439  const QgsTriangularMesh *mesh = triangularMesh();
440 
441  if ( mesh && index.isValid() )
442  {
443  if ( contains( QgsMesh::ElementType::Edge ) )
444  {
445  const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
446  return dataset1dValue( index, point, searchRadius );
447  }
448  const int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
449  if ( faceIndex >= 0 )
450  {
451  const int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
453  if ( isFaceActive( index, nativeFaceIndex ) )
454  {
455  switch ( dataType )
456  {
458  {
459  value = datasetValue( index, nativeFaceIndex );
460  }
461  break;
462 
464  {
465  const QgsMeshFace &face = mesh->triangles()[faceIndex];
466  const int v1 = face[0], v2 = face[1], v3 = face[2];
467  const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
468  const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
469  const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
470  const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
471  const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
472  double y = std::numeric_limits<double>::quiet_NaN();
473  const bool isVector = datasetGroupMetadata( index ).isVector();
474  if ( isVector )
475  y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
476 
477  value = QgsMeshDatasetValue( x, y );
478  }
479  break;
480 
482  {
483  const QgsMesh3dAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
484  if ( avgMethod )
485  {
486  const QgsMesh3dDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
487  const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
488  if ( block2d.isValid() )
489  {
490  value = block2d.value( 0 );
491  }
492  }
493  }
494  break;
495 
496  default:
497  break;
498  }
499  }
500  }
501  }
502 
503  return value;
504 }
505 
507 {
508  QgsMesh3dDataBlock block3d;
509 
510  const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
511 
512  if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
513  {
516  {
517  const int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
518  if ( faceIndex >= 0 )
519  {
520  const int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
521  block3d = dataset3dValues( index, nativeFaceIndex, 1 );
522  }
523  }
524  }
525  return block3d;
526 }
527 
528 QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
529 {
530  QgsMeshDatasetValue value;
531  QgsPointXY projectedPoint;
532  const int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
533  const QgsTriangularMesh *mesh = triangularMesh();
534  if ( selectedIndex >= 0 )
535  {
537  switch ( dataType )
538  {
540  {
541  value = datasetValue( index, selectedIndex );
542  }
543  break;
544 
546  {
547  const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
548  const int v1 = edge.first, v2 = edge.second;
549  const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
550  const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
551  const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
552  const double edgeLength = p1.distance( p2 );
553  const double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
554  value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
555  }
556  break;
557  default:
558  break;
559  }
560  }
561 
562  return value;
563 }
564 
566 {
567  if ( mDataProvider )
568  mDataProvider->setTransformContext( transformContext );
570 }
571 
572 QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
573 {
574  if ( ! mTemporalProperties->isActive() )
575  return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
576 
577  const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
578  QDateTime utcTime = timeRange.begin();
579  if ( utcTime.timeSpec() != Qt::UTC )
580  utcTime.setTimeSpec( Qt::UTC );
581  const qint64 startTime = layerReferenceTime.msecsTo( utcTime );
582 
583  return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
584 }
585 
586 QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
587 {
588  return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
589 }
590 
591 QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
592 {
593  qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
594  qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
595 
596  //adjust relative time if layer reference time is different from provider reference time
597  if ( mTemporalProperties->referenceTime().isValid() &&
598  mDataProvider &&
599  mDataProvider->isValid() &&
600  mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
601  {
602  usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
603  usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
604  }
605 
606  return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
607 }
608 
609 void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
610 {
611  if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
612  {
613  QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
614  QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
615  const QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
616 
617  QString units;
618  if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
619  units = meta.extraOptions()[ QStringLiteral( "units" )];
620 
621  QVector<QVector<double>> bounds;
622  for ( const QString &classe : classes )
623  {
624  const QStringList boundsStr = classe.split( ',' );
625  QVector<double> bound;
626  for ( const QString &boundStr : boundsStr )
627  bound.append( boundStr.toDouble() );
628  bounds.append( bound );
629  }
630 
631  if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
632  ( bounds.count() > 1 ) ) // or at least two classes
633  {
634  const QVector<double> firstClass = bounds.first();
635  const QVector<double> lastClass = bounds.last();
636  const double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
637  const double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
638  const double diff = maxValue - minValue;
639  QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
640  for ( int i = 0; i < bounds.count(); ++i )
641  {
642  const QVector<double> &boundClass = bounds.at( i );
644  item.value = i + 1;
645  if ( !boundClass.isEmpty() )
646  {
647  const double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
648  item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
649  if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
650  {
651  item.label = QString( ( "%1 - %2 %3" ) ).
652  arg( QString::number( boundClass.first() ) ).
653  arg( QString::number( boundClass.last() ) ).
654  arg( units );
655  }
656  }
657  colorRampItemlist.append( item );
658  }
659  //treat first and last labels
660  if ( firstClass.count() == 1 )
661  colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
662  arg( QString::number( firstClass.first() ) ).
663  arg( units );
664  else
665  {
666  colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
667  arg( QString::number( firstClass.first() ) ).
668  arg( QString::number( firstClass.last() ) ).
669  arg( units );
670  }
671 
672  if ( lastClass.count() == 1 )
673  colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
674  arg( QString::number( lastClass.first() ) ).
675  arg( units );
676  else
677  {
678  colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
679  arg( QString::number( lastClass.first() ) ).
680  arg( QString::number( lastClass.last() ) ).
681  arg( units );
682  }
683 
684  colorRampShader.setMinimumValue( 0 );
685  colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
686  scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
687  colorRampShader.setColorRampItemList( colorRampItemlist );
688  colorRampShader.setColorRampType( QgsColorRampShader::Exact );
690  }
691 
692  scalarSettings.setColorRampShader( colorRampShader );
694  }
695 }
696 
697 QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const
698 {
699  if ( mTemporalProperties->isActive() )
700  return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
701  else
702  return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
703 }
704 
705 QgsMeshDatasetIndex QgsMeshLayer::activeVectorDatasetAtTime( const QgsDateTimeRange &timeRange ) const
706 {
707  if ( mTemporalProperties->isActive() )
708  return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
709  else
710  return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
711 }
712 
713 void QgsMeshLayer::fillNativeMesh()
714 {
715  Q_ASSERT( !mNativeMesh );
716 
717  mNativeMesh.reset( new QgsMesh() );
718 
719  if ( !( dataProvider() && dataProvider()->isValid() ) )
720  return;
721 
722  dataProvider()->populateMesh( mNativeMesh.get() );
723 }
724 
725 void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
726 {
727  // assign default style to new dataset groups
728  for ( int i = 0; i < datasetGroupIndexes.count(); ++i )
729  assignDefaultStyleToDatasetGroup( datasetGroupIndexes.at( i ) );
730 
731  temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
732  emit rendererChanged();
733 }
734 
735 void QgsMeshLayer::onMeshEdited()
736 {
737  mRendererCache.reset( new QgsMeshLayerRendererCache() );
738  emit layerModified();
739  triggerRepaint();
740  trigger3DUpdate();
741 }
742 
744 {
745  return mDatasetGroupStore->datasetGroupTreeItem();
746 }
747 
749 {
750  mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
751  updateActiveDatasetGroups();
752 }
753 
754 int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
755 {
756  const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
757  const QgsTriangularMesh *mesh = triangularMesh();
758  // search for the closest edge in search area from point
759  const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
760  int selectedIndex = -1;
761  if ( mesh->contains( QgsMesh::Edge ) &&
762  mDataProvider->isValid() )
763  {
764  double sqrMaxDistFromPoint = pow( searchRadius, 2 );
765  for ( const int edgeIndex : edgeIndexes )
766  {
767  const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
768  const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
769  const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
770  QgsPointXY projPoint;
771  const double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint );
772  if ( sqrDist < sqrMaxDistFromPoint )
773  {
774  selectedIndex = edgeIndex;
775  projectedPoint = projPoint;
776  sqrMaxDistFromPoint = sqrDist;
777  }
778  }
779  }
780 
781  return selectedIndex;
782 }
783 
785 {
786  return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
787 }
788 
789 void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
790 {
791  if ( auto *lDataProvider = dataProvider() )
792  mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
793  else
794  mTemporalProperties->setReferenceTime( referenceTime, nullptr );
795 }
796 
798 {
799  mTemporalProperties->setMatchingMethod( matchingMethod );
800 }
801 
802 QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
803 {
804  const QgsTriangularMesh *mesh = triangularMesh();
805  QgsPointXY exactPosition;
806  if ( !mesh )
807  return exactPosition;
808  const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
809  double maxDistance = searchRadius;
810  //attempt to snap on edges's vertices
811  const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
812  for ( const int edgeIndex : edgeIndexes )
813  {
814  const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
815  const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
816  const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
817  const double dist1 = point.distance( vertex1 );
818  const double dist2 = point.distance( vertex2 );
819  if ( dist1 < maxDistance )
820  {
821  maxDistance = dist1;
822  exactPosition = vertex1;
823  }
824  if ( dist2 < maxDistance )
825  {
826  maxDistance = dist2;
827  exactPosition = vertex2;
828  }
829  }
830 
831  //attempt to snap on face's vertices
832  const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
833  for ( const int faceIndex : faceIndexes )
834  {
835  const QgsMeshFace &face = mesh->triangles().at( faceIndex );
836  for ( int i = 0; i < 3; ++i )
837  {
838  const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
839  const double dist = point.distance( vertex );
840  if ( dist < maxDistance )
841  {
842  maxDistance = dist;
843  exactPosition = vertex;
844  }
845  }
846  }
847 
848  return exactPosition;
849 }
850 
851 QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
852 {
853  QgsPointXY projectedPoint;
854  closestEdge( point, searchRadius, projectedPoint );
855 
856  return projectedPoint;
857 }
858 
859 QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
860 {
861  const QgsTriangularMesh *mesh = triangularMesh();
862  QgsPointXY centroidPosition;
863  if ( !mesh )
864  return centroidPosition;
865  const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
866  double maxDistance = std::numeric_limits<double>::max();
867 
868  const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
869  for ( const int faceIndex : faceIndexes )
870  {
871  const int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
872  if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
873  continue;
874  const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
875  const double dist = point.distance( centroid );
876  if ( dist < maxDistance )
877  {
878  maxDistance = dist;
879  centroidPosition = centroid;
880  }
881  }
882 
883  return centroidPosition;
884 }
885 
887 {
888  mDatasetGroupStore->resetDatasetGroupTreeItem();
889  updateActiveDatasetGroups();
890 }
891 
893 {
894  if ( !mDataProvider )
895  return QgsInterval();
896  const int groupCount = mDataProvider->datasetGroupCount();
897  for ( int i = 0; i < groupCount; ++i )
898  {
899  const qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
900  if ( timeStep > 0 )
902  }
903 
904  return QgsInterval();
905 }
906 
908 {
909  const qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
910 
911  if ( time == INVALID_MESHLAYER_TIME )
912  return QgsInterval();
913  else
915 }
916 
918 {
919  return mDatasetGroupStore->datasetRelativeTime( index );
920 }
921 
922 static QString detailsErrorMessage( const QgsMeshEditingError &error )
923 {
924  QString message;
925 
926  switch ( error.errorType )
927  {
929  break;
931  message = QObject::tr( "Face %1 invalid" ).arg( error.elementIndex );
932  break;
934  message = QObject::tr( "Too many vertices for face %1" ).arg( error.elementIndex );
935  break;
937  message = QObject::tr( "Face %1 is flat" ).arg( error.elementIndex );
938  break;
940  message = QObject::tr( "Vertex %1 is a unique shared vertex" ).arg( error.elementIndex );
941  break;
943  message = QObject::tr( "Vertex %1 is invalid" ).arg( error.elementIndex );
944  break;
946  message = QObject::tr( "Face %1 is manifold" ).arg( error.elementIndex );
947  break;
948  }
949 
950  return message;
951 }
952 
954 {
955  if ( !supportsEditing() )
956  {
957  QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" not support mesh editing" ).arg( name() ) );
958  return false;
959  }
960 
961  if ( mMeshEditor )
962  {
963  QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" already in editing mode" ).arg( name() ) );
964  return false;
965  }
966 
967  mSimplificationSettings.setEnabled( false );
968 
969  updateTriangularMesh( transform );
970 
971  mMeshEditor = new QgsMeshEditor( this );
972 
973  const QgsMeshEditingError error = mMeshEditor->initialize();
974 
975  if ( error.errorType != Qgis::MeshEditingErrorType::NoError )
976  {
977  mMeshEditor->deleteLater();
978  mMeshEditor = nullptr;
979 
980  QgsMessageLog::logMessage( QObject::tr( "Unable to start editing of mesh layer \"%1\": %2" ).
981  arg( name(), detailsErrorMessage( error ) ), QString(), Qgis::MessageLevel::Critical );
982  return false;
983  }
984 
985  // During editing, we don't need anymore the provider data. Mesh frame data is stored in the mesh editor.
986  mDataProvider->close();
987 
988  // All dataset group are removed and replace by a unique virtual dataset group that provide vertices elevation value.
989  mExtraDatasetUri.clear();
990  mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
991  mDatasetGroupStore->addDatasetGroup( mMeshEditor->createZValueDatasetGroup() );
993 
994  connect( mMeshEditor, &QgsMeshEditor::meshEdited, this, &QgsMeshLayer::onMeshEdited );
995 
996  emit dataChanged();
997  emit editingStarted();
998 
999  return true;
1000 }
1001 
1002 bool QgsMeshLayer::commitFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1003 {
1005  QString detailsError;
1006  if ( !mMeshEditor->checkConsistency( error ) )
1007  {
1008  if ( error.errorType == Qgis::MeshEditingErrorType::NoError )
1009  detailsError = tr( "Unknown inconsistent mesh error" );
1010  }
1011  else
1012  {
1013  error = QgsTopologicalMesh::checkTopology( *mNativeMesh, mMeshEditor->maximumVerticesPerFace() );
1014  detailsError = detailsErrorMessage( error );
1015  }
1016 
1017  if ( !detailsError.isEmpty() )
1018  {
1019  QgsMessageLog::logMessage( QObject::tr( "Edited mesh layer \"%1\" can't be save due to an error: %2" ).
1020  arg( name(), detailsError ), QString(), Qgis::MessageLevel::Critical );
1021  return false;
1022  }
1023 
1024  stopFrameEditing( transform );
1025 
1026  if ( !mDataProvider )
1027  return false;
1028 
1029  const bool res = mDataProvider->saveMeshFrame( *mNativeMesh.get() );
1030 
1031  if ( continueEditing )
1032  {
1033  mMeshEditor->initialize();
1034  emit layerModified();
1035  return res;
1036  }
1037 
1038  mMeshEditor->deleteLater();
1039  mMeshEditor = nullptr;
1040  emit editingStopped();
1041 
1042  mDataProvider->reloadData();
1043  mDataProvider->populateMesh( mNativeMesh.get() );
1044  mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1045  mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1047  return true;
1048 }
1049 
1050 bool QgsMeshLayer::rollBackFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1051 {
1052  stopFrameEditing( transform );
1053 
1054  if ( !mDataProvider )
1055  return false;
1056 
1057  mTriangularMeshes.clear();
1058  mDataProvider->reloadData();
1059  mDataProvider->populateMesh( mNativeMesh.get() );
1060  updateTriangularMesh( transform );
1061  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1062  trigger3DUpdate();
1063 
1064  if ( continueEditing )
1065  {
1066  mMeshEditor->resetTriangularMesh( triangularMesh() );
1067  return mMeshEditor->initialize() == QgsMeshEditingError();
1068  }
1069  else
1070  {
1071  mMeshEditor->deleteLater();
1072  mMeshEditor = nullptr;
1073  emit editingStopped();
1074 
1075  mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1076  mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1078  emit dataChanged();
1079  return true;
1080  }
1081 }
1082 
1084 {
1085  if ( !mMeshEditor )
1086  return;
1087 
1088  mMeshEditor->stopEditing();
1089  mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1090  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1091 }
1092 
1093 bool QgsMeshLayer::reindex( const QgsCoordinateTransform &transform, bool renumber )
1094 {
1095  if ( !mMeshEditor )
1096  return false;
1097 
1098  if ( !mMeshEditor->reindex( renumber ) )
1099  return false;
1100 
1101  mTriangularMeshes.clear();
1102  mTriangularMeshes.emplace_back( new QgsTriangularMesh );
1103  mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1104  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1105  mMeshEditor->resetTriangularMesh( mTriangularMeshes.at( 0 ).get() );
1106 
1107  return true;
1108 }
1109 
1111 {
1112  return mMeshEditor;
1113 }
1114 
1116 {
1117  if ( mMeshEditor )
1118  return mMeshEditor->isModified();
1119 
1120  return false;
1121 }
1122 
1124 {
1125  switch ( type )
1126  {
1127  case QgsMesh::ElementType::Vertex:
1128  return meshVertexCount() != 0;
1129  case QgsMesh::ElementType::Edge:
1130  return meshEdgeCount() != 0;
1131  case QgsMesh::ElementType::Face:
1132  return meshFaceCount() != 0;
1133  }
1134  return false;
1135 }
1136 
1138 {
1139  if ( mMeshEditor )
1140  return mMeshEditor->validVerticesCount();
1141  else if ( mDataProvider )
1142  return mDataProvider->vertexCount();
1143  else return 0;
1144 }
1145 
1147 {
1148  if ( mMeshEditor )
1149  return mMeshEditor->validFacesCount();
1150  else if ( mDataProvider )
1151  return mDataProvider->faceCount();
1152  else return 0;
1153 }
1154 
1156 {
1157  if ( mMeshEditor )
1158  return mNativeMesh->edgeCount();
1159  else if ( mDataProvider )
1160  return mDataProvider->edgeCount();
1161  else return 0;
1162 }
1163 
1164 void QgsMeshLayer::updateActiveDatasetGroups()
1165 {
1166  QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
1167 
1168  if ( !mDatasetGroupStore->datasetGroupTreeItem() )
1169  return;
1170 
1172  const int oldActiveScalar = settings.activeScalarDatasetGroup();
1173  const int oldActiveVector = settings.activeVectorDatasetGroup();
1174 
1175  QgsMeshDatasetGroupTreeItem *activeScalarItem =
1176  treeItem->childFromDatasetGroupIndex( oldActiveScalar );
1177 
1178  if ( !activeScalarItem && treeItem->childCount() > 0 )
1179  activeScalarItem = treeItem->child( 0 );
1180 
1181  if ( activeScalarItem && !activeScalarItem->isEnabled() )
1182  {
1183  for ( int i = 0; i < treeItem->childCount(); ++i )
1184  {
1185  activeScalarItem = treeItem->child( i );
1186  if ( activeScalarItem->isEnabled() )
1187  break;
1188  else
1189  activeScalarItem = nullptr;
1190  }
1191  }
1192 
1193  if ( activeScalarItem )
1194  settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
1195  else
1196  settings.setActiveScalarDatasetGroup( -1 );
1197 
1198  QgsMeshDatasetGroupTreeItem *activeVectorItem =
1199  treeItem->childFromDatasetGroupIndex( oldActiveVector );
1200 
1201  if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
1202  settings.setActiveVectorDatasetGroup( -1 );
1203 
1204  setRendererSettings( settings );
1205 
1206  if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
1208  if ( oldActiveVector != settings.activeVectorDatasetGroup() )
1210 }
1211 
1212 void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1213 {
1214  mDataSource = dataSource;
1215  mLayerName = baseName;
1216  setProviderType( provider );
1217 
1218  if ( !mDataSource.isEmpty() && !provider.isEmpty() )
1219  setDataProvider( provider, options, flags );
1220 }
1221 
1222 QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
1223 {
1224  switch ( elementType )
1225  {
1226  case QgsMesh::Vertex:
1227  return snapOnVertex( point, searchRadius );
1228  case QgsMesh::Edge:
1229  return snapOnEdge( point, searchRadius );
1230  case QgsMesh::Face:
1231  return snapOnFace( point, searchRadius );
1232  }
1233  return QgsPointXY(); // avoid warnings
1234 }
1235 
1237 {
1238  if ( !mNativeMesh )
1239  {
1240  // lazy loading of mesh data
1241  fillNativeMesh();
1242  }
1243 
1244  QList<int> ret;
1245 
1246  if ( !mNativeMesh )
1247  return ret;
1248 
1249  QgsExpressionContext context;
1250  std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Vertex ) );
1251  context.appendScope( expScope.release() );
1252  context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1253 
1254  expression.prepare( &context );
1255 
1256  for ( int i = 0; i < mNativeMesh->vertexCount(); ++i )
1257  {
1258  context.lastScope()->setVariable( QStringLiteral( "_mesh_vertex_index" ), i, false );
1259 
1260  if ( expression.evaluate( &context ).toBool() )
1261  ret.append( i );
1262  }
1263 
1264  return ret;
1265 }
1266 
1268 {
1269  if ( !mNativeMesh )
1270  {
1271  // lazy loading of mesh data
1272  fillNativeMesh();
1273  }
1274 
1275  QList<int> ret;
1276 
1277  if ( !mNativeMesh )
1278  return ret;
1279 
1280  QgsExpressionContext context;
1281  std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Face ) );
1282  context.appendScope( expScope.release() );
1283  context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1284 
1285  expression.prepare( &context );
1286 
1287  for ( int i = 0; i < mNativeMesh->faceCount(); ++i )
1288  {
1289  context.lastScope()->setVariable( QStringLiteral( "_mesh_face_index" ), i, false );
1290 
1291  if ( expression.evaluate( &context ).toBool() )
1292  ret.append( i );
1293  }
1294 
1295  return ret;
1296 }
1297 
1299 {
1300  return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
1301 }
1302 
1304 {
1305  const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
1306 
1307  mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
1309 
1310  if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
1311  emit activeVectorDatasetGroupChanged( mRendererSettings.activeVectorDatasetGroup() );
1312 }
1313 
1315 {
1316  const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
1317 
1318  mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
1320 
1321  if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
1322  emit activeScalarDatasetGroupChanged( mRendererSettings.activeScalarDatasetGroup() );
1323 }
1324 
1326 {
1327  return mSimplificationSettings;
1328 }
1329 
1331 {
1332  mSimplificationSettings = simplifySettings;
1333 }
1334 
1335 static QgsColorRamp *_createDefaultColorRamp()
1336 {
1337  QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
1338  if ( ramp )
1339  return ramp;
1340 
1341  // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
1342  QVariantMap props;
1343  props["color1"] = "13,8,135,255";
1344  props["color2"] = "240,249,33,255";
1345  props["stops"] =
1346  "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:"
1347  "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:"
1348  "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:"
1349  "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:"
1350  "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:"
1351  "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:"
1352  "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:"
1353  "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:"
1354  "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:"
1355  "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";
1356  return QgsGradientColorRamp::create( props );
1357 }
1358 
1359 void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1360 {
1362  const double groupMin = metadata.minimum();
1363  const double groupMax = metadata.maximum();
1364 
1365  QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1366  fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1367 
1368  QgsMeshRendererScalarSettings scalarSettings;
1369  scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1370  scalarSettings.setColorRampShader( fcn );
1371  QgsInterpolatedLineWidth edgeStrokeWidth;
1372  edgeStrokeWidth.setMinimumValue( groupMin );
1373  edgeStrokeWidth.setMaximumValue( groupMax );
1374  const QgsInterpolatedLineColor edgeStrokeColor( fcn );
1375  const QgsInterpolatedLineRenderer edgeStrokePen;
1376  scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1377  mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1378 
1379  if ( metadata.isVector() )
1380  {
1381  QgsMeshRendererVectorSettings vectorSettings;
1382  vectorSettings.setColorRampShader( fcn );
1383  mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1384  }
1385 }
1386 
1388 {
1389  // Triangular mesh
1390  updateTriangularMesh( rendererContext.coordinateTransform() );
1391 
1392  // Build overview triangular meshes if needed
1393  createSimplifiedMeshes();
1394 
1395  // Cache
1396  if ( !mRendererCache )
1397  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1398 
1399  return new QgsMeshLayerRenderer( this, rendererContext );
1400 }
1401 
1402 bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1403  QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1404 {
1405  Q_UNUSED( errorMessage )
1406  // TODO: implement categories for raster layer
1407 
1408  const QDomElement elem = node.toElement();
1409 
1410  readCommonStyle( elem, context, categories );
1411 
1412  const QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1413  if ( !elemRendererSettings.isNull() )
1414  mRendererSettings.readXml( elemRendererSettings, context );
1415 
1416  const QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1417  if ( !elemSimplifySettings.isNull() )
1418  mSimplificationSettings.readXml( elemSimplifySettings, context );
1419 
1420  // get and set the blend mode if it exists
1421  const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1422  if ( !blendModeNode.isNull() )
1423  {
1424  const QDomElement e = blendModeNode.toElement();
1425  setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1426  }
1427 
1428  // get and set the layer transparency
1429  if ( categories.testFlag( Rendering ) )
1430  {
1431  const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1432  if ( !layerOpacityNode.isNull() )
1433  {
1434  const QDomElement e = layerOpacityNode.toElement();
1435  setOpacity( e.text().toDouble() );
1436  }
1437  }
1438 
1439  return true;
1440 }
1441 
1442 bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1443  const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1444 {
1445  Q_UNUSED( errorMessage )
1446  // TODO: implement categories for raster layer
1447 
1448  QDomElement elem = node.toElement();
1449 
1450  writeCommonStyle( elem, doc, context, categories );
1451 
1452  const QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1453  elem.appendChild( elemRendererSettings );
1454 
1455  const QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1456  elem.appendChild( elemSimplifySettings );
1457 
1458  // add blend mode node
1459  QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1460  const QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1461  blendModeElement.appendChild( blendModeText );
1462  node.appendChild( blendModeElement );
1463 
1464  // add the layer opacity
1465  if ( categories.testFlag( Rendering ) )
1466  {
1467  QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1468  const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1469  layerOpacityElem.appendChild( layerOpacityText );
1470  node.appendChild( layerOpacityElem );
1471  }
1472 
1473  return true;
1474 }
1475 
1476 bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1477 {
1478  return writeSymbology( node, doc, errorMessage, context, categories );
1479 }
1480 
1481 bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1482 {
1483  return readSymbology( node, errorMessage, context, categories );
1484 }
1485 
1486 QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1487 {
1488  QString src( source );
1489  if ( provider == QLatin1String( "mdal" ) )
1490  {
1491  src = context.pathResolver().readPath( src );
1492  }
1493  return src;
1494 }
1495 
1496 QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1497 {
1498  QString src( source );
1499  if ( providerType() == QLatin1String( "mdal" ) )
1500  {
1501  src = context.pathResolver().writePath( src );
1502  }
1503  return src;
1504 }
1505 
1506 bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1507 {
1508  QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1509 
1510  //process provider key
1511  const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1512 
1513  if ( pkeyNode.isNull() )
1514  {
1515  mProviderKey.clear();
1516  }
1517  else
1518  {
1519  const QDomElement pkeyElt = pkeyNode.toElement();
1520  mProviderKey = pkeyElt.text();
1521  }
1522 
1524  {
1525  return false;
1526  }
1527 
1528  const QgsDataProvider::ProviderOptions providerOptions;
1529  QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
1531  {
1533  }
1534 
1535  const QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1536  if ( !elemExtraDatasets.isNull() )
1537  {
1538  QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1539  while ( !elemUri.isNull() )
1540  {
1541  const QString uri = context.pathResolver().readPath( elemUri.text() );
1542  mExtraDatasetUri.append( uri );
1543  elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1544  }
1545  }
1546 
1547  if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1548  mTemporalUnit = static_cast<QgsUnitTypes::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1549 
1550  // read dataset group store
1551  const QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1552  if ( elemDatasetGroupsStore.isNull() )
1554  else
1555  mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1556 
1557  setDataProvider( mProviderKey, providerOptions, flags );
1558 
1559  QString errorMsg;
1560  readSymbology( layer_node, errorMsg, context );
1561 
1562  if ( !mTemporalProperties->timeExtent().begin().isValid() )
1564 
1565  // read static dataset
1566  const QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1567  if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1568  {
1569  mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1570  }
1571  if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1572  {
1573  mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1574  }
1575 
1576  return isValid(); // should be true if read successfully
1577 }
1578 
1579 bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1580 {
1581  // first get the layer element so that we can append the type attribute
1582  QDomElement mapLayerNode = layer_node.toElement();
1583 
1584  if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1585  {
1586  QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1587  return false;
1588  }
1589 
1590  mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::MeshLayer ) );
1591 
1592  // add provider node
1593  if ( mDataProvider )
1594  {
1595  QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1596  const QDomText providerText = document.createTextNode( providerType() );
1597  provider.appendChild( providerText );
1598  layer_node.appendChild( provider );
1599  provider.setAttribute( QStringLiteral( "time-unit" ), mDataProvider->temporalCapabilities()->temporalUnit() );
1600 
1601  const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1602  QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1603  for ( const QString &uri : extraDatasetUris )
1604  {
1605  const QString path = context.pathResolver().writePath( uri );
1606  QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1607  elemUri.appendChild( document.createTextNode( path ) );
1608  elemExtraDatasets.appendChild( elemUri );
1609  }
1610  layer_node.appendChild( elemExtraDatasets );
1611  }
1612 
1613  QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1614  elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1615  elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1616  layer_node.appendChild( elemStaticDataset );
1617 
1618  // write dataset group store if not in edting mode
1619  if ( !isEditable() )
1620  layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1621 
1622  // renderer specific settings
1623  QString errorMsg;
1624  return writeSymbology( layer_node, document, errorMsg, context );
1625 }
1626 
1628 {
1629  if ( !mMeshEditor && mDataProvider && mDataProvider->isValid() )
1630  {
1631  mDataProvider->reloadData();
1632 
1633  //reload the mesh structure
1634  if ( !mNativeMesh )
1635  mNativeMesh.reset( new QgsMesh );
1636 
1637  dataProvider()->populateMesh( mNativeMesh.get() );
1638 
1639  //clear the TriangularMeshes
1640  mTriangularMeshes.clear();
1641 
1642  //clear the rendererCache
1643  mRendererCache.reset( new QgsMeshLayerRendererCache() );
1644  }
1645 }
1646 
1647 QStringList QgsMeshLayer::subLayers() const
1648 {
1649  if ( mDataProvider )
1650  return mDataProvider->subLayers();
1651  else
1652  return QStringList();
1653 }
1654 
1656 {
1657  const QgsLayerMetadataFormatter htmlFormatter( metadata() );
1658  QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1659 
1660  myMetadata += generalHtmlMetadata();
1661 
1662  // Begin Provider section
1663  myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1664  myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1665 
1666  // Extent
1667  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1668 
1669  // feature count
1670  QLocale locale = QLocale();
1671  locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1672 
1673  if ( dataProvider() )
1674  {
1675  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1676  + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
1677  + ( locale.toString( static_cast<qlonglong>( meshVertexCount() ) ) )
1678  + QStringLiteral( "</td></tr>\n" );
1679  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1680  + tr( "Face count" ) + QStringLiteral( "</td><td>" )
1681  + ( locale.toString( static_cast<qlonglong>( meshFaceCount() ) ) )
1682  + QStringLiteral( "</td></tr>\n" );
1683  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1684  + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
1685  + ( locale.toString( static_cast<qlonglong>( meshEdgeCount() ) ) )
1686  + QStringLiteral( "</td></tr>\n" );
1687  myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1688  + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
1689  + ( locale.toString( static_cast<qlonglong>( datasetGroupCount() ) ) )
1690  + QStringLiteral( "</td></tr>\n" );
1691  }
1692 
1693  // End Provider section
1694  myMetadata += QLatin1String( "</table>\n<br><br>" );
1695 
1696  // CRS
1697  myMetadata += crsHtmlMetadata();
1698 
1699  // identification section
1700  myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
1701  myMetadata += htmlFormatter.identificationSectionHtml( );
1702  myMetadata += QLatin1String( "<br><br>\n" );
1703 
1704  // extent section
1705  myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
1706  myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
1707  myMetadata += QLatin1String( "<br><br>\n" );
1708 
1709  // Start the Access section
1710  myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
1711  myMetadata += htmlFormatter.accessSectionHtml( );
1712  myMetadata += QLatin1String( "<br><br>\n" );
1713 
1714  // Start the contacts section
1715  myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
1716  myMetadata += htmlFormatter.contactsSectionHtml( );
1717  myMetadata += QLatin1String( "<br><br>\n" );
1718 
1719  // Start the links section
1720  myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
1721  myMetadata += htmlFormatter.linksSectionHtml( );
1722  myMetadata += QLatin1String( "<br><br>\n" );
1723 
1724  // Start the history section
1725  myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
1726  myMetadata += htmlFormatter.historySectionHtml( );
1727  myMetadata += QLatin1String( "<br><br>\n" );
1728 
1729  myMetadata += QLatin1String( "\n</body>\n</html>\n" );
1730  return myMetadata;
1731 }
1732 
1734 {
1735  return mMeshEditor != nullptr;
1736 }
1737 
1738 bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1739 {
1740  mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
1741 
1742  delete mDataProvider;
1743  mProviderKey = provider;
1744  const QString dataSource = mDataSource;
1745 
1746  mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
1747 
1748  if ( !mDataProvider )
1749  {
1750  QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
1751  return false;
1752  }
1753 
1754  mDataProvider->setParent( this );
1755  QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
1756 
1757  setValid( mDataProvider->isValid() );
1758  if ( !isValid() )
1759  {
1760  QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1761  return false;
1762  }
1763 
1764  if ( !mTemporalProperties->isValid() )
1765  {
1766  mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( dataProvider()->temporalCapabilities() );
1767  }
1768 
1769  mDataProvider->setTemporalUnit( mTemporalUnit );
1770 
1771  mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
1772 
1773  setCrs( mDataProvider->crs() );
1774 
1775  if ( provider == QLatin1String( "mesh_memory" ) )
1776  {
1777  // required so that source differs between memory layers
1778  mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1779  }
1780 
1781  // set default style if required by flags or if the dataset group does not has a style yet
1782  for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
1783  {
1784  int globalIndex = mDatasetGroupStore->globalDatasetGroupIndexInSource( mDataProvider, i );
1785  if ( globalIndex != -1 &&
1786  ( !mRendererSettings.hasSettings( globalIndex ) || ( flags & QgsDataProvider::FlagLoadDefaultStyle ) ) )
1787  assignDefaultStyleToDatasetGroup( globalIndex );
1788  }
1789 
1790  emit rendererChanged();
1791  emitStyleChanged();
1792 
1793  connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
1794 
1795  return true;
1796 }
1797 
1799 {
1800  return mTemporalProperties;
1801 }
@ TooManyVerticesInFace
A face has more vertices than the maximum number supported per face.
@ InvalidFace
An error occurs due to an invalid face (for example, vertex indexes are unordered)
@ UniqueSharedVertex
A least two faces share only one vertices.
@ ManifoldFace
ManifoldFace.
@ InvalidVertex
An error occurs due to an invalid vertex (for example, vertex index is out of range the available ver...
@ FlatFace
A flat face is present.
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:30
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.
@ FlagLoadDefaultStyle
Reset the layer's style to the default for the datasource.
@ 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.
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QgsExpressionContextScope * meshExpressionScope(QgsMesh::ElementType elementType)
Creates a new scope which contains functions relating to mesh layer element elementType.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QVariant evaluate()
Evaluate the feature and return the result.
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:73
QString name
Definition: qgsmaplayer.h:76
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
QString source() const
Returns the source for the layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void trigger3DUpdate()
Will advise any 3D maps that this layer requires to be updated in the scene.
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void editingStarted()
Emitted when editing on this layer has started.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1931
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:78
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:1969
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.
virtual QgsError error() const
Gets current status error.
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 emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
bool isValid
Definition: qgsmaplayer.h:81
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1928
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:641
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:640
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:1974
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:170
void layerModified()
Emitted when modifications has been done on layer.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
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:1981
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.
virtual QgsMeshDriverMetadata driverMetadata() const
Returns the mesh driver metadata of the provider.
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 close()=0
Closes the data provider and free every resources used.
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
virtual bool saveMeshFrame(const QgsMesh &mesh)=0
Saves the mesh frame to the source.
virtual int edgeCount() const =0
Returns number of edges in the native mesh.
virtual int faceCount() const =0
Returns number of faces in the native mesh.
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.
Holds metadata about mesh driver.
@ CanWriteMeshData
If the driver can write mesh data on file.
MeshDriverCapabilities capabilities() const
Returns the capabilities for this driver.
Class that represents an error during mesh editing.
Definition: qgsmesheditor.h:43
Qgis::MeshEditingErrorType errorType
Definition: qgsmesheditor.h:52
Class that makes edit operation on a mesh.
Definition: qgsmesheditor.h:68
QgsMeshEditingError initialize()
Initialize the mesh editor and return errors if the internal native mesh have topologic errors.
int validFacesCount() const
Returns the count of valid faces, that is non void faces in the mesh.
bool checkConsistency(QgsMeshEditingError &error) const
Return true if the edited mesh is consistent.
QgsRectangle extent() const
Returns the extent of the edited mesh.
int maximumVerticesPerFace() const
Returns the maximum count of vertices per face that the mesh can support.
void stopEditing()
Stops editing.
void meshEdited()
Emitted when the mesh is edited.
void resetTriangularMesh(QgsTriangularMesh *triangularMesh)
Resets the triangular mesh.
bool isModified() const
Returns whether the mesh has been modified.
int validVerticesCount() const
Returns the count of valid vertices, that is non void vertices in the mesh.
bool reindex(bool renumbering)
Reindexes the mesh, that is remove unusued index of face and vertices, this operation void the undo/r...
QgsMeshDatasetGroup * createZValueDatasetGroup()
Creates and returns a scalar dataset group with value on vertex that is can be used to access the Z v...
Implementation of threaded rendering for mesh layers.
Implementation of map layer temporal properties for mesh layers.
QDateTime referenceTime() const
Returns the reference time.
bool isValid() const
Returns whether the instance is valid.
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:97
~QgsMeshLayer() override
QList< int > selectVerticesByExpression(QgsExpression expression)
Returns a list of vertex indexes that meet the condition defined by expression with the context expre...
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.
void stopFrameEditing(const QgsCoordinateTransform &transform)
Stops edition of the mesh, re-indexes the faces and vertices, rebuilds the triangular mesh and its sp...
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.
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains at mesh elements of given type.
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.
QList< QgsMeshDatasetIndex > datasetIndexInRelativeTimeInterval(const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex) const
Returns a list of dataset indexes from datasets group that are in a interval time from the layer refe...
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.
bool isModified() const override
Returns whether the mesh frame has been modified since the last save.
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.
QgsMeshEditor * meshEditor()
Returns a pointer to the mesh editor own by the mesh 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)
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
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.
int meshFaceCount() const
Returns the faces count of the mesh frame.
QList< int > selectFacesByExpression(QgsExpression expression)
Returns a list of faces indexes that meet the condition defined by expression with the context expres...
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.
bool rollBackFrameEditing(const QgsCoordinateTransform &transform, bool continueEditing=true)
Rolls Back edition of the mesh frame.
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.
bool commitFrameEditing(const QgsCoordinateTransform &transform, bool continueEditing=true)
Commits edition of the mesh frame, Rebuilds the triangular mesh and its spatial index with transform,...
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.
int meshEdgeCount() const
Returns the edges count of the mesh frame.
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...
bool isEditable() const override
Returns true if the layer can be edited.
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.
bool supportsEditing() const override
Returns whether the layer supports editing or not.
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.
bool startFrameEditing(const QgsCoordinateTransform &transform)
Starts edition of the mesh frame.
bool reindex(const QgsCoordinateTransform &transform, bool renumber)
Re-indexes the faces and vertices, and renumber the indexes if renumber is true.
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
int meshVertexCount() const
Returns the vertices count of the mesh frame.
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.
bool hasSettings(int datasetGroupIndex) const
Returns whether the group with index has render settings (scalar or vector)
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 an overview renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
void setEnabled(bool isEnabled)
Sets if the overview is active.
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 void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
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
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:449
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
static QgsMeshEditingError checkTopology(const QgsMesh &mesh, int maxVerticesPerFace)
Checks the topology of the mesh mesh, if error occurs, this mesh can't be edited.
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 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:47
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
#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:105
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Definition: qgsmeshlayer.h:118
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
Definition: qgsmeshlayer.h:124
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:139
Mesh - vertices, edges and faces.
ElementType
Defines type of mesh elements.