QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
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( Qgis::LayerType::Mesh, 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 }
66 QgsMeshLayer::setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
69
70 if ( isValid() && options.loadDefaultStyle )
71 {
72 bool result = false;
73 loadDefaultStyle( result );
74 }
75
76 connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
77}
78
79void QgsMeshLayer::createSimplifiedMeshes()
80{
82
83 if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
84 {
85 const double reductionFactor = mSimplificationSettings.reductionFactor();
86
87 QVector<QgsTriangularMesh *> simplifyMeshes =
88 mTriangularMeshes[0]->simplifyMesh( reductionFactor );
89
90 for ( int i = 0; i < simplifyMeshes.count() ; ++i )
91 {
92 mTriangularMeshes.emplace_back( simplifyMeshes[i] );
93 }
94 }
95}
96
97bool QgsMeshLayer::hasSimplifiedMeshes() const
98{
100
101 //First mesh is the base mesh, so if size>1, there is no simplified meshes
102 return ( mTriangularMeshes.size() > 1 );
103}
104
106{
107 delete mDataProvider;
108}
109
111{
113
114 return mDataProvider;
115}
116
118{
120
121 return mDataProvider;
122}
123
125{
127
129 if ( mDataProvider )
130 {
131 options.transformContext = mDataProvider->transformContext();
132 }
133 QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
134 QgsMapLayer::clone( layer );
135
136 layer->mElevationProperties = mElevationProperties->clone();
137 layer->mElevationProperties->setParent( layer );
138
139 return layer;
140}
141
143{
145
146 if ( mMeshEditor )
147 return mMeshEditor->extent();
148
149 if ( mDataProvider )
150 return mDataProvider->extent();
151 else
152 {
153 QgsRectangle rec;
154 rec.setMinimal();
155 return rec;
156 }
157}
158
160{
162
163 return mProviderKey;
164}
165
167{
169
170 if ( !mDataProvider )
171 return false;
172
173 if ( mMeshEditor )
174 return true;
175
176 const QgsMeshDriverMetadata driverMetadata = mDataProvider->driverMetadata();
177
179}
180
181QString QgsMeshLayer::loadDefaultStyle( bool &resultFlag )
182{
184
185 const QList<int> groupsList = datasetGroupsIndexes();
186
187 for ( const int index : groupsList )
188 assignDefaultStyleToDatasetGroup( index );
189
190
191 QgsMeshRendererMeshSettings meshSettings;
192 if ( !groupsList.isEmpty() )
193 {
194 // Show data from the first dataset group
195 mRendererSettings.setActiveScalarDatasetGroup( 0 );
196 // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
198 if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
199 meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
200 meshSettings.setEnabled( true );
201 }
202 else
203 {
204 // show at least the mesh by default
205 meshSettings.setEnabled( true );
206 }
207
208 mRendererSettings.setNativeMeshSettings( meshSettings );
209
210 for ( const int i : groupsList )
211 {
212 assignDefaultStyleToDatasetGroup( i );
213
214 // Sets default resample method for scalar dataset
216 QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
217 switch ( meta.dataType() )
218 {
220 case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
222 break;
225 break;
227 break;
228 }
229
230 //override color ramp if the values in the dataset group are classified
231 applyClassificationOnScalarSettings( meta, scalarSettings );
232
233 mRendererSettings.setScalarSettings( i, scalarSettings );
234 }
235
236 if ( !groupsList.isEmpty() )
237 {
238 emit rendererChanged();
240 }
241
242 return QgsMapLayer::loadDefaultStyle( resultFlag );
243}
244
245bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
246{
248
249 const bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
250 if ( mDatasetGroupStore->addPersistentDatasets( path ) )
251 {
252 mExtraDatasetUri.append( path );
253 QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
254 if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
255 {
257 dataProvider()->temporalCapabilities() );
258
259 if ( ! temporalProperties->referenceTime().isValid() )
260 {
261 QDateTime referenceTime = defaultReferenceTime;
262 if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
263 referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
264 temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
265 }
266
267 mTemporalProperties->setIsActive( true );
268 }
269 emit dataSourceChanged();
270 return true;
271 }
272
273 return false;
274}
275
277{
279
280 if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
281 {
282 emit dataChanged();
283 return true;
284 }
285 return false;
286}
287
288bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
289{
291
292 return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
293}
294
296{
298
299 return mNativeMesh.get();
300}
301
303{
305
306 return mNativeMesh.get();
307}
308
309QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
310{
312
313 for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
314 {
315 if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
316 return lod.get();
317 }
318
319 if ( !mTriangularMeshes.empty() )
320 return mTriangularMeshes.back().get();
321 else
322 return nullptr;
323}
324
326{
328
329 return mTriangularMeshes.size();
330}
331
333{
335
336 if ( mTriangularMeshes.empty() )
337 return nullptr;
338 if ( lodIndex < 0 )
339 return mTriangularMeshes.front().get();
340
341 if ( lodIndex >= int( mTriangularMeshes.size() ) )
342 return mTriangularMeshes.back().get();
343
344 return mTriangularMeshes.at( lodIndex ).get();
345}
346
348{
350
351 // Native mesh
352 if ( !mNativeMesh )
353 {
354 // lazy loading of mesh data
355 fillNativeMesh();
356 }
357
358 // Triangular mesh
359 if ( mTriangularMeshes.empty() )
360 {
361 QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
362 mTriangularMeshes.emplace_back( baseMesh );
363 }
364
365 if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
366 mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
367
368 createSimplifiedMeshes();
369}
370
371QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
372{
374
375 return mRendererCache.get();
376}
377
379{
381
382 return mRendererSettings;
383}
384
386{
388
389 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
390 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
391 mRendererSettings = settings;
392
393 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
395
396 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
398
399 emit rendererChanged();
401}
402
404{
406
407 return mTimeSettings;
408}
409
411{
413
414 mTimeSettings = settings;
415 emit timeSettingsChanged();
416}
417
418QString QgsMeshLayer::formatTime( double hours )
419{
421
422 if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
423 return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
424 else
425 return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
426}
427
429{
431
432 return mDatasetGroupStore->datasetGroupCount();
433}
434
436{
438
439 return mDatasetGroupStore->extraDatasetGroupCount();
440}
441
443{
445
446 return mDatasetGroupStore->datasetGroupIndexes();
447}
448
450{
452
453 return mDatasetGroupStore->enabledDatasetGroupIndexes();
454}
455
457{
459
460 return mDatasetGroupStore->datasetGroupMetadata( index );
461}
462
464{
466
467 return mDatasetGroupStore->datasetCount( index.group() );
468}
469
471{
473
474 return mDatasetGroupStore->datasetMetadata( index );
475}
476
478{
480
481 return mDatasetGroupStore->datasetValue( index, valueIndex );
482}
483
484QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
485{
487
488 return mDatasetGroupStore->datasetValues( index, valueIndex, count );
489}
490
491QgsMesh3dDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
492{
494
495 return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
496}
497
498QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
499{
501
502 return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
503}
504
505bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
506{
508
509 return mDatasetGroupStore->isFaceActive( index, faceIndex );
510}
511
512QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
513{
515
517 const QgsTriangularMesh *mesh = triangularMesh();
518
519 if ( mesh && index.isValid() )
520 {
521 if ( contains( QgsMesh::ElementType::Edge ) )
522 {
523 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
524 return dataset1dValue( index, point, searchRadius );
525 }
526 const int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
527 if ( faceIndex >= 0 )
528 {
529 const int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
531 if ( isFaceActive( index, nativeFaceIndex ) )
532 {
533 switch ( dataType )
534 {
536 {
537 value = datasetValue( index, nativeFaceIndex );
538 }
539 break;
540
542 {
543 const QgsMeshFace &face = mesh->triangles()[faceIndex];
544 const int v1 = face[0], v2 = face[1], v3 = face[2];
545 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
546 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
547 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
548 const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
549 const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
550 double y = std::numeric_limits<double>::quiet_NaN();
551 const bool isVector = datasetGroupMetadata( index ).isVector();
552 if ( isVector )
553 y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
554
555 value = QgsMeshDatasetValue( x, y );
556 }
557 break;
558
560 {
561 const QgsMesh3dAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
562 if ( avgMethod )
563 {
564 const QgsMesh3dDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
565 const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
566 if ( block2d.isValid() )
567 {
568 value = block2d.value( 0 );
569 }
570 }
571 }
572 break;
573
574 default:
575 break;
576 }
577 }
578 }
579 }
580
581 return value;
582}
583
585{
587
588 QgsMesh3dDataBlock block3d;
589
590 const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
591
592 if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
593 {
596 {
597 const int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
598 if ( faceIndex >= 0 )
599 {
600 const int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
601 block3d = dataset3dValues( index, nativeFaceIndex, 1 );
602 }
603 }
604 }
605 return block3d;
606}
607
608QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
609{
611
613 QgsPointXY projectedPoint;
614 const int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
615 const QgsTriangularMesh *mesh = triangularMesh();
616 if ( selectedIndex >= 0 )
617 {
619 switch ( dataType )
620 {
622 {
623 value = datasetValue( index, selectedIndex );
624 }
625 break;
626
628 {
629 const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
630 const int v1 = edge.first, v2 = edge.second;
631 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
632 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
633 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
634 const double edgeLength = p1.distance( p2 );
635 const double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
636 value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
637 }
638 break;
639 default:
640 break;
641 }
642 }
643
644 return value;
645}
646
648{
650
651 if ( mDataProvider )
652 mDataProvider->setTransformContext( transformContext );
654}
655
656QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
657{
659
660 if ( ! mTemporalProperties->isActive() )
661 return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
662
663 const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
664 QDateTime utcTime = timeRange.begin();
665 if ( utcTime.timeSpec() != Qt::UTC )
666 utcTime.setTimeSpec( Qt::UTC );
667 const qint64 startTime = layerReferenceTime.msecsTo( utcTime );
668
669 return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
670}
671
672QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
673{
675
676 return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
677}
678
679QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
680{
682
683 qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
684 qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
685
686 //adjust relative time if layer reference time is different from provider reference time
687 if ( mTemporalProperties->referenceTime().isValid() &&
688 mDataProvider &&
689 mDataProvider->isValid() &&
690 mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
691 {
692 usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
693 usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
694 }
695
696 return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
697}
698
699void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
700{
702
703 if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
704 {
705 QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
706 QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
707 const QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
708
709 QString units;
710 if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
711 units = meta.extraOptions()[ QStringLiteral( "units" )];
712
713 QVector<QVector<double>> bounds;
714 for ( const QString &classe : classes )
715 {
716 const QStringList boundsStr = classe.split( ',' );
717 QVector<double> bound;
718 for ( const QString &boundStr : boundsStr )
719 bound.append( boundStr.toDouble() );
720 bounds.append( bound );
721 }
722
723 if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
724 ( bounds.count() > 1 ) ) // or at least two classes
725 {
726 const QVector<double> firstClass = bounds.first();
727 const QVector<double> lastClass = bounds.last();
728 const double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
729 const double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
730 const double diff = maxValue - minValue;
731 QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
732 for ( int i = 0; i < bounds.count(); ++i )
733 {
734 const QVector<double> &boundClass = bounds.at( i );
736 item.value = i + 1;
737 if ( !boundClass.isEmpty() )
738 {
739 const double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
740 item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
741 if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
742 {
743 item.label = QString( ( "%1 - %2 %3" ) ).
744 arg( QString::number( boundClass.first() ) ).
745 arg( QString::number( boundClass.last() ) ).
746 arg( units );
747 }
748 }
749 colorRampItemlist.append( item );
750 }
751 //treat first and last labels
752 if ( firstClass.count() == 1 )
753 colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
754 arg( QString::number( firstClass.first() ) ).
755 arg( units );
756 else
757 {
758 colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
759 arg( QString::number( firstClass.first() ) ).
760 arg( QString::number( firstClass.last() ) ).
761 arg( units );
762 }
763
764 if ( lastClass.count() == 1 )
765 colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
766 arg( QString::number( lastClass.first() ) ).
767 arg( units );
768 else
769 {
770 colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
771 arg( QString::number( lastClass.first() ) ).
772 arg( QString::number( lastClass.last() ) ).
773 arg( units );
774 }
775
776 colorRampShader.setMinimumValue( 0 );
777 colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
778 scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
779 colorRampShader.setColorRampItemList( colorRampItemlist );
782 }
783
784 scalarSettings.setColorRampShader( colorRampShader );
786 }
787}
788
789QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const
790{
792
793 if ( mTemporalProperties->isActive() )
794 return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
795 else
796 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
797}
798
799QgsMeshDatasetIndex QgsMeshLayer::activeVectorDatasetAtTime( const QgsDateTimeRange &timeRange ) const
800{
802
803 if ( mTemporalProperties->isActive() )
804 return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
805 else
806 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
807}
808
809void QgsMeshLayer::fillNativeMesh()
810{
812
813 Q_ASSERT( !mNativeMesh );
814
815 mNativeMesh.reset( new QgsMesh() );
816
817 if ( !( dataProvider() && dataProvider()->isValid() ) )
818 return;
819
820 dataProvider()->populateMesh( mNativeMesh.get() );
821}
822
823void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
824{
826
827 // assign default style to new dataset groups
828 for ( int datasetGroupIndex : datasetGroupIndexes )
829 {
830 if ( !mRendererSettings.hasSettings( datasetGroupIndex ) )
831 assignDefaultStyleToDatasetGroup( datasetGroupIndex );
832 }
833
834 temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
835 emit rendererChanged();
836}
837
838void QgsMeshLayer::onMeshEdited()
839{
841
842 mRendererCache.reset( new QgsMeshLayerRendererCache() );
843 emit layerModified();
846}
847
849{
851
852 return mDatasetGroupStore->datasetGroupTreeItem();
853}
854
856{
858
859 mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
860 updateActiveDatasetGroups();
861}
862
863int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
864{
866
867 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
868 const QgsTriangularMesh *mesh = triangularMesh();
869 // search for the closest edge in search area from point
870 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
871 int selectedIndex = -1;
872 if ( mesh->contains( QgsMesh::Edge ) &&
873 mDataProvider->isValid() )
874 {
875 double sqrMaxDistFromPoint = pow( searchRadius, 2 );
876 for ( const int edgeIndex : edgeIndexes )
877 {
878 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
879 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
880 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
881 QgsPointXY projPoint;
882 const double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint, 0 );
883 if ( sqrDist < sqrMaxDistFromPoint )
884 {
885 selectedIndex = edgeIndex;
886 projectedPoint = projPoint;
887 sqrMaxDistFromPoint = sqrDist;
888 }
889 }
890 }
891
892 return selectedIndex;
893}
894
896{
898
899 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
900}
901
902void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
903{
905
906 if ( auto *lDataProvider = dataProvider() )
907 mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
908 else
909 mTemporalProperties->setReferenceTime( referenceTime, nullptr );
910}
911
913{
915
916 mTemporalProperties->setMatchingMethod( matchingMethod );
917}
918
919QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
920{
922
923 const QgsTriangularMesh *mesh = triangularMesh();
924 QgsPointXY exactPosition;
925 if ( !mesh )
926 return exactPosition;
927 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
928 double maxDistance = searchRadius;
929 //attempt to snap on edges's vertices
930 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
931 for ( const int edgeIndex : edgeIndexes )
932 {
933 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
934 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
935 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
936 const double dist1 = point.distance( vertex1 );
937 const double dist2 = point.distance( vertex2 );
938 if ( dist1 < maxDistance )
939 {
940 maxDistance = dist1;
941 exactPosition = vertex1;
942 }
943 if ( dist2 < maxDistance )
944 {
945 maxDistance = dist2;
946 exactPosition = vertex2;
947 }
948 }
949
950 //attempt to snap on face's vertices
951 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
952 for ( const int faceIndex : faceIndexes )
953 {
954 const QgsMeshFace &face = mesh->triangles().at( faceIndex );
955 for ( int i = 0; i < 3; ++i )
956 {
957 const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
958 const double dist = point.distance( vertex );
959 if ( dist < maxDistance )
960 {
961 maxDistance = dist;
962 exactPosition = vertex;
963 }
964 }
965 }
966
967 return exactPosition;
968}
969
970QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
971{
973
974 QgsPointXY projectedPoint;
975 closestEdge( point, searchRadius, projectedPoint );
976
977 return projectedPoint;
978}
979
980QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
981{
983
984 const QgsTriangularMesh *mesh = triangularMesh();
985 QgsPointXY centroidPosition;
986 if ( !mesh )
987 return centroidPosition;
988 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
989 double maxDistance = std::numeric_limits<double>::max();
990
991 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
992 for ( const int faceIndex : faceIndexes )
993 {
994 const int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
995 if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
996 continue;
997 const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
998 const double dist = point.distance( centroid );
999 if ( dist < maxDistance )
1000 {
1001 maxDistance = dist;
1002 centroidPosition = centroid;
1003 }
1004 }
1005
1006 return centroidPosition;
1007}
1008
1010{
1012
1013 mDatasetGroupStore->resetDatasetGroupTreeItem();
1014 updateActiveDatasetGroups();
1015}
1016
1018{
1020
1021 if ( !mDataProvider )
1022 return QgsInterval();
1023 const int groupCount = mDataProvider->datasetGroupCount();
1024 for ( int i = 0; i < groupCount; ++i )
1025 {
1026 const qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
1027 if ( timeStep > 0 )
1028 return QgsInterval( timeStep, Qgis::TemporalUnit::Milliseconds );
1029 }
1030
1031 return QgsInterval();
1032}
1033
1035{
1037
1038 const qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
1039
1040 if ( time == INVALID_MESHLAYER_TIME )
1041 return QgsInterval();
1042 else
1043 return QgsInterval( time, Qgis::TemporalUnit::Milliseconds );
1044}
1045
1047{
1049
1050 return mDatasetGroupStore->datasetRelativeTime( index );
1051}
1052
1053static QString detailsErrorMessage( const QgsMeshEditingError &error )
1054{
1055 QString message;
1056
1057 switch ( error.errorType )
1058 {
1060 break;
1062 message = QObject::tr( "Face %1 invalid" ).arg( error.elementIndex );
1063 break;
1065 message = QObject::tr( "Too many vertices for face %1" ).arg( error.elementIndex );
1066 break;
1068 message = QObject::tr( "Face %1 is flat" ).arg( error.elementIndex );
1069 break;
1071 message = QObject::tr( "Vertex %1 is a unique shared vertex" ).arg( error.elementIndex );
1072 break;
1074 message = QObject::tr( "Vertex %1 is invalid" ).arg( error.elementIndex );
1075 break;
1077 message = QObject::tr( "Face %1 is manifold" ).arg( error.elementIndex );
1078 break;
1079 }
1080
1081 return message;
1082}
1083
1085{
1087
1089 return startFrameEditing( transform, error, false );
1090}
1091
1093{
1095
1096 if ( !supportsEditing() )
1097 {
1098 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" not support mesh editing" ).arg( name() ) );
1099 return false;
1100 }
1101
1102 if ( mMeshEditor )
1103 {
1104 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" already in editing mode" ).arg( name() ) );
1105 return false;
1106 }
1107
1108 mSimplificationSettings.setEnabled( false );
1109
1110 updateTriangularMesh( transform );
1111
1112 mMeshEditor = new QgsMeshEditor( this );
1113
1114 if ( fixErrors )
1115 {
1116 mRendererCache.reset(); // fixing errors could lead to remove faces/vertices
1117 error = mMeshEditor->initializeWithErrorsFix();
1118 }
1119 else
1120 error = mMeshEditor->initialize();
1121
1122 if ( error.errorType != Qgis::MeshEditingErrorType::NoError )
1123 {
1124 mMeshEditor->deleteLater();
1125 mMeshEditor = nullptr;
1126
1127 QgsMessageLog::logMessage( QObject::tr( "Unable to start editing of mesh layer \"%1\": %2" ).
1128 arg( name(), detailsErrorMessage( error ) ), QString(), Qgis::MessageLevel::Critical );
1129 return false;
1130 }
1131
1132 // During editing, we don't need anymore the provider data. Mesh frame data is stored in the mesh editor.
1133 mDataProvider->close();
1134
1135 // All dataset group are removed and replace by a unique virtual dataset group that provide vertices elevation value.
1136 mExtraDatasetUri.clear();
1137 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1138
1139 std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup( mMeshEditor->createZValueDatasetGroup() );
1140 if ( mDatasetGroupStore->addDatasetGroup( zValueDatasetGroup.get() ) )
1141 zValueDatasetGroup.release();
1142
1144
1145 connect( mMeshEditor, &QgsMeshEditor::meshEdited, this, &QgsMeshLayer::onMeshEdited );
1146
1147 emit dataChanged();
1148 emit editingStarted();
1149
1150 return true;
1151}
1152
1153bool QgsMeshLayer::commitFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1154{
1156
1158 QString detailsError;
1159 if ( !mMeshEditor->checkConsistency( error ) )
1160 {
1161 if ( error.errorType == Qgis::MeshEditingErrorType::NoError )
1162 detailsError = tr( "Unknown inconsistent mesh error" );
1163 }
1164 else
1165 {
1166 error = QgsTopologicalMesh::checkTopology( *mNativeMesh, mMeshEditor->maximumVerticesPerFace() );
1167 detailsError = detailsErrorMessage( error );
1168 }
1169
1170 if ( !detailsError.isEmpty() )
1171 {
1172 QgsMessageLog::logMessage( QObject::tr( "Edited mesh layer \"%1\" can't be save due to an error: %2" ).
1173 arg( name(), detailsError ), QString(), Qgis::MessageLevel::Critical );
1174 return false;
1175 }
1176
1177 stopFrameEditing( transform );
1178
1179 if ( !mDataProvider )
1180 return false;
1181
1182 const bool res = mDataProvider->saveMeshFrame( *mNativeMesh.get() );
1183
1184 if ( continueEditing )
1185 {
1186 mMeshEditor->initialize();
1187 emit layerModified();
1188 return res;
1189 }
1190
1191 mMeshEditor->deleteLater();
1192 mMeshEditor = nullptr;
1193 emit editingStopped();
1194
1195 mDataProvider->reloadData();
1196 mDataProvider->populateMesh( mNativeMesh.get() );
1197 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1198 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1200 return true;
1201}
1202
1203bool QgsMeshLayer::rollBackFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1204{
1206
1207 stopFrameEditing( transform );
1208
1209 if ( !mDataProvider )
1210 return false;
1211
1212 mTriangularMeshes.clear();
1213 mDataProvider->reloadData();
1214 mDataProvider->populateMesh( mNativeMesh.get() );
1215 updateTriangularMesh( transform );
1216 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1218
1219 if ( continueEditing )
1220 {
1221 mMeshEditor->resetTriangularMesh( triangularMesh() );
1222 return mMeshEditor->initialize() == QgsMeshEditingError();
1223 }
1224 else
1225 {
1226 mMeshEditor->deleteLater();
1227 mMeshEditor = nullptr;
1228 emit editingStopped();
1229
1230 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1231 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1233 emit dataChanged();
1234 return true;
1235 }
1236}
1237
1239{
1241
1242 if ( !mMeshEditor )
1243 return;
1244
1245 mMeshEditor->stopEditing();
1246 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1247 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1248}
1249
1250bool QgsMeshLayer::reindex( const QgsCoordinateTransform &transform, bool renumber )
1251{
1253
1254 if ( !mMeshEditor )
1255 return false;
1256
1257 if ( !mMeshEditor->reindex( renumber ) )
1258 return false;
1259
1260 mTriangularMeshes.clear();
1261 mTriangularMeshes.emplace_back( new QgsTriangularMesh );
1262 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1263 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1264 mMeshEditor->resetTriangularMesh( mTriangularMeshes.at( 0 ).get() );
1265
1266 return true;
1267}
1268
1270{
1272
1273 return mMeshEditor;
1274}
1275
1277{
1279
1280 if ( mMeshEditor )
1281 return mMeshEditor->isModified();
1282
1283 return false;
1284}
1285
1287{
1289
1290 switch ( type )
1291 {
1292 case QgsMesh::ElementType::Vertex:
1293 return meshVertexCount() != 0;
1294 case QgsMesh::ElementType::Edge:
1295 return meshEdgeCount() != 0;
1296 case QgsMesh::ElementType::Face:
1297 return meshFaceCount() != 0;
1298 }
1299 return false;
1300}
1301
1303{
1305
1306 if ( mMeshEditor )
1307 return mMeshEditor->validVerticesCount();
1308 else if ( mDataProvider )
1309 return mDataProvider->vertexCount();
1310 else return 0;
1311}
1312
1314{
1316
1317 if ( mMeshEditor )
1318 return mMeshEditor->validFacesCount();
1319 else if ( mDataProvider )
1320 return mDataProvider->faceCount();
1321 else return 0;
1322}
1323
1325{
1327
1328 if ( mMeshEditor )
1329 return mNativeMesh->edgeCount();
1330 else if ( mDataProvider )
1331 return mDataProvider->edgeCount();
1332 else return 0;
1333}
1334
1335void QgsMeshLayer::updateActiveDatasetGroups()
1336{
1338
1339 QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
1340
1341 if ( !mDatasetGroupStore->datasetGroupTreeItem() )
1342 return;
1343
1345 const int oldActiveScalar = settings.activeScalarDatasetGroup();
1346 const int oldActiveVector = settings.activeVectorDatasetGroup();
1347
1348 QgsMeshDatasetGroupTreeItem *activeScalarItem =
1349 treeItem->childFromDatasetGroupIndex( oldActiveScalar );
1350
1351 if ( !activeScalarItem && treeItem->childCount() > 0 && oldActiveScalar != -1 )
1352 activeScalarItem = treeItem->child( 0 );
1353
1354 if ( activeScalarItem && !activeScalarItem->isEnabled() )
1355 {
1356 for ( int i = 0; i < treeItem->childCount(); ++i )
1357 {
1358 activeScalarItem = treeItem->child( i );
1359 if ( activeScalarItem->isEnabled() )
1360 break;
1361 else
1362 activeScalarItem = nullptr;
1363 }
1364 }
1365
1366 if ( activeScalarItem )
1367 settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
1368 else
1369 settings.setActiveScalarDatasetGroup( -1 );
1370
1371 QgsMeshDatasetGroupTreeItem *activeVectorItem =
1372 treeItem->childFromDatasetGroupIndex( oldActiveVector );
1373
1374 if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
1375 settings.setActiveVectorDatasetGroup( -1 );
1376
1377 setRendererSettings( settings );
1378
1379 if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
1381 if ( oldActiveVector != settings.activeVectorDatasetGroup() )
1383}
1384
1385void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1386{
1388
1389 mDataSource = dataSource;
1390 mLayerName = baseName;
1391 setProviderType( provider );
1392
1393 if ( !mDataSource.isEmpty() && !provider.isEmpty() )
1394 setDataProvider( provider, options, flags );
1395}
1396
1397QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
1398{
1400
1401 switch ( elementType )
1402 {
1403 case QgsMesh::Vertex:
1404 return snapOnVertex( point, searchRadius );
1405 case QgsMesh::Edge:
1406 return snapOnEdge( point, searchRadius );
1407 case QgsMesh::Face:
1408 return snapOnFace( point, searchRadius );
1409 }
1410 return QgsPointXY(); // avoid warnings
1411}
1412
1414{
1416
1417 if ( !mNativeMesh )
1418 {
1419 // lazy loading of mesh data
1420 fillNativeMesh();
1421 }
1422
1423 QList<int> ret;
1424
1425 if ( !mNativeMesh )
1426 return ret;
1427
1428 QgsExpressionContext context;
1429 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Vertex ) );
1430 context.appendScope( expScope.release() );
1431 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1432
1433 expression.prepare( &context );
1434
1435 for ( int i = 0; i < mNativeMesh->vertexCount(); ++i )
1436 {
1437 context.lastScope()->setVariable( QStringLiteral( "_mesh_vertex_index" ), i, false );
1438
1439 if ( expression.evaluate( &context ).toBool() )
1440 ret.append( i );
1441 }
1442
1443 return ret;
1444}
1445
1447{
1449
1450 if ( !mNativeMesh )
1451 {
1452 // lazy loading of mesh data
1453 fillNativeMesh();
1454 }
1455
1456 QList<int> ret;
1457
1458 if ( !mNativeMesh )
1459 return ret;
1460
1461 QgsExpressionContext context;
1462 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Face ) );
1463 context.appendScope( expScope.release() );
1464 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1465
1466 expression.prepare( &context );
1467
1468 for ( int i = 0; i < mNativeMesh->faceCount(); ++i )
1469 {
1470 context.lastScope()->setVariable( QStringLiteral( "_mesh_face_index" ), i, false );
1471
1472 if ( expression.evaluate( &context ).toBool() )
1473 ret.append( i );
1474 }
1475
1476 return ret;
1477}
1478
1480{
1482
1483 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
1484}
1485
1487{
1489
1490 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
1491
1492 mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
1494
1495 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
1497}
1498
1500{
1502
1503 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
1504
1505 mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
1507
1508 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
1510}
1511
1513{
1515
1516 return mSimplificationSettings;
1517}
1518
1520{
1522
1523 mSimplificationSettings = simplifySettings;
1524}
1525
1526static QgsColorRamp *_createDefaultColorRamp()
1527{
1528 QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
1529 if ( ramp )
1530 return ramp;
1531
1532 // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
1533 QVariantMap props;
1534 props["color1"] = "13,8,135,255";
1535 props["color2"] = "240,249,33,255";
1536 props["stops"] =
1537 "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:"
1538 "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:"
1539 "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:"
1540 "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:"
1541 "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:"
1542 "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:"
1543 "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:"
1544 "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:"
1545 "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:"
1546 "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";
1547 return QgsGradientColorRamp::create( props );
1548}
1549
1550void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1551{
1553
1555 const double groupMin = metadata.minimum();
1556 const double groupMax = metadata.maximum();
1557
1558 QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1559 fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1560
1561 QgsMeshRendererScalarSettings scalarSettings;
1562 scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1563 scalarSettings.setColorRampShader( fcn );
1564 QgsInterpolatedLineWidth edgeStrokeWidth;
1565 edgeStrokeWidth.setMinimumValue( groupMin );
1566 edgeStrokeWidth.setMaximumValue( groupMax );
1567 const QgsInterpolatedLineColor edgeStrokeColor( fcn );
1568 const QgsInterpolatedLineRenderer edgeStrokePen;
1569 scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1570 mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1571
1572 if ( metadata.isVector() )
1573 {
1574 QgsMeshRendererVectorSettings vectorSettings;
1575 vectorSettings.setColorRampShader( fcn );
1576 mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1577 }
1578}
1579
1581{
1583
1584 // Triangular mesh
1585 updateTriangularMesh( rendererContext.coordinateTransform() );
1586
1587 // Build overview triangular meshes if needed
1588 createSimplifiedMeshes();
1589
1590 // Cache
1591 if ( !mRendererCache )
1592 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1593
1594 return new QgsMeshLayerRenderer( this, rendererContext );
1595}
1596
1598{
1600
1601 return new QgsMeshLayerProfileGenerator( this, request );
1602}
1603
1604void QgsMeshLayer::checkSymbologyConsistency()
1605{
1607
1608 const QList<int> groupIndexes = mDatasetGroupStore->datasetGroupIndexes();
1609 if ( !groupIndexes.contains( mRendererSettings.activeScalarDatasetGroup() ) )
1610 {
1611 if ( !groupIndexes.empty() )
1612 mRendererSettings.setActiveScalarDatasetGroup( groupIndexes.first() );
1613 else
1614 mRendererSettings.setActiveScalarDatasetGroup( -1 );
1615 }
1616
1617 if ( !groupIndexes.contains( mRendererSettings.activeVectorDatasetGroup() ) )
1618 {
1619 mRendererSettings.setActiveVectorDatasetGroup( -1 );
1620 }
1621}
1622
1623bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1624 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1625{
1627
1628 Q_UNUSED( errorMessage )
1629 // TODO: implement categories for raster layer
1630
1631 const QDomElement elem = node.toElement();
1632
1633 readCommonStyle( elem, context, categories );
1634
1635 const QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1636 if ( !elemRendererSettings.isNull() )
1637 mRendererSettings.readXml( elemRendererSettings, context );
1638
1639 checkSymbologyConsistency();
1640
1641 const QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1642 if ( !elemSimplifySettings.isNull() )
1643 mSimplificationSettings.readXml( elemSimplifySettings, context );
1644
1645 // get and set the blend mode if it exists
1646 const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1647 if ( !blendModeNode.isNull() )
1648 {
1649 const QDomElement e = blendModeNode.toElement();
1650 setBlendMode( QgsPainting::getCompositionMode( static_cast< Qgis::BlendMode >( e.text().toInt() ) ) );
1651 }
1652
1653 // get and set the layer transparency
1654 if ( categories.testFlag( Rendering ) )
1655 {
1656 const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1657 if ( !layerOpacityNode.isNull() )
1658 {
1659 const QDomElement e = layerOpacityNode.toElement();
1660 setOpacity( e.text().toDouble() );
1661 }
1662 }
1663
1664 return true;
1665}
1666
1667bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1668 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1669{
1671
1672 Q_UNUSED( errorMessage )
1673 // TODO: implement categories for raster layer
1674
1675 QDomElement elem = node.toElement();
1676
1677 writeCommonStyle( elem, doc, context, categories );
1678
1679 const QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1680 elem.appendChild( elemRendererSettings );
1681
1682 const QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1683 elem.appendChild( elemSimplifySettings );
1684
1685 // add blend mode node
1686 QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1687 const QDomText blendModeText = doc.createTextNode( QString::number( static_cast< int >( QgsPainting::getBlendModeEnum( blendMode() ) ) ) );
1688 blendModeElement.appendChild( blendModeText );
1689 node.appendChild( blendModeElement );
1690
1691 // add the layer opacity
1692 if ( categories.testFlag( Rendering ) )
1693 {
1694 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1695 const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1696 layerOpacityElem.appendChild( layerOpacityText );
1697 node.appendChild( layerOpacityElem );
1698 }
1699
1700 return true;
1701}
1702
1703bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1704{
1706
1707 return writeSymbology( node, doc, errorMessage, context, categories );
1708}
1709
1710bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1711{
1713
1714 return readSymbology( node, errorMessage, context, categories );
1715}
1716
1717QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1718{
1720
1721 return QgsProviderRegistry::instance()->relativeToAbsoluteUri( provider, source, context );
1722}
1723
1724QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1725{
1727
1729}
1730
1731bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1732{
1734
1735 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1736
1737 //process provider key
1738 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1739
1740 if ( pkeyNode.isNull() )
1741 {
1742 mProviderKey.clear();
1743 }
1744 else
1745 {
1746 const QDomElement pkeyElt = pkeyNode.toElement();
1747 mProviderKey = pkeyElt.text();
1748 }
1749
1751 {
1752 return false;
1753 }
1754
1755 const QgsDataProvider::ProviderOptions providerOptions;
1756 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
1758 {
1760 }
1762 {
1764 }
1765
1766 const QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1767 if ( !elemExtraDatasets.isNull() )
1768 {
1769 QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1770 while ( !elemUri.isNull() )
1771 {
1772 const QString uri = context.pathResolver().readPath( elemUri.text() );
1773 mExtraDatasetUri.append( uri );
1774 elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1775 }
1776 }
1777
1778 if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1779 mTemporalUnit = static_cast<Qgis::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1780
1781 // read dataset group store
1782 const QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1783 if ( elemDatasetGroupsStore.isNull() )
1785 else
1786 mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1787
1788 setDataProvider( mProviderKey, providerOptions, flags );
1789
1790 QString errorMsg;
1791 readSymbology( layer_node, errorMsg, context );
1792
1793 if ( !mTemporalProperties->timeExtent().begin().isValid() || mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1795
1796 // read static dataset
1797 const QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1798 if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1799 {
1800 mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1801 }
1802 if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1803 {
1804 mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1805 }
1806
1807 return isValid(); // should be true if read successfully
1808}
1809
1810bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1811{
1813
1814 // first get the layer element so that we can append the type attribute
1815 QDomElement mapLayerNode = layer_node.toElement();
1816
1817 if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1818 {
1819 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1820 return false;
1821 }
1822
1823 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( Qgis::LayerType::Mesh ) );
1824
1825 // add provider node
1826 if ( mDataProvider )
1827 {
1828 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1829 const QDomText providerText = document.createTextNode( providerType() );
1830 provider.appendChild( providerText );
1831 layer_node.appendChild( provider );
1832 provider.setAttribute( QStringLiteral( "time-unit" ), static_cast< int >( mDataProvider->temporalCapabilities()->temporalUnit() ) );
1833
1834 const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1835 QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1836 for ( const QString &uri : extraDatasetUris )
1837 {
1838 const QString path = context.pathResolver().writePath( uri );
1839 QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1840 elemUri.appendChild( document.createTextNode( path ) );
1841 elemExtraDatasets.appendChild( elemUri );
1842 }
1843 layer_node.appendChild( elemExtraDatasets );
1844 }
1845
1846 QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1847 elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1848 elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1849 layer_node.appendChild( elemStaticDataset );
1850
1851 // write dataset group store if not in edting mode
1852 if ( !isEditable() )
1853 layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1854
1855 // renderer specific settings
1856 QString errorMsg;
1857 return writeSymbology( layer_node, document, errorMsg, context );
1858}
1859
1861{
1863
1864 if ( !mMeshEditor && mDataProvider && mDataProvider->isValid() )
1865 {
1866 mDataProvider->reloadData();
1867 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() ); //extra dataset are already loaded
1868
1869 //reload the mesh structure
1870 if ( !mNativeMesh )
1871 mNativeMesh.reset( new QgsMesh );
1872
1873 dataProvider()->populateMesh( mNativeMesh.get() );
1874
1875 if ( mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1876 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
1877
1878 //clear the TriangularMeshes
1879 mTriangularMeshes.clear();
1880
1881 //clear the rendererCache
1882 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1883
1884 checkSymbologyConsistency();
1885
1886 emit reloaded();
1887 }
1888}
1889
1890QStringList QgsMeshLayer::subLayers() const
1891{
1893
1894 if ( mDataProvider )
1895 return mDataProvider->subLayers();
1896 else
1897 return QStringList();
1898}
1899
1901{
1903
1904 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
1905 QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1906
1907 myMetadata += generalHtmlMetadata();
1908
1909 // Begin Provider section
1910 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1911 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1912
1913 // Extent
1914 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1915
1916 // feature count
1917 QLocale locale = QLocale();
1918 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1919
1920 if ( dataProvider() )
1921 {
1922 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1923 + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
1924 + ( locale.toString( static_cast<qlonglong>( meshVertexCount() ) ) )
1925 + QStringLiteral( "</td></tr>\n" );
1926 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1927 + tr( "Face count" ) + QStringLiteral( "</td><td>" )
1928 + ( locale.toString( static_cast<qlonglong>( meshFaceCount() ) ) )
1929 + QStringLiteral( "</td></tr>\n" );
1930 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1931 + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
1932 + ( locale.toString( static_cast<qlonglong>( meshEdgeCount() ) ) )
1933 + QStringLiteral( "</td></tr>\n" );
1934 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1935 + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
1936 + ( locale.toString( static_cast<qlonglong>( datasetGroupCount() ) ) )
1937 + QStringLiteral( "</td></tr>\n" );
1938 }
1939
1940 // End Provider section
1941 myMetadata += QLatin1String( "</table>\n<br><br>" );
1942
1943 // CRS
1944 myMetadata += crsHtmlMetadata();
1945
1946 // identification section
1947 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
1948 myMetadata += htmlFormatter.identificationSectionHtml( );
1949 myMetadata += QLatin1String( "<br><br>\n" );
1950
1951 // extent section
1952 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
1953 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
1954 myMetadata += QLatin1String( "<br><br>\n" );
1955
1956 // Start the Access section
1957 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
1958 myMetadata += htmlFormatter.accessSectionHtml( );
1959 myMetadata += QLatin1String( "<br><br>\n" );
1960
1961 // Start the contacts section
1962 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
1963 myMetadata += htmlFormatter.contactsSectionHtml( );
1964 myMetadata += QLatin1String( "<br><br>\n" );
1965
1966 // Start the links section
1967 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
1968 myMetadata += htmlFormatter.linksSectionHtml( );
1969 myMetadata += QLatin1String( "<br><br>\n" );
1970
1971 // Start the history section
1972 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
1973 myMetadata += htmlFormatter.historySectionHtml( );
1974 myMetadata += QLatin1String( "<br><br>\n" );
1975
1976 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
1977 return myMetadata;
1978}
1979
1981{
1983
1984 return mMeshEditor != nullptr;
1985}
1986
1987bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1988{
1990
1991 mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
1992
1993 delete mDataProvider;
1994 mProviderKey = provider;
1995 const QString dataSource = mDataSource;
1996
1997 mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
1998
1999 if ( !mDataProvider )
2000 {
2001 QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
2002 return false;
2003 }
2004
2005 mDataProvider->setParent( this );
2006 QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
2007
2008 setValid( mDataProvider->isValid() );
2009 if ( !isValid() )
2010 {
2011 QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
2012 return false;
2013 }
2014
2015 if ( !mTemporalProperties->isValid() )
2016 {
2017 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( dataProvider()->temporalCapabilities() );
2018 }
2019
2020 mDataProvider->setTemporalUnit( mTemporalUnit );
2021
2022 mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
2023
2024 setCrs( mDataProvider->crs() );
2025
2026 if ( provider == QLatin1String( "mesh_memory" ) )
2027 {
2028 // required so that source differs between memory layers
2029 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
2030 }
2031
2032 // set default style if required by flags or if the dataset group does not has a style yet
2033 for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
2034 {
2035 int globalIndex = mDatasetGroupStore->globalDatasetGroupIndexInSource( mDataProvider, i );
2036 if ( globalIndex != -1 &&
2037 ( !mRendererSettings.hasSettings( globalIndex ) || ( flags & QgsDataProvider::FlagLoadDefaultStyle ) ) )
2038 assignDefaultStyleToDatasetGroup( globalIndex );
2039 }
2040
2041 emit rendererChanged();
2043
2044 connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
2045
2046 return true;
2047}
2048
2050{
2052
2053 return mTemporalProperties;
2054}
2055
2057{
2059
2060 return mElevationProperties;
2061}
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:55
@ TooManyVerticesInFace
A face has more vertices than the maximum number supported per face.
@ InvalidFace
An error occurs due to an invalid face (for example, vertex indexes are unordered)
@ UniqueSharedVertex
A least two faces share only one vertices.
@ ManifoldFace
ManifoldFace.
@ InvalidVertex
An error occurs due to an invalid vertex (for example, vertex index is out of range the available ver...
@ FlatFace
A flat face is present.
BlendMode
Blending modes defining the available composition modes that can be used when painting.
Definition: qgis.h:2978
TemporalUnit
Temporal units.
Definition: qgis.h:3152
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:42
double seconds() const
Returns the interval duration in seconds.
Definition: qgsinterval.h:242
Class for metadata formatter.
Base class for storage of map layer elevation properties.
static QString typeToString(Qgis::LayerType type)
Converts a map layer type to a string value.
static QgsMapLayerLegend * defaultMeshLegend(QgsMeshLayer *ml)
Create new legend implementation for mesh layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
virtual void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities)=0
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Base class for all map layer types.
Definition: qgsmaplayer.h: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.
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:2001
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
Qgis::LayerType type
Definition: qgsmaplayer.h:80
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:2039
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:1998
@ 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:2044
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:2051
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.
QDateTime referenceTime() const
Returns the reference time.
Qgis::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 firstTimeStepDuration(int group) const
Returns the duration of the first time step of the dataset group with index group.
Base class for providing data for QgsMeshLayer.
virtual QgsMeshDriverMetadata driverMetadata() const
Returns the mesh driver metadata of the provider.
void setTemporalUnit(Qgis::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
virtual void close()=0
Closes the data provider and free every resources used.
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
virtual bool saveMeshFrame(const QgsMesh &mesh)=0
Saves the mesh frame to the source.
virtual int edgeCount() const =0
Returns number of edges in the native mesh.
virtual int faceCount() const =0
Returns number of faces in the native mesh.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
QMap< QString, QString > extraOptions() const
Returns extra metadata options, for example description.
bool isVector() const
Returns whether dataset group has vector data.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
double minimum() const
Returns minimum scalar value/vector magnitude present for whole dataset group.
double maximum() const
Returns maximum scalar value/vector magnitude present for whole dataset group.
DataType
Location of where data is specified for datasets in the dataset group.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
Class used to register and access all the dataset groups related to a mesh layer.
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
Tree item for display of the mesh dataset groups.
QgsMeshDatasetGroupTreeItem * childFromDatasetGroupIndex(int index)
Returns the child with dataset group index Searches as depper as needed on the child hierarchy.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a dataset group.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group()
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
virtual QStringList extraDatasets() const =0
Returns list of additional dataset file URIs added using addDataset() calls.
QgsMeshDatasetValue represents single dataset value.
double y() const
Returns y value.
double x() const
Returns x value.
Holds metadata about mesh driver.
@ CanWriteMeshData
If the driver can write mesh data on file.
MeshDriverCapabilities capabilities() const
Returns the capabilities for this driver.
Class that represents an error during mesh editing.
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 Qgis::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(Qgis::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
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...
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
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:468
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.
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.