FlightGear next
fixlist.cxx
Go to the documentation of this file.
1// fixlist.cxx -- fix list management class
2//
3// Written by Curtis Olson, started April 2000.
4//
5// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
6//
7// This program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public License as
9// published by the Free Software Foundation; either version 2 of the
10// License, or (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful, but
13// WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15// General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program; if not, write to the Free Software
19// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20//
21// $Id$
22
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
28#include <stdlib.h> // atof()
29
30#include <algorithm>
31#include <string> // std::getline()
32#include <errno.h>
33
34#include <simgear/debug/logstream.hxx>
35#include <simgear/io/iostreams/sgstream.hxx>
36#include <simgear/misc/sg_path.hxx>
37#include <simgear/misc/strutils.hxx> // simgear::strutils::split()
38#include <simgear/math/SGGeod.hxx>
39#include <simgear/math/SGMathFwd.hxx>
40#include <simgear/math/SGVec3.hxx>
41#include <simgear/constants.h>
42#include <simgear/structure/exception.hxx>
43
44#include "fixlist.hxx"
45#include <Navaids/fix.hxx>
47
48// A navaid with the same ident as an existing navaid not more distant than
49// this will be considered duplicate.
50static const double DUPLICATE_DETECTION_RADIUS_NM = 15;
51
52FGFix::FGFix(PositionedID aGuid, const std::string& aIdent, const SGGeod& aPos) :
53 FGPositioned(aGuid, FIX, aIdent, aPos)
54{
55}
56
57
58namespace flightgear
59{
60
62{ }
63
66
67// Load fixes from the specified fix.dat (or fix.dat.gz) file
69 std::size_t bytesReadSoFar,
70 std::size_t totalSizeOfAllDatFiles)
71{
72 const SGPath path = sceneryLocation.datPath;
73 sg_gzifstream in( path );
74 const std::string utf8path = path.utf8Str();
75
76 if ( !in.is_open() ) {
77 throw sg_io_exception(
78 "Cannot open file (" + simgear::strutils::error_string(errno) + ")",
79 sg_location(path));
80 }
81
82 // toss the first two lines of the file
83 for (int i = 0; i < 2; i++) {
84 in >> skipeol;
85 throwExceptionIfStreamError(in, path);
86 }
87
88 unsigned int lineNumber = 3;
89
90 // read in each remaining line of the file
91 for (std::string line; std::getline(in, line); lineNumber++) {
92 std::vector<std::string> fields = simgear::strutils::split(line);
93 std::vector<std::string>::size_type nb_fields = fields.size();
94 const std::string endOfData = "99"; // special code in the fix.dat spec
95
96 if (nb_fields == 0) { // blank line
97 continue;
98 } else if (nb_fields == 1) {
99 if (fields[0] == endOfData)
100 break;
101 else {
102 SG_LOG(SG_NAVAID, SG_WARN, utf8path << ": malformed line #" <<
103 lineNumber << ": only one field, but it is not '99'");
104 continue;
105 }
106 } else if (nb_fields < 3) {
107 SG_LOG(SG_NAVAID, SG_WARN, utf8path << ": malformed line #" <<
108 lineNumber << ": expected at least 3 fields, but got " <<
109 fields.size());
110 continue;
111 } else if (nb_fields != 3 && nb_fields != 5 && nb_fields != 6) {
112 // XP FIX1101 format calls for 6 fields, the last being optional.
113 // XP FIX1100 has 5 fields.
114 // Earlier formats have 3 fields.
115 // In all these cases we need the first three only.
116 SG_LOG(SG_NAVAID, SG_INFO, utf8path << ": line #" <<
117 lineNumber << ": ignoring extra fields, past the first three " <<
118 "(expected 3 or 5 or 6 fields, but got " << fields.size() << ")");
119 }
120
121 std::string ident = fields[2];
122 double lat, lon;
123 try {
124 lat = std::stod(fields[0]);
125 lon = std::stod(fields[1]);
126 } catch (const std::exception&) {
127 SG_LOG(SG_NAVAID, SG_WARN, utf8path << ": malformed line #" <<
128 lineNumber << ": error parsing coordinates: " << fields[0] <<
129 " " << fields[1]);
130 continue;
131 }
132 SGGeod pos(SGGeod::fromDeg(lon, lat));
133 bool duplicate = false;
134 auto range = _loadedFixes.equal_range(ident);
135 for (auto it = range.first; it != range.second; ++it) {
136 double distNm = dist(SGVec3d::fromGeod(pos),
137 SGVec3d::fromGeod(it->second)) * SG_METER_TO_NM;
138 if (distNm < DUPLICATE_DETECTION_RADIUS_NM) {
139 SG_LOG(SG_NAVAID, SG_INFO,
140 utf8path << ":" << lineNumber << ": skipping fix " <<
141 ident << " (already defined nearby)");
142 duplicate = true;
143 break;
144 }
145 }
146
147 if (!duplicate) {
148 _cache->createPOI(FGPositioned::FIX, ident, pos, {}, false);
149 _loadedFixes.insert({ident, pos});
150 }
151
152 if ((lineNumber % 100) == 0) {
153 // every 100 lines
154 unsigned int percent = ((bytesReadSoFar + in.approxOffset()) * 100)
155 / totalSizeOfAllDatFiles;
156 _cache->setRebuildPhaseProgress(NavDataCache::REBUILD_FIXES, percent);
157 }
158 }
159
160 throwExceptionIfStreamError(in, path);
161}
162
163void FixesLoader::throwExceptionIfStreamError(
164 const sg_gzifstream& input_stream, const SGPath& path)
165{
166 if (input_stream.bad()) {
167 const std::string errMsg = simgear::strutils::error_string(errno);
168
169 SG_LOG(SG_NAVAID, SG_ALERT,
170 "Error while reading '" << path.utf8Str() << "': " << errMsg);
171 throw sg_io_exception("FixesLoader: error reading file (" + errMsg + ")",
172 sg_location(path));
173 }
174}
175
176
177} // of namespace flightgear;
#define i(x)
FGFix(PositionedID aGuid, const std::string &aIdent, const SGGeod &aPos)
Definition fixlist.cxx:52
FGPositioned(PositionedID aGuid, Type ty, const std::string &aIdent, const SGGeod &aPos)
void loadFixes(const NavDataCache::SceneryLocation &sceneryLocation, std::size_t bytesReadSoFar, std::size_t totalSizeOfAllDatFiles)
Definition fixlist.cxx:68
static const double DUPLICATE_DETECTION_RADIUS_NM
Definition fixlist.cxx:50
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
Definition Addon.cxx:53
static const double DUPLICATE_DETECTION_RADIUS_NM
Definition poidb.cxx:46
int64_t PositionedID