SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Waypoint / WaypointReaderCompeGPS.cpp
blobf3cfe9c4a66b2a888dac48880297593d35ff400e
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "WaypointReaderCompeGPS.hpp"
25 #include "Waypoint/Waypoints.hpp"
26 #include "IO/LineReader.hpp"
27 #include "Util/Macros.hpp"
28 #include "Geo/UTM.hpp"
30 #include <stdio.h>
32 static bool
33 ParseAngle(const TCHAR *&src, Angle &angle)
35 // 41.234234N
37 TCHAR *endptr;
39 // Parse numerical value
40 double value = _tcstod(src, &endptr);
41 if (endptr == src)
42 return false;
44 src = endptr;
45 angle = Angle::Degrees(value);
47 // Skip until next whitespace and look for NSEW signs
48 bool found = false;
49 while (*src != _T(' ') && *src != _T('\0')) {
50 if (!found) {
51 if (*src == _T('N') || *src == _T('n') ||
52 *src == _T('E') || *src == _T('e')) {
53 found = true;
54 } else if (*src == _T('S') || *src == _T('s') ||
55 *src == _T('W') || *src == _T('w')) {
56 found = true;
57 angle.Flip();
61 src++;
64 return found;
67 static bool
68 ParseLocation(const TCHAR *&src, GeoPoint &p)
70 // A 41.234234N 7.234424W
72 // Ignore but require 'A' placeholder
73 if (*src != _T('A'))
74 return false;
76 src++;
78 // Skip whitespace
79 while (*src == _T(' '))
80 src++;
82 Angle lat, lon;
83 if (!ParseAngle(src, lat) || !ParseAngle(src, lon))
84 return false;
86 p.longitude = lon;
87 p.latitude = lat;
89 // ensure longitude is within -180:180
90 p.Normalize();
92 return true;
95 static bool
96 ParseLocationUTM(const TCHAR *&src, GeoPoint &p)
98 // 31T 318570 4657569
100 TCHAR *endptr;
102 // Parse zone number
103 long zone_number = _tcstol(src, &endptr, 10);
104 if (endptr == src)
105 return false;
107 src = endptr;
108 char zone_letter = src[0];
110 src++;
111 long easting = _tcstol(src, &endptr, 10);
112 if (endptr == src || *endptr != _T(' '))
113 return false;
115 src = endptr;
116 long northing = _tcstol(src, &endptr, 10);
117 if (endptr == src || *endptr != _T(' '))
118 return false;
120 UTM u(zone_number, zone_letter, fixed(easting), fixed(northing));
121 p = u.ToGeoPoint();
123 // ensure longitude is within -180:180
124 p.Normalize();
126 src = endptr;
128 return true;
131 static bool
132 ParseAltitude(const TCHAR *&src, fixed &dest)
134 TCHAR *endptr;
135 double value = _tcstod(src, &endptr);
136 if (endptr == src)
137 return false;
139 dest = fixed(value);
140 src = endptr;
141 return true;
144 bool
145 WaypointReaderCompeGPS::ParseLine(const TCHAR* line, const unsigned linenum,
146 Waypoints &waypoints)
149 * G WGS 84
150 * U 1
151 * W IT05FC A 46.9121939503ºN 11.9605922700°E 27-MAR-62 00:00:00 566.000000 Ahornach Sand, Ahornach LP, GS und HG
152 * w Waypoint,0,-1.0,16777215,255,0,0,7,,0.0,
153 * W IT05FB A 46.9260440931ºN 11.9676733017°E 27-MAR-62 00:00:00 1425.000000 Ahornach Sand, Ahornach SP, GS und HG
154 * w Waypoint,0,-1.0,16777215,255,0,0,7,,0.0,
156 * W ShortName 31T 318570 4657569 27-MAR-62 00:00:00 0 some Comments
157 * W ShortName A 41.234234N 7.234424W 27-MAR-62 00:00:00 0 Comments
160 // Skip projection and file encoding information
161 if (*line == _T('G') || *line == _T('B'))
162 return true;
164 // Check for format: UTM or LatLon
165 if (*line == _T('U') && _tcsstr(line, _T("U 0")) == line) {
166 is_utm = true;
167 return true;
170 // Skip non-waypoint lines
171 if (*line != _T('W'))
172 return true;
174 // Skip W indicator and whitespace
175 line++;
176 while (*line == _T(' '))
177 line++;
179 // Find next space delimiter, skip shortname
180 const TCHAR *name = line;
181 const TCHAR *space = _tcsstr(line, _T(" "));
182 if (space == NULL)
183 return false;
185 unsigned name_length = space - line;
186 if (name_length == 0)
187 return false;
189 line = space;
190 while (*line == _T(' '))
191 line++;
193 // Parse location
194 GeoPoint location;
195 if ((!is_utm && !ParseLocation(line, location)) ||
196 (is_utm && !ParseLocationUTM(line, location)))
197 return false;
199 // Skip whitespace
200 while (*line == _T(' '))
201 line++;
203 // Skip unused date field
204 line = _tcsstr(line, _T(" "));
205 if (line == NULL)
206 return false;
208 line++;
210 // Skip unused time field
211 line = _tcsstr(line, _T(" "));
212 if (line == NULL)
213 return false;
215 line++;
217 // Create new waypoint instance
218 Waypoint waypoint(location);
219 waypoint.file_num = file_num;
220 waypoint.original_id = 0;
221 waypoint.name.assign(name, name_length);
223 // Parse altitude
224 if (!ParseAltitude(line, waypoint.elevation) &&
225 !CheckAltitude(waypoint))
226 return false;
228 // Skip whitespace
229 while (*line == _T(' '))
230 line++;
232 // Parse waypoint name
233 waypoint.comment.assign(line);
235 waypoints.Append(std::move(waypoint));
236 return true;
239 bool
240 WaypointReaderCompeGPS::VerifyFormat(TLineReader &reader)
242 const TCHAR *line = reader.ReadLine();
243 if (line == NULL)
244 return false;
246 // Ignore optional line with encoding information
247 if (StringStartsWith(line, _T("B ")))
248 if ((line = reader.ReadLine()) == NULL)
249 return false;
251 return StringStartsWith(line, _T("G WGS 84"));