dad_utils.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "squirrel.h"
  2. #include <stdio.h>
  3. #include <math.h>
  4. #ifndef M_PI
  5. #define M_PI 3.14159265358979323846
  6. #endif
  7. struct lat_long_st
  8. {
  9. double latitude, longitude;
  10. };
  11. inline double toDeg(double lat)
  12. {
  13. return lat * 180.0 / M_PI;
  14. }
  15. inline double toRad(double x)
  16. {
  17. return x * M_PI / 180.0;
  18. }
  19. //
  20. // Convert Ordnance Survey grid reference easting/northing coordinate to (OSGB36) latitude/longitude
  21. //
  22. // @param {OsGridRef} easting/northing to be converted to latitude/longitude
  23. // @return {LatLon} latitude/longitude (in OSGB36) of supplied grid reference
  24. //
  25. static lat_long_st osGridToLatLong(double easting, double northing)
  26. {
  27. double E = easting;
  28. double N = northing;
  29. double a = 6377563.396;
  30. double b = 6356256.910; // Airy 1830 major & minor semi-axes
  31. double F0 = 0.9996012717; // NatGrid scale factor on central meridian
  32. double lat0 = 49.0*M_PI/180.0;
  33. double lon0 = -2.0*M_PI/180.0; // NatGrid true origin
  34. double N0 = -100000.0;
  35. double E0 = 400000.0; // northing & easting of true origin, metres
  36. double e2 = 1.0 - (b*b)/(a*a); // eccentricity squared
  37. double n = (a-b)/(a+b);
  38. double n2 = n*n;
  39. double n3 = n*n*n;
  40. double lat=lat0;
  41. double M=0.0;
  42. double ma_p1 = (1.0 + n + (5.0/4.0)*n2 + (5.0/4.0)*n3);
  43. double mb_p1 = (3.0*n + 3.0*n2 + (21.0/8.0)*n3);
  44. double mc_p1 = ((15.0/8.0)*n2 + (15.0/8.0)*n3);
  45. double md_p1 = (35.0/24.0)*n3;
  46. double n_less_n0 = N-N0;
  47. double bf0 = b * F0;
  48. double af0 = a * F0;
  49. do
  50. {
  51. lat = (n_less_n0-M)/af0 + lat;
  52. double lat_less_lat0 = lat-lat0;
  53. double lat_plus_lat0 = lat+lat0;
  54. double Ma = ma_p1 * lat_less_lat0;
  55. double Mb = mb_p1 * sin(lat_less_lat0) * cos(lat_plus_lat0);
  56. double Mc = mc_p1 * sin(2*lat_less_lat0) * cos(2*lat_plus_lat0);
  57. double Md = md_p1 * sin(3.0*lat_less_lat0) * cos(3*lat_plus_lat0);
  58. M = bf0 * (Ma - Mb + Mc - Md); // meridional arc
  59. }
  60. while (n_less_n0-M >= 0.00001); // ie until < 0.01mm
  61. double cosLat = cos(lat);
  62. double sinLat = sin(lat);
  63. double e2_sinLat2 = 1.0-e2*sinLat*sinLat;
  64. double nu = a*F0/sqrt(e2_sinLat2); // transverse radius of curvature
  65. double rho = a*F0*(1.0-e2)/pow(e2_sinLat2, 1.5); // meridional radius of curvature
  66. double eta2 = nu/rho-1.0;
  67. double tanLat = tan(lat);
  68. double tan2lat = tanLat*tanLat;
  69. double tan4lat = tan2lat*tan2lat;
  70. double tan6lat = tan4lat*tan2lat;
  71. double secLat = 1.0/cosLat;
  72. double nu3 = nu*nu*nu;
  73. double nu5 = nu3*nu*nu;
  74. double nu7 = nu5*nu*nu;
  75. double VII = tanLat/(2.0*rho*nu);
  76. double VIII = tanLat/(24.0*rho*nu3)*(5+3.0*tan2lat+eta2-9.0*tan2lat*eta2);
  77. double IX = tanLat/(720.0*rho*nu5)*(61+90.0*tan2lat+45.0*tan4lat);
  78. double X = secLat/nu;
  79. double XI = secLat/(6.0*nu3)*(nu/rho+2.0*tan2lat);
  80. double XII = secLat/(120.0*nu5)*(5+28.0*tan2lat+24.0*tan4lat);
  81. double XIIA = secLat/(5040.0*nu7)*(61+662.0*tan2lat+1320.0*tan4lat+720.0*tan6lat);
  82. double dE = (E-E0);
  83. double dE2 = dE*dE;
  84. double dE3 = dE2*dE;
  85. double dE4 = dE2*dE2;
  86. double dE5 = dE3*dE2;
  87. double dE6 = dE4*dE2;
  88. double dE7 = dE5*dE2;
  89. lat = lat - VII*dE2 + VIII*dE4 - IX*dE6;
  90. double lon = lon0 + X*dE - XI*dE3 + XII*dE5 - XIIA*dE7;
  91. return {toDeg(lat), toDeg(lon)};
  92. }
  93. static SQRESULT sq_osGridToLatLong(HSQUIRRELVM v)
  94. {
  95. SQ_FUNC_VARS_NO_TOP();
  96. SQ_GET_FLOAT(v, 2, easting);
  97. SQ_GET_FLOAT(v, 3, northing);
  98. lat_long_st ll = osGridToLatLong(easting, northing);
  99. sq_newarray(v, 2);
  100. sq_pushfloat(v, ll.latitude);
  101. sq_arrayappend(v, -1);
  102. sq_pushfloat(v, ll.longitude);
  103. sq_arrayappend(v, -1);
  104. return 1;
  105. }
  106. #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
  107. typedef struct {
  108. HSQOBJECT func_to_call;
  109. HSQOBJECT param;
  110. } gc_scope_alert_st;
  111. static const SQChar *gc_scope_alert_TAG = _SC("gc_scope_alert");
  112. static SQRESULT gc_scope_alert_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
  113. {
  114. gc_scope_alert_st *self = ((gc_scope_alert_st *)p);
  115. //printf("%p %p\n", p, v);
  116. if(self){
  117. if(v){
  118. SQInteger top = sq_gettop(v);
  119. sq_reservestack(v, 20);
  120. sq_pushobject(v, self->func_to_call);
  121. sq_pushroottable(v);
  122. sq_pushobject(v, self->param);
  123. sq_call(v, 2, SQFalse, SQTrue);
  124. sq_release(v, &self->func_to_call);
  125. sq_release(v, &self->param);
  126. sq_settop(v, top);
  127. }
  128. //else
  129. sq_free(self, sizeof(gc_scope_alert_st));
  130. }
  131. return 0;
  132. }
  133. static SQRESULT gc_scope_alert_constructor(HSQUIRRELVM v)
  134. {
  135. SQInteger rc;
  136. gc_scope_alert_st proto;
  137. sq_resetobject(&proto.func_to_call);
  138. sq_resetobject(&proto.param);
  139. if((rc = sq_getstackobj(v, 2, &proto.func_to_call)) < 0) return rc;
  140. if(sq_gettop(v) > 2){
  141. if((rc = sq_getstackobj(v, 3, &proto.param)) < 0) return rc;
  142. }
  143. gc_scope_alert_st *self = (gc_scope_alert_st*)sq_malloc(sizeof(gc_scope_alert_st));
  144. if(!self) return sq_throwerror(v, "Failed to create %s", gc_scope_alert_TAG);
  145. sq_addref(v, &proto.func_to_call);
  146. sq_addref(v, &proto.param);
  147. *self = proto;
  148. sq_setinstanceup(v, 1, self);
  149. sq_setreleasehook(v,1, gc_scope_alert_releasehook);
  150. return 1;
  151. }
  152. #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), gc_scope_alert_##name,nparams,tycheck}
  153. static SQRegFunction gc_scope_alert_methods[] =
  154. {
  155. _DECL_FUNC(constructor, -2, _SC("xc.")),
  156. {0,0}
  157. };
  158. #endif // SQ_WITH_DELAYED_RELEASE_HOOKS
  159. static SQRESULT spectralnorm_A(HSQUIRRELVM v)
  160. {
  161. SQ_FUNC_VARS_NO_TOP();
  162. SQ_GET_INTEGER(v, 2, i);
  163. SQ_GET_INTEGER(v, 3, j);
  164. SQInteger ij = j + i++;
  165. sq_pushfloat(v, 1.0/(ij * (ij+1)/2.0+i));
  166. return 1;
  167. }
  168. #ifdef __cplusplus
  169. extern "C" {
  170. #endif
  171. SQRESULT sqext_register_dad_utils(HSQUIRRELVM v)
  172. {
  173. sq_pushstring(v,_SC("dad_utils"),-1);
  174. sq_newtable(v);
  175. sq_insertfunc(v, _SC("osGridToLatLong"), sq_osGridToLatLong, 3, _SC(".ff"), true);
  176. sq_insertfunc(v, _SC("spectralnorm_A"), spectralnorm_A, 3, _SC(".ii"), true);
  177. #ifdef SQ_WITH_DELAYED_RELEASE_HOOKS
  178. sq_pushstring(v,gc_scope_alert_TAG,-1);
  179. sq_newclass(v,SQFalse);
  180. sq_settypetag(v,-1,(void*)gc_scope_alert_TAG);
  181. sq_insert_reg_funcs(v, gc_scope_alert_methods);
  182. sq_rawset(v,-3);
  183. #endif // SQ_WITH_DELAYED_RELEASE_HOOKS
  184. sq_rawset(v,-3);//insert dad_utils
  185. return 1;
  186. }
  187. #ifdef __cplusplus
  188. }
  189. #endif