QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsmeshdataset.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshdataset.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 "qgsmeshdataset.h"
19
20#include "qgis.h"
21#include "qgsmeshdataprovider.h"
22#include "qgsrectangle.h"
23
24#include <QRegularExpression>
25#include <QRegularExpressionMatch>
26
28 : mGroupIndex( group ), mDatasetIndex( dataset )
29{}
30
32{
33 return mGroupIndex;
34}
35
37{
38 return mDatasetIndex;
39}
40
42{
43 return ( group() > -1 ) && ( dataset() > -1 );
44}
45
47{
48 if ( isValid() && other.isValid() )
49 return other.group() == group() && other.dataset() == dataset();
50 else
51 return isValid() == other.isValid();
52}
53
55{
56 return !( operator==( other ) );
57}
58
60 : mX( x ), mY( y )
61{}
62
66
68{
69 if ( std::isnan( mY ) )
70 {
71 return mX;
72 }
73 else if ( std::isnan( mX ) )
74 {
75 return std::numeric_limits<double>::quiet_NaN();
76 }
77 else
78 {
79 return std::sqrt( ( mX ) * ( mX ) + ( mY ) * ( mY ) );
80 }
81}
82
84{
85 setX( scalar );
86}
87
89{
90 mX = x;
91}
92
94{
95 mY = y;
96}
97
99{
100 return mX;
101}
102
104{
105 return mY;
106}
107
109{
110 bool equal = std::isnan( mX ) == std::isnan( other.x() );
111 equal &= std::isnan( mY ) == std::isnan( other.y() );
112
113 if ( equal )
114 {
115 if ( std::isnan( mY ) )
116 {
117 equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
118 }
119 else
120 {
121 equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
122 equal &= qgsDoubleNear( other.y(), mY, 1E-8 );
123 }
124 }
125 return equal;
126}
127
129 const QString uri,
130 bool isScalar,
132 double minimum,
133 double maximum,
134 int maximumVerticalLevels,
135 const QDateTime &referenceTime,
136 bool isTemporal,
137 const QMap<QString, QString> &extraOptions )
138 : mName( name )
139 , mUri( uri )
140 , mIsScalar( isScalar )
141 , mDataType( dataType )
142 , mMinimumValue( minimum )
143 , mMaximumValue( maximum )
144 , mExtraOptions( extraOptions )
145 , mMaximumVerticalLevelsCount( maximumVerticalLevels )
146 , mReferenceTime( referenceTime )
147 , mIsTemporal( isTemporal )
148{
149 // this relies on the naming convention used by MDAL's NetCDF driver: <group name>_<dimension_name>:<dimension_value>
150 // If future MDAL releases expose quantities via a standard API then we can safely remove this and port to the new API.
151 const thread_local QRegularExpression parentQuantityRegex( QStringLiteral( "^(.*):.*?$" ) );
152 const QRegularExpressionMatch parentQuantityMatch = parentQuantityRegex.match( mName );
153 if ( parentQuantityMatch.hasMatch() )
154 {
155 mParentQuantityName = parentQuantityMatch.captured( 1 );
156 }
157}
158
159QMap<QString, QString> QgsMeshDatasetGroupMetadata::extraOptions() const
160{
161 return mExtraOptions;
162}
163
165{
166 return !mIsScalar;
167}
168
170{
171 return mIsScalar;
172}
173
175{
176 return mIsTemporal;
177}
178
180{
181 return mName;
182}
183
185{
186 return mParentQuantityName;
187}
188
191{
192 return mDataType;
193}
194
196{
197 return mMinimumValue;
198}
199
201{
202 return mMaximumValue;
203}
204
206{
207 return mMaximumVerticalLevelsCount;
208}
209
211{
212 return mReferenceTime;
213}
214
216{
217 return mUri;
218}
219
221 double time,
222 bool isValid,
223 double minimum,
224 double maximum,
225 int maximumVerticalLevels )
226 : mTime( time )
227 , mIsValid( isValid )
228 , mMinimumValue( minimum )
229 , mMaximumValue( maximum )
230 , mMaximumVerticalLevelsCount( maximumVerticalLevels )
231{
232}
233
235{
236 return mTime;
237}
238
240{
241 return mIsValid;
242}
243
245{
246 return mMinimumValue;
247}
248
250{
251 return mMaximumValue;
252}
253
255{
256 return mMaximumVerticalLevelsCount;
257}
258
263
269
271{
272 return mType;
273}
274
276{
277 return mSize;
278}
279
281{
282 return ( count() > 0 ) && ( mIsValid );
283}
284
286{
287 if ( !isValid() )
288 return QgsMeshDatasetValue();
289
290 Q_ASSERT( mType != ActiveFlagInteger );
291
292 if ( mType == ScalarDouble )
293 return QgsMeshDatasetValue( mDoubleBuffer[index] );
294
295 return QgsMeshDatasetValue(
296 mDoubleBuffer[2 * index],
297 mDoubleBuffer[2 * index + 1]
298 );
299}
300
301bool QgsMeshDataBlock::active( int index ) const
302{
303 if ( !isValid() )
304 return false;
305
306 Q_ASSERT( mType == ActiveFlagInteger );
307
308 if ( mIntegerBuffer.empty() )
309 return true;
310 else
311 return bool( mIntegerBuffer[index] );
312}
313
314void QgsMeshDataBlock::setActive( const QVector<int> &vals )
315{
316 Q_ASSERT( mType == ActiveFlagInteger );
317 Q_ASSERT( vals.size() == count() );
318
319 mIntegerBuffer = vals;
320 setValid( true );
321}
322
323QVector<int> QgsMeshDataBlock::active() const
324{
325 Q_ASSERT( mType == ActiveFlagInteger );
326 return mIntegerBuffer;
327}
328
329QVector<double> QgsMeshDataBlock::values() const
330{
331 Q_ASSERT( mType != ActiveFlagInteger );
332
333 return mDoubleBuffer;
334}
335
336void QgsMeshDataBlock::setValues( const QVector<double> &vals )
337{
338 Q_ASSERT( mType != ActiveFlagInteger );
339 Q_ASSERT( mType == ScalarDouble ? vals.size() == count() : vals.size() == 2 * count() );
340
341 mDoubleBuffer = vals;
342 setValid( true );
343}
344
346{
347 mIsValid = valid;
348}
349
351
353
355 : mSize( other.mSize )
356 , mIsValid( other.mIsValid )
357 , mIsVector( other.mIsVector )
358 , mVerticalLevelsCount( other.mVerticalLevelsCount )
359 , mVerticalLevels( other.mVerticalLevels )
360 , mFaceToVolumeIndex( other.mFaceToVolumeIndex )
361 , mDoubleBuffer( other.mDoubleBuffer )
362{
363
364}
365
367 : mSize( other.mSize )
368 , mIsValid( other.mIsValid )
369 , mIsVector( other.mIsVector )
370 , mVerticalLevelsCount( std::move( other.mVerticalLevelsCount ) )
371 , mVerticalLevels( std::move( other.mVerticalLevels ) )
372 , mFaceToVolumeIndex( std::move( other.mFaceToVolumeIndex ) )
373 , mDoubleBuffer( std::move( other.mDoubleBuffer ) )
374{
375
376}
377
379{
380 if ( &other == this )
381 return *this;
382
383 mSize = other.mSize;
384 mIsValid = other.mIsValid;
385 mIsVector = other.mIsVector;
386 mVerticalLevelsCount = other.mVerticalLevelsCount;
387 mVerticalLevels = other.mVerticalLevels;
388 mFaceToVolumeIndex = other.mFaceToVolumeIndex;
389 mDoubleBuffer = other.mDoubleBuffer;
390 return *this;
391}
392
394{
395 if ( &other == this )
396 return *this;
397
398 mSize = other.mSize;
399 mIsValid = other.mIsValid;
400 mIsVector = other.mIsVector;
401 mVerticalLevelsCount = std::move( other.mVerticalLevelsCount );
402 mVerticalLevels = std::move( other.mVerticalLevels );
403 mFaceToVolumeIndex = std::move( other.mFaceToVolumeIndex );
404 mDoubleBuffer = std::move( other.mDoubleBuffer );
405 return *this;
406}
407
409 : mSize( count )
410 , mIsVector( isVector )
411{
412}
413
415{
416 return mIsValid;
417}
418
420{
421 return mIsVector;
422}
423
425{
426 return mSize;
427}
428
430{
431 if ( mFaceToVolumeIndex.empty() )
432 return -1;
433 return mFaceToVolumeIndex[0];
434}
435
437{
438 if ( mFaceToVolumeIndex.empty() || mVerticalLevelsCount.empty() )
439 return -1;
440 const int lastVolumeStartIndex = mFaceToVolumeIndex[mFaceToVolumeIndex.size() - 1];
441 const int volumesCountInLastRow = mVerticalLevelsCount[mVerticalLevelsCount.size() - 1];
442 return lastVolumeStartIndex + volumesCountInLastRow;
443}
444
449
451{
452 Q_ASSERT( isValid() );
453 return mVerticalLevelsCount;
454}
455
457{
458 Q_ASSERT( faceToVolumeIndex.size() == count() );
459 mFaceToVolumeIndex = faceToVolumeIndex;
460}
461
463{
464 Q_ASSERT( verticalLevelsCount.size() == count() );
465 mVerticalLevelsCount = verticalLevelsCount;
466}
467
469{
470 Q_ASSERT( isValid() );
471 return mVerticalLevels;
472}
473
475{
476 Q_ASSERT( verticalLevels.size() == volumesCount() + count() );
477 mVerticalLevels = verticalLevels;
478}
479
481{
482 Q_ASSERT( isValid() );
483 return mFaceToVolumeIndex;
484}
485
486QVector<double> QgsMesh3DDataBlock::values() const
487{
488 Q_ASSERT( isValid() );
489 return mDoubleBuffer;
490}
491
493{
494 if ( !isValid() )
495 return QgsMeshDatasetValue();
496
497 if ( !mIsVector )
498 return QgsMeshDatasetValue( mDoubleBuffer[volumeIndex] );
499
500 return QgsMeshDatasetValue(
501 mDoubleBuffer[2 * volumeIndex],
502 mDoubleBuffer[2 * volumeIndex + 1]
503 );
504}
505
506void QgsMesh3DDataBlock::setValues( const QVector<double> &doubleBuffer )
507{
508 Q_ASSERT( doubleBuffer.size() == ( isVector() ? 2 * volumesCount() : volumesCount() ) );
509 mDoubleBuffer = doubleBuffer;
510}
511
513{
514 mIsValid = valid;
515}
516
518
520 bool isVector,
521 int index )
522 : mOriginalName( defaultName )
523 , mSourceName( sourceName )
524 , mIsVector( isVector )
525 , mDatasetGroupIndex( index )
526{
527}
528
530{
531 Q_UNUSED( context );
532 if ( itemElement.hasAttribute( QStringLiteral( "display-name" ) ) )
533 mUserName = itemElement.attribute( QStringLiteral( "display-name" ), mUserName );
534
535 if ( itemElement.hasAttribute( QStringLiteral( "original-name" ) ) )
536 mOriginalName = itemElement.attribute( QStringLiteral( "original-name" ), mOriginalName );
537
538 if ( itemElement.hasAttribute( QStringLiteral( "source-name" ) ) )
539 mSourceName = itemElement.attribute( QStringLiteral( "source-name" ), mSourceName );
540
541 if ( itemElement.hasAttribute( QStringLiteral( "is-vector" ) ) )
542 mIsVector = itemElement.attribute( QStringLiteral( "is-vector" ) ).toInt();
543
544 if ( itemElement.hasAttribute( QStringLiteral( "dataset-index" ) ) )
545 mDatasetGroupIndex = itemElement.attribute( QStringLiteral( "dataset-index" ) ).toInt();
546
547 if ( itemElement.hasAttribute( QStringLiteral( "is-enabled" ) ) )
548 mIsEnabled = itemElement.attribute( QStringLiteral( "is-enabled" ) ).toInt();
549
550 if ( itemElement.hasAttribute( QStringLiteral( "dataset-group-type" ) ) )
551 mDatasetGroupType = static_cast<QgsMeshDatasetGroup::Type>( itemElement.attribute( QStringLiteral( "dataset-group-type" ) ) .toInt() ) ;
552
553 if ( itemElement.hasAttribute( QStringLiteral( "description" ) ) )
554 mDescription = itemElement.attribute( QStringLiteral( "description" ) );
555
556 QDomElement dependOnElement = itemElement.firstChildElement( QStringLiteral( "dependent-on-item" ) );
557 while ( !dependOnElement.isNull() )
558 {
559 if ( dependOnElement.hasAttribute( QStringLiteral( "dataset-index" ) ) )
560 mDatasetGroupDependentOn.append( dependOnElement.attribute( QStringLiteral( "dataset-index" ) ).toInt() );
561 dependOnElement = dependOnElement.nextSiblingElement( QStringLiteral( "dependent-on-item" ) );
562 }
563
564 QDomElement dependencyElement = itemElement.firstChildElement( QStringLiteral( "dependency-item" ) );
565 while ( !dependencyElement.isNull() )
566 {
567 if ( dependencyElement.hasAttribute( QStringLiteral( "dataset-index" ) ) )
568 mDatasetGroupDependencies.append( dependencyElement.attribute( QStringLiteral( "dataset-index" ) ).toInt() );
569 dependencyElement = dependencyElement.nextSiblingElement( QStringLiteral( "dependency-item" ) );
570 }
571
572 QDomElement childElement = itemElement.firstChildElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
573 while ( !childElement.isNull() )
574 {
575 appendChild( new QgsMeshDatasetGroupTreeItem( childElement, context ) );
576 childElement = childElement.nextSiblingElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
577 }
578}
579
581{
582 // Remove from where this item is linked
583
584 freeAsDependency();
585 freeFromDependencies();
586 qDeleteAll( mChildren );
587 if ( mParent )
588 {
589 mParent->mDatasetGroupIndexToChild.remove( mDatasetGroupIndex );
590 mParent->mChildren.removeOne( this );
591 }
592}
593
595{
596 QgsMeshDatasetGroupTreeItem *other = new QgsMeshDatasetGroupTreeItem( mOriginalName, mSourceName, mIsVector, mDatasetGroupIndex );
597 *other = *this;
598
599 other->mChildren.clear();
600 other->mDatasetGroupIndexToChild.clear();
601 if ( !mChildren.empty() )
602 for ( int i = 0; i < mChildren.count(); ++i )
603 other->appendChild( mChildren.at( i )->clone() );
604
605 return other;
606}
607
609{
610 mChildren.append( item );
611 item->mParent = this;
612 mDatasetGroupIndexToChild[item->datasetGroupIndex()] = item;
613}
614
619
621{
622 if ( row < mChildren.count() )
623 return mChildren.at( row );
624 else
625 return nullptr;
626}
627
629{
630 if ( mDatasetGroupIndexToChild.empty() )
631 return nullptr;
632
633 const QMap<int, QgsMeshDatasetGroupTreeItem *>::iterator it = mDatasetGroupIndexToChild.find( index );
634
635 if ( it != mDatasetGroupIndexToChild.end() )
636 return it.value();
637 else
638 {
639 QgsMeshDatasetGroupTreeItem *item = nullptr;
640 for ( int i = 0; i < mChildren.count(); ++i )
641 {
642 item = mChildren.at( i )->childFromDatasetGroupIndex( index );
643 if ( item )
644 break;
645 }
646 return item;
647 }
648}
649
651{
652 return mChildren.count();
653}
654
656{
657 int count = 0;
658 for ( int i = 0; i < mChildren.count(); ++i )
659 {
660 count++;
661 count += mChildren.at( i )->totalChildCount();
662 }
663 return count;
664}
665
667{
668 QList<int> indexesList;
669
670 for ( int i = 0; i < mChildren.count(); ++i )
671 {
672 if ( mChildren.at( i )->isEnabled() )
673 indexesList.append( mChildren.at( i )->datasetGroupIndex() );
674 indexesList.append( mChildren.at( i )->enabledDatasetGroupIndexes() );
675 }
676
677 return indexesList;
678}
679
684
686{
687 if ( mParent )
688 return mParent->mChildren.indexOf( const_cast<QgsMeshDatasetGroupTreeItem *>( this ) );
689
690 return 0;
691}
692
694{
695 if ( mUserName.isEmpty() )
696 return mOriginalName;
697 else
698 return mUserName;
699}
700
702{
703 return mIsVector;
704}
705
707{
708 return mDatasetGroupIndex;
709}
710
712{
713 return mIsEnabled;
714}
715
717{
718 mIsEnabled = enabled;
719}
720
722{
723 return mOriginalName;
724}
725
727{
728 return mDatasetGroupType;
729}
730
732{
733 return mDescription;
734}
735
737{
738 if ( datasetGroup )
739 {
740 mDescription = datasetGroup->description();
741 mDatasetGroupType = datasetGroup->type();
742 const QStringList &datasetGroupNames = datasetGroup->datasetGroupNamesDependentOn();
743 for ( const QString &varName : datasetGroupNames )
744 {
745 QgsMeshDatasetGroupTreeItem *varItem = searchItemBySourceName( varName );
746 if ( varItem )
747 {
748 varItem->mDatasetGroupDependencies.append( this->datasetGroupIndex() );
749 mDatasetGroupDependentOn.append( varItem->datasetGroupIndex() );
750 }
751 }
752 }
753}
754
756{
757 mDatasetGroupType = QgsMeshDatasetGroup::Persistent;
758 mDatasetGroupDependentOn.clear();
759 mDescription = uri;
760}
761
762QDomElement QgsMeshDatasetGroupTreeItem::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
763{
764 Q_UNUSED( context );
765
766 QDomElement itemElement = doc.createElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
767 itemElement.setAttribute( QStringLiteral( "display-name" ), mUserName );
768 itemElement.setAttribute( QStringLiteral( "source-name" ), mSourceName );
769 itemElement.setAttribute( QStringLiteral( "original-name" ), mOriginalName );
770 itemElement.setAttribute( QStringLiteral( "is-vector" ), mIsVector ? true : false );
771 itemElement.setAttribute( QStringLiteral( "dataset-index" ), mDatasetGroupIndex );
772 itemElement.setAttribute( QStringLiteral( "is-enabled" ), mIsEnabled ? true : false );
773 itemElement.setAttribute( QStringLiteral( "dataset-group-type" ), mDatasetGroupType );
774 itemElement.setAttribute( QStringLiteral( "description" ), mDescription );
775
776 for ( const int index : mDatasetGroupDependentOn )
777 {
778 QDomElement dependOnElement = doc.createElement( QStringLiteral( "dependent-on-item" ) );
779 dependOnElement.setAttribute( QStringLiteral( "dataset-index" ), index );
780 itemElement.appendChild( dependOnElement );
781 }
782
783 for ( const int index : mDatasetGroupDependencies )
784 {
785 QDomElement dependencyElement = doc.createElement( QStringLiteral( "dependency-item" ) );
786 dependencyElement.setAttribute( QStringLiteral( "dataset-index" ), index );
787 itemElement.appendChild( dependencyElement );
788 }
789
790 for ( int i = 0; i < mChildren.count(); ++i )
791 itemElement.appendChild( mChildren.at( i )->writeXml( doc, context ) );
792
793 return itemElement;
794}
795
797{
798 QList<int> dependencies;
799 QgsMeshDatasetGroupTreeItem *root = rootItem();
800 for ( const int index : mDatasetGroupDependencies )
801 {
802 if ( !dependencies.contains( index ) )
803 dependencies.append( index );
805 if ( item )
806 dependencies.append( item->groupIndexDependencies() );
807 }
808
809 for ( int i = 0; i < childCount(); ++i )
810 {
811 dependencies.append( child( i )->groupIndexDependencies() );
812 }
813
814 return dependencies;
815}
816
817QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::searchItemBySourceName( const QString &sourceName ) const
818{
819 QgsMeshDatasetGroupTreeItem *baseItem = rootItem();
820
821 QList<QgsMeshDatasetGroupTreeItem *> itemToCheck;
822 itemToCheck.append( baseItem );
823 while ( baseItem && baseItem->providerName() != sourceName && !itemToCheck.isEmpty() )
824 {
825 for ( int i = 0; i < baseItem->childCount(); ++i )
826 itemToCheck.append( baseItem->child( i ) );
827 itemToCheck.removeOne( baseItem );
828 if ( !itemToCheck.empty() )
829 baseItem = itemToCheck.first();
830 else
831 baseItem = nullptr;
832 }
833
834 return baseItem;
835}
836
837QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::rootItem() const
838{
839 const QgsMeshDatasetGroupTreeItem *baseItem = this;
840 while ( baseItem->parentItem() )
841 baseItem = baseItem->parentItem();
842
843 return const_cast<QgsMeshDatasetGroupTreeItem *>( baseItem );
844}
845
846void QgsMeshDatasetGroupTreeItem::freeAsDependency()
847{
848 QgsMeshDatasetGroupTreeItem *root = rootItem();
849 if ( !root )
850 return;
851
852 for ( const int index : mDatasetGroupDependentOn )
853 {
855 if ( item )
856 item->mDatasetGroupDependencies.removeOne( this->datasetGroupIndex() );
857 }
858}
859
860void QgsMeshDatasetGroupTreeItem::freeFromDependencies()
861{
862 QgsMeshDatasetGroupTreeItem *root = rootItem();
863 for ( const int index : mDatasetGroupDependencies )
864 {
866 if ( item )
867 item->mDatasetGroupDependentOn.removeOne( this->datasetGroupIndex() );
868 }
869}
870
872{
873 return mSourceName;
874}
875
877{
878 mUserName = name;
879}
880
881
883{
884 if ( valueIndex >= 0 && valueIndex < values.count() )
885 return values[valueIndex];
886 else
887 return QgsMeshDatasetValue();
888}
889
890QgsMeshDataBlock QgsMeshMemoryDataset::datasetValues( bool isScalar, int valueIndex, int count ) const
891{
893 QVector<double> buf( isScalar ? count : 2 * count );
894 for ( int i = 0; i < count; ++i )
895 {
896 const int idx = valueIndex + i;
897 if ( ( idx < 0 ) || ( idx >= values.size() ) )
898 return ret;
899
900 const QgsMeshDatasetValue val = values[ valueIndex + i ];
901 if ( isScalar )
902 buf[i] = val.x();
903 else
904 {
905 buf[2 * i] = val.x();
906 buf[2 * i + 1] = val.y();
907 }
908 }
909 ret.setValues( buf );
910 return ret;
911}
912
914{
916 if ( active.isEmpty() ||
917 ( faceIndex < 0 ) ||
918 ( faceIndex + count > active.size() )
919 )
920 ret.setValid( true );
921 else
922 ret.setActive( active );
923 return ret;
924}
925
930
932{
933 double min = std::numeric_limits<double>::max();
934 double max = std::numeric_limits<double>::lowest();
935
936 if ( !valid )
937 return;
938
939
940 bool firstIteration = true;
941 for ( int i = 0; i < values.size(); ++i )
942 {
943 const double v = values[i].scalar();
944
945 if ( std::isnan( v ) )
946 continue;
947 if ( firstIteration )
948 {
949 firstIteration = false;
950 min = v;
951 max = v;
952 }
953 else
954 {
955 if ( v < min )
956 min = v;
957 if ( v > max )
958 max = v;
959 }
960 }
961
962 minimum = min;
963 maximum = max;
964}
965
966bool QgsMeshMemoryDataset::isActive( int faceIndex ) const
967{
968 if ( active.isEmpty() || faceIndex >= active.count() )
969 return true;
970 else
971 return active.at( faceIndex );
972}
973
975{
976 return values.count();
977}
978
983
988
990{
992 name(),
993 QString(),
994 isScalar(),
995 dataType(),
996 minimum(),
997 maximum(),
998 0,
999 mReferenceTime,
1000 datasetCount() > 1,
1002 );
1003}
1004
1006{
1007 return memoryDatasets.size();
1008}
1009
1011{
1012 if ( datasetIndex >= 0 && datasetIndex < memoryDatasets.count() )
1013 return memoryDatasets[datasetIndex]->metadata();
1014 else
1015 return QgsMeshDatasetMetadata();
1016}
1017
1019{
1020 return memoryDatasets[index].get();
1021}
1022
1023void QgsMeshMemoryDatasetGroup::addDataset( std::shared_ptr<QgsMeshMemoryDataset> dataset )
1024{
1025 dataset->calculateMinMax();
1026 memoryDatasets.push_back( dataset );
1027}
1028
1033
1038
1039std::shared_ptr<const QgsMeshMemoryDataset> QgsMeshMemoryDatasetGroup::constDataset( int index ) const
1040{
1041 return memoryDatasets[index];
1042}
1043
1044QDomElement QgsMeshMemoryDatasetGroup::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
1045{
1046 Q_UNUSED( doc )
1047 Q_UNUSED( context )
1048 return QDomElement();
1049}
1050
1052{
1053 updateStatistic();
1054}
1055
1057{
1058 mIsStatisticObsolete = true;
1059}
1060
1062{
1063 return QStringList();
1064}
1065
1067{
1068 return QString();
1069}
1070
1071void QgsMeshDatasetGroup::setReferenceTime( const QDateTime &referenceTime )
1072{
1073 mReferenceTime = referenceTime;
1074}
1075
1076void QgsMeshDatasetGroup::updateStatistic() const
1077{
1078 if ( !mIsStatisticObsolete )
1079 return;
1080
1081 double min = std::numeric_limits<double>::max();
1082 double max = std::numeric_limits<double>::lowest();
1083
1084 const int count = datasetCount();
1085 for ( int i = 0; i < count; ++i )
1086 {
1087 const QgsMeshDatasetMetadata &meta = datasetMetadata( i );
1088 min = std::min( min, meta.minimum() );
1089 max = std::max( max, meta.maximum() );
1090 }
1091 mMinimum = min;
1092 mMaximum = max;
1093
1094 mIsStatisticObsolete = false;
1095}
1096
1098{
1099 for ( int i = 0; i < datasetCount(); ++i )
1100 if ( dataset( i )->valuesCount() != count )
1101 return false;
1102 return true;
1103}
1104
1107
1109
1111
1113{
1114 updateStatistic();
1115 return mMinimum;
1116}
1117
1119{
1120 updateStatistic();
1121 return mMaximum;
1122}
1123
1124void QgsMeshDatasetGroup::setMinimumMaximum( double min, double max ) const
1125{
1126 mMinimum = min;
1127 mMaximum = max;
1128}
1129
1131{
1132 return mName;
1133}
1134
1136{
1137 mName = name;
1138}
1139
1144
1149
1150void QgsMeshDatasetGroup::addExtraMetadata( QString key, QString value )
1151{
1152 mMetadata.insert( key, value );
1153}
1154
1155QMap<QString, QString> QgsMeshDatasetGroup::extraMetadata() const
1156{
1157 return mMetadata;
1158}
1159
1161{
1162 return mIsScalar;
1163}
1164
1169
1170
1174
1176{
1177 if ( mMesh && valueIndex >= 0 && valueIndex < mMesh->vertexCount() )
1178 return mMesh->vertex( valueIndex ).z();
1179
1180 return std::numeric_limits<double>::quiet_NaN();
1181}
1182
1183QgsMeshDataBlock QgsMeshVerticesElevationDataset::datasetValues( bool isScalar, int valueIndex, int count ) const
1184{
1185 if ( !isScalar || !mMesh )
1186 return QgsMeshDataBlock();
1187
1189 int effectiveValueCount = std::min( count, ( mMesh->vertexCount() - valueIndex ) );
1190 QVector<double> values( effectiveValueCount );
1191 for ( int i = valueIndex; i < effectiveValueCount; ++i )
1192 values[i] = mMesh->vertex( i - valueIndex ).z();
1193 block.setValues( values );
1194 block.setValid( true );
1195 return block;
1196}
1197
1199{
1200 QgsMeshDataBlock block( QgsMeshDataBlock::ActiveFlagInteger, std::min( count, ( mMesh->faceCount() - faceIndex ) ) );
1201 block.setValid( true );
1202 return block;
1203}
1204
1206{
1207 double min = std::numeric_limits<double>::max();
1208 double max = -std::numeric_limits<double>::max();
1209 if ( mMesh )
1210 for ( int i = 0; i < mMesh->vertexCount(); ++i )
1211 {
1212 const double z = mMesh->vertex( i ).z();
1213 if ( min > z )
1214 min = z;
1215 if ( max < z )
1216 max = z;
1217 }
1218
1219 return QgsMeshDatasetMetadata( 0, true, min, max, 0 );
1220}
1221
1223{
1224 if ( mMesh )
1225 return mMesh->vertexCount();
1226
1227 return 0;
1228}
1229
1236
1241
1243{
1244 if ( datasetIndex != 0 )
1245 return QgsMeshDatasetMetadata();
1246
1247 return mDataset->metadata();
1248}
1249
1251
1253{
1254 if ( index != 0 )
1255 return nullptr;
1256
1257 return mDataset.get();
1258}
1259
1264
void setFaceToVolumeIndex(const QVector< int > &faceToVolumeIndex)
Sets the indexing between faces and volumes.
QgsMeshDatasetValue value(int volumeIndex) const
Returns the value at volume centers.
QVector< double > values() const
Returns the values at volume centers.
void setVerticalLevels(const QVector< double > &verticalLevels)
Sets the vertical levels height.
void setValues(const QVector< double > &doubleBuffer)
Sets the values at volume centers.
QgsMesh3DDataBlock()
Constructs an invalid block.
bool isVector() const
Whether we store vector values.
int count() const
Number of 2d faces for which the volume data is stored in the block.
int volumesCount() const
Returns number of volumes stored in the buffer.
int firstVolumeIndex() const
Index of the first volume stored in the buffer (absolute).
int lastVolumeIndex() const
Index of the last volume stored in the buffer (absolute).
QVector< int > verticalLevelsCount() const
Returns number of vertical level above 2d faces.
bool isValid() const
Whether the block is valid.
void setVerticalLevelsCount(const QVector< int > &verticalLevelsCount)
Sets the vertical level counts.
void setValid(bool valid)
Sets block validity.
QgsMesh3DDataBlock & operator=(const QgsMesh3DDataBlock &other)
QVector< int > faceToVolumeIndex() const
Returns the indexing between faces and volumes.
QVector< double > verticalLevels() const
Returns the vertical levels height.
A block of integers/doubles from a mesh dataset.
QgsMeshDatasetValue value(int index) const
Returns a value represented by the index For active flag the behavior is undefined.
QVector< double > values() const
Returns buffer to the array with values For vector it is pairs (x1, y1, x2, y2, .....
void setActive(const QVector< int > &vals)
Sets active flag values.
QVector< int > active() const
Returns active flag array.
bool isValid() const
Whether the block is valid.
QgsMeshDataBlock()
Constructs an invalid block.
DataType type() const
Type of data stored in the block.
DataType
Type of data stored in the block.
@ ScalarDouble
Scalar double values.
@ Vector2DDouble
Vector double pairs (x1, y1, x2, y2, ... ).
@ ActiveFlagInteger
Integer boolean flag whether face is active.
int count() const
Number of items stored in the block.
void setValues(const QVector< double > &vals)
Sets values.
void setValid(bool valid)
Sets block validity.
A collection of dataset group metadata such as whether the data is vector or scalar,...
bool isTemporal() const
Returns whether the dataset group is temporal (contains time-related dataset).
QMap< QString, QString > extraOptions() const
Returns extra metadata options, for example description.
bool isVector() const
Returns whether dataset group has vector data.
QString parentQuantityName() const
Returns the name of the dataset's parent quantity, if available.
QString name() const
Returns name of the dataset group.
bool isScalar() const
Returns whether dataset group has scalar data.
int maximumVerticalLevelsCount() const
Returns maximum number of vertical levels for 3d stacked meshes.
QgsMeshDatasetGroupMetadata()=default
Constructs an empty metadata object.
DataType dataType() const
Returns whether dataset group data is defined on vertices or faces or volumes.
QDateTime referenceTime() const
Returns the reference time.
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.
QString uri() const
Returns the uri of the source.
Tree item for display of the mesh dataset groups.
void setName(const QString &name)
Overrides the default name with the name to display.
QgsMeshDatasetGroupTreeItem * clone() const
Clones the item.
QList< int > groupIndexDependencies() const
Returns a list of group index corresponding to dataset group that depends on the dataset group repres...
bool isVector() const
Return true if the dataset group is vector.
QString defaultName() const
Returns the default name.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context)
Writes the item and its children in a DOM document.
void setPersistentDatasetGroup(const QString &uri)
Set parameters of the item in accordance with the persistent dataset group with uri.
int childCount() const
Returns the count of children.
~QgsMeshDatasetGroupTreeItem()
Destructor, destructs also the children.
int datasetGroupIndex() const
Returns the dataset group index.
QgsMeshDatasetGroupTreeItem * parentItem() const
Returns the parent item, nullptr if it is root item.
QgsMeshDatasetGroupTreeItem * childFromDatasetGroupIndex(int index)
Returns the child with dataset group index Searches as depper as needed on the child hierarchy.
void removeChild(QgsMeshDatasetGroupTreeItem *item)
Removes and destroy a item child if exists.
void setIsEnabled(bool isEnabled)
Sets whether the item is enabled, that is if it is displayed in view.
int totalChildCount() const
Returns the total count of children, that is included deeper children and disabled items.
void setDatasetGroup(QgsMeshDatasetGroup *datasetGroup)
Set parameters of the item in accordance with the dataset group.
QList< int > enabledDatasetGroupIndexes() const
Returns a list of enabled dataset group indexes, included deeper children.
bool isEnabled() const
Returns true if the item is enabled, i.e.
QgsMeshDatasetGroupTreeItem()
Constructor for an empty dataset group tree item.
QString providerName() const
Returns the name used by the provider to identify the dataset.
void appendChild(QgsMeshDatasetGroupTreeItem *item)
Appends a child item.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
QString description() const
Returns description about the dataset group (URI, formula,...).
int row() const
Returns the position of the item in the parent.
QString name() const
Returns the name of the item This name is the default name if the name has not been overridden (.
QgsMeshDatasetGroup::Type datasetGroupType() const
Returns the dataset group type.
Abstract class that represents a dataset group.
bool isScalar() const
Returns whether the group contain scalar values.
void addExtraMetadata(QString key, QString value)
Adds extra metadata to the group.
bool checkValueCountPerDataset(int count) const
Returns whether all the datasets contain count values.
virtual QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const =0
Returns the metadata of the dataset with index datasetIndex.
void setMinimumMaximum(double min, double max) const
Overrides the minimum and the maximum value of the whole dataset group.
void setStatisticObsolete() const
Sets statistic obsolete, that means statistic will be recalculated when requested.
void setIsScalar(bool isScalar)
Sets whether the group contain scalar values.
QgsMeshDatasetGroup()=default
void setDataType(const QgsMeshDatasetGroupMetadata::DataType &dataType)
Sets the data type of the dataset group.
QString name() const
Returns the name of the dataset group.
QgsMeshDatasetGroupMetadata::DataType dataType() const
Returns the data type of the dataset group.
virtual ~QgsMeshDatasetGroup()
virtual QStringList datasetGroupNamesDependentOn() const
Returns the dataset group variable name which this dataset group depends on.
virtual QString description() const
Returns some information about the dataset group.
QMap< QString, QString > mMetadata
Type
Type of the dataset group.
@ Memory
Temporary dataset group in memory.
@ Persistent
Dataset group store in a file.
void setReferenceTime(const QDateTime &referenceTime)
Sets the reference time of the dataset group.
double maximum() const
Returns the maximum value of the whole dataset group.
virtual QgsMeshDatasetGroup::Type type() const =0
Returns the type of dataset group.
QgsMeshDatasetGroupMetadata groupMetadata() const
Returns the metadata of the dataset group.
double minimum() const
Returns the minimum value of the whole dataset group.
QMap< QString, QString > extraMetadata() const
Returns all the extra metadata of the group.
void setName(const QString &name)
Sets the name of the dataset group.
virtual int datasetCount() const =0
Returns the count of datasets in the group.
void calculateStatistic() const
Calculates the statistics (minimum and maximum).
virtual QgsMeshDataset * dataset(int index) const =0
Returns the dataset with index.
QgsMeshDatasetGroupMetadata::DataType mDataType
QgsMeshDatasetIndex(int group=-1, int dataset=-1)
Creates an index. -1 represents invalid group/dataset.
bool operator==(QgsMeshDatasetIndex other) const
bool operator!=(QgsMeshDatasetIndex other) const
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().
Represents mesh dataset metadata, such as whether the data is valid or the associated time.
double maximum() const
Returns maximum scalar value/vector magnitude present for the dataset.
int maximumVerticalLevelsCount() const
Returns maximum number of vertical levels for 3d stacked meshes.
double minimum() const
Returns minimum scalar value/vector magnitude present for the dataset.
double time() const
Returns the time value for this dataset.
bool isValid() const
Returns whether dataset is valid.
QgsMeshDatasetMetadata()=default
Constructs an empty metadata object.
Represents a single mesh dataset value.
void setY(double y)
Sets Y value.
void set(double scalar)
Sets scalar value.
double y() const
Returns y value.
bool operator==(QgsMeshDatasetValue other) const
QgsMeshDatasetValue()=default
Default Ctor, initialize to NaN.
double scalar() const
Returns magnitude of vector for vector data or scalar value for scalar data.
QgsMeshDatasetValue(double x, double y)
Constructor for vector value.
double x() const
Returns x value.
void setX(double x)
Sets X value.
Abstract class that represents a mesh dataset.
void addDataset(std::shared_ptr< QgsMeshMemoryDataset > dataset)
Adds a memory dataset to the group.
QgsMeshMemoryDatasetGroup()=default
QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const override
Returns the metadata of the dataset with index datasetIndex.
void clearDatasets()
Removes all the datasets from the group.
void initialize() override
Initialize the dataset group.
std::shared_ptr< const QgsMeshMemoryDataset > constDataset(int index) const
Returns the dataset with index.
QVector< std::shared_ptr< QgsMeshMemoryDataset > > memoryDatasets
Contains all the memory datasets.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context) const override
Returns a invalid DOM element.
QgsMeshDataset * dataset(int index) const override
Returns the dataset with index.
int datasetCount() const override
Returns the count of datasets in the group.
QgsMeshDataBlock areFacesActive(int faceIndex, int count) const override
Returns whether faces are active.
bool isActive(int faceIndex) const override
Returns whether the face is active.
QVector< QgsMeshDatasetValue > values
QgsMeshDatasetValue datasetValue(int valueIndex) const override
Returns the value with index valueIndex.
QgsMeshDatasetMetadata metadata() const override
Returns the metadata of the dataset.
QgsMeshDataBlock datasetValues(bool isScalar, int valueIndex, int count) const override
Returns count values from valueIndex.
int valuesCount() const override
Returns the values count.
QVector< int > active
void calculateMinMax()
Calculates the minimum and the maximum of this group.
int datasetCount() const override
Returns the count of datasets in the group.
QgsMeshVerticesElevationDatasetGroup(QString name, QgsMesh *mesh)
Constructor with a name and linked to mesh.
void initialize() override
Initialize the dataset group.
QgsMeshDatasetGroup::Type type() const override
Returns the type of dataset group.
QgsMeshDataset * dataset(int index) const override
Returns the dataset with index.
QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const override
Returns the metadata of the dataset with index datasetIndex.
Represents a dataset with elevation value of the vertices of an existing mesh that can be edited.
QgsMeshDatasetValue datasetValue(int valueIndex) const override
Returns the value with index valueIndex.
int valuesCount() const override
Returns the values count.
QgsMeshDataBlock areFacesActive(int faceIndex, int count) const override
Returns whether faces are active.
QgsMeshDatasetMetadata metadata() const override
Returns the metadata of the dataset.
QgsMeshDataBlock datasetValues(bool isScalar, int valueIndex, int count) const override
Returns count values from valueIndex.
QgsMeshVerticesElevationDataset(QgsMesh *mesh)
Constructor.
A container for the context for various read/write operations on objects.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
Mesh - vertices, edges and faces.