QGIS API Documentation 3.27.0-Master (c6eca784ad)
qgsmeshlayer.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshlayer.cpp
3 ----------------
4 begin : April 2018
5 copyright : (C) 2018 by Peter Petrik
6 email : zilolv at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include <cstddef>
19#include <limits>
20
21#include <QUuid>
22#include <QUrl>
23
24#include "qgscolorrampimpl.h"
25#include "qgslogger.h"
26#include "qgsmaplayerlegend.h"
27#include "qgsmaplayerfactory.h"
28#include "qgsmaplayerutils.h"
29#include "qgsmeshdataprovider.h"
31#include "qgsmeshlayer.h"
34#include "qgsmeshlayerutils.h"
35#include "qgsmeshtimesettings.h"
36#include "qgspainting.h"
37#include "qgsproviderregistry.h"
38#include "qgsreadwritecontext.h"
39#include "qgsstyle.h"
40#include "qgstriangularmesh.h"
41#include "qgsmesh3daveraging.h"
43#include "qgsmesheditor.h"
44#include "qgsmessagelog.h"
48
49QgsMeshLayer::QgsMeshLayer( const QString &meshLayerPath,
50 const QString &baseName,
51 const QString &providerKey,
52 const QgsMeshLayer::LayerOptions &options )
53 : QgsMapLayer( QgsMapLayerType::MeshLayer, baseName, meshLayerPath )
54 , mDatasetGroupStore( new QgsMeshDatasetGroupStore( this ) )
55 , mTemporalProperties( new QgsMeshLayerTemporalProperties( this ) )
56 , mElevationProperties( new QgsMeshLayerElevationProperties( this ) )
57{
59
60 const QgsDataProvider::ProviderOptions providerOptions { options.transformContext };
61 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
62 if ( options.loadDefaultStyle )
63 {
65 }
67 {
69 }
71 {
73 }
74 setDataSourcePrivate( meshLayerPath, baseName, providerKey, providerOptions, flags );
77
78 if ( isValid() && options.loadDefaultStyle )
79 {
80 bool result = false;
81 loadDefaultStyle( result );
82 }
83
84 connect( mDatasetGroupStore.get(), &QgsMeshDatasetGroupStore::datasetGroupsAdded, this, &QgsMeshLayer::onDatasetGroupsAdded );
85}
86
87void QgsMeshLayer::createSimplifiedMeshes()
88{
89 if ( mSimplificationSettings.isEnabled() && !hasSimplifiedMeshes() )
90 {
91 const double reductionFactor = mSimplificationSettings.reductionFactor();
92
93 QVector<QgsTriangularMesh *> simplifyMeshes =
94 mTriangularMeshes[0]->simplifyMesh( reductionFactor );
95
96 for ( int i = 0; i < simplifyMeshes.count() ; ++i )
97 {
98 mTriangularMeshes.emplace_back( simplifyMeshes[i] );
99 }
100 }
101}
102
103bool QgsMeshLayer::hasSimplifiedMeshes() const
104{
105 //First mesh is the base mesh, so if size>1, there is no simplified meshes
106 return ( mTriangularMeshes.size() > 1 );
107}
108
110{
111 delete mDataProvider;
112}
113
115{
116 return mDataProvider;
117}
118
120{
121 return mDataProvider;
122}
123
125{
127 if ( mDataProvider )
128 {
129 options.transformContext = mDataProvider->transformContext();
130 }
131 QgsMeshLayer *layer = new QgsMeshLayer( source(), name(), mProviderKey, options );
132 QgsMapLayer::clone( layer );
133
134 layer->mElevationProperties = mElevationProperties->clone();
135 layer->mElevationProperties->setParent( layer );
136
137 return layer;
138}
139
141{
142 if ( mMeshEditor )
143 return mMeshEditor->extent();
144
145 if ( mDataProvider )
146 return mDataProvider->extent();
147 else
148 {
149 QgsRectangle rec;
150 rec.setMinimal();
151 return rec;
152 }
153}
154
156{
157 return mProviderKey;
158}
159
161{
162 if ( !mDataProvider )
163 return false;
164
165 if ( mMeshEditor )
166 return true;
167
168 const QgsMeshDriverMetadata driverMetadata = mDataProvider->driverMetadata();
169
171}
172
173QString QgsMeshLayer::loadDefaultStyle( bool &resultFlag )
174{
175 const QList<int> groupsList = datasetGroupsIndexes();
176
177 for ( const int index : groupsList )
178 assignDefaultStyleToDatasetGroup( index );
179
180
181 QgsMeshRendererMeshSettings meshSettings;
182 if ( !groupsList.isEmpty() )
183 {
184 // Show data from the first dataset group
185 mRendererSettings.setActiveScalarDatasetGroup( 0 );
186 // If the first dataset group has nan min/max, display the mesh to avoid nothing displayed
188 if ( meta.maximum() == std::numeric_limits<double>::quiet_NaN() &&
189 meta.minimum() == std::numeric_limits<double>::quiet_NaN() )
190 meshSettings.setEnabled( true );
191 }
192 else
193 {
194 // show at least the mesh by default
195 meshSettings.setEnabled( true );
196 }
197
198 mRendererSettings.setNativeMeshSettings( meshSettings );
199
200 for ( const int i : groupsList )
201 {
202 assignDefaultStyleToDatasetGroup( i );
203
204 // Sets default resample method for scalar dataset
206 QgsMeshRendererScalarSettings scalarSettings = mRendererSettings.scalarSettings( i );
207 switch ( meta.dataType() )
208 {
210 case QgsMeshDatasetGroupMetadata::DataOnVolumes: // data on volumes are averaged to 2D data on faces
212 break;
215 break;
217 break;
218 }
219
220 //override color ramp if the values in the dataset group are classified
221 applyClassificationOnScalarSettings( meta, scalarSettings );
222
223 mRendererSettings.setScalarSettings( i, scalarSettings );
224 }
225
226 if ( !groupsList.isEmpty() )
227 {
228 emit rendererChanged();
230 }
231
232 return QgsMapLayer::loadDefaultStyle( resultFlag );
233}
234
235bool QgsMeshLayer::addDatasets( const QString &path, const QDateTime &defaultReferenceTime )
236{
237 const bool isTemporalBefore = dataProvider()->temporalCapabilities()->hasTemporalCapabilities();
238 if ( mDatasetGroupStore->addPersistentDatasets( path ) )
239 {
240 mExtraDatasetUri.append( path );
241 QgsMeshLayerTemporalProperties *temporalProperties = qobject_cast< QgsMeshLayerTemporalProperties * >( mTemporalProperties );
242 if ( !isTemporalBefore && dataProvider()->temporalCapabilities()->hasTemporalCapabilities() )
243 {
245 dataProvider()->temporalCapabilities() );
246
247 if ( ! temporalProperties->referenceTime().isValid() )
248 {
249 QDateTime referenceTime = defaultReferenceTime;
250 if ( !defaultReferenceTime.isValid() ) // If project reference time is invalid, use current date
251 referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );
252 temporalProperties->setReferenceTime( referenceTime, dataProvider()->temporalCapabilities() );
253 }
254
255 mTemporalProperties->setIsActive( true );
256 }
257 emit dataSourceChanged();
258 return true;
259 }
260
261 return false;
262}
263
265{
266 if ( mDatasetGroupStore->addDatasetGroup( datasetGroup ) )
267 {
268 emit dataChanged();
269 return true;
270 }
271 return false;
272}
273
274bool QgsMeshLayer::saveDataset( const QString &path, int datasetGroupIndex, QString driver )
275{
276 return mDatasetGroupStore->saveDatasetGroup( path, datasetGroupIndex, driver );
277}
278
280{
281 return mNativeMesh.get();
282}
283
285{
286 return mNativeMesh.get();
287}
288
289QgsTriangularMesh *QgsMeshLayer::triangularMesh( double minimumTriangleSize ) const
290{
291 for ( const std::unique_ptr<QgsTriangularMesh> &lod : mTriangularMeshes )
292 {
293 if ( lod && lod->averageTriangleSize() > minimumTriangleSize )
294 return lod.get();
295 }
296
297 if ( !mTriangularMeshes.empty() )
298 return mTriangularMeshes.back().get();
299 else
300 return nullptr;
301}
302
304{
305 return mTriangularMeshes.size();
306}
307
309{
310 if ( mTriangularMeshes.empty() )
311 return nullptr;
312 if ( lodIndex < 0 )
313 return mTriangularMeshes.front().get();
314
315 if ( lodIndex >= int( mTriangularMeshes.size() ) )
316 return mTriangularMeshes.back().get();
317
318 return mTriangularMeshes.at( lodIndex ).get();
319}
320
322{
323 // Native mesh
324 if ( !mNativeMesh )
325 {
326 // lazy loading of mesh data
327 fillNativeMesh();
328 }
329
330 // Triangular mesh
331 if ( mTriangularMeshes.empty() )
332 {
333 QgsTriangularMesh *baseMesh = new QgsTriangularMesh;
334 mTriangularMeshes.emplace_back( baseMesh );
335 }
336
337 if ( mTriangularMeshes[0].get()->update( mNativeMesh.get(), transform ) )
338 mTriangularMeshes.resize( 1 ); //if the base triangular mesh is effectivly updated, remove simplified meshes
339
340 createSimplifiedMeshes();
341}
342
343QgsMeshLayerRendererCache *QgsMeshLayer::rendererCache()
344{
345 return mRendererCache.get();
346}
347
349{
350 return mRendererSettings;
351}
352
354{
355 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
356 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
357 mRendererSettings = settings;
358
359 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
361
362 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
364
365 emit rendererChanged();
367}
368
370{
371 return mTimeSettings;
372}
373
375{
376 mTimeSettings = settings;
377 emit timeSettingsChanged();
378}
379
380QString QgsMeshLayer::formatTime( double hours )
381{
382 if ( dataProvider() && dataProvider()->temporalCapabilities()->hasReferenceTime() )
383 return QgsMeshLayerUtils::formatTime( hours, mTemporalProperties->referenceTime(), mTimeSettings );
384 else
385 return QgsMeshLayerUtils::formatTime( hours, QDateTime(), mTimeSettings );
386}
387
389{
390 return mDatasetGroupStore->datasetGroupCount();
391}
392
394{
395 return mDatasetGroupStore->extraDatasetGroupCount();
396}
397
399{
400 return mDatasetGroupStore->datasetGroupIndexes();
401}
402
404{
405 return mDatasetGroupStore->enabledDatasetGroupIndexes();
406}
407
409{
410 return mDatasetGroupStore->datasetGroupMetadata( index );
411}
412
414{
415 return mDatasetGroupStore->datasetCount( index.group() );
416}
417
419{
420 return mDatasetGroupStore->datasetMetadata( index );
421}
422
424{
425 return mDatasetGroupStore->datasetValue( index, valueIndex );
426}
427
428QgsMeshDataBlock QgsMeshLayer::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
429{
430 return mDatasetGroupStore->datasetValues( index, valueIndex, count );
431}
432
433QgsMesh3dDataBlock QgsMeshLayer::dataset3dValues( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
434{
435 return mDatasetGroupStore->dataset3dValues( index, faceIndex, count );
436}
437
438QgsMeshDataBlock QgsMeshLayer::areFacesActive( const QgsMeshDatasetIndex &index, int faceIndex, int count ) const
439{
440 return mDatasetGroupStore->areFacesActive( index, faceIndex, count );
441}
442
443bool QgsMeshLayer::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
444{
445 return mDatasetGroupStore->isFaceActive( index, faceIndex );
446}
447
448QgsMeshDatasetValue QgsMeshLayer::datasetValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
449{
451 const QgsTriangularMesh *mesh = triangularMesh();
452
453 if ( mesh && index.isValid() )
454 {
455 if ( contains( QgsMesh::ElementType::Edge ) )
456 {
457 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
458 return dataset1dValue( index, point, searchRadius );
459 }
460 const int faceIndex = mesh->faceIndexForPoint_v2( point ) ;
461 if ( faceIndex >= 0 )
462 {
463 const int nativeFaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
465 if ( isFaceActive( index, nativeFaceIndex ) )
466 {
467 switch ( dataType )
468 {
470 {
471 value = datasetValue( index, nativeFaceIndex );
472 }
473 break;
474
476 {
477 const QgsMeshFace &face = mesh->triangles()[faceIndex];
478 const int v1 = face[0], v2 = face[1], v3 = face[2];
479 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2], p3 = mesh->vertices()[v3];
480 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
481 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
482 const QgsMeshDatasetValue val3 = datasetValue( index, v3 );
483 const double x = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.x(), val2.x(), val3.x(), point );
484 double y = std::numeric_limits<double>::quiet_NaN();
485 const bool isVector = datasetGroupMetadata( index ).isVector();
486 if ( isVector )
487 y = QgsMeshLayerUtils::interpolateFromVerticesData( p1, p2, p3, val1.y(), val2.y(), val3.y(), point );
488
489 value = QgsMeshDatasetValue( x, y );
490 }
491 break;
492
494 {
495 const QgsMesh3dAveragingMethod *avgMethod = mRendererSettings.averagingMethod();
496 if ( avgMethod )
497 {
498 const QgsMesh3dDataBlock block3d = dataset3dValues( index, nativeFaceIndex, 1 );
499 const QgsMeshDataBlock block2d = avgMethod->calculate( block3d );
500 if ( block2d.isValid() )
501 {
502 value = block2d.value( 0 );
503 }
504 }
505 }
506 break;
507
508 default:
509 break;
510 }
511 }
512 }
513 }
514
515 return value;
516}
517
519{
520 QgsMesh3dDataBlock block3d;
521
522 const QgsTriangularMesh *baseTriangularMesh = triangularMesh();
523
524 if ( baseTriangularMesh && dataProvider() && dataProvider()->isValid() && index.isValid() )
525 {
528 {
529 const int faceIndex = baseTriangularMesh->faceIndexForPoint_v2( point );
530 if ( faceIndex >= 0 )
531 {
532 const int nativeFaceIndex = baseTriangularMesh->trianglesToNativeFaces().at( faceIndex );
533 block3d = dataset3dValues( index, nativeFaceIndex, 1 );
534 }
535 }
536 }
537 return block3d;
538}
539
540QgsMeshDatasetValue QgsMeshLayer::dataset1dValue( const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius ) const
541{
543 QgsPointXY projectedPoint;
544 const int selectedIndex = closestEdge( point, searchRadius, projectedPoint );
545 const QgsTriangularMesh *mesh = triangularMesh();
546 if ( selectedIndex >= 0 )
547 {
549 switch ( dataType )
550 {
552 {
553 value = datasetValue( index, selectedIndex );
554 }
555 break;
556
558 {
559 const QgsMeshEdge &edge = mesh->edges()[selectedIndex];
560 const int v1 = edge.first, v2 = edge.second;
561 const QgsPoint p1 = mesh->vertices()[v1], p2 = mesh->vertices()[v2];
562 const QgsMeshDatasetValue val1 = datasetValue( index, v1 );
563 const QgsMeshDatasetValue val2 = datasetValue( index, v2 );
564 const double edgeLength = p1.distance( p2 );
565 const double dist1 = p1.distance( projectedPoint.x(), projectedPoint.y() );
566 value = QgsMeshLayerUtils::interpolateFromVerticesData( dist1 / edgeLength, val1, val2 );
567 }
568 break;
569 default:
570 break;
571 }
572 }
573
574 return value;
575}
576
578{
579 if ( mDataProvider )
580 mDataProvider->setTransformContext( transformContext );
582}
583
584QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtTime( const QgsDateTimeRange &timeRange, int datasetGroupIndex ) const
585{
586 if ( ! mTemporalProperties->isActive() )
587 return QgsMeshDatasetIndex( datasetGroupIndex, -1 );
588
589 const QDateTime layerReferenceTime = mTemporalProperties->referenceTime();
590 QDateTime utcTime = timeRange.begin();
591 if ( utcTime.timeSpec() != Qt::UTC )
592 utcTime.setTimeSpec( Qt::UTC );
593 const qint64 startTime = layerReferenceTime.msecsTo( utcTime );
594
595 return mDatasetGroupStore->datasetIndexAtTime( startTime, datasetGroupIndex, mTemporalProperties->matchingMethod() );
596}
597
598QgsMeshDatasetIndex QgsMeshLayer::datasetIndexAtRelativeTime( const QgsInterval &relativeTime, int datasetGroupIndex ) const
599{
600 return mDatasetGroupStore->datasetIndexAtTime( relativeTime.seconds() * 1000, datasetGroupIndex, mTemporalProperties->matchingMethod() );
601}
602
603QList<QgsMeshDatasetIndex> QgsMeshLayer::datasetIndexInRelativeTimeInterval( const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex ) const
604{
605 qint64 usedRelativeTime1 = startRelativeTime.seconds() * 1000;
606 qint64 usedRelativeTime2 = endRelativeTime.seconds() * 1000;
607
608 //adjust relative time if layer reference time is different from provider reference time
609 if ( mTemporalProperties->referenceTime().isValid() &&
610 mDataProvider &&
611 mDataProvider->isValid() &&
612 mTemporalProperties->referenceTime() != mDataProvider->temporalCapabilities()->referenceTime() )
613 {
614 usedRelativeTime1 = usedRelativeTime1 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
615 usedRelativeTime2 = usedRelativeTime2 + mTemporalProperties->referenceTime().msecsTo( mDataProvider->temporalCapabilities()->referenceTime() );
616 }
617
618 return mDatasetGroupStore->datasetIndexInTimeInterval( usedRelativeTime1, usedRelativeTime2, datasetGroupIndex );
619}
620
621void QgsMeshLayer::applyClassificationOnScalarSettings( const QgsMeshDatasetGroupMetadata &meta, QgsMeshRendererScalarSettings &scalarSettings ) const
622{
623 if ( meta.extraOptions().contains( QStringLiteral( "classification" ) ) )
624 {
625 QgsColorRampShader colorRampShader = scalarSettings.colorRampShader();
626 QgsColorRamp *colorRamp = colorRampShader.sourceColorRamp();
627 const QStringList classes = meta.extraOptions()[QStringLiteral( "classification" )].split( QStringLiteral( ";;" ) );
628
629 QString units;
630 if ( meta.extraOptions().contains( QStringLiteral( "units" ) ) )
631 units = meta.extraOptions()[ QStringLiteral( "units" )];
632
633 QVector<QVector<double>> bounds;
634 for ( const QString &classe : classes )
635 {
636 const QStringList boundsStr = classe.split( ',' );
637 QVector<double> bound;
638 for ( const QString &boundStr : boundsStr )
639 bound.append( boundStr.toDouble() );
640 bounds.append( bound );
641 }
642
643 if ( ( bounds.count() == 1 && bounds.first().count() > 2 ) || // at least a class with two value
644 ( bounds.count() > 1 ) ) // or at least two classes
645 {
646 const QVector<double> firstClass = bounds.first();
647 const QVector<double> lastClass = bounds.last();
648 const double minValue = firstClass.count() > 1 ? ( firstClass.first() + firstClass.last() ) / 2 : firstClass.first();
649 const double maxValue = lastClass.count() > 1 ? ( lastClass.first() + lastClass.last() ) / 2 : lastClass.first();
650 const double diff = maxValue - minValue;
651 QList<QgsColorRampShader::ColorRampItem> colorRampItemlist;
652 for ( int i = 0; i < bounds.count(); ++i )
653 {
654 const QVector<double> &boundClass = bounds.at( i );
656 item.value = i + 1;
657 if ( !boundClass.isEmpty() )
658 {
659 const double scalarValue = ( boundClass.first() + boundClass.last() ) / 2;
660 item.color = colorRamp->color( ( scalarValue - minValue ) / diff );
661 if ( i != 0 && i < bounds.count() - 1 ) //The first and last labels are treated after
662 {
663 item.label = QString( ( "%1 - %2 %3" ) ).
664 arg( QString::number( boundClass.first() ) ).
665 arg( QString::number( boundClass.last() ) ).
666 arg( units );
667 }
668 }
669 colorRampItemlist.append( item );
670 }
671 //treat first and last labels
672 if ( firstClass.count() == 1 )
673 colorRampItemlist.first().label = QObject::tr( "below %1 %2" ).
674 arg( QString::number( firstClass.first() ) ).
675 arg( units );
676 else
677 {
678 colorRampItemlist.first().label = QString( ( "%1 - %2 %3" ) ).
679 arg( QString::number( firstClass.first() ) ).
680 arg( QString::number( firstClass.last() ) ).
681 arg( units );
682 }
683
684 if ( lastClass.count() == 1 )
685 colorRampItemlist.last().label = QObject::tr( "above %1 %2" ).
686 arg( QString::number( lastClass.first() ) ).
687 arg( units );
688 else
689 {
690 colorRampItemlist.last().label = QString( ( "%1 - %2 %3" ) ).
691 arg( QString::number( lastClass.first() ) ).
692 arg( QString::number( lastClass.last() ) ).
693 arg( units );
694 }
695
696 colorRampShader.setMinimumValue( 0 );
697 colorRampShader.setMaximumValue( colorRampItemlist.count() - 1 );
698 scalarSettings.setClassificationMinimumMaximum( 0, colorRampItemlist.count() - 1 );
699 colorRampShader.setColorRampItemList( colorRampItemlist );
702 }
703
704 scalarSettings.setColorRampShader( colorRampShader );
706 }
707}
708
709QgsMeshDatasetIndex QgsMeshLayer::activeScalarDatasetAtTime( const QgsDateTimeRange &timeRange ) const
710{
711 if ( mTemporalProperties->isActive() )
712 return datasetIndexAtTime( timeRange, mRendererSettings.activeScalarDatasetGroup() );
713 else
714 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
715}
716
717QgsMeshDatasetIndex QgsMeshLayer::activeVectorDatasetAtTime( const QgsDateTimeRange &timeRange ) const
718{
719 if ( mTemporalProperties->isActive() )
720 return datasetIndexAtTime( timeRange, mRendererSettings.activeVectorDatasetGroup() );
721 else
722 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
723}
724
725void QgsMeshLayer::fillNativeMesh()
726{
727 Q_ASSERT( !mNativeMesh );
728
729 mNativeMesh.reset( new QgsMesh() );
730
731 if ( !( dataProvider() && dataProvider()->isValid() ) )
732 return;
733
734 dataProvider()->populateMesh( mNativeMesh.get() );
735}
736
737void QgsMeshLayer::onDatasetGroupsAdded( const QList<int> &datasetGroupIndexes )
738{
739 // assign default style to new dataset groups
740 for ( int datasetGroupIndex : datasetGroupIndexes )
741 {
742 if ( !mRendererSettings.hasSettings( datasetGroupIndex ) )
743 assignDefaultStyleToDatasetGroup( datasetGroupIndex );
744 }
745
746 temporalProperties()->setIsActive( mDatasetGroupStore->hasTemporalCapabilities() );
747 emit rendererChanged();
748}
749
750void QgsMeshLayer::onMeshEdited()
751{
752 mRendererCache.reset( new QgsMeshLayerRendererCache() );
753 emit layerModified();
756}
757
759{
760 return mDatasetGroupStore->datasetGroupTreeItem();
761}
762
764{
765 mDatasetGroupStore->setDatasetGroupTreeItem( rootItem );
766 updateActiveDatasetGroups();
767}
768
769int QgsMeshLayer::closestEdge( const QgsPointXY &point, double searchRadius, QgsPointXY &projectedPoint ) const
770{
771 const QgsRectangle searchRectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
772 const QgsTriangularMesh *mesh = triangularMesh();
773 // search for the closest edge in search area from point
774 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( searchRectangle );
775 int selectedIndex = -1;
776 if ( mesh->contains( QgsMesh::Edge ) &&
777 mDataProvider->isValid() )
778 {
779 double sqrMaxDistFromPoint = pow( searchRadius, 2 );
780 for ( const int edgeIndex : edgeIndexes )
781 {
782 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
783 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
784 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
785 QgsPointXY projPoint;
786 const double sqrDist = point.sqrDistToSegment( vertex1.x(), vertex1.y(), vertex2.x(), vertex2.y(), projPoint );
787 if ( sqrDist < sqrMaxDistFromPoint )
788 {
789 selectedIndex = edgeIndex;
790 projectedPoint = projPoint;
791 sqrMaxDistFromPoint = sqrDist;
792 }
793 }
794 }
795
796 return selectedIndex;
797}
798
800{
801 return QgsMeshDatasetIndex( mRendererSettings.activeVectorDatasetGroup(), mStaticVectorDatasetIndex );
802}
803
804void QgsMeshLayer::setReferenceTime( const QDateTime &referenceTime )
805{
806 if ( auto *lDataProvider = dataProvider() )
807 mTemporalProperties->setReferenceTime( referenceTime, lDataProvider->temporalCapabilities() );
808 else
809 mTemporalProperties->setReferenceTime( referenceTime, nullptr );
810}
811
813{
814 mTemporalProperties->setMatchingMethod( matchingMethod );
815}
816
817QgsPointXY QgsMeshLayer::snapOnVertex( const QgsPointXY &point, double searchRadius )
818{
819 const QgsTriangularMesh *mesh = triangularMesh();
820 QgsPointXY exactPosition;
821 if ( !mesh )
822 return exactPosition;
823 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
824 double maxDistance = searchRadius;
825 //attempt to snap on edges's vertices
826 const QList<int> edgeIndexes = mesh->edgeIndexesForRectangle( rectangle );
827 for ( const int edgeIndex : edgeIndexes )
828 {
829 const QgsMeshEdge &edge = mesh->edges().at( edgeIndex );
830 const QgsMeshVertex &vertex1 = mesh->vertices()[edge.first];
831 const QgsMeshVertex &vertex2 = mesh->vertices()[edge.second];
832 const double dist1 = point.distance( vertex1 );
833 const double dist2 = point.distance( vertex2 );
834 if ( dist1 < maxDistance )
835 {
836 maxDistance = dist1;
837 exactPosition = vertex1;
838 }
839 if ( dist2 < maxDistance )
840 {
841 maxDistance = dist2;
842 exactPosition = vertex2;
843 }
844 }
845
846 //attempt to snap on face's vertices
847 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
848 for ( const int faceIndex : faceIndexes )
849 {
850 const QgsMeshFace &face = mesh->triangles().at( faceIndex );
851 for ( int i = 0; i < 3; ++i )
852 {
853 const QgsMeshVertex &vertex = mesh->vertices()[face.at( i )];
854 const double dist = point.distance( vertex );
855 if ( dist < maxDistance )
856 {
857 maxDistance = dist;
858 exactPosition = vertex;
859 }
860 }
861 }
862
863 return exactPosition;
864}
865
866QgsPointXY QgsMeshLayer::snapOnEdge( const QgsPointXY &point, double searchRadius )
867{
868 QgsPointXY projectedPoint;
869 closestEdge( point, searchRadius, projectedPoint );
870
871 return projectedPoint;
872}
873
874QgsPointXY QgsMeshLayer::snapOnFace( const QgsPointXY &point, double searchRadius )
875{
876 const QgsTriangularMesh *mesh = triangularMesh();
877 QgsPointXY centroidPosition;
878 if ( !mesh )
879 return centroidPosition;
880 const QgsRectangle rectangle( point.x() - searchRadius, point.y() - searchRadius, point.x() + searchRadius, point.y() + searchRadius );
881 double maxDistance = std::numeric_limits<double>::max();
882
883 const QList<int> faceIndexes = mesh->faceIndexesForRectangle( rectangle );
884 for ( const int faceIndex : faceIndexes )
885 {
886 const int nativefaceIndex = mesh->trianglesToNativeFaces().at( faceIndex );
887 if ( nativefaceIndex < 0 && nativefaceIndex >= mesh->faceCentroids().count() )
888 continue;
889 const QgsPointXY centroid = mesh->faceCentroids()[nativefaceIndex];
890 const double dist = point.distance( centroid );
891 if ( dist < maxDistance )
892 {
893 maxDistance = dist;
894 centroidPosition = centroid;
895 }
896 }
897
898 return centroidPosition;
899}
900
902{
903 mDatasetGroupStore->resetDatasetGroupTreeItem();
904 updateActiveDatasetGroups();
905}
906
908{
909 if ( !mDataProvider )
910 return QgsInterval();
911 const int groupCount = mDataProvider->datasetGroupCount();
912 for ( int i = 0; i < groupCount; ++i )
913 {
914 const qint64 timeStep = mDataProvider->temporalCapabilities()->firstTimeStepDuration( i );
915 if ( timeStep > 0 )
917 }
918
919 return QgsInterval();
920}
921
923{
924 const qint64 time = mDatasetGroupStore->datasetRelativeTime( index );
925
926 if ( time == INVALID_MESHLAYER_TIME )
927 return QgsInterval();
928 else
930}
931
933{
934 return mDatasetGroupStore->datasetRelativeTime( index );
935}
936
937static QString detailsErrorMessage( const QgsMeshEditingError &error )
938{
939 QString message;
940
941 switch ( error.errorType )
942 {
944 break;
946 message = QObject::tr( "Face %1 invalid" ).arg( error.elementIndex );
947 break;
949 message = QObject::tr( "Too many vertices for face %1" ).arg( error.elementIndex );
950 break;
952 message = QObject::tr( "Face %1 is flat" ).arg( error.elementIndex );
953 break;
955 message = QObject::tr( "Vertex %1 is a unique shared vertex" ).arg( error.elementIndex );
956 break;
958 message = QObject::tr( "Vertex %1 is invalid" ).arg( error.elementIndex );
959 break;
961 message = QObject::tr( "Face %1 is manifold" ).arg( error.elementIndex );
962 break;
963 }
964
965 return message;
966}
967
969{
970 if ( !supportsEditing() )
971 {
972 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" not support mesh editing" ).arg( name() ) );
973 return false;
974 }
975
976 if ( mMeshEditor )
977 {
978 QgsMessageLog::logMessage( QObject::tr( "Mesh layer \"%1\" already in editing mode" ).arg( name() ) );
979 return false;
980 }
981
982 mSimplificationSettings.setEnabled( false );
983
984 updateTriangularMesh( transform );
985
986 mMeshEditor = new QgsMeshEditor( this );
987
988 const QgsMeshEditingError error = mMeshEditor->initialize();
989
991 {
992 mMeshEditor->deleteLater();
993 mMeshEditor = nullptr;
994
995 QgsMessageLog::logMessage( QObject::tr( "Unable to start editing of mesh layer \"%1\": %2" ).
996 arg( name(), detailsErrorMessage( error ) ), QString(), Qgis::MessageLevel::Critical );
997 return false;
998 }
999
1000 // During editing, we don't need anymore the provider data. Mesh frame data is stored in the mesh editor.
1001 mDataProvider->close();
1002
1003 // All dataset group are removed and replace by a unique virtual dataset group that provide vertices elevation value.
1004 mExtraDatasetUri.clear();
1005 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1006
1007 std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup( mMeshEditor->createZValueDatasetGroup() );
1008 if ( mDatasetGroupStore->addDatasetGroup( zValueDatasetGroup.get() ) )
1009 zValueDatasetGroup.release();
1010
1012
1013 connect( mMeshEditor, &QgsMeshEditor::meshEdited, this, &QgsMeshLayer::onMeshEdited );
1014
1015 emit dataChanged();
1016 emit editingStarted();
1017
1018 return true;
1019}
1020
1021bool QgsMeshLayer::commitFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1022{
1024 QString detailsError;
1025 if ( !mMeshEditor->checkConsistency( error ) )
1026 {
1027 if ( error.errorType == Qgis::MeshEditingErrorType::NoError )
1028 detailsError = tr( "Unknown inconsistent mesh error" );
1029 }
1030 else
1031 {
1032 error = QgsTopologicalMesh::checkTopology( *mNativeMesh, mMeshEditor->maximumVerticesPerFace() );
1033 detailsError = detailsErrorMessage( error );
1034 }
1035
1036 if ( !detailsError.isEmpty() )
1037 {
1038 QgsMessageLog::logMessage( QObject::tr( "Edited mesh layer \"%1\" can't be save due to an error: %2" ).
1039 arg( name(), detailsError ), QString(), Qgis::MessageLevel::Critical );
1040 return false;
1041 }
1042
1043 stopFrameEditing( transform );
1044
1045 if ( !mDataProvider )
1046 return false;
1047
1048 const bool res = mDataProvider->saveMeshFrame( *mNativeMesh.get() );
1049
1050 if ( continueEditing )
1051 {
1052 mMeshEditor->initialize();
1053 emit layerModified();
1054 return res;
1055 }
1056
1057 mMeshEditor->deleteLater();
1058 mMeshEditor = nullptr;
1059 emit editingStopped();
1060
1061 mDataProvider->reloadData();
1062 mDataProvider->populateMesh( mNativeMesh.get() );
1063 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1064 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1066 return true;
1067}
1068
1069bool QgsMeshLayer::rollBackFrameEditing( const QgsCoordinateTransform &transform, bool continueEditing )
1070{
1071 stopFrameEditing( transform );
1072
1073 if ( !mDataProvider )
1074 return false;
1075
1076 mTriangularMeshes.clear();
1077 mDataProvider->reloadData();
1078 mDataProvider->populateMesh( mNativeMesh.get() );
1079 updateTriangularMesh( transform );
1080 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1082
1083 if ( continueEditing )
1084 {
1085 mMeshEditor->resetTriangularMesh( triangularMesh() );
1086 return mMeshEditor->initialize() == QgsMeshEditingError();
1087 }
1088 else
1089 {
1090 mMeshEditor->deleteLater();
1091 mMeshEditor = nullptr;
1092 emit editingStopped();
1093
1094 mDatasetGroupStore.reset( new QgsMeshDatasetGroupStore( this ) );
1095 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() );
1097 emit dataChanged();
1098 return true;
1099 }
1100}
1101
1103{
1104 if ( !mMeshEditor )
1105 return;
1106
1107 mMeshEditor->stopEditing();
1108 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1109 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1110}
1111
1112bool QgsMeshLayer::reindex( const QgsCoordinateTransform &transform, bool renumber )
1113{
1114 if ( !mMeshEditor )
1115 return false;
1116
1117 if ( !mMeshEditor->reindex( renumber ) )
1118 return false;
1119
1120 mTriangularMeshes.clear();
1121 mTriangularMeshes.emplace_back( new QgsTriangularMesh );
1122 mTriangularMeshes.at( 0 )->update( mNativeMesh.get(), transform );
1123 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1124 mMeshEditor->resetTriangularMesh( mTriangularMeshes.at( 0 ).get() );
1125
1126 return true;
1127}
1128
1130{
1131 return mMeshEditor;
1132}
1133
1135{
1136 if ( mMeshEditor )
1137 return mMeshEditor->isModified();
1138
1139 return false;
1140}
1141
1143{
1144 switch ( type )
1145 {
1146 case QgsMesh::ElementType::Vertex:
1147 return meshVertexCount() != 0;
1148 case QgsMesh::ElementType::Edge:
1149 return meshEdgeCount() != 0;
1150 case QgsMesh::ElementType::Face:
1151 return meshFaceCount() != 0;
1152 }
1153 return false;
1154}
1155
1157{
1158 if ( mMeshEditor )
1159 return mMeshEditor->validVerticesCount();
1160 else if ( mDataProvider )
1161 return mDataProvider->vertexCount();
1162 else return 0;
1163}
1164
1166{
1167 if ( mMeshEditor )
1168 return mMeshEditor->validFacesCount();
1169 else if ( mDataProvider )
1170 return mDataProvider->faceCount();
1171 else return 0;
1172}
1173
1175{
1176 if ( mMeshEditor )
1177 return mNativeMesh->edgeCount();
1178 else if ( mDataProvider )
1179 return mDataProvider->edgeCount();
1180 else return 0;
1181}
1182
1183void QgsMeshLayer::updateActiveDatasetGroups()
1184{
1185 QgsMeshDatasetGroupTreeItem *treeItem = mDatasetGroupStore->datasetGroupTreeItem();
1186
1187 if ( !mDatasetGroupStore->datasetGroupTreeItem() )
1188 return;
1189
1191 const int oldActiveScalar = settings.activeScalarDatasetGroup();
1192 const int oldActiveVector = settings.activeVectorDatasetGroup();
1193
1194 QgsMeshDatasetGroupTreeItem *activeScalarItem =
1195 treeItem->childFromDatasetGroupIndex( oldActiveScalar );
1196
1197 if ( !activeScalarItem && treeItem->childCount() > 0 && oldActiveScalar != -1 )
1198 activeScalarItem = treeItem->child( 0 );
1199
1200 if ( activeScalarItem && !activeScalarItem->isEnabled() )
1201 {
1202 for ( int i = 0; i < treeItem->childCount(); ++i )
1203 {
1204 activeScalarItem = treeItem->child( i );
1205 if ( activeScalarItem->isEnabled() )
1206 break;
1207 else
1208 activeScalarItem = nullptr;
1209 }
1210 }
1211
1212 if ( activeScalarItem )
1213 settings.setActiveScalarDatasetGroup( activeScalarItem->datasetGroupIndex() );
1214 else
1215 settings.setActiveScalarDatasetGroup( -1 );
1216
1217 QgsMeshDatasetGroupTreeItem *activeVectorItem =
1218 treeItem->childFromDatasetGroupIndex( oldActiveVector );
1219
1220 if ( !( activeVectorItem && activeVectorItem->isEnabled() ) )
1221 settings.setActiveVectorDatasetGroup( -1 );
1222
1223 setRendererSettings( settings );
1224
1225 if ( oldActiveScalar != settings.activeScalarDatasetGroup() )
1227 if ( oldActiveVector != settings.activeVectorDatasetGroup() )
1229}
1230
1231void QgsMeshLayer::setDataSourcePrivate( const QString &dataSource, const QString &baseName, const QString &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1232{
1233 mDataSource = dataSource;
1234 mLayerName = baseName;
1235 setProviderType( provider );
1236
1237 if ( !mDataSource.isEmpty() && !provider.isEmpty() )
1238 setDataProvider( provider, options, flags );
1239}
1240
1241QgsPointXY QgsMeshLayer::snapOnElement( QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius )
1242{
1243 switch ( elementType )
1244 {
1245 case QgsMesh::Vertex:
1246 return snapOnVertex( point, searchRadius );
1247 case QgsMesh::Edge:
1248 return snapOnEdge( point, searchRadius );
1249 case QgsMesh::Face:
1250 return snapOnFace( point, searchRadius );
1251 }
1252 return QgsPointXY(); // avoid warnings
1253}
1254
1256{
1257 if ( !mNativeMesh )
1258 {
1259 // lazy loading of mesh data
1260 fillNativeMesh();
1261 }
1262
1263 QList<int> ret;
1264
1265 if ( !mNativeMesh )
1266 return ret;
1267
1268 QgsExpressionContext context;
1269 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Vertex ) );
1270 context.appendScope( expScope.release() );
1271 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1272
1273 expression.prepare( &context );
1274
1275 for ( int i = 0; i < mNativeMesh->vertexCount(); ++i )
1276 {
1277 context.lastScope()->setVariable( QStringLiteral( "_mesh_vertex_index" ), i, false );
1278
1279 if ( expression.evaluate( &context ).toBool() )
1280 ret.append( i );
1281 }
1282
1283 return ret;
1284}
1285
1287{
1288 if ( !mNativeMesh )
1289 {
1290 // lazy loading of mesh data
1291 fillNativeMesh();
1292 }
1293
1294 QList<int> ret;
1295
1296 if ( !mNativeMesh )
1297 return ret;
1298
1299 QgsExpressionContext context;
1300 std::unique_ptr<QgsExpressionContextScope> expScope( QgsExpressionContextUtils::meshExpressionScope( QgsMesh::Face ) );
1301 context.appendScope( expScope.release() );
1302 context.lastScope()->setVariable( QStringLiteral( "_mesh_layer" ), QVariant::fromValue( this ) );
1303
1304 expression.prepare( &context );
1305
1306 for ( int i = 0; i < mNativeMesh->faceCount(); ++i )
1307 {
1308 context.lastScope()->setVariable( QStringLiteral( "_mesh_face_index" ), i, false );
1309
1310 if ( expression.evaluate( &context ).toBool() )
1311 ret.append( i );
1312 }
1313
1314 return ret;
1315}
1316
1318{
1319 return QgsMeshDatasetIndex( mRendererSettings.activeScalarDatasetGroup(), mStaticScalarDatasetIndex );
1320}
1321
1323{
1324 const int oldActiveVector = mRendererSettings.activeVectorDatasetGroup();
1325
1326 mStaticVectorDatasetIndex = staticVectorDatasetIndex.dataset();
1328
1329 if ( oldActiveVector != mRendererSettings.activeVectorDatasetGroup() )
1331}
1332
1334{
1335 const int oldActiveScalar = mRendererSettings.activeScalarDatasetGroup();
1336
1337 mStaticScalarDatasetIndex = staticScalarDatasetIndex.dataset();
1339
1340 if ( oldActiveScalar != mRendererSettings.activeScalarDatasetGroup() )
1342}
1343
1345{
1346 return mSimplificationSettings;
1347}
1348
1350{
1351 mSimplificationSettings = simplifySettings;
1352}
1353
1354static QgsColorRamp *_createDefaultColorRamp()
1355{
1356 QgsColorRamp *ramp = QgsStyle::defaultStyle()->colorRamp( QStringLiteral( "Plasma" ) );
1357 if ( ramp )
1358 return ramp;
1359
1360 // definition of "Plasma" color ramp (in case it is not available in the style for some reason)
1361 QVariantMap props;
1362 props["color1"] = "13,8,135,255";
1363 props["color2"] = "240,249,33,255";
1364 props["stops"] =
1365 "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:"
1366 "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:"
1367 "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:"
1368 "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:"
1369 "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:"
1370 "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:"
1371 "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:"
1372 "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:"
1373 "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:"
1374 "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";
1375 return QgsGradientColorRamp::create( props );
1376}
1377
1378void QgsMeshLayer::assignDefaultStyleToDatasetGroup( int groupIndex )
1379{
1381 const double groupMin = metadata.minimum();
1382 const double groupMax = metadata.maximum();
1383
1384 QgsColorRampShader fcn( groupMin, groupMax, _createDefaultColorRamp() );
1385 fcn.classifyColorRamp( 5, -1, QgsRectangle(), nullptr );
1386
1387 QgsMeshRendererScalarSettings scalarSettings;
1388 scalarSettings.setClassificationMinimumMaximum( groupMin, groupMax );
1389 scalarSettings.setColorRampShader( fcn );
1390 QgsInterpolatedLineWidth edgeStrokeWidth;
1391 edgeStrokeWidth.setMinimumValue( groupMin );
1392 edgeStrokeWidth.setMaximumValue( groupMax );
1393 const QgsInterpolatedLineColor edgeStrokeColor( fcn );
1394 const QgsInterpolatedLineRenderer edgeStrokePen;
1395 scalarSettings.setEdgeStrokeWidth( edgeStrokeWidth );
1396 mRendererSettings.setScalarSettings( groupIndex, scalarSettings );
1397
1398 if ( metadata.isVector() )
1399 {
1400 QgsMeshRendererVectorSettings vectorSettings;
1401 vectorSettings.setColorRampShader( fcn );
1402 mRendererSettings.setVectorSettings( groupIndex, vectorSettings );
1403 }
1404}
1405
1407{
1408 // Triangular mesh
1409 updateTriangularMesh( rendererContext.coordinateTransform() );
1410
1411 // Build overview triangular meshes if needed
1412 createSimplifiedMeshes();
1413
1414 // Cache
1415 if ( !mRendererCache )
1416 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1417
1418 return new QgsMeshLayerRenderer( this, rendererContext );
1419}
1420
1422{
1423 return new QgsMeshLayerProfileGenerator( this, request );
1424}
1425
1426void QgsMeshLayer::checkSymbologyConsistency()
1427{
1428 const QList<int> groupIndexes = mDatasetGroupStore->datasetGroupIndexes();
1429 if ( !groupIndexes.contains( mRendererSettings.activeScalarDatasetGroup() ) )
1430 {
1431 if ( !groupIndexes.empty() )
1432 mRendererSettings.setActiveScalarDatasetGroup( groupIndexes.first() );
1433 else
1434 mRendererSettings.setActiveScalarDatasetGroup( -1 );
1435 }
1436
1437 if ( !groupIndexes.contains( mRendererSettings.activeVectorDatasetGroup() ) )
1438 {
1439 mRendererSettings.setActiveVectorDatasetGroup( -1 );
1440 }
1441}
1442
1443bool QgsMeshLayer::readSymbology( const QDomNode &node, QString &errorMessage,
1444 QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1445{
1446 Q_UNUSED( errorMessage )
1447 // TODO: implement categories for raster layer
1448
1449 const QDomElement elem = node.toElement();
1450
1451 readCommonStyle( elem, context, categories );
1452
1453 const QDomElement elemRendererSettings = elem.firstChildElement( "mesh-renderer-settings" );
1454 if ( !elemRendererSettings.isNull() )
1455 mRendererSettings.readXml( elemRendererSettings, context );
1456
1457 checkSymbologyConsistency();
1458
1459 const QDomElement elemSimplifySettings = elem.firstChildElement( "mesh-simplify-settings" );
1460 if ( !elemSimplifySettings.isNull() )
1461 mSimplificationSettings.readXml( elemSimplifySettings, context );
1462
1463 // get and set the blend mode if it exists
1464 const QDomNode blendModeNode = node.namedItem( QStringLiteral( "blendMode" ) );
1465 if ( !blendModeNode.isNull() )
1466 {
1467 const QDomElement e = blendModeNode.toElement();
1468 setBlendMode( QgsPainting::getCompositionMode( static_cast< QgsPainting::BlendMode >( e.text().toInt() ) ) );
1469 }
1470
1471 // get and set the layer transparency
1472 if ( categories.testFlag( Rendering ) )
1473 {
1474 const QDomNode layerOpacityNode = node.namedItem( QStringLiteral( "layerOpacity" ) );
1475 if ( !layerOpacityNode.isNull() )
1476 {
1477 const QDomElement e = layerOpacityNode.toElement();
1478 setOpacity( e.text().toDouble() );
1479 }
1480 }
1481
1482 return true;
1483}
1484
1485bool QgsMeshLayer::writeSymbology( QDomNode &node, QDomDocument &doc, QString &errorMessage,
1486 const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1487{
1488 Q_UNUSED( errorMessage )
1489 // TODO: implement categories for raster layer
1490
1491 QDomElement elem = node.toElement();
1492
1493 writeCommonStyle( elem, doc, context, categories );
1494
1495 const QDomElement elemRendererSettings = mRendererSettings.writeXml( doc, context );
1496 elem.appendChild( elemRendererSettings );
1497
1498 const QDomElement elemSimplifySettings = mSimplificationSettings.writeXml( doc, context );
1499 elem.appendChild( elemSimplifySettings );
1500
1501 // add blend mode node
1502 QDomElement blendModeElement = doc.createElement( QStringLiteral( "blendMode" ) );
1503 const QDomText blendModeText = doc.createTextNode( QString::number( QgsPainting::getBlendModeEnum( blendMode() ) ) );
1504 blendModeElement.appendChild( blendModeText );
1505 node.appendChild( blendModeElement );
1506
1507 // add the layer opacity
1508 if ( categories.testFlag( Rendering ) )
1509 {
1510 QDomElement layerOpacityElem = doc.createElement( QStringLiteral( "layerOpacity" ) );
1511 const QDomText layerOpacityText = doc.createTextNode( QString::number( opacity() ) );
1512 layerOpacityElem.appendChild( layerOpacityText );
1513 node.appendChild( layerOpacityElem );
1514 }
1515
1516 return true;
1517}
1518
1519bool QgsMeshLayer::writeStyle( QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories ) const
1520{
1521 return writeSymbology( node, doc, errorMessage, context, categories );
1522}
1523
1524bool QgsMeshLayer::readStyle( const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories )
1525{
1526 return readSymbology( node, errorMessage, context, categories );
1527}
1528
1529QString QgsMeshLayer::decodedSource( const QString &source, const QString &provider, const QgsReadWriteContext &context ) const
1530{
1531 QString src( source );
1532
1533 QVariantMap uriParts = QgsProviderRegistry::instance()->decodeUri( provider, source );
1534 if ( uriParts.contains( QStringLiteral( "path" ) ) )
1535 {
1536 QString filePath = uriParts.value( QStringLiteral( "path" ) ).toString();
1537 filePath = context.pathResolver().readPath( filePath );
1538 uriParts.insert( QStringLiteral( "path" ), filePath );
1539 src = QgsProviderRegistry::instance()->encodeUri( provider, uriParts );
1540 }
1541
1542 return src;
1543}
1544
1545QString QgsMeshLayer::encodedSource( const QString &source, const QgsReadWriteContext &context ) const
1546{
1547 QString src( source );
1548 QVariantMap uriParts = QgsProviderRegistry::instance()->decodeUri( mProviderKey, source );
1549 if ( uriParts.contains( QStringLiteral( "path" ) ) )
1550 {
1551 QString filePath = uriParts.value( QStringLiteral( "path" ) ).toString();
1552 filePath = context.pathResolver().writePath( filePath );
1553 uriParts.insert( QStringLiteral( "path" ), filePath );
1555 }
1556 return src;
1557}
1558
1559bool QgsMeshLayer::readXml( const QDomNode &layer_node, QgsReadWriteContext &context )
1560{
1561 QgsDebugMsgLevel( QStringLiteral( "Datasource in QgsMeshLayer::readXml: %1" ).arg( mDataSource.toLocal8Bit().data() ), 3 );
1562
1563 //process provider key
1564 const QDomNode pkeyNode = layer_node.namedItem( QStringLiteral( "provider" ) );
1565
1566 if ( pkeyNode.isNull() )
1567 {
1568 mProviderKey.clear();
1569 }
1570 else
1571 {
1572 const QDomElement pkeyElt = pkeyNode.toElement();
1573 mProviderKey = pkeyElt.text();
1574 }
1575
1577 {
1578 return false;
1579 }
1580
1581 const QgsDataProvider::ProviderOptions providerOptions;
1582 QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags();
1584 {
1586 }
1587
1588 const QDomElement elemExtraDatasets = layer_node.firstChildElement( QStringLiteral( "extra-datasets" ) );
1589 if ( !elemExtraDatasets.isNull() )
1590 {
1591 QDomElement elemUri = elemExtraDatasets.firstChildElement( QStringLiteral( "uri" ) );
1592 while ( !elemUri.isNull() )
1593 {
1594 const QString uri = context.pathResolver().readPath( elemUri.text() );
1595 mExtraDatasetUri.append( uri );
1596 elemUri = elemUri.nextSiblingElement( QStringLiteral( "uri" ) );
1597 }
1598 }
1599
1600 if ( pkeyNode.toElement().hasAttribute( QStringLiteral( "time-unit" ) ) )
1601 mTemporalUnit = static_cast<QgsUnitTypes::TemporalUnit>( pkeyNode.toElement().attribute( QStringLiteral( "time-unit" ) ).toInt() );
1602
1603 // read dataset group store
1604 const QDomElement elemDatasetGroupsStore = layer_node.firstChildElement( QStringLiteral( "mesh-dataset-groups-store" ) );
1605 if ( elemDatasetGroupsStore.isNull() )
1607 else
1608 mDatasetGroupStore->readXml( elemDatasetGroupsStore, context );
1609
1610 setDataProvider( mProviderKey, providerOptions, flags );
1611
1612 QString errorMsg;
1613 readSymbology( layer_node, errorMsg, context );
1614
1615 if ( !mTemporalProperties->timeExtent().begin().isValid() || mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1617
1618 // read static dataset
1619 const QDomElement elemStaticDataset = layer_node.firstChildElement( QStringLiteral( "static-active-dataset" ) );
1620 if ( elemStaticDataset.hasAttribute( QStringLiteral( "scalar" ) ) )
1621 {
1622 mStaticScalarDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "scalar" ) ).toInt();
1623 }
1624 if ( elemStaticDataset.hasAttribute( QStringLiteral( "vector" ) ) )
1625 {
1626 mStaticVectorDatasetIndex = elemStaticDataset.attribute( QStringLiteral( "vector" ) ).toInt();
1627 }
1628
1629 return isValid(); // should be true if read successfully
1630}
1631
1632bool QgsMeshLayer::writeXml( QDomNode &layer_node, QDomDocument &document, const QgsReadWriteContext &context ) const
1633{
1634 // first get the layer element so that we can append the type attribute
1635 QDomElement mapLayerNode = layer_node.toElement();
1636
1637 if ( mapLayerNode.isNull() || ( QLatin1String( "maplayer" ) != mapLayerNode.nodeName() ) )
1638 {
1639 QgsDebugMsgLevel( QStringLiteral( "can't find <maplayer>" ), 2 );
1640 return false;
1641 }
1642
1643 mapLayerNode.setAttribute( QStringLiteral( "type" ), QgsMapLayerFactory::typeToString( QgsMapLayerType::MeshLayer ) );
1644
1645 // add provider node
1646 if ( mDataProvider )
1647 {
1648 QDomElement provider = document.createElement( QStringLiteral( "provider" ) );
1649 const QDomText providerText = document.createTextNode( providerType() );
1650 provider.appendChild( providerText );
1651 layer_node.appendChild( provider );
1652 provider.setAttribute( QStringLiteral( "time-unit" ), mDataProvider->temporalCapabilities()->temporalUnit() );
1653
1654 const QStringList extraDatasetUris = mDataProvider->extraDatasets();
1655 QDomElement elemExtraDatasets = document.createElement( QStringLiteral( "extra-datasets" ) );
1656 for ( const QString &uri : extraDatasetUris )
1657 {
1658 const QString path = context.pathResolver().writePath( uri );
1659 QDomElement elemUri = document.createElement( QStringLiteral( "uri" ) );
1660 elemUri.appendChild( document.createTextNode( path ) );
1661 elemExtraDatasets.appendChild( elemUri );
1662 }
1663 layer_node.appendChild( elemExtraDatasets );
1664 }
1665
1666 QDomElement elemStaticDataset = document.createElement( QStringLiteral( "static-active-dataset" ) );
1667 elemStaticDataset.setAttribute( QStringLiteral( "scalar" ), mStaticScalarDatasetIndex );
1668 elemStaticDataset.setAttribute( QStringLiteral( "vector" ), mStaticVectorDatasetIndex );
1669 layer_node.appendChild( elemStaticDataset );
1670
1671 // write dataset group store if not in edting mode
1672 if ( !isEditable() )
1673 layer_node.appendChild( mDatasetGroupStore->writeXml( document, context ) );
1674
1675 // renderer specific settings
1676 QString errorMsg;
1677 return writeSymbology( layer_node, document, errorMsg, context );
1678}
1679
1681{
1682 if ( !mMeshEditor && mDataProvider && mDataProvider->isValid() )
1683 {
1684 mDataProvider->reloadData();
1685 mDatasetGroupStore->setPersistentProvider( mDataProvider, QStringList() ); //extra dataset are already loaded
1686
1687 //reload the mesh structure
1688 if ( !mNativeMesh )
1689 mNativeMesh.reset( new QgsMesh );
1690
1691 dataProvider()->populateMesh( mNativeMesh.get() );
1692
1693 if ( mTemporalProperties->alwaysLoadReferenceTimeFromSource() )
1694 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( mDataProvider->temporalCapabilities() );
1695
1696 //clear the TriangularMeshes
1697 mTriangularMeshes.clear();
1698
1699 //clear the rendererCache
1700 mRendererCache.reset( new QgsMeshLayerRendererCache() );
1701
1702 checkSymbologyConsistency();
1703
1704 emit reloaded();
1705 }
1706}
1707
1708QStringList QgsMeshLayer::subLayers() const
1709{
1710 if ( mDataProvider )
1711 return mDataProvider->subLayers();
1712 else
1713 return QStringList();
1714}
1715
1717{
1718 const QgsLayerMetadataFormatter htmlFormatter( metadata() );
1719 QString myMetadata = QStringLiteral( "<html>\n<body>\n" );
1720
1721 myMetadata += generalHtmlMetadata();
1722
1723 // Begin Provider section
1724 myMetadata += QStringLiteral( "<h1>" ) + tr( "Information from provider" ) + QStringLiteral( "</h1>\n<hr>\n" );
1725 myMetadata += QLatin1String( "<table class=\"list-view\">\n" );
1726
1727 // Extent
1728 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" ) + tr( "Extent" ) + QStringLiteral( "</td><td>" ) + extent().toString() + QStringLiteral( "</td></tr>\n" );
1729
1730 // feature count
1731 QLocale locale = QLocale();
1732 locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
1733
1734 if ( dataProvider() )
1735 {
1736 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1737 + tr( "Vertex count" ) + QStringLiteral( "</td><td>" )
1738 + ( locale.toString( static_cast<qlonglong>( meshVertexCount() ) ) )
1739 + QStringLiteral( "</td></tr>\n" );
1740 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1741 + tr( "Face count" ) + QStringLiteral( "</td><td>" )
1742 + ( locale.toString( static_cast<qlonglong>( meshFaceCount() ) ) )
1743 + QStringLiteral( "</td></tr>\n" );
1744 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1745 + tr( "Edge count" ) + QStringLiteral( "</td><td>" )
1746 + ( locale.toString( static_cast<qlonglong>( meshEdgeCount() ) ) )
1747 + QStringLiteral( "</td></tr>\n" );
1748 myMetadata += QStringLiteral( "<tr><td class=\"highlight\">" )
1749 + tr( "Dataset groups count" ) + QStringLiteral( "</td><td>" )
1750 + ( locale.toString( static_cast<qlonglong>( datasetGroupCount() ) ) )
1751 + QStringLiteral( "</td></tr>\n" );
1752 }
1753
1754 // End Provider section
1755 myMetadata += QLatin1String( "</table>\n<br><br>" );
1756
1757 // CRS
1758 myMetadata += crsHtmlMetadata();
1759
1760 // identification section
1761 myMetadata += QStringLiteral( "<h1>" ) + tr( "Identification" ) + QStringLiteral( "</h1>\n<hr>\n" );
1762 myMetadata += htmlFormatter.identificationSectionHtml( );
1763 myMetadata += QLatin1String( "<br><br>\n" );
1764
1765 // extent section
1766 myMetadata += QStringLiteral( "<h1>" ) + tr( "Extent" ) + QStringLiteral( "</h1>\n<hr>\n" );
1767 myMetadata += htmlFormatter.extentSectionHtml( isSpatial() );
1768 myMetadata += QLatin1String( "<br><br>\n" );
1769
1770 // Start the Access section
1771 myMetadata += QStringLiteral( "<h1>" ) + tr( "Access" ) + QStringLiteral( "</h1>\n<hr>\n" );
1772 myMetadata += htmlFormatter.accessSectionHtml( );
1773 myMetadata += QLatin1String( "<br><br>\n" );
1774
1775 // Start the contacts section
1776 myMetadata += QStringLiteral( "<h1>" ) + tr( "Contacts" ) + QStringLiteral( "</h1>\n<hr>\n" );
1777 myMetadata += htmlFormatter.contactsSectionHtml( );
1778 myMetadata += QLatin1String( "<br><br>\n" );
1779
1780 // Start the links section
1781 myMetadata += QStringLiteral( "<h1>" ) + tr( "Links" ) + QStringLiteral( "</h1>\n<hr>\n" );
1782 myMetadata += htmlFormatter.linksSectionHtml( );
1783 myMetadata += QLatin1String( "<br><br>\n" );
1784
1785 // Start the history section
1786 myMetadata += QStringLiteral( "<h1>" ) + tr( "History" ) + QStringLiteral( "</h1>\n<hr>\n" );
1787 myMetadata += htmlFormatter.historySectionHtml( );
1788 myMetadata += QLatin1String( "<br><br>\n" );
1789
1790 myMetadata += QLatin1String( "\n</body>\n</html>\n" );
1791 return myMetadata;
1792}
1793
1795{
1796 return mMeshEditor != nullptr;
1797}
1798
1799bool QgsMeshLayer::setDataProvider( QString const &provider, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags )
1800{
1801 mDatasetGroupStore->setPersistentProvider( nullptr, QStringList() );
1802
1803 delete mDataProvider;
1804 mProviderKey = provider;
1805 const QString dataSource = mDataSource;
1806
1807 mDataProvider = qobject_cast<QgsMeshDataProvider *>( QgsProviderRegistry::instance()->createProvider( provider, dataSource, options, flags ) );
1808
1809 if ( !mDataProvider )
1810 {
1811 QgsDebugMsgLevel( QStringLiteral( "Unable to get mesh data provider" ), 2 );
1812 return false;
1813 }
1814
1815 mDataProvider->setParent( this );
1816 QgsDebugMsgLevel( QStringLiteral( "Instantiated the mesh data provider plugin" ), 2 );
1817
1818 setValid( mDataProvider->isValid() );
1819 if ( !isValid() )
1820 {
1821 QgsDebugMsgLevel( QStringLiteral( "Invalid mesh provider plugin %1" ).arg( QString( mDataSource.toUtf8() ) ), 2 );
1822 return false;
1823 }
1824
1825 if ( !mTemporalProperties->isValid() )
1826 {
1827 mTemporalProperties->setDefaultsFromDataProviderTemporalCapabilities( dataProvider()->temporalCapabilities() );
1828 }
1829
1830 mDataProvider->setTemporalUnit( mTemporalUnit );
1831
1832 mDatasetGroupStore->setPersistentProvider( mDataProvider, mExtraDatasetUri );
1833
1834 setCrs( mDataProvider->crs() );
1835
1836 if ( provider == QLatin1String( "mesh_memory" ) )
1837 {
1838 // required so that source differs between memory layers
1839 mDataSource = mDataSource + QStringLiteral( "&uid=%1" ).arg( QUuid::createUuid().toString() );
1840 }
1841
1842 // set default style if required by flags or if the dataset group does not has a style yet
1843 for ( int i = 0; i < mDataProvider->datasetGroupCount(); ++i )
1844 {
1845 int globalIndex = mDatasetGroupStore->globalDatasetGroupIndexInSource( mDataProvider, i );
1846 if ( globalIndex != -1 &&
1847 ( !mRendererSettings.hasSettings( globalIndex ) || ( flags & QgsDataProvider::FlagLoadDefaultStyle ) ) )
1848 assignDefaultStyleToDatasetGroup( globalIndex );
1849 }
1850
1851 emit rendererChanged();
1853
1854 connect( mDataProvider, &QgsMeshDataProvider::dataChanged, this, &QgsMeshLayer::dataChanged );
1855
1856 return true;
1857}
1858
1860{
1861 return mTemporalProperties;
1862}
1863
1865{
1866 return mElevationProperties;
1867}
@ 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.
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:236
Class for metadata formatter.
QString linksSectionHtml() const
Formats the "Links" section according to a metadata object.
QString extentSectionHtml(const bool showSpatialExtent=true) const
Formats the "Extents" section according to a metadata object (extent and temporal).
QString contactsSectionHtml() const
Formats the "Contacts" section according to a metadata object.
QString identificationSectionHtml() const
Formats the "Identification" section according to a metadata object.
QString historySectionHtml() const
Formats the "History" section according to a metadata object.
QString accessSectionHtml() const
Formats the "Access" section according to a metadata object.
Base class for storage of map layer elevation properties.
static QString typeToString(QgsMapLayerType type)
Converts a map layer type to a string value.
static QgsMapLayerLegend * defaultMeshLegend(QgsMeshLayer *ml)
Create new legend implementation for mesh layer.
Base class for utility classes that encapsulate information necessary for rendering of map layers.
Base class for storage of map layer temporal properties.
virtual void setDefaultsFromDataProviderTemporalCapabilities(const QgsDataProviderTemporalCapabilities *capabilities)=0
Sets the layers temporal settings to appropriate defaults based on a provider's temporal capabilities...
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QString name
Definition: qgsmaplayer.h:76
virtual bool isSpatial() const
Returns true if the layer is considered a spatial layer, ie it has some form of geometry associated w...
void editingStopped()
Emitted when edited changes have been successfully written to the data provider.
QString source() const
Returns the source for the layer.
void setBlendMode(QPainter::CompositionMode blendMode)
Set the blending mode used for rendering a layer.
QgsMapLayerType type
Definition: qgsmaplayer.h:80
void trigger3DUpdate()
Will advise any 3D maps that this layer requires to be updated in the scene.
QgsMapLayer::LayerFlags flags() const
Returns the flags for this layer.
void editingStarted()
Emitted when editing on this layer has started.
virtual QString loadDefaultStyle(bool &resultFlag)
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QString mLayerName
Name of the layer - used for display.
Definition: qgsmaplayer.h:1945
void triggerRepaint(bool deferredUpdate=false)
Will advise the map canvas (and any other interested party) that this layer requires to be repainted.
QString crsHtmlMetadata() const
Returns a HTML fragment containing the layer's CRS metadata, for use in the htmlMetadata() method.
QgsLayerMetadata metadata
Definition: qgsmaplayer.h:78
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
virtual void setOpacity(double opacity)
Sets the opacity for the layer, where opacity is a value between 0 (totally transparent) and 1....
QString mProviderKey
Data provider key (name of the data provider)
Definition: qgsmaplayer.h:1983
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:1942
@ FlagTrustLayerMetadata
Trust layer metadata. Improves layer load time by skipping expensive checks like primary key unicity,...
Definition: qgsmaplayer.h:641
@ FlagForceReadOnly
Force open as read only.
Definition: qgsmaplayer.h:643
@ FlagDontResolveLayers
Don't resolve layer paths or create data providers for layers.
Definition: qgsmaplayer.h:640
void setValid(bool valid)
Sets whether layer is valid or not.
void readCommonStyle(const QDomElement &layerElement, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories)
Read style data common to all layer types.
QgsMapLayer::ReadFlags mReadFlags
Read flags. It's up to the subclass to respect these when restoring state from XML.
Definition: qgsmaplayer.h:1988
void setLegend(QgsMapLayerLegend *legend)
Assign a legend controller to the map layer.
double opacity
Definition: qgsmaplayer.h:82
@ Rendering
Rendering: scale visibility, simplify method, opacity.
Definition: qgsmaplayer.h:170
void layerModified()
Emitted when modifications has been done on layer.
void setProviderType(const QString &providerType)
Sets the providerType (provider key)
QString generalHtmlMetadata() const
Returns an HTML fragment containing general metadata information, for use in the htmlMetadata() metho...
void writeCommonStyle(QDomElement &layerElement, QDomDocument &document, const QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) const
Write style data common to all layer types.
void invalidateWgs84Extent()
Invalidates the WGS84 extent.
bool mShouldValidateCrs
true if the layer's CRS should be validated and invalid CRSes are not permitted.
Definition: qgsmaplayer.h:1995
void setCrs(const QgsCoordinateReferenceSystem &srs, bool emitSignal=true)
Sets layer's spatial reference system.
Abstract class to interpolate 3d stacked mesh data to 2d data.
QgsMeshDataBlock calculate(const QgsMesh3dDataBlock &block3d, QgsFeedback *feedback=nullptr) const
Calculated 2d block values from 3d stacked mesh values.
QgsMesh3dDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
bool isValid() const
Whether the block is valid.
QgsUnitTypes::TemporalUnit temporalUnit() const
Returns the temporal unit used to read data by the data provider.
QDateTime referenceTime() const
Returns the reference time.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 firstTimeStepDuration(int group) const
Returns the duration of the first time step of the dataset group with index group.
Base class for providing data for QgsMeshLayer.
virtual QgsMeshDriverMetadata driverMetadata() const
Returns the mesh driver metadata of the provider.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
void setTemporalUnit(QgsUnitTypes::TemporalUnit unit)
Sets the temporal unit of the provider and reload data if it changes.
virtual void close()=0
Closes the data provider and free every resources used.
virtual int vertexCount() const =0
Returns number of vertices in the native mesh.
virtual void populateMesh(QgsMesh *mesh) const =0
Populates the mesh vertices, edges and faces.
virtual bool saveMeshFrame(const QgsMesh &mesh)=0
Saves the mesh frame to the source.
virtual int edgeCount() const =0
Returns number of edges in the native mesh.
virtual int faceCount() const =0
Returns number of faces in the native mesh.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
QMap< QString, QString > extraOptions() const
Returns extra metadata options, for example description.
bool isVector() const
Returns whether dataset group has vector data.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
double minimum() const
Returns minimum scalar value/vector magnitude present for whole dataset group.
double maximum() const
Returns maximum scalar value/vector magnitude present for whole dataset group.
DataType
Location of where data is specified for datasets in the dataset group.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
Class used to register and access all the dataset groups related to a mesh layer.
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
Tree item for display of the mesh dataset groups.
int childCount() const
Returns the count of children.
QgsMeshDatasetGroupTreeItem * childFromDatasetGroupIndex(int index)
Returns the child with dataset group index Searches as depper as needed on the child hierarchy.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a dataset group.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group()
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
virtual QStringList extraDatasets() const =0
Returns list of additional dataset file URIs added using addDataset() calls.
QgsMeshDatasetValue represents single dataset value.
double y() const
Returns y value.
double x() const
Returns x value.
Holds metadata about mesh driver.
@ CanWriteMeshData
If the driver can write mesh data on file.
MeshDriverCapabilities capabilities() const
Returns the capabilities for this driver.
Class that represents an error during mesh editing.
Definition: qgsmesheditor.h:43
Qgis::MeshEditingErrorType errorType
Definition: qgsmesheditor.h:52
Class that makes edit operation on a mesh.
Definition: qgsmesheditor.h:68
QgsMeshEditingError initialize()
Initialize the mesh editor and return errors if the internal native mesh have topologic errors.
int validFacesCount() const
Returns the count of valid faces, that is non void faces in the mesh.
bool checkConsistency(QgsMeshEditingError &error) const
Return true if the edited mesh is consistent.
QgsRectangle extent() const
Returns the extent of the edited mesh.
int maximumVerticesPerFace() const
Returns the maximum count of vertices per face that the mesh can support.
void stopEditing()
Stops editing.
void meshEdited()
Emitted when the mesh is edited.
void resetTriangularMesh(QgsTriangularMesh *triangularMesh)
Resets the triangular mesh.
bool isModified() const
Returns whether the mesh has been modified.
int validVerticesCount() const
Returns the count of valid vertices, that is non void vertices in the mesh.
bool reindex(bool renumbering)
Reindexes the mesh, that is remove unusued index of face and vertices, this operation void the undo/r...
QgsMeshDatasetGroup * createZValueDatasetGroup()
Creates and returns a scalar dataset group with value on vertex that is can be used to access the Z v...
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:99
~QgsMeshLayer() override
QList< int > selectVerticesByExpression(QgsExpression expression)
Returns a list of vertex indexes that meet the condition defined by expression with the context expre...
void setMeshSimplificationSettings(const QgsMeshSimplificationSettings &meshSimplificationSettings)
Sets mesh simplification settings.
int datasetCount(const QgsMeshDatasetIndex &index) const
Returns the dataset count in the dataset groups.
QList< int > datasetGroupsIndexes() const
Returns the list of indexes of dataset groups handled by the layer.
void stopFrameEditing(const QgsCoordinateTransform &transform)
Stops edition of the mesh, re-indexes the faces and vertices, rebuilds the triangular mesh and its sp...
QgsRectangle extent() const override
Returns the extent of the layer.
void setStaticVectorDatasetIndex(const QgsMeshDatasetIndex &staticVectorDatasetIndex)
Sets the static vector dataset index that is rendered if the temporal properties is not active.
void setStaticScalarDatasetIndex(const QgsMeshDatasetIndex &staticScalarDatasetIndex)
Sets the static scalar dataset index that is rendered if the temporal properties is not active.
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains at mesh elements of given type.
QgsMeshRendererSettings rendererSettings() const
Returns renderer settings.
QgsMesh3dDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
QList< QgsMeshDatasetIndex > datasetIndexInRelativeTimeInterval(const QgsInterval &startRelativeTime, const QgsInterval &endRelativeTime, int datasetGroupIndex) const
Returns a list of dataset indexes from datasets group that are in a interval time from the layer refe...
void activeScalarDatasetGroupChanged(int index)
Emitted when active scalar group dataset is changed.
int datasetGroupCount() const
Returns the dataset groups count handle by the layer.
void updateTriangularMesh(const QgsCoordinateTransform &transform=QgsCoordinateTransform())
Gets native mesh and updates (creates if it doesn't exist) the base triangular mesh.
bool addDatasets(const QString &path, const QDateTime &defaultReferenceTime=QDateTime())
Adds datasets to the mesh from file with path.
bool isModified() const override
Returns whether the mesh frame has been modified since the last save.
void activeVectorDatasetGroupChanged(int index)
Emitted when active vector group dataset is changed.
void reload() override
Synchronises with changes in the datasource.
QgsMeshDatasetIndex activeScalarDatasetAtTime(const QgsDateTimeRange &timeRange) const
Returns dataset index from active scalar group depending on the time range.
QgsPointXY snapOnElement(QgsMesh::ElementType elementType, const QgsPointXY &point, double searchRadius)
Returns the position of the snapped point on the mesh element closest to point intersecting with the ...
bool readXml(const QDomNode &layer_node, QgsReadWriteContext &context) override
Called by readLayerXML(), used by children to read state specific to them from project files.
QStringList subLayers() const override
Returns the sublayers of this layer.
QgsMeshEditor * meshEditor()
Returns a pointer to the mesh editor own by the mesh layer.
void setDatasetGroupTreeRootItem(QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root items of the dataset group tree item.
QgsMeshDatasetValue dataset1dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point, double searchRadius) const
Returns the value of 1D mesh dataset defined on edge that are in the search area defined by point ans...
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
QString loadDefaultStyle(bool &resultFlag) FINAL
Retrieve the default style for this layer if one exists (either as a .qml file on disk or as a record...
QgsTriangularMesh * triangularMeshByLodIndex(int lodIndex) const
Returns triangular corresponding to the index of level of details.
QString htmlMetadata() const override
Obtain a formatted HTML string containing assorted metadata for this layer.
int meshFaceCount() const
Returns the faces count of the mesh frame.
QList< int > selectFacesByExpression(QgsExpression expression)
Returns a list of faces indexes that meet the condition defined by expression with the context expres...
QgsMesh3dDataBlock dataset3dValue(const QgsMeshDatasetIndex &index, const QgsPointXY &point) const
Returns the 3d values of stacked 3d mesh defined by the given point.
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 edition of the mesh frame.
QString encodedSource(const QString &source, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by derived classes to encode provider's specific data source to proje...
QgsMeshDatasetIndex staticVectorDatasetIndex() const
Returns the static vector dataset index that is rendered if the temporal properties is not active.
QgsMeshDatasetIndex datasetIndexAtRelativeTime(const QgsInterval &relativeTime, int datasetGroupIndex) const
Returns dataset index from datasets group depending on the relative time from the layer reference tim...
bool writeXml(QDomNode &layer_node, QDomDocument &doc, const QgsReadWriteContext &context) const override
Called by writeLayerXML(), used by children to write state specific to them to project files.
bool commitFrameEditing(const QgsCoordinateTransform &transform, bool continueEditing=true)
Commits edition of the mesh frame, Rebuilds the triangular mesh and its spatial index with transform,...
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.
bool startFrameEditing(const QgsCoordinateTransform &transform)
Starts edition of the mesh frame.
bool reindex(const QgsCoordinateTransform &transform, bool renumber)
Re-indexes the faces and vertices, and renumber the indexes if renumber is true.
QgsMeshDatasetValue datasetValue(const QgsMeshDatasetIndex &index, int valueIndex) const
Returns vector/scalar value associated with the index from the dataset To read multiple continuous va...
QgsMeshTimeSettings timeSettings() const
Returns time format settings.
QgsMapLayerTemporalProperties * temporalProperties() override
Returns the layer's temporal properties.
bool writeSymbology(QDomNode &node, QDomDocument &doc, QString &errorMessage, const QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) const override
int meshVertexCount() const
Returns the vertices count of the mesh frame.
void setReferenceTime(const QDateTime &referenceTime)
Sets the reference time of the layer.
bool readStyle(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, StyleCategories categories=AllStyleCategories) override
Read the style for the current layer from the DOM node supplied.
int extraDatasetGroupCount() const
Returns the extra dataset groups count handle by the layer.
void setRendererSettings(const QgsMeshRendererSettings &settings)
Sets new renderer settings.
qint64 datasetRelativeTimeInMilliseconds(const QgsMeshDatasetIndex &index)
Returns the relative time (in milliseconds) of the dataset from the reference time of its group.
QgsTriangularMesh * triangularMesh(double minimumTriangleSize=0) const
Returns triangular mesh (nullptr before rendering or calling to updateMesh).
void setTemporalMatchingMethod(const QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod &matchingMethod)
Sets the method used to match the temporal dataset from a requested time, see activeVectorDatasetAtTi...
QgsMeshDatasetGroupTreeItem * datasetGroupTreeRootItem() const
Returns the root items of the dataset group tree item.
bool readSymbology(const QDomNode &node, QString &errorMessage, QgsReadWriteContext &context, QgsMapLayer::StyleCategories categories=QgsMapLayer::AllStyleCategories) override
QString providerType() const
Returns the provider type for this layer.
QString decodedSource(const QString &source, const QString &provider, const QgsReadWriteContext &context) const override
Called by readLayerXML(), used by derived classes to decode provider's specific data source from proj...
void reloaded()
Emitted when the mesh layer is reloaded, see reload()
QString formatTime(double hours)
Returns (date) time in hours formatted to human readable form.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the dataset groups metadata.
QgsMeshLayerRendererCache * rendererCache()
Returns native mesh (nullptr before rendering)
void setTimeSettings(const QgsMeshTimeSettings &settings)
Sets time format settings.
QgsMeshLayer(const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib=QStringLiteral("mesh_memory"), const QgsMeshLayer::LayerOptions &options=QgsMeshLayer::LayerOptions())
Constructor - creates a mesh layer.
Represents a mesh renderer settings for mesh object.
void setEnabled(bool enabled)
Sets whether mesh structure rendering is enabled.
Represents a mesh renderer settings for scalar datasets.
void setClassificationMinimumMaximum(double minimum, double maximum)
Sets min/max values used for creation of the color ramp shader.
void setColorRampShader(const QgsColorRampShader &shader)
Sets color ramp shader function.
QgsColorRampShader colorRampShader() const
Returns color ramp shader function.
@ NeighbourAverage
Does a simple average of values defined for all surrounding faces/vertices.
void setEdgeStrokeWidth(const QgsInterpolatedLineWidth &strokeWidth)
Sets the stroke width used to render edges scalar dataset.
void setDataResamplingMethod(const DataResamplingMethod &dataResamplingMethod)
Sets data interpolation method.
Represents all mesh renderer settings.
void setActiveVectorDatasetGroup(int activeVectorDatasetGroup)
Sets the active vector dataset group.
QgsMeshRendererScalarSettings scalarSettings(int groupIndex) const
Returns renderer settings.
int activeVectorDatasetGroup() const
Returns the active vector dataset group.
bool hasSettings(int datasetGroupIndex) const
Returns whether the group with index has render settings (scalar or vector)
int activeScalarDatasetGroup() const
Returns the active scalar dataset group.
QgsMesh3dAveragingMethod * averagingMethod() const
Returns averaging method for conversion of 3d stacked mesh data to 2d data.
void setActiveScalarDatasetGroup(int activeScalarDatasetGroup)
Sets the active scalar dataset group.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context=QgsReadWriteContext())
Reads configuration from the given DOM element.
void setVectorSettings(int groupIndex, const QgsMeshRendererVectorSettings &settings)
Sets new renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context=QgsReadWriteContext()) const
Writes configuration to a new DOM element.
void setScalarSettings(int groupIndex, const QgsMeshRendererScalarSettings &settings)
Sets new renderer settings.
void setNativeMeshSettings(const QgsMeshRendererMeshSettings &settings)
Sets new native mesh renderer settings, triggers repaint.
Represents a renderer settings for vector datasets.
void setColorRampShader(const QgsColorRampShader &colorRampShader)
Returns the color ramp shader used to render vector datasets.
Represents an overview renderer settings.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const
Writes configuration to a new DOM element.
void setEnabled(bool isEnabled)
Sets if the overview is active.
double reductionFactor() const
Returns the reduction factor used to build simplified mesh.
bool isEnabled() const
Returns if the overview is active.
void readXml(const QDomElement &elem, const QgsReadWriteContext &context)
Reads configuration from the given DOM element.
Represents a mesh time settings for mesh datasets.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static QgsPainting::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
Definition: qgspainting.cpp:80
static QPainter::CompositionMode getCompositionMode(QgsPainting::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
Definition: qgspainting.cpp:20
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer.
Definition: qgspainting.h:37
QString writePath(const QString &filename) const
Prepare a filename to save it to the project file.
QString readPath(const QString &filename) const
Turn filename read from the project file to an absolute path.
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
double distance(double x, double y) const SIP_HOLDGIL
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspointxy.h:211
double sqrDistToSegment(double x1, double y1, double x2, double y2, QgsPointXY &minDistPoint, double epsilon=DEFAULT_SEGMENT_EPSILON) const SIP_HOLDGIL
Returns the minimum distance between this point and a segment.
Definition: qgspointxy.cpp:95
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
double distance(double x, double y) const SIP_HOLDGIL
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:343
Q_GADGET double x
Definition: qgspoint.h:52
double y
Definition: qgspoint.h:53
Encapsulates properties and constraints relating to fetching elevation profiles from different source...
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
virtual void setMaximumValue(double value)
Sets the maximum value for the raster shader.
virtual void setMinimumValue(double value)
Sets the minimum value for the raster shader.
The class is used as a container of context for various read/write operations on other objects.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
Contains information about the context of a rendering operation.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
static QgsStyle * defaultStyle()
Returns default application-wide style.
Definition: qgsstyle.cpp:145
QgsColorRamp * colorRamp(const QString &name) const
Returns a new copy of the specified color ramp.
Definition: qgsstyle.cpp:462
bool isActive() const
Returns true if the temporal property is active.
void setIsActive(bool active)
Sets whether the temporal property is active.
static QgsMeshEditingError checkTopology(const QgsMesh &mesh, int maxVerticesPerFace)
Checks the topology of the mesh mesh, if error occurs, this mesh can't be edited.
Triangular/Derived Mesh is mesh with vertices in map coordinates.
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
QList< int > edgeIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of edges intersecting given bounding box It uses spatial indexing.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
const QVector< QgsMeshEdge > & edges() const
Returns edges.
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains mesh elements of given type.
const QVector< QgsMeshVertex > & faceCentroids() const
Returns centroids of the native faces in map CRS.
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
TemporalUnit
Temporal units.
Definition: qgsunittypes.h:150
@ TemporalMilliseconds
Milliseconds.
Definition: qgsunittypes.h:151
QgsMapLayerType
Types of layers that can be added to a map.
Definition: qgis.h:47
@ MeshLayer
Mesh layer. Added in QGIS 3.2.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
#define SIP_SKIP
Definition: qgis_sip.h:126
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QVector< int > QgsMeshFace
List of vertex indexes.
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
Setting options for creating vector data providers.
Setting options for loading mesh layers.
Definition: qgsmeshlayer.h:107
QgsCoordinateTransformContext transformContext
Coordinate transform context.
Definition: qgsmeshlayer.h:120
bool loadDefaultStyle
Set to true if the default layer style should be loaded.
Definition: qgsmeshlayer.h:126
bool skipCrsValidation
Controls whether the layer is allowed to have an invalid/unknown CRS.
Definition: qgsmeshlayer.h:141
Mesh - vertices, edges and faces.
ElementType
Defines type of mesh elements.