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