qgis / QGIS-Enhancement-Proposals

QEP's (QGIS Enhancement Proposals) are used in the process of creating and discussing new enhancements for QGIS
118 stars 37 forks source link

Add vertical CRS handling to QGIS #267

Open nyalldawson opened 1 year ago

nyalldawson commented 1 year ago

QGIS Enhancement: Add vertical CRS handling to QGIS

Date 2023/05/02

Author Nyall Dawson (@nyalldawson)

Contact nyall dot dawson at gmail dot com

maintainer @nyalldawson

Version QGIS 3.34

Summary

Coordinate Reference Systems (CRS) can consist of both a horizontal and vertical component, where the vertical component contains information about datum used for elevation values in that CRS. While the underlying PROJ library has mature support for vertical CRS, these are not utilised anywhere within QGIS (and for legacy reasons, QGIS actively removes all vertical CRS information from datasets).

This limitation blocks a wide range of valuable use cases for QGIS users, including transformation of data between two different height datums. Correct handling of vertical datums is of particular importance when viewing datasets in 3D or elevation profile views, where datasets from potentially different vertical datums must be correctly vertically aligned with respect to each other. Furthermore, because QGIS currently actively removes all vertical datum information from datasets, it is impossible to determine properties of elevation/Z data such as the vertical measurement units (i.e. meters or feet), which in turns makes it impossible for QGIS to perform calculations such as determining the slope for a elevation profile measurement.

Legacy Reasons for Removing Vertical CRS Information

As mentioned in the Summary section, current QGIS versions actively remove any vertical component from dataset CRS information. This decision was made during the initial port of QGIS from the older PROJ 4 library version to PROJ 6. At this time, a huge refactoring was undertaken in order to move all of the coordinate reference system and transformation handling and logic from being custom logic within QGIS to instead relying on PROJ for ALL CRS, datum, and transformation logic. This was a very large, complex project and in order to minimise the impact of the changes it was decided to strip the vertical CRS information in order to maintain the same transformation results and handling as QGIS users would get when using QGIS versions built with the older PROJ 4 release.

The transition to PROJ 6 is now well in the past, and all QGIS builds require at least the PROJ 7.2 version or later. Accordingly, we are no longer bound by these legacy restrictions.

Proposed Solution

In keeping with best practice, we will rely on the PROJ library's support for vertical CRS as much as possible. All handling of vertical datums, reference systems and vertical transformations will be delegated to PROJ and no duplication of logic between QGIS and PROJ will be permitted. We will rely entirely on the PROJ CRS database for vertical CRS/datum properties and on PROJ's logic for determining the appropriate transformation pipelines to use when converting between two vertical datums.

Despite this, there are many changes required throughout the QGIS code base in order to support vertical CRS handling.

Targeted Deliverables

  1. Extend the QgsCoordinateReferenceSystem class to handle vertical and compound (horizontal + vertical) CRS. While the underlying CRS support in QGIS resides in the PROJ library, the QgsCoordinateReferenceSystem class wraps the PROJ library into API which fits into the QGIS and PyQGIS framework. Currently, this class is designed around the needs of a single horizontal CRS only and needs extending to support vertical and compound CRS. This class will be reworked to retain vertical CRS information, and methods added for determining the type of CRS and extracting the horizontal or vertical components only from compound CRSes.

  2. Ensure that coordinate transformations between two CRSes respect the vertical datums. Whilst the actual low-level transformation logic resides in the PROJ library, changes are required in the QGIS classes which utilise PROJ's transformation functionality in order to ensure that vertical/elevation values are correctly passed to PROJ for transformation.

  3. Add support for vertical datums to the QGIS classes (QgsDatumTransform, QgsCoordinateTransformContext and QgsCoordinateOperationWidget) which expose transformation pipelines to users. These classes are used when two datasets are loaded into QGIS with different datums, and there are multiple possible transformation pipelines to use to convert between the reference systems.

  4. Ensure that any vertical CRS information in existing datasets is retained when loading the dataset into QGIS. Many dataset formats support vertical CRS storage, for example the GDAL library makes this accessible to QGIS. We need to ensure when loading any datasets from data providers which support vertical CRS/datums that this information is not discarded, but is instead retained so that the QGIS codebase (and plugins) have access to this information. Initially, this support will be implemented and tested for the GDAL, OGR and PDAL providers only, but may be extended to other applicable data providers in future. Support will be added for both PROJ Vertical CRS + Compound CRSes.

  5. Expose vertical CRS metadata for existing datasets which contain a vertical component. Users will be able to determine through the "Layer Properties" dialog whether a particular dataset has a vertical CRS component, and metadata for the vertical CRS will be shown here alongside the existing horizontal CRS metadata (e.g. vertical CRS units).

  6. Add methods for querying available vertical CRSes to QgsCoordinateReferenceSystemRegistry. While the PROJ library will be responsible for providing, updating and maintaining these CRSes, we need to expose methods for querying the available values via the QGIS/PyQGIS API for use in QGIS graphical widgets.

  7. Add a project level setting for "vertical datum" and expose via GUI. This will allow users to select the desired vertical datum for a particular project, and sets the "reference" datum which all vertical/elevation values should be transformed to prior to display.

Out of scope

Whilst the following features are desirable, they are deemed as out-of-scope for this project in order to keep the current project focused on the minimum baseline functionality for vertical CRS handling.

It is hoped that community efforts or commercial sponsorship will provide the means to fund these additional features, following the initial investment by QGIS.org.

Affected Files

Performance Implications

No implications if vertical transformation is not performed. There may be some added expense in situations where vertical transformations are required between two datums (e.g. when viewing two datasets in 3D or an elevation profile and the datasets have different vertical datums).

Additional Considerations

Since elevation values are an implicit component of GNSS positions, there may be downstream implications for the QField and Mergin data collection clients. These clients will be able to utilise the new vertical datum support and transformations in order to accurately handle GNSS elevation values and their storage in datasets with differing vertical datums.

Backwards Compatibility

N/A. This work requires new API additions which will not be backported to stable releases, and will only be available for use by plugins in later QGIS versions.

Issue Tracking ID(s)

https://github.com/qgis/QGIS/issues/13188

Votes

(required)

rouault commented 1 year ago

Excellent addition proposal.

Some remarks:

wonder-sk commented 1 year ago

This is absolutely fantastic. With more and more 3D data around, this is an increasingly important thing.

Few random thoughts (maybe outside of the scope of this proposal):

haubourg commented 1 year ago

I have been hoping for this for a long time. A huge +1 here. Thanks for the proposal. We will have to write a nice documentation here since most GIS users never used such features. When using 2d correctino grids is still something advanced, we'll probably need some kind of vulgarisation landing page in the docs.

9ls1 commented 1 year ago

@nyalldawson I can't find anything about vertical handling in changelog for QGIS 3.34?

nyalldawson commented 1 year ago

@9ls1 there's only backend work completed so far -- no user facing changes as yet. They'll trickle in over the 3.36 cycle.

anitagraser commented 10 months ago

Hi @nyalldawson. I'm working on wrapping up the 2023 grant programme. How is the progress on this project? Can you give me an estimate for the completion and final report? As you probably know, I'm collecting all final reports and summarizing them so everyone can read up on the results of the programme.

twest820 commented 9 months ago

Just another +1 here. I work with a range of data flows originating from point clouds and frequently need to add code to manage vertical CRSes. We originate a lot of processing control layers in QGIS and sometimes bounce data back through QGIS. The current pattern's basically readyToUseData = fixMissingVertCS(loadQgisLayer(...), wellKnownEpsgTable). Which works but is potentially fragile to z consistency. And it does get old. So increments towards being able to add a vertical CRS and then consistently flow it are pretty cool.