mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added support for world file maps
This commit is contained in:
parent
4ada19b4bf
commit
ec5a1c7851
10
gpxsee.pro
10
gpxsee.pro
@ -107,6 +107,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/IMG/rastertile.h \
|
||||
src/map/IMG/shield.h \
|
||||
src/map/mapsforge/style.h \
|
||||
src/map/prjfile.h \
|
||||
src/map/textpathitem.h \
|
||||
src/map/textpointitem.h \
|
||||
src/map/mapsforge/mapdata.h \
|
||||
@ -149,6 +150,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/ct.h \
|
||||
src/map/mapsource.h \
|
||||
src/map/tileloader.h \
|
||||
src/map/wldfile.h \
|
||||
src/map/wmtsmap.h \
|
||||
src/map/wmts.h \
|
||||
src/map/wmsmap.h \
|
||||
@ -221,7 +223,8 @@ HEADERS += src/common/config.h \
|
||||
src/data/geojsonparser.h \
|
||||
src/GUI/timezoneinfo.h \
|
||||
src/map/aqmmap.h \
|
||||
src/map/mapsforgemap.h
|
||||
src/map/mapsforgemap.h \
|
||||
src/map/worldfilemap.h
|
||||
|
||||
SOURCES += src/main.cpp \
|
||||
src/GUI/axislabelitem.cpp \
|
||||
@ -295,6 +298,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/IMG/mapdata.cpp \
|
||||
src/map/IMG/rastertile.cpp \
|
||||
src/map/mapsforge/style.cpp \
|
||||
src/map/prjfile.cpp \
|
||||
src/map/textpathitem.cpp \
|
||||
src/map/textpointitem.cpp \
|
||||
src/map/mapsforge/mapdata.cpp \
|
||||
@ -332,6 +336,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/linearunits.cpp \
|
||||
src/map/mapsource.cpp \
|
||||
src/map/tileloader.cpp \
|
||||
src/map/wldfile.cpp \
|
||||
src/map/wmtsmap.cpp \
|
||||
src/map/wmts.cpp \
|
||||
src/map/wmsmap.cpp \
|
||||
@ -389,7 +394,8 @@ SOURCES += src/main.cpp \
|
||||
src/GUI/pngexportdialog.cpp \
|
||||
src/data/geojsonparser.cpp \
|
||||
src/map/aqmmap.cpp \
|
||||
src/map/mapsforgemap.cpp
|
||||
src/map/mapsforgemap.cpp \
|
||||
src/map/worldfilemap.cpp
|
||||
|
||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
|
||||
QT_NO_DEPRECATED_WARNINGS
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "map/maplist.h"
|
||||
#include "map/emptymap.h"
|
||||
#include "map/downloader.h"
|
||||
#include "map/crs.h"
|
||||
#include "icons.h"
|
||||
#include "keys.h"
|
||||
#include "settings.h"
|
||||
@ -123,7 +124,8 @@ TreeNode<MapAction*> GUI::createMapActions()
|
||||
if (mapDir.isNull())
|
||||
return TreeNode<MapAction*>();
|
||||
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
return createMapActionsNode(maps);
|
||||
}
|
||||
|
||||
@ -1006,8 +1008,19 @@ void GUI::openOptions()
|
||||
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
|
||||
SET_VIEW_OPTION(useOpenGL, useOpenGL);
|
||||
SET_VIEW_OPTION(sliderColor, setMarkerColor);
|
||||
SET_VIEW_OPTION(outputProjection, setOutputProjection);
|
||||
SET_VIEW_OPTION(inputProjection, setInputProjection);
|
||||
|
||||
if (options.hidpiMap != _options.hidpiMap)
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
if (options.outputProjection != _options.outputProjection)
|
||||
_mapView->setOutputProjection(CRS::projection(options.outputProjection));
|
||||
if (options.inputProjection != _options.inputProjection)
|
||||
_mapView->setInputProjection(CRS::projection(options.inputProjection));
|
||||
if (options.timeZone != _options.timeZone) {
|
||||
_mapView->setTimeZone(options.timeZone.zone());
|
||||
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
|
||||
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
|
||||
}
|
||||
|
||||
SET_TAB_OPTION(palette, setPalette);
|
||||
SET_TAB_OPTION(graphWidth, setGraphWidth);
|
||||
@ -1047,16 +1060,6 @@ void GUI::openOptions()
|
||||
if (options.enableHTTP2 != _options.enableHTTP2)
|
||||
Downloader::enableHTTP2(options.enableHTTP2);
|
||||
|
||||
if (options.hidpiMap != _options.hidpiMap)
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
|
||||
if (options.timeZone != _options.timeZone) {
|
||||
_mapView->setTimeZone(options.timeZone.zone());
|
||||
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
|
||||
_dateRange.second = _dateRange.second.toTimeZone(options.timeZone.zone());
|
||||
}
|
||||
|
||||
if (reload)
|
||||
reloadFiles();
|
||||
|
||||
@ -1561,7 +1564,8 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
|
||||
|
||||
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
|
||||
{
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
|
||||
return loadMapNode(maps, action, silent, existingActions);
|
||||
@ -1650,7 +1654,8 @@ void GUI::loadMapDir()
|
||||
return;
|
||||
|
||||
QFileInfo fi(dir);
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
QList<MapAction*> actions;
|
||||
QMenu *menu = new QMenu(maps.name());
|
||||
@ -2581,8 +2586,8 @@ void GUI::readSettings()
|
||||
_mapView->useOpenGL(true);
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
_mapView->setOutputProjection(_options.outputProjection);
|
||||
_mapView->setInputProjection(_options.inputProjection);
|
||||
_mapView->setOutputProjection(CRS::projection(_options.outputProjection));
|
||||
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
|
||||
_mapView->setTimeZone(_options.timeZone.zone());
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++) {
|
||||
|
@ -1121,37 +1121,19 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
reloadMap();
|
||||
}
|
||||
|
||||
void MapView::setOutputProjection(int id)
|
||||
void MapView::setOutputProjection(const Projection &proj)
|
||||
{
|
||||
const PCS *pcs;
|
||||
const GCS *gcs;
|
||||
_outputProjection = proj;
|
||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
||||
|
||||
if ((pcs = PCS::pcs(id)))
|
||||
_outputProjection = Projection(pcs);
|
||||
else if ((gcs = GCS::gcs(id)))
|
||||
_outputProjection = Projection(gcs);
|
||||
else
|
||||
qWarning("%d: Unknown PCS/GCS id", id);
|
||||
|
||||
_map->setOutputProjection(_outputProjection);
|
||||
rescale();
|
||||
centerOn(_map->ll2xy(center));
|
||||
}
|
||||
|
||||
void MapView::setInputProjection(int id)
|
||||
void MapView::setInputProjection(const Projection &proj)
|
||||
{
|
||||
const PCS *pcs;
|
||||
const GCS *gcs;
|
||||
_inputProjection = proj;
|
||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
||||
|
||||
if ((pcs = PCS::pcs(id)))
|
||||
_inputProjection = Projection(pcs);
|
||||
else if ((gcs = GCS::gcs(id)))
|
||||
_inputProjection = Projection(gcs);
|
||||
else
|
||||
qWarning("%d: Unknown PCS/GCS id", id);
|
||||
|
||||
_map->setInputProjection(_inputProjection);
|
||||
rescale();
|
||||
centerOn(_map->ll2xy(center));
|
||||
|
@ -83,8 +83,8 @@ public:
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void setTimeZone(const QTimeZone &zone);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void setOutputProjection(int id);
|
||||
void setInputProjection(int id);
|
||||
void setOutputProjection(const Projection &proj);
|
||||
void setInputProjection(const Projection &proj);
|
||||
void clearMapCache();
|
||||
void fitContentToSize();
|
||||
|
||||
|
@ -44,11 +44,12 @@ void OptionsDialog::automaticPauseDetectionSet(bool set)
|
||||
_pauseSpeed->setEnabled(!set);
|
||||
}
|
||||
|
||||
QWidget *OptionsDialog::createMapPage()
|
||||
static LimitedComboBox *projectionBox()
|
||||
{
|
||||
LimitedComboBox *box;
|
||||
int last = -1;
|
||||
|
||||
_outputProjection = new LimitedComboBox(200);
|
||||
box = new LimitedComboBox(200);
|
||||
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
|
||||
std::sort(projections.begin(), projections.end());
|
||||
for (int i = 0; i < projections.size(); i++) {
|
||||
@ -59,33 +60,26 @@ QWidget *OptionsDialog::createMapPage()
|
||||
else
|
||||
last = proj.key();
|
||||
QString text = QString::number(proj.key()) + " - " + proj.value();
|
||||
_outputProjection->addItem(text, QVariant(proj.key()));
|
||||
box->addItem(text, QVariant(proj.key()));
|
||||
}
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
QWidget *OptionsDialog::createMapPage()
|
||||
{
|
||||
_outputProjection = projectionBox();
|
||||
_outputProjection->setCurrentIndex(_outputProjection->findData(
|
||||
_options.outputProjection));
|
||||
|
||||
_inputProjection = new LimitedComboBox(200);
|
||||
last = -1;
|
||||
for (int i = 0; i < projections.size(); i++) {
|
||||
const KV<int, QString> &proj = projections.at(i);
|
||||
// There may be same EPSG codes with different names
|
||||
if (proj.key() == last)
|
||||
continue;
|
||||
else
|
||||
last = proj.key();
|
||||
if (proj.key() == 4326 || proj.key() == 3857) {
|
||||
QString text = QString::number(proj.key()) + " - " + proj.value();
|
||||
_inputProjection->addItem(text, QVariant(proj.key()));
|
||||
}
|
||||
}
|
||||
_inputProjection = projectionBox();
|
||||
_inputProjection->setCurrentIndex(_inputProjection->findData(
|
||||
_options.inputProjection));
|
||||
|
||||
QLabel *inInfo = new QLabel(tr("Select the proper projection of"
|
||||
" JNX and KMZ maps. Both EPSG:3857 and EPSG:4326 projected maps"
|
||||
" exist and there is no projection info in the map file."));
|
||||
QLabel *outInfo = new QLabel(tr("Select the desired projection of IMG"
|
||||
" maps. The projection must be valid for the whole map area."));
|
||||
QLabel *inInfo = new QLabel(tr("Select the proper projection of maps"
|
||||
" without a projection definition (JNX, KMZ and world file maps)"));
|
||||
QLabel *outInfo = new QLabel(tr("Select the desired projection of vector"
|
||||
" maps (IMG and Mapsforge maps). The projection must be valid for"
|
||||
" the whole map area."));
|
||||
QFont f = inInfo->font();
|
||||
f.setPointSize(f.pointSize() - 1);
|
||||
inInfo->setWordWrap(true);
|
||||
|
@ -34,7 +34,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
Q_UNUSED(routes);
|
||||
Q_UNUSED(polygons);
|
||||
bool res;
|
||||
const GCS *gcs = 0;
|
||||
GCS gcs;
|
||||
|
||||
_errorLine = 1;
|
||||
_errorString.clear();
|
||||
@ -54,7 +54,8 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
} else if (_errorLine == 2) {
|
||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
||||
gcs = GCS::gcs(QString(line.trimmed()));
|
||||
if (gcs.isNull()) {
|
||||
_errorString = "Invalid/unknown datum";
|
||||
return false;
|
||||
}
|
||||
@ -80,7 +81,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
|
||||
Trackpoint tp(gcs->toWGS84(Coordinates(lon, lat)));
|
||||
Trackpoint tp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||
|
||||
if (list.size() >= 4) {
|
||||
QByteArray field(list.at(3).trimmed());
|
||||
@ -125,7 +126,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
Q_UNUSED(tracks);
|
||||
Q_UNUSED(polygons);
|
||||
bool res, record = false;
|
||||
const GCS *gcs = 0;
|
||||
GCS gcs;
|
||||
|
||||
_errorLine = 1;
|
||||
_errorString.clear();
|
||||
@ -141,7 +142,8 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
} else if (_errorLine == 2) {
|
||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
||||
gcs = GCS::gcs(QString(line.trimmed()));
|
||||
if (gcs.isNull()) {
|
||||
_errorString = "Invalid/unknown datum";
|
||||
return false;
|
||||
}
|
||||
@ -181,7 +183,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
|
||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
||||
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||
|
||||
QByteArray name(list.at(4).trimmed());
|
||||
if (!name.isEmpty())
|
||||
@ -225,7 +227,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
Q_UNUSED(routes);
|
||||
Q_UNUSED(polygons);
|
||||
bool res;
|
||||
const GCS *gcs = 0;
|
||||
GCS gcs;
|
||||
|
||||
_errorLine = 1;
|
||||
_errorString.clear();
|
||||
@ -240,7 +242,8 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
} else if (_errorLine == 2) {
|
||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
||||
gcs = GCS::gcs(QString(line.trimmed()));
|
||||
if (gcs.isNull()) {
|
||||
_errorString = "Invalid/unknown datum";
|
||||
return false;
|
||||
}
|
||||
@ -262,7 +265,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
return false;
|
||||
}
|
||||
|
||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
||||
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||
|
||||
QByteArray name(list.at(1).trimmed());
|
||||
if (!name.isEmpty())
|
||||
|
@ -53,7 +53,7 @@ Defense.
|
||||
((clat) / sqrt(one_minus_sqr_e_sin))
|
||||
|
||||
|
||||
AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||
AlbersEqual::AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
|
||||
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||
double falseEasting, double falseNorthing)
|
||||
{
|
||||
@ -74,8 +74,8 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||
sp1 = deg2rad(standardParallel1);
|
||||
sp2 = deg2rad(standardParallel2);
|
||||
|
||||
_a2 = ellipsoid->radius() * ellipsoid->radius();
|
||||
_es = ellipsoid->es();
|
||||
_a2 = ellipsoid.radius() * ellipsoid.radius();
|
||||
_es = ellipsoid.es();
|
||||
_e = sqrt(_es);
|
||||
_one_minus_es = 1 - _es;
|
||||
_two_e = 2 * _e;
|
||||
@ -105,7 +105,7 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||
_n = sin_lat1;
|
||||
|
||||
_c = sqr_m1 + _n * q1;
|
||||
_a_over_n = ellipsoid->radius() / _n;
|
||||
_a_over_n = ellipsoid.radius() / _n;
|
||||
nq0 = _n * q0;
|
||||
_rho0 = (_c < nq0) ? 0 : _a_over_n * sqrt(_c - nq0);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class AlbersEqual : public CT
|
||||
{
|
||||
public:
|
||||
AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||
AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
|
||||
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||
double falseEasting, double falseNorthing);
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include "common/coordinates.h"
|
||||
#include "common/util.h"
|
||||
#include "angularunits.h"
|
||||
|
||||
|
@ -3,12 +3,14 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <QDebug>
|
||||
#include "common/coordinates.h"
|
||||
|
||||
class AngularUnits
|
||||
{
|
||||
public:
|
||||
AngularUnits() : _code(0), _f(NAN) {}
|
||||
AngularUnits(int code);
|
||||
AngularUnits(double val) : _code(0), _f(rad2deg(val)) {}
|
||||
|
||||
bool operator==(const AngularUnits &other) const
|
||||
{
|
||||
|
@ -290,14 +290,14 @@ bool BSBMap::createTransform(QList<ReferencePoint> &points)
|
||||
bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
||||
double params[9], const Coordinates &c)
|
||||
{
|
||||
const GCS *gcs = 0;
|
||||
GCS gcs;
|
||||
PCS pcs;
|
||||
|
||||
if (datum.isEmpty())
|
||||
gcs = GCS::gcs(4326);
|
||||
else
|
||||
gcs = GCS::gcs(datum);
|
||||
if (!gcs) {
|
||||
if (gcs.isNull()) {
|
||||
_errorString = datum + ": Unknown datum";
|
||||
return false;
|
||||
}
|
||||
@ -323,7 +323,7 @@ bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
||||
return false;
|
||||
}
|
||||
|
||||
_projection = Projection(&pcs);
|
||||
_projection = Projection(pcs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -7,9 +7,6 @@ Projection CRS::projection(const QString &crs)
|
||||
QStringList list(crs.split(':'));
|
||||
QString authority, code;
|
||||
bool res;
|
||||
int epsg;
|
||||
const PCS *pcs;
|
||||
const GCS *gcs;
|
||||
|
||||
switch (list.size()) {
|
||||
case 2:
|
||||
@ -33,15 +30,18 @@ Projection CRS::projection(const QString &crs)
|
||||
}
|
||||
|
||||
if (!authority.compare("EPSG", Qt::CaseInsensitive)) {
|
||||
epsg = code.toInt(&res);
|
||||
int epsg = code.toInt(&res);
|
||||
if (!res)
|
||||
return Projection();
|
||||
|
||||
if ((pcs = PCS::pcs(epsg)))
|
||||
const PCS &pcs = PCS::pcs(epsg);
|
||||
if (!pcs.isNull())
|
||||
return Projection(pcs);
|
||||
else if ((gcs = GCS::gcs(epsg)))
|
||||
|
||||
const GCS &gcs = GCS::gcs(epsg);
|
||||
if (!gcs.isNull())
|
||||
return Projection(gcs);
|
||||
else
|
||||
|
||||
return Projection();
|
||||
} else if (!authority.compare("OGC", Qt::CaseInsensitive)) {
|
||||
if (code == "CRS84")
|
||||
@ -51,3 +51,16 @@ Projection CRS::projection(const QString &crs)
|
||||
} else
|
||||
return Projection();
|
||||
}
|
||||
|
||||
Projection CRS::projection(int id)
|
||||
{
|
||||
const PCS &pcs = PCS::pcs(id);
|
||||
if (!pcs.isNull())
|
||||
return Projection(pcs);
|
||||
|
||||
const GCS &gcs = GCS::gcs(id);
|
||||
if (!gcs.isNull())
|
||||
return Projection(gcs);
|
||||
|
||||
return Projection();
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
namespace CRS
|
||||
{
|
||||
Projection projection(const QString &crs);
|
||||
Projection projection(int id);
|
||||
}
|
||||
|
||||
#endif // CRS_H
|
||||
|
@ -23,11 +23,11 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
||||
double dy = from.dy() - to.dy();
|
||||
double dz = from.dz() - to.dz();
|
||||
|
||||
double from_f = from.ellipsoid()->flattening();
|
||||
double to_f = to.ellipsoid()->flattening();
|
||||
double from_f = from.ellipsoid().flattening();
|
||||
double to_f = to.ellipsoid().flattening();
|
||||
double df = to_f - from_f;
|
||||
double from_a = from.ellipsoid()->radius();
|
||||
double to_a = to.ellipsoid()->radius();
|
||||
double from_a = from.ellipsoid().radius();
|
||||
double to_a = to.ellipsoid().radius();
|
||||
double da = to_a - from_a;
|
||||
double from_esq = from_f * (2.0 - from_f);
|
||||
double adb = 1.0 / (1.0 - from_f);
|
||||
@ -45,7 +45,7 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
||||
|
||||
const Datum &Datum::WGS84()
|
||||
{
|
||||
static Datum d(&Ellipsoid::WGS84(), 0.0, 0.0, 0.0);
|
||||
static Datum d(Ellipsoid::WGS84(), 0.0, 0.0, 0.0);
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -66,12 +66,12 @@ Point3D Datum::helmertr(const Point3D &p) const
|
||||
* y + z);
|
||||
}
|
||||
|
||||
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
||||
Datum::Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz,
|
||||
double rx, double ry, double rz, double ds)
|
||||
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
|
||||
_ry(as2rad(ry)), _rz(as2rad(rz)), _scale(ds2scale(ds))
|
||||
{
|
||||
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
||||
if (_ellipsoid.radius() == WGS84_RADIUS && _ellipsoid.flattening()
|
||||
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0
|
||||
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
|
||||
_transformation = None;
|
||||
@ -79,11 +79,11 @@ Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
||||
_transformation = Helmert;
|
||||
}
|
||||
|
||||
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
|
||||
Datum::Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz)
|
||||
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(0.0), _ry(0.0),
|
||||
_rz(0.0), _scale(1.0)
|
||||
{
|
||||
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
||||
if (_ellipsoid.radius() == WGS84_RADIUS && _ellipsoid.flattening()
|
||||
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
|
||||
_transformation = None;
|
||||
else
|
||||
@ -119,7 +119,7 @@ Coordinates Datum::fromWGS84(const Coordinates &c) const
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Datum &datum)
|
||||
{
|
||||
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
|
||||
dbg.nospace() << "Datum(" << datum.ellipsoid() << ", " << datum.dx()
|
||||
<< ", " << datum.dy() << ", " << datum.dz() << ", " << rad2as(datum.rx())
|
||||
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
|
||||
<< scale2ds(datum.scale()) << ")";
|
||||
|
@ -10,13 +10,13 @@
|
||||
class Datum
|
||||
{
|
||||
public:
|
||||
Datum() : _ellipsoid(0), _transformation(None), _dx(NAN), _dy(NAN),
|
||||
Datum() : _transformation(None), _dx(NAN), _dy(NAN),
|
||||
_dz(NAN), _rx(NAN), _ry(NAN), _rz(NAN), _scale(NAN) {}
|
||||
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
||||
Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz,
|
||||
double rx, double ry, double rz, double ds);
|
||||
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz);
|
||||
Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz);
|
||||
|
||||
const Ellipsoid *ellipsoid() const {return _ellipsoid;}
|
||||
const Ellipsoid &ellipsoid() const {return _ellipsoid;}
|
||||
double dx() const {return _dx;}
|
||||
double dy() const {return _dy;}
|
||||
double dz() const {return _dz;}
|
||||
@ -26,9 +26,9 @@ public:
|
||||
double scale() const {return _scale;}
|
||||
|
||||
bool isNull() const
|
||||
{return !_ellipsoid;}
|
||||
{return _ellipsoid.isNull();}
|
||||
bool isValid() const
|
||||
{return (_ellipsoid && !std::isnan(_dx) && !std::isnan(_dy)
|
||||
{return (_ellipsoid.isValid() && !std::isnan(_dx) && !std::isnan(_dy)
|
||||
&& !std::isnan(_dz) && !std::isnan(_scale) && !std::isnan(_rx)
|
||||
&& !std::isnan(_ry) && !std::isnan(_rz));}
|
||||
|
||||
@ -47,13 +47,13 @@ private:
|
||||
Point3D helmert(const Point3D &p) const;
|
||||
Point3D helmertr(const Point3D &p) const;
|
||||
|
||||
const Ellipsoid *_ellipsoid;
|
||||
Ellipsoid _ellipsoid;
|
||||
TransformationType _transformation;
|
||||
double _dx, _dy, _dz, _rx, _ry, _rz, _scale;
|
||||
};
|
||||
|
||||
inline bool operator==(const Datum &d1, const Datum &d2)
|
||||
{return (*d1.ellipsoid() == *d2.ellipsoid() && d1.dx() == d2.dx()
|
||||
{return (d1.ellipsoid() == d2.ellipsoid() && d1.dx() == d2.dx()
|
||||
&& d1.dy() == d2.dy() && d1.dz() == d2.dz() && d1.rx() == d2.rx()
|
||||
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.scale() == d2.scale());}
|
||||
|
||||
|
@ -18,14 +18,15 @@ QMap<int, Ellipsoid> Ellipsoid::defaults()
|
||||
return map;
|
||||
}
|
||||
|
||||
const Ellipsoid *Ellipsoid::ellipsoid(int id)
|
||||
const Ellipsoid &Ellipsoid::ellipsoid(int id)
|
||||
{
|
||||
QMap<int, Ellipsoid>::const_iterator it(_ellipsoids.find(id));
|
||||
static const Ellipsoid null;
|
||||
|
||||
if (it == _ellipsoids.constEnd())
|
||||
return 0;
|
||||
return null;
|
||||
else
|
||||
return &(it.value());
|
||||
return it.value();
|
||||
}
|
||||
|
||||
void Ellipsoid::loadList(const QString &path)
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
{return !(std::isnan(_radius) || std::isnan(_flattening));}
|
||||
|
||||
static const Ellipsoid &WGS84();
|
||||
static const Ellipsoid *ellipsoid(int id);
|
||||
static const Ellipsoid &ellipsoid(int id);
|
||||
static void loadList(const QString &path);
|
||||
|
||||
private:
|
||||
|
@ -58,34 +58,40 @@ QList<GCS::Entry> GCS::defaults()
|
||||
return list;
|
||||
}
|
||||
|
||||
const GCS *GCS::gcs(int id)
|
||||
const GCS &GCS::gcs(int id)
|
||||
{
|
||||
static const GCS null;
|
||||
|
||||
for (int i = 0; i < _gcss.size(); i++)
|
||||
if (_gcss.at(i).id() == id)
|
||||
return &(_gcss.at(i).gcs());
|
||||
return _gcss.at(i).gcs();
|
||||
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
const GCS *GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits)
|
||||
const GCS &GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits)
|
||||
{
|
||||
static const GCS null;
|
||||
|
||||
for (int i = 0; i < _gcss.size(); i++) {
|
||||
const Entry &e = _gcss.at(i);
|
||||
if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
|
||||
&& e.gcs().angularUnits() == angularUnits)
|
||||
return &(e.gcs());
|
||||
return e.gcs();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
const GCS *GCS::gcs(const QString &name)
|
||||
const GCS &GCS::gcs(const QString &name)
|
||||
{
|
||||
static const GCS null;
|
||||
|
||||
for (int i = 0; i < _gcss.size(); i++)
|
||||
if (_gcss.at(i).name() == name)
|
||||
return &(_gcss.at(i).gcs());
|
||||
return _gcss.at(i).gcs();
|
||||
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
void GCS::loadList(const QString &path)
|
||||
@ -93,7 +99,6 @@ void GCS::loadList(const QString &path)
|
||||
QFile file(path);
|
||||
bool res;
|
||||
int ln = 0;
|
||||
const Ellipsoid *e;
|
||||
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
@ -182,7 +187,8 @@ void GCS::loadList(const QString &path)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(e = Ellipsoid::ellipsoid(el))) {
|
||||
const Ellipsoid &e = Ellipsoid::ellipsoid(el);
|
||||
if (e.isNull()) {
|
||||
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ public:
|
||||
Coordinates toWGS84(const Coordinates &c) const;
|
||||
Coordinates fromWGS84(const Coordinates &c) const;
|
||||
|
||||
static const GCS *gcs(int id);
|
||||
static const GCS *gcs(int geodeticDatum, int primeMeridian,
|
||||
static const GCS &gcs(int id);
|
||||
static const GCS &gcs(int geodeticDatum, int primeMeridian,
|
||||
int angularUnits);
|
||||
static const GCS *gcs(const QString &name);
|
||||
static const GCS &gcs(const QString &name);
|
||||
static const GCS &WGS84();
|
||||
|
||||
static void loadList(const QString &path);
|
||||
|
@ -47,23 +47,23 @@ Defense.
|
||||
|
||||
#define AD_C 1.0026000
|
||||
|
||||
Point3D Geocentric::fromGeodetic(const Coordinates &c, const Ellipsoid *e)
|
||||
Point3D Geocentric::fromGeodetic(const Coordinates &c, const Ellipsoid &e)
|
||||
{
|
||||
double lat = deg2rad(c.lat());
|
||||
double lon = deg2rad(c.lon());
|
||||
double slat = sin(lat);
|
||||
double slat2 = slat * slat;
|
||||
double clat = cos(lat);
|
||||
double Rn = e->radius() / (sqrt(1.0 - e->es() * slat2));
|
||||
double Rn = e.radius() / (sqrt(1.0 - e.es() * slat2));
|
||||
|
||||
if (lon > M_PI)
|
||||
lon -= 2 * M_PI;
|
||||
|
||||
return Point3D(Rn * clat * cos(lon), Rn * clat * sin(lon),
|
||||
(Rn * (1 - e->es())) * slat);
|
||||
(Rn * (1 - e.es())) * slat);
|
||||
}
|
||||
|
||||
Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid *e)
|
||||
Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid &e)
|
||||
{
|
||||
bool pole = false;
|
||||
double lat, lon;
|
||||
@ -93,8 +93,8 @@ Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid *e)
|
||||
double Sin_B0 = T0 / S0;
|
||||
double Cos_B0 = W / S0;
|
||||
double Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
|
||||
double T1 = p.z() + e->b() * e->e2s() * Sin3_B0;
|
||||
double Sum = W - e->radius() * e->es() * Cos_B0 * Cos_B0 * Cos_B0;
|
||||
double T1 = p.z() + e.b() * e.e2s() * Sin3_B0;
|
||||
double Sum = W - e.radius() * e.es() * Cos_B0 * Cos_B0 * Cos_B0;
|
||||
double S1 = sqrt(T1*T1 + Sum * Sum);
|
||||
double Sin_p1 = T1 / S1;
|
||||
double Cos_p1 = Sum / S1;
|
||||
|
@ -22,8 +22,8 @@ private:
|
||||
};
|
||||
|
||||
namespace Geocentric {
|
||||
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid *e);
|
||||
Coordinates toGeodetic(const Point3D &p, const Ellipsoid *e);
|
||||
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid &e);
|
||||
Coordinates toGeodetic(const Point3D &p, const Ellipsoid &e);
|
||||
}
|
||||
|
||||
#endif // GEOCENTRIC_H
|
||||
|
@ -289,12 +289,13 @@ bool GeoTIFF::readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
|
||||
return true;
|
||||
}
|
||||
|
||||
const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
||||
GCS GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
||||
{
|
||||
const GCS *gcs = 0;
|
||||
GCS gcs;
|
||||
|
||||
if (IS_SET(kv, GeographicTypeGeoKey)) {
|
||||
if (!(gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT)))
|
||||
gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT);
|
||||
if (gcs.isNull())
|
||||
_errorString = QString("%1: unknown GCS")
|
||||
.arg(kv.value(GeographicTypeGeoKey).SHORT);
|
||||
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||
@ -310,7 +311,8 @@ const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
||||
int gd = IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||
? kv.value(GeogGeodeticDatumGeoKey).SHORT : 6326;
|
||||
|
||||
if (!(gcs = GCS::gcs(gd, pm, au)))
|
||||
gcs = GCS::gcs(gd, pm, au);
|
||||
if (gcs.isNull())
|
||||
_errorString = QString("%1+%2+%3: unknown geodetic datum + prime"
|
||||
" meridian + units combination").arg(gd).arg(pm).arg(au);
|
||||
} else
|
||||
@ -357,19 +359,19 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
|
||||
bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
{
|
||||
if (IS_SET(kv, ProjectedCSTypeGeoKey)) {
|
||||
const PCS *pcs;
|
||||
if (!(pcs = PCS::pcs(kv.value(ProjectedCSTypeGeoKey).SHORT))) {
|
||||
const PCS &pcs = PCS::pcs(kv.value(ProjectedCSTypeGeoKey).SHORT);
|
||||
if (pcs.isNull()) {
|
||||
_errorString = QString("%1: unknown PCS")
|
||||
.arg(kv.value(ProjectedCSTypeGeoKey).SHORT);
|
||||
return false;
|
||||
}
|
||||
_projection = Projection(pcs);
|
||||
} else if (IS_SET(kv, ProjectionGeoKey)) {
|
||||
const GCS *g = gcs(kv);
|
||||
if (!g)
|
||||
const GCS g(gcs(kv));
|
||||
if (g.isNull())
|
||||
return false;
|
||||
const PCS *pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT);
|
||||
if (!pcs) {
|
||||
const PCS &pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT);
|
||||
if (pcs.isNull()) {
|
||||
_errorString = QString("%1: unknown projection code")
|
||||
.arg(kv.value(GeographicTypeGeoKey).SHORT)
|
||||
.arg(kv.value(ProjectionGeoKey).SHORT);
|
||||
@ -379,8 +381,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
} else {
|
||||
double lat0, lon0, scale, fe, fn, sp1, sp2;
|
||||
|
||||
const GCS *g = gcs(kv);
|
||||
if (!g)
|
||||
GCS g(gcs(kv));
|
||||
if (g.isNull())
|
||||
return false;
|
||||
Projection::Method m(method(kv));
|
||||
if (m.isNull())
|
||||
@ -453,7 +455,7 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
|
||||
Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2);
|
||||
PCS pcs(g, m, setup, lu, CoordinateSystem());
|
||||
_projection = Projection(&pcs);
|
||||
_projection = Projection(pcs);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -461,8 +463,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
|
||||
bool GeoTIFF::geographicModel(QMap<quint16, Value> &kv)
|
||||
{
|
||||
const GCS *g = gcs(kv);
|
||||
if (!g)
|
||||
GCS g(gcs(kv));
|
||||
if (g.isNull())
|
||||
return false;
|
||||
|
||||
_projection = Projection(g);
|
||||
|
@ -48,7 +48,7 @@ private:
|
||||
bool readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
|
||||
double &val) const;
|
||||
|
||||
const GCS *gcs(QMap<quint16, Value> &kv);
|
||||
GCS gcs(QMap<quint16, Value> &kv);
|
||||
Projection::Method method(QMap<quint16, Value> &kv);
|
||||
bool geographicModel(QMap<quint16, Value> &kv);
|
||||
bool projectedModel(QMap<quint16, Value> &kv);
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <QFileInfo>
|
||||
#include <QPainter>
|
||||
#include <QImageReader>
|
||||
#include "common/util.h"
|
||||
|
@ -131,12 +131,10 @@ bool JNXMap::readTiles()
|
||||
return true;
|
||||
}
|
||||
|
||||
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _file(fileName), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
JNXMap::JNXMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||
: Map(fileName, parent), _file(fileName), _zoom(0), _projection(proj),
|
||||
_mapRatio(1.0), _valid(false)
|
||||
{
|
||||
_projection = Projection(GCS::gcs(4326));
|
||||
|
||||
if (!_file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = fileName + ": " + _file.errorString();
|
||||
return;
|
||||
|
@ -15,7 +15,7 @@ public:
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JNXMap(const QString &fileName, QObject *parent = 0);
|
||||
JNXMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||
~JNXMap();
|
||||
|
||||
QRectF bounds();
|
||||
|
@ -307,16 +307,14 @@ void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip)
|
||||
}
|
||||
|
||||
|
||||
KMZMap::KMZMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _ratio(1.0),
|
||||
_valid(false)
|
||||
KMZMap::KMZMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _projection(proj),
|
||||
_ratio(1.0), _valid(false)
|
||||
{
|
||||
QZipReader zip(fileName, QIODevice::ReadOnly);
|
||||
QByteArray xml(zip.fileData("doc.kml"));
|
||||
QXmlStreamReader reader(xml);
|
||||
|
||||
_projection = Projection(GCS::gcs(4326));
|
||||
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("kml"))
|
||||
kml(reader, zip);
|
||||
|
@ -15,7 +15,7 @@ class KMZMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KMZMap(const QString &fileName, QObject *parent = 0);
|
||||
KMZMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "ellipsoid.h"
|
||||
#include "krovak.h"
|
||||
|
||||
Krovak::Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
||||
Krovak::Krovak(const Ellipsoid &ellipsoid, double standardParallel,
|
||||
double azimuth, double scale, double centerLatitude, double longitudeOrigin,
|
||||
double falseEasting, double falseNorthing)
|
||||
{
|
||||
@ -14,10 +14,10 @@ Krovak::Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
||||
double alphaC = deg2rad(azimuth);
|
||||
|
||||
_phiP = deg2rad(standardParallel);
|
||||
_e = sqrt(ellipsoid->es());
|
||||
_a = ellipsoid->radius() * sqrt(1.0 - ellipsoid->es())
|
||||
/ (1.0 - ellipsoid->es() * sinPhiC2);
|
||||
_b = sqrt(1.0 + (ellipsoid->es() * cosPhiC4 / (1.0 - ellipsoid->es())));
|
||||
_e = sqrt(ellipsoid.es());
|
||||
_a = ellipsoid.radius() * sqrt(1.0 - ellipsoid.es())
|
||||
/ (1.0 - ellipsoid.es() * sinPhiC2);
|
||||
_b = sqrt(1.0 + (ellipsoid.es() * cosPhiC4 / (1.0 - ellipsoid.es())));
|
||||
double gamma0 = asin(sinPhiC / _b);
|
||||
_t0 = tan(M_PI_4 + gamma0 / 2.0) * pow((1.0 + _e * sinPhiC) /
|
||||
(1.0 - _e * sinPhiC), _e*_b / 2.0) / pow(tan(M_PI_4 + phiC/2.0), _b);
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class Krovak : public CT
|
||||
{
|
||||
public:
|
||||
Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
||||
Krovak(const Ellipsoid &ellipsoid, double standardParallel,
|
||||
double azimuth, double scale, double centerLatitude,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
@ -26,7 +26,7 @@ private:
|
||||
class KrovakNE : public CT
|
||||
{
|
||||
public:
|
||||
KrovakNE(const Ellipsoid *ellipsoid, double standardParallel,
|
||||
KrovakNE(const Ellipsoid &ellipsoid, double standardParallel,
|
||||
double azimuth, double scale, double centerLatitude,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||
: _k(ellipsoid, standardParallel, azimuth, scale, centerLatitude,
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define sin2(x) (sin(x) * sin(x))
|
||||
#define sqr(x) ((x) * (x))
|
||||
|
||||
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
|
||||
LambertAzimuthal::LambertAzimuthal(const Ellipsoid &ellipsoid,
|
||||
double latitudeOrigin, double longitudeOrigin, double falseEasting,
|
||||
double falseNorthing)
|
||||
{
|
||||
@ -15,8 +15,8 @@ LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
|
||||
_fn = falseNorthing;
|
||||
_lon0 = deg2rad(longitudeOrigin);
|
||||
|
||||
_a = ellipsoid->radius();
|
||||
_es = ellipsoid->es();
|
||||
_a = ellipsoid.radius();
|
||||
_es = ellipsoid.es();
|
||||
_e = sqrt(_es);
|
||||
|
||||
double q0 = (1.0 - _es) * ((sin(lat0) / (1.0 - _es * sin2(lat0)))
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class LambertAzimuthal : public CT
|
||||
{
|
||||
public:
|
||||
LambertAzimuthal(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
LambertAzimuthal(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
virtual CT *clone() const {return new LambertAzimuthal(*this);}
|
||||
|
@ -53,7 +53,7 @@ Defense.
|
||||
(tan(M_PI_4 - lat / 2) / pow((1.0 - essin) / (1.0 + essin), es_over_2))
|
||||
|
||||
|
||||
LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
LambertConic1::LambertConic1(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double scale, double falseEasting,
|
||||
double falseNorthing)
|
||||
{
|
||||
@ -70,7 +70,7 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
_falseEasting = falseEasting;
|
||||
_falseNorthing = falseNorthing;
|
||||
|
||||
_e = sqrt(ellipsoid->es());
|
||||
_e = sqrt(ellipsoid.es());
|
||||
_e_over_2 = _e / 2.0;
|
||||
|
||||
_n = sin(lat_orig);
|
||||
@ -79,7 +79,7 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
m0 = LAMBERT_m(cos(lat_orig), e_sin);
|
||||
_t0 = LAMBERT1_t(lat_orig, e_sin, _e_over_2);
|
||||
|
||||
_rho0 = ellipsoid->radius() * scale * m0 / _n;
|
||||
_rho0 = ellipsoid.radius() * scale * m0 / _n;
|
||||
|
||||
_rho_olat = _rho0;
|
||||
}
|
||||
@ -204,7 +204,7 @@ bool LambertConic1::operator==(const CT &ct) const
|
||||
}
|
||||
|
||||
|
||||
LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
|
||||
LambertConic2::LambertConic2(const Ellipsoid &ellipsoid,
|
||||
double standardParallel1, double standardParallel2, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||
{
|
||||
@ -228,7 +228,7 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
|
||||
sp2 = deg2rad(standardParallel2);
|
||||
|
||||
if (fabs(sp1 - sp2) > 1.0e-10) {
|
||||
e = sqrt(ellipsoid->es());
|
||||
e = sqrt(ellipsoid.es());
|
||||
e_over_2 = e / 2.0;
|
||||
|
||||
e_sin = e * sin(lat_orig);
|
||||
@ -252,7 +252,7 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
|
||||
|
||||
k0 = (m1 / m0) * (pow(t0 / t1, n));
|
||||
|
||||
const_value = ((ellipsoid->radius() * m2) / (n * pow(t2, n)));
|
||||
const_value = ((ellipsoid.radius() * m2) / (n * pow(t2, n)));
|
||||
|
||||
falseNorthing += (const_value * pow(t_olat, n)) - (const_value
|
||||
* pow(t0, n));
|
||||
|
@ -9,7 +9,7 @@ class LambertConic1 : public CT
|
||||
{
|
||||
public:
|
||||
LambertConic1() {}
|
||||
LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
LambertConic1(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double scale, double falseEasting,
|
||||
double falseNorthing);
|
||||
|
||||
@ -35,7 +35,7 @@ private:
|
||||
class LambertConic2 : public CT
|
||||
{
|
||||
public:
|
||||
LambertConic2(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||
LambertConic2(const Ellipsoid &ellipsoid, double standardParallel1,
|
||||
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||
double falseEasting, double falseNorthing);
|
||||
|
||||
|
@ -10,6 +10,7 @@ class LinearUnits
|
||||
public:
|
||||
LinearUnits() : _f(NAN) {}
|
||||
LinearUnits(int code);
|
||||
LinearUnits(double val) : _f(val) {}
|
||||
|
||||
bool operator==(const LinearUnits &other) const
|
||||
{return (_f == other._f);}
|
||||
|
@ -161,21 +161,17 @@ bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
|
||||
return (!el);
|
||||
}
|
||||
|
||||
const GCS *MapFile::createGCS(const QString &datum)
|
||||
{
|
||||
const GCS *gcs;
|
||||
|
||||
if (!(gcs = GCS::gcs(datum)))
|
||||
_errorString = QString("%1: Unknown datum").arg(datum);
|
||||
|
||||
return gcs;
|
||||
}
|
||||
|
||||
bool MapFile::createProjection(const GCS *gcs, const QString &name,
|
||||
bool MapFile::createProjection(const QString &datum, const QString &name,
|
||||
const Projection::Setup &setup)
|
||||
{
|
||||
PCS pcs;
|
||||
|
||||
GCS gcs(GCS::gcs(datum));
|
||||
if (gcs.isNull()) {
|
||||
_errorString = QString("%1: Unknown datum").arg(datum);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name == "Latitude/Longitude") {
|
||||
_projection = Projection(gcs);
|
||||
return true;
|
||||
@ -230,7 +226,7 @@ bool MapFile::createProjection(const GCS *gcs, const QString &name,
|
||||
return false;
|
||||
}
|
||||
|
||||
_projection = Projection(&pcs);
|
||||
_projection = Projection(pcs);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -256,13 +252,10 @@ MapFile::MapFile(QIODevice &file)
|
||||
QList<CalibrationPoint> points;
|
||||
QString ct, datum;
|
||||
Projection::Setup setup;
|
||||
const GCS *gcs;
|
||||
|
||||
if (!parseMapFile(file, points, ct, setup, datum))
|
||||
return;
|
||||
if (!(gcs = createGCS(datum)))
|
||||
return;
|
||||
if (!createProjection(gcs, ct, setup))
|
||||
if (!createProjection(datum, ct, setup))
|
||||
return;
|
||||
if (!computeTransformation(points))
|
||||
return;
|
||||
|
@ -29,8 +29,7 @@ private:
|
||||
QString &projection, Projection::Setup &setup, QString &datum);
|
||||
bool parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
|
||||
QString &projection, Projection::Setup &setup, QString &datum);
|
||||
const GCS *createGCS(const QString &datum);
|
||||
bool createProjection(const GCS *gcs, const QString &projection,
|
||||
bool createProjection(const QString &datum, const QString &projection,
|
||||
const Projection::Setup &setup);
|
||||
bool computeTransformation(const QList<CalibrationPoint> &points);
|
||||
|
||||
|
@ -15,11 +15,12 @@
|
||||
#include "aqmmap.h"
|
||||
#include "sqlitemap.h"
|
||||
#include "mapsforgemap.h"
|
||||
#include "worldfilemap.h"
|
||||
#include "invalidmap.h"
|
||||
#include "maplist.h"
|
||||
|
||||
|
||||
Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
@ -38,7 +39,7 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
*isDir = true;
|
||||
}
|
||||
} else if (suffix == "jnx")
|
||||
map = new JNXMap(path);
|
||||
map = new JNXMap(path, proj);
|
||||
else if (suffix == "tif" || suffix == "tiff")
|
||||
map = new GeoTIFFMap(path);
|
||||
else if (suffix == "mbtiles")
|
||||
@ -57,16 +58,20 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
else if (suffix == "kap")
|
||||
map = new BSBMap(path);
|
||||
else if (suffix == "kmz")
|
||||
map = new KMZMap(path);
|
||||
map = new KMZMap(path, proj);
|
||||
else if (suffix == "aqm")
|
||||
map = new AQMMap(path);
|
||||
else if (suffix == "sqlitedb")
|
||||
map = new SqliteMap(path);
|
||||
else if (suffix == "wld" || suffix == "jgw" || suffix == "gfw"
|
||||
|| suffix == "pgw" || suffix == "tfw")
|
||||
map = new WorldFileMap(path, proj);
|
||||
|
||||
return map ? map : new InvalidMap(path, "Unknown file format");
|
||||
}
|
||||
|
||||
TreeNode<Map *> MapList::loadDir(const QString &path, TreeNode<Map *> *parent)
|
||||
TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map *> *parent)
|
||||
{
|
||||
QDir md(path);
|
||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -79,12 +84,12 @@ TreeNode<Map *> MapList::loadDir(const QString &path, TreeNode<Map *> *parent)
|
||||
QString suffix = fi.suffix().toLower();
|
||||
|
||||
if (fi.isDir()) {
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), &tree));
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), proj, &tree));
|
||||
if (!child.isEmpty())
|
||||
tree.addChild(child);
|
||||
} else if (filter().contains("*." + suffix)) {
|
||||
bool isDir = false;
|
||||
Map *map = loadFile(fi.absoluteFilePath(), &isDir);
|
||||
Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir);
|
||||
if (isDir) {
|
||||
if (parent)
|
||||
parent->addItem(map);
|
||||
@ -99,13 +104,13 @@ TreeNode<Map *> MapList::loadDir(const QString &path, TreeNode<Map *> *parent)
|
||||
return tree;
|
||||
}
|
||||
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path)
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path, const Projection &proj)
|
||||
{
|
||||
if (QFileInfo(path).isDir())
|
||||
return loadDir(path);
|
||||
return loadDir(path, proj);
|
||||
else {
|
||||
TreeNode<Map*> tree;
|
||||
tree.addItem(loadFile(path));
|
||||
tree.addItem(loadFile(path, proj));
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
@ -129,14 +134,17 @@ QString MapList::formats()
|
||||
+ " (*.sqlitedb);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||
+ qApp->translate("MapList", "GeoTIFF images") + " (*.tif *.tiff);;"
|
||||
+ qApp->translate("MapList", "World-file georeferenced images")
|
||||
+ " (*.wld *.jgw *.gfw *.pgw *.tfw);;"
|
||||
+ qApp->translate("MapList", "Online map sources") + " (*.xml)";
|
||||
}
|
||||
|
||||
QStringList MapList::filter()
|
||||
{
|
||||
QStringList filter;
|
||||
filter << "*.aqm" << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.kap"
|
||||
<< "*.kmz" << "*.map" << "*.mbtiles" << "*.rmap" << "*.rtmap"
|
||||
<< "*.sqlitedb" << "*.tar" << "*.tba" << "*.tif" << "*.tiff" << "*.xml";
|
||||
filter << "*.aqm" << "*.gfw" << "*.gmap" << "*.gmapi" << "*.img" << "*.jgw"
|
||||
<< "*.jnx" << "*.kap" << "*.kmz" << "*.map" << "*.mbtiles" << "*.pgw"
|
||||
<< "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba" << "*.tfw"
|
||||
<< "*.tif" << "*.tiff" << "*.wld" << "*.xml";
|
||||
return filter;
|
||||
}
|
||||
|
@ -5,17 +5,19 @@
|
||||
#include "common/treenode.h"
|
||||
|
||||
class Map;
|
||||
class Projection;
|
||||
|
||||
class MapList
|
||||
{
|
||||
public:
|
||||
static TreeNode<Map*> loadMaps(const QString &path);
|
||||
static TreeNode<Map*> loadMaps(const QString &path, const Projection &proj);
|
||||
static QString formats();
|
||||
static QStringList filter();
|
||||
|
||||
private:
|
||||
static Map *loadFile(const QString &path, bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path,
|
||||
static Map *loadFile(const QString &path, const Projection &proj,
|
||||
bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map *> *parent = 0);
|
||||
};
|
||||
|
||||
|
@ -44,10 +44,10 @@ Defense.
|
||||
#include "ellipsoid.h"
|
||||
#include "mercator.h"
|
||||
|
||||
Mercator::Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
Mercator::Mercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||
{
|
||||
double es = ellipsoid->es();
|
||||
double es = ellipsoid.es();
|
||||
double es2;
|
||||
double es3;
|
||||
double es4;
|
||||
@ -60,7 +60,7 @@ Mercator::Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
_falseNorthing = falseNorthing;
|
||||
_falseEasting = falseEasting;
|
||||
|
||||
_a = ellipsoid->radius();
|
||||
_a = ellipsoid.radius();
|
||||
_e = sqrt(es);
|
||||
|
||||
sin_olat = sin(_latitudeOrigin);
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class Mercator : public CT
|
||||
{
|
||||
public:
|
||||
Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
Mercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
virtual CT *clone() const {return new Mercator(*this);}
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define S1(x) ((1.0 + x) / (1.0 - x))
|
||||
#define S2(x) ((1.0 - _e * x) / (1.0 + _e * x))
|
||||
|
||||
ObliqueStereographic::ObliqueStereographic(const Ellipsoid *ellipsoid,
|
||||
ObliqueStereographic::ObliqueStereographic(const Ellipsoid &ellipsoid,
|
||||
double latitudeOrigin, double longitudeOrigin, double scale,
|
||||
double falseEasting, double falseNorthing)
|
||||
: _fe(falseEasting), _fn(falseNorthing)
|
||||
@ -15,8 +15,8 @@ ObliqueStereographic::ObliqueStereographic(const Ellipsoid *ellipsoid,
|
||||
double cosPhi0 = cos(lat0);
|
||||
double sinLat0s = sinPhi0 * sinPhi0;
|
||||
|
||||
double a = ellipsoid->radius();
|
||||
_es = ellipsoid->es();
|
||||
double a = ellipsoid.radius();
|
||||
_es = ellipsoid.es();
|
||||
_e = sqrt(_es);
|
||||
|
||||
double rho0 = a * (1.0 - _es) / pow(1.0 - _es * sinLat0s, 1.5);
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class ObliqueStereographic : public CT
|
||||
{
|
||||
public:
|
||||
ObliqueStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
ObliqueStereographic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double scale, double falseEasting,
|
||||
double falseNorthing);
|
||||
|
||||
|
@ -25,7 +25,7 @@ QList<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),
|
||||
PCS(GCS::WGS84(), 1024, Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN),
|
||||
9001, 4499)));
|
||||
return list;
|
||||
}
|
||||
@ -117,22 +117,26 @@ static int projectionSetup(const QList<QByteArray> &list,
|
||||
}
|
||||
|
||||
|
||||
const PCS *PCS::pcs(int id)
|
||||
const PCS &PCS::pcs(int id)
|
||||
{
|
||||
static const PCS null;
|
||||
|
||||
for (int i = 0; i < _pcss.size(); i++)
|
||||
if (_pcss.at(i).id() == id)
|
||||
return &(_pcss.at(i).pcs());
|
||||
return _pcss.at(i).pcs();
|
||||
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
const PCS *PCS::pcs(const GCS *gcs, int proj)
|
||||
const 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());
|
||||
static const PCS null;
|
||||
|
||||
return 0;
|
||||
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 null;
|
||||
}
|
||||
|
||||
void PCS::loadList(const QString &path)
|
||||
@ -140,7 +144,7 @@ void PCS::loadList(const QString &path)
|
||||
QFile file(path);
|
||||
bool res;
|
||||
int ln = 0, pn;
|
||||
const GCS *gcs;
|
||||
|
||||
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
|
||||
@ -206,7 +210,8 @@ void PCS::loadList(const QString &path)
|
||||
ln);
|
||||
continue;
|
||||
}
|
||||
if (!(gcs = GCS::gcs(gcsid))) {
|
||||
const GCS &gcs = GCS::gcs(gcsid);
|
||||
if (gcs.isNull()) {
|
||||
qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
@ -236,7 +241,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() << ", "
|
||||
dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.method() << ", "
|
||||
<< pcs.units() << ", " << pcs.setup() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
@ -12,29 +12,31 @@
|
||||
class PCS
|
||||
{
|
||||
public:
|
||||
PCS() : _gcs(0) {}
|
||||
PCS(const GCS *gcs, const Projection::Method &method,
|
||||
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, int proj);
|
||||
|
||||
const GCS *gcs() const {return _gcs;}
|
||||
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;}
|
||||
|
||||
bool isNull() const
|
||||
{return (!_gcs && _units.isNull() && _method.isNull() && _setup.isNull()
|
||||
&& _cs.isNull());}
|
||||
bool isValid() const
|
||||
{return (_gcs && _gcs->isValid() && _units.isValid()
|
||||
&& _method.isValid() && _cs.isValid());}
|
||||
bool isNull() const {
|
||||
return (_gcs.isNull() && _units.isNull() && _method.isNull()
|
||||
&& _setup.isNull() && _cs.isNull());
|
||||
}
|
||||
bool isValid() const {
|
||||
return (_gcs.isValid() && _units.isValid() && _method.isValid()
|
||||
&& _cs.isValid());
|
||||
}
|
||||
|
||||
static void loadList(const QString &path);
|
||||
static const PCS *pcs(int id);
|
||||
static const PCS *pcs(const GCS *gcs, int proj);
|
||||
static const PCS &pcs(int id);
|
||||
static const PCS &pcs(const GCS &gcs, int proj);
|
||||
static QList<KV<int, QString> > list();
|
||||
|
||||
private:
|
||||
@ -42,7 +44,7 @@ private:
|
||||
|
||||
static QList<Entry> defaults();
|
||||
|
||||
const GCS *_gcs;
|
||||
GCS _gcs;
|
||||
Projection::Method _method;
|
||||
Projection::Setup _setup;
|
||||
LinearUnits _units;
|
||||
|
@ -47,11 +47,11 @@ Defense.
|
||||
|
||||
#define POLAR_POW(EsSin) pow((1.0 - EsSin) / (1.0 + EsSin), _es_OVER_2)
|
||||
|
||||
PolarStereographic::PolarStereographic(const Ellipsoid *ellipsoid,
|
||||
PolarStereographic::PolarStereographic(const Ellipsoid &ellipsoid,
|
||||
double latitudeOrigin, double longitudeOrigin,
|
||||
double falseEasting, double falseNorthing)
|
||||
{
|
||||
_two_a = 2.0 * ellipsoid->radius();
|
||||
_two_a = 2.0 * ellipsoid.radius();
|
||||
|
||||
if (longitudeOrigin > M_PI)
|
||||
longitudeOrigin -= 2*M_PI;
|
||||
@ -68,7 +68,7 @@ PolarStereographic::PolarStereographic(const Ellipsoid *ellipsoid,
|
||||
_falseEasting = falseEasting;
|
||||
_falseNorthing = falseNorthing;
|
||||
|
||||
double es2 = ellipsoid->es();
|
||||
double es2 = ellipsoid.es();
|
||||
_es = sqrt(es2);
|
||||
_es_OVER_2 = _es / 2.0;
|
||||
|
||||
@ -78,7 +78,7 @@ PolarStereographic::PolarStereographic(const Ellipsoid *ellipsoid,
|
||||
double pow_es = POLAR_POW(essin);
|
||||
double clat = cos(_originLatitude);
|
||||
_mc = clat / sqrt(1.0 - essin * essin);
|
||||
_a_mc = ellipsoid->radius() * _mc;
|
||||
_a_mc = ellipsoid.radius() * _mc;
|
||||
_tc = tan(M_PI_4 - _originLatitude / 2.0) / pow_es;
|
||||
} else {
|
||||
double one_PLUS_es = 1.0 + _es;
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class PolarStereographic : public CT
|
||||
{
|
||||
public:
|
||||
PolarStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
PolarStereographic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
virtual CT *clone() const {return new PolarStereographic(*this);}
|
||||
|
@ -51,7 +51,7 @@ Defense.
|
||||
#define FLOAT_EQ(x, v, epsilon) \
|
||||
(((v - epsilon) < x) && (x < (v + epsilon)))
|
||||
|
||||
Polyconic::Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
Polyconic::Polyconic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||
{
|
||||
double j, three_es4;
|
||||
@ -61,8 +61,8 @@ Polyconic::Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
|
||||
_longitudeOrigin = deg2rad(longitudeOrigin);
|
||||
_latitudeOrigin = deg2rad(latitudeOrigin);
|
||||
_a = ellipsoid->radius();
|
||||
_b = ellipsoid->b();
|
||||
_a = ellipsoid.radius();
|
||||
_b = ellipsoid.b();
|
||||
if (_longitudeOrigin > M_PI)
|
||||
_longitudeOrigin -= 2 * M_PI;
|
||||
_falseNorthing = falseNorthing;
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class Polyconic : public CT
|
||||
{
|
||||
public:
|
||||
Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
Polyconic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
virtual CT *clone() const {return new Polyconic(*this);}
|
||||
|
@ -9,6 +9,7 @@ class PrimeMeridian
|
||||
public:
|
||||
PrimeMeridian() : _pm(NAN) {}
|
||||
PrimeMeridian(int code);
|
||||
PrimeMeridian(double lon) : _pm(lon) {}
|
||||
|
||||
bool isNull() const {return std::isnan(_pm);}
|
||||
bool isValid() const {return !std::isnan(_pm);}
|
||||
|
665
src/map/prjfile.cpp
Normal file
665
src/map/prjfile.cpp
Normal file
@ -0,0 +1,665 @@
|
||||
#include <QFile>
|
||||
#include "gcs.h"
|
||||
#include "pcs.h"
|
||||
#include "prjfile.h"
|
||||
|
||||
|
||||
#define ARRAY_SIZE(array) \
|
||||
(sizeof(array) / sizeof(array[0]))
|
||||
|
||||
static Projection::Method projectionMethod(const QString &name)
|
||||
{
|
||||
static const struct {
|
||||
int id;
|
||||
QString name;
|
||||
} methods[] = {
|
||||
{1024, "Mercator_Auxiliary_Sphere"},
|
||||
{1041, "Krovak"},
|
||||
{9801, "Lambert_Conformal_Conic_1SP"},
|
||||
{9802, "Lambert_Conformal_Conic_2SP"},
|
||||
{9804, "Mercator_1SP"},
|
||||
{9807, "Transverse_Mercator"},
|
||||
{9809, "Oblique_Stereographic"},
|
||||
{9815, "Oblique_Mercator"},
|
||||
{9818, "Polyconic"},
|
||||
{9820, "Lambert_Azimuthal_Equal_Area"},
|
||||
{9822, "Albers_Conic_Equal_Area"},
|
||||
{9829, "Polar_Stereographic"}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(methods); i++)
|
||||
if (!name.compare(methods[i].name, Qt::CaseInsensitive))
|
||||
return methods[i].id;
|
||||
|
||||
qWarning("%s: unknown projection", qPrintable(name));
|
||||
|
||||
return Projection::Method();
|
||||
}
|
||||
|
||||
static void setParameter(Projection::Setup *setup, const QString &name,
|
||||
double val)
|
||||
{
|
||||
// latitude origin
|
||||
if (!name.compare("latitude_of_origin", Qt::CaseInsensitive))
|
||||
setup->setLatitudeOrigin(val);
|
||||
else if (!name.compare("latitude_of_center", Qt::CaseInsensitive))
|
||||
setup->setLatitudeOrigin(val);
|
||||
// longitude origin
|
||||
else if (!name.compare("central_meridian", Qt::CaseInsensitive))
|
||||
setup->setLongitudeOrigin(val);
|
||||
else if (!name.compare("longitude_of_center", Qt::CaseInsensitive))
|
||||
setup->setLongitudeOrigin(val);
|
||||
// scale factor
|
||||
else if (!name.compare("scale_factor", Qt::CaseInsensitive))
|
||||
setup->setScale(val);
|
||||
// false easting
|
||||
else if (!name.compare("false_easting", Qt::CaseInsensitive))
|
||||
setup->setFalseEasting(val);
|
||||
// false northing
|
||||
else if (!name.compare("false_northing", Qt::CaseInsensitive))
|
||||
setup->setFalseNorthing(val);
|
||||
// standard parallel 1
|
||||
else if (!name.compare("standard_parallel_1", Qt::CaseInsensitive))
|
||||
setup->setStandardParallel1(val);
|
||||
else if (!name.compare("pseudo_standard_parallel_1", Qt::CaseInsensitive))
|
||||
setup->setStandardParallel1(val);
|
||||
// standard parallel 2
|
||||
else if (!name.compare("standard_parallel_2", Qt::CaseInsensitive))
|
||||
setup->setStandardParallel2(val);
|
||||
else if (!name.compare("azimuth", Qt::CaseInsensitive))
|
||||
setup->setStandardParallel2(val);
|
||||
else
|
||||
qWarning("%s: unknown projection parameter", qPrintable(name));
|
||||
}
|
||||
|
||||
PRJFile::Token PRJFile::keyword(CTX &ctx)
|
||||
{
|
||||
static const struct {
|
||||
Token token;
|
||||
QString name;
|
||||
} keywords[] = {
|
||||
{PROJCS, "PROJCS"},
|
||||
{PROJECTION, "PROJECTION"},
|
||||
{PARAMETER, "PARAMETER"},
|
||||
{GEOGCS, "GEOGCS"},
|
||||
{DATUM, "DATUM"},
|
||||
{SPHEROID, "SPHEROID"},
|
||||
{PRIMEM, "PRIMEM"},
|
||||
{UNIT, "UNIT"},
|
||||
{AUTHORITY, "AUTHORITY"},
|
||||
{AXIS, "AXIS"},
|
||||
{TOWGS84, "TOWGS84"},
|
||||
{NORTH, "NORTH"},
|
||||
{SOUTH, "SOUTH"},
|
||||
{EAST, "EAST"},
|
||||
{WEST, "WEST"},
|
||||
{UP, "UP"},
|
||||
{DOWN, "DOWN"},
|
||||
{OTHER, "OTHER"}
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(keywords); i++)
|
||||
if (!ctx.string.compare(keywords[i].name, Qt::CaseInsensitive))
|
||||
return keywords[i].token;
|
||||
|
||||
error(ctx);
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
void PRJFile::error(CTX &ctx)
|
||||
{
|
||||
if (ctx.token == ERROR)
|
||||
return;
|
||||
|
||||
_errorString = "parse error";
|
||||
ctx.token = ERROR;
|
||||
}
|
||||
|
||||
int PRJFile::getChar(CTX &ctx)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (ctx.file.getChar(&c))
|
||||
return c;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void PRJFile::nextToken(CTX &ctx)
|
||||
{
|
||||
int c, state = 0;
|
||||
QString flstr;
|
||||
|
||||
while (1) {
|
||||
c = getChar(ctx);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (isspace(c))
|
||||
break;
|
||||
if (c == '[') {
|
||||
ctx.token = LBRK;
|
||||
return;
|
||||
}
|
||||
if (c == ']') {
|
||||
ctx.token = RBRK;
|
||||
return;
|
||||
}
|
||||
if (c == ',') {
|
||||
ctx.token = COMMA;
|
||||
return;
|
||||
}
|
||||
if (isalpha(c)) {
|
||||
ctx.string = c;
|
||||
state = 2;
|
||||
break;
|
||||
}
|
||||
if (isdigit(c)) {
|
||||
flstr += c;
|
||||
state = 3;
|
||||
break;
|
||||
}
|
||||
if (c == '.') {
|
||||
flstr += c;
|
||||
state = 4;
|
||||
break;
|
||||
}
|
||||
if (c == '+') {
|
||||
flstr += c;
|
||||
state = 3;
|
||||
break;
|
||||
}
|
||||
if (c == '-') {
|
||||
flstr += c;
|
||||
state = 3;
|
||||
break;
|
||||
}
|
||||
if (c == '"') {
|
||||
ctx.string.clear();
|
||||
state = 7;
|
||||
break;
|
||||
}
|
||||
if (c == -1) {
|
||||
ctx.token = EOI;
|
||||
return;
|
||||
}
|
||||
error(ctx);
|
||||
return;
|
||||
|
||||
case 2:
|
||||
if (isalnum(c)) {
|
||||
ctx.string += c;
|
||||
break;
|
||||
}
|
||||
ctx.file.ungetChar(c);
|
||||
ctx.token = keyword(ctx);
|
||||
return;
|
||||
|
||||
case 3:
|
||||
if (c == '.') {
|
||||
flstr += c;
|
||||
state = 4;
|
||||
break;
|
||||
}
|
||||
if (c == 'e' || c == 'E') {
|
||||
flstr += c;
|
||||
state = 5;
|
||||
break;
|
||||
}
|
||||
if (isdigit(c)) {
|
||||
flstr += c;
|
||||
break;
|
||||
}
|
||||
ctx.file.ungetChar(c);
|
||||
ctx.number = flstr.toDouble();
|
||||
ctx.token = NUMBER;
|
||||
return;
|
||||
|
||||
case 4:
|
||||
if (isdigit(c)) {
|
||||
flstr += c;
|
||||
break;
|
||||
}
|
||||
if (c == 'e' || c == 'E') {
|
||||
flstr += c;
|
||||
state = 5;
|
||||
break;
|
||||
}
|
||||
ctx.file.ungetChar(c);
|
||||
ctx.number = flstr.toDouble();
|
||||
ctx.token = NUMBER;
|
||||
return;
|
||||
|
||||
case 5:
|
||||
if (c == '+') {
|
||||
flstr += c;
|
||||
state = 6;
|
||||
break;
|
||||
}
|
||||
if (c == '-') {
|
||||
flstr += c;
|
||||
state = 6;
|
||||
break;
|
||||
}
|
||||
if (isdigit(c)) {
|
||||
flstr += c;
|
||||
state = 6;
|
||||
break;
|
||||
}
|
||||
error(ctx);
|
||||
return;
|
||||
|
||||
case 6:
|
||||
if (isdigit(c)) {
|
||||
flstr += c;
|
||||
break;
|
||||
}
|
||||
ctx.file.ungetChar(c);
|
||||
ctx.number = flstr.toDouble();
|
||||
ctx.token = NUMBER;
|
||||
return;
|
||||
|
||||
case 7:
|
||||
if (c == -1) {
|
||||
error(ctx);
|
||||
return;
|
||||
}
|
||||
if (c == '"') {
|
||||
ctx.token = STRING;
|
||||
return;
|
||||
}
|
||||
ctx.string += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::compare(CTX &ctx, Token token)
|
||||
{
|
||||
if (ctx.token == token)
|
||||
nextToken(ctx);
|
||||
else
|
||||
error(ctx);
|
||||
}
|
||||
|
||||
void PRJFile::toWGS84(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds)
|
||||
{
|
||||
compare(ctx, TOWGS84);
|
||||
compare(ctx, LBRK);
|
||||
*dx = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*dy = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*dz = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*rx = -ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*ry = -ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*rz = -ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
*ds = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, RBRK);
|
||||
}
|
||||
|
||||
void PRJFile::optAuthority(CTX &ctx, int *epsg)
|
||||
{
|
||||
if (ctx.token == COMMA) {
|
||||
nextToken(ctx);
|
||||
authority(ctx, epsg);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::authority(CTX &ctx, int *epsg)
|
||||
{
|
||||
bool isEpsg = false;
|
||||
|
||||
compare(ctx, AUTHORITY);
|
||||
compare(ctx, LBRK);
|
||||
|
||||
if (!ctx.string.compare("EPSG", Qt::CaseInsensitive))
|
||||
isEpsg = true;
|
||||
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
|
||||
if (isEpsg) {
|
||||
bool ok;
|
||||
*epsg = ctx.string.toUInt(&ok);
|
||||
if (!ok) {
|
||||
_errorString = ctx.string + ": invalid EPSG code";
|
||||
ctx.token = ERROR;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
*epsg = -1;
|
||||
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, RBRK);
|
||||
}
|
||||
|
||||
void PRJFile::spheroid(CTX &ctx, Ellipsoid *el)
|
||||
{
|
||||
int epsg = -1;
|
||||
double radius, flattening;
|
||||
|
||||
compare(ctx, SPHEROID);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
radius = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, COMMA);
|
||||
flattening = 1.0 / ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
optAuthority(ctx, &epsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*el = (epsg > 0)
|
||||
? Ellipsoid::ellipsoid(epsg)
|
||||
: Ellipsoid(radius, flattening);
|
||||
}
|
||||
|
||||
void PRJFile::optDatum2(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds, int *epsg)
|
||||
{
|
||||
switch (ctx.token) {
|
||||
case TOWGS84:
|
||||
toWGS84(ctx, dx, dy, dz, rx, ry, rz, ds);
|
||||
optAuthority(ctx, epsg);
|
||||
break;
|
||||
case AUTHORITY:
|
||||
authority(ctx, epsg);
|
||||
break;
|
||||
default:
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::optDatum(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds, int *epsg)
|
||||
{
|
||||
if (ctx.token == COMMA) {
|
||||
nextToken(ctx);
|
||||
optDatum2(ctx, dx, dy, dz, rx, ry, rz, ds, epsg);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::datum(CTX &ctx, Datum *dtm, int *epsg)
|
||||
{
|
||||
double dx = NAN, dy = NAN, dz = NAN, rx = NAN, ry = NAN, rz = NAN, ds = NAN;
|
||||
Ellipsoid el;
|
||||
|
||||
compare(ctx, DATUM);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
spheroid(ctx, &el);
|
||||
optDatum(ctx, &dx, &dy, &dz, &rx, &ry, &rz, &ds, epsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*dtm = Datum(el, dx, dy, dz, rx, ry, rz, ds);
|
||||
}
|
||||
|
||||
void PRJFile::unit(CTX &ctx, double *val, int *epsg)
|
||||
{
|
||||
compare(ctx, UNIT);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
*val = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
optAuthority(ctx, epsg);
|
||||
compare(ctx, RBRK);
|
||||
}
|
||||
|
||||
void PRJFile::linearUnit(CTX &ctx, LinearUnits *lu)
|
||||
{
|
||||
double val;
|
||||
int epsg = -1;
|
||||
|
||||
unit(ctx, &val, &epsg);
|
||||
*lu = (epsg > 0) ? LinearUnits(epsg) : LinearUnits(val);
|
||||
}
|
||||
|
||||
void PRJFile::angularUnit(CTX &ctx, AngularUnits *au, int *epsg)
|
||||
{
|
||||
double val;
|
||||
|
||||
unit(ctx, &val, epsg);
|
||||
*au = AngularUnits(val);
|
||||
}
|
||||
|
||||
void PRJFile::primeMeridian(CTX &ctx, PrimeMeridian *pm, int *epsg)
|
||||
{
|
||||
double lon;
|
||||
|
||||
compare(ctx, PRIMEM);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
lon = ctx.number;
|
||||
compare(ctx, NUMBER);
|
||||
optAuthority(ctx, epsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*pm = PrimeMeridian(lon);
|
||||
}
|
||||
|
||||
void PRJFile::parameter(CTX &ctx, Projection::Setup *setup)
|
||||
{
|
||||
QString name;
|
||||
|
||||
if (ctx.token == PARAMETER) {
|
||||
nextToken(ctx);
|
||||
compare(ctx, LBRK);
|
||||
name = ctx.string;
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
setParameter(setup, name, ctx.number);
|
||||
compare(ctx, NUMBER);
|
||||
compare(ctx, RBRK);
|
||||
compare(ctx, COMMA);
|
||||
parameter(ctx, setup);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::projection(CTX &ctx, Projection::Method *method)
|
||||
{
|
||||
int epsg = -1;
|
||||
QString proj;
|
||||
|
||||
compare(ctx, PROJECTION);
|
||||
compare(ctx, LBRK);
|
||||
proj = ctx.string;
|
||||
compare(ctx, STRING);
|
||||
optAuthority(ctx, &epsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*method = (epsg > 0) ? Projection::Method(epsg) : projectionMethod(proj);
|
||||
}
|
||||
|
||||
void PRJFile::optProjectedCS2(CTX &ctx, int *epsg)
|
||||
{
|
||||
switch (ctx.token) {
|
||||
case AXIS:
|
||||
twinAxis(ctx);
|
||||
optAuthority(ctx, epsg);
|
||||
break;
|
||||
case AUTHORITY:
|
||||
authority(ctx, epsg);
|
||||
break;
|
||||
default:
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::optProjectedCS(CTX &ctx, int *epsg)
|
||||
{
|
||||
if (ctx.token == COMMA) {
|
||||
nextToken(ctx);
|
||||
optProjectedCS2(ctx, epsg);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::projectedCS(CTX &ctx, PCS *pcs)
|
||||
{
|
||||
int epsg = -1;
|
||||
GCS gcs;
|
||||
LinearUnits lu;
|
||||
CoordinateSystem cs(CoordinateSystem::XY);
|
||||
Projection::Method method;
|
||||
Projection::Setup setup;
|
||||
|
||||
compare(ctx, PROJCS);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
geographicCS(ctx, &gcs);
|
||||
compare(ctx, COMMA);
|
||||
projection(ctx, &method);
|
||||
compare(ctx, COMMA);
|
||||
parameter(ctx, &setup);
|
||||
linearUnit(ctx, &lu);
|
||||
optProjectedCS(ctx, &epsg);
|
||||
|
||||
*pcs = (epsg > 0) ? PCS::pcs(epsg) : PCS(gcs, method, setup, lu, cs);
|
||||
}
|
||||
|
||||
void PRJFile::axisType(CTX &ctx)
|
||||
{
|
||||
switch (ctx.token) {
|
||||
case NORTH:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case SOUTH:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case EAST:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case WEST:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case UP:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case DOWN:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
case OTHER:
|
||||
nextToken(ctx);
|
||||
break;
|
||||
default:
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::axis(CTX &ctx)
|
||||
{
|
||||
compare(ctx, AXIS);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
axisType(ctx);
|
||||
compare(ctx, RBRK);
|
||||
}
|
||||
|
||||
void PRJFile::twinAxis(CTX &ctx)
|
||||
{
|
||||
axis(ctx);
|
||||
compare(ctx, COMMA);
|
||||
axis(ctx);
|
||||
}
|
||||
|
||||
void PRJFile::optGeographicCS2(CTX &ctx, int *epsg)
|
||||
{
|
||||
switch (ctx.token) {
|
||||
case AXIS:
|
||||
twinAxis(ctx);
|
||||
optAuthority(ctx, epsg);
|
||||
break;
|
||||
case AUTHORITY:
|
||||
authority(ctx, epsg);
|
||||
break;
|
||||
default:
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::optGeographicCS(CTX &ctx, int *epsg)
|
||||
{
|
||||
if (ctx.token == COMMA) {
|
||||
nextToken(ctx);
|
||||
optGeographicCS2(ctx, epsg);
|
||||
}
|
||||
}
|
||||
|
||||
void PRJFile::geographicCS(CTX &ctx, GCS *gcs)
|
||||
{
|
||||
int gcsEpsg = -1, datumEpsg = -1, pmEpsg = -1, auEpsg = -1;
|
||||
PrimeMeridian pm;
|
||||
AngularUnits au;
|
||||
Datum dat;
|
||||
|
||||
compare(ctx, GEOGCS);
|
||||
compare(ctx, LBRK);
|
||||
compare(ctx, STRING);
|
||||
compare(ctx, COMMA);
|
||||
datum(ctx, &dat, &datumEpsg);
|
||||
compare(ctx, COMMA);
|
||||
primeMeridian(ctx, &pm, &pmEpsg);
|
||||
compare(ctx, COMMA);
|
||||
angularUnit(ctx, &au, &auEpsg);
|
||||
optGeographicCS(ctx, &gcsEpsg);
|
||||
compare(ctx, RBRK);
|
||||
|
||||
*gcs = (gcsEpsg > 0)
|
||||
? GCS::gcs(gcsEpsg)
|
||||
: (datumEpsg > 0 && pmEpsg > 0 && auEpsg > 0)
|
||||
? GCS::gcs(datumEpsg, pmEpsg, auEpsg)
|
||||
: GCS(dat, pm, au);
|
||||
}
|
||||
|
||||
void PRJFile::horizontalCS(CTX &ctx)
|
||||
{
|
||||
switch (ctx.token) {
|
||||
case PROJCS:
|
||||
{PCS pcs;
|
||||
projectedCS(ctx, &pcs);
|
||||
_projection = Projection(pcs);}
|
||||
break;
|
||||
case GEOGCS:
|
||||
{GCS gcs;
|
||||
geographicCS(ctx, &gcs);
|
||||
_projection = Projection(gcs);}
|
||||
break;
|
||||
default:
|
||||
error(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
PRJFile::PRJFile(const QString &fileName)
|
||||
{
|
||||
CTX ctx(fileName);
|
||||
|
||||
if (!ctx.file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = ctx.file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
nextToken(ctx);
|
||||
horizontalCS(ctx);
|
||||
|
||||
if (ctx.token != ERROR && !_projection.isValid())
|
||||
_errorString = "invalid/incomplete projection";
|
||||
}
|
83
src/map/prjfile.h
Normal file
83
src/map/prjfile.h
Normal file
@ -0,0 +1,83 @@
|
||||
#ifndef PRJFILE_H
|
||||
#define PRJFILE_H
|
||||
|
||||
#include <QFile>
|
||||
#include "projection.h"
|
||||
|
||||
class Datum;
|
||||
class Ellipsoid;
|
||||
class PrimeMeridian;
|
||||
|
||||
class PRJFile
|
||||
{
|
||||
public:
|
||||
PRJFile(const QString &fileName);
|
||||
|
||||
const Projection projection() const {return _projection;}
|
||||
const QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
enum Token {
|
||||
START, /* Initial value */
|
||||
EOI, /* End of File */
|
||||
ERROR, /* Parse error */
|
||||
|
||||
NUMBER, /* Real number */
|
||||
STRING, /* String */
|
||||
|
||||
LBRK, /* '[' */
|
||||
RBRK, /* ']' */
|
||||
COMMA, /* ',' */
|
||||
|
||||
/* Keywords */
|
||||
PROJCS, PROJECTION, GEOGCS, DATUM, SPHEROID, PRIMEM, UNIT, AUTHORITY,
|
||||
AXIS, TOWGS84, PARAMETER, NORTH, SOUTH, EAST, WEST, UP, DOWN, OTHER
|
||||
};
|
||||
|
||||
struct CTX {
|
||||
CTX(const QString &fileName) : file(fileName), token(START) {}
|
||||
|
||||
QFile file;
|
||||
Token token;
|
||||
QString string;
|
||||
double number;
|
||||
};
|
||||
|
||||
Token keyword(CTX &ctx);
|
||||
int getChar(CTX &ctx);
|
||||
void error(CTX &ctx);
|
||||
void nextToken(CTX &ctx);
|
||||
void compare(CTX &ctx, Token token);
|
||||
|
||||
void horizontalCS(CTX &ctx);
|
||||
void geographicCS(CTX &ctx, GCS *gcs);
|
||||
void projectedCS(CTX &ctx, PCS *pcs);
|
||||
void projection(CTX &ctx, Projection::Method *method);
|
||||
void parameter(CTX &ctx, Projection::Setup *setup);
|
||||
void datum(CTX &ctx, Datum *dtm, int *epsg);
|
||||
void unit(CTX &ctx, double *val, int *epsg);
|
||||
void angularUnit(CTX &ctx, AngularUnits *au, int *epsg);
|
||||
void primeMeridian(CTX &ctx, PrimeMeridian *pm, int *epsg);
|
||||
void linearUnit(CTX &ctx, LinearUnits *lu);
|
||||
void spheroid(CTX &ctx, Ellipsoid *el);
|
||||
void authority(CTX &ctx, int *epsg);
|
||||
void toWGS84(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds);
|
||||
void twinAxis(CTX &ctx);
|
||||
void axis(CTX &ctx);
|
||||
void axisType(CTX &ctx);
|
||||
void optAuthority(CTX &ctx, int *epsg);
|
||||
void optDatum(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds, int *epsg);
|
||||
void optDatum2(CTX &ctx, double *dx, double *dy, double *dz, double *rx,
|
||||
double *ry, double *rz, double *ds, int *epsg);
|
||||
void optGeographicCS(CTX &ctx, int *epsg);
|
||||
void optGeographicCS2(CTX &ctx, int *epsg);
|
||||
void optProjectedCS(CTX &ctx, int *epsg);
|
||||
void optProjectedCS2(CTX &ctx, int *epsg);
|
||||
|
||||
Projection _projection;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // PRJFILE_H
|
@ -38,19 +38,14 @@ Projection::Method::Method(int id)
|
||||
}
|
||||
}
|
||||
|
||||
Projection::Projection(const PCS *pcs) : _gcs(0), _ct(0), _geographic(false)
|
||||
Projection::Projection(const PCS &pcs)
|
||||
: _gcs(pcs.gcs()), _ct(0), _units(pcs.units()), _cs(pcs.coordinateSystem()),
|
||||
_geographic(false)
|
||||
{
|
||||
if (!pcs)
|
||||
return;
|
||||
const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid();
|
||||
const Projection::Setup &setup = pcs.setup();
|
||||
|
||||
_gcs = pcs->gcs();
|
||||
_units = pcs->units();
|
||||
_cs = pcs->coordinateSystem();
|
||||
|
||||
const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid();
|
||||
const Projection::Setup &setup = pcs->setup();
|
||||
|
||||
switch (pcs->method().id()) {
|
||||
switch (pcs.method().id()) {
|
||||
case 1024:
|
||||
_ct = new WebMercator();
|
||||
break;
|
||||
@ -119,13 +114,10 @@ Projection::Projection(const PCS *pcs) : _gcs(0), _ct(0), _geographic(false)
|
||||
}
|
||||
}
|
||||
|
||||
Projection::Projection(const GCS *gcs, const CoordinateSystem &cs)
|
||||
Projection::Projection(const GCS &gcs, const CoordinateSystem &cs)
|
||||
: _gcs(gcs), _ct(0), _units(LinearUnits(9001)), _cs(cs), _geographic(true)
|
||||
{
|
||||
if (!gcs)
|
||||
return;
|
||||
|
||||
_ct = new LatLon(gcs->angularUnits());
|
||||
_ct = new LatLon(gcs.angularUnits());
|
||||
}
|
||||
|
||||
Projection::Projection(const Projection &p)
|
||||
@ -162,20 +154,20 @@ bool Projection::operator==(const Projection &p) const
|
||||
if (!isValid() || !p.isValid())
|
||||
return false;
|
||||
|
||||
return (*_ct == *p._ct && *_gcs == *p._gcs && _units == p._units
|
||||
return (*_ct == *p._ct && _gcs == p._gcs && _units == p._units
|
||||
&& _cs == p._cs && _geographic == p._geographic);
|
||||
}
|
||||
|
||||
PointD Projection::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
Q_ASSERT(isValid());
|
||||
return _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c)));
|
||||
return _units.fromMeters(_ct->ll2xy(_gcs.fromWGS84(c)));
|
||||
}
|
||||
|
||||
Coordinates Projection::xy2ll(const PointD &p) const
|
||||
{
|
||||
Q_ASSERT(isValid());
|
||||
return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p)));
|
||||
return _gcs.toWGS84(_ct->xy2ll(_units.toMeters(p)));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
|
@ -6,8 +6,8 @@
|
||||
#include "pointd.h"
|
||||
#include "linearunits.h"
|
||||
#include "coordinatesystem.h"
|
||||
#include "gcs.h"
|
||||
|
||||
class GCS;
|
||||
class PCS;
|
||||
class CT;
|
||||
class AngularUnits;
|
||||
@ -70,18 +70,18 @@ public:
|
||||
int _id;
|
||||
};
|
||||
|
||||
Projection() : _gcs(0), _ct(0), _geographic(false) {}
|
||||
Projection() : _ct(0), _geographic(false) {}
|
||||
Projection(const Projection &p);
|
||||
Projection(const PCS *pcs);
|
||||
Projection(const GCS *gcs, const CoordinateSystem &cs
|
||||
Projection(const PCS &pcs);
|
||||
Projection(const GCS &gcs, const CoordinateSystem &cs
|
||||
= CoordinateSystem(CoordinateSystem::YX));
|
||||
~Projection();
|
||||
|
||||
Projection &operator=(const Projection &p);
|
||||
bool operator==(const Projection &p) const;
|
||||
|
||||
bool isNull() const {return (_gcs == 0 && _ct == 0 && _units.isNull());}
|
||||
bool isValid() const {return !(_gcs == 0 || _ct == 0 || _units.isNull());}
|
||||
bool isNull() const {return (_gcs.isNull() && _ct == 0 && _units.isNull());}
|
||||
bool isValid() const {return _gcs.isValid() && _ct != 0 && _units.isValid();}
|
||||
bool isGeographic() const {return _geographic;}
|
||||
|
||||
PointD ll2xy(const Coordinates &c) const;
|
||||
@ -91,7 +91,7 @@ public:
|
||||
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
||||
|
||||
private:
|
||||
const GCS *_gcs;
|
||||
GCS _gcs;
|
||||
const CT *_ct;
|
||||
LinearUnits _units;
|
||||
CoordinateSystem _cs;
|
||||
|
@ -40,7 +40,7 @@ static CalibrationPoint parseCalibrationPoint(const QString &str)
|
||||
: CalibrationPoint(xy, pp);
|
||||
}
|
||||
|
||||
static Projection parseProjection(const QString &str, const GCS *gcs)
|
||||
static Projection parseProjection(const QString &str, const GCS &gcs)
|
||||
{
|
||||
QStringList fields(str.split(","));
|
||||
if (fields.isEmpty())
|
||||
@ -49,7 +49,6 @@ static Projection parseProjection(const QString &str, const GCS *gcs)
|
||||
int id = fields.at(0).toDouble(&ret);
|
||||
if (!ret)
|
||||
return Projection();
|
||||
PCS pcs;
|
||||
int zone;
|
||||
|
||||
switch (id) {
|
||||
@ -61,49 +60,40 @@ static Projection parseProjection(const QString &str, const GCS *gcs)
|
||||
return Projection();
|
||||
if (fields.at(3) == "S")
|
||||
zone = -zone;
|
||||
pcs = PCS(gcs, 9807, UTM::setup(zone), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9807, UTM::setup(zone), 9001));
|
||||
case 1: // LatLon
|
||||
return Projection(gcs);
|
||||
case 2: // Mercator
|
||||
pcs = PCS(gcs, 1024, Projection::Setup(), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 1024, Projection::Setup(), 9001));
|
||||
case 3: // Transversal Mercator
|
||||
if (fields.size() < 7)
|
||||
return Projection();
|
||||
pcs = PCS(gcs, 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);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 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));
|
||||
case 4: // Lambert 2SP
|
||||
if (fields.size() < 8)
|
||||
return Projection();
|
||||
pcs = PCS(gcs, 9802, Projection::Setup(fields.at(4).toDouble(),
|
||||
fields.at(5).toDouble(), NAN,
|
||||
return Projection(PCS(gcs, 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);
|
||||
return Projection(&pcs);
|
||||
fields.at(3).toDouble(), fields.at(2).toDouble()), 9001));
|
||||
case 6: // BGN (British National Grid)
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, 400000,
|
||||
-100000, NAN, NAN), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601,
|
||||
400000, -100000, NAN, NAN), 9001));
|
||||
case 12: // France Lambert II etendu
|
||||
pcs = PCS(gcs, 9801, Projection::Setup(52, 0, 0.99987742, 600000,
|
||||
2200000, NAN, NAN), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9801, Projection::Setup(52, 0,
|
||||
0.99987742, 600000, 2200000, NAN, NAN), 9001));
|
||||
case 14: // Swiss Grid
|
||||
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0,
|
||||
600000, 200000, 90.0, 90.0), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9815, Projection::Setup(46.570866,
|
||||
7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001));
|
||||
case 108: // Dutch RD grid
|
||||
pcs = PCS(gcs, 9809, Projection::Setup(52.15616055555555,
|
||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9809, Projection::Setup(52.15616055555555,
|
||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001));
|
||||
case 184: // Swedish Grid
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, 1500000, 0,
|
||||
NAN, NAN), 9001);
|
||||
return Projection(&pcs);
|
||||
return Projection(PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1,
|
||||
1500000, 0, NAN, NAN), 9001));
|
||||
default:
|
||||
return Projection();
|
||||
}
|
||||
@ -113,7 +103,6 @@ bool RMap::parseIMP(const QByteArray &data)
|
||||
{
|
||||
QStringList lines = QString(data).split("\r\n");
|
||||
QVector<CalibrationPoint> calibrationPoints;
|
||||
const GCS *gcs = 0;
|
||||
QString projection, datum;
|
||||
QRegularExpression re("^P[0-9]+=");
|
||||
|
||||
@ -136,7 +125,8 @@ bool RMap::parseIMP(const QByteArray &data)
|
||||
}
|
||||
}
|
||||
|
||||
if (!(gcs = GCS::gcs(datum))) {
|
||||
const GCS &gcs = GCS::gcs(datum);
|
||||
if (gcs.isNull()) {
|
||||
_errorString = datum + ": unknown/invalid datum";
|
||||
return false;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ Defense.
|
||||
((double)(_a * (1.e0 - _es) / pow(DENOM(lat), 3)))
|
||||
|
||||
|
||||
TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
|
||||
TransverseMercator::TransverseMercator(const Ellipsoid &ellipsoid,
|
||||
double latitudeOrigin, double longitudeOrigin, double scale,
|
||||
double falseEasting, double falseNorthing)
|
||||
{
|
||||
@ -65,16 +65,16 @@ TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
|
||||
double b;
|
||||
|
||||
|
||||
_a = ellipsoid->radius();
|
||||
_a = ellipsoid.radius();
|
||||
_longitudeOrigin = deg2rad(longitudeOrigin);
|
||||
_latitudeOrigin = deg2rad(latitudeOrigin);
|
||||
_scale = scale;
|
||||
_falseEasting = falseEasting;
|
||||
_falseNorthing = falseNorthing;
|
||||
|
||||
_es = ellipsoid->es();
|
||||
_es = ellipsoid.es();
|
||||
_ebs = (1 / (1 - _es)) - 1;
|
||||
b = ellipsoid->b();
|
||||
b = ellipsoid.b();
|
||||
|
||||
tn = (_a - b) / (_a + b);
|
||||
tn2 = tn * tn;
|
||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
||||
class TransverseMercator : public CT
|
||||
{
|
||||
public:
|
||||
TransverseMercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
TransverseMercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double scale, double falseEasting,
|
||||
double falseNorthing);
|
||||
|
||||
|
29
src/map/wldfile.cpp
Normal file
29
src/map/wldfile.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include <QFile>
|
||||
#include "wldfile.h"
|
||||
|
||||
WLDFile::WLDFile(const QString &fileName)
|
||||
{
|
||||
bool ok;
|
||||
double val[6];
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
QByteArray line(file.readLine().trimmed());
|
||||
val[i] = line.toDouble(&ok);
|
||||
if (!ok) {
|
||||
_errorString = line + ": invalid parameter";
|
||||
return;
|
||||
}
|
||||
}
|
||||
double matrix[16] = {val[0], val[1], 0, val[4], val[2], val[3], 0, val[5]};
|
||||
|
||||
_transform = Transform(matrix);
|
||||
|
||||
if (!_transform.isValid())
|
||||
_errorString = _transform.errorString();
|
||||
}
|
19
src/map/wldfile.h
Normal file
19
src/map/wldfile.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef WLDFILE_H
|
||||
#define WLDFILE_H
|
||||
|
||||
#include "transform.h"
|
||||
|
||||
class WLDFile
|
||||
{
|
||||
public:
|
||||
WLDFile(const QString &fileName);
|
||||
|
||||
const Transform &transform() const {return _transform;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
Transform _transform;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // WLDFILE_H
|
123
src/map/worldfilemap.cpp
Normal file
123
src/map/worldfilemap.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QPainter>
|
||||
#include <QImageReader>
|
||||
#include "image.h"
|
||||
#include "gcs.h"
|
||||
#include "prjfile.h"
|
||||
#include "wldfile.h"
|
||||
#include "worldfilemap.h"
|
||||
|
||||
|
||||
WorldFileMap::WorldFileMap(const QString &fileName, const Projection &proj,
|
||||
QObject *parent) : Map(fileName, parent), _projection(proj), _img(0),
|
||||
_ratio(1.0), _hasPRJ(false), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QDir dir(fi.absoluteDir());
|
||||
QString basename(fi.baseName());
|
||||
|
||||
|
||||
// Get transformation from the WLD file
|
||||
WLDFile wld(fileName);
|
||||
if (wld.transform().isValid())
|
||||
_transform = wld.transform();
|
||||
else {
|
||||
_errorString = wld.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the projection from PRJ file if any
|
||||
QString prjFile(basename + ".prj");
|
||||
if (dir.exists(prjFile)) {
|
||||
PRJFile prj(dir.filePath(prjFile));
|
||||
if (prj.projection().isValid()) {
|
||||
_projection = prj.projection();
|
||||
_hasPRJ = true;
|
||||
} else {
|
||||
_errorString = prjFile + ": " + prj.errorString();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the corresponding image file
|
||||
QList<QByteArray> formats(QImageReader::supportedImageFormats());
|
||||
QString imgFile;
|
||||
|
||||
for (int i = 0; i < formats.size(); i++) {
|
||||
imgFile = basename + "." + formats.at(i);
|
||||
if (dir.exists(imgFile)) {
|
||||
_imgFile = dir.filePath(imgFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_imgFile.isNull()) {
|
||||
_errorString = "image file not found";
|
||||
return;
|
||||
}
|
||||
|
||||
QImageReader ir(_imgFile);
|
||||
if (!ir.canRead()) {
|
||||
_errorString = imgFile + ": unsupported/invalid image file";
|
||||
return;
|
||||
}
|
||||
_size = ir.size();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
WorldFileMap::~WorldFileMap()
|
||||
{
|
||||
delete _img;
|
||||
}
|
||||
|
||||
QPointF WorldFileMap::ll2xy(const Coordinates &c)
|
||||
{
|
||||
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _ratio;
|
||||
}
|
||||
|
||||
Coordinates WorldFileMap::xy2ll(const QPointF &p)
|
||||
{
|
||||
return _projection.xy2ll(_transform.img2proj(p * _ratio));
|
||||
}
|
||||
|
||||
QRectF WorldFileMap::bounds()
|
||||
{
|
||||
return QRectF(QPointF(0, 0), _size / _ratio);
|
||||
}
|
||||
|
||||
void WorldFileMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
if (_img)
|
||||
_img->draw(painter, rect, flags);
|
||||
}
|
||||
|
||||
void WorldFileMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
|
||||
_ratio = mapRatio;
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
|
||||
void WorldFileMap::load()
|
||||
{
|
||||
if (!_img)
|
||||
_img = new Image(_imgFile);
|
||||
}
|
||||
|
||||
void WorldFileMap::unload()
|
||||
{
|
||||
delete _img;
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
void WorldFileMap::setInputProjection(const Projection &projection)
|
||||
{
|
||||
if (_hasPRJ || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
}
|
45
src/map/worldfilemap.h
Normal file
45
src/map/worldfilemap.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef WORLDFILEMAP_H
|
||||
#define WORLDFILEMAP_H
|
||||
|
||||
#include "transform.h"
|
||||
#include "projection.h"
|
||||
#include "map.h"
|
||||
|
||||
class Image;
|
||||
|
||||
class WorldFileMap : public Map
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WorldFileMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||
~WorldFileMap();
|
||||
|
||||
QRectF bounds();
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void setInputProjection(const Projection &projection);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
Projection _projection;
|
||||
Transform _transform;
|
||||
Image *_img;
|
||||
QSize _size;
|
||||
qreal _ratio;
|
||||
QString _imgFile;
|
||||
bool _hasPRJ;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // WORLDFILEMAP_H
|
Loading…
Reference in New Issue
Block a user