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