mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-12-05 00:39:09 +01:00
Compare commits
3 Commits
aec052edaf
...
fea1f61235
Author | SHA1 | Date | |
---|---|---|---|
fea1f61235 | |||
4724d1deb5 | |||
e5199f8648 |
@ -1,4 +1,4 @@
|
||||
version: 12.4.{build}
|
||||
version: 13.0.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
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
@ -3,7 +3,7 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 12.4
|
||||
VERSION = 13.0
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -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 \
|
||||
|
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
@ -37,7 +37,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "12.4"
|
||||
!define VERSION "13.0"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -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