QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsmeshdatasetgroupstore.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmeshdatasetgroupstore.cpp
3 ---------------------
4 begin : June 2020
5 copyright : (C) 2020 by Vincent Cloarec
6 email : vcloarec at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19#include "moc_qgsmeshdatasetgroupstore.cpp"
20#include "qgsmeshlayer.h"
21#include "qgsmeshlayerutils.h"
22#include "qgsapplication.h"
24#include "qgslogger.h"
25
27{
28 return mRegistry.keys();
29}
30
32{
33 return mDatasetGroupTreeRootItem->enabledDatasetGroupIndexes();
34}
35
37{
38 return mRegistry.count();
39}
40
42{
43 return mExtraDatasets.datasetGroupCount();
44}
45
47 mLayer( layer ),
48 mDatasetGroupTreeRootItem( new QgsMeshDatasetGroupTreeItem )
49{}
50
51void QgsMeshDatasetGroupStore::setPersistentProvider( QgsMeshDataProvider *provider, const QStringList &extraDatasetUri )
52{
53 removePersistentProvider();
54 mPersistentProvider = provider;
55 if ( !mPersistentProvider )
56 return;
57 for ( const QString &uri : extraDatasetUri )
58 mPersistentProvider->addDataset( uri );
59
60 onPersistentDatasetAdded( mPersistentProvider->datasetGroupCount() );
61
62 checkDatasetConsistency( mPersistentProvider );
63 removeUnregisteredItemFromTree();
64
65 //Once everything is in place, initialize the extra dataset groups
66 const int groupCount = mExtraDatasets.datasetGroupCount();
67 for ( int i = 0; i < groupCount; ++i )
68 if ( mExtraDatasets.datasetGroup( i ) )
69 mExtraDatasets.datasetGroup( i )->initialize();
70
71 mExtraDatasets.updateTemporalCapabilities();
72
73 connect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
74}
75
76QgsMeshDatasetGroupStore::DatasetGroup QgsMeshDatasetGroupStore::datasetGroup( int index ) const
77{
78 return mRegistry.value( index, DatasetGroup{nullptr, -1} );
79}
80
82{
83 if ( !mPersistentProvider )
84 return false;
85 return mPersistentProvider->addDataset( path ) ;
86}
87
89{
90 if ( !mLayer )
91 return false;
92
93 switch ( group->dataType() )
94 {
96 if ( ! group->checkValueCountPerDataset( mLayer->meshFaceCount() ) )
97 return false;
98 break;
100 if ( ! group->checkValueCountPerDataset( mLayer->meshVertexCount() ) )
101 return false;
102 break;
104 return false; // volume not supported for extra dataset
105 break;
107 if ( ! group->checkValueCountPerDataset( mLayer->meshEdgeCount() ) )
108 return false;
109 break;
110 }
111
112 int nativeIndex = mExtraDatasets.addDatasetGroup( group );
113 int groupIndex = registerDatasetGroup( DatasetGroup{&mExtraDatasets, nativeIndex} );
114
115 if ( groupIndex == -1 )
116 return false;
117
118 QList<int> groupIndexes;
119 groupIndexes.append( groupIndex );
120 createDatasetGroupTreeItems( groupIndexes );
121 syncItemToDatasetGroup( groupIndex );
122
123 emit datasetGroupsAdded( groupIndexes );
124
125 return true;
126}
127
129{
130 const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index );
131 if ( group.first == mPersistentProvider )
132 mPersistentProvider->removeDatasetGroup( group.second );
133 else if ( group.first == &mExtraDatasets )
134 eraseExtraDataset( group.second );
135
136 reindexDatasetGroups();
137}
138
139void QgsMeshDatasetGroupStore::reindexDatasetGroups()
140{
141 mRegistry.clear();
142 mPersistentExtraDatasetGroupIndexes.clear();
143 mGroupNameToGlobalIndex.clear();
144
145 int globalIndex = 0;
146
147 for ( int i = 0; i < mPersistentProvider->datasetGroupCount(); i++ )
148 {
149 const QString name = mPersistentProvider->datasetGroupMetadata( i ).name();
150 mRegistry[globalIndex] = DatasetGroup{mPersistentProvider, i};
151 mPersistentExtraDatasetGroupIndexes.append( globalIndex );
152 mGroupNameToGlobalIndex.insert( name, globalIndex );
153 globalIndex++;
154 }
155
156 for ( int i = 0; i < mExtraDatasets.datasetGroupCount(); i++ )
157 {
158 QgsMeshDatasetSourceInterface *source = &mExtraDatasets;
159 const QString name = source->datasetGroupMetadata( i ).name();
160 mRegistry[globalIndex] = DatasetGroup{source, i};
161 mGroupNameToGlobalIndex.insert( name, globalIndex );
162 globalIndex++;
163 }
164}
165
167{
168 mDatasetGroupTreeRootItem.reset( new QgsMeshDatasetGroupTreeItem );
169 createDatasetGroupTreeItems( datasetGroupIndexes() );
170 QList<int> groupIndexes = datasetGroupIndexes();
171 for ( int groupIndex : groupIndexes )
172 syncItemToDatasetGroup( groupIndex );
173}
174
176{
177 return mDatasetGroupTreeRootItem.get();
178}
179
181{
182 if ( rootItem )
183 mDatasetGroupTreeRootItem.reset( rootItem->clone() );
184 else
185 mDatasetGroupTreeRootItem.reset();
186
187 unregisterGroupNotPresentInTree();
188}
189
191{
192 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
193 if ( group.first )
194 return group.first->datasetGroupMetadata( group.second );
195 else
197}
198
199int QgsMeshDatasetGroupStore::datasetCount( int groupIndex ) const
200{
201 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
202 if ( group.first )
203 return group.first->datasetCount( group.second );
204 else
205 return 0;
206}
207
209{
210 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
211 if ( group.first )
212 return group.first->datasetMetadata( QgsMeshDatasetIndex( group.second, index.dataset() ) );
213 else
214 return QgsMeshDatasetMetadata();
215}
216
218{
219 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
220 if ( group.first )
221 return group.first->datasetValue( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex );
222 else
223 return QgsMeshDatasetValue();
224}
225
227{
228 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
229 if ( group.first )
230 return group.first->datasetValues( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex, count );
231 else
232 return QgsMeshDataBlock();
233}
234
236{
237 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
238 if ( group.first )
239 return group.first->dataset3dValues( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
240 else
241 return QgsMesh3DDataBlock();
242}
243
245{
246 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
247 if ( group.first )
248 return group.first->areFacesActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
249 else
250 return QgsMeshDataBlock();
251}
252
253bool QgsMeshDatasetGroupStore::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
254{
255 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
256 if ( group.first )
257 return group.first->isFaceActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex );
258 else
259 return false;
260}
261
263 qint64 time,
265{
266 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
267 if ( !group.first )
268 return QgsMeshDatasetIndex();
269
270 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
271
272 return QgsMeshDatasetIndex( groupIndex,
273 group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
274}
275
277 qint64 time1,
278 qint64 time2,
279 int groupIndex ) const
280{
281 const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
282 if ( !group.first )
283 return QList<QgsMeshDatasetIndex>();
284
285 const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
286
287 const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
288
289 QList<QgsMeshDatasetIndex> ret;
290 ret.reserve( datasetIndexes.count() );
291
292 for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
293 ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
294
295 return ret;
296}
297
299{
300 QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
301 if ( !group.first || group.second < 0 )
303
304 QgsMeshDatasetIndex nativeIndex( group.second, index.dataset() );
305
306 if ( group.first == mPersistentProvider )
307 return mPersistentProvider->temporalCapabilities()->datasetTime( nativeIndex );
308 else if ( group.first == &mExtraDatasets )
309 return mExtraDatasets.datasetRelativeTime( nativeIndex );
310
312
313}
314
316{
317 return ( mPersistentProvider && mPersistentProvider->temporalCapabilities()->hasTemporalCapabilities() ) ||
318 ( mExtraDatasets.hasTemporalCapabilities() );
319}
320
321QDomElement QgsMeshDatasetGroupStore::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
322{
323 Q_UNUSED( context );
324 QDomElement storeElement = doc.createElement( QStringLiteral( "mesh-dataset-groups-store" ) );
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( QStringLiteral( "mesh-dataset" ) );
334 elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
335 elemDataset.setAttribute( QStringLiteral( "source-type" ), QStringLiteral( "persitent-provider" ) );
336 elemDataset.setAttribute( QStringLiteral( "source-index" ), 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( QStringLiteral( "global-index" ), 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( QStringLiteral( "name-to-global-index" ) );
357 elemNameToIndex.setAttribute( QStringLiteral( "name" ), it.key() );
358 elemNameToIndex.setAttribute( QStringLiteral( "global-index" ), 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 QMap<int, QgsMeshDatasetGroup *> extraDatasetGroups;
372 while ( !datasetElem.isNull() )
373 {
374 int globalIndex = datasetElem.attribute( QStringLiteral( "global-index" ) ).toInt();
375
376 const QString sourceType = datasetElem.attribute( QStringLiteral( "source-type" ) );
377 if ( sourceType == QLatin1String( "persitent-provider" ) )
378 {
379 mPersistentExtraDatasetGroupIndexes.append( globalIndex );
380 }
381 else if ( sourceType == QLatin1String( "virtual" ) )
382 {
383 QgsMeshDatasetSourceInterface *source = &mExtraDatasets;
384 QString name = datasetElem.attribute( QStringLiteral( "name" ) );
385 QString formula = datasetElem.attribute( QStringLiteral( "formula" ) );
386 qint64 startTime = datasetElem.attribute( QStringLiteral( "start-time" ) ).toLongLong();
387 qint64 endTime = datasetElem.attribute( QStringLiteral( "end-time" ) ).toLongLong();
388
389 QgsMeshDatasetGroup *dsg = new QgsMeshVirtualDatasetGroup( name, formula, mLayer, startTime, endTime );
390 extraDatasetGroups[globalIndex] = dsg;
391 int sourceIndex = mExtraDatasets.addDatasetGroup( dsg );
392
393 mRegistry[globalIndex] = DatasetGroup{source, sourceIndex};
394 }
395 else
396 {
397 QgsDebugError( QStringLiteral( "Unhandled source-type: %1." ).arg( sourceType ) );
398 }
399
400 datasetElem = datasetElem.nextSiblingElement( QStringLiteral( "mesh-dataset" ) );
401 }
402
403 QDomElement nameToIndexElem = storeElem.firstChildElement( "name-to-global-index" );
404 mGroupNameToGlobalIndex.clear();
405 while ( !nameToIndexElem.isNull() )
406 {
407 QString name = nameToIndexElem.attribute( QStringLiteral( "name" ) );
408 int globalIndex = nameToIndexElem.attribute( QStringLiteral( "global-index" ) ).toInt();
409
410 mGroupNameToGlobalIndex.insert( name, globalIndex );
411
412 nameToIndexElem = nameToIndexElem.nextSiblingElement( QStringLiteral( "name-to-global-index" ) );
413 }
414
415 QDomElement rootTreeItemElem = storeElem.firstChildElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
416 if ( !rootTreeItemElem.isNull() )
417 {
418 const QgsMeshDatasetGroupTreeItem groupTreeItem( rootTreeItemElem, context );
419 setDatasetGroupTreeItem( &groupTreeItem );
420 }
421}
422
424{
425 for ( QMap<int, DatasetGroup>::const_iterator it = mRegistry.cbegin(); it != mRegistry.cend(); ++it )
426 {
427 if ( it.value().first == source && it.value().second == nativeGroupIndex )
428 return it.key();
429 }
430
431 return -1;
432}
433
434int QgsMeshDatasetGroupStore::indexFromGroupName( const QString &groupName ) const
435{
436 return mGroupNameToGlobalIndex.value( groupName, -1 );
437}
438
439QString QgsMeshDatasetGroupStore::groupName( int groupIndex ) const
440{
441 return datasetGroupMetadata( groupIndex ).name();
442}
443
444bool QgsMeshDatasetGroupStore::saveDatasetGroup( QString filePath, int groupIndex, QString driver )
445{
446 DatasetGroup group = datasetGroup( groupIndex );
447
448 bool fail = true;
449 if ( group.first && group.second >= 0 )
450 fail = mPersistentProvider->persistDatasetGroup( filePath, driver, group.first, group.second );
451
452 if ( !fail )
453 {
454 eraseDatasetGroup( group );
455 group.first = mPersistentProvider;
456 group.second = mPersistentProvider->datasetGroupCount() - 1;
457 mRegistry[groupIndex] = group;
458 //update the item type
459 if ( mDatasetGroupTreeRootItem )
460 {
461 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
462 if ( item )
463 item->setPersistentDatasetGroup( filePath );
464 }
465 }
466
467 return fail;
468}
469
470void QgsMeshDatasetGroupStore::onPersistentDatasetAdded( int count )
471{
472 Q_ASSERT( mPersistentProvider );
473
474 int providerTotalCount = mPersistentProvider->datasetGroupCount();
475 int providerBeginIndex = mPersistentProvider->datasetGroupCount() - count;
476 QList<int> newGroupIndexes;
477 for ( int i = providerBeginIndex; i < providerTotalCount; ++i )
478 {
479 const QString groupName = mPersistentProvider->datasetGroupMetadata( i ).name();
480 if ( mGroupNameToGlobalIndex.empty() && i < mPersistentExtraDatasetGroupIndexes.count() )
481 {
482 // This happens with QGIS project saved with version < 3.28
483 mRegistry[mPersistentExtraDatasetGroupIndexes.at( i )] = DatasetGroup( mPersistentProvider, i );
484 }
485 else if ( mGroupNameToGlobalIndex.contains( groupName ) )
486 {
487 // The dataset group name is associated with an index, so it is not a new dataset group
488 registerDatasetGroup( DatasetGroup{mPersistentProvider, i} );
489 }
490 else
491 {
492 int newGroupIndex = registerDatasetGroup( DatasetGroup{mPersistentProvider, i} );
493 if ( newGroupIndex != -1 )
494 newGroupIndexes.append( newGroupIndex );
495 }
496 }
497
498 if ( !newGroupIndexes.isEmpty() )
499 {
500 createDatasetGroupTreeItems( newGroupIndexes );
501 mPersistentExtraDatasetGroupIndexes.append( newGroupIndexes );
502
503 for ( int groupIndex : std::as_const( newGroupIndexes ) )
504 syncItemToDatasetGroup( groupIndex );
505
506 emit datasetGroupsAdded( newGroupIndexes );
507 }
508}
509
510void QgsMeshDatasetGroupStore::removePersistentProvider()
511{
512 if ( !mPersistentProvider )
513 return;
514
515 disconnect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
516
517 QMap < int, DatasetGroup>::iterator it = mRegistry.begin();
518 while ( it != mRegistry.end() )
519 {
520 if ( it.value().first == mPersistentProvider )
521 it = mRegistry.erase( it );
522 else
523 ++it;
524 }
525
526 mPersistentProvider = nullptr;
527}
528
529int QgsMeshDatasetGroupStore::newIndex()
530{
531 QSet usedIndex = qgis::listToSet( mRegistry.keys() );
532 usedIndex.unite( qgis::listToSet( mGroupNameToGlobalIndex.values() ) );
533 int index = 0;
534
535 while ( usedIndex.contains( index ) )
536 ++index;
537
538 return index;
539}
540
541int QgsMeshDatasetGroupStore::registerDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
542{
543 const QString &name = group.first->datasetGroupMetadata( group.second ).name();
544 auto it = mGroupNameToGlobalIndex.find( name );
545
546 int groupIndex;
547 if ( it != mGroupNameToGlobalIndex.end() )
548 {
549 groupIndex = it.value();
550
551 if ( mRegistry.contains( groupIndex ) )
552 {
553 QgsDebugError( QStringLiteral( "Duplicate group name for %1." ).arg( name ) );
554 return -1; // The registry has already a group with this index, we can't have two groups with the same name
555 }
556 }
557 else
558 {
559 groupIndex = newIndex();
560 mGroupNameToGlobalIndex.insert( name, groupIndex );
561 }
562
563 mRegistry[groupIndex] = group;
564 return groupIndex;
565}
566
567void QgsMeshDatasetGroupStore::eraseDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
568{
569 if ( group.first == mPersistentProvider )
570 return; //removing persistent dataset group from the store is not allowed
571 else if ( group.first == &mExtraDatasets )
572 eraseExtraDataset( group.second );
573}
574
575void QgsMeshDatasetGroupStore::eraseExtraDataset( int indexInExtraStore )
576{
577 mExtraDatasets.removeDatasetGroup( indexInExtraStore );
578
579 //search dataset with index greater than indexInExtraStore and decrement it
580 QMap < int, DatasetGroup>::iterator it = mRegistry.begin();
581 while ( it != mRegistry.end() )
582 {
583 int localIndex = it.value().second;
584 if ( it.value().first == &mExtraDatasets && localIndex > indexInExtraStore )
585 it->second = localIndex - 1;
586 ++it;
587 }
588}
589
590void QgsMeshDatasetGroupStore::checkDatasetConsistency( QgsMeshDatasetSourceInterface *source )
591{
592 // check if datasets of source are present, if not, add them
593 QList<int> indexes;
594 for ( int i = 0; i < source->datasetGroupCount(); ++i )
595 {
596 int globalIndex = globalDatasetGroupIndexInSource( source, i );
597 if ( globalIndex == -1 )
598 globalIndex = registerDatasetGroup( DatasetGroup{source, i} );
599
600 if ( globalIndex != - 1 )
601 indexes.append( globalIndex );
602 }
603
604 if ( !indexes.isEmpty() )
605 createDatasetGroupTreeItems( indexes );
606
607 const QList<int> globalIndexes = mRegistry.keys();
608 for ( int globalIndex : globalIndexes )
609 {
610 if ( mRegistry.value( globalIndex ).first == source )
611 syncItemToDatasetGroup( globalIndex );
612 }
613}
614
615void QgsMeshDatasetGroupStore::removeUnregisteredItemFromTree()
616{
617 QList<QgsMeshDatasetGroupTreeItem *> itemsToCheck;
618 QList<int> indexItemToRemove;
619 for ( int i = 0; i < mDatasetGroupTreeRootItem->childCount(); ++i )
620 itemsToCheck.append( mDatasetGroupTreeRootItem->child( i ) );
621
622 while ( !itemsToCheck.isEmpty() )
623 {
624 QgsMeshDatasetGroupTreeItem *item = itemsToCheck.takeFirst();
625 int globalIndex = item->datasetGroupIndex();
626 if ( !mRegistry.contains( globalIndex ) )
627 indexItemToRemove.append( globalIndex );
628 for ( int i = 0; i < item->childCount(); ++i )
629 itemsToCheck.append( item->child( i ) );
630 }
631
632 for ( int i : indexItemToRemove )
633 {
634 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( i );
635 if ( item )
636 item->parentItem()->removeChild( item );
637 }
638}
639
640void QgsMeshDatasetGroupStore::unregisterGroupNotPresentInTree()
641{
642 if ( !mDatasetGroupTreeRootItem )
643 {
644 mRegistry.clear();
645 return;
646 }
647
648 QMap < int, DatasetGroup>::iterator it = mRegistry.begin();
649 while ( it != mRegistry.end() )
650 {
651 DatasetGroup datasetGroup = it.value();
652 int globalIndex = it.key();
653 if ( ! mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( globalIndex ) // Not in the tree item
654 && datasetGroup.first != mPersistentProvider ) // and not persistent
655 {
656 it = mRegistry.erase( it ); //remove from registry
657 eraseDatasetGroup( datasetGroup ); //remove from where the dataset group is stored
658 }
659 else
660 ++it;
661 }
662}
663
664void QgsMeshDatasetGroupStore::syncItemToDatasetGroup( int groupIndex )
665{
666 if ( !mDatasetGroupTreeRootItem )
667 return;
668 const DatasetGroup group = datasetGroup( groupIndex );
669 QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
670 if ( group.first == mPersistentProvider && mPersistentProvider )
671 {
672 const QgsMeshDatasetGroupMetadata meta = mPersistentProvider->datasetGroupMetadata( group.second );
673 if ( item )
674 item->setPersistentDatasetGroup( meta.uri() );
675 }
676 else if ( group.first == &mExtraDatasets )
677 {
678 if ( item )
679 item->setDatasetGroup( mExtraDatasets.datasetGroup( group.second ) );
680 }
681}
682
683void QgsMeshDatasetGroupStore::createDatasetGroupTreeItems( const QList<int> &indexes )
684{
685 QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
686
687 for ( int i = 0; i < indexes.count(); ++i )
688 {
689 int groupIndex = indexes.at( i );
690 if ( mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex ) )
691 continue; //item already exists
692 const QgsMeshDatasetGroupMetadata meta = datasetGroupMetadata( groupIndex );
693 const QString name = meta.name();
694 const QStringList subdatasets = name.split( '/' );
695
696 QString displayName = name;
697 QgsMeshDatasetGroupTreeItem *parent = mDatasetGroupTreeRootItem.get();
698
699 if ( subdatasets.size() == 2 )
700 {
701 auto it = mNameToItem.find( subdatasets[0] );
702 if ( it == mNameToItem.end() )
703 QgsDebugError( QStringLiteral( "Unable to find parent group for %1." ).arg( name ) );
704 else
705 {
706 displayName = subdatasets[1];
707 parent = it.value();
708 }
709 }
710 else if ( subdatasets.size() != 1 )
711 QgsDebugError( QStringLiteral( "Ignoring too deep child group name %1." ).arg( name ) );
712
713 QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( displayName, name, meta.isVector(), groupIndex );
714 parent->appendChild( item );
715 if ( mNameToItem.contains( name ) )
716 QgsDebugError( QStringLiteral( "Group %1 is not unique" ).arg( displayName ) );
717 mNameToItem[name] = item;
718 }
719}
720
722{
723 int groupIndex = mGroups.size();
724 mGroups.push_back( std::unique_ptr<QgsMeshDatasetGroup>( datasetGroup ) );
725
726 if ( datasetGroup->datasetCount() > 1 )
727 {
728 mTemporalCapabilities->setHasTemporalCapabilities( true );
729 for ( int i = 0; i < datasetGroup->datasetCount(); ++i )
730 mTemporalCapabilities->addDatasetTime( groupIndex, datasetGroup->datasetMetadata( i ).time() );
731 }
732
733 return mGroups.size() - 1;
734}
735
737{
738 if ( groupIndex < datasetGroupCount() )
739 mGroups.erase( mGroups.begin() + groupIndex );
740
741
743}
744
746{
747 return mTemporalCapabilities->hasTemporalCapabilities();
748}
749
751{
752 return mTemporalCapabilities->datasetTime( index );
753}
754
755QString QgsMeshExtraDatasetStore::description( int groupIndex ) const
756{
757 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
758 return mGroups.at( groupIndex )->description();
759 else
760 return QString();
761}
762
764{
765 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
766 return mGroups[groupIndex].get();
767 else
768 return nullptr;
769}
770
771bool QgsMeshExtraDatasetStore::addDataset( const QString &uri )
772{
773 Q_UNUSED( uri );
774 return false;
775}
776
778{
779 return QStringList();
780}
781
783{
784 return mGroups.size();
785}
786
787int QgsMeshExtraDatasetStore::datasetCount( int groupIndex ) const
788{
789 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
790 return mGroups.at( groupIndex )->datasetCount();
791 else
792 return 0;
793}
794
796{
797 if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
798 return mGroups.at( groupIndex )->groupMetadata();
799 else
801}
802
804{
805 int groupIndex = index.group();
806 if ( index.isValid() && groupIndex < datasetGroupCount() )
807 {
808 int datasetIndex = index.dataset();
809 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
810 if ( datasetIndex < group->datasetCount() )
811 return group->datasetMetadata( datasetIndex );
812 }
813 return QgsMeshDatasetMetadata();
814}
815
817{
818 int groupIndex = index.group();
819 if ( index.isValid() && groupIndex < datasetGroupCount() )
820 {
821 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
822 int datasetIndex = index.dataset();
823 if ( datasetIndex < group->datasetCount() )
824 return group->dataset( datasetIndex )->datasetValue( valueIndex );
825 }
826
827 return QgsMeshDatasetValue();
828}
829
831{
832 int groupIndex = index.group();
833 if ( index.isValid() && groupIndex < datasetGroupCount() )
834 {
835 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
836 int datasetIndex = index.dataset();
837 if ( datasetIndex < group->datasetCount() )
838 return group->dataset( datasetIndex )->datasetValues( group->isScalar(), valueIndex, count );
839 }
840
841 return QgsMeshDataBlock();
842}
843
845{
846 // Not supported for now
847 Q_UNUSED( index )
848 Q_UNUSED( faceIndex )
849 Q_UNUSED( count )
850 return QgsMesh3DDataBlock();
851}
852
854{
855 int groupIndex = index.group();
856 if ( index.isValid() && groupIndex < datasetGroupCount() )
857 {
858 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
859 int datasetIndex = index.dataset();
860 if ( datasetIndex < group->datasetCount() )
861 return group->dataset( datasetIndex )->isActive( faceIndex );
862 }
863
864 return false;
865}
866
868{
869 int groupIndex = index.group();
870 if ( index.isValid() && groupIndex < datasetGroupCount() )
871 {
872 const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
873 int datasetIndex = index.dataset();
874 if ( datasetIndex < group->datasetCount() )
875 return group->dataset( datasetIndex )->areFacesActive( faceIndex, count );
876 }
877 return QgsMeshDataBlock();
878}
879
880bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
881 const QString &outputDriver,
882 const QgsMeshDatasetGroupMetadata &meta,
883 const QVector<QgsMeshDataBlock> &datasetValues,
884 const QVector<QgsMeshDataBlock> &datasetActive,
885 const QVector<double> &times )
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,
897 const QString &outputDriver,
899 int datasetGroupIndex )
900{
901 Q_UNUSED( outputFilePath )
902 Q_UNUSED( outputDriver )
903 Q_UNUSED( source )
904 Q_UNUSED( datasetGroupIndex )
905 return true; // not implemented/supported
906}
907
908QDomElement QgsMeshExtraDatasetStore::writeXml( int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context )
909{
910 if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) && mGroups[groupIndex] )
911 return mGroups[groupIndex]->writeXml( doc, context );
912 else
913 return QDomElement();
914}
915
917{
918 //update temporal capabilitie
919 mTemporalCapabilities->clear();
920 bool hasTemporal = false;
921 for ( size_t g = 0; g < mGroups.size(); ++g )
922 {
923 const QgsMeshDatasetGroup *group = mGroups[g].get();
924 hasTemporal |= group->datasetCount() > 1;
925 for ( int i = 0; i < group->datasetCount(); ++i )
926 mTemporalCapabilities->addDatasetTime( g, group->datasetMetadata( i ).time() );
927 }
928
929 mTemporalCapabilities->setHasTemporalCapabilities( hasTemporal );
930}
bool hasTemporalCapabilities() const
Returns true if the provider has temporal capabilities available.
QgsMesh3DDataBlock is a block of 3d stacked mesh data related N faces defined on base mesh frame.
QgsMeshDataBlock is a block of integers/doubles that can be used to retrieve: active flags (e....
QDateTime referenceTime() const
Returns the reference time.
MatchingTemporalDatasetMethod
Method for selection of temporal mesh dataset from a range time.
qint64 datasetTime(const QgsMeshDatasetIndex &index) const
Returns the relative time in milliseconds of the dataset.
Base class for providing data for QgsMeshLayer.
virtual bool removeDatasetGroup(int index)=0
Remove dataset group from the mesh.
void datasetGroupsAdded(int count)
Emitted when some new dataset groups have been added.
QgsMeshDataProviderTemporalCapabilities * temporalCapabilities() override
Returns the provider's temporal capabilities.
QgsMeshDatasetGroupMetadata is a collection of dataset group metadata such as whether the data is vec...
bool isVector() const
Returns whether dataset group has vector data.
QString name() const
Returns name of the dataset group.
@ DataOnEdges
Data is defined on edges.
@ DataOnFaces
Data is defined on faces.
@ DataOnVertices
Data is defined on vertices.
@ DataOnVolumes
Data is defined on volumes.
QString uri() const
Returns the uri of the source.
QgsMeshDatasetGroupTreeItem * datasetGroupTreeItem() const
Returns a pointer to the root of the dataset groups tree item.
QgsMeshDatasetMetadata datasetMetadata(const QgsMeshDatasetIndex &index) const
Returns the metadata of the dataset with global index.
void setDatasetGroupTreeItem(const QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root of the dataset groups tree item.
QList< int > enabledDatasetGroupIndexes() const
Returns a list of all group indexes that are enabled.
bool addPersistentDatasets(const QString &path)
Adds persistent datasets from a file with path.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(const QgsMeshDatasetIndex &index) const
Returns the metadata of the dataset group with global index.
bool isFaceActive(const QgsMeshDatasetIndex &index, int faceIndex) const
Returns whether face is active for particular dataset.
QList< int > datasetGroupIndexes() const
Returns a list of all group indexes.
bool hasTemporalCapabilities() const
Returns whether at lea&st one of stored dataset group is temporal.
void resetDatasetGroupTreeItem()
Resets to default state the dataset groups tree item.
QgsMeshDataBlock datasetValues(const QgsMeshDatasetIndex &index, int valueIndex, int count) const
Returns count values of the dataset with global index and from valueIndex.
QgsMeshDatasetIndex datasetIndexAtTime(qint64 time, int groupIndex, QgsMeshDataProviderTemporalCapabilities::MatchingTemporalDatasetMethod method) const
Returns the global dataset index of the dataset int the dataset group with groupIndex,...
bool saveDatasetGroup(QString filePath, int groupIndex, QString driver)
Saves on a file with filePath the dataset groups index with groupIndex with the specified driver.
QList< QgsMeshDatasetIndex > datasetIndexInTimeInterval(qint64 time1, qint64 time2, int groupIndex) const
Returns the global dataset index of the dataset int the dataset group with groupIndex,...
bool addDatasetGroup(QgsMeshDatasetGroup *group)
Adds a extra dataset group, take ownership, returns True if the group is effectivly added.
QgsMeshDatasetValue datasetValue(const QgsMeshDatasetIndex &index, int valueIndex) const
Returns the value of the dataset with global index and valueIndex.
void removeDatasetGroup(int groupIndex)
Removes dataset group with global index groupIndex.
QDomElement writeXml(QDomDocument &doc, const QgsReadWriteContext &context)
Writes the store's information in a DOM document.
int extraDatasetGroupCount() const
Returns the count of extra dataset groups.
int datasetGroupCount() const
Returns the count of dataset groups.
QgsMeshDatasetGroupStore(QgsMeshLayer *layer)
Constructor.
QgsMeshDataBlock areFacesActive(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns whether faces are active for particular dataset.
QString groupName(int groupIndex) const
Returns the name of the dataset group with global index groupIndex.
void setPersistentProvider(QgsMeshDataProvider *provider, const QStringList &extraDatasetUri)
Sets the persistent mesh data provider with the path of its extra dataset to be loaded by the provide...
qint64 datasetRelativeTime(const QgsMeshDatasetIndex &index) const
Returns the relative time of the dataset from the persistent provider reference time.
int datasetCount(int groupIndex) const
Returns the total count of dataset group in the store.
void readXml(const QDomElement &storeElem, const QgsReadWriteContext &context)
Reads the store's information from a DOM document.
int globalDatasetGroupIndexInSource(QgsMeshDatasetSourceInterface *source, int nativeGroupIndex) const
Returns the global dataset group index of the dataset group with native index nativeGroupIndex in the...
int indexFromGroupName(const QString &groupName) const
Returns the global dataset group index of the dataset with name groupName.
void datasetGroupsAdded(QList< int > indexes)
Emitted after dataset groups are added.
QgsMesh3DDataBlock dataset3dValues(const QgsMeshDatasetIndex &index, int faceIndex, int count) const
Returns count 3D values of the dataset with global index and from valueIndex.
Tree item for display of the mesh dataset groups.
QgsMeshDatasetGroupTreeItem * clone() const
Clones the item.
void setPersistentDatasetGroup(const QString &uri)
Set parameters of the item in accordance with the persistent dataset group with uri.
int childCount() const
Returns the count of children.
QgsMeshDatasetGroupTreeItem * parentItem() const
Returns the parent item, nullptr if it is root item.
void removeChild(QgsMeshDatasetGroupTreeItem *item)
Removes and destroy a item child if exists.
void setDatasetGroup(QgsMeshDatasetGroup *datasetGroup)
Set parameters of the item in accordance with the dataset group.
void appendChild(QgsMeshDatasetGroupTreeItem *item)
Appends a child item.
QgsMeshDatasetGroupTreeItem * child(int row) const
Returns a child.
Abstract class that represents a dataset group.
bool isScalar() const
Returns whether the group contain scalar values.
bool checkValueCountPerDataset(int count) const
Returns whether all the datasets contain count values.
virtual QgsMeshDatasetMetadata datasetMetadata(int datasetIndex) const =0
Returns the metadata of the dataset with index datasetIndex.
QgsMeshDatasetGroupMetadata::DataType dataType() const
Returns the data type of the dataset group.
virtual void initialize()=0
Initialize the dataset group.
virtual int datasetCount() const =0
Returns the count of datasets in the group.
virtual QgsMeshDataset * dataset(int index) const =0
Returns the dataset with index.
QgsMeshDatasetIndex is index that identifies the dataset group (e.g.
bool isValid() const
Returns whether index is valid, ie at least groups is set.
int group() const
Returns a group index.
int dataset() const
Returns a dataset index within group()
QgsMeshDatasetMetadata is a collection of mesh dataset metadata such as whether the data is valid or ...
double time() const
Returns the time value for this dataset.
Interface for mesh datasets and dataset groups.
virtual Q_DECL_DEPRECATED bool persistDatasetGroup(const QString &path, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times)
Creates a new dataset group from a data and persists it into a destination path.
virtual QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const =0
Returns dataset group metadata.
virtual int datasetGroupCount() const =0
Returns number of datasets groups loaded.
std::unique_ptr< QgsMeshDataProviderTemporalCapabilities > mTemporalCapabilities
virtual bool addDataset(const QString &uri)=0
Associate dataset with the mesh.
QgsMeshDatasetValue represents single dataset value.
virtual QgsMeshDataBlock datasetValues(bool isScalar, int valueIndex, int count) const =0
Returns count values from valueIndex.
virtual bool isActive(int faceIndex) const =0
Returns whether the face is active.
virtual QgsMeshDataBlock areFacesActive(int faceIndex, int count) const =0
Returns whether faces are active.
virtual QgsMeshDatasetValue datasetValue(int valueIndex) const =0
Returns the value with index valueIndex.
int datasetCount(int groupIndex) const override
Returns number of datasets loaded in the group.
QString description(int groupIndex) const
Returns information related to the dataset group with groupIndex.
void updateTemporalCapabilities()
Updates the temporal capabilities.
QStringList extraDatasets() const override
Not implemented, always returns empty list.
QgsMeshDatasetGroup * datasetGroup(int groupIndex) const
Returns a pointer to the dataset group.
QgsMesh3DDataBlock dataset3dValues(QgsMeshDatasetIndex index, int faceIndex, int count) const override
Returns N vector/scalar values from the face index from the dataset for 3d stacked meshes.
bool persistDatasetGroup(const QString &outputFilePath, const QString &outputDriver, const QgsMeshDatasetGroupMetadata &meta, const QVector< QgsMeshDataBlock > &datasetValues, const QVector< QgsMeshDataBlock > &datasetActive, const QVector< double > &times) override
Not implemented, always returns true.
qint64 datasetRelativeTime(QgsMeshDatasetIndex index) const
Returns the relative times of the dataset index with index, returned value in milliseconds.
QgsMeshDataBlock datasetValues(QgsMeshDatasetIndex index, int valueIndex, int count) const override
Returns N vector/scalar values from the index from the dataset.
int addDatasetGroup(QgsMeshDatasetGroup *datasetGroup)
Adds a dataset group, returns the index of the added dataset group.
QgsMeshDataBlock areFacesActive(QgsMeshDatasetIndex index, int faceIndex, int count) const override
Returns whether the faces are active for particular dataset.
int datasetGroupCount() const override
Returns number of datasets groups loaded.
bool hasTemporalCapabilities() const
Returns whether if the dataset groups have temporal capabilities (a least one dataset group with more...
bool isFaceActive(QgsMeshDatasetIndex index, int faceIndex) const override
Returns whether the face is active for particular dataset.
QDomElement writeXml(int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context)
Writes the store's information in a DOM document.
QgsMeshDatasetMetadata datasetMetadata(QgsMeshDatasetIndex index) const override
Returns dataset metadata.
void removeDatasetGroup(int index)
Removes the dataset group with the local index.
QgsMeshDatasetGroupMetadata datasetGroupMetadata(int groupIndex) const override
Returns dataset group metadata.
QgsMeshDatasetValue datasetValue(QgsMeshDatasetIndex index, int valueIndex) const override
Returns vector/scalar value associated with the index from the dataset To read multiple continuous va...
bool addDataset(const QString &uri) override
Not implemented, always returns false.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
int meshFaceCount() const
Returns the faces count of the mesh frame.
int meshEdgeCount() const
Returns the edges count of the mesh frame.
int meshVertexCount() const
Returns the vertices count of the mesh frame.
Represents a dataset group calculated from a formula string.
The class is used as a container of context for various read/write operations on other objects.
#define QgsDebugError(str)
Definition qgslogger.h:38