mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 03:35:53 +01:00
Redesigned CRS logic (including CSV files structure)
This commit is contained in:
parent
aec052edaf
commit
e5199f8648
7502
data/csv/pcs.csv
7502
data/csv/pcs.csv
File diff suppressed because it is too large
Load Diff
1706
data/csv/projections.csv
Normal file
1706
data/csv/projections.csv
Normal file
File diff suppressed because it is too large
Load Diff
@ -125,6 +125,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/ENC/style.h \
|
||||
src/map/IMG/section.h \
|
||||
src/map/IMG/zoom.h \
|
||||
src/map/conversion.h \
|
||||
src/map/encmap.h \
|
||||
src/map/ENC/iso8211.h \
|
||||
src/map/gemfmap.h \
|
||||
@ -335,6 +336,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/ENC/mapdata.cpp \
|
||||
src/map/ENC/rastertile.cpp \
|
||||
src/map/ENC/style.cpp \
|
||||
src/map/conversion.cpp \
|
||||
src/map/encmap.cpp \
|
||||
src/map/ENC/iso8211.cpp \
|
||||
src/map/gemfmap.cpp \
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "common/downloader.h"
|
||||
#include "map/ellipsoid.h"
|
||||
#include "map/gcs.h"
|
||||
#include "map/conversion.h"
|
||||
#include "map/pcs.h"
|
||||
#include "data/dem.h"
|
||||
#include "data/waypoint.h"
|
||||
@ -172,11 +173,21 @@ void App::loadDatums()
|
||||
|
||||
void App::loadPCSs()
|
||||
{
|
||||
QString projectionsFile(ProgramPaths::projectionsFile());
|
||||
QString pcsFile(ProgramPaths::pcsFile());
|
||||
|
||||
if (!QFileInfo::exists(projectionsFile)) {
|
||||
qWarning("No projections file found.");
|
||||
projectionsFile = QString();
|
||||
}
|
||||
if (!QFileInfo::exists(pcsFile)) {
|
||||
qWarning("No PCS file found.");
|
||||
qWarning("Maps based on a projection different from EPSG:3857 won't work.");
|
||||
} else
|
||||
pcsFile = QString();
|
||||
}
|
||||
|
||||
if (!projectionsFile.isNull() && !pcsFile.isNull()) {
|
||||
Conversion::loadList(projectionsFile);
|
||||
PCS::loadList(pcsFile);
|
||||
} else
|
||||
qWarning("Maps based on a projection different from EPSG:3857 won't work.");
|
||||
}
|
||||
|
@ -2745,7 +2745,8 @@ void GUI::loadOptions()
|
||||
_mapView->useOpenGL(true);
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
_mapView->setOutputProjection(CRS::projection(_options.outputProjection));
|
||||
_mapView->setOutputProjection(CRS::projection(4326,
|
||||
_options.outputProjection));
|
||||
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
|
||||
_mapView->setTimeZone(_options.timeZone.zone());
|
||||
_mapView->setPositionSource(_positionSource);
|
||||
@ -2859,7 +2860,8 @@ void GUI::updateOptions(const Options &options)
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
if (options.outputProjection != _options.outputProjection)
|
||||
_mapView->setOutputProjection(CRS::projection(options.outputProjection));
|
||||
_mapView->setOutputProjection(CRS::projection(4326,
|
||||
options.outputProjection));
|
||||
if (options.inputProjection != _options.inputProjection)
|
||||
_mapView->setInputProjection(CRS::projection(options.inputProjection));
|
||||
if (options.timeZone != _options.timeZone) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <QSysInfo>
|
||||
#include <QButtonGroup>
|
||||
#include <QGeoPositionInfoSource>
|
||||
#include "map/pcs.h"
|
||||
#include "icons.h"
|
||||
#include "infolabel.h"
|
||||
#include "colorbox.h"
|
||||
@ -52,18 +53,20 @@ void OptionsDialog::automaticPauseDetectionSet(bool set)
|
||||
|
||||
QWidget *OptionsDialog::createMapPage()
|
||||
{
|
||||
_outputProjection = new ProjectionComboBox();
|
||||
_outputProjection = new ProjectionComboBox(GCS::WGS84List()
|
||||
+ Conversion::list());
|
||||
_outputProjection->setCurrentIndex(_outputProjection->findData(
|
||||
_options.outputProjection));
|
||||
_inputProjection = new ProjectionComboBox();
|
||||
_inputProjection = new ProjectionComboBox(GCS::list() + PCS::list());
|
||||
_inputProjection->setCurrentIndex(_inputProjection->findData(
|
||||
_options.inputProjection));
|
||||
|
||||
InfoLabel *inInfo = new InfoLabel(tr("Select the proper projection of maps"
|
||||
" without a projection definition (JNX, KMZ and world file maps)."));
|
||||
InfoLabel *outInfo = new InfoLabel(tr("Select the desired projection of"
|
||||
" vector maps (IMG and Mapsforge maps). The projection must be valid for"
|
||||
" the whole map area."));
|
||||
InfoLabel *inInfo = new InfoLabel(tr("Select the proper coordinate "
|
||||
"reference system (CRS) of maps without a CRS definition "
|
||||
"(JNX, KMZ and World file maps)."));
|
||||
InfoLabel *outInfo = new InfoLabel(tr("Select the desired projection of "
|
||||
"vector maps (IMG, Mapsforge and ENC maps). The projection must be valid "
|
||||
"for the whole map area."));
|
||||
|
||||
_hidpi = new QRadioButton(tr("High-resolution"));
|
||||
_lodpi = new QRadioButton(tr("Standard"));
|
||||
|
@ -1,21 +1,16 @@
|
||||
#include "map/pcs.h"
|
||||
#include "projectioncombobox.h"
|
||||
|
||||
ProjectionComboBox::ProjectionComboBox(QWidget *parent) : QComboBox(parent)
|
||||
ProjectionComboBox::ProjectionComboBox(const QList<KV<int, QString> > &list,
|
||||
QWidget *parent) : QComboBox(parent)
|
||||
{
|
||||
setSizeAdjustPolicy(AdjustToMinimumContentsLengthWithIcon);
|
||||
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
|
||||
|
||||
int last = -1;
|
||||
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
|
||||
std::sort(projections.begin(), projections.end());
|
||||
for (int i = 0; i < projections.size(); i++) {
|
||||
const KV<int, QString> &proj = projections.at(i);
|
||||
// There may be duplicit EPSG codes with different names
|
||||
if (proj.key() == last)
|
||||
continue;
|
||||
else
|
||||
last = proj.key();
|
||||
QList<KV<int, QString> > projs(list);
|
||||
std::sort(projs.begin(), projs.end());
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
const KV<int, QString> &proj = projs.at(i);
|
||||
QString text = QString::number(proj.key()) + " - " + proj.value();
|
||||
addItem(text, QVariant(proj.key()));
|
||||
}
|
||||
|
@ -2,11 +2,13 @@
|
||||
#define PROJECTIONCOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QList>
|
||||
#include "common/kv.h"
|
||||
|
||||
class ProjectionComboBox : public QComboBox
|
||||
{
|
||||
public:
|
||||
ProjectionComboBox(QWidget *parent = 0);
|
||||
ProjectionComboBox(const QList<KV<int, QString> > &list, QWidget *parent = 0);
|
||||
};
|
||||
|
||||
#endif // PROJECTIONCOMBOBOX_H
|
||||
|
@ -256,7 +256,7 @@ SETTING(printMovingTime, "printMovingTime", false );
|
||||
SETTING(printItemCount, "printItemCount", true );
|
||||
SETTING(separateGraphPage, "separateGraphPage", false );
|
||||
SETTING(sliderColor, "sliderColor", QColor(Qt::red) );
|
||||
SETTING(outputProjection, "outputProjection", 3857 );
|
||||
SETTING(outputProjection, "outputProjection", 3856 );
|
||||
SETTING(inputProjection, "inputProjection", 4326 );
|
||||
SETTING(hidpiMap, "HiDPIMap", true );
|
||||
SETTING(poiPath, "poiPath", "" );
|
||||
|
@ -13,7 +13,8 @@
|
||||
#define STYLE_DIR "style"
|
||||
#define SYMBOLS_DIR "symbols"
|
||||
|
||||
#define ELLIPSOID_FILE "ellipsoids.csv"
|
||||
#define ELLIPSOIDS_FILE "ellipsoids.csv"
|
||||
#define PROJECTIONS_FILE "projections.csv"
|
||||
#define GCS_FILE "gcs.csv"
|
||||
#define PCS_FILE "pcs.csv"
|
||||
#define TYP_FILE "style.typ"
|
||||
@ -131,7 +132,7 @@ QString ProgramPaths::translationsDir()
|
||||
|
||||
QString ProgramPaths::ellipsoidsFile()
|
||||
{
|
||||
return QDir(csvDir()).filePath(ELLIPSOID_FILE);
|
||||
return QDir(csvDir()).filePath(ELLIPSOIDS_FILE);
|
||||
}
|
||||
|
||||
QString ProgramPaths::gcsFile()
|
||||
@ -139,6 +140,11 @@ QString ProgramPaths::gcsFile()
|
||||
return QDir(csvDir()).filePath(GCS_FILE);
|
||||
}
|
||||
|
||||
QString ProgramPaths::projectionsFile()
|
||||
{
|
||||
return QDir(csvDir()).filePath(PROJECTIONS_FILE);
|
||||
}
|
||||
|
||||
QString ProgramPaths::pcsFile()
|
||||
{
|
||||
return QDir(csvDir()).filePath(PCS_FILE);
|
||||
|
@ -15,6 +15,7 @@ namespace ProgramPaths
|
||||
QString translationsDir();
|
||||
QString ellipsoidsFile();
|
||||
QString gcsFile();
|
||||
QString projectionsFile();
|
||||
QString pcsFile();
|
||||
QString typFile();
|
||||
QString renderthemeFile();
|
||||
|
@ -304,20 +304,20 @@ bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
||||
|
||||
if (!proj.compare("MERCATOR", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, c.lon(), NAN, 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9804, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9804, setup, 9001));
|
||||
} else if (!proj.compare("TRANSVERSE MERCATOR", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[1], params[2], 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9807, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, setup, 9001));
|
||||
} else if (!proj.compare("UNIVERSAL TRANSVERSE MERCATOR",
|
||||
Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], 0.9996, 500000, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9807, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, setup, 9001));
|
||||
} else if (!proj.compare("LAMBERT CONFORMAL CONIC", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], NAN, 0, 0, params[2], params[3]);
|
||||
pcs = PCS(gcs, 9802, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, setup, 9001));
|
||||
} else if (!proj.compare("POLYCONIC", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], NAN, 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9818, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9818, setup, 9001));
|
||||
} else {
|
||||
_errorString = proj + ": Unknown/missing projection";
|
||||
return false;
|
||||
|
203
src/map/conversion.cpp
Normal file
203
src/map/conversion.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
#include <QFile>
|
||||
#include "conversion.h"
|
||||
|
||||
static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
{
|
||||
switch (key) {
|
||||
case 8801:
|
||||
case 8811:
|
||||
case 8821:
|
||||
case 8832:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setLatitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8802:
|
||||
case 8812:
|
||||
case 8822:
|
||||
case 8833:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setLongitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8805:
|
||||
case 8815:
|
||||
case 8819:
|
||||
setup.setScale(val);
|
||||
return true;
|
||||
case 8806:
|
||||
case 8816:
|
||||
case 8826:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
return false;
|
||||
setup.setFalseEasting(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8807:
|
||||
case 8817:
|
||||
case 8827:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
return false;
|
||||
setup.setFalseNorthing(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8813:
|
||||
case 8818:
|
||||
case 8823:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setStandardParallel1(au.toDegrees(val));}
|
||||
return true;
|
||||
case 1036:
|
||||
case 8814:
|
||||
case 8824:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setStandardParallel2(au.toDegrees(val));}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int projectionSetup(const QList<QByteArray> &list,
|
||||
Projection::Setup &setup)
|
||||
{
|
||||
bool r1, r2, r3;
|
||||
|
||||
for (int i = 5; i < 26; i += 3) {
|
||||
QString ks = list[i].trimmed();
|
||||
if (ks.isEmpty())
|
||||
break;
|
||||
|
||||
int key = ks.toInt(&r1);
|
||||
double val = list[i+1].trimmed().toDouble(&r2);
|
||||
int un = list[i+2].trimmed().toInt(&r3);
|
||||
if (!r1 || !r2 || !r3)
|
||||
return (i - 5)/3 + 1;
|
||||
|
||||
if (!parameter(key, val, un, setup))
|
||||
return (i - 5)/3 + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QMap<int, Conversion::Entry> Conversion::_conversions = defaults();
|
||||
|
||||
QMap<int, Conversion::Entry> Conversion::defaults()
|
||||
{
|
||||
QMap<int, Conversion::Entry> map;
|
||||
map.insert(3856, Entry("Popular Visualisation Pseudo-Mercator", 1024,
|
||||
Projection::Setup(), 9001, 4400));
|
||||
return map;
|
||||
}
|
||||
|
||||
Conversion Conversion::conversion(int id)
|
||||
{
|
||||
QMap<int, Entry>::const_iterator it = _conversions.find(id);
|
||||
|
||||
if (it == _conversions.constEnd())
|
||||
return Conversion();
|
||||
else {
|
||||
const Entry &e = it.value();
|
||||
return Conversion(e.method(), e.setup(), e.units(), e.cs());
|
||||
}
|
||||
}
|
||||
|
||||
void Conversion::loadList(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
bool res;
|
||||
int ln = 0, pn;
|
||||
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qWarning("Error opening projections file: %s: %s", qPrintable(path),
|
||||
qPrintable(file.errorString()));
|
||||
return;
|
||||
}
|
||||
|
||||
while (!file.atEnd()) {
|
||||
ln++;
|
||||
|
||||
QByteArray line = file.readLine(4096);
|
||||
QList<QByteArray> list = line.split(',');
|
||||
if (list.size() != 26) {
|
||||
qWarning("%s:%d: Format error", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
QString name(list.at(0).trimmed());
|
||||
int proj = list.at(1).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid projection code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int units = list.at(2).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int transform = list.at(3).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid coordinate transformation code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int cs = list.at(4).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid coordinate system code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!LinearUnits(units).isValid()) {
|
||||
qWarning("%s:%d: Unknown linear units code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
if (!Projection::Method(transform).isValid()) {
|
||||
qWarning("%s:%d: Unknown coordinate transformation code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
if (!CoordinateSystem(cs).isValid()) {
|
||||
qWarning("%s:%d: Unknown coordinate system code", qPrintable(path),
|
||||
ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
Projection::Setup setup;
|
||||
if ((pn = projectionSetup(list, setup))) {
|
||||
qWarning("%s: %d: Invalid projection parameter #%d",
|
||||
qPrintable(path), ln, pn);
|
||||
continue;
|
||||
}
|
||||
|
||||
_conversions.insert(proj, Entry(name, transform, setup, units, cs));
|
||||
}
|
||||
}
|
||||
|
||||
QList<KV<int, QString> > Conversion::list()
|
||||
{
|
||||
QList<KV<int, QString> > list;
|
||||
|
||||
for (QMap<int, Entry>::const_iterator it = _conversions.constBegin();
|
||||
it != _conversions.constEnd(); ++it)
|
||||
list.append(KV<int, QString>(it.key(), it.value().name()));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Conversion &conversion)
|
||||
{
|
||||
dbg.nospace() << "Conversion(" << conversion.method() << ", "
|
||||
<< conversion.units() << ", " << conversion.setup() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
71
src/map/conversion.h
Normal file
71
src/map/conversion.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef CONVERSION_H
|
||||
#define CONVERSION_H
|
||||
|
||||
#include "projection.h"
|
||||
|
||||
class Conversion {
|
||||
public:
|
||||
Conversion() {}
|
||||
Conversion(const Projection::Method &method,
|
||||
const Projection::Setup &setup, const LinearUnits &units,
|
||||
const CoordinateSystem &cs = CoordinateSystem()) : _method(method),
|
||||
_setup(setup), _units(units), _cs(cs) {}
|
||||
|
||||
const Projection::Method &method() const {return _method;}
|
||||
const Projection::Setup &setup() const {return _setup;}
|
||||
const LinearUnits &units() const {return _units;}
|
||||
const CoordinateSystem &cs() const {return _cs;}
|
||||
|
||||
bool isNull() const {
|
||||
return (_units.isNull() && _method.isNull() && _setup.isNull()
|
||||
&& _cs.isNull());
|
||||
}
|
||||
bool isValid() const {
|
||||
/* We do not check the CoordinateSystem here as it is not always defined
|
||||
and except of WMTS/WMS it is not needed. The projection setup is
|
||||
always valid as we do not have any checks for it. */
|
||||
return (_units.isValid() && _method.isValid());
|
||||
}
|
||||
|
||||
static void loadList(const QString &path);
|
||||
static Conversion conversion(int id);
|
||||
static QList<KV<int, QString> > list();
|
||||
|
||||
private:
|
||||
class Entry {
|
||||
public:
|
||||
Entry(const QString &name, const Projection::Method &method,
|
||||
const Projection::Setup &setup, const LinearUnits &units,
|
||||
const CoordinateSystem &cs = CoordinateSystem())
|
||||
: _name(name), _method(method), _setup(setup), _units(units),
|
||||
_cs(cs) {}
|
||||
|
||||
const QString &name() const {return _name;}
|
||||
const Projection::Method &method() const {return _method;}
|
||||
const Projection::Setup &setup() const {return _setup;}
|
||||
const LinearUnits &units() const {return _units;}
|
||||
const CoordinateSystem &cs() const {return _cs;}
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
Projection::Method _method;
|
||||
Projection::Setup _setup;
|
||||
LinearUnits _units;
|
||||
CoordinateSystem _cs;
|
||||
};
|
||||
|
||||
static QMap<int, Entry> defaults();
|
||||
|
||||
Projection::Method _method;
|
||||
Projection::Setup _setup;
|
||||
LinearUnits _units;
|
||||
CoordinateSystem _cs;
|
||||
|
||||
static QMap<int, Entry> _conversions;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Conversion &conversion);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // CONVERSION_H
|
@ -58,9 +58,24 @@ Projection CRS::projection(int id)
|
||||
if (!pcs.isNull())
|
||||
return Projection(pcs);
|
||||
|
||||
// Geographic 2D projections
|
||||
GCS gcs(GCS::gcs(id));
|
||||
if (!gcs.isNull())
|
||||
return Projection(gcs);
|
||||
|
||||
return Projection();
|
||||
}
|
||||
|
||||
Projection CRS::projection(int gcsId, int projId)
|
||||
{
|
||||
Conversion proj(Conversion::conversion(projId));
|
||||
if (!proj.isNull())
|
||||
return Projection(PCS(GCS::gcs(gcsId), proj));
|
||||
|
||||
// Geographic 2D projections
|
||||
GCS gcs(GCS::gcs(projId));
|
||||
if (!gcs.isNull())
|
||||
return Projection(gcs);
|
||||
|
||||
return Projection();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ namespace CRS
|
||||
{
|
||||
Projection projection(const QString &crs);
|
||||
Projection projection(int id);
|
||||
Projection projection(int gcsId, int projId);
|
||||
}
|
||||
|
||||
#endif // CRS_H
|
||||
|
@ -52,17 +52,17 @@ void Ellipsoid::loadList(const QString &path)
|
||||
continue;
|
||||
}
|
||||
|
||||
int id = list[1].trimmed().toInt(&res);
|
||||
int id = list.at(1).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
double radius = list[2].trimmed().toDouble(&res);
|
||||
double radius = list.at(2).trimmed().toDouble(&res);
|
||||
if (!res) {
|
||||
qWarning("%s: %d: Invalid radius", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
double flattening = list[3].trimmed().toDouble(&res);
|
||||
double flattening = list.at(3).trimmed().toDouble(&res);
|
||||
if (!res) {
|
||||
qWarning("%s: %d: Invalid flattening", qPrintable(path), ln);
|
||||
continue;
|
||||
|
@ -227,7 +227,7 @@ void ENCMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
|
||||
void ENCMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (projection == _projection)
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
@ -235,11 +235,21 @@ QList<KV<int, QString> > GCS::list()
|
||||
{
|
||||
QList<KV<int, QString> > list;
|
||||
|
||||
for (int i = 0; i < _gcss.size(); i++)
|
||||
if (_gcss.at(i).id())
|
||||
list.append(KV<int, QString>(_gcss.at(i).id(), _gcss.at(i).name()
|
||||
+ " / Geographic 2D"));
|
||||
for (int i = 0; i < _gcss.size(); i++) {
|
||||
const Entry &e = _gcss.at(i);
|
||||
if (!e.id() || (i && e.id() == list.last().key()))
|
||||
continue;
|
||||
|
||||
list.append(KV<int, QString>(e.id(), e.name() + " / Geographic 2D"));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<KV<int, QString> > GCS::WGS84List()
|
||||
{
|
||||
QList<KV<int, QString> > list;
|
||||
list.append(KV<int, QString>(4326, "Geographic 2D"));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
|
||||
static void loadList(const QString &path);
|
||||
static QList<KV<int, QString> > list();
|
||||
static QList<KV<int, QString> > WGS84List();
|
||||
|
||||
private:
|
||||
class Entry;
|
||||
|
@ -370,14 +370,13 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
GCS gcs(geographicCS(kv));
|
||||
if (gcs.isNull())
|
||||
return false;
|
||||
PCS pcs(PCS::pcs(gcs, kv.value(ProjectionGeoKey).SHORT));
|
||||
if (pcs.isNull()) {
|
||||
Conversion c(Conversion::conversion(kv.value(ProjectionGeoKey).SHORT));
|
||||
if (c.isNull()) {
|
||||
_errorString = QString("%1: unknown projection code")
|
||||
.arg(kv.value(GeographicTypeGeoKey).SHORT)
|
||||
.arg(kv.value(ProjectionGeoKey).SHORT);
|
||||
return false;
|
||||
}
|
||||
_projection = Projection(pcs);
|
||||
_projection = Projection(PCS(gcs, c));
|
||||
} else {
|
||||
double lat0, lon0, scale, fe, fn, sp1, sp2;
|
||||
|
||||
@ -454,7 +453,7 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
fe = NAN;
|
||||
|
||||
Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2);
|
||||
_projection = Projection(PCS(gcs, method, setup, lu));
|
||||
_projection = Projection(PCS(gcs, Conversion(method, setup, lu)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -270,7 +270,7 @@ void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
|
||||
void IMGMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (projection == _projection)
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
@ -269,7 +269,7 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
|
||||
void JNXMap::setInputProjection(const Projection &projection)
|
||||
{
|
||||
if (projection == _projection)
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
@ -471,7 +471,7 @@ void KMZMap::unload()
|
||||
|
||||
void KMZMap::setInputProjection(const Projection &projection)
|
||||
{
|
||||
if (projection == _projection)
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
@ -175,51 +175,51 @@ bool MapFile::createProjection(const QString &datum, const QString &name,
|
||||
_projection = Projection(gcs);
|
||||
return true;
|
||||
} else if (name == "Mercator")
|
||||
pcs = PCS(gcs, 1024, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(1024, setup, 9001));
|
||||
else if (name == "Transverse Mercator"
|
||||
|| name == "(UTM) Universal Transverse Mercator")
|
||||
pcs = PCS(gcs, 9807, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, setup, 9001));
|
||||
else if (name == "Lambert Conformal Conic")
|
||||
pcs = PCS(gcs, 9802, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, setup, 9001));
|
||||
else if (name == "Albers Equal Area")
|
||||
pcs = PCS(gcs, 9822, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9822, setup, 9001));
|
||||
else if (name == "(A)Lambert Azimuthual Equal Area")
|
||||
pcs = PCS(gcs, 9820, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9820, setup, 9001));
|
||||
else if (name == "Polyconic (American)")
|
||||
pcs = PCS(gcs, 9818, setup, 9001);
|
||||
pcs = PCS(gcs, Conversion(9818, setup, 9001));
|
||||
else if (name == "(NZTM2) New Zealand TM 2000")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, 1600000,
|
||||
10000000, NAN, NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 173.0, 0.9996,
|
||||
1600000, 10000000, NAN, NAN), 9001));
|
||||
else if (name == "(BNG) British National Grid")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, 400000,
|
||||
-100000, NAN, NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, Projection::Setup(49, -2, 0.999601,
|
||||
400000, -100000, NAN, NAN), 9001));
|
||||
else if (name == "(IG) Irish Grid")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(53.5, -8, 1.000035, 200000,
|
||||
250000, NAN, NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035,
|
||||
200000, 250000, NAN, NAN), 9001));
|
||||
else if (name == "(SG) Swedish Grid")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, 1500000, 0, NAN,
|
||||
NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 15.808278, 1,
|
||||
1500000, 0, NAN, NAN), 9001));
|
||||
else if (name == "(I) France Zone I")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(49.5, 2.337229, NAN, 600000,
|
||||
1200000, 48.598523, 50.395912), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(49.5, 2.337229, NAN,
|
||||
600000, 1200000, 48.598523, 50.395912), 9001));
|
||||
else if (name == "(II) France Zone II")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(46.8, 2.337229, NAN, 600000,
|
||||
2200000, 45.898919, 47.696014), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(46.8, 2.337229, NAN,
|
||||
600000, 2200000, 45.898919, 47.696014), 9001));
|
||||
else if (name == "(III) France Zone III")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(44.1, 2.337229, NAN, 600000,
|
||||
3200000, 43.199291, 44.996094), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(44.1, 2.337229, NAN,
|
||||
600000, 3200000, 43.199291, 44.996094), 9001));
|
||||
else if (name == "(IV) France Zone IV")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(42.165, 2.337229, NAN, 234.358,
|
||||
4185861.369, 41.560388, 42.767663), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(42.165, 2.337229, NAN,
|
||||
234.358, 4185861.369, 41.560388, 42.767663), 9001));
|
||||
else if (name == "(VICGRID) Victoria Australia")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 4500000,
|
||||
-36, -38), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN,
|
||||
2500000, 4500000, -36, -38), 9001));
|
||||
else if (name == "(VG94) VICGRID94 Victoria Australia")
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 2500000,
|
||||
-36, -38), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN,
|
||||
2500000, 2500000, -36, -38), 9001));
|
||||
else if (name == "(SUI) Swiss Grid")
|
||||
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0, 600000,
|
||||
200000, 90.0, 90.0), 9001);
|
||||
pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225,
|
||||
1.0, 600000, 200000, 90.0, 90.0), 9001));
|
||||
else {
|
||||
_errorString = QString("%1: Unknown map projection").arg(name);
|
||||
return false;
|
||||
|
@ -230,7 +230,7 @@ void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
|
||||
void MapsforgeMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (projection == _projection)
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
@ -178,28 +178,28 @@ static Projection createProjection(const GCS &gcs, const QString &name)
|
||||
if (pl.first() == "Latitude/Longitude")
|
||||
return Projection(gcs);
|
||||
else if (pl.first() == "UTM")
|
||||
pcs = PCS(gcs, 9807, utm2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, utm2setup(pl), 9001));
|
||||
else if (pl.first() == "Mercator")
|
||||
pcs = PCS(gcs, 1024, Projection::Setup(), 9001);
|
||||
pcs = PCS(gcs, Conversion(1024, Projection::Setup(), 9001));
|
||||
else if (pl.first() == "Mercator Ellipsoidal")
|
||||
pcs = PCS(gcs, 9804, mercator2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9804, mercator2setup(pl), 9001));
|
||||
else if (pl.first() == "Transverse Mercator")
|
||||
pcs = PCS(gcs, 9807, tm2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, tm2setup(pl), 9001));
|
||||
else if (pl.first() == "Lambert Conformal Conic")
|
||||
pcs = PCS(gcs, 9802, lcc2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9802, lcc2setup(pl), 9001));
|
||||
else if (pl.first() == "(A)Lambert Azimuthual Equal Area")
|
||||
pcs = PCS(gcs, 9820, laea2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9820, laea2setup(pl), 9001));
|
||||
else if (pl.first() == "Polyconic (American)")
|
||||
pcs = PCS(gcs, 9818, polyconic2setup(pl), 9001);
|
||||
pcs = PCS(gcs, Conversion(9818, polyconic2setup(pl), 9001));
|
||||
else if (pl.first() == "(IG) Irish Grid")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(53.5, -8, 1.000035, 200000,
|
||||
250000, NAN, NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035,
|
||||
200000, 250000, NAN, NAN), 9001));
|
||||
else if (pl.first() == "(SUI) Swiss Grid")
|
||||
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0, 600000,
|
||||
200000, 90.0, 90.0), 9001);
|
||||
pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225,
|
||||
1.0, 600000, 200000, 90.0, 90.0), 9001));
|
||||
else if (pl.first() == "Rijksdriehoeksmeting")
|
||||
pcs = PCS(gcs, 9809, Projection::Setup(52.1561605555556,
|
||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001);
|
||||
pcs = PCS(gcs, Conversion(9809, Projection::Setup(52.1561605555556,
|
||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001));
|
||||
else
|
||||
return Projection();
|
||||
|
||||
|
195
src/map/pcs.cpp
195
src/map/pcs.cpp
@ -2,145 +2,32 @@
|
||||
#include "angularunits.h"
|
||||
#include "pcs.h"
|
||||
|
||||
QMap<int, PCS::Entry> PCS::_pcss = defaults();
|
||||
|
||||
class PCS::Entry {
|
||||
public:
|
||||
Entry(const QString &name, int id, int proj, const PCS &pcs)
|
||||
: _name(name), _id(id), _proj(proj), _pcs(pcs) {}
|
||||
|
||||
const QString &name() const {return _name;}
|
||||
int id() const {return _id;}
|
||||
int proj() const {return _proj;}
|
||||
const PCS &pcs() const {return _pcs;}
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
int _id, _proj;
|
||||
PCS _pcs;
|
||||
};
|
||||
|
||||
QList<PCS::Entry> PCS::_pcss = defaults();
|
||||
|
||||
QList<PCS::Entry> PCS::defaults()
|
||||
QMap<int, PCS::Entry> PCS::defaults()
|
||||
{
|
||||
QList<PCS::Entry> list;
|
||||
list.append(PCS::Entry("WGS 84 / Pseudo-Mercator", 3857, 3856,
|
||||
PCS(GCS::WGS84(), 1024, Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN),
|
||||
9001, 4499)));
|
||||
return list;
|
||||
QMap<int, Entry> map;
|
||||
map.insert(3857, Entry("WGS 84 / Pseudo-Mercator", 4326, 3856));
|
||||
return map;
|
||||
}
|
||||
|
||||
static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
{
|
||||
switch (key) {
|
||||
case 8801:
|
||||
case 8811:
|
||||
case 8821:
|
||||
case 8832:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setLatitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8802:
|
||||
case 8812:
|
||||
case 8822:
|
||||
case 8833:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setLongitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8805:
|
||||
case 8815:
|
||||
case 8819:
|
||||
setup.setScale(val);
|
||||
return true;
|
||||
case 8806:
|
||||
case 8816:
|
||||
case 8826:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
return false;
|
||||
setup.setFalseEasting(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8807:
|
||||
case 8817:
|
||||
case 8827:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
return false;
|
||||
setup.setFalseNorthing(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8813:
|
||||
case 8818:
|
||||
case 8823:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setStandardParallel1(au.toDegrees(val));}
|
||||
return true;
|
||||
case 1036:
|
||||
case 8814:
|
||||
case 8824:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setStandardParallel2(au.toDegrees(val));}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int projectionSetup(const QList<QByteArray> &list,
|
||||
Projection::Setup &setup)
|
||||
{
|
||||
bool r1, r2, r3;
|
||||
|
||||
for (int i = 7; i < 28; i += 3) {
|
||||
QString ks = list[i].trimmed();
|
||||
if (ks.isEmpty())
|
||||
break;
|
||||
|
||||
int key = ks.toInt(&r1);
|
||||
double val = list[i+1].trimmed().toDouble(&r2);
|
||||
int un = list[i+2].trimmed().toInt(&r3);
|
||||
if (!r1 || !r2 || !r3)
|
||||
return (i - 7)/3 + 1;
|
||||
|
||||
if (!parameter(key, val, un, setup))
|
||||
return (i - 7)/3 + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PCS PCS::pcs(int id)
|
||||
{
|
||||
for (int i = 0; i < _pcss.size(); i++)
|
||||
if (_pcss.at(i).id() == id)
|
||||
return _pcss.at(i).pcs();
|
||||
QMap<int, Entry>::const_iterator it = _pcss.find(id);
|
||||
|
||||
return PCS();
|
||||
}
|
||||
|
||||
PCS PCS::pcs(const GCS &gcs, int proj)
|
||||
{
|
||||
for (int i = 0; i < _pcss.size(); i++)
|
||||
if (_pcss.at(i).proj() == proj && _pcss.at(i).pcs().gcs() == gcs)
|
||||
return _pcss.at(i).pcs();
|
||||
|
||||
return PCS();
|
||||
if (it == _pcss.constEnd())
|
||||
return PCS();
|
||||
else {
|
||||
const Entry &e = it.value();
|
||||
return PCS(GCS::gcs(e.gcs()), Conversion::conversion(e.proj()));
|
||||
}
|
||||
}
|
||||
|
||||
void PCS::loadList(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
bool res;
|
||||
int ln = 0, pn;
|
||||
|
||||
int ln = 0;
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
|
||||
@ -153,7 +40,7 @@ void PCS::loadList(const QString &path)
|
||||
|
||||
QByteArray line = file.readLine(4096);
|
||||
QList<QByteArray> list = line.split(',');
|
||||
if (list.size() != 28) {
|
||||
if (list.size() != 4) {
|
||||
qWarning("%s:%d: Format error", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
@ -164,7 +51,7 @@ void PCS::loadList(const QString &path)
|
||||
qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int gcsid = list.at(2).trimmed().toInt(&res);
|
||||
int gcs = list.at(2).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
|
||||
continue;
|
||||
@ -174,53 +61,13 @@ void PCS::loadList(const QString &path)
|
||||
qWarning("%s:%d: Invalid projection code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int units = list.at(4).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int transform = list.at(5).trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid coordinate transformation code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
int cs = list[6].trimmed().toInt(&res);
|
||||
if (!res) {
|
||||
qWarning("%s:%d: Invalid coordinate system code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!LinearUnits(units).isValid()) {
|
||||
qWarning("%s:%d: Unknown linear units code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
if (!Projection::Method(transform).isValid()) {
|
||||
qWarning("%s:%d: Unknown coordinate transformation code",
|
||||
qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
if (!CoordinateSystem(cs).isValid()) {
|
||||
qWarning("%s:%d: Unknown coordinate system code", qPrintable(path),
|
||||
ln);
|
||||
continue;
|
||||
}
|
||||
GCS gcs(GCS::gcs(gcsid));
|
||||
if (gcs.isNull()) {
|
||||
if (GCS::gcs(gcs).isNull()) {
|
||||
qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
Projection::Setup setup;
|
||||
if ((pn = projectionSetup(list, setup))) {
|
||||
qWarning("%s: %d: Invalid projection parameter #%d",
|
||||
qPrintable(path), ln, pn);
|
||||
continue;
|
||||
}
|
||||
|
||||
PCS pcs(gcs, transform, setup, units, cs);
|
||||
_pcss.append(Entry(name, id, proj, pcs));
|
||||
_pcss.insert(id, Entry(name, gcs, proj));
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,8 +75,9 @@ QList<KV<int, QString> > PCS::list()
|
||||
{
|
||||
QList<KV<int, QString> > list;
|
||||
|
||||
for (int i = 0; i < _pcss.size(); i++)
|
||||
list.append(KV<int, QString>(_pcss.at(i).id(), _pcss.at(i).name()));
|
||||
for (QMap<int, Entry>::const_iterator it = _pcss.constBegin();
|
||||
it != _pcss.constEnd(); ++it)
|
||||
list.append(KV<int, QString>(it.key(), it.value().name()));
|
||||
|
||||
return list;
|
||||
}
|
||||
@ -237,8 +85,7 @@ QList<KV<int, QString> > PCS::list()
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PCS &pcs)
|
||||
{
|
||||
dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.method() << ", "
|
||||
<< pcs.units() << ", " << pcs.setup() << ")";
|
||||
dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.conversion() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -2,56 +2,51 @@
|
||||
#define PCS_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include "common/kv.h"
|
||||
#include "gcs.h"
|
||||
#include "linearunits.h"
|
||||
#include "coordinatesystem.h"
|
||||
#include "projection.h"
|
||||
#include "conversion.h"
|
||||
|
||||
class PCS
|
||||
{
|
||||
public:
|
||||
PCS() {}
|
||||
PCS(const GCS &gcs, const Projection::Method &method,
|
||||
const Projection::Setup &setup, const LinearUnits &units,
|
||||
const CoordinateSystem &cs = CoordinateSystem())
|
||||
: _gcs(gcs), _method(method), _setup(setup), _units(units), _cs(cs) {}
|
||||
PCS(const GCS &gcs, int proj);
|
||||
PCS(const GCS &gcs, const Conversion &conversion)
|
||||
: _gcs(gcs), _conversion(conversion) {}
|
||||
|
||||
const GCS &gcs() const {return _gcs;}
|
||||
const Projection::Method &method() const {return _method;}
|
||||
const Projection::Setup &setup() const {return _setup;}
|
||||
const LinearUnits &units() const {return _units;}
|
||||
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
||||
const Conversion &conversion() const {return _conversion;}
|
||||
|
||||
bool isNull() const {
|
||||
return (_gcs.isNull() && _units.isNull() && _method.isNull()
|
||||
&& _setup.isNull() && _cs.isNull());
|
||||
}
|
||||
bool isValid() const {
|
||||
// We do not check the CoordinateSystem here as it is not always defined
|
||||
// and except of WMTS/WMS it is not needed.
|
||||
return (_gcs.isValid() && _units.isValid() && _method.isValid());
|
||||
}
|
||||
bool isNull() const {return (_gcs.isNull() && _conversion.isNull());}
|
||||
bool isValid() const {return (_gcs.isValid() && _conversion.isValid());}
|
||||
|
||||
static void loadList(const QString &path);
|
||||
static PCS pcs(int id);
|
||||
static PCS pcs(const GCS &gcs, int proj);
|
||||
static QList<KV<int, QString> > list();
|
||||
|
||||
private:
|
||||
class Entry;
|
||||
class Entry {
|
||||
public:
|
||||
Entry(const QString &name, int gcs, int proj)
|
||||
: _name(name), _gcs(gcs), _proj(proj) {}
|
||||
|
||||
static QList<Entry> defaults();
|
||||
const QString &name() const {return _name;}
|
||||
int proj() const {return _proj;}
|
||||
int gcs() const {return _gcs;}
|
||||
|
||||
private:
|
||||
QString _name;
|
||||
int _gcs, _proj;
|
||||
};
|
||||
|
||||
static QMap<int, Entry> defaults();
|
||||
|
||||
GCS _gcs;
|
||||
Projection::Method _method;
|
||||
Projection::Setup _setup;
|
||||
LinearUnits _units;
|
||||
CoordinateSystem _cs;
|
||||
Conversion _conversion;
|
||||
|
||||
static QList<Entry> _pcss;
|
||||
static QMap<int, Entry> _pcss;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
|
@ -537,7 +537,7 @@ void PRJFile::projectedCS(CTX &ctx, PCS *pcs)
|
||||
optProjectedCS(ctx, &epsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*pcs = (epsg > 0) ? PCS::pcs(epsg) : PCS(gcs, method, setup, lu);
|
||||
*pcs = (epsg > 0) ? PCS::pcs(epsg) : PCS(gcs, Conversion(method, setup, lu));
|
||||
}
|
||||
|
||||
void PRJFile::axisType(CTX &ctx)
|
||||
|
@ -39,13 +39,13 @@ Projection::Method::Method(int id)
|
||||
}
|
||||
|
||||
Projection::Projection(const PCS &pcs)
|
||||
: _gcs(pcs.gcs()), _ct(0), _units(pcs.units()), _cs(pcs.coordinateSystem()),
|
||||
_geographic(false)
|
||||
: _gcs(pcs.gcs()), _ct(0), _units(pcs.conversion().units()),
|
||||
_cs(pcs.conversion().cs()), _geographic(false)
|
||||
{
|
||||
const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid();
|
||||
const Projection::Setup &setup = pcs.setup();
|
||||
const Projection::Setup &setup = pcs.conversion().setup();
|
||||
|
||||
switch (pcs.method().id()) {
|
||||
switch (pcs.conversion().method().id()) {
|
||||
case 1024:
|
||||
_ct = new WebMercator();
|
||||
break;
|
||||
|
@ -37,7 +37,7 @@ static CalibrationPoint parseCalibrationPoint(const QString &str)
|
||||
|
||||
static Projection parseProjection(const QString &str, const GCS &gcs)
|
||||
{
|
||||
QStringList fields(str.split(","));
|
||||
QStringList fields(str.split(','));
|
||||
if (fields.isEmpty())
|
||||
return Projection();
|
||||
bool ret;
|
||||
@ -55,40 +55,42 @@ static Projection parseProjection(const QString &str, const GCS &gcs)
|
||||
return Projection();
|
||||
if (fields.at(3) == "S")
|
||||
zone = -zone;
|
||||
return Projection(PCS(gcs, 9807, UTM::setup(zone), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9807, UTM::setup(zone), 9001)));
|
||||
case 1: // LatLon
|
||||
return Projection(gcs);
|
||||
case 2: // Mercator
|
||||
return Projection(PCS(gcs, 1024, Projection::Setup(), 9001));
|
||||
return Projection(PCS(gcs, Conversion(1024, Projection::Setup(),
|
||||
9001)));
|
||||
case 3: // Transversal Mercator
|
||||
if (fields.size() < 7)
|
||||
return Projection();
|
||||
return Projection(PCS(gcs, 9807, Projection::Setup(
|
||||
return Projection(PCS(gcs, Conversion(9807, Projection::Setup(
|
||||
fields.at(3).toDouble(), fields.at(2).toDouble(),
|
||||
fields.at(6).toDouble(), fields.at(5).toDouble(),
|
||||
fields.at(4).toDouble(), NAN, NAN), 9001));
|
||||
fields.at(4).toDouble(), NAN, NAN), 9001)));
|
||||
case 4: // Lambert 2SP
|
||||
if (fields.size() < 8)
|
||||
return Projection();
|
||||
return Projection(PCS(gcs, 9802, Projection::Setup(
|
||||
return Projection(PCS(gcs, Conversion(9802, Projection::Setup(
|
||||
fields.at(4).toDouble(), fields.at(5).toDouble(), NAN,
|
||||
fields.at(6).toDouble(), fields.at(7).toDouble(),
|
||||
fields.at(3).toDouble(), fields.at(2).toDouble()), 9001));
|
||||
fields.at(3).toDouble(), fields.at(2).toDouble()), 9001)));
|
||||
case 6: // BGN (British National Grid)
|
||||
return Projection(PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601,
|
||||
400000, -100000, NAN, NAN), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9807, Projection::Setup(49,
|
||||
-2, 0.999601, 400000, -100000, NAN, NAN), 9001)));
|
||||
case 12: // France Lambert II etendu
|
||||
return Projection(PCS(gcs, 9801, Projection::Setup(52, 0,
|
||||
0.99987742, 600000, 2200000, NAN, NAN), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9801, Projection::Setup(52, 0,
|
||||
0.99987742, 600000, 2200000, NAN, NAN), 9001)));
|
||||
case 14: // Swiss Grid
|
||||
return Projection(PCS(gcs, 9815, Projection::Setup(46.570866,
|
||||
7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9815, Projection::Setup(
|
||||
46.570866, 7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001)));
|
||||
case 108: // Dutch RD grid
|
||||
return Projection(PCS(gcs, 9809, Projection::Setup(52.15616055555555,
|
||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9809, Projection::Setup(
|
||||
52.15616055555555, 5.38763888888889, 0.9999079, 155000, 463000,
|
||||
NAN, NAN), 9001)));
|
||||
case 184: // Swedish Grid
|
||||
return Projection(PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1,
|
||||
1500000, 0, NAN, NAN), 9001));
|
||||
return Projection(PCS(gcs, Conversion(9807, Projection::Setup(0,
|
||||
15.808278, 1, 1500000, 0, NAN, NAN), 9001)));
|
||||
default:
|
||||
return Projection();
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ void WorldFileMap::unload()
|
||||
|
||||
void WorldFileMap::setInputProjection(const Projection &projection)
|
||||
{
|
||||
if (_hasPRJ || projection == _projection)
|
||||
if (_hasPRJ || !projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
Loading…
Reference in New Issue
Block a user