GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
geodist.c
Go to the documentation of this file.
1 
26 #include <math.h>
27 #include <grass/gis.h>
28 #include "pi.h"
29 
30 
31 static double boa;
32 static double f;
33 static double ff64;
34 static double al;
35 static double t1, t2, t3, t4, t1r, t2r;
36 
37 
52 int G_begin_geodesic_distance(double a, double e2)
53 {
54  al = a;
55  boa = sqrt(1 - e2);
56  f = 1 - boa;
57  ff64 = f * f / 64;
58 
59  return 0;
60 }
61 
62 
63 
76 {
77  t1r = atan(boa * tan(Radians(lat1)));
78 
79  return 0;
80 }
81 
82 
95 {
96  double stm, ctm, sdtm, cdtm;
97  double tm, dtm;
98 
99  t2r = atan(boa * tan(Radians(lat2)));
100 
101  tm = (t1r + t2r) / 2;
102  dtm = (t2r - t1r) / 2;
103 
104  stm = sin(tm);
105  ctm = cos(tm);
106  sdtm = sin(dtm);
107  cdtm = cos(dtm);
108 
109  t1 = stm * cdtm;
110  t1 = t1 * t1 * 2;
111 
112  t2 = sdtm * ctm;
113  t2 = t2 * t2 * 2;
114 
115  t3 = sdtm * sdtm;
116  t4 = cdtm * cdtm - stm * stm;
117 
118  return 0;
119 }
120 
121 
135 double G_geodesic_distance_lon_to_lon(double lon1, double lon2)
136 {
137  double a, cd, d, e, /*dl, */
138  q, sd, sdlmr, t, u, v, x, y;
139 
140 
141  sdlmr = sin(Radians(lon2 - lon1) / 2);
142 
143  /* special case - shapiro */
144  if (sdlmr == 0.0 && t1r == t2r)
145  return 0.0;
146 
147  q = t3 + sdlmr * sdlmr * t4;
148 
149  /* special case - shapiro */
150  if (q == 1.0)
151  return M_PI * al;
152 
153  /* Mod: shapiro
154  * cd=1-2q is ill-conditioned if q is small O(10**-23)
155  * (for high lats? with lon1-lon2 < .25 degrees?)
156  * the computation of cd = 1-2*q will give cd==1.0.
157  * However, note that t=dl/sd is dl/sin(dl) which approaches 1 as dl->0.
158  * So the first step is to compute a good value for sd without using sin()
159  * and then check cd && q to see if we got cd==1.0 when we shouldn't.
160  * Note that dl isn't used except to get t,
161  * but both cd and sd are used later
162  */
163 
164  /* original code
165  cd=1-2*q;
166  dl=acos(cd);
167  sd=sin(dl);
168  t=dl/sd;
169  */
170 
171  cd = 1 - 2 * q; /* ill-conditioned subtraction for small q */
172  /* mod starts here */
173  sd = 2 * sqrt(q - q * q); /* sd^2 = 1 - cd^2 */
174  if (q != 0.0 && cd == 1.0) /* test for small q */
175  t = 1.0;
176  else if (sd == 0.0)
177  t = 1.0;
178  else
179  t = acos(cd) / sd; /* don't know how to fix acos(1-2*q) yet */
180  /* mod ends here */
181 
182  u = t1 / (1 - q);
183  v = t2 / q;
184  d = 4 * t * t;
185  x = u + v;
186  e = -2 * cd;
187  y = u - v;
188  a = -d * e;
189 
190  return (al * sd *
191  (t - f / 4 * (t * x - y) +
192  ff64 * (x * (a + (t - (a + e) / 2) * x) + y * (-2 * d + e * y)
193  + d * x * y)
194  )
195  );
196 }
197 
198 
212 double G_geodesic_distance(double lon1, double lat1, double lon2, double lat2)
213 {
216  return G_geodesic_distance_lon_to_lon(lon1, lon2);
217 }
double G_geodesic_distance_lon_to_lon(double lon1, double lon2)
Calculates geodesic distance.
Definition: geodist.c:135
tuple q
Definition: forms.py:2019
int G_set_geodesic_distance_lat1(double lat1)
Sets geodesic distance lat1.
Definition: geodist.c:75
int G_set_geodesic_distance_lat2(double lat2)
Sets geodesic distance lat2.
Definition: geodist.c:94
int y
Definition: plot.c:34
#define Radians(x)
Definition: pi.h:6
int G_begin_geodesic_distance(double a, double e2)
Begin geodesic distance.
Definition: geodist.c:52
double G_geodesic_distance(double lon1, double lat1, double lon2, double lat2)
Calculates geodesic distance.
Definition: geodist.c:212