QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgsmeshdatasetgroupstore.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshdatasetgroupstore.cpp
3 ---------------------
4 begin : June 2020
5 copyright : (C) 2020 by Vincent Cloarec
6 email : vcloarec 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
19#include "qgsmeshlayer.h"
20#include "qgsmeshlayerutils.h"
21#include "qgsapplication.h"
23#include "qgslogger.h"
24
26{
27 return mRegistery.keys();
28}
29
31{
32 return mDatasetGroupTreeRootItem->enabledDatasetGroupIndexes();
33}
34
36{
37 return mRegistery.count();
38}
39
41{
42 return mExtraDatasets->datasetGroupCount();
43}
44
46 mLayer( layer ),
47 mExtraDatasets( new QgsMeshExtraDatasetStore ),
48 mDatasetGroupTreeRootItem( new QgsMeshDatasetGroupTreeItem )
49{}
50
51void QgsMeshDatasetGroupStore::setPersistentProvider( QgsMeshDataProvider *provider, const QStringList &extraDatasetUri )
52{
53 removePersistentProvider();
54 mPersistentProvider = provider;
55 if ( !mPersistentProvider )
56 return;
57 for ( const QString &uri : extraDatasetUri )
58 mPersistentProvider->addDataset( uri );
59
60 onPersistentDatasetAdded( mPersistentProvider->datasetGroupCount() );
61
62 checkDatasetConsistency( mPersistentProvider );
63 removeUnregisteredItemFromTree();
64
65 //Once everything is in place, initialize the extra dataset groups
66 if ( mExtraDatasets )
67 {
68 const int groupCount = mExtraDatasets->datasetGroupCount();
69 for ( int i = 0; i < groupCount; ++i )
70 if ( mExtraDatasets->datasetGroup( i ) )
71 mExtraDatasets->datasetGroup( i )->initialize();
72 }
73
74 mExtraDatasets->updateTemporalCapabilities();
75
76 connect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
77}
78
79QgsMeshDatasetGroupStore::DatasetGroup QgsMeshDatasetGroupStore::datasetGroup( int index ) const
80{
81 return mRegistery.value( index, DatasetGroup{nullptr, -1} );
82}
83
85{
86 if ( !mPersistentProvider )
87 return false;
88 return mPersistentProvider->addDataset( path ) ;
89}
90
92{
93 if ( !mExtraDatasets && !mLayer )
94 return false;
95
96 switch ( group->dataType() )
97 {
99 if ( ! group->checkValueCountPerDataset( mLayer->meshFaceCount() ) )
100 return false;
101 break;
103 if ( ! group->checkValueCountPerDataset( mLayer->meshVertexCount() ) )
104 return false;
105 break;
107 return false; // volume not supported for extra dataset
108 break;
110 if ( ! group->checkValueCountPerDataset( mLayer->meshEdgeCount() ) )
111 return false;
112 break;
113 }
114
115 int nativeIndex = mExtraDatasets->addDatasetGroup( group );
116 int groupIndex = registerDatasetGroup( DatasetGroup{mExtraDatasets.get(), nativeIndex} );
117
118 if ( groupIndex == -1 )
119 return false;
120
121 QList<int> groupIndexes;
122 groupIndexes.append( groupIndex );
123 createDatasetGroupTreeItems( groupIndexes );
124 syncItemToDatasetGroup( groupIndex );
125
126 emit datasetGroupsAdded( groupIndexes );
127
128 return true;
129}
130
132{
133 mDatasetGroupTreeRootItem.reset( new QgsMeshDatasetGroupTreeItem );
134 createDatasetGroupTreeItems( datasetGroupIndexes() );
135 QList<int> groupIndexes = datasetGroupIndexes();
136 for ( int groupIndex : groupIndexes )
137 syncItemToDatasetGroup( groupIndex );
138}
139
141{
142 return mDatasetGroupTreeRootItem.get();
143}
144
146{
147 if ( rootItem )
148 mDatasetGroupTreeRootItem.reset( rootItem->clone() );
149 else
150 mDatasetGroupTreeRootItem.reset();
151
152 unregisterGroupNotPresentInTree();
153}
154
156{
157 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
158 if ( group.first )
159 return group.first->datasetGroupMetadata( group.second );
160 else
162}
163
164int QgsMeshDatasetGroupStore::datasetCount( int groupIndex ) const
165{
166 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
167 if ( group.first )
168 return group.first->datasetCount( group.second );
169 else
170 return 0;
171}
172
174{
175 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
176 if ( group.first )
177 return group.first->datasetMetadata( QgsMeshDatasetIndex( group.second, index.dataset() ) );
178 else
179 return QgsMeshDatasetMetadata();
180}
181
183{
184 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
185 if ( group.first )
186 return group.first->datasetValue( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex );
187 else
188 return QgsMeshDatasetValue();
189}
190
192{
193 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
194 if ( group.first )
195 return group.first->datasetValues( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex, count );
196 else
197 return QgsMeshDataBlock();
198}
199
201{
202 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
203 if ( group.first )
204 return group.first->dataset3dValues( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
205 else
206 return QgsMesh3dDataBlock();
207}
208
210{
211 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
212 if ( group.first )
213 return group.first->areFacesActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
214 else
215 return QgsMeshDataBlock();
216}
217
218bool QgsMeshDatasetGroupStore::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
219{
220 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
221 if ( group.first )
222 return group.first->isFaceActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex );
223 else
224 return false;
225}
226
228 qint64 time,
230{
231 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
232 if ( !group.first )
233 return QgsMeshDatasetIndex();
234
235 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
236
237 return QgsMeshDatasetIndex( groupIndex,
238 group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
239}
240
242 qint64 time1,
243 qint64 time2,
244 int groupIndex ) const
245{
246 const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
247 if ( !group.first )
248 return QList<QgsMeshDatasetIndex>();
249
250 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
251
252 const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
253
254 QList<QgsMeshDatasetIndex> ret;
255 ret.reserve( datasetIndexes.count() );
256
257 for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
258 ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
259
260 return ret;
261}
262
264{
265 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
266 if ( !group.first || group.second < 0 )
268
269 QgsMeshDatasetIndex nativeIndex( group.second, index.dataset() );
270
271 if ( group.first == mPersistentProvider )
272 return mPersistentProvider->temporalCapabilities()->datasetTime( nativeIndex );
273 else if ( group.first == mExtraDatasets.get() )
274 return mExtraDatasets->datasetRelativeTime( nativeIndex );
275
277
278}
279
281{
282 return ( mPersistentProvider && mPersistentProvider->temporalCapabilities()->hasTemporalCapabilities() ) ||
283 ( mExtraDatasets && mExtraDatasets->hasTemporalCapabilities() );
284}
285
286QDomElement QgsMeshDatasetGroupStore::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
287{
288 Q_UNUSED( context );
289 QDomElement storeElement = doc.createElement( QStringLiteral( "mesh-dataset-groups-store" ) );
290 storeElement.appendChild( mDatasetGroupTreeRootItem->writeXml( doc, context ) );
291
292 QMap < int, DatasetGroup>::const_iterator it = mRegistery.constBegin();
293 while ( it != mRegistery.constEnd() )
294 {
295 QDomElement elemDataset;
296 if ( it.value().first == mPersistentProvider )
297 {
298 elemDataset = doc.createElement( QStringLiteral( "mesh-dataset" ) );
299 elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
300 elemDataset.setAttribute( QStringLiteral( "source-type" ), QStringLiteral( "persitent-provider" ) );
301 elemDataset.setAttribute( QStringLiteral( "source-index" ), it.value().second );
302 }
303 else if ( it.value().first == mExtraDatasets.get() )
304 {
305 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( it.key() );
306 if ( item )
307 {
308 elemDataset = mExtraDatasets->writeXml( it.value().second, doc, context );
309 if ( !elemDataset.isNull() )
310 elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
311 }
312 }
313
314 if ( !elemDataset.isNull() )
315 storeElement.appendChild( elemDataset );
316 ++it;
317 }
318
319 for ( auto it = mGroupNameToGlobalIndex.constBegin(); it != mGroupNameToGlobalIndex.constEnd(); ++it )
320 {
321 QDomElement elemNameToIndex = doc.createElement( QStringLiteral( "name-to-global-index" ) );
322 elemNameToIndex.setAttribute( QStringLiteral( "name" ), it.key() );
323 elemNameToIndex.setAttribute( QStringLiteral( "global-index" ), it.value() );
324
325 storeElement.appendChild( elemNameToIndex );
326 }
327
328 return storeElement;
329}
330
331void QgsMeshDatasetGroupStore::readXml( const QDomElement &storeElem, const QgsReadWriteContext &context )
332{
333 Q_UNUSED( context );
334 mRegistery.clear();
335 QDomElement datasetElem = storeElem.firstChildElement( "mesh-dataset" );
336 QMap<int, QgsMeshDatasetGroup *> extraDatasetGroups;
337 while ( !datasetElem.isNull() )
338 {
339 int globalIndex = datasetElem.attribute( QStringLiteral( "global-index" ) ).toInt();
340
341 const QString sourceType = datasetElem.attribute( QStringLiteral( "source-type" ) );
342 if ( sourceType == QLatin1String( "persitent-provider" ) )
343 {
344 mPersistentExtraDatasetGroupIndexes.append( globalIndex );
345 }
346 else if ( sourceType == QLatin1String( "virtual" ) )
347 {
348 QgsMeshDatasetSourceInterface *source = mExtraDatasets.get();
349 QString name = datasetElem.attribute( QStringLiteral( "name" ) );
350 QString formula = datasetElem.attribute( QStringLiteral( "formula" ) );
351 qint64 startTime = datasetElem.attribute( QStringLiteral( "start-time" ) ).toLongLong();
352 qint64 endTime = datasetElem.attribute( QStringLiteral( "end-time" ) ).toLongLong();
353
354 QgsMeshDatasetGroup *dsg = new QgsMeshVirtualDatasetGroup( name, formula, mLayer, startTime, endTime );
355 extraDatasetGroups[globalIndex] = dsg;
356 int sourceIndex = mExtraDatasets->addDatasetGroup( dsg );
357
358 mRegistery[globalIndex] = DatasetGroup{source, sourceIndex};
359 }
360 else
361 {
362 QgsDebugMsg( QStringLiteral( "Unhandled source-type: %1." ).arg( sourceType ) );
363 }
364
365 datasetElem = datasetElem.nextSiblingElement( QStringLiteral( "mesh-dataset" ) );
366 }
367
368 QDomElement nameToIndexElem = storeElem.firstChildElement( "name-to-global-index" );
369 mGroupNameToGlobalIndex.clear();
370 while ( !nameToIndexElem.isNull() )
371 {
372 QString name = nameToIndexElem.attribute( QStringLiteral( "name" ) );
373 int globalIndex = nameToIndexElem.attribute( QStringLiteral( "global-index" ) ).toInt();
374
375 mGroupNameToGlobalIndex.insert( name, globalIndex );
376
377 nameToIndexElem = nameToIndexElem.nextSiblingElement( QStringLiteral( "name-to-global-index" ) );
378 }
379
380 QDomElement rootTreeItemElem = storeElem.firstChildElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
381 if ( !rootTreeItemElem.isNull() )
382 {
383 const QgsMeshDatasetGroupTreeItem groupTreeItem( rootTreeItemElem, context );
384 setDatasetGroupTreeItem( &groupTreeItem );
385 }
386}
387
389{
390 for ( QMap<int, DatasetGroup>::const_iterator it = mRegistery.cbegin(); it != mRegistery.cend(); ++it )
391 {
392 if ( it.value().first == source && it.value().second == nativeGroupIndex )
393 return it.key();
394 }
395
396 return -1;
397}
398
399bool QgsMeshDatasetGroupStore::saveDatasetGroup( QString filePath, int groupIndex, QString driver )
400{
401 DatasetGroup group = datasetGroup( groupIndex );
402
403 bool fail = true;
404 if ( group.first && group.second >= 0 )
405 fail = mPersistentProvider->persistDatasetGroup( filePath, driver, group.first, group.second );
406
407 if ( !fail )
408 {
409 eraseDatasetGroup( group );
410 group.first = mPersistentProvider;
411 group.second = mPersistentProvider->datasetGroupCount() - 1;
412 mRegistery[groupIndex] = group;
413 //update the item type
414 if ( mDatasetGroupTreeRootItem )
415 {
416 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
417 if ( item )
418 item->setPersistentDatasetGroup( filePath );
419 }
420 }
421
422 return fail;
423}
424
425void QgsMeshDatasetGroupStore::onPersistentDatasetAdded( int count )
426{
427 Q_ASSERT( mPersistentProvider );
428
429 int providerTotalCount = mPersistentProvider->datasetGroupCount();
430 int providerBeginIndex = mPersistentProvider->datasetGroupCount() - count;
431 QList<int> newGroupIndexes;
432 for ( int i = providerBeginIndex; i < providerTotalCount; ++i )
433 {
434 const QString groupName = mPersistentProvider->datasetGroupMetadata( i ).name();
435 if ( mGroupNameToGlobalIndex.empty() && i < mPersistentExtraDatasetGroupIndexes.count() )
436 {
437 // This happens with QGIS project saved with version < 3.28
438 mRegistery[mPersistentExtraDatasetGroupIndexes.at( i )] = DatasetGroup( mPersistentProvider, i );
439 }
440 else if ( mGroupNameToGlobalIndex.contains( groupName ) )
441 {
442 // The dataset group name is associated with an index, so it is not a new dataset group
443 registerDatasetGroup( DatasetGroup{mPersistentProvider, i} );
444 }
445 else
446 {
447 int newGroupIndex = registerDatasetGroup( DatasetGroup{mPersistentProvider, i} );
448 if ( newGroupIndex != -1 )
449 newGroupIndexes.append( newGroupIndex );
450 }
451 }
452
453 if ( !newGroupIndexes.isEmpty() )
454 {
455 createDatasetGroupTreeItems( newGroupIndexes );
456 mPersistentExtraDatasetGroupIndexes.append( newGroupIndexes );
457
458 for ( int groupIndex : std::as_const( newGroupIndexes ) )
459 syncItemToDatasetGroup( groupIndex );
460
461 emit datasetGroupsAdded( newGroupIndexes );
462 }
463}
464
465void QgsMeshDatasetGroupStore::removePersistentProvider()
466{
467 if ( !mPersistentProvider )
468 return;
469
470 disconnect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
471
472 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
473 while ( it != mRegistery.end() )
474 {
475 if ( it.value().first == mPersistentProvider )
476 it = mRegistery.erase( it );
477 else
478 ++it;
479 }
480
481 mPersistentProvider = nullptr;
482}
483
484int QgsMeshDatasetGroupStore::newIndex()
485{
486 QSet usedIndex = qgis::listToSet( mRegistery.keys() );
487 usedIndex.unite( qgis::listToSet( mGroupNameToGlobalIndex.values() ) );
488 int index = 0;
489
490 while ( usedIndex.contains( index ) )
491 ++index;
492
493 return index;
494}
495
496int QgsMeshDatasetGroupStore::registerDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
497{
498 const QString &name = group.first->datasetGroupMetadata( group.second ).name();
499 auto it = mGroupNameToGlobalIndex.find( name );
500
501 int groupIndex;
502 if ( it != mGroupNameToGlobalIndex.end() )
503 {
504 groupIndex = it.value();
505
506 if ( mRegistery.contains( groupIndex ) )
507 {
508 QgsDebugMsg( QStringLiteral( "Dupplicate group name for %1." ).arg( name ) );
509 return -1; // The registery has already a group with this index, we can't have two groups with the same name
510 }
511 }
512 else
513 {
514 groupIndex = newIndex();
515 mGroupNameToGlobalIndex.insert( name, groupIndex );
516 }
517
518 mRegistery[groupIndex] = group;
519 return groupIndex;
520}
521
522void QgsMeshDatasetGroupStore::eraseDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
523{
524 if ( group.first == mPersistentProvider )
525 return; //removing persistent dataset group from the store is not allowed
526 else if ( group.first == mExtraDatasets.get() )
527 eraseExtraDataset( group.second );
528}
529
530void QgsMeshDatasetGroupStore::eraseExtraDataset( int indexInExtraStore )
531{
532 mExtraDatasets->removeDatasetGroup( indexInExtraStore );
533
534 //search dataset with index greater than indexInExtraStore and decrement it
535 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
536 while ( it != mRegistery.end() )
537 {
538 int localIndex = it.value().second;
539 if ( it.value().first == mExtraDatasets.get() && localIndex > indexInExtraStore )
540 it->second = localIndex - 1;
541 ++it;
542 }
543}
544
545void QgsMeshDatasetGroupStore::checkDatasetConsistency( QgsMeshDatasetSourceInterface *source )
546{
547 // check if datasets of source are present, if not, add them
548 QList<int> indexes;
549 for ( int i = 0; i < source->datasetGroupCount(); ++i )
550 {
551 int globalIndex = globalDatasetGroupIndexInSource( source, i );
552 if ( globalIndex == -1 )
553 globalIndex = registerDatasetGroup( DatasetGroup{source, i} );
554
555 if ( globalIndex != - 1 )
556 indexes.append( globalIndex );
557 }
558
559 if ( !indexes.isEmpty() )
560 createDatasetGroupTreeItems( indexes );
561
562 const QList<int> globalIndexes = mRegistery.keys();
563 for ( int globalIndex : globalIndexes )
564 {
565 if ( mRegistery.value( globalIndex ).first == source )
566 syncItemToDatasetGroup( globalIndex );
567 }
568}
569
570void QgsMeshDatasetGroupStore::removeUnregisteredItemFromTree()
571{
572 QList<QgsMeshDatasetGroupTreeItem *> itemsToCheck;
573 QList<int> indexItemToRemove;
574 for ( int i = 0; i < mDatasetGroupTreeRootItem->childCount(); ++i )
575 itemsToCheck.append( mDatasetGroupTreeRootItem->child( i ) );
576
577 while ( !itemsToCheck.isEmpty() )
578 {
579 QgsMeshDatasetGroupTreeItem *item = itemsToCheck.takeFirst();
580 int globalIndex = item->datasetGroupIndex();
581 if ( !mRegistery.contains( globalIndex ) )
582 indexItemToRemove.append( globalIndex );
583 for ( int i = 0; i < item->childCount(); ++i )
584 itemsToCheck.append( item->child( i ) );
585 }
586
587 for ( int i : indexItemToRemove )
588 {
589 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( i );
590 if ( item )
591 item->parentItem()->removeChild( item );
592 }
593}
594
595void QgsMeshDatasetGroupStore::unregisterGroupNotPresentInTree()
596{
597 if ( !mDatasetGroupTreeRootItem )
598 {
599 mRegistery.clear();
600 return;
601 }
602
603 QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
604 while ( it != mRegistery.end() )
605 {
606 DatasetGroup datasetGroup = it.value();
607 int globalIndex = it.key();
608 if ( ! mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( globalIndex ) // Not in the tree item
609 && datasetGroup.first != mPersistentProvider ) // and not persistent
610 {
611 it = mRegistery.erase( it ); //remove from registery
612 eraseDatasetGroup( datasetGroup ); //remove from where the dataset group is stored
613 }
614 else
615 ++it;
616 }
617}
618
619void QgsMeshDatasetGroupStore::syncItemToDatasetGroup( int groupIndex )
620{
621 if ( !mDatasetGroupTreeRootItem )
622 return;
623 const DatasetGroup group = datasetGroup( groupIndex );
624 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
625 if ( group.first == mPersistentProvider && mPersistentProvider )
626 {
627 const QgsMeshDatasetGroupMetadata meta = mPersistentProvider->datasetGroupMetadata( group.second );
628 if ( item )
629 item->setPersistentDatasetGroup( meta.uri() );
630 }
631 else if ( group.first == mExtraDatasets.get() )
632 {
633 if ( item )
634 item->setDatasetGroup( mExtraDatasets->datasetGroup( group.second ) );
635 }
636}
637
638void QgsMeshDatasetGroupStore::createDatasetGroupTreeItems( const QList<int> &indexes )
639{
640 QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
641
642 for ( int i = 0; i < indexes.count(); ++i )
643 {
644 int groupIndex = indexes.at( i );
645 if ( mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex ) )
646 continue; //item already exists
647 const QgsMeshDatasetGroupMetadata meta = datasetGroupMetadata( groupIndex );
648 const QString name = meta.name();
649 const QStringList subdatasets = name.split( '/' );
650
651 QString displayName = name;
652 QgsMeshDatasetGroupTreeItem *parent = mDatasetGroupTreeRootItem.get();
653
654 if ( subdatasets.size() == 2 )
655 {
656 auto it = mNameToItem.find( subdatasets[0] );
657 if ( it == mNameToItem.end() )
658 QgsDebugMsg( QStringLiteral( "Unable to find parent group for %1." ).arg( name ) );
659 else
660 {
661 displayName = subdatasets[1];
662 parent = it.value();
663 }
664 }
665 else if ( subdatasets.size() != 1 )
666 QgsDebugMsg( QStringLiteral( "Ignoring too deep child group name %1." ).arg( name ) );
667
668 QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( displayName, name, meta.isVector(), groupIndex );
669 parent->appendChild( item );
670 if ( mNameToItem.contains( name ) )
671 QgsDebugMsg( QStringLiteral( "Group %1 is not unique" ).arg( displayName ) );
672 mNameToItem[name] = item;
673 }
674}
675
677{
678 int groupIndex = mGroups.size();
679 mGroups.push_back( std::unique_ptr<QgsMeshDatasetGroup>( datasetGroup ) );
680
681 if ( datasetGroup->datasetCount() > 1 )
682 {
683 mTemporalCapabilities->setHasTemporalCapabilities( true );
684 for ( int i = 0; i < datasetGroup->datasetCount(); ++i )
685 mTemporalCapabilities->addDatasetTime( groupIndex, datasetGroup->datasetMetadata( i ).time() );
686 }
687
688 return mGroups.size() - 1;
689}
690
692{
693 if ( index < datasetGroupCount() )
694 mGroups.erase( mGroups.begin() + index );
695
696
698}
699
701{
702 return mTemporalCapabilities->hasTemporalCapabilities();
703}
704
706{
707 return mTemporalCapabilities->datasetTime( index );
708}
709
710QString QgsMeshExtraDatasetStore::description( int groupIndex ) const
711{
712 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
713 return mGroups.at( groupIndex )->description();
714 else
715 return QString();
716}
717
719{
720 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
721 return mGroups[groupIndex].get();
722 else
723 return nullptr;
724}
725
726bool QgsMeshExtraDatasetStore::addDataset( const QString &uri )
727{
728 Q_UNUSED( uri );
729 return false;
730}
731
733{
734 return QStringList();
735}
736
738{
739 return mGroups.size();
740}
741
742int QgsMeshExtraDatasetStore::datasetCount( int groupIndex ) const
743{
744 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
745 return mGroups.at( groupIndex )->datasetCount();
746 else
747 return 0;
748}
749
751{
752 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
753 return mGroups.at( groupIndex )->groupMetadata();
754 else
756}
757
759{
760 int groupIndex = index.group();
761 if ( index.isValid() && groupIndex < datasetGroupCount() )
762 {
763 int datasetIndex = index.dataset();
764 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
765 if ( datasetIndex < group->datasetCount() )
766 return group->datasetMetadata( datasetIndex );
767 }
768 return QgsMeshDatasetMetadata();
769}
770
772{
773 int groupIndex = index.group();
774 if ( index.isValid() && groupIndex < datasetGroupCount() )
775 {
776 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
777 int datasetIndex = index.dataset();
778 if ( datasetIndex < group->datasetCount() )
779 return group->dataset( datasetIndex )->datasetValue( valueIndex );
780 }
781
782 return QgsMeshDatasetValue();
783}
784
786{
787 int groupIndex = index.group();
788 if ( index.isValid() && groupIndex < datasetGroupCount() )
789 {
790 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
791 int datasetIndex = index.dataset();
792 if ( datasetIndex < group->datasetCount() )
793 return group->dataset( datasetIndex )->datasetValues( group->isScalar(), valueIndex, count );
794 }
795
796 return QgsMeshDataBlock();
797}
798
800{
801 // Not supported for now
802 Q_UNUSED( index )
803 Q_UNUSED( faceIndex )
804 Q_UNUSED( count )
805 return QgsMesh3dDataBlock();
806}
807
809{
810 int groupIndex = index.group();
811 if ( index.isValid() && groupIndex < datasetGroupCount() )
812 {
813 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
814 int datasetIndex = index.dataset();
815 if ( datasetIndex < group->datasetCount() )
816 return group->dataset( datasetIndex )->isActive( faceIndex );
817 }
818
819 return false;
820}
821
823{
824 int groupIndex = index.group();
825 if ( index.isValid() && groupIndex < datasetGroupCount() )
826 {
827 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
828 int datasetIndex = index.dataset();
829 if ( datasetIndex < group->datasetCount() )
830 return group->dataset( datasetIndex )->areFacesActive( faceIndex, count );
831 }
832 return QgsMeshDataBlock();
833}
834
835bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
836 const QString &outputDriver,
837 const QgsMeshDatasetGroupMetadata &meta,
838 const QVector<QgsMeshDataBlock> &datasetValues,
839 const QVector<QgsMeshDataBlock> &datasetActive,
840 const QVector<double> &times )
841{
842 Q_UNUSED( outputFilePath )
843 Q_UNUSED( outputDriver )
844 Q_UNUSED( meta )
845 Q_UNUSED( datasetValues )
846 Q_UNUSED( datasetActive )
847 Q_UNUSED( times )
848 return true; // not implemented/supported
849}
850
851bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
852 const QString &outputDriver,
854 int datasetGroupIndex )
855{
856 Q_UNUSED( outputFilePath )
857 Q_UNUSED( outputDriver )
858 Q_UNUSED( source )
859 Q_UNUSED( datasetGroupIndex )
860 return true; // not implemented/supported
861}
862
863QDomElement QgsMeshExtraDatasetStore::writeXml( int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context )
864{
865 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) && mGroups[groupIndex] )
866 return mGroups[groupIndex]->writeXml( doc, context );
867 else
868 return QDomElement();
869}
870
872{
873 //update temporal capabilitie
874 mTemporalCapabilities->clear();
875 bool hasTemporal = false;
876 for ( size_t g = 0; g < mGroups.size(); ++g )
877 {
878 const QgsMeshDatasetGroup *group = mGroups[g].get();
879 hasTemporal |= group->datasetCount() > 1;
880 for ( int i = 0; i < group->datasetCount(); ++i )
881 mTemporalCapabilities->addDatasetTime( g, group->datasetMetadata( i ).time() );
882 }
883
884 mTemporalCapabilities->setHasTemporalCapabilities( hasTemporal );
885}
bool hasTemporalCapabilities() const
Returns true if the provider has temporal capabilities available.
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....
QDateTime referenceTime() const
Returns the reference time.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 datasetTime(const QgsMeshDatasetIndex &index) const
Returns the relative time in milliseconds of the dataset.
Base class for providing data for QgsMeshLayer.
void datasetGroupsAdded(int count)
Emitted when some new dataset groups have been added.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
bool isVector() const
Returns whether dataset group has vector data.
QString name() const
Returns name of 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.
QString uri() const
Returns the uri of the source.
QgsMeshDatasetGroupTreeItem * datasetGroupTreeItem() const
Returns a pointer to the root of the dataset groups tree item.
QgsMeshDatasetMetadata datasetMetadata(const QgsMeshDatasetIndex &index) const
Returns the metadata of the dataset with global index.
void setDatasetGroupTreeItem(const QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root of the dataset groups tree item.
QList< int > enabledDatasetGroupIndexes() const
Returns a list of all group indexes that are enabled.
bool addPersistentDatasets(const QString &path)
Adds persistent datasets from a file with path.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the metadata of the dataset group with global index.
bool isFaceActive(const QgsMeshDatasetIndex &index, int faceIndex) const
Returns whether face is active for particular dataset.
QList< int > datasetGroupIndexes() const
Returns a list of all group indexes.
bool hasTemporalCapabilities() const
Returns whether at lea&st one of stored dataset group is temporal.
void resetDatasetGroupTreeItem()
Resets to default state the dataset groups tree item.
QgsMeshDataBlock datasetValues(const QgsMeshDatasetIndex &index, int valueIndex, int count) const
Returns count values of the dataset with global index and from valueIndex.
QgsMesh3dDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns count 3D values of the dataset with global index and from valueIndex.
QgsMeshDatasetIndex datasetIndexAtTime(qint64 time, int groupIndex, QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method) const
Returns the global dataset index of the dataset int the dataset group with groupIndex,...
bool saveDatasetGroup(QString filePath, int groupIndex, QString driver)
Saves on a file with filePath the dataset groups index with groupIndex with the specified driver.
QList< QgsMeshDatasetIndex > datasetIndexInTimeInterval(qint64 time1, qint64 time2, int groupIndex) const
Returns the global dataset index of the dataset int the dataset group with groupIndex,...
bool addDatasetGroup(QgsMeshDatasetGroup *group)
Adds a extra dataset group, take ownership, returns True if the group is effectivly added.
QgsMeshDatasetValue datasetValue(const QgsMeshDatasetIndex &index, int valueIndex) const
Returns the value of the dataset with global index and valueIndex.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context)
Writes the store's information in a DOM document.
int extraDatasetGroupCount() const
Returns the count of extra dataset groups.
int datasetGroupCount() const
Returns the count of dataset groups.
QgsMeshDatasetGroupStore(QgsMeshLayer *layer)
Constructor.
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether faces are active for particular dataset.
void setPersistentProvider(QgsMeshDataProvider *provider, const QStringList &extraDatasetUri)
Sets the persistent mesh data provider with the path of its extra dataset to be loaded by the provide...
qint64 datasetRelativeTime(const QgsMeshDatasetIndex &index) const
Returns the relative time of the dataset from the persistent provider reference time.
int datasetCount(int groupIndex) const
Returns the total count of dataset group in the store.
void readXml(const QDomElement &storeElem, const QgsReadWriteContext &context)
Reads the store's information from a DOM document.
int globalDatasetGroupIndexInSource(QgsMeshDatasetSourceInterface *source, int nativeGroupIndex) const
Returns the global dataset group index of the dataset group with native index nativeGroupIndex in the...
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
Tree item for display of the mesh dataset groups.
QgsMeshDatasetGroupTreeItem * clone() const
Clones the item.
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 * parentItem() const
Returns the parent item, nullptr if it is root item.
void removeChild(QgsMeshDatasetGroupTreeItem *item)
Removes a item child if exists.
void setDatasetGroup(QgsMeshDatasetGroup *datasetGroup)
Set parameters of the item in accordance with the dataset group.
void appendChild(QgsMeshDatasetGroupTreeItem *item)
Appends a child item.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a dataset group.
bool isScalar() const
Returns whether the group contain scalar values.
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.
QgsMeshDatasetGroupMetadata::DataType dataType() const
Returns the data type of the dataset group.
virtual int datasetCount() const =0
Returns the count of datasets in the group.
virtual QgsMeshDataset * dataset(int index) const =0
Returns the dataset with index.
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 ...
double time() const
Returns the time value for this dataset.
Interface for mesh datasets and dataset groups.
virtual Q_DECL_DEPRECATED bool persistDatasetGroup(const QString &path, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times)
Creates a new dataset group from a data and persists it into a destination path.
virtual QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const =0
Returns dataset group metadata.
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
std::unique_ptr< QgsMeshDataProviderTemporalCapabilities > mTemporalCapabilities
virtual bool addDataset(const QString &uri)=0
Associate dataset with the mesh.
QgsMeshDatasetValue represents single dataset value.
virtual QgsMeshDataBlock datasetValues(bool isScalar, int valueIndex, int count) const =0
Returns count values from valueIndex.
virtual bool isActive(int faceIndex) const =0
Returns whether the face is active.
virtual QgsMeshDataBlock areFacesActive(int faceIndex, int count) const =0
Returns whether faces are active.
virtual QgsMeshDatasetValue datasetValue(int valueIndex) const =0
Returns the value with index valueIndex.
Class that can be used to store and access extra dataset group, like memory dataset (temporary) Deriv...
int datasetCount(int groupIndex) const override
Returns number of datasets loaded in the group.
QString description(int groupIndex) const
Returns information related to the dataset group with groupIndex.
void updateTemporalCapabilities()
Updates the temporal capabilities.
QStringList extraDatasets() const override
Not implemented, always returns empty list.
QgsMeshDatasetGroup * datasetGroup(int groupIndex) const
Returns a pointer to the dataset group.
bool persistDatasetGroup(const QString &outputFilePath, const QString &outputDriver, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times) override
Not implemented, always returns true.
quint64 datasetRelativeTime(QgsMeshDatasetIndex index)
Returns the relative times of the dataset index with index, returned value in milliseconds.
QgsMeshDataBlock datasetValues(QgsMeshDatasetIndex index, int valueIndex, int count) const override
Returns N vector/scalar values from the index from the dataset.
int addDatasetGroup(QgsMeshDatasetGroup *datasetGroup)
Adds a dataset group, returns the index of the added dataset group.
QgsMeshDataBlock areFacesActive(QgsMeshDatasetIndex index, int faceIndex, int count) const override
Returns whether the faces are active for particular dataset.
int datasetGroupCount() const override
Returns number of datasets groups loaded.
bool hasTemporalCapabilities() const
Returns whether if the dataset groups have temporal capabilities (a least one dataset group with more...
bool isFaceActive(QgsMeshDatasetIndex index, int faceIndex) const override
Returns whether the face is active for particular dataset.
QDomElement writeXml(int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context)
Writes the store's information in a DOM document.
QgsMeshDatasetMetadata datasetMetadata(QgsMeshDatasetIndex index) const override
Returns dataset metadata.
void removeDatasetGroup(int index)
Removes the dataset group with the local index.
QgsMesh3dDataBlock dataset3dValues(QgsMeshDatasetIndex index, int faceIndex, int count) const override
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const override
Returns dataset group metadata.
QgsMeshDatasetValue datasetValue(QgsMeshDatasetIndex index, int valueIndex) const override
Returns vector/scalar value associated with the index from the dataset To read multiple continuous va...
bool addDataset(const QString &uri) override
Not implemented, always returns false.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
Definition: qgsmeshlayer.h:100
int meshFaceCount() const
Returns the faces count of the mesh frame.
int meshEdgeCount() const
Returns the edges count of the mesh frame.
int meshVertexCount() const
Returns the vertices count of the mesh frame.
Represents a dataset group calculated from a formula string.
The class is used as a container of context for various read/write operations on other objects.
#define QgsDebugMsg(str)
Definition: qgslogger.h:38