QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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  mExtraDatasets( new QgsMeshExtraDatasetStore ),
48  mDatasetGroupTreeRootItem( new QgsMeshDatasetGroupTreeItem )
49 {}
50 
51 void 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  if ( mExtraDatasets )
67  {
68  const int groupCount = mExtraDatasets->datasetGroupCount();
69  for ( int i = 0; i < groupCount; ++i )
70  if ( mExtraDatasets->datasetGroup( i ) )
71  mExtraDatasets->datasetGroup( i )->initialize();
72  }
73 
74  mExtraDatasets->updateTemporalCapabilities();
75 
76  connect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
77 }
78 
79 QgsMeshDatasetGroupStore::DatasetGroup QgsMeshDatasetGroupStore::datasetGroup( int index ) const
80 {
81  if ( mRegistery.contains( index ) )
82  return mRegistery[index];
83  else
84  return DatasetGroup{nullptr, -1};
85 }
86 
88 {
89  if ( !mPersistentProvider )
90  return false;
91  return mPersistentProvider->addDataset( path ) ;
92 }
93 
95 {
96  if ( !mExtraDatasets && !mLayer )
97  return false;
98 
99  switch ( group->dataType() )
100  {
102  if ( ! group->checkValueCountPerDataset( mLayer->meshFaceCount() ) )
103  return false;
104  break;
106  if ( ! group->checkValueCountPerDataset( mLayer->meshVertexCount() ) )
107  return false;
108  break;
110  return false; // volume not supported for extra dataset
111  break;
113  if ( ! group->checkValueCountPerDataset( mLayer->meshEdgeCount() ) )
114  return false;
115  break;
116  }
117 
118  int nativeIndex = mExtraDatasets->addDatasetGroup( group );
119  int groupIndex = registerDatasetGroup( DatasetGroup{mExtraDatasets.get(), nativeIndex} );
120  QList<int> groupIndexes;
121  groupIndexes.append( groupIndex );
122  createDatasetGroupTreeItems( groupIndexes );
123  syncItemToDatasetGroup( groupIndex );
124 
125  emit datasetGroupsAdded( groupIndexes );
126 
127  return true;
128 }
129 
131 {
132  mDatasetGroupTreeRootItem.reset( new QgsMeshDatasetGroupTreeItem );
133  createDatasetGroupTreeItems( datasetGroupIndexes() );
134  QList<int> groupIndexes = datasetGroupIndexes();
135  for ( int groupIndex : groupIndexes )
136  syncItemToDatasetGroup( groupIndex );
137 }
138 
140 {
141  return mDatasetGroupTreeRootItem.get();
142 }
143 
145 {
146  if ( rootItem )
147  mDatasetGroupTreeRootItem.reset( rootItem->clone() );
148  else
149  mDatasetGroupTreeRootItem.reset();
150 
151  unregisterGroupNotPresentInTree();
152 }
153 
155 {
156  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
157  if ( group.first )
158  return group.first->datasetGroupMetadata( group.second );
159  else
161 }
162 
163 int QgsMeshDatasetGroupStore::datasetCount( int groupIndex ) const
164 {
165  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
166  if ( group.first )
167  return group.first->datasetCount( group.second );
168  else
169  return 0;
170 }
171 
173 {
174  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
175  if ( group.first )
176  return group.first->datasetMetadata( QgsMeshDatasetIndex( group.second, index.dataset() ) );
177  else
178  return QgsMeshDatasetMetadata();
179 }
180 
182 {
183  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
184  if ( group.first )
185  return group.first->datasetValue( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex );
186  else
187  return QgsMeshDatasetValue();
188 }
189 
190 QgsMeshDataBlock QgsMeshDatasetGroupStore::datasetValues( const QgsMeshDatasetIndex &index, int valueIndex, int count ) const
191 {
192  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
193  if ( group.first )
194  return group.first->datasetValues( QgsMeshDatasetIndex( group.second, index.dataset() ), valueIndex, count );
195  else
196  return QgsMeshDataBlock();
197 }
198 
200 {
201  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
202  if ( group.first )
203  return group.first->dataset3dValues( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
204  else
205  return QgsMesh3dDataBlock();
206 }
207 
209 {
210  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
211  if ( group.first )
212  return group.first->areFacesActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex, count );
213  else
214  return QgsMeshDataBlock();
215 }
216 
217 bool QgsMeshDatasetGroupStore::isFaceActive( const QgsMeshDatasetIndex &index, int faceIndex ) const
218 {
219  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
220  if ( group.first )
221  return group.first->isFaceActive( QgsMeshDatasetIndex( group.second, index.dataset() ), faceIndex );
222  else
223  return false;
224 }
225 
227  qint64 time,
229 {
230  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
231  if ( !group.first )
232  return QgsMeshDatasetIndex();
233 
234  const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
235 
236  return QgsMeshDatasetIndex( groupIndex,
237  group.first->datasetIndexAtTime( referenceTime, group.second, time, method ).dataset() );
238 }
239 
241  qint64 time1,
242  qint64 time2,
243  int groupIndex ) const
244 {
245  const QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( groupIndex );
246  if ( !group.first )
247  return QList<QgsMeshDatasetIndex>();
248 
249  const QDateTime &referenceTime = mPersistentProvider ? mPersistentProvider->temporalCapabilities()->referenceTime() : QDateTime();
250 
251  const QList<QgsMeshDatasetIndex> datasetIndexes = group.first->datasetIndexInTimeInterval( referenceTime, group.second, time1, time2 );
252 
253  QList<QgsMeshDatasetIndex> ret;
254  ret.reserve( datasetIndexes.count() );
255 
256  for ( const QgsMeshDatasetIndex &sourceDatasetIndex : datasetIndexes )
257  ret.append( QgsMeshDatasetIndex( groupIndex, sourceDatasetIndex.dataset() ) );
258 
259  return ret;
260 }
261 
263 {
264  QgsMeshDatasetGroupStore::DatasetGroup group = datasetGroup( index.group() );
265  if ( !group.first || group.second < 0 )
266  return INVALID_MESHLAYER_TIME;
267 
268  QgsMeshDatasetIndex nativeIndex( group.second, index.dataset() );
269 
270  if ( group.first == mPersistentProvider )
271  return mPersistentProvider->temporalCapabilities()->datasetTime( nativeIndex );
272  else if ( group.first == mExtraDatasets.get() )
273  return mExtraDatasets->datasetRelativeTime( nativeIndex );
274 
275  return INVALID_MESHLAYER_TIME;
276 
277 }
278 
280 {
281  return ( mPersistentProvider && mPersistentProvider->temporalCapabilities()->hasTemporalCapabilities() ) ||
282  ( mExtraDatasets && mExtraDatasets->hasTemporalCapabilities() );
283 }
284 
285 QDomElement QgsMeshDatasetGroupStore::writeXml( QDomDocument &doc, const QgsReadWriteContext &context )
286 {
287  Q_UNUSED( context );
288  QDomElement storeElement = doc.createElement( QStringLiteral( "mesh-dataset-groups-store" ) );
289  storeElement.appendChild( mDatasetGroupTreeRootItem->writeXml( doc, context ) );
290 
291  QMap < int, DatasetGroup>::const_iterator it = mRegistery.constBegin();
292  while ( it != mRegistery.constEnd() )
293  {
294  QDomElement elemDataset;
295  if ( it.value().first == mPersistentProvider )
296  {
297  elemDataset = doc.createElement( QStringLiteral( "mesh-dataset" ) );
298  elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
299  elemDataset.setAttribute( QStringLiteral( "source-type" ), QStringLiteral( "persitent-provider" ) );
300  elemDataset.setAttribute( QStringLiteral( "source-index" ), it.value().second );
301  }
302  else if ( it.value().first == mExtraDatasets.get() )
303  {
304  QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( it.key() );
305  if ( item )
306  {
307  elemDataset = mExtraDatasets->writeXml( it.value().second, doc, context );
308  if ( !elemDataset.isNull() )
309  elemDataset.setAttribute( QStringLiteral( "global-index" ), it.key() );
310  }
311  }
312 
313  if ( !elemDataset.isNull() )
314  storeElement.appendChild( elemDataset );
315  ++it;
316  }
317 
318  return storeElement;
319 }
320 
321 void QgsMeshDatasetGroupStore::readXml( const QDomElement &storeElem, const QgsReadWriteContext &context )
322 {
323  Q_UNUSED( context );
324  mRegistery.clear();
325  QDomElement datasetElem = storeElem.firstChildElement( "mesh-dataset" );
326  QMap<int, QgsMeshDatasetGroup *> extraDatasetGroups;
327  while ( !datasetElem.isNull() )
328  {
329  int globalIndex = datasetElem.attribute( QStringLiteral( "global-index" ) ).toInt();
330  int sourceIndex = -1;
331  QgsMeshDatasetSourceInterface *source = nullptr;
332  const QString sourceType = datasetElem.attribute( QStringLiteral( "source-type" ) );
333  if ( sourceType == QLatin1String( "persitent-provider" ) )
334  {
335  source = mPersistentProvider;
336  sourceIndex = datasetElem.attribute( QStringLiteral( "source-index" ) ).toInt();
337  mPersistentExtraDatasetGroupIndexes.append( globalIndex );
338  }
339  else if ( sourceType == QLatin1String( "virtual" ) )
340  {
341  source = mExtraDatasets.get();
342  QString name = datasetElem.attribute( QStringLiteral( "name" ) );
343  QString formula = datasetElem.attribute( QStringLiteral( "formula" ) );
344  qint64 startTime = datasetElem.attribute( QStringLiteral( "start-time" ) ).toLongLong();
345  qint64 endTime = datasetElem.attribute( QStringLiteral( "end-time" ) ).toLongLong();
346 
347  QgsMeshDatasetGroup *dsg = new QgsMeshVirtualDatasetGroup( name, formula, mLayer, startTime, endTime );
348  extraDatasetGroups[globalIndex] = dsg;
349  sourceIndex = mExtraDatasets->addDatasetGroup( dsg );
350  }
351  else
352  {
353  QgsDebugMsg( QStringLiteral( "Unhandled source-type: %1." ).arg( sourceType ) );
354  }
355  if ( source )
356  {
357  mRegistery[globalIndex] = DatasetGroup{source, sourceIndex};
358  }
359 
360  datasetElem = datasetElem.nextSiblingElement( QStringLiteral( "mesh-dataset" ) );
361  }
362 
363  QDomElement rootTreeItemElem = storeElem.firstChildElement( QStringLiteral( "mesh-dataset-group-tree-item" ) );
364  if ( !rootTreeItemElem.isNull() )
365  setDatasetGroupTreeItem( new QgsMeshDatasetGroupTreeItem( rootTreeItemElem, context ) );
366 }
367 
369 {
370  for ( QMap<int, DatasetGroup>::const_iterator it = mRegistery.cbegin(); it != mRegistery.cend(); ++it )
371  {
372  if ( it.value().first == source && it.value().second == nativeGroupIndex )
373  return it.key();
374  }
375 
376  return -1;
377 }
378 
379 bool QgsMeshDatasetGroupStore::saveDatasetGroup( QString filePath, int groupIndex, QString driver )
380 {
381  DatasetGroup group = datasetGroup( groupIndex );
382 
383  bool fail = true;
384  if ( group.first && group.second >= 0 )
385  fail = mPersistentProvider->persistDatasetGroup( filePath, driver, group.first, group.second );
386 
387  if ( !fail )
388  {
389  eraseDatasetGroup( group );
390  group.first = mPersistentProvider;
391  group.second = mPersistentProvider->datasetGroupCount() - 1;
392  mRegistery[groupIndex] = group;
393  //update the item type
394  if ( mDatasetGroupTreeRootItem )
395  {
396  QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
397  if ( item )
398  item->setPersistentDatasetGroup( filePath );
399  }
400  }
401 
402  return fail;
403 }
404 
405 void QgsMeshDatasetGroupStore::onPersistentDatasetAdded( int count )
406 {
407  Q_ASSERT( mPersistentProvider );
408 
409  int providerTotalCount = mPersistentProvider->datasetGroupCount();
410  int providerBeginIndex = mPersistentProvider->datasetGroupCount() - count;
411  QList<int> newGroupIndexes;
412  for ( int i = providerBeginIndex; i < providerTotalCount; ++i )
413  {
414  if ( i < mPersistentExtraDatasetGroupIndexes.count() )
415  mRegistery[mPersistentExtraDatasetGroupIndexes.at( i )] = DatasetGroup( mPersistentProvider, i );
416  else
417  newGroupIndexes.append( registerDatasetGroup( DatasetGroup{mPersistentProvider, i} ) );
418  }
419 
420  if ( !newGroupIndexes.isEmpty() )
421  {
422  createDatasetGroupTreeItems( newGroupIndexes );
423  mPersistentExtraDatasetGroupIndexes.append( newGroupIndexes );
424 
425  for ( int groupIndex : std::as_const( newGroupIndexes ) )
426  syncItemToDatasetGroup( groupIndex );
427 
428  emit datasetGroupsAdded( newGroupIndexes );
429  }
430 }
431 
432 void QgsMeshDatasetGroupStore::removePersistentProvider()
433 {
434  if ( !mPersistentProvider )
435  return;
436 
437  disconnect( mPersistentProvider, &QgsMeshDataProvider::datasetGroupsAdded, this, &QgsMeshDatasetGroupStore::onPersistentDatasetAdded );
438 
439  QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
440  while ( it != mRegistery.end() )
441  {
442  if ( it.value().first == mPersistentProvider )
443  it = mRegistery.erase( it );
444  else
445  ++it;
446  }
447 
448  mPersistentProvider = nullptr;
449 }
450 
451 int QgsMeshDatasetGroupStore::newIndex()
452 {
453  int index = 0;
454  QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
455  while ( it != mRegistery.end() )
456  {
457  if ( index <= it.key() )
458  index = it.key() + 1;
459  ++it;
460  }
461  return index;
462 }
463 
464 int QgsMeshDatasetGroupStore::registerDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
465 {
466  int groupIndex = newIndex();
467  mRegistery[newIndex()] = group;
468  return groupIndex;
469 }
470 
471 void QgsMeshDatasetGroupStore::eraseDatasetGroup( const QgsMeshDatasetGroupStore::DatasetGroup &group )
472 {
473  if ( group.first == mPersistentProvider )
474  return; //removing persistent dataset group from the store is not allowed
475  else if ( group.first == mExtraDatasets.get() )
476  eraseExtraDataset( group.second );
477 }
478 
479 void QgsMeshDatasetGroupStore::eraseExtraDataset( int indexInExtraStore )
480 {
481  mExtraDatasets->removeDatasetGroup( indexInExtraStore );
482 
483  //search dataset with index greater than indexInExtraStore and decrement it
484  QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
485  while ( it != mRegistery.end() )
486  {
487  int localIndex = it.value().second;
488  if ( it.value().first == mExtraDatasets.get() && localIndex > indexInExtraStore )
489  it->second = localIndex - 1;
490  ++it;
491  }
492 }
493 
494 int QgsMeshDatasetGroupStore::nativeIndexToGroupIndex( QgsMeshDatasetSourceInterface *source, int nativeIndex )
495 {
496  QMap < int, DatasetGroup>::const_iterator it = mRegistery.constBegin();
497  while ( it != mRegistery.constEnd() )
498  {
499  if ( it.value() == DatasetGroup{source, nativeIndex} )
500  return it.key();
501  ++it;
502  }
503  return -1;
504 }
505 
506 void QgsMeshDatasetGroupStore::checkDatasetConsistency( QgsMeshDatasetSourceInterface *source )
507 {
508  // check if datasets of source are present, if not, add them
509  QList<int> indexes;
510  for ( int i = 0; i < source->datasetGroupCount(); ++i )
511  if ( nativeIndexToGroupIndex( source, i ) == -1 )
512  indexes.append( registerDatasetGroup( DatasetGroup{source, i} ) );
513 
514  if ( !indexes.isEmpty() )
515  createDatasetGroupTreeItems( indexes );
516 
517  for ( int globalIndex : mRegistery.keys() )
518  {
519  if ( mRegistery.value( globalIndex ).first == source )
520  syncItemToDatasetGroup( globalIndex );
521  }
522 }
523 
524 void QgsMeshDatasetGroupStore::removeUnregisteredItemFromTree()
525 {
526  QList<QgsMeshDatasetGroupTreeItem *> itemsToCheck;
527  QList<int> indexItemToRemove;
528  for ( int i = 0; i < mDatasetGroupTreeRootItem->childCount(); ++i )
529  itemsToCheck.append( mDatasetGroupTreeRootItem->child( i ) );
530 
531  while ( !itemsToCheck.isEmpty() )
532  {
533  QgsMeshDatasetGroupTreeItem *item = itemsToCheck.takeFirst();
534  int globalIndex = item->datasetGroupIndex();
535  if ( !mRegistery.contains( globalIndex ) )
536  indexItemToRemove.append( globalIndex );
537  for ( int i = 0; i < item->childCount(); ++i )
538  itemsToCheck.append( item->child( i ) );
539  }
540 
541  for ( int i : indexItemToRemove )
542  {
543  QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( i );
544  if ( item )
545  item->parentItem()->removeChild( item );
546  }
547 }
548 
549 void QgsMeshDatasetGroupStore::unregisterGroupNotPresentInTree()
550 {
551  if ( !mDatasetGroupTreeRootItem )
552  {
553  mRegistery.clear();
554  return;
555  }
556 
557  QMap < int, DatasetGroup>::iterator it = mRegistery.begin();
558  while ( it != mRegistery.end() )
559  {
560  DatasetGroup datasetGroup = it.value();
561  int globalIndex = it.key();
562  if ( ! mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( globalIndex ) // Not in the tree item
563  && datasetGroup.first != mPersistentProvider ) // and not persistent
564  {
565  it = mRegistery.erase( it ); //remove from registery
566  eraseDatasetGroup( datasetGroup ); //remove from where the dataset group is stored
567  }
568  else
569  ++it;
570  }
571 }
572 
573 void QgsMeshDatasetGroupStore::syncItemToDatasetGroup( int groupIndex )
574 {
575  if ( !mDatasetGroupTreeRootItem )
576  return;
577  DatasetGroup group = datasetGroup( groupIndex );
578  QgsMeshDatasetGroupTreeItem *item = mDatasetGroupTreeRootItem->childFromDatasetGroupIndex( groupIndex );
579  if ( group.first == mPersistentProvider && mPersistentProvider )
580  {
581  QgsMeshDatasetGroupMetadata meta = mPersistentProvider->datasetGroupMetadata( group.second );
582  if ( item )
583  item->setPersistentDatasetGroup( meta.uri() );
584  }
585  else if ( group.first == mExtraDatasets.get() )
586  {
587  if ( item )
588  item->setDatasetGroup( mExtraDatasets->datasetGroup( group.second ) );
589  }
590 }
591 
592 void QgsMeshDatasetGroupStore::createDatasetGroupTreeItems( const QList<int> &indexes )
593 {
594  QMap<QString, QgsMeshDatasetGroupTreeItem *> mNameToItem;
595 
596  for ( int i = 0; i < indexes.count(); ++i )
597  {
598  int groupIndex = indexes.at( i );
599  const QgsMeshDatasetGroupMetadata meta = datasetGroupMetadata( groupIndex );
600  const QString name = meta.name();
601  const QStringList subdatasets = name.split( '/' );
602 
603  QString displayName = name;
604  QgsMeshDatasetGroupTreeItem *parent = mDatasetGroupTreeRootItem.get();
605 
606  if ( subdatasets.size() == 2 )
607  {
608  auto it = mNameToItem.find( subdatasets[0] );
609  if ( it == mNameToItem.end() )
610  QgsDebugMsg( QStringLiteral( "Unable to find parent group for %1." ).arg( name ) );
611  else
612  {
613  displayName = subdatasets[1];
614  parent = it.value();
615  }
616  }
617  else if ( subdatasets.size() != 1 )
618  QgsDebugMsg( QStringLiteral( "Ignoring too deep child group name %1." ).arg( name ) );
619 
620  QgsMeshDatasetGroupTreeItem *item = new QgsMeshDatasetGroupTreeItem( displayName, name, meta.isVector(), groupIndex );
621  parent->appendChild( item );
622  if ( mNameToItem.contains( name ) )
623  QgsDebugMsg( QStringLiteral( "Group %1 is not unique" ).arg( displayName ) );
624  mNameToItem[name] = item;
625  }
626 }
627 
629 {
630  int groupIndex = mGroups.size();
631  mGroups.push_back( std::unique_ptr<QgsMeshDatasetGroup>( datasetGroup ) );
632 
633  if ( datasetGroup->datasetCount() > 1 )
634  {
635  mTemporalCapabilities->setHasTemporalCapabilities( true );
636  for ( int i = 0; i < datasetGroup->datasetCount(); ++i )
637  mTemporalCapabilities->addDatasetTime( groupIndex, datasetGroup->datasetMetadata( i ).time() );
638  }
639 
640  return mGroups.size() - 1;
641 }
642 
644 {
645  if ( index < datasetGroupCount() )
646  mGroups.erase( mGroups.begin() + index );
647 
648 
650 }
651 
653 {
654  return mTemporalCapabilities->hasTemporalCapabilities();
655 }
656 
658 {
659  return mTemporalCapabilities->datasetTime( index );
660 }
661 
662 QString QgsMeshExtraDatasetStore::description( int groupIndex ) const
663 {
664  if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
665  return mGroups.at( groupIndex )->description();
666  else
667  return QString();
668 }
669 
671 {
672  if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) )
673  return mGroups[groupIndex].get();
674  else
675  return nullptr;
676 }
677 
678 bool QgsMeshExtraDatasetStore::addDataset( const QString &uri )
679 {
680  Q_UNUSED( uri );
681  return false;
682 }
683 
685 {
686  return QStringList();
687 }
688 
690 {
691  return mGroups.size();
692 }
693 
694 int QgsMeshExtraDatasetStore::datasetCount( int groupIndex ) const
695 {
696  if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
697  return mGroups.at( groupIndex )->datasetCount();
698  else
699  return 0;
700 }
701 
703 {
704  if ( groupIndex >= 0 && groupIndex < datasetGroupCount() )
705  return mGroups.at( groupIndex )->groupMetadata();
706  else
708 }
709 
711 {
712  int groupIndex = index.group();
713  if ( index.isValid() && groupIndex < datasetGroupCount() )
714  {
715  int datasetIndex = index.dataset();
716  const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
717  if ( datasetIndex < group->datasetCount() )
718  return group->datasetMetadata( datasetIndex );
719  }
720  return QgsMeshDatasetMetadata();
721 }
722 
724 {
725  int groupIndex = index.group();
726  if ( index.isValid() && groupIndex < datasetGroupCount() )
727  {
728  const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
729  int datasetIndex = index.dataset();
730  if ( datasetIndex < group->datasetCount() )
731  return group->dataset( datasetIndex )->datasetValue( valueIndex );
732  }
733 
734  return QgsMeshDatasetValue();
735 }
736 
738 {
739  int groupIndex = index.group();
740  if ( index.isValid() && groupIndex < datasetGroupCount() )
741  {
742  const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
743  int datasetIndex = index.dataset();
744  if ( datasetIndex < group->datasetCount() )
745  return group->dataset( datasetIndex )->datasetValues( group->isScalar(), valueIndex, count );
746  }
747 
748  return QgsMeshDataBlock();
749 }
750 
752 {
753  // Not supported for now
754  Q_UNUSED( index )
755  Q_UNUSED( faceIndex )
756  Q_UNUSED( count )
757  return QgsMesh3dDataBlock();
758 }
759 
761 {
762  int groupIndex = index.group();
763  if ( index.isValid() && groupIndex < datasetGroupCount() )
764  {
765  const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
766  int datasetIndex = index.dataset();
767  if ( datasetIndex < group->datasetCount() )
768  return group->dataset( datasetIndex )->isActive( faceIndex );
769  }
770 
771  return false;
772 }
773 
775 {
776  int groupIndex = index.group();
777  if ( index.isValid() && groupIndex < datasetGroupCount() )
778  {
779  const QgsMeshDatasetGroup *group = mGroups.at( groupIndex ).get();
780  int datasetIndex = index.dataset();
781  if ( datasetIndex < group->datasetCount() )
782  return group->dataset( datasetIndex )->areFacesActive( faceIndex, count );
783  }
784  return QgsMeshDataBlock();
785 }
786 
787 bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
788  const QString &outputDriver,
789  const QgsMeshDatasetGroupMetadata &meta,
790  const QVector<QgsMeshDataBlock> &datasetValues,
791  const QVector<QgsMeshDataBlock> &datasetActive,
792  const QVector<double> &times )
793 {
794  Q_UNUSED( outputFilePath )
795  Q_UNUSED( outputDriver )
796  Q_UNUSED( meta )
797  Q_UNUSED( datasetValues )
798  Q_UNUSED( datasetActive )
799  Q_UNUSED( times )
800  return true; // not implemented/supported
801 }
802 
803 bool QgsMeshExtraDatasetStore::persistDatasetGroup( const QString &outputFilePath,
804  const QString &outputDriver,
806  int datasetGroupIndex )
807 {
808  Q_UNUSED( outputFilePath )
809  Q_UNUSED( outputDriver )
810  Q_UNUSED( source )
811  Q_UNUSED( datasetGroupIndex )
812  return true; // not implemented/supported
813 }
814 
815 QDomElement QgsMeshExtraDatasetStore::writeXml( int groupIndex, QDomDocument &doc, const QgsReadWriteContext &context )
816 {
817  if ( groupIndex >= 0 && groupIndex < int( mGroups.size() ) && mGroups[groupIndex] )
818  return mGroups[groupIndex]->writeXml( doc, context );
819  else
820  return QDomElement();
821 }
822 
824 {
825  //update temporal capabilitie
826  mTemporalCapabilities->clear();
827  bool hasTemporal = false;
828  for ( size_t g = 0; g < mGroups.size(); ++g )
829  {
830  const QgsMeshDatasetGroup *group = mGroups[g].get();
831  hasTemporal |= group->datasetCount() > 1;
832  for ( int i = 0; i < group->datasetCount(); ++i )
833  mTemporalCapabilities->addDatasetTime( g, group->datasetMetadata( i ).time() );
834  }
835 
836  mTemporalCapabilities->setHasTemporalCapabilities( hasTemporal );
837 }
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.
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.
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 setDatasetGroupTreeItem(QgsMeshDatasetGroupTreeItem *rootItem)
Sets the root of the dataset groups tree item, doesn't take onwnershib but clone the root item.
void setPersistentProvider(QgsMeshDataProvider *provider, const QStringList &extraDatasetUri)
Sets the persistent mesh data provider with the path of its extra dataset.
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 globalGroupIndex 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.
virtual QgsMeshDataset * dataset(int index) const =0
Returns the dataset with index.
QgsMeshDatasetGroupMetadata::DataType dataType() const
Returns the data type of the dataset group.
virtual int datasetCount() const =0
Returns the count of datasets in the group.
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.
Class that can be used to store and access extra dataset group, like memory dataset (temporary) Deriv...
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.
quint64 datasetRelativeTime(QgsMeshDatasetIndex index)
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:97
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