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