Skip to content

Comments

Adds CRS.geodetic_crs property#3218

Merged
sgillies merged 10 commits intorasterio:mainfrom
AndrewAnnex:add_geodetic_crs
Nov 8, 2024
Merged

Adds CRS.geodetic_crs property#3218
sgillies merged 10 commits intorasterio:mainfrom
AndrewAnnex:add_geodetic_crs

Conversation

@AndrewAnnex
Copy link
Contributor

Following a discussion on the rasterio groups.io email list,

This PR adds a new function .to_geodetic that is inspired by pyproj's .geodetic_crs function to return the corresponding base geographic CRS for a given CRS. This is helpful for projections that may not use common geographic CRSs and for cases when you want to know what geographic CRS to use for vector features that minimizes the work needed to get to projected coordinates or vice versa.

I went with the name to_geodetic for the moment as it is returning a new object that is transformed from the parent object, and reflects the intent imho better than .geodetic_crs which reads more as a property of the CRS, but as a new object is created... Anyways I don't hold a strong desire here on the name of the function.

geodetic is retained because of this heritage, the vocabulary here is majorly overloaded but maybe to_geographic would be better here? Happy to look into this more. It could also make sense to just keep it aligned to pyproj to maintain compatibility better.

* inspired by pyproj's .geodetic_crs function to return the
  corresponding base geographic CRS for a given CRS
* helpful for projections that may not use common geographic CRSs
Copy link
Member

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

@AndrewAnnex I'm in favor. I think to_geodetic() is fine.

@AndrewAnnex
Copy link
Contributor Author

test failure looks unrelated to changes made in this PR and occur in tests/test_warpedvrt.py

@AndrewAnnex AndrewAnnex requested a review from sgillies October 28, 2024 19:04
Copy link
Member

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

Thanks @AndrewAnnex !

Copy link
Member

@vincentsarago vincentsarago left a comment

Choose a reason for hiding this comment

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

🫶

@AndrewAnnex
Copy link
Contributor Author

AndrewAnnex commented Oct 29, 2024

would be great to merge this after #3206 (but not before #3227, this pr can wait for a future version)

@snowman2
Copy link
Member

snowman2 commented Nov 5, 2024

I am a little late to the party here, but figured this insight may be helpful when deciding on naming in to_geodetic versus geodetic_crs.

geodetic_crs is a property of the CRS. An example is seen here:
https://pyproj4.github.io/pyproj/stable/build_crs.html#projected-crs

from pyproj.crs import GeographicCRS, ProjectedCRS
from pyproj.crs.coordinate_operation import UTMConversion
from pyproj.crs.datum import CustomDatum, CustomEllipsoid

ell = CustomEllipsoid(semi_major_axis=6378137, semi_minor_axis=6356752)
cd = CustomDatum(ellipsoid=ell, prime_meridian="Lisbon")
proj_crs = ProjectedCRS(
    conversion=UTMConversion(14), geodetic_crs=GeographicCRS(datum=cd)
)

In this example, calling geodetic_crs, you are retrieving the geodetic CRS of the original CRS and not converting it to a geodetic CRS.

@snowman2
Copy link
Member

snowman2 commented Nov 5, 2024

Also, pyproj caches the internal _geodetic_crs code to improve the performance in the scenario that it is called multiple times.

@AndrewAnnex
Copy link
Contributor Author

@snowman2 That makes sense regarding the naming. I wanted to keep the scope of this PR limited to make it easier to merge, but we could update the pr to go the route of Pyproj to make the api more equivalent. But it would require the similar caching mechanism. But it is unclear given the prior approval from @sgillies if that's the desired outcome for this PR.

@snowman2
Copy link
Member

snowman2 commented Nov 6, 2024

The information above was for informational purposes for decision making and design considerations only. Caching is not a requirement, just sharing so you are aware.

@sgillies
Copy link
Member

sgillies commented Nov 6, 2024

@snowman2 that appeals to me, and it's good to have Rasterio and Pyproj agree, even though I think Rasterio can be less complete than Pyproj (there's a lot of other stuff to be concerned about). For example, Rasterio doesn't need (as far as I can tell) to be able to create generic projected CRS, passing a geodetic CRS to the constructor. Rasterio really only needs to work with standardized CRS. Engineering CRS might be an exception to this.

@AndrewAnnex are you okay with making this an attribute instead of a method?

@AndrewAnnex
Copy link
Contributor Author

@sgillies yep I am happy to implement that, I'll get to it later today or tomorrow

@AndrewAnnex
Copy link
Contributor Author

okay I think this does what's needed but happy to respond to feedback. I'd also wonder if there is a good example projected CRS that doesn't have a resolvable geodetic CRS to test that case but that might require making a projection with a custom geographic crs that doesn't compare to anything... something I'll think more about

@AndrewAnnex AndrewAnnex changed the title Adds CRS.to_geodetic function Adds CRS.geodetic_crs property Nov 6, 2024
Copy link
Member

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

@AndrewAnnex I'm suggesting a pattern for this kind of property that we use elsewhere in Rasterio.

@sgillies
Copy link
Member

sgillies commented Nov 7, 2024

I'd also wonder if there is a good example projected CRS that doesn't have a resolvable geodetic CRS...

@AndrewAnnex this is an interesting question. Let me know what you discover.

@AndrewAnnex AndrewAnnex requested a review from sgillies November 8, 2024 21:01
Copy link
Member

@sgillies sgillies left a comment

Choose a reason for hiding this comment

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

@AndrewAnnex thanks for the contribution and bearing with me. I made two suggestions that you can commit if you like.

AndrewAnnex and others added 2 commits November 8, 2024 13:34
Co-authored-by: Sean Gillies <[email protected]>
Co-authored-by: Sean Gillies <[email protected]>
@sgillies sgillies merged commit a6dd570 into rasterio:main Nov 8, 2024
@sgillies
Copy link
Member

sgillies commented Nov 8, 2024

I forgot to ask "what is the geodetic CRS corresponding to a geodetic CRS?" but it seems that GDAL and PROJ do the least surprising thing 👍

>>> from rasterio.crs import CRS
>>> CRS.from_epsg(32618).geodetic_crs
CRS.from_wkt('GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]')
>>> CRS.from_epsg(32618).geodetic_crs.geodetic_crs
CRS.from_wkt('GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4326"]]')

sgillies added a commit that referenced this pull request Nov 9, 2024
Follow up to #3218
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants