1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/map/mapfile.cpp

268 lines
7.2 KiB
C++
Raw Normal View History

2018-03-10 09:25:52 +01:00
#include <QIODevice>
2018-01-08 23:47:45 +01:00
#include "utm.h"
#include "gcs.h"
2018-01-08 23:47:45 +01:00
#include "mapfile.h"
static double parameter(const QString &str, bool *res)
{
QString field = str.trimmed();
if (field.isEmpty()) {
*res = true;
return NAN;
}
return field.toDouble(res);
}
int MapFile::parse(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum)
{
bool res, r[8];
int ln = 1;
while (!device.atEnd()) {
QByteArray line = device.readLine();
if (ln == 1) {
if (!line.trimmed().startsWith("OziExplorer Map Data File"))
return ln;
} else if (ln == 2)
_name = line.trimmed();
else if (ln == 3)
_image = line.trimmed();
else if (ln == 5)
datum = line.split(',').at(0).trimmed();
else {
QList<QByteArray> list = line.split(',');
QString key(list.at(0).trimmed());
bool ll = true; bool pp = true;
if (key.startsWith("Point") && list.count() == 17
&& !list.at(2).trimmed().isEmpty()) {
CalibrationPoint p;
int x = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int y = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
int latd = list.at(6).trimmed().toInt(&res);
if (!res)
ll = false;
qreal latm = list.at(7).trimmed().toFloat(&res);
if (!res)
ll = false;
int lond = list.at(9).trimmed().toInt(&res);
if (!res)
ll = false;
qreal lonm = list.at(10).trimmed().toFloat(&res);
if (!res)
ll = false;
if (ll && list.at(8).trimmed() == "S") {
latd = -latd;
latm = -latm;
}
if (ll && list.at(11).trimmed() == "W") {
lond = -lond;
lonm = -lonm;
}
p.zone = list.at(13).trimmed().toInt(&res);
if (!res)
p.zone = 0;
qreal ppx = list.at(14).trimmed().toFloat(&res);
if (!res)
pp = false;
qreal ppy = list.at(15).trimmed().toFloat(&res);
if (!res)
pp = false;
if (list.at(16).trimmed() == "S")
p.zone = -p.zone;
p.rp.xy = QPoint(x, y);
if (ll) {
p.ll = Coordinates(lond + lonm/60.0, latd + latm/60.0);
if (p.ll.isValid())
points.append(p);
else
return ln;
} else if (pp) {
p.rp.pp = QPointF(ppx, ppy);
points.append(p);
} else
return ln;
} else if (key == "IWH") {
if (list.count() < 4)
return ln;
int w = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int h = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
_size = QSize(w, h);
} else if (key == "Map Projection") {
if (list.count() < 2)
return ln;
projection = list.at(1);
} else if (key == "Projection Setup") {
if (list.count() < 8)
return ln;
setup = Projection::Setup(
parameter(list[1], &r[1]), parameter(list[2], &r[2]),
parameter(list[3], &r[3]), parameter(list[4], &r[4]),
parameter(list[5], &r[5]), parameter(list[6], &r[6]),
parameter(list[7], &r[7]));
for (int i = 1; i < 8; i++)
if (!r[i])
return ln;
}
}
ln++;
}
2018-03-21 19:09:37 +01:00
return (ln < 9) ? ln : 0;
2018-01-08 23:47:45 +01:00
}
bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum)
{
int el;
if (!device.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening file: %1")
2018-01-08 23:47:45 +01:00
.arg(device.errorString());
return false;
}
if ((el = parse(device, points, projection, setup, datum))) {
_errorString = QString("Parse error on line %1").arg(el);
2018-01-08 23:47:45 +01:00
return false;
}
return true;
}
const GCS *MapFile::createGCS(const QString &datum)
2018-01-08 23:47:45 +01:00
{
const GCS *gcs;
if (!(gcs = GCS::gcs(datum)))
2018-01-08 23:47:45 +01:00
_errorString = QString("%1: Unknown datum").arg(datum);
return gcs;
2018-01-08 23:47:45 +01:00
}
bool MapFile::createProjection(const GCS *gcs, const QString &name,
2018-01-08 23:47:45 +01:00
const Projection::Setup &setup, QList<CalibrationPoint> &points)
{
if (name == "Mercator")
_projection = Projection(gcs, 1024, setup, 9001);
2018-01-08 23:47:45 +01:00
else if (name == "Transverse Mercator")
_projection = Projection(gcs, 9807, setup, 9001);
2018-01-08 23:47:45 +01:00
else if (name == "Latitude/Longitude")
_projection = Projection(gcs);
2018-01-08 23:47:45 +01:00
else if (name == "Lambert Conformal Conic")
_projection = Projection(gcs, 9802, setup, 9001);
2018-01-08 23:47:45 +01:00
else if (name == "Albers Equal Area")
_projection = Projection(gcs, 9822, setup, 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(A)Lambert Azimuthual Equal Area")
_projection = Projection(gcs, 9820, setup, 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(UTM) Universal Transverse Mercator") {
2018-01-09 23:19:24 +01:00
int zone;
2018-01-08 23:47:45 +01:00
if (points.first().zone)
2018-01-09 23:19:24 +01:00
zone = points.first().zone;
2018-01-08 23:47:45 +01:00
else if (!points.first().ll.isNull())
2018-01-09 23:19:24 +01:00
zone = UTM::zone(points.first().ll);
2018-01-08 23:47:45 +01:00
else {
_errorString = "Can not determine UTM zone";
return false;
2018-01-08 23:47:45 +01:00
}
_projection = Projection(gcs, 9807, UTM::setup(zone), 9001);
2018-01-08 23:47:45 +01:00
} else if (name == "(NZTM2) New Zealand TM 2000")
_projection = Projection(gcs, 9807, Projection::Setup(0, 173.0, 0.9996,
1600000, 10000000, NAN, NAN), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(BNG) British National Grid")
_projection = Projection(gcs, 9807, Projection::Setup(49, -2, 0.999601,
400000, -100000, NAN, NAN), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(IG) Irish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(53.5, -8,
1.000035, 200000, 250000, NAN, NAN), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(SG) Swedish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(0, 15.808278, 1,
1500000, 0, NAN, NAN), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(I) France Zone I")
_projection = Projection(gcs, 9802, Projection::Setup(49.5, 2.337229,
NAN, 600000, 1200000, 48.598523, 50.395912), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(II) France Zone II")
_projection = Projection(gcs, 9802, Projection::Setup(46.8, 2.337229,
NAN, 600000, 2200000, 45.898919, 47.696014), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(III) France Zone III")
_projection = Projection(gcs, 9802, Projection::Setup(44.1, 2.337229,
NAN, 600000, 3200000, 43.199291, 44.996094), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(IV) France Zone IV")
_projection = Projection(gcs, 9802, Projection::Setup(42.165, 2.337229,
NAN, 234.358, 4185861.369, 41.560388, 42.767663), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(VICGRID) Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN,
2500000, 4500000, -36, -38), 9001);
2018-01-08 23:47:45 +01:00
else if (name == "(VG94) VICGRID94 Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN,
2500000, 2500000, -36, -38), 9001);
else if (name == "(SUI) Swiss Grid")
_projection = Projection(gcs, 9815, Projection::Setup(46.570866,
7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001);
2018-01-08 23:47:45 +01:00
else {
_errorString = QString("%1: Unknown map projection").arg(name);
return false;
}
return true;
}
bool MapFile::computeTransformation(QList<CalibrationPoint> &points)
{
QList<ReferencePoint> rp;
for (int i = 0; i < points.size(); i++) {
if (points.at(i).rp.pp.isNull())
points[i].rp.pp = _projection.ll2xy(points.at(i).ll);
2018-01-08 23:47:45 +01:00
rp.append(points.at(i).rp);
}
Transform t(rp);
if (t.isNull()) {
_errorString = t.errorString();
return false;
}
_transform = t.transform();
return true;
}
2018-03-21 19:09:37 +01:00
MapFile::MapFile(QIODevice &file)
2018-01-08 23:47:45 +01:00
{
QList<CalibrationPoint> points;
QString ct, datum;
2018-01-08 23:47:45 +01:00
Projection::Setup setup;
const GCS *gcs;
2018-01-08 23:47:45 +01:00
if (!parseMapFile(file, points, ct, setup, datum))
2018-03-21 19:09:37 +01:00
return;
if (!(gcs = createGCS(datum)))
2018-03-21 19:09:37 +01:00
return;
if (!createProjection(gcs, ct, setup, points))
2018-03-21 19:09:37 +01:00
return;
2018-01-08 23:47:45 +01:00
if (!computeTransformation(points))
2018-03-21 19:09:37 +01:00
_image = QString();
2018-01-08 23:47:45 +01:00
}