QGIS API Documentation 3.99.0-Master (d270888f95f)
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#include <QString>
27
28using namespace Qt::StringLiterals;
29
31 : mGroupIndex( group ), mDatasetIndex( dataset )
32{}
33
35{
36 return mGroupIndex;
37}
38
40{
41 return mDatasetIndex;
42}
43
45{
46 return ( group() > -1 ) && ( dataset() > -1 );
47}
48
50{
51 if ( isValid() && other.isValid() )
52 return other.group() == group() && other.dataset() == dataset();
53 else
54 return isValid() == other.isValid();
55}
56
58{
59 return !( operator==( other ) );
60}
61
63 : mX( x ), mY( y )
64{}
65
69
71{
72 if ( std::isnan( mY ) )
73 {
74 return mX;
75 }
76 else if ( std::isnan( mX ) )
77 {
78 return std::numeric_limits<double>::quiet_NaN();
79 }
80 else
81 {
82 return std::sqrt( ( mX ) * ( mX ) + ( mY ) * ( mY ) );
83 }
84}
85
87{
88 setX( scalar );
89}
90
92{
93 mX = x;
94}
95
97{
98 mY = y;
99}
100
102{
103 return mX;
104}
105
107{
108 return mY;
109}
110
112{
113 bool equal = std::isnan( mX ) == std::isnan( other.x() );
114 equal &= std::isnan( mY ) == std::isnan( other.y() );
115
116 if ( equal )
117 {
118 if ( std::isnan( mY ) )
119 {
120 equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
121 }
122 else
123 {
124 equal &= qgsDoubleNear( other.x(), mX, 1E-8 );
125 equal &= qgsDoubleNear( other.y(), mY, 1E-8 );
126 }
127 }
128 return equal;
129}
130
132 const QString uri,
133 bool isScalar,
135 double minimum,
136 double maximum,
137 int maximumVerticalLevels,
138 const QDateTime &referenceTime,
139 bool isTemporal,
140 const QMap<QString, QString> &extraOptions )
141 : mName( name )
142 , mUri( uri )
143 , mIsScalar( isScalar )
144 , mDataType( dataType )
145 , mMinimumValue( minimum )
146 , mMaximumValue( maximum )
147 , mExtraOptions( extraOptions )
148 , mMaximumVerticalLevelsCount( maximumVerticalLevels )
149 , mReferenceTime( referenceTime )
150 , mIsTemporal( isTemporal )
151{
152 // this relies on the naming convention used by MDAL's NetCDF driver: <group name>_<dimension_name>:<dimension_value>
153 // If future MDAL releases expose quantities via a standard API then we can safely remove this and port to the new API.
154 const thread_local QRegularExpression parentQuantityRegex( u"^(.*):.*?$"_s );
155 const QRegularExpressionMatch parentQuantityMatch = parentQuantityRegex.match( mName );
156 if ( parentQuantityMatch.hasMatch() )
157 {
158 mParentQuantityName = parentQuantityMatch.captured( 1 );
159 }
160}
161
162QMap<QString, QString> QgsMeshDatasetGroupMetadata::extraOptions() const
163{
164 return mExtraOptions;
165}
166
168{
169 return !mIsScalar;
170}
171
173{
174 return mIsScalar;
175}
176
178{
179 return mIsTemporal;
180}
181
183{
184 return mName;
185}
186
188{
189 return mParentQuantityName;
190}
191
194{
195 return mDataType;
196}
197
199{
200 return mMinimumValue;
201}
202
204{
205 return mMaximumValue;
206}
207
209{
210 return mMaximumVerticalLevelsCount;
211}
212
214{
215 return mReferenceTime;
216}
217
219{
220 return mUri;
221}
222
224 double time,
225 bool isValid,
226 double minimum,
227 double maximum,
228 int maximumVerticalLevels )
229 : mTime( time )
230 , mIsValid( isValid )
231 , mMinimumValue( minimum )
232 , mMaximumValue( maximum )
233 , mMaximumVerticalLevelsCount( maximumVerticalLevels )
234{
235}
236
238{
239 return mTime;
240}
241
243{
244 return mIsValid;
245}
246
248{
249 return mMinimumValue;
250}
251
253{
254 return mMaximumValue;
255}
256
258{
259 return mMaximumVerticalLevelsCount;
260}
261
266
272
274{
275 return mType;
276}
277
279{
280 return mSize;
281}
282
284{
285 return ( count() > 0 ) && ( mIsValid );
286}
287
289{
290 if ( !isValid() )
291 return QgsMeshDatasetValue();
292
293 Q_ASSERT( mType != ActiveFlagInteger );
294
295 if ( mType == ScalarDouble )
296 return QgsMeshDatasetValue( mDoubleBuffer[index] );
297
298 return QgsMeshDatasetValue(
299 mDoubleBuffer[2 * index],
300 mDoubleBuffer[2 * index + 1]
301 );
302}
303
304bool QgsMeshDataBlock::active( int index ) const
305{
306 if ( !isValid() )
307 return false;
308
309 Q_ASSERT( mType == ActiveFlagInteger );
310
311 if ( mIntegerBuffer.empty() )
312 return true;
313 else
314 return bool( mIntegerBuffer[index] );
315}
316
317void QgsMeshDataBlock::setActive( const QVector<int> &vals )
318{
319 Q_ASSERT( mType == ActiveFlagInteger );
320 Q_ASSERT( vals.size() == count() );
321
322 mIntegerBuffer = vals;
323 setValid( true );
324}
325
326QVector<int> QgsMeshDataBlock::active() const
327{
328 Q_ASSERT( mType == ActiveFlagInteger );
329 return mIntegerBuffer;
330}
331
332QVector<double> QgsMeshDataBlock::values() const
333{
334 Q_ASSERT( mType != ActiveFlagInteger );
335
336 return mDoubleBuffer;
337}
338
339void QgsMeshDataBlock::setValues( const QVector<double> &vals )
340{
341 Q_ASSERT( mType != ActiveFlagInteger );
342 Q_ASSERT( mType == ScalarDouble ? vals.size() == count() : vals.size() == 2 * count() );
343
344 mDoubleBuffer = vals;
345 setValid( true );
346}
347
349{
350 mIsValid = valid;
351}
352
354
356
358 : mSize( other.mSize )
359 , mIsValid( other.mIsValid )
360 , mIsVector( other.mIsVector )
361 , mVerticalLevelsCount( other.mVerticalLevelsCount )
362 , mVerticalLevels( other.mVerticalLevels )
363 , mFaceToVolumeIndex( other.mFaceToVolumeIndex )
364 , mDoubleBuffer( other.mDoubleBuffer )
365{
366
367}
368
370 : mSize( other.mSize )
371 , mIsValid( other.mIsValid )
372 , mIsVector( other.mIsVector )
373 , mVerticalLevelsCount( std::move( other.mVerticalLevelsCount ) )
374 , mVerticalLevels( std::move( other.mVerticalLevels ) )
375 , mFaceToVolumeIndex( std::move( other.mFaceToVolumeIndex ) )
376 , mDoubleBuffer( std::move( other.mDoubleBuffer ) )
377{
378
379}
380
382{
383 if ( &other == this )
384 return *this;
385
386 mSize = other.mSize;
387 mIsValid = other.mIsValid;
388 mIsVector = other.mIsVector;
389 mVerticalLevelsCount = other.mVerticalLevelsCount;
390 mVerticalLevels = other.mVerticalLevels;
391 mFaceToVolumeIndex = other.mFaceToVolumeIndex;
392 mDoubleBuffer = other.mDoubleBuffer;
393 return *this;
394}
395
397{
398 if ( &other == this )
399 return *this;
400
401 mSize = other.mSize;
402 mIsValid = other.mIsValid;
403 mIsVector = other.mIsVector;
404 mVerticalLevelsCount = std::move( other.mVerticalLevelsCount );
405 mVerticalLevels = std::move( other.mVerticalLevels );
406 mFaceToVolumeIndex = std::move( other.mFaceToVolumeIndex );
407 mDoubleBuffer = std::move( other.mDoubleBuffer );
408 return *this;
409}
410
412 : mSize( count )
413 , mIsVector( isVector )
414{
415}
416
418{
419 return mIsValid;
420}
421
423{
424 return mIsVector;
425}
426
428{
429 return mSize;
430}
431
433{
434 if ( mFaceToVolumeIndex.empty() )
435 return -1;
436 return mFaceToVolumeIndex[0];
437}
438
440{
441 if ( mFaceToVolumeIndex.empty() || mVerticalLevelsCount.empty() )
442 return -1;
443 const int lastVolumeStartIndex = mFaceToVolumeIndex[mFaceToVolumeIndex.size() - 1];
444 const int volumesCountInLastRow = mVerticalLevelsCount[mVerticalLevelsCount.size() - 1];
445 return lastVolumeStartIndex + volumesCountInLastRow;
446}
447
452
454{
455 Q_ASSERT( isValid() );
456 return mVerticalLevelsCount;
457}
458
460{
461 Q_ASSERT( faceToVolumeIndex.size() == count() );
462 mFaceToVolumeIndex = faceToVolumeIndex;
463}
464
466{
467 Q_ASSERT( verticalLevelsCount.size() == count() );
468 mVerticalLevelsCount = verticalLevelsCount;
469}
470
472{
473 Q_ASSERT( isValid() );
474 return mVerticalLevels;
475}
476
478{
479 Q_ASSERT( verticalLevels.size() == volumesCount() + count() );
480 mVerticalLevels = verticalLevels;
481}
482
484{
485 Q_ASSERT( isValid() );
486 return mFaceToVolumeIndex;
487}
488
489QVector<double> QgsMesh3DDataBlock::values() const
490{
491 Q_ASSERT( isValid() );
492 return mDoubleBuffer;
493}
494
496{
497 if ( !isValid() )
498 return QgsMeshDatasetValue();
499
500 if ( !mIsVector )
501 return QgsMeshDatasetValue( mDoubleBuffer[volumeIndex] );
502
503 return QgsMeshDatasetValue(
504 mDoubleBuffer[2 * volumeIndex],
505 mDoubleBuffer[2 * volumeIndex + 1]
506 );
507}
508
509void QgsMesh3DDataBlock::setValues( const QVector<double> &doubleBuffer )
510{
511 Q_ASSERT( doubleBuffer.size() == ( isVector() ? 2 * volumesCount() : volumesCount() ) );
512 mDoubleBuffer = doubleBuffer;
513}
514
516{
517 mIsValid = valid;
518}
519
521
523 bool isVector,
524 int index )
525 : mOriginalName( defaultName )
526 , mSourceName( sourceName )
527 , mIsVector( isVector )
528 , mDatasetGroupIndex( index )
529{
530}
531
533{
534 Q_UNUSED( context );
535 if ( itemElement.hasAttribute( u"display-name"_s ) )
536 mUserName = itemElement.attribute( u"display-name"_s, mUserName );
537
538 if ( itemElement.hasAttribute( u"original-name"_s ) )
539 mOriginalName = itemElement.attribute( u"original-name"_s, mOriginalName );
540
541 if ( itemElement.hasAttribute( u"source-name"_s ) )
542 mSourceName = itemElement.attribute( u"source-name"_s, mSourceName );
543
544 if ( itemElement.hasAttribute( u"is-vector"_s ) )
545 mIsVector = itemElement.attribute( u"is-vector"_s ).toInt();
546
547 if ( itemElement.hasAttribute( u"dataset-index"_s ) )
548 mDatasetGroupIndex = itemElement.attribute( u"dataset-index"_s ).toInt();
549
550 if ( itemElement.hasAttribute( u"is-enabled"_s ) )
551 mIsEnabled = itemElement.attribute( u"is-enabled"_s ).toInt();
552
553 if ( itemElement.hasAttribute( u"dataset-group-type"_s ) )
554 mDatasetGroupType = static_cast<QgsMeshDatasetGroup::Type>( itemElement.attribute( u"dataset-group-type"_s ) .toInt() ) ;
555
556 if ( itemElement.hasAttribute( u"description"_s ) )
557 mDescription = itemElement.attribute( u"description"_s );
558
559 QDomElement dependOnElement = itemElement.firstChildElement( u"dependent-on-item"_s );
560 while ( !dependOnElement.isNull() )
561 {
562 if ( dependOnElement.hasAttribute( u"dataset-index"_s ) )
563 mDatasetGroupDependentOn.append( dependOnElement.attribute( u"dataset-index"_s ).toInt() );
564 dependOnElement = dependOnElement.nextSiblingElement( u"dependent-on-item"_s );
565 }
566
567 QDomElement dependencyElement = itemElement.firstChildElement( u"dependency-item"_s );
568 while ( !dependencyElement.isNull() )
569 {
570 if ( dependencyElement.hasAttribute( u"dataset-index"_s ) )
571 mDatasetGroupDependencies.append( dependencyElement.attribute( u"dataset-index"_s ).toInt() );
572 dependencyElement = dependencyElement.nextSiblingElement( u"dependency-item"_s );
573 }
574
575 QDomElement childElement = itemElement.firstChildElement( u"mesh-dataset-group-tree-item"_s );
576 while ( !childElement.isNull() )
577 {
578 appendChild( new QgsMeshDatasetGroupTreeItem( childElement, context ) );
579 childElement = childElement.nextSiblingElement( u"mesh-dataset-group-tree-item"_s );
580 }
581}
582
584{
585 // Remove from where this item is linked
586
587 freeAsDependency();
588 freeFromDependencies();
589 qDeleteAll( mChildren );
590 if ( mParent )
591 {
592 mParent->mDatasetGroupIndexToChild.remove( mDatasetGroupIndex );
593 mParent->mChildren.removeOne( this );
594 }
595}
596
598{
599 QgsMeshDatasetGroupTreeItem *other = new QgsMeshDatasetGroupTreeItem( mOriginalName, mSourceName, mIsVector, mDatasetGroupIndex );
600 *other = *this;
601
602 other->mChildren.clear();
603 other->mDatasetGroupIndexToChild.clear();
604 if ( !mChildren.empty() )
605 for ( int i = 0; i < mChildren.count(); ++i )
606 other->appendChild( mChildren.at( i )->clone() );
607
608 return other;
609}
610
612{
613 mChildren.append( item );
614 item->mParent = this;
615 mDatasetGroupIndexToChild[item->datasetGroupIndex()] = item;
616}
617
622
624{
625 if ( row < mChildren.count() )
626 return mChildren.at( row );
627 else
628 return nullptr;
629}
630
632{
633 if ( mDatasetGroupIndexToChild.empty() )
634 return nullptr;
635
636 const QMap<int, QgsMeshDatasetGroupTreeItem *>::iterator it = mDatasetGroupIndexToChild.find( index );
637
638 if ( it != mDatasetGroupIndexToChild.end() )
639 return it.value();
640 else
641 {
642 QgsMeshDatasetGroupTreeItem *item = nullptr;
643 for ( int i = 0; i < mChildren.count(); ++i )
644 {
645 item = mChildren.at( i )->childFromDatasetGroupIndex( index );
646 if ( item )
647 break;
648 }
649 return item;
650 }
651}
652
654{
655 return mChildren.count();
656}
657
659{
660 int count = 0;
661 for ( int i = 0; i < mChildren.count(); ++i )
662 {
663 count++;
664 count += mChildren.at( i )->totalChildCount();
665 }
666 return count;
667}
668
670{
671 QList<int> indexesList;
672
673 for ( int i = 0; i < mChildren.count(); ++i )
674 {
675 if ( mChildren.at( i )->isEnabled() )
676 indexesList.append( mChildren.at( i )->datasetGroupIndex() );
677 indexesList.append( mChildren.at( i )->enabledDatasetGroupIndexes() );
678 }
679
680 return indexesList;
681}
682
687
689{
690 if ( mParent )
691 return mParent->mChildren.indexOf( const_cast<QgsMeshDatasetGroupTreeItem *>( this ) );
692
693 return 0;
694}
695
697{
698 if ( mUserName.isEmpty() )
699 return mOriginalName;
700 else
701 return mUserName;
702}
703
705{
706 return mIsVector;
707}
708
710{
711 return mDatasetGroupIndex;
712}
713
715{
716 return mIsEnabled;
717}
718
720{
721 mIsEnabled = enabled;
722}
723
725{
726 return mOriginalName;
727}
728
730{
731 return mDatasetGroupType;
732}
733
735{
736 return mDescription;
737}
738
740{
741 if ( datasetGroup )
742 {
743 mDescription = datasetGroup->description();
744 mDatasetGroupType = datasetGroup->type();
745 const QStringList &datasetGroupNames = datasetGroup->datasetGroupNamesDependentOn();
746 for ( const QString &varName : datasetGroupNames )
747 {
748 QgsMeshDatasetGroupTreeItem *varItem = searchItemBySourceName( varName );
749 if ( varItem )
750 {
751 varItem->mDatasetGroupDependencies.append( this->datasetGroupIndex() );
752 mDatasetGroupDependentOn.append( varItem->datasetGroupIndex() );
753 }
754 }
755 }
756}
757
759{
760 mDatasetGroupType = QgsMeshDatasetGroup::Persistent;
761 mDatasetGroupDependentOn.clear();
762 mDescription = uri;
763}
764
765QDomElement QgsMeshDatasetGroupTreeItem::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
766{
767 Q_UNUSED( context );
768
769 QDomElement itemElement = doc.createElement( u"mesh-dataset-group-tree-item"_s );
770 itemElement.setAttribute( u"display-name"_s, mUserName );
771 itemElement.setAttribute( u"source-name"_s, mSourceName );
772 itemElement.setAttribute( u"original-name"_s, mOriginalName );
773 itemElement.setAttribute( u"is-vector"_s, mIsVector ? true : false );
774 itemElement.setAttribute( u"dataset-index"_s, mDatasetGroupIndex );
775 itemElement.setAttribute( u"is-enabled"_s, mIsEnabled ? true : false );
776 itemElement.setAttribute( u"dataset-group-type"_s, mDatasetGroupType );
777 itemElement.setAttribute( u"description"_s, mDescription );
778
779 for ( const int index : mDatasetGroupDependentOn )
780 {
781 QDomElement dependOnElement = doc.createElement( u"dependent-on-item"_s );
782 dependOnElement.setAttribute( u"dataset-index"_s, index );
783 itemElement.appendChild( dependOnElement );
784 }
785
786 for ( const int index : mDatasetGroupDependencies )
787 {
788 QDomElement dependencyElement = doc.createElement( u"dependency-item"_s );
789 dependencyElement.setAttribute( u"dataset-index"_s, index );
790 itemElement.appendChild( dependencyElement );
791 }
792
793 for ( int i = 0; i < mChildren.count(); ++i )
794 itemElement.appendChild( mChildren.at( i )->writeXml( doc, context ) );
795
796 return itemElement;
797}
798
800{
801 QList<int> dependencies;
802 QgsMeshDatasetGroupTreeItem *root = rootItem();
803 for ( const int index : mDatasetGroupDependencies )
804 {
805 if ( !dependencies.contains( index ) )
806 dependencies.append( index );
808 if ( item )
809 dependencies.append( item->groupIndexDependencies() );
810 }
811
812 for ( int i = 0; i < childCount(); ++i )
813 {
814 dependencies.append( child( i )->groupIndexDependencies() );
815 }
816
817 return dependencies;
818}
819
820QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::searchItemBySourceName( const QString &sourceName ) const
821{
822 QgsMeshDatasetGroupTreeItem *baseItem = rootItem();
823
824 QList<QgsMeshDatasetGroupTreeItem *> itemToCheck;
825 itemToCheck.append( baseItem );
826 while ( baseItem && baseItem->providerName() != sourceName && !itemToCheck.isEmpty() )
827 {
828 for ( int i = 0; i < baseItem->childCount(); ++i )
829 itemToCheck.append( baseItem->child( i ) );
830 itemToCheck.removeOne( baseItem );
831 if ( !itemToCheck.empty() )
832 baseItem = itemToCheck.first();
833 else
834 baseItem = nullptr;
835 }
836
837 return baseItem;
838}
839
840QgsMeshDatasetGroupTreeItem *QgsMeshDatasetGroupTreeItem::rootItem() const
841{
842 const QgsMeshDatasetGroupTreeItem *baseItem = this;
843 while ( baseItem->parentItem() )
844 baseItem = baseItem->parentItem();
845
846 return const_cast<QgsMeshDatasetGroupTreeItem *>( baseItem );
847}
848
849void QgsMeshDatasetGroupTreeItem::freeAsDependency()
850{
851 QgsMeshDatasetGroupTreeItem *root = rootItem();
852 if ( !root )
853 return;
854
855 for ( const int index : mDatasetGroupDependentOn )
856 {
858 if ( item )
859 item->mDatasetGroupDependencies.removeOne( this->datasetGroupIndex() );
860 }
861}
862
863void QgsMeshDatasetGroupTreeItem::freeFromDependencies()
864{
865 QgsMeshDatasetGroupTreeItem *root = rootItem();
866 for ( const int index : mDatasetGroupDependencies )
867 {
869 if ( item )
870 item->mDatasetGroupDependentOn.removeOne( this->datasetGroupIndex() );
871 }
872}
873
875{
876 return mSourceName;
877}
878
880{
881 mUserName = name;
882}
883
884
886{
887 if ( valueIndex >= 0 && valueIndex < values.count() )
888 return values[valueIndex];
889 else
890 return QgsMeshDatasetValue();
891}
892
893QgsMeshDataBlock QgsMeshMemoryDataset::datasetValues( bool isScalar, int valueIndex, int count ) const
894{
896 QVector<double> buf( isScalar ? count : 2 * count );
897 for ( int i = 0; i < count; ++i )
898 {
899 const int idx = valueIndex + i;
900 if ( ( idx < 0 ) || ( idx >= values.size() ) )
901 return ret;
902
903 const QgsMeshDatasetValue val = values[ valueIndex + i ];
904 if ( isScalar )
905 buf[i] = val.x();
906 else
907 {
908 buf[2 * i] = val.x();
909 buf[2 * i + 1] = val.y();
910 }
911 }
912 ret.setValues( buf );
913 return ret;
914}
915
917{
919 if ( active.isEmpty() ||
920 ( faceIndex < 0 ) ||
921 ( faceIndex + count > active.size() )
922 )
923 ret.setValid( true );
924 else
925 ret.setActive( active );
926 return ret;
927}
928
933
935{
936 double min = std::numeric_limits<double>::max();
937 double max = std::numeric_limits<double>::lowest();
938
939 if ( !valid )
940 return;
941
942
943 bool firstIteration = true;
944 for ( int i = 0; i < values.size(); ++i )
945 {
946 const double v = values[i].scalar();
947
948 if ( std::isnan( v ) )
949 continue;
950 if ( firstIteration )
951 {
952 firstIteration = false;
953 min = v;
954 max = v;
955 }
956 else
957 {
958 if ( v < min )
959 min = v;
960 if ( v > max )
961 max = v;
962 }
963 }
964
965 minimum = min;
966 maximum = max;
967}
968
969bool QgsMeshMemoryDataset::isActive( int faceIndex ) const
970{
971 if ( active.isEmpty() || faceIndex >= active.count() )
972 return true;
973 else
974 return active.at( faceIndex );
975}
976
978{
979 return values.count();
980}
981
986
991
993{
995 name(),
996 QString(),
997 isScalar(),
998 dataType(),
999 minimum(),
1000 maximum(),
1001 0,
1002 mReferenceTime,
1003 datasetCount() > 1,
1005 );
1006}
1007
1009{
1010 return memoryDatasets.size();
1011}
1012
1014{
1015 if ( datasetIndex >= 0 && datasetIndex < memoryDatasets.count() )
1016 return memoryDatasets[datasetIndex]->metadata();
1017 else
1018 return QgsMeshDatasetMetadata();
1019}
1020
1022{
1023 return memoryDatasets[index].get();
1024}
1025
1026void QgsMeshMemoryDatasetGroup::addDataset( std::shared_ptr<QgsMeshMemoryDataset> dataset )
1027{
1028 dataset->calculateMinMax();
1029 memoryDatasets.push_back( dataset );
1030}
1031
1036
1041
1042std::shared_ptr<const QgsMeshMemoryDataset> QgsMeshMemoryDatasetGroup::constDataset( int index ) const
1043{
1044 return memoryDatasets[index];
1045}
1046
1047QDomElement QgsMeshMemoryDatasetGroup::writeXml( QDomDocument &doc, const QgsReadWriteContext &context ) const
1048{
1049 Q_UNUSED( doc )
1050 Q_UNUSED( context )
1051 return QDomElement();
1052}
1053
1055{
1056 updateStatistic();
1057}
1058
1060{
1061 mIsStatisticObsolete = true;
1062}
1063
1065{
1066 return QStringList();
1067}
1068
1070{
1071 return QString();
1072}
1073
1074void QgsMeshDatasetGroup::setReferenceTime( const QDateTime &referenceTime )
1075{
1076 mReferenceTime = referenceTime;
1077}
1078
1079void QgsMeshDatasetGroup::updateStatistic() const
1080{
1081 if ( !mIsStatisticObsolete )
1082 return;
1083
1084 double min = std::numeric_limits<double>::max();
1085 double max = std::numeric_limits<double>::lowest();
1086
1087 const int count = datasetCount();
1088 for ( int i = 0; i < count; ++i )
1089 {
1090 const QgsMeshDatasetMetadata &meta = datasetMetadata( i );
1091 min = std::min( min, meta.minimum() );
1092 max = std::max( max, meta.maximum() );
1093 }
1094 mMinimum = min;
1095 mMaximum = max;
1096
1097 mIsStatisticObsolete = false;
1098}
1099
1101{
1102 for ( int i = 0; i < datasetCount(); ++i )
1103 if ( dataset( i )->valuesCount() != count )
1104 return false;
1105 return true;
1106}
1107
1110
1112
1114
1116{
1117 updateStatistic();
1118 return mMinimum;
1119}
1120
1122{
1123 updateStatistic();
1124 return mMaximum;
1125}
1126
1127void QgsMeshDatasetGroup::setMinimumMaximum( double min, double max ) const
1128{
1129 mMinimum = min;
1130 mMaximum = max;
1131}
1132
1134{
1135 return mName;
1136}
1137
1139{
1140 mName = name;
1141}
1142
1147
1152
1153void QgsMeshDatasetGroup::addExtraMetadata( QString key, QString value )
1154{
1155 mMetadata.insert( key, value );
1156}
1157
1158QMap<QString, QString> QgsMeshDatasetGroup::extraMetadata() const
1159{
1160 return mMetadata;
1161}
1162
1164{
1165 return mIsScalar;
1166}
1167
1172
1173
1177
1179{
1180 if ( mMesh && valueIndex >= 0 && valueIndex < mMesh->vertexCount() )
1181 return mMesh->vertex( valueIndex ).z();
1182
1183 return std::numeric_limits<double>::quiet_NaN();
1184}
1185
1186QgsMeshDataBlock QgsMeshVerticesElevationDataset::datasetValues( bool isScalar, int valueIndex, int count ) const
1187{
1188 if ( !isScalar || !mMesh )
1189 return QgsMeshDataBlock();
1190
1192 int effectiveValueCount = std::min( count, ( mMesh->vertexCount() - valueIndex ) );
1193 QVector<double> values( effectiveValueCount );
1194 for ( int i = valueIndex; i < effectiveValueCount; ++i )
1195 values[i] = mMesh->vertex( i - valueIndex ).z();
1196 block.setValues( values );
1197 block.setValid( true );
1198 return block;
1199}
1200
1202{
1203 QgsMeshDataBlock block( QgsMeshDataBlock::ActiveFlagInteger, std::min( count, ( mMesh->faceCount() - faceIndex ) ) );
1204 block.setValid( true );
1205 return block;
1206}
1207
1209{
1210 double min = std::numeric_limits<double>::max();
1211 double max = -std::numeric_limits<double>::max();
1212 if ( mMesh )
1213 for ( int i = 0; i < mMesh->vertexCount(); ++i )
1214 {
1215 const double z = mMesh->vertex( i ).z();
1216 if ( min > z )
1217 min = z;
1218 if ( max < z )
1219 max = z;
1220 }
1221
1222 return QgsMeshDatasetMetadata( 0, true, min, max, 0 );
1223}
1224
1226{
1227 if ( mMesh )
1228 return mMesh->vertexCount();
1229
1230 return 0;
1231}
1232
1239
1244
1246{
1247 if ( datasetIndex != 0 )
1248 return QgsMeshDatasetMetadata();
1249
1250 return mDataset->metadata();
1251}
1252
1254
1256{
1257 if ( index != 0 )
1258 return nullptr;
1259
1260 return mDataset.get();
1261}
1262
1267
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:6900
Mesh - vertices, edges and faces.