1 module geodesicd.geodesic_warper; 2 3 private { 4 5 extern(C){ 6 7 struct geod_geodesic { 8 double a; 9 double f; 10 double f1; 11 double e2; 12 double ep2; 13 double n; 14 double b; 15 double c2; 16 double etol2; 17 double[6] A3x; 18 double[15] C3x; 19 double[21] C4x; 20 }; 21 22 void geod_init( geod_geodesic* g, double a, double f); 23 24 void geod_inverse(const geod_geodesic* g, 25 double lat1, double lon1, double lat2, double lon2, 26 double* ps12, double* pazi1, double* pazi2); 27 28 void geod_direct(const geod_geodesic* g, 29 double lat1, double lon1, double azi1, double s12, 30 double* plat2, double* plon2, double* pazi2); 31 32 } 33 34 } 35 // WGS84 as default; 36 struct Ellipsoid{ 37 double a = 6378137; 38 double f = 1/298.257223563; 39 } 40 41 struct LatLon{ 42 double lat = 0.0; 43 double lon = 0.0; 44 } 45 46 struct AzDist{ 47 double az = 0.0; 48 double distance = 0.0; 49 } 50 51 struct LatLonAz{ 52 double lat = 0.0; 53 double lon = 0.0; 54 double az = 0.0; 55 } 56 57 struct DistAz1Az2{ 58 double distance = 0.0; 59 double az1 = 0.0; 60 double az2 = 0.0; 61 } 62 63 static Ellipsoid EllipsoidWGS84 = {6378137, 1/298.257223563}; 64 65 // D warper 66 struct Geodesic{ 67 68 private geod_geodesic g; 69 private Ellipsoid ellipsoid; 70 71 this(double a, double f){ 72 ellipsoid.a=a; 73 ellipsoid.f=f; 74 geod_init(&g, ellipsoid.a, ellipsoid.f); 75 } 76 77 this(Ellipsoid e){ 78 ellipsoid = e; 79 geod_init(&g,ellipsoid.a,ellipsoid.f); 80 } 81 82 double[3] inverse(double lat1, double lon1, double lat2, double lon2){ 83 double[3] v; 84 geod_inverse(&this.g, lat1, lon1, lat2, lon2, &v[0], &v[1], &v[2]); 85 return v; 86 } 87 88 DistAz1Az2 inverse(LatLon p1, LatLon p2){ 89 DistAz1Az2 v; 90 geod_inverse(&this.g, p1.lat, p1.lon, p2.lat, p2.lon, &v.distance, &v.az1, &v.az2); 91 return v; 92 } 93 94 double[3] direct(double lat1, double lon1, double azi1, double s12){ 95 double[3] v; 96 geod_direct(&this.g, lat1, lon1, azi1, s12, &v[0], &v[1], &v[2]); 97 return v; 98 } 99 100 LatLonAz direct(LatLon p1, AzDist azd){ 101 LatLonAz v; 102 geod_direct(&this.g, p1.lat, p1.lon, azd.az, azd.distance, &v.lat, &v.lon, &v.az); 103 return v; 104 } 105 106 } 107 108 // test init! 109 unittest{ 110 import std.stdio; 111 auto g1 = Geodesic(); 112 auto g2 = Geodesic(6378137, 1/298.257223563); 113 auto g3 = Geodesic(EllipsoidWGS84); 114 115 // writeln("OK"); 116 117 } 118 unittest{ 119 import std.stdio; 120 import std.math; 121 122 double a = 6378137, f = 1/298.257223563; /* WGS84 */ 123 double lat1, lon1, azi1, lat2, lon2, azi2, s12; 124 125 lat1 = 54.5; 126 lon1 = 18.5; 127 lat2 = 55.5; 128 lon2 = 17.5; 129 130 auto g1 = Geodesic(a,f); 131 auto g_out1 = g1.inverse(lat1, lon1, lat2, lon2); 132 double [3] g_out1_test = [128403.130195, -29.483701, -30.302891]; 133 134 assert(abs(g_out1[0] - g_out1_test[0]) < 1e-6); 135 assert(abs(g_out1[1] - g_out1_test[1]) < 1e-6); 136 assert(abs(g_out1[2] - g_out1_test[2]) < 1e-6); 137 138 auto g_out2 = g1.direct(lat1, lon1, 90.0, 50000.0); 139 double [3] g_out2_test = [54.497537, 19.271724, 90.628266]; 140 141 assert(abs(g_out2[0] - g_out2_test[0]) < 1e-6); 142 assert(abs(g_out2[1] - g_out2_test[1]) < 1e-6); 143 assert(abs(g_out2[2] - g_out2_test[2]) < 1e-6); 144 145 //writefln("%f, %f, %f ", g_out2[0], g_out2[1],g_out2[2]); 146 //auto dd = g1.direct(lat1, lon1, 90.0, 50000.0); 147 //writeln(dd); 148 } 149 150 unittest{ 151 import std.stdio; 152 import std.math; 153 154 auto g1 = Geodesic(EllipsoidWGS84); 155 auto p1 = LatLon(54.5, 18.5); 156 auto p2 = LatLon(55.5, 17.5); 157 auto g_out1 = g1.inverse(p1, p2); 158 DistAz1Az2 g_out1_test = {128403.130195, -29.483701, -30.302891}; 159 //writeln(g_out1); 160 assert(abs(g_out1.distance - g_out1_test.distance) < 1e-6); 161 assert(abs(g_out1.az1 - g_out1_test.az1) < 1e-6); 162 assert(abs(g_out1.az2 - g_out1_test.az2) < 1e-6); 163 164 auto g_out2 = g1.direct(p1, AzDist(90.0, 50000.0)); 165 LatLonAz g_out2_test = {54.497537, 19.271724, 90.628266}; 166 assert(abs(g_out2.lon - g_out2_test.lon) < 1e-6); 167 assert(abs(g_out2.lat - g_out2_test.lat) < 1e-6); 168 assert(abs(g_out2.az - g_out2_test.az) < 1e-6); 169 //writeln(g_out2); 170 }