Header includes cleanup
[GPXSee.git] / src / map / gcs.cpp
blob7b72a46ba84cc4a9ea4264739bd6ed5d1797021c
1 #include <QFile>
2 #include "common/csv.h"
3 #include "gcs.h"
6 class GCS::Entry {
7 public:
8 Entry(int id, int gd, const QString &name, const GCS &gcs)
9 : _id(id), _gd(gd), _name(name), _gcs(gcs) {}
11 int id() const {return _id;}
12 int gd() const {return _gd;}
13 const QString &name() const {return _name;}
14 const GCS &gcs() const {return _gcs;}
16 private:
17 int _id, _gd;
18 QString _name;
19 GCS _gcs;
22 static int parameter(const QByteArray &str, bool *res)
24 if (str.isEmpty()) {
25 *res = true;
26 return 0;
29 return str.toInt(res);
32 static double parameterd(const QByteArray &str, bool *res)
34 if (str.isEmpty()) {
35 *res = true;
36 return NAN;
39 return str.toDouble(res);
43 QList<GCS::Entry> GCS::_gcss = defaults();
45 const GCS &GCS::WGS84()
47 static GCS g(Datum::WGS84(), 8901, 9122);
48 return g;
51 QList<GCS::Entry> GCS::defaults()
53 QList<GCS::Entry> list;
54 list.append(GCS::Entry(4326, 6326, "WGS 1984", WGS84()));
55 list.append(GCS::Entry(4326, 6326, "WGS 84", WGS84()));
56 list.append(GCS::Entry(4326, 6326, "WGS84", WGS84()));
57 return list;
60 GCS GCS::gcs(int id)
62 for (int i = 0; i < _gcss.size(); i++)
63 if (_gcss.at(i).id() == id)
64 return _gcss.at(i).gcs();
66 return GCS();
69 GCS GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits)
71 for (int i = 0; i < _gcss.size(); i++) {
72 const Entry &e = _gcss.at(i);
73 if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
74 && e.gcs().angularUnits() == angularUnits)
75 return e.gcs();
78 return GCS();
81 GCS GCS::gcs(const QString &name)
83 for (int i = 0; i < _gcss.size(); i++)
84 if (_gcss.at(i).name() == name)
85 return _gcss.at(i).gcs();
87 return GCS();
90 bool GCS::loadList(const QString &path)
92 QFile file(path);
93 CSV csv(&file);
94 QByteArrayList entry;
95 bool res;
97 if (!file.open(QFile::ReadOnly)) {
98 qWarning("Error opening GCS file: %s: %s", qPrintable(path),
99 qPrintable(file.errorString()));
100 return false;
103 while (!csv.atEnd()) {
104 if (!csv.readEntry(entry) || entry.size() < 14) {
105 qWarning("%s:%d: Parse error", qPrintable(path), csv.line());
106 return false;
109 int id = parameter(entry.at(1), &res);
110 if (!res) {
111 qWarning("%s:%d: Invalid GCS code", qPrintable(path), csv.line());
112 continue;
114 int gd = parameter(entry.at(2), &res);
115 if (!res) {
116 qWarning("%s:%d: Invalid geodetic datum code", qPrintable(path),
117 csv.line());
118 continue;
120 int au = entry.at(3).toInt(&res);
121 if (!res) {
122 qWarning("%s:%d: Invalid angular units code", qPrintable(path),
123 csv.line());
124 continue;
126 int el = entry.at(4).toInt(&res);
127 if (!res) {
128 qWarning("%s:%d: Invalid ellipsoid code", qPrintable(path),
129 csv.line());
130 continue;
132 int pm = entry.at(5).toInt(&res);
133 if (!res) {
134 qWarning("%s:%d: Invalid prime meridian code", qPrintable(path),
135 csv.line());
136 continue;
138 int ct = entry.at(6).toInt(&res);
139 if (!res) {
140 qWarning("%s:%d: Invalid coordinates transformation code",
141 qPrintable(path), csv.line());
142 continue;
144 double dx = entry.at(7).toDouble(&res);
145 if (!res) {
146 qWarning("%s:%d: Invalid dx", qPrintable(path), csv.line());
147 continue;
149 double dy = entry.at(8).toDouble(&res);
150 if (!res) {
151 qWarning("%s:%d: Invalid dy", qPrintable(path), csv.line());
152 continue;
154 double dz = entry.at(9).toDouble(&res);
155 if (!res) {
156 qWarning("%s:%d: Invalid dz", qPrintable(path), csv.line());
157 continue;
159 double rx = parameterd(entry.at(10), &res);
160 if (!res) {
161 qWarning("%s:%d: Invalid rx", qPrintable(path), csv.line());
162 continue;
164 double ry = parameterd(entry.at(11), &res);
165 if (!res) {
166 qWarning("%s:%d: Invalid ry", qPrintable(path), csv.line());
167 continue;
169 double rz = parameterd(entry.at(12), &res);
170 if (!res) {
171 qWarning("%s:%d: Invalid rz", qPrintable(path), csv.line());
172 continue;
174 double ds = parameterd(entry.at(13), &res);
175 if (!res) {
176 qWarning("%s:%d: Invalid ds", qPrintable(path), csv.line());
177 continue;
180 const Ellipsoid &e = Ellipsoid::ellipsoid(el);
181 if (e.isNull()) {
182 qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path),
183 csv.line());
184 continue;
187 Datum datum;
188 switch (ct) {
189 case 9603:
190 datum = Datum(e, dx, dy, dz);
191 break;
192 case 9606:
193 datum = Datum(e, dx, dy, dz, -rx, -ry, -rz, ds);
194 break;
195 case 9607:
196 datum = Datum(e, dx, dy, dz, rx, ry, rz, ds);
197 break;
198 default:
199 qWarning("%s:%d: Unknown coordinates transformation method",
200 qPrintable(path), csv.line());
201 continue;
203 if (!datum.isValid()) {
204 qWarning("%s:%d: Invalid coordinates transformation parameters",
205 qPrintable(path), csv.line());
206 continue;
209 GCS gcs(datum, pm, au);
210 if (gcs.isValid())
211 _gcss.append(Entry(id, gd, entry.at(0), gcs));
212 else
213 qWarning("%s:%d: Unknown prime meridian/angular units code",
214 qPrintable(path), csv.line());
217 return true;
220 Coordinates GCS::toWGS84(const Coordinates &c) const
222 return datum().toWGS84(Coordinates(_primeMeridian.toGreenwich(c.lon()),
223 c.lat()));
226 Coordinates GCS::fromWGS84(const Coordinates &c) const
228 Coordinates ds(datum().fromWGS84(c));
229 return Coordinates(_primeMeridian.fromGreenwich(ds.lon()), ds.lat());
232 QList<KV<int, QString> > GCS::list()
234 QList<KV<int, QString> > list;
236 for (int i = 0; i < _gcss.size(); i++) {
237 const Entry &e = _gcss.at(i);
238 if (!e.id() || (i && e.id() == list.last().key()))
239 continue;
241 list.append(KV<int, QString>(e.id(), e.name() + " / Geographic 2D"));
244 return list;
247 QList<KV<int, QString> > GCS::WGS84List()
249 QList<KV<int, QString> > list;
250 list.append(KV<int, QString>(4326, "Geographic 2D"));
251 return list;
254 #ifndef QT_NO_DEBUG
255 QDebug operator<<(QDebug dbg, const GCS &gcs)
257 dbg.nospace() << "GCS(" << gcs.datum() << ", " << gcs.primeMeridian()
258 << ", " << gcs.angularUnits() << ")";
259 return dbg.space();
261 #endif // QT_NO_DEBUG