mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-02-17 16:20:48 +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/rastertile.h \
|
||||||
src/map/IMG/shield.h \
|
src/map/IMG/shield.h \
|
||||||
src/map/mapsforge/style.h \
|
src/map/mapsforge/style.h \
|
||||||
|
src/map/prjfile.h \
|
||||||
src/map/textpathitem.h \
|
src/map/textpathitem.h \
|
||||||
src/map/textpointitem.h \
|
src/map/textpointitem.h \
|
||||||
src/map/mapsforge/mapdata.h \
|
src/map/mapsforge/mapdata.h \
|
||||||
@ -149,6 +150,7 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/ct.h \
|
src/map/ct.h \
|
||||||
src/map/mapsource.h \
|
src/map/mapsource.h \
|
||||||
src/map/tileloader.h \
|
src/map/tileloader.h \
|
||||||
|
src/map/wldfile.h \
|
||||||
src/map/wmtsmap.h \
|
src/map/wmtsmap.h \
|
||||||
src/map/wmts.h \
|
src/map/wmts.h \
|
||||||
src/map/wmsmap.h \
|
src/map/wmsmap.h \
|
||||||
@ -221,7 +223,8 @@ HEADERS += src/common/config.h \
|
|||||||
src/data/geojsonparser.h \
|
src/data/geojsonparser.h \
|
||||||
src/GUI/timezoneinfo.h \
|
src/GUI/timezoneinfo.h \
|
||||||
src/map/aqmmap.h \
|
src/map/aqmmap.h \
|
||||||
src/map/mapsforgemap.h
|
src/map/mapsforgemap.h \
|
||||||
|
src/map/worldfilemap.h
|
||||||
|
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/GUI/axislabelitem.cpp \
|
src/GUI/axislabelitem.cpp \
|
||||||
@ -295,6 +298,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/IMG/mapdata.cpp \
|
src/map/IMG/mapdata.cpp \
|
||||||
src/map/IMG/rastertile.cpp \
|
src/map/IMG/rastertile.cpp \
|
||||||
src/map/mapsforge/style.cpp \
|
src/map/mapsforge/style.cpp \
|
||||||
|
src/map/prjfile.cpp \
|
||||||
src/map/textpathitem.cpp \
|
src/map/textpathitem.cpp \
|
||||||
src/map/textpointitem.cpp \
|
src/map/textpointitem.cpp \
|
||||||
src/map/mapsforge/mapdata.cpp \
|
src/map/mapsforge/mapdata.cpp \
|
||||||
@ -332,6 +336,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/linearunits.cpp \
|
src/map/linearunits.cpp \
|
||||||
src/map/mapsource.cpp \
|
src/map/mapsource.cpp \
|
||||||
src/map/tileloader.cpp \
|
src/map/tileloader.cpp \
|
||||||
|
src/map/wldfile.cpp \
|
||||||
src/map/wmtsmap.cpp \
|
src/map/wmtsmap.cpp \
|
||||||
src/map/wmts.cpp \
|
src/map/wmts.cpp \
|
||||||
src/map/wmsmap.cpp \
|
src/map/wmsmap.cpp \
|
||||||
@ -389,7 +394,8 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/pngexportdialog.cpp \
|
src/GUI/pngexportdialog.cpp \
|
||||||
src/data/geojsonparser.cpp \
|
src/data/geojsonparser.cpp \
|
||||||
src/map/aqmmap.cpp \
|
src/map/aqmmap.cpp \
|
||||||
src/map/mapsforgemap.cpp
|
src/map/mapsforgemap.cpp \
|
||||||
|
src/map/worldfilemap.cpp
|
||||||
|
|
||||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
|
DEFINES += APP_VERSION=\\\"$$VERSION\\\" \
|
||||||
QT_NO_DEPRECATED_WARNINGS
|
QT_NO_DEPRECATED_WARNINGS
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "map/maplist.h"
|
#include "map/maplist.h"
|
||||||
#include "map/emptymap.h"
|
#include "map/emptymap.h"
|
||||||
#include "map/downloader.h"
|
#include "map/downloader.h"
|
||||||
|
#include "map/crs.h"
|
||||||
#include "icons.h"
|
#include "icons.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -123,7 +124,8 @@ TreeNode<MapAction*> GUI::createMapActions()
|
|||||||
if (mapDir.isNull())
|
if (mapDir.isNull())
|
||||||
return TreeNode<MapAction*>();
|
return TreeNode<MapAction*>();
|
||||||
|
|
||||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
|
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
|
||||||
|
CRS::projection(_options.inputProjection)));
|
||||||
return createMapActionsNode(maps);
|
return createMapActionsNode(maps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,8 +1008,19 @@ void GUI::openOptions()
|
|||||||
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
|
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
|
||||||
SET_VIEW_OPTION(useOpenGL, useOpenGL);
|
SET_VIEW_OPTION(useOpenGL, useOpenGL);
|
||||||
SET_VIEW_OPTION(sliderColor, setMarkerColor);
|
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(palette, setPalette);
|
||||||
SET_TAB_OPTION(graphWidth, setGraphWidth);
|
SET_TAB_OPTION(graphWidth, setGraphWidth);
|
||||||
@ -1047,16 +1060,6 @@ void GUI::openOptions()
|
|||||||
if (options.enableHTTP2 != _options.enableHTTP2)
|
if (options.enableHTTP2 != _options.enableHTTP2)
|
||||||
Downloader::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)
|
if (reload)
|
||||||
reloadFiles();
|
reloadFiles();
|
||||||
|
|
||||||
@ -1561,7 +1564,8 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
|
|||||||
|
|
||||||
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
|
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());
|
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||||
|
|
||||||
return loadMapNode(maps, action, silent, existingActions);
|
return loadMapNode(maps, action, silent, existingActions);
|
||||||
@ -1650,7 +1654,8 @@ void GUI::loadMapDir()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QFileInfo fi(dir);
|
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<QAction*> existingActions(_mapsActionGroup->actions());
|
||||||
QList<MapAction*> actions;
|
QList<MapAction*> actions;
|
||||||
QMenu *menu = new QMenu(maps.name());
|
QMenu *menu = new QMenu(maps.name());
|
||||||
@ -2581,8 +2586,8 @@ void GUI::readSettings()
|
|||||||
_mapView->useOpenGL(true);
|
_mapView->useOpenGL(true);
|
||||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||||
_mapView->setOutputProjection(_options.outputProjection);
|
_mapView->setOutputProjection(CRS::projection(_options.outputProjection));
|
||||||
_mapView->setInputProjection(_options.inputProjection);
|
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
|
||||||
_mapView->setTimeZone(_options.timeZone.zone());
|
_mapView->setTimeZone(_options.timeZone.zone());
|
||||||
|
|
||||||
for (int i = 0; i < _tabs.count(); i++) {
|
for (int i = 0; i < _tabs.count(); i++) {
|
||||||
|
@ -1121,37 +1121,19 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
|||||||
reloadMap();
|
reloadMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::setOutputProjection(int id)
|
void MapView::setOutputProjection(const Projection &proj)
|
||||||
{
|
{
|
||||||
const PCS *pcs;
|
_outputProjection = proj;
|
||||||
const GCS *gcs;
|
|
||||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
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);
|
_map->setOutputProjection(_outputProjection);
|
||||||
rescale();
|
rescale();
|
||||||
centerOn(_map->ll2xy(center));
|
centerOn(_map->ll2xy(center));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::setInputProjection(int id)
|
void MapView::setInputProjection(const Projection &proj)
|
||||||
{
|
{
|
||||||
const PCS *pcs;
|
_inputProjection = proj;
|
||||||
const GCS *gcs;
|
|
||||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
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);
|
_map->setInputProjection(_inputProjection);
|
||||||
rescale();
|
rescale();
|
||||||
centerOn(_map->ll2xy(center));
|
centerOn(_map->ll2xy(center));
|
||||||
|
@ -83,8 +83,8 @@ public:
|
|||||||
void setCoordinatesFormat(CoordinatesFormat format);
|
void setCoordinatesFormat(CoordinatesFormat format);
|
||||||
void setTimeZone(const QTimeZone &zone);
|
void setTimeZone(const QTimeZone &zone);
|
||||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||||
void setOutputProjection(int id);
|
void setOutputProjection(const Projection &proj);
|
||||||
void setInputProjection(int id);
|
void setInputProjection(const Projection &proj);
|
||||||
void clearMapCache();
|
void clearMapCache();
|
||||||
void fitContentToSize();
|
void fitContentToSize();
|
||||||
|
|
||||||
|
@ -44,11 +44,12 @@ void OptionsDialog::automaticPauseDetectionSet(bool set)
|
|||||||
_pauseSpeed->setEnabled(!set);
|
_pauseSpeed->setEnabled(!set);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *OptionsDialog::createMapPage()
|
static LimitedComboBox *projectionBox()
|
||||||
{
|
{
|
||||||
|
LimitedComboBox *box;
|
||||||
int last = -1;
|
int last = -1;
|
||||||
|
|
||||||
_outputProjection = new LimitedComboBox(200);
|
box = new LimitedComboBox(200);
|
||||||
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
|
QList<KV<int, QString> > projections(GCS::list() + PCS::list());
|
||||||
std::sort(projections.begin(), projections.end());
|
std::sort(projections.begin(), projections.end());
|
||||||
for (int i = 0; i < projections.size(); i++) {
|
for (int i = 0; i < projections.size(); i++) {
|
||||||
@ -59,33 +60,26 @@ QWidget *OptionsDialog::createMapPage()
|
|||||||
else
|
else
|
||||||
last = proj.key();
|
last = proj.key();
|
||||||
QString text = QString::number(proj.key()) + " - " + proj.value();
|
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(
|
_outputProjection->setCurrentIndex(_outputProjection->findData(
|
||||||
_options.outputProjection));
|
_options.outputProjection));
|
||||||
|
_inputProjection = projectionBox();
|
||||||
_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->setCurrentIndex(_inputProjection->findData(
|
_inputProjection->setCurrentIndex(_inputProjection->findData(
|
||||||
_options.inputProjection));
|
_options.inputProjection));
|
||||||
|
|
||||||
QLabel *inInfo = new QLabel(tr("Select the proper projection of"
|
QLabel *inInfo = new QLabel(tr("Select the proper projection of maps"
|
||||||
" JNX and KMZ maps. Both EPSG:3857 and EPSG:4326 projected maps"
|
" without a projection definition (JNX, KMZ and world file maps)"));
|
||||||
" exist and there is no projection info in the map file."));
|
QLabel *outInfo = new QLabel(tr("Select the desired projection of vector"
|
||||||
QLabel *outInfo = new QLabel(tr("Select the desired projection of IMG"
|
" maps (IMG and Mapsforge maps). The projection must be valid for"
|
||||||
" maps. The projection must be valid for the whole map area."));
|
" the whole map area."));
|
||||||
QFont f = inInfo->font();
|
QFont f = inInfo->font();
|
||||||
f.setPointSize(f.pointSize() - 1);
|
f.setPointSize(f.pointSize() - 1);
|
||||||
inInfo->setWordWrap(true);
|
inInfo->setWordWrap(true);
|
||||||
|
@ -34,7 +34,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
Q_UNUSED(routes);
|
Q_UNUSED(routes);
|
||||||
Q_UNUSED(polygons);
|
Q_UNUSED(polygons);
|
||||||
bool res;
|
bool res;
|
||||||
const GCS *gcs = 0;
|
GCS gcs;
|
||||||
|
|
||||||
_errorLine = 1;
|
_errorLine = 1;
|
||||||
_errorString.clear();
|
_errorString.clear();
|
||||||
@ -54,7 +54,8 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (_errorLine == 2) {
|
} else if (_errorLine == 2) {
|
||||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
gcs = GCS::gcs(QString(line.trimmed()));
|
||||||
|
if (gcs.isNull()) {
|
||||||
_errorString = "Invalid/unknown datum";
|
_errorString = "Invalid/unknown datum";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -80,7 +81,7 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Trackpoint tp(gcs->toWGS84(Coordinates(lon, lat)));
|
Trackpoint tp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||||
|
|
||||||
if (list.size() >= 4) {
|
if (list.size() >= 4) {
|
||||||
QByteArray field(list.at(3).trimmed());
|
QByteArray field(list.at(3).trimmed());
|
||||||
@ -125,7 +126,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
Q_UNUSED(tracks);
|
Q_UNUSED(tracks);
|
||||||
Q_UNUSED(polygons);
|
Q_UNUSED(polygons);
|
||||||
bool res, record = false;
|
bool res, record = false;
|
||||||
const GCS *gcs = 0;
|
GCS gcs;
|
||||||
|
|
||||||
_errorLine = 1;
|
_errorLine = 1;
|
||||||
_errorString.clear();
|
_errorString.clear();
|
||||||
@ -141,7 +142,8 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (_errorLine == 2) {
|
} else if (_errorLine == 2) {
|
||||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
gcs = GCS::gcs(QString(line.trimmed()));
|
||||||
|
if (gcs.isNull()) {
|
||||||
_errorString = "Invalid/unknown datum";
|
_errorString = "Invalid/unknown datum";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -181,7 +183,7 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||||
|
|
||||||
QByteArray name(list.at(4).trimmed());
|
QByteArray name(list.at(4).trimmed());
|
||||||
if (!name.isEmpty())
|
if (!name.isEmpty())
|
||||||
@ -225,7 +227,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
Q_UNUSED(routes);
|
Q_UNUSED(routes);
|
||||||
Q_UNUSED(polygons);
|
Q_UNUSED(polygons);
|
||||||
bool res;
|
bool res;
|
||||||
const GCS *gcs = 0;
|
GCS gcs;
|
||||||
|
|
||||||
_errorLine = 1;
|
_errorLine = 1;
|
||||||
_errorString.clear();
|
_errorString.clear();
|
||||||
@ -240,7 +242,8 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (_errorLine == 2) {
|
} else if (_errorLine == 2) {
|
||||||
if (!(gcs = GCS::gcs(QString(line.trimmed())))) {
|
gcs = GCS::gcs(QString(line.trimmed()));
|
||||||
|
if (gcs.isNull()) {
|
||||||
_errorString = "Invalid/unknown datum";
|
_errorString = "Invalid/unknown datum";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -262,7 +265,7 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
Waypoint wp(gcs.toWGS84(Coordinates(lon, lat)));
|
||||||
|
|
||||||
QByteArray name(list.at(1).trimmed());
|
QByteArray name(list.at(1).trimmed());
|
||||||
if (!name.isEmpty())
|
if (!name.isEmpty())
|
||||||
|
@ -53,7 +53,7 @@ Defense.
|
|||||||
((clat) / sqrt(one_minus_sqr_e_sin))
|
((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 standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||||
double falseEasting, double falseNorthing)
|
double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -74,8 +74,8 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
|||||||
sp1 = deg2rad(standardParallel1);
|
sp1 = deg2rad(standardParallel1);
|
||||||
sp2 = deg2rad(standardParallel2);
|
sp2 = deg2rad(standardParallel2);
|
||||||
|
|
||||||
_a2 = ellipsoid->radius() * ellipsoid->radius();
|
_a2 = ellipsoid.radius() * ellipsoid.radius();
|
||||||
_es = ellipsoid->es();
|
_es = ellipsoid.es();
|
||||||
_e = sqrt(_es);
|
_e = sqrt(_es);
|
||||||
_one_minus_es = 1 - _es;
|
_one_minus_es = 1 - _es;
|
||||||
_two_e = 2 * _e;
|
_two_e = 2 * _e;
|
||||||
@ -105,7 +105,7 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
|||||||
_n = sin_lat1;
|
_n = sin_lat1;
|
||||||
|
|
||||||
_c = sqr_m1 + _n * q1;
|
_c = sqr_m1 + _n * q1;
|
||||||
_a_over_n = ellipsoid->radius() / _n;
|
_a_over_n = ellipsoid.radius() / _n;
|
||||||
nq0 = _n * q0;
|
nq0 = _n * q0;
|
||||||
_rho0 = (_c < nq0) ? 0 : _a_over_n * sqrt(_c - nq0);
|
_rho0 = (_c < nq0) ? 0 : _a_over_n * sqrt(_c - nq0);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class AlbersEqual : public CT
|
class AlbersEqual : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
|
||||||
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||||
double falseEasting, double falseNorthing);
|
double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include "common/coordinates.h"
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "angularunits.h"
|
#include "angularunits.h"
|
||||||
|
|
||||||
|
@ -3,12 +3,14 @@
|
|||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include "common/coordinates.h"
|
||||||
|
|
||||||
class AngularUnits
|
class AngularUnits
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AngularUnits() : _code(0), _f(NAN) {}
|
AngularUnits() : _code(0), _f(NAN) {}
|
||||||
AngularUnits(int code);
|
AngularUnits(int code);
|
||||||
|
AngularUnits(double val) : _code(0), _f(rad2deg(val)) {}
|
||||||
|
|
||||||
bool operator==(const AngularUnits &other) const
|
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,
|
bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
||||||
double params[9], const Coordinates &c)
|
double params[9], const Coordinates &c)
|
||||||
{
|
{
|
||||||
const GCS *gcs = 0;
|
GCS gcs;
|
||||||
PCS pcs;
|
PCS pcs;
|
||||||
|
|
||||||
if (datum.isEmpty())
|
if (datum.isEmpty())
|
||||||
gcs = GCS::gcs(4326);
|
gcs = GCS::gcs(4326);
|
||||||
else
|
else
|
||||||
gcs = GCS::gcs(datum);
|
gcs = GCS::gcs(datum);
|
||||||
if (!gcs) {
|
if (gcs.isNull()) {
|
||||||
_errorString = datum + ": Unknown datum";
|
_errorString = datum + ": Unknown datum";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -323,7 +323,7 @@ bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_projection = Projection(&pcs);
|
_projection = Projection(pcs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,6 @@ Projection CRS::projection(const QString &crs)
|
|||||||
QStringList list(crs.split(':'));
|
QStringList list(crs.split(':'));
|
||||||
QString authority, code;
|
QString authority, code;
|
||||||
bool res;
|
bool res;
|
||||||
int epsg;
|
|
||||||
const PCS *pcs;
|
|
||||||
const GCS *gcs;
|
|
||||||
|
|
||||||
switch (list.size()) {
|
switch (list.size()) {
|
||||||
case 2:
|
case 2:
|
||||||
@ -33,16 +30,19 @@ Projection CRS::projection(const QString &crs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!authority.compare("EPSG", Qt::CaseInsensitive)) {
|
if (!authority.compare("EPSG", Qt::CaseInsensitive)) {
|
||||||
epsg = code.toInt(&res);
|
int epsg = code.toInt(&res);
|
||||||
if (!res)
|
if (!res)
|
||||||
return Projection();
|
return Projection();
|
||||||
|
|
||||||
if ((pcs = PCS::pcs(epsg)))
|
const PCS &pcs = PCS::pcs(epsg);
|
||||||
|
if (!pcs.isNull())
|
||||||
return Projection(pcs);
|
return Projection(pcs);
|
||||||
else if ((gcs = GCS::gcs(epsg)))
|
|
||||||
|
const GCS &gcs = GCS::gcs(epsg);
|
||||||
|
if (!gcs.isNull())
|
||||||
return Projection(gcs);
|
return Projection(gcs);
|
||||||
else
|
|
||||||
return Projection();
|
return Projection();
|
||||||
} else if (!authority.compare("OGC", Qt::CaseInsensitive)) {
|
} else if (!authority.compare("OGC", Qt::CaseInsensitive)) {
|
||||||
if (code == "CRS84")
|
if (code == "CRS84")
|
||||||
return Projection(GCS::gcs(4326), CoordinateSystem::XY);
|
return Projection(GCS::gcs(4326), CoordinateSystem::XY);
|
||||||
@ -51,3 +51,16 @@ Projection CRS::projection(const QString &crs)
|
|||||||
} else
|
} else
|
||||||
return Projection();
|
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
|
namespace CRS
|
||||||
{
|
{
|
||||||
Projection projection(const QString &crs);
|
Projection projection(const QString &crs);
|
||||||
|
Projection projection(int id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // CRS_H
|
#endif // CRS_H
|
||||||
|
@ -23,11 +23,11 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
|||||||
double dy = from.dy() - to.dy();
|
double dy = from.dy() - to.dy();
|
||||||
double dz = from.dz() - to.dz();
|
double dz = from.dz() - to.dz();
|
||||||
|
|
||||||
double from_f = from.ellipsoid()->flattening();
|
double from_f = from.ellipsoid().flattening();
|
||||||
double to_f = to.ellipsoid()->flattening();
|
double to_f = to.ellipsoid().flattening();
|
||||||
double df = to_f - from_f;
|
double df = to_f - from_f;
|
||||||
double from_a = from.ellipsoid()->radius();
|
double from_a = from.ellipsoid().radius();
|
||||||
double to_a = to.ellipsoid()->radius();
|
double to_a = to.ellipsoid().radius();
|
||||||
double da = to_a - from_a;
|
double da = to_a - from_a;
|
||||||
double from_esq = from_f * (2.0 - from_f);
|
double from_esq = from_f * (2.0 - from_f);
|
||||||
double adb = 1.0 / (1.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()
|
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;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,12 +66,12 @@ Point3D Datum::helmertr(const Point3D &p) const
|
|||||||
* y + z);
|
* 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)
|
double rx, double ry, double rz, double ds)
|
||||||
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
|
||||||
_ry(as2rad(ry)), _rz(as2rad(rz)), _scale(ds2scale(ds))
|
_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
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0
|
||||||
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
|
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
|
||||||
_transformation = None;
|
_transformation = None;
|
||||||
@ -79,11 +79,11 @@ Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
|||||||
_transformation = Helmert;
|
_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),
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(0.0), _ry(0.0),
|
||||||
_rz(0.0), _scale(1.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)
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
|
||||||
_transformation = None;
|
_transformation = None;
|
||||||
else
|
else
|
||||||
@ -119,7 +119,7 @@ Coordinates Datum::fromWGS84(const Coordinates &c) const
|
|||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const Datum &datum)
|
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())
|
<< ", " << datum.dy() << ", " << datum.dz() << ", " << rad2as(datum.rx())
|
||||||
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
|
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
|
||||||
<< scale2ds(datum.scale()) << ")";
|
<< scale2ds(datum.scale()) << ")";
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
class Datum
|
class Datum
|
||||||
{
|
{
|
||||||
public:
|
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) {}
|
_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);
|
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 dx() const {return _dx;}
|
||||||
double dy() const {return _dy;}
|
double dy() const {return _dy;}
|
||||||
double dz() const {return _dz;}
|
double dz() const {return _dz;}
|
||||||
@ -26,9 +26,9 @@ public:
|
|||||||
double scale() const {return _scale;}
|
double scale() const {return _scale;}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{return !_ellipsoid;}
|
{return _ellipsoid.isNull();}
|
||||||
bool isValid() const
|
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(_dz) && !std::isnan(_scale) && !std::isnan(_rx)
|
||||||
&& !std::isnan(_ry) && !std::isnan(_rz));}
|
&& !std::isnan(_ry) && !std::isnan(_rz));}
|
||||||
|
|
||||||
@ -47,13 +47,13 @@ private:
|
|||||||
Point3D helmert(const Point3D &p) const;
|
Point3D helmert(const Point3D &p) const;
|
||||||
Point3D helmertr(const Point3D &p) const;
|
Point3D helmertr(const Point3D &p) const;
|
||||||
|
|
||||||
const Ellipsoid *_ellipsoid;
|
Ellipsoid _ellipsoid;
|
||||||
TransformationType _transformation;
|
TransformationType _transformation;
|
||||||
double _dx, _dy, _dz, _rx, _ry, _rz, _scale;
|
double _dx, _dy, _dz, _rx, _ry, _rz, _scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Datum &d1, const Datum &d2)
|
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.dy() == d2.dy() && d1.dz() == d2.dz() && d1.rx() == d2.rx()
|
||||||
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.scale() == d2.scale());}
|
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.scale() == d2.scale());}
|
||||||
|
|
||||||
|
@ -18,14 +18,15 @@ QMap<int, Ellipsoid> Ellipsoid::defaults()
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Ellipsoid *Ellipsoid::ellipsoid(int id)
|
const Ellipsoid &Ellipsoid::ellipsoid(int id)
|
||||||
{
|
{
|
||||||
QMap<int, Ellipsoid>::const_iterator it(_ellipsoids.find(id));
|
QMap<int, Ellipsoid>::const_iterator it(_ellipsoids.find(id));
|
||||||
|
static const Ellipsoid null;
|
||||||
|
|
||||||
if (it == _ellipsoids.constEnd())
|
if (it == _ellipsoids.constEnd())
|
||||||
return 0;
|
return null;
|
||||||
else
|
else
|
||||||
return &(it.value());
|
return it.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ellipsoid::loadList(const QString &path)
|
void Ellipsoid::loadList(const QString &path)
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
{return !(std::isnan(_radius) || std::isnan(_flattening));}
|
{return !(std::isnan(_radius) || std::isnan(_flattening));}
|
||||||
|
|
||||||
static const Ellipsoid &WGS84();
|
static const Ellipsoid &WGS84();
|
||||||
static const Ellipsoid *ellipsoid(int id);
|
static const Ellipsoid &ellipsoid(int id);
|
||||||
static void loadList(const QString &path);
|
static void loadList(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,34 +58,40 @@ QList<GCS::Entry> GCS::defaults()
|
|||||||
return list;
|
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++)
|
for (int i = 0; i < _gcss.size(); i++)
|
||||||
if (_gcss.at(i).id() == id)
|
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++) {
|
for (int i = 0; i < _gcss.size(); i++) {
|
||||||
const Entry &e = _gcss.at(i);
|
const Entry &e = _gcss.at(i);
|
||||||
if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
|
if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
|
||||||
&& e.gcs().angularUnits() == angularUnits)
|
&& 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++)
|
for (int i = 0; i < _gcss.size(); i++)
|
||||||
if (_gcss.at(i).name() == name)
|
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)
|
void GCS::loadList(const QString &path)
|
||||||
@ -93,7 +99,6 @@ void GCS::loadList(const QString &path)
|
|||||||
QFile file(path);
|
QFile file(path);
|
||||||
bool res;
|
bool res;
|
||||||
int ln = 0;
|
int ln = 0;
|
||||||
const Ellipsoid *e;
|
|
||||||
|
|
||||||
|
|
||||||
if (!file.open(QFile::ReadOnly)) {
|
if (!file.open(QFile::ReadOnly)) {
|
||||||
@ -182,7 +187,8 @@ void GCS::loadList(const QString &path)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(e = Ellipsoid::ellipsoid(el))) {
|
const Ellipsoid &e = Ellipsoid::ellipsoid(el);
|
||||||
|
if (e.isNull()) {
|
||||||
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
|
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,10 @@ public:
|
|||||||
Coordinates toWGS84(const Coordinates &c) const;
|
Coordinates toWGS84(const Coordinates &c) const;
|
||||||
Coordinates fromWGS84(const Coordinates &c) const;
|
Coordinates fromWGS84(const Coordinates &c) const;
|
||||||
|
|
||||||
static const GCS *gcs(int id);
|
static const GCS &gcs(int id);
|
||||||
static const GCS *gcs(int geodeticDatum, int primeMeridian,
|
static const GCS &gcs(int geodeticDatum, int primeMeridian,
|
||||||
int angularUnits);
|
int angularUnits);
|
||||||
static const GCS *gcs(const QString &name);
|
static const GCS &gcs(const QString &name);
|
||||||
static const GCS &WGS84();
|
static const GCS &WGS84();
|
||||||
|
|
||||||
static void loadList(const QString &path);
|
static void loadList(const QString &path);
|
||||||
|
@ -47,23 +47,23 @@ Defense.
|
|||||||
|
|
||||||
#define AD_C 1.0026000
|
#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 lat = deg2rad(c.lat());
|
||||||
double lon = deg2rad(c.lon());
|
double lon = deg2rad(c.lon());
|
||||||
double slat = sin(lat);
|
double slat = sin(lat);
|
||||||
double slat2 = slat * slat;
|
double slat2 = slat * slat;
|
||||||
double clat = cos(lat);
|
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)
|
if (lon > M_PI)
|
||||||
lon -= 2 * M_PI;
|
lon -= 2 * M_PI;
|
||||||
|
|
||||||
return Point3D(Rn * clat * cos(lon), Rn * clat * sin(lon),
|
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;
|
bool pole = false;
|
||||||
double lat, lon;
|
double lat, lon;
|
||||||
@ -93,8 +93,8 @@ Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid *e)
|
|||||||
double Sin_B0 = T0 / S0;
|
double Sin_B0 = T0 / S0;
|
||||||
double Cos_B0 = W / S0;
|
double Cos_B0 = W / S0;
|
||||||
double Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
|
double Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
|
||||||
double T1 = p.z() + e->b() * e->e2s() * Sin3_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 Sum = W - e.radius() * e.es() * Cos_B0 * Cos_B0 * Cos_B0;
|
||||||
double S1 = sqrt(T1*T1 + Sum * Sum);
|
double S1 = sqrt(T1*T1 + Sum * Sum);
|
||||||
double Sin_p1 = T1 / S1;
|
double Sin_p1 = T1 / S1;
|
||||||
double Cos_p1 = Sum / S1;
|
double Cos_p1 = Sum / S1;
|
||||||
|
@ -22,8 +22,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
namespace Geocentric {
|
namespace Geocentric {
|
||||||
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid *e);
|
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid &e);
|
||||||
Coordinates toGeodetic(const Point3D &p, const Ellipsoid *e);
|
Coordinates toGeodetic(const Point3D &p, const Ellipsoid &e);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GEOCENTRIC_H
|
#endif // GEOCENTRIC_H
|
||||||
|
@ -289,12 +289,13 @@ bool GeoTIFF::readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
|
|||||||
return true;
|
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 (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")
|
_errorString = QString("%1: unknown GCS")
|
||||||
.arg(kv.value(GeographicTypeGeoKey).SHORT);
|
.arg(kv.value(GeographicTypeGeoKey).SHORT);
|
||||||
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)
|
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||||
@ -310,7 +311,8 @@ const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
|||||||
int gd = IS_SET(kv, GeogGeodeticDatumGeoKey)
|
int gd = IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||||
? kv.value(GeogGeodeticDatumGeoKey).SHORT : 6326;
|
? 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"
|
_errorString = QString("%1+%2+%3: unknown geodetic datum + prime"
|
||||||
" meridian + units combination").arg(gd).arg(pm).arg(au);
|
" meridian + units combination").arg(gd).arg(pm).arg(au);
|
||||||
} else
|
} else
|
||||||
@ -357,19 +359,19 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
|
|||||||
bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||||
{
|
{
|
||||||
if (IS_SET(kv, ProjectedCSTypeGeoKey)) {
|
if (IS_SET(kv, ProjectedCSTypeGeoKey)) {
|
||||||
const PCS *pcs;
|
const PCS &pcs = PCS::pcs(kv.value(ProjectedCSTypeGeoKey).SHORT);
|
||||||
if (!(pcs = PCS::pcs(kv.value(ProjectedCSTypeGeoKey).SHORT))) {
|
if (pcs.isNull()) {
|
||||||
_errorString = QString("%1: unknown PCS")
|
_errorString = QString("%1: unknown PCS")
|
||||||
.arg(kv.value(ProjectedCSTypeGeoKey).SHORT);
|
.arg(kv.value(ProjectedCSTypeGeoKey).SHORT);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_projection = Projection(pcs);
|
_projection = Projection(pcs);
|
||||||
} else if (IS_SET(kv, ProjectionGeoKey)) {
|
} else if (IS_SET(kv, ProjectionGeoKey)) {
|
||||||
const GCS *g = gcs(kv);
|
const GCS g(gcs(kv));
|
||||||
if (!g)
|
if (g.isNull())
|
||||||
return false;
|
return false;
|
||||||
const PCS *pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT);
|
const PCS &pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT);
|
||||||
if (!pcs) {
|
if (pcs.isNull()) {
|
||||||
_errorString = QString("%1: unknown projection code")
|
_errorString = QString("%1: unknown projection code")
|
||||||
.arg(kv.value(GeographicTypeGeoKey).SHORT)
|
.arg(kv.value(GeographicTypeGeoKey).SHORT)
|
||||||
.arg(kv.value(ProjectionGeoKey).SHORT);
|
.arg(kv.value(ProjectionGeoKey).SHORT);
|
||||||
@ -379,8 +381,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
|||||||
} else {
|
} else {
|
||||||
double lat0, lon0, scale, fe, fn, sp1, sp2;
|
double lat0, lon0, scale, fe, fn, sp1, sp2;
|
||||||
|
|
||||||
const GCS *g = gcs(kv);
|
GCS g(gcs(kv));
|
||||||
if (!g)
|
if (g.isNull())
|
||||||
return false;
|
return false;
|
||||||
Projection::Method m(method(kv));
|
Projection::Method m(method(kv));
|
||||||
if (m.isNull())
|
if (m.isNull())
|
||||||
@ -453,7 +455,7 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
|||||||
|
|
||||||
Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2);
|
Projection::Setup setup(lat0, lon0, scale, fe, fn, sp1, sp2);
|
||||||
PCS pcs(g, m, setup, lu, CoordinateSystem());
|
PCS pcs(g, m, setup, lu, CoordinateSystem());
|
||||||
_projection = Projection(&pcs);
|
_projection = Projection(pcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -461,8 +463,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
|||||||
|
|
||||||
bool GeoTIFF::geographicModel(QMap<quint16, Value> &kv)
|
bool GeoTIFF::geographicModel(QMap<quint16, Value> &kv)
|
||||||
{
|
{
|
||||||
const GCS *g = gcs(kv);
|
GCS g(gcs(kv));
|
||||||
if (!g)
|
if (g.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_projection = Projection(g);
|
_projection = Projection(g);
|
||||||
|
@ -48,7 +48,7 @@ private:
|
|||||||
bool readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
|
bool readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
|
||||||
double &val) const;
|
double &val) const;
|
||||||
|
|
||||||
const GCS *gcs(QMap<quint16, Value> &kv);
|
GCS gcs(QMap<quint16, Value> &kv);
|
||||||
Projection::Method method(QMap<quint16, Value> &kv);
|
Projection::Method method(QMap<quint16, Value> &kv);
|
||||||
bool geographicModel(QMap<quint16, Value> &kv);
|
bool geographicModel(QMap<quint16, Value> &kv);
|
||||||
bool projectedModel(QMap<quint16, Value> &kv);
|
bool projectedModel(QMap<quint16, Value> &kv);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#include <QFileInfo>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QImageReader>
|
#include <QImageReader>
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
@ -131,12 +131,10 @@ bool JNXMap::readTiles()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
JNXMap::JNXMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||||
: Map(fileName, parent), _file(fileName), _zoom(0), _mapRatio(1.0),
|
: Map(fileName, parent), _file(fileName), _zoom(0), _projection(proj),
|
||||||
_valid(false)
|
_mapRatio(1.0), _valid(false)
|
||||||
{
|
{
|
||||||
_projection = Projection(GCS::gcs(4326));
|
|
||||||
|
|
||||||
if (!_file.open(QIODevice::ReadOnly)) {
|
if (!_file.open(QIODevice::ReadOnly)) {
|
||||||
_errorString = fileName + ": " + _file.errorString();
|
_errorString = fileName + ": " + _file.errorString();
|
||||||
return;
|
return;
|
||||||
|
@ -15,7 +15,7 @@ public:
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JNXMap(const QString &fileName, QObject *parent = 0);
|
JNXMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||||
~JNXMap();
|
~JNXMap();
|
||||||
|
|
||||||
QRectF bounds();
|
QRectF bounds();
|
||||||
|
@ -307,16 +307,14 @@ void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
KMZMap::KMZMap(const QString &fileName, QObject *parent)
|
KMZMap::KMZMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _ratio(1.0),
|
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _projection(proj),
|
||||||
_valid(false)
|
_ratio(1.0), _valid(false)
|
||||||
{
|
{
|
||||||
QZipReader zip(fileName, QIODevice::ReadOnly);
|
QZipReader zip(fileName, QIODevice::ReadOnly);
|
||||||
QByteArray xml(zip.fileData("doc.kml"));
|
QByteArray xml(zip.fileData("doc.kml"));
|
||||||
QXmlStreamReader reader(xml);
|
QXmlStreamReader reader(xml);
|
||||||
|
|
||||||
_projection = Projection(GCS::gcs(4326));
|
|
||||||
|
|
||||||
if (reader.readNextStartElement()) {
|
if (reader.readNextStartElement()) {
|
||||||
if (reader.name() == QLatin1String("kml"))
|
if (reader.name() == QLatin1String("kml"))
|
||||||
kml(reader, zip);
|
kml(reader, zip);
|
||||||
|
@ -15,7 +15,7 @@ class KMZMap : public Map
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
KMZMap(const QString &fileName, QObject *parent = 0);
|
KMZMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||||
|
|
||||||
QRectF bounds();
|
QRectF bounds();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "ellipsoid.h"
|
#include "ellipsoid.h"
|
||||||
#include "krovak.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 azimuth, double scale, double centerLatitude, double longitudeOrigin,
|
||||||
double falseEasting, double falseNorthing)
|
double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -14,10 +14,10 @@ Krovak::Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
|||||||
double alphaC = deg2rad(azimuth);
|
double alphaC = deg2rad(azimuth);
|
||||||
|
|
||||||
_phiP = deg2rad(standardParallel);
|
_phiP = deg2rad(standardParallel);
|
||||||
_e = sqrt(ellipsoid->es());
|
_e = sqrt(ellipsoid.es());
|
||||||
_a = ellipsoid->radius() * sqrt(1.0 - ellipsoid->es())
|
_a = ellipsoid.radius() * sqrt(1.0 - ellipsoid.es())
|
||||||
/ (1.0 - ellipsoid->es() * sinPhiC2);
|
/ (1.0 - ellipsoid.es() * sinPhiC2);
|
||||||
_b = sqrt(1.0 + (ellipsoid->es() * cosPhiC4 / (1.0 - ellipsoid->es())));
|
_b = sqrt(1.0 + (ellipsoid.es() * cosPhiC4 / (1.0 - ellipsoid.es())));
|
||||||
double gamma0 = asin(sinPhiC / _b);
|
double gamma0 = asin(sinPhiC / _b);
|
||||||
_t0 = tan(M_PI_4 + gamma0 / 2.0) * pow((1.0 + _e * sinPhiC) /
|
_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);
|
(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
|
class Krovak : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
Krovak(const Ellipsoid &ellipsoid, double standardParallel,
|
||||||
double azimuth, double scale, double centerLatitude,
|
double azimuth, double scale, double centerLatitude,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ private:
|
|||||||
class KrovakNE : public CT
|
class KrovakNE : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
KrovakNE(const Ellipsoid *ellipsoid, double standardParallel,
|
KrovakNE(const Ellipsoid &ellipsoid, double standardParallel,
|
||||||
double azimuth, double scale, double centerLatitude,
|
double azimuth, double scale, double centerLatitude,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||||
: _k(ellipsoid, standardParallel, azimuth, scale, centerLatitude,
|
: _k(ellipsoid, standardParallel, azimuth, scale, centerLatitude,
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#define sin2(x) (sin(x) * sin(x))
|
#define sin2(x) (sin(x) * sin(x))
|
||||||
#define sqr(x) ((x) * (x))
|
#define sqr(x) ((x) * (x))
|
||||||
|
|
||||||
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
|
LambertAzimuthal::LambertAzimuthal(const Ellipsoid &ellipsoid,
|
||||||
double latitudeOrigin, double longitudeOrigin, double falseEasting,
|
double latitudeOrigin, double longitudeOrigin, double falseEasting,
|
||||||
double falseNorthing)
|
double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -15,8 +15,8 @@ LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
|
|||||||
_fn = falseNorthing;
|
_fn = falseNorthing;
|
||||||
_lon0 = deg2rad(longitudeOrigin);
|
_lon0 = deg2rad(longitudeOrigin);
|
||||||
|
|
||||||
_a = ellipsoid->radius();
|
_a = ellipsoid.radius();
|
||||||
_es = ellipsoid->es();
|
_es = ellipsoid.es();
|
||||||
_e = sqrt(_es);
|
_e = sqrt(_es);
|
||||||
|
|
||||||
double q0 = (1.0 - _es) * ((sin(lat0) / (1.0 - _es * sin2(lat0)))
|
double q0 = (1.0 - _es) * ((sin(lat0) / (1.0 - _es * sin2(lat0)))
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class LambertAzimuthal : public CT
|
class LambertAzimuthal : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LambertAzimuthal(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
LambertAzimuthal(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
virtual CT *clone() const {return new LambertAzimuthal(*this);}
|
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))
|
(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 longitudeOrigin, double scale, double falseEasting,
|
||||||
double falseNorthing)
|
double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -70,7 +70,7 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
|||||||
_falseEasting = falseEasting;
|
_falseEasting = falseEasting;
|
||||||
_falseNorthing = falseNorthing;
|
_falseNorthing = falseNorthing;
|
||||||
|
|
||||||
_e = sqrt(ellipsoid->es());
|
_e = sqrt(ellipsoid.es());
|
||||||
_e_over_2 = _e / 2.0;
|
_e_over_2 = _e / 2.0;
|
||||||
|
|
||||||
_n = sin(lat_orig);
|
_n = sin(lat_orig);
|
||||||
@ -79,7 +79,7 @@ LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
|||||||
m0 = LAMBERT_m(cos(lat_orig), e_sin);
|
m0 = LAMBERT_m(cos(lat_orig), e_sin);
|
||||||
_t0 = LAMBERT1_t(lat_orig, e_sin, _e_over_2);
|
_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;
|
_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 standardParallel1, double standardParallel2, double latitudeOrigin,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -228,7 +228,7 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
|
|||||||
sp2 = deg2rad(standardParallel2);
|
sp2 = deg2rad(standardParallel2);
|
||||||
|
|
||||||
if (fabs(sp1 - sp2) > 1.0e-10) {
|
if (fabs(sp1 - sp2) > 1.0e-10) {
|
||||||
e = sqrt(ellipsoid->es());
|
e = sqrt(ellipsoid.es());
|
||||||
e_over_2 = e / 2.0;
|
e_over_2 = e / 2.0;
|
||||||
|
|
||||||
e_sin = e * sin(lat_orig);
|
e_sin = e * sin(lat_orig);
|
||||||
@ -252,7 +252,7 @@ LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
|
|||||||
|
|
||||||
k0 = (m1 / m0) * (pow(t0 / t1, n));
|
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
|
falseNorthing += (const_value * pow(t_olat, n)) - (const_value
|
||||||
* pow(t0, n));
|
* pow(t0, n));
|
||||||
|
@ -9,7 +9,7 @@ class LambertConic1 : public CT
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LambertConic1() {}
|
LambertConic1() {}
|
||||||
LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
LambertConic1(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double scale, double falseEasting,
|
double longitudeOrigin, double scale, double falseEasting,
|
||||||
double falseNorthing);
|
double falseNorthing);
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ private:
|
|||||||
class LambertConic2 : public CT
|
class LambertConic2 : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LambertConic2(const Ellipsoid *ellipsoid, double standardParallel1,
|
LambertConic2(const Ellipsoid &ellipsoid, double standardParallel1,
|
||||||
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
|
||||||
double falseEasting, double falseNorthing);
|
double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ class LinearUnits
|
|||||||
public:
|
public:
|
||||||
LinearUnits() : _f(NAN) {}
|
LinearUnits() : _f(NAN) {}
|
||||||
LinearUnits(int code);
|
LinearUnits(int code);
|
||||||
|
LinearUnits(double val) : _f(val) {}
|
||||||
|
|
||||||
bool operator==(const LinearUnits &other) const
|
bool operator==(const LinearUnits &other) const
|
||||||
{return (_f == other._f);}
|
{return (_f == other._f);}
|
||||||
|
@ -161,21 +161,17 @@ bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
|
|||||||
return (!el);
|
return (!el);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GCS *MapFile::createGCS(const QString &datum)
|
bool MapFile::createProjection(const QString &datum, const QString &name,
|
||||||
{
|
|
||||||
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,
|
|
||||||
const Projection::Setup &setup)
|
const Projection::Setup &setup)
|
||||||
{
|
{
|
||||||
PCS pcs;
|
PCS pcs;
|
||||||
|
|
||||||
|
GCS gcs(GCS::gcs(datum));
|
||||||
|
if (gcs.isNull()) {
|
||||||
|
_errorString = QString("%1: Unknown datum").arg(datum);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (name == "Latitude/Longitude") {
|
if (name == "Latitude/Longitude") {
|
||||||
_projection = Projection(gcs);
|
_projection = Projection(gcs);
|
||||||
return true;
|
return true;
|
||||||
@ -230,7 +226,7 @@ bool MapFile::createProjection(const GCS *gcs, const QString &name,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_projection = Projection(&pcs);
|
_projection = Projection(pcs);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -256,13 +252,10 @@ MapFile::MapFile(QIODevice &file)
|
|||||||
QList<CalibrationPoint> points;
|
QList<CalibrationPoint> points;
|
||||||
QString ct, datum;
|
QString ct, datum;
|
||||||
Projection::Setup setup;
|
Projection::Setup setup;
|
||||||
const GCS *gcs;
|
|
||||||
|
|
||||||
if (!parseMapFile(file, points, ct, setup, datum))
|
if (!parseMapFile(file, points, ct, setup, datum))
|
||||||
return;
|
return;
|
||||||
if (!(gcs = createGCS(datum)))
|
if (!createProjection(datum, ct, setup))
|
||||||
return;
|
|
||||||
if (!createProjection(gcs, ct, setup))
|
|
||||||
return;
|
return;
|
||||||
if (!computeTransformation(points))
|
if (!computeTransformation(points))
|
||||||
return;
|
return;
|
||||||
|
@ -29,8 +29,7 @@ private:
|
|||||||
QString &projection, Projection::Setup &setup, QString &datum);
|
QString &projection, Projection::Setup &setup, QString &datum);
|
||||||
bool parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
|
bool parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
|
||||||
QString &projection, Projection::Setup &setup, QString &datum);
|
QString &projection, Projection::Setup &setup, QString &datum);
|
||||||
const GCS *createGCS(const QString &datum);
|
bool createProjection(const QString &datum, const QString &projection,
|
||||||
bool createProjection(const GCS *gcs, const QString &projection,
|
|
||||||
const Projection::Setup &setup);
|
const Projection::Setup &setup);
|
||||||
bool computeTransformation(const QList<CalibrationPoint> &points);
|
bool computeTransformation(const QList<CalibrationPoint> &points);
|
||||||
|
|
||||||
|
@ -15,11 +15,12 @@
|
|||||||
#include "aqmmap.h"
|
#include "aqmmap.h"
|
||||||
#include "sqlitemap.h"
|
#include "sqlitemap.h"
|
||||||
#include "mapsforgemap.h"
|
#include "mapsforgemap.h"
|
||||||
|
#include "worldfilemap.h"
|
||||||
#include "invalidmap.h"
|
#include "invalidmap.h"
|
||||||
#include "maplist.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);
|
QFileInfo fi(path);
|
||||||
QString suffix = fi.suffix().toLower();
|
QString suffix = fi.suffix().toLower();
|
||||||
@ -38,7 +39,7 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
|||||||
*isDir = true;
|
*isDir = true;
|
||||||
}
|
}
|
||||||
} else if (suffix == "jnx")
|
} else if (suffix == "jnx")
|
||||||
map = new JNXMap(path);
|
map = new JNXMap(path, proj);
|
||||||
else if (suffix == "tif" || suffix == "tiff")
|
else if (suffix == "tif" || suffix == "tiff")
|
||||||
map = new GeoTIFFMap(path);
|
map = new GeoTIFFMap(path);
|
||||||
else if (suffix == "mbtiles")
|
else if (suffix == "mbtiles")
|
||||||
@ -57,16 +58,20 @@ Map *MapList::loadFile(const QString &path, bool *isDir)
|
|||||||
else if (suffix == "kap")
|
else if (suffix == "kap")
|
||||||
map = new BSBMap(path);
|
map = new BSBMap(path);
|
||||||
else if (suffix == "kmz")
|
else if (suffix == "kmz")
|
||||||
map = new KMZMap(path);
|
map = new KMZMap(path, proj);
|
||||||
else if (suffix == "aqm")
|
else if (suffix == "aqm")
|
||||||
map = new AQMMap(path);
|
map = new AQMMap(path);
|
||||||
else if (suffix == "sqlitedb")
|
else if (suffix == "sqlitedb")
|
||||||
map = new SqliteMap(path);
|
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");
|
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);
|
QDir md(path);
|
||||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
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();
|
QString suffix = fi.suffix().toLower();
|
||||||
|
|
||||||
if (fi.isDir()) {
|
if (fi.isDir()) {
|
||||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), &tree));
|
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), proj, &tree));
|
||||||
if (!child.isEmpty())
|
if (!child.isEmpty())
|
||||||
tree.addChild(child);
|
tree.addChild(child);
|
||||||
} else if (filter().contains("*." + suffix)) {
|
} else if (filter().contains("*." + suffix)) {
|
||||||
bool isDir = false;
|
bool isDir = false;
|
||||||
Map *map = loadFile(fi.absoluteFilePath(), &isDir);
|
Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir);
|
||||||
if (isDir) {
|
if (isDir) {
|
||||||
if (parent)
|
if (parent)
|
||||||
parent->addItem(map);
|
parent->addItem(map);
|
||||||
@ -99,13 +104,13 @@ TreeNode<Map *> MapList::loadDir(const QString &path, TreeNode<Map *> *parent)
|
|||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeNode<Map *> MapList::loadMaps(const QString &path)
|
TreeNode<Map *> MapList::loadMaps(const QString &path, const Projection &proj)
|
||||||
{
|
{
|
||||||
if (QFileInfo(path).isDir())
|
if (QFileInfo(path).isDir())
|
||||||
return loadDir(path);
|
return loadDir(path, proj);
|
||||||
else {
|
else {
|
||||||
TreeNode<Map*> tree;
|
TreeNode<Map*> tree;
|
||||||
tree.addItem(loadFile(path));
|
tree.addItem(loadFile(path, proj));
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,14 +134,17 @@ QString MapList::formats()
|
|||||||
+ " (*.sqlitedb);;"
|
+ " (*.sqlitedb);;"
|
||||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||||
+ qApp->translate("MapList", "GeoTIFF images") + " (*.tif *.tiff);;"
|
+ 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)";
|
+ qApp->translate("MapList", "Online map sources") + " (*.xml)";
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MapList::filter()
|
QStringList MapList::filter()
|
||||||
{
|
{
|
||||||
QStringList filter;
|
QStringList filter;
|
||||||
filter << "*.aqm" << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.kap"
|
filter << "*.aqm" << "*.gfw" << "*.gmap" << "*.gmapi" << "*.img" << "*.jgw"
|
||||||
<< "*.kmz" << "*.map" << "*.mbtiles" << "*.rmap" << "*.rtmap"
|
<< "*.jnx" << "*.kap" << "*.kmz" << "*.map" << "*.mbtiles" << "*.pgw"
|
||||||
<< "*.sqlitedb" << "*.tar" << "*.tba" << "*.tif" << "*.tiff" << "*.xml";
|
<< "*.rmap" << "*.rtmap" << "*.sqlitedb" << "*.tar" << "*.tba" << "*.tfw"
|
||||||
|
<< "*.tif" << "*.tiff" << "*.wld" << "*.xml";
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
@ -5,17 +5,19 @@
|
|||||||
#include "common/treenode.h"
|
#include "common/treenode.h"
|
||||||
|
|
||||||
class Map;
|
class Map;
|
||||||
|
class Projection;
|
||||||
|
|
||||||
class MapList
|
class MapList
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static TreeNode<Map*> loadMaps(const QString &path);
|
static TreeNode<Map*> loadMaps(const QString &path, const Projection &proj);
|
||||||
static QString formats();
|
static QString formats();
|
||||||
static QStringList filter();
|
static QStringList filter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Map *loadFile(const QString &path, bool *isDir = 0);
|
static Map *loadFile(const QString &path, const Projection &proj,
|
||||||
static TreeNode<Map*> loadDir(const QString &path,
|
bool *isDir = 0);
|
||||||
|
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
|
||||||
TreeNode<Map *> *parent = 0);
|
TreeNode<Map *> *parent = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,10 +44,10 @@ Defense.
|
|||||||
#include "ellipsoid.h"
|
#include "ellipsoid.h"
|
||||||
#include "mercator.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 longitudeOrigin, double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
double es = ellipsoid->es();
|
double es = ellipsoid.es();
|
||||||
double es2;
|
double es2;
|
||||||
double es3;
|
double es3;
|
||||||
double es4;
|
double es4;
|
||||||
@ -60,7 +60,7 @@ Mercator::Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
|||||||
_falseNorthing = falseNorthing;
|
_falseNorthing = falseNorthing;
|
||||||
_falseEasting = falseEasting;
|
_falseEasting = falseEasting;
|
||||||
|
|
||||||
_a = ellipsoid->radius();
|
_a = ellipsoid.radius();
|
||||||
_e = sqrt(es);
|
_e = sqrt(es);
|
||||||
|
|
||||||
sin_olat = sin(_latitudeOrigin);
|
sin_olat = sin(_latitudeOrigin);
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class Mercator : public CT
|
class Mercator : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Mercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
Mercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
virtual CT *clone() const {return new Mercator(*this);}
|
virtual CT *clone() const {return new Mercator(*this);}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#define S1(x) ((1.0 + x) / (1.0 - x))
|
#define S1(x) ((1.0 + x) / (1.0 - x))
|
||||||
#define S2(x) ((1.0 - _e * x) / (1.0 + _e * 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 latitudeOrigin, double longitudeOrigin, double scale,
|
||||||
double falseEasting, double falseNorthing)
|
double falseEasting, double falseNorthing)
|
||||||
: _fe(falseEasting), _fn(falseNorthing)
|
: _fe(falseEasting), _fn(falseNorthing)
|
||||||
@ -15,8 +15,8 @@ ObliqueStereographic::ObliqueStereographic(const Ellipsoid *ellipsoid,
|
|||||||
double cosPhi0 = cos(lat0);
|
double cosPhi0 = cos(lat0);
|
||||||
double sinLat0s = sinPhi0 * sinPhi0;
|
double sinLat0s = sinPhi0 * sinPhi0;
|
||||||
|
|
||||||
double a = ellipsoid->radius();
|
double a = ellipsoid.radius();
|
||||||
_es = ellipsoid->es();
|
_es = ellipsoid.es();
|
||||||
_e = sqrt(_es);
|
_e = sqrt(_es);
|
||||||
|
|
||||||
double rho0 = a * (1.0 - _es) / pow(1.0 - _es * sinLat0s, 1.5);
|
double rho0 = a * (1.0 - _es) / pow(1.0 - _es * sinLat0s, 1.5);
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class ObliqueStereographic : public CT
|
class ObliqueStereographic : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ObliqueStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
ObliqueStereographic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double scale, double falseEasting,
|
double longitudeOrigin, double scale, double falseEasting,
|
||||||
double falseNorthing);
|
double falseNorthing);
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ QList<PCS::Entry> PCS::defaults()
|
|||||||
{
|
{
|
||||||
QList<PCS::Entry> list;
|
QList<PCS::Entry> list;
|
||||||
list.append(PCS::Entry("WGS 84 / Pseudo-Mercator", 3857, 3856,
|
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)));
|
9001, 4499)));
|
||||||
return list;
|
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++)
|
for (int i = 0; i < _pcss.size(); i++)
|
||||||
if (_pcss.at(i).id() == id)
|
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++)
|
static const PCS null;
|
||||||
if (_pcss.at(i).proj() == proj && *(_pcss.at(i).pcs().gcs()) == *gcs)
|
|
||||||
return &(_pcss.at(i).pcs());
|
|
||||||
|
|
||||||
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)
|
void PCS::loadList(const QString &path)
|
||||||
@ -140,7 +144,7 @@ void PCS::loadList(const QString &path)
|
|||||||
QFile file(path);
|
QFile file(path);
|
||||||
bool res;
|
bool res;
|
||||||
int ln = 0, pn;
|
int ln = 0, pn;
|
||||||
const GCS *gcs;
|
|
||||||
|
|
||||||
if (!file.open(QFile::ReadOnly)) {
|
if (!file.open(QFile::ReadOnly)) {
|
||||||
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
|
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
|
||||||
@ -206,7 +210,8 @@ void PCS::loadList(const QString &path)
|
|||||||
ln);
|
ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(gcs = GCS::gcs(gcsid))) {
|
const GCS &gcs = GCS::gcs(gcsid);
|
||||||
|
if (gcs.isNull()) {
|
||||||
qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
|
qWarning("%s:%d: Unknown GCS code", qPrintable(path), ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -236,7 +241,7 @@ QList<KV<int, QString> > PCS::list()
|
|||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const PCS &pcs)
|
QDebug operator<<(QDebug dbg, const PCS &pcs)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "PCS(" << *pcs.gcs() << ", " << pcs.method() << ", "
|
dbg.nospace() << "PCS(" << pcs.gcs() << ", " << pcs.method() << ", "
|
||||||
<< pcs.units() << ", " << pcs.setup() << ")";
|
<< pcs.units() << ", " << pcs.setup() << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
|
@ -12,29 +12,31 @@
|
|||||||
class PCS
|
class PCS
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PCS() : _gcs(0) {}
|
PCS() {}
|
||||||
PCS(const GCS *gcs, const Projection::Method &method,
|
PCS(const GCS &gcs, const Projection::Method &method,
|
||||||
const Projection::Setup &setup, const LinearUnits &units,
|
const Projection::Setup &setup, const LinearUnits &units,
|
||||||
const CoordinateSystem &cs = CoordinateSystem())
|
const CoordinateSystem &cs = CoordinateSystem())
|
||||||
: _gcs(gcs), _method(method), _setup(setup), _units(units), _cs(cs) {}
|
: _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::Method &method() const {return _method;}
|
||||||
const Projection::Setup &setup() const {return _setup;}
|
const Projection::Setup &setup() const {return _setup;}
|
||||||
const LinearUnits &units() const {return _units;}
|
const LinearUnits &units() const {return _units;}
|
||||||
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const {
|
||||||
{return (!_gcs && _units.isNull() && _method.isNull() && _setup.isNull()
|
return (_gcs.isNull() && _units.isNull() && _method.isNull()
|
||||||
&& _cs.isNull());}
|
&& _setup.isNull() && _cs.isNull());
|
||||||
bool isValid() const
|
}
|
||||||
{return (_gcs && _gcs->isValid() && _units.isValid()
|
bool isValid() const {
|
||||||
&& _method.isValid() && _cs.isValid());}
|
return (_gcs.isValid() && _units.isValid() && _method.isValid()
|
||||||
|
&& _cs.isValid());
|
||||||
|
}
|
||||||
|
|
||||||
static void loadList(const QString &path);
|
static void loadList(const QString &path);
|
||||||
static const PCS *pcs(int id);
|
static const PCS &pcs(int id);
|
||||||
static const PCS *pcs(const GCS *gcs, int proj);
|
static const PCS &pcs(const GCS &gcs, int proj);
|
||||||
static QList<KV<int, QString> > list();
|
static QList<KV<int, QString> > list();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -42,7 +44,7 @@ private:
|
|||||||
|
|
||||||
static QList<Entry> defaults();
|
static QList<Entry> defaults();
|
||||||
|
|
||||||
const GCS *_gcs;
|
GCS _gcs;
|
||||||
Projection::Method _method;
|
Projection::Method _method;
|
||||||
Projection::Setup _setup;
|
Projection::Setup _setup;
|
||||||
LinearUnits _units;
|
LinearUnits _units;
|
||||||
|
@ -47,11 +47,11 @@ Defense.
|
|||||||
|
|
||||||
#define POLAR_POW(EsSin) pow((1.0 - EsSin) / (1.0 + EsSin), _es_OVER_2)
|
#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 latitudeOrigin, double longitudeOrigin,
|
||||||
double falseEasting, double falseNorthing)
|
double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
_two_a = 2.0 * ellipsoid->radius();
|
_two_a = 2.0 * ellipsoid.radius();
|
||||||
|
|
||||||
if (longitudeOrigin > M_PI)
|
if (longitudeOrigin > M_PI)
|
||||||
longitudeOrigin -= 2*M_PI;
|
longitudeOrigin -= 2*M_PI;
|
||||||
@ -68,7 +68,7 @@ PolarStereographic::PolarStereographic(const Ellipsoid *ellipsoid,
|
|||||||
_falseEasting = falseEasting;
|
_falseEasting = falseEasting;
|
||||||
_falseNorthing = falseNorthing;
|
_falseNorthing = falseNorthing;
|
||||||
|
|
||||||
double es2 = ellipsoid->es();
|
double es2 = ellipsoid.es();
|
||||||
_es = sqrt(es2);
|
_es = sqrt(es2);
|
||||||
_es_OVER_2 = _es / 2.0;
|
_es_OVER_2 = _es / 2.0;
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ PolarStereographic::PolarStereographic(const Ellipsoid *ellipsoid,
|
|||||||
double pow_es = POLAR_POW(essin);
|
double pow_es = POLAR_POW(essin);
|
||||||
double clat = cos(_originLatitude);
|
double clat = cos(_originLatitude);
|
||||||
_mc = clat / sqrt(1.0 - essin * essin);
|
_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;
|
_tc = tan(M_PI_4 - _originLatitude / 2.0) / pow_es;
|
||||||
} else {
|
} else {
|
||||||
double one_PLUS_es = 1.0 + _es;
|
double one_PLUS_es = 1.0 + _es;
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class PolarStereographic : public CT
|
class PolarStereographic : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PolarStereographic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
PolarStereographic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
virtual CT *clone() const {return new PolarStereographic(*this);}
|
virtual CT *clone() const {return new PolarStereographic(*this);}
|
||||||
|
@ -51,7 +51,7 @@ Defense.
|
|||||||
#define FLOAT_EQ(x, v, epsilon) \
|
#define FLOAT_EQ(x, v, epsilon) \
|
||||||
(((v - epsilon) < x) && (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 longitudeOrigin, double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
double j, three_es4;
|
double j, three_es4;
|
||||||
@ -61,8 +61,8 @@ Polyconic::Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
|||||||
|
|
||||||
_longitudeOrigin = deg2rad(longitudeOrigin);
|
_longitudeOrigin = deg2rad(longitudeOrigin);
|
||||||
_latitudeOrigin = deg2rad(latitudeOrigin);
|
_latitudeOrigin = deg2rad(latitudeOrigin);
|
||||||
_a = ellipsoid->radius();
|
_a = ellipsoid.radius();
|
||||||
_b = ellipsoid->b();
|
_b = ellipsoid.b();
|
||||||
if (_longitudeOrigin > M_PI)
|
if (_longitudeOrigin > M_PI)
|
||||||
_longitudeOrigin -= 2 * M_PI;
|
_longitudeOrigin -= 2 * M_PI;
|
||||||
_falseNorthing = falseNorthing;
|
_falseNorthing = falseNorthing;
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class Polyconic : public CT
|
class Polyconic : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
Polyconic(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
virtual CT *clone() const {return new Polyconic(*this);}
|
virtual CT *clone() const {return new Polyconic(*this);}
|
||||||
|
@ -9,6 +9,7 @@ class PrimeMeridian
|
|||||||
public:
|
public:
|
||||||
PrimeMeridian() : _pm(NAN) {}
|
PrimeMeridian() : _pm(NAN) {}
|
||||||
PrimeMeridian(int code);
|
PrimeMeridian(int code);
|
||||||
|
PrimeMeridian(double lon) : _pm(lon) {}
|
||||||
|
|
||||||
bool isNull() const {return std::isnan(_pm);}
|
bool isNull() const {return std::isnan(_pm);}
|
||||||
bool isValid() 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)
|
const Ellipsoid &ellipsoid = _gcs.datum().ellipsoid();
|
||||||
return;
|
const Projection::Setup &setup = pcs.setup();
|
||||||
|
|
||||||
_gcs = pcs->gcs();
|
switch (pcs.method().id()) {
|
||||||
_units = pcs->units();
|
|
||||||
_cs = pcs->coordinateSystem();
|
|
||||||
|
|
||||||
const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid();
|
|
||||||
const Projection::Setup &setup = pcs->setup();
|
|
||||||
|
|
||||||
switch (pcs->method().id()) {
|
|
||||||
case 1024:
|
case 1024:
|
||||||
_ct = new WebMercator();
|
_ct = new WebMercator();
|
||||||
break;
|
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)
|
: _gcs(gcs), _ct(0), _units(LinearUnits(9001)), _cs(cs), _geographic(true)
|
||||||
{
|
{
|
||||||
if (!gcs)
|
_ct = new LatLon(gcs.angularUnits());
|
||||||
return;
|
|
||||||
|
|
||||||
_ct = new LatLon(gcs->angularUnits());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Projection::Projection(const Projection &p)
|
Projection::Projection(const Projection &p)
|
||||||
@ -162,20 +154,20 @@ bool Projection::operator==(const Projection &p) const
|
|||||||
if (!isValid() || !p.isValid())
|
if (!isValid() || !p.isValid())
|
||||||
return false;
|
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);
|
&& _cs == p._cs && _geographic == p._geographic);
|
||||||
}
|
}
|
||||||
|
|
||||||
PointD Projection::ll2xy(const Coordinates &c) const
|
PointD Projection::ll2xy(const Coordinates &c) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(isValid());
|
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
|
Coordinates Projection::xy2ll(const PointD &p) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(isValid());
|
Q_ASSERT(isValid());
|
||||||
return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p)));
|
return _gcs.toWGS84(_ct->xy2ll(_units.toMeters(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include "pointd.h"
|
#include "pointd.h"
|
||||||
#include "linearunits.h"
|
#include "linearunits.h"
|
||||||
#include "coordinatesystem.h"
|
#include "coordinatesystem.h"
|
||||||
|
#include "gcs.h"
|
||||||
|
|
||||||
class GCS;
|
|
||||||
class PCS;
|
class PCS;
|
||||||
class CT;
|
class CT;
|
||||||
class AngularUnits;
|
class AngularUnits;
|
||||||
@ -70,18 +70,18 @@ public:
|
|||||||
int _id;
|
int _id;
|
||||||
};
|
};
|
||||||
|
|
||||||
Projection() : _gcs(0), _ct(0), _geographic(false) {}
|
Projection() : _ct(0), _geographic(false) {}
|
||||||
Projection(const Projection &p);
|
Projection(const Projection &p);
|
||||||
Projection(const PCS *pcs);
|
Projection(const PCS &pcs);
|
||||||
Projection(const GCS *gcs, const CoordinateSystem &cs
|
Projection(const GCS &gcs, const CoordinateSystem &cs
|
||||||
= CoordinateSystem(CoordinateSystem::YX));
|
= CoordinateSystem(CoordinateSystem::YX));
|
||||||
~Projection();
|
~Projection();
|
||||||
|
|
||||||
Projection &operator=(const Projection &p);
|
Projection &operator=(const Projection &p);
|
||||||
bool operator==(const Projection &p) const;
|
bool operator==(const Projection &p) const;
|
||||||
|
|
||||||
bool isNull() const {return (_gcs == 0 && _ct == 0 && _units.isNull());}
|
bool isNull() const {return (_gcs.isNull() && _ct == 0 && _units.isNull());}
|
||||||
bool isValid() const {return !(_gcs == 0 || _ct == 0 || _units.isNull());}
|
bool isValid() const {return _gcs.isValid() && _ct != 0 && _units.isValid();}
|
||||||
bool isGeographic() const {return _geographic;}
|
bool isGeographic() const {return _geographic;}
|
||||||
|
|
||||||
PointD ll2xy(const Coordinates &c) const;
|
PointD ll2xy(const Coordinates &c) const;
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
const CoordinateSystem &coordinateSystem() const {return _cs;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const GCS *_gcs;
|
GCS _gcs;
|
||||||
const CT *_ct;
|
const CT *_ct;
|
||||||
LinearUnits _units;
|
LinearUnits _units;
|
||||||
CoordinateSystem _cs;
|
CoordinateSystem _cs;
|
||||||
|
@ -40,7 +40,7 @@ static CalibrationPoint parseCalibrationPoint(const QString &str)
|
|||||||
: CalibrationPoint(xy, pp);
|
: 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(","));
|
QStringList fields(str.split(","));
|
||||||
if (fields.isEmpty())
|
if (fields.isEmpty())
|
||||||
@ -49,7 +49,6 @@ static Projection parseProjection(const QString &str, const GCS *gcs)
|
|||||||
int id = fields.at(0).toDouble(&ret);
|
int id = fields.at(0).toDouble(&ret);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return Projection();
|
return Projection();
|
||||||
PCS pcs;
|
|
||||||
int zone;
|
int zone;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
@ -61,49 +60,40 @@ static Projection parseProjection(const QString &str, const GCS *gcs)
|
|||||||
return Projection();
|
return Projection();
|
||||||
if (fields.at(3) == "S")
|
if (fields.at(3) == "S")
|
||||||
zone = -zone;
|
zone = -zone;
|
||||||
pcs = PCS(gcs, 9807, UTM::setup(zone), 9001);
|
return Projection(PCS(gcs, 9807, UTM::setup(zone), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 1: // LatLon
|
case 1: // LatLon
|
||||||
return Projection(gcs);
|
return Projection(gcs);
|
||||||
case 2: // Mercator
|
case 2: // Mercator
|
||||||
pcs = PCS(gcs, 1024, Projection::Setup(), 9001);
|
return Projection(PCS(gcs, 1024, Projection::Setup(), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 3: // Transversal Mercator
|
case 3: // Transversal Mercator
|
||||||
if (fields.size() < 7)
|
if (fields.size() < 7)
|
||||||
return Projection();
|
return Projection();
|
||||||
pcs = PCS(gcs, 9807, Projection::Setup(fields.at(3).toDouble(),
|
return Projection(PCS(gcs, 9807, Projection::Setup(
|
||||||
fields.at(2).toDouble(), fields.at(6).toDouble(),
|
fields.at(3).toDouble(), fields.at(2).toDouble(),
|
||||||
fields.at(5).toDouble(), fields.at(4).toDouble(),
|
fields.at(6).toDouble(), fields.at(5).toDouble(),
|
||||||
NAN, NAN), 9001);
|
fields.at(4).toDouble(), NAN, NAN), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 4: // Lambert 2SP
|
case 4: // Lambert 2SP
|
||||||
if (fields.size() < 8)
|
if (fields.size() < 8)
|
||||||
return Projection();
|
return Projection();
|
||||||
pcs = PCS(gcs, 9802, Projection::Setup(fields.at(4).toDouble(),
|
return Projection(PCS(gcs, 9802, Projection::Setup(
|
||||||
fields.at(5).toDouble(), NAN,
|
fields.at(4).toDouble(), fields.at(5).toDouble(), NAN,
|
||||||
fields.at(6).toDouble(), fields.at(7).toDouble(),
|
fields.at(6).toDouble(), fields.at(7).toDouble(),
|
||||||
fields.at(3).toDouble(), fields.at(2).toDouble()), 9001);
|
fields.at(3).toDouble(), fields.at(2).toDouble()), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 6: // BGN (British National Grid)
|
case 6: // BGN (British National Grid)
|
||||||
pcs = PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601, 400000,
|
return Projection(PCS(gcs, 9807, Projection::Setup(49, -2, 0.999601,
|
||||||
-100000, NAN, NAN), 9001);
|
400000, -100000, NAN, NAN), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 12: // France Lambert II etendu
|
case 12: // France Lambert II etendu
|
||||||
pcs = PCS(gcs, 9801, Projection::Setup(52, 0, 0.99987742, 600000,
|
return Projection(PCS(gcs, 9801, Projection::Setup(52, 0,
|
||||||
2200000, NAN, NAN), 9001);
|
0.99987742, 600000, 2200000, NAN, NAN), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 14: // Swiss Grid
|
case 14: // Swiss Grid
|
||||||
pcs = PCS(gcs, 9815, Projection::Setup(46.570866, 7.26225, 1.0,
|
return Projection(PCS(gcs, 9815, Projection::Setup(46.570866,
|
||||||
600000, 200000, 90.0, 90.0), 9001);
|
7.26225, 1.0, 600000, 200000, 90.0, 90.0), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 108: // Dutch RD grid
|
case 108: // Dutch RD grid
|
||||||
pcs = PCS(gcs, 9809, Projection::Setup(52.15616055555555,
|
return Projection(PCS(gcs, 9809, Projection::Setup(52.15616055555555,
|
||||||
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001);
|
5.38763888888889, 0.9999079, 155000, 463000, NAN, NAN), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
case 184: // Swedish Grid
|
case 184: // Swedish Grid
|
||||||
pcs = PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1, 1500000, 0,
|
return Projection(PCS(gcs, 9807, Projection::Setup(0, 15.808278, 1,
|
||||||
NAN, NAN), 9001);
|
1500000, 0, NAN, NAN), 9001));
|
||||||
return Projection(&pcs);
|
|
||||||
default:
|
default:
|
||||||
return Projection();
|
return Projection();
|
||||||
}
|
}
|
||||||
@ -113,7 +103,6 @@ bool RMap::parseIMP(const QByteArray &data)
|
|||||||
{
|
{
|
||||||
QStringList lines = QString(data).split("\r\n");
|
QStringList lines = QString(data).split("\r\n");
|
||||||
QVector<CalibrationPoint> calibrationPoints;
|
QVector<CalibrationPoint> calibrationPoints;
|
||||||
const GCS *gcs = 0;
|
|
||||||
QString projection, datum;
|
QString projection, datum;
|
||||||
QRegularExpression re("^P[0-9]+=");
|
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";
|
_errorString = datum + ": unknown/invalid datum";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ Defense.
|
|||||||
((double)(_a * (1.e0 - _es) / pow(DENOM(lat), 3)))
|
((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 latitudeOrigin, double longitudeOrigin, double scale,
|
||||||
double falseEasting, double falseNorthing)
|
double falseEasting, double falseNorthing)
|
||||||
{
|
{
|
||||||
@ -65,16 +65,16 @@ TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
|
|||||||
double b;
|
double b;
|
||||||
|
|
||||||
|
|
||||||
_a = ellipsoid->radius();
|
_a = ellipsoid.radius();
|
||||||
_longitudeOrigin = deg2rad(longitudeOrigin);
|
_longitudeOrigin = deg2rad(longitudeOrigin);
|
||||||
_latitudeOrigin = deg2rad(latitudeOrigin);
|
_latitudeOrigin = deg2rad(latitudeOrigin);
|
||||||
_scale = scale;
|
_scale = scale;
|
||||||
_falseEasting = falseEasting;
|
_falseEasting = falseEasting;
|
||||||
_falseNorthing = falseNorthing;
|
_falseNorthing = falseNorthing;
|
||||||
|
|
||||||
_es = ellipsoid->es();
|
_es = ellipsoid.es();
|
||||||
_ebs = (1 / (1 - _es)) - 1;
|
_ebs = (1 / (1 - _es)) - 1;
|
||||||
b = ellipsoid->b();
|
b = ellipsoid.b();
|
||||||
|
|
||||||
tn = (_a - b) / (_a + b);
|
tn = (_a - b) / (_a + b);
|
||||||
tn2 = tn * tn;
|
tn2 = tn * tn;
|
||||||
|
@ -8,7 +8,7 @@ class Ellipsoid;
|
|||||||
class TransverseMercator : public CT
|
class TransverseMercator : public CT
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TransverseMercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
TransverseMercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
|
||||||
double longitudeOrigin, double scale, double falseEasting,
|
double longitudeOrigin, double scale, double falseEasting,
|
||||||
double falseNorthing);
|
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…
x
Reference in New Issue
Block a user