-
Notifications
You must be signed in to change notification settings - Fork 57
Add ability to convert 3d coordinates #176
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
base: main
Are you sure you want to change the base?
Conversation
|
Hi @PaulWagener, thanks for the PR! As ever with 2D -> 3D, there's likely to be some discussion… At minimum, I don't think we can remove the As for Even more radically: we could adopt Rust-Geodesy's coordinate struct… |
|
As long as 3D coordinates will be supported I will be happy :) |
|
What more is needed for this feature to be added ? I'd be happy to help. |
|
I just wanted to bring up that this issue hurt me on a recent project. It would be great to see a solution to 3d transformations, or at least allowing transformation into ECEF, into the project and released. |
|
@lx-88 - does using this branch work for you? |
A new struct or a new trait? I thought the whole "bring your own struct" thing was kind of nice, so users don't have to first convert their data to an intermediate proj-crate format. Just brainstorming... if avoiding api-breakage is a concern, could we introduce the new 3d method with a default impl? trait Coord {
...
+ #[deprecated(note = "implement from_xyz instead, this method will be removed in a future release")]
fn from_xy(x: f64, y: f64, z:f64) -> Self;
// at some point we'd remove the default impl, which would be a breaking release - presumably in the same release as we remove `from_xy`
+ fn from_xyz(x: f64, y: f64, z:f64) -> Self {
+ Self::from_xy(x, y)
+ }
} |
|
Hello! I know that it is very difficult to do this, but what is the reason that this PR has not been merged? |
|
This is great! I'll use it as a reference! |
|
incorporated the contents of this PR into my fork. https://github.com/nokonoko1203/proj/blob/f643a9a197921fc7f31571972f522bbd5149a20e/src/proj.rs#L1330 #[test]
fn test_3d_crs() {
let from = "EPSG:6677";
let to = "EPSG:6697";
let proj = Proj::new_known_crs(from, to, None).unwrap();
let (x, y, z) = (-5998.998, -35838.918, 3.901);
let (lng, lat, height) = proj.convert((x, y, z)).unwrap();
assert_relative_eq!(lng, 139.76706139226548, epsilon = 1e-3);
assert_relative_eq!(lat, 35.67694831658619, epsilon = 1e-3);
assert_relative_eq!(height, 3.901, epsilon = 1e-3);
let from = "EPSG:6697";
let to = "EPSG:4979";
let proj = Proj::new_known_crs(from, to, None).unwrap();
let (lng, lat, height) = proj.convert((lng, lat, height)).unwrap();
assert_relative_eq!(lng, 139.76706139226548, epsilon = 1e-3);
assert_relative_eq!(lat, 35.67694831658619, epsilon = 1e-3);
assert_relative_eq!(height, 40.53393140934767, epsilon = 1e-3);
let from = "EPSG:4979";
let to = "EPSG:4978";
let proj = Proj::new_known_crs(from, to, None).unwrap();
let (x, y, z) = proj.convert((lng, lat, height)).unwrap();
assert_relative_eq!(x, -3959898.9249523925, epsilon = 1e-3);
assert_relative_eq!(y, 3350278.1607454875, epsilon = 1e-3);
assert_relative_eq!(z, 3699157.243055472, epsilon = 1e-3);
} |
|
I just encountered this lack-of-feature, and implemented the same solution, so I am glad this is getting attention. However, from an API standpoint, sometimes I just want to change my CRS for degrees of an ellipsoid with no 3d component, but sometimes I require 3d for operations like ECEF So should users be required to add 0 z's for 2d coordinates in their I'm honestly fine with either solution, but am just curious on others thoughts |
|
I've stumbled upon this missing functionality, trying to convert from ECEF (EPSG:4978) to EPSG:4326. Tried nokonoko1203's fork which works well (rebased to main). What leftover tasks remaining here to merge this? |
|
What is the work required to merge this PR? |
|
(Comming back to look at this after a l-o-o-n-g time) In 2023, @urschrei said:
While much later @michaelkirk added:
I just want to add, that in the meantime, Rust Geodesy has gone the "bring your own struct" way, so implementing the /// `CoordinateTuple` is the ISO-19111 atomic spatial/spatiotemporal
/// referencing element. So loosely speaking, a CoordinateSet is a
/// collection of CoordinateTuples.
///
/// Note that (despite the formal name) the underlying data structure
/// need not be a Rust tuple: It can be any item, for which it makes
/// sense to implement the CoordinateTuple trait.
///
/// The CoordinateTuple trait provides a number of convenience accessors
/// for accessing single coordinate elements or tuples of subsets.
/// These accessors are pragmatically named (x, y, xy, etc.). While these
/// names may be geodetically naïve, they are suggestive, practical, and
/// aligns well with the internal coordinate order convention of most
/// Geodesy operators.
///
/// All accessors have default implementations, except the 3 methods
/// [`nth_unchecked()`](Self::nth_unchecked()),
/// [`set_nth_unchecked()`](Self::set_nth_unchecked) and
/// [`dim()`](Self::dim()),
/// which must be provided by the implementer.
///
/// When accessing dimensions outside of the domain of the CoordinateTuple,
/// [NaN](f64::NAN) will be returned.
Returning NaNs for out-of-domain ensures that computations unintentionally needing access to e.g. height or time, will ensure NaN propagating in cases of data sets not supporting them. For convenience, Rust Geodesy provides ready-to-eat implementations for these cases: pub struct Coor2D(pub [f64; 2]);
pub struct Coor3D(pub [f64; 3]);
pub struct Coor4D(pub [f64; 4]);
pub struct Coor32(pub [f32; 2]);and It would be nice (but non-trivial, due to integer indexing, and need for length being the total number of coordinates, not of geometries) to implement those for GeometryCollection, for in-place transformation of geometry coordinates. |
Fixes #150
This PR adds the ability to convert 3d coordinates.
The
Coordtrait is changed to add a Z coordinate so at least a minor version bump is warranted with this change.