QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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{
272 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
273 if ( !group.first )
274 return QgsMeshDatasetIndex();
275
276 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
277
278 return QgsMeshDatasetIndex( groupIndex, group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
279}
280
281QList<QgsMeshDatasetIndex> QgsMeshDatasetGroupStore::datasetIndexInTimeInterval( qint64 time1, qint64 time2, int groupIndex ) const
282{
283 const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
284 if ( !group.first )
285 return QList<QgsMeshDatasetIndex>();
286
287 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
288
289 const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
290
291 QList<QgsMeshDatasetIndex> ret;
292 ret.reserve( datasetIndexes.count() );
293
294 for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
295 ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
296
297 return ret;
298}
299
301{
302 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
303 if ( !group.first || group.second < 0 )
305
306 QgsMeshDatasetIndex nativeIndex( group.second, index.dataset() );
307
308 if ( group.first == mPersistentProvider )
309 return mPersistentProvider->temporalCapabilities()->datasetTime( nativeIndex );
310 else if ( group.first == &mExtraDatasets )
311 return mExtraDatasets.datasetRelativeTime( nativeIndex );
312
314}
315
317{
318 return ( mPersistentProvider && mPersistentProvider->temporalCapabilities()->hasTemporalCapabilities() ) || ( mExtraDatasets.hasTemporalCapabilities() );
319}
320
321QDomElement QgsMeshDatasetGroupStore::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
322{
323 Q_UNUSED( context );
324 QDomElement storeElement = doc.createElement( u"mesh-dataset-groups-store"_s );
325 storeElement.appendChild( mDatasetGroupTreeRootItem->writeXml( doc, context ) );
326
327 QMap< int, DatasetGroup>::const_iterator it = mRegistry.constBegin();
328 while ( it != mRegistry.constEnd() )
329 {
330 QDomElement elemDataset;
331 if ( it.value().first == mPersistentProvider )
332 {
333 elemDataset = doc.createElement( u"mesh-dataset"_s );
334 elemDataset.setAttribute( u"global-index"_s, it.key() );
335 elemDataset.setAttribute( u"source-type"_s, u"persitent-provider"_s );
336 elemDataset.setAttribute( u"source-index"_s, it.value().second );
337 }
338 else if ( it.value().first == &mExtraDatasets )
339 {
340 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( it.key() );
341 if ( item )
342 {
343 elemDataset = mExtraDatasets.writeXml( it.value().second, doc, context );
344 if ( !elemDataset.isNull() )
345 elemDataset.setAttribute( u"global-index"_s, it.key() );
346 }
347 }
348
349 if ( !elemDataset.isNull() )
350 storeElement.appendChild( elemDataset );
351 ++it;
352 }
353
354 for ( auto it = mGroupNameToGlobalIndex.constBegin(); it != mGroupNameToGlobalIndex.constEnd(); ++it )
355 {
356 QDomElement elemNameToIndex = doc.createElement( u"name-to-global-index"_s );
357 elemNameToIndex.setAttribute( u"name"_s, it.key() );
358 elemNameToIndex.setAttribute( u"global-index"_s, it.value() );
359
360 storeElement.appendChild( elemNameToIndex );
361 }
362
363 return storeElement;
364}
365
366void QgsMeshDatasetGroupStore::readXml( const QDomElement &storeElem, const QgsReadWriteContext &context )
367{
368 Q_UNUSED( context );
369 mRegistry.clear();
370 QDomElement datasetElem = storeElem.firstChildElement( "mesh-dataset" );
371 while ( !datasetElem.isNull() )
372 {
373 int globalIndex = datasetElem.attribute( u"global-index"_s ).toInt();
374
375 const QString sourceType = datasetElem.attribute( u"source-type"_s );
376 if ( sourceType == "persitent-provider"_L1 )
377 {
378 mPersistentExtraDatasetGroupIndexes.append( globalIndex );
379 }
380 else if ( sourceType == "virtual"_L1 )
381 {
382 QgsMeshDatasetSourceInterface *source = &mExtraDatasets;
383 QString name = datasetElem.attribute( u"name"_s );
384 QString formula = datasetElem.attribute( u"formula"_s );
385 qint64 startTime = datasetElem.attribute( u"start-time"_s ).toLongLong();
386 qint64 endTime = datasetElem.attribute( u"end-time"_s ).toLongLong();
387
388 auto dsg = std::make_unique< QgsMeshVirtualDatasetGroup >( name, formula, mLayer, startTime, endTime );
389 int sourceIndex = mExtraDatasets.addDatasetGroup( std::move( dsg ) );
390
391 mRegistry[globalIndex] = DatasetGroup { source, sourceIndex };
392 }
393 else
394 {
395 QgsDebugError( u"Unhandled source-type: %1."_s.arg( sourceType ) );
396 }
397
398 datasetElem = datasetElem.nextSiblingElement( u"mesh-dataset"_s );
399 }
400
401 QDomElement nameToIndexElem = storeElem.firstChildElement( "name-to-global-index" );
402 mGroupNameToGlobalIndex.clear();
403 while ( !nameToIndexElem.isNull() )
404 {
405 QString name = nameToIndexElem.attribute( u"name"_s );
406 int globalIndex = nameToIndexElem.attribute( u"global-index"_s ).toInt();
407
408 mGroupNameToGlobalIndex.insert( name, globalIndex );
409
410 nameToIndexElem = nameToIndexElem.nextSiblingElement( u"name-to-global-index"_s );
411 }
412
413 QDomElement rootTreeItemElem = storeElem.firstChildElement( u"mesh-dataset-group-tree-item"_s );
414 if ( !rootTreeItemElem.isNull() )
415 {
416 const QgsMeshDatasetGroupTreeItem groupTreeItem( rootTreeItemElem, context );
417 setDatasetGroupTreeItem( &groupTreeItem );
418 }
419}
420
422{
423 for ( QMap<int, DatasetGroup>::const_iterator it = mRegistry.cbegin(); it != mRegistry.cend(); ++it )
424 {
425 if ( it.value().first == source && it.value().second == nativeGroupIndex )
426 return it.key();
427 }
428
429 return -1;
430}
431
433{
434 return mGroupNameToGlobalIndex.value( groupName, -1 );
435}
436
437QString QgsMeshDatasetGroupStore::groupName( int groupIndex ) const
438{
439 return datasetGroupMetadata( groupIndex ).name();
440}
441
442bool QgsMeshDatasetGroupStore::saveDatasetGroup( QString filePath, int groupIndex, QString driver )
443{
444 DatasetGroup group = datasetGroup( groupIndex );
445
446 bool fail = true;
447 if ( group.first && group.second >= 0 )
448 fail = mPersistentProvider->persistDatasetGroup( filePath, driver, group.first, group.second );
449
450 if ( !fail )
451 {
452 eraseDatasetGroup( group );
453 group.first = mPersistentProvider;
454 group.second = mPersistentProvider->datasetGroupCount() - 1;
455 mRegistry[groupIndex] = group;
456 //update the item type
457 if ( mDatasetGroupTreeRootItem )
458 {
459 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
460 if ( item )
461 item->setPersistentDatasetGroup( filePath );
462 }
463 }
464
465 return fail;
466}
467
468void QgsMeshDatasetGroupStore::onPersistentDatasetAdded( int count )
469{
470 Q_ASSERT( mPersistentProvider );
471
472 int providerTotalCount = mPersistentProvider->datasetGroupCount();
473 int providerBeginIndex = mPersistentProvider->datasetGroupCount() - count;
474 QList<int> newGroupIndexes;
475 for ( int i = providerBeginIndex; i < providerTotalCount; ++i )
476 {
477 const QString groupName = mPersistentProvider->datasetGroupMetadata( i ).name();
478 if ( mGroupNameToGlobalIndex.empty() && i < mPersistentExtraDatasetGroupIndexes.count() )
479 {
480 // This happens with QGIS project saved with version < 3.28
481 mRegistry[mPersistentExtraDatasetGroupIndexes.at( i )] = DatasetGroup( mPersistentProvider, i );
482 }
483 else if ( mGroupNameToGlobalIndex.contains( groupName ) )
484 {
485 // The dataset group name is associated with an index, so it is not a new dataset group
486 registerDatasetGroup( DatasetGroup { mPersistentProvider, i } );
487 }
488 else
489 {
490 int newGroupIndex = registerDatasetGroup( DatasetGroup { mPersistentProvider, i } );
491 if ( newGroupIndex != -1 )
492 newGroupIndexes.append( newGroupIndex );
493 }
494 }
495
496 if ( !newGroupIndexes.isEmpty() )
497 {
498 createDatasetGroupTreeItems( newGroupIndexes );
499 mPersistentExtraDatasetGroupIndexes.append( newGroupIndexes );
500
501 for ( int groupIndex : std::as_const( newGroupIndexes ) )
502 syncItemToDatasetGroup( groupIndex );
503
504 emit datasetGroupsAdded( newGroupIndexes );
505 }
506}
507
508void QgsMeshDatasetGroupStore::removePersistentProvider()
509{
510 if ( !mPersistentProvider )
511 return;
512
513 disconnect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
514
515 QMap< int, DatasetGroup>::iterator it = mRegistry.begin();
516 while ( it != mRegistry.end() )
517 {
518 if ( it.value().first == mPersistentProvider )
519 it = mRegistry.erase( it );
520 else
521 ++it;
522 }
523
524 mPersistentProvider = nullptr;
525}
526
527int QgsMeshDatasetGroupStore::newIndex()
528{
529 QSet usedIndex = qgis::listToSet( mRegistry.keys() );
530 usedIndex.unite( qgis::listToSet( mGroupNameToGlobalIndex.values() ) );
531 int index = 0;
532
533 while ( usedIndex.contains( index ) )
534 ++index;
535
536 return index;
537}
538
539int QgsMeshDatasetGroupStore::registerDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
540{
541 const QString &name = group.first->datasetGroupMetadata( group.second ).name();
542 auto it = mGroupNameToGlobalIndex.find( name );
543
544 int groupIndex;
545 if ( it != mGroupNameToGlobalIndex.end() )
546 {
547 groupIndex = it.value();
548
549 if ( mRegistry.contains( groupIndex ) )
550 {
551 QgsDebugError( u"Duplicate group name for %1."_s.arg( name ) );
552 return -1; // The registry has already a group with this index, we can't have two groups with the same name
553 }
554 }
555 else
556 {
557 groupIndex = newIndex();
558 mGroupNameToGlobalIndex.insert( name, groupIndex );
559 }
560
561 mRegistry[groupIndex] = group;
562 return groupIndex;
563}
564
565void QgsMeshDatasetGroupStore::eraseDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
566{
567 if ( group.first == mPersistentProvider )
568 return; //removing persistent dataset group from the store is not allowed
569 else if ( group.first == &mExtraDatasets )
570 eraseExtraDataset( group.second );
571}
572
573void QgsMeshDatasetGroupStore::eraseExtraDataset( int indexInExtraStore )
574{
575 mExtraDatasets.removeDatasetGroup( indexInExtraStore );
576
577 //search dataset with index greater than indexInExtraStore and decrement it
578 QMap< int, DatasetGroup>::iterator it = mRegistry.begin();
579 while ( it != mRegistry.end() )
580 {
581 int localIndex = it.value().second;
582 if ( it.value().first == &mExtraDatasets && localIndex > indexInExtraStore )
583 it->second = localIndex - 1;
584 ++it;
585 }
586}
587
588void QgsMeshDatasetGroupStore::checkDatasetConsistency( QgsMeshDatasetSourceInterface *source )
589{
590 // check if datasets of source are present, if not, add them
591 QList<int> indexes;
592 for ( int i = 0; i < source->datasetGroupCount(); ++i )
593 {
594 int globalIndex = globalDatasetGroupIndexInSource( source, i );
595 if ( globalIndex == -1 )
596 globalIndex = registerDatasetGroup( DatasetGroup { source, i } );
597
598 if ( globalIndex != -1 )
599 indexes.append( globalIndex );
600 }
601
602 if ( !indexes.isEmpty() )
603 createDatasetGroupTreeItems( indexes );
604
605 const QList<int> globalIndexes = mRegistry.keys();
606 for ( int globalIndex : globalIndexes )
607 {
608 if ( mRegistry.value( globalIndex ).first == source )
609 syncItemToDatasetGroup( globalIndex );
610 }
611}
612
613void QgsMeshDatasetGroupStore::removeUnregisteredItemFromTree()
614{
615 QList<QgsMeshDatasetGroupTreeItem *> itemsToCheck;
616 QList<int> indexItemToRemove;
617 for ( int i = 0; i < mDatasetGroupTreeRootItem->childCount(); ++i )
618 itemsToCheck.append( mDatasetGroupTreeRootItem->child( i ) );
619
620 while ( !itemsToCheck.isEmpty() )
621 {
622 QgsMeshDatasetGroupTreeItem *item = itemsToCheck.takeFirst();
623 int globalIndex = item->datasetGroupIndex();
624 if ( !mRegistry.contains( globalIndex ) )
625 indexItemToRemove.append( globalIndex );
626 for ( int i = 0; i < item->childCount(); ++i )
627 itemsToCheck.append( item->child( i ) );
628 }
629
630 for ( int i : indexItemToRemove )
631 {
632 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( i );
633 if ( item )
634 item->parentItem()->removeChild( item );
635 }
636}
637
638void QgsMeshDatasetGroupStore::unregisterGroupNotPresentInTree()
639{
640 if ( !mDatasetGroupTreeRootItem )
641 {
642 mRegistry.clear();
643 return;
644 }
645
646 QMap< int, DatasetGroup>::iterator it = mRegistry.begin();
647 while ( it != mRegistry.end() )
648 {
649 DatasetGroup datasetGroup = it.value();
650 int globalIndex = it.key();
651 if ( !mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( globalIndex ) // Not in the tree item
652 && datasetGroup.first != mPersistentProvider ) // and not persistent
653 {
654 it = mRegistry.erase( it ); //remove from registry
655 eraseDatasetGroup( datasetGroup ); //remove from where the dataset group is stored
656 }
657 else
658 ++it;
659 }
660}
661
662void QgsMeshDatasetGroupStore::syncItemToDatasetGroup( int groupIndex )
663{
664 if ( !mDatasetGroupTreeRootItem )
665 return;
666 const DatasetGroup group = datasetGroup( groupIndex );
667 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
668 if ( group.first == mPersistentProvider && mPersistentProvider )
669 {
670 const QgsMeshDatasetGroupMetadata meta = mPersistentProvider->datasetGroupMetadata( group.second );
671 if ( item )
672 item->setPersistentDatasetGroup( meta.uri() );
673 }
674 else if ( group.first == &mExtraDatasets )
675 {
676 if ( item )
677 item->setDatasetGroup( mExtraDatasets.datasetGroup( group.second ) );
678 }
679}
680
681void QgsMeshDatasetGroupStore::createDatasetGroupTreeItems( const QList<int> &indexes )
682{
683 QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
684
685 for ( int i = 0; i < indexes.count(); ++i )
686 {
687 int groupIndex = indexes.at( i );
688 if ( mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex ) )
689 continue; //item already exists
690 const QgsMeshDatasetGroupMetadata meta = datasetGroupMetadata( groupIndex );
691 const QString name = meta.name();
692 const QStringList subdatasets = name.split( '/' );
693
694 QString displayName = name;
695 QgsMeshDatasetGroupTreeItem *parent = mDatasetGroupTreeRootItem.get();
696
697 if ( subdatasets.size() == 2 )
698 {
699 auto it = mNameToItem.find( subdatasets[0] );
700 if ( it == mNameToItem.end() )
701 QgsDebugError( u"Unable to find parent group for %1."_s.arg( name ) );
702 else
703 {
704 displayName = subdatasets[1];
705 parent = it.value();
706 }
707 }
708 else if ( subdatasets.size() != 1 )
709 QgsDebugError( u"Ignoring too deep child group name %1."_s.arg( name ) );
710
711 QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( displayName, name, meta.isVector(), groupIndex );
712 parent->appendChild( item );
713 if ( mNameToItem.contains( name ) )
714 QgsDebugError( u"Group %1 is not unique"_s.arg( displayName ) );
715 mNameToItem[name] = item;
716 }
717}
718
719int QgsMeshExtraDatasetStore::addDatasetGroup( std::unique_ptr<QgsMeshDatasetGroup> datasetGroup )
720{
721 int groupIndex = mGroups.size();
722 QgsMeshDatasetGroup *addedGroup = mGroups.emplace_back( std::move( datasetGroup ) ).get();
723
724 if ( addedGroup->datasetCount() > 1 )
725 {
726 mTemporalCapabilities->setHasTemporalCapabilities( true );
727 for ( int i = 0; i < addedGroup->datasetCount(); ++i )
728 mTemporalCapabilities->addDatasetTime( groupIndex, addedGroup->datasetMetadata( i ).time() );
729 }
730
731 return mGroups.size() - 1;
732}
733
735{
736 if ( groupIndex < datasetGroupCount() )
737 mGroups.erase( mGroups.begin() + groupIndex );
738
739
741}
742
744{
745 return mTemporalCapabilities->hasTemporalCapabilities();
746}
747
749{
750 return mTemporalCapabilities->datasetTime( index );
751}
752
753QString QgsMeshExtraDatasetStore::description( int groupIndex ) const
754{
755 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
756 return mGroups.at( groupIndex )->description();
757 else
758 return QString();
759}
760
762{
763 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
764 return mGroups[groupIndex].get();
765 else
766 return nullptr;
767}
768
769bool QgsMeshExtraDatasetStore::addDataset( const QString &uri )
770{
771 Q_UNUSED( uri );
772 return false;
773}
774
776{
777 return QStringList();
778}
779
781{
782 return mGroups.size();
783}
784
785int QgsMeshExtraDatasetStore::datasetCount( int groupIndex ) const
786{
787 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
788 return mGroups.at( groupIndex )->datasetCount();
789 else
790 return 0;
791}
792
794{
795 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
796 return mGroups.at( groupIndex )->groupMetadata();
797 else
799}
800
802{
803 int groupIndex = index.group();
804 if ( index.isValid() && groupIndex < datasetGroupCount() )
805 {
806 int datasetIndex = index.dataset();
807 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
808 if ( datasetIndex < group->datasetCount() )
809 return group->datasetMetadata( datasetIndex );
810 }
811 return QgsMeshDatasetMetadata();
812}
813
815{
816 int groupIndex = index.group();
817 if ( index.isValid() && groupIndex < datasetGroupCount() )
818 {
819 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
820 int datasetIndex = index.dataset();
821 if ( datasetIndex < group->datasetCount() )
822 return group->dataset( datasetIndex )->datasetValue( valueIndex );
823 }
824
825 return QgsMeshDatasetValue();
826}
827
829{
830 int groupIndex = index.group();
831 if ( index.isValid() && groupIndex < datasetGroupCount() )
832 {
833 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
834 int datasetIndex = index.dataset();
835 if ( datasetIndex < group->datasetCount() )
836 return group->dataset( datasetIndex )->datasetValues( group->isScalar(), valueIndex, count );
837 }
838
839 return QgsMeshDataBlock();
840}
841
843{
844 // Not supported for now
845 Q_UNUSED( index )
846 Q_UNUSED( faceIndex )
847 Q_UNUSED( count )
848 return QgsMesh3DDataBlock();
849}
850
852{
853 int groupIndex = index.group();
854 if ( index.isValid() && groupIndex < datasetGroupCount() )
855 {
856 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
857 int datasetIndex = index.dataset();
858 if ( datasetIndex < group->datasetCount() )
859 return group->dataset( datasetIndex )->isActive( faceIndex );
860 }
861
862 return false;
863}
864
866{
867 int groupIndex = index.group();
868 if ( index.isValid() && groupIndex < datasetGroupCount() )
869 {
870 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
871 int datasetIndex = index.dataset();
872 if ( datasetIndex < group->datasetCount() )
873 return group->dataset( datasetIndex )->areFacesActive( faceIndex, count );
874 }
875 return QgsMeshDataBlock();
876}
877
879 const QString &outputFilePath,
880 const QString &outputDriver,
881 const QgsMeshDatasetGroupMetadata &meta,
882 const QVector<QgsMeshDataBlock> &datasetValues,
883 const QVector<QgsMeshDataBlock> &datasetActive,
884 const QVector<double> &times
885)
886{
887 Q_UNUSED( outputFilePath )
888 Q_UNUSED( outputDriver )
889 Q_UNUSED( meta )
890 Q_UNUSED( datasetValues )
891 Q_UNUSED( datasetActive )
892 Q_UNUSED( times )
893 return true; // not implemented/supported
894}
895
896bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath, const QString &outputDriver, QgsMeshDatasetSourceInterface *source, int datasetGroupIndex )
897{
898 Q_UNUSED( outputFilePath )
899 Q_UNUSED( outputDriver )
900 Q_UNUSED( source )
901 Q_UNUSED( datasetGroupIndex )
902 return true; // not implemented/supported
903}
904
905QDomElement QgsMeshExtraDatasetStore::writeXml( int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context )
906{
907 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) && mGroups[groupIndex] )
908 return mGroups[groupIndex]->writeXml( doc, context );
909 else
910 return QDomElement();
911}
912
914{
915 //update temporal capabilitie
916 mTemporalCapabilities->clear();
917 bool hasTemporal = false;
918 for ( size_t g = 0; g < mGroups.size(); ++g )
919 {
920 const QgsMeshDatasetGroup *group = mGroups[g].get();
921 hasTemporal |= group->datasetCount() > 1;
922 for ( int i = 0; i < group->datasetCount(); ++i )
923 mTemporalCapabilities->addDatasetTime( g, group->datasetMetadata( i ).time() );
924 }
925
926 mTemporalCapabilities->setHasTemporalCapabilities( hasTemporal );
927}
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