mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-01 05:19:15 +02:00
Compare commits
78 Commits
Author | SHA1 | Date | |
---|---|---|---|
309fdb675c | |||
e0daf367fb | |||
32d8672698 | |||
0ef89e200d | |||
6d6c232dba | |||
8132ff722d | |||
49792064d7 | |||
7aef81d823 | |||
1d3d1aa5b7 | |||
bcd14726f3 | |||
fd15799114 | |||
a8bc2ae4c4 | |||
67aba4703b | |||
a64e5e13c3 | |||
60fcff7658 | |||
bc881836ac | |||
de05f5e64b | |||
16476dbf74 | |||
a21464d98d | |||
d6746bc444 | |||
e4d8af2040 | |||
b40e0d3bbf | |||
9300d671a1 | |||
b9ed0c3933 | |||
46cefada94 | |||
e1e49b32e6 | |||
fa99d01a77 | |||
688e309ef7 | |||
ae4723acb1 | |||
8c6f70d837 | |||
d1b0e2ef73 | |||
962310df7d | |||
f8c031e931 | |||
8022a9efbe | |||
fbab4b0097 | |||
5e5ff6d96f | |||
55e967673c | |||
757ba6a566 | |||
ee80260e46 | |||
fa3e6d8550 | |||
6e95d484cd | |||
376587202b | |||
d11ffc9ea4 | |||
bf6ebdc088 | |||
619df591e2 | |||
10aa7d3945 | |||
12319fd8fd | |||
ccb7336e3f | |||
a7fea3878c | |||
a6cf88aa92 | |||
b054cf9046 | |||
9c5153f89a | |||
2ebcdeeeff | |||
1bc4833a81 | |||
3202fc4c15 | |||
5852a9dc09 | |||
c587d8cd9a | |||
586f30a337 | |||
da06c032bc | |||
3def9f95b0 | |||
dc25290637 | |||
9fd5b1b80a | |||
94ee5b6e67 | |||
9556476f1b | |||
b6e798f5c3 | |||
e82f2a02c2 | |||
361ffacc35 | |||
18fc6cc3e2 | |||
9815f0bff2 | |||
805cbe921c | |||
d529055ea3 | |||
5d590b7c86 | |||
1003c7b56f | |||
820f967bd6 | |||
27632bf07e | |||
ee5b8fa333 | |||
7e42b57d73 | |||
292fc9b433 |
@ -1,4 +1,4 @@
|
||||
version: 5.0.{build}
|
||||
version: 5.4.{build}
|
||||
configuration: Release
|
||||
platform: Any CPU
|
||||
environment:
|
||||
|
@ -3,8 +3,8 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports GPX, TCX,
|
||||
KML, FIT, IGC and NMEA files.
|
||||
|
||||
## Features
|
||||
* User-definable online maps.
|
||||
* Offline maps (OziExplorer maps and TrekBuddy maps/atlases).
|
||||
* User-definable online maps (OSM/Google tiles, WMTS).
|
||||
* Offline maps (OziExplorer maps, TrekBuddy maps/atlases, GeoTIFF images).
|
||||
* Elevation, speed, heart rate, cadence, power and temperature graphs.
|
||||
* Support for multiple tracks in one view.
|
||||
* Support for POI files.
|
||||
|
12
gpxsee.pro
12
gpxsee.pro
@ -1,5 +1,5 @@
|
||||
TARGET = GPXSee
|
||||
VERSION = 5.0
|
||||
VERSION = 5.4
|
||||
QT += core \
|
||||
gui \
|
||||
network
|
||||
@ -116,7 +116,10 @@ HEADERS += src/config.h \
|
||||
src/map/primemeridian.h \
|
||||
src/map/linearunits.h \
|
||||
src/map/ct.h \
|
||||
src/map/mapsource.h
|
||||
src/map/mapsource.h \
|
||||
src/map/tileloader.h \
|
||||
src/map/wmtsmap.h \
|
||||
src/map/wmts.h
|
||||
SOURCES += src/main.cpp \
|
||||
src/common/coordinates.cpp \
|
||||
src/common/rectc.cpp \
|
||||
@ -202,7 +205,10 @@ SOURCES += src/main.cpp \
|
||||
src/map/angularunits.cpp \
|
||||
src/map/primemeridian.cpp \
|
||||
src/map/linearunits.cpp \
|
||||
src/map/mapsource.cpp
|
||||
src/map/mapsource.cpp \
|
||||
src/map/tileloader.cpp \
|
||||
src/map/wmtsmap.cpp \
|
||||
src/map/wmts.cpp
|
||||
RESOURCES += gpxsee.qrc
|
||||
TRANSLATIONS = lang/gpxsee_cs.ts \
|
||||
lang/gpxsee_sv.ts \
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
58
pkg/appdata.xml
Normal file
58
pkg/appdata.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop">
|
||||
<id>gpxsee.desktop</id>
|
||||
<metadata_license>MIT</metadata_license>
|
||||
<project_license>GPL-3.0</project_license>
|
||||
|
||||
<name>GPXSee</name>
|
||||
<summary>GPS log file viewer and analyzer</summary>
|
||||
<description>
|
||||
<p>GPXSee is a GPS log file viewer and analyzer that supports GPX, TCX,
|
||||
KML, FIT, IGC and NMEA files.</p>
|
||||
|
||||
<p>Features:</p>
|
||||
<ul>
|
||||
<li>User-definable online maps.</li>
|
||||
<li>Offline maps (OziExplorer maps, TrekBuddy maps/atlases, GeoTIFF
|
||||
images).</li>
|
||||
<li>Elevation, speed, heart rate, cadence, power and temperature
|
||||
graphs.</li>
|
||||
<li>Support for multiple tracks in one view.</li>
|
||||
<li>Support for POI files.</li>
|
||||
<li>Print/export to PDF.</li>
|
||||
<li>Full-screen mode.</li>
|
||||
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA and Garmin CSV files.</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>http://www.gpxsee.org/gallery/lin1.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>http://www.gpxsee.org/gallery/lin2.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<categories>
|
||||
<category>Graphics</category>
|
||||
<category>Viewer</category>
|
||||
</categories>
|
||||
|
||||
<url type="homepage">http://www.gpxsee.org</url>
|
||||
|
||||
<launchable type="desktop-id">gpxsee.desktop</launchable>
|
||||
|
||||
<provides>
|
||||
<binary>gpxsee</binary>
|
||||
</provides>
|
||||
|
||||
<mimetypes>
|
||||
<mimetype>application/gpx+xml</mimetype>
|
||||
<mimetype>application/tcx+xml</mimetype>
|
||||
<mimetype>application/vnd.ant.fit</mimetype>
|
||||
<mimetype>application/vnd.google-earth.kml+xml</mimetype>
|
||||
<mimetype>application/vnd.fai.igc</mimetype>
|
||||
<mimetype>application/vnd.nmea.nmea</mimetype>
|
||||
</mimetypes>
|
||||
</component>
|
@ -21,7 +21,7 @@ Canton Astro 1966,4716,6716,9122,7022,8901,9603,298,-304,-375
|
||||
Cape,4222,6222,9122,7012,8901,9603,-136,-108,-292
|
||||
Cape Canaveral,4717,6717,9122,7008,8901,9603,-2,150,181
|
||||
Carthage,4223,6223,9122,7012,8901,9603,-263,6,431
|
||||
CH-1903,4149,6149,9122,7004,8901,9603,674,15,405
|
||||
CH-1903,4149,6149,9122,7004,8901,9603,674.374,15.056,405.343
|
||||
Chatham 1971,4672,6672,9122,7022,8901,9603,175,-38,113
|
||||
Chua Astro,4224,6224,9122,7022,8901,9603,-134,229,-29
|
||||
Corrego Alegre,4225,6225,9122,7022,8901,9603,-206,172,-6
|
||||
@ -29,6 +29,7 @@ Djakarta (Batavia),4211,6211,9122,7004,8901,9603,-377,681,-50
|
||||
DOS 1968,,,9122,7022,8901,9603,230,-199,-752
|
||||
Easter Island 1967,4719,6719,9122,7022,8901,9603,211,147,111
|
||||
Egypt,4199,6199,9122,7022,8901,9603,-130,-117,-151
|
||||
ETRS 89,4258,6258,9122,7019,8901,9603,0,0,0
|
||||
European 1950,4230,6230,9122,7022,8901,9603,-87,-98,-121
|
||||
European 1950 (Mean France),,,9122,7022,8901,9603,-87,-96,-120
|
||||
European 1950 (Spain and Portugal),,,9122,7022,8901,9603,-84,-107,-120
|
||||
@ -104,6 +105,7 @@ Rijksdriehoeksmeting,4289,6289,9122,7004,8901,9603,593,26,478
|
||||
Rome 1940,4806,6806,9122,7022,8906,9603,-225,-65,9
|
||||
RT 90,4124,6124,9122,7004,8901,9603,498,-36,568
|
||||
S42,4179,6179,9122,7024,8901,9603,28,-121,-77
|
||||
S42 (83),4178,6178,9122,7024,8901,9603,26,-121,-78
|
||||
Santo (DOS),4730,6730,9122,7022,8901,9603,170,42,84
|
||||
Sao Braz,4184,6184,9122,7022,8901,9603,-203,141,53
|
||||
Sapper Hill 1943,4292,6292,9122,7022,8901,9603,-355,16,74
|
||||
|
|
3415
pkg/csv/pcs.csv
3415
pkg/csv/pcs.csv
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "5.0"
|
||||
!define VERSION "5.4"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
|
@ -5,7 +5,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "5.0"
|
||||
!define VERSION "5.4"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -4,4 +4,5 @@
|
||||
<url>http://4umaps.eu/$z/$x/$y.png</url>
|
||||
<zoom min="2" max="15"/>
|
||||
<bounds bottom="-65"/>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
|
||||
</map>
|
||||
|
@ -2,4 +2,5 @@
|
||||
<map>
|
||||
<name>Open Street Map</name>
|
||||
<url>http://tile.openstreetmap.org/$z/$x/$y.png</url>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © OpenStreetMap (CC-BY-SA)</copyright>
|
||||
</map>
|
||||
|
@ -3,4 +3,5 @@
|
||||
<name>Open Topo Map</name>
|
||||
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
|
||||
<zoom max="17"/>
|
||||
<copyright>Map data: © OpenStreetMap contributors (ODbL), SRTM | Rendering: © OpenTopoMap (CC-BY-SA)</copyright>
|
||||
</map>
|
||||
|
@ -4,4 +4,5 @@
|
||||
<url>https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y</url>
|
||||
<zoom min="2" max="15"/>
|
||||
<bounds bottom="0" top="74"/>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
</map>
|
||||
|
@ -3,4 +3,5 @@
|
||||
<name>USGS Topo</name>
|
||||
<url>https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png</url>
|
||||
<zoom min="2" max="15"/>
|
||||
<copyright>Map services and data available from U.S. Geological Survey, National Geospatial Program.</copyright>
|
||||
</map>
|
||||
|
@ -4,7 +4,8 @@
|
||||
#include <QFileOpenEvent>
|
||||
#include <QNetworkProxyFactory>
|
||||
#include <QLibraryInfo>
|
||||
#include "map/onlinemap.h"
|
||||
#include "map/wmts.h"
|
||||
#include "map/tileloader.h"
|
||||
#include "map/downloader.h"
|
||||
#include "map/ellipsoid.h"
|
||||
#include "map/gcs.h"
|
||||
@ -36,7 +37,9 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
OnlineMap::setDownloader(new Downloader(this));
|
||||
Downloader *dl = new Downloader(this);
|
||||
TileLoader::setDownloader(dl);
|
||||
WMTS::setDownloader(dl);
|
||||
OPENGL_SET_SAMPLES(4);
|
||||
loadDatums();
|
||||
loadPCSs();
|
||||
|
@ -62,12 +62,17 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
_bottomMargin = new QDoubleSpinBox();
|
||||
_leftMargin = new QDoubleSpinBox();
|
||||
_rightMargin = new QDoubleSpinBox();
|
||||
QString us = (_export->units == Imperial) ? tr("in") : tr("mm");
|
||||
QString us = (_export->units == Metric) ? tr("mm") : tr("in");
|
||||
_topMargin->setSuffix(UNIT_SPACE + us);
|
||||
_bottomMargin->setSuffix(UNIT_SPACE + us);
|
||||
_leftMargin->setSuffix(UNIT_SPACE + us);
|
||||
_rightMargin->setSuffix(UNIT_SPACE + us);
|
||||
if (_export->units == Imperial) {
|
||||
if (_export->units == Metric) {
|
||||
_topMargin->setValue(_export->margins.top());
|
||||
_bottomMargin->setValue(_export->margins.bottom());
|
||||
_leftMargin->setValue(_export->margins.left());
|
||||
_rightMargin->setValue(_export->margins.right());
|
||||
} else {
|
||||
_topMargin->setValue(_export->margins.top() * MM2IN);
|
||||
_bottomMargin->setValue(_export->margins.bottom() * MM2IN);
|
||||
_leftMargin->setValue(_export->margins.left() * MM2IN);
|
||||
@ -76,11 +81,6 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
||||
_bottomMargin->setSingleStep(0.1);
|
||||
_leftMargin->setSingleStep(0.1);
|
||||
_rightMargin->setSingleStep(0.1);
|
||||
} else {
|
||||
_topMargin->setValue(_export->margins.top());
|
||||
_bottomMargin->setValue(_export->margins.bottom());
|
||||
_leftMargin->setValue(_export->margins.left());
|
||||
_rightMargin->setValue(_export->margins.right());
|
||||
}
|
||||
|
||||
QGridLayout *marginsLayout = new QGridLayout();
|
||||
|
@ -2,6 +2,32 @@
|
||||
#include "common/coordinates.h"
|
||||
#include "format.h"
|
||||
|
||||
|
||||
static QString deg2DMS(double val)
|
||||
{
|
||||
int deg = val;
|
||||
double r1 = val - deg;
|
||||
|
||||
int min = r1 * 60.0;
|
||||
double r2 = r1 - (min / 60.0);
|
||||
|
||||
double sec = r2 * 3600.0;
|
||||
|
||||
return QString("%1°%2'%3\"").arg(deg).arg(min, 2, 10, QChar('0'))
|
||||
.arg(sec, 4, 'f', 1, QChar('0'));
|
||||
}
|
||||
|
||||
static QString deg2DMM(double val)
|
||||
{
|
||||
int deg = val;
|
||||
double r1 = val - deg;
|
||||
|
||||
double min = r1 * 60.0;
|
||||
|
||||
return QString("%1°%2'").arg(deg).arg(min, 6, 'f', 3, QChar('0'));
|
||||
}
|
||||
|
||||
|
||||
QString Format::timeSpan(qreal time, bool full)
|
||||
{
|
||||
unsigned h, m, s;
|
||||
@ -27,6 +53,13 @@ QString Format::distance(qreal value, Units units)
|
||||
else
|
||||
return QString::number(value * M2MI, 'f', 1) + UNIT_SPACE
|
||||
+ qApp->translate("Format", "mi");
|
||||
} else if (units == Nautical) {
|
||||
if (value < NMIINM)
|
||||
return QString::number(value * M2FT, 'f', 0) + UNIT_SPACE
|
||||
+ qApp->translate("Format", "ft");
|
||||
else
|
||||
return QString::number(value * M2NMI, 'f', 1) + UNIT_SPACE
|
||||
+ qApp->translate("Format", "nmi");
|
||||
} else {
|
||||
if (value < KMINM)
|
||||
return QString::number(value, 'f', 0) + UNIT_SPACE
|
||||
@ -47,11 +80,22 @@ QString Format::elevation(qreal value, Units units)
|
||||
+ qApp->translate("Format", "ft");
|
||||
}
|
||||
|
||||
QString Format::coordinates(const Coordinates &value)
|
||||
QString Format::coordinates(const Coordinates &value, CoordinatesFormat type)
|
||||
{
|
||||
QChar yH = (value.lat() < 0) ? 'S' : 'N';
|
||||
QChar xH = (value.lon() < 0) ? 'W' : 'E';
|
||||
|
||||
return QString::number(qAbs(value.lat()), 'f', 5) + yH + "," + QChar(0x00A0)
|
||||
+ QString::number(qAbs(value.lon()), 'f', 5) + xH;
|
||||
switch (type) {
|
||||
case DegreesMinutes:
|
||||
return deg2DMM(qAbs(value.lat())) + yH + "," + QChar(0x00A0)
|
||||
+ deg2DMM(qAbs(value.lon())) + xH;
|
||||
break;
|
||||
case DMS:
|
||||
return deg2DMS(qAbs(value.lat())) + yH + "," + QChar(0x00A0)
|
||||
+ deg2DMS(qAbs(value.lon())) + xH;
|
||||
break;
|
||||
default:
|
||||
return QString::number(qAbs(value.lat()), 'f', 5) + yH + ","
|
||||
+ QChar(0x00A0) + QString::number(qAbs(value.lon()), 'f', 5) + xH;
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,18 @@
|
||||
|
||||
class Coordinates;
|
||||
|
||||
enum CoordinatesFormat {
|
||||
DecimalDegrees,
|
||||
DegreesMinutes,
|
||||
DMS
|
||||
};
|
||||
|
||||
namespace Format
|
||||
{
|
||||
QString timeSpan(qreal time, bool full = true);
|
||||
QString distance(qreal value, Units units);
|
||||
QString elevation(qreal value, Units units);
|
||||
QString coordinates(const Coordinates &value);
|
||||
QString coordinates(const Coordinates &value, CoordinatesFormat type);
|
||||
}
|
||||
|
||||
#endif // FORMAT_H
|
||||
|
@ -12,6 +12,7 @@ class GraphItem : public QGraphicsObject
|
||||
|
||||
public:
|
||||
GraphItem(const Graph &graph, GraphType type, QGraphicsItem *parent = 0);
|
||||
virtual ~GraphItem() {}
|
||||
|
||||
QPainterPath shape() const {return _shape;}
|
||||
QRectF boundingRect() const {return _shape.boundingRect();}
|
||||
|
@ -16,6 +16,7 @@ class GraphTab : public GraphView
|
||||
public:
|
||||
GraphTab(QWidget *parent = 0) : GraphView(parent)
|
||||
{setFrameShape(QFrame::NoFrame);}
|
||||
virtual ~GraphTab() {}
|
||||
|
||||
virtual QString label() const = 0;
|
||||
virtual void loadData(const Data &data, const QList<PathItem *> &paths) = 0;
|
||||
|
@ -104,15 +104,7 @@ void GraphView::setYUnits(const QString &units)
|
||||
void GraphView::setXUnits()
|
||||
{
|
||||
if (_graphType == Distance) {
|
||||
if (_units == Metric) {
|
||||
if (bounds().width() < KMINM) {
|
||||
_xUnits = tr("m");
|
||||
_xScale = 1;
|
||||
} else {
|
||||
_xUnits = tr("km");
|
||||
_xScale = M2KM;
|
||||
}
|
||||
} else {
|
||||
if (_units == Imperial) {
|
||||
if (bounds().width() < MIINM) {
|
||||
_xUnits = tr("ft");
|
||||
_xScale = M2FT;
|
||||
@ -120,6 +112,22 @@ void GraphView::setXUnits()
|
||||
_xUnits = tr("mi");
|
||||
_xScale = M2MI;
|
||||
}
|
||||
} else if (_units == Nautical) {
|
||||
if (bounds().width() < NMIINM) {
|
||||
_xUnits = tr("ft");
|
||||
_xScale = M2FT;
|
||||
} else {
|
||||
_xUnits = tr("nmi");
|
||||
_xScale = M2NMI;
|
||||
}
|
||||
} else {
|
||||
if (bounds().width() < KMINM) {
|
||||
_xUnits = tr("m");
|
||||
_xScale = 1;
|
||||
} else {
|
||||
_xUnits = tr("km");
|
||||
_xScale = M2KM;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (bounds().width() < MININS) {
|
||||
|
112
src/GUI/gui.cpp
112
src/GUI/gui.cpp
@ -40,7 +40,6 @@
|
||||
#include "filebrowser.h"
|
||||
#include "cpuarch.h"
|
||||
#include "graphtab.h"
|
||||
#include "format.h"
|
||||
#include "gui.h"
|
||||
|
||||
|
||||
@ -373,6 +372,28 @@ void GUI::createActions()
|
||||
_imperialUnitsAction->setActionGroup(ag);
|
||||
connect(_imperialUnitsAction, SIGNAL(triggered()), this,
|
||||
SLOT(setImperialUnits()));
|
||||
_nauticalUnitsAction = new QAction(tr("Nautical"), this);
|
||||
_nauticalUnitsAction->setCheckable(true);
|
||||
_nauticalUnitsAction->setActionGroup(ag);
|
||||
connect(_nauticalUnitsAction, SIGNAL(triggered()), this,
|
||||
SLOT(setNauticalUnits()));
|
||||
ag = new QActionGroup(this);
|
||||
ag->setExclusive(true);
|
||||
_decimalDegreesAction = new QAction(tr("Decimal degrees (DD)"), this);
|
||||
_decimalDegreesAction->setCheckable(true);
|
||||
_decimalDegreesAction->setActionGroup(ag);
|
||||
connect(_decimalDegreesAction, SIGNAL(triggered()), this,
|
||||
SLOT(setDecimalDegrees()));
|
||||
_degreesMinutesAction = new QAction(tr("Degrees and decimal minutes (DMM)"),
|
||||
this);
|
||||
_degreesMinutesAction->setCheckable(true);
|
||||
_degreesMinutesAction->setActionGroup(ag);
|
||||
connect(_degreesMinutesAction, SIGNAL(triggered()), this,
|
||||
SLOT(setDegreesMinutes()));
|
||||
_DMSAction = new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
|
||||
_DMSAction->setCheckable(true);
|
||||
_DMSAction->setActionGroup(ag);
|
||||
connect(_DMSAction, SIGNAL(triggered()), this, SLOT(setDMS()));
|
||||
_fullscreenAction = new QAction(QIcon(QPixmap(FULLSCREEN_ICON)),
|
||||
tr("Fullscreen mode"), this);
|
||||
_fullscreenAction->setCheckable(true);
|
||||
@ -404,7 +425,7 @@ void GUI::createActions()
|
||||
|
||||
void GUI::createMenus()
|
||||
{
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("File"));
|
||||
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
|
||||
fileMenu->addAction(_openFileAction);
|
||||
fileMenu->addSeparator();
|
||||
fileMenu->addAction(_printFileAction);
|
||||
@ -418,7 +439,7 @@ void GUI::createMenus()
|
||||
fileMenu->addAction(_exitAction);
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
_mapMenu = menuBar()->addMenu(tr("Map"));
|
||||
_mapMenu = menuBar()->addMenu(tr("&Map"));
|
||||
_mapMenu->addActions(_mapActions);
|
||||
_mapsEnd = _mapMenu->addSeparator();
|
||||
_mapMenu->addAction(_loadMapAction);
|
||||
@ -426,7 +447,7 @@ void GUI::createMenus()
|
||||
_mapMenu->addSeparator();
|
||||
_mapMenu->addAction(_showMapAction);
|
||||
|
||||
QMenu *graphMenu = menuBar()->addMenu(tr("Graph"));
|
||||
QMenu *graphMenu = menuBar()->addMenu(tr("&Graph"));
|
||||
graphMenu->addAction(_distanceGraphAction);
|
||||
graphMenu->addAction(_timeGraphAction);
|
||||
graphMenu->addSeparator();
|
||||
@ -435,7 +456,7 @@ void GUI::createMenus()
|
||||
graphMenu->addSeparator();
|
||||
graphMenu->addAction(_showGraphsAction);
|
||||
|
||||
QMenu *poiMenu = menuBar()->addMenu(tr("POI"));
|
||||
QMenu *poiMenu = menuBar()->addMenu(tr("&POI"));
|
||||
_poiFilesMenu = poiMenu->addMenu(tr("POI files"));
|
||||
_poiFilesMenu->addActions(_poiFilesActions);
|
||||
poiMenu->addSeparator();
|
||||
@ -447,7 +468,7 @@ void GUI::createMenus()
|
||||
poiMenu->addSeparator();
|
||||
poiMenu->addAction(_showPOIAction);
|
||||
|
||||
QMenu *dataMenu = menuBar()->addMenu(tr("Data"));
|
||||
QMenu *dataMenu = menuBar()->addMenu(tr("&Data"));
|
||||
QMenu *displayMenu = dataMenu->addMenu(tr("Display"));
|
||||
displayMenu->addAction(_showWaypointLabelsAction);
|
||||
displayMenu->addAction(_showRouteWaypointsAction);
|
||||
@ -456,20 +477,25 @@ void GUI::createMenus()
|
||||
dataMenu->addAction(_showRoutesAction);
|
||||
dataMenu->addAction(_showWaypointsAction);
|
||||
|
||||
QMenu *settingsMenu = menuBar()->addMenu(tr("Settings"));
|
||||
QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
|
||||
QMenu *timeMenu = settingsMenu->addMenu(tr("Time"));
|
||||
timeMenu->addAction(_totalTimeAction);
|
||||
timeMenu->addAction(_movingTimeAction);
|
||||
QMenu *unitsMenu = settingsMenu->addMenu(tr("Units"));
|
||||
unitsMenu->addAction(_metricUnitsAction);
|
||||
unitsMenu->addAction(_imperialUnitsAction);
|
||||
unitsMenu->addAction(_nauticalUnitsAction);
|
||||
QMenu *coordinatesMenu = settingsMenu->addMenu(tr("Coordinates format"));
|
||||
coordinatesMenu->addAction(_decimalDegreesAction);
|
||||
coordinatesMenu->addAction(_degreesMinutesAction);
|
||||
coordinatesMenu->addAction(_DMSAction);
|
||||
settingsMenu->addSeparator();
|
||||
settingsMenu->addAction(_showToolbarsAction);
|
||||
settingsMenu->addAction(_fullscreenAction);
|
||||
settingsMenu->addSeparator();
|
||||
settingsMenu->addAction(_openOptionsAction);
|
||||
|
||||
QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
|
||||
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
|
||||
helpMenu->addAction(_pathsAction);
|
||||
helpMenu->addAction(_keysAction);
|
||||
helpMenu->addSeparator();
|
||||
@ -1121,7 +1147,7 @@ bool GUI::loadMap(const QString &fileName)
|
||||
_mapMenu->insertAction(_mapsEnd, a);
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
_mapActions.last()->activate(QAction::Trigger);
|
||||
_mapActions.last()->trigger();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@ -1293,6 +1319,11 @@ void GUI::setUnits(Units units)
|
||||
updateStatusBarInfo();
|
||||
}
|
||||
|
||||
void GUI::setCoordinatesFormat(CoordinatesFormat format)
|
||||
{
|
||||
_mapView->setCoordinatesFormat(format);
|
||||
}
|
||||
|
||||
void GUI::setGraphType(GraphType type)
|
||||
{
|
||||
_sliderPos = 0;
|
||||
@ -1363,15 +1394,15 @@ void GUI::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
case TOGGLE_GRAPH_TYPE_KEY:
|
||||
if (_timeGraphAction->isChecked())
|
||||
_distanceGraphAction->activate(QAction::Trigger);
|
||||
_distanceGraphAction->trigger();
|
||||
else
|
||||
_timeGraphAction->activate(QAction::Trigger);
|
||||
_timeGraphAction->trigger();
|
||||
break;
|
||||
case TOGGLE_TIME_TYPE_KEY:
|
||||
if (_movingTimeAction->isChecked())
|
||||
_totalTimeAction->activate(QAction::Trigger);
|
||||
_totalTimeAction->trigger();
|
||||
else
|
||||
_movingTimeAction->activate(QAction::Trigger);
|
||||
_movingTimeAction->trigger();
|
||||
break;
|
||||
|
||||
case Qt::Key_Escape:
|
||||
@ -1437,11 +1468,15 @@ void GUI::writeSettings()
|
||||
if ((_movingTimeAction->isChecked() ? Moving : Total) !=
|
||||
TIME_TYPE_DEFAULT)
|
||||
settings.setValue(TIME_TYPE_SETTING, _movingTimeAction->isChecked()
|
||||
? Moving : Total);
|
||||
if ((_imperialUnitsAction->isChecked() ? Imperial : Metric) !=
|
||||
UNITS_DEFAULT)
|
||||
settings.setValue(UNITS_SETTING, _imperialUnitsAction->isChecked()
|
||||
? Imperial : Metric);
|
||||
? Moving : Total);
|
||||
Units units = _imperialUnitsAction->isChecked() ? Imperial
|
||||
: _nauticalUnitsAction->isChecked() ? Nautical : Metric;
|
||||
if (units != UNITS_DEFAULT)
|
||||
settings.setValue(UNITS_SETTING, units);
|
||||
CoordinatesFormat format = _DMSAction->isChecked() ? DMS
|
||||
: _degreesMinutesAction->isChecked() ? DegreesMinutes : DecimalDegrees;
|
||||
if (format != COORDINATES_DEFAULT)
|
||||
settings.setValue(COORDINATES_SETTING, format);
|
||||
if (_showToolbarsAction->isChecked() != SHOW_TOOLBARS_DEFAULT)
|
||||
settings.setValue(SHOW_TOOLBARS_SETTING,
|
||||
_showToolbarsAction->isChecked());
|
||||
@ -1601,6 +1636,7 @@ void GUI::writeSettings()
|
||||
|
||||
void GUI::readSettings()
|
||||
{
|
||||
int value;
|
||||
QSettings settings(APP_NAME, APP_NAME);
|
||||
|
||||
settings.beginGroup(WINDOW_SETTINGS_GROUP);
|
||||
@ -1610,20 +1646,27 @@ void GUI::readSettings()
|
||||
|
||||
settings.beginGroup(SETTINGS_SETTINGS_GROUP);
|
||||
if (settings.value(TIME_TYPE_SETTING, TIME_TYPE_DEFAULT).toInt()
|
||||
== Moving) {
|
||||
setTimeType(Moving);
|
||||
_movingTimeAction->setChecked(true);
|
||||
} else {
|
||||
setTimeType(Total);
|
||||
_totalTimeAction->setChecked(true);
|
||||
}
|
||||
if (settings.value(UNITS_SETTING, UNITS_DEFAULT).toInt() == Imperial) {
|
||||
setUnits(Imperial);
|
||||
_imperialUnitsAction->setChecked(true);
|
||||
} else {
|
||||
setUnits(Metric);
|
||||
_metricUnitsAction->setChecked(true);
|
||||
}
|
||||
== Moving)
|
||||
_movingTimeAction->trigger();
|
||||
else
|
||||
_totalTimeAction->trigger();
|
||||
|
||||
value = settings.value(UNITS_SETTING, UNITS_DEFAULT).toInt();
|
||||
if (value == Imperial)
|
||||
_imperialUnitsAction->trigger();
|
||||
else if (value == Nautical)
|
||||
_nauticalUnitsAction->trigger();
|
||||
else
|
||||
_metricUnitsAction->trigger();
|
||||
|
||||
value = settings.value(COORDINATES_SETTING, COORDINATES_DEFAULT).toInt();
|
||||
if (value == DMS)
|
||||
_DMSAction->trigger();
|
||||
else if (value == DegreesMinutes)
|
||||
_degreesMinutesAction->trigger();
|
||||
else
|
||||
_decimalDegreesAction->trigger();
|
||||
|
||||
if (!settings.value(SHOW_TOOLBARS_SETTING, SHOW_TOOLBARS_DEFAULT).toBool())
|
||||
showToolbars(false);
|
||||
else
|
||||
@ -1633,6 +1676,8 @@ void GUI::readSettings()
|
||||
settings.beginGroup(MAP_SETTINGS_GROUP);
|
||||
if (settings.value(SHOW_MAP_SETTING, SHOW_MAP_DEFAULT).toBool())
|
||||
_showMapAction->setChecked(true);
|
||||
else
|
||||
_mapView->showMap(false);
|
||||
if (_ml->maps().count()) {
|
||||
int index = mapIndex(settings.value(CURRENT_MAP_SETTING).toString());
|
||||
_mapActions.at(index)->trigger();
|
||||
@ -1867,7 +1912,8 @@ int GUI::mapIndex(const QString &name)
|
||||
|
||||
Units GUI::units() const
|
||||
{
|
||||
return _imperialUnitsAction->isChecked() ? Imperial : Metric;
|
||||
return _imperialUnitsAction->isChecked() ? Imperial
|
||||
: _nauticalUnitsAction->isChecked() ? Nautical : Metric;
|
||||
}
|
||||
|
||||
qreal GUI::distance() const
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "data/poi.h"
|
||||
#include "units.h"
|
||||
#include "timetype.h"
|
||||
#include "format.h"
|
||||
#include "exportdialog.h"
|
||||
#include "optionsdialog.h"
|
||||
|
||||
@ -73,8 +74,12 @@ private slots:
|
||||
void setMovingTime() {setTimeType(Moving);}
|
||||
void setMetricUnits() {setUnits(Metric);}
|
||||
void setImperialUnits() {setUnits(Imperial);}
|
||||
void setNauticalUnits() {setUnits(Nautical);}
|
||||
void setDistanceGraph() {setGraphType(Distance);}
|
||||
void setTimeGraph() {setGraphType(Time);}
|
||||
void setDecimalDegrees() {setCoordinatesFormat(DecimalDegrees);}
|
||||
void setDegreesMinutes() {setCoordinatesFormat(DegreesMinutes);}
|
||||
void setDMS() {setCoordinatesFormat(DMS);}
|
||||
|
||||
void sliderPositionChanged(qreal pos);
|
||||
|
||||
@ -111,6 +116,7 @@ private:
|
||||
Units units() const;
|
||||
void setTimeType(TimeType type);
|
||||
void setUnits(Units units);
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void setGraphType(GraphType type);
|
||||
|
||||
qreal distance() const;
|
||||
@ -165,6 +171,10 @@ private:
|
||||
QAction *_firstAction;
|
||||
QAction *_metricUnitsAction;
|
||||
QAction *_imperialUnitsAction;
|
||||
QAction *_nauticalUnitsAction;
|
||||
QAction *_decimalDegreesAction;
|
||||
QAction *_degreesMinutesAction;
|
||||
QAction *_DMSAction;
|
||||
QAction *_totalTimeAction;
|
||||
QAction *_movingTimeAction;
|
||||
QAction *_nextMapAction;
|
||||
|
@ -49,6 +49,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
connect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
|
||||
|
||||
_units = Metric;
|
||||
_coordinatesFormat = DecimalDegrees;
|
||||
_opacity = 1.0;
|
||||
_backgroundColor = Qt::white;
|
||||
_markerColor = Qt::red;
|
||||
@ -75,6 +76,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
_digitalZoom = 0;
|
||||
|
||||
_map->setBackgroundColor(_backgroundColor);
|
||||
_res = _map->resolution(_map->bounds());
|
||||
_scene->setSceneRect(_map->bounds());
|
||||
|
||||
centerOn(_scene->sceneRect().center());
|
||||
@ -83,18 +85,8 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
void MapView::centerOn(const QPointF &pos)
|
||||
{
|
||||
QGraphicsView::centerOn(pos);
|
||||
|
||||
/* Fix the offset caused by QGraphicsView::centerOn() approximation */
|
||||
QPointF center = mapToScene(viewport()->rect().center());
|
||||
QPoint offset((int)(pos.x() - center.x()), (int)(pos.y() - center.y()));
|
||||
if (qAbs(offset.x()) == 1)
|
||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value()
|
||||
+ offset.x());
|
||||
if (qAbs(offset.y()) == 1)
|
||||
verticalScrollBar()->setValue(verticalScrollBar()->value()
|
||||
+ offset.y());
|
||||
|
||||
_res = _map->resolution(pos);
|
||||
QRectF vr(mapToScene(viewport()->rect()).boundingRect());
|
||||
_res = _map->resolution(vr);
|
||||
_mapScale->setResolution(_res);
|
||||
}
|
||||
|
||||
@ -137,6 +129,7 @@ PathItem *MapView::addRoute(const Route &route)
|
||||
ri->setWidth(_routeWidth);
|
||||
ri->setStyle(_routeStyle);
|
||||
ri->setUnits(_units);
|
||||
ri->setCoordinatesFormat(_coordinatesFormat);
|
||||
ri->setVisible(_showRoutes);
|
||||
ri->showWaypoints(_showRouteWaypoints);
|
||||
ri->showWaypointLabels(_showWaypointLabels);
|
||||
@ -162,7 +155,7 @@ void MapView::addWaypoints(const QList<Waypoint> &waypoints)
|
||||
wi->setSize(_waypointSize);
|
||||
wi->setColor(_waypointColor);
|
||||
wi->showLabel(_showWaypointLabels);
|
||||
wi->setUnits(_units);
|
||||
wi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
wi->setVisible(_showWaypoints);
|
||||
wi->setDigitalZoom(_digitalZoom);
|
||||
_scene->addItem(wi);
|
||||
@ -175,7 +168,7 @@ void MapView::addWaypoints(const QList<Waypoint> &waypoints)
|
||||
QList<PathItem *> MapView::loadData(const Data &data)
|
||||
{
|
||||
QList<PathItem *> paths;
|
||||
qreal zoom = _map->zoom();
|
||||
int zoom = _map->zoom();
|
||||
|
||||
for (int i = 0; i < data.tracks().count(); i++)
|
||||
paths.append(addTrack(*(data.tracks().at(i))));
|
||||
@ -196,7 +189,7 @@ QList<PathItem *> MapView::loadData(const Data &data)
|
||||
return paths;
|
||||
}
|
||||
|
||||
qreal MapView::mapZoom() const
|
||||
int MapView::mapZoom() const
|
||||
{
|
||||
RectC br = _tr | _rr | _wr;
|
||||
|
||||
@ -265,9 +258,9 @@ void MapView::setPalette(const Palette &palette)
|
||||
|
||||
void MapView::setMap(Map *map)
|
||||
{
|
||||
QPointF pos = mapToScene(viewport()->rect().center());
|
||||
Coordinates center = _map->xy2ll(pos);
|
||||
qreal resolution = _map->resolution(pos);
|
||||
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
|
||||
.intersected(_map->bounds()));
|
||||
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
||||
|
||||
_map->unload();
|
||||
disconnect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
||||
@ -279,7 +272,7 @@ void MapView::setMap(Map *map)
|
||||
|
||||
digitalZoom(0);
|
||||
|
||||
_map->zoomFit(resolution, center);
|
||||
_map->zoomFit(viewport()->rect().size(), cr);
|
||||
_scene->setSceneRect(_map->bounds());
|
||||
|
||||
for (int i = 0; i < _tracks.size(); i++)
|
||||
@ -294,7 +287,7 @@ void MapView::setMap(Map *map)
|
||||
it.value()->setMap(_map);
|
||||
updatePOIVisibility();
|
||||
|
||||
centerOn(_map->ll2xy(center));
|
||||
centerOn(_map->ll2xy(cr.center()));
|
||||
|
||||
resetCachedContent();
|
||||
QPixmapCache::clear();
|
||||
@ -348,28 +341,49 @@ void MapView::addPOI(const QList<Waypoint> &waypoints)
|
||||
pi->showLabel(_showPOILabels);
|
||||
pi->setVisible(_showPOI);
|
||||
pi->setDigitalZoom(_digitalZoom);
|
||||
pi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
_scene->addItem(pi);
|
||||
|
||||
_pois.insert(SearchPointer<Waypoint>(&(pi->waypoint())), pi);
|
||||
}
|
||||
}
|
||||
|
||||
void MapView::setUnits(enum Units units)
|
||||
void MapView::setUnits(Units units)
|
||||
{
|
||||
if (_units == units)
|
||||
return;
|
||||
|
||||
_units = units;
|
||||
|
||||
_mapScale->setUnits(units);
|
||||
_mapScale->setUnits(_units);
|
||||
|
||||
for (int i = 0; i < _tracks.count(); i++)
|
||||
_tracks[i]->setUnits(units);
|
||||
_tracks[i]->setUnits(_units);
|
||||
for (int i = 0; i < _routes.count(); i++)
|
||||
_routes[i]->setUnits(units);
|
||||
_routes[i]->setUnits(_units);
|
||||
for (int i = 0; i < _waypoints.size(); i++)
|
||||
_waypoints.at(i)->setUnits(units);
|
||||
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
|
||||
|
||||
QHash<SearchPointer<Waypoint>, WaypointItem*>::const_iterator it;
|
||||
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
|
||||
it.value()->setUnits(units);
|
||||
it.value()->setToolTipFormat(_units, _coordinatesFormat);
|
||||
}
|
||||
|
||||
void MapView::setCoordinatesFormat(CoordinatesFormat format)
|
||||
{
|
||||
if (_coordinatesFormat == format)
|
||||
return;
|
||||
|
||||
_coordinatesFormat = format;
|
||||
|
||||
for (int i = 0; i < _waypoints.count(); i++)
|
||||
_waypoints.at(i)->setToolTipFormat(_units, _coordinatesFormat);
|
||||
for (int i = 0; i < _routes.count(); i++)
|
||||
_routes[i]->setCoordinatesFormat(_coordinatesFormat);
|
||||
|
||||
QHash<SearchPointer<Waypoint>, WaypointItem*>::const_iterator it;
|
||||
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
|
||||
it.value()->setToolTipFormat(_units, _coordinatesFormat);
|
||||
}
|
||||
|
||||
void MapView::clearMapCache()
|
||||
@ -476,9 +490,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
bool hires)
|
||||
{
|
||||
QRect orig, adj;
|
||||
qreal ratio, diff, origRes, q;
|
||||
qreal ratio, diff, q;
|
||||
QPointF origScene, origPos;
|
||||
Coordinates origLL;
|
||||
RectC origC;
|
||||
|
||||
|
||||
// Enter plot mode
|
||||
@ -503,9 +517,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
|
||||
// Adjust the view for printing
|
||||
if (hires) {
|
||||
origScene = mapToScene(orig.center());
|
||||
origLL = _map->xy2ll(origScene);
|
||||
origRes = _map->resolution(origScene);
|
||||
QRectF vr(mapToScene(orig).boundingRect());
|
||||
origC = RectC(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
||||
origScene = vr.center();
|
||||
|
||||
QPointF s(painter->device()->logicalDpiX()
|
||||
/ (qreal)metric(QPaintDevice::PdmDpiX),
|
||||
@ -535,7 +549,7 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
|
||||
// Revert view changes to display mode
|
||||
if (hires) {
|
||||
_map->zoomFit(origRes, origLL);
|
||||
_map->zoomFit(orig.size(), origC);
|
||||
rescale();
|
||||
centerOn(origScene);
|
||||
}
|
||||
@ -738,24 +752,21 @@ void MapView::setBackgroundColor(const QColor &color)
|
||||
|
||||
void MapView::drawBackground(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
painter->fillRect(rect, _backgroundColor);
|
||||
|
||||
if (_showMap) {
|
||||
QRectF ir = rect.intersected(_map->bounds());
|
||||
|
||||
if (_opacity < 1.0 || ir != rect)
|
||||
painter->fillRect(rect, _backgroundColor);
|
||||
if (_opacity < 1.0)
|
||||
painter->setOpacity(_opacity);
|
||||
|
||||
_map->draw(painter, ir);
|
||||
} else
|
||||
painter->fillRect(rect, _backgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
void MapView::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QGraphicsView::resizeEvent(event);
|
||||
|
||||
qreal zoom = _map->zoom();
|
||||
int zoom = _map->zoom();
|
||||
if (mapZoom() != zoom)
|
||||
rescale();
|
||||
|
||||
@ -777,8 +788,8 @@ void MapView::scrollContentsBy(int dx, int dy)
|
||||
{
|
||||
QGraphicsView::scrollContentsBy(dx, dy);
|
||||
|
||||
QPointF center = mapToScene(viewport()->rect().center());
|
||||
qreal res = _map->resolution(center);
|
||||
QRectF sr(mapToScene(viewport()->rect()).boundingRect());
|
||||
qreal res = _map->resolution(sr);
|
||||
|
||||
if (qMax(res, _res) / qMin(res, _res) > 1.1) {
|
||||
_mapScale->setResolution(res);
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "data/waypoint.h"
|
||||
#include "searchpointer.h"
|
||||
#include "units.h"
|
||||
#include "format.h"
|
||||
#include "palette.h"
|
||||
|
||||
class Data;
|
||||
@ -34,12 +35,13 @@ public:
|
||||
void setPalette(const Palette &palette);
|
||||
void setPOI(POI *poi);
|
||||
void setMap(Map *map);
|
||||
void setUnits(enum Units units);
|
||||
|
||||
void plot(QPainter *painter, const QRectF &target, qreal scale, bool hires);
|
||||
|
||||
void clear();
|
||||
|
||||
void setUnits(Units units);
|
||||
void setMarkerColor(const QColor &color);
|
||||
void setTrackWidth(int width);
|
||||
void setRouteWidth(int width);
|
||||
void setTrackStyle(Qt::PenStyle style);
|
||||
@ -52,7 +54,6 @@ public:
|
||||
void setBackgroundColor(const QColor &color);
|
||||
void useOpenGL(bool use);
|
||||
void useAntiAliasing(bool use);
|
||||
void setMarkerColor(const QColor &color);
|
||||
|
||||
public slots:
|
||||
void showMap(bool show);
|
||||
@ -65,6 +66,7 @@ public slots:
|
||||
void showWaypoints(bool show);
|
||||
void showRouteWaypoints(bool show);
|
||||
void clearMapCache();
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
|
||||
private slots:
|
||||
void updatePOI();
|
||||
@ -78,7 +80,7 @@ private:
|
||||
void loadPOI();
|
||||
void clearPOI();
|
||||
|
||||
qreal mapZoom() const;
|
||||
int mapZoom() const;
|
||||
QPointF contentCenter() const;
|
||||
void rescale();
|
||||
void centerOn(const QPointF &pos);
|
||||
@ -108,6 +110,7 @@ private:
|
||||
POI *_poi;
|
||||
Palette _palette;
|
||||
Units _units;
|
||||
CoordinatesFormat _coordinatesFormat;
|
||||
|
||||
qreal _opacity;
|
||||
QColor _backgroundColor;
|
||||
|
@ -25,11 +25,13 @@ private:
|
||||
qreal _left, _top, _right, _bottom;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const MarginsF &margins)
|
||||
{
|
||||
dbg.nospace() << "MarginsF(" << margins.left() << ", " << margins.top()
|
||||
<< ", " << margins.right() << margins.bottom() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // MARGINS_H
|
||||
|
@ -291,6 +291,9 @@ QWidget *OptionsDialog::createDataPage()
|
||||
if (_options->units == Imperial) {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2MIH);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("mi/h"));
|
||||
} else if (_options->units == Nautical) {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KN);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("kn"));
|
||||
} else {
|
||||
_pauseSpeed->setValue(_options->pauseSpeed * MS2KMH);
|
||||
_pauseSpeed->setSuffix(UNIT_SPACE + tr("km/h"));
|
||||
@ -323,6 +326,9 @@ QWidget *OptionsDialog::createPOIPage()
|
||||
if (_options->units == Imperial) {
|
||||
_poiRadius->setValue(_options->poiRadius / MIINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("mi"));
|
||||
} else if (_options->units == Nautical) {
|
||||
_poiRadius->setValue(_options->poiRadius / NMIINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("nmi"));
|
||||
} else {
|
||||
_poiRadius->setValue(_options->poiRadius / KMINM);
|
||||
_poiRadius->setSuffix(UNIT_SPACE + tr("km"));
|
||||
@ -525,13 +531,15 @@ void OptionsDialog::accept()
|
||||
_options->powerFilter = _powerFilter->value();
|
||||
_options->outlierEliminate = _outlierEliminate->isChecked();
|
||||
qreal pauseSpeed = (_options->units == Imperial)
|
||||
? _pauseSpeed->value() / MS2MIH : _pauseSpeed->value() / MS2KMH;
|
||||
? _pauseSpeed->value() / MS2MIH : (_options->units == Nautical)
|
||||
? _pauseSpeed->value() / MS2KN : _pauseSpeed->value() / MS2KMH;
|
||||
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
|
||||
_options->pauseSpeed = pauseSpeed;
|
||||
_options->pauseInterval = _pauseInterval->value();
|
||||
|
||||
qreal poiRadius = (_options->units == Imperial)
|
||||
? _poiRadius->value() * MIINM : _poiRadius->value() * KMINM;
|
||||
? _poiRadius->value() * MIINM : (_options->units == Nautical)
|
||||
? _poiRadius->value() * NMIINM : _poiRadius->value() * KMINM;
|
||||
if (qAbs(poiRadius - _options->poiRadius) > 0.01)
|
||||
_options->poiRadius = poiRadius;
|
||||
|
||||
|
@ -37,9 +37,11 @@ void Palette::reset()
|
||||
_state = _h;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Palette &palette)
|
||||
{
|
||||
dbg.nospace() << "Palette(" << palette.color() << ", " << palette.shift()
|
||||
<< ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -28,6 +28,8 @@ private:
|
||||
qreal _state;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Palette &palette);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // PALLETE_H
|
||||
|
@ -30,6 +30,8 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
|
||||
|
||||
_name = route.name();
|
||||
_desc = route.description();
|
||||
_units = Metric;
|
||||
_coordinatesFormat = DecimalDegrees;
|
||||
|
||||
setToolTip(toolTip(Metric));
|
||||
}
|
||||
@ -47,9 +49,38 @@ void RouteItem::setMap(Map *map)
|
||||
PathItem::setMap(map);
|
||||
}
|
||||
|
||||
void RouteItem::setUnits(enum Units units)
|
||||
void RouteItem::setUnits(Units units)
|
||||
{
|
||||
setToolTip(toolTip(units));
|
||||
if (_units == units)
|
||||
return;
|
||||
|
||||
_units = units;
|
||||
|
||||
setToolTip(toolTip(_units));
|
||||
|
||||
QList<QGraphicsItem *> childs = childItems();
|
||||
for (int i = 0; i < childs.count(); i++) {
|
||||
if (childs.at(i) != _marker) {
|
||||
WaypointItem *wi = static_cast<WaypointItem*>(childs.at(i));
|
||||
wi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
|
||||
{
|
||||
if (_coordinatesFormat == format)
|
||||
return;
|
||||
|
||||
_coordinatesFormat = format;
|
||||
|
||||
QList<QGraphicsItem *> childs = childItems();
|
||||
for (int i = 0; i < childs.count(); i++) {
|
||||
if (childs.at(i) != _marker) {
|
||||
WaypointItem *wi = static_cast<WaypointItem*>(childs.at(i));
|
||||
wi->setToolTipFormat(_units, _coordinatesFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RouteItem::showWaypoints(bool show)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "data/route.h"
|
||||
#include "pathitem.h"
|
||||
#include "units.h"
|
||||
#include "format.h"
|
||||
|
||||
class Map;
|
||||
|
||||
@ -17,6 +18,7 @@ public:
|
||||
void setMap(Map *map);
|
||||
|
||||
void setUnits(Units units);
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void showWaypoints(bool show);
|
||||
void showWaypointLabels(bool show);
|
||||
|
||||
@ -25,6 +27,8 @@ private:
|
||||
|
||||
QString _name;
|
||||
QString _desc;
|
||||
Units _units;
|
||||
CoordinatesFormat _coordinatesFormat;
|
||||
};
|
||||
|
||||
#endif // ROUTEITEM_H
|
||||
|
@ -82,6 +82,9 @@ QString ScaleItem::units() const
|
||||
if (_units == Imperial)
|
||||
return _scale ? qApp->translate("ScaleItem", "mi")
|
||||
: qApp->translate("ScaleItem", "ft");
|
||||
else if (_units == Nautical)
|
||||
return _scale ? qApp->translate("ScaleItem", "nmi")
|
||||
: qApp->translate("ScaleItem", "ft");
|
||||
else
|
||||
return _scale ? qApp->translate("ScaleItem", "km")
|
||||
: qApp->translate("ScaleItem", "m");
|
||||
@ -94,8 +97,18 @@ void ScaleItem::computeScale()
|
||||
if (_units == Imperial) {
|
||||
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1);
|
||||
if (_length >= MIINFT) {
|
||||
_length = niceNum((res * M2FT * FT2MI * SCALE_WIDTH) / SEGMENTS, 1);
|
||||
_width = (_length / (res * M2FT * FT2MI));
|
||||
_length = niceNum((res * M2MI * SCALE_WIDTH) / SEGMENTS, 1);
|
||||
_width = (_length / (res * M2MI));
|
||||
_scale = true;
|
||||
} else {
|
||||
_width = (_length / (res * M2FT));
|
||||
_scale = false;
|
||||
}
|
||||
} else if (_units == Nautical) {
|
||||
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1);
|
||||
if (_length >= NMIINFT) {
|
||||
_length = niceNum((res * M2NMI * SCALE_WIDTH) / SEGMENTS, 1);
|
||||
_width = (_length / (res * M2NMI));
|
||||
_scale = true;
|
||||
} else {
|
||||
_width = (_length / (res * M2FT));
|
||||
|
@ -15,6 +15,8 @@
|
||||
#define TIME_TYPE_DEFAULT Total
|
||||
#define UNITS_SETTING "units"
|
||||
#define UNITS_DEFAULT (IMPERIAL_UNITS() ? Imperial : Metric)
|
||||
#define COORDINATES_SETTING "coordinates"
|
||||
#define COORDINATES_DEFAULT DecimalDegrees
|
||||
#define SHOW_TOOLBARS_SETTING "toolbar"
|
||||
#define SHOW_TOOLBARS_DEFAULT true
|
||||
|
||||
|
@ -1,16 +1,18 @@
|
||||
#include "data/data.h"
|
||||
#include "config.h"
|
||||
#include "tooltip.h"
|
||||
#include "format.h"
|
||||
#include "speedgraphitem.h"
|
||||
#include "speedgraph.h"
|
||||
|
||||
|
||||
SpeedGraph::SpeedGraph(QWidget *parent) : GraphTab(parent)
|
||||
{
|
||||
_units = Metric;
|
||||
_timeType = Total;
|
||||
_showTracks = true;
|
||||
|
||||
setYUnits(Metric);
|
||||
setYUnits();
|
||||
setYLabel(tr("Speed"));
|
||||
|
||||
setSliderPrecision(1);
|
||||
@ -19,10 +21,15 @@ SpeedGraph::SpeedGraph(QWidget *parent) : GraphTab(parent)
|
||||
void SpeedGraph::setInfo()
|
||||
{
|
||||
if (_showTracks) {
|
||||
QString pace = Format::timeSpan((3600.0 / (avg() * yScale())), false);
|
||||
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
|
||||
tr("min/mi") : tr("min/nmi");
|
||||
|
||||
GraphView::addInfo(tr("Average"), QString::number(avg() * yScale(), 'f',
|
||||
1) + UNIT_SPACE + yUnits());
|
||||
GraphView::addInfo(tr("Maximum"), QString::number(max() * yScale(), 'f',
|
||||
1) + UNIT_SPACE + yUnits());
|
||||
GraphView::addInfo(tr("Pace"), pace + UNIT_SPACE + pu);
|
||||
} else
|
||||
clearInfo();
|
||||
}
|
||||
@ -77,20 +84,25 @@ void SpeedGraph::clear()
|
||||
GraphView::clear();
|
||||
}
|
||||
|
||||
void SpeedGraph::setYUnits(Units units)
|
||||
void SpeedGraph::setYUnits()
|
||||
{
|
||||
if (units == Metric) {
|
||||
GraphView::setYUnits(tr("km/h"));
|
||||
setYScale(MS2KMH);
|
||||
} else {
|
||||
if (_units == Nautical) {
|
||||
GraphView::setYUnits(tr("kn"));
|
||||
setYScale(MS2KN);
|
||||
} else if (_units == Imperial) {
|
||||
GraphView::setYUnits(tr("mi/h"));
|
||||
setYScale(MS2MIH);
|
||||
} else {
|
||||
GraphView::setYUnits(tr("km/h"));
|
||||
setYScale(MS2KMH);
|
||||
}
|
||||
}
|
||||
|
||||
void SpeedGraph::setUnits(Units units)
|
||||
{
|
||||
setYUnits(units);
|
||||
_units = units;
|
||||
|
||||
setYUnits();
|
||||
setInfo();
|
||||
|
||||
GraphView::setUnits(units);
|
||||
|
@ -21,13 +21,14 @@ public:
|
||||
private:
|
||||
qreal avg() const;
|
||||
qreal max() const {return bounds().bottom();}
|
||||
void setYUnits(Units units);
|
||||
void setYUnits();
|
||||
void setInfo();
|
||||
|
||||
QList<QPointF> _avg;
|
||||
QList<QPointF> _mavg;
|
||||
|
||||
enum TimeType _timeType;
|
||||
Units _units;
|
||||
TimeType _timeType;
|
||||
bool _showTracks;
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "tooltip.h"
|
||||
#include "format.h"
|
||||
#include "speedgraphitem.h"
|
||||
|
||||
SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type,
|
||||
@ -16,13 +17,20 @@ SpeedGraphItem::SpeedGraphItem(const Graph &graph, GraphType type,
|
||||
QString SpeedGraphItem::toolTip() const
|
||||
{
|
||||
ToolTip tt;
|
||||
qreal scale = (_units == Metric) ? MS2KMH : MS2MIH;
|
||||
QString su = (_units == Metric) ? tr("km/h") : tr("mi/h");
|
||||
qreal scale = (_units == Imperial) ? MS2MIH : (_units == Nautical)
|
||||
? MS2KN : MS2KMH;
|
||||
QString su = (_units == Imperial) ? tr("mi/h") : (_units == Nautical)
|
||||
? tr("kn") : tr("km/h");
|
||||
QString pace = Format::timeSpan((3600.0 / ((_timeType == Total)
|
||||
? avg() * scale : mavg() * scale)), false);
|
||||
QString pu = (_units == Metric) ? tr("min/km") : (_units == Imperial) ?
|
||||
tr("min/mi") : tr("min/nmi");
|
||||
|
||||
tt.insert(tr("Maximum"), QString::number(max() * scale, 'f', 1)
|
||||
+ UNIT_SPACE + su);
|
||||
tt.insert(tr("Average"), QString::number((_timeType == Total)
|
||||
? avg() * scale : mavg() * scale, 'f', 1) + UNIT_SPACE + su);
|
||||
tt.insert(tr("Pace"), pace + UNIT_SPACE + pu);
|
||||
|
||||
return tt.toString();
|
||||
}
|
||||
|
@ -3,24 +3,29 @@
|
||||
|
||||
enum Units {
|
||||
Metric,
|
||||
Imperial
|
||||
Imperial,
|
||||
Nautical
|
||||
};
|
||||
|
||||
#define M2KM 0.001000000000 // m -> km
|
||||
#define M2MI 0.000621371192 // m -> mi
|
||||
#define M2NMI 0.000539956803 // m -> nmi
|
||||
#define M2FT 3.280839900000 // m -> ft
|
||||
#define MS2KMH 3.600000000000 // m/s -> km/h
|
||||
#define MS2MIH 2.236936290000 // m/s -> mi/h
|
||||
#define MS2KN 1.943844490000 // m/s -> kn
|
||||
#define FT2MI 0.000189393939 // ft -> mi
|
||||
#define MM2IN 0.039370100000 // mm -> in
|
||||
#define H2S 0.000277777778 // h -> s
|
||||
#define MIN2S 0.016666666667 // min -> s
|
||||
|
||||
#define KMINM 1000.0 // 1 km in m
|
||||
#define MIINFT 5280.0 // 1 mi in ft
|
||||
#define MIINM 1609.344 // 1 mi in m
|
||||
#define MININS 60.0 // 1 min in s
|
||||
#define HINS 3600.0 // 1 hins
|
||||
#define KMINM 1000.0 // 1 km in m
|
||||
#define MIINFT 5280.0 // 1 mi in ft
|
||||
#define NMIINFT 6076.11549 // 1 nm in ft
|
||||
#define MIINM 1609.344 // 1 mi in m
|
||||
#define NMIINM 1852.0 // 1 nmi in m
|
||||
#define MININS 60.0 // 1 min in s
|
||||
#define HINS 3600.0 // 1 hins
|
||||
|
||||
#define C2FS 1.8 // Celsius to Farenheit - scale
|
||||
#define C2FO 32.0 // Celsius to Farenheit - offset
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include "config.h"
|
||||
#include "format.h"
|
||||
#include "tooltip.h"
|
||||
#include "waypointitem.h"
|
||||
|
||||
@ -11,14 +10,14 @@
|
||||
#define FS(size) \
|
||||
((int)((qreal)size * 1.41))
|
||||
|
||||
QString WaypointItem::toolTip(Units units)
|
||||
QString WaypointItem::toolTip(Units units, CoordinatesFormat format)
|
||||
{
|
||||
ToolTip tt;
|
||||
|
||||
if (!_waypoint.name().isEmpty())
|
||||
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
|
||||
tt.insert(qApp->translate("WaypointItem", "Coordinates"),
|
||||
Format::coordinates(_waypoint.coordinates()));
|
||||
Format::coordinates(_waypoint.coordinates(), format));
|
||||
if (!std::isnan(_waypoint.elevation()))
|
||||
tt.insert(qApp->translate("WaypointItem", "Elevation"),
|
||||
Format::elevation(_waypoint.elevation(), units));
|
||||
@ -44,7 +43,7 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
||||
updateShape();
|
||||
|
||||
setPos(map->ll2xy(waypoint.coordinates()));
|
||||
setToolTip(toolTip(Metric));
|
||||
setToolTip(toolTip(Metric, DecimalDegrees));
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
@ -108,6 +107,9 @@ void WaypointItem::paint(QPainter *painter,
|
||||
|
||||
void WaypointItem::setSize(int size)
|
||||
{
|
||||
if (_size == size)
|
||||
return;
|
||||
|
||||
prepareGeometryChange();
|
||||
_size = size;
|
||||
updateShape();
|
||||
@ -115,17 +117,23 @@ void WaypointItem::setSize(int size)
|
||||
|
||||
void WaypointItem::setColor(const QColor &color)
|
||||
{
|
||||
if (_color == color)
|
||||
return;
|
||||
|
||||
_color = color;
|
||||
update();
|
||||
}
|
||||
|
||||
void WaypointItem::setUnits(enum Units units)
|
||||
void WaypointItem::setToolTipFormat(Units units, CoordinatesFormat format)
|
||||
{
|
||||
setToolTip(toolTip(units));
|
||||
setToolTip(toolTip(units, format));
|
||||
}
|
||||
|
||||
void WaypointItem::showLabel(bool show)
|
||||
{
|
||||
if (_showLabel == show)
|
||||
return;
|
||||
|
||||
prepareGeometryChange();
|
||||
_showLabel = show;
|
||||
updateShape();
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "data/waypoint.h"
|
||||
#include "map/map.h"
|
||||
#include "units.h"
|
||||
#include "format.h"
|
||||
|
||||
class WaypointItem : public QGraphicsItem
|
||||
{
|
||||
@ -15,7 +16,7 @@ public:
|
||||
const Waypoint &waypoint() const {return _waypoint;}
|
||||
|
||||
void setMap(Map *map) {setPos(map->ll2xy(_waypoint.coordinates()));}
|
||||
void setUnits(Units units);
|
||||
void setToolTipFormat(Units units, CoordinatesFormat format);
|
||||
void setSize(int size);
|
||||
void setColor(const QColor &color);
|
||||
void showLabel(bool show);
|
||||
@ -31,7 +32,7 @@ private:
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
|
||||
void updateShape();
|
||||
QString toolTip(Units units);
|
||||
QString toolTip(Units units, CoordinatesFormat format);
|
||||
|
||||
QPainterPath _shape;
|
||||
Waypoint _waypoint;
|
||||
|
@ -16,12 +16,6 @@ qreal Coordinates::distanceTo(const Coordinates &c) const
|
||||
return (WGS84_RADIUS * (2.0 * atan2(sqrt(a), sqrt(1.0 - a))));
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c)
|
||||
{
|
||||
dbg.nospace() << "Coordinates(" << c.lon() << ", " << c.lat() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
|
||||
QPair<Coordinates, Coordinates> Coordinates::boundingRect(qreal distance) const
|
||||
{
|
||||
qreal radDist = distance / WGS84_RADIUS;
|
||||
@ -50,3 +44,11 @@ QPair<Coordinates, Coordinates> Coordinates::boundingRect(qreal distance) const
|
||||
maxLon)), rad2deg(qMin(minLat, maxLat))), Coordinates(rad2deg(qMax(minLon,
|
||||
maxLon)), rad2deg(qMax(minLat, maxLat))));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c)
|
||||
{
|
||||
dbg.nospace() << "Coordinates(" << c.lon() << ", " << c.lat() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -43,6 +43,8 @@ inline bool operator==(const Coordinates &c1, const Coordinates &c2)
|
||||
inline bool operator!=(const Coordinates &c1, const Coordinates &c2)
|
||||
{return !(c1 == c2);}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // COORDINATES_H
|
||||
|
@ -8,6 +8,7 @@ void RangeF::resize(qreal size)
|
||||
_max += adj;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Range &range)
|
||||
{
|
||||
dbg.nospace() << "Range(" << range.min() << ", " << range.max() << ")";
|
||||
@ -19,3 +20,4 @@ QDebug operator<<(QDebug dbg, const RangeF &range)
|
||||
dbg.nospace() << "RangeF(" << range.min() << ", " << range.max() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -14,6 +14,8 @@ public:
|
||||
int max() const {return _max;}
|
||||
int size() const {return (_max - _min);}
|
||||
|
||||
bool isValid() const {return size() >= 0;}
|
||||
|
||||
private:
|
||||
int _min, _max;
|
||||
};
|
||||
@ -28,13 +30,17 @@ public:
|
||||
qreal max() const {return _max;}
|
||||
qreal size() const {return (_max - _min);}
|
||||
|
||||
bool isValid() const {return size() >= 0;}
|
||||
|
||||
void resize(qreal size);
|
||||
|
||||
private:
|
||||
qreal _min, _max;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Range &range);
|
||||
QDebug operator<<(QDebug dbg, const RangeF &range);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // RANGE_H
|
||||
|
@ -61,8 +61,10 @@ void RectC::unite(const Coordinates &c)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RectC &rect)
|
||||
{
|
||||
dbg.nospace() << "RectC(" << rect.topLeft() << ", " << rect.size() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -37,6 +37,8 @@ private:
|
||||
Coordinates _tl, _br;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RectC &rect);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // RECTC_H
|
||||
|
@ -23,13 +23,13 @@ static QHash<QString, Parser*> parsers()
|
||||
{
|
||||
QHash<QString, Parser*> hash;
|
||||
|
||||
hash.insert("gpx", &gpx);
|
||||
hash.insert("tcx", &tcx);
|
||||
hash.insert("kml", &kml);
|
||||
hash.insert("fit", &fit);
|
||||
hash.insert("csv", &csv);
|
||||
hash.insert("igc", &igc);
|
||||
hash.insert("nmea", &nmea);
|
||||
hash.insert("gpx", &gpx);
|
||||
hash.insert("tcx", &tcx);
|
||||
hash.insert("kml", &kml);
|
||||
hash.insert("fit", &fit);
|
||||
hash.insert("csv", &csv);
|
||||
hash.insert("igc", &igc);
|
||||
hash.insert("nmea", &nmea);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
@ -30,12 +30,14 @@ private:
|
||||
|
||||
Q_DECLARE_TYPEINFO(GraphPoint, Q_PRIMITIVE_TYPE);
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const GraphPoint &point)
|
||||
{
|
||||
dbg.nospace() << "GraphPoint(" << point.s() << ", " << point.t() << ", "
|
||||
<< point.y() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
typedef QVector<GraphPoint> Graph;
|
||||
|
||||
|
@ -13,9 +13,11 @@ RectC Path::boundingRect() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PathPoint &point)
|
||||
{
|
||||
dbg.nospace() << "PathPoint(" << point.distance() << ", "
|
||||
<< point.coordinates() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -23,7 +23,9 @@ private:
|
||||
};
|
||||
|
||||
Q_DECLARE_TYPEINFO(PathPoint, Q_PRIMITIVE_TYPE);
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PathPoint &point);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
|
||||
class Path : public QVector<PathPoint>
|
||||
|
@ -49,9 +49,7 @@ static QSet<int> eliminate(const QVector<qreal> &v, int window)
|
||||
|
||||
static Graph filter(const Graph &g, int window)
|
||||
{
|
||||
if (g.size() < window)
|
||||
return Graph();
|
||||
if (window < 2)
|
||||
if (g.size() < window || window < 2)
|
||||
return Graph(g);
|
||||
|
||||
qreal acc = 0;
|
||||
@ -77,27 +75,32 @@ static Graph filter(const Graph &g, int window)
|
||||
Track::Track(const TrackData &data) : _data(data)
|
||||
{
|
||||
qreal dt, ds, total;
|
||||
int last;
|
||||
|
||||
|
||||
_time.append(0);
|
||||
_distance.append(0);
|
||||
_speed.append(0);
|
||||
|
||||
for (int i = 1; i < data.count(); i++) {
|
||||
ds = data.at(i).coordinates().distanceTo(data.at(i-1).coordinates());
|
||||
last = 0;
|
||||
|
||||
for (int i = 1; i < _data.count(); i++) {
|
||||
ds = _data.at(i).coordinates().distanceTo(_data.at(i-1).coordinates());
|
||||
_distance.append(ds);
|
||||
|
||||
if (data.first().hasTimestamp() && data.at(i).hasTimestamp())
|
||||
if (_data.first().hasTimestamp() && _data.at(i).hasTimestamp()
|
||||
&& _data.at(i).timestamp() > _data.at(last).timestamp()) {
|
||||
_time.append(_data.first().timestamp().msecsTo(
|
||||
_data.at(i).timestamp()) / 1000.0);
|
||||
else
|
||||
last = i;
|
||||
} else
|
||||
_time.append(NAN);
|
||||
|
||||
if (std::isnan(_time.at(i)) || std::isnan(_time.at(i-1)))
|
||||
_speed.append(NAN);
|
||||
else {
|
||||
dt = _time.at(i) - _time.at(i-1);
|
||||
if (!dt) {
|
||||
if (dt < 1e-3) {
|
||||
_speed.append(_speed.at(i-1));
|
||||
continue;
|
||||
}
|
||||
@ -106,7 +109,7 @@ Track::Track(const TrackData &data) : _data(data)
|
||||
}
|
||||
|
||||
_pause = 0;
|
||||
for (int i = 1; i < data.count(); i++) {
|
||||
for (int i = 1; i < _data.count(); i++) {
|
||||
if (_time.at(i) > _time.at(i-1) + _pauseInterval
|
||||
&& _speed.at(i) < _pauseSpeed) {
|
||||
_pause += _time.at(i) - _time.at(i-1);
|
||||
|
@ -57,6 +57,7 @@ private:
|
||||
|
||||
Q_DECLARE_TYPEINFO(Trackpoint, Q_MOVABLE_TYPE);
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const Trackpoint &trackpoint)
|
||||
{
|
||||
dbg.nospace() << "Trackpoint(" << trackpoint.coordinates() << ", "
|
||||
@ -65,5 +66,6 @@ inline QDebug operator<<(QDebug dbg, const Trackpoint &trackpoint)
|
||||
<< trackpoint.temperature() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // TRACKPOINT_H
|
||||
|
@ -48,12 +48,14 @@ inline uint qHash(const Waypoint &key)
|
||||
return ::qHash(key.name());
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const Waypoint &waypoint)
|
||||
{
|
||||
dbg.nospace() << "Waypoint(" << waypoint.coordinates() << ", "
|
||||
<< waypoint.name() << ", " << waypoint.description() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
Q_DECLARE_TYPEINFO(Waypoint, Q_MOVABLE_TYPE);
|
||||
|
||||
|
@ -41,6 +41,7 @@ Defense.
|
||||
|
||||
*/
|
||||
|
||||
#include "ellipsoid.h"
|
||||
#include "albersequal.h"
|
||||
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef ALBERSEQUAL_H
|
||||
#define ALBERSEQUAL_H
|
||||
|
||||
#include "ellipsoid.h"
|
||||
#include "ct.h"
|
||||
|
||||
class Ellipsoid;
|
||||
|
||||
class AlbersEqual : public CT
|
||||
{
|
||||
public:
|
||||
|
@ -8,7 +8,8 @@ static double sDMS2deg(double val)
|
||||
const char *decimal;
|
||||
|
||||
QString qstr(QString::number(qAbs(val), 'f', 7));
|
||||
const char *str = qstr.toLatin1().constData();
|
||||
QByteArray ba = qstr.toLatin1();
|
||||
const char *str = ba.constData();
|
||||
decimal = strrchr(str, '.');
|
||||
int deg = str2int(str, decimal - str);
|
||||
int min = str2int(decimal + 1, 2);
|
||||
@ -83,8 +84,10 @@ double AngularUnits::fromDegrees(double val) const
|
||||
return (_code == 9110) ? deg2sDMS(val) : val / _f;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const AngularUnits &au)
|
||||
{
|
||||
dbg.nospace() << "AngularUnits(" << deg2rad(au._f) << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -17,8 +17,9 @@ public:
|
||||
double fromDegrees(double val) const;
|
||||
|
||||
friend bool operator==(const AngularUnits &au1, const AngularUnits &au2);
|
||||
#ifndef QT_NO_DEBUG
|
||||
friend QDebug operator<<(QDebug dbg, const AngularUnits &au);
|
||||
|
||||
#endif // QT_NO_DEBUG
|
||||
private:
|
||||
int _code;
|
||||
double _f;
|
||||
@ -27,6 +28,8 @@ private:
|
||||
inline bool operator==(const AngularUnits &au1, const AngularUnits &au2)
|
||||
{return (au1._f == au2._f);}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const AngularUnits &au);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // ANGULARUNITS_H
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <QtAlgorithms>
|
||||
#include <QPainter>
|
||||
#include "common/rectc.h"
|
||||
#include "offlinemap.h"
|
||||
#include "tar.h"
|
||||
#include "atlas.h"
|
||||
|
||||
@ -15,8 +16,8 @@ static bool resCmp(const OfflineMap *m1, const OfflineMap *m2)
|
||||
{
|
||||
qreal r1, r2;
|
||||
|
||||
r1 = m1->resolution(m1->bounds().center());
|
||||
r2 = m2->resolution(m2->bounds().center());
|
||||
r1 = m1->resolution(m1->bounds());
|
||||
r2 = m2->resolution(m2->bounds());
|
||||
|
||||
return r1 > r2;
|
||||
}
|
||||
@ -37,8 +38,8 @@ void Atlas::computeZooms()
|
||||
|
||||
_zooms.append(QPair<int, int>(0, _maps.count() - 1));
|
||||
for (int i = 1; i < _maps.count(); i++) {
|
||||
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds().center());
|
||||
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds().center());
|
||||
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds());
|
||||
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
|
||||
if (cur < last * ZOOM_THRESHOLD) {
|
||||
_zooms.last().second = i-1;
|
||||
_zooms.append(QPair<int, int>(i, _maps.count() - 1));
|
||||
@ -78,21 +79,19 @@ void Atlas::computeBounds()
|
||||
BR(_maps.at(i))), QRectF(offsets.at(i), _maps.at(i)->bounds().size())));
|
||||
}
|
||||
|
||||
Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
|
||||
Atlas::Atlas(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _zoom(0), _mapIndex(-1), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QByteArray ba;
|
||||
QString suffix = fi.suffix().toLower();
|
||||
Tar tar;
|
||||
Tar tar(fileName);
|
||||
|
||||
|
||||
_valid = false;
|
||||
_zoom = 0;
|
||||
_name = fi.dir().dirName();
|
||||
_ci = -1; _cz = -1;
|
||||
|
||||
|
||||
if (suffix == "tar") {
|
||||
if (!tar.load(fileName)) {
|
||||
if (!tar.open()) {
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
@ -112,7 +111,6 @@ Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QDir dir(fi.absolutePath());
|
||||
QFileInfoList layers = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
for (int n = 0; n < layers.count(); n++) {
|
||||
@ -149,12 +147,6 @@ Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
Atlas::~Atlas()
|
||||
{
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
delete _maps.at(i);
|
||||
}
|
||||
|
||||
QRectF Atlas::bounds() const
|
||||
{
|
||||
QSizeF s(0, 0);
|
||||
@ -169,28 +161,24 @@ QRectF Atlas::bounds() const
|
||||
return QRectF(QPointF(0, 0), s);
|
||||
}
|
||||
|
||||
qreal Atlas::resolution(const QPointF &p) const
|
||||
qreal Atlas::resolution(const QRectF &rect) const
|
||||
{
|
||||
int idx = _zooms.at(_zoom).first;
|
||||
|
||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
||||
if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(p))) {
|
||||
if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(rect.center()))) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _maps.at(idx)->resolution(p);
|
||||
return _maps.at(idx)->resolution(rect);
|
||||
}
|
||||
|
||||
qreal Atlas::zoom() const
|
||||
{
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal Atlas::zoomFit(const QSize &size, const RectC &br)
|
||||
int Atlas::zoomFit(const QSize &size, const RectC &br)
|
||||
{
|
||||
_zoom = 0;
|
||||
_mapIndex = -1;
|
||||
|
||||
if (!br.isValid()) {
|
||||
_zoom = _zooms.size() - 1;
|
||||
@ -217,35 +205,19 @@ qreal Atlas::zoomFit(const QSize &size, const RectC &br)
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal Atlas::zoomFit(qreal resolution, const Coordinates &c)
|
||||
{
|
||||
_zoom = 0;
|
||||
|
||||
for (int z = 0; z < _zooms.count(); z++) {
|
||||
for (int i = _zooms.at(z).first; i <= _zooms.at(z).second; i++) {
|
||||
if (!_bounds.at(i).first.contains(_maps.at(i)->ll2pp(c)))
|
||||
continue;
|
||||
|
||||
if (_maps.at(i)->resolution(_maps.at(i)->ll2xy(c)) < resolution)
|
||||
return _zoom;
|
||||
|
||||
_zoom = z;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal Atlas::zoomIn()
|
||||
int Atlas::zoomIn()
|
||||
{
|
||||
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
|
||||
_mapIndex = -1;
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal Atlas::zoomOut()
|
||||
int Atlas::zoomOut()
|
||||
{
|
||||
_zoom = qMax(_zoom - 1, 0);
|
||||
_mapIndex = -1;
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
@ -253,26 +225,21 @@ QPointF Atlas::ll2xy(const Coordinates &c)
|
||||
{
|
||||
QPointF pp;
|
||||
|
||||
if (_cz != _zoom) {
|
||||
_ci = -1;
|
||||
_cz = _zoom;
|
||||
}
|
||||
|
||||
if (_ci >= 0)
|
||||
pp = _maps.at(_ci)->ll2pp(c);
|
||||
if (_ci < 0 || !_bounds.at(_ci).first.contains(pp)) {
|
||||
_ci = _zooms.at(_zoom).first;
|
||||
if (_mapIndex >= 0)
|
||||
pp = _maps.at(_mapIndex)->ll2pp(c);
|
||||
if (_mapIndex < 0 || !_bounds.at(_mapIndex).first.contains(pp)) {
|
||||
_mapIndex = _zooms.at(_zoom).first;
|
||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
||||
pp = _maps.at(i)->ll2pp(c);
|
||||
if (_bounds.at(i).first.contains(pp)) {
|
||||
_ci = i;
|
||||
_mapIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPointF p = _maps.at(_ci)->pp2xy(pp);
|
||||
return p + _bounds.at(_ci).second.topLeft();
|
||||
QPointF p = _maps.at(_mapIndex)->pp2xy(pp);
|
||||
return p + _bounds.at(_mapIndex).second.topLeft();
|
||||
}
|
||||
|
||||
Coordinates Atlas::xy2ll(const QPointF &p)
|
||||
@ -332,10 +299,10 @@ bool Atlas::isAtlas(const QString &path)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
Tar tar;
|
||||
Tar tar(path);
|
||||
|
||||
if (suffix == "tar") {
|
||||
if (!tar.load(path))
|
||||
if (!tar.open())
|
||||
return false;
|
||||
QString tbaFileName = fi.completeBaseName() + ".tba";
|
||||
return tar.contains(tbaFileName);
|
||||
|
@ -1,10 +1,9 @@
|
||||
#ifndef ATLAS_H
|
||||
#define ATLAS_H
|
||||
|
||||
#include <QFileInfoList>
|
||||
#include "map.h"
|
||||
#include "offlinemap.h"
|
||||
|
||||
class OfflineMap;
|
||||
|
||||
class Atlas : public Map
|
||||
{
|
||||
@ -12,18 +11,16 @@ class Atlas : public Map
|
||||
|
||||
public:
|
||||
Atlas(const QString &fileName, QObject *parent = 0);
|
||||
~Atlas();
|
||||
|
||||
const QString &name() const {return _name;}
|
||||
|
||||
QRectF bounds() const;
|
||||
qreal resolution(const QPointF &p) const;
|
||||
qreal resolution(const QRectF &rect) const;
|
||||
|
||||
qreal zoom() const;
|
||||
qreal zoomFit(const QSize &size, const RectC &br);
|
||||
qreal zoomFit(qreal resolution, const Coordinates &c);
|
||||
qreal zoomIn();
|
||||
qreal zoomOut();
|
||||
int zoom() const {return _zoom;}
|
||||
int zoomFit(const QSize &size, const RectC &br);
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
@ -33,7 +30,7 @@ public:
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static bool isAtlas(const QString &path);
|
||||
|
||||
@ -43,15 +40,15 @@ private:
|
||||
void computeBounds();
|
||||
|
||||
QString _name;
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
||||
QList<OfflineMap*> _maps;
|
||||
QVector<QPair<int, int> > _zooms;
|
||||
QVector<QPair<QRectF, QRectF> > _bounds;
|
||||
int _zoom;
|
||||
int _mapIndex;
|
||||
|
||||
int _ci, _cz;
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // ATLAS_H
|
||||
|
@ -43,11 +43,12 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
||||
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
|
||||
}
|
||||
|
||||
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy,
|
||||
double dz) : _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz)
|
||||
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
|
||||
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz)
|
||||
{
|
||||
_WGS84 = (*_ellipsoid == *WGS84.ellipsoid() && _dx == WGS84.dx()
|
||||
&& _dy == WGS84.dy() && _dz == WGS84.dz()) ? true : false;
|
||||
_WGS84 = (_ellipsoid->radius() == WGS84_RADIUS
|
||||
&& _ellipsoid->flattening() == WGS84_FLATTENING && _dx == 0.0
|
||||
&& _dy == 0.0 && _dz == 0.0) ? true : false;
|
||||
}
|
||||
|
||||
Coordinates Datum::toWGS84(const Coordinates &c) const
|
||||
@ -60,9 +61,11 @@ Coordinates Datum::fromWGS84(const Coordinates &c) const
|
||||
return _WGS84 ? c : molodensky(c, WGS84, *this);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Datum &datum)
|
||||
{
|
||||
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
|
||||
<< ", " << datum.dy() << ", " << datum.dz() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -39,6 +39,8 @@ inline bool operator==(const Datum &d1, const Datum &d2)
|
||||
{return (d1.ellipsoid() == d2.ellipsoid() && d1.dx() == d2.dx()
|
||||
&& d1.dy() == d2.dy() && d1.dz() == d2.dz());}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Datum &datum);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // DATUM_H
|
||||
|
@ -61,7 +61,7 @@ bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
|
||||
QFile file(filename);
|
||||
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qWarning("Error writing map tile: %s: %s\n",
|
||||
qWarning("Error writing file: %s: %s\n",
|
||||
qPrintable(filename), qPrintable(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
@ -80,11 +80,11 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
||||
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
|
||||
if (origin.isEmpty()) {
|
||||
_errorDownloads.insert(url);
|
||||
qWarning("Error downloading map tile: %s: %s\n",
|
||||
qWarning("Error downloading file: %s: %s\n",
|
||||
url.toEncoded().constData(), qPrintable(reply->errorString()));
|
||||
} else {
|
||||
_errorDownloads.insert(origin);
|
||||
qWarning("Error downloading map tile: %s -> %s: %s\n",
|
||||
qWarning("Error downloading file: %s -> %s: %s\n",
|
||||
origin.toEncoded().constData(), url.toEncoded().constData(),
|
||||
qPrintable(reply->errorString()));
|
||||
}
|
||||
@ -99,11 +99,11 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
||||
|
||||
if (location == url) {
|
||||
_errorDownloads.insert(url);
|
||||
qWarning("Error downloading map tile: %s: "
|
||||
qWarning("Error downloading file: %s: "
|
||||
"redirect loop\n", url.toEncoded().constData());
|
||||
} else if (level >= MAX_REDIRECT_LEVEL) {
|
||||
_errorDownloads.insert(origin);
|
||||
qWarning("Error downloading map tile: %s: "
|
||||
qWarning("Error downloading file: %s: "
|
||||
"redirect level limit reached\n",
|
||||
origin.toEncoded().constData());
|
||||
} else {
|
||||
|
@ -66,9 +66,11 @@ void Ellipsoid::loadList(const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid)
|
||||
{
|
||||
dbg.nospace() << "Ellipsoid(" << ellipsoid.radius() << ", "
|
||||
<< 1.0 / ellipsoid.flattening() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -35,6 +35,8 @@ private:
|
||||
inline bool operator==(const Ellipsoid &e1, const Ellipsoid &e2)
|
||||
{return (e1.radius() == e2.radius() && e1.flattening() == e2.flattening());}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // ELLIPSOID_H
|
||||
|
@ -3,16 +3,47 @@
|
||||
#include "common/coordinates.h"
|
||||
#include "common/rectc.h"
|
||||
#include "common/wgs84.h"
|
||||
#include "mercator.h"
|
||||
#include "emptymap.h"
|
||||
|
||||
|
||||
#define SCALE_MIN 0.5
|
||||
#define SCALE_MAX 1.0E-6
|
||||
#define ZOOM_MIN 0
|
||||
#define ZOOM_MAX 19
|
||||
#define TILE_SIZE 256
|
||||
|
||||
static QPointF ll2m(const Coordinates &c)
|
||||
{
|
||||
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
|
||||
}
|
||||
|
||||
static Coordinates m2ll(const QPointF &p)
|
||||
{
|
||||
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
|
||||
}
|
||||
|
||||
static qreal zoom2scale(int zoom)
|
||||
{
|
||||
return (360.0/(qreal)((1<<zoom) * TILE_SIZE));
|
||||
}
|
||||
|
||||
static int scale2zoom(qreal scale)
|
||||
{
|
||||
return (int)log2(360.0/(scale * (qreal)TILE_SIZE));
|
||||
}
|
||||
|
||||
static int limitZoom(int zoom)
|
||||
{
|
||||
if (zoom < ZOOM_MIN)
|
||||
return ZOOM_MIN;
|
||||
if (zoom > ZOOM_MAX)
|
||||
return ZOOM_MAX;
|
||||
|
||||
return zoom;
|
||||
}
|
||||
|
||||
|
||||
EmptyMap::EmptyMap(QObject *parent) : Map(parent)
|
||||
{
|
||||
_scale = SCALE_MAX;
|
||||
_zoom = ZOOM_MAX;
|
||||
}
|
||||
|
||||
QRectF EmptyMap::bounds() const
|
||||
@ -20,50 +51,38 @@ QRectF EmptyMap::bounds() const
|
||||
return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85)));
|
||||
}
|
||||
|
||||
qreal EmptyMap::zoomFit(const QSize &size, const RectC &br)
|
||||
int EmptyMap::zoomFit(const QSize &size, const RectC &br)
|
||||
{
|
||||
if (!br.isValid())
|
||||
_scale = SCALE_MAX;
|
||||
_zoom = ZOOM_MAX;
|
||||
else {
|
||||
QRectF tbr(Mercator().ll2xy(br.topLeft()),
|
||||
Mercator().ll2xy(br.bottomRight()));
|
||||
QRectF tbr(ll2m(br.topLeft()), ll2m(br.bottomRight()));
|
||||
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
|
||||
_scale = qMax(sc.x(), sc.y());
|
||||
|
||||
_zoom = limitZoom(scale2zoom(qMax(sc.x(), sc.y())));
|
||||
}
|
||||
|
||||
_scale = qMax(_scale, SCALE_MAX);
|
||||
_scale = qMin(_scale, SCALE_MIN);
|
||||
|
||||
return _scale;
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal EmptyMap::zoomFit(qreal resolution, const Coordinates &c)
|
||||
qreal EmptyMap::resolution(const QRectF &rect) const
|
||||
{
|
||||
_scale = (360.0 * resolution) / (WGS84_RADIUS * 2 * M_PI
|
||||
* cos(deg2rad(c.lat())));
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
|
||||
_scale = qMax(_scale, SCALE_MAX);
|
||||
_scale = qMin(_scale, SCALE_MIN);
|
||||
|
||||
return _scale;
|
||||
return (WGS84_RADIUS * 2.0 * M_PI * scale / 360.0
|
||||
* cos(2.0 * atan(exp(deg2rad(-rect.center().y() * scale))) - M_PI/2));
|
||||
}
|
||||
|
||||
qreal EmptyMap::resolution(const QPointF &p) const
|
||||
int EmptyMap::zoomIn()
|
||||
{
|
||||
return (WGS84_RADIUS * 2 * M_PI * _scale / 360.0
|
||||
* cos(2.0 * atan(exp(deg2rad(-p.y() * _scale))) - M_PI/2));
|
||||
_zoom = qMin(_zoom + 1, ZOOM_MAX);
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal EmptyMap::zoomIn()
|
||||
int EmptyMap::zoomOut()
|
||||
{
|
||||
_scale = qMax(_scale / 2.0, SCALE_MAX);
|
||||
return _scale;
|
||||
}
|
||||
|
||||
qreal EmptyMap::zoomOut()
|
||||
{
|
||||
_scale = qMin(_scale * 2.0, SCALE_MIN);
|
||||
return _scale;
|
||||
_zoom = qMax(_zoom - 1, ZOOM_MIN);
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
void EmptyMap::draw(QPainter *painter, const QRectF &rect)
|
||||
@ -73,12 +92,13 @@ void EmptyMap::draw(QPainter *painter, const QRectF &rect)
|
||||
|
||||
QPointF EmptyMap::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
QPointF m = Mercator().ll2xy(c);
|
||||
return QPointF(m.x() / _scale, m.y() / -_scale);
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
QPointF m = ll2m(c);
|
||||
return QPointF(m.x() / scale, m.y() / -scale);
|
||||
}
|
||||
|
||||
Coordinates EmptyMap::xy2ll(const QPointF &p) const
|
||||
{
|
||||
QPointF m(p.x() * _scale, -p.y() * _scale);
|
||||
return Mercator().xy2ll(m);
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
return m2ll(QPointF(p.x() * scale, -p.y() * scale));
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef EMPTYMAP_H
|
||||
#define EMPTYMAP_H
|
||||
|
||||
#include "common/coordinates.h"
|
||||
#include "map.h"
|
||||
|
||||
class EmptyMap : public Map
|
||||
@ -14,13 +13,12 @@ public:
|
||||
const QString &name() const {return _name;}
|
||||
|
||||
QRectF bounds() const;
|
||||
qreal resolution(const QPointF &p) const;
|
||||
qreal resolution(const QRectF &rect) const;
|
||||
|
||||
qreal zoom() const {return _scale;}
|
||||
qreal zoomFit(const QSize &size, const RectC &br);
|
||||
qreal zoomFit(qreal resolution, const Coordinates &c);
|
||||
qreal zoomIn();
|
||||
qreal zoomOut();
|
||||
int zoom() const {return _zoom;}
|
||||
int zoomFit(const QSize &size, const RectC &br);
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
QPointF ll2xy(const Coordinates &c)
|
||||
{return static_cast<const EmptyMap &>(*this).ll2xy(c);}
|
||||
@ -34,7 +32,7 @@ private:
|
||||
Coordinates xy2ll(const QPointF &p) const;
|
||||
|
||||
QString _name;
|
||||
qreal _scale;
|
||||
int _zoom;
|
||||
};
|
||||
|
||||
#endif // EMPTYMAP_H
|
||||
|
@ -183,9 +183,11 @@ Coordinates GCS::fromWGS84(const Coordinates &c) const
|
||||
return Coordinates(_primeMeridian.fromGreenwich(ds.lon()), ds.lat());
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const GCS &gcs)
|
||||
{
|
||||
dbg.nospace() << "GCS(" << gcs.datum() << ", " << gcs.primeMeridian()
|
||||
<< ", " << gcs.angularUnits() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -25,7 +25,6 @@ public:
|
||||
Coordinates toWGS84(const Coordinates &c) const;
|
||||
Coordinates fromWGS84(const Coordinates &c) const;
|
||||
|
||||
|
||||
static const GCS *gcs(int id);
|
||||
static const GCS *gcs(int geodeticDatum, int primeMeridian,
|
||||
int angularUnits);
|
||||
@ -50,6 +49,8 @@ inline bool operator==(const GCS &gcs1, const GCS &gcs2)
|
||||
&& gcs1.primeMeridian() == gcs2.primeMeridian()
|
||||
&& gcs1.angularUnits() == gcs2.angularUnits());}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const GCS &gcs);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // GCS_H
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QtEndian>
|
||||
#include "pcs.h"
|
||||
#include "latlon.h"
|
||||
#include "tifffile.h"
|
||||
#include "geotiff.h"
|
||||
|
||||
|
||||
@ -9,38 +9,55 @@
|
||||
#define TIFF_SHORT 3
|
||||
#define TIFF_LONG 4
|
||||
|
||||
#define ModelPixelScaleTag 33550
|
||||
#define ModelTiepointTag 33922
|
||||
#define ModelTransformationTag 34264
|
||||
#define GeoKeyDirectoryTag 34735
|
||||
#define GeoDoubleParamsTag 34736
|
||||
#define ImageWidth 256
|
||||
#define ImageHeight 257
|
||||
#define ModelPixelScaleTag 33550
|
||||
#define ModelTiepointTag 33922
|
||||
#define ModelTransformationTag 34264
|
||||
#define GeoKeyDirectoryTag 34735
|
||||
#define GeoDoubleParamsTag 34736
|
||||
|
||||
#define GTModelTypeGeoKey 1024
|
||||
#define GTRasterTypeGeoKey 1025
|
||||
#define GeographicTypeGeoKey 2048
|
||||
#define GeogGeodeticDatumGeoKey 2050
|
||||
#define GeogPrimeMeridianGeoKey 2051
|
||||
#define GeogAngularUnitsGeoKey 2054
|
||||
#define ProjectedCSTypeGeoKey 3072
|
||||
#define ProjectionGeoKey 3074
|
||||
#define ProjCoordTransGeoKey 3075
|
||||
#define ProjLinearUnitsGeoKey 3076
|
||||
#define ProjStdParallel1GeoKey 3078
|
||||
#define ProjStdParallel2GeoKey 3079
|
||||
#define ProjNatOriginLongGeoKey 3080
|
||||
#define ProjNatOriginLatGeoKey 3081
|
||||
#define ProjFalseEastingGeoKey 3082
|
||||
#define ProjFalseNorthingGeoKey 3083
|
||||
#define ProjScaleAtNatOriginGeoKey 3092
|
||||
#define GTModelTypeGeoKey 1024
|
||||
#define GTRasterTypeGeoKey 1025
|
||||
#define GeographicTypeGeoKey 2048
|
||||
#define GeogGeodeticDatumGeoKey 2050
|
||||
#define GeogPrimeMeridianGeoKey 2051
|
||||
#define GeogAngularUnitsGeoKey 2054
|
||||
#define GeogEllipsoidGeoKey 2056
|
||||
#define ProjectedCSTypeGeoKey 3072
|
||||
#define ProjectionGeoKey 3074
|
||||
#define ProjCoordTransGeoKey 3075
|
||||
#define ProjLinearUnitsGeoKey 3076
|
||||
#define ProjStdParallel1GeoKey 3078
|
||||
#define ProjStdParallel2GeoKey 3079
|
||||
#define ProjNatOriginLongGeoKey 3080
|
||||
#define ProjNatOriginLatGeoKey 3081
|
||||
#define ProjFalseEastingGeoKey 3082
|
||||
#define ProjFalseNorthingGeoKey 3083
|
||||
#define ProjCenterLongGeoKey 3088
|
||||
#define ProjCenterLatGeoKey 3089
|
||||
#define ProjScaleAtNatOriginGeoKey 3092
|
||||
#define ProjScaleAtCenterGeoKey 3093
|
||||
#define ProjAzimuthAngleGeoKey 3094
|
||||
#define ProjRectifiedGridAngleGeoKey 3096
|
||||
|
||||
#define ModelTypeProjected 1
|
||||
#define ModelTypeGeographic 2
|
||||
#define ModelTypeGeocentric 3
|
||||
|
||||
#define CT_TransverseMercator 1
|
||||
#define CT_ObliqueMercator 3
|
||||
#define CT_Mercator 7
|
||||
#define CT_LambertConfConic_2SP 8
|
||||
#define CT_LambertConfConic_1SP 9
|
||||
#define CT_LambertAzimEqualArea 10
|
||||
#define CT_AlbersEqualArea 11
|
||||
|
||||
#define ModelTypeProjected 1
|
||||
#define ModelTypeGeographic 2
|
||||
#define ModelTypeGeocentric 3
|
||||
|
||||
#define IS_SET(map, key) \
|
||||
((map).contains(key) && (map).value(key).SHORT != 32767)
|
||||
#define TO_M(lu, val) \
|
||||
(std::isnan(val) ? val : (lu).toMeters(val))
|
||||
#define TO_DEG(au, val) \
|
||||
(std::isnan(val) ? val : (au).toDegrees(val))
|
||||
|
||||
#define ARRAY_SIZE(a) \
|
||||
(sizeof(a) / sizeof(*a))
|
||||
@ -223,6 +240,7 @@ bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
|
||||
case ProjectionGeoKey:
|
||||
case ProjCoordTransGeoKey:
|
||||
case ProjLinearUnitsGeoKey:
|
||||
case GeogEllipsoidGeoKey:
|
||||
if (entry.TIFFTagLocation != 0 || entry.Count != 1)
|
||||
return false;
|
||||
value.SHORT = entry.ValueOffset;
|
||||
@ -235,6 +253,11 @@ bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
|
||||
case ProjFalseNorthingGeoKey:
|
||||
case ProjStdParallel1GeoKey:
|
||||
case ProjStdParallel2GeoKey:
|
||||
case ProjCenterLongGeoKey:
|
||||
case ProjCenterLatGeoKey:
|
||||
case ProjScaleAtCenterGeoKey:
|
||||
case ProjAzimuthAngleGeoKey:
|
||||
case ProjRectifiedGridAngleGeoKey:
|
||||
if (!readGeoValue(file, ctx.values, entry.ValueOffset,
|
||||
value.DOUBLE))
|
||||
return false;
|
||||
@ -272,13 +295,19 @@ const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
||||
if (!(gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT)))
|
||||
_errorString = QString("%1: unknown GCS")
|
||||
.arg(kv.value(GeographicTypeGeoKey).SHORT);
|
||||
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)) {
|
||||
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||
|| kv.value(GeogEllipsoidGeoKey).SHORT == 7019) {
|
||||
int pm = IS_SET(kv, GeogPrimeMeridianGeoKey)
|
||||
? kv.value(GeogPrimeMeridianGeoKey).SHORT : 8901;
|
||||
int au = IS_SET(kv, GeogAngularUnitsGeoKey)
|
||||
? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102;
|
||||
|
||||
if (!(gcs = GCS::gcs(kv.value(GeogGeodeticDatumGeoKey).SHORT, pm, au)))
|
||||
/* If only the ellipsoid is defined and it is GRS80, handle such
|
||||
definition as a WGS84 geodetic datum. */
|
||||
int gd = IS_SET(kv, GeogGeodeticDatumGeoKey)
|
||||
? kv.value(GeogGeodeticDatumGeoKey).SHORT : 6326;
|
||||
|
||||
if (!(gcs = GCS::gcs(gd, pm, au)))
|
||||
_errorString = QString("%1+%2: unknown geodetic datum + prime"
|
||||
" meridian combination")
|
||||
.arg(kv.value(GeogGeodeticDatumGeoKey).SHORT)
|
||||
@ -297,17 +326,19 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
|
||||
}
|
||||
|
||||
switch (kv.value(ProjCoordTransGeoKey).SHORT) {
|
||||
case 1:
|
||||
case CT_TransverseMercator:
|
||||
return Projection::Method(9807);
|
||||
case 7:
|
||||
case CT_ObliqueMercator:
|
||||
return Projection::Method(9815);
|
||||
case CT_Mercator:
|
||||
return Projection::Method(1024);
|
||||
case 8:
|
||||
return Projection::Method(9801);
|
||||
case 9:
|
||||
case CT_LambertConfConic_2SP:
|
||||
return Projection::Method(9802);
|
||||
case 10:
|
||||
case CT_LambertConfConic_1SP:
|
||||
return Projection::Method(9801);
|
||||
case CT_LambertAzimEqualArea:
|
||||
return Projection::Method(9820);
|
||||
case 11:
|
||||
case CT_AlbersEqualArea:
|
||||
return Projection::Method(9822);
|
||||
default:
|
||||
_errorString = QString("%1: unknown coordinate transformation method")
|
||||
@ -341,6 +372,8 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(),
|
||||
pcs->units());
|
||||
} else {
|
||||
double lat0, lon0, scale, fe, fn, sp1, sp2;
|
||||
|
||||
const GCS *g = gcs(kv);
|
||||
if (!g)
|
||||
return false;
|
||||
@ -358,15 +391,47 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
||||
return false;
|
||||
}
|
||||
|
||||
Projection::Setup setup(
|
||||
au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE),
|
||||
au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE),
|
||||
kv.value(ProjScaleAtNatOriginGeoKey).DOUBLE,
|
||||
lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE),
|
||||
lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE),
|
||||
au.toDegrees(kv.value(ProjStdParallel1GeoKey).DOUBLE),
|
||||
au.toDegrees(kv.value(ProjStdParallel2GeoKey).DOUBLE)
|
||||
);
|
||||
if (kv.contains(ProjNatOriginLatGeoKey))
|
||||
lat0 = kv.value(ProjNatOriginLatGeoKey).DOUBLE;
|
||||
else if (kv.contains(ProjCenterLatGeoKey))
|
||||
lat0 = kv.value(ProjCenterLatGeoKey).DOUBLE;
|
||||
else
|
||||
lat0 = NAN;
|
||||
if (kv.contains(ProjNatOriginLongGeoKey))
|
||||
lon0 = kv.value(ProjNatOriginLongGeoKey).DOUBLE;
|
||||
else if (kv.contains(ProjCenterLongGeoKey))
|
||||
lon0 = kv.value(ProjCenterLongGeoKey).DOUBLE;
|
||||
else
|
||||
lon0 = NAN;
|
||||
if (kv.contains(ProjScaleAtNatOriginGeoKey))
|
||||
scale = kv.value(ProjScaleAtNatOriginGeoKey).DOUBLE;
|
||||
else if (kv.contains(ProjScaleAtCenterGeoKey))
|
||||
scale = kv.value(ProjScaleAtCenterGeoKey).DOUBLE;
|
||||
else
|
||||
scale = NAN;
|
||||
if (kv.contains(ProjStdParallel1GeoKey))
|
||||
sp1 = kv.value(ProjStdParallel1GeoKey).DOUBLE;
|
||||
else if (kv.contains(ProjAzimuthAngleGeoKey))
|
||||
sp1 = kv.value(ProjAzimuthAngleGeoKey).DOUBLE;
|
||||
else
|
||||
sp1 = NAN;
|
||||
if (kv.contains(ProjStdParallel2GeoKey))
|
||||
sp2 = kv.value(ProjStdParallel2GeoKey).DOUBLE;
|
||||
else if (kv.contains(ProjRectifiedGridAngleGeoKey))
|
||||
sp2 = kv.value(ProjRectifiedGridAngleGeoKey).DOUBLE;
|
||||
else
|
||||
sp2 = NAN;
|
||||
if (kv.contains(ProjFalseNorthingGeoKey))
|
||||
fn = kv.value(ProjFalseNorthingGeoKey).DOUBLE;
|
||||
else
|
||||
fn = NAN;
|
||||
if (kv.contains(ProjFalseEastingGeoKey))
|
||||
fe = kv.value(ProjFalseEastingGeoKey).DOUBLE;
|
||||
else
|
||||
fe = NAN;
|
||||
|
||||
Projection::Setup setup(TO_DEG(au, lat0), TO_DEG(au, lon0), scale,
|
||||
TO_M(lu, fe), TO_M(lu, fn), TO_DEG(au, sp1), TO_DEG(au, sp2));
|
||||
|
||||
_projection = Projection(g, m, setup, lu);
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
#ifndef GEOTIFF_H
|
||||
#define GEOTIFF_H
|
||||
|
||||
#include <QTransform>
|
||||
#include <QFile>
|
||||
#include <QMap>
|
||||
#include "gcs.h"
|
||||
#include "projection.h"
|
||||
#include "tifffile.h"
|
||||
#include <QList>
|
||||
#include <QTransform>
|
||||
#include "transform.h"
|
||||
#include "linearunits.h"
|
||||
#include "projection.h"
|
||||
|
||||
class TIFFFile;
|
||||
class GCS;
|
||||
|
||||
class GeoTIFF
|
||||
{
|
||||
|
@ -1,193 +1,72 @@
|
||||
/*
|
||||
* Based on libgeotrans with the following Source Code Disclaimer:
|
||||
|
||||
1. The GEOTRANS source code ("the software") is provided free of charge by
|
||||
the National Imagery and Mapping Agency (NIMA) of the United States
|
||||
Department of Defense. Although NIMA makes no copyright claim under Title 17
|
||||
U.S.C., NIMA claims copyrights in the source code under other legal regimes.
|
||||
NIMA hereby grants to each user of the software a license to use and
|
||||
distribute the software, and develop derivative works.
|
||||
|
||||
2. Warranty Disclaimer: The software was developed to meet only the internal
|
||||
requirements of the U.S. National Imagery and Mapping Agency. The software
|
||||
is provided "as is," and no warranty, express or implied, including but not
|
||||
limited to the implied warranties of merchantability and fitness for
|
||||
particular purpose or arising by statute or otherwise in law or from a
|
||||
course of dealing or usage in trade, is made by NIMA as to the accuracy and
|
||||
functioning of the software.
|
||||
|
||||
3. NIMA and its personnel are not required to provide technical support or
|
||||
general assistance with respect to the software.
|
||||
|
||||
4. Neither NIMA nor its personnel will be liable for any claims, losses, or
|
||||
damages arising from or connected with the use of the software. The user
|
||||
agrees to hold harmless the United States National Imagery and Mapping
|
||||
Agency. The user's sole and exclusive remedy is to stop using the software.
|
||||
|
||||
5. NIMA requests that products developed using the software credit the
|
||||
source of the software with the following statement, "The product was
|
||||
developed using GEOTRANS, a product of the National Imagery and Mapping
|
||||
Agency and U.S. Army Engineering Research and Development Center."
|
||||
|
||||
6. For any products developed using the software, NIMA requires a disclaimer
|
||||
that use of the software does not indicate endorsement or approval of the
|
||||
product by the Secretary of Defense or the National Imagery and Mapping
|
||||
Agency. Pursuant to the United States Code, 10 U.S.C. Sec. 2797, the name of
|
||||
the National Imagery and Mapping Agency, the initials "NIMA", the seal of
|
||||
the National Imagery and Mapping Agency, or any colorable imitation thereof
|
||||
shall not be used to imply approval, endorsement, or authorization of a
|
||||
product without prior written permission from United States Secretary of
|
||||
Defense.
|
||||
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "ellipsoid.h"
|
||||
#include "lambertazimuthal.h"
|
||||
|
||||
|
||||
#ifndef M_PI_2
|
||||
#define M_PI_2 1.57079632679489661923
|
||||
#endif // M_PI_2
|
||||
#define sin2(x) (sin(x) * sin(x))
|
||||
#define sqr(x) ((x) * (x))
|
||||
|
||||
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
|
||||
double latitudeOrigin, double longitudeOrigin, double falseEasting,
|
||||
double falseNorthing)
|
||||
{
|
||||
double es2, es4, es6;
|
||||
double lat0 = deg2rad(latitudeOrigin);
|
||||
|
||||
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
|
||||
* ellipsoid->flattening();
|
||||
|
||||
es4 = es2 * es2;
|
||||
es6 = es4 * es2;
|
||||
_ra = ellipsoid->radius() * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0
|
||||
* es6 / 3024.0);
|
||||
_latOrigin = deg2rad(latitudeOrigin);
|
||||
_sinLatOrigin = sin(_latOrigin);
|
||||
_cosLatOrigin = cos(_latOrigin);
|
||||
_absLatOrigin = fabs(_latOrigin);
|
||||
_lonOrigin = deg2rad(longitudeOrigin);
|
||||
if (_lonOrigin > M_PI)
|
||||
_lonOrigin -= 2.0 * M_PI;
|
||||
|
||||
_falseNorthing = falseNorthing;
|
||||
_falseEasting = falseEasting;
|
||||
_falseNorthing = falseNorthing;
|
||||
_lon0 = deg2rad(longitudeOrigin);
|
||||
|
||||
_a = ellipsoid->radius();
|
||||
|
||||
_es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
|
||||
* ellipsoid->flattening();
|
||||
_es = sqrt(_es2);
|
||||
|
||||
double q0 = (1.0 - _es2) * ((sin(lat0) / (1.0 - _es2 * sin2(lat0)))
|
||||
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat0)) / (1.0 + _es
|
||||
* sin(lat0)))));
|
||||
_qP = (1.0 - _es2) * ((1.0 / (1.0 - _es2)) - ((1.0/(2.0*_es))
|
||||
* log((1.0 - _es) / (1.0 + _es))));
|
||||
_beta0 = asin(q0 / _qP);
|
||||
_Rq = _a * sqrt(_qP / 2.0);
|
||||
_D = _a * (cos(lat0) / sqrt(1.0 - _es2 * sin2(lat0))) / (_Rq * cos(_beta0));
|
||||
}
|
||||
|
||||
QPointF LambertAzimuthal::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
double dlam;
|
||||
double k_prime;
|
||||
double cd;
|
||||
double rlat = deg2rad(c.lat());
|
||||
double slat = sin(rlat);
|
||||
double clat = cos(rlat);
|
||||
double cos_c;
|
||||
double sin_dlam, cos_dlam;
|
||||
double Ra_kprime;
|
||||
double Ra_PI_OVER_2_Lat;
|
||||
QPointF p;
|
||||
double lon = deg2rad(c.lon());
|
||||
double lat = deg2rad(c.lat());
|
||||
|
||||
double q = (1.0 - _es2) * ((sin(lat) / (1.0 - _es2 * sin2(lat)))
|
||||
- ((1.0/(2.0*_es)) * log((1.0 - _es * sin(lat)) / (1.0 + _es
|
||||
* sin(lat)))));
|
||||
double beta = asin(q / _qP);
|
||||
double B = _Rq * sqrt(2.0 / (1.0 + sin(_beta0) * sin(beta) + (cos(_beta0)
|
||||
* cos(beta) * cos(lon - _lon0))));
|
||||
|
||||
dlam = deg2rad(c.lon()) - _lonOrigin;
|
||||
if (dlam > M_PI)
|
||||
dlam -= 2.0 * M_PI;
|
||||
if (dlam < -M_PI)
|
||||
dlam += 2.0 * M_PI;
|
||||
double x = _falseEasting + ((B * _D) * (cos(beta) * sin(lon - _lon0)));
|
||||
double y = _falseNorthing + (B / _D) * ((cos(_beta0) * sin(beta))
|
||||
- (sin(_beta0) * cos(beta) * cos(lon - _lon0)));
|
||||
|
||||
sin_dlam = sin(dlam);
|
||||
cos_dlam = cos(dlam);
|
||||
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
|
||||
if (_latOrigin >= 0.0) {
|
||||
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 - rlat);
|
||||
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
|
||||
p.ry() = -1.0 * (Ra_PI_OVER_2_Lat * cos_dlam) + _falseNorthing;
|
||||
} else {
|
||||
Ra_PI_OVER_2_Lat = _ra * (M_PI_2 + rlat);
|
||||
p.rx() = Ra_PI_OVER_2_Lat * sin_dlam + _falseEasting;
|
||||
p.ry() = Ra_PI_OVER_2_Lat * cos_dlam + _falseNorthing;
|
||||
}
|
||||
} else if (_absLatOrigin <= 1.0e-10) {
|
||||
cos_c = clat * cos_dlam;
|
||||
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
|
||||
if (cos_c >= 0.0) {
|
||||
p.rx() = _falseEasting;
|
||||
p.ry() = _falseNorthing;
|
||||
} else
|
||||
return QPointF(NAN, NAN);
|
||||
} else {
|
||||
cd = acos(cos_c);
|
||||
k_prime = cd / sin(cd);
|
||||
Ra_kprime = _ra * k_prime;
|
||||
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
|
||||
p.ry() = Ra_kprime * slat + _falseNorthing;
|
||||
}
|
||||
} else {
|
||||
cos_c = (_sinLatOrigin * slat) + (_cosLatOrigin * clat * cos_dlam);
|
||||
if (fabs(fabs(cos_c) - 1.0) < 1.0e-14) {
|
||||
if (cos_c >= 0.0) {
|
||||
p.rx() = _falseEasting;
|
||||
p.ry() = _falseNorthing;
|
||||
} else
|
||||
return QPointF(NAN, NAN);
|
||||
} else {
|
||||
cd = acos(cos_c);
|
||||
k_prime = cd / sin(cd);
|
||||
Ra_kprime = _ra * k_prime;
|
||||
p.rx() = Ra_kprime * clat * sin_dlam + _falseEasting;
|
||||
p.ry() = Ra_kprime * (_cosLatOrigin * slat - _sinLatOrigin * clat
|
||||
* cos_dlam) + _falseNorthing;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
return QPointF(x, y);
|
||||
}
|
||||
|
||||
Coordinates LambertAzimuthal::xy2ll(const QPointF &p) const
|
||||
{
|
||||
double dx, dy;
|
||||
double rho;
|
||||
double cd;
|
||||
double sin_c, cos_c, dy_sinc;
|
||||
double lat, lon;
|
||||
double es4 = _es2 * _es2;
|
||||
double es6 = _es2 * es4;
|
||||
|
||||
double rho = sqrt(sqr((p.x() - _falseEasting) / _D) + sqr(_D * (p.y()
|
||||
- _falseNorthing)));
|
||||
double C = 2.0 * asin(rho / (2.0*_Rq));
|
||||
double betaS = asin((cos(C) * sin(_beta0)) + ((_D * (p.y() -_falseNorthing)
|
||||
* sin(C) * cos(_beta0)) / rho));
|
||||
|
||||
dy = p.y() - _falseNorthing;
|
||||
dx = p.x() - _falseEasting;
|
||||
rho = sqrt(dx * dx + dy * dy);
|
||||
if (fabs(rho) <= 1.0e-10) {
|
||||
lat = _latOrigin;
|
||||
lon = _lonOrigin;
|
||||
} else {
|
||||
cd = rho / _ra;
|
||||
sin_c = sin(cd);
|
||||
cos_c = cos(cd);
|
||||
dy_sinc = dy * sin_c;
|
||||
lat = asin((cos_c * _sinLatOrigin) + ((dy_sinc * _cosLatOrigin) / rho));
|
||||
if (fabs(_absLatOrigin - M_PI_2) < 1.0e-10) {
|
||||
if (_latOrigin >= 0.0)
|
||||
lon = _lonOrigin + atan2(dx, -dy);
|
||||
else
|
||||
lon = _lonOrigin + atan2(dx, dy);
|
||||
}
|
||||
else
|
||||
lon = _lonOrigin + atan2((dx * sin_c), ((rho * _cosLatOrigin
|
||||
* cos_c) - (dy_sinc * _sinLatOrigin)));
|
||||
}
|
||||
|
||||
if (lat > M_PI_2)
|
||||
lat = M_PI_2;
|
||||
else if (lat < -M_PI_2)
|
||||
lat = -M_PI_2;
|
||||
|
||||
if (lon > M_PI)
|
||||
lon -= 2.0 * M_PI;
|
||||
if (lon < -M_PI)
|
||||
lon += 2.0 * M_PI;
|
||||
|
||||
if (lon > M_PI)
|
||||
lon = M_PI;
|
||||
else if (lon < -M_PI)
|
||||
lon = -M_PI;
|
||||
double lon = _lon0 + atan((p.x() - _falseEasting) * sin(C) / (_D * rho
|
||||
* cos(_beta0) * cos(C) - sqr(_D) * (p.y() - _falseNorthing) * sin(_beta0)
|
||||
* sin(C)));
|
||||
double lat = betaS + ((_es2/3.0 + 31.0*es4/180.0 + 517.0*es6/5040.0)
|
||||
* sin(2.0*betaS)) + ((23.0*es4/360.0 + 251.0*es6/3780.0) * sin(4.0*betaS))
|
||||
+ ((761.0*es6/45360.0)*sin(6.0*betaS));
|
||||
|
||||
return Coordinates(rad2deg(lon), rad2deg(lat));
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef LAMBERTAZIMUTHAL_H
|
||||
#define LAMBERTAZIMUTHAL_H
|
||||
|
||||
#include "ellipsoid.h"
|
||||
#include "ct.h"
|
||||
|
||||
class Ellipsoid;
|
||||
|
||||
class LambertAzimuthal : public CT
|
||||
{
|
||||
public:
|
||||
@ -16,15 +17,10 @@ public:
|
||||
virtual Coordinates xy2ll(const QPointF &p) const;
|
||||
|
||||
private:
|
||||
double _ra;
|
||||
double _sinLatOrigin;
|
||||
double _cosLatOrigin;
|
||||
double _absLatOrigin;
|
||||
|
||||
double _latOrigin;
|
||||
double _lonOrigin;
|
||||
double _lon0;
|
||||
double _falseNorthing;
|
||||
double _falseEasting;
|
||||
double _a, _es, _es2, _qP, _beta0, _Rq, _D;
|
||||
};
|
||||
|
||||
#endif // LAMBERTAZIMUTHAL_H
|
||||
|
@ -42,6 +42,7 @@ Defense.
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include "ellipsoid.h"
|
||||
#include "lambertconic.h"
|
||||
|
||||
#ifndef M_PI_2
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifndef LAMBERTCONIC_H
|
||||
#define LAMBERTCONIC_H
|
||||
|
||||
#include "ellipsoid.h"
|
||||
#include "ct.h"
|
||||
|
||||
class Ellipsoid;
|
||||
|
||||
class LambertConic1 : public CT
|
||||
{
|
||||
public:
|
||||
|
@ -20,8 +20,10 @@ LinearUnits::LinearUnits(int code)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const LinearUnits &lu)
|
||||
{
|
||||
dbg.nospace() << "LinearUnits(" << lu._f << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -22,7 +22,9 @@ public:
|
||||
{return QPointF(p.x() / _f, p.y() /_f);}
|
||||
|
||||
friend bool operator==(const LinearUnits &lu1, const LinearUnits &lu2);
|
||||
#ifndef QT_NO_DEBUG
|
||||
friend QDebug operator<<(QDebug dbg, const LinearUnits &lu);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
private:
|
||||
double _f;
|
||||
@ -31,6 +33,8 @@ private:
|
||||
inline bool operator==(const LinearUnits &lu1, const LinearUnits &lu2)
|
||||
{return (lu1._f == lu2._f);}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const LinearUnits &lu);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // LINEARUNITS_H
|
||||
|
@ -5,9 +5,9 @@
|
||||
#include <QString>
|
||||
#include <QRectF>
|
||||
#include <QColor>
|
||||
#include "common/coordinates.h"
|
||||
|
||||
class QPainter;
|
||||
class Coordinates;
|
||||
class RectC;
|
||||
|
||||
class Map : public QObject
|
||||
@ -15,18 +15,18 @@ class Map : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Map(QObject *parent = 0) : QObject(parent) {_backgroundColor = Qt::white;}
|
||||
Map(QObject *parent = 0) : QObject(parent), _backgroundColor(Qt::white) {}
|
||||
virtual ~Map() {}
|
||||
|
||||
virtual const QString &name() const = 0;
|
||||
|
||||
virtual QRectF bounds() const = 0;
|
||||
virtual qreal resolution(const QPointF &p) const = 0;
|
||||
virtual qreal resolution(const QRectF &rect) const = 0;
|
||||
|
||||
virtual qreal zoom() const = 0;
|
||||
virtual qreal zoomFit(const QSize &size, const RectC &br) = 0;
|
||||
virtual qreal zoomFit(qreal resolution, const Coordinates &c) = 0;
|
||||
virtual qreal zoomIn() = 0;
|
||||
virtual qreal zoomOut() = 0;
|
||||
virtual int zoom() const = 0;
|
||||
virtual int zoomFit(const QSize &size, const RectC &br) = 0;
|
||||
virtual int zoomIn() = 0;
|
||||
virtual int zoomOut() = 0;
|
||||
|
||||
virtual QPointF ll2xy(const Coordinates &c) = 0;
|
||||
virtual Coordinates xy2ll(const QPointF &p) = 0;
|
||||
@ -40,6 +40,9 @@ public:
|
||||
|
||||
void setBackgroundColor(const QColor &color) {_backgroundColor = color;}
|
||||
|
||||
virtual bool isValid() const {return true;}
|
||||
virtual QString errorString() const {return QString();}
|
||||
|
||||
signals:
|
||||
void loaded();
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <QIODevice>
|
||||
#include "utm.h"
|
||||
#include "gcs.h"
|
||||
#include "mapfile.h"
|
||||
|
@ -1,12 +1,13 @@
|
||||
#ifndef MAPFILE_H
|
||||
#define MAPFILE_H
|
||||
|
||||
#include <QIODevice>
|
||||
#include <QTransform>
|
||||
#include "gcs.h"
|
||||
#include "transform.h"
|
||||
#include "projection.h"
|
||||
|
||||
class QIODevice;
|
||||
|
||||
class MapFile
|
||||
{
|
||||
public:
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include "common/range.h"
|
||||
#include "atlas.h"
|
||||
#include "offlinemap.h"
|
||||
#include "onlinemap.h"
|
||||
@ -13,7 +12,7 @@ bool MapList::loadSource(const QString &path, bool dir)
|
||||
MapSource ms;
|
||||
Map *map;
|
||||
|
||||
if (!ms.loadFile(path, &map)) {
|
||||
if (!(map = ms.loadFile(path))) {
|
||||
if (dir)
|
||||
_errorString += path + ": " + ms.errorString() + "\n";
|
||||
else
|
||||
|
@ -3,9 +3,8 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include "map.h"
|
||||
|
||||
class Tar;
|
||||
class Map;
|
||||
|
||||
class MapList : public QObject
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include <QFile>
|
||||
#include <QXmlStreamReader>
|
||||
#include "onlinemap.h"
|
||||
#include "wmtsmap.h"
|
||||
#include "mapsource.h"
|
||||
|
||||
|
||||
#define ZOOM_MAX 19
|
||||
#define ZOOM_MIN 0
|
||||
#define BOUNDS_LEFT -180
|
||||
@ -11,6 +11,11 @@
|
||||
#define BOUNDS_RIGHT 180
|
||||
#define BOUNDS_BOTTOM -85.0511
|
||||
|
||||
MapSource::TMSConfig::TMSConfig()
|
||||
: zooms(ZOOM_MIN, ZOOM_MAX), bounds(Coordinates(BOUNDS_LEFT, BOUNDS_TOP),
|
||||
Coordinates(BOUNDS_RIGHT, BOUNDS_BOTTOM)) {}
|
||||
|
||||
|
||||
Range MapSource::zooms(QXmlStreamReader &reader)
|
||||
{
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
@ -43,7 +48,7 @@ Range MapSource::zooms(QXmlStreamReader &reader)
|
||||
} else
|
||||
max = ZOOM_MAX;
|
||||
|
||||
if (min > max || max < min) {
|
||||
if (min > max) {
|
||||
reader.raiseError("Invalid maximal/minimal zoom level combination");
|
||||
return Range();
|
||||
}
|
||||
@ -109,11 +114,11 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
|
||||
} else
|
||||
right = BOUNDS_RIGHT;
|
||||
|
||||
if (bottom > top || top < bottom) {
|
||||
if (bottom >= top) {
|
||||
reader.raiseError("Invalid bottom/top bounds combination");
|
||||
return RectC();
|
||||
}
|
||||
if (left > right || right < left) {
|
||||
if (left >= right) {
|
||||
reader.raiseError("Invalid left/right bounds combination");
|
||||
return RectC();
|
||||
}
|
||||
@ -121,52 +126,109 @@ RectC MapSource::bounds(QXmlStreamReader &reader)
|
||||
return RectC(Coordinates(left, top), Coordinates(right, bottom));
|
||||
}
|
||||
|
||||
void MapSource::map(QXmlStreamReader &reader, Map **map)
|
||||
void MapSource::map(QXmlStreamReader &reader, Config &config)
|
||||
{
|
||||
QString name, url;
|
||||
Range z(ZOOM_MIN, ZOOM_MAX);
|
||||
RectC b(Coordinates(BOUNDS_LEFT, BOUNDS_TOP),
|
||||
Coordinates(BOUNDS_RIGHT, BOUNDS_BOTTOM));
|
||||
config.type = (reader.attributes().value("type") == "WMTS") ? WMTS : TMS;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == "name")
|
||||
name = reader.readElementText();
|
||||
else if (reader.name() == "url")
|
||||
url = reader.readElementText();
|
||||
else if (reader.name() == "zoom") {
|
||||
z = zooms(reader);
|
||||
config.name = reader.readElementText();
|
||||
else if (reader.name() == "url") {
|
||||
config.wmts.rest = (reader.attributes().value("type") == "REST")
|
||||
? true : false;
|
||||
config.url = reader.readElementText();
|
||||
} else if (reader.name() == "zoom") {
|
||||
config.tms.zooms = zooms(reader);
|
||||
reader.skipCurrentElement();
|
||||
} else if (reader.name() == "bounds") {
|
||||
b = bounds(reader);
|
||||
config.tms.bounds = bounds(reader);
|
||||
reader.skipCurrentElement();
|
||||
} else if (reader.name() == "format") {
|
||||
config.wmts.format = reader.readElementText();
|
||||
} else if (reader.name() == "layer")
|
||||
config.wmts.layer = reader.readElementText();
|
||||
else if (reader.name() == "style")
|
||||
config.wmts.style = reader.readElementText();
|
||||
else if (reader.name() == "set") {
|
||||
config.wmts.yx = (reader.attributes().value("axis") == "yx")
|
||||
? true : false;
|
||||
config.wmts.set = reader.readElementText();
|
||||
} else if (reader.name() == "dimension") {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (!attr.hasAttribute("id"))
|
||||
reader.raiseError("Missing dimension id");
|
||||
else
|
||||
config.wmts.dimensions.append(QPair<QString, QString>(
|
||||
attr.value("id").toString(), reader.readElementText()));
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
*map = reader.error() ? 0 : new OnlineMap(name, url, z, b);
|
||||
}
|
||||
|
||||
bool MapSource::loadFile(const QString &path, Map **map)
|
||||
Map *MapSource::loadFile(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
QXmlStreamReader reader;
|
||||
Config config;
|
||||
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
_errorString = file.errorString();
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
reader.setDevice(&file);
|
||||
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == "map")
|
||||
MapSource::map(reader, map);
|
||||
map(reader, config);
|
||||
else
|
||||
reader.raiseError("Not an online map source file");
|
||||
}
|
||||
if (reader.error()) {
|
||||
_errorString = QString("%1: %2").arg(reader.lineNumber())
|
||||
.arg(reader.errorString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
_errorString = reader.error() ? QString("%1: %2").arg(reader.lineNumber())
|
||||
.arg(reader.errorString()) : QString();
|
||||
if (config.name.isEmpty()) {
|
||||
_errorString = "Missing name definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.url.isEmpty()) {
|
||||
_errorString = "Missing URL definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.type == WMTS) {
|
||||
if (config.wmts.layer.isEmpty()) {
|
||||
_errorString = "Missing layer definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.wmts.style.isEmpty()) {
|
||||
_errorString = "Missing style definiton";
|
||||
return 0;
|
||||
}
|
||||
if (config.wmts.set.isEmpty()) {
|
||||
_errorString = "Missing set definiton";
|
||||
return 0;
|
||||
}
|
||||
if (config.wmts.format.isEmpty()) {
|
||||
_errorString = "Missing format definition";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return !reader.error();
|
||||
Map *m;
|
||||
if (config.type == WMTS)
|
||||
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.wmts.layer,
|
||||
config.wmts.set, config.wmts.style, config.wmts.format,
|
||||
config.wmts.rest, config.wmts.yx, config.wmts.dimensions));
|
||||
else
|
||||
m = new OnlineMap(config.name, config.url, config.tms.zooms,
|
||||
config.tms.bounds);
|
||||
if (!m->isValid()) {
|
||||
_errorString = m->errorString();
|
||||
delete m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@ -11,13 +11,47 @@ class QXmlStreamReader;
|
||||
class MapSource
|
||||
{
|
||||
public:
|
||||
bool loadFile(const QString &path, Map **map);
|
||||
Map *loadFile(const QString &path);
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
TMS,
|
||||
WMTS
|
||||
};
|
||||
|
||||
struct TMSConfig {
|
||||
Range zooms;
|
||||
RectC bounds;
|
||||
|
||||
TMSConfig();
|
||||
};
|
||||
|
||||
struct WMTSConfig {
|
||||
QString layer;
|
||||
QString style;
|
||||
QString set;
|
||||
QString format;
|
||||
bool rest;
|
||||
bool yx;
|
||||
QList<QPair<QString, QString> > dimensions;
|
||||
|
||||
WMTSConfig() : format("image/png"), rest(false), yx(false) {}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
QString name;
|
||||
QString url;
|
||||
Type type;
|
||||
WMTSConfig wmts;
|
||||
TMSConfig tms;
|
||||
|
||||
Config() : type(TMS) {}
|
||||
};
|
||||
|
||||
RectC bounds(QXmlStreamReader &reader);
|
||||
Range zooms(QXmlStreamReader &reader);
|
||||
void map(QXmlStreamReader &reader, Map **map);
|
||||
void map(QXmlStreamReader &reader, Config &config);
|
||||
|
||||
QString _errorString;
|
||||
};
|
||||
|
@ -116,6 +116,7 @@ void Matrix::zeroize()
|
||||
_m[i] = 0;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Matrix &matrix)
|
||||
{
|
||||
dbg.nospace() << "Matrix(" << endl;
|
||||
@ -128,3 +129,4 @@ QDebug operator<<(QDebug dbg, const Matrix &matrix)
|
||||
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -5,7 +5,8 @@
|
||||
#include <cfloat>
|
||||
#include <QDebug>
|
||||
|
||||
class Matrix {
|
||||
class Matrix
|
||||
{
|
||||
public:
|
||||
Matrix() {_h = 0; _w = 0; _m = 0;}
|
||||
Matrix(size_t h, size_t w);
|
||||
@ -31,6 +32,8 @@ private:
|
||||
size_t _w;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Matrix &matrix);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // MATRIX_H
|
||||
|
@ -1,12 +1,16 @@
|
||||
#include <cmath>
|
||||
#include "common/coordinates.h"
|
||||
#include "common/wgs84.h"
|
||||
#include "mercator.h"
|
||||
|
||||
QPointF Mercator::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
|
||||
return QPointF(deg2rad(c.lon()) * WGS84_RADIUS,
|
||||
log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0)) * WGS84_RADIUS);
|
||||
}
|
||||
|
||||
Coordinates Mercator::xy2ll(const QPointF &p) const
|
||||
{
|
||||
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
|
||||
return Coordinates(rad2deg(p.x() / WGS84_RADIUS),
|
||||
rad2deg(2 * atan(exp(p.y() / WGS84_RADIUS)) - M_PI/2));
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
#include <QtGlobal>
|
||||
#include <QPainter>
|
||||
#include <QFileInfo>
|
||||
#include <QMap>
|
||||
@ -9,56 +8,49 @@
|
||||
#include <QPixmapCache>
|
||||
#include "common/coordinates.h"
|
||||
#include "common/rectc.h"
|
||||
#include "tar.h"
|
||||
#include "ozf.h"
|
||||
#include "mapfile.h"
|
||||
#include "geotiff.h"
|
||||
#include "offlinemap.h"
|
||||
|
||||
|
||||
void OfflineMap::computeResolution()
|
||||
bool OfflineMap::setImageInfo(const QString &path)
|
||||
{
|
||||
Coordinates tl = xy2ll((bounds().topLeft()));
|
||||
Coordinates br = xy2ll(bounds().bottomRight());
|
||||
|
||||
qreal ds = tl.distanceTo(br);
|
||||
qreal ps = QLineF(bounds().topLeft(), bounds().bottomRight()).length();
|
||||
|
||||
_resolution = ds/ps;
|
||||
}
|
||||
|
||||
bool OfflineMap::getImageInfo(const QString &path)
|
||||
{
|
||||
QFileInfo ii(_imgPath);
|
||||
QFileInfo ii(_map.path);
|
||||
|
||||
if (ii.isRelative())
|
||||
ii.setFile(path + "/" + _imgPath);
|
||||
ii.setFile(path + "/" + _map.path);
|
||||
|
||||
if (!ii.exists()) {
|
||||
int last = _imgPath.lastIndexOf('\\');
|
||||
if (last >= 0 && last < _imgPath.length() - 1) {
|
||||
QStringRef fn(&_imgPath, last + 1, _imgPath.length() - last - 1);
|
||||
int last = _map.path.lastIndexOf('\\');
|
||||
if (last >= 0 && last < _map.path.length() - 1) {
|
||||
QStringRef fn(&_map.path, last + 1, _map.path.length() - last - 1);
|
||||
ii.setFile(path + "/" + fn.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (ii.exists())
|
||||
_imgPath = ii.absoluteFilePath();
|
||||
_map.path = ii.absoluteFilePath();
|
||||
else {
|
||||
_errorString = QString("%1: No such image file").arg(_imgPath);
|
||||
_errorString = QString("%1: No such image file").arg(_map.path);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (OZF::isOZF(_imgPath)) {
|
||||
if (!_ozf.load(_imgPath)) {
|
||||
if (OZF::isOZF(_map.path)) {
|
||||
_ozf = new OZF(_map.path);
|
||||
if (!_ozf->open()) {
|
||||
_errorString = QString("%1: Error loading OZF file")
|
||||
.arg(QFileInfo(_imgPath).fileName());
|
||||
.arg(_ozf->fileName());
|
||||
return false;
|
||||
}
|
||||
_scale = _ozf->scale(_zoom);
|
||||
} else {
|
||||
QImageReader img(_imgPath);
|
||||
_size = img.size();
|
||||
if (!_size.isValid()) {
|
||||
QImageReader img(_map.path);
|
||||
_map.size = img.size();
|
||||
if (!_map.size.isValid()) {
|
||||
_errorString = QString("%1: Error reading map image")
|
||||
.arg(QFileInfo(_imgPath).fileName());
|
||||
.arg(QFileInfo(_map.path).fileName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -66,27 +58,33 @@ bool OfflineMap::getImageInfo(const QString &path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
|
||||
bool OfflineMap::setTileInfo(const QStringList &tiles, const QString &path)
|
||||
{
|
||||
if (!_map.size.isValid()) {
|
||||
_errorString = "Missing total image size (IWH)";
|
||||
return false;
|
||||
}
|
||||
|
||||
QRegExp rx("_[0-9]+_[0-9]+\\.");
|
||||
for (int i = 0; i < tiles.size(); i++) {
|
||||
if (tiles.at(i).contains(rx)) {
|
||||
_tileName = QString(tiles.at(i)).replace(rx, "_%1_%2.");
|
||||
_tile.path = QString(tiles.at(i)).replace(rx, "_%1_%2.");
|
||||
|
||||
if (path.isNull()) {
|
||||
QByteArray ba = _tar.file(tiles.at(i));
|
||||
if (_tar) {
|
||||
QByteArray ba = _tar->file(tiles.at(i));
|
||||
QBuffer buffer(&ba);
|
||||
_tileSize = QImageReader(&buffer).size();
|
||||
_tile.size = QImageReader(&buffer).size();
|
||||
} else {
|
||||
_tileName = path + "/" + _tileName;
|
||||
_tileSize = QImageReader(path + "/" + tiles.at(i)).size();
|
||||
_tile.path = path + "/" + _tile.path;
|
||||
_tile.size = QImageReader(path + "/" + tiles.at(i)).size();
|
||||
}
|
||||
if (!_tileSize.isValid()) {
|
||||
if (!_tile.size.isValid()) {
|
||||
_errorString = QString("Error retrieving tile size: "
|
||||
"%1: Invalid image").arg(QFileInfo(tiles.at(i)).fileName());
|
||||
return false;
|
||||
}
|
||||
|
||||
_map.path = QString();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -95,35 +93,22 @@ bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OfflineMap::totalSizeSet()
|
||||
{
|
||||
if (!_size.isValid()) {
|
||||
_errorString = "Missing total image size (IWH)";
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent)
|
||||
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
|
||||
_valid = false;
|
||||
_img = 0;
|
||||
_resolution = 0.0;
|
||||
_zoom = 0;
|
||||
_scale = QPointF(1.0, 1.0);
|
||||
|
||||
if (suffix == "tar") {
|
||||
if (!_tar.load(fileName)) {
|
||||
_tar = new Tar(fileName);
|
||||
if (!_tar->open()) {
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
|
||||
QString mapFileName = fi.completeBaseName() + ".map";
|
||||
QByteArray ba = _tar.file(mapFileName);
|
||||
QByteArray ba = _tar->file(mapFileName);
|
||||
if (ba.isNull()) {
|
||||
_errorString = "Map file not found";
|
||||
return;
|
||||
@ -135,8 +120,8 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
|
||||
return;
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_size = mf.size();
|
||||
_imgPath = mf.image();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
@ -148,8 +133,8 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
|
||||
return;
|
||||
} else {
|
||||
_name = mf.name();
|
||||
_size = mf.size();
|
||||
_imgPath = mf.image();
|
||||
_map.size = mf.size();
|
||||
_map.path = mf.image();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
@ -160,7 +145,7 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
|
||||
return;
|
||||
} else {
|
||||
_name = fi.fileName();
|
||||
_imgPath = fileName;
|
||||
_map.path = fileName;
|
||||
_projection = gt.projection();
|
||||
_transform = gt.transform();
|
||||
}
|
||||
@ -169,43 +154,31 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_tar.isOpen()) {
|
||||
if (!totalSizeSet())
|
||||
if (_tar) {
|
||||
if (!setTileInfo(_tar->files()))
|
||||
return;
|
||||
if (!getTileInfo(_tar.files()))
|
||||
return;
|
||||
_imgPath = QString();
|
||||
} else {
|
||||
QDir set(fi.absolutePath() + "/" + "set");
|
||||
if (set.exists()) {
|
||||
if (!totalSizeSet())
|
||||
if (!setTileInfo(set.entryList(), set.absolutePath()))
|
||||
return;
|
||||
if (!getTileInfo(set.entryList(), set.absolutePath()))
|
||||
return;
|
||||
_imgPath = QString();
|
||||
} else {
|
||||
if (!getImageInfo(fi.absolutePath()))
|
||||
if (!setImageInfo(fi.absolutePath()))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_inverted = _transform.inverted();
|
||||
computeResolution();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
: Map(parent)
|
||||
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
MapFile mf;
|
||||
|
||||
_valid = false;
|
||||
_img = 0;
|
||||
_resolution = 0.0;
|
||||
_zoom = 0;
|
||||
_scale = QPointF(1.0, 1.0);
|
||||
|
||||
QFileInfo map(fi.absolutePath());
|
||||
QFileInfo layer(map.absolutePath());
|
||||
@ -224,38 +197,40 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
}
|
||||
|
||||
_name = mf.name();
|
||||
_size = mf.size();
|
||||
_map.size = mf.size();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
|
||||
_inverted = _transform.inverted();
|
||||
computeResolution();
|
||||
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
|
||||
|
||||
_tarPath = fi.absolutePath() + "/" + fi.completeBaseName() + ".tar";
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
OfflineMap::~OfflineMap()
|
||||
{
|
||||
delete _img;
|
||||
delete _tar;
|
||||
delete _ozf;
|
||||
}
|
||||
|
||||
void OfflineMap::load()
|
||||
{
|
||||
if (!_tarPath.isNull() && !_tileSize.isValid()) {
|
||||
if (!_tar.load(_tarPath)) {
|
||||
qWarning("%s: error loading tar file", qPrintable(_tarPath));
|
||||
if (_tar && !_tar->isOpen()) {
|
||||
if (!_tar->open()) {
|
||||
qWarning("%s: error loading tar file",
|
||||
qPrintable(_tar->fileName()));
|
||||
return;
|
||||
}
|
||||
if (!getTileInfo(_tar.files()))
|
||||
qWarning("%s: %s", qPrintable(_tarPath), qPrintable(_errorString));
|
||||
if (!setTileInfo(_tar->files()))
|
||||
qWarning("%s: %s", qPrintable(_tar->fileName()),
|
||||
qPrintable(_errorString));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_img && !_imgPath.isNull() && !_ozf.isOpen()) {
|
||||
_img = new QImage(_imgPath);
|
||||
if (!_ozf && !_img && _map.isValid()) {
|
||||
_img = new QImage(_map.path);
|
||||
if (_img->isNull())
|
||||
qWarning("%s: error loading map image", qPrintable(_imgPath));
|
||||
qWarning("%s: error loading map image", qPrintable(_map.path));
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,26 +240,26 @@ void OfflineMap::unload()
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
|
||||
void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const
|
||||
{
|
||||
QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tileSize.width())
|
||||
* _tileSize.width(), (int)floor(rect.top() / _tileSize.height())
|
||||
* _tileSize.height());
|
||||
QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tile.size.width())
|
||||
* _tile.size.width(), (int)floor(rect.top() / _tile.size.height())
|
||||
* _tile.size.height());
|
||||
|
||||
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
|
||||
for (int i = 0; i < ceil(s.width() / _tileSize.width()); i++) {
|
||||
for (int j = 0; j < ceil(s.height() / _tileSize.height()); j++) {
|
||||
int x = tl.x() + i * _tileSize.width();
|
||||
int y = tl.y() + j * _tileSize.height();
|
||||
for (int i = 0; i < ceil(s.width() / _tile.size.width()); i++) {
|
||||
for (int j = 0; j < ceil(s.height() / _tile.size.height()); j++) {
|
||||
int x = tl.x() + i * _tile.size.width();
|
||||
int y = tl.y() + j * _tile.size.height();
|
||||
|
||||
QString tileName(_tileName.arg(QString::number(x),
|
||||
QString tileName(_tile.path.arg(QString::number(x),
|
||||
QString::number(y)));
|
||||
QPixmap pixmap;
|
||||
|
||||
if (_tar.isOpen()) {
|
||||
QString key = _tar.fileName() + "/" + tileName;
|
||||
if (_tar) {
|
||||
QString key = _tar->fileName() + "/" + tileName;
|
||||
if (!QPixmapCache::find(key, &pixmap)) {
|
||||
QByteArray ba = _tar.file(tileName);
|
||||
QByteArray ba = _tar->file(tileName);
|
||||
pixmap = QPixmap::fromImage(QImage::fromData(ba));
|
||||
if (!pixmap.isNull())
|
||||
QPixmapCache::insert(key, pixmap);
|
||||
@ -294,8 +269,8 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
|
||||
|
||||
if (pixmap.isNull()) {
|
||||
qWarning("%s: error loading tile image", qPrintable(
|
||||
_tileName.arg(QString::number(x), QString::number(y))));
|
||||
painter->fillRect(QRectF(QPoint(x, y), _tileSize),
|
||||
_tile.path.arg(QString::number(x), QString::number(y))));
|
||||
painter->fillRect(QRectF(QPoint(x, y), _tile.size),
|
||||
_backgroundColor);
|
||||
} else
|
||||
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||
@ -303,30 +278,30 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
|
||||
}
|
||||
}
|
||||
|
||||
void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect)
|
||||
void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const
|
||||
{
|
||||
QPoint tl = QPoint((int)floor(rect.left() / _ozf.tileSize().width())
|
||||
* _ozf.tileSize().width(), (int)floor(rect.top()
|
||||
/ _ozf.tileSize().height()) * _ozf.tileSize().height());
|
||||
QPoint tl = QPoint((int)floor(rect.left() / _ozf->tileSize().width())
|
||||
* _ozf->tileSize().width(), (int)floor(rect.top()
|
||||
/ _ozf->tileSize().height()) * _ozf->tileSize().height());
|
||||
|
||||
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
|
||||
for (int i = 0; i < ceil(s.width() / _ozf.tileSize().width()); i++) {
|
||||
for (int j = 0; j < ceil(s.height() / _ozf.tileSize().height()); j++) {
|
||||
int x = tl.x() + i * _ozf.tileSize().width();
|
||||
int y = tl.y() + j * _ozf.tileSize().height();
|
||||
for (int i = 0; i < ceil(s.width() / _ozf->tileSize().width()); i++) {
|
||||
for (int j = 0; j < ceil(s.height() / _ozf->tileSize().height()); j++) {
|
||||
int x = tl.x() + i * _ozf->tileSize().width();
|
||||
int y = tl.y() + j * _ozf->tileSize().height();
|
||||
|
||||
QPixmap pixmap;
|
||||
QString key = _ozf.fileName() + "/" + QString::number(_zoom) + "_"
|
||||
QString key = _ozf->fileName() + "/" + QString::number(_zoom) + "_"
|
||||
+ QString::number(x) + "_" + QString::number(y);
|
||||
if (!QPixmapCache::find(key, &pixmap)) {
|
||||
pixmap = _ozf.tile(_zoom, x, y);
|
||||
pixmap = _ozf->tile(_zoom, x, y);
|
||||
if (!pixmap.isNull())
|
||||
QPixmapCache::insert(key, pixmap);
|
||||
}
|
||||
|
||||
if (pixmap.isNull()) {
|
||||
qWarning("%s: error loading tile image", qPrintable(key));
|
||||
painter->fillRect(QRectF(QPoint(x, y), _ozf.tileSize()),
|
||||
painter->fillRect(QRectF(QPoint(x, y), _ozf->tileSize()),
|
||||
_backgroundColor);
|
||||
} else
|
||||
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||
@ -334,7 +309,7 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect)
|
||||
}
|
||||
}
|
||||
|
||||
void OfflineMap::drawImage(QPainter *painter, const QRectF &rect)
|
||||
void OfflineMap::drawImage(QPainter *painter, const QRectF &rect) const
|
||||
{
|
||||
QRect r(rect.toRect());
|
||||
painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(),
|
||||
@ -343,9 +318,9 @@ void OfflineMap::drawImage(QPainter *painter, const QRectF &rect)
|
||||
|
||||
void OfflineMap::draw(QPainter *painter, const QRectF &rect)
|
||||
{
|
||||
if (_ozf.isOpen())
|
||||
if (_ozf)
|
||||
drawOZF(painter, rect);
|
||||
else if (_tileSize.isValid())
|
||||
else if (_tile.isValid())
|
||||
drawTiled(painter, rect);
|
||||
else if (_img && !_img->isNull())
|
||||
drawImage(painter, rect);
|
||||
@ -353,18 +328,18 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect)
|
||||
painter->fillRect(rect, _backgroundColor);
|
||||
}
|
||||
|
||||
QPointF OfflineMap::ll2xy(const Coordinates &c)
|
||||
QPointF OfflineMap::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
if (_ozf.isOpen()) {
|
||||
if (_ozf) {
|
||||
QPointF p(_transform.map(_projection.ll2xy(c)));
|
||||
return QPointF(p.x() * _scale.x(), p.y() * _scale.y());
|
||||
} else
|
||||
return _transform.map(_projection.ll2xy(c));
|
||||
}
|
||||
|
||||
Coordinates OfflineMap::xy2ll(const QPointF &p)
|
||||
Coordinates OfflineMap::xy2ll(const QPointF &p) const
|
||||
{
|
||||
if (_ozf.isOpen()) {
|
||||
if (_ozf) {
|
||||
return _projection.xy2ll(_inverted.map(QPointF(p.x() / _scale.x(),
|
||||
p.y() / _scale.y())));
|
||||
} else
|
||||
@ -373,25 +348,26 @@ Coordinates OfflineMap::xy2ll(const QPointF &p)
|
||||
|
||||
QRectF OfflineMap::bounds() const
|
||||
{
|
||||
if (_ozf.isOpen())
|
||||
return QRectF(QPointF(0, 0), _ozf.size(_zoom));
|
||||
if (_ozf)
|
||||
return QRectF(QPointF(0, 0), _ozf->size(_zoom));
|
||||
else
|
||||
return QRectF(QPointF(0, 0), _size);
|
||||
return QRectF(QPointF(0, 0), _map.size);
|
||||
}
|
||||
|
||||
qreal OfflineMap::resolution(const QPointF &p) const
|
||||
qreal OfflineMap::resolution(const QRectF &rect) const
|
||||
{
|
||||
Q_UNUSED(p);
|
||||
Coordinates tl = xy2ll((rect.topLeft()));
|
||||
Coordinates br = xy2ll(rect.bottomRight());
|
||||
|
||||
if (_ozf.isOpen())
|
||||
return _resolution / ((_scale.x() + _scale.y()) / 2.0);
|
||||
else
|
||||
return _resolution;
|
||||
qreal ds = tl.distanceTo(br);
|
||||
qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
|
||||
|
||||
return ds/ps;
|
||||
}
|
||||
|
||||
qreal OfflineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
int OfflineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
{
|
||||
if (_ozf.isOpen()) {
|
||||
if (_ozf) {
|
||||
if (!br.isValid())
|
||||
rescale(0);
|
||||
else {
|
||||
@ -399,7 +375,7 @@ qreal OfflineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
_transform.map(_projection.ll2xy(br.bottomRight())))
|
||||
.toRect().normalized());
|
||||
|
||||
for (int i = 0; i < _ozf.zooms(); i++) {
|
||||
for (int i = 0; i < _ozf->zooms(); i++) {
|
||||
rescale(i);
|
||||
if (sbr.size().width() * _scale.x() <= size.width()
|
||||
&& sbr.size().height() * _scale.y() <= size.height())
|
||||
@ -411,34 +387,18 @@ qreal OfflineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OfflineMap::zoomFit(qreal resolution, const Coordinates &c)
|
||||
int OfflineMap::zoomIn()
|
||||
{
|
||||
Q_UNUSED(c);
|
||||
|
||||
if (_ozf.isOpen()) {
|
||||
for (int i = 0; i < _ozf.zooms(); i++) {
|
||||
rescale(i);
|
||||
qreal sr = _resolution / ((_scale.x() + _scale.y()) / 2.0);
|
||||
if (sr >= resolution)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OfflineMap::zoomIn()
|
||||
{
|
||||
if (_ozf.isOpen())
|
||||
if (_ozf)
|
||||
rescale(qMax(_zoom - 1, 0));
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OfflineMap::zoomOut()
|
||||
int OfflineMap::zoomOut()
|
||||
{
|
||||
if (_ozf.isOpen())
|
||||
rescale(qMin(_zoom + 1, _ozf.zooms() - 1));
|
||||
if (_ozf)
|
||||
rescale(qMin(_zoom + 1, _ozf->zooms() - 1));
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
@ -446,7 +406,5 @@ qreal OfflineMap::zoomOut()
|
||||
void OfflineMap::rescale(int zoom)
|
||||
{
|
||||
_zoom = zoom;
|
||||
_scale = QPointF(
|
||||
(qreal)_ozf.size(_zoom).width() / (qreal)_ozf.size(0).width(),
|
||||
(qreal)_ozf.size(_zoom).height() / (qreal)_ozf.size(0).height());
|
||||
_scale = _ozf->scale(zoom);
|
||||
}
|
||||
|
@ -3,13 +3,10 @@
|
||||
|
||||
#include <QTransform>
|
||||
#include "projection.h"
|
||||
#include "transform.h"
|
||||
#include "linearunits.h"
|
||||
#include "map.h"
|
||||
#include "tar.h"
|
||||
#include "ozf.h"
|
||||
|
||||
class QIODevice;
|
||||
class Tar;
|
||||
class OZF;
|
||||
class QImage;
|
||||
|
||||
class OfflineMap : public Map
|
||||
@ -24,16 +21,17 @@ public:
|
||||
const QString &name() const {return _name;}
|
||||
|
||||
QRectF bounds() const;
|
||||
qreal resolution(const QPointF &p) const;
|
||||
qreal resolution(const QRectF &rect) const;
|
||||
|
||||
qreal zoom() const {return _zoom;}
|
||||
qreal zoomFit(const QSize &size, const RectC &br);
|
||||
qreal zoomFit(qreal resolution, const Coordinates &c);
|
||||
qreal zoomIn();
|
||||
qreal zoomOut();
|
||||
int zoom() const {return _zoom;}
|
||||
int zoomFit(const QSize &size, const RectC &br);
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
QPointF ll2xy(const Coordinates &c)
|
||||
{return static_cast<const OfflineMap &>(*this).ll2xy(c);}
|
||||
Coordinates xy2ll(const QPointF &p)
|
||||
{return static_cast<const OfflineMap &>(*this).xy2ll(p);}
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect);
|
||||
|
||||
@ -41,7 +39,7 @@ public:
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
QPointF ll2pp(const Coordinates &c) const
|
||||
{return _projection.ll2xy(c);}
|
||||
@ -51,15 +49,23 @@ public:
|
||||
{return _transform.map(p);}
|
||||
|
||||
private:
|
||||
bool getTileInfo(const QStringList &tiles, const QString &path = QString());
|
||||
bool getImageInfo(const QString &path);
|
||||
bool totalSizeSet();
|
||||
struct ImageInfo {
|
||||
QSize size;
|
||||
QString path;
|
||||
|
||||
void drawTiled(QPainter *painter, const QRectF &rect);
|
||||
void drawOZF(QPainter *painter, const QRectF &rect);
|
||||
void drawImage(QPainter *painter, const QRectF &rect);
|
||||
bool isValid() const {return size.isValid() && !path.isEmpty();}
|
||||
};
|
||||
|
||||
QPointF ll2xy(const Coordinates &c) const;
|
||||
Coordinates xy2ll(const QPointF &p) const;
|
||||
|
||||
bool setTileInfo(const QStringList &tiles, const QString &path = QString());
|
||||
bool setImageInfo(const QString &path);
|
||||
|
||||
void drawTiled(QPainter *painter, const QRectF &rect) const;
|
||||
void drawOZF(QPainter *painter, const QRectF &rect) const;
|
||||
void drawImage(QPainter *painter, const QRectF &rect) const;
|
||||
|
||||
void computeResolution();
|
||||
void rescale(int zoom);
|
||||
|
||||
QString _name;
|
||||
@ -67,17 +73,12 @@ private:
|
||||
Projection _projection;
|
||||
QTransform _transform, _inverted;
|
||||
|
||||
OZF _ozf;
|
||||
Tar _tar;
|
||||
QString _tarPath;
|
||||
QImage *_img;
|
||||
QString _imgPath;
|
||||
QSize _tileSize;
|
||||
QString _tileName;
|
||||
QSize _size;
|
||||
Tar *_tar;
|
||||
OZF *_ozf;
|
||||
ImageInfo _map, _tile;
|
||||
|
||||
int _zoom;
|
||||
qreal _resolution;
|
||||
QPointF _scale;
|
||||
|
||||
bool _valid;
|
||||
|
@ -1,10 +1,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QPainter>
|
||||
#include "common/coordinates.h"
|
||||
#include "common/rectc.h"
|
||||
#include "common/wgs84.h"
|
||||
#include "mercator.h"
|
||||
#include "downloader.h"
|
||||
#include "config.h"
|
||||
#include "onlinemap.h"
|
||||
@ -12,6 +9,16 @@
|
||||
|
||||
#define TILE_SIZE 256
|
||||
|
||||
static QPointF ll2m(const Coordinates &c)
|
||||
{
|
||||
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
|
||||
}
|
||||
|
||||
static Coordinates m2ll(const QPointF &p)
|
||||
{
|
||||
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
|
||||
}
|
||||
|
||||
static QPoint mercator2tile(const QPointF &m, int z)
|
||||
{
|
||||
QPoint tile;
|
||||
@ -32,45 +39,35 @@ static int scale2zoom(qreal scale)
|
||||
return (int)log2(360.0/(scale * (qreal)TILE_SIZE));
|
||||
}
|
||||
|
||||
static bool loadTileFile(Tile &tile, const QString &file)
|
||||
{
|
||||
if (!tile.pixmap().load(file)) {
|
||||
qWarning("%s: error loading tile file\n", qPrintable(file));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Downloader *OnlineMap::downloader;
|
||||
|
||||
OnlineMap::OnlineMap(const QString &name, const QString &url,
|
||||
const Range &zooms, const RectC &bounds, QObject *parent)
|
||||
: Map(parent), _name(name), _url(url), _zooms(zooms), _bounds(bounds)
|
||||
const Range &zooms, const RectC &bounds, QObject *parent) :
|
||||
Map(parent), _name(name), _zooms(zooms), _bounds(bounds),
|
||||
_block(false), _valid(false)
|
||||
{
|
||||
_block = false;
|
||||
_zoom = _zooms.max();
|
||||
QString dir(TILES_DIR + "/" + _name);
|
||||
|
||||
QString path = TILES_DIR + QString("/") + name;
|
||||
if (!QDir().mkpath(path))
|
||||
qWarning("Error creating tiles dir: %s\n", qPrintable(path));
|
||||
_zoom = _zooms.max();
|
||||
_tileLoader = TileLoader(url, dir);
|
||||
|
||||
if (!QDir().mkpath(dir)) {
|
||||
_errorString = "Error creating tiles dir";
|
||||
return;
|
||||
}
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void OnlineMap::load()
|
||||
{
|
||||
connect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded()));
|
||||
connect(TileLoader::downloader(), SIGNAL(finished()), this,
|
||||
SLOT(emitLoaded()));
|
||||
}
|
||||
|
||||
void OnlineMap::unload()
|
||||
{
|
||||
disconnect(downloader, SIGNAL(finished()), this, SLOT(emitLoaded()));
|
||||
}
|
||||
|
||||
void OnlineMap::fillTile(Tile &tile)
|
||||
{
|
||||
tile.pixmap() = QPixmap(TILE_SIZE, TILE_SIZE);
|
||||
tile.pixmap().fill(_backgroundColor);
|
||||
disconnect(TileLoader::downloader(), SIGNAL(finished()), this,
|
||||
SLOT(emitLoaded()));
|
||||
}
|
||||
|
||||
void OnlineMap::emitLoaded()
|
||||
@ -78,91 +75,6 @@ void OnlineMap::emitLoaded()
|
||||
emit loaded();
|
||||
}
|
||||
|
||||
void OnlineMap::loadTilesAsync(QList<Tile> &list)
|
||||
{
|
||||
QList<Download> dl;
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Tile &t = list[i];
|
||||
QString file = tileFile(t);
|
||||
QFileInfo fi(file);
|
||||
|
||||
if (!fi.exists()) {
|
||||
fillTile(t);
|
||||
dl.append(Download(tileUrl(t), file));
|
||||
} else
|
||||
loadTileFile(t, file);
|
||||
}
|
||||
|
||||
if (!dl.empty())
|
||||
downloader->get(dl);
|
||||
}
|
||||
|
||||
void OnlineMap::loadTilesSync(QList<Tile> &list)
|
||||
{
|
||||
QList<Download> dl;
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Tile &t = list[i];
|
||||
QString file = tileFile(t);
|
||||
QFileInfo fi(file);
|
||||
|
||||
if (!fi.exists())
|
||||
dl.append(Download(tileUrl(t), file));
|
||||
else
|
||||
loadTileFile(t, file);
|
||||
}
|
||||
|
||||
if (dl.empty())
|
||||
return;
|
||||
|
||||
QEventLoop wait;
|
||||
connect(downloader, SIGNAL(finished()), &wait, SLOT(quit()));
|
||||
if (downloader->get(dl))
|
||||
wait.exec();
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Tile &t = list[i];
|
||||
|
||||
if (t.pixmap().isNull()) {
|
||||
QString file = tileFile(t);
|
||||
QFileInfo fi(file);
|
||||
|
||||
if (!(fi.exists() && loadTileFile(t, file)))
|
||||
fillTile(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString OnlineMap::tileUrl(const Tile &tile) const
|
||||
{
|
||||
QString url(_url);
|
||||
|
||||
url.replace("$z", QString::number(tile.zoom()));
|
||||
url.replace("$x", QString::number(tile.xy().x()));
|
||||
url.replace("$y", QString::number(tile.xy().y()));
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
QString OnlineMap::tileFile(const Tile &tile) const
|
||||
{
|
||||
QString file = TILES_DIR + QString("/%1/%2-%3-%4").arg(name())
|
||||
.arg(tile.zoom()).arg(tile.xy().x()).arg(tile.xy().y());
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
void OnlineMap::clearCache()
|
||||
{
|
||||
QString path = TILES_DIR + QString("/") + name();
|
||||
QDir dir = QDir(path);
|
||||
QStringList list = dir.entryList();
|
||||
|
||||
for (int i = 0; i < list.count(); i++)
|
||||
dir.remove(list.at(i));
|
||||
}
|
||||
|
||||
QRectF OnlineMap::bounds() const
|
||||
{
|
||||
return QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight()));
|
||||
@ -178,13 +90,12 @@ int OnlineMap::limitZoom(int zoom) const
|
||||
return zoom;
|
||||
}
|
||||
|
||||
qreal OnlineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
int OnlineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
{
|
||||
if (!br.isValid())
|
||||
_zoom = _zooms.max();
|
||||
else {
|
||||
QRectF tbr(Mercator().ll2xy(br.topLeft()),
|
||||
Mercator().ll2xy(br.bottomRight()));
|
||||
QRectF tbr(ll2m(br.topLeft()), ll2m(br.bottomRight()));
|
||||
QPointF sc(tbr.width() / size.width(), tbr.height() / size.height());
|
||||
|
||||
_zoom = limitZoom(scale2zoom(qMax(sc.x(), sc.y())));
|
||||
@ -193,29 +104,21 @@ qreal OnlineMap::zoomFit(const QSize &size, const RectC &br)
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OnlineMap::zoomFit(qreal resolution, const Coordinates &c)
|
||||
{
|
||||
_zoom = limitZoom((int)log2((WGS84_RADIUS * 2.0 * M_PI
|
||||
* cos(deg2rad(c.lat()))) / (resolution * TILE_SIZE)));
|
||||
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OnlineMap::resolution(const QPointF &p) const
|
||||
qreal OnlineMap::resolution(const QRectF &rect) const
|
||||
{
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
|
||||
return (WGS84_RADIUS * 2.0 * M_PI * scale / 360.0
|
||||
* cos(2.0 * atan(exp(deg2rad(-p.y() * scale))) - M_PI/2));
|
||||
* cos(2.0 * atan(exp(deg2rad(-rect.center().y() * scale))) - M_PI/2));
|
||||
}
|
||||
|
||||
qreal OnlineMap::zoomIn()
|
||||
int OnlineMap::zoomIn()
|
||||
{
|
||||
_zoom = qMin(_zoom + 1, _zooms.max());
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
qreal OnlineMap::zoomOut()
|
||||
int OnlineMap::zoomOut()
|
||||
{
|
||||
_zoom = qMax(_zoom - 1, _zooms.min());
|
||||
return _zoom;
|
||||
@ -237,28 +140,31 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect)
|
||||
tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom));
|
||||
|
||||
if (_block)
|
||||
loadTilesSync(tiles);
|
||||
_tileLoader.loadTilesSync(tiles);
|
||||
else
|
||||
loadTilesAsync(tiles);
|
||||
_tileLoader.loadTilesAsync(tiles);
|
||||
|
||||
for (int i = 0; i < tiles.count(); i++) {
|
||||
Tile &t = tiles[i];
|
||||
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE,
|
||||
tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE);
|
||||
painter->drawPixmap(tp, t.pixmap());
|
||||
if (t.pixmap().isNull())
|
||||
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
|
||||
_backgroundColor);
|
||||
else
|
||||
painter->drawPixmap(tp, t.pixmap());
|
||||
}
|
||||
}
|
||||
|
||||
QPointF OnlineMap::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
QPointF m = Mercator().ll2xy(c);
|
||||
QPointF m = ll2m(c);
|
||||
return QPointF(m.x() / scale, m.y() / -scale);
|
||||
}
|
||||
|
||||
Coordinates OnlineMap::xy2ll(const QPointF &p) const
|
||||
{
|
||||
qreal scale = zoom2scale(_zoom);
|
||||
QPointF m(p.x() * scale, -p.y() * scale);
|
||||
return Mercator().xy2ll(m);
|
||||
return m2ll(QPointF(p.x() * scale, -p.y() * scale));
|
||||
}
|
||||
|
@ -1,13 +1,10 @@
|
||||
#ifndef ONLINEMAP_H
|
||||
#define ONLINEMAP_H
|
||||
|
||||
#include "common/coordinates.h"
|
||||
#include "common/range.h"
|
||||
#include "common/rectc.h"
|
||||
#include "map.h"
|
||||
#include "tile.h"
|
||||
|
||||
class Downloader;
|
||||
#include "tileloader.h"
|
||||
|
||||
class OnlineMap : public Map
|
||||
{
|
||||
@ -20,13 +17,12 @@ public:
|
||||
const QString &name() const {return _name;}
|
||||
|
||||
QRectF bounds() const;
|
||||
qreal resolution(const QPointF &p) const;
|
||||
qreal resolution(const QRectF &rect) const;
|
||||
|
||||
qreal zoom() const {return _zoom;}
|
||||
qreal zoomFit(const QSize &size, const RectC &br);
|
||||
qreal zoomFit(qreal resolution, const Coordinates &c);
|
||||
qreal zoomIn();
|
||||
qreal zoomOut();
|
||||
int zoom() const {return _zoom;}
|
||||
int zoomFit(const QSize &size, const RectC &br);
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
QPointF ll2xy(const Coordinates &c)
|
||||
{return static_cast<const OnlineMap &>(*this).ll2xy(c);}
|
||||
@ -36,36 +32,31 @@ public:
|
||||
void draw(QPainter *painter, const QRectF &rect);
|
||||
|
||||
void setBlockingMode(bool block) {_block = block;}
|
||||
void clearCache();
|
||||
|
||||
static void setDownloader(Downloader *downloader)
|
||||
{OnlineMap::downloader = downloader;}
|
||||
void clearCache() {_tileLoader.clearCache();}
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private slots:
|
||||
void emitLoaded();
|
||||
|
||||
private:
|
||||
QPointF ll2xy(const Coordinates &c) const;
|
||||
Coordinates xy2ll(const QPointF &p) const;
|
||||
|
||||
void fillTile(Tile &tile);
|
||||
QString tileUrl(const Tile &tile) const;
|
||||
QString tileFile(const Tile &tile) const;
|
||||
void loadTilesAsync(QList<Tile> &list);
|
||||
void loadTilesSync(QList<Tile> &list);
|
||||
int limitZoom(int zoom) const;
|
||||
|
||||
TileLoader _tileLoader;
|
||||
QString _name;
|
||||
QString _url;
|
||||
Range _zooms;
|
||||
RectC _bounds;
|
||||
int _zoom;
|
||||
bool _block;
|
||||
|
||||
static Downloader *downloader;
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // ONLINEMAP_H
|
||||
|
@ -185,12 +185,8 @@ bool OZF::readTileTable()
|
||||
return _zooms.isEmpty() ? false : true;
|
||||
}
|
||||
|
||||
bool OZF::load(const QString &path)
|
||||
bool OZF::open()
|
||||
{
|
||||
if (_file.isOpen())
|
||||
_file.close();
|
||||
|
||||
_file.setFileName(path);
|
||||
if (!_file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
@ -250,6 +246,12 @@ QSize OZF::size(int zoom) const
|
||||
return _zooms.at(zoom).size;
|
||||
}
|
||||
|
||||
QPointF OZF::scale(int zoom) const
|
||||
{
|
||||
return QPointF((qreal)size(zoom).width() / (qreal)size(0).width(),
|
||||
(qreal)size(zoom).height() / (qreal)size(0).height());
|
||||
}
|
||||
|
||||
bool OZF::isOZF(const QString &path)
|
||||
{
|
||||
QFile file(path);
|
||||
|
@ -12,15 +12,17 @@
|
||||
class OZF
|
||||
{
|
||||
public:
|
||||
OZF() : _tileSize(0), _decrypt(false), _key(0) {}
|
||||
OZF(const QString &name) : _tileSize(0), _decrypt(false), _key(0),
|
||||
_file(name) {}
|
||||
|
||||
bool load(const QString &path);
|
||||
bool open();
|
||||
|
||||
QString fileName() const {return _file.fileName();}
|
||||
bool isOpen() const {return _file.isOpen();}
|
||||
|
||||
int zooms() const {return _zooms.size();}
|
||||
QSize size(int zoom) const;
|
||||
QPointF scale(int zoom) const;
|
||||
QSize tileSize() const {return QSize(_tileSize, _tileSize);}
|
||||
QPixmap tile(int zoom, int x, int y);
|
||||
|
||||
|
@ -22,6 +22,7 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
{
|
||||
switch (key) {
|
||||
case 8801:
|
||||
case 8811:
|
||||
case 8821:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
@ -29,6 +30,7 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
setup.setLatitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8802:
|
||||
case 8812:
|
||||
case 8822:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
@ -36,9 +38,11 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
setup.setLongitudeOrigin(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8805:
|
||||
case 8815:
|
||||
setup.setScale(val);
|
||||
return true;
|
||||
case 8806:
|
||||
case 8816:
|
||||
case 8826:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
@ -46,18 +50,21 @@ static bool parameter(int key, double val, int units, Projection::Setup &setup)
|
||||
setup.setFalseEasting(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8807:
|
||||
case 8817:
|
||||
case 8827:
|
||||
{LinearUnits lu(units);
|
||||
if (lu.isNull())
|
||||
return false;
|
||||
setup.setFalseNorthing(lu.toMeters(val));}
|
||||
return true;
|
||||
case 8813:
|
||||
case 8823:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
return false;
|
||||
setup.setStandardParallel1(au.toDegrees(val));}
|
||||
return true;
|
||||
case 8814:
|
||||
case 8824:
|
||||
{AngularUnits au(units);
|
||||
if (au.isNull())
|
||||
@ -74,7 +81,7 @@ static int projectionSetup(const QList<QByteArray> &list,
|
||||
{
|
||||
bool r1, r2, r3;
|
||||
|
||||
for (int i = 6; i < 24; i += 3) {
|
||||
for (int i = 6; i < 27; i += 3) {
|
||||
QString ks = list[i].trimmed();
|
||||
if (ks.isEmpty())
|
||||
break;
|
||||
@ -129,7 +136,7 @@ void PCS::loadList(const QString &path)
|
||||
|
||||
QByteArray line = file.readLine();
|
||||
QList<QByteArray> list = line.split(',');
|
||||
if (list.size() != 24) {
|
||||
if (list.size() != 27) {
|
||||
qWarning("%s: %d: Format error", qPrintable(path), ln);
|
||||
continue;
|
||||
}
|
||||
@ -187,9 +194,11 @@ void PCS::loadList(const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PCS &pcs)
|
||||
{
|
||||
dbg.nospace() << "PCS(" << *pcs.gcs() << ", " << pcs.method() << ", "
|
||||
<< pcs.units() << ", " << pcs.setup() << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -40,9 +40,10 @@ private:
|
||||
LinearUnits _units;
|
||||
|
||||
static QList<Entry> _pcss;
|
||||
static GCS _nullGCS;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PCS &pcs);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // PCS_H
|
||||
|
@ -66,8 +66,10 @@ double PrimeMeridian::fromGreenwich(double val) const
|
||||
return shift(val, -_pm);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PrimeMeridian &pm)
|
||||
{
|
||||
dbg.nospace() << "PrimeMeridian(" << pm._pm << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -17,7 +17,9 @@ public:
|
||||
double fromGreenwich(double val) const;
|
||||
|
||||
friend bool operator==(const PrimeMeridian &pm1, const PrimeMeridian &pm2);
|
||||
#ifndef QT_NO_DEBUG
|
||||
friend QDebug operator<<(QDebug dbg, const PrimeMeridian &pm);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
private:
|
||||
double _pm;
|
||||
@ -26,6 +28,8 @@ private:
|
||||
inline bool operator==(const PrimeMeridian &pm1, const PrimeMeridian &pm2)
|
||||
{return (pm1._pm == pm2._pm);}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const PrimeMeridian &pm);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // PRIMEMERIDIAN_H
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user