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

Use WGS84 (G2139) as the geographic CRS #2205

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

pkturner
Copy link
Contributor

These changes replace the geographic CRS spec string "+proj=latlong +datum=WGS84" with "EPSG:9755" for most Georeferencing purposes. EPSG:9755 is code for the current realization (G2139) of WGS84.

When creating a template with GDAL, OgrFileImport::setSRS will now recognize whether the data SRS (as detected by GDAL) is geographic and uses the ensemble/ballpark WGS84. In that case it changes the data SRS to EPSG:9755. As a result, alignment of tracks is more accurate, and tracks are aligned the same whether or not imported with GDAL.

map file format
The old spec string "+proj=latlong +datum=WGS84" continues to be used when Mapper saves to file. In Mapper's file format, this string appears as the map's geographic CRS and as the CRS of some templates. Because the file format is unchanged, this version of Mapper is interoperable with v0.9.5 and earlier.

However, this compatibility has unfortunate consequences.

  1. Because the file has <geographic_crs_spec> elements, a Mapper that uses EPSG:9755 should put "EPSG:9755" in the file. The current PR throws away this information.
  2. Future users of Mapper may need to work with old maps in a way that preserves the original alignment of tracks and images. It should be possible to distinguish old maps from new.

In the future, I plan to extend this PR with a change to the file format for new maps.

fixes
This is a draft, intended to address #2196 (Inaccurate import of images and tracks), along the lines suggested by @sfroyen. It fixes #1709 (Tracks positioned differently with GDAL enabled). It fixes #1264 (UTM coordinates should vary with datum).

There has been plenty of discussion of fixing these problems, along with hopes for a fix that would use PROJ to transform directly from CRS to CRS without an intermediate geographic CRS "pivot". Those efforts have not succeeded. This draft is worth considering because it is a simple change.

The gnss_crs_spec is EPSG:9755, i.e. WGS84 (G2139).
The name for the spec string "+proj=latlong +datum=WGS84" is changed
from geographic_crs_spec to ballpark_geographic_crs_spec, because
it is retained for compatibility.
Replace Georeferencing::ballpark_geographic_crs_spec with
Georeferencing::gns_crs_spec in all occurrences that relate to Mapper
internals. The former refers to the long-term evolution of WGS84,
while the latter to an up-to-date realization G1762.

Georeferencing::ballpark_geographic_crs_spec continues to be used
for the map file format, for interoperability with older versions
of Mapper.
In OgrFileImport::setSRS that sets the transformation of imported
coodinates to the map SRS, if the source SRS is being set to WGS84,
substitute Georeferencing::gnss_crs_spec. This makes the resulting
transformation more accurate, for example if the map's datum is NAD83.
With Mapper now using the WGS84 (G2139) realization for templates and
as a pivot for coordinate transformations, template alignment has
changed, causing differences in the test results. The test cases
    TemplateTrack NAD83
    OgrTemplate NAD83
in ogrTemplateTest no longer fail, because the tracks are now aligned
well enough with the map and its datum to pass the test. In addition,
TemplateTrack and OgrTemplate now align tracks the same, causing those
same test cases to pass in the templateTypesConsistentTest.

On the other hand, the test cases
    TemplateTrack from v0.8.4
    OGRTemplate from v0.9.3
in ogrTemplateTest now fail, because behavior of earlier versions of
Mapper did not handle track coordinates as accurately. The position
is changed by 0.3mm on the map, or 1.3m on the ground.
This changes Georeferencing::gnss_crs_spec from EPSG:9755 to
EPSG:9057. PROJ handles EPSG:9057 with with an epoch several years
earlier than EPSG:9755, which makes coordinate transformations to
NAD83 less accurate, by 20 cm.

With EPSG:9755, Mapper was failing tests in Azure pipelines.
Changing to the earlier EPSG:9057, which indicates the
WGS 84 (G1762) realization, may work with the older version
of PROJ that's available in the superbuild.
@pkturner
Copy link
Contributor Author

I added a commit which changes the WGS84 realization to the older G1762 and EPSG:9057. Evidently the version of PROJ that's in the Azure pipeline does not support EPSG:9755. The older geographic CRS provides less accurate transformation to NAD83-based georeferencing, but passes the same tests.

TemplateTrack will always rely on the map's Georeferencing to convert
GPS tracks to map coordinates, which can now be a more accurate
realization of the ballpark geographic CRS. At the same time, to save
the realization CRS in the file, or to keep it in the TemplateTrack
object would provide no benefit.
Each Georeferencing object is given its own geographic_crs value,
so that Mapper will be able to support older maps without affecting the
alignment of their templates, while simultaneously providing more
accurate positioning of georeferenced templates in new maps.

For this purpose, ProjTransform objects are enhanced to have an
explicit geographic CRS in addition to the projected CRS.

This modification to ProjTransform is unsuited to another scenario to
which ProjTransform used to be applied, namely when the ProjTransform
would do no more than indicate a CRS. The mechanism supporting
'forward' and 'inverse' methods of such objects was not constructed. A
new struct, 'ProjCRS' is provided for this specialized need. Splitting
off ProjCRS from ProjTransform provides clarity to see which of these
utility objects define a transformation from a geographic CRS, and
which define just a CRS.
The static value Georeferencing::gnss_crs_spec is made private to the
Georeferencing class, so that non-core uses of the map's geographic
WGS84 CRS will be sure to depend on the map to obtain the CRS, rather
than specify a particular variant of WGS84. Their references to
gnss_crs_spec are replaced with calls to getGeographicCRSSpec(), which
in the future will depend on the map. The Georeferencing's
toGeographicCoords, toProjectedCoords, and toMapCoords methods will be
consistent with the CRS returned by getGeographicCRSSpec().
The isDatumBallpark() method indicates compatibility for working with
old maps. It enables GDAL import to provide compatibility with the way
old Mappers aligned template tracks. When compatibility is not called
for, track import is tweaked to use a more accurate geographic CRS.
The attribute 'is_realization' is added to the Georeferencing class
and to the geographic_crs_spec of the xml file format. A 'true' value
indicates the new, more accurate geographic CRS, while 'false'
provides the same geographic CRS as earlier versions of Mapper.  The
geographic CRS is used as pivot when transforming from one version of
map coordinates to another. It is also used for GNSS tracks and for
display of geographic coordinates.

The Georeferencing::setDatumBallpark() method provides for the
compatibility mode to be turned on or off.

On loading a map, the user is warned if they haven't decided whether
compatibility is wanted. When the user opens the georeferencing dialog,
a message box asks the user whether they want extra accuracy, or
alignment that is compatible with older Mappers.

Example and test maps are updated to indicate the 'is_realization'
attribute. The template_t test had two test files as examples of what
older versions of Mapper would save. This commit provides the
compatibility which makes the corresponding two tests succeed.
Adds a test map that has a geographic CRS with is_realization="false".
This is used with TemplateTest::ogrTemplateTest to check support for
template alignment that's compatible with Mapper v0.95.

Also, for FileFormatTest::saveAndLoad, getGeographicCRSSpec() is
added to the map comparison.
Instead of saving _that_ the map was developed with a recent
realization of WGS84 for its geographic CRS, save the _spec_ of the
geographic CRS itself.
@pkturner
Copy link
Contributor Author

I have uploaded further development on the new-geographic-crs branch. This enhances the change so that when a user opens an existing map in Mapper, that map's templates are aligned just as in the past. If the user wishes to switch to use the more accurate alignment that comes from using EPSG:9057, that is optional. New maps would all use EPSG:9057.

The most useful versions are:

  • 8869ce6 - basic fix using EPSG:9057 for all maps
  • addecfe - preserves template alignment for old maps
  • 68c70f5 - saves CRS spec "EPSG:9057" in map file

@pkturner
Copy link
Contributor Author

This PR is relevant to several open issues.

All of these issues arise from situations when WGS84-based coordinates are converted to NAD83 coordinates, where a transformation is relevant, and leads to inaccuracy if PROJ or GDAL does not apply the transformation. Factors affecting the omission of the transformation could be

  • live track vs. loaded as GPX file
  • version of PROJ
  • setting of whether GPX is imported using GDAL

As far as I know, the aspects of those three issues that remain are due to either

  1. GDAL import of data does not apply the needed transformation.
  2. Mapper built with PROJ 8 and later requires the fix from Preserve GPX track accuracy by accepting any authority #2024. That fix is not present in any downloadable Mapper.

The present PR addresses GDAL import of GPX. It probably also takes care of images that have an associated geographic CRS, that are imported using GDAL.

@pkturner
Copy link
Contributor Author

To provide an option for the user to switch their map to the newly available accuracy of EPSG:9057, Mapper (1) provides a warning when opening an old map, and (2) asks the user to decide between the two options, when opening the Georeferencing dialog. Mapper only asks the user once. Mapper preserves that decision when the map is saved.

So that older Mappers can open the output of new Mapper, <geographic_crs_spec>+proj=latlong +datum=WGS84</geographic_crs_spec> will continue to be present in the map file. <realization_spec>EPSG:9057</realization_spec> indicates that there's more going on than just the same old ensemble +proj=latlong +datum=WGS84.

<realization_spec/> indicates that the user has chosen alignment-compatibility.

The EPSG:9057 pivot does not actually benefit non-GDAL tracks, because in Mapper v0.9.5, PROJ already finds a datum transform when converting to EPSG:6342. I tried EPSG:9755, but it failed the automated checks, presumably because the version of PROJ in the superbuild is too old.

@pkturner
Copy link
Contributor Author

One change to the Georeferencing code has a subtle rationale, which I express because in other respects this PR is straightforward.

Splitting off the ProjCRS from ProjTransform is needed because the ProjTransform class already had a split personality. Either you construct it with ProjTransform::crs(const QString&) or you construct it with ProjTransform(const QString&). In the first it represents a CRS, and cannot be used to transform coordinates. In the second the forward and inverse methods are available.

Implementation of this PR forces the split, because the second type of ProjTransform relies on a ProjTransform of the first type, named geographic_crs. Until now, geographic_crs has been a single object shared by all ProjTransforms. But now, different maps need different geographic_crs values, which calls for each ProjTransform of the transforming type to have its own member representing its geographic CRS.

In C++, a class (ProjTransform) can't have a regular data member of the same class.

So within ProjTransform there are distinct purposes, distinct construction, and a distinction in the data required. Splitting out the ProjCRS class is obvious. Now each ProjTransform has its own ProjCRS named geographic_crs.

@dg0yt dg0yt self-assigned this Apr 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants