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