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.algorithm.searching : 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 => WGS84Coordinate!T(latitude, longitude); 54 55 auto wgs84Coordinate(T = double, S, Separator)(S s, Separator separator = ` `) 56 if (isSomeString!S && 57 isSomeString!Separator) 58 => WGS84Coordinate!T(s, separator); 59 60 @safe unittest { 61 alias T = float; 62 63 T latitude = 1.5; 64 T longitude = 2.5; 65 66 import std.conv : to; 67 assert(wgs84Coordinate(latitude, longitude) == 68 wgs84Coordinate!T(`1.5 2.5`)); 69 70 auto x = wgs84Coordinate(`36.7,3.216666666666667`, `,`); 71 assert(x.to!string == `36.700000° N 3.216667° W`); 72 }