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