1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-08 08:14:28 +02:00

Compare commits

..

62 Commits
7.6 ... 7.8

Author SHA1 Message Date
494a8a6da1 Fixed tick box size computation 2019-05-29 21:24:37 +02:00
47206316b7 Path tick distance now based on map resolution rather then path length. 2019-05-29 18:38:49 +02:00
fe69280cc5 Fixed broken zoom fit on IMG maps 2019-05-29 18:27:11 +02:00
ff3c0aafa1 Fixed memory leak 2019-05-29 18:26:29 +02:00
2fb2beecda Translated using Weblate (Czech)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2019-05-28 23:38:33 +02:00
432ca35df9 Merge branch 'origin/master' into Weblate. 2019-05-28 23:26:34 +02:00
301172f5e8 Added support for GPX 1.0 speed data 2019-05-28 23:26:03 +02:00
20956625db Enable hover in styles that use it 2019-05-28 23:22:58 +02:00
273fe51dcd Merge branch 'origin/master' into Weblate. 2019-05-28 07:29:26 +02:00
e4098e6dfb Version++ 2019-05-28 07:29:07 +02:00
747acf1580 Merge branch 'origin/master' into Weblate. 2019-05-28 07:27:55 +02:00
738b49668c Fixed broken WMS scale denominators -> zooms transition 2019-05-28 07:26:13 +02:00
48674bb50b Propper path tick tooltip
+ code cleanup
2019-05-28 07:24:39 +02:00
6d054c76f9 Translated using Weblate (German)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2019-05-25 12:52:19 +02:00
40578d0dee Merge branch 'origin/master' into Weblate. 2019-05-24 18:38:02 +02:00
a16354a6ba Propper reimplementation of the path ticks 2019-05-24 18:37:15 +02:00
44862cebcc Translated using Weblate (Turkish)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2019-05-24 18:10:46 +02:00
ef5cfde22b Translated using Weblate (Norwegian Bokmål)
Currently translated at 91.2% (312 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2019-05-24 10:46:33 +02:00
019bd4de10 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2019-05-24 10:46:32 +02:00
9c6ffed35e Translated using Weblate (Swedish)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2019-05-24 10:46:32 +02:00
d7a55b3f9c Translated using Weblate (Finnish)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2019-05-23 20:40:11 +02:00
a9327d2cca Translated using Weblate (Russian)
Currently translated at 100.0% (342 of 342 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2019-05-23 20:40:10 +02:00
c059cbb848 Merge branch 'origin/master' into Weblate. 2019-05-23 19:25:57 +02:00
3b3559eacf Localization update 2019-05-23 19:25:44 +02:00
f071e88bd0 Merge branch 'origin/master' into Weblate. 2019-05-23 19:19:32 +02:00
8bec307e03 km/mi markers polishing 2019-05-23 19:19:07 +02:00
3204723614 Merge branch 'origin/master' into Weblate. 2019-05-23 08:46:45 +02:00
c688b5fc09 Added optional km/mi markers
closes #84
2019-05-23 08:44:55 +02:00
94bca87982 Merge branch 'origin/master' into Weblate. 2019-05-21 18:00:03 +02:00
3f97d12a76 Code cleanup 2019-05-21 17:59:46 +02:00
ab7aa63a33 Merge branch 'origin/master' into Weblate. 2019-05-21 17:45:25 +02:00
4de22d6679 Fixed broken IMG maps after print/PDF export 2019-05-21 17:44:47 +02:00
c58a52e362 Merge branch 'origin/master' into Weblate. 2019-05-20 23:24:04 +02:00
5b2af9fc9c Added support for QuadTiles maps 2019-05-20 23:23:24 +02:00
4eb54ed8f2 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2019-05-20 05:48:41 +02:00
681c83d017 Version++ 2019-05-18 20:40:59 +02:00
dbd8750524 Updated appdata.xml info 2019-05-18 20:39:55 +02:00
d9489935df Translated using Weblate (German)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/de/
2019-05-18 15:27:12 +02:00
f5d2ccfdb9 Translated using Weblate (Swedish)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2019-05-18 07:11:35 +02:00
1afd59902b Translated using Weblate (Turkish)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2019-05-17 18:01:40 +02:00
a253147760 Translated using Weblate (Finnish)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2019-05-17 18:01:40 +02:00
667a1c350d Translated using Weblate (Norwegian Bokmål)
Currently translated at 91.5% (312 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2019-05-17 18:01:39 +02:00
d7a9464e37 Translated using Weblate (Czech)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/cs/
2019-05-17 18:01:38 +02:00
d1be147f64 Translated using Weblate (Russian)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2019-05-17 18:01:38 +02:00
98708f11ac Localization update 2019-05-16 22:52:39 +02:00
c5605eeab1 Translated using Weblate (Swedish)
Currently translated at 100.0% (340 of 340 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/sv/
2019-05-16 22:02:52 +02:00
f29ac69594 Translated using Weblate (Turkish)
Currently translated at 100.0% (340 of 340 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/tr/
2019-05-16 22:02:52 +02:00
49101cba6c Translated using Weblate (Finnish)
Currently translated at 100.0% (340 of 340 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2019-05-16 22:02:52 +02:00
c1f746b32a Translated using Weblate (Norwegian Bokmål)
Currently translated at 91.5% (311 of 340 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/nb_NO/
2019-05-16 22:02:52 +02:00
704be7baf9 Translated using Weblate (Russian)
Currently translated at 100.0% (340 of 340 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2019-05-16 22:02:52 +02:00
3c6ec704ab Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/pt_BR/
2019-05-16 22:02:52 +02:00
bf6b6fb100 Translated using Weblate (Finnish)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fi/
2019-05-16 22:02:52 +02:00
56a2618f29 Translated using Weblate (Russian)
Currently translated at 100.0% (341 of 341 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/ru/
2019-05-16 22:02:52 +02:00
785bf94a01 Added support for user defined TYP files for Garmin IMG maps 2019-05-16 20:23:37 +02:00
3747ae6afc Localization update 2019-05-15 21:36:01 +02:00
1f5a051bee Fixed broken text display in Qt < 5.4
(Qt bug workaround)
2019-05-15 21:29:34 +02:00
268c42ab03 Always limit the number of shown items in the combo box. 2019-05-15 20:33:03 +02:00
8a8595d98e Fixed Qt4 build 2019-05-15 07:47:57 +02:00
37c971a720 Added support for vector maps projection setting
Removed obsolete "Always show the map" setting
2019-05-14 23:01:24 +02:00
f0d71d667b Fixed builds with Qt 5 versions < 5.4 2019-05-12 21:26:45 +02:00
f652457f19 One Garmin is enough 2019-05-12 18:13:30 +02:00
1acf603076 Added Garmin IMG info 2019-05-12 18:04:04 +02:00
62 changed files with 3575 additions and 3092 deletions

View File

@ -1,4 +1,4 @@
version: 7.6.{build}
version: 7.8.{build}
configuration: Release
platform: Any CPU
environment:

View File

@ -4,7 +4,7 @@ GPXSee is a Qt-based GPS log file viewer and analyzer that supports all common G
## Features
* Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, GeoJSON, OziExplorer (PLT, RTE, WPT), Garmin CSV and geotagged JPEG files.
* User-definable online maps (OpenStreetMap/Google tiles, WMTS, WMS, TMS).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin JNX maps, TwoNav RMaps, GeoTIFF images).
* Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases, Garmin IMG & JNX maps, TwoNav RMaps, GeoTIFF images).
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
* Support for DEM files (SRTM HGT).
* Support for multiple tracks in one view.

View File

@ -3,7 +3,7 @@ unix:!macx {
} else {
TARGET = GPXSee
}
VERSION = 7.6
VERSION = 7.8
QT += core \
gui \
@ -177,7 +177,9 @@ HEADERS += src/common/config.h \
src/map/IMG/subdiv.h \
src/map/IMG/units.h \
src/map/IMG/style.h \
src/map/IMG/netfile.h
src/map/IMG/netfile.h \
src/GUI/limitedcombobox.h \
src/GUI/pathtickitem.h
SOURCES += src/main.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
@ -306,7 +308,8 @@ SOURCES += src/main.cpp \
src/map/IMG/lblfile.cpp \
src/map/IMG/vectortile.cpp \
src/map/IMG/style.cpp \
src/map/IMG/netfile.cpp
src/map/IMG/netfile.cpp \
src/GUI/pathtickitem.cpp
greaterThan(QT_MAJOR_VERSION, 4) {
HEADERS += src/data/geojsonparser.h
@ -388,7 +391,7 @@ win32 {
unix:!macx {
isEmpty(PREFIX):PREFIX = /usr/local
lessThan(QT_MAJOR_VERSION, 5) {DEFINES += PREFIX=\\\"$$PREFIX\\\"}
DEFINES += PREFIX=\\\"$$PREFIX\\\"
maps.files = pkg/maps/*
maps.path = $$PREFIX/share/gpxsee/maps

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,15 +7,17 @@
<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, NMEA, SLF, LOC, GeoJSON and OziExplorer files.</p>
<p>GPXSee is a GPS log file viewer and analyzer that supports all common
GPS log file formats.</p>
<p>Features:</p>
<ul>
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
WPT, RTE), GeoJSON, Garmin CSV and geotagged JPEG files.</li>
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
WMS, TMS).</li>
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
GeoTIFF images).</li>
TwoNav RMaps, Garmin IMG &amp; JNX, GeoTIFF images).</li>
<li>Elevation, speed, heart rate, cadence, power and temperature
graphs.</li>
<li>Support for multiple tracks in one view.</li>
@ -23,8 +25,6 @@
<li>Print/export to PDF.</li>
<li>Full-screen mode.</li>
<li>HiDPI/Retina displays &amp; maps support.</li>
<li>Opens GPX, TCX, FIT, KML, IGC, NMEA, SLF, LOC, OziExplorer (PLT,
WPT, RTE), GeoJSON and Garmin CSV files.</li>
</ul>
</description>

View File

@ -7,7 +7,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "7.6"
!define VERSION "7.8"
; The file to write
OutFile "GPXSee-${VERSION}.exe"

View File

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

View File

@ -29,8 +29,8 @@ private:
Ticks::Ticks(double minValue, double maxValue, int maxCount)
{
double range = niceNum(maxValue - minValue, 0);
_d = niceNum(range / maxCount, 1);
double range = niceNum(maxValue - minValue, false);
_d = niceNum(range / maxCount, true);
_min = ceil(minValue / _d) * _d;
_max = floor(maxValue / _d) * _d;
}

View File

@ -12,6 +12,7 @@ ColorBox::ColorBox(QWidget *parent) : QWidget(parent)
_alpha = true;
setSizePolicy(QSizePolicy::QSizePolicy::Minimum, QSizePolicy::Fixed);
setAttribute(Qt::WA_Hover);
}
QSize ColorBox::sizeHint() const

View File

@ -103,7 +103,6 @@ GUI::GUI()
readSettings();
updateGraphTabs();
updateMapView();
updateStatusBarInfo();
}
@ -350,6 +349,11 @@ void GUI::createActions()
_showRouteWaypointsAction->setCheckable(true);
connect(_showRouteWaypointsAction, SIGNAL(triggered(bool)), _mapView,
SLOT(showRouteWaypoints(bool)));
_showTicksAction = new QAction(tr("km/mi markers"), this);
_showTicksAction->setMenuRole(QAction::NoRole);
_showTicksAction->setCheckable(true);
connect(_showTicksAction, SIGNAL(triggered(bool)), _mapView,
SLOT(showTicks(bool)));
// Graph actions
_showGraphsAction = new QAction(QIcon(SHOW_GRAPHS_ICON), tr("Show graphs"),
@ -537,6 +541,7 @@ void GUI::createMenus()
QMenu *displayMenu = dataMenu->addMenu(tr("Display"));
displayMenu->addAction(_showWaypointLabelsAction);
displayMenu->addAction(_showRouteWaypointsAction);
displayMenu->addAction(_showTicksAction);
dataMenu->addSeparator();
dataMenu->addAction(_showTracksAction);
dataMenu->addAction(_showRoutesAction);
@ -725,6 +730,8 @@ void GUI::paths()
+ QDir::cleanPath(ProgramPaths::csvDir(true)) + "</code></td></tr><tr><td>"
+ tr("DEM directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::demDir(true)) + "</code></td></tr><tr><td>"
+ tr("Styles directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::styleDir(true)) + "</code></td></tr><tr><td>"
+ tr("Tile cache directory:") + "</td><td><code>"
+ QDir::cleanPath(ProgramPaths::tilesDir()) + "</code></td></tr></table>"
);
@ -805,7 +812,7 @@ bool GUI::loadFile(const QString &fileName)
for (int i = 0; i < _tabs.count(); i++)
graphs.append(_tabs.at(i)->loadData(data));
if (updateGraphTabs() | updateMapView())
if (updateGraphTabs())
_splitter->refresh();
paths = _mapView->loadData(data);
@ -828,7 +835,6 @@ bool GUI::loadFile(const QString &fileName)
updateStatusBarInfo();
updateWindowTitle();
updateGraphTabs();
updateMapView();
QString error = tr("Error loading data file:") + "\n\n"
+ fileName + "\n\n" + data.errorString();
@ -930,6 +936,7 @@ void GUI::openOptions()
SET_VIEW_OPTION(pathAntiAliasing, useAntiAliasing);
SET_VIEW_OPTION(useOpenGL, useOpenGL);
SET_VIEW_OPTION(sliderColor, setMarkerColor);
SET_VIEW_OPTION(projection, setProjection);
SET_TAB_OPTION(palette, setPalette);
SET_TAB_OPTION(graphWidth, setGraphWidth);
@ -974,8 +981,6 @@ void GUI::openOptions()
reloadFile();
_options = options;
updateMapView();
}
void GUI::printFile()
@ -1230,7 +1235,6 @@ void GUI::closeAll()
updateStatusBarInfo();
updateWindowTitle();
updateGraphTabs();
updateMapView();
}
void GUI::showGraphs(bool show)
@ -1473,19 +1477,6 @@ bool GUI::updateGraphTabs()
return (hidden != _graphTabWidget->isHidden());
}
bool GUI::updateMapView()
{
bool hidden = _mapView->isHidden();
if (_options.alwaysShowMap)
_mapView->setHidden(false);
else
_mapView->setHidden(!(_trackCount + _routeCount + _waypointCount
+ _areaCount));
return (hidden != _mapView->isHidden());
}
void GUI::setTimeType(TimeType type)
{
for (int i = 0; i <_tabs.count(); i++)
@ -1736,6 +1727,9 @@ void GUI::writeSettings()
if (_showRouteWaypointsAction->isChecked() != SHOW_ROUTE_WAYPOINTS_DEFAULT)
settings.setValue(SHOW_ROUTE_WAYPOINTS_SETTING,
_showRouteWaypointsAction->isChecked());
if (_showTicksAction->isChecked() != SHOW_TICKS_DEFAULT)
settings.setValue(SHOW_TICKS_SETTING,
_showTicksAction->isChecked());
settings.endGroup();
settings.beginGroup(EXPORT_SETTINGS_GROUP);
@ -1847,8 +1841,8 @@ void GUI::writeSettings()
_options.separateGraphPage);
if (_options.sliderColor != SLIDER_COLOR_DEFAULT)
settings.setValue(SLIDER_COLOR_SETTING, _options.sliderColor);
if (_options.alwaysShowMap != ALWAYS_SHOW_MAP_DEFAULT)
settings.setValue(ALWAYS_SHOW_MAP_SETTING, _options.alwaysShowMap);
if (_options.projection != PROJECTION_DEFAULT)
settings.setValue(PROJECTION_SETTING, _options.projection);
#ifdef ENABLE_HIDPI
if (_options.hidpiMap != HIDPI_MAP_DEFAULT)
settings.setValue(HIDPI_MAP_SETTING, _options.hidpiMap);
@ -1999,6 +1993,10 @@ void GUI::readSettings()
_mapView->showRouteWaypoints(false);
else
_showRouteWaypointsAction->setChecked(true);
if (settings.value(SHOW_TICKS_SETTING, SHOW_TICKS_DEFAULT).toBool()) {
_mapView->showTicks(true);
_showTicksAction->setChecked(true);
}
settings.endGroup();
settings.beginGroup(EXPORT_SETTINGS_GROUP);
@ -2110,8 +2108,8 @@ void GUI::readSettings()
SEPARATE_GRAPH_PAGE_DEFAULT).toBool();
_options.sliderColor = settings.value(SLIDER_COLOR_SETTING,
SLIDER_COLOR_DEFAULT).value<QColor>();
_options.alwaysShowMap = settings.value(ALWAYS_SHOW_MAP_SETTING,
ALWAYS_SHOW_MAP_DEFAULT).toBool();
_options.projection = settings.value(PROJECTION_SETTING, PROJECTION_DEFAULT)
.toInt();
#ifdef ENABLE_HIDPI
_options.hidpiMap = settings.value(HIDPI_MAP_SETTING, HIDPI_MAP_SETTING)
.toBool();
@ -2139,6 +2137,7 @@ void GUI::readSettings()
_mapView->setDevicePixelRatio(devicePixelRatioF(),
_options.hidpiMap ? devicePixelRatioF() : 1.0);
#endif // ENABLE_HIDPI
_mapView->setProjection(_options.projection);
for (int i = 0; i < _tabs.count(); i++) {
_tabs.at(i)->setPalette(_options.palette);

View File

@ -116,7 +116,6 @@ private:
void updateWindowTitle();
void updateNavigationActions();
bool updateGraphTabs();
bool updateMapView();
TimeType timeType() const;
Units units() const;
@ -193,6 +192,7 @@ private:
QAction *_showAreasAction;
QAction *_showRouteWaypointsAction;
QAction *_showMarkersAction;
QAction *_showTicksAction;
QAction *_showCoordinatesAction;
QAction *_openOptionsAction;
QAction *_mapsEnd;

39
src/GUI/limitedcombobox.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef LIMITEDCOMBOBOX_H
#define LIMITEDCOMBOBOX_H
#include <QComboBox>
#include <QEvent>
class LimitedComboBox : public QComboBox
{
public:
LimitedComboBox(int limit, QWidget *parent = 0)
: QComboBox(parent), _limit(limit)
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setStyleSheet("combobox-popup: 0;");
}
QSize sizeHint() const
{
return QSize(qMin(_limit, QComboBox::sizeHint().width()),
QComboBox::sizeHint().height());
}
QSize minimumSizeHint() const
{
return QSize(qMin(_limit, QComboBox::minimumSizeHint().width()),
QComboBox::minimumSizeHint().height());
}
bool event(QEvent *e)
{
if (e->type() == QEvent::Polish)
view()->setMinimumWidth(QComboBox::sizeHint().width());
return QComboBox::event(e);
}
private:
int _limit;
};
#endif // LIMITEDCOMBOBOX_H

View File

@ -7,6 +7,7 @@
#include "data/poi.h"
#include "data/data.h"
#include "map/map.h"
#include "map/pcs.h"
#include "opengl.h"
#include "trackitem.h"
#include "routeitem.h"
@ -48,8 +49,10 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_coordinates->setVisible(false);
_scene->addItem(_coordinates);
_projection = PCS::pcs(3857);
_map = map;
_map->load();
_map->setProjection(_projection);
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
_poi = poi;
@ -72,6 +75,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
_overlapPOIs = true;
_showRouteWaypoints = true;
_showMarkers = true;
_showPathTicks = false;
_trackWidth = 3;
_routeWidth = 3;
_trackStyle = Qt::SolidLine;
@ -122,6 +126,7 @@ PathItem *MapView::addTrack(const Track &track)
ti->setDigitalZoom(_digitalZoom);
ti->setMarkerColor(_markerColor);
ti->showMarker(_showMarkers);
ti->showTicks(_showPathTicks);
_scene->addItem(ti);
if (_showTracks)
@ -151,6 +156,7 @@ PathItem *MapView::addRoute(const Route &route)
ri->setDigitalZoom(_digitalZoom);
ri->setMarkerColor(_markerColor);
ri->showMarker(_showMarkers);
ri->showTicks(_showPathTicks);
_scene->addItem(ri);
if (_showRoutes)
@ -312,6 +318,7 @@ void MapView::setMap(Map *map)
_map = map;
_map->load();
_map->setProjection(_projection);
#ifdef ENABLE_HIDPI
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
#endif // ENABLE_HIDPI
@ -720,6 +727,15 @@ void MapView::showMarkers(bool show)
_routes.at(i)->showMarker(show);
}
void MapView::showTicks(bool show)
{
_showPathTicks = show;
for (int i = 0; i < _tracks.size(); i++)
_tracks.at(i)->showTicks(show);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->showTicks(show);
}
void MapView::showMap(bool show)
{
_showMap = show;
@ -1012,3 +1028,17 @@ void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
Q_UNUSED(mapRatio);
#endif // ENABLE_HIDPI
}
void MapView::setProjection(int id)
{
Projection projection(PCS::pcs(id));
if (!projection.isValid())
return;
_projection = projection;
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
_map->setProjection(_projection);
rescale();
centerOn(_map->ll2xy(center));
}

View File

@ -8,11 +8,13 @@
#include "common/rectc.h"
#include "common/config.h"
#include "data/waypoint.h"
#include "data/polygon.h"
#include "map/projection.h"
#include "searchpointer.h"
#include "units.h"
#include "format.h"
#include "palette.h"
#include "data/polygon.h"
class Data;
class POI;
@ -77,9 +79,11 @@ public slots:
void showRouteWaypoints(bool show);
void showMarkers(bool show);
void showCoordinates(bool show);
void showTicks(bool show);
void clearMapCache();
void setCoordinatesFormat(CoordinatesFormat format);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void setProjection(int id);
private slots:
void updatePOI();
@ -132,10 +136,11 @@ private:
Units _units;
CoordinatesFormat _coordinatesFormat;
qreal _mapOpacity;
Projection _projection;
bool _showMap, _showTracks, _showRoutes, _showAreas, _showWaypoints,
_showWaypointLabels, _showPOI, _showPOILabels, _showRouteWaypoints,
_showMarkers;
_showMarkers, _showPathTicks;
bool _overlapPOIs;
int _trackWidth, _routeWidth, _areaWidth;
Qt::PenStyle _trackStyle, _routeStyle, _areaStyle;

View File

@ -12,11 +12,14 @@
#include <QRadioButton>
#include <QLabel>
#include <QSysInfo>
#include <QInputDialog>
#include "map/pcs.h"
#include "icons.h"
#include "colorbox.h"
#include "stylecombobox.h"
#include "oddspinbox.h"
#include "percentslider.h"
#include "limitedcombobox.h"
#include "optionsdialog.h"
@ -36,10 +39,15 @@ static QFrame *line()
QWidget *OptionsDialog::createMapPage()
{
_alwaysShowMap = new QCheckBox(tr("Always show the map"));
_alwaysShowMap->setChecked(_options->alwaysShowMap);
_alwaysShowMap->setToolTip("<p>" +
tr("Show the map even when no files are loaded.") + "</p>");
_projection = new LimitedComboBox(200);
QList<PCS::Info> projections(PCS::pcsList());
qSort(projections);
for (int i = 0; i < projections.size(); i++) {
QString text = QString::number(projections.at(i).id()) + " - "
+ projections.at(i).name();
_projection->addItem(text, QVariant(projections.at(i).id()));
}
_projection->setCurrentIndex(_projection->findData(_options->projection));
#ifdef ENABLE_HIDPI
_hidpi = new QRadioButton(tr("High-resolution"));
@ -60,14 +68,14 @@ QWidget *OptionsDialog::createMapPage()
llo->setFont(f);
#endif // ENABLE_HIDPI
QFormLayout *showMapLayout = new QFormLayout();
showMapLayout->addWidget(_alwaysShowMap);
QFormLayout *vectorLayout = new QFormLayout();
vectorLayout->addRow(tr("Projection:"), _projection);
QWidget *mapTab = new QWidget();
QVBoxLayout *mapTabLayout = new QVBoxLayout();
mapTabLayout->addLayout(showMapLayout);
mapTabLayout->addStretch();
mapTab->setLayout(mapTabLayout);
QWidget *vectorMapsTab = new QWidget();
QVBoxLayout *vectorMapsTabLayout = new QVBoxLayout();
vectorMapsTabLayout->addLayout(vectorLayout);
vectorMapsTabLayout->addStretch();
vectorMapsTab->setLayout(vectorMapsTabLayout);
#ifdef ENABLE_HIDPI
QVBoxLayout *hidpiTabLayout = new QVBoxLayout();
@ -83,7 +91,7 @@ QWidget *OptionsDialog::createMapPage()
#endif // ENABLE_HIDPI
QTabWidget *mapPage = new QTabWidget();
mapPage->addTab(mapTab, tr("General"));
mapPage->addTab(vectorMapsTab, tr("Vector maps"));
#ifdef ENABLE_HIDPI
mapPage->addTab(hidpiTab, tr("HiDPI display mode"));
#endif // ENABLE_HIDPI
@ -261,6 +269,7 @@ QWidget *OptionsDialog::createAppearancePage()
_backgroundColor = new ColorBox();
_backgroundColor->setColor(_options->backgroundColor);
_backgroundColor->enableAlphaChannel(false);
QFormLayout *mapLayout = new QFormLayout();
mapLayout->addRow(tr("Background color:"), _backgroundColor);
mapLayout->addRow(tr("Map opacity:"), _mapOpacity);
@ -656,7 +665,8 @@ void OptionsDialog::accept()
_options->sliderColor = _sliderColor->color();
_options->graphAntiAliasing = _graphAA->isChecked();
_options->alwaysShowMap = _alwaysShowMap->isChecked();
_options->projection = _projection->itemData(_projection->currentIndex())
.toInt();
#ifdef ENABLE_HIDPI
_options->hidpiMap = _hidpi->isChecked();
#endif // ENABLE_HIDPI

View File

@ -15,6 +15,7 @@ class QComboBox;
class QCheckBox;
class QRadioButton;
class PercentSlider;
class LimitedComboBox;
struct Options {
// Appearance
@ -37,7 +38,7 @@ struct Options {
int mapOpacity;
QColor backgroundColor;
// Map
bool alwaysShowMap;
int projection;
#ifdef ENABLE_HIDPI
bool hidpiMap;
#endif // ENABLE_HIDPI
@ -79,11 +80,14 @@ class OptionsDialog : public QDialog
{
Q_OBJECT
public slots:
void accept();
public:
OptionsDialog(Options *options, QWidget *parent = 0);
public slots:
void accept();
//private slots:
// void projectionChanged(int index);
private:
QWidget *createMapPage();
@ -116,7 +120,7 @@ private:
ColorBox *_sliderColor;
QCheckBox *_graphAA;
// Map
QCheckBox *_alwaysShowMap;
LimitedComboBox *_projection;
#ifdef ENABLE_HIDPI
QRadioButton *_hidpi;
QRadioButton *_lodpi;

View File

@ -3,6 +3,7 @@
#include <QPainter>
#include "common/greatcircle.h"
#include "map/map.h"
#include "pathtickitem.h"
#include "pathitem.h"
@ -23,14 +24,17 @@ PathItem::PathItem(const Path &path, Map *map, QGraphicsItem *parent)
{
Q_ASSERT(_path.isValid());
_units = Metric;
_digitalZoom = 0;
_width = 3;
QBrush brush(Qt::SolidPattern);
_pen = QPen(brush, _width);
_showMarker = true;
_showTicks = false;
updatePainterPath();
updateShape();
updateTicks();
_markerDistance = _path.first().first().distance();
_marker = new MarkerItem(this);
@ -111,8 +115,7 @@ void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
painter->drawPath(_painterPath);
/*
QPen p = QPen(QBrush(Qt::red), 0);
painter->setPen(p);
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
*/
}
@ -125,6 +128,7 @@ void PathItem::setMap(Map *map)
updatePainterPath();
updateShape();
updateTicks();
QPointF pos = position(_markerDistance);
if (isValid(pos))
@ -284,6 +288,75 @@ void PathItem::showMarker(bool show)
_marker->setVisible(show && isValid(position(_markerDistance)));
}
qreal PathItem::xInM() const
{
return (_units == Nautical) ? NMIINM : (_units == Imperial) ? MIINM : KMINM;
}
unsigned PathItem::tickSize() const
{
qreal res = _map->resolution(sceneBoundingRect());
if (res < 10)
return 1;
else if (res < 25)
return 5;
else if (res < 100)
return 10;
else if (res < 500)
return 50;
else if (res < 2000)
return 100;
else if (res < 10000)
return 500;
else if (res < 20000)
return 1000;
else
return 5000;
}
void PathItem::updateTicks()
{
for (int i = 0; i < _ticks.size(); i++)
delete _ticks[i];
_ticks.clear();
if (!_showTicks)
return;
int ts = tickSize();
int tc = _path.last().last().distance() / (ts * xInM());
QRect tr = PathTickItem::tickRect(ts * tc);
_ticks.resize(tc);
for (int i = 0; i < tc; i++) {
_ticks[i] = new PathTickItem(tr, (i + 1) * ts, this);
_ticks[i]->setPos(position((i + 1) * ts * xInM()));
_ticks[i]->setColor(_pen.color());
_ticks[i]->setToolTip(toolTip());
}
}
void PathItem::showTicks(bool show)
{
if (_showTicks == show)
return;
prepareGeometryChange();
_showTicks = show;
updateTicks();
}
void PathItem::setUnits(Units units)
{
if (_units == units)
return;
prepareGeometryChange();
_units = units;
updateTicks();
}
void PathItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);

View File

@ -5,8 +5,10 @@
#include <QPen>
#include "data/path.h"
#include "markeritem.h"
#include "units.h"
class Map;
class PathTickItem;
class PathItem : public QGraphicsObject
{
@ -24,12 +26,16 @@ public:
void setMap(Map *map);
void setUnits(Units units);
void setColor(const QColor &color);
void setWidth(qreal width);
void setStyle(Qt::PenStyle style);
void setDigitalZoom(int zoom);
void setMarkerColor(const QColor &color);
void showMarker(bool show);
void showTicks(bool show);
Units units() const {return _units;}
public slots:
void moveMarker(qreal distance);
@ -38,10 +44,6 @@ public slots:
signals:
void selected(bool);
protected:
Path _path;
MarkerItem *_marker;
private:
const PathSegment *segment(qreal x) const;
QPointF position(qreal distance) const;
@ -49,19 +51,28 @@ private:
void updateShape();
void addSegment(const Coordinates &c1, const Coordinates &c2);
qreal xInM() const;
unsigned tickSize() const;
void updateTicks();
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
Path _path;
Map *_map;
qreal _markerDistance;
int _digitalZoom;
Units _units;
qreal _width;
QPen _pen;
QPainterPath _shape;
QPainterPath _painterPath;
bool _showMarker;
bool _showTicks;
MarkerItem *_marker;
QVector<PathTickItem*> _ticks;
};
#endif // PATHITEM_H

71
src/GUI/pathtickitem.cpp Normal file
View File

@ -0,0 +1,71 @@
#include <QPainter>
#include <QCursor>
#include "font.h"
#include "pathtickitem.h"
static QFont defaultFont()
{
QFont font;
font.setPixelSize(10);
font.setFamily(FONT_FAMILY);
font.setBold(true);
return font;
}
QFont PathTickItem::_font = defaultFont();
PathTickItem::PathTickItem(const QRectF &tickRect, int value,
QGraphicsItem *parent) : QGraphicsItem(parent), _tickRect(tickRect),
_text(QString::number(value))
{
_tickRect.moveCenter(QPointF(0, -_tickRect.height()/2.0 - 3));
setCursor(Qt::ArrowCursor);
setAcceptHoverEvents(true);
}
QRectF PathTickItem::boundingRect() const
{
return _tickRect.adjusted(0, 0, 0, 3);
}
void PathTickItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
QPointF arrow[3] = {QPointF(0, 0), QPointF(3, -3), QPointF(-3, -3)};
painter->setFont(_font);
painter->setRenderHint(QPainter::Antialiasing, false);
painter->setPen(Qt::white);
painter->setBrush(_brush);
painter->drawPolygon(arrow, 3);
painter->drawRoundedRect(_tickRect, 1.5, 1.5);
painter->drawText(_tickRect, Qt::AlignCenter, _text);
/*
painter->setBrush(Qt::NoBrush);
painter->setPen(Qt::red);
painter->drawRect(boundingRect());
*/
}
void PathTickItem::setPos(const QPointF &pos)
{
/* For propper rounded rect rendering, the item must be positioned in the
middle of a pixel */
QPoint p(pos.toPoint());
QGraphicsItem::setPos(QPointF(p.x() - 0.5, p.y() - 0.5));
}
QRect PathTickItem::tickRect(int value)
{
QFontMetrics fm(_font);
return fm.boundingRect(QRect(), Qt::AlignCenter,
QString::number(qMax(value, 10))).adjusted(-2, 0, 2, 0);
}

29
src/GUI/pathtickitem.h Normal file
View File

@ -0,0 +1,29 @@
#ifndef PATHTICKITEM_H
#define PATHTICKITEM_H
#include <QFont>
#include <QGraphicsItem>
class PathTickItem : public QGraphicsItem
{
public:
PathTickItem(const QRectF &tickRect, int value, QGraphicsItem *parent = 0);
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
void setPos(const QPointF &pos);
void setColor(const QColor &color) {_brush = QBrush(color);}
static QRect tickRect(int value);
private:
QRectF _tickRect;
QString _text;
QBrush _brush;
static QFont _font;
};
#endif // PATHTICKITEM_H

View File

@ -15,7 +15,7 @@ QString RouteItem::toolTip(Units units) const
tt.insert(tr("Name"), _name);
if (!_desc.isEmpty())
tt.insert(tr("Description"), _desc);
tt.insert(tr("Distance"), Format::distance(_path.last().last().distance(),
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
units));
return tt.toString();
@ -26,12 +26,12 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
{
const QVector<Waypoint> &waypoints = route.waypoints();
_waypoints.resize(waypoints.size());
for (int i = 0; i < waypoints.size(); i++)
new WaypointItem(waypoints.at(i), map, this);
_waypoints[i] = new WaypointItem(waypoints.at(i), map, this);
_name = route.name();
_desc = route.description();
_units = Metric;
_coordinatesFormat = DecimalDegrees;
setToolTip(toolTip(Metric));
@ -39,33 +39,23 @@ RouteItem::RouteItem(const Route &route, Map *map, QGraphicsItem *parent)
void RouteItem::setMap(Map *map)
{
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->setMap(map);
}
}
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setMap(map);
PathItem::setMap(map);
}
void RouteItem::setUnits(Units units)
void RouteItem::setUnits(Units u)
{
if (_units == units)
if (units() == u)
return;
_units = units;
PathItem::setUnits(u);
setToolTip(toolTip(_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);
}
}
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setToolTipFormat(units(), _coordinatesFormat);
}
void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
@ -75,30 +65,18 @@ void RouteItem::setCoordinatesFormat(CoordinatesFormat format)
_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);
}
}
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setToolTipFormat(units(), _coordinatesFormat);
}
void RouteItem::showWaypoints(bool show)
{
QList<QGraphicsItem *> childs = childItems();
for (int i = 0; i < childs.count(); i++)
if (childs.at(i) != _marker)
childs.at(i)->setVisible(show);
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->setVisible(show);
}
void RouteItem::showWaypointLabels(bool show)
{
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->showLabel(show);
}
}
for (int i = 0; i < _waypoints.count(); i++)
_waypoints[i]->showLabel(show);
}

View File

@ -7,6 +7,7 @@
#include "format.h"
class Map;
class WaypointItem;
class RouteItem : public PathItem
{
@ -17,7 +18,7 @@ public:
void setMap(Map *map);
void setUnits(Units units);
void setUnits(Units u);
void setCoordinatesFormat(CoordinatesFormat format);
void showWaypoints(bool show);
void showWaypointLabels(bool show);
@ -27,8 +28,9 @@ private:
QString _name;
QString _desc;
Units _units;
CoordinatesFormat _coordinatesFormat;
QVector<WaypointItem*> _waypoints;
};
#endif // ROUTEITEM_H

View File

@ -61,9 +61,9 @@ void ScaleItem::computeScale()
qreal res = _res * pow(2, -_digitalZoom);
if (_units == Imperial) {
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1);
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, true);
if (_length >= MIINFT) {
_length = niceNum((res * M2MI * SCALE_WIDTH) / SEGMENTS, 1);
_length = niceNum((res * M2MI * SCALE_WIDTH) / SEGMENTS, true);
_width = (_length / (res * M2MI));
_scale = true;
} else {
@ -71,9 +71,9 @@ void ScaleItem::computeScale()
_scale = false;
}
} else if (_units == Nautical) {
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, 1);
_length = niceNum((res * M2FT * SCALE_WIDTH) / SEGMENTS, true);
if (_length >= NMIINFT) {
_length = niceNum((res * M2NMI * SCALE_WIDTH) / SEGMENTS, 1);
_length = niceNum((res * M2NMI * SCALE_WIDTH) / SEGMENTS, true);
_width = (_length / (res * M2NMI));
_scale = true;
} else {
@ -81,7 +81,7 @@ void ScaleItem::computeScale()
_scale = false;
}
} else {
_length = niceNum((res * SCALE_WIDTH) / SEGMENTS, 1);
_length = niceNum((res * SCALE_WIDTH) / SEGMENTS, true);
if (_length >= KMINM) {
_length *= M2KM;
_width = (_length / (res * M2KM));

View File

@ -32,6 +32,8 @@
#define SHOW_GRAPH_SLIDER_INFO_DEFAULT true
#define SHOW_MARKERS_SETTING "pathMarkers"
#define SHOW_MARKERS_DEFAULT true
#define SHOW_TICKS_SETTING "pathTicks"
#define SHOW_TICKS_DEFAULT false
#define MAP_SETTINGS_GROUP "Map"
#define CURRENT_MAP_SETTING "map"
@ -171,8 +173,8 @@
#define SEPARATE_GRAPH_PAGE_DEFAULT false
#define SLIDER_COLOR_SETTING "sliderColor"
#define SLIDER_COLOR_DEFAULT QColor(Qt::red)
#define ALWAYS_SHOW_MAP_SETTING "alwaysShowMap"
#define ALWAYS_SHOW_MAP_DEFAULT true
#define PROJECTION_SETTING "projection"
#define PROJECTION_DEFAULT 3857
#define HIDPI_MAP_SETTING "HiDPIMap"
#define HIDPI_MAP_DEFAULT true

View File

@ -13,7 +13,7 @@ QString TrackItem::toolTip(Units units) const
tt.insert(tr("Name"), _name);
if (!_desc.isEmpty())
tt.insert(tr("Description"), _desc);
tt.insert(tr("Distance"), Format::distance(_path.last().last().distance(),
tt.insert(tr("Distance"), Format::distance(path().last().last().distance(),
units));
if (_time > 0)
tt.insert(tr("Total time"), Format::timeSpan(_time));
@ -39,5 +39,6 @@ TrackItem::TrackItem(const Track &track, Map *map, QGraphicsItem *parent)
void TrackItem::setUnits(Units units)
{
PathItem::setUnits(units);
setToolTip(toolTip(units));
}

View File

@ -9,9 +9,11 @@
#define DEM_DIR "DEM"
#define TILES_DIR "tiles"
#define TRANSLATIONS_DIR "translations"
#define STYLE_DIR "style"
#define ELLIPSOID_FILE "ellipsoids.csv"
#define GCS_FILE "gcs.csv"
#define PCS_FILE "pcs.csv"
#define TYP_FILE "style.typ"
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
@ -79,6 +81,11 @@ QString ProgramPaths::demDir(bool writable)
return dir(DEM_DIR, writable);
}
QString ProgramPaths::styleDir(bool writable)
{
return dir(STYLE_DIR, writable);
}
QString ProgramPaths::tilesDir()
{
#if defined(Q_OS_WIN32)
@ -113,6 +120,11 @@ QString ProgramPaths::pcsFile()
return file(dir(CSV_DIR), PCS_FILE);
}
QString ProgramPaths::typFile()
{
return file(dir(STYLE_DIR), TYP_FILE);
}
#else // QT_VERSION < 5
#include <QStandardPaths>
@ -157,6 +169,16 @@ QString ProgramPaths::demDir(bool writable)
DEM_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::styleDir(bool writable)
{
if (writable)
return QDir(QStandardPaths::writableLocation(
QStandardPaths::AppDataLocation)).filePath(STYLE_DIR);
else
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
STYLE_DIR, QStandardPaths::LocateDirectory);
}
QString ProgramPaths::tilesDir()
{
return QDir(QStandardPaths::writableLocation(
@ -187,4 +209,10 @@ QString ProgramPaths::pcsFile()
CSV_DIR "/" PCS_FILE, QStandardPaths::LocateFile);
}
QString ProgramPaths::typFile()
{
return QStandardPaths::locate(QStandardPaths::AppDataLocation,
STYLE_DIR "/" TYP_FILE, QStandardPaths::LocateFile);
}
#endif // QT_VERSION < 5

View File

@ -9,11 +9,13 @@ namespace ProgramPaths
QString poiDir(bool writable = false);
QString csvDir(bool writable = false);
QString demDir(bool writable = false);
QString styleDir(bool writable = false);
QString tilesDir();
QString translationsDir();
QString ellipsoidsFile();
QString gcsFile();
QString pcsFile();
QString typFile();
}
#endif // PROGRAMPATHS_H

View File

@ -17,7 +17,7 @@ int str2int(const char *str, int len)
return res;
}
double niceNum(double x, int round)
double niceNum(double x, bool round)
{
int expv;
double f;

View File

@ -2,6 +2,6 @@
#define UTIL_H
int str2int(const char *str, int len);
double niceNum(double x, int round);
double niceNum(double x, bool round);
#endif // UTIL_H

View File

@ -118,6 +118,9 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
trackpoint.setTimestamp(time());
else if (_reader.name() == QLatin1String("geoidheight"))
gh = number();
// GPX 1.0
else if (_reader.name() == QLatin1String("speed"))
trackpoint.setSpeed(number());
else if (_reader.name() == QLatin1String("extensions"))
trkptExtensions(trackpoint);
else

View File

@ -1,5 +1,6 @@
#include <QSet>
#include <QtEndian>
#include "common/programpaths.h"
#include "vectortile.h"
#include "img.h"
@ -162,9 +163,18 @@ IMG::IMG(const QString &fileName) : _file(fileName), _valid(false)
// Read TYP file if any
if (!TYPMap.isEmpty()) {
if (TYPMap.size() > 1)
qWarning("%s: Multiple TYP files, using %s",
qPrintable(_file.fileName()), qPrintable(TYPMap.keys().first()));
SubFile *typ = TYPMap.values().first();
_style = Style(typ);
qDeleteAll(TYPMap);
} else {
QFile typFile(ProgramPaths::typFile());
if (typFile.exists()) {
SubFile typ(&typFile);
_style = Style(&typ);
}
}
_valid = true;

View File

@ -50,20 +50,19 @@ public:
const QString &name() const {return _name;}
const RectC &bounds() const {return _bounds;}
Range zooms() const {return Range(_bits.first(), _bits.last());}
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points) const;
const Style &style() const {return _style;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points) const;
const Style &style() const {return _style;}
private:
friend class SubFile;
typedef RTree<VectorTile*, double, 2> TileTree;
QString fileName() const {return _file.fileName();}
int blockSize() const {return _blockSize;}
bool readBlock(int blockNum, QByteArray &data);
qint64 read(char *data, qint64 maxSize);

View File

@ -779,7 +779,7 @@ bool Style::parseTYPFile(SubFile *file)
&& parsePolygons(file, hdl, polygons)
&& parseDrawOrder(file, hdl, order))) {
qWarning("%s: Invalid TYP file, using default style",
qPrintable(file->imgName()));
qPrintable(file->fileName()));
return false;
}
@ -791,7 +791,7 @@ Style::Style(SubFile *typ)
defaultLineStyle();
defaultPolygonStyle();
if (typ)
if (typ && typ->isValid())
parseTYPFile(typ);
}

View File

@ -1,3 +1,4 @@
#include <QFile>
#include "img.h"
#include "subfile.h"
@ -19,42 +20,68 @@ SubFile::Type SubFile::type(const char str[3])
return Unknown;
}
SubFile::SubFile(QFile *file) : _img(0), _file(file), _size(0)
{
if (!_file->open(QIODevice::ReadOnly))
qWarning("Error opening %s: %s", qPrintable(_file->fileName()),
qPrintable(_file->errorString()));
}
bool SubFile::isValid() const
{
return ((quint32)_img->blockSize() * (quint32)_blocks.size() - _size
< (quint32)_img->blockSize());
return _file
? _file->isOpen()
: ((quint32)_img->blockSize() * (quint32)_blocks.size() - _size
< (quint32)_img->blockSize());
}
bool SubFile::seek(Handle &handle, quint32 pos) const
{
quint32 blockSize = _img->blockSize();
int blockNum = pos / blockSize;
Q_ASSERT(_img || _file);
if (handle.blockNum != blockNum) {
if (blockNum >= _blocks.size())
return false;
if (!_img->readBlock(_blocks.at(blockNum), handle.data))
return false;
handle.blockNum = blockNum;
if (_file)
return _file->seek(pos);
else {
quint32 blockSize = _img->blockSize();
int blockNum = pos / blockSize;
if (handle.blockNum != blockNum) {
if (blockNum >= _blocks.size())
return false;
if (!_img->readBlock(_blocks.at(blockNum), handle.data))
return false;
handle.blockNum = blockNum;
}
handle.blockPos = pos % blockSize;
handle.pos = pos;
return true;
}
handle.blockPos = pos % blockSize;
handle.pos = pos;
return true;
}
bool SubFile::readByte(Handle &handle, quint8 &val) const
{
val = handle.data.at(handle.blockPos++);
handle.pos++;
return (handle.blockPos >= _img->blockSize())
? seek(handle, handle.pos) : true;
Q_ASSERT(_img || _file);
if (_file)
return _file->getChar((char*)&val);
else {
val = handle.data.at(handle.blockPos++);
handle.pos++;
return (handle.blockPos >= _img->blockSize())
? seek(handle, handle.pos) : true;
}
}
const QString &SubFile::imgName() const
quint32 SubFile::size() const
{
return _img->name();
return _img ? _size : (quint32)_file->size();
}
QString SubFile::fileName() const
{
return _img ? _img->fileName() : _file->fileName();
}
#ifndef QT_NO_DEBUG

View File

@ -5,6 +5,7 @@
#include <QDebug>
class IMG;
class QFile;
class SubFile
{
@ -21,12 +22,13 @@ public:
int pos;
};
SubFile(IMG *img, quint32 size) : _img(img), _size(size) {}
SubFile(IMG *img, quint32 size) : _img(img), _file(0), _size(size) {}
SubFile(QFile *file);
void addBlock(quint16 block) {_blocks.append(block);}
bool isValid() const;
quint32 size() const {return _size;}
quint32 size() const;
bool seek(Handle &handle, quint32 pos) const;
bool readByte(Handle &handle, quint8 &val) const;
@ -79,7 +81,7 @@ public:
}
quint16 offset() const {return _blocks.first();}
const QString &imgName() const;
QString fileName() const;
static Type type(const char str[3]);
@ -87,6 +89,7 @@ public:
private:
IMG *_img;
QFile *_file;
quint32 _size;
QVector<quint16> _blocks;
};

View File

@ -66,8 +66,14 @@ void TextPointItem::paint(QPainter *painter) const
painter->setPen(*_color);
painter->drawText(_textRect, FLAGS, *_text);
} else {
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
img.invertPixels();
painter->drawImage(_textRect, img);
#else // QT >= 5.4
QImage iimg(img.convertToFormat(QImage::Format_ARGB32));
iimg.invertPixels();
painter->drawImage(_textRect, iimg);
#endif // QT >= 5.4
}
}

View File

@ -109,13 +109,13 @@ QRectF IMGMap::bounds()
int IMGMap::zoomFit(const QSize &size, const RectC &rect)
{
if (rect.isValid()) {
QPointF sc((rect.right() - rect.left()) / size.width(),
(rect.top() - rect.bottom()) / size.height());
double resolution = qMax(qAbs(sc.x()), qAbs(sc.y()));
RectD pr(rect, _projection, 10);
_zoom = _zooms.min();
for (int i = _zooms.min(); i <= _zooms.max(); i++) {
if (360.0 / (1<<i) < resolution)
for (int i = _zooms.min() + 1; i <= _zooms.max(); i++) {
Transform t(transform(i));
QRectF r(t.proj2img(pr.topLeft()), t.proj2img(pr.bottomRight()));
if (size.width() < r.width() || size.height() < r.height())
break;
_zoom = i;
}
@ -141,12 +141,23 @@ int IMGMap::zoomOut()
return _zoom;
}
void IMGMap::setZoom(int zoom)
{
_zoom = zoom;
updateTransform();
}
Transform IMGMap::transform(int zoom) const
{
double scale = (2.0 * M_PI * WGS84_RADIUS) / (1<<zoom);
PointD topLeft(_projection.ll2xy(_img.bounds().topLeft()));
return Transform(ReferencePoint(PointD(0, 0), topLeft),
PointD(scale, scale));
}
void IMGMap::updateTransform()
{
double scale = (2.0 * M_PI * WGS84_RADIUS) / (1<<_zoom);;
PointD topLeft(_projection.ll2xy(_img.bounds().topLeft()));
_transform = Transform(ReferencePoint(PointD(0, 0), topLeft),
PointD(scale, scale));
_transform = transform(_zoom);
}
QPointF IMGMap::ll2xy(const Coordinates &c)
@ -369,3 +380,10 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
painter->drawPixmap(mt.xy(), pm);
}
}
void IMGMap::setProjection(const Projection &projection)
{
_projection = projection;
updateTransform();
QPixmapCache::clear();
}

View File

@ -21,7 +21,7 @@ public:
QRectF bounds();
virtual int zoom() const {return _zoom;}
virtual void setZoom(int zoom) {_zoom = zoom;}
virtual void setZoom(int zoom);
virtual int zoomFit(const QSize &, const RectC &);
virtual int zoomIn();
virtual int zoomOut();
@ -31,12 +31,15 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setProjection(const Projection &projection);
bool isValid() const {return _valid;}
QString errorString() const {return _errorString;}
private:
friend class RasterTile;
Transform transform(int zoom) const;
void updateTransform();
void drawPolygons(QPainter *painter, QList<IMG::Poly> &polygons);
void drawLines(QPainter *painter, QList<IMG::Poly> &lines,

View File

@ -1,5 +1,6 @@
#include <QLineF>
#include "map.h"
#include "pcs.h"
qreal Map::resolution(const QRectF &rect)
{

View File

@ -7,8 +7,10 @@
#include <QFlags>
#include "common/coordinates.h"
class QPainter;
class RectC;
class Projection;
class Map : public QObject
{
@ -45,6 +47,7 @@ public:
virtual void load() {}
virtual void unload() {}
virtual void setDevicePixelRatio(qreal, qreal) {}
virtual void setProjection(const Projection &) {}
virtual bool isValid() const {return true;}
virtual QString errorString() const {return QString();}

View File

@ -160,6 +160,8 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
config.type = WMS;
else if (type == "TMS")
config.type = TMS;
else if (type == "QuadTiles")
config.type = QuadTiles;
else if (type == "OSM" || type.isEmpty())
config.type = OSM;
else {
@ -293,11 +295,15 @@ Map *MapSource::loadMap(const QString &path, QString &errorString)
case TMS:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization,
config.tileSize, config.scalable, true);
config.tileSize, config.scalable, true, false);
case OSM:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization,
config.tileSize, config.scalable, false);
config.tileSize, config.scalable, false, false);
case QuadTiles:
return new OnlineMap(config.name, config.url, config.zooms,
config.bounds, config.tileRatio, config.authorization,
config.tileSize, config.scalable, false, true);
default:
return 0;
}

View File

@ -21,7 +21,8 @@ private:
OSM,
WMTS,
WMS,
TMS
TMS,
QuadTiles
};
struct Config {

View File

@ -11,15 +11,16 @@
OnlineMap::OnlineMap(const QString &name, const QString &url,
const Range &zooms, const RectC &bounds, qreal tileRatio,
const Authorization &authorization, int tileSize, bool scalable, bool invertY,
QObject *parent)
bool quadTiles, QObject *parent)
: Map(parent), _name(name), _zooms(zooms), _bounds(bounds),
_zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio),
_tileSize(tileSize), _scalable(scalable), _invertY(invertY), _scaledSize(0)
_tileSize(tileSize), _scalable(scalable), _invertY(invertY)
{
_tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name),
this);
_tileLoader->setUrl(url);
_tileLoader->setAuthorization(authorization);
_tileLoader->setQuadTiles(quadTiles);
connect(_tileLoader, SIGNAL(finished()), this, SIGNAL(loaded()));
}
@ -74,7 +75,7 @@ void OnlineMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
_mapRatio = mapRatio;
if (_scalable) {
_scaledSize = _tileSize * deviceRatio;
_tileLoader->setScaledSize(_tileSize * deviceRatio);
_tileRatio = deviceRatio;
}
}
@ -112,7 +113,7 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
tiles.append(Tile(QPoint(tile.x() + i, _invertY ? (1<<_zoom)
- (tile.y() + j) - 1 : tile.y() + j), _zoom, _scaledSize));
- (tile.y() + j) - 1 : tile.y() + j), _zoom));
if (flags & Map::Block)
_tileLoader->loadTilesSync(tiles);

View File

@ -13,7 +13,8 @@ class OnlineMap : public Map
public:
OnlineMap(const QString &name, const QString &url, const Range &zooms,
const RectC &bounds, qreal tileRatio, const Authorization &authorization,
int tileSize, bool scalable, bool invertY, QObject *parent = 0);
int tileSize, bool scalable, bool invertY, bool quadTiles,
QObject *parent = 0);
QString name() const {return _name;}
@ -49,7 +50,6 @@ private:
int _tileSize;
bool _scalable;
bool _invertY;
int _scaledSize;
};
#endif // ONLINEMAP_H

View File

@ -5,13 +5,16 @@
class PCS::Entry {
public:
Entry(int id, int proj, const PCS &pcs) : _id(id), _proj(proj), _pcs(pcs) {}
Entry(const QString &name, int id, int proj, const PCS &pcs)
: _name(name), _id(id), _proj(proj), _pcs(pcs) {}
const QString &name() const {return _name;}
int id() const {return _id;}
int proj() const {return _proj;}
const PCS &pcs() const {return _pcs;}
private:
QString _name;
int _id, _proj;
PCS _pcs;
};
@ -21,8 +24,9 @@ QList<PCS::Entry> PCS::_pcss = defaults();
QList<PCS::Entry> PCS::defaults()
{
QList<PCS::Entry> list;
list.append(PCS::Entry(3857, 3856, PCS(&GCS::WGS84(), 1024,
Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN), 9001, 4499)));
list.append(PCS::Entry("WGS 84 / Pseudo-Mercator", 3857, 3856,
PCS(&GCS::WGS84(), 1024, Projection::Setup(0, 0, NAN, 0, 0, NAN, NAN),
9001, 4499)));
return list;
}
@ -154,27 +158,28 @@ void PCS::loadList(const QString &path)
continue;
}
int id = list[1].trimmed().toInt(&res);
QString name(list.at(0).trimmed());
int id = list.at(1).trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid PCS code", qPrintable(path), ln);
continue;
}
int gcsid = list[2].trimmed().toInt(&res);
int gcsid = list.at(2).trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid GCS code", qPrintable(path), ln);
continue;
}
int proj = list[3].trimmed().toInt(&res);
int proj = list.at(3).trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid projection code", qPrintable(path), ln);
continue;
}
int units = list[4].trimmed().toInt(&res);
int units = list.at(4).trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid linear units code", qPrintable(path), ln);
continue;
}
int transform = list[5].trimmed().toInt(&res);
int transform = list.at(5).trimmed().toInt(&res);
if (!res) {
qWarning("%s:%d: Invalid coordinate transformation code",
qPrintable(path), ln);
@ -214,10 +219,20 @@ void PCS::loadList(const QString &path)
}
PCS pcs(gcs, transform, setup, units, cs);
_pcss.append(Entry(id, proj, pcs));
_pcss.append(Entry(name, id, proj, pcs));
}
}
QList<PCS::Info> PCS::pcsList()
{
QList<Info> list;
for (int i = 0; i < _pcss.size(); i++)
list.append(Info(_pcss.at(i).id(), _pcss.at(i).name()));
return list;
}
#ifndef QT_NO_DEBUG
QDebug operator<<(QDebug dbg, const PCS &pcs)
{

View File

@ -11,6 +11,20 @@
class PCS
{
public:
class Info {
public:
Info(int id, const QString &name) : _id(id), _name(name) {}
int id() const {return _id;}
const QString &name() const {return _name;}
bool operator<(const Info &other) const {return _id < other._id;}
private:
int _id;
QString _name;
};
PCS() : _gcs(0) {}
PCS(const GCS *gcs, const Projection::Method &method,
const Projection::Setup &setup, const LinearUnits &units,
@ -34,11 +48,12 @@ public:
static void loadList(const QString &path);
static const PCS *pcs(int id);
static const PCS *pcs(const GCS *gcs, int proj);
static QList<Info> pcsList();
private:
class Entry;
static QList<PCS::Entry> defaults();
static QList<Entry> defaults();
const GCS *_gcs;
Projection::Method _method;

View File

@ -128,6 +128,8 @@ Projection::~Projection()
Projection &Projection::operator=(const Projection &p)
{
delete _ct;
_gcs = p._gcs;
_units = p._units;
_ct = p._ct ? p._ct->clone() : 0;

View File

@ -10,21 +10,18 @@
class Tile
{
public:
Tile() : _scaledSize(0) {}
Tile(const QPoint &xy, const QVariant &zoom, int scaledSize = 0,
const RectD &bbox = RectD()) : _xy(xy), _zoom(zoom),
_scaledSize(scaledSize), _bbox(bbox) {}
Tile() {}
Tile(const QPoint &xy, const QVariant &zoom, const RectD &bbox = RectD())
: _xy(xy), _zoom(zoom), _bbox(bbox) {}
const QVariant &zoom() const {return _zoom;}
const QPoint &xy() const {return _xy;}
const RectD &bbox() const {return _bbox;}
int scaledSize() const {return _scaledSize;}
QPixmap& pixmap() {return _pixmap;}
private:
QPoint _xy;
QVariant _zoom;
int _scaledSize;
RectD _bbox;
QPixmap _pixmap;
};

View File

@ -14,9 +14,9 @@
class TileImage
{
public:
TileImage() : _tile(0) {}
TileImage(const QString &file, Tile *tile)
: _file(file), _tile(tile) {}
TileImage() : _tile(0), _scaledSize(0) {}
TileImage(const QString &file, Tile *tile, int scaledSize)
: _file(file), _tile(tile), _scaledSize(scaledSize) {}
void createPixmap()
{
@ -26,8 +26,8 @@ public:
{
QByteArray z(_tile->zoom().toString().toLatin1());
QImageReader reader(_file, z);
if (_tile->scaledSize())
reader.setScaledSize(QSize(_tile->scaledSize(), _tile->scaledSize()));
if (_scaledSize)
reader.setScaledSize(QSize(_scaledSize, _scaledSize));
reader.read(&_image);
}
@ -37,6 +37,7 @@ public:
private:
QString _file;
Tile *_tile;
int _scaledSize;
QImage _image;
};
@ -45,8 +46,25 @@ static void render(TileImage &ti)
ti.load();
}
static QString quadKey(const QPoint &xy, int zoom)
{
QString qk;
for (int i = zoom; i > 0; i--) {
char digit = '0';
unsigned mask = 1 << (i - 1);
if (xy.x() & mask)
digit++;
if (xy.y() & mask)
digit += 2;
qk.append(digit);
}
return qk;
}
TileLoader::TileLoader(const QString &dir, QObject *parent)
: QObject(parent), _dir(dir)
: QObject(parent), _dir(dir), _scaledSize(0), _quadTiles(false)
{
if (!QDir().mkpath(_dir))
qWarning("%s: %s", qPrintable(_dir), "Error creating tiles directory");
@ -70,11 +88,11 @@ void TileLoader::loadTilesAsync(QVector<Tile> &list)
QFileInfo fi(file);
if (fi.exists())
imgs.append(TileImage(file, &t));
imgs.append(TileImage(file, &t, _scaledSize));
else {
QUrl url(tileUrl(t));
if (url.isLocalFile())
imgs.append(TileImage(url.toLocalFile(), &t));
imgs.append(TileImage(url.toLocalFile(), &t, _scaledSize));
else
dl.append(Download(url, file));
}
@ -109,11 +127,11 @@ void TileLoader::loadTilesSync(QVector<Tile> &list)
QFileInfo fi(file);
if (fi.exists())
imgs.append(TileImage(file, &t));
imgs.append(TileImage(file, &t, _scaledSize));
else {
QUrl url(tileUrl(t));
if (url.isLocalFile())
imgs.append(TileImage(url.toLocalFile(), &t));
imgs.append(TileImage(url.toLocalFile(), &t, _scaledSize));
else {
dl.append(Download(url, file));
tl.append(&t);
@ -131,7 +149,7 @@ void TileLoader::loadTilesSync(QVector<Tile> &list)
Tile *t = tl[i];
QString file = tileFile(*t);
if (QFileInfo(file).exists())
imgs.append(TileImage(file, t));
imgs.append(TileImage(file, t, _scaledSize));
}
}
@ -164,6 +182,8 @@ QUrl TileLoader::tileUrl(const Tile &tile) const
QString::number(tile.bbox().right(), 'f', 6),
QString::number(tile.bbox().top(), 'f', 6));
url.replace("$bbox", bbox);
} else if (_quadTiles) {
url.replace("$quadkey", quadKey(tile.xy(), tile.zoom().toInt()));
} else {
url.replace("$z", tile.zoom().toString());
url.replace("$x", QString::number(tile.xy().x()));

View File

@ -16,6 +16,8 @@ public:
void setUrl(const QString &url) {_url = url;}
void setAuthorization(const Authorization &authorization)
{_authorization = authorization;}
void setScaledSize(int size) {_scaledSize = size;}
void setQuadTiles(bool quadTiles) {_quadTiles = quadTiles;}
void loadTilesAsync(QVector<Tile> &list);
void loadTilesSync(QVector<Tile> &list);
@ -32,6 +34,8 @@ private:
QString _url;
QString _dir;
Authorization _authorization;
int _scaledSize;
bool _quadTiles;
};
#endif // TILELOADER_Honlinemap

View File

@ -11,6 +11,7 @@
#define CAPABILITIES_FILE "capabilities.xml"
#define TILE_SIZE 256
#define EPSILON 1e-6
double WMSMap::sd2res(double scaleDenominator) const
{
@ -50,14 +51,15 @@ void WMSMap::computeZooms(const RangeF &scaleDenominator)
_zooms.clear();
if (scaleDenominator.size() > 0) {
double ld = log2(scaleDenominator.max()) - log2(scaleDenominator.min());
double ld = log2(scaleDenominator.max() - EPSILON)
- log2(scaleDenominator.min() + EPSILON);
int cld = (int)ceil(ld);
double step = ld / (double)cld;
double lmax = log2(scaleDenominator.max());
double lmax = log2(scaleDenominator.max() - EPSILON);
for (int i = 0; i <= cld; i++)
_zooms.append(pow(2.0, lmax - i * step));
} else
_zooms.append(scaleDenominator.min());
_zooms.append(scaleDenominator.min() + EPSILON);
}
void WMSMap::updateTransform()
@ -194,13 +196,13 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
for (int j = tl.y(); j < br.y(); j++) {
PointD ttl(_transform.img2proj(QPointF(i * TILE_SIZE,
j * TILE_SIZE)));
PointD tbr(_transform.img2proj(QPointF(i * TILE_SIZE + TILE_SIZE
- 1, j * TILE_SIZE + TILE_SIZE - 1)));
PointD tbr(_transform.img2proj(QPointF(i * TILE_SIZE + TILE_SIZE,
j * TILE_SIZE + TILE_SIZE)));
RectD bbox = (_cs.axisOrder() == CoordinateSystem::YX)
? RectD(PointD(tbr.y(), tbr.x()), PointD(ttl.y(), ttl.x()))
: RectD(ttl, tbr);
tiles.append(Tile(QPoint(i, j), _zoom, 0, bbox));
tiles.append(Tile(QPoint(i, j), _zoom, bbox));
}
}