GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
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
42static int scan_ll(const char *, const char *, double *, int);
43static int check_minutes(const char *);
44static int check_seconds(const char *);
45
46int G_lat_scan(const char *buf, double *lat)
47{
48 return scan_ll(buf, "sn", lat, 90 + LL_TOLERANCE);
49}
50
51int G_lon_scan(const char *buf, double *lon)
52{
53 return scan_ll(buf, "we", lon, 360 + LL_TOLERANCE);
54}
55
56int 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
65static 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
149static 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
167static 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}
#define MARKER
Definition: ll_scan.c:64
#define LL_TOLERANCE
Definition: ll_scan.c:40
int G_lat_scan(const char *buf, double *lat)
Definition: ll_scan.c:46
int G_lon_scan(const char *buf, double *lon)
Definition: ll_scan.c:51
int G_llres_scan(const char *buf, double *res)
Definition: ll_scan.c:56
#define max(a, b)
struct ps_state ps
void G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition: strings.c:300