QGIS API Documentation 3.29.0-Master (19d7edcfed)
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
49QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
50 const QString &baseName,
51 const QString &providerKey,
52 const QgsMeshLayer::LayerOptions &options )
53 : QgsMapLayer( QgsMapLayerType::MeshLayer, baseName, meshLayerPath )
54 , mDatasetGroupStore( new QgsMeshDatasetGroupStore( this ) )
55 , mTemporalProperties( new QgsMeshLayerTemporalProperties( this ) )
56 , mElevationProperties( new QgsMeshLayerElevationProperties( this ) )
57{
59
60 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
61 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
62 if ( options.loadDefaultStyle )
63 {
65 }
67 {
69 }
71 {
73 }
74 QgsMeshLayer::setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
77
78 if ( isValid() && options.loadDefaultStyle )
79 {
80 bool result = false;
81 loadDefaultStyle( result );
82 }
83
84 connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
85}
86
87void QgsMeshLayer::createSimplifiedMeshes()
88{
90
91 if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
92 {
93 const double reductionFactor = mSimplificationSettings.reductionFactor();
94
95 QVector<QgsTriangularMesh *> simplifyMeshes =
96 mTriangularMeshes[0]->simplifyMesh( reductionFactor );
97
98 for ( int i = 0; i < simplifyMeshes.count() ; ++i )
99 {
100 mTriangularMeshes.emplace_back( simplifyMeshes[i] );
101 }
102 }
103}
104
105bool QgsMeshLayer::hasSimplifiedMeshes() const
106{
108
109 //First mesh is the base mesh, so if size>1, there is no simplified meshes
110 return ( mTriangularMeshes.size() > 1 );
111}
112
114{
115 delete mDataProvider;
116}
117
119{
121
122 return mDataProvider;
123}
124
126{
128
129 return mDataProvider;
130}
131
133{
135
137 if ( mDataProvider )
138 {
139 options.transformContext = mDataProvider->transformContext();
140 }
141 QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
142 QgsMapLayer::clone( layer );
143
144 layer->mElevationProperties = mElevationProperties->clone();
145 layer->mElevationProperties->setParent( layer );
146
147 return layer;
148}
149
151{
153
154 if ( mMeshEditor )
155 return mMeshEditor->extent();
156
157 if ( mDataProvider )
158 return mDataProvider->extent();
159 else
160 {
161 QgsRectangle rec;
162 rec.setMinimal();
163 return rec;
164 }
165}
166
168{
170
171 return mProviderKey;
172}
173
175{
177
178 if ( !mDataProvider )
179 return false;
180
181 if ( mMeshEditor )
182 return true;
183
184 const QgsMeshDriverMetadata driverMetadata = mDataProvider->driverMetadata();
185
187}
188
189QString QgsMeshLayer::loadDefaultStyle( bool &resultFlag )
190{
192
193 const QList<int> groupsList = datasetGroupsIndexes();
194
195 for ( const int index : groupsList )
196 assignDefaultStyleToDatasetGroup( index );
197
198
199 QgsMeshRendererMeshSettings meshSettings;
200 if ( !groupsList.isEmpty() )
201 {
202 // Show data from the first dataset group
203 mRendererSettings.setActiveScalarDatasetGroup( 0 );
204 // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
206 if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
207 meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
208 meshSettings.setEnabled( true );
209 }
210 else
211 {
212 // show at least the mesh by default
213 meshSettings.setEnabled( true );
214 }
215
216 mRendererSettings.setNativeMeshSettings( meshSettings );
217
218 for ( const int i : groupsList )
219 {
220 assignDefaultStyleToDatasetGroup( i );
221
222 // Sets default resample method for scalar dataset
224 QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
225 switch ( meta.dataType() )
226 {
228 case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
230 break;
233 break;
235 break;
236 }
237
238 //override color ramp if the values in the dataset group are classified
239 applyClassificationOnScalarSettings( meta, scalarSettings );
240
241 mRendererSettings.setScalarSettings( i, scalarSettings );
242 }
243
244 if ( !groupsList.isEmpty() )
245 {
246 emit rendererChanged();
248 }
249
250 return QgsMapLayer::loadDefaultStyle( resultFlag );
251}
252
253bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
254{
256
257 const bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
258 if ( mDatasetGroupStore->addPersistentDatasets( path ) )
259 {
260 mExtraDatasetUri.append( path );
261 QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
262 if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
263 {
265 dataProvider()->temporalCapabilities() );
266
267 if ( ! temporalProperties->referenceTime().isValid() )
268 {
269 QDateTime referenceTime = defaultReferenceTime;
270 if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
271 referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
272 temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
273 }
274
275 mTemporalProperties->setIsActive( true );
276 }
277 emit dataSourceChanged();
278 return true;
279 }
280
281 return false;
282}
283
285{
287
288 if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
289 {
290 emit dataChanged();
291 return true;
292 }
293 return false;
294}
295
296bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
297{
299
300 return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
301}
302
304{
306
307 return mNativeMesh.get();
308}
309
311{
313
314 return mNativeMesh.get();
315}
316
317QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
318{
320
321 for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
322 {
323 if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
324 return lod.get();
325 }
326
327 if ( !mTriangularMeshes.empty() )
328 return mTriangularMeshes.back().get();
329 else
330 return nullptr;
331}
332
334{
336
337 return mTriangularMeshes.size();
338}
339
341{
343
344 if ( mTriangularMeshes.empty() )
345 return nullptr;
346 if ( lodIndex < 0 )
347 return mTriangularMeshes.front().get();
348
349 if ( lodIndex >= int( mTriangularMeshes.size() ) )
350 return mTriangularMeshes.back().get();
351
352 return mTriangularMeshes.at( lodIndex ).get();
353}
354
356{
358
359 // Native mesh
360 if ( !mNativeMesh )
361 {
362 // lazy loading of mesh data
363 fillNativeMesh();
364 }
365
366 // Triangular mesh
367 if ( mTriangularMeshes.empty() )
368 {
369 QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
370 mTriangularMeshes.emplace_back( baseMesh );
371 }
372
373 if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
374 mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
375
376 createSimplifiedMeshes();
377}
378
379QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
380{
382
383 return mRendererCache.get();
384}
385
387{
389
390 return mRendererSettings;
391}
392
394{
396
397 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
398 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
399 mRendererSettings = settings;
400
401 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
403
404 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
406
407 emit rendererChanged();
409}
410
412{
414
415 return mTimeSettings;
416}
417
419{
421
422 mTimeSettings = settings;
423 emit timeSettingsChanged();
424}
425
426QString QgsMeshLayer::formatTime( double hours )
427{
429
430 if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
431 return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
432 else
433 return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
434}
435
437{
439
440 return mDatasetGroupStore->datasetGroupCount();
441}
442
444{
446
447 return mDatasetGroupStore->extraDatasetGroupCount();
448}
449
451{
453
454 return mDatasetGroupStore->datasetGroupIndexes();
455}
456
458{
460
461 return mDatasetGroupStore->enabledDatasetGroupIndexes();
462}
463
465{
467
468 return mDatasetGroupStore->datasetGroupMetadata( index );
469}
470
472{
474
475 return mDatasetGroupStore->datasetCount( index.group() );
476}
477
479{
481
482 return mDatasetGroupStore->datasetMetadata( index );
483}
484
486{
488
489 return mDatasetGroupStore->datasetValue( index, valueIndex );
490}
491
492QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
493{
495
496 return mDatasetGroupStore->datasetValues( index, valueIndex, count );
497}
498
499QgsMesh3dDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
500{
502
503 return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
504}
505
506QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
507{
509
510 return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
511}
512
513bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
514{
516
517 return mDatasetGroupStore->isFaceActive( index, faceIndex );
518}
519
520QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
521{
523
525 const QgsTriangularMesh *mesh = triangularMesh();
526
527 if ( mesh && index.isValid() )
528 {
529 if ( contains( QgsMesh::ElementType::Edge ) )
530 {
531 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
532 return dataset1dValue( index, point, searchRadius );
533 }
534 const int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
535 if ( faceIndex >= 0 )
536 {
537 const int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
539 if ( isFaceActive( index, nativeFaceIndex ) )
540 {
541 switch ( dataType )
542 {
544 {
545 value = datasetValue( index, nativeFaceIndex );
546 }
547 break;
548
550 {
551 const QgsMeshFace &face = mesh->triangles()[faceIndex];
552 const int v1 = face[0], v2 = face[1], v3 = face[2];
553 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
554 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
555 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
556 const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
557 const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
558 double y = std::numeric_limits<double>::quiet_NaN();
559 const bool isVector = datasetGroupMetadata( index ).isVector();
560 if ( isVector )
561 y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
562
563 value = QgsMeshDatasetValue( x, y );
564 }
565 break;
566
568 {
569 const QgsMesh3dAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
570 if ( avgMethod )
571 {
572 const QgsMesh3dDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
573 const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
574 if ( block2d.isValid() )
575 {
576 value = block2d.value( 0 );
577 }
578 }
579 }
580 break;
581
582 default:
583 break;
584 }
585 }
586 }
587 }
588
589 return value;
590}
591
593{
595
596 QgsMesh3dDataBlock block3d;
597
598 const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
599
600 if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
601 {
604 {
605 const int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
606 if ( faceIndex >= 0 )
607 {
608 const int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
609 block3d = dataset3dValues( index, nativeFaceIndex, 1 );
610 }
611 }
612 }
613 return block3d;
614}
615
616QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
617{
619
621 QgsPointXY projectedPoint;
622 const int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
623 const QgsTriangularMesh *mesh = triangularMesh();
624 if ( selectedIndex >= 0 )
625 {
627 switch ( dataType )
628 {
630 {
631 value = datasetValue( index, selectedIndex );
632 }
633 break;
634
636 {
637 const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
638 const int v1 = edge.first, v2 = edge.second;
639 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
640 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
641 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
642 const double edgeLength = p1.distance( p2 );
643 const double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
644 value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
645 }
646 break;
647 default:
648 break;
649 }
650 }
651
652 return value;
653}
654
656{
658
659 if ( mDataProvider )
660 mDataProvider->setTransformContext( transformContext );
662}
663
664QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
665{
667
668 if ( ! mTemporalProperties->isActive() )
669 return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
670
671 const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
672 QDateTime utcTime = timeRange.begin();
673 if ( utcTime.timeSpec() != Qt::UTC )
674 utcTime.setTimeSpec( Qt::UTC );
675 const qint64 startTime = layerReferenceTime.msecsTo( utcTime );
676
677 return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
678}
679
680QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
681{
683
684 return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
685}
686
687QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
688{
690
691 qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
692 qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
693
694 //adjust relative time if layer reference time is different from provider reference time
695 if ( mTemporalProperties->referenceTime().isValid() &&
696 mDataProvider &&
697 mDataProvider->isValid() &&
698 mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
699 {
700 usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
701 usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
702 }
703
704 return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
705}
706
707void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
708{
710
711 if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
712 {
713 QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
714 QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
715 const QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
716
717 QString units;
718 if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
719 units = meta.extraOptions()[ QStringLiteral( "units" )];
720
721 QVector<QVector<double>> bounds;
722 for ( const QString &classe : classes )
723 {
724 const QStringList boundsStr = classe.split( ',' );
725 QVector<double> bound;
726 for ( const QString &boundStr : boundsStr )
727 bound.append( boundStr.toDouble() );
728 bounds.append( bound );
729 }
730
731 if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
732 ( bounds.count() > 1 ) ) // or at least two classes
733 {
734 const QVector<double> firstClass = bounds.first();
735 const QVector<double> lastClass = bounds.last();
736 const double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
737 const double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
738 const double diff = maxValue - minValue;
739 QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
740 for ( int i = 0; i < bounds.count(); ++i )
741 {
742 const QVector<double> &boundClass = bounds.at( i );
744 item.value = i + 1;
745 if ( !boundClass.isEmpty() )
746 {
747 const double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
748 item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
749 if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
750 {
751 item.label = QString( ( "%1 - %2 %3" ) ).
752 arg( QString::number( boundClass.first() ) ).
753 arg( QString::number( boundClass.last() ) ).
754 arg( units );
755 }
756 }
757 colorRampItemlist.append( item );
758 }
759 //treat first and last labels
760 if ( firstClass.count() == 1 )
761 colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
762 arg( QString::number( firstClass.first() ) ).
763 arg( units );
764 else
765 {
766 colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
767 arg( QString::number( firstClass.first() ) ).
768 arg( QString::number( firstClass.last() ) ).
769 arg( units );
770 }
771
772 if ( lastClass.count() == 1 )
773 colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
774 arg( QString::number( lastClass.first() ) ).
775 arg( units );
776 else
777 {
778 colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
779 arg( QString::number( lastClass.first() ) ).
780 arg( QString::number( lastClass.last() ) ).
781 arg( units );
782 }
783
784 colorRampShader.setMinimumValue( 0 );
785 colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
786 scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
787 colorRampShader.setColorRampItemList( colorRampItemlist );
790 }
791
792 scalarSettings.setColorRampShader( colorRampShader );
794 }
795}
796
797QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const
798{
800
801 if ( mTemporalProperties->isActive() )
802 return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
803 else
804 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
805}
806
807QgsMeshDatasetIndex QgsMeshLayer::activeVectorDatasetAtTime( const QgsDateTimeRange &timeRange ) const
808{
810
811 if ( mTemporalProperties->isActive() )
812 return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
813 else
814 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
815}
816
817void QgsMeshLayer::fillNativeMesh()
818{
820
821 Q_ASSERT( !mNativeMesh );
822
823 mNativeMesh.reset( new QgsMesh() );
824
825 if ( !( dataProvider() && dataProvider()->isValid() ) )
826 return;
827
828 dataProvider()->populateMesh( mNativeMesh.get() );
829}
830
831void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
832{
834
835 // assign default style to new dataset groups
836 for ( int datasetGroupIndex : datasetGroupIndexes )
837 {
838 if ( !mRendererSettings.hasSettings( datasetGroupIndex ) )
839 assignDefaultStyleToDatasetGroup( datasetGroupIndex );
840 }
841
842 temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
843 emit rendererChanged();
844}
845
846void QgsMeshLayer::onMeshEdited()
847{
849
850 mRendererCache.reset( new QgsMeshLayerRendererCache() );
851 emit layerModified();
854}
855
857{
859
860 return mDatasetGroupStore->datasetGroupTreeItem();
861}
862
864{
866
867 mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
868 updateActiveDatasetGroups();
869}
870
871int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
872{
874
875 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
876 const QgsTriangularMesh *mesh = triangularMesh();
877 // search for the closest edge in search area from point
878 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
879 int selectedIndex = -1;
880 if ( mesh->contains( QgsMesh::Edge ) &&
881 mDataProvider->isValid() )
882 {
883 double sqrMaxDistFromPoint = pow( searchRadius, 2 );
884 for ( const int edgeIndex : edgeIndexes )
885 {
886 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
887 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
888 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
889 QgsPointXY projPoint;
890 const double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint, 0 );
891 if ( sqrDist < sqrMaxDistFromPoint )
892 {
893 selectedIndex = edgeIndex;
894 projectedPoint = projPoint;
895 sqrMaxDistFromPoint = sqrDist;
896 }
897 }
898 }
899
900 return selectedIndex;
901}
902
904{
906
907 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
908}
909
910void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
911{
913
914 if ( auto *lDataProvider = dataProvider() )
915 mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
916 else
917 mTemporalProperties->setReferenceTime( referenceTime, nullptr );
918}
919
921{
923
924 mTemporalProperties->setMatchingMethod( matchingMethod );
925}
926
927QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
928{
930
931 const QgsTriangularMesh *mesh = triangularMesh();
932 QgsPointXY exactPosition;
933 if ( !mesh )
934 return exactPosition;
935 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
936 double maxDistance = searchRadius;
937 //attempt to snap on edges's vertices
938 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
939 for ( const int edgeIndex : edgeIndexes )
940 {
941 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
942 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
943 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
944 const double dist1 = point.distance( vertex1 );
945 const double dist2 = point.distance( vertex2 );
946 if ( dist1 < maxDistance )
947 {
948 maxDistance = dist1;
949 exactPosition = vertex1;
950 }
951 if ( dist2 < maxDistance )
952 {
953 maxDistance = dist2;
954 exactPosition = vertex2;
955 }
956 }
957
958 //attempt to snap on face's vertices
959 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
960 for ( const int faceIndex : faceIndexes )
961 {
962 const QgsMeshFace &face = mesh->triangles().at( faceIndex );
963 for ( int i = 0; i < 3; ++i )
964 {
965 const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
966 const double dist = point.distance( vertex );
967 if ( dist < maxDistance )
968 {
969 maxDistance = dist;
970 exactPosition = vertex;
971 }
972 }
973 }
974
975 return exactPosition;
976}
977
978QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
979{
981
982 QgsPointXY projectedPoint;
983 closestEdge( point, searchRadius, projectedPoint );
984
985 return projectedPoint;
986}
987
988QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
989{
991
992 const QgsTriangularMesh *mesh = triangularMesh();
993 QgsPointXY centroidPosition;
994 if ( !mesh )
995 return centroidPosition;
996 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
997 double maxDistance = std::numeric_limits<double>::max();
998
999 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
1000 for ( const int faceIndex : faceIndexes )
1001 {
1002 const int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
1003 if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
1004 continue;
1005 const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
1006 const double dist = point.distance( centroid );
1007 if ( dist < maxDistance )
1008 {
1009 maxDistance = dist;
1010 centroidPosition = centroid;
1011 }
1012 }
1013
1014 return centroidPosition;
1015}
1016
1018{
1020
1021 mDatasetGroupStore->resetDatasetGroupTreeItem();
1022 updateActiveDatasetGroups();
1023}
1024
1026{
1028
1029 if ( !mDataProvider )
1030 return QgsInterval();
1031 const int groupCount = mDataProvider->datasetGroupCount();
1032 for ( int i = 0; i < groupCount; ++i )
1033 {
1034 const qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
1035 if ( timeStep > 0 )
1037 }
1038
1039 return QgsInterval();
1040}
1041
1043{
1045
1046 const qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
1047
1048 if ( time == INVALID_MESHLAYER_TIME )
1049 return QgsInterval();
1050 else
1052}
1053
1055{
1057
1058 return mDatasetGroupStore->datasetRelativeTime( index );
1059}
1060
1061static QString detailsErrorMessage( const QgsMeshEditingError &error )
1062{
1063 QString message;
1064
1065 switch ( error.errorType )
1066 {
1068 break;
1070 message = QObject::tr( "Face %1 invalid" ).arg( error.elementIndex );
1071 break;
1073 message = QObject::tr( "Too many vertices for face %1" ).arg( error.elementIndex );
1074 break;
1076 message = QObject::tr( "Face %1 is flat" ).arg( error.elementIndex );
1077 break;
1079 message = QObject::tr( "Vertex %1 is a unique shared vertex" ).arg( error.elementIndex );
1080 break;
1082 message = QObject::tr( "Vertex %1 is invalid" ).arg( error.elementIndex );
1083 break;
1085 message = QObject::tr( "Face %1 is manifold" ).arg( error.elementIndex );
1086 break;
1087 }
1088
1089 return message;
1090}
1091
1093{
1095
1097 return startFrameEditing( transform, error, false );
1098}
1099
1101{
1103
1104 if ( !supportsEditing() )
1105 {
1106 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" not support mesh editing" ).arg( name() ) );
1107 return false;
1108 }
1109
1110 if ( mMeshEditor )
1111 {
1112 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" already in editing mode" ).arg( name() ) );
1113 return false;
1114 }
1115
1116 mSimplificationSettings.setEnabled( false );
1117
1118 updateTriangularMesh( transform );
1119
1120 mMeshEditor = new QgsMeshEditor( this );
1121
1122 if ( fixErrors )
1123 {
1124 mRendererCache.reset(); // fixing errors could lead to remove faces/vertices
1125 error = mMeshEditor->initializeWithErrorsFix();
1126 }
1127 else
1128 error = mMeshEditor->initialize();
1129
1130 if ( error.errorType != Qgis::MeshEditingErrorType::NoError )
1131 {
1132 mMeshEditor->deleteLater();
1133 mMeshEditor = nullptr;
1134
1135 QgsMessageLog::logMessage( QObject::tr( "Unable to start editing of mesh layer \"%1\": %2" ).
1136 arg( name(), detailsErrorMessage( error ) ), QString(), Qgis::MessageLevel::Critical );
1137 return false;
1138 }
1139
1140 // During editing, we don't need anymore the provider data. Mesh frame data is stored in the mesh editor.
1141 mDataProvider->close();
1142
1143 // All dataset group are removed and replace by a unique virtual dataset group that provide vertices elevation value.
1144 mExtraDatasetUri.clear();
1145 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1146
1147 std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup( mMeshEditor->createZValueDatasetGroup() );
1148 if ( mDatasetGroupStore->addDatasetGroup( zValueDatasetGroup.get() ) )
1149 zValueDatasetGroup.release();
1150
1152
1153 connect( mMeshEditor, &QgsMeshEditor::meshEdited, this, &QgsMeshLayer::onMeshEdited );
1154
1155 emit dataChanged();
1156 emit editingStarted();
1157
1158 return true;
1159}
1160
1161bool QgsMeshLayer::commitFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1162{
1164
1166 QString detailsError;
1167 if ( !mMeshEditor->checkConsistency( error ) )
1168 {
1169 if ( error.errorType == Qgis::MeshEditingErrorType::NoError )
1170 detailsError = tr( "Unknown inconsistent mesh error" );
1171 }
1172 else
1173 {
1174 error = QgsTopologicalMesh::checkTopology( *mNativeMesh, mMeshEditor->maximumVerticesPerFace() );
1175 detailsError = detailsErrorMessage( error );
1176 }
1177
1178 if ( !detailsError.isEmpty() )
1179 {
1180 QgsMessageLog::logMessage( QObject::tr( "Edited mesh layer \"%1\" can't be save due to an error: %2" ).
1181 arg( name(), detailsError ), QString(), Qgis::MessageLevel::Critical );
1182 return false;
1183 }
1184
1185 stopFrameEditing( transform );
1186
1187 if ( !mDataProvider )
1188 return false;
1189
1190 const bool res = mDataProvider->saveMeshFrame( *mNativeMesh.get() );
1191
1192 if ( continueEditing )
1193 {
1194 mMeshEditor->initialize();
1195 emit layerModified();
1196 return res;
1197 }
1198
1199 mMeshEditor->deleteLater();
1200 mMeshEditor = nullptr;
1201 emit editingStopped();
1202
1203 mDataProvider->reloadData();
1204 mDataProvider->populateMesh( mNativeMesh.get() );
1205 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1206 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1208 return true;
1209}
1210
1211bool QgsMeshLayer::rollBackFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1212{
1214
1215 stopFrameEditing( transform );
1216
1217 if ( !mDataProvider )
1218 return false;
1219
1220 mTriangularMeshes.clear();
1221 mDataProvider->reloadData();
1222 mDataProvider->populateMesh( mNativeMesh.get() );
1223 updateTriangularMesh( transform );
1224 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1226
1227 if ( continueEditing )
1228 {
1229 mMeshEditor->resetTriangularMesh( triangularMesh() );
1230 return mMeshEditor->initialize() == QgsMeshEditingError();
1231 }
1232 else
1233 {
1234 mMeshEditor->deleteLater();
1235 mMeshEditor = nullptr;
1236 emit editingStopped();
1237
1238 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1239 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1241 emit dataChanged();
1242 return true;
1243 }
1244}
1245
1247{
1249
1250 if ( !mMeshEditor )
1251 return;
1252
1253 mMeshEditor->stopEditing();
1254 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1255 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1256}
1257
1258bool QgsMeshLayer::reindex( const QgsCoordinateTransform &transform, bool renumber )
1259{
1261
1262 if ( !mMeshEditor )
1263 return false;
1264
1265 if ( !mMeshEditor->reindex( renumber ) )
1266 return false;
1267
1268 mTriangularMeshes.clear();
1269 mTriangularMeshes.emplace_back( new QgsTriangularMesh );
1270 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1271 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1272 mMeshEditor->resetTriangularMesh( mTriangularMeshes.at( 0 ).get() );
1273
1274 return true;
1275}
1276
1278{
1280
1281 return mMeshEditor;
1282}
1283
1285{
1287
1288 if ( mMeshEditor )
1289 return mMeshEditor->isModified();
1290
1291 return false;
1292}
1293
1295{
1297
1298 switch ( type )
1299 {
1300 case QgsMesh::ElementType::Vertex:
1301 return meshVertexCount() != 0;
1302 case QgsMesh::ElementType::Edge:
1303 return meshEdgeCount() != 0;
1304 case QgsMesh::ElementType::Face:
1305 return meshFaceCount() != 0;
1306 }
1307 return false;
1308}
1309
1311{
1313
1314 if ( mMeshEditor )
1315 return mMeshEditor->validVerticesCount();
1316 else if ( mDataProvider )
1317 return mDataProvider->vertexCount();
1318 else return 0;
1319}
1320
1322{
1324
1325 if ( mMeshEditor )
1326 return mMeshEditor->validFacesCount();
1327 else if ( mDataProvider )
1328 return mDataProvider->faceCount();
1329 else return 0;
1330}
1331
1333{
1335
1336 if ( mMeshEditor )
1337 return mNativeMesh->edgeCount();
1338 else if ( mDataProvider )
1339 return mDataProvider->edgeCount();
1340 else return 0;
1341}
1342
1343void QgsMeshLayer::updateActiveDatasetGroups()
1344{
1346
1347 QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
1348
1349 if ( !mDatasetGroupStore->datasetGroupTreeItem() )
1350 return;
1351
1353 const int oldActiveScalar = settings.activeScalarDatasetGroup();
1354 const int oldActiveVector = settings.activeVectorDatasetGroup();
1355
1356 QgsMeshDatasetGroupTreeItem *activeScalarItem =
1357 treeItem->childFromDatasetGroupIndex( oldActiveScalar );
1358
1359 if ( !activeScalarItem && treeItem->childCount() > 0 && oldActiveScalar != -1 )
1360 activeScalarItem = treeItem->child( 0 );
1361
1362 if ( activeScalarItem && !activeScalarItem->isEnabled() )
1363 {
1364 for ( int i = 0; i < treeItem->childCount(); ++i )
1365 {
1366 activeScalarItem = treeItem->child( i );
1367 if ( activeScalarItem->isEnabled() )
1368 break;
1369 else
1370 activeScalarItem = nullptr;
1371 }
1372 }
1373
1374 if ( activeScalarItem )
1375 settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
1376 else
1377 settings.setActiveScalarDatasetGroup( -1 );
1378
1379 QgsMeshDatasetGroupTreeItem *activeVectorItem =
1380 treeItem->childFromDatasetGroupIndex( oldActiveVector );
1381
1382 if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
1383 settings.setActiveVectorDatasetGroup( -1 );
1384
1385 setRendererSettings( settings );
1386
1387 if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
1389 if ( oldActiveVector != settings.activeVectorDatasetGroup() )
1391}
1392
1393void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1394{
1396
1397 mDataSource = dataSource;
1398 mLayerName = baseName;
1399 setProviderType( provider );
1400
1401 if ( !mDataSource.isEmpty() && !provider.isEmpty() )
1402 setDataProvider( provider, options, flags );
1403}
1404
1405QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
1406{
1408
1409 switch ( elementType )
1410 {
1411 case QgsMesh::Vertex:
1412 return snapOnVertex( point, searchRadius );
1413 case QgsMesh::Edge:
1414 return snapOnEdge( point, searchRadius );
1415 case QgsMesh::Face:
1416 return snapOnFace( point, searchRadius );
1417 }
1418 return QgsPointXY(); // avoid warnings
1419}
1420
1422{
1424
1425 if ( !mNativeMesh )
1426 {
1427 // lazy loading of mesh data
1428 fillNativeMesh();
1429 }
1430
1431 QList<int> ret;
1432
1433 if ( !mNativeMesh )
1434 return ret;
1435
1436 QgsExpressionContext context;
1437 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Vertex ) );
1438 context.appendScope( expScope.release() );
1439 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1440
1441 expression.prepare( &context );
1442
1443 for ( int i = 0; i < mNativeMesh->vertexCount(); ++i )
1444 {
1445 context.lastScope()->setVariable( QStringLiteral( "_mesh_vertex_index" ), i, false );
1446
1447 if ( expression.evaluate( &context ).toBool() )
1448 ret.append( i );
1449 }
1450
1451 return ret;
1452}
1453
1455{
1457
1458 if ( !mNativeMesh )
1459 {
1460 // lazy loading of mesh data
1461 fillNativeMesh();
1462 }
1463
1464 QList<int> ret;
1465
1466 if ( !mNativeMesh )
1467 return ret;
1468
1469 QgsExpressionContext context;
1470 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Face ) );
1471 context.appendScope( expScope.release() );
1472 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1473
1474 expression.prepare( &context );
1475
1476 for ( int i = 0; i < mNativeMesh->faceCount(); ++i )
1477 {
1478 context.lastScope()->setVariable( QStringLiteral( "_mesh_face_index" ), i, false );
1479
1480 if ( expression.evaluate( &context ).toBool() )
1481 ret.append( i );
1482 }
1483
1484 return ret;
1485}
1486
1488{
1490
1491 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
1492}
1493
1495{
1497
1498 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
1499
1500 mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
1502
1503 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
1505}
1506
1508{
1510
1511 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
1512
1513 mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
1515
1516 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
1518}
1519
1521{
1523
1524 return mSimplificationSettings;
1525}
1526
1528{
1530
1531 mSimplificationSettings = simplifySettings;
1532}
1533
1534static QgsColorRamp *_createDefaultColorRamp()
1535{
1536 QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
1537 if ( ramp )
1538 return ramp;
1539
1540 // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
1541 QVariantMap props;
1542 props["color1"] = "13,8,135,255";
1543 props["color2"] = "240,249,33,255";
1544 props["stops"] =
1545 "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:"
1546 "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:"
1547 "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:"
1548 "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:"
1549 "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:"
1550 "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:"
1551 "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:"
1552 "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:"
1553 "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:"
1554 "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";
1555 return QgsGradientColorRamp::create( props );
1556}
1557
1558void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1559{
1561
1563 const double groupMin = metadata.minimum();
1564 const double groupMax = metadata.maximum();
1565
1566 QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1567 fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1568
1569 QgsMeshRendererScalarSettings scalarSettings;
1570 scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1571 scalarSettings.setColorRampShader( fcn );
1572 QgsInterpolatedLineWidth edgeStrokeWidth;
1573 edgeStrokeWidth.setMinimumValue( groupMin );
1574 edgeStrokeWidth.setMaximumValue( groupMax );
1575 const QgsInterpolatedLineColor edgeStrokeColor( fcn );
1576 const QgsInterpolatedLineRenderer edgeStrokePen;
1577 scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1578 mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1579
1580 if ( metadata.isVector() )
1581 {
1582 QgsMeshRendererVectorSettings vectorSettings;
1583 vectorSettings.setColorRampShader( fcn );
1584 mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1585 }
1586}
1587
1589{
1591
1592 // Triangular mesh
1593 updateTriangularMesh( rendererContext.coordinateTransform() );
1594
1595 // Build overview triangular meshes if needed
1596 createSimplifiedMeshes();
1597
1598 // Cache
1599 if ( !mRendererCache )
1600 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1601
1602 return new QgsMeshLayerRenderer( this, rendererContext );
1603}
1604
1606{
1608
1609 return new QgsMeshLayerProfileGenerator( this, request );
1610}
1611
1612void QgsMeshLayer::checkSymbologyConsistency()
1613{
1615
1616 const QList<int> groupIndexes = mDatasetGroupStore->datasetGroupIndexes();
1617 if ( !groupIndexes.contains( mRendererSettings.activeScalarDatasetGroup() ) )
1618 {
1619 if ( !groupIndexes.empty() )
1620 mRendererSettings.setActiveScalarDatasetGroup( groupIndexes.first() );
1621 else
1622 mRendererSettings.setActiveScalarDatasetGroup( -1 );
1623 }
1624
1625 if ( !groupIndexes.contains( mRendererSettings.activeVectorDatasetGroup() ) )
1626 {
1627 mRendererSettings.setActiveVectorDatasetGroup( -1 );
1628 }
1629}
1630
1631bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1632 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1633{
1635
1636 Q_UNUSED( errorMessage )
1637 // TODO: implement categories for raster layer
1638
1639 const QDomElement elem = node.toElement();
1640
1641 readCommonStyle( elem, context, categories );
1642
1643 const QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1644 if ( !elemRendererSettings.isNull() )
1645 mRendererSettings.readXml( elemRendererSettings, context );
1646
1647 checkSymbologyConsistency();
1648
1649 const QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1650 if ( !elemSimplifySettings.isNull() )
1651 mSimplificationSettings.readXml( elemSimplifySettings, context );
1652
1653 // get and set the blend mode if it exists
1654 const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1655 if ( !blendModeNode.isNull() )
1656 {
1657 const QDomElement e = blendModeNode.toElement();
1658 setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1659 }
1660
1661 // get and set the layer transparency
1662 if ( categories.testFlag( Rendering ) )
1663 {
1664 const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1665 if ( !layerOpacityNode.isNull() )
1666 {
1667 const QDomElement e = layerOpacityNode.toElement();
1668 setOpacity( e.text().toDouble() );
1669 }
1670 }
1671
1672 return true;
1673}
1674
1675bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1676 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1677{
1679
1680 Q_UNUSED( errorMessage )
1681 // TODO: implement categories for raster layer
1682
1683 QDomElement elem = node.toElement();
1684
1685 writeCommonStyle( elem, doc, context, categories );
1686
1687 const QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1688 elem.appendChild( elemRendererSettings );
1689
1690 const QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1691 elem.appendChild( elemSimplifySettings );
1692
1693 // add blend mode node
1694 QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1695 const QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1696 blendModeElement.appendChild( blendModeText );
1697 node.appendChild( blendModeElement );
1698
1699 // add the layer opacity
1700 if ( categories.testFlag( Rendering ) )
1701 {
1702 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1703 const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1704 layerOpacityElem.appendChild( layerOpacityText );
1705 node.appendChild( layerOpacityElem );
1706 }
1707
1708 return true;
1709}
1710
1711bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1712{
1714
1715 return writeSymbology( node, doc, errorMessage, context, categories );
1716}
1717
1718bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1719{
1721
1722 return readSymbology( node, errorMessage, context, categories );
1723}
1724
1725QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1726{
1728
1729 QString src( source );
1730
1731 QVariantMap uriParts = QgsProviderRegistry::instance()->decodeUri( provider, source );
1732 if ( uriParts.contains( QStringLiteral( "path" ) ) )
1733 {
1734 QString filePath = uriParts.value( QStringLiteral( "path" ) ).toString();
1735 filePath = context.pathResolver().readPath( filePath );
1736 uriParts.insert( QStringLiteral( "path" ), filePath );
1737 src = QgsProviderRegistry::instance()->encodeUri( provider, uriParts );
1738 }
1739
1740 return src;
1741}
1742
1743QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1744{
1746
1747 QString src( source );
1748 QVariantMap uriParts = QgsProviderRegistry::instance()->decodeUri( mProviderKey, source );
1749 if ( uriParts.contains( QStringLiteral( "path" ) ) )
1750 {
1751 QString filePath = uriParts.value( QStringLiteral( "path" ) ).toString();
1752 filePath = context.pathResolver().writePath( filePath );
1753 uriParts.insert( QStringLiteral( "path" ), filePath );
1755 }
1756 return src;
1757}
1758
1759bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1760{
1762
1763 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1764
1765 //process provider key
1766 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1767
1768 if ( pkeyNode.isNull() )
1769 {
1770 mProviderKey.clear();
1771 }
1772 else
1773 {
1774 const QDomElement pkeyElt = pkeyNode.toElement();
1775 mProviderKey = pkeyElt.text();
1776 }
1777
1779 {
1780 return false;
1781 }
1782
1783 const QgsDataProvider::ProviderOptions providerOptions;
1784 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
1786 {
1788 }
1789
1790 const QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1791 if ( !elemExtraDatasets.isNull() )
1792 {
1793 QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1794 while ( !elemUri.isNull() )
1795 {
1796 const QString uri = context.pathResolver().readPath( elemUri.text() );
1797 mExtraDatasetUri.append( uri );
1798 elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1799 }
1800 }
1801
1802 if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1803 mTemporalUnit = static_cast<QgsUnitTypes::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1804
1805 // read dataset group store
1806 const QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1807 if ( elemDatasetGroupsStore.isNull() )
1809 else
1810 mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1811
1812 setDataProvider( mProviderKey, providerOptions, flags );
1813
1814 QString errorMsg;
1815 readSymbology( layer_node, errorMsg, context );
1816
1817 if ( !mTemporalProperties->timeExtent().begin().isValid() || mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1819
1820 // read static dataset
1821 const QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1822 if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1823 {
1824 mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1825 }
1826 if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1827 {
1828 mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1829 }
1830
1831 return isValid(); // should be true if read successfully
1832}
1833
1834bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1835{
1837
1838 // first get the layer element so that we can append the type attribute
1839 QDomElement mapLayerNode = layer_node.toElement();
1840
1841 if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1842 {
1843 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1844 return false;
1845 }
1846
1847 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::MeshLayer ) );
1848
1849 // add provider node
1850 if ( mDataProvider )
1851 {
1852 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1853 const QDomText providerText = document.createTextNode( providerType() );
1854 provider.appendChild( providerText );
1855 layer_node.appendChild( provider );
1856 provider.setAttribute( QStringLiteral( "time-unit" ), mDataProvider->temporalCapabilities()->temporalUnit() );
1857
1858 const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1859 QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1860 for ( const QString &uri : extraDatasetUris )
1861 {
1862 const QString path = context.pathResolver().writePath( uri );
1863 QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1864 elemUri.appendChild( document.createTextNode( path ) );
1865 elemExtraDatasets.appendChild( elemUri );
1866 }
1867 layer_node.appendChild( elemExtraDatasets );
1868 }
1869
1870 QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1871 elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1872 elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1873 layer_node.appendChild( elemStaticDataset );
1874
1875 // write dataset group store if not in edting mode
1876 if ( !isEditable() )
1877 layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1878
1879 // renderer specific settings
1880 QString errorMsg;
1881 return writeSymbology( layer_node, document, errorMsg, context );
1882}
1883
1885{
1887
1888 if ( !mMeshEditor && mDataProvider && mDataProvider->isValid() )
1889 {
1890 mDataProvider->reloadData();
1891 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() ); //extra dataset are already loaded
1892
1893 //reload the mesh structure
1894 if ( !mNativeMesh )
1895 mNativeMesh.reset( new QgsMesh );
1896
1897 dataProvider()->populateMesh( mNativeMesh.get() );
1898
1899 if ( mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1900 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
1901
1902 //clear the TriangularMeshes
1903 mTriangularMeshes.clear();
1904
1905 //clear the rendererCache
1906 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1907
1908 checkSymbologyConsistency();
1909
1910 emit reloaded();
1911 }
1912}
1913
1914QStringList QgsMeshLayer::subLayers() const
1915{
1917
1918 if ( mDataProvider )
1919 return mDataProvider->subLayers();
1920 else
1921 return QStringList();
1922}
1923
1925{
1927
1928 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
1929 QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1930
1931 myMetadata += generalHtmlMetadata();
1932
1933 // Begin Provider section
1934 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1935 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1936
1937 // Extent
1938 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1939
1940 // feature count
1941 QLocale locale = QLocale();
1942 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1943
1944 if ( dataProvider() )
1945 {
1946 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1947 + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
1948 + ( locale.toString( static_cast<qlonglong>( meshVertexCount() ) ) )
1949 + QStringLiteral( "</td></tr>\n" );
1950 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1951 + tr( "Face count" ) + QStringLiteral( "</td><td>" )
1952 + ( locale.toString( static_cast<qlonglong>( meshFaceCount() ) ) )
1953 + QStringLiteral( "</td></tr>\n" );
1954 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1955 + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
1956 + ( locale.toString( static_cast<qlonglong>( meshEdgeCount() ) ) )
1957 + QStringLiteral( "</td></tr>\n" );
1958 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1959 + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
1960 + ( locale.toString( static_cast<qlonglong>( datasetGroupCount() ) ) )
1961 + QStringLiteral( "</td></tr>\n" );
1962 }
1963
1964 // End Provider section
1965 myMetadata += QLatin1String( "</table>\n<br><br>" );
1966
1967 // CRS
1968 myMetadata += crsHtmlMetadata();
1969
1970 // identification section
1971 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
1972 myMetadata += htmlFormatter.identificationSectionHtml( );
1973 myMetadata += QLatin1String( "<br><br>\n" );
1974
1975 // extent section
1976 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
1977 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
1978 myMetadata += QLatin1String( "<br><br>\n" );
1979
1980 // Start the Access section
1981 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
1982 myMetadata += htmlFormatter.accessSectionHtml( );
1983 myMetadata += QLatin1String( "<br><br>\n" );
1984
1985 // Start the contacts section
1986 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
1987 myMetadata += htmlFormatter.contactsSectionHtml( );
1988 myMetadata += QLatin1String( "<br><br>\n" );
1989
1990 // Start the links section
1991 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
1992 myMetadata += htmlFormatter.linksSectionHtml( );
1993 myMetadata += QLatin1String( "<br><br>\n" );
1994
1995 // Start the history section
1996 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
1997 myMetadata += htmlFormatter.historySectionHtml( );
1998 myMetadata += QLatin1String( "<br><br>\n" );
1999
2000 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
2001 return myMetadata;
2002}
2003
2005{
2007
2008 return mMeshEditor != nullptr;
2009}
2010
2011bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
2012{
2014
2015 mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
2016
2017 delete mDataProvider;
2018 mProviderKey = provider;
2019 const QString dataSource = mDataSource;
2020
2021 mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
2022
2023 if ( !mDataProvider )
2024 {
2025 QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
2026 return false;
2027 }
2028
2029 mDataProvider->setParent( this );
2030 QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
2031
2032 setValid( mDataProvider->isValid() );
2033 if ( !isValid() )
2034 {
2035 QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
2036 return false;
2037 }
2038
2039 if ( !mTemporalProperties->isValid() )
2040 {
2041 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( dataProvider()->temporalCapabilities() );
2042 }
2043
2044 mDataProvider->setTemporalUnit( mTemporalUnit );
2045
2046 mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
2047
2048 setCrs( mDataProvider->crs() );
2049
2050 if ( provider == QLatin1String( "mesh_memory" ) )
2051 {
2052 // required so that source differs between memory layers
2053 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
2054 }
2055
2056 // set default style if required by flags or if the dataset group does not has a style yet
2057 for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
2058 {
2059 int globalIndex = mDatasetGroupStore->globalDatasetGroupIndexInSource( mDataProvider, i );
2060 if ( globalIndex != -1 &&
2061 ( !mRendererSettings.hasSettings( globalIndex ) || ( flags & QgsDataProvider::FlagLoadDefaultStyle ) ) )
2062 assignDefaultStyleToDatasetGroup( globalIndex );
2063 }
2064
2065 emit rendererChanged();
2067
2068 connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
2069
2070 return true;
2071}
2072
2074{
2076
2077 return mTemporalProperties;
2078}
2079
2081{
2083
2084 return mElevationProperties;
2085}
@ 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.
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.
A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
@ EqualInterval
Uses equal interval.
QgsColorRamp * sourceColorRamp() const
Returns the source color ramp.
@ Exact
Assigns the color of the exact matching value in the color ramp item list.
void setClassificationMode(ClassificationMode classificationMode)
Sets classification mode.
void setColorRampItemList(const QList< QgsColorRampShader::ColorRampItem > &list)
Sets a custom colormap.
void setColorRampType(QgsColorRampShader::Type colorRampType)
Sets the color ramp type.
Abstract base class for color ramps.
Definition: qgscolorramp.h:30
virtual QColor color(double value) const =0
Returns the color corresponding to a specified value.
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
bool hasTemporalCapabilities() const
Returns true if the provider has temporal capabilities available.
@ FlagLoadDefaultStyle
Reset the layer's style to the default for the datasource.
@ FlagTrustDataSource
Trust datasource config (primary key unicity, geometry type and srid, etc). Improves provider load ti...
@ ForceReadOnly
Open layer in a read-only mode (since QGIS 3.28)
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:43
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:243
Class for metadata formatter.
Base class for storage of map layer elevation properties.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
static QgsMapLayerLegend * defaultMeshLegend(QgsMeshLayer *ml)
Create new legend implementation for mesh layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
virtual void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities)=0
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
QString source() const
Returns the source for the layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void trigger3DUpdate()
Will advise any 3D maps that this layer requires to be updated in the scene.
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void editingStarted()
Emitted when editing on this layer has started.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1994
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:2032
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
void rendererChanged()
Signal emitted when renderer is changed.
virtual QgsError error() const
Gets current status error.
void dataSourceChanged()
Emitted whenever the layer's data source has been changed.
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.
bool isValid
Definition: qgsmaplayer.h:81
QString mDataSource
Data source description string, varies by layer type.
Definition: qgsmaplayer.h:1991
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:634
@ FlagForceReadOnly
Force open as read only.
Definition: qgsmaplayer.h:636
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:633
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:2037
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:171
void layerModified()
Emitted when modifications has been done on layer.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:2044
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Abstract class to interpolate 3d stacked mesh data to 2d data.
QgsMeshDataBlock calculate(const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
QgsMesh3dDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
bool isValid() const
Whether the block is valid.
QgsUnitTypes::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
QDateTime referenceTime() const
Returns the reference time.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 firstTimeStepDuration(int group) const
Returns the duration of the first time step of the dataset group with index group.
Base class for providing data for QgsMeshLayer.
virtual QgsMeshDriverMetadata driverMetadata() const
Returns the mesh driver metadata of the provider.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
void setTemporalUnit(QgsUnitTypes::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
virtual void close()=0
Closes the data provider and free every resources used.
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
virtual bool saveMeshFrame(const QgsMesh &mesh)=0
Saves the mesh frame to the source.
virtual int edgeCount() const =0
Returns number of edges in the native mesh.
virtual int faceCount() const =0
Returns number of faces in the native mesh.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
QMap< QString, QString > extraOptions() const
Returns extra metadata options, for example description.
bool isVector() const
Returns whether dataset group has vector data.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
double minimum() const
Returns minimum scalar value/vector magnitude present for whole dataset group.
double maximum() const
Returns maximum scalar value/vector magnitude present for whole dataset group.
DataType
Location of where data is specified for datasets in the dataset group.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
Class used to register and access all the dataset groups related to a mesh layer.
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
Tree item for display of the mesh dataset groups.
QgsMeshDatasetGroupTreeItem * childFromDatasetGroupIndex(int index)
Returns the child with dataset group index Searches as depper as needed on the child hierarchy.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a dataset group.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group()
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
virtual QStringList extraDatasets() const =0
Returns list of additional dataset file URIs added using addDataset() calls.
QgsMeshDatasetValue represents single dataset value.
double y() const
Returns y value.
double x() const
Returns x value.
Holds metadata about mesh driver.
@ CanWriteMeshData
If the driver can write mesh data on file.
MeshDriverCapabilities capabilities() const
Returns the capabilities for this driver.
Class that represents an error during mesh editing.
Definition: qgsmesheditor.h:43
Qgis::MeshEditingErrorType errorType
Definition: qgsmesheditor.h:52
Class that makes edit operation on a mesh.
Definition: qgsmesheditor.h:68
QgsMeshEditingError initialize()
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.
Definition: qgsmeshlayer.h:100
~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.
QgsMesh3dDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
QList< QgsMeshDatasetIndex > datasetIndexInRelativeTimeInterval(const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex) const
Returns a list of dataset indexes from datasets group that are in a interval time from the layer refe...
void activeScalarDatasetGroupChanged(int index)
Emitted when active scalar group dataset is changed.
int datasetGroupCount() const
Returns the dataset groups count handle by the layer.
void updateTriangularMesh(const QgsCoordinateTransform &transform=QgsCoordinateTransform())
Gets native mesh and updates (creates if it doesn't exist) the base triangular mesh.
bool addDatasets(const QString &path, const QDateTime &defaultReferenceTime=QDateTime())
Adds datasets to the mesh from file with path.
bool isModified() const override
Returns whether the mesh frame has been modified since the last save.
void activeVectorDatasetGroupChanged(int index)
Emitted when active vector group dataset is changed.
void reload() override
Synchronises with changes in the datasource.
QgsMeshDatasetIndex activeScalarDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active scalar group depending on the time range.
QgsPointXY snapOnElement(QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius)
Returns the position of the snapped point on the mesh element closest to point intersecting with the ...
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
QStringList subLayers() const override
Returns the sublayers of this layer.
QgsMeshEditor * meshEditor()
Returns a pointer to the mesh editor own by the mesh layer.
void setDatasetGroupTreeRootItem(QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root items of the dataset group tree item.
QgsMeshDatasetValue dataset1dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius) const
Returns the value of 1D mesh dataset defined on edge that are in the search area defined by point ans...
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QgsTriangularMesh * triangularMeshByLodIndex(int lodIndex) const
Returns triangular corresponding to the index of level of details.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
int meshFaceCount() const
Returns the faces count of the mesh frame.
QList< int > selectFacesByExpression(QgsExpression expression)
Returns a list of faces indexes that meet the condition defined by expression with the context expres...
QgsMesh3dDataBlock dataset3dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point) const
Returns the 3d values of stacked 3d mesh defined by the given point.
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.
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 hasSettings(int datasetGroupIndex) const
Returns whether the group with index has render settings (scalar or vector)
int activeScalarDatasetGroup() const
Returns the active scalar dataset group.
QgsMesh3dAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
void setActiveScalarDatasetGroup(int activeScalarDatasetGroup)
Sets the active scalar dataset group.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
void setVectorSettings(int groupIndex, const QgsMeshRendererVectorSettings &settings)
Sets new renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
void setScalarSettings(int groupIndex, const QgsMeshRendererScalarSettings &settings)
Sets new renderer settings.
void setNativeMeshSettings(const QgsMeshRendererMeshSettings &settings)
Sets new native mesh renderer settings, triggers repaint.
Represents a renderer settings for vector datasets.
void setColorRampShader(const QgsColorRampShader &colorRampShader)
Returns the color ramp shader used to render vector datasets.
Represents an overview renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
void setEnabled(bool isEnabled)
Sets if the overview is active.
double reductionFactor() const
Returns the reduction factor used to build simplified mesh.
bool isEnabled() const
Returns if the overview is active.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from the given DOM element.
Represents a mesh time settings for mesh datasets.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspointxy.h:211
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const SIP_HOLDGIL
Returns the minimum distance between this point and a segment.
Definition: qgspointxy.cpp:95
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:343
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
Contains information about the context of a rendering operation.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition: qgsstyle.cpp:462
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
static QgsMeshEditingError checkTopology(const QgsMesh &mesh, int maxVerticesPerFace)
Checks the topology of the mesh mesh, if error occurs, this mesh can't be edited.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
QList< int > edgeIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of edges intersecting given bounding box It uses spatial indexing.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
const QVector< QgsMeshEdge > & edges() const
Returns edges.
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains mesh elements of given type.
const QVector< 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.
TemporalUnit
Temporal units.
Definition: qgsunittypes.h:150
@ TemporalMilliseconds
Milliseconds.
Definition: qgsunittypes.h:151
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
#define 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.
Definition: qgsmeshlayer.h:108
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Definition: qgsmeshlayer.h:121
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
Definition: qgsmeshlayer.h:127
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:142
Mesh - vertices, edges and faces.
ElementType
Defines type of mesh elements.