GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-eb16a2cfc9
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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  snprintf(tbuf, sizeof(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  snprintf(tbuf, sizeof(tbuf), "%s%c", buf,
74  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 }
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