-
Notifications
You must be signed in to change notification settings - Fork 200
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
One Length trait to rule them all 💍 #256
Comments
There are two topics that need to be discussed here:
|
I agree about euclidean distance by default.
The trait here takes ownership of a Line. Would it be better to take a reference to 2 points? To prevent creating and discarding a Line struct each time? (or am I misunderstanding something about rust? 🙂)
…On 4 June 2018 14:38:44 CEST, "Stephan Hügel" ***@***.***> wrote:
I would say the default should be Euclidean, since `Geo` deals
primarily with planar geometry.
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
|
I have opinions about euclidean as a default, but short on time right now to expand. Regarding taking ownership, you're right, it should take |
PostGIS has a Maybe a feature like that would be very useful for rust-geo, and avoid the "which should it be?" discussion? |
As long as the underlying Rust issue remains open, I don't think we can make much progress on this, so I'm going to close. |
With #1216 this starts to look pretty nice! See my WIP: 33436c5 Given all the unification in #1216, a unified Length trait is pretty concise to implement: pub trait Length<F: CoordFloat> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F;
}
impl<F: CoordFloat> Length<F> for Line<F> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F {
MetricSpace::distance(self.start_point(), self.end_point())
}
}
impl<F: CoordFloat> Length<F> for LineString<F> {
fn length<MetricSpace: Distance<F, Point<F>, Point<F>>>(&self) -> F {
let mut length = F::zero();
for line in self.lines() {
length = length + line.length::<MetricSpace>();
}
length
}
} And then the call sites look like this: let line_string = LineString::new(vec![
coord!(x: -58.3816f64, y: -34.6037), // Buenos Aires, Argentina
coord!(x: -77.0428, y: -12.0464), // Lima, Peru
coord!(x: -47.9292, y: -15.7801), // Brasília, Brazil
]);
assert_eq!(
6_302_220., // meters
line_string.length::<Geodesic>().round()
);
assert_eq!(
6_332_790., // meters
line_string.length::<Rhumb>().round()
);
assert_eq!(
6_304_387., // meters
line_string.length::<Haversine>().round()
);
// computing Euclidean length of an unprojected (lng/lat) gives a nonsense answer
assert_eq!(
59., // nonsense!
line_string.length::<Euclidean>().round()
);
// EPSG:102033
let projected_line_string = LineString::from(vec![
coord!(x: 143042.46f64, y: -1932485.45), // Buenos Aires, Argentina
coord!(x: -1797084.08, y: 583528.84), // Lima, Peru
coord!(x: 1240052.27, y: 207169.12), // Brasília, Brazil
]);
assert_eq!(
6_237_538.,
projected_line_string.length::<Euclidean>().round()
); |
I'll call out that Vincenty is awkward because it returns a Maybe we can do something fancy, but I haven't thought very hard about it yet. |
I'm also diverging from your original approach by not including a default trait implementation. I feel like people using geographic (lon/lat) coords and people using projected coordinates are both big enough groups that picking a default is too much of a footgun. |
The following code is blocked on rust-lang/rust#51344. Relevant discussion happened in #47.
The text was updated successfully, but these errors were encountered: