QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
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 "qgsmeshdataprovider.h"
30#include "qgsmeshlayer.h"
33#include "qgsmeshlayerutils.h"
34#include "qgsmeshtimesettings.h"
35#include "qgspainting.h"
36#include "qgsproviderregistry.h"
37#include "qgsreadwritecontext.h"
38#include "qgsstyle.h"
39#include "qgstriangularmesh.h"
40#include "qgsmesh3daveraging.h"
42#include "qgsmesheditor.h"
43#include "qgsmessagelog.h"
47#include "qgsthreadingutils.h"
48#include "qgsapplication.h"
49#include "qgsruntimeprofiler.h"
50
51QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
52 const QString &baseName,
53 const QString &providerKey,
54 const QgsMeshLayer::LayerOptions &options )
55 : QgsMapLayer( Qgis::LayerType::Mesh, baseName, meshLayerPath )
56 , mDatasetGroupStore( new QgsMeshDatasetGroupStore( this ) )
57 , mTemporalProperties( new QgsMeshLayerTemporalProperties( this ) )
58 , mElevationProperties( new QgsMeshLayerElevationProperties( this ) )
59{
61
62 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
63 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
64 if ( options.loadDefaultStyle )
65 {
67 }
68 QgsMeshLayer::setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
71
72 if ( isValid() && options.loadDefaultStyle )
73 {
74 bool result = false;
75 loadDefaultStyle( result );
76 }
77
78 connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
79}
80
81void QgsMeshLayer::createSimplifiedMeshes()
82{
84
85 if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
86 {
87 const double reductionFactor = mSimplificationSettings.reductionFactor();
88
89 QVector<QgsTriangularMesh *> simplifyMeshes =
90 mTriangularMeshes[0]->simplifyMesh( reductionFactor );
91
92 for ( int i = 0; i < simplifyMeshes.count() ; ++i )
93 {
94 mTriangularMeshes.emplace_back( simplifyMeshes[i] );
95 }
96 }
97}
98
99bool QgsMeshLayer::hasSimplifiedMeshes() const
100{
102
103 //First mesh is the base mesh, so if size>1, there is no simplified meshes
104 return ( mTriangularMeshes.size() > 1 );
105}
106
108{
109 delete mDataProvider;
110}
111
118
120{
122
123 return mDataProvider;
124}
125
127{
129
131 if ( mDataProvider )
132 {
133 options.transformContext = mDataProvider->transformContext();
134 }
135 QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
136 QgsMapLayer::clone( layer );
137
138 layer->mElevationProperties = mElevationProperties->clone();
139 layer->mElevationProperties->setParent( layer );
140
141 return layer;
142}
143
145{
147
148 if ( mMeshEditor )
149 return mMeshEditor->extent();
150
151 if ( mDataProvider )
152 return mDataProvider->extent();
153 else
154 {
155 QgsRectangle rec;
156 rec.setNull();
157 return rec;
158 }
159}
160
167
169{
171
172 if ( !mDataProvider )
173 return false;
174
175 if ( mMeshEditor )
176 return true;
177
178 const QgsMeshDriverMetadata driverMetadata = mDataProvider->driverMetadata();
179
181}
182
183QString QgsMeshLayer::loadDefaultStyle( bool &resultFlag )
184{
186
187 const QList<int> groupsList = datasetGroupsIndexes();
188
189 for ( const int index : groupsList )
190 assignDefaultStyleToDatasetGroup( index );
191
192
193 QgsMeshRendererMeshSettings meshSettings;
194 if ( !groupsList.isEmpty() )
195 {
196 // Show data from the first dataset group
197 mRendererSettings.setActiveScalarDatasetGroup( 0 );
198 // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
200 if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
201 meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
202 meshSettings.setEnabled( true );
203 }
204 else
205 {
206 // show at least the mesh by default
207 meshSettings.setEnabled( true );
208 }
209
210 mRendererSettings.setNativeMeshSettings( meshSettings );
211
212 for ( const int i : groupsList )
213 {
214 assignDefaultStyleToDatasetGroup( i );
215
216 // Sets default resample method for scalar dataset
218 QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
219 switch ( meta.dataType() )
220 {
222 case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
224 break;
227 break;
229 break;
230 }
231
232 //override color ramp if the values in the dataset group are classified
233 applyClassificationOnScalarSettings( meta, scalarSettings );
234
235 mRendererSettings.setScalarSettings( i, scalarSettings );
236 }
237
238 if ( !groupsList.isEmpty() )
239 {
240 emit rendererChanged();
242 }
243
244 return QgsMapLayer::loadDefaultStyle( resultFlag );
245}
246
247bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
248{
250
251 const bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
252 if ( mDatasetGroupStore->addPersistentDatasets( path ) )
253 {
254 mExtraDatasetUri.append( path );
255 QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
256 if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
257 {
259 dataProvider()->temporalCapabilities() );
260
261 if ( ! temporalProperties->referenceTime().isValid() )
262 {
263 QDateTime referenceTime = defaultReferenceTime;
264 if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
265 referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
266 temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
267 }
268
269 mTemporalProperties->setIsActive( true );
270 }
271 emit dataSourceChanged();
272 return true;
273 }
274
275 return false;
276}
277
279{
281
282 if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
283 {
284 emit dataChanged();
285 return true;
286 }
287 return false;
288}
289
290bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
291{
293
294 return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
295}
296
298{
300
301 return mNativeMesh.get();
302}
303
305{
307
308 return mNativeMesh.get();
309}
310
311QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
312{
314
315 for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
316 {
317 if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
318 return lod.get();
319 }
320
321 if ( !mTriangularMeshes.empty() )
322 return mTriangularMeshes.back().get();
323 else
324 return nullptr;
325}
326
328{
330
331 return mTriangularMeshes.size();
332}
333
335{
337
338 if ( mTriangularMeshes.empty() )
339 return nullptr;
340 if ( lodIndex < 0 )
341 return mTriangularMeshes.front().get();
342
343 if ( lodIndex >= int( mTriangularMeshes.size() ) )
344 return mTriangularMeshes.back().get();
345
346 return mTriangularMeshes.at( lodIndex ).get();
347}
348
350{
352
353 // Native mesh
354 if ( !mNativeMesh )
355 {
356 // lazy loading of mesh data
357 fillNativeMesh();
358 }
359
360 // Triangular mesh
361 if ( mTriangularMeshes.empty() )
362 {
363 QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
364 mTriangularMeshes.emplace_back( baseMesh );
365 }
366
367 if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
368 mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
369
370 createSimplifiedMeshes();
371}
372
373QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
374{
376
377 return mRendererCache.get();
378}
379
386
388{
390
391 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
392 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
393 mRendererSettings = settings;
394
395 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
397
398 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
400
401 emit rendererChanged();
403}
404
411
413{
415
416 mTimeSettings = settings;
417 emit timeSettingsChanged();
418}
419
420QString QgsMeshLayer::formatTime( double hours )
421{
423
424 if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
425 return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
426 else
427 return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
428}
429
431{
433
434 return mDatasetGroupStore->datasetGroupCount();
435}
436
438{
440
441 return mDatasetGroupStore->extraDatasetGroupCount();
442}
443
445{
447
448 return mDatasetGroupStore->datasetGroupIndexes();
449}
450
452{
454
455 return mDatasetGroupStore->enabledDatasetGroupIndexes();
456}
457
459{
461
462 return mDatasetGroupStore->datasetGroupMetadata( index );
463}
464
466{
468
469 return mDatasetGroupStore->datasetCount( index.group() );
470}
471
473{
475
476 return mDatasetGroupStore->datasetMetadata( index );
477}
478
480{
482
483 return mDatasetGroupStore->datasetValue( index, valueIndex );
484}
485
486QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
487{
489
490 return mDatasetGroupStore->datasetValues( index, valueIndex, count );
491}
492
493QgsMesh3DDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
494{
496
497 return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
498}
499
500QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
501{
503
504 return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
505}
506
507bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
508{
510
511 return mDatasetGroupStore->isFaceActive( index, faceIndex );
512}
513
514QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
515{
517
519 const QgsTriangularMesh *mesh = triangularMesh();
520
521 if ( mesh && index.isValid() )
522 {
524 {
525 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
526 return dataset1dValue( index, point, searchRadius );
527 }
528 const int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
529 if ( faceIndex >= 0 )
530 {
531 const int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
533 if ( isFaceActive( index, nativeFaceIndex ) )
534 {
535 switch ( dataType )
536 {
538 {
539 value = datasetValue( index, nativeFaceIndex );
540 }
541 break;
542
544 {
545 const QgsMeshFace &face = mesh->triangles()[faceIndex];
546 const int v1 = face[0], v2 = face[1], v3 = face[2];
547 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
548 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
549 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
550 const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
551 const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
552 double y = std::numeric_limits<double>::quiet_NaN();
553 const bool isVector = datasetGroupMetadata( index ).isVector();
554 if ( isVector )
555 y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
556
557 value = QgsMeshDatasetValue( x, y );
558 }
559 break;
560
562 {
563 const QgsMesh3DAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
564 if ( avgMethod )
565 {
566 const QgsMesh3DDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
567 const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
568 if ( block2d.isValid() )
569 {
570 value = block2d.value( 0 );
571 }
572 }
573 }
574 break;
575
576 default:
577 break;
578 }
579 }
580 }
581 }
582
583 return value;
584}
585
587{
589
590 QgsMesh3DDataBlock block3d;
591
592 const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
593
594 if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
595 {
598 {
599 const int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
600 if ( faceIndex >= 0 )
601 {
602 const int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
603 block3d = dataset3dValues( index, nativeFaceIndex, 1 );
604 }
605 }
606 }
607 return block3d;
608}
609
610QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
611{
613
615 QgsPointXY projectedPoint;
616 const int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
617 const QgsTriangularMesh *mesh = triangularMesh();
618 if ( selectedIndex >= 0 )
619 {
621 switch ( dataType )
622 {
624 {
625 value = datasetValue( index, selectedIndex );
626 }
627 break;
628
630 {
631 const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
632 const int v1 = edge.first, v2 = edge.second;
633 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
634 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
635 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
636 const double edgeLength = p1.distance( p2 );
637 const double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
638 value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
639 }
640 break;
641 default:
642 break;
643 }
644 }
645
646 return value;
647}
648
650{
652
653 if ( mDataProvider )
654 mDataProvider->setTransformContext( transformContext );
656}
657
658QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
659{
661
662 if ( ! mTemporalProperties->isActive() )
663 return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
664
665 const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
666 QDateTime utcTime = timeRange.begin();
667 if ( utcTime.timeSpec() != Qt::UTC )
668 utcTime.setTimeSpec( Qt::UTC );
669 const qint64 startTime = layerReferenceTime.msecsTo( utcTime );
670
671 return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
672}
673
674QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
675{
677
678 return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
679}
680
681QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
682{
684
685 qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
686 qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
687
688 //adjust relative time if layer reference time is different from provider reference time
689 if ( mTemporalProperties->referenceTime().isValid() &&
690 mDataProvider &&
691 mDataProvider->isValid() &&
692 mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
693 {
694 usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
695 usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
696 }
697
698 return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
699}
700
701void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
702{
704
705 if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
706 {
707 QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
708 QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
709 const QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
710
711 QString units;
712 if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
713 units = meta.extraOptions()[ QStringLiteral( "units" )];
714
715 QVector<QVector<double>> bounds;
716 for ( const QString &classe : classes )
717 {
718 const QStringList boundsStr = classe.split( ',' );
719 QVector<double> bound;
720 for ( const QString &boundStr : boundsStr )
721 bound.append( boundStr.toDouble() );
722 bounds.append( bound );
723 }
724
725 if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
726 ( bounds.count() > 1 ) ) // or at least two classes
727 {
728 const QVector<double> firstClass = bounds.first();
729 const QVector<double> lastClass = bounds.last();
730 const double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
731 const double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
732 const double diff = maxValue - minValue;
733 QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
734 for ( int i = 0; i < bounds.count(); ++i )
735 {
736 const QVector<double> &boundClass = bounds.at( i );
738 item.value = i + 1;
739 if ( !boundClass.isEmpty() )
740 {
741 const double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
742 item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
743 if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
744 {
745 item.label = QString( ( "%1 - %2 %3" ) ).
746 arg( QString::number( boundClass.first() ) ).
747 arg( QString::number( boundClass.last() ) ).
748 arg( units );
749 }
750 }
751 colorRampItemlist.append( item );
752 }
753 //treat first and last labels
754 if ( firstClass.count() == 1 )
755 colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
756 arg( QString::number( firstClass.first() ) ).
757 arg( units );
758 else
759 {
760 colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
761 arg( QString::number( firstClass.first() ) ).
762 arg( QString::number( firstClass.last() ) ).
763 arg( units );
764 }
765
766 if ( lastClass.count() == 1 )
767 colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
768 arg( QString::number( lastClass.first() ) ).
769 arg( units );
770 else
771 {
772 colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
773 arg( QString::number( lastClass.first() ) ).
774 arg( QString::number( lastClass.last() ) ).
775 arg( units );
776 }
777
778 colorRampShader.setMinimumValue( 0 );
779 colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
780 scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
781 colorRampShader.setColorRampItemList( colorRampItemlist );
784 }
785
786 scalarSettings.setColorRampShader( colorRampShader );
788 }
789}
790
792{
794
795 if ( mTemporalProperties->isActive() )
796 return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
797 else
798 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
799}
800
802{
804
805 if ( mTemporalProperties->isActive() )
806 return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
807 else
808 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
809}
810
811void QgsMeshLayer::fillNativeMesh()
812{
814
815 Q_ASSERT( !mNativeMesh );
816
817 mNativeMesh.reset( new QgsMesh() );
818
819 if ( !( dataProvider() && dataProvider()->isValid() ) )
820 return;
821
822 dataProvider()->populateMesh( mNativeMesh.get() );
823}
824
825void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
826{
828
829 // assign default style to new dataset groups
830 for ( int datasetGroupIndex : datasetGroupIndexes )
831 {
832 if ( !mRendererSettings.hasSettings( datasetGroupIndex ) )
833 assignDefaultStyleToDatasetGroup( datasetGroupIndex );
834 }
835
836 temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
837 emit rendererChanged();
838}
839
840void QgsMeshLayer::onMeshEdited()
841{
843
844 mRendererCache.reset( new QgsMeshLayerRendererCache() );
845 emit layerModified();
848}
849
851{
853
854 return mDatasetGroupStore->datasetGroupTreeItem();
855}
856
858{
860
861 mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
862 updateActiveDatasetGroups();
863}
864
865int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
866{
868
869 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
870 const QgsTriangularMesh *mesh = triangularMesh();
871 // search for the closest edge in search area from point
872 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
873 int selectedIndex = -1;
874 if ( mesh->contains( QgsMesh::Edge ) &&
875 mDataProvider->isValid() )
876 {
877 double sqrMaxDistFromPoint = pow( searchRadius, 2 );
878 for ( const int edgeIndex : edgeIndexes )
879 {
880 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
881 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
882 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
883 QgsPointXY projPoint;
884 const double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint, 0 );
885 if ( sqrDist < sqrMaxDistFromPoint )
886 {
887 selectedIndex = edgeIndex;
888 projectedPoint = projPoint;
889 sqrMaxDistFromPoint = sqrDist;
890 }
891 }
892 }
893
894 return selectedIndex;
895}
896
898{
900
901 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
902}
903
904void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
905{
907
908 if ( auto *lDataProvider = dataProvider() )
909 mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
910 else
911 mTemporalProperties->setReferenceTime( referenceTime, nullptr );
912}
913
920
921QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
922{
924
925 const QgsTriangularMesh *mesh = triangularMesh();
926 QgsPointXY exactPosition;
927 if ( !mesh )
928 return exactPosition;
929 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
930 double maxDistance = searchRadius;
931 //attempt to snap on edges's vertices
932 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
933 for ( const int edgeIndex : edgeIndexes )
934 {
935 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
936 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
937 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
938 const double dist1 = point.distance( vertex1 );
939 const double dist2 = point.distance( vertex2 );
940 if ( dist1 < maxDistance )
941 {
942 maxDistance = dist1;
943 exactPosition = vertex1;
944 }
945 if ( dist2 < maxDistance )
946 {
947 maxDistance = dist2;
948 exactPosition = vertex2;
949 }
950 }
951
952 //attempt to snap on face's vertices
953 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
954 for ( const int faceIndex : faceIndexes )
955 {
956 const QgsMeshFace &face = mesh->triangles().at( faceIndex );
957 for ( int i = 0; i < 3; ++i )
958 {
959 const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
960 const double dist = point.distance( vertex );
961 if ( dist < maxDistance )
962 {
963 maxDistance = dist;
964 exactPosition = vertex;
965 }
966 }
967 }
968
969 return exactPosition;
970}
971
972QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
973{
975
976 QgsPointXY projectedPoint;
977 closestEdge( point, searchRadius, projectedPoint );
978
979 return projectedPoint;
980}
981
982QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
983{
985
986 const QgsTriangularMesh *mesh = triangularMesh();
987 QgsPointXY centroidPosition;
988 if ( !mesh )
989 return centroidPosition;
990 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
991 double maxDistance = std::numeric_limits<double>::max();
992
993 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
994 for ( const int faceIndex : faceIndexes )
995 {
996 const int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
997 if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
998 continue;
999 const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
1000 const double dist = point.distance( centroid );
1001 if ( dist < maxDistance )
1002 {
1003 maxDistance = dist;
1004 centroidPosition = centroid;
1005 }
1006 }
1007
1008 return centroidPosition;
1009}
1010
1012{
1014
1015 mDatasetGroupStore->resetDatasetGroupTreeItem();
1016 updateActiveDatasetGroups();
1017}
1018
1020{
1022
1023 if ( !mDataProvider )
1024 return QgsInterval();
1025 const int groupCount = mDataProvider->datasetGroupCount();
1026 for ( int i = 0; i < groupCount; ++i )
1027 {
1028 const qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
1029 if ( timeStep > 0 )
1031 }
1032
1033 return QgsInterval();
1034}
1035
1037{
1039
1040 const qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
1041
1042 if ( time == INVALID_MESHLAYER_TIME )
1043 return QgsInterval();
1044 else
1046}
1047
1049{
1051
1052 return mDatasetGroupStore->datasetRelativeTime( index );
1053}
1054
1055static QString detailsErrorMessage( const QgsMeshEditingError &error )
1056{
1057 QString message;
1058
1059 switch ( error.errorType )
1060 {
1062 break;
1064 message = QObject::tr( "Face %1 invalid" ).arg( error.elementIndex );
1065 break;
1067 message = QObject::tr( "Too many vertices for face %1" ).arg( error.elementIndex );
1068 break;
1070 message = QObject::tr( "Face %1 is flat" ).arg( error.elementIndex );
1071 break;
1073 message = QObject::tr( "Vertex %1 is a unique shared vertex" ).arg( error.elementIndex );
1074 break;
1076 message = QObject::tr( "Vertex %1 is invalid" ).arg( error.elementIndex );
1077 break;
1079 message = QObject::tr( "Face %1 is manifold" ).arg( error.elementIndex );
1080 break;
1081 }
1082
1083 return message;
1084}
1085
1087{
1089
1091 return startFrameEditing( transform, error, false );
1092}
1093
1095{
1097
1098 if ( !supportsEditing() )
1099 {
1100 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" not support mesh editing" ).arg( name() ) );
1101 return false;
1102 }
1103
1104 if ( mMeshEditor )
1105 {
1106 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" already in editing mode" ).arg( name() ) );
1107 return false;
1108 }
1109
1110 mSimplificationSettings.setEnabled( false );
1111
1112 updateTriangularMesh( transform );
1113
1114 mMeshEditor = new QgsMeshEditor( this );
1115
1116 if ( fixErrors )
1117 {
1118 mRendererCache.reset(); // fixing errors could lead to remove faces/vertices
1119 error = mMeshEditor->initializeWithErrorsFix();
1120 }
1121 else
1122 error = mMeshEditor->initialize();
1123
1124 if ( error.errorType != Qgis::MeshEditingErrorType::NoError )
1125 {
1126 mMeshEditor->deleteLater();
1127 mMeshEditor = nullptr;
1128
1129 QgsMessageLog::logMessage( QObject::tr( "Unable to start editing of mesh layer \"%1\": %2" ).
1130 arg( name(), detailsErrorMessage( error ) ), QString(), Qgis::MessageLevel::Critical );
1131 return false;
1132 }
1133
1134 // During editing, we don't need anymore the provider data. Mesh frame data is stored in the mesh editor.
1135 mDataProvider->close();
1136
1137 // All dataset group are removed and replace by a unique virtual dataset group that provide vertices elevation value.
1138 mExtraDatasetUri.clear();
1139 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1140
1141 std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup( mMeshEditor->createZValueDatasetGroup() );
1142 if ( mDatasetGroupStore->addDatasetGroup( zValueDatasetGroup.get() ) )
1143 zValueDatasetGroup.release();
1144
1146
1147 connect( mMeshEditor, &QgsMeshEditor::meshEdited, this, &QgsMeshLayer::onMeshEdited );
1148
1149 emit dataChanged();
1150 emit editingStarted();
1151
1152 return true;
1153}
1154
1155bool QgsMeshLayer::commitFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1156{
1158
1160 QString detailsError;
1161 if ( !mMeshEditor->checkConsistency( error ) )
1162 {
1163 if ( error.errorType == Qgis::MeshEditingErrorType::NoError )
1164 detailsError = tr( "Unknown inconsistent mesh error" );
1165 }
1166 else
1167 {
1168 error = QgsTopologicalMesh::checkTopology( *mNativeMesh, mMeshEditor->maximumVerticesPerFace() );
1169 detailsError = detailsErrorMessage( error );
1170 }
1171
1172 if ( !detailsError.isEmpty() )
1173 {
1174 QgsMessageLog::logMessage( QObject::tr( "Edited mesh layer \"%1\" can't be save due to an error: %2" ).
1175 arg( name(), detailsError ), QString(), Qgis::MessageLevel::Critical );
1176 return false;
1177 }
1178
1179 stopFrameEditing( transform );
1180
1181 if ( !mDataProvider )
1182 return false;
1183
1184 const bool res = mDataProvider->saveMeshFrame( *mNativeMesh.get() );
1185
1186 if ( continueEditing )
1187 {
1188 mMeshEditor->initialize();
1189 emit layerModified();
1190 return res;
1191 }
1192
1193 mMeshEditor->deleteLater();
1194 mMeshEditor = nullptr;
1195 emit editingStopped();
1196
1197 mDataProvider->reloadData();
1198 mDataProvider->populateMesh( mNativeMesh.get() );
1199 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1200 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1202 return true;
1203}
1204
1205bool QgsMeshLayer::rollBackFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1206{
1208
1209 stopFrameEditing( transform );
1210
1211 if ( !mDataProvider )
1212 return false;
1213
1214 mTriangularMeshes.clear();
1215 mDataProvider->reloadData();
1216 mDataProvider->populateMesh( mNativeMesh.get() );
1217 updateTriangularMesh( transform );
1218 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1220
1221 if ( continueEditing )
1222 {
1223 mMeshEditor->resetTriangularMesh( triangularMesh() );
1224 return mMeshEditor->initialize() == QgsMeshEditingError();
1225 }
1226 else
1227 {
1228 mMeshEditor->deleteLater();
1229 mMeshEditor = nullptr;
1230 emit editingStopped();
1231
1232 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1233 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1235 emit dataChanged();
1236 return true;
1237 }
1238}
1239
1241{
1243
1244 if ( !mMeshEditor )
1245 return;
1246
1247 mMeshEditor->stopEditing();
1248 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1249 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1250}
1251
1252bool QgsMeshLayer::reindex( const QgsCoordinateTransform &transform, bool renumber )
1253{
1255
1256 if ( !mMeshEditor )
1257 return false;
1258
1259 if ( !mMeshEditor->reindex( renumber ) )
1260 return false;
1261
1262 mTriangularMeshes.clear();
1263 mTriangularMeshes.emplace_back( new QgsTriangularMesh );
1264 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1265 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1266 mMeshEditor->resetTriangularMesh( mTriangularMeshes.at( 0 ).get() );
1267
1268 return true;
1269}
1270
1272{
1274
1275 return mMeshEditor;
1276}
1277
1279{
1281
1282 if ( mMeshEditor )
1283 return mMeshEditor->isModified();
1284
1285 return false;
1286}
1287
1289{
1291
1292 switch ( type )
1293 {
1295 return meshVertexCount() != 0;
1297 return meshEdgeCount() != 0;
1299 return meshFaceCount() != 0;
1300 }
1301 return false;
1302}
1303
1305{
1307
1308 if ( mMeshEditor )
1309 return mMeshEditor->validVerticesCount();
1310 else if ( mDataProvider )
1311 return mDataProvider->vertexCount();
1312 else return 0;
1313}
1314
1316{
1318
1319 if ( mMeshEditor )
1320 return mMeshEditor->validFacesCount();
1321 else if ( mDataProvider )
1322 return mDataProvider->faceCount();
1323 else return 0;
1324}
1325
1327{
1329
1330 if ( mMeshEditor )
1331 return mNativeMesh->edgeCount();
1332 else if ( mDataProvider )
1333 return mDataProvider->edgeCount();
1334 else return 0;
1335}
1336
1337void QgsMeshLayer::updateActiveDatasetGroups()
1338{
1340
1341 QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
1342
1343 if ( !mDatasetGroupStore->datasetGroupTreeItem() )
1344 return;
1345
1347 const int oldActiveScalar = settings.activeScalarDatasetGroup();
1348 const int oldActiveVector = settings.activeVectorDatasetGroup();
1349
1350 QgsMeshDatasetGroupTreeItem *activeScalarItem =
1351 treeItem->childFromDatasetGroupIndex( oldActiveScalar );
1352
1353 if ( !activeScalarItem && treeItem->childCount() > 0 && oldActiveScalar != -1 )
1354 activeScalarItem = treeItem->child( 0 );
1355
1356 if ( activeScalarItem && !activeScalarItem->isEnabled() )
1357 {
1358 for ( int i = 0; i < treeItem->childCount(); ++i )
1359 {
1360 activeScalarItem = treeItem->child( i );
1361 if ( activeScalarItem->isEnabled() )
1362 break;
1363 else
1364 activeScalarItem = nullptr;
1365 }
1366 }
1367
1368 if ( activeScalarItem )
1369 settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
1370 else
1371 settings.setActiveScalarDatasetGroup( -1 );
1372
1373 QgsMeshDatasetGroupTreeItem *activeVectorItem =
1374 treeItem->childFromDatasetGroupIndex( oldActiveVector );
1375
1376 if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
1377 settings.setActiveVectorDatasetGroup( -1 );
1378
1379 setRendererSettings( settings );
1380
1381 if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
1383 if ( oldActiveVector != settings.activeVectorDatasetGroup() )
1385}
1386
1387QgsMeshRendererSettings QgsMeshLayer::accordSymbologyWithGroupName( const QgsMeshRendererSettings &settings, const QMap<QString, int> &nameToIndex )
1388{
1389 QString activeScalarName;
1390 QString activeVectorName;
1391 QgsMeshRendererSettings consistentSettings = settings;
1392 int activeScalar = consistentSettings.activeScalarDatasetGroup();
1393 int activeVector = consistentSettings.activeVectorDatasetGroup();
1394
1395 for ( auto it = nameToIndex.constBegin(); it != nameToIndex.constEnd(); ++it )
1396 {
1397 int index = it.value();
1398 const QString name = it.key() ;
1399 int globalIndex = mDatasetGroupStore->indexFromGroupName( name );
1400 if ( globalIndex >= 0 )
1401 {
1402 QgsMeshRendererScalarSettings scalarSettings = settings.scalarSettings( index );
1403 consistentSettings.setScalarSettings( globalIndex, scalarSettings );
1404 if ( settings.hasVectorSettings( it.value() ) && mDatasetGroupStore->datasetGroupMetadata( globalIndex ).isVector() )
1405 {
1406 QgsMeshRendererVectorSettings vectorSettings = settings.vectorSettings( index );
1407 consistentSettings.setVectorSettings( globalIndex, vectorSettings );
1408 }
1409 }
1410 else
1411 {
1412 consistentSettings.removeScalarSettings( index );
1413 if ( settings.hasVectorSettings( it.value() ) )
1414 consistentSettings.removeVectorSettings( index );
1415 }
1416
1417 if ( index == activeScalar )
1418 activeScalarName = name;
1419 if ( index == activeVector )
1420 activeVectorName = name;
1421 }
1422
1423 const QList<int> globalIndexes = datasetGroupsIndexes();
1424 for ( int globalIndex : globalIndexes )
1425 {
1426 const QString name = mDatasetGroupStore->groupName( globalIndex );
1427 if ( !nameToIndex.contains( name ) )
1428 {
1429 consistentSettings.setScalarSettings( globalIndex, mRendererSettings.scalarSettings( globalIndex ) );
1430 if ( mDatasetGroupStore->datasetGroupMetadata( globalIndex ).isVector() )
1431 {
1432 consistentSettings.setVectorSettings( globalIndex, mRendererSettings.vectorSettings( globalIndex ) );
1433 }
1434 }
1435 }
1436
1437 if ( !activeScalarName.isEmpty() )
1438 consistentSettings.setActiveScalarDatasetGroup( mDatasetGroupStore->indexFromGroupName( activeScalarName ) );
1439 if ( !activeVectorName.isEmpty() )
1440 consistentSettings.setActiveVectorDatasetGroup( mDatasetGroupStore->indexFromGroupName( activeVectorName ) );
1441
1442 return consistentSettings;
1443}
1444
1445void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1446{
1448
1449 mDataSource = dataSource;
1450 mLayerName = baseName;
1451 setProviderType( provider );
1452
1453 if ( !mDataSource.isEmpty() && !provider.isEmpty() )
1454 setDataProvider( provider, options, flags );
1455}
1456
1457QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
1458{
1460
1461 switch ( elementType )
1462 {
1463 case QgsMesh::Vertex:
1464 return snapOnVertex( point, searchRadius );
1465 case QgsMesh::Edge:
1466 return snapOnEdge( point, searchRadius );
1467 case QgsMesh::Face:
1468 return snapOnFace( point, searchRadius );
1469 }
1470 return QgsPointXY(); // avoid warnings
1471}
1472
1474{
1476
1477 if ( !mNativeMesh )
1478 {
1479 // lazy loading of mesh data
1480 fillNativeMesh();
1481 }
1482
1483 QList<int> ret;
1484
1485 if ( !mNativeMesh )
1486 return ret;
1487
1488 QgsExpressionContext context;
1489 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Vertex ) );
1490 context.appendScope( expScope.release() );
1491 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1492
1493 expression.prepare( &context );
1494
1495 for ( int i = 0; i < mNativeMesh->vertexCount(); ++i )
1496 {
1497 context.lastScope()->setVariable( QStringLiteral( "_mesh_vertex_index" ), i, false );
1498
1499 if ( expression.evaluate( &context ).toBool() )
1500 ret.append( i );
1501 }
1502
1503 return ret;
1504}
1505
1507{
1509
1510 if ( !mNativeMesh )
1511 {
1512 // lazy loading of mesh data
1513 fillNativeMesh();
1514 }
1515
1516 QList<int> ret;
1517
1518 if ( !mNativeMesh )
1519 return ret;
1520
1521 QgsExpressionContext context;
1522 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Face ) );
1523 context.appendScope( expScope.release() );
1524 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1525
1526 expression.prepare( &context );
1527
1528 for ( int i = 0; i < mNativeMesh->faceCount(); ++i )
1529 {
1530 context.lastScope()->setVariable( QStringLiteral( "_mesh_face_index" ), i, false );
1531
1532 if ( expression.evaluate( &context ).toBool() )
1533 ret.append( i );
1534 }
1535
1536 return ret;
1537}
1538
1540{
1542
1543 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
1544}
1545
1547{
1549
1550 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
1551
1552 mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
1554
1555 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
1557}
1558
1560{
1562
1563 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
1564
1565 mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
1567
1568 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
1570}
1571
1578
1580{
1582
1583 mSimplificationSettings = simplifySettings;
1584}
1585
1586static QgsColorRamp *_createDefaultColorRamp()
1587{
1588 QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
1589 if ( ramp )
1590 return ramp;
1591
1592 // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
1593 QVariantMap props;
1594 props["color1"] = "13,8,135,255";
1595 props["color2"] = "240,249,33,255";
1596 props["stops"] =
1597 "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:"
1598 "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:"
1599 "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:"
1600 "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:"
1601 "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:"
1602 "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:"
1603 "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:"
1604 "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:"
1605 "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:"
1606 "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";
1607 return QgsGradientColorRamp::create( props );
1608}
1609
1610void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1611{
1613
1615 const double groupMin = metadata.minimum();
1616 const double groupMax = metadata.maximum();
1617
1618 QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1619 fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1620
1621 QgsMeshRendererScalarSettings scalarSettings;
1622 scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1623 scalarSettings.setColorRampShader( fcn );
1624 QgsInterpolatedLineWidth edgeStrokeWidth;
1625 edgeStrokeWidth.setMinimumValue( groupMin );
1626 edgeStrokeWidth.setMaximumValue( groupMax );
1627 const QgsInterpolatedLineColor edgeStrokeColor( fcn );
1628 const QgsInterpolatedLineRenderer edgeStrokePen;
1629 scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1630 mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1631
1632 if ( metadata.isVector() )
1633 {
1634 QgsMeshRendererVectorSettings vectorSettings;
1635 vectorSettings.setColorRampShader( fcn );
1636 mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1637 }
1638}
1639
1641{
1643
1644 // Triangular mesh
1645 updateTriangularMesh( rendererContext.coordinateTransform() );
1646
1647 // Build overview triangular meshes if needed
1648 createSimplifiedMeshes();
1649
1650 // Cache
1651 if ( !mRendererCache )
1652 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1653
1654 return new QgsMeshLayerRenderer( this, rendererContext );
1655}
1656
1663
1664void QgsMeshLayer::checkSymbologyConsistency()
1665{
1667
1668 const QList<int> groupIndexes = mDatasetGroupStore->datasetGroupIndexes();
1669 if ( !groupIndexes.contains( mRendererSettings.activeScalarDatasetGroup() ) &&
1670 mRendererSettings.activeScalarDatasetGroup() != -1 )
1671 {
1672 if ( !groupIndexes.empty() )
1673 mRendererSettings.setActiveScalarDatasetGroup( groupIndexes.first() );
1674 else
1675 mRendererSettings.setActiveScalarDatasetGroup( -1 );
1676 }
1677
1678 if ( !groupIndexes.contains( mRendererSettings.activeVectorDatasetGroup() ) &&
1679 mRendererSettings.activeVectorDatasetGroup() != -1 )
1680 {
1681 mRendererSettings.setActiveVectorDatasetGroup( -1 );
1682 }
1683}
1684
1685bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1686 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1687{
1689
1690 Q_UNUSED( errorMessage )
1691 // TODO: implement categories for raster layer
1692
1693 const QDomElement elem = node.toElement();
1694
1695 readCommonStyle( elem, context, categories );
1696
1698 const QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1699 if ( !elemRendererSettings.isNull() )
1700 rendererSettings.readXml( elemRendererSettings, context );
1701
1702 QMap<QString, int> groupNameToGlobalIndex;
1703 QDomElement nameToIndexElem = elem.firstChildElement( "name-to-global-index" );
1704 while ( !nameToIndexElem.isNull() )
1705 {
1706 const QString name = nameToIndexElem.attribute( QStringLiteral( "name" ) );
1707 int globalIndex = nameToIndexElem.attribute( QStringLiteral( "global-index" ) ).toInt();
1708 groupNameToGlobalIndex.insert( name, globalIndex );
1709 nameToIndexElem = nameToIndexElem.nextSiblingElement( QStringLiteral( "name-to-global-index" ) );
1710 }
1711
1712 mRendererSettings = accordSymbologyWithGroupName( rendererSettings, groupNameToGlobalIndex );
1713
1714 checkSymbologyConsistency();
1715
1716 const QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1717 if ( !elemSimplifySettings.isNull() )
1718 mSimplificationSettings.readXml( elemSimplifySettings, context );
1719
1720 // get and set the blend mode if it exists
1721 const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1722 if ( !blendModeNode.isNull() )
1723 {
1724 const QDomElement e = blendModeNode.toElement();
1725 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
1726 }
1727
1728 // get and set the layer transparency
1729 if ( categories.testFlag( Rendering ) )
1730 {
1731 const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1732 if ( !layerOpacityNode.isNull() )
1733 {
1734 const QDomElement e = layerOpacityNode.toElement();
1735 setOpacity( e.text().toDouble() );
1736 }
1737 }
1738
1739 return true;
1740}
1741
1742bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1743 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1744{
1746
1747 Q_UNUSED( errorMessage )
1748 // TODO: implement categories for raster layer
1749
1750 QDomElement elem = node.toElement();
1751
1752 writeCommonStyle( elem, doc, context, categories );
1753
1754 const QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1755 elem.appendChild( elemRendererSettings );
1756
1757 const QList<int> groupIndexes = datasetGroupsIndexes();
1758 // we store the relation between name and indexes to be able to retrieve the consistency between name and symbology
1759 for ( int index : groupIndexes )
1760 {
1761 QDomElement elemNameToIndex = doc.createElement( QStringLiteral( "name-to-global-index" ) );
1762 elemNameToIndex.setAttribute( QStringLiteral( "name" ), mDatasetGroupStore->groupName( index ) );
1763 elemNameToIndex.setAttribute( QStringLiteral( "global-index" ), index );
1764 elem.appendChild( elemNameToIndex );
1765 }
1766
1767 const QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1768 elem.appendChild( elemSimplifySettings );
1769
1770 // add blend mode node
1771 QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1772 const QDomText blendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
1773 blendModeElement.appendChild( blendModeText );
1774 node.appendChild( blendModeElement );
1775
1776 // add the layer opacity
1777 if ( categories.testFlag( Rendering ) )
1778 {
1779 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1780 const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1781 layerOpacityElem.appendChild( layerOpacityText );
1782 node.appendChild( layerOpacityElem );
1783 }
1784
1785 return true;
1786}
1787
1788bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1789{
1791
1792 return writeSymbology( node, doc, errorMessage, context, categories );
1793}
1794
1795bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1796{
1798
1799 return readSymbology( node, errorMessage, context, categories );
1800}
1801
1802QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1803{
1805
1806 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
1807}
1808
1809QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1810{
1812
1814}
1815
1816bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1817{
1819
1820 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1821
1822 //process provider key
1823 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1824
1825 if ( pkeyNode.isNull() )
1826 {
1827 mProviderKey.clear();
1828 }
1829 else
1830 {
1831 const QDomElement pkeyElt = pkeyNode.toElement();
1832 mProviderKey = pkeyElt.text();
1833 }
1834
1836 {
1837 return false;
1838 }
1839
1840 const QgsDataProvider::ProviderOptions providerOptions;
1841 QgsDataProvider::ReadFlags flags = providerReadFlags( layer_node, mReadFlags );
1842
1843 const QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1844 if ( !elemExtraDatasets.isNull() )
1845 {
1846 QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1847 while ( !elemUri.isNull() )
1848 {
1849 const QString uri = context.pathResolver().readPath( elemUri.text() );
1850 mExtraDatasetUri.append( uri );
1851 elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1852 }
1853 }
1854
1855 if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1856 mTemporalUnit = static_cast<Qgis::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1857
1858 // read dataset group store
1859 const QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1860 if ( elemDatasetGroupsStore.isNull() )
1862 else
1863 mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1864
1865 setDataProvider( mProviderKey, providerOptions, flags );
1866
1867 QString errorMsg;
1868 readSymbology( layer_node, errorMsg, context );
1869
1870 if ( !mTemporalProperties->timeExtent().begin().isValid() || mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1872
1873 // read static dataset
1874 const QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1875 if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1876 {
1877 mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1878 }
1879 if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1880 {
1881 mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1882 }
1883
1884 return isValid(); // should be true if read successfully
1885}
1886
1887bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1888{
1890
1891 // first get the layer element so that we can append the type attribute
1892 QDomElement mapLayerNode = layer_node.toElement();
1893
1894 if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1895 {
1896 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1897 return false;
1898 }
1899
1900 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::Mesh ) );
1901
1902 // add provider node
1903 if ( mDataProvider )
1904 {
1905 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1906 const QDomText providerText = document.createTextNode( providerType() );
1907 provider.appendChild( providerText );
1908 layer_node.appendChild( provider );
1909 provider.setAttribute( QStringLiteral( "time-unit" ), static_cast< int >( mDataProvider->temporalCapabilities()->temporalUnit() ) );
1910
1911 const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1912 QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1913 for ( const QString &uri : extraDatasetUris )
1914 {
1915 const QString path = context.pathResolver().writePath( uri );
1916 QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1917 elemUri.appendChild( document.createTextNode( path ) );
1918 elemExtraDatasets.appendChild( elemUri );
1919 }
1920 layer_node.appendChild( elemExtraDatasets );
1921 }
1922
1923 QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1924 elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1925 elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1926 layer_node.appendChild( elemStaticDataset );
1927
1928 // write dataset group store if not in edting mode
1929 if ( !isEditable() )
1930 layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1931
1932 // renderer specific settings
1933 QString errorMsg;
1934 return writeSymbology( layer_node, document, errorMsg, context );
1935}
1936
1938{
1940
1941 if ( !mMeshEditor && mDataProvider && mDataProvider->isValid() )
1942 {
1943 mDataProvider->reloadData();
1944 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() ); //extra dataset are already loaded
1945
1946 //reload the mesh structure
1947 if ( !mNativeMesh )
1948 mNativeMesh.reset( new QgsMesh );
1949
1950 dataProvider()->populateMesh( mNativeMesh.get() );
1951
1952 if ( mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1953 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
1954
1955 //clear the TriangularMeshes
1956 mTriangularMeshes.clear();
1957
1958 //clear the rendererCache
1959 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1960
1961 checkSymbologyConsistency();
1962
1963 emit reloaded();
1964 }
1965}
1966
1967QStringList QgsMeshLayer::subLayers() const
1968{
1970
1971 if ( mDataProvider )
1972 return mDataProvider->subLayers();
1973 else
1974 return QStringList();
1975}
1976
1978{
1980
1981 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
1982 QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1983
1984 myMetadata += generalHtmlMetadata();
1985
1986 // Begin Provider section
1987 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1988 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1989
1990 // Extent
1991 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1992
1993 // feature count
1994 QLocale locale = QLocale();
1995 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1996
1997 if ( dataProvider() )
1998 {
1999 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
2000 + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
2001 + ( locale.toString( static_cast<qlonglong>( meshVertexCount() ) ) )
2002 + QStringLiteral( "</td></tr>\n" );
2003 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
2004 + tr( "Face count" ) + QStringLiteral( "</td><td>" )
2005 + ( locale.toString( static_cast<qlonglong>( meshFaceCount() ) ) )
2006 + QStringLiteral( "</td></tr>\n" );
2007 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
2008 + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
2009 + ( locale.toString( static_cast<qlonglong>( meshEdgeCount() ) ) )
2010 + QStringLiteral( "</td></tr>\n" );
2011 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
2012 + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
2013 + ( locale.toString( static_cast<qlonglong>( datasetGroupCount() ) ) )
2014 + QStringLiteral( "</td></tr>\n" );
2015 }
2016
2017 // End Provider section
2018 myMetadata += QLatin1String( "</table>\n<br><br>" );
2019
2020 // CRS
2021 myMetadata += crsHtmlMetadata();
2022
2023 // identification section
2024 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
2025 myMetadata += htmlFormatter.identificationSectionHtml( );
2026 myMetadata += QLatin1String( "<br><br>\n" );
2027
2028 // extent section
2029 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
2030 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
2031 myMetadata += QLatin1String( "<br><br>\n" );
2032
2033 // Start the Access section
2034 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
2035 myMetadata += htmlFormatter.accessSectionHtml( );
2036 myMetadata += QLatin1String( "<br><br>\n" );
2037
2038 // Start the contacts section
2039 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
2040 myMetadata += htmlFormatter.contactsSectionHtml( );
2041 myMetadata += QLatin1String( "<br><br>\n" );
2042
2043 // Start the links section
2044 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
2045 myMetadata += htmlFormatter.linksSectionHtml( );
2046 myMetadata += QLatin1String( "<br><br>\n" );
2047
2048 // Start the history section
2049 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
2050 myMetadata += htmlFormatter.historySectionHtml( );
2051 myMetadata += QLatin1String( "<br><br>\n" );
2052
2053 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
2054 return myMetadata;
2055}
2056
2058{
2060
2061 return mMeshEditor != nullptr;
2062}
2063
2064bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
2065{
2067
2068 mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
2069
2070 delete mDataProvider;
2071 mProviderKey = provider;
2072 const QString dataSource = mDataSource;
2073
2074 if ( mPreloadedProvider )
2075 {
2076 mDataProvider = qobject_cast< QgsMeshDataProvider * >( mPreloadedProvider.release() );
2077 }
2078 else
2079 {
2080 std::unique_ptr< QgsScopedRuntimeProfile > profile;
2081 if ( QgsApplication::profiler()->groupIsActive( QStringLiteral( "projectload" ) ) )
2082 profile = std::make_unique< QgsScopedRuntimeProfile >( tr( "Create %1 provider" ).arg( provider ), QStringLiteral( "projectload" ) );
2083
2084 mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
2085 }
2086
2087 if ( !mDataProvider )
2088 {
2089 QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
2090 return false;
2091 }
2092
2093 mDataProvider->setParent( this );
2094 QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
2095
2096 setValid( mDataProvider->isValid() );
2097 if ( !isValid() )
2098 {
2099 QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
2100 return false;
2101 }
2102
2103 if ( !mTemporalProperties->isValid() )
2104 {
2105 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( dataProvider()->temporalCapabilities() );
2106 }
2107
2108 mDataProvider->setTemporalUnit( mTemporalUnit );
2109
2110 mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
2111
2112 setCrs( mDataProvider->crs() );
2113
2114 if ( provider == QLatin1String( "mesh_memory" ) )
2115 {
2116 // required so that source differs between memory layers
2117 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
2118 }
2119
2120 // set default style if required by flags or if the dataset group does not has a style yet
2121 for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
2122 {
2123 int globalIndex = mDatasetGroupStore->globalDatasetGroupIndexInSource( mDataProvider, i );
2124 if ( globalIndex != -1 &&
2125 ( !mRendererSettings.hasSettings( globalIndex ) || ( flags & QgsDataProvider::FlagLoadDefaultStyle ) ) )
2126 assignDefaultStyleToDatasetGroup( globalIndex );
2127 }
2128
2129 emit rendererChanged();
2131
2132 connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
2133
2134 return true;
2135}
2136
2143
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ Critical
Critical/error message.
Definition qgis.h:102
@ 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.
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition qgis.h:3413
TemporalUnit
Temporal units.
Definition qgis.h:3603
@ Milliseconds
Milliseconds.
@ Mesh
Mesh layer. Added in QGIS 3.2.
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
Abstract base class for objects which generate elevation profiles.
static QgsRuntimeProfiler * profiler()
Returns the application runtime profiler.
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.
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.
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.
Class for metadata formatter.
Base class for storage of map layer elevation properties.
static QString typeToString(Qgis::LayerType 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:74
QString name
Definition qgsmaplayer.h:77
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.
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.
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:79
Qgis::LayerType type
Definition qgsmaplayer.h:81
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)
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
std::unique_ptr< QgsDataProvider > mPreloadedProvider
Optionally used when loading a project, it is released when the layer is effectively created.
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.
void emitStyleChanged()
Triggers an emission of the styleChanged() signal.
void dataChanged()
Data of layer changed.
virtual QgsMapLayer * clone() const =0
Returns a new instance equivalent to this one except for the id which is still unique.
QString mDataSource
Data source description string, varies by layer type.
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
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.
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition qgsmaplayer.h:83
@ Rendering
Rendering: scale visibility, simplify method, opacity.
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.
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
static QgsDataProvider::ReadFlags providerReadFlags(const QDomNode &layerNode, QgsMapLayer::ReadFlags layerReadFlags)
Returns provider read flag deduced from layer read flags layerReadFlags and a dom node layerNode that...
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.
QDateTime referenceTime() const
Returns the reference time.
Qgis::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
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.
void setTemporalUnit(Qgis::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
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.
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.
Qgis::MeshEditingErrorType errorType
Class that makes edit operation on a mesh.
QgsMeshEditingError initialize()
Initializes the mesh editor and returns first error if the internal native mesh has topological error...
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.
QgsMeshEditingError initializeWithErrorsFix()
Initializes the mesh editor.
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...
Mesh layer specific subclass of QgsMapLayerElevationProperties.
QgsMeshLayerElevationProperties * clone() const override
Creates a clone of the properties.
Implementation of QgsAbstractProfileGenerator for mesh layers.
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...
bool alwaysLoadReferenceTimeFromSource() const
Returns whether the time proporties are automatically reloaded from provider when project is opened o...
QgsDateTimeRange timeExtent() const
Returns the time extent.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
~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 editing 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.
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...
QgsMapLayerElevationProperties * elevationProperties() override
Returns the layer's elevation properties.
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 editing 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 editing of the mesh frame, Rebuilds the triangular mesh and its spatial index with transform,...
QgsAbstractProfileGenerator * createProfileGenerator(const QgsProfileRequest &request) override
Given a profile request, returns a new profile generator ready for generating elevation profiles.
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.
Q_DECL_DEPRECATED bool startFrameEditing(const QgsCoordinateTransform &transform)
Starts editing 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.
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.
QgsMesh3DDataBlock dataset3dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point) const
Returns the 3d values of stacked 3d mesh defined by the given point.
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...
void reloaded()
Emitted when the mesh layer is reloaded, see reload()
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 hasVectorSettings(int groupIndex) const
Returns whether groupIndex has existing vector settings.
QgsMesh3DAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
bool removeVectorSettings(int groupIndex)
Removes vector settings for groupIndex.
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.
QgsMeshRendererVectorSettings vectorSettings(int groupIndex) const
Returns renderer settings.
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.
bool removeScalarSettings(int groupIndex)
Removes scalar settings with groupIndex.
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 Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a Qgis::BlendMode corresponding to a QPainter::CompositionMode.
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a Qgis::BlendMode.
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 distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
Definition qgspointxy.h:211
double y
Definition qgspointxy.h:63
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const
Returns the minimum distance between this point and a segment.
double x
Definition qgspointxy.h:62
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
double x
Definition qgspoint.h:52
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition qgspoint.h:343
double y
Definition qgspoint.h:53
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
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.
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void setNull()
Mark a rectangle as being null (holding no spatial information).
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:145
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition qgsstyle.cpp:468
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
T begin() const
Returns the beginning of the range.
Definition qgsrange.h:394
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< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
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.
#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.
#define QGIS_PROTECT_QOBJECT_THREAD_ACCESS
Setting options for creating vector data providers.
Setting options for loading mesh layers.
QgsCoordinateTransformContext transformContext
Coordinate transform context.
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Mesh - vertices, edges and faces.
ElementType
Defines type of mesh elements.