Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE][MESH] plug mesh layer to QGIS temporal framework #35466

Merged
merged 15 commits into from
Apr 3, 2020

Conversation

vcloarec
Copy link
Member

time

Time handling in mesh layer

The time in a mesh layer is defined by :

  • a reference time provided by the data, the project or the user
  • each dataset is associated with a relative times
  • time extent is defined by the first time and the last time of all dataset
  Reference time :          AT
  Dataset 1 time            o-----RT------RT-----RT-----------RT
  Dataset 2 time            o---------RT------RT--------RT
  Dataset 3 time            o------------------------------RT-------RT----------RT
  Time extent of layer      o-----<--------------------------------------------->
  
  AT : absolute time (QDateTime)
  RT : relative time (qint64)

The class QgsMeshDataprovidertemporalCapabilities stores the reference time provided by the data and all the relative times of the dataset. This class has the ability to return dataset index from a dataset group index and a relative time since the reference time.
The reference time (can be different than the provider reference time) and the absolute time extent are stored in the class QgsMeshTemporalProperties

The temporal settings in the properties widget are only the reference time and the provider time unit:
image

The default reference time of the layer is set by (sorted by priority):

  • from the data provider if defined in data
  • from the project if defined
  • from current date with time 00h00
    The user can change it if he wants.

Rendering principle

The 2D and 3D renderers access to the active dataset index from the layer with the time range stored in the QgsContextRenderer and in the Qgs3DMapSettings :
Relative time is calculated with difference between the time range of QgsContextRenderer and the reference time stored by QgsMeshTemporalProperties. The dataset index come from the QgsMeshDataproviderTemporalCapabilities that maps the relative time with dataset index.

Then data are brought from the provider with the dataset index.

Static dataset

There is also the possibility to set static dataset, that is to choose the dataset that will be rendered independently of the QGIS time controller. To do that the user can check the check box that is is at the bottom of the temporal page of the properties widget:
image
For now, as that was simpler to implement and allows to choose directly wanted dataset, the used can choose independently scalar dataset and vector dataset from combo boxes with the time associated to each dataset (relative time for data without reference time). If wanted, a unique time could be implemented, but that's could lead to inconsistently results with non synchronous dataset.
The static dataset settings are in the temporal page but can be easily put in the source page if wanted.

@github-actions github-actions bot added this to the 3.14.0 milestone Mar 30, 2020
@vcloarec vcloarec changed the title [FEATURE][MESH plug mesh layer to QGIS temporal framework [FEATURE][MESH] plug mesh layer to QGIS temporal framework Mar 30, 2020
@vcloarec vcloarec closed this Mar 31, 2020
@vcloarec vcloarec reopened this Mar 31, 2020
src/3d/qgs3dmapscene.h Show resolved Hide resolved
src/app/3d/qgs3dmapcanvasdockwidget.cpp Outdated Show resolved Hide resolved
src/core/mesh/qgsmeshdataprovidertemporalcapabilities.cpp Outdated Show resolved Hide resolved
if ( datasetTimes.isEmpty() )
return QgsMeshDatasetIndex();

// If requested time is before the timestamp of the first dataset, return the first dataset
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one -- shouldn't we return an "invalid" dataset instead so that nothing gets rendered?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With mesh layer, some datasets (for example, terrain elevation) are not really temporal and there is no reason to not display them for particular time step. But, MDAL doesn't provide way to distinguish "static" datasets and "dynamic" datasets. I used this workaround to always display such datasets, but, sure, it is not very clean... We can add the condition that the dataset group has only one dataset but it is not completely satisfying...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that this situation should be handled by users disabling the temporal option for those layers - that has the effect that the layer is always shown.

One option that is missing here is an equivalent of the raster temporal properties "fixed time range" mode, where a user can manually set a particular time range for that layer to shown within. It's in place to allow the animation framework to work with non-temporal-aware data sources (e.g. geotiff) where a user may have a set of multiple layers representing different time periods, and wants the animation to automatically switch them on or off if they fall within this fixed time range.

I think the mesh layers could also benefit from this option -- it's a "last resort" fallback for users allowing maximum flexibility for animations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set the whole layer static could be a solution for the user, but for mesh layer, there is not only one dataset group, we can have a terrain elevation dataset and many other dynamic dataset groups. I think also about the min/max dataset group...
More over, the problem is the same when the request time is greater than the time extent of the datasets. That is like this because the request of dataset is done with only one relative time value.
I wonder if it will not be better to request dataset with interval of relative time, and add an option to allow the display with the extreme dataset when the request time interval is before or after the time extent of the datasets?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

discussed with Vincent:

  1. implement MDAL_EXPORT bool MDAL_G_isTemporal( DatasetGroupH group );
  2. add isTemporal() to QgsMeshDatasetGroup class
  3. check the code that if group is not temporal, display always regardless of the time settings

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as for "fixed time range" mode, I would propose to have it available (optionally) only for static mesh layers. for dynamic I do not see much sense

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll defer to your superior knowledge of mesh internals here! 👍

src/core/mesh/qgsmeshdataprovidertemporalcapabilities.cpp Outdated Show resolved Hide resolved
src/core/mesh/qgsmeshlayerrenderer.cpp Outdated Show resolved Hide resolved
src/core/mesh/qgsmeshlayertemporalproperties.cpp Outdated Show resolved Hide resolved
src/core/mesh/qgsmeshlayertemporalproperties.cpp Outdated Show resolved Hide resolved
src/core/mesh/qgsmeshtracerenderer.cpp Show resolved Hide resolved
src/core/qgsdataprovider.h Outdated Show resolved Hide resolved
@nyalldawson
Copy link
Collaborator

Looking great! It's nice to see the temporal capabilities being brought into the 3d world too!

The static dataset settings are in the temporal page but can be easily put in the source page if wanted.

I think for consistency with raster layers this should be done

@PeterPetrik
Copy link
Contributor

nice work! Already did some pre-review in the PR in Vincent's fork before official PR

@PeterPetrik PeterPetrik added Changelog Items that are queued to appear in the visual changelog - remove after harvesting Feature Mesh Related to general mesh layer handling (not specific data formats) Needs Documentation When merging a labeled PR, an issue will be created in the Doc repo. Squash! Remember to squash this PR, instead of merging or rebasing labels Mar 31, 2020

void clear();
%Docstring
Clears alls stored reference times and dataset times
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Clears alls stored reference times and dataset times
Clears all stored reference times and dataset times

.. versionadded:: 3.14
%End

virtual const QgsDataProviderTemporalCapabilities *temporalCapabilities() const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to update the existing raster and vector data providers to implement the const version too

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and SIP_SKIP, no?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, correct.

Thinking about this - it might be nicer to make the const version non virtual:

const QgsDataProviderTemporalCapabilities* temporalCapabilities() const { return const_cast< QgsDataProvider* >( this )->temporalCapabilities(); }

?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, very nice and smart!
But, a little cons, there will be no visibility of this const method in the derived class... easier to implement but maybe future issue ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not sure. Something feels "off" about the double virtual method though...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally, as the compiler looks to no like very much this elegant way, I kept the first choice.

src/3d/qgs3dmapscene.h Show resolved Hide resolved
@@ -5470,6 +5471,15 @@ QgsMeshLayer *QgisApp::addMeshLayerPrivate( const QString &url, const QString &b
return nullptr;
}

// Manage default reference time, if not reference time is present by default in the layer -> assign one
if ( ! layer->temporalProperties()->referenceTime().isValid() )
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for now! If there's more need for this in future we could consider adding a method to the layer temporal properties, something like "setDefaultsFromProject( QgsProject* project )" which we call here instead, but for now this is fine.

if ( datasetTimes.isEmpty() )
return QgsMeshDatasetIndex();

// If requested time is before the timestamp of the first dataset, return the first dataset
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue that this situation should be handled by users disabling the temporal option for those layers - that has the effect that the layer is always shown.

One option that is missing here is an equivalent of the raster temporal properties "fixed time range" mode, where a user can manually set a particular time range for that layer to shown within. It's in place to allow the animation framework to work with non-temporal-aware data sources (e.g. geotiff) where a user may have a set of multiple layers representing different time periods, and wants the animation to automatically switch them on or off if they fall within this fixed time range.

I think the mesh layers could also benefit from this option -- it's a "last resort" fallback for users allowing maximum flexibility for animations.

@nyalldawson
Copy link
Collaborator

Looks good to me -- apart from the typo and const note above I'm +1 to merge

@vcloarec
Copy link
Member Author

vcloarec commented Apr 2, 2020

Now, dataset group can be temporal or not.
Temporal dataset are displayed only if a dataset is contained in the current map temporal range (if not, take the last dataset before the time range except if it is the last one of whole the group, so for little time range between to dataset time, there are still a dataset displayed.. not sure explanation is clear, but works fine...).
Non temporal dataset groups (as terrain elevation, min/max group) are always displayed, whatever the map time range.

For now, non temporal are defined in the data provider when there is only one dataset because MDAL doesn't support this feature. Next version of MDAL will support it and the provider will be modified to take account.

@nyalldawson
Copy link
Collaborator

Looks good to me, but I can't comment on the mesh specifics. I'm +1 to merge, but let's give @PeterPetrik a final chance to look over...

@PeterPetrik
Copy link
Contributor

@vcloarec there is failing test for mesh3d

1749   Loc: [../tests/src/3d/testqgs3drendering.cpp(454)]```

@vcloarec vcloarec closed this Apr 2, 2020
@vcloarec vcloarec reopened this Apr 2, 2020
@nyalldawson
Copy link
Collaborator

@PeterPetrik time to merge?

@nirvn
Copy link
Contributor

nirvn commented Apr 3, 2020

Nice to see the disjointed temporal stuff starting to come together :)

@qgis-bot
Copy link
Collaborator

qgis-bot commented Apr 3, 2020

@vcloarec
A documentation ticket has been opened at qgis/QGIS-Documentation#5226
It is your responsibility to visit this ticket and add as much detail as possible for the documentation team to correctly document this change.
Thank you!

@vcloarec vcloarec deleted the QGIS_TIme branch April 4, 2020 14:52
@timlinux timlinux removed the Changelog Items that are queued to appear in the visual changelog - remove after harvesting label May 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Mesh Related to general mesh layer handling (not specific data formats) Needs Documentation When merging a labeled PR, an issue will be created in the Doc repo. Squash! Remember to squash this PR, instead of merging or rebasing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants