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