1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-01 21:39:15 +02:00

Compare commits

..

31 Commits
4.2 ... 4.5

Author SHA1 Message Date
699e4f32d5 Version++ 2017-04-23 18:15:08 +02:00
992c8aaaf9 Improved error reporting 2017-04-23 13:37:17 +02:00
68a72c5809 Added proper OZF files detection 2017-04-23 12:49:40 +02:00
eace308774 Properly open all selected files (tar content/atlas structure is however still case sensitive) 2017-04-23 12:26:01 +02:00
e4e3f7d143 Added missing atlas maps unloading on atlas unload 2017-04-22 10:19:02 +02:00
acc49d015e Use only the "Map" word for maps/atlases in the GUI 2017-04-21 21:57:29 +02:00
b48652cb78 Localization update 2017-04-21 21:25:56 +02:00
0808f6679e Added "runtime" offline map loading
Offline map loading & error handling cleanup
2017-04-21 21:15:58 +02:00
610ac3d73f Fixed atlas zoom fitting algorithm 2017-04-19 00:07:01 +02:00
1d719fdcc8 Localization files update 2017-04-17 22:13:30 +02:00
1746e1cf08 Merge pull request #25 from mkroehnert/german-translation
add german translation
2017-04-17 21:58:05 +02:00
5d5a5365cd add german translation 2017-04-17 20:56:56 +02:00
7dfdeac1da Version++ 2017-04-17 19:57:52 +02:00
1ff13ee9f8 Added datum files to packages 2017-04-17 19:56:29 +02:00
34b1fb6b5d Cosmetics 2017-04-17 19:37:03 +02:00
02bf85780a Improved OZF files handling. 2017-04-17 19:34:44 +02:00
47199348d8 Improved error reporting 2017-04-17 19:15:20 +02:00
3b55bc0efc Added missing Lat/Lon based calibration points conversion to WGS84 2017-04-17 19:01:01 +02:00
4de3ddf71b Switched from hardcoded values to CSV files for datum definitions.
Non-WGS84 maps now fit correctly when defined using map grid.
2017-04-17 18:03:04 +02:00
e26fa92ce6 Code cleanup 2017-04-15 13:13:26 +02:00
dfb69b2755 Yet another error handling fix. 2017-04-15 11:47:30 +02:00
c2a30738cb Update README.md 2017-04-15 09:11:16 +02:00
fd53e89ea5 Improved error handling 2017-04-15 08:59:31 +02:00
ccf91bb29f Added support for ozf2 files 2017-04-14 22:39:33 +02:00
75bd388be0 Try to load maps with incorrect (windows absolute) image paths. 2017-04-13 20:00:27 +02:00
aef0357204 Version++ 2017-04-12 18:19:03 +02:00
d073d606d0 Added missing cache reset (causing huge redraw rects causing system memory exhaustion) 2017-04-12 18:11:53 +02:00
8822bf7e5f Code cleanup 2017-04-09 10:26:09 +02:00
051a3ed303 Replaced wrong NAD27 ellipsoid with the correct one 2017-04-07 18:19:56 +02:00
96437ae6ab Cosmetics 2017-04-07 10:16:14 +02:00
89c25bbc3a Update README.md 2017-04-07 10:02:41 +02:00
34 changed files with 2583 additions and 722 deletions

View File

@ -4,7 +4,7 @@ KML, FIT, IGC and NMEA files.
## Features
* User-definable online maps.
* Offline maps (image-based OziExplorer maps and tiled TrekBuddy maps/atlases).
* Offline maps (OziExplorer maps and TrekBuddy maps/atlases).
* Elevation, speed, heart rate, cadence, power and temperature graphs.
* Support for multiple tracks in one view.
* Support for POI files.
@ -16,22 +16,18 @@ KML, FIT, IGC and NMEA files.
![GPXSee - Linux](https://a.fsdn.com/con/app/proj/gpxsee/screenshots/linux2.png)
## Build
### Linux/OS X
```shell
lrelease gpxsee.pro
qmake gpxsee.pro
make
```
### Windows
```shell
lrelease gpxsee.pro
qmake gpxsee.pro
nmake release
```
## Binaries
## Download
* [Windows & OS X builds](http://sourceforge.net/projects/gpxsee)
* [Linux packages](http://software.opensuse.org/download.html?project=home%3Atumic%3AGPXSee&package=gpxsee)
## Changelog
[Changelog](https://build.opensuse.org/package/view_file/home:tumic:GPXSee/gpxsee/gpxsee.changes)
## Homepage
GPXSee homepage: http://tumic.wz.cz/gpxsee

View File

@ -1,5 +1,5 @@
TARGET = GPXSee
VERSION = 4.2
VERSION = 4.5
QT += core \
gui \
network
@ -23,7 +23,6 @@ HEADERS += src/config.h \
src/filebrowser.h \
src/map.h \
src/onlinemap.h \
src/maplist.h \
src/downloader.h \
src/units.h \
src/scaleitem.h \
@ -81,7 +80,6 @@ HEADERS += src/config.h \
src/timetype.h \
src/emptymap.h \
src/offlinemap.h \
src/mapdir.h \
src/matrix.h \
src/tar.h \
src/atlas.h \
@ -91,7 +89,10 @@ HEADERS += src/config.h \
src/latlon.h \
src/utm.h \
src/lambertconic.h \
src/ellipsoid.h
src/ellipsoid.h \
src/ozf.h \
src/datum.h \
src/maplist.h
SOURCES += src/main.cpp \
src/gui.cpp \
src/poi.cpp \
@ -104,7 +105,6 @@ SOURCES += src/main.cpp \
src/sliderinfoitem.cpp \
src/filebrowser.cpp \
src/onlinemap.cpp \
src/maplist.cpp \
src/downloader.cpp \
src/scaleitem.cpp \
src/track.cpp \
@ -148,7 +148,6 @@ SOURCES += src/main.cpp \
src/stylecombobox.cpp \
src/emptymap.cpp \
src/offlinemap.cpp \
src/mapdir.cpp \
src/matrix.cpp \
src/tar.cpp \
src/atlas.cpp \
@ -156,10 +155,14 @@ SOURCES += src/main.cpp \
src/transversemercator.cpp \
src/utm.cpp \
src/lambertconic.cpp \
src/ellipsoid.cpp
src/ellipsoid.cpp \
src/ozf.cpp \
src/datum.cpp \
src/maplist.cpp
RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_cs.ts \
lang/gpxsee_sv.ts
lang/gpxsee_sv.ts \
lang/gpxsee_de.ts
macx {
ICON = icons/gpxsee.icns
QMAKE_INFO_PLIST = Info.plist
@ -169,7 +172,9 @@ macx {
icons/fit.icns \
icons/igc.icns \
icons/nmea.icns \
pkg/maps.txt
pkg/maps.txt \
pkg/ellipsoids.csv \
pkg/datums.csv
APP_RESOURCES.path = Contents/Resources
QMAKE_BUNDLE_DATA += APP_RESOURCES
}

View File

@ -21,5 +21,6 @@
<file>icons/document-print-preview.png</file>
<file>lang/gpxsee_cs.qm</file>
<file>lang/gpxsee_sv.qm</file>
<file>lang/gpxsee_de.qm</file>
</qresource>
</RCC>

View File

@ -190,351 +190,367 @@
<context>
<name>GUI</name>
<message>
<location filename="../src/gui.cpp" line="578"/>
<location filename="../src/gui.cpp" line="653"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>Program GPXSee je distribuován pod podmínkami licence GNU General Public License verze 3. Pro více informací navštivte stránky programu na adrese </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="656"/>
<location filename="../src/gui.cpp" line="731"/>
<source>Open file</source>
<translation>Otevřít soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="746"/>
<location filename="../src/gui.cpp" line="821"/>
<source>Open POI file</source>
<translation>Otevřít POI soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="237"/>
<location filename="../src/gui.cpp" line="310"/>
<source>Open</source>
<translation>Otevřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="221"/>
<location filename="../src/gui.cpp" line="294"/>
<source>Quit</source>
<translation>Ukončit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="229"/>
<location filename="../src/gui.cpp" line="594"/>
<location filename="../src/gui.cpp" line="595"/>
<location filename="../src/gui.cpp" line="302"/>
<location filename="../src/gui.cpp" line="669"/>
<location filename="../src/gui.cpp" line="670"/>
<source>Keyboard controls</source>
<translation>Ovládací klávesy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="253"/>
<location filename="../src/gui.cpp" line="326"/>
<source>Close</source>
<translation>Zavřít</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="259"/>
<location filename="../src/gui.cpp" line="332"/>
<source>Reload</source>
<translation>Znovu načíst</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="508"/>
<location filename="../src/gui.cpp" line="583"/>
<source>Show</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="426"/>
<location filename="../src/gui.cpp" line="502"/>
<location filename="../src/gui.cpp" line="500"/>
<location filename="../src/gui.cpp" line="577"/>
<source>File</source>
<translation>Soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="105"/>
<location filename="../src/gui.cpp" line="107"/>
<source>FIT files (*.fit)</source>
<translation>Soubory FIT (*.fit)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="106"/>
<location filename="../src/gui.cpp" line="108"/>
<source>IGC files (*.igc)</source>
<translation>Soubory IGC (*.igc)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="107"/>
<location filename="../src/gui.cpp" line="109"/>
<source>NMEA files (*.nmea)</source>
<translation>Soubory NMEA (*.nmea)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="227"/>
<location filename="../src/gui.cpp" line="623"/>
<location filename="../src/gui.cpp" line="624"/>
<location filename="../src/gui.cpp" line="300"/>
<location filename="../src/gui.cpp" line="698"/>
<location filename="../src/gui.cpp" line="699"/>
<source>Data sources</source>
<translation>Zdroje dat</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="267"/>
<location filename="../src/gui.cpp" line="340"/>
<source>Load POI file</source>
<translation>Nahrát POI soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="270"/>
<location filename="../src/gui.cpp" line="343"/>
<source>Close POI files</source>
<translation>Zavřit POI soubory</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="272"/>
<location filename="../src/gui.cpp" line="345"/>
<source>Overlap POIs</source>
<translation>Překrývat POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="276"/>
<location filename="../src/gui.cpp" line="349"/>
<source>Show POI labels</source>
<translation>Zobrazit názvy POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="281"/>
<location filename="../src/gui.cpp" line="354"/>
<source>Show POIs</source>
<translation>Zobrazit POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="290"/>
<location filename="../src/gui.cpp" line="363"/>
<source>Show map</source>
<translation>Zobrazit mapu</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="297"/>
<location filename="../src/gui.cpp" line="370"/>
<location filename="../src/gui.cpp" line="1165"/>
<source>Load map</source>
<translation>Nahrát mapu</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="373"/>
<source>Clear tile cache</source>
<translation>Vymazat mezipaměť dlaždic</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="306"/>
<location filename="../src/gui.cpp" line="310"/>
<location filename="../src/gui.cpp" line="606"/>
<location filename="../src/gui.cpp" line="377"/>
<location filename="../src/gui.cpp" line="381"/>
<location filename="../src/gui.cpp" line="681"/>
<source>Next map</source>
<translation>Následující mapa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="317"/>
<location filename="../src/gui.cpp" line="391"/>
<source>Show tracks</source>
<translation>Zobrazit cesty</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="321"/>
<location filename="../src/gui.cpp" line="395"/>
<source>Show routes</source>
<translation>Zobrazit trasy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="325"/>
<location filename="../src/gui.cpp" line="399"/>
<source>Show waypoints</source>
<translation>Zobrazit navigační body</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="329"/>
<location filename="../src/gui.cpp" line="403"/>
<source>Waypoint labels</source>
<translation>Názvy navigačních bodů</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="340"/>
<location filename="../src/gui.cpp" line="414"/>
<source>Show graphs</source>
<translation>Zobrazit grafy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="362"/>
<location filename="../src/gui.cpp" line="436"/>
<source>Show grid</source>
<translation>Zobrazit mřížku</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="368"/>
<location filename="../src/gui.cpp" line="442"/>
<source>Show toolbars</source>
<translation>Zobrazovat nástrojové lišty</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="374"/>
<location filename="../src/gui.cpp" line="448"/>
<source>Total time</source>
<translation>Celkový čas</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="379"/>
<location filename="../src/gui.cpp" line="899"/>
<location filename="../src/gui.cpp" line="453"/>
<location filename="../src/gui.cpp" line="974"/>
<source>Moving time</source>
<translation>Čistý čas</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="386"/>
<location filename="../src/gui.cpp" line="460"/>
<source>Metric</source>
<translation>Metrické</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="391"/>
<location filename="../src/gui.cpp" line="465"/>
<source>Imperial</source>
<translation>Imperiální</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="397"/>
<location filename="../src/gui.cpp" line="471"/>
<source>Fullscreen mode</source>
<translation>Celoobrazovkový režim</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="403"/>
<location filename="../src/gui.cpp" line="477"/>
<source>Options...</source>
<translation>Nastavení...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="408"/>
<location filename="../src/gui.cpp" line="482"/>
<source>Next</source>
<translation>Následující</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="411"/>
<location filename="../src/gui.cpp" line="485"/>
<source>Previous</source>
<translation>Předchozí</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="415"/>
<location filename="../src/gui.cpp" line="489"/>
<source>Last</source>
<translation>Poslední</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="418"/>
<location filename="../src/gui.cpp" line="492"/>
<source>First</source>
<translation>První</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="440"/>
<location filename="../src/gui.cpp" line="514"/>
<source>Map</source>
<translation>Mapa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="447"/>
<location filename="../src/gui.cpp" line="522"/>
<source>Graph</source>
<translation>Graf</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="455"/>
<location filename="../src/gui.cpp" line="530"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="456"/>
<location filename="../src/gui.cpp" line="531"/>
<source>POI files</source>
<translation>POI soubory</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="467"/>
<location filename="../src/gui.cpp" line="542"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="468"/>
<location filename="../src/gui.cpp" line="543"/>
<source>Display</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="476"/>
<location filename="../src/gui.cpp" line="551"/>
<source>Settings</source>
<translation>Nastavení</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="480"/>
<location filename="../src/gui.cpp" line="555"/>
<source>Units</source>
<translation>Jednotky</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="489"/>
<location filename="../src/gui.cpp" line="564"/>
<source>Help</source>
<translation>Nápověda</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="604"/>
<location filename="../src/gui.cpp" line="679"/>
<source>Append file</source>
<translation>Přidat soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="605"/>
<location filename="../src/gui.cpp" line="680"/>
<source>Next/Previous</source>
<translation>Následující/Předchozí</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="608"/>
<location filename="../src/gui.cpp" line="683"/>
<source>Previous map</source>
<translation>Předchozí mapa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="609"/>
<location filename="../src/gui.cpp" line="684"/>
<source>Zoom in</source>
<translation>Přiblížit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="611"/>
<location filename="../src/gui.cpp" line="686"/>
<source>Zoom out</source>
<translation>Oddálit</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="613"/>
<location filename="../src/gui.cpp" line="688"/>
<source>Digital zoom</source>
<translation>Digitální zoom</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="614"/>
<location filename="../src/gui.cpp" line="689"/>
<source>Zoom</source>
<translation>Zoom</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="626"/>
<location filename="../src/gui.cpp" line="701"/>
<source>Online maps</source>
<translation>Online mapy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="627"/>
<location filename="../src/gui.cpp" line="702"/>
<source>Online map URLs are read on program startup from the following file:</source>
<translation>URL online map jsou načteny při startu programu z následujícího souboru:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="638"/>
<location filename="../src/gui.cpp" line="713"/>
<source>Offline maps are loaded on program startup from the following directory:</source>
<translation>Offline mapy jsou načítány při startu aplikace z následujícího adresáře:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="641"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziMap image-based maps and tiled TrekBuddy maps/atlases (tared and non-tared).</source>
<translation>Očekávaná struktura je jedna mapa/atlas v samostatném podadresáři. Podporované mapové formáty jsou OziMap mapy a TrekBuddy mapy/atlasy (včetně tar varianty).</translation>
<location filename="../src/gui.cpp" line="716"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziExplorer image-based maps and tiled TrekBuddy maps/atlases (tared and non-tared).</source>
<translation>Očekávaná struktura je jedna mapa/atlas v samostatném podadresáři. Podporované mapové formáty jsou OziExplorer mapy a TrekBuddy mapy/atlasy (včetně tar varianty).</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1097"/>
<location filename="../src/gui.cpp" line="1198"/>
<source>No files loaded</source>
<translation>Nejsou načteny žádné soubory</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="106"/>
<location filename="../src/gui.cpp" line="108"/>
<source>GPX files (*.gpx)</source>
<translation>Soubory GPX (*.gpx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="108"/>
<location filename="../src/gui.cpp" line="110"/>
<source>TCX files (*.tcx)</source>
<translation>Soubory TCX (*.tcx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="107"/>
<location filename="../src/gui.cpp" line="109"/>
<source>KML files (*.kml)</source>
<translation>Soubory KML (*.kml)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="105"/>
<location filename="../src/gui.cpp" line="107"/>
<source>CSV files (*.csv)</source>
<translation>Soubory CSV (*.csv)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="108"/>
<location filename="../src/gui.cpp" line="110"/>
<source>All files (*)</source>
<translation>Všechny soubory (*)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="885"/>
<location filename="../src/gui.cpp" line="888"/>
<location filename="../src/gui.cpp" line="960"/>
<location filename="../src/gui.cpp" line="963"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="877"/>
<location filename="../src/gui.cpp" line="952"/>
<source>Routes</source>
<translation>Trasy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1166"/>
<source>Map files (*.map *.tba *.tar)</source>
<translation>Mapové soubory (*.map *.tba *.tar)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1183"/>
<source>Error loading map:</source>
<translation>Mapu nelze načíst:</translation>
</message>
<message numerus="yes">
<location filename="../src/gui.cpp" line="1101"/>
<location filename="../src/gui.cpp" line="1202"/>
<source>%n files</source>
<translation>
<numerusform>%n soubor</numerusform>
@ -543,122 +559,122 @@
</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="598"/>
<location filename="../src/gui.cpp" line="673"/>
<source>Next file</source>
<translation>Následující soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="575"/>
<location filename="../src/gui.cpp" line="650"/>
<source>Version </source>
<translation>Verze </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="242"/>
<location filename="../src/gui.cpp" line="315"/>
<source>Print...</source>
<translation>Tisknout...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="247"/>
<location filename="../src/gui.cpp" line="320"/>
<source>Export to PDF...</source>
<translation>Exportovat do PDF...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="879"/>
<location filename="../src/gui.cpp" line="954"/>
<source>Waypoints</source>
<translation>Navigační body</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="599"/>
<location filename="../src/gui.cpp" line="674"/>
<source>Previous file</source>
<translation>Předchozí soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="104"/>
<location filename="../src/gui.cpp" line="106"/>
<source>Supported files (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</source>
<translation>Podporované soubory (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="333"/>
<location filename="../src/gui.cpp" line="407"/>
<source>Route waypoints</source>
<translation>Body tras</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="601"/>
<location filename="../src/gui.cpp" line="676"/>
<source>First file</source>
<translation>První soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="603"/>
<location filename="../src/gui.cpp" line="678"/>
<source>Last file</source>
<translation>Poslední soubor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="630"/>
<location filename="../src/gui.cpp" line="705"/>
<source>The file format is one map entry per line, consisting of the map name and tiles URL delimited by a TAB character. The tile X and Y coordinates are replaced with $x and $y in the URL and the zoom level is replaced with $z. An example map file could look like:</source>
<translation>Formát souboru je jeden mapový záznam na řádku, kde mapový záznam sestává ze jména mapy a URL dlaždic navzájem oddělených tabulátorem. Souřadnice dlaždice jsou v URL nahrazeny řetězci $x a $y, úroven přiblížení (zoom) pak řetězcem $z. Příklad:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="637"/>
<location filename="../src/gui.cpp" line="712"/>
<source>Offline maps</source>
<translation>Offline mapy</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="646"/>
<location filename="../src/gui.cpp" line="721"/>
<source>To make GPXSee load a POI file automatically on startup, add the file to the following directory:</source>
<translation>POI soubory, které se mají automaticky nahrát při startu programu jsou načítány z následujícího adresáře:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="735"/>
<location filename="../src/gui.cpp" line="810"/>
<source>Error loading data file:</source>
<translation>Datový soubor nelze načíst:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="738"/>
<location filename="../src/gui.cpp" line="763"/>
<location filename="../src/gui.cpp" line="813"/>
<location filename="../src/gui.cpp" line="838"/>
<source>Line: %1</source>
<translation>Řádka: %1</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="760"/>
<location filename="../src/gui.cpp" line="835"/>
<source>Error loading POI file:</source>
<translation>Soubor POI nelze načíst:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="871"/>
<location filename="../src/gui.cpp" line="946"/>
<source>Name</source>
<translation>Název</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="875"/>
<location filename="../src/gui.cpp" line="950"/>
<source>Tracks</source>
<translation>Cesty</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="232"/>
<location filename="../src/gui.cpp" line="574"/>
<location filename="../src/gui.cpp" line="305"/>
<location filename="../src/gui.cpp" line="649"/>
<source>About GPXSee</source>
<translation>O aplikaci GPXSee</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="513"/>
<location filename="../src/gui.cpp" line="588"/>
<source>Navigation</source>
<translation>Navigace</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="645"/>
<location filename="../src/gui.cpp" line="720"/>
<source>POIs</source>
<translation>POI body</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="348"/>
<location filename="../src/gui.cpp" line="895"/>
<location filename="../src/gui.cpp" line="422"/>
<location filename="../src/gui.cpp" line="970"/>
<source>Distance</source>
<translation>Vzdálenost</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="355"/>
<location filename="../src/gui.cpp" line="477"/>
<location filename="../src/gui.cpp" line="897"/>
<location filename="../src/gui.cpp" line="429"/>
<location filename="../src/gui.cpp" line="552"/>
<location filename="../src/gui.cpp" line="972"/>
<source>Time</source>
<translation>Čas</translation>
</message>

1100
lang/gpxsee_de.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -190,320 +190,336 @@
<context>
<name>GUI</name>
<message>
<location filename="../src/gui.cpp" line="578"/>
<location filename="../src/gui.cpp" line="653"/>
<source>GPXSee is distributed under the terms of the GNU General Public License version 3. For more info about GPXSee visit the project homepage at </source>
<translation>GPXSee distribueras under vilkoren för GNU General Public License version 3. För mer info om GPXSee, besök hemsidan </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="656"/>
<location filename="../src/gui.cpp" line="731"/>
<source>Open file</source>
<translation>Öppna fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="746"/>
<location filename="../src/gui.cpp" line="821"/>
<source>Open POI file</source>
<translation>Öppna POI-fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="237"/>
<location filename="../src/gui.cpp" line="310"/>
<source>Open</source>
<translation>Öppna</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="221"/>
<location filename="../src/gui.cpp" line="294"/>
<source>Quit</source>
<translation>Avsluta</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="229"/>
<location filename="../src/gui.cpp" line="594"/>
<location filename="../src/gui.cpp" line="595"/>
<location filename="../src/gui.cpp" line="302"/>
<location filename="../src/gui.cpp" line="669"/>
<location filename="../src/gui.cpp" line="670"/>
<source>Keyboard controls</source>
<translation>Snabbtangenter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="253"/>
<location filename="../src/gui.cpp" line="326"/>
<source>Close</source>
<translation>Stäng</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="259"/>
<location filename="../src/gui.cpp" line="332"/>
<source>Reload</source>
<translation>Uppdatera</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="508"/>
<location filename="../src/gui.cpp" line="583"/>
<source>Show</source>
<translation>Visa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="426"/>
<location filename="../src/gui.cpp" line="502"/>
<location filename="../src/gui.cpp" line="500"/>
<location filename="../src/gui.cpp" line="577"/>
<source>File</source>
<translation>Arkiv</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="105"/>
<location filename="../src/gui.cpp" line="107"/>
<source>FIT files (*.fit)</source>
<translation>FIT-filer (*.fit)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="106"/>
<location filename="../src/gui.cpp" line="108"/>
<source>IGC files (*.igc)</source>
<translation>IGC-filer (*.igc)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="107"/>
<location filename="../src/gui.cpp" line="109"/>
<source>NMEA files (*.nmea)</source>
<translation>NMEA-filer (*.nmea)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="227"/>
<location filename="../src/gui.cpp" line="623"/>
<location filename="../src/gui.cpp" line="624"/>
<location filename="../src/gui.cpp" line="300"/>
<location filename="../src/gui.cpp" line="698"/>
<location filename="../src/gui.cpp" line="699"/>
<source>Data sources</source>
<translation>Datakällor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="267"/>
<location filename="../src/gui.cpp" line="340"/>
<source>Load POI file</source>
<translation>Läs in POI-fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="270"/>
<location filename="../src/gui.cpp" line="343"/>
<source>Close POI files</source>
<translation>Stäng POI-filer</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="272"/>
<location filename="../src/gui.cpp" line="345"/>
<source>Overlap POIs</source>
<translation>Överlappa POI:er</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="276"/>
<location filename="../src/gui.cpp" line="349"/>
<source>Show POI labels</source>
<translation>Visa POI-namn</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="281"/>
<location filename="../src/gui.cpp" line="354"/>
<source>Show POIs</source>
<translation>Visa POI:er</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="290"/>
<location filename="../src/gui.cpp" line="363"/>
<source>Show map</source>
<translation>Visa karta</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="297"/>
<location filename="../src/gui.cpp" line="370"/>
<location filename="../src/gui.cpp" line="1165"/>
<source>Load map</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui.cpp" line="373"/>
<source>Clear tile cache</source>
<translation>Rensa kart-cache</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="306"/>
<location filename="../src/gui.cpp" line="310"/>
<location filename="../src/gui.cpp" line="606"/>
<location filename="../src/gui.cpp" line="377"/>
<location filename="../src/gui.cpp" line="381"/>
<location filename="../src/gui.cpp" line="681"/>
<source>Next map</source>
<translation>Nästa karta</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="317"/>
<location filename="../src/gui.cpp" line="391"/>
<source>Show tracks</source>
<translation>Visa spår</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="321"/>
<location filename="../src/gui.cpp" line="395"/>
<source>Show routes</source>
<translation>Visa rutter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="325"/>
<location filename="../src/gui.cpp" line="399"/>
<source>Show waypoints</source>
<translation>Visa vägpunkter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="329"/>
<location filename="../src/gui.cpp" line="403"/>
<source>Waypoint labels</source>
<translation>Vägpunktsnamn</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="340"/>
<location filename="../src/gui.cpp" line="414"/>
<source>Show graphs</source>
<translation>Visa diagram</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="362"/>
<location filename="../src/gui.cpp" line="436"/>
<source>Show grid</source>
<translation>Visa stödlinjer</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="368"/>
<location filename="../src/gui.cpp" line="442"/>
<source>Show toolbars</source>
<translation>Visa verktygsfält</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="374"/>
<location filename="../src/gui.cpp" line="448"/>
<source>Total time</source>
<translation>Total tid</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="379"/>
<location filename="../src/gui.cpp" line="899"/>
<location filename="../src/gui.cpp" line="453"/>
<location filename="../src/gui.cpp" line="974"/>
<source>Moving time</source>
<translation>Förflyttningstid</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="386"/>
<location filename="../src/gui.cpp" line="460"/>
<source>Metric</source>
<translation>Meter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="391"/>
<location filename="../src/gui.cpp" line="465"/>
<source>Imperial</source>
<translation>Imperial</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="397"/>
<location filename="../src/gui.cpp" line="471"/>
<source>Fullscreen mode</source>
<translation>Helskärmsläge</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="403"/>
<location filename="../src/gui.cpp" line="477"/>
<source>Options...</source>
<translation>Alternativ...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="408"/>
<location filename="../src/gui.cpp" line="482"/>
<source>Next</source>
<translation>Nästa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="411"/>
<location filename="../src/gui.cpp" line="485"/>
<source>Previous</source>
<translation>Föregående</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="415"/>
<location filename="../src/gui.cpp" line="489"/>
<source>Last</source>
<translation>Sista</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="418"/>
<location filename="../src/gui.cpp" line="492"/>
<source>First</source>
<translation>Första</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="440"/>
<location filename="../src/gui.cpp" line="514"/>
<source>Map</source>
<translation>Karta</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="447"/>
<location filename="../src/gui.cpp" line="522"/>
<source>Graph</source>
<translation>Diagram</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="455"/>
<location filename="../src/gui.cpp" line="530"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="456"/>
<location filename="../src/gui.cpp" line="531"/>
<source>POI files</source>
<translation>POI-filer</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="467"/>
<location filename="../src/gui.cpp" line="542"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="468"/>
<location filename="../src/gui.cpp" line="543"/>
<source>Display</source>
<translation>Visa</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="476"/>
<location filename="../src/gui.cpp" line="551"/>
<source>Settings</source>
<translation>Inställningar</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="480"/>
<location filename="../src/gui.cpp" line="555"/>
<source>Units</source>
<translation>Enhet</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="489"/>
<location filename="../src/gui.cpp" line="564"/>
<source>Help</source>
<translation>Hjälp</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="604"/>
<location filename="../src/gui.cpp" line="679"/>
<source>Append file</source>
<translation>Lägg till fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="605"/>
<location filename="../src/gui.cpp" line="680"/>
<source>Next/Previous</source>
<translation>Nästa/Föregående</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="608"/>
<location filename="../src/gui.cpp" line="683"/>
<source>Previous map</source>
<translation>Föregående karta</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="609"/>
<location filename="../src/gui.cpp" line="684"/>
<source>Zoom in</source>
<translation>Zooma in</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="611"/>
<location filename="../src/gui.cpp" line="686"/>
<source>Zoom out</source>
<translation>Zooma ut</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="613"/>
<location filename="../src/gui.cpp" line="688"/>
<source>Digital zoom</source>
<translation>Digital zoom</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="614"/>
<location filename="../src/gui.cpp" line="689"/>
<source>Zoom</source>
<translation>Zoom</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="626"/>
<location filename="../src/gui.cpp" line="701"/>
<source>Online maps</source>
<translation>Online-kartor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="627"/>
<location filename="../src/gui.cpp" line="702"/>
<source>Online map URLs are read on program startup from the following file:</source>
<translation>Online-kartors URL:er, läses från följande fil vid programstart:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="637"/>
<location filename="../src/gui.cpp" line="712"/>
<source>Offline maps</source>
<translation>Offline-kartor</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="638"/>
<location filename="../src/gui.cpp" line="713"/>
<source>Offline maps are loaded on program startup from the following directory:</source>
<translation>Offline-kartor läses in från följande mapp vid programstart:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="641"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziMap image-based maps and tiled TrekBuddy maps/atlases (tared and non-tared).</source>
<translation>Den förväntade strukturen är en karta/atlas i en separat undermapp. Kartformat som stöds är OziMap bildbaserade kartor och rutindelade TrekBuddy-kartor/-kartsamlingar (tarerade och icke tarerade).</translation>
<location filename="../src/gui.cpp" line="716"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziExplorer image-based maps and tiled TrekBuddy maps/atlases (tared and non-tared).</source>
<translation>Den förväntade strukturen är en karta/atlas i en separat undermapp. Kartformat som stöds är OziExplorer bildbaserade kartor och rutindelade TrekBuddy-kartor/-kartsamlingar (tarerade och icke tarerade).</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1097"/>
<location filename="../src/gui.cpp" line="1166"/>
<source>Map files (*.map *.tba *.tar)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1183"/>
<source>Error loading map:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../src/gui.cpp" line="1198"/>
<source>No files loaded</source>
<translation>Inga filer inlästa</translation>
</message>
<message numerus="yes">
<location filename="../src/gui.cpp" line="1101"/>
<location filename="../src/gui.cpp" line="1202"/>
<source>%n files</source>
<translation>
<numerusform>%n filer</numerusform>
@ -511,153 +527,153 @@
</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="106"/>
<location filename="../src/gui.cpp" line="108"/>
<source>GPX files (*.gpx)</source>
<translation>GPX-filer (*.gpx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="108"/>
<location filename="../src/gui.cpp" line="110"/>
<source>TCX files (*.tcx)</source>
<translation>TCX-filer (*.tcx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="107"/>
<location filename="../src/gui.cpp" line="109"/>
<source>KML files (*.kml)</source>
<translation>KML-filer (*.kml)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="105"/>
<location filename="../src/gui.cpp" line="107"/>
<source>CSV files (*.csv)</source>
<translation>CSV-filer (*.csv)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="108"/>
<location filename="../src/gui.cpp" line="110"/>
<source>All files (*)</source>
<translation>Alla filer (*)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="885"/>
<location filename="../src/gui.cpp" line="888"/>
<location filename="../src/gui.cpp" line="960"/>
<location filename="../src/gui.cpp" line="963"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="877"/>
<location filename="../src/gui.cpp" line="952"/>
<source>Routes</source>
<translation>Rutter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="598"/>
<location filename="../src/gui.cpp" line="673"/>
<source>Next file</source>
<translation>Nästa fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="575"/>
<location filename="../src/gui.cpp" line="650"/>
<source>Version </source>
<translation>Version </translation>
</message>
<message>
<location filename="../src/gui.cpp" line="242"/>
<location filename="../src/gui.cpp" line="315"/>
<source>Print...</source>
<translation>Skriv ut...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="247"/>
<location filename="../src/gui.cpp" line="320"/>
<source>Export to PDF...</source>
<translation>Exportera till PDF...</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="879"/>
<location filename="../src/gui.cpp" line="954"/>
<source>Waypoints</source>
<translation>Vägpunkter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="599"/>
<location filename="../src/gui.cpp" line="674"/>
<source>Previous file</source>
<translation>Föregående fil</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="104"/>
<location filename="../src/gui.cpp" line="106"/>
<source>Supported files (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</source>
<translation>Filer som stöds (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="333"/>
<location filename="../src/gui.cpp" line="407"/>
<source>Route waypoints</source>
<translation>Ruttvägpunkter</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="601"/>
<location filename="../src/gui.cpp" line="676"/>
<source>First file</source>
<translation>Första filen</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="603"/>
<location filename="../src/gui.cpp" line="678"/>
<source>Last file</source>
<translation>Sista filen</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="630"/>
<location filename="../src/gui.cpp" line="705"/>
<source>The file format is one map entry per line, consisting of the map name and tiles URL delimited by a TAB character. The tile X and Y coordinates are replaced with $x and $y in the URL and the zoom level is replaced with $z. An example map file could look like:</source>
<translation>Filformatet är en kartpost per rad, bestående av kartnamn och kartrutans URL, avgränsade med ett TAB-tecken. Kartrutans X- och Y-koordinater ersätts med $x och $y i URL:en och zoomnivån ersätts med $z. Exempel en kartfil kan se ut här:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="646"/>
<location filename="../src/gui.cpp" line="721"/>
<source>To make GPXSee load a POI file automatically on startup, add the file to the following directory:</source>
<translation>För att GPXSee skall läsa in en POI-fil automatiskt vid programstart, läggs filen i följande mapp:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="735"/>
<location filename="../src/gui.cpp" line="810"/>
<source>Error loading data file:</source>
<translation>Fel vid inläsning av datafil:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="738"/>
<location filename="../src/gui.cpp" line="763"/>
<location filename="../src/gui.cpp" line="813"/>
<location filename="../src/gui.cpp" line="838"/>
<source>Line: %1</source>
<translation>Rad: %1</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="760"/>
<location filename="../src/gui.cpp" line="835"/>
<source>Error loading POI file:</source>
<translation>Fel vid inläsning av POI-fil:</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="871"/>
<location filename="../src/gui.cpp" line="946"/>
<source>Name</source>
<translation>Namn</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="875"/>
<location filename="../src/gui.cpp" line="950"/>
<source>Tracks</source>
<translation>Spår</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="232"/>
<location filename="../src/gui.cpp" line="574"/>
<location filename="../src/gui.cpp" line="305"/>
<location filename="../src/gui.cpp" line="649"/>
<source>About GPXSee</source>
<translation>Om GPXSee</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="513"/>
<location filename="../src/gui.cpp" line="588"/>
<source>Navigation</source>
<translation>Navigation</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="645"/>
<location filename="../src/gui.cpp" line="720"/>
<source>POIs</source>
<translation>POI:er</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="348"/>
<location filename="../src/gui.cpp" line="895"/>
<location filename="../src/gui.cpp" line="422"/>
<location filename="../src/gui.cpp" line="970"/>
<source>Distance</source>
<translation>Avstånd</translation>
</message>
<message>
<location filename="../src/gui.cpp" line="355"/>
<location filename="../src/gui.cpp" line="477"/>
<location filename="../src/gui.cpp" line="897"/>
<location filename="../src/gui.cpp" line="429"/>
<location filename="../src/gui.cpp" line="552"/>
<location filename="../src/gui.cpp" line="972"/>
<source>Time</source>
<translation>Tid</translation>
</message>

123
pkg/datums.csv Normal file
View File

@ -0,0 +1,123 @@
Adindan,4201,5,-162,-12,206
Afgooye,4205,15,-43,-163,45
Ain el Abd 1970,4204,14,-150,-251,-2
Anna 1 Astro 1965,4708,2,-491,-22,435
Arc 1950,4209,5,-143,-90,-294
Arc 1960,4210,5,-160,-8,-300
Ascension Island 1958,4712,14,-207,107,52
Astro B4 Sorol Atoll,4707,14,114,-116,-333
Astro Beacon 1945,4709,14,145,75,-272
Astro DOS 71/4,4710,14,-320,550,-494
Astronomic Stn 1952,4711,14,124,-234,-25
Australian Geodetic 1966,4202,2,-133,-48,148
Australian Geodetic 1984,4203,2,-134,-48,149
Australian Geocentric 1994 (GDA94),4283,11,0,0,0
Austrian,4312,3,594,84,471
Bellevue (IGN),4714,14,-127,-769,472
Bermuda 1957,4216,4,-73,213,296
Bogota Observatory,4218,14,307,304,-318
Campo Inchauspe,4221,14,-148,136,90
Canton Astro 1966,4716,14,298,-304,-375
Cape,4222,5,-136,-108,-292
Cape Canaveral,4717,4,-2,150,181
Carthage,4223,5,-263,6,431
CH-1903,4149,3,674,15,405
Chatham 1971,4672,14,175,-38,113
Chua Astro,4224,14,-134,229,-29
Corrego Alegre,4225,14,-206,172,-6
Djakarta (Batavia),4211,3,-377,681,-50
DOS 1968,,14,230,-199,-752
Easter Island 1967,4719,14,211,147,111
Egypt,,14,-130,-117,-151
European 1950,4230,14,-87,-98,-121
European 1950 (Mean France),,14,-87,-96,-120
European 1950 (Spain and Portugal),,14,-84,-107,-120
European 1979,4668,14,-86,-98,-119
Finland Hayford,4123,14,-78,-231,-97
Gandajika Base,4233,14,-133,-321,50
Geodetic Datum 1949,4272,14,84,-22,209
GGRS 87,4121,11,-199.87,74.79,246.62
Guam 1963,4675,4,-100,-248,259
GUX 1 Astro,4718,14,252,-209,-751
Hartebeeshoek94,4148,20,0,0,0
Hermannskogel,3906,3,653,-212,449
Hjorsey 1955,4658,14,-73,46,-86
Hong Kong 1963,4739,14,-156,-271,-189
Hu-Tzu-Shan,4236,14,-634,-549,-201
Indian Bangladesh,4682,6,289,734,257
Indian Thailand,4240,6,214,836,303
Israeli,4281,23,-235,-85,264
Ireland 1965,4299,1,506,-122,611
ISTS 073 Astro 1969,4724,14,208,-435,-229
Johnston Island,4725,14,191,-77,-204
Kandawala,4244,6,-97,787,86
Kerguelen Island,4698,14,145,-187,103
Kertau 1948,4245,7,-11,851,5
L.C. 5 Astro,4726,4,42,124,147
Liberia 1964,4251,5,-90,40,88
Luzon Mindanao,,4,-133,-79,-72
Luzon Philippines,4253,4,-133,-77,-51
Mahe 1971,4256,5,41,-220,-134
Marco Astro,4616,14,-289,-124,60
Massawa,4262,3,639,405,60
Merchich,4261,5,31,146,47
Midway Astro 1961,4727,14,912,-58,1227
Minna,4263,5,-92,-93,122
NAD27 Alaska,,4,-5,135,172
NAD27 Bahamas,,4,-4,154,178
NAD27 Canada,,4,-10,158,187
NAD27 Canal Zone,,4,0,125,201
NAD27 Caribbean,,4,-7,152,178
NAD27 Central,,4,0,125,194
NAD27 CONUS,,4,-8,160,176
NAD27 Cuba,,4,-9,152,178
NAD27 Greenland,,4,11,114,195
NAD27 Mexico,,4,-12,130,190
NAD27 San Salvador,,4,1,140,165
NAD83,4269,11,0,0,0
Nahrwn Masirah Ilnd,,5,-247,-148,369
Nahrwn Saudi Arbia,,5,-231,-196,482
Nahrwn United Arab,,5,-249,-156,381
Naparima BWI,4271,14,-2,374,172
NGO1948,4273,27,315,-217,528
NTF France,4275,24,-168,-60,320
Norsk,4817,27,278,93,474
NZGD1949,4272,14,84,-22,209
NZGD2000,4167,20,0,0,0
Observatorio 1966,4182,14,-425,-169,81
Old Egyptian,4229,12,-130,110,-13
Old Hawaiian,4135,4,61,-285,-181
Oman,4232,5,-346,-1,224
Ord Srvy Grt Britn,4277,0,375,-111,431
Pico De Las Nieves,4728,14,-307,-92,127
Pitcairn Astro 1967,4729,14,185,165,42
Potsdam Rauenberg DHDN,4314,3,606,23,413
Prov So Amrican 1956,4248,14,-288,175,-376
Prov So Chilean 1963,4254,14,16,196,93
Puerto Rico,4139,4,11,72,-101
Pulkovo 1942 (1),4284,15,28,-130,-95
Pulkovo 1942 (2),4284,15,28,-130,-95
Qatar National,4285,14,-128,-283,22
Qornoq,4287,14,164,138,-189
Reunion,4626,14,94,-948,-1262
Rijksdriehoeksmeting,4289,3,593,26,478
Rome 1940,4806,14,-225,-65,9
RT 90,4124,3,498,-36,568
S42,4179,15,28,-121,-77
Santo (DOS),4730,14,170,42,84
Sao Braz,4184,14,-203,141,53
Sapper Hill 1943,4292,14,-355,16,74
Schwarzeck,4293,21,616,97,-251
South American 1969,4291,16,-57,1,-41
South Asia,,8,7,-10,-26
Southeast Base,4615,14,-499,-249,314
Southwest Base,4183,14,-104,167,-38
Timbalai 1948,4298,6,-689,691,-46
Tokyo,4301,3,-128,481,664
Tristan Astro 1968,4734,14,-632,438,-609
Viti Levu 1916,4731,5,51,391,-36
Wake-Eniwetok 1960,4732,13,101,52,-39
WGS 72,4322,19,0,0,5
WGS 84,4326,20,0,0,0
Yacare,4309,14,-155,171,37
Zanderij,4311,14,-265,120,-358
1 Adindan 4201 5 -162 -12 206
2 Afgooye 4205 15 -43 -163 45
3 Ain el Abd 1970 4204 14 -150 -251 -2
4 Anna 1 Astro 1965 4708 2 -491 -22 435
5 Arc 1950 4209 5 -143 -90 -294
6 Arc 1960 4210 5 -160 -8 -300
7 Ascension Island 1958 4712 14 -207 107 52
8 Astro B4 Sorol Atoll 4707 14 114 -116 -333
9 Astro Beacon 1945 4709 14 145 75 -272
10 Astro DOS 71/4 4710 14 -320 550 -494
11 Astronomic Stn 1952 4711 14 124 -234 -25
12 Australian Geodetic 1966 4202 2 -133 -48 148
13 Australian Geodetic 1984 4203 2 -134 -48 149
14 Australian Geocentric 1994 (GDA94) 4283 11 0 0 0
15 Austrian 4312 3 594 84 471
16 Bellevue (IGN) 4714 14 -127 -769 472
17 Bermuda 1957 4216 4 -73 213 296
18 Bogota Observatory 4218 14 307 304 -318
19 Campo Inchauspe 4221 14 -148 136 90
20 Canton Astro 1966 4716 14 298 -304 -375
21 Cape 4222 5 -136 -108 -292
22 Cape Canaveral 4717 4 -2 150 181
23 Carthage 4223 5 -263 6 431
24 CH-1903 4149 3 674 15 405
25 Chatham 1971 4672 14 175 -38 113
26 Chua Astro 4224 14 -134 229 -29
27 Corrego Alegre 4225 14 -206 172 -6
28 Djakarta (Batavia) 4211 3 -377 681 -50
29 DOS 1968 14 230 -199 -752
30 Easter Island 1967 4719 14 211 147 111
31 Egypt 14 -130 -117 -151
32 European 1950 4230 14 -87 -98 -121
33 European 1950 (Mean France) 14 -87 -96 -120
34 European 1950 (Spain and Portugal) 14 -84 -107 -120
35 European 1979 4668 14 -86 -98 -119
36 Finland Hayford 4123 14 -78 -231 -97
37 Gandajika Base 4233 14 -133 -321 50
38 Geodetic Datum 1949 4272 14 84 -22 209
39 GGRS 87 4121 11 -199.87 74.79 246.62
40 Guam 1963 4675 4 -100 -248 259
41 GUX 1 Astro 4718 14 252 -209 -751
42 Hartebeeshoek94 4148 20 0 0 0
43 Hermannskogel 3906 3 653 -212 449
44 Hjorsey 1955 4658 14 -73 46 -86
45 Hong Kong 1963 4739 14 -156 -271 -189
46 Hu-Tzu-Shan 4236 14 -634 -549 -201
47 Indian Bangladesh 4682 6 289 734 257
48 Indian Thailand 4240 6 214 836 303
49 Israeli 4281 23 -235 -85 264
50 Ireland 1965 4299 1 506 -122 611
51 ISTS 073 Astro 1969 4724 14 208 -435 -229
52 Johnston Island 4725 14 191 -77 -204
53 Kandawala 4244 6 -97 787 86
54 Kerguelen Island 4698 14 145 -187 103
55 Kertau 1948 4245 7 -11 851 5
56 L.C. 5 Astro 4726 4 42 124 147
57 Liberia 1964 4251 5 -90 40 88
58 Luzon Mindanao 4 -133 -79 -72
59 Luzon Philippines 4253 4 -133 -77 -51
60 Mahe 1971 4256 5 41 -220 -134
61 Marco Astro 4616 14 -289 -124 60
62 Massawa 4262 3 639 405 60
63 Merchich 4261 5 31 146 47
64 Midway Astro 1961 4727 14 912 -58 1227
65 Minna 4263 5 -92 -93 122
66 NAD27 Alaska 4 -5 135 172
67 NAD27 Bahamas 4 -4 154 178
68 NAD27 Canada 4 -10 158 187
69 NAD27 Canal Zone 4 0 125 201
70 NAD27 Caribbean 4 -7 152 178
71 NAD27 Central 4 0 125 194
72 NAD27 CONUS 4 -8 160 176
73 NAD27 Cuba 4 -9 152 178
74 NAD27 Greenland 4 11 114 195
75 NAD27 Mexico 4 -12 130 190
76 NAD27 San Salvador 4 1 140 165
77 NAD83 4269 11 0 0 0
78 Nahrwn Masirah Ilnd 5 -247 -148 369
79 Nahrwn Saudi Arbia 5 -231 -196 482
80 Nahrwn United Arab 5 -249 -156 381
81 Naparima BWI 4271 14 -2 374 172
82 NGO1948 4273 27 315 -217 528
83 NTF France 4275 24 -168 -60 320
84 Norsk 4817 27 278 93 474
85 NZGD1949 4272 14 84 -22 209
86 NZGD2000 4167 20 0 0 0
87 Observatorio 1966 4182 14 -425 -169 81
88 Old Egyptian 4229 12 -130 110 -13
89 Old Hawaiian 4135 4 61 -285 -181
90 Oman 4232 5 -346 -1 224
91 Ord Srvy Grt Britn 4277 0 375 -111 431
92 Pico De Las Nieves 4728 14 -307 -92 127
93 Pitcairn Astro 1967 4729 14 185 165 42
94 Potsdam Rauenberg DHDN 4314 3 606 23 413
95 Prov So Amrican 1956 4248 14 -288 175 -376
96 Prov So Chilean 1963 4254 14 16 196 93
97 Puerto Rico 4139 4 11 72 -101
98 Pulkovo 1942 (1) 4284 15 28 -130 -95
99 Pulkovo 1942 (2) 4284 15 28 -130 -95
100 Qatar National 4285 14 -128 -283 22
101 Qornoq 4287 14 164 138 -189
102 Reunion 4626 14 94 -948 -1262
103 Rijksdriehoeksmeting 4289 3 593 26 478
104 Rome 1940 4806 14 -225 -65 9
105 RT 90 4124 3 498 -36 568
106 S42 4179 15 28 -121 -77
107 Santo (DOS) 4730 14 170 42 84
108 Sao Braz 4184 14 -203 141 53
109 Sapper Hill 1943 4292 14 -355 16 74
110 Schwarzeck 4293 21 616 97 -251
111 South American 1969 4291 16 -57 1 -41
112 South Asia 8 7 -10 -26
113 Southeast Base 4615 14 -499 -249 314
114 Southwest Base 4183 14 -104 167 -38
115 Timbalai 1948 4298 6 -689 691 -46
116 Tokyo 4301 3 -128 481 664
117 Tristan Astro 1968 4734 14 -632 438 -609
118 Viti Levu 1916 4731 5 51 391 -36
119 Wake-Eniwetok 1960 4732 13 101 52 -39
120 WGS 72 4322 19 0 0 5
121 WGS 84 4326 20 0 0 0
122 Yacare 4309 14 -155 171 37
123 Zanderij 4311 14 -265 120 -358

30
pkg/ellipsoids.csv Normal file
View File

@ -0,0 +1,30 @@
0,Airy 1830,6377563.396,299.3249646
1,Modified Airy,6377340.189,299.3249646
2,Australian National,6378160.0,298.25
3,Bessel 1841,6377397.155,299.1528128
4,Clarke 1866,6378206.4,294.9786982
5,Clarke 1880,6378249.145,293.465
6,Everest (India 1830),6377276.345,300.8017
7,Everest (1948),6377304.063,300.8017
8,Modified Fischer 1960,6378155.0,298.3
9,Everest (Pakistan),6377309.613,300.8017
10,Indonesian 1974,6378160.0,298.247
11,GRS 80,6378137.0,298.257222101
12,Helmert 1906,6378200.0,298.3
13,Hough 1960,6378270.0,297.0
14,International 1924,6378388.0,297.0
15,Krassovsky 1940,6378245.0,298.3
16,South American 1969,6378160.0,298.25
17,Everest (Malaysia 1969),6377295.664,300.8017
18,Everest (Sabah Sarawak),6377298.556,300.8017
19,WGS 72,6378135.0,298.26
20,WGS 84,6378137.0,298.257223563
21,Bessel 1841 (Namibia),6377483.865,299.1528128
22,Everest (India 1956),6377301.243,300.8017
23,Clarke 1880 Palestine,6378300.789,293.466
24,Clarke 1880 IGN,6378249.2,293.466021
25,Hayford 1909,6378388.0,296.959263
26,Clarke 1858,6378350.87,294.26
27,Bessel 1841 (Norway),6377492.0176,299.1528
28,Plessis 1817 (France),6376523.0,308.6409971
29,Hayford 1924,6378388.0,297.0
1 0 Airy 1830 6377563.396 299.3249646
2 1 Modified Airy 6377340.189 299.3249646
3 2 Australian National 6378160.0 298.25
4 3 Bessel 1841 6377397.155 299.1528128
5 4 Clarke 1866 6378206.4 294.9786982
6 5 Clarke 1880 6378249.145 293.465
7 6 Everest (India 1830) 6377276.345 300.8017
8 7 Everest (1948) 6377304.063 300.8017
9 8 Modified Fischer 1960 6378155.0 298.3
10 9 Everest (Pakistan) 6377309.613 300.8017
11 10 Indonesian 1974 6378160.0 298.247
12 11 GRS 80 6378137.0 298.257222101
13 12 Helmert 1906 6378200.0 298.3
14 13 Hough 1960 6378270.0 297.0
15 14 International 1924 6378388.0 297.0
16 15 Krassovsky 1940 6378245.0 298.3
17 16 South American 1969 6378160.0 298.25
18 17 Everest (Malaysia 1969) 6377295.664 300.8017
19 18 Everest (Sabah Sarawak) 6377298.556 300.8017
20 19 WGS 72 6378135.0 298.26
21 20 WGS 84 6378137.0 298.257223563
22 21 Bessel 1841 (Namibia) 6377483.865 299.1528128
23 22 Everest (India 1956) 6377301.243 300.8017
24 23 Clarke 1880 Palestine 6378300.789 293.466
25 24 Clarke 1880 IGN 6378249.2 293.466021
26 25 Hayford 1909 6378388.0 296.959263
27 26 Clarke 1858 6378350.87 294.26
28 27 Bessel 1841 (Norway) 6377492.0176 299.1528
29 28 Plessis 1817 (France) 6376523.0 308.6409971
30 29 Hayford 1924 6378388.0 297.0

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "4.2"
!define VERSION "4.5"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -82,6 +82,8 @@ Section "GPXSee" SEC_APP
; Put the files there
File "gpxsee.exe"
File "maps.txt"
File "ellipsoids.csv"
File "datums.csv"
; Create start menu entry and add links
SetShellVarContext all
@ -250,4 +252,4 @@ LangString DESC_APP ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_ANGLE} $(DESC_ANGLE)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "4.2"
!define VERSION "4.5"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -89,6 +89,8 @@ Section "GPXSee" SEC_APP
; Put the files there
File "gpxsee.exe"
File "maps.txt"
File "ellipsoids.csv"
File "datums.csv"
; Create start menu entry and add links
SetShellVarContext all
@ -253,4 +255,4 @@ LangString DESC_APP ${LANG_ENGLISH} \
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_ANGLE} $(DESC_ANGLE)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
!insertmacro MUI_FUNCTION_DESCRIPTION_END
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -30,25 +30,35 @@ static bool yCmp(const OfflineMap *m1, const OfflineMap *m2)
return TL(m1).y() > TL(m2).y();
}
bool Atlas::isAtlas(Tar &tar, const QFileInfoList &files)
bool Atlas::isAtlas(Tar &tar, const QString &path)
{
for (int i = 0; i < files.count(); i++) {
const QString &fileName = files.at(i).fileName();
if (fileName.endsWith(".tar")) {
if (!tar.load(files.at(i).absoluteFilePath())) {
qWarning("%s: %s: error loading tar file", qPrintable(_name),
qPrintable(fileName));
return false;
}
QStringList tarFiles = tar.files();
for (int j = 0; j < tarFiles.size(); j++)
if (tarFiles.at(j).endsWith(".tba"))
return true;
} else if (fileName.endsWith(".tba"))
return true;
QFileInfo fi(path);
QByteArray ba;
QString suffix = fi.suffix().toLower();
if (suffix == "tar") {
if (!tar.load(path)) {
_errorString = "Error reading tar file";
return false;
}
QString tbaFileName = fi.completeBaseName() + ".tba";
ba = tar.file(tbaFileName);
} else if (suffix == "tba") {
QFile tbaFile(path);
if (!tbaFile.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening tba file: %1")
.arg(tbaFile.errorString());
return false;
}
ba = tbaFile.readAll();
}
return false;
if (ba.startsWith("Atlas 1.0"))
return true;
else {
_errorString = "Missing or invalid tba file";
return false;
}
}
void Atlas::computeZooms()
@ -100,38 +110,45 @@ void Atlas::computeBounds()
BR(_maps.at(i))), QRectF(offsets.at(i), _maps.at(i)->bounds().size())));
}
Atlas::Atlas(const QString &path, QObject *parent) : Map(parent)
Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
{
Tar tar;
QFileInfo fi(fileName);
_valid = false;
_zoom = 0;
_name = fi.dir().dirName();
QFileInfo fi(path);
_name = fi.fileName();
QDir dir(path);
QFileInfoList files = dir.entryInfoList(QDir::Files);
if (!isAtlas(tar, files))
if (!isAtlas(tar, fileName))
return;
QDir dir(fi.absolutePath());
QFileInfoList layers = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (int n = 0; n < layers.count(); n++) {
QDir zdir(layers.at(n).absoluteFilePath());
QFileInfoList maps = zdir.entryInfoList(QDir::Dirs
| QDir::NoDotAndDotDot);
for (int i = 0; i < maps.count(); i++) {
QString mapFile = maps.at(i).absoluteFilePath() + "/"
+ maps.at(i).fileName() + ".map";
OfflineMap *map;
if (tar.isOpen())
map = new OfflineMap(tar, maps.at(i).absoluteFilePath(), this);
map = new OfflineMap(mapFile, tar, this);
else
map = new OfflineMap(maps.at(i).absoluteFilePath(), this);
map = new OfflineMap(mapFile, this);
if (map->isValid())
_maps.append(map);
else {
_errorString = QString("Error loading map: %1: %2")
.arg(mapFile, map->errorString());
return;
}
}
}
if (_maps.isEmpty()) {
qWarning("%s: No usable maps available", qPrintable(_name));
_errorString = "No maps found in atlas";
return;
}
@ -186,7 +203,7 @@ qreal Atlas::zoomFit(const QSize &size, const QRectF &br)
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(br.center())))
if (!_bounds.at(i).first.contains(_maps.at(i)->ll2pp(br.center())))
continue;
QRect sbr = QRectF(_maps.at(i)->ll2xy(br.topLeft()),
@ -278,3 +295,9 @@ void Atlas::draw(QPainter *painter, const QRectF &rect, int mapIndex)
map->draw(painter, pr);
painter->translate(-offset);
}
void Atlas::unload()
{
for (int i = 0; i < _maps.count(); i++)
_maps.at(i)->unload();
}

View File

@ -11,7 +11,7 @@ class Atlas : public Map
Q_OBJECT
public:
Atlas(const QString &path, QObject *parent = 0);
Atlas(const QString &fileName, QObject *parent = 0);
~Atlas();
const QString &name() const {return _name;}
@ -29,16 +29,20 @@ public:
void draw(QPainter *painter, const QRectF &rect);
bool isValid() {return _valid;}
void unload();
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
private:
void draw(QPainter *painter, const QRectF &rect, int mapIndex);
bool isAtlas(Tar &tar, const QFileInfoList &files);
bool isAtlas(Tar &tar, const QString &path);
void computeZooms();
void computeBounds();
QString _name;
bool _valid;
QString _errorString;
QList<OfflineMap*> _maps;
QVector<QPair<int, int> > _zooms;

View File

@ -13,6 +13,8 @@
#define FONT_SIZE 12
#define SCREEN_DPI 96.0
#define ELLIPSOID_FILE QString("ellipsoids.csv")
#define DATUM_FILE QString("datums.csv")
#define MAP_FILE QString("maps.txt")
#define MAP_DIR QString("maps")
#define POI_DIR QString("POI")
@ -29,12 +31,16 @@
#define GLOBAL_DIR QString("/usr/share/gpxsee")
#endif
#define USER_MAP_DIR USER_DIR + QString("/") + MAP_DIR
#define USER_MAP_FILE USER_DIR + QString("/") + MAP_FILE
#define USER_POI_DIR USER_DIR + QString("/") + POI_DIR
#define GLOBAL_MAP_DIR GLOBAL_DIR + QString("/") + MAP_DIR
#define GLOBAL_MAP_FILE GLOBAL_DIR + QString("/") + MAP_FILE
#define GLOBAL_POI_DIR GLOBAL_DIR + QString("/") + POI_DIR
#define TILES_DIR USER_DIR + QString("/tiles")
#define USER_ELLIPSOID_FILE USER_DIR + QString("/") + ELLIPSOID_FILE
#define USER_DATUM_FILE USER_DIR + QString("/") + DATUM_FILE
#define USER_MAP_DIR USER_DIR + QString("/") + MAP_DIR
#define USER_MAP_FILE USER_DIR + QString("/") + MAP_FILE
#define USER_POI_DIR USER_DIR + QString("/") + POI_DIR
#define GLOBAL_ELLIPSOID_FILE GLOBAL_DIR + QString("/") + ELLIPSOID_FILE
#define GLOBAL_DATUM_FILE GLOBAL_DIR + QString("/") + DATUM_FILE
#define GLOBAL_MAP_DIR GLOBAL_DIR + QString("/") + MAP_DIR
#define GLOBAL_MAP_FILE GLOBAL_DIR + QString("/") + MAP_FILE
#define GLOBAL_POI_DIR GLOBAL_DIR + QString("/") + POI_DIR
#define TILES_DIR USER_DIR + QString("/tiles")
#endif /* CONFIG_H */

83
src/datum.cpp Normal file
View File

@ -0,0 +1,83 @@
#include <QFile>
#include "wgs84.h"
#include "datum.h"
static QMap<QString, Datum> WGS84()
{
QMap<QString, Datum> map;
map.insert("WGS 84", Datum(Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING),
0, 0, 0));
return map;
}
QMap<QString, Datum> Datum::_datums = WGS84();
QString Datum::_errorString;
int Datum::_errorLine = 0;
Datum Datum::datum(const QString &name)
{
QMap<QString, Datum>::const_iterator it = _datums.find(name);
if (it == _datums.end())
return Datum();
return it.value();
}
bool Datum::loadList(const QString &path)
{
QFile file(path);
bool res;
if (!file.open(QFile::ReadOnly)) {
_errorString = qPrintable(file.errorString());
return false;
}
_errorLine = 1;
_errorString.clear();
while (!file.atEnd()) {
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() != 6) {
_errorString = "Format error";
return false;
}
int eid = list[2].trimmed().toInt(&res);
if (!res) {
_errorString = "Invalid ellipsoid id";
return false;
}
double dx = list[3].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid dx";
return false;
}
double dy = list[4].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid dy";
return false;
}
double dz = list[5].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid dz";
return false;
}
Ellipsoid e = Ellipsoid::ellipsoid(eid);
if (e.isNull()) {
_errorString = "Unknown ellipsoid ID";
return false;
}
Datum d(e, dx, dy, dz);
_datums.insert(list[0].trimmed(), d);
_errorLine++;
}
return true;
}

38
src/datum.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef DATUM_H
#define DATUM_H
#include <QMap>
#include "ellipsoid.h"
class Datum
{
public:
Datum() : _ellipsoid(Ellipsoid()), _dx(0), _dy(0), _dz(0) {}
Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz)
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz) {}
const Ellipsoid &ellipsoid() const {return _ellipsoid;}
double dx() const {return _dx;}
double dy() const {return _dy;}
double dz() const {return _dz;}
bool isNull() const {return _ellipsoid.isNull();}
bool isWGS84() const
{return _ellipsoid.isWGS84() && _dx == 0 && _dy == 0 && _dz == 0;}
static bool loadList(const QString &path);
static const QString &errorString() {return _errorString;}
static int errorLine() {return _errorLine;}
static Datum datum(const QString &name);
private:
Ellipsoid _ellipsoid;
double _dx, _dy, _dz;
static QMap<QString, Datum> _datums;
static QString _errorString;
static int _errorLine;
};
#endif // DATUM_H

View File

@ -1,96 +1,62 @@
#include <cmath>
#include <QString>
#include "wgs84.h"
#include <QFile>
#include "ellipsoid.h"
QMap<int, Ellipsoid> Ellipsoid::_ellipsoids;
QString Ellipsoid::_errorString;
int Ellipsoid::_errorLine = 0;
#define INTERNATIONAL_RADIUS 6378388.0
#define INTERNATIONAL_FLATTENING (1.0/297.0)
#define KRASSOVSKY_RADIUS 6378245.0
#define KRASSOVSKY_FLATTENING (1.0/298.3)
#define BESSEL_RADIUS 6377397.155
#define BESSEL_FLATTENING (1.0/299.1528128)
#define GRS80_RADIUS 6378137.0
#define GRS80_FLATTENING (1.0/298.257222101)
#define WGS70_RADIUS 6378135.0
#define WGS70_FLATTENING (1.0/298.26)
#define SAD69_RADIUS 6378160.0
#define SAD69_FLATTENING (1.0/298.25)
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#ifndef M_PI_4
#define M_PI_4 0.78539816339744830962
#endif // M_PI_4
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
typedef struct {
const char *name;
double radius;
double flattening;
} Entry;
static Entry list[] = {
{"S42", KRASSOVSKY_RADIUS, KRASSOVSKY_FLATTENING},
{"Pulkovo 1942", KRASSOVSKY_RADIUS, KRASSOVSKY_FLATTENING},
{"European 1950", INTERNATIONAL_RADIUS, INTERNATIONAL_FLATTENING},
{"European 1979", INTERNATIONAL_RADIUS, INTERNATIONAL_FLATTENING},
{"NZGD1949", INTERNATIONAL_RADIUS, INTERNATIONAL_FLATTENING},
{"NAD27", BESSEL_RADIUS, BESSEL_FLATTENING},
{"NAD83", GRS80_RADIUS, GRS80_FLATTENING},
{"WGS 72", WGS70_RADIUS, WGS70_FLATTENING},
{"South American 1969", SAD69_RADIUS, SAD69_FLATTENING}
};
Ellipsoid::Ellipsoid()
Ellipsoid Ellipsoid::ellipsoid(int id)
{
_radius = WGS84_RADIUS;
_flattening = WGS84_FLATTENING;
QMap<int, Ellipsoid>::const_iterator it = _ellipsoids.find(id);
if (it == _ellipsoids.end())
return Ellipsoid();
return it.value();
}
Ellipsoid::Ellipsoid(const QString &datum)
bool Ellipsoid::loadList(const QString &path)
{
for (size_t i = 0; i < ARRAY_SIZE(list); i++) {
if (datum.startsWith(list[i].name)) {
_radius = list[i].radius;
_flattening = list[i].flattening;
return;
}
QFile file(path);
bool res;
if (!file.open(QFile::ReadOnly)) {
_errorString = qPrintable(file.errorString());
return false;
}
_radius = WGS84_RADIUS;
_flattening = WGS84_FLATTENING;
}
double Ellipsoid::q(double b) const
{
double e = sqrt(_flattening * (2. - _flattening));
double esb = e * sin(b);
return log(tan(M_PI_4 + b / 2.) * pow((1. - esb) / (1. + esb), e / 2.));
}
double Ellipsoid::iq(double q) const
{
double e = sqrt(_flattening * (2. - _flattening));
double b0 = 0.;
double b = 2. * atan(exp(q)) - M_PI_2;
do {
b0 = b;
double esb = e * sin(b);
b = 2. * atan(exp(q) * pow((1. - esb) / (1. + esb), -e / 2.)) - M_PI_2;
} while (fabs(b - b0) > 1e-10);
return b;
}
double Ellipsoid::nradius(double phi) const
{
double sin_phi = sin(phi);
return (_radius / sqrt(1. - (_flattening * (2. - _flattening)) * sin_phi
* sin_phi));
_errorLine = 1;
_errorString.clear();
while (!file.atEnd()) {
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() != 4) {
_errorString = "Format error";
return false;
}
int id = list[0].trimmed().toInt(&res);
if (!res) {
_errorString = "Invalid ellipsoid id";
return false;
}
double radius = list[2].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid ellipsoid radius";
return false;
}
double flattening = list[3].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid ellipsoid flattening";
return false;
}
Ellipsoid e(radius, 1.0/flattening);
_ellipsoids.insert(id, e);
_errorLine++;
}
return true;
}

View File

@ -1,24 +1,37 @@
#ifndef ELLIPSOID_H
#define ELLIPSOID_H
class QString;
#include <QString>
#include <QMap>
#include "wgs84.h"
class Ellipsoid
{
public:
Ellipsoid();
Ellipsoid(const QString &datum);
Ellipsoid() : _radius(-1.0), _flattening(-1.0) {}
Ellipsoid(double radius, double flattening)
: _radius(radius), _flattening(flattening) {}
double radius() const {return _radius;}
double flattening() const {return _flattening;}
double q(double b) const;
double iq(double q) const;
double nradius(double phi) const;
bool isNull() const {return _radius < 0 || _flattening < 0;}
bool isWGS84() const
{return _radius == WGS84_RADIUS && _flattening == WGS84_FLATTENING;}
static bool loadList(const QString &path);
static const QString &errorString() {return _errorString;}
static int errorLine() {return _errorLine;}
static Ellipsoid ellipsoid(int id);
private:
double _radius;
double _flattening;
static QMap<int, Ellipsoid> _ellipsoids;
static QString _errorString;
static int _errorLine;
};
#endif // ELLIPSOID_H

View File

@ -26,9 +26,10 @@
#include "keys.h"
#include "settings.h"
#include "data.h"
#include "ellipsoid.h"
#include "datum.h"
#include "map.h"
#include "maplist.h"
#include "mapdir.h"
#include "emptymap.h"
#include "elevationgraph.h"
#include "speedgraph.h"
@ -47,6 +48,7 @@
GUI::GUI()
{
loadDatums();
loadMaps();
loadPOIs();
@ -117,23 +119,94 @@ void GUI::createBrowser()
_browser->setFilter(filter);
}
void GUI::loadDatums()
{
QString ef, df;
bool ok = false;
if (QFile::exists(USER_ELLIPSOID_FILE))
ef = USER_ELLIPSOID_FILE;
else if (QFile::exists(GLOBAL_ELLIPSOID_FILE))
ef = GLOBAL_ELLIPSOID_FILE;
else
qWarning("No ellipsoids file found.");
if (QFile::exists(USER_DATUM_FILE))
df = USER_DATUM_FILE;
else if (QFile::exists(GLOBAL_DATUM_FILE))
df = GLOBAL_DATUM_FILE;
else
qWarning("No datums file found.");
if (!ef.isNull() && !df.isNull()) {
if (!Ellipsoid::loadList(ef)) {
if (Ellipsoid::errorLine())
qWarning("%s: parse error on line %d: %s", qPrintable(ef),
Ellipsoid::errorLine(), qPrintable(Ellipsoid::errorString()));
else
qWarning("%s: %s", qPrintable(ef), qPrintable(
Ellipsoid::errorString()));
} else {
if (!Datum::loadList(df)) {
if (Datum::errorLine())
qWarning("%s: parse error on line %d: %s", qPrintable(ef),
Datum::errorLine(), qPrintable(Datum::errorString()));
else
qWarning("%s: %s", qPrintable(ef), qPrintable(
Datum::errorString()));
} else
ok = true;
}
}
if (!ok)
qWarning("Maps based on a datum different from WGS84 won't work.");
}
void GUI::loadMaps()
{
QList<Map*> online, offline;
_ml = new MapList(this);
QString offline, online;
if (QFile::exists(USER_MAP_FILE))
online = MapList::load(USER_MAP_FILE, this);
else
online = MapList::load(GLOBAL_MAP_FILE, this);
online = USER_MAP_FILE;
else if (QFile::exists(GLOBAL_MAP_FILE))
online = GLOBAL_MAP_FILE;
if (!online.isNull() && !_ml->loadList(online))
qWarning("%s: %s", qPrintable(online), qPrintable(_ml->errorString()));
if (QFile::exists(USER_MAP_DIR))
offline = MapDir::load(USER_MAP_DIR, this);
else
offline = MapDir::load(GLOBAL_MAP_DIR, this);
offline = USER_MAP_DIR;
else if (QFile::exists(GLOBAL_MAP_DIR))
offline = GLOBAL_MAP_DIR;
_maps = online + offline;
if (!offline.isNull()) {
QDir md(offline);
QFileInfoList ml = md.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
QStringList filters;
filters << "*.map" << "*.tba" << "*.tar";
_map = _maps.isEmpty() ? new EmptyMap(this) : _maps.first();
for (int i = 0; i < ml.size(); i++) {
QDir dir(ml.at(i).absoluteFilePath());
QFileInfoList fl = dir.entryInfoList(filters, QDir::Files);
if (fl.isEmpty())
qWarning("%s: no map/atlas file found",
qPrintable(ml.at(i).absoluteFilePath()));
else if (fl.size() > 1)
qWarning("%s: ambiguous directory content",
qPrintable(ml.at(i).absoluteFilePath()));
else
if (!_ml->loadMap(fl.first().absoluteFilePath()))
qWarning("%s: %s", qPrintable(fl.first().absoluteFilePath()),
qPrintable(_ml->errorString()));
}
}
_map = _ml->maps().isEmpty() ? new EmptyMap(this) : _ml->maps().first();
}
void GUI::loadPOIs()
@ -162,33 +235,33 @@ void GUI::loadPOIs()
void GUI::createMapActions()
{
QActionGroup *ag = new QActionGroup(this);
ag->setExclusive(true);
_mapsSignalMapper = new QSignalMapper(this);
_mapsActionGroup = new QActionGroup(this);
_mapsActionGroup->setExclusive(true);
QSignalMapper *sm = new QSignalMapper(this);
for (int i = 0; i < _maps.count(); i++) {
QAction *a = new QAction(_maps.at(i)->name(), this);
for (int i = 0; i < _ml->maps().count(); i++) {
QAction *a = new QAction(_ml->maps().at(i)->name(), this);
a->setCheckable(true);
a->setActionGroup(ag);
a->setActionGroup(_mapsActionGroup);
sm->setMapping(a, i);
connect(a, SIGNAL(triggered()), sm, SLOT(map()));
_mapsSignalMapper->setMapping(a, i);
connect(a, SIGNAL(triggered()), _mapsSignalMapper, SLOT(map()));
_mapActions.append(a);
}
connect(sm, SIGNAL(mapped(int)), this, SLOT(mapChanged(int)));
connect(_mapsSignalMapper, SIGNAL(mapped(int)), this,
SLOT(mapChanged(int)));
}
void GUI::createPOIFilesActions()
{
_poiFilesSM = new QSignalMapper(this);
_poiFilesSignalMapper = new QSignalMapper(this);
for (int i = 0; i < _poi->files().count(); i++)
createPOIFileAction(i);
connect(_poiFilesSM, SIGNAL(mapped(int)), this, SLOT(poiFileChecked(int)));
connect(_poiFilesSignalMapper, SIGNAL(mapped(int)), this, SLOT(poiFileChecked(int)));
}
QAction *GUI::createPOIFileAction(int index)
@ -197,8 +270,8 @@ QAction *GUI::createPOIFileAction(int index)
this);
a->setCheckable(true);
_poiFilesSM->setMapping(a, index);
connect(a, SIGNAL(triggered()), _poiFilesSM, SLOT(map()));
_poiFilesSignalMapper->setMapping(a, index);
connect(a, SIGNAL(triggered()), _poiFilesSignalMapper, SLOT(map()));
_poiFilesActions.append(a);
@ -294,23 +367,24 @@ void GUI::createActions()
connect(_showMapAction, SIGNAL(triggered(bool)), _pathView,
SLOT(showMap(bool)));
addAction(_showMapAction);
_loadMapAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)), tr("Load map"),
this);
connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap()));
_clearMapCacheAction = new QAction(tr("Clear tile cache"), this);
connect(_clearMapCacheAction, SIGNAL(triggered()), this,
SLOT(clearMapCache()));
if (_maps.empty()) {
createMapActions();
_nextMapAction = new QAction(tr("Next map"), this);
_nextMapAction->setShortcut(NEXT_MAP_SHORTCUT);
connect(_nextMapAction, SIGNAL(triggered()), this, SLOT(nextMap()));
addAction(_nextMapAction);
_prevMapAction = new QAction(tr("Next map"), this);
_prevMapAction->setShortcut(PREV_MAP_SHORTCUT);
connect(_prevMapAction, SIGNAL(triggered()), this, SLOT(prevMap()));
addAction(_prevMapAction);
if (_ml->maps().isEmpty()) {
_showMapAction->setEnabled(false);
_clearMapCacheAction->setEnabled(false);
} else {
createMapActions();
_nextMapAction = new QAction(tr("Next map"), this);
_nextMapAction->setShortcut(NEXT_MAP_SHORTCUT);
connect(_nextMapAction, SIGNAL(triggered()), this, SLOT(nextMap()));
addAction(_nextMapAction);
_prevMapAction = new QAction(tr("Next map"), this);
_prevMapAction->setShortcut(PREV_MAP_SHORTCUT);
connect(_prevMapAction, SIGNAL(triggered()), this, SLOT(prevMap()));
addAction(_prevMapAction);
}
// Data actions
@ -437,12 +511,13 @@ void GUI::createMenus()
fileMenu->addAction(_exitAction);
#endif // Q_OS_MAC
QMenu *mapMenu = menuBar()->addMenu(tr("Map"));
mapMenu->addActions(_mapActions);
mapMenu->addSeparator();
mapMenu->addAction(_clearMapCacheAction);
mapMenu->addSeparator();
mapMenu->addAction(_showMapAction);
_mapMenu = menuBar()->addMenu(tr("Map"));
_mapMenu->addActions(_mapActions);
_mapsEnd = _mapMenu->addSeparator();
_mapMenu->addAction(_loadMapAction);
_mapMenu->addAction(_clearMapCacheAction);
_mapMenu->addSeparator();
_mapMenu->addAction(_showMapAction);
QMenu *graphMenu = menuBar()->addMenu(tr("Graph"));
graphMenu->addAction(_distanceGraphAction);
@ -639,8 +714,8 @@ void GUI::dataSources()
"directory:")
+ "</p><p><code>" + USER_MAP_DIR + "</code></p><p>"
+ tr("The expected structure is one map/atlas in a separate subdirectory."
" Supported map formats are OziMap image-based maps and tiled TrekBuddy"
" maps/atlases (tared and non-tared).") + "</p>"
" Supported map formats are OziExplorer image-based maps and tiled"
" TrekBuddy maps/atlases (tared and non-tared).") + "</p>"
+ "<h4>" + tr("POIs") + "</h4><p>"
+ tr("To make GPXSee load a POI file automatically on startup, add "
@ -1085,6 +1160,32 @@ void GUI::showGraphGrids(bool show)
_tabs.at(i)->showGrid(show);
}
void GUI::loadMap()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Load map"),
QString(), tr("Map files (*.map *.tba *.tar)"));
if (fileName.isEmpty())
return;
if (_ml->loadMap(fileName)) {
QAction *a = new QAction(_ml->maps().last()->name(), this);
a->setCheckable(true);
a->setActionGroup(_mapsActionGroup);
_mapsSignalMapper->setMapping(a, _ml->maps().size() - 1);
connect(a, SIGNAL(triggered()), _mapsSignalMapper, SLOT(map()));
_mapActions.append(a);
_mapMenu->insertAction(_mapsEnd, a);
_showMapAction->setEnabled(true);
_clearMapCacheAction->setEnabled(true);
a->activate(QAction::Trigger);
} else {
QString error = tr("Error loading map:") + "\n\n"
+ fileName + "\n\n" + _ml->errorString();
QMessageBox::critical(this, APP_NAME, error);
}
}
void GUI::clearMapCache()
{
_map->clearCache();
@ -1131,26 +1232,27 @@ void GUI::updateWindowTitle()
void GUI::mapChanged(int index)
{
_map = _maps.at(index);
_map = _ml->maps().at(index);
_pathView->setMap(_map);
}
void GUI::nextMap()
{
if (_maps.count() < 2)
if (_ml->maps().count() < 2)
return;
int next = (_maps.indexOf(_map) + 1) % _maps.count();
int next = (_ml->maps().indexOf(_map) + 1) % _ml->maps().count();
_mapActions.at(next)->setChecked(true);
mapChanged(next);
}
void GUI::prevMap()
{
if (_maps.count() < 2)
if (_ml->maps().count() < 2)
return;
int prev = (_maps.indexOf(_map) + _maps.count() - 1) % _maps.count();
int prev = (_ml->maps().indexOf(_map) + _ml->maps().count() - 1)
% _ml->maps().count();
_mapActions.at(prev)->setChecked(true);
mapChanged(prev);
}
@ -1531,10 +1633,10 @@ void GUI::readSettings()
settings.beginGroup(MAP_SETTINGS_GROUP);
if (settings.value(SHOW_MAP_SETTING, SHOW_MAP_DEFAULT).toBool())
_showMapAction->setChecked(true);
if (_maps.count()) {
if (_ml->maps().count()) {
int index = mapIndex(settings.value(CURRENT_MAP_SETTING).toString());
_mapActions.at(index)->setChecked(true);
_map = _maps.at(index);
_map = _ml->maps().at(index);
_pathView->setMap(_map);
}
settings.endGroup();
@ -1696,8 +1798,8 @@ void GUI::readSettings()
int GUI::mapIndex(const QString &name)
{
for (int i = 0; i < _maps.count(); i++)
if (_maps.at(i)->name() == name)
for (int i = 0; i < _ml->maps().count(); i++)
if (_ml->maps().at(i)->name() == name)
return i;
return 0;

View File

@ -13,6 +13,7 @@
#include "exportdialog.h"
#include "optionsdialog.h"
class QMenu;
class QToolBar;
class QTabWidget;
@ -25,6 +26,7 @@ class FileBrowser;
class GraphTab;
class PathView;
class Map;
class MapList;
class GUI : public QMainWindow
{
@ -53,6 +55,7 @@ private slots:
void showFullscreen(bool show);
void showTracks(bool show);
void showRoutes(bool show);
void loadMap();
void clearMapCache();
void nextMap();
void prevMap();
@ -79,6 +82,7 @@ private slots:
private:
typedef QPair<QDate, QDate> DateRange;
void loadDatums();
void loadMaps();
void loadPOIs();
void closeFiles();
@ -128,9 +132,11 @@ private:
QToolBar *_showToolBar;
QToolBar *_navigationToolBar;
QMenu *_poiFilesMenu;
QMenu *_mapMenu;
QActionGroup *_fileActionGroup;
QActionGroup *_navigationActionGroup;
QActionGroup *_mapsActionGroup;
QAction *_exitAction;
QAction *_keysAction;
QAction *_dataSourcesAction;
@ -148,6 +154,7 @@ private:
QAction *_showPOILabelsAction;
QAction *_showMapAction;
QAction *_fullscreenAction;
QAction *_loadMapAction;
QAction *_clearMapCacheAction;
QAction *_showGraphsAction;
QAction *_showGraphGridAction;
@ -170,10 +177,12 @@ private:
QAction *_showWaypointLabelsAction;
QAction *_showRouteWaypointsAction;
QAction *_openOptionsAction;
QAction *_mapsEnd;
QList<QAction*> _mapActions;
QList<QAction*> _poiFilesActions;
QSignalMapper *_poiFilesSM;
QSignalMapper *_poiFilesSignalMapper;
QSignalMapper *_mapsSignalMapper;
QLabel *_fileNameLabel;
QLabel *_distanceLabel;
@ -184,7 +193,7 @@ private:
QList<GraphTab*> _tabs;
POI *_poi;
QList<Map*> _maps;
MapList *_ml;
FileBrowser *_browser;
QList<QString> _files;

View File

@ -2,24 +2,59 @@
#include "rd.h"
#include "lambertconic.h"
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
#ifndef M_PI_4
#define M_PI_4 0.78539816339744830962
#endif // M_PI_4
static double q(const Ellipsoid &el, double b)
{
double e = sqrt(el.flattening() * (2. - el.flattening()));
double esb = e * sin(b);
return log(tan(M_PI_4 + b / 2.) * pow((1. - esb) / (1. + esb), e / 2.));
}
static double iq(const Ellipsoid &el, double q)
{
double e = sqrt(el.flattening() * (2. - el.flattening()));
double b0 = 0.;
double b = 2. * atan(exp(q)) - M_PI_2;
do {
b0 = b;
double esb = e * sin(b);
b = 2. * atan(exp(q) * pow((1. - esb) / (1. + esb), -e / 2.)) - M_PI_2;
} while (fabs(b - b0) > 1e-10);
return b;
}
static double nradius(const Ellipsoid &el, double phi)
{
double sin_phi = sin(phi);
return (el.radius() / sqrt(1. - (el.flattening() * (2. - el.flattening()))
* sin_phi * sin_phi));
}
LambertConic::LambertConic(const Ellipsoid &ellipsoid, double standardParallel1,
double standardParallel2, double centralParallel, double centralMeridian,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double scale, double falseEasting, double falseNorthing) : _e(ellipsoid)
{
_cm = centralMeridian;
_cm = longitudeOrigin;
_fe = falseEasting;
_fn = falseNorthing;
double sp1 = deg2rad(standardParallel1);
double sp2 = deg2rad(standardParallel2);
double N1 = _e.nradius(sp1);
double N2 = _e.nradius(sp2);
double N1 = nradius(_e, sp1);
double N2 = nradius(_e, sp2);
_q0 = ellipsoid.q(deg2rad(centralParallel));
double q1 = _e.q(sp1);
double q2 = _e.q(sp2);
_q0 = q(_e, deg2rad(latitudeOrigin));
double q1 = q(_e, sp1);
double q2 = q(_e, sp2);
_n = log((N1 * cos(sp1)) / (N2 * cos(sp2))) / (q2 - q1);
double R1 = N1 * cos(sp1) / _n;
@ -29,7 +64,7 @@ LambertConic::LambertConic(const Ellipsoid &ellipsoid, double standardParallel1,
QPointF LambertConic::ll2xy(const Coordinates &c) const
{
double dl = _n * (deg2rad(c.lon()) - deg2rad(_cm));
double R = _R0 * exp(_n * (_q0 - _e.q(deg2rad(c.lat()))));
double R = _R0 * exp(_n * (_q0 - q(_e, deg2rad(c.lat()))));
return QPointF(_fe + R * sin(dl), _fn + _R0 - R * cos(dl));
}
@ -42,5 +77,5 @@ Coordinates LambertConic::xy2ll(const QPointF &p) const
double R = sqrt(dx * dx + dy * dy);
double q = _q0 - log(R / _R0) / _n;
return Coordinates(rad2deg(deg2rad(_cm) + dl / _n), rad2deg(_e.iq(q)));
return Coordinates(rad2deg(deg2rad(_cm) + dl / _n), rad2deg(iq(_e, q)));
}

View File

@ -8,7 +8,7 @@ class LambertConic : public Projection
{
public:
LambertConic(const Ellipsoid &ellipsoid, double standardParallel1,
double standardParallel2, double centralParallel, double centralMeridian,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double scale, double falseEasting, double falseNorthing);
virtual QPointF ll2xy(const Coordinates &c) const;

View File

@ -1,40 +0,0 @@
#include <QDir>
#include "atlas.h"
#include "offlinemap.h"
#include "mapdir.h"
QList<Map*> MapDir::load(const QString &path, QObject *parent)
{
QList<Map*> maps;
QDir dir(path);
if (!dir.exists())
return maps;
if (!dir.isReadable()) {
qWarning("Map directory not readable: %s\n", qPrintable(path));
return maps;
}
QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (int i = 0; i < list.size(); i++) {
QFileInfo fileInfo = list.at(i);
Atlas *atlas = new Atlas(fileInfo.absoluteFilePath(), parent);
if (atlas->isValid())
maps.append(atlas);
else {
delete atlas;
OfflineMap *map = new OfflineMap(fileInfo.absoluteFilePath(),
parent);
if (map->isValid())
maps.append(map);
else
delete map;
}
}
return maps;
}

View File

@ -1,16 +0,0 @@
#ifndef MAPDIR_H
#define MAPDIR_H
#include <QList>
#include <QString>
class QObject;
class Map;
class MapDir
{
public:
static QList<Map*> load(const QString &path, QObject *parent = 0);
};
#endif // MAPDIR_H

View File

@ -1,41 +1,100 @@
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include "atlas.h"
#include "offlinemap.h"
#include "onlinemap.h"
#include "maplist.h"
QList<Map*> MapList::load(const QString &fileName, QObject *parent)
bool MapList::loadListEntry(const QByteArray &line)
{
QList<Map*> maps;
QFileInfo fi(fileName);
QList<QByteArray> list = line.split('\t');
if (list.size() != 2)
return false;
if (!fi.exists())
return maps;
QByteArray ba1 = list[0].trimmed();
QByteArray ba2 = list[1].trimmed();
if (ba1.isEmpty() || ba2.isEmpty())
return false;
QFile file(fileName);
_maps.append(new OnlineMap(QString::fromUtf8(ba1.data(), ba1.size()),
QString::fromLatin1(ba2.data(), ba2.size()), this));
return true;
}
bool MapList::loadList(const QString &path)
{
QFile file(path);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
qWarning("Error opening map list file: %s: %s\n",
qPrintable(fileName), qPrintable(file.errorString()));
return maps;
_errorString = file.errorString();
return false;
}
int ln = 0;
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
QList<QByteArray> list = line.split('\t');
if (list.size() != 2) {
qWarning("Invalid map list entry on line %d\n", ln);
continue;
if (!loadListEntry(line)) {
_errorString = QString("Invalid map list entry on line %1.")
.arg(QString::number(ln));
return false;
}
QByteArray ba1 = list[0].trimmed();
QByteArray ba2 = list[1].trimmed();
maps.append(new OnlineMap(QString::fromUtf8(ba1.data(), ba1.size()),
QString::fromLatin1(ba2.data(), ba2.size()), parent));
}
return maps;
return true;
}
bool MapList::loadMap(const QString &path)
{
QFileInfo fi(path);
QString suffix = fi.suffix().toLower();
if (suffix == "map") {
OfflineMap *om = new OfflineMap(path, this);
if (om->isValid()) {
_maps.append(om);
return true;
} else {
_errorString = om->errorString();
delete om;
return false;
}
} else if (suffix == "tba") {
Atlas *atlas = new Atlas(path, this);
if (atlas->isValid()) {
_maps.append(atlas);
return true;
} else {
_errorString = atlas->errorString();
delete atlas;
return false;
}
} else if (suffix == "tar") {
Atlas *atlas = new Atlas(path, this);
if (atlas->isValid()) {
_maps.append(atlas);
return true;
} else {
_errorString = atlas->errorString();
delete atlas;
OfflineMap *om = new OfflineMap(path, this);
if (om->isValid()) {
_maps.append(om);
return true;
} else {
qWarning("%s: %s", qPrintable(path), qPrintable(_errorString));
qWarning("%s: %s", qPrintable(path),
qPrintable(om->errorString()));
_errorString = "Not a map/atlas file";
delete om;
return false;
}
}
} else {
_errorString = "Not a map/atlas file";
return false;
}
}

View File

@ -1,16 +1,28 @@
#ifndef MAPLIST_H
#define MAPLIST_H
#include <QList>
#include <QObject>
#include <QString>
#include "map.h"
class QObject;
class Map;
class MapList
class MapList : public QObject
{
Q_OBJECT
public:
static QList<Map*> load(const QString &fileName, QObject *parent = 0);
MapList(QObject *parent = 0) : QObject(parent) {}
bool loadMap(const QString &path);
bool loadList(const QString &path);
QList<Map*> &maps() {return _maps;}
const QString &errorString() const {return _errorString;}
private:
bool loadListEntry(const QByteArray &line);
QList<Map*> _maps;
QString _errorString;
};
#endif // MAPLIST_H

View File

@ -3,6 +3,9 @@
#include <QRectF>
#define ARRAY_SIZE(array) \
(sizeof(array) / sizeof((array)[0]))
double niceNum(double x, int round);
int str2int(const char *str, int len);
QRectF scaled(const QRectF &rect, qreal factor);

View File

@ -12,32 +12,66 @@
#include "wgs84.h"
#include "coordinates.h"
#include "matrix.h"
#include "ellipsoid.h"
#include "datum.h"
#include "latlon.h"
#include "mercator.h"
#include "transversemercator.h"
#include "utm.h"
#include "lambertconic.h"
#include "ozf.h"
#include "offlinemap.h"
int OfflineMap::parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
// Abridged Molodensky transformation
static Coordinates toWGS84(Coordinates c, const Datum &datum)
{
Ellipsoid WGS84(WGS84_RADIUS, WGS84_FLATTENING);
double dX = datum.dx();
double dY = datum.dy();
double dZ = datum.dz();
double slat = sin(deg2rad(c.lat()));
double clat = cos(deg2rad(c.lat()));
double slon = sin(deg2rad(c.lon()));
double clon = cos(deg2rad(c.lon()));
double ssqlat = slat * slat;
double from_f = datum.ellipsoid().flattening();
double df = WGS84.flattening() - from_f;
double from_a = datum.ellipsoid().radius();
double da = WGS84.radius() - from_a;
double from_esq = datum.ellipsoid().flattening()
* (2.0 - datum.ellipsoid().flattening());
double adb = 1.0 / (1.0 - from_f);
double rn = from_a / sqrt(1 - from_esq * ssqlat);
double rm = from_a * (1 - from_esq) / pow((1 - from_esq * ssqlat), 1.5);
double from_h = 0.0;
double dlat = (-dX * slat * clon - dY * slat * slon + dZ * clat + da * rn
* from_esq * slat * clat / from_a + +df * (rm * adb + rn / adb) * slat
* clat) / (rm + from_h);
double dlon = (-dX * slon + dY * clon) / ((rn + from_h) * clat);
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
}
int OfflineMap::parse(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, ProjectionSetup &setup, QString &datum)
{
bool res;
int ln = 1;
if (!device.open(QIODevice::ReadOnly))
return -1;
while (!device.atEnd()) {
QByteArray line = device.readLine();
if (ln == 1) {
if (!line.trimmed().startsWith("OziExplorer Map Data File"))
return ln;
} else if (ln == 3)
} else if (ln == 2)
_name = line.trimmed();
else if (ln == 3)
_imgPath = line.trimmed();
else if (ln == 5)
datum = line.split(',').at(0).trimmed();
@ -108,12 +142,12 @@ int OfflineMap::parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
} else if (key == "Projection Setup") {
if (list.count() < 8)
return ln;
setup.centralParallel = list.at(1).trimmed().toFloat(&res);
setup.latitudeOrigin = list.at(1).trimmed().toFloat(&res);
if (!res)
setup.centralParallel = 0;
setup.centralMeridian = list.at(2).trimmed().toFloat(&res);
setup.latitudeOrigin = 0;
setup.longitudeOrigin = list.at(2).trimmed().toFloat(&res);
if (!res)
setup.centralMeridian = 0;
setup.longitudeOrigin = 0;
setup.scale = list.at(3).trimmed().toFloat(&res);
if (!res)
setup.scale = 1.0;
@ -138,46 +172,78 @@ int OfflineMap::parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
return 0;
}
bool OfflineMap::parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, ProjectionSetup &setup, QString &datum)
{
int el;
if (!device.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening map file: %1")
.arg(device.errorString());
return false;
}
if ((el = parse(device, points, projection, setup, datum))) {
_errorString = QString("Map file parse error on line %1").arg(el);
return false;
}
return true;
}
bool OfflineMap::createProjection(const QString &datum,
const QString &projection, const ProjectionSetup &setup,
QList<ReferencePoint> &points)
{
if (points.count() < 2) {
qWarning("%s: insufficient number of reference points",
qPrintable(_name));
_errorString = "Insufficient number of reference points";
return false;
}
Datum d = Datum::datum(datum);
if (d.isNull()) {
_errorString = QString("%1: Unknown datum").arg(datum);
return false;
}
if (projection == "Mercator")
_projection = new Mercator();
else if (projection == "Transverse Mercator")
_projection = new TransverseMercator(Ellipsoid(datum),
setup.centralMeridian, setup.scale, setup.falseEasting,
_projection = new TransverseMercator(d.ellipsoid(),
setup.longitudeOrigin, setup.scale, setup.falseEasting,
setup.falseNorthing);
else if (projection == "Latitude/Longitude")
_projection = new LatLon();
else if (projection == "Lambert Conformal Conic")
_projection = new LambertConic(Ellipsoid(datum), setup.standardParallel1,
setup.standardParallel2, setup.centralParallel, setup.centralMeridian,
setup.scale, setup.falseEasting, setup.falseNorthing);
_projection = new LambertConic(d.ellipsoid(),
setup.standardParallel1, setup.standardParallel2,
setup.latitudeOrigin, setup.longitudeOrigin, setup.scale,
setup.falseEasting, setup.falseNorthing);
else if (projection == "(UTM) Universal Transverse Mercator") {
if (setup.zone)
_projection = new UTM(setup.zone);
_projection = new UTM(d.ellipsoid(), setup.zone);
else if (!points.first().ll.isNull())
_projection = new UTM(points.first().ll);
_projection = new UTM(d.ellipsoid(), points.first().ll);
else {
qWarning("%s: Can not determine UTM zone", qPrintable(_name));
_errorString = "Can not determine UTM zone";
return false;
}
} else {
qWarning("%s: %s: unsupported map projection", qPrintable(_name),
qPrintable(projection));
_errorString = QString("%1: Unknown map projection").arg(projection);
return false;
}
for (int i = 0; i < points.size(); i++)
if (points.at(i).ll.isNull())
points[i].ll = _projection->xy2ll(points.at(i).pp);
for (int i = 0; i < points.size(); i++) {
if (points.at(i).ll.isNull()) {
if (d.isWGS84())
points[i].ll = _projection->xy2ll(points.at(i).pp);
else
points[i].ll = toWGS84(_projection->xy2ll(points.at(i).pp), d);
} else {
if (!d.isWGS84())
points[i].ll = toWGS84(points[i].ll, d);
}
}
return true;
}
@ -220,7 +286,7 @@ bool OfflineMap::computeTransformation(const QList<ReferencePoint> &points)
Matrix M = Q.augemented(c);
if (!M.eliminate()) {
qWarning("%s: singular transformation matrix", qPrintable(_name));
_errorString = "Singular transformation matrix";
return false;
}
@ -262,14 +328,40 @@ bool OfflineMap::computeResolution(QList<ReferencePoint> &points)
bool OfflineMap::getImageInfo(const QString &path)
{
QFileInfo ii(_imgPath);
if (ii.isRelative())
_imgPath = path + "/" + _imgPath;
QImageReader img(_imgPath);
_size = img.size();
if (ii.isRelative())
ii.setFile(path + "/" + _imgPath);
if (!ii.exists()) {
int last = _imgPath.lastIndexOf('\\');
if (last >= 0 && last < _imgPath.length() - 1) {
QStringRef fn(&_imgPath, last + 1, _imgPath.length() - last - 1);
ii.setFile(path + "/" + fn.toString());
}
}
if (ii.exists())
_imgPath = ii.absoluteFilePath();
else {
_errorString = QString("%1: No such image file").arg(_imgPath);
return false;
}
QString suffix = ii.suffix().toLower();
if (suffix == "ozf3" || suffix == "ozf4") {
_errorString = QString("%1: Obfuscated image files not supported")
.arg(QFileInfo(_imgPath).fileName());
return false;
} else if (suffix == "ozf2") {
_ozf.load(_imgPath);
_size = _ozf.size();
} else {
QImageReader img(_imgPath);
_size = img.size();
}
if (!_size.isValid()) {
qWarning("%s: %s: error reading map image", qPrintable(_name),
qPrintable(ii.absoluteFilePath()));
_errorString = QString("%1: Error reading map image")
.arg(QFileInfo(_imgPath).fileName());
return false;
}
@ -278,11 +370,6 @@ bool OfflineMap::getImageInfo(const QString &path)
bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
{
if (tiles.isEmpty()) {
qWarning("%s: empty tile set", qPrintable(_name));
return false;
}
QRegExp rx("_[0-9]+_[0-9]+\\.");
for (int i = 0; i < tiles.size(); i++) {
if (tiles.at(i).contains(rx)) {
@ -297,9 +384,8 @@ bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
_tileSize = QImageReader(path + "/" + tiles.at(i)).size();
}
if (!_tileSize.isValid()) {
qWarning("%s: error retrieving tile size: %s: invalid image",
qPrintable(_name), qPrintable(QFileInfo(tiles.at(i))
.fileName()));
_errorString = QString("Error retrieving tile size: "
"%1: Invalid image").arg(QFileInfo(tiles.at(i)).fileName());
return false;
}
@ -307,42 +393,27 @@ bool OfflineMap::getTileInfo(const QStringList &tiles, const QString &path)
}
}
qWarning("%s: invalid tile names", qPrintable(_name));
_errorString = "Invalid/missing tile set";
return false;
}
bool OfflineMap::mapLoaded(int res)
{
if (res) {
if (res == -2)
qWarning("%s: no map file found", qPrintable(_name));
else if (res == -1)
qWarning("%s: error opening map file", qPrintable(_name));
else
qWarning("%s: map file parse error on line: %d", qPrintable(_name),
res);
return false;
}
return true;
}
bool OfflineMap::totalSizeSet()
{
if (!_size.isValid()) {
qWarning("%s: missing total image size (IWH)", qPrintable(_name));
_errorString = "Missing total image size (IWH)";
return false;
} else
return true;
}
OfflineMap::OfflineMap(const QString &path, QObject *parent) : Map(parent)
OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
: Map(parent)
{
int errorLine = -2;
QList<ReferencePoint> points;
QString proj, datum;
ProjectionSetup setup;
QFileInfo fi(fileName);
QString suffix = fi.suffix().toLower();
_valid = false;
@ -350,38 +421,29 @@ OfflineMap::OfflineMap(const QString &path, QObject *parent) : Map(parent)
_projection = 0;
_resolution = 0;
QFileInfo fi(path);
_name = fi.fileName();
QDir dir(path);
QFileInfoList mapFiles = dir.entryInfoList(QDir::Files);
for (int i = 0; i < mapFiles.count(); i++) {
const QString &fileName = mapFiles.at(i).fileName();
if (fileName.endsWith(".tar")) {
if (!_tar.load(mapFiles.at(i).absoluteFilePath())) {
qWarning("%s: %s: error loading tar file", qPrintable(_name),
qPrintable(fileName));
return;
}
QStringList tarFiles = _tar.files();
for (int j = 0; j < tarFiles.size(); j++) {
if (tarFiles.at(j).endsWith(".map")) {
QByteArray ba = _tar.file(tarFiles.at(j));
QBuffer buffer(&ba);
errorLine = parseMapFile(buffer, points, proj, setup, datum);
_imgPath = QString();
break;
}
}
break;
} else if (fileName.endsWith(".map")) {
QFile mapFile(mapFiles.at(i).absoluteFilePath());
errorLine = parseMapFile(mapFile, points, proj, setup, datum);
break;
if (suffix == "tar") {
if (!_tar.load(fileName)) {
_errorString = "Error reading tar file";
return;
}
}
if (!mapLoaded(errorLine))
QString mapFileName = fi.completeBaseName() + ".map";
QByteArray ba = _tar.file(mapFileName);
if (ba.isNull()) {
_errorString = "Map file not found";
return;
}
QBuffer mapFile(&ba);
if (!parseMapFile(mapFile, points, proj, setup, datum))
return;
} else if (suffix =="map") {
QFile mapFile(fileName);
if (!parseMapFile(mapFile, points, proj, setup, datum))
return;
} else {
_errorString = "Not a map file";
return;
}
if (!createProjection(datum, proj, setup, points))
return;
@ -394,16 +456,17 @@ OfflineMap::OfflineMap(const QString &path, QObject *parent) : Map(parent)
return;
if (!getTileInfo(_tar.files()))
return;
_imgPath = QString();
} else {
QDir set(fi.absoluteFilePath() + "/" + "set");
QDir set(fi.absolutePath() + "/" + "set");
if (set.exists()) {
if (!totalSizeSet())
return;
if (!getTileInfo(set.entryList(), set.canonicalPath()))
if (!getTileInfo(set.entryList(), set.absolutePath()))
return;
_imgPath = QString();
} else {
if (!getImageInfo(fi.absoluteFilePath()))
if (!getImageInfo(fi.absolutePath()))
return;
}
}
@ -411,36 +474,31 @@ OfflineMap::OfflineMap(const QString &path, QObject *parent) : Map(parent)
_valid = true;
}
OfflineMap::OfflineMap(Tar &tar, const QString &path, QObject *parent)
OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
: Map(parent)
{
int errorLine = -2;
QList<ReferencePoint> points;
QString proj, datum;
ProjectionSetup setup;
QFileInfo fi(fileName);
_valid = false;
_img = 0;
_projection = 0;
QFileInfo fi(path);
_name = fi.fileName();
QFileInfo li(fi.absoluteDir().dirName());
QString prefix = li.fileName() + "/" + fi.fileName() + "/";
QStringList tarFiles = tar.files();
for (int j = 0; j < tarFiles.size(); j++) {
if (tarFiles.at(j).startsWith(prefix)) {
QByteArray ba = tar.file(tarFiles.at(j));
QBuffer buffer(&ba);
errorLine = parseMapFile(buffer, points, proj, setup, datum);
break;
}
}
if (!mapLoaded(errorLine))
QFileInfo map(fi.absolutePath());
QFileInfo layer(map.absolutePath());
QString mapFile = layer.fileName() + "/" + map.fileName() + "/"
+ fi.fileName();
QByteArray ba = tar.file(mapFile);
if (ba.isNull()) {
_errorString = "Map file not found";
return;
}
QBuffer buffer(&ba);
if (!parseMapFile(buffer, points, proj, setup, datum))
return;
if (!createProjection(datum, proj, setup, points))
return;
if (!totalSizeSet())
@ -449,14 +507,8 @@ OfflineMap::OfflineMap(Tar &tar, const QString &path, QObject *parent)
return;
computeResolution(points);
QDir dir(path);
QFileInfoList mapFiles = dir.entryInfoList(QDir::Files);
for (int i = 0; i < mapFiles.count(); i++) {
const QString &fileName = mapFiles.at(i).absoluteFilePath();
if (fileName.endsWith(".tar"))
_tarPath = fileName;
}
_tarPath = fi.absolutePath() + "/" + fi.completeBaseName() + ".tar";
_imgPath = QString();
_valid = true;
}
@ -473,15 +525,15 @@ void OfflineMap::load()
{
if (!_tarPath.isNull() && !_tileSize.isValid()) {
if (!_tar.load(_tarPath)) {
qWarning("%s: %s: error loading tar file", qPrintable(_name),
qPrintable(_tarPath));
qWarning("%s: error loading tar file", qPrintable(_tarPath));
return;
}
getTileInfo(_tar.files());
if (!getTileInfo(_tar.files()))
qWarning("%s: %s", qPrintable(_tarPath), qPrintable(_errorString));
return;
}
if (!_img && !_imgPath.isNull()) {
if (!_img && !_imgPath.isNull() && !_ozf.isOpen()) {
_img = new QImage(_imgPath);
if (_img->isNull())
qWarning("%s: error loading map image", qPrintable(_imgPath));
@ -496,79 +548,100 @@ void OfflineMap::unload()
}
}
QRectF OfflineMap::bounds() const
void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
{
return QRectF(QPointF(0, 0), _size);
QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tileSize.width())
* _tileSize.width(), (int)floor(rect.top() / _tileSize.height())
* _tileSize.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();
if (!QRectF(QPointF(x, y), _ozf.tileSize()).intersects(bounds())) {
painter->fillRect(QRectF(QPoint(x, y), _tileSize), Qt::white);
continue;
}
QString tileName(_tileName.arg(QString::number(x),
QString::number(y)));
QPixmap pixmap;
if (_tar.isOpen()) {
QString key = _tar.fileName() + "/" + tileName;
if (!QPixmapCache::find(key, &pixmap)) {
QByteArray ba = _tar.file(tileName);
pixmap = QPixmap::fromImage(QImage::fromData(ba));
if (!pixmap.isNull())
QPixmapCache::insert(key, pixmap);
}
} else
pixmap = QPixmap(tileName);
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), Qt::white);
} else
painter->drawPixmap(QPoint(x, y), pixmap);
}
}
}
qreal OfflineMap::zoomFit(const QSize &size, const QRectF &br)
void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(size);
Q_UNUSED(br);
QPoint tl = QPoint((int)floor(rect.left() / _ozf.tileSize().width())
* _ozf.tileSize().width(), (int)floor(rect.top()
/ _ozf.tileSize().height()) * _ozf.tileSize().height());
return 1.0;
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();
if (!QRectF(QPointF(x, y), _ozf.tileSize()).intersects(bounds())) {
painter->fillRect(QRectF(QPoint(x, y), _tileSize), Qt::white);
continue;
}
QPixmap pixmap;
QString key = _ozf.fileName() + "/" + QString::number(x)
+ "_" + QString::number(y);
if (!QPixmapCache::find(key, &pixmap)) {
pixmap = _ozf.tile(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), _tileSize), Qt::white);
} else
painter->drawPixmap(QPoint(x, y), pixmap);
}
}
}
qreal OfflineMap::resolution(const QPointF &p) const
void OfflineMap::drawImage(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(p);
return _resolution;
}
qreal OfflineMap::zoomIn()
{
return 1.0;
}
qreal OfflineMap::zoomOut()
{
return 1.0;
if (!_img || _img->isNull())
painter->fillRect(rect, Qt::white);
else {
QPoint p = rect.topLeft().toPoint();
QImage crop = _img->copy(QRect(p, rect.size().toSize()));
painter->drawImage(rect.topLeft(), crop);
}
}
void OfflineMap::draw(QPainter *painter, const QRectF &rect)
{
if (_tileSize.isValid()) {
QPoint tl = QPoint((int)floor(rect.left() / (qreal)_tileSize.width())
* _tileSize.width(), (int)floor(rect.top() / _tileSize.height())
* _tileSize.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();
QString tileName(_tileName.arg(QString::number(x),
QString::number(y)));
QPixmap pixmap;
if (_tar.isOpen()) {
QString key = _tar.fileName() + "/" + tileName;
if (!QPixmapCache::find(key, &pixmap)) {
QByteArray ba = _tar.file(tileName);
pixmap = QPixmap::fromImage(QImage::fromData(ba));
if (!pixmap.isNull())
QPixmapCache::insert(key, pixmap);
}
} else
pixmap = QPixmap(tileName);
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),
Qt::white);
} else
painter->drawPixmap(QPoint(x, y), pixmap);
}
}
} else {
if (!_img || _img->isNull())
painter->fillRect(rect, Qt::white);
else {
QPoint p = rect.topLeft().toPoint();
QImage crop = _img->copy(QRect(p, rect.size().toSize()));
painter->drawImage(rect.topLeft(), crop);
}
}
if (_ozf.isOpen())
drawOZF(painter, rect);
else if (_tileSize.isValid())
drawTiled(painter, rect);
else
drawImage(painter, rect);
}

View File

@ -4,6 +4,7 @@
#include <QTransform>
#include "map.h"
#include "tar.h"
#include "ozf.h"
#include "coordinates.h"
#include "projection.h"
@ -16,19 +17,19 @@ class OfflineMap : public Map
Q_OBJECT
public:
OfflineMap(const QString &path, QObject *parent = 0);
OfflineMap(Tar &tar, const QString &path, QObject *parent = 0);
OfflineMap(const QString &fileName, QObject *parent = 0);
OfflineMap(const QString &fileName, Tar &tar, QObject *parent = 0);
~OfflineMap();
const QString &name() const {return _name;}
QRectF bounds() const;
qreal resolution(const QPointF &p) const;
QRectF bounds() const {return QRectF(QPointF(0, 0), _size);}
qreal resolution(const QPointF &) const {return _resolution;}
qreal zoom() const {return 1.0;}
qreal zoomFit(const QSize &size, const QRectF &br);
qreal zoomIn();
qreal zoomOut();
qreal zoomFit(const QSize &, const QRectF &) {return 1.0;}
qreal zoomIn() {return 1.0;}
qreal zoomOut() {return 1.0;}
QPointF ll2xy(const Coordinates &c) const
{return _transform.map(_projection->ll2xy(c));}
@ -40,7 +41,8 @@ public:
void load();
void unload();
bool isValid() {return _valid;}
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
QPointF ll2pp(const Coordinates &c) const
{return _projection->ll2xy(c);}
@ -57,8 +59,8 @@ private:
} ReferencePoint;
typedef struct {
double centralParallel;
double centralMeridian;
double latitudeOrigin;
double longitudeOrigin;
double scale;
double falseEasting;
double falseNorthing;
@ -67,9 +69,10 @@ private:
int zone;
} ProjectionSetup;
int parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
int parse(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, ProjectionSetup &setup, QString &datum);
bool parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, ProjectionSetup &setup, QString &datum);
bool mapLoaded(int res);
bool totalSizeSet();
bool createProjection(const QString &datum, const QString &projection,
const ProjectionSetup &setup, QList<ReferencePoint> &points);
@ -78,20 +81,26 @@ private:
bool getTileInfo(const QStringList &tiles, const QString &path = QString());
bool getImageInfo(const QString &path);
void drawTiled(QPainter *painter, const QRectF &rect);
void drawOZF(QPainter *painter, const QRectF &rect);
void drawImage(QPainter *painter, const QRectF &rect);
QString _name;
bool _valid;
QString _errorString;
QSize _size;
Projection *_projection;
QTransform _transform, _inverted;
qreal _resolution;
OZF _ozf;
Tar _tar;
QString _tarPath;
QImage *_img;
QString _imgPath;
QSize _tileSize;
QString _tileName;
bool _valid;
};
#endif // OFFLINEMAP_H

142
src/ozf.cpp Normal file
View File

@ -0,0 +1,142 @@
#include <QtEndian>
#include <QFile>
#include "ozf.h"
#define OZF2_MAGIC 0x7778
#define OZF2_SEPARATOR 0x77777777
template<class T> bool OZF::readValue(T &val)
{
T data;
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
return false;
if (sizeof(T) > 1)
val = qFromLittleEndian(data);
else
val = data;
return true;
}
bool OZF::readHeaders()
{
quint16 magic;
quint32 separator;
if (!readValue(magic) || magic != OZF2_MAGIC)
return false;
if (!_file.seek(_file.pos() + 52))
return false;
if (!readValue(separator) || separator != OZF2_SEPARATOR)
return false;
return true;
}
bool OZF::readTileTable()
{
quint32 offset, bgr0, w, h;
quint16 x, y;
if (!_file.seek(_file.size() - 4))
return false;
// table offset
if (!readValue(offset))
return false;
if (!_file.seek(offset))
return false;
// tiles offset (zoom level 0)
if (!readValue(offset))
return false;
if (!_file.seek(offset))
return false;
if (!readValue(w))
return false;
if (!readValue(h))
return false;
if (!readValue(x))
return false;
if (!readValue(y))
return false;
_size = QSize(w, h);
_dim = QSize(x, y);
_palette = QVector<quint32>(256);
for (int i = 0; i < _palette.size(); i++) {
if (!readValue(bgr0))
return false;
quint32 b = (bgr0 & 0x000000FF);
quint32 g = (bgr0 & 0x0000FF00) >> 8;
quint32 r = (bgr0 & 0x00FF0000) >> 16;
_palette[i] = 0xFF000000 | r << 16 | g << 8 | b;
}
_tiles = QVector<quint32>(_dim.width() * _dim.height() + 1);
for (int i = 0; i < _tiles.size(); i++)
if (!readValue(_tiles[i]))
return false;
return true;
}
bool OZF::load(const QString &path)
{
if (_file.isOpen())
_file.close();
_file.setFileName(path);
if (!_file.open(QIODevice::ReadOnly))
return false;
if (!readHeaders()) {
qWarning("%s: not a OZF2 file", qPrintable(_file.fileName()));
_file.close();
return false;
}
if (!readTileTable()) {
qWarning("%s: file format error", qPrintable(_file.fileName()));
_file.close();
_size = QSize();
return false;
}
return true;
}
QPixmap OZF::tile(int x, int y)
{
Q_ASSERT(_file.isOpen());
int i = (y/tileSize().height()) * _dim.width() + (x/tileSize().width());
if (i >= _tiles.size() - 1 || i < 0)
return QPixmap();
int size = _tiles.at(i+1) - _tiles.at(i);
if (!_file.seek(_tiles.at(i)))
return QPixmap();
QByteArray ba = _file.read(size);
if (ba.size() != size)
return QPixmap();
quint32 bes = qToBigEndian(tileSize().width() * tileSize().height());
ba.prepend(QByteArray((char*)&bes, sizeof(bes)));
QByteArray uba = qUncompress(ba);
if (uba.size() != tileSize().width() * tileSize().height())
return QPixmap();
QImage img((const uchar*)uba.constData(), tileSize().width(),
tileSize().height(), QImage::Format_Indexed8);
img.setColorTable(_palette);
return QPixmap::fromImage(img.mirrored());
}

36
src/ozf.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef OZF_H
#define OZF_H
#include <QString>
#include <QSize>
#include <QColor>
#include <QVector>
#include <QFile>
#include <QPixmap>
class OZF
{
public:
bool load(const QString &path);
QString fileName() const {return _file.fileName();}
bool isOpen() const {return _file.isOpen();}
QSize size() const {return _size;}
QSize tileSize() const {return QSize(64, 64);}
QPixmap tile(int x, int y);
private:
template<class T> bool readValue(T &val);
bool readHeaders();
bool readTileTable();
QSize _size;
QSize _dim;
QVector<QRgb> _palette;
QVector<quint32> _tiles;
QFile _file;
};
#endif // OZF_H

View File

@ -521,6 +521,8 @@ void PathView::clear()
_digitalZoom = 0;
resetTransform();
resetCachedContent();
}
void PathView::showTracks(bool show)

View File

@ -50,18 +50,26 @@ bool Tar::load(const QString &path)
quint64 size;
qint64 ret;
if (_file.isOpen())
_file.close();
_index.clear();
_file.setFileName(path);
if (!_file.open(QIODevice::ReadOnly))
return false;
while ((ret = _file.read(buffer, BLOCKSIZE)) > 0) {
if (ret < BLOCKSIZE)
if (ret < BLOCKSIZE) {
_file.close();
return false;
}
size = number(hdr->size, sizeof(hdr->size));
if (size)
_index.insert(hdr->name, Info(size, _file.pos()));
if (!_file.seek(_file.pos() + BLOCKCOUNT(size) * BLOCKSIZE))
if (!_file.seek(_file.pos() + BLOCKCOUNT(size) * BLOCKSIZE)) {
_file.close();
return false;
}
}
return true;
@ -73,6 +81,7 @@ QByteArray Tar::file(const QString &name)
if (it == _index.end())
return QByteArray();
Q_ASSERT(_file.isOpen());
if (_file.seek(it.value().offset()))
return _file.read(it.value().size());
else

View File

@ -1,12 +1,14 @@
#include "ellipsoid.h"
#include "utm.h"
UTM::UTM(int zone) : _tm(Ellipsoid(), (qAbs(zone) - 1)*6 - 180 + 3, 0.9996,
500000, zone < 0 ? 10000000 : 0)
UTM::UTM(const Ellipsoid &ellipsoid, int zone)
: _tm(ellipsoid, (qAbs(zone) - 1)*6 - 180 + 3, 0.9996, 500000,
zone < 0 ? 10000000 : 0)
{
}
UTM::UTM(const Coordinates &c) : _tm(Ellipsoid(), 0, 0, 0, 0)
UTM::UTM(const Ellipsoid &ellipsoid, const Coordinates &c)
: _tm(ellipsoid, 0, 0, 0, 0)
{
int zone = int((c.lon() + 180)/6) + 1;
@ -24,6 +26,6 @@ UTM::UTM(const Coordinates &c) : _tm(Ellipsoid(), 0, 0, 0, 0)
}
double cm = (zone - 1)*6 - 180 + 3;
_tm = TransverseMercator(Ellipsoid(), cm, 0.9996, 500000,
_tm = TransverseMercator(ellipsoid, cm, 0.9996, 500000,
(c.lat() < 0) ? 10000000 : 0);
}

View File

@ -7,8 +7,8 @@
class UTM : public Projection
{
public:
UTM(int zone);
UTM(const Coordinates &c);
UTM(const Ellipsoid &ellipsoid, int zone);
UTM(const Ellipsoid &ellipsoid, const Coordinates &c);
virtual QPointF ll2xy(const Coordinates &c) const
{return _tm.ll2xy(c);}