GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
ll_scan.c
Go to the documentation of this file.
1 
2 /******************************************************************************
3  G_lat_scan (buf, lat)
4  char *buf;
5  double *lat;
6 
7  G_lon_scan (buf, lon)
8  char *buf;
9  double *lon;
10 
11  G_llres_scan (buf, res)
12  char *buf;
13  double *res;
14 
15  Convert ascii string representations of latitude/longitude to a double.
16  The string format is:
17 
18  dd:mm:ss.ffh
19 
20  where:
21  dd is degrees, 0-90 for latitude, 0-180 for longitude
22  mm is minutes, 0-59
23  ss is seconds, 0-59
24  ff is fractions of a second, >= 0
25  h is 'n' or 's' for latitude,
26  'e' or 'w' for longitude.
27  missing for resolution
28 
29  lat (or lon) is set to the double value for the lat/lon represented in buf.
30 
31  lat is always in the range -90 thru 90,
32  lon is always in the range -180 thru 180.
33 
34  note: southern latitude and western longitude are returned as negative values.
35 
36  returns 1 if input format is ok, 0 otherwise.
37 ******************************************************************************/
38 #include <grass/gis.h>
39 
40 #define LL_TOLERANCE 10
41 
42 static int scan_ll(const char *, const char *, double *, int);
43 static int check_minutes(const char *);
44 static int check_seconds(const char *);
45 
46 int G_lat_scan(const char *buf, double *lat)
47 {
48  return scan_ll(buf, "sn", lat, 90 + LL_TOLERANCE);
49 }
50 
51 int G_lon_scan(const char *buf, double *lon)
52 {
53  return scan_ll(buf, "we", lon, 360 + LL_TOLERANCE);
54 }
55 
56 int G_llres_scan(const char *buf, double *res)
57 {
58  char tbuf[100];
59 
60  sprintf(tbuf, "%se", buf);
61  return scan_ll(tbuf, "we", res, 0);
62 }
63 
64 #define MARKER 1
65 static int scan_ll(const char *buf, const char *dir, double *result, int max)
66 {
67  char h[100];
68  int d, m, s;
69  char ps[20], *pps;
70  double p, f;
71  double pm = 0.0;
72  char tbuf[100];
73 
74  sprintf(tbuf, "%s%c", buf, MARKER); /* add a marker at end of string */
75  buf = tbuf;
76 
77  if (sscanf(buf, "%d:%d:%d.%[0123456789]%[^\n]", &d, &m, &s, ps, h) == 5) {
78  p = 0.0;
79  f = .1;
80  for (pps = ps; *pps; pps++) {
81  p += (*pps - '0') * f;
82  f /= 10.0;
83  }
84  }
85  else if (sscanf(buf, "%d:%d:%d%[^\n]", &d, &m, &s, h) == 4) {
86  p = 0.0;
87  }
88  else if (sscanf(buf, "%d:%d.%[0123456789]%[^\n]", &d, &m, ps, h) == 4) {
89  s = 0;
90  p = 0.0;
91  f = .1;
92  for (pps = ps; *pps; pps++) {
93  pm += (*pps - '0') * f;
94  f /= 10.0;
95  }
96  }
97  else if (sscanf(buf, "%d:%d%[^\n]", &d, &m, h) == 3) {
98  p = 0.0;
99  s = 0;
100  }
101  else if (sscanf(buf, "%d%[^\n]", &d, h) == 2) {
102  p = 0.0;
103  s = m = 0;
104  }
105  else
106  return 0;
107 
108  if (d < 0)
109  return 0;
110  if (m < 0 || m >= 60)
111  return 0;
112  if (s < 0 || s >= 60)
113  return 0;
114 
115  if (max) {
116  if (d > max)
117  return 0;
118  if (d == max && (m > 0 || s > 0 || p > 0.0))
119  return 0;
120  }
121 
122  if (m && !check_minutes(buf))
123  return 0;
124  if (s && !check_seconds(buf))
125  return 0;
126 
127  *result = d + (m + pm) / 60.0 + (s + p) / 3600.0;
128 
129  G_strip(h);
130 
131  if (*result == 0.0 && *h == MARKER)
132  return (1);
133 
134  if (*h >= 'A' && *h <= 'Z')
135  *h += 'a' - 'A';
136 
137  if (*h != dir[0] && *h != dir[1])
138  return 0;
139 
140  if (h[1] != MARKER)
141  return 0;
142 
143  if (*h == dir[0] && *result != 0.0)
144  *result = -(*result);
145 
146  return 1;
147 }
148 
149 static int check_minutes(const char *buf)
150 {
151  /* skip over degrees */
152  while (*buf != ':')
153  if (*buf++ == 0)
154  return 1;
155  buf++;
156 
157  /* must have 2 digits for minutes */
158  if (*buf < '0' || *buf > '9')
159  return 0;
160  buf++;
161  if (*buf < '0' || *buf > '9')
162  return 0;
163  buf++;
164  return (*buf < '0' || *buf > '9');
165 }
166 
167 static int check_seconds(const char *buf)
168 {
169  /* skip over degrees */
170  while (*buf != ':')
171  if (*buf++ == 0)
172  return 1;
173  buf++;
174  /* skip over minutes */
175  while (*buf != ':')
176  if (*buf++ == 0)
177  return 1;
178  buf++;
179 
180  /* must have 2 digits for seconds */
181  if (*buf < '0' || *buf > '9')
182  return 0;
183  buf++;
184  if (*buf < '0' || *buf > '9')
185  return 0;
186  buf++;
187  return (*buf < '0' || *buf > '9');
188 }
struct ps_state ps
#define MARKER
Definition: ll_scan.c:64
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
#define max(x, y)
Definition: draw2.c:32
int G_lat_scan(const char *buf, double *lat)
Definition: ll_scan.c:46
int G_llres_scan(const char *buf, double *res)
Definition: ll_scan.c:56
#define LL_TOLERANCE
Definition: ll_scan.c:40
int G_lon_scan(const char *buf, double *lon)
Definition: ll_scan.c:51