1 module geodetic;
2 
3 import std.traits : isFloatingPoint, isSomeString;
4 
5 /** WGS84 Coordinate
6     See also: https://en.wikipedia.org/wiki/World_Geodetic_System
7    */
8 struct WGS84Coordinate(T = double)
9     if (isFloatingPoint!T)
10 {
11     @safe: // TODO nothrow @nogc
12 
13     this(T latitude,
14          T longitude) pure
15     {
16         this.latitude = latitude;
17         this.longitude = longitude;
18     }
19 
20     this(S, Separator)(S s, Separator separator = ` `)
21         if (isSomeString!S,
22             isSomeString!Separator)
23     {
24         import std.algorithm : findSplit;
25         if (auto parts = s.findSplit(separator)) // TODO reuse functional findSplit in DMD 2.070
26         {
27             import std.conv : to;
28             this(parts[0].to!T, parts[2].to!T);
29         }
30         else
31         {
32             this(T.nan, T.nan);
33         }
34     }
35 
36     auto toString() const
37     {
38         import std.conv : to;
39         return latitude.to!string ~ `° N ` ~ longitude.to!string ~ `° W`;
40     }
41 
42     T latitude;
43     T longitude;
44 }
45 
46 auto wgs84Coordinate(T)(T latitude,
47                         T longitude)
48     if (isFloatingPoint!T)
49 {
50     return WGS84Coordinate!T(latitude, longitude);
51 }
52 
53 auto wgs84Coordinate(T = double, S, Separator)(S s, Separator separator = ` `)
54     if (isSomeString!S,
55         isSomeString!Separator)
56 {
57     return WGS84Coordinate!T(s, separator);
58 }
59 
60 @safe // TODO pure/ nothrow
61 unittest
62 {
63     alias T = float;
64 
65     T latitude = 1.5;
66     T longitude = 2.5;
67 
68     import std.conv : to;
69     assert(wgs84Coordinate(latitude, longitude) ==
70            wgs84Coordinate!T("1.5 2.5"));
71 
72     auto x = wgs84Coordinate("36.7,3.216666666666667", ",");
73     assert(x.to!string == "36.7° N 3.21667° W");
74 }