/[xlog]/xlog/src/gc.c
ViewVC logotype

Diff of /xlog/src/gc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by pa4tu, Sat Oct 19 17:50:20 2002 UTC revision 1.2 by pa4tu, Thu Nov 21 19:57:46 2002 UTC
# Line 20  Line 20 
20  /*  /*
21   * gc.c - see description below by N5OWK, adopted for xlog October 2001   * gc.c - see description below by N5OWK, adopted for xlog October 2001
22   */   */
23    
24  /*  /*
25   * Great Circle.  This program is used to determine bearing   * Great Circle.  This program is used to determine bearing
26   * and range to two stations given latitude and longitude.   * and range to two stations given latitude and longitude.
# Line 58  Line 58 
58    
59  #define RADIAN (180.0 / M_PI)  #define RADIAN (180.0 / M_PI)
60    
61  struct {  struct
62          gdouble miles; /* arc length for 1 degree, various units of measure */  {
63          gchar *text;    gdouble miles;                /* arc length for 1 degree, various units of measure */
64  } Units[] = {    gchar *text;
65          { 60.0, "m"},  }
66          { 111.2, "km"},  Units[] =
67  };  {
68      {
69      60.0, "m"}
70      ,
71      {
72      111.2, "km"}
73    ,};
74    
75  /* Error routine */  /* Error routine */
76  static void err(gint type) {  static void
77          switch(type) {  err (gint type)
78                  case 1:  {
79                          update_statusbar(_("Latitude Out of Range (90N to 90S)\n"));    switch (type)
80                          break;      {
81                  case 2:      case 1:
82                          update_statusbar(_("Longitude Out of Range (180W to 180E)\n"));        update_statusbar (_("Latitude Out of Range (90N to 90S)\n"));
83                          break;        break;
84                  case 3:      case 2:
85                          update_statusbar(_("Minutes Out of Range (0 to 59)\n"));        update_statusbar (_("Longitude Out of Range (180W to 180E)\n"));
86          }        break;
87        case 3:
88          update_statusbar (_("Minutes Out of Range (0 to 59)\n"));
89        }
90  }  }
91    
92  /* Convert Degrees and Minutes to Decimal */  /* Convert Degrees and Minutes to Decimal */
93  static gdouble dm2dec(gdouble n) {  static gdouble
94          gdouble t;  dm2dec (gdouble n)
95    {
96      gdouble t;
97    
98          t = (gint)n;    t = (gint) n;
99          n -= t;    n -= t;
100          n /= .60;    n /= .60;
101          if (n >= 1.0) {    if (n >= 1.0)
102                  err(3);      {
103                  return(-1);        err (3);
104          }        return (-1);
105          return (n + t);      }
106      return (n + t);
107  }  }
108    
109  /* Parse the input line dd(.mm)[NnSs]ddd(.mm)[EeWw] */  /* Parse the input line dd(.mm)[NnSs]ddd(.mm)[EeWw] */
110  static gint parse(gchar *s, gdouble *lat, gdouble *lon) {  static gint
111          register gchar *i, *t = NULL, *e;  parse (gchar * s, gdouble * lat, gdouble * lon)
112    {
113          e = s + strlen(s);    register gchar *i, *t = NULL, *e;
         for (i = s; i < e; ++i) {  
                 switch (*i)     {  
                 case 'n':  
                 case 'N':  
                         *i = '\0';  
                         t = i + 1;  
                         *lat = atof(s);  
                         break;  
                 case 's':  
                 case 'S':  
                         *i = '\0';  
                         t = i + 1;  
                         *lat = -atof(s);  
                         break;  
                 case 'e':  
                 case 'E':  
                         *i = '\0';  
                         *lon = -atof(t);  
                         break;  
                 case 'w':  
                 case 'W':  
                         *i = '\0';  
                         *lon = atof(t);  
                         break;  
                 }  
         }  
   
         *lat = dm2dec(*lat);  
         *lon = dm2dec(*lon);  
   
         if (*lat > 90.0 || *lat < -90.0) {  
                 err(1);  
                 return(-1);  
         }  
114    
115          if (*lon > 180.0 || *lon < -180.0) {    e = s + strlen (s);
116                  err(2);    for (i = s; i < e; ++i)
117                  return(-1);      {
118          }        switch (*i)
119            {
120            case 'n':
121            case 'N':
122              *i = '\0';
123              t = i + 1;
124              *lat = atof (s);
125              break;
126            case 's':
127            case 'S':
128              *i = '\0';
129              t = i + 1;
130              *lat = -atof (s);
131              break;
132            case 'e':
133            case 'E':
134              *i = '\0';
135              *lon = -atof (t);
136              break;
137            case 'w':
138            case 'W':
139              *i = '\0';
140              *lon = atof (t);
141              break;
142            }
143        }
144    
145      *lat = dm2dec (*lat);
146      *lon = dm2dec (*lon);
147    
148      if (*lat > 90.0 || *lat < -90.0)
149        {
150          err (1);
151          return (-1);
152        }
153    
154      if (*lon > 180.0 || *lon < -180.0)
155        {
156          err (2);
157          return (-1);
158        }
159    
160      /* Prevent ACOS() Domain Error */
161      if (*lat == 90.0)
162        *lat = 89.9;
163      if (*lat == -90.0)
164        *lat = -89.9;
165    
166          /* Prevent ACOS() Domain Error */    return (0);
         if (*lat == 90.0) *lat = 89.9;  
         if (*lat == -90.0) *lat = -89.9;  
                                   
         return(0);  
167  }  }
168    
169  gchar *gc(gint units, gchar *qth, gchar *dest)  gchar *
170    gc (gint units, gchar * qth, gchar * dest)
171  {  {
172          gdouble tmp, arc, cosaz, az, azsp, azlp, distsp, distlp;    gdouble tmp, arc, cosaz, az, azsp, azlp, distsp, distlp;
173          gdouble QTH_Lat, QTH_Long, DEST_Lat, DEST_Long, Delta_Long;    gdouble QTH_Lat, QTH_Long, DEST_Lat, DEST_Long, Delta_Long;
174          gint parseresult = 0;    gint parseresult = 0;
175          gchar *result = NULL;    gchar *result = NULL;
176    
177          parseresult = parse(g_strdup(qth), &QTH_Lat, &QTH_Long);    parseresult = parse (g_strdup (qth), &QTH_Lat, &QTH_Long);
178          if (parseresult == -1) return("");    if (parseresult == -1)
179          parseresult = parse(g_strdup(dest), &DEST_Lat, &DEST_Long);      return ("");
180          if (parseresult == -1) return("");    parseresult = parse (g_strdup (dest), &DEST_Lat, &DEST_Long);
181      if (parseresult == -1)
182          QTH_Lat /= RADIAN; /* Convert variables to Radians */      return ("");
183          QTH_Long /= RADIAN;  
184          DEST_Lat /= RADIAN;    QTH_Lat /= RADIAN;            /* Convert variables to Radians */
185          DEST_Long /= RADIAN;    QTH_Long /= RADIAN;
186      DEST_Lat /= RADIAN;
187          Delta_Long = DEST_Long - QTH_Long;    DEST_Long /= RADIAN;
188    
189          tmp = (sin(QTH_Lat) * sin(DEST_Lat)) +    Delta_Long = DEST_Long - QTH_Long;
190                  (cos(QTH_Lat) * cos(DEST_Lat) * cos(Delta_Long));  
191      tmp = (sin (QTH_Lat) * sin (DEST_Lat)) +
192          if (tmp > .999999)      (cos (QTH_Lat) * cos (DEST_Lat) * cos (Delta_Long));
193          {  
194                  /* Station points coincide, use an Omni! */    if (tmp > .999999)
195                  return("");      {
196          }        /* Station points coincide, use an Omni! */
197          else if (tmp < -.999999)        return ("");
198          {      }
199      else if (tmp < -.999999)
200        {
201    
202  /*  /*
203   * points are antipodal, he's straight down.   * points are antipodal, he's straight down.
204   * So take 180 Degrees of arc times 60 nm,   * So take 180 Degrees of arc times 60 nm,
205   * and you get 10800 nm, or whatever units...   * and you get 10800 nm, or whatever units...
206   */   */
207                  return("");        return ("");
208          }      }
209          else    else
210          {      {
211                  arc = acos(tmp);        arc = acos (tmp);
212    
213  /*  /*
214   * One degree of arc is 60 Nautical miles   * One degree of arc is 60 Nautical miles
# Line 193  gchar *gc(gint units, gchar *qth, gchar Line 216  gchar *gc(gint units, gchar *qth, gchar
216   * This method is easier than the one in the handbook   * This method is easier than the one in the handbook
217   */   */
218    
219                  /* Short Path */        /* Short Path */
220                  distsp = (Units[units].miles) * (arc * RADIAN);        distsp = (Units[units].miles) * (arc * RADIAN);
221                  /* Long Path */        /* Long Path */
222                  distlp = ((Units[units].miles) * 360.0) - distsp;        distlp = ((Units[units].miles) * 360.0) - distsp;
223          }      }
224    
225          cosaz = (sin(DEST_Lat) - (sin(QTH_Lat) * cos(arc))) /    cosaz = (sin (DEST_Lat) - (sin (QTH_Lat) * cos (arc))) /
226                  (sin(arc) * cos(QTH_Lat));      (sin (arc) * cos (QTH_Lat));
227    
228          if (cosaz > .999999) az = 0.0;    if (cosaz > .999999)
229          else if (cosaz < -.999999) az = 180.0;      az = 0.0;
230          else az = acos(cosaz) * RADIAN;    else if (cosaz < -.999999)
231        az = 180.0;
232          /* Handbook had the test ">= 0.0" which looks backwards??       */    else
233        az = acos (cosaz) * RADIAN;
234          if (sin(Delta_Long) < 0.0)  
235          {    /* Handbook had the test ">= 0.0" which looks backwards??       */
236                  azsp = az;  
237                  azlp = 180.0 + az;    if (sin (Delta_Long) < 0.0)
238          }      {
239          else {        azsp = az;
240                  azsp = 360.0 - az;        azlp = 180.0 + az;
241                  azlp = 180.0 - az;      }
242          }    else
243        {
244          /* Computations complete, show answer */        azsp = 360.0 - az;
245          result = g_strdup_printf(_("\nShort Path: %03.0f deg, %.0f %s\n\        azlp = 180.0 - az;
246  Long Path: %03.0f deg, %.0f %s\n"),      }
247                  azsp, distsp, Units[units].text, azlp, distlp, Units[units].text);  
248          return(result);    /* Computations complete, show answer */
249      result = g_strdup_printf (_("\nShort Path: %03.0f deg, %.0f %s\n\
250    Long Path: %03.0f deg, %.0f %s\n"), azsp, distsp, Units[units].text, azlp, distlp, Units[units].text);
251      return (result);
252  }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26