Skip to content

Commit 8fdbda2

Browse files
committed
A CoordTrait experiment
1 parent 5ed8773 commit 8fdbda2

File tree

2 files changed

+261
-15
lines changed

2 files changed

+261
-15
lines changed

src/coordinate/mod.rs

+237
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,240 @@ pub trait CoordinateSet: CoordinateMetadata {
104104
}
105105
}
106106
}
107+
108+
// An experiment with an extended version of Kyle Barron's CoordTrait PR
109+
// over at https://github.com/georust/geo/pull/1157
110+
111+
pub trait CoordNum {}
112+
impl CoordNum for f32 {}
113+
impl CoordNum for f64 {}
114+
115+
/// A trait for accessing data from a generic Coord.
116+
pub trait CoordTrait {
117+
type T: CoordNum;
118+
119+
/// Accessors for the coordinate tuple components
120+
fn first(&self) -> Self::T;
121+
fn second(&self) -> Self::T;
122+
fn third(&self) -> Self::T;
123+
fn fourth(&self) -> Self::T;
124+
fn measure(&self) -> Self::T;
125+
126+
/// Accessors for the coordinate tuple components
127+
fn first_as_f64(&self) -> f64;
128+
fn second_as_f64(&self) -> f64;
129+
fn third_as_f64(&self) -> f64;
130+
fn fourth_as_f64(&self) -> f64;
131+
fn measure_as_f64(&self) -> f64;
132+
133+
/// x component of this coord
134+
fn x(&self) -> Self::T {
135+
self.first()
136+
}
137+
138+
/// y component of this coord
139+
fn y(&self) -> Self::T {
140+
self.second()
141+
}
142+
143+
/// z component of this coord
144+
fn z(&self) -> Self::T {
145+
self.third()
146+
}
147+
148+
/// t component of this coord
149+
fn t(&self) -> Self::T {
150+
self.fourth()
151+
}
152+
153+
/// Returns a tuple that contains the two first components of the coord.
154+
fn xy(&self) -> (Self::T, Self::T) {
155+
(self.first(), self.second())
156+
}
157+
158+
/// Returns a tuple that contains the three first components of the coord.
159+
fn xyz(&self) -> (Self::T, Self::T, Self::T) {
160+
(self.first(), self.second(), self.third())
161+
}
162+
163+
/// Returns a tuple that contains the three first components of the coord.
164+
fn xyzt(&self) -> (Self::T, Self::T, Self::T, Self::T) {
165+
(self.first(), self.second(), self.third(), self.fourth())
166+
}
167+
168+
/// Returns a tuple that contains the two first components of the coord converted to f64.
169+
fn xy_as_f64(&self) -> (f64, f64) {
170+
(self.first_as_f64(), self.second_as_f64())
171+
}
172+
173+
/// Returns a tuple that contains the three first components of the coord converted to f64.
174+
fn xyz_as_f64(&self) -> (f64, f64, f64) {
175+
(
176+
self.first_as_f64(),
177+
self.second_as_f64(),
178+
self.third_as_f64(),
179+
)
180+
}
181+
182+
/// Returns a tuple that contains the three first components of the coord converted to f64.
183+
fn xyzt_as_f64(&self) -> (f64, f64, f64, f64) {
184+
(
185+
self.first_as_f64(),
186+
self.second_as_f64(),
187+
self.third_as_f64(),
188+
self.fourth_as_f64(),
189+
)
190+
}
191+
}
192+
193+
impl CoordTrait for Coor2D {
194+
type T = f64;
195+
196+
/// Accessors for the coordinate tuple components
197+
fn first(&self) -> Self::T {
198+
self.0[0]
199+
}
200+
fn second(&self) -> Self::T {
201+
self.0[1]
202+
}
203+
fn third(&self) -> Self::T {
204+
f64::NAN
205+
}
206+
fn fourth(&self) -> Self::T {
207+
f64::NAN
208+
}
209+
fn measure(&self) -> Self::T {
210+
f64::NAN
211+
}
212+
213+
/// Accessors for the coordinate tuple components
214+
fn first_as_f64(&self) -> f64 {
215+
self.0[0]
216+
}
217+
fn second_as_f64(&self) -> f64 {
218+
self.0[1]
219+
}
220+
fn third_as_f64(&self) -> f64 {
221+
f64::NAN
222+
}
223+
fn fourth_as_f64(&self) -> f64 {
224+
f64::NAN
225+
}
226+
fn measure_as_f64(&self) -> f64 {
227+
f64::NAN
228+
}
229+
}
230+
231+
impl CoordTrait for Coor32 {
232+
type T = f32;
233+
234+
/// Accessors for the coordinate tuple components
235+
fn first(&self) -> Self::T {
236+
self.0[0]
237+
}
238+
fn second(&self) -> Self::T {
239+
self.0[1]
240+
}
241+
fn third(&self) -> Self::T {
242+
f32::NAN
243+
}
244+
fn fourth(&self) -> Self::T {
245+
f32::NAN
246+
}
247+
fn measure(&self) -> Self::T {
248+
f32::NAN
249+
}
250+
251+
/// Accessors for the coordinate tuple components
252+
fn first_as_f64(&self) -> f64 {
253+
self.0[0] as f64
254+
}
255+
fn second_as_f64(&self) -> f64 {
256+
self.0[1] as f64
257+
}
258+
fn third_as_f64(&self) -> f64 {
259+
f64::NAN
260+
}
261+
fn fourth_as_f64(&self) -> f64 {
262+
f64::NAN
263+
}
264+
fn measure_as_f64(&self) -> f64 {
265+
f64::NAN
266+
}
267+
}
268+
269+
impl CoordTrait for Coor3D {
270+
type T = f64;
271+
272+
/// Accessors for the coordinate tuple components
273+
fn first(&self) -> Self::T {
274+
self.0[0]
275+
}
276+
fn second(&self) -> Self::T {
277+
self.0[1]
278+
}
279+
fn third(&self) -> Self::T {
280+
self.0[2]
281+
}
282+
fn fourth(&self) -> Self::T {
283+
f64::NAN
284+
}
285+
fn measure(&self) -> Self::T {
286+
f64::NAN
287+
}
288+
289+
/// Accessors for the coordinate tuple components
290+
fn first_as_f64(&self) -> f64 {
291+
self.0[0]
292+
}
293+
fn second_as_f64(&self) -> f64 {
294+
self.0[1]
295+
}
296+
fn third_as_f64(&self) -> f64 {
297+
self.0[2]
298+
}
299+
fn fourth_as_f64(&self) -> f64 {
300+
f64::NAN
301+
}
302+
fn measure_as_f64(&self) -> f64 {
303+
f64::NAN
304+
}
305+
}
306+
307+
impl CoordTrait for Coor4D {
308+
type T = f64;
309+
310+
/// Accessors for the coordinate tuple components
311+
fn first(&self) -> Self::T {
312+
self.0[0]
313+
}
314+
fn second(&self) -> Self::T {
315+
self.0[1]
316+
}
317+
fn third(&self) -> Self::T {
318+
self.0[2]
319+
}
320+
fn fourth(&self) -> Self::T {
321+
self.0[3]
322+
}
323+
fn measure(&self) -> Self::T {
324+
f64::NAN
325+
}
326+
327+
/// Accessors for the coordinate tuple components
328+
fn first_as_f64(&self) -> f64 {
329+
self.0[0]
330+
}
331+
fn second_as_f64(&self) -> f64 {
332+
self.0[1]
333+
}
334+
fn third_as_f64(&self) -> f64 {
335+
self.0[2]
336+
}
337+
fn fourth_as_f64(&self) -> f64 {
338+
self.0[3]
339+
}
340+
fn measure_as_f64(&self) -> f64 {
341+
f64::NAN
342+
}
343+
}

src/ellipsoid/geodesics.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
use crate::coordinate::CoordTrait;
2+
3+
// Now using an extended version of Kyle Barron's CoordTrait, cf. src/coordinate/mod.rs
4+
15
use super::*;
26

37
// ----- Geodesics -------------------------------------------------------------
@@ -14,10 +18,12 @@ impl Ellipsoid {
1418
/// Federico Dolce and Michael Kirk, provides a Rust implementation of Karney's algorithm.
1519
#[must_use]
1620
#[allow(non_snake_case)]
17-
pub fn geodesic_fwd(&self, from: &Coor4D, azimuth: f64, distance: f64) -> Coor4D {
21+
pub fn geodesic_fwd<T>(&self, from: &T, azimuth: f64, distance: f64) -> Coor4D
22+
where
23+
T: CoordTrait,
24+
{
1825
// Coordinates of the point of origin, P1
19-
let B1 = from[1];
20-
let L1 = from[0];
26+
let (L1, B1) = from.xy_as_f64();
2127

2228
// The latitude of P1 projected onto the auxiliary sphere
2329
let U1 = self.latitude_geographic_to_reduced(B1);
@@ -93,13 +99,13 @@ impl Ellipsoid {
9399
/// See [`geodesic_fwd`](crate::Ellipsoid::geodesic_fwd)
94100
#[must_use]
95101
#[allow(non_snake_case)] // So we can use the mathematical notation from the original text
96-
pub fn geodesic_inv(&self, from: &Coor4D, to: &Coor4D) -> Coor4D {
97-
let B1 = from[1];
98-
let B2 = to[1];
102+
pub fn geodesic_inv<T>(&self, from: &T, to: &T) -> Coor4D
103+
where
104+
T: CoordTrait,
105+
{
106+
let (L1, B1) = from.xy_as_f64();
107+
let (L2, B2) = to.xy_as_f64();
99108
let B = B2 - B1;
100-
101-
let L1 = from[0];
102-
let L2 = to[0];
103109
let L = L2 - L1;
104110

105111
// Below the micrometer level, we don't care about directions
@@ -191,14 +197,17 @@ impl Ellipsoid {
191197
/// // Compute the distance between Copenhagen and Paris
192198
/// use geodesy::prelude::*;
193199
/// if let Ok(ellps) = Ellipsoid::named("GRS80") {
194-
/// let p0 = Coor4D::geo(55., 12., 0., 0.);
195-
/// let p1 = Coor4D::geo(49., 2., 0., 0.);
200+
/// let p0 = Coor2D::geo(55., 12.);
201+
/// let p1 = Coor2D::geo(49., 2.);
196202
/// let d = ellps.distance(&p0, &p1);
197203
/// assert!((d - 956_066.231_959).abs() < 1e-5);
198204
/// }
199205
/// ```
200206
#[must_use]
201-
pub fn distance(&self, from: &Coor4D, to: &Coor4D) -> f64 {
207+
pub fn distance<T>(&self, from: &T, to: &T) -> f64
208+
where
209+
T: CoordTrait,
210+
{
202211
self.geodesic_inv(from, to)[2]
203212
}
204213
}
@@ -216,8 +225,8 @@ mod tests {
216225

217226
// Copenhagen (Denmark)--Paris (France)
218227
// Expect distance good to 0.01 mm, azimuths to a nanodegree
219-
let p1 = Coor4D::gis(12., 55., 0., 0.);
220-
let p2 = Coor4D::gis(2., 49., 0., 0.);
228+
let p1 = Coor2D::gis(12., 55.);
229+
let p2 = Coor2D::gis(2., 49.);
221230

222231
let d = ellps.geodesic_inv(&p1, &p2);
223232
assert!((d[0].to_degrees() - (-130.15406042072)).abs() < 1e-9);
@@ -231,7 +240,7 @@ mod tests {
231240

232241
// Copenhagen (Denmark)--Rabat (Morocco)
233242
// Expect distance good to 0.1 mm, azimuths to a nanodegree
234-
let p2 = Coor4D::gis(7., 34., 0., 0.);
243+
let p2 = Coor2D::gis(7., 34.);
235244

236245
let d = ellps.geodesic_inv(&p1, &p2);
237246
assert!((d[0].to_degrees() - (-168.48914418666)).abs() < 1e-9);

0 commit comments

Comments
 (0)