1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-22 18:20:49 +01:00

Compare commits

..

3 Commits

Author SHA1 Message Date
fea1f61235 Localization update 2023-04-13 09:40:06 +02:00
4724d1deb5 Version++ 2023-04-13 09:03:20 +02:00
e5199f8648 Redesigned CRS logic (including CSV files structure) 2023-04-13 08:39:33 +02:00
54 changed files with 12583 additions and 10592 deletions

View File

@ -1,4 +1,4 @@
version: 12.4.{build} version: 13.0.{build}
configuration: configuration:
- Release - Release

File diff suppressed because it is too large Load Diff

1706
data/csv/projections.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 12.4 VERSION = 13.0
QT += core \ QT += core \
gui \ gui \
@ -125,6 +125,7 @@ HEADERS += src/common/config.h \
src/map/ENC/style.h \ src/map/ENC/style.h \
src/map/IMG/section.h \ src/map/IMG/section.h \
src/map/IMG/zoom.h \ src/map/IMG/zoom.h \
src/map/conversion.h \
src/map/encmap.h \ src/map/encmap.h \
src/map/ENC/iso8211.h \ src/map/ENC/iso8211.h \
src/map/gemfmap.h \ src/map/gemfmap.h \
@ -335,6 +336,7 @@ SOURCES += src/main.cpp \
src/map/ENC/mapdata.cpp \ src/map/ENC/mapdata.cpp \
src/map/ENC/rastertile.cpp \ src/map/ENC/rastertile.cpp \
src/map/ENC/style.cpp \ src/map/ENC/style.cpp \
src/map/conversion.cpp \
src/map/encmap.cpp \ src/map/encmap.cpp \
src/map/ENC/iso8211.cpp \ src/map/ENC/iso8211.cpp \
src/map/gemfmap.cpp \ src/map/gemfmap.cpp \

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "12.4" !define VERSION "13.0"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -17,6 +17,7 @@
#include "common/downloader.h" #include "common/downloader.h"
#include "map/ellipsoid.h" #include "map/ellipsoid.h"
#include "map/gcs.h" #include "map/gcs.h"
#include "map/conversion.h"
#include "map/pcs.h" #include "map/pcs.h"
#include "data/dem.h" #include "data/dem.h"
#include "data/waypoint.h" #include "data/waypoint.h"
@ -172,11 +173,21 @@ void App::loadDatums()
void App::loadPCSs() void App::loadPCSs()
{ {
QString projectionsFile(ProgramPaths::projectionsFile());
QString pcsFile(ProgramPaths::pcsFile()); QString pcsFile(ProgramPaths::pcsFile());
if (!QFileInfo::exists(projectionsFile)) {
qWarning("No projections file found.");
projectionsFile = QString();
}
if (!QFileInfo::exists(pcsFile)) { if (!QFileInfo::exists(pcsFile)) {
qWarning("No PCS file found."); qWarning("No PCS file found.");
qWarning("Maps based on a projection different from EPSG:3857 won't work."); pcsFile = QString();
} else }
if (!projectionsFile.isNull() && !pcsFile.isNull()) {
Conversion::loadList(projectionsFile);
PCS::loadList(pcsFile); PCS::loadList(pcsFile);
} else
qWarning("Maps based on a projection different from EPSG:3857 won't work.");
} }

View File

@ -2745,7 +2745,8 @@ void GUI::loadOptions()
_mapView->useOpenGL(true); _mapView->useOpenGL(true);
_mapView->setDevicePixelRatio(devicePixelRatioF(), _mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0); _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->setInputProjection(CRS::projection(_options.inputProjection));
_mapView->setTimeZone(_options.timeZone.zone()); _mapView->setTimeZone(_options.timeZone.zone());
_mapView->setPositionSource(_positionSource); _mapView->setPositionSource(_positionSource);
@ -2859,7 +2860,8 @@ void GUI::updateOptions(const Options &options)
_mapView->setDevicePixelRatio(devicePixelRatioF(), _mapView->setDevicePixelRatio(devicePixelRatioF(),
options.hidpiMap ? devicePixelRatioF() : 1.0); options.hidpiMap ? devicePixelRatioF() : 1.0);
if (options.outputProjection != _options.outputProjection) if (options.outputProjection != _options.outputProjection)
_mapView->setOutputProjection(CRS::projection(options.outputProjection)); _mapView->setOutputProjection(CRS::projection(4326,
options.outputProjection));
if (options.inputProjection != _options.inputProjection) if (options.inputProjection != _options.inputProjection)
_mapView->setInputProjection(CRS::projection(options.inputProjection)); _mapView->setInputProjection(CRS::projection(options.inputProjection));
if (options.timeZone != _options.timeZone) { if (options.timeZone != _options.timeZone) {

View File

@ -14,6 +14,7 @@
#include <QSysInfo> #include <QSysInfo>
#include <QButtonGroup> #include <QButtonGroup>
#include <QGeoPositionInfoSource> #include <QGeoPositionInfoSource>
#include "map/pcs.h"
#include "icons.h" #include "icons.h"
#include "infolabel.h" #include "infolabel.h"
#include "colorbox.h" #include "colorbox.h"
@ -52,18 +53,20 @@ void OptionsDialog::automaticPauseDetectionSet(bool set)
QWidget *OptionsDialog::createMapPage() QWidget *OptionsDialog::createMapPage()
{ {
_outputProjection = new ProjectionComboBox(); _outputProjection = new ProjectionComboBox(GCS::WGS84List()
+ Conversion::list());
_outputProjection->setCurrentIndex(_outputProjection->findData( _outputProjection->setCurrentIndex(_outputProjection->findData(
_options.outputProjection)); _options.outputProjection));
_inputProjection = new ProjectionComboBox(); _inputProjection = new ProjectionComboBox(GCS::list() + PCS::list());
_inputProjection->setCurrentIndex(_inputProjection->findData( _inputProjection->setCurrentIndex(_inputProjection->findData(
_options.inputProjection)); _options.inputProjection));
InfoLabel *inInfo = new InfoLabel(tr("Select the proper projection of maps" InfoLabel *inInfo = new InfoLabel(tr("Select the proper coordinate "
" without a projection definition (JNX, KMZ and world file maps).")); "reference system (CRS) of maps without a CRS definition "
InfoLabel *outInfo = new InfoLabel(tr("Select the desired projection of" "(JNX, KMZ and World file maps)."));
" vector maps (IMG and Mapsforge maps). The projection must be valid for" InfoLabel *outInfo = new InfoLabel(tr("Select the desired projection of "
" the whole map area.")); "vector maps (IMG, Mapsforge and ENC maps). The projection must be valid "
"for the whole map area."));
_hidpi = new QRadioButton(tr("High-resolution")); _hidpi = new QRadioButton(tr("High-resolution"));
_lodpi = new QRadioButton(tr("Standard")); _lodpi = new QRadioButton(tr("Standard"));

View File

@ -1,21 +1,16 @@
#include "map/pcs.h"
#include "projectioncombobox.h" #include "projectioncombobox.h"
ProjectionComboBox::ProjectionComboBox(QWidget *parent) : QComboBox(parent) ProjectionComboBox::ProjectionComboBox(const QList<KV<int, QString> > &list,
QWidget *parent) : QComboBox(parent)
{ {
setSizeAdjustPolicy(AdjustToMinimumContentsLengthWithIcon); setSizeAdjustPolicy(AdjustToMinimumContentsLengthWithIcon);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
int last = -1; QList<KV<int, QString> > projs(list);
QList<KV<int, QString> > projections(GCS::list() + PCS::list()); std::sort(projs.begin(), projs.end());
std::sort(projections.begin(), projections.end());
for (int i = 0; i < projections.size(); i++) { for (int i = 0; i < list.size(); i++) {
const KV<int, QString> &proj = projections.at(i); const KV<int, QString> &proj = projs.at(i);
// There may be duplicit EPSG codes with different names
if (proj.key() == last)
continue;
else
last = proj.key();
QString text = QString::number(proj.key()) + " - " + proj.value(); QString text = QString::number(proj.key()) + " - " + proj.value();
addItem(text, QVariant(proj.key())); addItem(text, QVariant(proj.key()));
} }

View File

@ -2,11 +2,13 @@
#define PROJECTIONCOMBOBOX_H #define PROJECTIONCOMBOBOX_H
#include <QComboBox> #include <QComboBox>
#include <QList>
#include "common/kv.h"
class ProjectionComboBox : public QComboBox class ProjectionComboBox : public QComboBox
{ {
public: public:
ProjectionComboBox(QWidget *parent = 0); ProjectionComboBox(const QList<KV<int, QString> > &list, QWidget *parent = 0);
}; };
#endif // PROJECTIONCOMBOBOX_H #endif // PROJECTIONCOMBOBOX_H

View File

@ -256,7 +256,7 @@ SETTING(printMovingTime, "printMovingTime", false );
SETTING(printItemCount, "printItemCount", true ); SETTING(printItemCount, "printItemCount", true );
SETTING(separateGraphPage, "separateGraphPage", false ); SETTING(separateGraphPage, "separateGraphPage", false );
SETTING(sliderColor, "sliderColor", QColor(Qt::red) ); SETTING(sliderColor, "sliderColor", QColor(Qt::red) );
SETTING(outputProjection, "outputProjection", 3857 ); SETTING(outputProjection, "outputProjection", 3856 );
SETTING(inputProjection, "inputProjection", 4326 ); SETTING(inputProjection, "inputProjection", 4326 );
SETTING(hidpiMap, "HiDPIMap", true ); SETTING(hidpiMap, "HiDPIMap", true );
SETTING(poiPath, "poiPath", "" ); SETTING(poiPath, "poiPath", "" );

View File

@ -13,7 +13,8 @@
#define STYLE_DIR "style" #define STYLE_DIR "style"
#define SYMBOLS_DIR "symbols" #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 GCS_FILE "gcs.csv"
#define PCS_FILE "pcs.csv" #define PCS_FILE "pcs.csv"
#define TYP_FILE "style.typ" #define TYP_FILE "style.typ"
@ -131,7 +132,7 @@ QString ProgramPaths::translationsDir()
QString ProgramPaths::ellipsoidsFile() QString ProgramPaths::ellipsoidsFile()
{ {
return QDir(csvDir()).filePath(ELLIPSOID_FILE); return QDir(csvDir()).filePath(ELLIPSOIDS_FILE);
} }
QString ProgramPaths::gcsFile() QString ProgramPaths::gcsFile()
@ -139,6 +140,11 @@ QString ProgramPaths::gcsFile()
return QDir(csvDir()).filePath(GCS_FILE); return QDir(csvDir()).filePath(GCS_FILE);
} }
QString ProgramPaths::projectionsFile()
{
return QDir(csvDir()).filePath(PROJECTIONS_FILE);
}
QString ProgramPaths::pcsFile() QString ProgramPaths::pcsFile()
{ {
return QDir(csvDir()).filePath(PCS_FILE); return QDir(csvDir()).filePath(PCS_FILE);

View File

@ -15,6 +15,7 @@ namespace ProgramPaths
QString translationsDir(); QString translationsDir();
QString ellipsoidsFile(); QString ellipsoidsFile();
QString gcsFile(); QString gcsFile();
QString projectionsFile();
QString pcsFile(); QString pcsFile();
QString typFile(); QString typFile();
QString renderthemeFile(); QString renderthemeFile();

View File

@ -304,20 +304,20 @@ bool BSBMap::createProjection(const QString &datum, const QString &proj,
if (!proj.compare("MERCATOR", Qt::CaseInsensitive)) { if (!proj.compare("MERCATOR", Qt::CaseInsensitive)) {
Projection::Setup setup(0, c.lon(), NAN, 0, 0, NAN, NAN); 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)) { } else if (!proj.compare("TRANSVERSE MERCATOR", Qt::CaseInsensitive)) {
Projection::Setup setup(0, params[1], params[2], 0, 0, NAN, NAN); 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", } else if (!proj.compare("UNIVERSAL TRANSVERSE MERCATOR",
Qt::CaseInsensitive)) { Qt::CaseInsensitive)) {
Projection::Setup setup(0, params[0], 0.9996, 500000, 0, NAN, NAN); 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)) { } else if (!proj.compare("LAMBERT CONFORMAL CONIC", Qt::CaseInsensitive)) {
Projection::Setup setup(0, params[0], NAN, 0, 0, params[2], params[3]); 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)) { } else if (!proj.compare("POLYCONIC", Qt::CaseInsensitive)) {
Projection::Setup setup(0, params[0], NAN, 0, 0, NAN, NAN); 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 { } else {
_errorString = proj + ": Unknown/missing projection"; _errorString = proj + ": Unknown/missing projection";
return false; return false;

203
src/map/conversion.cpp Normal file
View 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
View 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

View File

@ -58,9 +58,24 @@ Projection CRS::projection(int id)
if (!pcs.isNull()) if (!pcs.isNull())
return Projection(pcs); return Projection(pcs);
// Geographic 2D projections
GCS gcs(GCS::gcs(id)); GCS gcs(GCS::gcs(id));
if (!gcs.isNull()) if (!gcs.isNull())
return Projection(gcs); return Projection(gcs);
return Projection(); 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();
}

View File

@ -7,6 +7,7 @@ namespace CRS
{ {
Projection projection(const QString &crs); Projection projection(const QString &crs);
Projection projection(int id); Projection projection(int id);
Projection projection(int gcsId, int projId);
} }
#endif // CRS_H #endif // CRS_H

View File

@ -52,17 +52,17 @@ void Ellipsoid::loadList(const QString &path)
continue; continue;
} }
int id = list[1].trimmed().toInt(&res); int id = list.at(1).trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln); qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln);
continue; continue;
} }
double radius = list[2].trimmed().toDouble(&res); double radius = list.at(2).trimmed().toDouble(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid radius", qPrintable(path), ln); qWarning("%s: %d: Invalid radius", qPrintable(path), ln);
continue; continue;
} }
double flattening = list[3].trimmed().toDouble(&res); double flattening = list.at(3).trimmed().toDouble(&res);
if (!res) { if (!res) {
qWarning("%s: %d: Invalid flattening", qPrintable(path), ln); qWarning("%s: %d: Invalid flattening", qPrintable(path), ln);
continue; continue;

View File

@ -227,7 +227,7 @@ void ENCMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
void ENCMap::setOutputProjection(const Projection &projection) void ENCMap::setOutputProjection(const Projection &projection)
{ {
if (projection == _projection) if (!projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;

View File

@ -235,11 +235,21 @@ QList<KV<int, QString> > GCS::list()
{ {
QList<KV<int, QString> > list; QList<KV<int, QString> > list;
for (int i = 0; i < _gcss.size(); i++) for (int i = 0; i < _gcss.size(); i++) {
if (_gcss.at(i).id()) const Entry &e = _gcss.at(i);
list.append(KV<int, QString>(_gcss.at(i).id(), _gcss.at(i).name() if (!e.id() || (i && e.id() == list.last().key()))
+ " / Geographic 2D")); 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; return list;
} }

View File

@ -39,6 +39,7 @@ public:
static void loadList(const QString &path); static void loadList(const QString &path);
static QList<KV<int, QString> > list(); static QList<KV<int, QString> > list();
static QList<KV<int, QString> > WGS84List();
private: private:
class Entry; class Entry;

View File

@ -370,14 +370,13 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
GCS gcs(geographicCS(kv)); GCS gcs(geographicCS(kv));
if (gcs.isNull()) if (gcs.isNull())
return false; return false;
PCS pcs(PCS::pcs(gcs, kv.value(ProjectionGeoKey).SHORT)); Conversion c(Conversion::conversion(kv.value(ProjectionGeoKey).SHORT));
if (pcs.isNull()) { if (c.isNull()) {
_errorString = QString("%1: unknown projection code") _errorString = QString("%1: unknown projection code")
.arg(kv.value(GeographicTypeGeoKey).SHORT)
.arg(kv.value(ProjectionGeoKey).SHORT); .arg(kv.value(ProjectionGeoKey).SHORT);
return false; return false;
} }
_projection = Projection(pcs); _projection = Projection(PCS(gcs, c));
} else { } else {
double lat0, lon0, scale, fe, fn, sp1, sp2; double lat0, lon0, scale, fe, fn, sp1, sp2;
@ -454,7 +453,7 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
fe = NAN; fe = NAN;
Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2); 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; return true;

View File

@ -270,7 +270,7 @@ void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
void IMGMap::setOutputProjection(const Projection &projection) void IMGMap::setOutputProjection(const Projection &projection)
{ {
if (projection == _projection) if (!projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;

View File

@ -269,7 +269,7 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
void JNXMap::setInputProjection(const Projection &projection) void JNXMap::setInputProjection(const Projection &projection)
{ {
if (projection == _projection) if (!projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;

View File

@ -471,7 +471,7 @@ void KMZMap::unload()
void KMZMap::setInputProjection(const Projection &projection) void KMZMap::setInputProjection(const Projection &projection)
{ {
if (projection == _projection) if (!projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;

View File

@ -175,51 +175,51 @@ bool MapFile::createProjection(const QString &datum, const QString &name,
_projection = Projection(gcs); _projection = Projection(gcs);
return true; return true;
} else if (name == "Mercator") } else if (name == "Mercator")
pcs = PCS(gcs, 1024, setup, 9001); pcs = PCS(gcs, Conversion(1024, setup, 9001));
else if (name == "Transverse Mercator" else if (name == "Transverse Mercator"
|| name == "(UTM) Universal 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") 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") 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") 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)") 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") else if (name == "(NZTM2) New Zealand TM 2000")
pcs = PCS(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, 1600000, pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 173.0, 0.9996,
10000000, NAN, NAN), 9001); 1600000, 10000000, NAN, NAN), 9001));
else if (name == "(BNG) British National Grid") else if (name == "(BNG) British National Grid")
pcs = PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, 400000, pcs = PCS(gcs, Conversion(9807, Projection::Setup(49, -2, 0.999601,
-100000, NAN, NAN), 9001); 400000, -100000, NAN, NAN), 9001));
else if (name == "(IG) Irish Grid") else if (name == "(IG) Irish Grid")
pcs = PCS(gcs, 9807, Projection::Setup(53.5, -8, 1.000035, 200000, pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035,
250000, NAN, NAN), 9001); 200000, 250000, NAN, NAN), 9001));
else if (name == "(SG) Swedish Grid") else if (name == "(SG) Swedish Grid")
pcs = PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, 1500000, 0, NAN, pcs = PCS(gcs, Conversion(9807, Projection::Setup(0, 15.808278, 1,
NAN), 9001); 1500000, 0, NAN, NAN), 9001));
else if (name == "(I) France Zone I") else if (name == "(I) France Zone I")
pcs = PCS(gcs, 9802, Projection::Setup(49.5, 2.337229, NAN, 600000, pcs = PCS(gcs, Conversion(9802, Projection::Setup(49.5, 2.337229, NAN,
1200000, 48.598523, 50.395912), 9001); 600000, 1200000, 48.598523, 50.395912), 9001));
else if (name == "(II) France Zone II") else if (name == "(II) France Zone II")
pcs = PCS(gcs, 9802, Projection::Setup(46.8, 2.337229, NAN, 600000, pcs = PCS(gcs, Conversion(9802, Projection::Setup(46.8, 2.337229, NAN,
2200000, 45.898919, 47.696014), 9001); 600000, 2200000, 45.898919, 47.696014), 9001));
else if (name == "(III) France Zone III") else if (name == "(III) France Zone III")
pcs = PCS(gcs, 9802, Projection::Setup(44.1, 2.337229, NAN, 600000, pcs = PCS(gcs, Conversion(9802, Projection::Setup(44.1, 2.337229, NAN,
3200000, 43.199291, 44.996094), 9001); 600000, 3200000, 43.199291, 44.996094), 9001));
else if (name == "(IV) France Zone IV") else if (name == "(IV) France Zone IV")
pcs = PCS(gcs, 9802, Projection::Setup(42.165, 2.337229, NAN, 234.358, pcs = PCS(gcs, Conversion(9802, Projection::Setup(42.165, 2.337229, NAN,
4185861.369, 41.560388, 42.767663), 9001); 234.358, 4185861.369, 41.560388, 42.767663), 9001));
else if (name == "(VICGRID) Victoria Australia") else if (name == "(VICGRID) Victoria Australia")
pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 4500000, pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN,
-36, -38), 9001); 2500000, 4500000, -36, -38), 9001));
else if (name == "(VG94) VICGRID94 Victoria Australia") else if (name == "(VG94) VICGRID94 Victoria Australia")
pcs = PCS(gcs, 9802, Projection::Setup(-37, 145, NAN, 2500000, 2500000, pcs = PCS(gcs, Conversion(9802, Projection::Setup(-37, 145, NAN,
-36, -38), 9001); 2500000, 2500000, -36, -38), 9001));
else if (name == "(SUI) Swiss Grid") else if (name == "(SUI) Swiss Grid")
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0, 600000, pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225,
200000, 90.0, 90.0), 9001); 1.0, 600000, 200000, 90.0, 90.0), 9001));
else { else {
_errorString = QString("%1: Unknown map projection").arg(name); _errorString = QString("%1: Unknown map projection").arg(name);
return false; return false;

View File

@ -230,7 +230,7 @@ void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
void MapsforgeMap::setOutputProjection(const Projection &projection) void MapsforgeMap::setOutputProjection(const Projection &projection)
{ {
if (projection == _projection) if (!projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;

View File

@ -178,28 +178,28 @@ static Projection createProjection(const GCS &gcs, const QString &name)
if (pl.first() == "Latitude/Longitude") if (pl.first() == "Latitude/Longitude")
return Projection(gcs); return Projection(gcs);
else if (pl.first() == "UTM") 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") 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") 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") 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") 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") 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)") 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") else if (pl.first() == "(IG) Irish Grid")
pcs = PCS(gcs, 9807, Projection::Setup(53.5, -8, 1.000035, 200000, pcs = PCS(gcs, Conversion(9807, Projection::Setup(53.5, -8, 1.000035,
250000, NAN, NAN), 9001); 200000, 250000, NAN, NAN), 9001));
else if (pl.first() == "(SUI) Swiss Grid") else if (pl.first() == "(SUI) Swiss Grid")
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0, 600000, pcs = PCS(gcs, Conversion(9815, Projection::Setup(46.570866, 7.26225,
200000, 90.0, 90.0), 9001); 1.0, 600000, 200000, 90.0, 90.0), 9001));
else if (pl.first() == "Rijksdriehoeksmeting") else if (pl.first() == "Rijksdriehoeksmeting")
pcs = PCS(gcs, 9809, Projection::Setup(52.1561605555556, pcs = PCS(gcs, Conversion(9809, Projection::Setup(52.1561605555556,
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001); 5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001));
else else
return Projection(); return Projection();

View File

@ -2,145 +2,32 @@
#include "angularunits.h" #include "angularunits.h"
#include "pcs.h" #include "pcs.h"
QMap<int, PCS::Entry> PCS::_pcss = defaults();
class PCS::Entry { QMap<int, PCS::Entry> PCS::defaults()
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()
{ {
QList<PCS::Entry> list; QMap<int, Entry> map;
list.append(PCS::Entry("WGS 84 / Pseudo-Mercator", 3857, 3856, map.insert(3857, Entry("WGS 84 / Pseudo-Mercator", 4326, 3856));
PCS(GCS::WGS84(), 1024, Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN), return map;
9001, 4499)));
return list;
} }
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) PCS PCS::pcs(int id)
{ {
for (int i = 0; i < _pcss.size(); i++) QMap<int, Entry>::const_iterator it = _pcss.find(id);
if (_pcss.at(i).id() == id)
return _pcss.at(i).pcs();
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();
if (it == _pcss.constEnd())
return PCS(); return PCS();
else {
const Entry &e = it.value();
return PCS(GCS::gcs(e.gcs()), Conversion::conversion(e.proj()));
}
} }
void PCS::loadList(const QString &path) void PCS::loadList(const QString &path)
{ {
QFile file(path); QFile file(path);
bool res; bool res;
int ln = 0, pn; int ln = 0;
if (!file.open(QFile::ReadOnly)) { if (!file.open(QFile::ReadOnly)) {
qWarning("Error opening PCS file: %s: %s", qPrintable(path), qWarning("Error opening PCS file: %s: %s", qPrintable(path),
@ -153,7 +40,7 @@ void PCS::loadList(const QString &path)
QByteArray line = file.readLine(4096); QByteArray line = file.readLine(4096);
QList<QByteArray> list = line.split(','); QList<QByteArray> list = line.split(',');
if (list.size() != 28) { if (list.size() != 4) {
qWarning("%s:%d: Format error", qPrintable(path), ln); qWarning("%s:%d: Format error", qPrintable(path), ln);
continue; continue;
} }
@ -164,7 +51,7 @@ void PCS::loadList(const QString &path)
qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln); qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln);
continue; continue;
} }
int gcsid = list.at(2).trimmed().toInt(&res); int gcs = list.at(2).trimmed().toInt(&res);
if (!res) { if (!res) {
qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln); qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
continue; continue;
@ -174,53 +61,13 @@ void PCS::loadList(const QString &path)
qWarning("%s:%d: Invalid projection code", qPrintable(path), ln); qWarning("%s:%d: Invalid projection code", qPrintable(path), ln);
continue; 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()) { if (GCS::gcs(gcs).isNull()) {
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()) {
qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln); qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
continue; continue;
} }
Projection::Setup setup; _pcss.insert(id, Entry(name, gcs, proj));
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));
} }
} }
@ -228,8 +75,9 @@ QList<KV<int, QString> > PCS::list()
{ {
QList<KV<int, QString> > list; QList<KV<int, QString> > list;
for (int i = 0; i < _pcss.size(); i++) for (QMap<int, Entry>::const_iterator it = _pcss.constBegin();
list.append(KV<int, QString>(_pcss.at(i).id(), _pcss.at(i).name())); it != _pcss.constEnd(); ++it)
list.append(KV<int, QString>(it.key(), it.value().name()));
return list; return list;
} }
@ -237,8 +85,7 @@ QList<KV<int, QString> > PCS::list()
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const PCS &pcs) QDebug operator<<(QDebug dbg, const PCS &pcs)
{ {
dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.method() << ", " dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.conversion() << ")";
<< pcs.units() << ", " << pcs.setup() << ")";
return dbg.space(); return dbg.space();
} }
#endif // QT_NO_DEBUG #endif // QT_NO_DEBUG

View File

@ -2,56 +2,51 @@
#define PCS_H #define PCS_H
#include <QDebug> #include <QDebug>
#include <QList> #include <QMap>
#include "common/kv.h" #include "common/kv.h"
#include "gcs.h" #include "gcs.h"
#include "linearunits.h" #include "linearunits.h"
#include "coordinatesystem.h" #include "coordinatesystem.h"
#include "projection.h" #include "conversion.h"
class PCS class PCS
{ {
public: public:
PCS() {} PCS() {}
PCS(const GCS &gcs, const Projection::Method &method, PCS(const GCS &gcs, const Conversion &conversion)
const Projection::Setup &setup, const LinearUnits &units, : _gcs(gcs), _conversion(conversion) {}
const CoordinateSystem &cs = CoordinateSystem())
: _gcs(gcs), _method(method), _setup(setup), _units(units), _cs(cs) {}
PCS(const GCS &gcs, int proj);
const GCS &gcs() const {return _gcs;} const GCS &gcs() const {return _gcs;}
const Projection::Method &method() const {return _method;} const Conversion &conversion() const {return _conversion;}
const Projection::Setup &setup() const {return _setup;}
const LinearUnits &units() const {return _units;}
const CoordinateSystem &coordinateSystem() const {return _cs;}
bool isNull() const { bool isNull() const {return (_gcs.isNull() && _conversion.isNull());}
return (_gcs.isNull() && _units.isNull() && _method.isNull() bool isValid() const {return (_gcs.isValid() && _conversion.isValid());}
&& _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());
}
static void loadList(const QString &path); static void loadList(const QString &path);
static PCS pcs(int id); static PCS pcs(int id);
static PCS pcs(const GCS &gcs, int proj);
static QList<KV<int, QString> > list(); static QList<KV<int, QString> > list();
private: 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; GCS _gcs;
Projection::Method _method; Conversion _conversion;
Projection::Setup _setup;
LinearUnits _units;
CoordinateSystem _cs;
static QList<Entry> _pcss; static QMap<int, Entry> _pcss;
}; };
#ifndef QT_NO_DEBUG #ifndef QT_NO_DEBUG

View File

@ -537,7 +537,7 @@ void PRJFile::projectedCS(CTX &ctx, PCS *pcs)
optProjectedCS(ctx, &epsg); optProjectedCS(ctx, &epsg);
compare(ctx, RBRK); 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) void PRJFile::axisType(CTX &ctx)

View File

@ -39,13 +39,13 @@ Projection::Method::Method(int id)
} }
Projection::Projection(const PCS &pcs) Projection::Projection(const PCS &pcs)
: _gcs(pcs.gcs()), _ct(0), _units(pcs.units()), _cs(pcs.coordinateSystem()), : _gcs(pcs.gcs()), _ct(0), _units(pcs.conversion().units()),
_geographic(false) _cs(pcs.conversion().cs()), _geographic(false)
{ {
const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid(); 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: case 1024:
_ct = new WebMercator(); _ct = new WebMercator();
break; break;

View File

@ -37,7 +37,7 @@ static CalibrationPoint parseCalibrationPoint(const QString &str)
static Projection parseProjection(const QString &str, const GCS &gcs) static Projection parseProjection(const QString &str, const GCS &gcs)
{ {
QStringList fields(str.split(",")); QStringList fields(str.split(','));
if (fields.isEmpty()) if (fields.isEmpty())
return Projection(); return Projection();
bool ret; bool ret;
@ -55,40 +55,42 @@ static Projection parseProjection(const QString &str, const GCS &gcs)
return Projection(); return Projection();
if (fields.at(3) == "S") if (fields.at(3) == "S")
zone = -zone; zone = -zone;
return Projection(PCS(gcs, 9807, UTM::setup(zone), 9001)); return Projection(PCS(gcs, Conversion(9807, UTM::setup(zone), 9001)));
case 1: // LatLon case 1: // LatLon
return Projection(gcs); return Projection(gcs);
case 2: // Mercator case 2: // Mercator
return Projection(PCS(gcs, 1024, Projection::Setup(), 9001)); return Projection(PCS(gcs, Conversion(1024, Projection::Setup(),
9001)));
case 3: // Transversal Mercator case 3: // Transversal Mercator
if (fields.size() < 7) if (fields.size() < 7)
return Projection(); 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(3).toDouble(), fields.at(2).toDouble(),
fields.at(6).toDouble(), fields.at(5).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 case 4: // Lambert 2SP
if (fields.size() < 8) if (fields.size() < 8)
return Projection(); 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(4).toDouble(), fields.at(5).toDouble(), NAN,
fields.at(6).toDouble(), fields.at(7).toDouble(), 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) case 6: // BGN (British National Grid)
return Projection(PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, return Projection(PCS(gcs, Conversion(9807, Projection::Setup(49,
400000, -100000, NAN, NAN), 9001)); -2, 0.999601, 400000, -100000, NAN, NAN), 9001)));
case 12: // France Lambert II etendu case 12: // France Lambert II etendu
return Projection(PCS(gcs, 9801, Projection::Setup(52, 0, return Projection(PCS(gcs, Conversion(9801, Projection::Setup(52, 0,
0.99987742, 600000, 2200000, NAN, NAN), 9001)); 0.99987742, 600000, 2200000, NAN, NAN), 9001)));
case 14: // Swiss Grid case 14: // Swiss Grid
return Projection(PCS(gcs, 9815, Projection::Setup(46.570866, return Projection(PCS(gcs, Conversion(9815, Projection::Setup(
7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001)); 46.570866, 7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001)));
case 108: // Dutch RD grid case 108: // Dutch RD grid
return Projection(PCS(gcs, 9809, Projection::Setup(52.15616055555555, return Projection(PCS(gcs, Conversion(9809, Projection::Setup(
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001)); 52.15616055555555, 5.38763888888889, 0.9999079, 155000, 463000,
NAN, NAN), 9001)));
case 184: // Swedish Grid case 184: // Swedish Grid
return Projection(PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, return Projection(PCS(gcs, Conversion(9807, Projection::Setup(0,
1500000, 0, NAN, NAN), 9001)); 15.808278, 1, 1500000, 0, NAN, NAN), 9001)));
default: default:
return Projection(); return Projection();
} }

View File

@ -116,7 +116,7 @@ void WorldFileMap::unload()
void WorldFileMap::setInputProjection(const Projection &projection) void WorldFileMap::setInputProjection(const Projection &projection)
{ {
if (_hasPRJ || projection == _projection) if (_hasPRJ || !projection.isValid() || projection == _projection)
return; return;
_projection = projection; _projection = projection;