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