1 module nxt.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 /// Construct from `latitude` and `longitude`. 14 this(T latitude, 15 T longitude) 16 pure nothrow @nogc 17 { 18 this.latitude = latitude; 19 this.longitude = longitude; 20 } 21 22 /// Construct from string `s` and separator `separator`. 23 this(scope const(char)[] s, 24 scope string separator = ` `) 25 { 26 import nxt.array_algorithm : findSplit; 27 if (auto parts = s.findSplit(separator)) 28 { 29 import std.conv : to; 30 this(parts.pre.to!T, 31 parts.post.to!T); 32 } 33 else 34 { 35 this(T.nan, T.nan); 36 } 37 } 38 39 /// Convert to `string`. 40 auto toString(scope void delegate(scope const(char)[]) @safe sink) const @safe 41 { 42 import std.format : formattedWrite; 43 sink.formattedWrite!(`%f° N %f° W`)(latitude, longitude); 44 } 45 46 T latitude; 47 T longitude; 48 } 49 50 auto wgs84Coordinate(T)(T latitude, 51 T longitude) 52 if (isFloatingPoint!T) 53 { 54 return WGS84Coordinate!T(latitude, longitude); 55 } 56 57 auto wgs84Coordinate(T = double, S, Separator)(S s, Separator separator = ` `) 58 if (isSomeString!S && 59 isSomeString!Separator) 60 { 61 return WGS84Coordinate!T(s, separator); 62 } 63 64 @safe // TODO pure/ nothrow 65 unittest 66 { 67 alias T = float; 68 69 T latitude = 1.5; 70 T longitude = 2.5; 71 72 import std.conv : to; 73 assert(wgs84Coordinate(latitude, longitude) == 74 wgs84Coordinate!T(`1.5 2.5`)); 75 76 auto x = wgs84Coordinate(`36.7,3.216666666666667`, `,`); 77 assert(x.to!string == `36.700000° N 3.216667° W`); 78 }