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

Compare commits

...

75 Commits
4.19 ... 5.0

Author SHA1 Message Date
089d796194 Normalize paths when displaying them. 2018-02-10 16:01:01 +01:00
2677bb77f8 Moved Mac plist to the pkg directory 2018-02-10 11:17:31 +01:00
13dba26d3e Fixed appveyor build script 2018-02-10 10:26:06 +01:00
9675e19b94 Fixed error reporting 2018-02-10 09:57:21 +01:00
8d3fcc7a17 Moved all csv files to a separate directory 2018-02-10 09:29:10 +01:00
8dc5cb7aa8 Load qt translations on OS X 2018-02-10 09:14:24 +01:00
af99e4e05a Fixed translations loading 2018-02-09 22:34:38 +01:00
d18c0d1643 OS X resources fix + cleanup 2018-02-09 22:25:20 +01:00
b9a93d30c0 Create CONTRIBUTING.md 2018-02-09 21:41:16 +01:00
2b6d3799ec Properly load QT translations on windows 2018-02-09 21:04:37 +01:00
152828042f Fixed copy command 2018-02-09 00:11:06 +01:00
e1683a7560 Copy only *.qm files 2018-02-08 20:54:37 +01:00
444cf344a9 Appveyor build fix 2018-02-08 20:31:00 +01:00
7ac0bcf6d2 Fixed typos 2018-02-08 20:24:39 +01:00
a1ac306bfc Added French localization to Windows installer 2018-02-08 20:22:35 +01:00
db4a436ff5 Added the localization files into the bundle 2018-02-08 19:50:15 +01:00
84a6f6c875 Silenced clang warning 2018-02-08 18:34:06 +01:00
06f2c883d4 Added French localization file to qmake 2018-02-08 18:21:04 +01:00
fc95ebfe2b Add French translation file (#62)
in GPXSee/lang/gpxsee_fr.qm
2018-02-08 18:17:29 +01:00
4b64ee467c Moved translations outside of the binary 2018-02-08 18:16:44 +01:00
331cb48e11 Added czech description 2018-02-05 20:45:40 +01:00
fce0c49504 Added missing German strings 2018-02-05 20:39:44 +01:00
f670fb0859 Update gpxsee.desktop (#59) 2018-02-05 19:22:22 +01:00
1e45713aa4 Add .gitignore (#51) 2018-02-05 19:19:11 +01:00
7265c85b83 Update gpxsee_ru.ts, gpxsee_fi.ts (#57) 2018-02-05 19:17:35 +01:00
4d156044d0 Update gpxsee_sv.ts (#58)
New strings translated
2018-02-04 22:51:00 +01:00
17c9416532 Added USGS-imagery map bounds 2018-02-04 15:59:27 +01:00
8e9db2354e Localization update 2018-02-04 15:30:54 +01:00
544a838821 Added linux desktop & MIME files 2018-02-04 14:54:26 +01:00
44d84bf19e API cleanup 2018-01-31 20:03:50 +01:00
4ca9c79dc4 Only 6 projection parameters are required in PCS CSV 2018-01-31 20:02:09 +01:00
cb77cc37c4 Cosmetics 2018-01-31 20:01:49 +01:00
98dd8c264c Replaced data sources info with bare paths info 2018-01-31 08:14:25 +01:00
84d860e2a2 Added recursive POI dir searching to be consistent with map dir searching 2018-01-30 00:30:26 +01:00
e10f8e9c1b Retry... 2018-01-30 00:10:43 +01:00
f433f855a4 Fixed appveyor build 2018-01-29 22:58:57 +01:00
c90a03e22c Enable loading of multiple map files at once 2018-01-29 22:43:55 +01:00
fbc0fd86cf Only allow one map per file 2018-01-29 00:19:57 +01:00
aa07b20aa4 Switched to XML defined online map sources 2018-01-28 22:56:08 +01:00
8a7edcfd8d Properly removed the obsolete header file 2018-01-26 01:33:00 +01:00
04a145a2e7 Using a more human-readable online maps bounds definition 2018-01-26 01:26:26 +01:00
66f0f6a202 Make the conversion functions a little bit more universal. 2018-01-25 20:49:01 +01:00
5698b4c9b0 Fixed another bunch of GeoTIFF handling bugs 2018-01-25 00:19:11 +01:00
77c4eda385 Code cleanup 2018-01-22 00:38:13 +01:00
d6de3acbd2 Added correct handling of the DMS degree definition (9110) 2018-01-22 00:28:58 +01:00
652ed8e919 Fixed broken error handling 2018-01-21 11:38:01 +01:00
58e1980b0d Debug stream code cleanup/unification 2018-01-21 11:19:46 +01:00
fda33cc95b Improved error reporting 2018-01-21 11:17:32 +01:00
02e724fefb Added remaining missing units conversions 2018-01-21 10:18:15 +01:00
da220c4b62 Improved error handling 2018-01-21 01:01:58 +01:00
6ffc71fd36 Improved debuging 2018-01-21 00:48:34 +01:00
635e2f1fe3 Fixed switched lat/lon parameter fetch 2018-01-21 00:47:51 +01:00
23e4e66c1b Use a PCS file format more compatible with the EPSG PCS database 2018-01-20 23:51:39 +01:00
1739625896 Added support for prime meridians and angular units to GCS 2018-01-20 20:13:56 +01:00
e9ef68a81c Improved map file selection 2018-01-14 23:58:11 +01:00
06205470fe Fixed broken online map lists loading 2018-01-14 23:46:39 +01:00
c535632eb6 Updated map info text
Deleted obsolete stuff
2018-01-14 23:33:13 +01:00
9f1f06577c Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-01-14 23:04:15 +01:00
0e45831111 Do not require a directory per map anymore 2018-01-14 23:03:27 +01:00
0c8e864d32 Return the correct error value 2018-01-14 22:51:20 +01:00
c9cac70e1f Add Finnish translation (#50) 2018-01-11 10:34:00 +01:00
045cbe81bf Added support for matrix-defined transformations
Fixed transformation matrix computation
2018-01-10 01:28:40 +01:00
bffd1d9172 Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-01-09 23:21:05 +01:00
b8102d6bb7 Do a propper cleanup on error 2018-01-09 23:19:35 +01:00
fc80bd1b7c Code cleanup 2018-01-09 23:19:24 +01:00
2441c4996d Fix typos in Russian translation (#49) 2018-01-09 22:57:58 +01:00
89878fade1 Made the MM/II code work on Windows as well 2018-01-09 09:39:35 +01:00
83b7741ed9 Added missing include 2018-01-09 09:35:56 +01:00
f44b14473d Fixed broken MM files size issue 2018-01-09 01:29:20 +01:00
699de8b133 Added support for files referenced using geodetic datum+projection combination 2018-01-09 00:26:18 +01:00
b7dd11fa1f Add Russian translation (#48) 2018-01-08 23:57:33 +01:00
0a32a9b865 Merge branch 'geotiff' 2018-01-08 23:53:18 +01:00
02ad65461c Merge branch 'master' of https://github.com/tumic0/GPXSee 2018-01-08 23:49:00 +01:00
5fa52b0166 Add support for GeoTIFF images 2018-01-08 23:47:45 +01:00
84f41b5aa9 Added support for negative altitude values.
Fixes #43.
2018-01-06 21:44:03 +01:00
100 changed files with 10112 additions and 1744 deletions

View File

@ -1,4 +1,4 @@
version: 4.19.{build}
version: 5.0.{build}
configuration: Release
platform: Any CPU
environment:
@ -34,11 +34,11 @@ build_script:
copy pkg\%NSI% installer
copy pkg\datums.csv installer
xcopy pkg\csv installer\csv /i
copy pkg\ellipsoids.csv installer
xcopy pkg\maps installer\maps /i
copy pkg\maps.txt installer
xcopy lang\*.qm installer\translations\ /sy
copy licence.txt installer
@ -49,4 +49,4 @@ build_script:
makensis.exe installer\%NSI%
artifacts:
- path: installer\GPXSee-*.exe
- path: installer\GPXSee-*.exe

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# C++ objects and libs
*.o
# Qt-es
/.qmake.stash
moc_*.cpp
moc_*.h
qrc_*.cpp
Makefile*
*.qm
# Binary
GPXSee

7
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,7 @@
Only localization contributions are accepted at the moment, code pull requests will be rejected.
The rationale is, that I want leave the possibility to distribute GPXsee builds in the OS X/Windows
stores under a non-GPL licence open. In the future, code pull requests under a QT-like contribution
agreement [1] will be possible.
[1] https://d21tv0wm5mksdn.cloudfront.net/wp-content/uploads/2015/03/Qt-ContributionLicenseAgreement_v1_2_FINAL.pdf

View File

@ -1,5 +1,5 @@
TARGET = GPXSee
VERSION = 4.19
VERSION = 5.0
QT += core \
gui \
network
@ -14,6 +14,7 @@ HEADERS += src/config.h \
src/common/range.h \
src/common/rectc.h \
src/common/wgs84.h \
src/common/str2int.h \
src/GUI/app.h \
src/GUI/icons.h \
src/GUI/gui.h \
@ -86,7 +87,11 @@ HEADERS += src/config.h \
src/map/ozf.h \
src/map/atlas.h \
src/map/matrix.h \
src/map/misc.h \
src/map/geotiff.h \
src/map/pcs.h \
src/map/transform.h \
src/map/mapfile.h \
src/map/tifffile.h \
src/data/graph.h \
src/data/poi.h \
src/data/waypoint.h \
@ -106,11 +111,17 @@ HEADERS += src/config.h \
src/data/fitparser.h \
src/data/igcparser.h \
src/data/nmeaparser.h \
src/data/str2int.h
src/map/gcs.h \
src/map/angularunits.h \
src/map/primemeridian.h \
src/map/linearunits.h \
src/map/ct.h \
src/map/mapsource.h
SOURCES += src/main.cpp \
src/common/coordinates.cpp \
src/common/rectc.cpp \
src/common/range.cpp \
src/common/str2int.cpp \
src/GUI/app.cpp \
src/GUI/gui.cpp \
src/GUI/axisitem.cpp \
@ -163,13 +174,17 @@ SOURCES += src/main.cpp \
src/map/matrix.cpp \
src/map/ellipsoid.cpp \
src/map/datum.cpp \
src/map/projection.cpp \
src/map/mercator.cpp \
src/map/transversemercator.cpp \
src/map/utm.cpp \
src/map/lambertconic.cpp \
src/map/albersequal.cpp \
src/map/lambertazimuthal.cpp \
src/map/geotiff.cpp \
src/map/pcs.cpp \
src/map/transform.cpp \
src/map/mapfile.cpp \
src/map/tifffile.cpp \
src/data/data.cpp \
src/data/poi.cpp \
src/data/track.cpp \
@ -182,25 +197,40 @@ SOURCES += src/main.cpp \
src/data/fitparser.cpp \
src/data/igcparser.cpp \
src/data/nmeaparser.cpp \
src/data/str2int.cpp
src/map/projection.cpp \
src/map/gcs.cpp \
src/map/angularunits.cpp \
src/map/primemeridian.cpp \
src/map/linearunits.cpp \
src/map/mapsource.cpp
RESOURCES += gpxsee.qrc
TRANSLATIONS = lang/gpxsee_cs.ts \
lang/gpxsee_sv.ts \
lang/gpxsee_de.ts
lang/gpxsee_de.ts \
lang/gpxsee_ru.ts \
lang/gpxsee_fi.ts \
lang/gpxsee_fr.ts
macx {
ICON = icons/gpxsee.icns
QMAKE_INFO_PLIST = Info.plist
APP_RESOURCES.files = icons/gpx.icns \
icons/tcx.icns \
QMAKE_INFO_PLIST = pkg/Info.plist
LOCALE.path = Contents/Resources/translations
LOCALE.files = lang/gpxsee_cs.qm \
lang/gpxsee_de.qm \
lang/gpxsee_fi.qm \
lang/gpxsee_fr.qm \
lang/gpxsee_ru.qm \
lang/gpxsee_sv.qm
CSV.path = Contents/Resources
CSV.files = pkg/csv
MAPS.path = Contents/Resources
MAPS.files = pkg/maps
ICONS.path = Contents/Resources/icons
ICONS.files = icons/tcx.icns \
icons/kml.icns \
icons/fit.icns \
icons/igc.icns \
icons/nmea.icns \
pkg/maps.txt \
pkg/ellipsoids.csv \
pkg/datums.csv
APP_RESOURCES.path = Contents/Resources
QMAKE_BUNDLE_DATA += APP_RESOURCES
icons/nmea.icns
QMAKE_BUNDLE_DATA += LOCALE MAPS ICONS CSV
}
win32 {
RC_ICONS = icons/gpxsee.ico \

View File

@ -20,8 +20,5 @@
<file>icons/system-run.png</file>
<file>icons/document-print-preview.png</file>
<file>icons/view-filter.png</file>
<file>lang/gpxsee_cs.qm</file>
<file>lang/gpxsee_sv.qm</file>
<file>lang/gpxsee_de.qm</file>
</qresource>
</RCC>

View File

@ -46,50 +46,50 @@
</context>
<context>
<name>Data</name>
<message>
<location filename="../src/data/data.cpp" line="102"/>
<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/data/data.cpp" line="103"/>
<source>CSV files (*.csv)</source>
<translation>Soubory CSV (*.csv)</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="103"/>
<source>FIT files (*.fit)</source>
<translation>Soubory FIT (*.fit)</translation>
<source>Supported files</source>
<translation>Podporované soubory</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>GPX files (*.gpx)</source>
<translation>Soubory GPX (*.gpx)</translation>
<source>CSV files</source>
<translation>Soubory CSV</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>IGC files (*.igc)</source>
<translation>Soubory IGC (*.igc)</translation>
<source>FIT files</source>
<translation>Soubory FIT</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>KML files (*.kml)</source>
<translation>Soubory KML (*.kml)</translation>
<source>GPX files</source>
<translation>Soubory GPX</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>NMEA files (*.nmea)</source>
<translation>Soubory NMEA (*.nmea)</translation>
<source>IGC files</source>
<translation>Soubory IGC</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>TCX files (*.tcx)</source>
<translation>Soubory TCX (*.tcx)</translation>
<source>KML files</source>
<translation>Soubory KML</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>All files (*)</source>
<translation>Všechny soubory (*)</translation>
<source>NMEA files</source>
<translation>Soubory NMEA</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>TCX files</source>
<translation>Soubory TCX</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>All files</source>
<translation>Všechny soubory</translation>
</message>
</context>
<context>
@ -295,341 +295,351 @@
<context>
<name>GUI</name>
<message>
<location filename="../src/GUI/gui.cpp" line="600"/>
<location filename="../src/GUI/gui.cpp" line="562"/>
<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/gui.cpp" line="685"/>
<location filename="../src/GUI/gui.cpp" line="634"/>
<source>Open file</source>
<translation>Otevřít soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="775"/>
<location filename="../src/GUI/gui.cpp" line="723"/>
<source>Open POI file</source>
<translation>Otevřít POI soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="234"/>
<location filename="../src/GUI/gui.cpp" line="196"/>
<source>Quit</source>
<translation>Ukončit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="243"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<location filename="../src/GUI/gui.cpp" line="618"/>
<location filename="../src/GUI/gui.cpp" line="205"/>
<location filename="../src/GUI/gui.cpp" line="579"/>
<location filename="../src/GUI/gui.cpp" line="580"/>
<source>Keyboard controls</source>
<translation>Ovládací klávesy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="268"/>
<location filename="../src/GUI/gui.cpp" line="230"/>
<source>Close</source>
<translation>Zavřít</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="274"/>
<location filename="../src/GUI/gui.cpp" line="236"/>
<source>Reload</source>
<translation>Znovu načíst</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="529"/>
<location filename="../src/GUI/gui.cpp" line="491"/>
<source>Show</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="445"/>
<location filename="../src/GUI/gui.cpp" line="523"/>
<location filename="../src/GUI/gui.cpp" line="407"/>
<location filename="../src/GUI/gui.cpp" line="485"/>
<source>File</source>
<translation>Soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="241"/>
<location filename="../src/GUI/gui.cpp" line="651"/>
<location filename="../src/GUI/gui.cpp" line="652"/>
<source>Data sources</source>
<translation>Zdroje dat</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="247"/>
<source>Close POI files</source>
<translation>Zavřit POI soubory</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="287"/>
<location filename="../src/GUI/gui.cpp" line="249"/>
<source>Overlap POIs</source>
<translation>Překrývat POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="291"/>
<location filename="../src/GUI/gui.cpp" line="253"/>
<source>Show POI labels</source>
<translation>Zobrazit názvy POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="296"/>
<location filename="../src/GUI/gui.cpp" line="258"/>
<source>Show POIs</source>
<translation>Zobrazit POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="305"/>
<location filename="../src/GUI/gui.cpp" line="267"/>
<source>Show map</source>
<translation>Zobrazit mapu</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="315"/>
<location filename="../src/GUI/gui.cpp" line="277"/>
<source>Clear tile cache</source>
<translation>Vymazat mezipaměť dlaždic</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="252"/>
<location filename="../src/GUI/gui.cpp" line="214"/>
<source>Open...</source>
<translation>Otevřít...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="282"/>
<location filename="../src/GUI/gui.cpp" line="203"/>
<location filename="../src/GUI/gui.cpp" line="613"/>
<location filename="../src/GUI/gui.cpp" line="614"/>
<source>Paths</source>
<translation>Cesty</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="244"/>
<source>Load POI file...</source>
<translation>Nahrát POI soubor...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="313"/>
<location filename="../src/GUI/gui.cpp" line="275"/>
<source>Load map...</source>
<translation>Nahrát mapu...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="319"/>
<location filename="../src/GUI/gui.cpp" line="323"/>
<location filename="../src/GUI/gui.cpp" line="634"/>
<location filename="../src/GUI/gui.cpp" line="281"/>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<source>Next map</source>
<translation>Následující mapa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="333"/>
<location filename="../src/GUI/gui.cpp" line="295"/>
<source>Show tracks</source>
<translation>Zobrazit cesty</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="337"/>
<location filename="../src/GUI/gui.cpp" line="299"/>
<source>Show routes</source>
<translation>Zobrazit trasy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="341"/>
<location filename="../src/GUI/gui.cpp" line="303"/>
<source>Show waypoints</source>
<translation>Zobrazit navigační body</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="345"/>
<location filename="../src/GUI/gui.cpp" line="307"/>
<source>Waypoint labels</source>
<translation>Názvy navigačních bodů</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="356"/>
<location filename="../src/GUI/gui.cpp" line="318"/>
<source>Show graphs</source>
<translation>Zobrazit grafy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="376"/>
<location filename="../src/GUI/gui.cpp" line="338"/>
<source>Show grid</source>
<translation>Zobrazit mřížku</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="380"/>
<location filename="../src/GUI/gui.cpp" line="342"/>
<source>Show slider info</source>
<translation>Zobrazit informace o posuvníku</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="386"/>
<location filename="../src/GUI/gui.cpp" line="348"/>
<source>Show toolbars</source>
<translation>Zobrazovat nástrojové lišty</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="392"/>
<location filename="../src/GUI/gui.cpp" line="354"/>
<source>Total time</source>
<translation>Celkový čas</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="397"/>
<location filename="../src/GUI/gui.cpp" line="950"/>
<location filename="../src/GUI/gui.cpp" line="359"/>
<location filename="../src/GUI/gui.cpp" line="898"/>
<source>Moving time</source>
<translation>Čistý čas</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="404"/>
<location filename="../src/GUI/gui.cpp" line="366"/>
<source>Metric</source>
<translation>Metrické</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="409"/>
<location filename="../src/GUI/gui.cpp" line="371"/>
<source>Imperial</source>
<translation>Imperiální</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="415"/>
<location filename="../src/GUI/gui.cpp" line="377"/>
<source>Fullscreen mode</source>
<translation>Celoobrazovkový režim</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="421"/>
<location filename="../src/GUI/gui.cpp" line="383"/>
<source>Options...</source>
<translation>Nastavení...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="427"/>
<location filename="../src/GUI/gui.cpp" line="389"/>
<source>Next</source>
<translation>Následující</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="430"/>
<location filename="../src/GUI/gui.cpp" line="392"/>
<source>Previous</source>
<translation>Předchozí</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="434"/>
<location filename="../src/GUI/gui.cpp" line="396"/>
<source>Last</source>
<translation>Poslední</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="437"/>
<location filename="../src/GUI/gui.cpp" line="399"/>
<source>First</source>
<translation>První</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<location filename="../src/GUI/gui.cpp" line="421"/>
<source>Map</source>
<translation>Mapa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="467"/>
<location filename="../src/GUI/gui.cpp" line="429"/>
<source>Graph</source>
<translation>Graf</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="476"/>
<location filename="../src/GUI/gui.cpp" line="438"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="477"/>
<location filename="../src/GUI/gui.cpp" line="439"/>
<source>POI files</source>
<translation>POI soubory</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="488"/>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="489"/>
<location filename="../src/GUI/gui.cpp" line="451"/>
<source>Display</source>
<translation>Zobrazit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="497"/>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>Settings</source>
<translation>Nastavení</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="501"/>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>Units</source>
<translation>Jednotky</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="510"/>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Help</source>
<translation>Nápověda</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="627"/>
<location filename="../src/GUI/gui.cpp" line="589"/>
<source>Append file</source>
<translation>Přidat soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="628"/>
<location filename="../src/GUI/gui.cpp" line="590"/>
<source>Next/Previous</source>
<translation>Následující/Předchozí</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="630"/>
<location filename="../src/GUI/gui.cpp" line="592"/>
<source>Toggle graph type</source>
<translation>Přepnout typ grafu</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="632"/>
<location filename="../src/GUI/gui.cpp" line="594"/>
<source>Toggle time type</source>
<translation>Přepnout typ času</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="636"/>
<location filename="../src/GUI/gui.cpp" line="598"/>
<source>Previous map</source>
<translation>Předchozí mapa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="637"/>
<location filename="../src/GUI/gui.cpp" line="599"/>
<source>Zoom in</source>
<translation>Přiblížit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="639"/>
<location filename="../src/GUI/gui.cpp" line="601"/>
<source>Zoom out</source>
<translation>Oddálit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="641"/>
<location filename="../src/GUI/gui.cpp" line="603"/>
<source>Digital zoom</source>
<translation>Digitální zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="642"/>
<location filename="../src/GUI/gui.cpp" line="604"/>
<source>Zoom</source>
<translation>Zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="654"/>
<source>Online maps</source>
<translation>Online mapy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="655"/>
<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/gui.cpp" line="658"/>
<source>The file format is one map entry per line, consisting of the map name, tiles URL and an optional maximal zoom level 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, URL dlaždic a volitelně maximálního zoomu navzájem oddělených tabulátorem. Souřadnice dlaždice jsou v URL nahrazeny řetězci $x a $y, zoom pak řetězcem $z. Příklad:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="667"/>
<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/gui.cpp" line="1151"/>
<location filename="../src/GUI/gui.cpp" line="1099"/>
<source>Open map file</source>
<translation>Otevřít mapový soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1181"/>
<location filename="../src/GUI/gui.cpp" line="1137"/>
<source>No files loaded</source>
<translation>Nejsou načteny žádné soubory</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="936"/>
<location filename="../src/GUI/gui.cpp" line="939"/>
<location filename="../src/GUI/gui.cpp" line="884"/>
<location filename="../src/GUI/gui.cpp" line="887"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="928"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<source>Map directory:</source>
<translation>Adresář s mapami:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="618"/>
<source>POI directory:</source>
<translation>Adresář s POI body:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="620"/>
<source>GCS file:</source>
<translation>Soubor s GCS daty:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<source>PCS file:</source>
<translation>Soubor s PCS daty:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<source>Ellipsoids file:</source>
<translation>Soubor s daty elipsoidů:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="625"/>
<source>User override directory:</source>
<translation>Uživatelský adresář:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="876"/>
<source>Routes</source>
<translation>Trasy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1172"/>
<location filename="../src/GUI/gui.cpp" line="1126"/>
<source>Error loading map:</source>
<translation>Mapu nelze načíst:</translation>
</message>
<message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1185"/>
<location filename="../src/GUI/gui.cpp" line="1141"/>
<source>%n files</source>
<translation>
<numerusform>%n soubor</numerusform>
@ -638,117 +648,97 @@
</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<location filename="../src/GUI/gui.cpp" line="583"/>
<source>Next file</source>
<translation>Následující soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="597"/>
<location filename="../src/GUI/gui.cpp" line="559"/>
<source>Version </source>
<translation>Verze </translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="257"/>
<location filename="../src/GUI/gui.cpp" line="219"/>
<source>Print...</source>
<translation>Tisknout...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="262"/>
<location filename="../src/GUI/gui.cpp" line="224"/>
<source>Export to PDF...</source>
<translation>Exportovat do PDF...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="930"/>
<location filename="../src/GUI/gui.cpp" line="878"/>
<source>Waypoints</source>
<translation>Navigační body</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<location filename="../src/GUI/gui.cpp" line="584"/>
<source>Previous file</source>
<translation>Předchozí soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="349"/>
<location filename="../src/GUI/gui.cpp" line="311"/>
<source>Route waypoints</source>
<translation>Body tras</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="624"/>
<location filename="../src/GUI/gui.cpp" line="586"/>
<source>First file</source>
<translation>První soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="626"/>
<location filename="../src/GUI/gui.cpp" line="588"/>
<source>Last file</source>
<translation>Poslední soubor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="666"/>
<source>Offline maps</source>
<translation>Offline mapy</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="670"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziExplorer maps and 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/gui.cpp" line="675"/>
<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/gui.cpp" line="764"/>
<location filename="../src/GUI/gui.cpp" line="712"/>
<source>Error loading data file:</source>
<translation>Datový soubor nelze načíst:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="767"/>
<location filename="../src/GUI/gui.cpp" line="792"/>
<location filename="../src/GUI/gui.cpp" line="715"/>
<location filename="../src/GUI/gui.cpp" line="740"/>
<source>Line: %1</source>
<translation>Řádka: %1</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="789"/>
<location filename="../src/GUI/gui.cpp" line="737"/>
<source>Error loading POI file:</source>
<translation>Soubor POI nelze načíst:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="922"/>
<location filename="../src/GUI/gui.cpp" line="870"/>
<source>Name</source>
<translation>Název</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="926"/>
<location filename="../src/GUI/gui.cpp" line="874"/>
<source>Tracks</source>
<translation>Cesty</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="246"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="558"/>
<source>About GPXSee</source>
<translation>O aplikaci GPXSee</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="534"/>
<location filename="../src/GUI/gui.cpp" line="496"/>
<source>Navigation</source>
<translation>Navigace</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="674"/>
<source>POIs</source>
<translation>POI body</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="364"/>
<location filename="../src/GUI/gui.cpp" line="946"/>
<location filename="../src/GUI/gui.cpp" line="326"/>
<location filename="../src/GUI/gui.cpp" line="894"/>
<source>Distance</source>
<translation>Vzdálenost</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="370"/>
<location filename="../src/GUI/gui.cpp" line="498"/>
<location filename="../src/GUI/gui.cpp" line="948"/>
<location filename="../src/GUI/gui.cpp" line="332"/>
<location filename="../src/GUI/gui.cpp" line="460"/>
<location filename="../src/GUI/gui.cpp" line="896"/>
<source>Time</source>
<translation>Čas</translation>
</message>
@ -848,14 +838,29 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="141"/>
<source>Map files (*.map *.tba *.tar)</source>
<translation>Mapové soubory (*.map *.tba *.tar)</translation>
<location filename="../src/map/maplist.cpp" line="128"/>
<source>Supported files</source>
<translation>Podporované soubory</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="142"/>
<source>URL list files (*.txt)</source>
<translation>Seznamy URL (*.txt)</translation>
<location filename="../src/map/maplist.cpp" line="129"/>
<source>OziExplorer maps</source>
<translation>OziExplorer mapy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy mapy/atlasy</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF obrázky</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<source>Online map sources</source>
<translation>Online mapové zdroje</translation>
</message>
</context>
<context>

View File

@ -46,50 +46,50 @@
</context>
<context>
<name>Data</name>
<message>
<location filename="../src/data/data.cpp" line="102"/>
<source>Supported files (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</source>
<translation>Unterstütze Dateien (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="103"/>
<source>CSV files (*.csv)</source>
<translation>CSV-Dateien (*.csv)</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="103"/>
<source>FIT files (*.fit)</source>
<translation>FIT-Dateien (*.fit)</translation>
<source>Supported files</source>
<translation>Unterstütze Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>GPX files (*.gpx)</source>
<translation>GPX-Dateien (*.gpx)</translation>
<source>CSV files</source>
<translation>CSV-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>IGC files (*.igc)</source>
<translation>IGC-Dateien (*.igc)</translation>
<source>FIT files</source>
<translation>FIT-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>KML files (*.kml)</source>
<translation>KML-Dateien (*.kml)</translation>
<source>GPX files</source>
<translation>GPX-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>NMEA files (*.nmea)</source>
<translation>NMEA-Dateien (*.nmea)</translation>
<source>IGC files</source>
<translation>IGC-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>TCX files (*.tcx)</source>
<translation>TCX-Dateien (*.tcx)</translation>
<source>KML files</source>
<translation>KML-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>All files (*)</source>
<translation>Alle Dateien (*)</translation>
<source>NMEA files</source>
<translation>NMEA-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>TCX files</source>
<translation>TCX-Dateien</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
</context>
<context>
@ -295,335 +295,340 @@
<context>
<name>GUI</name>
<message>
<location filename="../src/GUI/gui.cpp" line="600"/>
<location filename="../src/GUI/gui.cpp" line="562"/>
<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 wird unter der GNU General Public License version 3 vertrieben. Mehr Informationen zu GPXSee auf der Homepage </translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="685"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<source>Map directory:</source>
<translation>Kartenverzeichnis:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="618"/>
<source>POI directory:</source>
<translation>POI-Verzeichnis:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="620"/>
<source>GCS file:</source>
<translation>GCS-Datei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<source>PCS file:</source>
<translation>PCS-Datei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<source>Ellipsoids file:</source>
<translation>Ellipsoidendatei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="625"/>
<source>User override directory:</source>
<translation>Benutzerverzeichnis:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="634"/>
<source>Open file</source>
<translation>Datei öffnen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="775"/>
<location filename="../src/GUI/gui.cpp" line="723"/>
<source>Open POI file</source>
<translation>POI Datei öffnen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="234"/>
<location filename="../src/GUI/gui.cpp" line="196"/>
<source>Quit</source>
<translation>Beenden</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="243"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<location filename="../src/GUI/gui.cpp" line="618"/>
<location filename="../src/GUI/gui.cpp" line="205"/>
<location filename="../src/GUI/gui.cpp" line="579"/>
<location filename="../src/GUI/gui.cpp" line="580"/>
<source>Keyboard controls</source>
<translation>Tastaturkürzel</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="268"/>
<location filename="../src/GUI/gui.cpp" line="230"/>
<source>Close</source>
<translation>Schließen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="274"/>
<location filename="../src/GUI/gui.cpp" line="236"/>
<source>Reload</source>
<translation>Neu Laden</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="529"/>
<location filename="../src/GUI/gui.cpp" line="491"/>
<source>Show</source>
<translation>Ansicht</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="445"/>
<location filename="../src/GUI/gui.cpp" line="523"/>
<location filename="../src/GUI/gui.cpp" line="407"/>
<location filename="../src/GUI/gui.cpp" line="485"/>
<source>File</source>
<translation>Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="241"/>
<location filename="../src/GUI/gui.cpp" line="651"/>
<location filename="../src/GUI/gui.cpp" line="652"/>
<source>Data sources</source>
<translation>Datenquellen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="247"/>
<source>Close POI files</source>
<translation>POI-Datei schließen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="287"/>
<location filename="../src/GUI/gui.cpp" line="249"/>
<source>Overlap POIs</source>
<translation>POI überlappen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="291"/>
<location filename="../src/GUI/gui.cpp" line="253"/>
<source>Show POI labels</source>
<translation>POI-Labels anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="296"/>
<location filename="../src/GUI/gui.cpp" line="258"/>
<source>Show POIs</source>
<translation>POIs anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="305"/>
<location filename="../src/GUI/gui.cpp" line="267"/>
<source>Show map</source>
<translation>Karte anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="315"/>
<location filename="../src/GUI/gui.cpp" line="277"/>
<source>Clear tile cache</source>
<translation>Tile-Cache bereinigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="252"/>
<location filename="../src/GUI/gui.cpp" line="214"/>
<source>Open...</source>
<translation>Öffnen...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="282"/>
<location filename="../src/GUI/gui.cpp" line="203"/>
<location filename="../src/GUI/gui.cpp" line="613"/>
<location filename="../src/GUI/gui.cpp" line="614"/>
<source>Paths</source>
<translation>Pfade</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="244"/>
<source>Load POI file...</source>
<translation>POI-Datei laden...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="313"/>
<location filename="../src/GUI/gui.cpp" line="275"/>
<source>Load map...</source>
<translation>Karte laden...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="319"/>
<location filename="../src/GUI/gui.cpp" line="323"/>
<location filename="../src/GUI/gui.cpp" line="634"/>
<location filename="../src/GUI/gui.cpp" line="281"/>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<source>Next map</source>
<translation>Nächste Karte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="333"/>
<location filename="../src/GUI/gui.cpp" line="295"/>
<source>Show tracks</source>
<translation>Strecken anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="337"/>
<location filename="../src/GUI/gui.cpp" line="299"/>
<source>Show routes</source>
<translation>Routen anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="341"/>
<location filename="../src/GUI/gui.cpp" line="303"/>
<source>Show waypoints</source>
<translation>Wegpunkte anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="345"/>
<location filename="../src/GUI/gui.cpp" line="307"/>
<source>Waypoint labels</source>
<translation>Wegpunkt Labels</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="356"/>
<location filename="../src/GUI/gui.cpp" line="318"/>
<source>Show graphs</source>
<translation>Graphen anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="376"/>
<location filename="../src/GUI/gui.cpp" line="338"/>
<source>Show grid</source>
<translation>Gitter anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="380"/>
<location filename="../src/GUI/gui.cpp" line="342"/>
<source>Show slider info</source>
<translation>Schieberinfo anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="386"/>
<location filename="../src/GUI/gui.cpp" line="348"/>
<source>Show toolbars</source>
<translation>Toolbars anzeigen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="392"/>
<location filename="../src/GUI/gui.cpp" line="354"/>
<source>Total time</source>
<translation>Gesamtzeit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="397"/>
<location filename="../src/GUI/gui.cpp" line="950"/>
<location filename="../src/GUI/gui.cpp" line="359"/>
<location filename="../src/GUI/gui.cpp" line="898"/>
<source>Moving time</source>
<translation>Bewegungszeit</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="404"/>
<location filename="../src/GUI/gui.cpp" line="366"/>
<source>Metric</source>
<translation>Metrisch</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="409"/>
<location filename="../src/GUI/gui.cpp" line="371"/>
<source>Imperial</source>
<translation>Imperial</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="415"/>
<location filename="../src/GUI/gui.cpp" line="377"/>
<source>Fullscreen mode</source>
<translation>Vollbildmodus</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="421"/>
<location filename="../src/GUI/gui.cpp" line="383"/>
<source>Options...</source>
<translation>Einstellungen...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="427"/>
<location filename="../src/GUI/gui.cpp" line="389"/>
<source>Next</source>
<translation>Nächste</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="430"/>
<location filename="../src/GUI/gui.cpp" line="392"/>
<source>Previous</source>
<translation>Vorherige</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="434"/>
<location filename="../src/GUI/gui.cpp" line="396"/>
<source>Last</source>
<translation>Letzte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="437"/>
<location filename="../src/GUI/gui.cpp" line="399"/>
<source>First</source>
<translation>Erste</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<location filename="../src/GUI/gui.cpp" line="421"/>
<source>Map</source>
<translation>Karte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="467"/>
<location filename="../src/GUI/gui.cpp" line="429"/>
<source>Graph</source>
<translation>Graph</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="476"/>
<location filename="../src/GUI/gui.cpp" line="438"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="477"/>
<location filename="../src/GUI/gui.cpp" line="439"/>
<source>POI files</source>
<translation>POI-Dateien</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="488"/>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Data</source>
<translation>Daten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="489"/>
<location filename="../src/GUI/gui.cpp" line="451"/>
<source>Display</source>
<translation>Anzeige</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="497"/>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="501"/>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>Units</source>
<translation>Einheiten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="510"/>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="627"/>
<location filename="../src/GUI/gui.cpp" line="589"/>
<source>Append file</source>
<translation>An Datei anhängen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="628"/>
<location filename="../src/GUI/gui.cpp" line="590"/>
<source>Next/Previous</source>
<translation>Nächste/Vorherige</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="630"/>
<location filename="../src/GUI/gui.cpp" line="592"/>
<source>Toggle graph type</source>
<translation>Graphtyp umschalten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="632"/>
<location filename="../src/GUI/gui.cpp" line="594"/>
<source>Toggle time type</source>
<translation>Zeittyp umschalten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="636"/>
<location filename="../src/GUI/gui.cpp" line="598"/>
<source>Previous map</source>
<translation>Vorherige Karte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="637"/>
<location filename="../src/GUI/gui.cpp" line="599"/>
<source>Zoom in</source>
<translation>Hineinzoomen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="639"/>
<location filename="../src/GUI/gui.cpp" line="601"/>
<source>Zoom out</source>
<translation>Herauszoomen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="641"/>
<location filename="../src/GUI/gui.cpp" line="603"/>
<source>Digital zoom</source>
<translation>Digitaler Zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="642"/>
<location filename="../src/GUI/gui.cpp" line="604"/>
<source>Zoom</source>
<translation>Zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="654"/>
<source>Online maps</source>
<translation>Onlinekarten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="655"/>
<source>Online map URLs are read on program startup from the following file:</source>
<translation>Onlinekarten URLs werden zu Programmstart aus der folgenden Datei gelesen:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="658"/>
<source>The file format is one map entry per line, consisting of the map name, tiles URL and an optional maximal zoom level 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>Das Dateiformat ist eine Karte pro Linie. Jede Linie besteht aus dem Kartenname, der Tiles URL und wahlweise dem maximalen Zoomlevel getrennt durch ein TAB Zeichen. X und Y Koordinate einer Tile werden in der URL durch $x und $y ersetzt und das Zoomlevel durch $z. Ein Beispiel einer Kartendatei könnte so aussehen:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="666"/>
<source>Offline maps</source>
<translation>Offlinekarten</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="667"/>
<source>Offline maps are loaded on program startup from the following directory:</source>
<translation>Offlinekarten werden zu Programmstart aus dem folgenden Verzeichnis geladen:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1151"/>
<location filename="../src/GUI/gui.cpp" line="1099"/>
<source>Open map file</source>
<translation>Karte Datei öffnen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1172"/>
<location filename="../src/GUI/gui.cpp" line="1126"/>
<source>Error loading map:</source>
<translation>Fehler beim Laden der Karte-Datei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1181"/>
<location filename="../src/GUI/gui.cpp" line="1137"/>
<source>No files loaded</source>
<translation>Keine Dateien geladen</translation>
</message>
<message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1185"/>
<location filename="../src/GUI/gui.cpp" line="1141"/>
<source>%n files</source>
<translation>
<numerusform>%n Datei</numerusform>
@ -631,123 +636,108 @@
</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="936"/>
<location filename="../src/GUI/gui.cpp" line="939"/>
<location filename="../src/GUI/gui.cpp" line="884"/>
<location filename="../src/GUI/gui.cpp" line="887"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="928"/>
<location filename="../src/GUI/gui.cpp" line="876"/>
<source>Routes</source>
<translation>Routen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<location filename="../src/GUI/gui.cpp" line="583"/>
<source>Next file</source>
<translation>Nächste Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="597"/>
<location filename="../src/GUI/gui.cpp" line="559"/>
<source>Version </source>
<translation>Version </translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="257"/>
<location filename="../src/GUI/gui.cpp" line="219"/>
<source>Print...</source>
<translation>Drucken...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="262"/>
<location filename="../src/GUI/gui.cpp" line="224"/>
<source>Export to PDF...</source>
<translation>Als PDF exportieren...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="930"/>
<location filename="../src/GUI/gui.cpp" line="878"/>
<source>Waypoints</source>
<translation>Wegpunkte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<location filename="../src/GUI/gui.cpp" line="584"/>
<source>Previous file</source>
<translation>Vorherige Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="349"/>
<location filename="../src/GUI/gui.cpp" line="311"/>
<source>Route waypoints</source>
<translation>Routen Wegpunkte</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="624"/>
<location filename="../src/GUI/gui.cpp" line="586"/>
<source>First file</source>
<translation>Erste Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="626"/>
<location filename="../src/GUI/gui.cpp" line="588"/>
<source>Last file</source>
<translation>Letzte Datei</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="670"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziExplorer maps and TrekBuddy maps/atlases (tared and non-tared).</source>
<translation>Die erwartete Struktur ist eine Karte/ein Atlas pro Unterverzeichnis. Unterstützte Kartenformate sind OziExplorer Karten und TrekBuddy Karten/Atlanten (mit oder ohne tar Kompression).</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="675"/>
<source>To make GPXSee load a POI file automatically on startup, add the file to the following directory:</source>
<translation>Damit GPXSee zu Programmstart automatisch eine POI-Datei lädt, fügen Sie diese zu folgendem Verzeichnis hinzu:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="764"/>
<location filename="../src/GUI/gui.cpp" line="712"/>
<source>Error loading data file:</source>
<translation>Fehler beim Laden der Datei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="767"/>
<location filename="../src/GUI/gui.cpp" line="792"/>
<location filename="../src/GUI/gui.cpp" line="715"/>
<location filename="../src/GUI/gui.cpp" line="740"/>
<source>Line: %1</source>
<translation>Linie: %1</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="789"/>
<location filename="../src/GUI/gui.cpp" line="737"/>
<source>Error loading POI file:</source>
<translation>Fehler beim Laden der POI-Datei:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="922"/>
<location filename="../src/GUI/gui.cpp" line="870"/>
<source>Name</source>
<translation>Name</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="926"/>
<location filename="../src/GUI/gui.cpp" line="874"/>
<source>Tracks</source>
<translation>Strecken</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="246"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="558"/>
<source>About GPXSee</source>
<translation>Über GPXSee</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="534"/>
<location filename="../src/GUI/gui.cpp" line="496"/>
<source>Navigation</source>
<translation>Navigation</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="674"/>
<source>POIs</source>
<translation>POIs</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="364"/>
<location filename="../src/GUI/gui.cpp" line="946"/>
<location filename="../src/GUI/gui.cpp" line="326"/>
<location filename="../src/GUI/gui.cpp" line="894"/>
<source>Distance</source>
<translation>Distanz</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="370"/>
<location filename="../src/GUI/gui.cpp" line="498"/>
<location filename="../src/GUI/gui.cpp" line="948"/>
<location filename="../src/GUI/gui.cpp" line="332"/>
<location filename="../src/GUI/gui.cpp" line="460"/>
<location filename="../src/GUI/gui.cpp" line="896"/>
<source>Time</source>
<translation>Zeit</translation>
</message>
@ -847,14 +837,29 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="141"/>
<source>Map files (*.map *.tba *.tar)</source>
<translation>Karten-Dateien (*.map *.tba *.tar)</translation>
<location filename="../src/map/maplist.cpp" line="128"/>
<source>Supported files</source>
<translation>Unterstütze Dateien</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="142"/>
<source>URL list files (*.txt)</source>
<translation>URL-Liste Dateien (*.txt)</translation>
<location filename="../src/map/maplist.cpp" line="129"/>
<source>OziExplorer maps</source>
<translation>OziExplorer Karten</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy Karten/Atlanten</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF Bilder</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<source>Online map sources</source>
<translation>Online-Kartenquellen</translation>
</message>
</context>
<context>

1501
lang/gpxsee_fi.ts Normal file

File diff suppressed because it is too large Load Diff

1501
lang/gpxsee_fr.ts Normal file

File diff suppressed because it is too large Load Diff

1502
lang/gpxsee_ru.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -46,50 +46,50 @@
</context>
<context>
<name>Data</name>
<message>
<location filename="../src/data/data.cpp" line="102"/>
<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/data/data.cpp" line="103"/>
<source>CSV files (*.csv)</source>
<translation>CSV-filer (*.csv)</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="103"/>
<source>FIT files (*.fit)</source>
<translation>FIT-filer (*.fit)</translation>
<source>Supported files</source>
<translation>Filer som stöds</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>GPX files (*.gpx)</source>
<translation>GPX-filer (*.gpx)</translation>
<source>CSV files</source>
<translation>CSV-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="104"/>
<source>IGC files (*.igc)</source>
<translation>IGC-filer (*.igc)</translation>
<source>FIT files</source>
<translation>FIT-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>KML files (*.kml)</source>
<translation>KML-filer (*.kml)</translation>
<source>GPX files</source>
<translation>GPX-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="105"/>
<source>NMEA files (*.nmea)</source>
<translation>NMEA-filer (*.nmea)</translation>
<source>IGC files</source>
<translation>IGC-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>TCX files (*.tcx)</source>
<translation>TCX-filer (*.tcx)</translation>
<source>KML files</source>
<translation>KML-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="106"/>
<source>All files (*)</source>
<translation>Alla filer (*)</translation>
<source>NMEA files</source>
<translation>NMEA-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>TCX files</source>
<translation>TCX-filer</translation>
</message>
<message>
<location filename="../src/data/data.cpp" line="107"/>
<source>All files</source>
<translation>Alla filer</translation>
</message>
</context>
<context>
@ -295,335 +295,340 @@
<context>
<name>GUI</name>
<message>
<location filename="../src/GUI/gui.cpp" line="600"/>
<location filename="../src/GUI/gui.cpp" line="562"/>
<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/gui.cpp" line="685"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<source>Map directory:</source>
<translation>Kartmapp:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="618"/>
<source>POI directory:</source>
<translation>POI-mapp:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="620"/>
<source>GCS file:</source>
<translation>GCS-fil:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<source>PCS file:</source>
<translation>PCS-fil:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<source>Ellipsoids file:</source>
<translation>Ellipsoids-fil:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="625"/>
<source>User override directory:</source>
<translation>Användarspecificerad mapp:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="634"/>
<source>Open file</source>
<translation>Öppna fil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="775"/>
<location filename="../src/GUI/gui.cpp" line="723"/>
<source>Open POI file</source>
<translation>Öppna POI-fil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="234"/>
<location filename="../src/GUI/gui.cpp" line="196"/>
<source>Quit</source>
<translation>Avsluta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="243"/>
<location filename="../src/GUI/gui.cpp" line="617"/>
<location filename="../src/GUI/gui.cpp" line="618"/>
<location filename="../src/GUI/gui.cpp" line="205"/>
<location filename="../src/GUI/gui.cpp" line="579"/>
<location filename="../src/GUI/gui.cpp" line="580"/>
<source>Keyboard controls</source>
<translation>Snabbtangenter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="268"/>
<location filename="../src/GUI/gui.cpp" line="230"/>
<source>Close</source>
<translation>Stäng</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="274"/>
<location filename="../src/GUI/gui.cpp" line="236"/>
<source>Reload</source>
<translation>Uppdatera</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="529"/>
<location filename="../src/GUI/gui.cpp" line="491"/>
<source>Show</source>
<translation>Visa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="445"/>
<location filename="../src/GUI/gui.cpp" line="523"/>
<location filename="../src/GUI/gui.cpp" line="407"/>
<location filename="../src/GUI/gui.cpp" line="485"/>
<source>File</source>
<translation>Arkiv</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="241"/>
<location filename="../src/GUI/gui.cpp" line="651"/>
<location filename="../src/GUI/gui.cpp" line="652"/>
<source>Data sources</source>
<translation>Datakällor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="247"/>
<source>Close POI files</source>
<translation>Stäng POI-filer</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="287"/>
<location filename="../src/GUI/gui.cpp" line="249"/>
<source>Overlap POIs</source>
<translation>Överlappa POI:er</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="291"/>
<location filename="../src/GUI/gui.cpp" line="253"/>
<source>Show POI labels</source>
<translation>Visa POI-namn</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="296"/>
<location filename="../src/GUI/gui.cpp" line="258"/>
<source>Show POIs</source>
<translation>Visa POI:er</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="305"/>
<location filename="../src/GUI/gui.cpp" line="267"/>
<source>Show map</source>
<translation>Visa karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="315"/>
<location filename="../src/GUI/gui.cpp" line="277"/>
<source>Clear tile cache</source>
<translation>Rensa kart-cache</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="252"/>
<location filename="../src/GUI/gui.cpp" line="214"/>
<source>Open...</source>
<translation>Öppna...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="282"/>
<location filename="../src/GUI/gui.cpp" line="203"/>
<location filename="../src/GUI/gui.cpp" line="613"/>
<location filename="../src/GUI/gui.cpp" line="614"/>
<source>Paths</source>
<translation type="unfinished">Sökvägar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="244"/>
<source>Load POI file...</source>
<translation>Läs in POI-fil...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="313"/>
<location filename="../src/GUI/gui.cpp" line="275"/>
<source>Load map...</source>
<translation>Läs in karta...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="319"/>
<location filename="../src/GUI/gui.cpp" line="323"/>
<location filename="../src/GUI/gui.cpp" line="634"/>
<location filename="../src/GUI/gui.cpp" line="281"/>
<location filename="../src/GUI/gui.cpp" line="285"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<source>Next map</source>
<translation>Nästa karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="333"/>
<location filename="../src/GUI/gui.cpp" line="295"/>
<source>Show tracks</source>
<translation>Visa spår</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="337"/>
<location filename="../src/GUI/gui.cpp" line="299"/>
<source>Show routes</source>
<translation>Visa rutter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="341"/>
<location filename="../src/GUI/gui.cpp" line="303"/>
<source>Show waypoints</source>
<translation>Visa vägpunkter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="345"/>
<location filename="../src/GUI/gui.cpp" line="307"/>
<source>Waypoint labels</source>
<translation>Vägpunktsnamn</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="356"/>
<location filename="../src/GUI/gui.cpp" line="318"/>
<source>Show graphs</source>
<translation>Visa diagram</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="376"/>
<location filename="../src/GUI/gui.cpp" line="338"/>
<source>Show grid</source>
<translation>Visa stödlinjer</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="380"/>
<location filename="../src/GUI/gui.cpp" line="342"/>
<source>Show slider info</source>
<translation>Visa reglageinfo</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="386"/>
<location filename="../src/GUI/gui.cpp" line="348"/>
<source>Show toolbars</source>
<translation>Visa verktygsfält</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="392"/>
<location filename="../src/GUI/gui.cpp" line="354"/>
<source>Total time</source>
<translation>Total tid</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="397"/>
<location filename="../src/GUI/gui.cpp" line="950"/>
<location filename="../src/GUI/gui.cpp" line="359"/>
<location filename="../src/GUI/gui.cpp" line="898"/>
<source>Moving time</source>
<translation>Förflyttningstid</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="404"/>
<location filename="../src/GUI/gui.cpp" line="366"/>
<source>Metric</source>
<translation>Meter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="409"/>
<location filename="../src/GUI/gui.cpp" line="371"/>
<source>Imperial</source>
<translation>Imperial</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="415"/>
<location filename="../src/GUI/gui.cpp" line="377"/>
<source>Fullscreen mode</source>
<translation>Helskärmsläge</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="421"/>
<location filename="../src/GUI/gui.cpp" line="383"/>
<source>Options...</source>
<translation>Alternativ...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="427"/>
<location filename="../src/GUI/gui.cpp" line="389"/>
<source>Next</source>
<translation>Nästa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="430"/>
<location filename="../src/GUI/gui.cpp" line="392"/>
<source>Previous</source>
<translation>Föregående</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="434"/>
<location filename="../src/GUI/gui.cpp" line="396"/>
<source>Last</source>
<translation>Sista</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="437"/>
<location filename="../src/GUI/gui.cpp" line="399"/>
<source>First</source>
<translation>Första</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="459"/>
<location filename="../src/GUI/gui.cpp" line="421"/>
<source>Map</source>
<translation>Karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="467"/>
<location filename="../src/GUI/gui.cpp" line="429"/>
<source>Graph</source>
<translation>Diagram</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="476"/>
<location filename="../src/GUI/gui.cpp" line="438"/>
<source>POI</source>
<translation>POI</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="477"/>
<location filename="../src/GUI/gui.cpp" line="439"/>
<source>POI files</source>
<translation>POI-filer</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="488"/>
<location filename="../src/GUI/gui.cpp" line="450"/>
<source>Data</source>
<translation>Data</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="489"/>
<location filename="../src/GUI/gui.cpp" line="451"/>
<source>Display</source>
<translation>Visa</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="497"/>
<location filename="../src/GUI/gui.cpp" line="459"/>
<source>Settings</source>
<translation>Inställningar</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="501"/>
<location filename="../src/GUI/gui.cpp" line="463"/>
<source>Units</source>
<translation>Enhet</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="510"/>
<location filename="../src/GUI/gui.cpp" line="472"/>
<source>Help</source>
<translation>Hjälp</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="627"/>
<location filename="../src/GUI/gui.cpp" line="589"/>
<source>Append file</source>
<translation>Lägg till fil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="628"/>
<location filename="../src/GUI/gui.cpp" line="590"/>
<source>Next/Previous</source>
<translation>Nästa/Föregående</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="630"/>
<location filename="../src/GUI/gui.cpp" line="592"/>
<source>Toggle graph type</source>
<translation>Växla diagramtyp</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="632"/>
<location filename="../src/GUI/gui.cpp" line="594"/>
<source>Toggle time type</source>
<translation>Växla tidstyp</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="636"/>
<location filename="../src/GUI/gui.cpp" line="598"/>
<source>Previous map</source>
<translation>Föregående karta</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="637"/>
<location filename="../src/GUI/gui.cpp" line="599"/>
<source>Zoom in</source>
<translation>Zooma in</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="639"/>
<location filename="../src/GUI/gui.cpp" line="601"/>
<source>Zoom out</source>
<translation>Zooma ut</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="641"/>
<location filename="../src/GUI/gui.cpp" line="603"/>
<source>Digital zoom</source>
<translation>Digital zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="642"/>
<location filename="../src/GUI/gui.cpp" line="604"/>
<source>Zoom</source>
<translation>Zoom</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="654"/>
<source>Online maps</source>
<translation>Online-kartor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="655"/>
<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/gui.cpp" line="658"/>
<source>The file format is one map entry per line, consisting of the map name, tiles URL and an optional maximal zoom level 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 kartans namn, webbadress och maximal zoomnivå om tillämpligt, Kartrutans X- och Y-koordinater ersätts med $x och $y, i webbadressen och zoomnivån ersätts med $z. Ett exempel en kartfil kan se ut här:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="666"/>
<source>Offline maps</source>
<translation>Offline-kartor</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="667"/>
<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/gui.cpp" line="1151"/>
<location filename="../src/GUI/gui.cpp" line="1099"/>
<source>Open map file</source>
<translation>Öppna kartfil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1172"/>
<location filename="../src/GUI/gui.cpp" line="1126"/>
<source>Error loading map:</source>
<translation>Fel vid inläsning av karta:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="1181"/>
<location filename="../src/GUI/gui.cpp" line="1137"/>
<source>No files loaded</source>
<translation>Inga filer inlästa</translation>
</message>
<message numerus="yes">
<location filename="../src/GUI/gui.cpp" line="1185"/>
<location filename="../src/GUI/gui.cpp" line="1141"/>
<source>%n files</source>
<translation>
<numerusform>%n filer</numerusform>
@ -631,123 +636,108 @@
</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="936"/>
<location filename="../src/GUI/gui.cpp" line="939"/>
<location filename="../src/GUI/gui.cpp" line="884"/>
<location filename="../src/GUI/gui.cpp" line="887"/>
<source>Date</source>
<translation>Datum</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="928"/>
<location filename="../src/GUI/gui.cpp" line="876"/>
<source>Routes</source>
<translation>Rutter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="621"/>
<location filename="../src/GUI/gui.cpp" line="583"/>
<source>Next file</source>
<translation>Nästa fil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="597"/>
<location filename="../src/GUI/gui.cpp" line="559"/>
<source>Version </source>
<translation>Version </translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="257"/>
<location filename="../src/GUI/gui.cpp" line="219"/>
<source>Print...</source>
<translation>Skriv ut...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="262"/>
<location filename="../src/GUI/gui.cpp" line="224"/>
<source>Export to PDF...</source>
<translation>Exportera till PDF...</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="930"/>
<location filename="../src/GUI/gui.cpp" line="878"/>
<source>Waypoints</source>
<translation>Vägpunkter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="622"/>
<location filename="../src/GUI/gui.cpp" line="584"/>
<source>Previous file</source>
<translation>Föregående fil</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="349"/>
<location filename="../src/GUI/gui.cpp" line="311"/>
<source>Route waypoints</source>
<translation>Ruttvägpunkter</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="624"/>
<location filename="../src/GUI/gui.cpp" line="586"/>
<source>First file</source>
<translation>Första filen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="626"/>
<location filename="../src/GUI/gui.cpp" line="588"/>
<source>Last file</source>
<translation>Sista filen</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="670"/>
<source>The expected structure is one map/atlas in a separate subdirectory. Supported map formats are OziExplorer maps and 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 kartor och TrekBuddy-kartor/-kartsamlingar (tarerade och icke tarerade).</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="675"/>
<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/gui.cpp" line="764"/>
<location filename="../src/GUI/gui.cpp" line="712"/>
<source>Error loading data file:</source>
<translation>Fel vid inläsning av datafil:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="767"/>
<location filename="../src/GUI/gui.cpp" line="792"/>
<location filename="../src/GUI/gui.cpp" line="715"/>
<location filename="../src/GUI/gui.cpp" line="740"/>
<source>Line: %1</source>
<translation>Rad: %1</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="789"/>
<location filename="../src/GUI/gui.cpp" line="737"/>
<source>Error loading POI file:</source>
<translation>Fel vid inläsning av POI-fil:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="922"/>
<location filename="../src/GUI/gui.cpp" line="870"/>
<source>Name</source>
<translation>Namn</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="926"/>
<location filename="../src/GUI/gui.cpp" line="874"/>
<source>Tracks</source>
<translation>Spår</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="246"/>
<location filename="../src/GUI/gui.cpp" line="596"/>
<location filename="../src/GUI/gui.cpp" line="208"/>
<location filename="../src/GUI/gui.cpp" line="558"/>
<source>About GPXSee</source>
<translation>Om GPXSee</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="534"/>
<location filename="../src/GUI/gui.cpp" line="496"/>
<source>Navigation</source>
<translation>Navigation</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="674"/>
<source>POIs</source>
<translation>POI:er</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="364"/>
<location filename="../src/GUI/gui.cpp" line="946"/>
<location filename="../src/GUI/gui.cpp" line="326"/>
<location filename="../src/GUI/gui.cpp" line="894"/>
<source>Distance</source>
<translation>Avstånd</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="370"/>
<location filename="../src/GUI/gui.cpp" line="498"/>
<location filename="../src/GUI/gui.cpp" line="948"/>
<location filename="../src/GUI/gui.cpp" line="332"/>
<location filename="../src/GUI/gui.cpp" line="460"/>
<location filename="../src/GUI/gui.cpp" line="896"/>
<source>Time</source>
<translation>Tid</translation>
</message>
@ -847,14 +837,29 @@
<context>
<name>MapList</name>
<message>
<location filename="../src/map/maplist.cpp" line="141"/>
<source>Map files (*.map *.tba *.tar)</source>
<translation>Kartfiler (*.map *.tba *.tar)</translation>
<location filename="../src/map/maplist.cpp" line="128"/>
<source>Supported files</source>
<translation>Filer som stöds</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="142"/>
<source>URL list files (*.txt)</source>
<translation>URL-listfiler (*.txt)</translation>
<location filename="../src/map/maplist.cpp" line="129"/>
<source>OziExplorer maps</source>
<translation>OziExplorer-kartor</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="130"/>
<source>TrekBuddy maps/atlases</source>
<translation>TrekBuddy-kartor/-atlaser</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="131"/>
<source>GeoTIFF images</source>
<translation>GeoTIFF-bilder</translation>
</message>
<message>
<location filename="../src/map/maplist.cpp" line="132"/>
<source>Online map sources</source>
<translation>Online-kartkällor</translation>
</message>
</context>
<context>

View File

@ -29,7 +29,7 @@
<string>application/gpx+xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>gpx.icns</string>
<string>icons/gpx.icns</string>
<key>CFBundleTypeName</key>
<string>GPS Exchange Format</string>
<key>CFBundleTypeRole</key>
@ -45,7 +45,7 @@
<string>application/tcx+xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>tcx.icns</string>
<string>icons/tcx.icns</string>
<key>CFBundleTypeName</key>
<string>Training Center XML</string>
<key>CFBundleTypeRole</key>
@ -61,7 +61,7 @@
<string>application/vnd.google-earth.kml+xml</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>kml.icns</string>
<string>icons/kml.icns</string>
<key>CFBundleTypeName</key>
<string>Keyhole Markup Language</string>
<key>CFBundleTypeRole</key>
@ -77,7 +77,7 @@
<string>application/vnd.ant.fit</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>fit.icns</string>
<string>icons/fit.icns</string>
<key>CFBundleTypeName</key>
<string>Flexible and Interoperable Data Transfer</string>
<key>CFBundleTypeRole</key>
@ -93,7 +93,7 @@
<string>application/vnd.fai.igc</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>igc.icns</string>
<string>icons/igc.icns</string>
<key>CFBundleTypeName</key>
<string>Flight Recorder Data Format</string>
<key>CFBundleTypeRole</key>
@ -109,7 +109,7 @@
<string>application/vnd.nmea.nmea</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>nmea.icns</string>
<string>icons/nmea.icns</string>
<key>CFBundleTypeName</key>
<string>NMEA 0183 data</string>
<key>CFBundleTypeRole</key>

19
pkg/csv/ellipsoids.csv Normal file
View File

@ -0,0 +1,19 @@
Airy 1830,7001,6377563.396,299.3249646
Modified Airy,7002,6377340.189,299.3249646
Australian National,7003,6378160.0,298.25
Bessel 1841,7004,6377397.155,299.1528128
Bessel 1841 (Norway),7005,6377492.0176,299.1528
Clarke 1866,7008,6378206.4,294.9786982
Clarke 1880 (Palestine),7010,6378300.789,293.466
Clarke 1880 (IGN),7011,6378249.2,293.466021
Clarke 1880,7012,6378249.145,293.465
Everest 1830 (1937 Adjustment),7015,6377276.345,300.8017
Everest 1830 Modified,7018,6377304.063,300.8017
GRS 80,7019,6378137.0,298.257222101
Helmert 1906,7020,6378200.0,298.3
International 1924,7022,6378388.0,297.0
Krassovsky 1940,7024,6378245.0,298.3
South American 1969,7036,6378160.0,298.25
WGS 72,7043,6378135.0,298.26
Bessel 1841 (Namibia),7046,6377483.865,299.1528128
Hough 1960,7053,6378270.0,297.0
1 Airy 1830 7001 6377563.396 299.3249646
2 Modified Airy 7002 6377340.189 299.3249646
3 Australian National 7003 6378160.0 298.25
4 Bessel 1841 7004 6377397.155 299.1528128
5 Bessel 1841 (Norway) 7005 6377492.0176 299.1528
6 Clarke 1866 7008 6378206.4 294.9786982
7 Clarke 1880 (Palestine) 7010 6378300.789 293.466
8 Clarke 1880 (IGN) 7011 6378249.2 293.466021
9 Clarke 1880 7012 6378249.145 293.465
10 Everest 1830 (1937 Adjustment) 7015 6377276.345 300.8017
11 Everest 1830 Modified 7018 6377304.063 300.8017
12 GRS 80 7019 6378137.0 298.257222101
13 Helmert 1906 7020 6378200.0 298.3
14 International 1924 7022 6378388.0 297.0
15 Krassovsky 1940 7024 6378245.0 298.3
16 South American 1969 7036 6378160.0 298.25
17 WGS 72 7043 6378135.0 298.26
18 Bessel 1841 (Namibia) 7046 6377483.865 299.1528128
19 Hough 1960 7053 6378270.0 297.0

121
pkg/csv/gcs.csv Normal file
View File

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

1626
pkg/csv/pcs.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,123 +0,0 @@
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

View File

@ -1,30 +0,0 @@
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

12
pkg/gpxsee.desktop Normal file
View File

@ -0,0 +1,12 @@
[Desktop Entry]
Name=GPXSee
Comment=GPS log file viewer and analyzer
Comment[cz]=Prohlížeč a analyzátor GPS logů
Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
Comment[ru]=Программа для просмотра и анализа GPS логов
Exec=gpxsee %F
Icon=gpxsee
Terminal=false
Type=Application
Categories=Graphics;Viewer;Maps;Qt;
MimeType=application/gpx+xml;application/tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "4.19"
!define VERSION "5.0"
; The file to write
OutFile "GPXSee-${VERSION}.exe"
@ -83,9 +83,8 @@ Section "GPXSee" SEC_APP
; Put the files there
File "gpxsee.exe"
File "maps.txt"
File "ellipsoids.csv"
File "datums.csv"
File /r "maps"
File /r "csv"
; Create start menu entry and add links
SetShellVarContext all
@ -195,6 +194,38 @@ Section "ANGLE" SEC_ANGLE
SectionEnd
SectionGroup "Localization" SEC_LOCALIZATION
Section "Czech"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_cs.qm translations\gpxsee_cs.qm
File /oname=translations\qt_cs.qm translations\qt_cs.qm
SectionEnd
Section "Finnish"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_fi.qm translations\gpxsee_fi.qm
File /oname=translations\qt_fi.qm translations\qt_fi.qm
SectionEnd
Section "French"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_fr.qm translations\gpxsee_fr.qm
File /oname=translations\qt_fr.qm translations\qt_fr.qm
SectionEnd
Section "German"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_de.qm translations\gpxsee_de.qm
File /oname=translations\qt_de.qm translations\qt_de.qm
SectionEnd
Section "Russian"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_ru.qm translations\gpxsee_ru.qm
File /oname=translations\qt_ru.qm translations\qt_ru.qm
SectionEnd
Section "Swedish"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_sv.qm translations\gpxsee_sv.qm
SectionEnd
SectionGroupEnd
;--------------------------------
; Uninstaller
@ -246,6 +277,8 @@ LangString DESC_ANGLE ${LANG_ENGLISH} \
"ANGLE (OpenGL via Direct3D). Enables OpenGL on systems without native OpenGL drivers."
LangString DESC_APP ${LANG_ENGLISH} \
"GPXSee application"
LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
"Localization"
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
@ -254,4 +287,5 @@ 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_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

46
pkg/gpxsee.xml Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/gpx+xml">
<comment>GPS Exchange Format</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="application-xml"/>
<glob pattern="*.gpx"/>
</mime-type>
<mime-type type="application/tcx+xml">
<comment>Training Center XML</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="application-xml"/>
<glob pattern="*.tcx"/>
</mime-type>
<mime-type type="application/kml+xml">
<comment>Keyhole Markup Language</comment>
<sub-class-of type="application/xml"/>
<generic-icon name="application-xml"/>
<glob pattern="*.kml"/>
</mime-type>
<mime-type type="application/vnd.ant.fit">
<comment>Flexible and Interoperable Data Transfer</comment>
<sub-class-of type="application/octet-stream"/>
<generic-icon name="application-octet-stream"/>
<glob pattern="*.fit"/>
</mime-type>
<mime-type type="application/vnd.fai.igc">
<comment>Flight Recorder Data Format</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-plain"/>
<glob pattern="*.igc"/>
</mime-type>
<mime-type type="application/vnd.nmea.nmea">
<comment>NMEA 0183 data</comment>
<sub-class-of type="text/plain"/>
<generic-icon name="text-plain"/>
<glob pattern="*.nmea"/>
</mime-type>
</mime-info>

View File

@ -5,7 +5,7 @@
; The name of the installer
Name "GPXSee"
; Program version
!define VERSION "4.19"
!define VERSION "5.0"
; The file to write
OutFile "GPXSee-${VERSION}_x64.exe"
@ -90,9 +90,8 @@ Section "GPXSee" SEC_APP
; Put the files there
File "gpxsee.exe"
File "maps.txt"
File "ellipsoids.csv"
File "datums.csv"
File /r "maps"
File /r "csv"
; Create start menu entry and add links
SetShellVarContext all
@ -197,6 +196,38 @@ Section "ANGLE" SEC_ANGLE
SectionEnd
SectionGroup "Localization" SEC_LOCALIZATION
Section "Czech"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_cs.qm translations\gpxsee_cs.qm
File /oname=translations\qt_cs.qm translations\qt_cs.qm
SectionEnd
Section "Finnish"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_fi.qm translations\gpxsee_fi.qm
File /oname=translations\qt_fi.qm translations\qt_fi.qm
SectionEnd
Section "French"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_fr.qm translations\gpxsee_fr.qm
File /oname=translations\qt_fr.qm translations\qt_fr.qm
SectionEnd
Section "German"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_de.qm translations\gpxsee_de.qm
File /oname=translations\qt_de.qm translations\qt_de.qm
SectionEnd
Section "Russian"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_ru.qm translations\gpxsee_ru.qm
File /oname=translations\qt_ru.qm translations\qt_ru.qm
SectionEnd
Section "Swedish"
CreateDirectory "$INSTDIR\translations"
File /oname=translations\gpxsee_sv.qm translations\gpxsee_sv.qm
SectionEnd
SectionGroupEnd
;--------------------------------
; Uninstaller
@ -249,6 +280,8 @@ LangString DESC_ANGLE ${LANG_ENGLISH} \
"ANGLE (OpenGL via Direct3D). Enables OpenGL on systems without native OpenGL drivers."
LangString DESC_APP ${LANG_ENGLISH} \
"GPXSee application"
LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
"Localization"
;Assign language strings to sections
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
@ -257,4 +290,5 @@ 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_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
!insertmacro MUI_FUNCTION_DESCRIPTION_END

View File

@ -1,5 +0,0 @@
Open Topo Map https://a.tile.opentopomap.org/$z/$x/$y.png 17
4UMaps http://4umaps.eu/$z/$x/$y.png 15
Open Street Map http://tile.openstreetmap.org/$z/$x/$y.png 19
USGS Topo https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png 15
USGS Imagery https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y 15

7
pkg/maps/4UMaps.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<name>4UMaps</name>
<url>http://4umaps.eu/$z/$x/$y.png</url>
<zoom min="2" max="15"/>
<bounds bottom="-65"/>
</map>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<name>Open Street Map</name>
<url>http://tile.openstreetmap.org/$z/$x/$y.png</url>
</map>

6
pkg/maps/OpenTopoMap.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<name>Open Topo Map</name>
<url>https://a.tile.opentopomap.org/$z/$x/$y.png</url>
<zoom max="17"/>
</map>

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<name>USGS Imagery</name>
<url>https://navigator.er.usgs.gov/tiles/aerial_Imagery.cgi/$z/$x/$y</url>
<zoom min="2" max="15"/>
<bounds bottom="0" top="74"/>
</map>

6
pkg/maps/USGS-topo.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<map>
<name>USGS Topo</name>
<url>https://navigator.er.usgs.gov/tiles/tcr.cgi/$z/$x/$y.png</url>
<zoom min="2" max="15"/>
</map>

View File

@ -7,7 +7,8 @@
#include "map/onlinemap.h"
#include "map/downloader.h"
#include "map/ellipsoid.h"
#include "map/datum.h"
#include "map/gcs.h"
#include "map/pcs.h"
#include "opengl.h"
#include "gui.h"
#include "config.h"
@ -18,13 +19,16 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
_argc(argc), _argv(argv)
{
QTranslator *gpxsee = new QTranslator(this);
QString locale = QLocale::system().name();
gpxsee->load(QString(":/lang/gpxsee_") + locale);
gpxsee->load(QLocale::system(), "gpxsee", "_", TRANSLATIONS_DIR);
installTranslator(gpxsee);
QTranslator *qt = new QTranslator(this);
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MAC)
qt->load(QLocale::system(), "qt", "_", TRANSLATIONS_DIR);
#else // Q_OS_WINDOWS || Q_OS_MAC
qt->load(QLocale::system(), "qt", "_", QLibraryInfo::location(
QLibraryInfo::TranslationsPath));
#endif // Q_OS_WINDOWS || Q_OS_MAC
installTranslator(qt);
#ifdef Q_OS_MAC
@ -35,6 +39,7 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
OnlineMap::setDownloader(new Downloader(this));
OPENGL_SET_SAMPLES(4);
loadDatums();
loadPCSs();
_gui = new GUI();
}
@ -67,7 +72,6 @@ bool App::event(QEvent *event)
void App::loadDatums()
{
QString ef, df;
bool ok = false;
if (QFile::exists(USER_ELLIPSOID_FILE))
ef = USER_ELLIPSOID_FILE;
@ -76,34 +80,32 @@ void App::loadDatums()
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;
if (QFile::exists(USER_GCS_FILE))
df = USER_GCS_FILE;
else if (QFile::exists(GLOBAL_GCS_FILE))
df = GLOBAL_GCS_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(df),
Datum::errorLine(), qPrintable(Datum::errorString()));
else
qWarning("%s: %s", qPrintable(df), qPrintable(
Datum::errorString()));
} else
ok = true;
}
}
if (!ok)
Ellipsoid::loadList(ef);
GCS::loadList(df);
} else
qWarning("Maps based on a datum different from WGS84 won't work.");
}
void App::loadPCSs()
{
QString file;
if (QFile::exists(USER_PCS_FILE))
file = USER_PCS_FILE;
else if (QFile::exists(GLOBAL_PCS_FILE))
file = GLOBAL_PCS_FILE;
else {
qWarning("No PCS file found.");
return;
}
PCS::loadList(file);
}

View File

@ -19,6 +19,7 @@ protected:
private:
void loadDatums();
void loadPCSs();
int &_argc;
char **_argv;

View File

@ -101,69 +101,31 @@ GUI::~GUI()
void GUI::loadMaps()
{
_ml = new MapList(this);
QString offline, online;
if (QFile::exists(USER_MAP_FILE))
online = USER_MAP_FILE;
else if (QFile::exists(GLOBAL_MAP_FILE))
online = GLOBAL_MAP_FILE;
if (!online.isNull() && !_ml->loadFile(online))
qWarning("%s: %s", qPrintable(online), qPrintable(_ml->errorString()));
QString dir;
if (QFile::exists(USER_MAP_DIR))
offline = USER_MAP_DIR;
dir = USER_MAP_DIR;
else if (QFile::exists(GLOBAL_MAP_DIR))
offline = GLOBAL_MAP_DIR;
dir = GLOBAL_MAP_DIR;
if (!offline.isNull()) {
QDir md(offline);
QFileInfoList ml = md.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (int i = 0; i < ml.size(); i++) {
QDir dir(ml.at(i).absoluteFilePath());
QFileInfoList fl = dir.entryInfoList(MapList::filter(), 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->loadFile(fl.first().absoluteFilePath()))
qWarning("%s: %s", qPrintable(fl.first().absoluteFilePath()),
qPrintable(_ml->errorString()));
}
}
if (!dir.isNull() && !_ml->loadDir(dir))
qWarning("%s", qPrintable(_ml->errorString()));
_map = new EmptyMap(this);
}
void GUI::loadPOIs()
{
QFileInfoList list;
QDir userDir(USER_POI_DIR);
QDir globalDir(GLOBAL_POI_DIR);
_poi = new POI(this);
QString dir;
if (userDir.exists())
list = userDir.entryInfoList(QStringList(), QDir::Files);
else
list = globalDir.entryInfoList(QStringList(), QDir::Files);
if (QFile::exists(USER_POI_DIR))
dir = USER_POI_DIR;
else if (QFile::exists(GLOBAL_POI_DIR))
dir = GLOBAL_POI_DIR;
for (int i = 0; i < list.size(); ++i) {
if (!_poi->loadFile(list.at(i).absoluteFilePath())) {
qWarning("Error loading POI file: %s: %s\n",
qPrintable(list.at(i).fileName()),
qPrintable(_poi->errorString()));
if (_poi->errorLine())
qWarning("Line: %d\n", _poi->errorLine());
}
}
if (!dir.isNull() && !_poi->loadDir(dir))
qWarning("%s", qPrintable(_poi->errorString()));
}
void GUI::createBrowser()
@ -238,8 +200,8 @@ void GUI::createActions()
addAction(_exitAction);
// Help & About
_dataSourcesAction = new QAction(tr("Data sources"), this);
connect(_dataSourcesAction, SIGNAL(triggered()), this, SLOT(dataSources()));
_pathsAction = new QAction(tr("Paths"), this);
connect(_pathsAction, SIGNAL(triggered()), this, SLOT(paths()));
_keysAction = new QAction(tr("Keyboard controls"), this);
connect(_keysAction, SIGNAL(triggered()), this, SLOT(keys()));
_aboutAction = new QAction(QIcon(QPixmap(APP_ICON)),
@ -508,7 +470,7 @@ void GUI::createMenus()
settingsMenu->addAction(_openOptionsAction);
QMenu *helpMenu = menuBar()->addMenu(tr("Help"));
helpMenu->addAction(_dataSourcesAction);
helpMenu->addAction(_pathsAction);
helpMenu->addAction(_keysAction);
helpMenu->addSeparator();
helpMenu->addAction(_aboutAction);
@ -644,37 +606,26 @@ void GUI::keys()
msgBox.exec();
}
void GUI::dataSources()
void GUI::paths()
{
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Data sources"));
msgBox.setText("<h3>" + tr("Data sources") + "</h3>");
msgBox.setWindowTitle(tr("Paths"));
msgBox.setText("<h3>" + tr("Paths") + "</h3>");
msgBox.setInformativeText(
"<h4>" + tr("Online maps") + "</h4><p>"
+ tr("Online map URLs are read on program startup from the "
"following file:")
+ "</p><p><code>" + USER_MAP_FILE + "</code></p><p>"
+ tr("The file format is one map entry per line, consisting of the map "
"name, tiles URL and an optional maximal zoom level 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:")
+ "</p><p><code>Map1 http://tile.server.com/map/$z/$x/$y.png 15"
"<br/>Map2 http://mapserver.org/map/$z-$x-$y</code></p>"
+ "<h4>" + tr("Offline maps") + "</h4><p>"
+ tr("Offline maps are loaded on program startup from the following "
"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 OziExplorer maps and 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 "
"the file to the following directory:")
+ "</p><p><code>" + USER_POI_DIR + "</code></p>"
"<style>td {white-space: pre; padding-right: 1em;}</style>"
"<div><table><tr><td>" + tr("Map directory:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_MAP_DIR) + "</code></td></tr><tr><td>"
+ tr("POI directory:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_POI_DIR) + "</code></td></tr><tr><td>"
+ tr("GCS file:") + "</td><td><code>" + QDir::cleanPath(GLOBAL_GCS_FILE)
+ "</code></td></tr><tr><td>" + tr("PCS file:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_PCS_FILE) + "</code></td></tr><tr><td>"
+ tr("Ellipsoids file:") + "</td><td><code>"
+ QDir::cleanPath(GLOBAL_ELLIPSOID_FILE) + "</code></td></tr>"
+ "<tr><td></td><td></td></tr></table></div><div><table><tr><td>"
+ tr("User override directory:") + "</td><td><code>"
+ QDir::cleanPath(USER_DIR) + "</td></tr></table></div>"
);
msgBox.exec();
@ -692,8 +643,6 @@ void GUI::openFile()
bool GUI::openFile(const QString &fileName)
{
bool ret = true;
if (fileName.isEmpty() || _files.contains(fileName))
return false;
@ -708,13 +657,14 @@ bool GUI::openFile(const QString &fileName)
updateWindowTitle();
updateGraphTabs();
updateMapView();
return true;
} else {
if (_files.isEmpty())
_fileActionGroup->setEnabled(false);
ret = false;
}
return ret;
return false;
}
}
bool GUI::loadFile(const QString &fileName)
@ -1148,30 +1098,38 @@ void GUI::showGraphSliderInfo(bool show)
void GUI::loadMap()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open map file"),
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open map file"),
QString(), MapList::formats());
QStringList list = files;
for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
loadMap(*it);
}
bool GUI::loadMap(const QString &fileName)
{
if (fileName.isEmpty())
return;
return false;
int count = _ml->maps().count();
if (_ml->loadFile(fileName)) {
for (int i = count; i < _ml->maps().count(); i++) {
QAction *a = new QAction(_ml->maps().at(i)->name(), this);
a->setCheckable(true);
a->setActionGroup(_mapsActionGroup);
_mapsSignalMapper->setMapping(a, i);
connect(a, SIGNAL(triggered()), _mapsSignalMapper, SLOT(map()));
_mapActions.append(a);
_mapMenu->insertAction(_mapsEnd, a);
}
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);
_mapActions.last()->activate(QAction::Trigger);
return true;
} else {
QString error = tr("Error loading map:") + "\n\n"
+ fileName + "\n\n" + _ml->errorString();
QMessageBox::critical(this, APP_NAME, error);
return false;
}
}

View File

@ -40,7 +40,7 @@ public:
private slots:
void about();
void keys();
void dataSources();
void paths();
void printFile();
void exportFile();
void openFile();
@ -99,6 +99,7 @@ private:
bool openPOIFile(const QString &fileName);
bool loadFile(const QString &fileName);
bool loadMap(const QString &fileName);
void exportFile(const QString &fileName);
void updateStatusBarInfo();
void updateWindowTitle();
@ -135,7 +136,7 @@ private:
QActionGroup *_mapsActionGroup;
QAction *_exitAction;
QAction *_keysAction;
QAction *_dataSourcesAction;
QAction *_pathsAction;
QAction *_aboutAction;
QAction *_aboutQtAction;
QAction *_printFileAction;

View File

@ -1,9 +0,0 @@
#include "margins.h"
QDebug operator<<(QDebug dbg, const MarginsF &margins)
{
dbg.nospace() << "MarginsF(" << margins.left() << ", " << margins.top()
<< ", " << margins.right() << margins.bottom() << ")";
return dbg.maybeSpace();
}

View File

@ -25,6 +25,11 @@ private:
qreal _left, _top, _right, _bottom;
};
QDebug operator<<(QDebug dbg, const MarginsF &margins);
inline QDebug operator<<(QDebug dbg, const MarginsF &margins)
{
dbg.nospace() << "MarginsF(" << margins.left() << ", " << margins.top()
<< ", " << margins.right() << margins.bottom() << ")";
return dbg.space();
}
#endif // MARGINS_H

View File

@ -12,9 +12,9 @@
#define FONT_FAMILY "Arial"
#define FONT_SIZE 12 // px
#define ELLIPSOID_FILE QString("ellipsoids.csv")
#define DATUM_FILE QString("datums.csv")
#define MAP_FILE QString("maps.txt")
#define ELLIPSOID_FILE QString("csv/ellipsoids.csv")
#define GCS_FILE QString("csv/gcs.csv")
#define PCS_FILE QString("csv/pcs.csv")
#define MAP_DIR QString("maps")
#define POI_DIR QString("POI")
@ -31,15 +31,16 @@
#endif
#define USER_ELLIPSOID_FILE USER_DIR + QString("/") + ELLIPSOID_FILE
#define USER_DATUM_FILE USER_DIR + QString("/") + DATUM_FILE
#define USER_GCS_FILE USER_DIR + QString("/") + GCS_FILE
#define USER_PCS_FILE USER_DIR + QString("/") + PCS_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_GCS_FILE GLOBAL_DIR + QString("/") + GCS_FILE
#define GLOBAL_PCS_FILE GLOBAL_DIR + QString("/") + PCS_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")
#define TRANSLATIONS_DIR GLOBAL_DIR + QString("/translations")
#endif /* CONFIG_H */

View File

@ -7,7 +7,6 @@ class CSVParser : public Parser
{
public:
CSVParser() : _errorLine(0) {}
~CSVParser() {}
bool parse(QFile *file, QList<TrackData> &track, QList<RouteData> &routes,
QList<Waypoint> &waypoints);

View File

@ -99,11 +99,12 @@ bool Data::loadFile(const QString &fileName)
QString Data::formats()
{
return tr("Supported files (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx)")
+ ";;" + tr("CSV files (*.csv)") + ";;" + tr("FIT files (*.fit)") + ";;"
+ tr("GPX files (*.gpx)") + ";;" + tr("IGC files (*.igc)") + ";;"
+ tr("KML files (*.kml)") + ";;" + tr("NMEA files (*.nmea)") + ";;"
+ tr("TCX files (*.tcx)") + ";;" + tr("All files (*)");
return
tr("Supported files") + " (*.csv *.fit *.gpx *.igc *.kml *.nmea *.tcx);;"
+ tr("CSV files") + " (*.csv);;" + tr("FIT files") + " (*.fit);;"
+ tr("GPX files") + " (*.gpx);;" + tr("IGC files") + " (*.igc);;"
+ tr("KML files") + " (*.kml);;" + tr("NMEA files") + " (*.nmea);;"
+ tr("TCX files") + " (*.tcx);;" + tr("All files") + "(*)";
}
QStringList Data::filter()

View File

@ -7,7 +7,6 @@ class FITParser : public Parser
{
public:
FITParser();
~FITParser() {}
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
QList<Waypoint> &waypoints);

View File

@ -8,8 +8,6 @@
class GPXParser : public Parser
{
public:
~GPXParser() {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}

View File

@ -1,5 +1,5 @@
#include <cstring>
#include "str2int.h"
#include "common/str2int.h"
#include "igcparser.h"

View File

@ -10,7 +10,6 @@ class IGCParser : public Parser
{
public:
IGCParser() : _errorLine(0) {}
~IGCParser() {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Waypoint> &waypoints);

View File

@ -8,8 +8,6 @@
class KMLParser : public Parser
{
public:
~KMLParser() {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}

View File

@ -1,5 +1,5 @@
#include <cstring>
#include "str2int.h"
#include "common/str2int.h"
#include "nmeaparser.h"

View File

@ -9,7 +9,6 @@ class NMEAParser : public Parser
{
public:
NMEAParser() : _errorLine(0), _GGA(false) {}
~NMEAParser() {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Waypoint> &waypoints);

View File

@ -1,4 +1,5 @@
#include <QFile>
#include <QDir>
#include "data.h"
#include "poi.h"
@ -9,20 +10,25 @@ POI::POI(QObject *parent) : QObject(parent)
_radius = 1000;
}
bool POI::loadFile(const QString &fileName)
bool POI::loadFile(const QString &path, bool dir)
{
Data data;
FileIndex index;
_errorString.clear();
_errorLine = 0;
index.enabled = true;
index.start = _data.size();
if (!data.loadFile(fileName)) {
_errorString = data.errorString();
_errorLine = data.errorLine();
if (!data.loadFile(path)) {
if (dir) {
if (data.errorLine())
_errorString += QString("%1:%2: %3\n").arg(path)
.arg(data.errorLine()).arg(data.errorString());
else
_errorString += path + ": " + data.errorString() + "\n";
} else {
_errorString = data.errorString();
_errorLine = data.errorLine();
}
return false;
}
@ -38,7 +44,7 @@ bool POI::loadFile(const QString &fileName)
_tree.Insert(c, c, i);
}
_files.append(fileName);
_files.append(path);
_indexes.append(index);
emit pointsChanged();
@ -46,6 +52,39 @@ bool POI::loadFile(const QString &fileName)
return true;
}
bool POI::loadFile(const QString &path)
{
_errorString.clear();
_errorLine = 0;
return loadFile(path, false);
}
bool POI::loadDir(const QString &path)
{
QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfoList fl = md.entryInfoList();
bool ret = true;
_errorString.clear();
_errorLine = 0;
for (int i = 0; i < fl.size(); i++) {
const QFileInfo &fi = fl.at(i);
if (fi.isDir()) {
if (!loadDir(fi.absoluteFilePath()))
ret = false;
} else {
if (!loadFile(fi.absoluteFilePath(), true))
ret = false;
}
}
return ret;
}
static bool cb(size_t data, void* context)
{
QSet<int> *set = (QSet<int>*) context;

View File

@ -18,7 +18,8 @@ class POI : public QObject
public:
POI(QObject *parent = 0);
bool loadFile(const QString &fileName);
bool loadFile(const QString &path);
bool loadDir(const QString &path);
const QString &errorString() const {return _errorString;}
int errorLine() const {return _errorLine;}
@ -43,6 +44,8 @@ private:
bool enabled;
};
bool loadFile(const QString &path, bool dir);
POITree _tree;
QVector<Waypoint> _data;
QStringList _files;

View File

@ -8,8 +8,6 @@
class TCXParser : public Parser
{
public:
~TCXParser() {}
bool parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Waypoint> &waypoints);
QString errorString() const {return _reader.errorString();}

View File

@ -56,7 +56,7 @@ Defense.
((clat) / sqrt(one_minus_sqr_es_sin))
AlbersEqual::AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double falseEasting, double falseNorthing)
{
@ -78,7 +78,7 @@ AlbersEqual::AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
sp1 = deg2rad(standardParallel1);
sp2 = deg2rad(standardParallel2);
_es2 = 2 * _e.flattening() - _e.flattening() * _e.flattening();
_es2 = 2 * _e->flattening() - _e->flattening() * _e->flattening();
_es = sqrt(_es2);
_one_minus_es2 = 1 - _es2;
_two_es = 2 * _es;
@ -108,7 +108,7 @@ AlbersEqual::AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
_n = sin_lat1;
_C = sqr_m1 + _n * q1;
_a_over_n = _e.radius() / _n;
_a_over_n = _e->radius() / _n;
nq0 = _n * q0;
_rho0 = (_C < nq0) ? 0 : _a_over_n * sqrt(_C - nq0);
}
@ -171,7 +171,7 @@ Coordinates AlbersEqual::xy2ll(const QPointF &p) const
if (rho != 0.0)
theta = atan2(dx, rho0_minus_dy);
rho_n = rho * _n;
q = (_C - (rho_n * rho_n) / (_e.radius() * _e.radius())) / _n;
q = (_C - (rho_n * rho_n) / (_e->radius() * _e->radius())) / _n;
qc = 1 - ((_one_minus_es2) / (_two_es)) * log((1.0 - _es) / (1.0 + _es));
if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) {
q_over_2 = q / 2.0;

View File

@ -2,20 +2,22 @@
#define ALBERSEQUAL_H
#include "ellipsoid.h"
#include "projection.h"
#include "ct.h"
class AlbersEqual : public Projection
class AlbersEqual : public CT
{
public:
AlbersEqual(const Ellipsoid &ellipsoid, double standardParallel1,
AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double falseEasting, double falseNorthing);
virtual CT *clone() const {return new AlbersEqual(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
private:
Ellipsoid _e;
const Ellipsoid *_e;
double _latitudeOrigin;
double _longitudeOrigin;

90
src/map/angularunits.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "common/coordinates.h"
#include "common/str2int.h"
#include "angularunits.h"
static double sDMS2deg(double val)
{
double angle;
const char *decimal;
QString qstr(QString::number(qAbs(val), 'f', 7));
const char *str = qstr.toLatin1().constData();
decimal = strrchr(str, '.');
int deg = str2int(str, decimal - str);
int min = str2int(decimal + 1, 2);
int sec = str2int(decimal + 3, 2);
int f = str2int(decimal + 5, 3);
angle = deg + min/60.0 + sec/3600.0 + (f/1000.0)/3600.0;
return (val < 0) ? -angle : angle;
}
static double deg2sDMS(double val)
{
double aval = qAbs(val);
int deg = aval;
double r1 = aval - deg;
int min = r1 * 60.0;
double r2 = r1 - (min / 60.0);
int sec = r2 * 3600.0;
double r3 = r2 - (sec / 3600.0);
int f = (int)(r3 * 3600.0 * 1000.0);
QString str(QString("%1.%2%3%4").arg(deg).arg(min, 2, 10, QChar('0'))
.arg(sec, 2, 10, QChar('0')).arg(f, 3, 10, QChar('0')));
return (val < 0) ? -str.toDouble() : str.toDouble();
}
AngularUnits::AngularUnits(int code) : _code(code)
{
switch (code) {
case 9101:
_f = 180.0 / M_PI;
break;
case 9102:
case 9107:
case 9108:
case 9110:
case 9122:
_f = 1.0;
break;
case 9103:
_f = 1 / 60.0;
break;
case 9104:
_f = 1 / 3600.0;
break;
case 9105:
_f = 180.0 / 200.0;
break;
case 9106:
_f = 180.0 / 200.0;
break;
case 9109:
_f = 180.0 / (M_PI * 1000000.0);
break;
default:
_f = NAN;
}
}
double AngularUnits::toDegrees(double val) const
{
return (_code == 9110) ? sDMS2deg(val) : val * _f;
}
double AngularUnits::fromDegrees(double val) const
{
return (_code == 9110) ? deg2sDMS(val) : val / _f;
}
QDebug operator<<(QDebug dbg, const AngularUnits &au)
{
dbg.nospace() << "AngularUnits(" << deg2rad(au._f) << ")";
return dbg.space();
}

32
src/map/angularunits.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef ANGULARUNITS_H
#define ANGULARUNITS_H
#include <cmath>
#include <QDebug>
class AngularUnits
{
public:
AngularUnits() : _code(0), _f(NAN) {}
AngularUnits(int code);
bool isNull() const {return std::isnan(_f);}
bool isValid() const {return !std::isnan(_f);}
double toDegrees(double val) const;
double fromDegrees(double val) const;
friend bool operator==(const AngularUnits &au1, const AngularUnits &au2);
friend QDebug operator<<(QDebug dbg, const AngularUnits &au);
private:
int _code;
double _f;
};
inline bool operator==(const AngularUnits &au1, const AngularUnits &au2)
{return (au1._f == au2._f);}
QDebug operator<<(QDebug dbg, const AngularUnits &au);
#endif // ANGULARUNITS_H

View File

@ -31,37 +31,6 @@ static bool yCmp(const OfflineMap *m1, const OfflineMap *m2)
return TL(m1).y() > TL(m2).y();
}
bool Atlas::isAtlas(Tar &tar, const QString &path)
{
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();
}
if (ba.startsWith("Atlas 1.0"))
return true;
else {
_errorString = "Missing or invalid tba file";
return false;
}
}
void Atlas::computeZooms()
{
qSort(_maps.begin(), _maps.end(), resCmp);
@ -111,16 +80,38 @@ void Atlas::computeBounds()
Atlas::Atlas(const QString &fileName, QObject *parent) : Map(parent)
{
Tar tar;
QFileInfo fi(fileName);
QByteArray ba;
QString suffix = fi.suffix().toLower();
Tar tar;
_valid = false;
_zoom = 0;
_name = fi.dir().dirName();
_ci = -1; _cz = -1;
if (!isAtlas(tar, fileName))
if (suffix == "tar") {
if (!tar.load(fileName)) {
_errorString = "Error reading tar file";
return;
}
QString tbaFileName = fi.completeBaseName() + ".tba";
ba = tar.file(tbaFileName);
} else if (suffix == "tba") {
QFile tbaFile(fileName);
if (!tbaFile.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening tba file: %1")
.arg(tbaFile.errorString());
return;
}
ba = tbaFile.readAll();
}
if (!ba.startsWith("Atlas 1.0")) {
_errorString = "Missing or invalid tba file";
return;
}
QDir dir(fi.absolutePath());
QFileInfoList layers = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
@ -336,3 +327,20 @@ void Atlas::unload()
for (int i = 0; i < _maps.count(); i++)
_maps.at(i)->unload();
}
bool Atlas::isAtlas(const QString &path)
{
QFileInfo fi(path);
QString suffix = fi.suffix().toLower();
Tar tar;
if (suffix == "tar") {
if (!tar.load(path))
return false;
QString tbaFileName = fi.completeBaseName() + ".tba";
return tar.contains(tbaFileName);
} else if (suffix == "tba")
return true;
return false;
}

View File

@ -35,9 +35,10 @@ public:
bool isValid() const {return _valid;}
const QString &errorString() const {return _errorString;}
static bool isAtlas(const QString &path);
private:
void draw(QPainter *painter, const QRectF &rect, int mapIndex);
bool isAtlas(Tar &tar, const QString &path);
void computeZooms();
void computeBounds();

17
src/map/ct.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef CT_H
#define CT_H
#include <QPointF>
#include "common/coordinates.h"
class CT {
public:
virtual ~CT() {}
virtual CT *clone() const = 0;
virtual QPointF ll2xy(const Coordinates &c) const = 0;
virtual Coordinates xy2ll(const QPointF &p) const = 0;
};
#endif // CT_H

View File

@ -1,96 +1,14 @@
#include <cmath>
#include <QFile>
#include "common/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.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;
}
static Ellipsoid WGS84e = Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING);
static Datum WGS84 = Datum(&WGS84e, 0.0, 0.0, 0.0);
// Abridged Molodensky transformation
Coordinates Datum::toWGS84(const Coordinates &c) const
static Coordinates molodensky(const Coordinates &c, const Datum &from,
const Datum &to)
{
if (_ellipsoid.radius() == WGS84_RADIUS
&& _ellipsoid.flattening() == WGS84_FLATTENING
&& _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
return c;
double rlat = deg2rad(c.lat());
double rlon = deg2rad(c.lon());
@ -100,21 +18,51 @@ Coordinates Datum::toWGS84(const Coordinates &c) const
double clon = cos(rlon);
double ssqlat = slat * slat;
double from_f = ellipsoid().flattening();
double df = WGS84_FLATTENING - from_f;
double from_a = ellipsoid().radius();
double da = WGS84_RADIUS - from_a;
double from_esq = ellipsoid().flattening()
* (2.0 - ellipsoid().flattening());
double dx = from.dx() - to.dx();
double dy = from.dy() - to.dy();
double dz = from.dz() - to.dz();
double from_f = from.ellipsoid()->flattening();
double to_f = to.ellipsoid()->flattening();
double df = to_f - from_f;
double from_a = from.ellipsoid()->radius();
double to_a = to.ellipsoid()->radius();
double da = to_a - from_a;
double from_esq = from_f * (2.0 - from_f);
double adb = 1.0 / (1.0 - from_f);
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
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);
double dlon = (-dx * slon + dy * clon) / ((rn + from_h) * clat);
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
}
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy,
double dz) : _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz)
{
_WGS84 = (*_ellipsoid == *WGS84.ellipsoid() && _dx == WGS84.dx()
&& _dy == WGS84.dy() && _dz == WGS84.dz()) ? true : false;
}
Coordinates Datum::toWGS84(const Coordinates &c) const
{
return _WGS84 ? c : molodensky(c, *this, WGS84);
}
Coordinates Datum::fromWGS84(const Coordinates &c) const
{
return _WGS84 ? c : molodensky(c, WGS84, *this);
}
QDebug operator<<(QDebug dbg, const Datum &datum)
{
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
<< ", " << datum.dy() << ", " << datum.dz() << ")";
return dbg.space();
}

View File

@ -1,40 +1,44 @@
#ifndef DATUM_H
#define DATUM_H
#include <QMap>
#include <cmath>
#include <QList>
#include <QDebug>
#include "ellipsoid.h"
#include "common/coordinates.h"
class Datum
{
public:
Datum() : _ellipsoid(Ellipsoid()), _dx(0.0), _dy(0.0), _dz(0.0) {}
Datum(const Ellipsoid &ellipsoid, double dx, double dy, double dz)
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz) {}
Datum() : _ellipsoid(0), _dx(NAN), _dy(NAN), _dz(NAN),
_WGS84(false) {}
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz);
const Ellipsoid &ellipsoid() const {return _ellipsoid;}
const Ellipsoid *ellipsoid() const {return _ellipsoid;}
double dx() const {return _dx;}
double dy() const {return _dy;}
double dz() const {return _dz;}
bool isNull() const
{return (_ellipsoid.isNull() && _dx == 0.0 && _dy == 0.0 && _dz == 0.0);}
{return (!_ellipsoid && std::isnan(_dx) && std::isnan(_dy)
&& std::isnan(_dz));}
bool isValid() const
{return (_ellipsoid && !std::isnan(_dx) && !std::isnan(_dy)
&& !std::isnan(_dz));}
Coordinates toWGS84(const Coordinates &c) const;
static bool loadList(const QString &path);
static const QString &errorString() {return _errorString;}
static int errorLine() {return _errorLine;}
static Datum datum(const QString &name);
Coordinates fromWGS84(const Coordinates &c) const;
private:
Ellipsoid _ellipsoid;
const Ellipsoid *_ellipsoid;
double _dx, _dy, _dz;
static QMap<QString, Datum> _datums;
static QString _errorString;
static int _errorLine;
bool _WGS84;
};
inline bool operator==(const Datum &d1, const Datum &d2)
{return (d1.ellipsoid() == d2.ellipsoid() && d1.dx() == d2.dx()
&& d1.dy() == d2.dy() && d1.dz() == d2.dz());}
QDebug operator<<(QDebug dbg, const Datum &datum);
#endif // DATUM_H

View File

@ -1,62 +1,74 @@
#include <QFile>
#include <QDebug>
#include "common/wgs84.h"
#include "ellipsoid.h"
QMap<int, Ellipsoid> Ellipsoid::_ellipsoids;
QString Ellipsoid::_errorString;
int Ellipsoid::_errorLine = 0;
QMap<int, Ellipsoid> Ellipsoid::_ellipsoids = WGS84();
Ellipsoid Ellipsoid::ellipsoid(int id)
QMap<int, Ellipsoid> Ellipsoid::WGS84()
{
QMap<int, Ellipsoid> map;
map.insert(7030, Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING));
return map;
}
const Ellipsoid *Ellipsoid::ellipsoid(int id)
{
QMap<int, Ellipsoid>::const_iterator it = _ellipsoids.find(id);
if (it == _ellipsoids.end())
return Ellipsoid();
return it.value();
return 0;
else
return &(it.value());
}
bool Ellipsoid::loadList(const QString &path)
void Ellipsoid::loadList(const QString &path)
{
QFile file(path);
bool res;
int ln = 0;
if (!file.open(QFile::ReadOnly)) {
_errorString = qPrintable(file.errorString());
return false;
qWarning("Error opening ellipsoids file: %s: %s", qPrintable(path),
qPrintable(file.errorString()));
return;
}
_errorLine = 1;
_errorString.clear();
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() != 4) {
_errorString = "Format error";
return false;
qWarning("%s: %d: Format error", qPrintable(path), ln);
continue;
}
int id = list[0].trimmed().toInt(&res);
int id = list[1].trimmed().toInt(&res);
if (!res) {
_errorString = "Invalid ellipsoid id";
return false;
qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln);
continue;
}
double radius = list[2].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid ellipsoid radius";
return false;
qWarning("%s: %d: Invalid radius", qPrintable(path), ln);
continue;
}
double flattening = list[3].trimmed().toDouble(&res);
if (!res) {
_errorString = "Invalid ellipsoid flattening";
return false;
qWarning("%s: %d: Invalid flattening", qPrintable(path), ln);
continue;
}
Ellipsoid e(radius, 1.0/flattening);
_ellipsoids.insert(id, e);
_errorLine++;
}
return true;
}
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid)
{
dbg.nospace() << "Ellipsoid(" << ellipsoid.radius() << ", "
<< 1.0 / ellipsoid.flattening() << ")";
return dbg.space();
}

View File

@ -1,34 +1,40 @@
#ifndef ELLIPSOID_H
#define ELLIPSOID_H
#include <cmath>
#include <QString>
#include <QMap>
#include <QDebug>
class Ellipsoid
{
public:
Ellipsoid() : _radius(0.0), _flattening(0.0) {}
Ellipsoid() : _radius(NAN), _flattening(NAN) {}
Ellipsoid(double radius, double flattening)
: _radius(radius), _flattening(flattening) {}
double radius() const {return _radius;}
double flattening() const {return _flattening;}
bool isNull() const {return (_radius == 0.0 && _flattening == 0.0);}
bool isNull() const
{return (std::isnan(_radius) && std::isnan(_flattening));}
bool isValid() const
{return !(std::isnan(_radius) || std::isnan(_flattening));}
static bool loadList(const QString &path);
static const QString &errorString() {return _errorString;}
static int errorLine() {return _errorLine;}
static Ellipsoid ellipsoid(int id);
static const Ellipsoid *ellipsoid(int id);
static void loadList(const QString &path);
private:
double _radius;
double _flattening;
static QMap<int, Ellipsoid> WGS84();
static QMap<int, Ellipsoid> _ellipsoids;
static QString _errorString;
static int _errorLine;
};
inline bool operator==(const Ellipsoid &e1, const Ellipsoid &e2)
{return (e1.radius() == e2.radius() && e1.flattening() == e2.flattening());}
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid);
#endif // ELLIPSOID_H

View File

@ -4,7 +4,6 @@
#include "common/rectc.h"
#include "common/wgs84.h"
#include "mercator.h"
#include "misc.h"
#include "emptymap.h"
@ -18,7 +17,7 @@ EmptyMap::EmptyMap(QObject *parent) : Map(parent)
QRectF EmptyMap::bounds() const
{
return scaled(QRectF(QPointF(-180, -180), QSizeF(360, 360)), 1.0/_scale);
return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85)));
}
qreal EmptyMap::zoomFit(const QSize &size, const RectC &br)
@ -72,13 +71,13 @@ void EmptyMap::draw(QPainter *painter, const QRectF &rect)
painter->fillRect(rect, _backgroundColor);
}
QPointF EmptyMap::ll2xy(const Coordinates &c)
QPointF EmptyMap::ll2xy(const Coordinates &c) const
{
QPointF m = Mercator().ll2xy(c);
return QPointF(m.x() / _scale, m.y() / -_scale);
}
Coordinates EmptyMap::xy2ll(const QPointF &p)
Coordinates EmptyMap::xy2ll(const QPointF &p) const
{
QPointF m(p.x() * _scale, -p.y() * _scale);
return Mercator().xy2ll(m);

View File

@ -1,6 +1,7 @@
#ifndef EMPTYMAP_H
#define EMPTYMAP_H
#include "common/coordinates.h"
#include "map.h"
class EmptyMap : public Map
@ -21,12 +22,17 @@ public:
qreal zoomIn();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p);
QPointF ll2xy(const Coordinates &c)
{return static_cast<const EmptyMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const EmptyMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect);
private:
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
QString _name;
qreal _scale;
};

191
src/map/gcs.cpp Normal file
View File

@ -0,0 +1,191 @@
#include <QFile>
#include "common/wgs84.h"
#include "gcs.h"
class GCS::Entry {
public:
Entry(int id, int gd, const QString &name, const GCS &gcs)
: _id(id), _gd(gd), _name(name), _gcs(gcs) {}
int id() const {return _id;}
int gd() const {return _gd;}
const QString &name() const {return _name;}
const GCS &gcs() const {return _gcs;}
private:
int _id, _gd;
QString _name;
GCS _gcs;
};
static Ellipsoid WGS84e = Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING);
static Datum WGS84d = Datum(&WGS84e, 0.0, 0.0, 0.0);
static int parameter(const QString &str, bool *res)
{
QString field = str.trimmed();
if (field.isEmpty()) {
*res = true;
return 0;
}
return field.toInt(res);
}
QList<GCS::Entry> GCS::_gcss = WGS84();
QList<GCS::Entry> GCS::WGS84()
{
QList<GCS::Entry> list;
list.append(GCS::Entry(4326, 6326, "WGS 84", GCS(WGS84d, 8901, 9122)));
return list;
}
const GCS *GCS::gcs(int id)
{
for (int i = 0; i < _gcss.size(); i++)
if (_gcss.at(i).id() == id)
return &(_gcss.at(i).gcs());
return 0;
}
const GCS *GCS::gcs(int geodeticDatum, int primeMeridian, int angularUnits)
{
for (int i = 0; i < _gcss.size(); i++) {
const Entry &e = _gcss.at(i);
if (e.gd() == geodeticDatum && e.gcs().primeMeridian() == primeMeridian
&& e.gcs().angularUnits() == angularUnits)
return &(e.gcs());
}
return 0;
}
const GCS *GCS::gcs(const QString &name)
{
for (int i = 0; i < _gcss.size(); i++)
if (_gcss.at(i).name() == name)
return &(_gcss.at(i).gcs());
return 0;
}
void GCS::loadList(const QString &path)
{
QFile file(path);
bool res;
int ln = 0;
const Ellipsoid *e;
if (!file.open(QFile::ReadOnly)) {
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
qPrintable(file.errorString()));
return;
}
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() < 10) {
qWarning("%s: %d: Format error", qPrintable(path), ln);
continue;
}
int id = parameter(list[1], &res);
if (!res) {
qWarning("%s: %d: Invalid GCS code", qPrintable(path), ln);
continue;
}
int gd = parameter(list[2], &res);
if (!res) {
qWarning("%s: %d: Invalid geodetic datum code", qPrintable(path),
ln);
continue;
}
int au = list[3].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid angular units code", qPrintable(path),
ln);
continue;
}
int el = list[4].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid ellipsoid code", qPrintable(path), ln);
continue;
}
int pm = list[5].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid prime meridian code", qPrintable(path),
ln);
continue;
}
int ct = list[6].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid coordinates transformation code",
qPrintable(path), ln);
continue;
}
double dx = list[7].trimmed().toDouble(&res);
if (!res) {
qWarning("%s: %d: Invalid dx", qPrintable(path), ln);
continue;
}
double dy = list[8].trimmed().toDouble(&res);
if (!res) {
qWarning("%s: %d: Invalid dy", qPrintable(path), ln);
continue;
}
double dz = list[9].trimmed().toDouble(&res);
if (!res) {
qWarning("%s: %d: Invalid dz", qPrintable(path), ln);
continue;
}
if (!(e = Ellipsoid::ellipsoid(el))) {
qWarning("%s: %d: Unknown ellipsoid code", qPrintable(path), ln);
continue;
}
Datum datum;
switch (ct) {
case 9603:
datum = Datum(e, dx, dy, dz);
break;
default:
qWarning("%s: %d: Unknown coordinates transformation method",
qPrintable(path), ln);
continue;
}
GCS gcs(datum, pm, au);
if (gcs.isValid())
_gcss.append(Entry(id, gd, list[0].trimmed(), gcs));
else
qWarning("%s: %d: Unknown prime meridian/angular units code",
qPrintable(path), ln);
}
}
Coordinates GCS::toWGS84(const Coordinates &c) const
{
return datum().toWGS84(Coordinates(_primeMeridian.toGreenwich(c.lon()),
c.lat()));
}
Coordinates GCS::fromWGS84(const Coordinates &c) const
{
Coordinates ds(datum().fromWGS84(c));
return Coordinates(_primeMeridian.fromGreenwich(ds.lon()), ds.lat());
}
QDebug operator<<(QDebug dbg, const GCS &gcs)
{
dbg.nospace() << "GCS(" << gcs.datum() << ", " << gcs.primeMeridian()
<< ", " << gcs.angularUnits() << ")";
return dbg.space();
}

55
src/map/gcs.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef GCS_H
#define GCS_H
#include "datum.h"
#include "angularunits.h"
#include "primemeridian.h"
class GCS
{
public:
GCS() {}
GCS(const Datum &datum, const PrimeMeridian &primeMeridian,
const AngularUnits &angularUnits) : _datum(datum),
_primeMeridian(primeMeridian), _angularUnits(angularUnits) {}
const PrimeMeridian &primeMeridian() const {return _primeMeridian;}
const AngularUnits &angularUnits() const {return _angularUnits;}
const Datum &datum() const {return _datum;}
bool isNull() const {return _datum.isNull() && _angularUnits.isNull()
&& _primeMeridian.isNull();}
bool isValid() const {return _datum.isValid() && _angularUnits.isValid()
&& _primeMeridian.isValid();}
Coordinates toWGS84(const Coordinates &c) const;
Coordinates fromWGS84(const Coordinates &c) const;
static const GCS *gcs(int id);
static const GCS *gcs(int geodeticDatum, int primeMeridian,
int angularUnits);
static const GCS *gcs(const QString &name);
static void loadList(const QString &path);
private:
class Entry;
static QList<Entry> WGS84();
Datum _datum;
PrimeMeridian _primeMeridian;
AngularUnits _angularUnits;
static QList<Entry> _gcss;
};
inline bool operator==(const GCS &gcs1, const GCS &gcs2)
{return (gcs1.datum() == gcs2.datum()
&& gcs1.primeMeridian() == gcs2.primeMeridian()
&& gcs1.angularUnits() == gcs2.angularUnits());}
QDebug operator<<(QDebug dbg, const GCS &gcs);
#endif // GCS_H

484
src/map/geotiff.cpp Normal file
View File

@ -0,0 +1,484 @@
#include <QFileInfo>
#include <QtEndian>
#include "pcs.h"
#include "latlon.h"
#include "geotiff.h"
#define TIFF_DOUBLE 12
#define TIFF_SHORT 3
#define TIFF_LONG 4
#define ModelPixelScaleTag 33550
#define ModelTiepointTag 33922
#define ModelTransformationTag 34264
#define GeoKeyDirectoryTag 34735
#define GeoDoubleParamsTag 34736
#define ImageWidth 256
#define ImageHeight 257
#define GTModelTypeGeoKey 1024
#define GTRasterTypeGeoKey 1025
#define GeographicTypeGeoKey 2048
#define GeogGeodeticDatumGeoKey 2050
#define GeogPrimeMeridianGeoKey 2051
#define GeogAngularUnitsGeoKey 2054
#define ProjectedCSTypeGeoKey 3072
#define ProjectionGeoKey 3074
#define ProjCoordTransGeoKey 3075
#define ProjLinearUnitsGeoKey 3076
#define ProjStdParallel1GeoKey 3078
#define ProjStdParallel2GeoKey 3079
#define ProjNatOriginLongGeoKey 3080
#define ProjNatOriginLatGeoKey 3081
#define ProjFalseEastingGeoKey 3082
#define ProjFalseNorthingGeoKey 3083
#define ProjScaleAtNatOriginGeoKey 3092
#define ModelTypeProjected 1
#define ModelTypeGeographic 2
#define ModelTypeGeocentric 3
#define IS_SET(map, key) \
((map).contains(key) && (map).value(key).SHORT != 32767)
#define ARRAY_SIZE(a) \
(sizeof(a) / sizeof(*a))
typedef struct {
quint16 KeyDirectoryVersion;
quint16 KeyRevision;
quint16 MinorRevision;
quint16 NumberOfKeys;
} Header;
typedef struct {
quint16 KeyID;
quint16 TIFFTagLocation;
quint16 Count;
quint16 ValueOffset;
} KeyEntry;
bool GeoTIFF::readEntry(TIFFFile &file, Ctx &ctx) const
{
quint16 tag;
quint16 type;
quint32 count, offset;
if (!file.readValue(tag))
return false;
if (!file.readValue(type))
return false;
if (!file.readValue(count))
return false;
if (!file.readValue(offset))
return false;
switch (tag) {
case ModelPixelScaleTag:
if (type != TIFF_DOUBLE || count != 3)
return false;
ctx.scale = offset;
break;
case ModelTiepointTag:
if (type != TIFF_DOUBLE || count < 6 || count % 6)
return false;
ctx.tiepoints = offset;
ctx.tiepointCount = count / 6;
break;
case GeoKeyDirectoryTag:
if (type != TIFF_SHORT)
return false;
ctx.keys = offset;
break;
case GeoDoubleParamsTag:
if (type != TIFF_DOUBLE)
return false;
ctx.values = offset;
break;
case ModelTransformationTag:
if (type != TIFF_DOUBLE || count != 16)
return false;
ctx.matrix = offset;
break;
}
return true;
}
bool GeoTIFF::readIFD(TIFFFile &file, quint32 &offset, Ctx &ctx) const
{
quint16 count;
if (!file.seek(offset))
return false;
if (!file.readValue(count))
return false;
for (quint16 i = 0; i < count; i++)
if (!readEntry(file, ctx))
return false;
if (!file.readValue(offset))
return false;
return true;
}
bool GeoTIFF::readScale(TIFFFile &file, quint32 offset, QPointF &scale) const
{
if (!file.seek(offset))
return false;
if (!file.readValue(scale.rx()))
return false;
if (!file.readValue(scale.ry()))
return false;
return true;
}
bool GeoTIFF::readTiepoints(TIFFFile &file, quint32 offset, quint32 count,
QList<ReferencePoint> &points) const
{
double z, pz;
QPointF xy, pp;
if (!file.seek(offset))
return false;
for (quint32 i = 0; i < count; i++) {
if (!file.readValue(xy.rx()))
return false;
if (!file.readValue(xy.ry()))
return false;
if (!file.readValue(z))
return false;
if (!file.readValue(pp.rx()))
return false;
if (!file.readValue(pp.ry()))
return false;
if (!file.readValue(pz))
return false;
ReferencePoint p;
p.xy = xy.toPoint();
p.pp = pp;
points.append(p);
}
return true;
}
bool GeoTIFF::readMatrix(TIFFFile &file, quint32 offset, double matrix[16]) const
{
if (!file.seek(offset))
return false;
for (int i = 0; i < 16; i++)
if (!file.readValue(matrix[i]))
return false;
return true;
}
bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
{
Header header;
KeyEntry entry;
Value value;
if (!file.seek(ctx.keys))
return false;
if (!file.readValue(header.KeyDirectoryVersion))
return false;
if (!file.readValue(header.KeyRevision))
return false;
if (!file.readValue(header.MinorRevision))
return false;
if (!file.readValue(header.NumberOfKeys))
return false;
for (int i = 0; i < header.NumberOfKeys; i++) {
if (!file.readValue(entry.KeyID))
return false;
if (!file.readValue(entry.TIFFTagLocation))
return false;
if (!file.readValue(entry.Count))
return false;
if (!file.readValue(entry.ValueOffset))
return false;
switch (entry.KeyID) {
case GTModelTypeGeoKey:
case GTRasterTypeGeoKey:
case GeographicTypeGeoKey:
case GeogGeodeticDatumGeoKey:
case GeogPrimeMeridianGeoKey:
case GeogAngularUnitsGeoKey:
case ProjectedCSTypeGeoKey:
case ProjectionGeoKey:
case ProjCoordTransGeoKey:
case ProjLinearUnitsGeoKey:
if (entry.TIFFTagLocation != 0 || entry.Count != 1)
return false;
value.SHORT = entry.ValueOffset;
kv.insert(entry.KeyID, value);
break;
case ProjScaleAtNatOriginGeoKey:
case ProjNatOriginLongGeoKey:
case ProjNatOriginLatGeoKey:
case ProjFalseEastingGeoKey:
case ProjFalseNorthingGeoKey:
case ProjStdParallel1GeoKey:
case ProjStdParallel2GeoKey:
if (!readGeoValue(file, ctx.values, entry.ValueOffset,
value.DOUBLE))
return false;
kv.insert(entry.KeyID, value);
break;
default:
break;
}
}
return true;
}
bool GeoTIFF::readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
double &val) const
{
qint64 pos = file.pos();
if (!file.seek(offset + index * sizeof(double)))
return false;
if (!file.readValue(val))
return false;
if (!file.seek(pos))
return false;
return true;
}
const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
{
const GCS *gcs = 0;
if (IS_SET(kv, GeographicTypeGeoKey)) {
if (!(gcs = GCS::gcs(kv.value(GeographicTypeGeoKey).SHORT)))
_errorString = QString("%1: unknown GCS")
.arg(kv.value(GeographicTypeGeoKey).SHORT);
} else if (IS_SET(kv, GeogGeodeticDatumGeoKey)) {
int pm = IS_SET(kv, GeogPrimeMeridianGeoKey)
? kv.value(GeogPrimeMeridianGeoKey).SHORT : 8901;
int au = IS_SET(kv, GeogAngularUnitsGeoKey)
? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102;
if (!(gcs = GCS::gcs(kv.value(GeogGeodeticDatumGeoKey).SHORT, pm, au)))
_errorString = QString("%1+%2: unknown geodetic datum + prime"
" meridian combination")
.arg(kv.value(GeogGeodeticDatumGeoKey).SHORT)
.arg(kv.value(GeogPrimeMeridianGeoKey).SHORT);
} else
_errorString = "Can not determine GCS";
return gcs;
}
Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
{
if (!IS_SET(kv, ProjCoordTransGeoKey)) {
_errorString = "Missing coordinate transformation method";
return Projection::Method();
}
switch (kv.value(ProjCoordTransGeoKey).SHORT) {
case 1:
return Projection::Method(9807);
case 7:
return Projection::Method(1024);
case 8:
return Projection::Method(9801);
case 9:
return Projection::Method(9802);
case 10:
return Projection::Method(9820);
case 11:
return Projection::Method(9822);
default:
_errorString = QString("%1: unknown coordinate transformation method")
.arg(kv.value(ProjCoordTransGeoKey).SHORT);
return Projection::Method();
}
}
bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
{
if (IS_SET(kv, ProjectedCSTypeGeoKey)) {
const PCS *pcs;
if (!(pcs = PCS::pcs(kv.value(ProjectedCSTypeGeoKey).SHORT))) {
_errorString = QString("%1: unknown PCS")
.arg(kv.value(ProjectedCSTypeGeoKey).SHORT);
return false;
}
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(),
pcs->units());
} else if (IS_SET(kv, ProjectionGeoKey)) {
const GCS *g = gcs(kv);
if (!g)
return false;
const PCS *pcs = PCS::pcs(g, kv.value(ProjectionGeoKey).SHORT);
if (!pcs) {
_errorString = QString("%1: unknown projection code")
.arg(kv.value(GeographicTypeGeoKey).SHORT)
.arg(kv.value(ProjectionGeoKey).SHORT);
return false;
}
_projection = Projection(pcs->gcs(), pcs->method(), pcs->setup(),
pcs->units());
} else {
const GCS *g = gcs(kv);
if (!g)
return false;
Projection::Method m(method(kv));
if (m.isNull())
return false;
AngularUnits au(IS_SET(kv, GeogAngularUnitsGeoKey)
? kv.value(GeogAngularUnitsGeoKey).SHORT : 9102);
LinearUnits lu(IS_SET(kv, ProjLinearUnitsGeoKey)
? kv.value(ProjLinearUnitsGeoKey).SHORT : 9001);
if (lu.isNull()) {
_errorString = QString("%1: unknown projection linear units code")
.arg(kv.value(ProjLinearUnitsGeoKey).SHORT);
return false;
}
Projection::Setup setup(
au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE),
au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE),
kv.value(ProjScaleAtNatOriginGeoKey).DOUBLE,
lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE),
lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE),
au.toDegrees(kv.value(ProjStdParallel1GeoKey).DOUBLE),
au.toDegrees(kv.value(ProjStdParallel2GeoKey).DOUBLE)
);
_projection = Projection(g, m, setup, lu);
}
return true;
}
bool GeoTIFF::geographicModel(QMap<quint16, Value> &kv)
{
const GCS *g = gcs(kv);
if (!g)
return false;
_projection = Projection(g);
return true;
}
bool GeoTIFF::load(const QString &path)
{
quint32 ifd;
QList<ReferencePoint> points;
QPointF scale;
QMap<quint16, Value> kv;
Ctx ctx;
TIFFFile file;
file.setFileName(path);
if (!file.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening TIFF file: %1")
.arg(file.errorString());
return false;
}
if (!file.readHeader(ifd)) {
_errorString = "Invalid TIFF header";
return false;
}
while (ifd) {
if (!readIFD(file, ifd, ctx)) {
_errorString = "Invalid IFD";
return false;
}
}
if (!ctx.keys) {
_errorString = "Not a GeoTIFF file";
return false;
}
if (ctx.scale) {
if (!readScale(file, ctx.scale, scale)) {
_errorString = "Error reading model pixel scale";
return false;
}
}
if (ctx.tiepoints) {
if (!readTiepoints(file, ctx.tiepoints, ctx.tiepointCount, points)) {
_errorString = "Error reading raster->model tiepoint pairs";
return false;
}
}
if (!readKeys(file, ctx, kv)) {
_errorString = "Error reading Geo key/value";
return false;
}
switch (kv.value(GTModelTypeGeoKey).SHORT) {
case ModelTypeProjected:
if (!projectedModel(kv))
return false;
break;
case ModelTypeGeographic:
if (!geographicModel(kv))
return false;
break;
case ModelTypeGeocentric:
_errorString = "Geocentric models are not supported";
return false;
default:
_errorString = "Unknown/missing model type";
return false;
}
if (ctx.scale && ctx.tiepoints) {
const ReferencePoint &p = points.first();
_transform = QTransform(scale.x(), 0, 0, -scale.y(), p.pp.x() - p.xy.x()
/ scale.x(), p.pp.y() + p.xy.x() / scale.y()).inverted();
} else if (ctx.tiepointCount > 1) {
Transform t(points);
if (t.isNull()) {
_errorString = t.errorString();
return false;
}
_transform = t.transform();
} else if (ctx.matrix) {
double m[16];
if (!readMatrix(file, ctx.matrix, m)) {
_errorString = "Error reading transformation matrix";
return false;
}
if (m[2] != 0.0 || m[6] != 0.0 || m[8] != 0.0 || m[9] != 0.0
|| m[10] != 0.0 || m[11] != 0.0) {
_errorString = "Not a baseline transformation matrix";
}
_transform = QTransform(m[0], m[1], m[4], m[5], m[3], m[7]).inverted();
} else {
_errorString = "Incomplete/missing model transformation info";
return false;
}
return true;
}

61
src/map/geotiff.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef GEOTIFF_H
#define GEOTIFF_H
#include <QTransform>
#include <QFile>
#include <QMap>
#include "gcs.h"
#include "projection.h"
#include "tifffile.h"
#include "transform.h"
#include "linearunits.h"
class GeoTIFF
{
public:
bool load(const QString &path);
const QString &errorString() const {return _errorString;}
const Projection &projection() const {return _projection;}
const QTransform &transform() const {return _transform;}
private:
union Value {
quint16 SHORT;
double DOUBLE;
};
struct Ctx {
quint32 scale;
quint32 tiepoints;
quint32 tiepointCount;
quint32 matrix;
quint32 keys;
quint32 values;
Ctx() : scale(0), tiepoints(0), tiepointCount(0), matrix(0), keys(0),
values(0) {}
};
bool readEntry(TIFFFile &file, Ctx &ctx) const;
bool readIFD(TIFFFile &file, quint32 &offset, Ctx &ctx) const;
bool readScale(TIFFFile &file, quint32 offset, QPointF &scale) const;
bool readTiepoints(TIFFFile &file, quint32 offset, quint32 count,
QList<ReferencePoint> &points) const;
bool readMatrix(TIFFFile &file, quint32 offset, double matrix[16]) const;
bool readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const;
bool readGeoValue(TIFFFile &file, quint32 offset, quint16 index,
double &val) const;
const GCS *gcs(QMap<quint16, Value> &kv);
Projection::Method method(QMap<quint16, Value> &kv);
bool geographicModel(QMap<quint16, Value> &kv);
bool projectedModel(QMap<quint16, Value> &kv);
QTransform _transform;
Projection _projection;
QString _errorString;
};
#endif // GEOTIFF_H

View File

@ -48,19 +48,19 @@ Defense.
#define M_PI_2 1.57079632679489661923
#endif // M_PI_2
LambertAzimuthal::LambertAzimuthal(const Ellipsoid &ellipsoid,
LambertAzimuthal::LambertAzimuthal(const Ellipsoid *ellipsoid,
double latitudeOrigin, double longitudeOrigin, double falseEasting,
double falseNorthing)
{
double es2, es4, es6;
_e = ellipsoid;
es2 = 2 * _e.flattening() - _e.flattening() * _e.flattening();
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
es4 = es2 * es2;
es6 = es4 * es2;
_ra = _e.radius() * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0 * es6
/ 3024.0);
_ra = ellipsoid->radius() * (1.0 - es2 / 6.0 - 17.0 * es4 / 360.0 - 67.0
* es6 / 3024.0);
_latOrigin = deg2rad(latitudeOrigin);
_sinLatOrigin = sin(_latOrigin);
_cosLatOrigin = cos(_latOrigin);

View File

@ -2,20 +2,20 @@
#define LAMBERTAZIMUTHAL_H
#include "ellipsoid.h"
#include "projection.h"
#include "ct.h"
class LambertAzimuthal : public Projection
class LambertAzimuthal : public CT
{
public:
LambertAzimuthal(const Ellipsoid &ellipsoid, double latitudeOrigin,
LambertAzimuthal(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double falseEasting, double falseNorthing);
virtual CT *clone() const {return new LambertAzimuthal(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
private:
Ellipsoid _e;
double _ra;
double _sinLatOrigin;
double _cosLatOrigin;

View File

@ -1,3 +1,46 @@
/*
* Based on libgeotrans with the following Source Code Disclaimer:
1. The GEOTRANS source code ("the software") is provided free of charge by
the National Imagery and Mapping Agency (NIMA) of the United States
Department of Defense. Although NIMA makes no copyright claim under Title 17
U.S.C., NIMA claims copyrights in the source code under other legal regimes.
NIMA hereby grants to each user of the software a license to use and
distribute the software, and develop derivative works.
2. Warranty Disclaimer: The software was developed to meet only the internal
requirements of the U.S. National Imagery and Mapping Agency. The software
is provided "as is," and no warranty, express or implied, including but not
limited to the implied warranties of merchantability and fitness for
particular purpose or arising by statute or otherwise in law or from a
course of dealing or usage in trade, is made by NIMA as to the accuracy and
functioning of the software.
3. NIMA and its personnel are not required to provide technical support or
general assistance with respect to the software.
4. Neither NIMA nor its personnel will be liable for any claims, losses, or
damages arising from or connected with the use of the software. The user
agrees to hold harmless the United States National Imagery and Mapping
Agency. The user's sole and exclusive remedy is to stop using the software.
5. NIMA requests that products developed using the software credit the
source of the software with the following statement, "The product was
developed using GEOTRANS, a product of the National Imagery and Mapping
Agency and U.S. Army Engineering Research and Development Center."
6. For any products developed using the software, NIMA requires a disclaimer
that use of the software does not indicate endorsement or approval of the
product by the Secretary of Defense or the National Imagery and Mapping
Agency. Pursuant to the United States Code, 10 U.S.C. Sec. 2797, the name of
the National Imagery and Mapping Agency, the initials "NIMA", the seal of
the National Imagery and Mapping Agency, or any colorable imitation thereof
shall not be used to imply approval, endorsement, or authorization of a
product without prior written permission from United States Secretary of
Defense.
*/
#include <cmath>
#include "lambertconic.h"
@ -5,76 +48,229 @@
#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 M_PI_4 0.785398163397448309616
#endif /* M_PI_4 */
static double q(const Ellipsoid &el, double b)
#define LAMBERT_m(clat, essin) (clat / sqrt(1.0 - essin * essin))
#define LAMBERT2_t(lat, essin, es_over_2) \
(tan(M_PI_4 - lat / 2) * pow((1.0 + essin) / (1.0 - essin), es_over_2))
#define LAMBERT1_t(lat, essin, es_over_2) \
(tan(M_PI_4 - lat / 2) / pow((1.0 - essin) / (1.0 + essin), es_over_2))
LambertConic1::LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double scale, double falseEasting,
double falseNorthing)
{
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.));
double es2;
double es_sin;
double m0;
double lat_orig;
lat_orig = deg2rad(latitudeOrigin);
_longitudeOrigin = deg2rad(longitudeOrigin);
if (_longitudeOrigin > M_PI)
_longitudeOrigin -= 2 * M_PI;
_falseEasting = falseEasting;
_falseNorthing = falseNorthing;
es2 = 2.0 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
_es = sqrt(es2);
_es_over_2 = _es / 2.0;
_n = sin(lat_orig);
es_sin = _es * sin(lat_orig);
m0 = LAMBERT_m(cos(lat_orig), es_sin);
_t0 = LAMBERT1_t(lat_orig, es_sin, _es_over_2);
_rho0 = ellipsoid->radius() * scale * m0 / _n;
_rho_olat = _rho0;
}
static double iq(const Ellipsoid &el, double q)
QPointF LambertConic1::ll2xy(const Coordinates &c) const
{
double e = sqrt(el.flattening() * (2. - el.flattening()));
double b0 = 0.;
double b = 2. * atan(exp(q)) - M_PI_2;
double t;
double rho;
double dlam;
double theta;
double lat = deg2rad(c.lat());
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;
if (fabs(fabs(lat) - M_PI_2) > 1.0e-10) {
t = LAMBERT1_t(lat, _es * sin(lat), _es_over_2);
rho = _rho0 * pow(t / _t0, _n);
} else
rho = 0.0;
dlam = deg2rad(c.lon()) - _longitudeOrigin;
if (dlam > M_PI)
dlam -= 2 * M_PI;
if (dlam < -M_PI)
dlam += 2 * M_PI;
theta = _n * dlam;
return QPointF(rho * sin(theta) + _falseEasting, _rho_olat - rho
* cos(theta) + _falseNorthing);
}
static double nradius(const Ellipsoid &el, double phi)
Coordinates LambertConic1::xy2ll(const QPointF &p) const
{
double sin_phi = sin(phi);
return (el.radius() / sqrt(1. - (el.flattening() * (2. - el.flattening()))
* sin_phi * sin_phi));
double dx;
double dy;
double rho;
double rho_olat_minus_dy;
double t;
double PHI;
double es_sin;
double tempPHI = 0.0;
double theta = 0.0;
double tolerance = 4.85e-10;
int count = 30;
double lat, lon;
dy = p.y() - _falseNorthing;
dx = p.x() - _falseEasting;
rho_olat_minus_dy = _rho_olat - dy;
rho = sqrt(dx * dx + (rho_olat_minus_dy) * (rho_olat_minus_dy));
if (_n < 0.0) {
rho *= -1.0;
dx *= -1.0;
rho_olat_minus_dy *= -1.0;
}
if (rho != 0.0) {
theta = atan2(dx, rho_olat_minus_dy) / _n;
t = _t0 * pow(rho / _rho0, 1 / _n);
PHI = M_PI_2 - 2.0 * atan(t);
while (fabs(PHI - tempPHI) > tolerance && count) {
tempPHI = PHI;
es_sin = _es * sin(PHI);
PHI = M_PI_2 - 2.0 * atan(t * pow((1.0 - es_sin) / (1.0 + es_sin),
_es_over_2));
count--;
}
if (!count)
return Coordinates();
lat = PHI;
lon = theta + _longitudeOrigin;
if (fabs(lat) < 2.0e-7)
lat = 0.0;
if (lat > M_PI_2)
lat = M_PI_2;
else if (lat < -M_PI_2)
lat = -M_PI_2;
if (lon > M_PI) {
if (lon - M_PI < 3.5e-6)
lon = M_PI;
else
lon -= 2 * M_PI;
}
if (lon < -M_PI) {
if (fabs(lon + M_PI) < 3.5e-6)
lon = -M_PI;
else
lon += 2 * M_PI;
}
if (fabs(lon) < 2.0e-7)
lon = 0.0;
if (lon > M_PI)
lon = M_PI;
else if (lon < -M_PI)
lon = -M_PI;
} else {
if (_n > 0.0)
lat = M_PI_2;
else
lat = -M_PI_2;
lon = _longitudeOrigin;
}
return Coordinates(rad2deg(lon), rad2deg(lat));
}
LambertConic::LambertConic(const Ellipsoid &ellipsoid, double standardParallel1,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double scale, double falseEasting, double falseNorthing) : _e(ellipsoid)
LambertConic2::LambertConic2(const Ellipsoid *ellipsoid,
double standardParallel1, double standardParallel2, double latitudeOrigin,
double longitudeOrigin, double falseEasting, double falseNorthing)
{
_cm = deg2rad(longitudeOrigin);
_fe = falseEasting;
_fn = falseNorthing;
double es, es_over_2, es2, es_sin;
double lat0;
double k0;
double t0;
double t1, t2;
double t_olat;
double m0;
double m1;
double m2;
double n;
double const_value;
double sp1, sp2;
double lat_orig;
double sp1 = deg2rad(standardParallel1);
double sp2 = deg2rad(standardParallel2);
double N1 = nradius(_e, sp1);
double N2 = nradius(_e, sp2);
lat_orig = deg2rad(latitudeOrigin);
sp1 = deg2rad(standardParallel1);
sp2 = deg2rad(standardParallel2);
_q0 = q(_e, deg2rad(latitudeOrigin));
double q1 = q(_e, sp1);
double q2 = q(_e, sp2);
if (fabs(sp1 - sp2) > 1.0e-10) {
es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
* ellipsoid->flattening();
es = sqrt(es2);
es_over_2 = es / 2.0;
_n = log((N1 * cos(sp1)) / (N2 * cos(sp2))) / (q2 - q1);
double R1 = N1 * cos(sp1) / _n;
_R0 = scale * R1 * exp(_n * (q1 - _q0));
es_sin = es * sin(lat_orig);
t_olat = LAMBERT2_t(lat_orig, es_sin, es_over_2);
es_sin = es * sin(sp1);
m1 = LAMBERT_m(cos(sp1), es_sin);
t1 = LAMBERT2_t(sp1, es_sin, es_over_2);
es_sin = es * sin(sp2);
m2 = LAMBERT_m(cos(sp2), es_sin);
t2 = LAMBERT2_t(sp2, es_sin, es_over_2);
n = log(m1 / m2) / log(t1 / t2);
lat0 = asin(n);
es_sin = es * sin(lat0);
m0 = LAMBERT_m(cos(lat0), es_sin);
t0 = LAMBERT2_t(lat0, es_sin, es_over_2);
k0 = (m1 / m0) * (pow(t0 / t1, n));
const_value = ((ellipsoid->radius() * m2) / (n * pow(t2, n)));
falseNorthing += (const_value * pow(t_olat, n)) - (const_value
* pow(t0, n));
} else {
lat0 = sp1;
k0 = 1.0;
}
_lc1 = LambertConic1(ellipsoid, rad2deg(lat0), longitudeOrigin, k0,
falseEasting, falseNorthing);
}
QPointF LambertConic::ll2xy(const Coordinates &c) const
QPointF LambertConic2::ll2xy(const Coordinates &c) const
{
double dl = _n * (deg2rad(c.lon()) - _cm);
double R = _R0 * exp(_n * (_q0 - q(_e, deg2rad(c.lat()))));
return QPointF(_fe + R * sin(dl), _fn + _R0 - R * cos(dl));
return _lc1.ll2xy(c);
}
Coordinates LambertConic::xy2ll(const QPointF &p) const
Coordinates LambertConic2::xy2ll(const QPointF &p) const
{
double dl = atan((p.x() - _fe) / (_fn + _R0 - p.y()));
double dx = p.x() - _fe;
double dy = p.y() - _fn - _R0;
double R = sqrt(dx * dx + dy * dy);
double q = _q0 - log(fabs(R / _R0)) / _n;
return Coordinates(rad2deg(_cm + dl / _n), rad2deg(iq(_e, q)));
return _lc1.xy2ll(p);
}

View File

@ -2,28 +2,48 @@
#define LAMBERTCONIC_H
#include "ellipsoid.h"
#include "projection.h"
#include "ct.h"
class LambertConic : public Projection
class LambertConic1 : public CT
{
public:
LambertConic(const Ellipsoid &ellipsoid, double standardParallel1,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double scale, double falseEasting, double falseNorthing);
LambertConic1() {}
LambertConic1(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double scale, double falseEasting,
double falseNorthing);
virtual CT *clone() const {return new LambertConic1(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
private:
Ellipsoid _e;
double _longitudeOrigin;
double _falseEasting;
double _falseNorthing;
double _cm;
double _fe;
double _fn;
double _q0;
double _R0;
double _es;
double _es_over_2;
double _n;
double _t0;
double _rho0;
double _rho_olat;
};
class LambertConic2 : public CT
{
public:
LambertConic2(const Ellipsoid *ellipsoid, double standardParallel1,
double standardParallel2, double latitudeOrigin, double longitudeOrigin,
double falseEasting, double falseNorthing);
virtual CT *clone() const {return new LambertConic2(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
private:
LambertConic1 _lc1;
};
#endif // LAMBERTCONIC_H

View File

@ -1,15 +1,23 @@
#ifndef LATLON_H
#define LATLON_H
#include "projection.h"
#include "ct.h"
#include "angularunits.h"
class LatLon : public Projection
class LatLon : public CT
{
public:
LatLon(const AngularUnits &au) : _au(au) {}
virtual CT *clone() const {return new LatLon(*this);}
virtual QPointF ll2xy(const Coordinates &c) const
{return QPointF(c.lon(), c.lat());}
{return QPointF(_au.fromDegrees(c.lon()), _au.fromDegrees(c.lat()));}
virtual Coordinates xy2ll(const QPointF &p) const
{return Coordinates(p.x(), p.y());}
{return Coordinates(_au.toDegrees(p.x()), _au.toDegrees(p.y()));}
private:
AngularUnits _au;
};
#endif // LATLON_H

27
src/map/linearunits.cpp Normal file
View File

@ -0,0 +1,27 @@
#include "linearunits.h"
LinearUnits::LinearUnits(int code)
{
switch (code) {
case 9001:
_f = 1.0;
break;
case 9002:
_f = 0.3048;
break;
case 9003:
_f = 12.0 / 39.37;
break;
case 9040:
_f = 36.0 / 39.370147;
break;
default:
_f = NAN;
}
}
QDebug operator<<(QDebug dbg, const LinearUnits &lu)
{
dbg.nospace() << "LinearUnits(" << lu._f << ")";
return dbg.space();
}

36
src/map/linearunits.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef LINEARUNITS_H
#define LINEARUNITS_H
#include <cmath>
#include <QDebug>
#include <QPointF>
class LinearUnits
{
public:
LinearUnits() : _f(NAN) {}
LinearUnits(int code);
bool isNull() const {return std::isnan(_f);}
bool isValid() const {return !std::isnan(_f);}
double toMeters(double val) const {return val * _f;}
QPointF toMeters(const QPointF &p) const
{return QPointF(p.x() * _f, p.y() * _f);}
double fromMeters(double val) const {return val / _f;}
QPointF fromMeters(const QPointF &p) const
{return QPointF(p.x() / _f, p.y() /_f);}
friend bool operator==(const LinearUnits &lu1, const LinearUnits &lu2);
friend QDebug operator<<(QDebug dbg, const LinearUnits &lu);
private:
double _f;
};
inline bool operator==(const LinearUnits &lu1, const LinearUnits &lu2)
{return (lu1._f == lu2._f);}
QDebug operator<<(QDebug dbg, const LinearUnits &lu);
#endif // LINEARUNITS_H

265
src/map/mapfile.cpp Normal file
View File

@ -0,0 +1,265 @@
#include "utm.h"
#include "gcs.h"
#include "mapfile.h"
static double parameter(const QString &str, bool *res)
{
QString field = str.trimmed();
if (field.isEmpty()) {
*res = true;
return NAN;
}
return field.toDouble(res);
}
int MapFile::parse(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum)
{
bool res, r[8];
int ln = 1;
while (!device.atEnd()) {
QByteArray line = device.readLine();
if (ln == 1) {
if (!line.trimmed().startsWith("OziExplorer Map Data File"))
return ln;
} else if (ln == 2)
_name = line.trimmed();
else if (ln == 3)
_image = line.trimmed();
else if (ln == 5)
datum = line.split(',').at(0).trimmed();
else {
QList<QByteArray> list = line.split(',');
QString key(list.at(0).trimmed());
bool ll = true; bool pp = true;
if (key.startsWith("Point") && list.count() == 17
&& !list.at(2).trimmed().isEmpty()) {
CalibrationPoint p;
int x = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int y = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
int latd = list.at(6).trimmed().toInt(&res);
if (!res)
ll = false;
qreal latm = list.at(7).trimmed().toFloat(&res);
if (!res)
ll = false;
int lond = list.at(9).trimmed().toInt(&res);
if (!res)
ll = false;
qreal lonm = list.at(10).trimmed().toFloat(&res);
if (!res)
ll = false;
if (ll && list.at(8).trimmed() == "S") {
latd = -latd;
latm = -latm;
}
if (ll && list.at(11).trimmed() == "W") {
lond = -lond;
lonm = -lonm;
}
p.zone = list.at(13).trimmed().toInt(&res);
if (!res)
p.zone = 0;
qreal ppx = list.at(14).trimmed().toFloat(&res);
if (!res)
pp = false;
qreal ppy = list.at(15).trimmed().toFloat(&res);
if (!res)
pp = false;
if (list.at(16).trimmed() == "S")
p.zone = -p.zone;
p.rp.xy = QPoint(x, y);
if (ll) {
p.ll = Coordinates(lond + lonm/60.0, latd + latm/60.0);
if (p.ll.isValid())
points.append(p);
else
return ln;
} else if (pp) {
p.rp.pp = QPointF(ppx, ppy);
points.append(p);
} else
return ln;
} else if (key == "IWH") {
if (list.count() < 4)
return ln;
int w = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int h = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
_size = QSize(w, h);
} else if (key == "Map Projection") {
if (list.count() < 2)
return ln;
projection = list.at(1);
} else if (key == "Projection Setup") {
if (list.count() < 8)
return ln;
setup = Projection::Setup(
parameter(list[1], &r[1]), parameter(list[2], &r[2]),
parameter(list[3], &r[3]), parameter(list[4], &r[4]),
parameter(list[5], &r[5]), parameter(list[6], &r[6]),
parameter(list[7], &r[7]));
for (int i = 1; i < 8; i++)
if (!r[i])
return ln;
}
}
ln++;
}
return (ln == 1) ? 1 : 0;
}
bool MapFile::parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum)
{
int el;
if (!device.open(QIODevice::ReadOnly)) {
_errorString = QString("Error opening file: %1")
.arg(device.errorString());
return false;
}
if ((el = parse(device, points, projection, setup, datum))) {
_errorString = QString("Parse error on line %1").arg(el);
return false;
}
return true;
}
const GCS *MapFile::createGCS(const QString &datum)
{
const GCS *gcs;
if (!(gcs = GCS::gcs(datum)))
_errorString = QString("%1: Unknown datum").arg(datum);
return gcs;
}
bool MapFile::createProjection(const GCS *gcs, const QString &name,
const Projection::Setup &setup, QList<CalibrationPoint> &points)
{
if (name == "Mercator")
_projection = Projection(gcs, 1024, setup, 9001);
else if (name == "Transverse Mercator")
_projection = Projection(gcs, 9807, setup, 9001);
else if (name == "Latitude/Longitude")
_projection = Projection(gcs);
else if (name == "Lambert Conformal Conic")
_projection = Projection(gcs, 9802, setup, 9001);
else if (name == "Albers Equal Area")
_projection = Projection(gcs, 9822, setup, 9001);
else if (name == "(A)Lambert Azimuthual Equal Area")
_projection = Projection(gcs, 9820, setup, 9001);
else if (name == "(UTM) Universal Transverse Mercator") {
int zone;
if (points.first().zone)
zone = points.first().zone;
else if (!points.first().ll.isNull())
zone = UTM::zone(points.first().ll);
else {
_errorString = "Can not determine UTM zone";
return false;
}
_projection = Projection(gcs, 9807, UTM::setup(zone), 9001);
} else if (name == "(NZTM2) New Zealand TM 2000")
_projection = Projection(gcs, 9807, Projection::Setup(0, 173.0, 0.9996,
1600000, 10000000, NAN, NAN), 9001);
else if (name == "(BNG) British National Grid")
_projection = Projection(gcs, 9807, Projection::Setup(49, -2, 0.999601,
400000, -100000, NAN, NAN), 9001);
else if (name == "(IG) Irish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(53.5, -8,
1.000035, 200000, 250000, NAN, NAN), 9001);
else if (name == "(SG) Swedish Grid")
_projection = Projection(gcs, 9807, Projection::Setup(0, 15.808278, 1,
1500000, 0, NAN, NAN), 9001);
else if (name == "(I) France Zone I")
_projection = Projection(gcs, 9802, Projection::Setup(49.5, 2.337229,
NAN, 600000, 1200000, 48.598523, 50.395912), 9001);
else if (name == "(II) France Zone II")
_projection = Projection(gcs, 9802, Projection::Setup(46.8, 2.337229,
NAN, 600000, 2200000, 45.898919, 47.696014), 9001);
else if (name == "(III) France Zone III")
_projection = Projection(gcs, 9802, Projection::Setup(44.1, 2.337229,
NAN, 600000, 3200000, 43.199291, 44.996094), 9001);
else if (name == "(IV) France Zone IV")
_projection = Projection(gcs, 9802, Projection::Setup(42.165, 2.337229,
NAN, 234.358, 4185861.369, 41.560388, 42.767663), 9001);
else if (name == "(VICGRID) Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN,
2500000, 4500000, -36, -38), 9001);
else if (name == "(VG94) VICGRID94 Victoria Australia")
_projection = Projection(gcs, 9802, Projection::Setup(-37, 145, NAN,
2500000, 2500000, -36, -38), 9001);
else {
_errorString = QString("%1: Unknown map projection").arg(name);
return false;
}
return true;
}
bool MapFile::computeTransformation(QList<CalibrationPoint> &points)
{
QList<ReferencePoint> rp;
for (int i = 0; i < points.size(); i++) {
if (points.at(i).rp.pp.isNull())
points[i].rp.pp = _projection.ll2xy(points.at(i).ll);
rp.append(points.at(i).rp);
}
Transform t(rp);
if (t.isNull()) {
_errorString = t.errorString();
return false;
}
_transform = t.transform();
return true;
}
bool MapFile::load(QIODevice &file)
{
QList<CalibrationPoint> points;
QString ct, datum;
Projection::Setup setup;
const GCS *gcs;
if (!parseMapFile(file, points, ct, setup, datum))
return false;
if (!(gcs = createGCS(datum)))
return false;
if (!createProjection(gcs, ct, setup, points))
return false;
if (!computeTransformation(points))
return false;
return true;
}

49
src/map/mapfile.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef MAPFILE_H
#define MAPFILE_H
#include <QIODevice>
#include <QTransform>
#include "gcs.h"
#include "transform.h"
#include "projection.h"
class MapFile
{
public:
bool load(QIODevice &file);
const QString &errorString() const {return _errorString;}
const Projection &projection() const {return _projection;}
const QTransform &transform() const {return _transform;}
const QString &name() const {return _name;}
const QString &image() const {return _image;}
const QSize &size() const {return _size;}
private:
struct CalibrationPoint {
ReferencePoint rp;
Coordinates ll;
int zone;
};
int parse(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum);
bool parseMapFile(QIODevice &device, QList<CalibrationPoint> &points,
QString &projection, Projection::Setup &setup, QString &datum);
const GCS *createGCS(const QString &datum);
bool createProjection(const GCS *gcs, const QString &projection,
const Projection::Setup &setup, QList<CalibrationPoint> &points);
bool computeTransformation(QList<CalibrationPoint> &points);
QString _name;
QString _image;
QSize _size;
Projection _projection;
QTransform _transform;
QString _errorString;
};
#endif // MAPFILE_H

View File

@ -4,147 +4,140 @@
#include "atlas.h"
#include "offlinemap.h"
#include "onlinemap.h"
#include "mapsource.h"
#include "maplist.h"
#define ZOOM_MAX 18
#define ZOOM_MIN 2
Map *MapList::loadListEntry(const QByteArray &line)
bool MapList::loadSource(const QString &path, bool dir)
{
int max;
MapSource ms;
Map *map;
QList<QByteArray> list = line.split('\t');
if (list.size() < 2)
return 0;
QByteArray ba1 = list.at(0).trimmed();
QByteArray ba2 = list.at(1).trimmed();
if (ba1.isEmpty() || ba2.isEmpty())
return 0;
if (list.size() == 3) {
bool ok;
max = QString(list.at(2).trimmed()).toInt(&ok);
if (!ok)
return 0;
} else
max = ZOOM_MAX;
return new OnlineMap(QString::fromUtf8(ba1.data(), ba1.size()),
QString::fromLatin1(ba2.data(), ba2.size()), Range(ZOOM_MIN, max), this);
}
bool MapList::loadList(const QString &path)
{
QFile file(path);
QList<Map*> maps;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
if (!ms.loadFile(path, &map)) {
if (dir)
_errorString += path + ": " + ms.errorString() + "\n";
else
_errorString = ms.errorString();
return false;
}
int ln = 0;
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
Map *map = loadListEntry(line);
if (map)
maps.append(map);
else {
for (int i = 0; i < maps.count(); i++)
delete maps.at(i);
_errorString = QString("Invalid map list entry on line %1.")
.arg(QString::number(ln));
return false;
}
}
_maps += maps;
map->setParent(this);
_maps.append(map);
return true;
}
bool MapList::loadMap(const QString &path)
bool MapList::loadMap(const QString &path, bool dir)
{
OfflineMap *map = new OfflineMap(path, this);
if (map->isValid()) {
_maps.append(map);
return true;
} else {
_errorString = map->errorString();
if (dir)
_errorString += path + ": " + map->errorString() + "\n";
else
_errorString = map->errorString();
delete map;
return false;
}
}
bool MapList::loadTba(const QString &path)
bool MapList::loadAtlas(const QString &path, bool dir)
{
Atlas *atlas = new Atlas(path, this);
if (atlas->isValid()) {
_maps.append(atlas);
return true;
} else {
_errorString = atlas->errorString();
if (dir)
_errorString += path + ": " + atlas->errorString() + "\n";
else
_errorString = atlas->errorString();
delete atlas;
return false;
}
}
bool MapList::loadTar(const QString &path)
{
Atlas *atlas = new Atlas(path, this);
if (atlas->isValid()) {
_maps.append(atlas);
return true;
} else {
_errorString = atlas->errorString();
delete atlas;
OfflineMap *map = new OfflineMap(path, this);
if (map->isValid()) {
_maps.append(map);
return true;
} else {
qWarning("%s: %s", qPrintable(path), qPrintable(_errorString));
qWarning("%s: %s", qPrintable(path),
qPrintable(map->errorString()));
_errorString = "Not a map/atlas file";
delete map;
return false;
}
}
}
bool MapList::loadFile(const QString &path)
bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
{
QFileInfo fi(path);
QString suffix = fi.suffix().toLower();
if (suffix == "txt")
return loadList(path);
else if (suffix == "map")
return loadMap(path);
else if (suffix == "tba")
return loadTba(path);
else if (suffix == "tar")
return loadTar(path);
else {
_errorString = "Not a map/atlas file";
return false;
if (Atlas::isAtlas(path)) {
*atlas = true;
return loadAtlas(path, dir);
} else if (suffix == "xml") {
*atlas = false;
return loadSource(path, dir);
} else {
*atlas = false;
return loadMap(path, dir);
}
}
bool MapList::loadDirR(const QString &path)
{
QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
md.setSorting(QDir::DirsLast);
QFileInfoList ml = md.entryInfoList();
bool atlas, ret = true;
for (int i = 0; i < ml.size(); i++) {
const QFileInfo &fi = ml.at(i);
QString suffix = fi.suffix().toLower();
if (fi.isDir() && fi.fileName() != "set") {
if (!loadDirR(fi.absoluteFilePath()))
ret = false;
} else if (filter().contains("*." + suffix)) {
if (!loadFile(fi.absoluteFilePath(), &atlas, true))
ret = false;
if (atlas)
break;
}
}
return ret;
}
bool MapList::loadFile(const QString &path)
{
bool atlas;
_errorString.clear();
return loadFile(path, &atlas, false);
}
bool MapList::loadDir(const QString &path)
{
_errorString.clear();
return loadDirR(path);
}
void MapList::clear()
{
for (int i = 0; i < _maps.count(); i++)
delete _maps.at(i);
_maps.clear();
}
QString MapList::formats()
{
return tr("Map files (*.map *.tba *.tar)") + ";;"
+ tr("URL list files (*.txt)");
return
tr("Supported files") + " (*.map *.tar *.tba *.tif *.tiff *.xml);;"
+ tr("OziExplorer maps") + " (*.map);;"
+ tr("TrekBuddy maps/atlases") + " (*.tar *.tba);;"
+ tr("GeoTIFF images") + " (*.tif *.tiff);;"
+ tr("Online map sources") + " (*.xml)";
}
QStringList MapList::filter()
{
QStringList filter;
filter << "*.map" << "*.tba" << "*.tar" << "*.txt";
filter << "*.map" << "*.tba" << "*.tar" << "*.xml" << "*.tif" << "*.tiff";
return filter;
}

View File

@ -5,6 +5,8 @@
#include <QString>
#include "map.h"
class Tar;
class MapList : public QObject
{
Q_OBJECT
@ -13,6 +15,8 @@ public:
MapList(QObject *parent = 0) : QObject(parent) {}
bool loadFile(const QString &path);
bool loadDir(const QString &path);
void clear();
const QList<Map*> &maps() const {return _maps;}
const QString &errorString() const {return _errorString;}
@ -21,12 +25,14 @@ public:
static QStringList filter();
private:
bool loadFile(const QString &path, bool *atlas, bool dir);
bool loadDirR(const QString &path);
Map *loadListEntry(const QByteArray &line);
bool loadList(const QString &path);
bool loadMap(const QString &path);
bool loadTba(const QString &path);
bool loadTar(const QString &path);
bool loadSource(const QString &path, bool dir);
bool loadMap(const QString &path, bool dir);
bool loadAtlas(const QString &path, bool dir);
QList<Map*> _maps;
QString _errorString;

172
src/map/mapsource.cpp Normal file
View File

@ -0,0 +1,172 @@
#include <QFile>
#include <QXmlStreamReader>
#include "onlinemap.h"
#include "mapsource.h"
#define ZOOM_MAX 19
#define ZOOM_MIN 0
#define BOUNDS_LEFT -180
#define BOUNDS_TOP 85.0511
#define BOUNDS_RIGHT 180
#define BOUNDS_BOTTOM -85.0511
Range MapSource::zooms(QXmlStreamReader &reader)
{
const QXmlStreamAttributes &attr = reader.attributes();
int min, max;
bool res;
if (attr.hasAttribute("min")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
min = attr.value("min").toString().toInt(&res);
#else // QT_VERSION < 5
min = attr.value("min").toInt(&res);
#endif // QT_VERSION < 5
if (!res || (min < ZOOM_MIN || min > ZOOM_MAX)) {
reader.raiseError("Invalid minimal zoom level");
return Range();
}
} else
min = ZOOM_MIN;
if (attr.hasAttribute("max")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
max = attr.value("max").toString().toInt(&res);
#else // QT_VERSION < 5
max = attr.value("max").toInt(&res);
#endif // QT_VERSION < 5
if (!res || (max < ZOOM_MIN || max > ZOOM_MAX)) {
reader.raiseError("Invalid maximal zoom level");
return Range();
}
} else
max = ZOOM_MAX;
if (min > max || max < min) {
reader.raiseError("Invalid maximal/minimal zoom level combination");
return Range();
}
return Range(min, max);
}
RectC MapSource::bounds(QXmlStreamReader &reader)
{
const QXmlStreamAttributes &attr = reader.attributes();
double top, left, bottom, right;
bool res;
if (attr.hasAttribute("top")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
top = attr.value("top").toString().toDouble(&res);
#else // QT_VERSION < 5
top = attr.value("top").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (top < BOUNDS_BOTTOM || top > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds top value");
return RectC();
}
} else
top = BOUNDS_TOP;
if (attr.hasAttribute("bottom")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
bottom = attr.value("bottom").toString().toDouble(&res);
#else // QT_VERSION < 5
bottom = attr.value("bottom").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (bottom < BOUNDS_BOTTOM || bottom > BOUNDS_TOP)) {
reader.raiseError("Invalid bounds bottom value");
return RectC();
}
} else
bottom = BOUNDS_BOTTOM;
if (attr.hasAttribute("left")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
left = attr.value("left").toString().toDouble(&res);
#else // QT_VERSION < 5
left = attr.value("left").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (left < BOUNDS_LEFT || left > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds left value");
return RectC();
}
} else
left = BOUNDS_LEFT;
if (attr.hasAttribute("right")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
right = attr.value("right").toString().toDouble(&res);
#else // QT_VERSION < 5
right = attr.value("right").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (right < BOUNDS_LEFT || right > BOUNDS_RIGHT)) {
reader.raiseError("Invalid bounds right value");
return RectC();
}
} else
right = BOUNDS_RIGHT;
if (bottom > top || top < bottom) {
reader.raiseError("Invalid bottom/top bounds combination");
return RectC();
}
if (left > right || right < left) {
reader.raiseError("Invalid left/right bounds combination");
return RectC();
}
return RectC(Coordinates(left, top), Coordinates(right, bottom));
}
void MapSource::map(QXmlStreamReader &reader, Map **map)
{
QString name, url;
Range z(ZOOM_MIN, ZOOM_MAX);
RectC b(Coordinates(BOUNDS_LEFT, BOUNDS_TOP),
Coordinates(BOUNDS_RIGHT, BOUNDS_BOTTOM));
while (reader.readNextStartElement()) {
if (reader.name() == "name")
name = reader.readElementText();
else if (reader.name() == "url")
url = reader.readElementText();
else if (reader.name() == "zoom") {
z = zooms(reader);
reader.skipCurrentElement();
} else if (reader.name() == "bounds") {
b = bounds(reader);
reader.skipCurrentElement();
} else
reader.skipCurrentElement();
}
*map = reader.error() ? 0 : new OnlineMap(name, url, z, b);
}
bool MapSource::loadFile(const QString &path, Map **map)
{
QFile file(path);
QXmlStreamReader reader;
if (!file.open(QFile::ReadOnly | QFile::Text)) {
_errorString = file.errorString();
return false;
}
reader.setDevice(&file);
if (reader.readNextStartElement()) {
if (reader.name() == "map")
MapSource::map(reader, map);
else
reader.raiseError("Not an online map source file");
}
_errorString = reader.error() ? QString("%1: %2").arg(reader.lineNumber())
.arg(reader.errorString()) : QString();
return !reader.error();
}

25
src/map/mapsource.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef MAPSOURCE_H
#define MAPSOURCE_H
#include <QList>
#include "common/range.h"
#include "common/rectc.h"
class Map;
class QXmlStreamReader;
class MapSource
{
public:
bool loadFile(const QString &path, Map **map);
const QString &errorString() const {return _errorString;}
private:
RectC bounds(QXmlStreamReader &reader);
Range zooms(QXmlStreamReader &reader);
void map(QXmlStreamReader &reader, Map **map);
QString _errorString;
};
#endif // MAPSOURCE_H

View File

@ -1,11 +1,13 @@
#ifndef MERCATOR_H
#define MERCATOR_H
#include "projection.h"
#include "ct.h"
class Mercator : public Projection
class Mercator : public CT
{
public:
virtual CT *clone() const {return new Mercator(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
};

View File

@ -1,7 +0,0 @@
#include <QRectF>
inline QRectF scaled(const QRectF &rect, qreal factor)
{
return QRectF(QPointF(rect.left() * factor, rect.top() * factor),
QSizeF(rect.width() * factor, rect.height() * factor));
}

View File

@ -9,297 +9,20 @@
#include <QPixmapCache>
#include "common/coordinates.h"
#include "common/rectc.h"
#include "datum.h"
#include "utm.h"
#include "matrix.h"
#include "ozf.h"
#include "mapfile.h"
#include "geotiff.h"
#include "offlinemap.h"
int OfflineMap::parse(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, Projection::Setup &setup, QString &datum)
void OfflineMap::computeResolution()
{
bool res;
int ln = 1;
Coordinates tl = xy2ll((bounds().topLeft()));
Coordinates br = xy2ll(bounds().bottomRight());
while (!device.atEnd()) {
QByteArray line = device.readLine();
qreal ds = tl.distanceTo(br);
qreal ps = QLineF(bounds().topLeft(), bounds().bottomRight()).length();
if (ln == 1) {
if (!line.trimmed().startsWith("OziExplorer Map Data File"))
return ln;
} else if (ln == 2)
_name = line.trimmed();
else if (ln == 3)
_imgPath = line.trimmed();
else if (ln == 5)
datum = line.split(',').at(0).trimmed();
else {
QList<QByteArray> list = line.split(',');
QString key(list.at(0).trimmed());
bool ll = true; bool pp = true;
if (key.startsWith("Point") && list.count() == 17
&& !list.at(2).trimmed().isEmpty()) {
int x = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int y = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
int latd = list.at(6).trimmed().toInt(&res);
if (!res)
ll = false;
qreal latm = list.at(7).trimmed().toFloat(&res);
if (!res)
ll = false;
int lond = list.at(9).trimmed().toInt(&res);
if (!res)
ll = false;
qreal lonm = list.at(10).trimmed().toFloat(&res);
if (!res)
ll = false;
if (ll && list.at(8).trimmed() == "S") {
latd = -latd;
latm = -latm;
}
if (ll && list.at(11).trimmed() == "W") {
lond = -lond;
lonm = -lonm;
}
setup.zone = list.at(13).trimmed().toInt(&res);
if (!res)
setup.zone = 0;
qreal ppx = list.at(14).trimmed().toFloat(&res);
if (!res)
pp = false;
qreal ppy = list.at(15).trimmed().toFloat(&res);
if (!res)
pp = false;
if (list.at(16).trimmed() == "S")
setup.zone = -setup.zone;
ReferencePoint p;
p.xy = QPoint(x, y);
if (ll) {
p.ll = Coordinates(lond + lonm/60.0, latd + latm/60.0);
if (p.ll.isValid())
points.append(p);
else
return ln;
} else if (pp) {
p.pp = QPointF(ppx, ppy);
points.append(p);
} else
return ln;
} else if (key == "IWH") {
if (list.count() < 4)
return ln;
int w = list.at(2).trimmed().toInt(&res);
if (!res)
return ln;
int h = list.at(3).trimmed().toInt(&res);
if (!res)
return ln;
_size = QSize(w, h);
} else if (key == "Map Projection") {
if (list.count() < 2)
return ln;
projection = list.at(1);
} else if (key == "Projection Setup") {
if (list.count() < 8)
return ln;
setup.latitudeOrigin = list.at(1).trimmed().toFloat(&res);
if (!res)
setup.latitudeOrigin = 0;
setup.longitudeOrigin = list.at(2).trimmed().toFloat(&res);
if (!res)
setup.longitudeOrigin = 0;
setup.scale = list.at(3).trimmed().toFloat(&res);
if (!res)
setup.scale = 1.0;
setup.falseEasting = list.at(4).trimmed().toFloat(&res);
if (!res)
setup.falseEasting = 0;
setup.falseNorthing = list.at(5).trimmed().toFloat(&res);
if (!res)
setup.falseNorthing = 0;
setup.standardParallel1 = list.at(6).trimmed().toFloat(&res);
if (!res)
setup.standardParallel1 = 0;
setup.standardParallel2 = list.at(7).trimmed().toFloat(&res);
if (!res)
setup.standardParallel2 = 0;
}
}
ln++;
}
if (!setup.zone && !points.first().ll.isNull())
setup.zone = UTM::zone(points.first().ll);
return 0;
}
bool OfflineMap::parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, Projection::Setup &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 Projection::Setup &setup,
QList<ReferencePoint> &points)
{
if (points.count() < 2) {
_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;
}
_projection = Projection::projection(projection, d.ellipsoid(), setup);
if (!_projection) {
_errorString = Projection::errorString();
return false;
}
for (int i = 0; i < points.size(); i++) {
if (points.at(i).ll.isNull())
points[i].ll = d.toWGS84(_projection->xy2ll(points.at(i).pp));
else
points[i].ll = d.toWGS84(points[i].ll);
}
return true;
}
bool OfflineMap::simpleTransformation(const QList<ReferencePoint> &points)
{
if (points.at(0).xy.x() == points.at(1).xy.x()
|| points.at(0).xy.y() == points.at(1).xy.y()) {
_errorString = "Invalid reference points tuple";
return false;
}
QPointF p0(_projection->ll2xy(points.at(0).ll));
QPointF p1(_projection->ll2xy(points.at(1).ll));
qreal dX, dY, lat0, lon0;
dX = (p0.x() - p1.x()) / (points.at(0).xy.x() - points.at(1).xy.x());
dY = (p1.y() - p0.y()) / (points.at(1).xy.y() - points.at(0).xy.y());
lat0 = p0.y() - points.at(0).xy.y() * dY;
lon0 = p1.x() - points.at(1).xy.x() * dX;
_transform = QTransform(1.0/dX, 0, 0, 1.0/dY, -lon0/dX, -lat0/dY);
_inverted = _transform.inverted();
return true;
}
bool OfflineMap::affineTransformation(const QList<ReferencePoint> &points)
{
Matrix c(3, 2);
c.zeroize();
for (size_t i = 0; i < c.h(); i++) {
for (size_t j = 0; j < c.w(); j++) {
for (int k = 0; k < points.size(); k++) {
double f[3], t[2];
QPointF p = _projection->ll2xy(points.at(k).ll);
f[0] = p.x();
f[1] = p.y();
f[2] = 1.0;
t[0] = points.at(k).xy.x();
t[1] = points.at(k).xy.y();
c.m(i,j) += f[i] * t[j];
}
}
}
Matrix Q(3, 3);
Q.zeroize();
for (int qi = 0; qi < points.size(); qi++) {
double v[3];
QPointF p = _projection->ll2xy(points.at(qi).ll);
v[0] = p.x();
v[1] = p.y();
v[2] = 1.0;
for (size_t i = 0; i < Q.h(); i++)
for (size_t j = 0; j < Q.w(); j++)
Q.m(i,j) += v[i] * v[j];
}
Matrix M = Q.augemented(c);
if (!M.eliminate()) {
_errorString = "Singular transformation matrix";
return false;
}
_transform = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3),
M.m(2,4));
_inverted = _transform.inverted();
return true;
}
bool OfflineMap::computeTransformation(const QList<ReferencePoint> &points)
{
Q_ASSERT(points.size() >= 2);
if (points.size() == 2)
return simpleTransformation(points);
else
return affineTransformation(points);
}
bool OfflineMap::computeResolution(QList<ReferencePoint> &points)
{
Q_ASSERT(points.count() >= 2);
int maxLon = 0, minLon = 0, maxLat = 0, minLat = 0;
qreal dLon, pLon, dLat, pLat;
for (int i = 1; i < points.size(); i++) {
if (points.at(i).ll.lon() < points.at(minLon).ll.lon())
minLon = i;
if (points.at(i).ll.lon() > points.at(maxLon).ll.lon())
maxLon = i;
if (points.at(i).ll.lat() < points.at(minLat).ll.lat())
minLat = i;
if (points.at(i).ll.lat() > points.at(maxLat).ll.lat())
maxLat = i;
}
dLon = points.at(minLon).ll.distanceTo(points.at(maxLon).ll);
pLon = QLineF(points.at(minLon).xy, points.at(maxLon).xy).length();
dLat = points.at(minLat).ll.distanceTo(points.at(maxLat).ll);
pLat = QLineF(points.at(minLat).xy, points.at(maxLat).xy).length();
_resolution = (dLon/pLon + dLat/pLat) / 2.0;
return true;
_resolution = ds/ps;
}
bool OfflineMap::getImageInfo(const QString &path)
@ -384,16 +107,11 @@ bool OfflineMap::totalSizeSet()
OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
: Map(parent)
{
QList<ReferencePoint> points;
QString proj, datum;
Projection::Setup setup;
QFileInfo fi(fileName);
QString suffix = fi.suffix().toLower();
_valid = false;
_img = 0;
_projection = 0;
_resolution = 0.0;
_zoom = 0;
_scale = QPointF(1.0, 1.0);
@ -411,23 +129,46 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
return;
}
QBuffer mapFile(&ba);
if (!parseMapFile(mapFile, points, proj, setup, datum))
MapFile mf;
if (!mf.load(mapFile)) {
_errorString = mf.errorString();
return;
} else if (suffix =="map") {
} else {
_name = mf.name();
_size = mf.size();
_imgPath = mf.image();
_projection = mf.projection();
_transform = mf.transform();
}
} else if (suffix == "map") {
MapFile mf;
QFile mapFile(fileName);
if (!parseMapFile(mapFile, points, proj, setup, datum))
if (!mf.load(mapFile)) {
_errorString = mf.errorString();
return;
} else {
_name = mf.name();
_size = mf.size();
_imgPath = mf.image();
_projection = mf.projection();
_transform = mf.transform();
}
} else if (suffix == "tif" || suffix == "tiff") {
GeoTIFF gt;
if (!gt.load(fileName)) {
_errorString = gt.errorString();
return;
} else {
_name = fi.fileName();
_imgPath = fileName;
_projection = gt.projection();
_transform = gt.transform();
}
} else {
_errorString = "Not a map file";
return;
}
if (!createProjection(datum, proj, setup, points))
return;
if (!computeTransformation(points))
return;
computeResolution(points);
if (_tar.isOpen()) {
if (!totalSizeSet())
return;
@ -448,20 +189,20 @@ OfflineMap::OfflineMap(const QString &fileName, QObject *parent)
}
}
_inverted = _transform.inverted();
computeResolution();
_valid = true;
}
OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
: Map(parent)
{
QList<ReferencePoint> points;
QString proj, datum;
Projection::Setup setup;
QFileInfo fi(fileName);
MapFile mf;
_valid = false;
_img = 0;
_projection = 0;
_resolution = 0.0;
_zoom = 0;
_scale = QPointF(1.0, 1.0);
@ -477,28 +218,26 @@ OfflineMap::OfflineMap(const QString &fileName, Tar &tar, QObject *parent)
}
QBuffer buffer(&ba);
if (!parseMapFile(buffer, points, proj, setup, datum))
if (!mf.load(buffer)) {
_errorString = mf.errorString();
return;
if (!createProjection(datum, proj, setup, points))
return;
if (!totalSizeSet())
return;
if (!computeTransformation(points))
return;
computeResolution(points);
}
_name = mf.name();
_size = mf.size();
_projection = mf.projection();
_transform = mf.transform();
_inverted = _transform.inverted();
computeResolution();
_tarPath = fi.absolutePath() + "/" + fi.completeBaseName() + ".tar";
_imgPath = QString();
_valid = true;
}
OfflineMap::~OfflineMap()
{
if (_img)
delete _img;
if (_projection)
delete _projection;
delete _img;
}
void OfflineMap::load()
@ -522,10 +261,8 @@ void OfflineMap::load()
void OfflineMap::unload()
{
if (_img) {
delete _img;
_img = 0;
}
delete _img;
_img = 0;
}
void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect)
@ -599,13 +336,9 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect)
void OfflineMap::drawImage(QPainter *painter, const QRectF &rect)
{
if (!_img || _img->isNull())
painter->fillRect(rect, _backgroundColor);
else {
QRect r(rect.toRect());
painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(),
r.width(), r.height());
}
QRect r(rect.toRect());
painter->drawImage(r.left(), r.top(), *_img, r.left(), r.top(),
r.width(), r.height());
}
void OfflineMap::draw(QPainter *painter, const QRectF &rect)
@ -614,26 +347,28 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect)
drawOZF(painter, rect);
else if (_tileSize.isValid())
drawTiled(painter, rect);
else
else if (_img && !_img->isNull())
drawImage(painter, rect);
else
painter->fillRect(rect, _backgroundColor);
}
QPointF OfflineMap::ll2xy(const Coordinates &c)
{
if (_ozf.isOpen()) {
QPointF p(_transform.map(_projection->ll2xy(c)));
QPointF p(_transform.map(_projection.ll2xy(c)));
return QPointF(p.x() * _scale.x(), p.y() * _scale.y());
} else
return _transform.map(_projection->ll2xy(c));
return _transform.map(_projection.ll2xy(c));
}
Coordinates OfflineMap::xy2ll(const QPointF &p)
{
if (_ozf.isOpen()) {
return _projection->xy2ll(_inverted.map(QPointF(p.x() / _scale.x(),
return _projection.xy2ll(_inverted.map(QPointF(p.x() / _scale.x(),
p.y() / _scale.y())));
} else
return _projection->xy2ll(_inverted.map(p));
return _projection.xy2ll(_inverted.map(p));
}
QRectF OfflineMap::bounds() const
@ -660,8 +395,8 @@ qreal OfflineMap::zoomFit(const QSize &size, const RectC &br)
if (!br.isValid())
rescale(0);
else {
QRect sbr(QRectF(_transform.map(_projection->ll2xy(br.topLeft())),
_transform.map(_projection->ll2xy(br.bottomRight())))
QRect sbr(QRectF(_transform.map(_projection.ll2xy(br.topLeft())),
_transform.map(_projection.ll2xy(br.bottomRight())))
.toRect().normalized());
for (int i = 0; i < _ozf.zooms(); i++) {

View File

@ -2,8 +2,9 @@
#define OFFLINEMAP_H
#include <QTransform>
#include "common/coordinates.h"
#include "projection.h"
#include "transform.h"
#include "linearunits.h"
#include "map.h"
#include "tar.h"
#include "ozf.h"
@ -43,47 +44,28 @@ public:
const QString &errorString() const {return _errorString;}
QPointF ll2pp(const Coordinates &c) const
{return _projection->ll2xy(c);}
{return _projection.ll2xy(c);}
QPointF xy2pp(const QPointF &p) const
{return _inverted.map(p);}
QPointF pp2xy(const QPointF &p) const
{return _transform.map(p);}
private:
struct ReferencePoint {
QPoint xy;
Coordinates ll;
QPointF pp;
};
int parse(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, Projection::Setup &setup, QString &datum);
bool parseMapFile(QIODevice &device, QList<ReferencePoint> &points,
QString &projection, Projection::Setup &setup, QString &datum);
bool totalSizeSet();
bool createProjection(const QString &datum, const QString &projection,
const Projection::Setup &setup, QList<ReferencePoint> &points);
bool simpleTransformation(const QList<ReferencePoint> &points);
bool affineTransformation(const QList<ReferencePoint> &points);
bool computeTransformation(const QList<ReferencePoint> &points);
bool computeResolution(QList<ReferencePoint> &points);
bool getTileInfo(const QStringList &tiles, const QString &path = QString());
bool getImageInfo(const QString &path);
bool totalSizeSet();
void drawTiled(QPainter *painter, const QRectF &rect);
void drawOZF(QPainter *painter, const QRectF &rect);
void drawImage(QPainter *painter, const QRectF &rect);
void computeResolution();
void rescale(int zoom);
QString _name;
bool _valid;
QString _errorString;
QSize _size;
Projection *_projection;
Projection _projection;
QTransform _transform, _inverted;
qreal _resolution;
OZF _ozf;
Tar _tar;
@ -92,9 +74,14 @@ private:
QString _imgPath;
QSize _tileSize;
QString _tileName;
QSize _size;
int _zoom;
qreal _resolution;
QPointF _scale;
bool _valid;
QString _errorString;
};
#endif // OFFLINEMAP_H

View File

@ -7,7 +7,6 @@
#include "mercator.h"
#include "downloader.h"
#include "config.h"
#include "misc.h"
#include "onlinemap.h"
@ -47,13 +46,11 @@ static bool loadTileFile(Tile &tile, const QString &file)
Downloader *OnlineMap::downloader;
OnlineMap::OnlineMap(const QString &name, const QString &url,
const Range &zooms, QObject *parent) : Map(parent)
const Range &zooms, const RectC &bounds, QObject *parent)
: Map(parent), _name(name), _url(url), _zooms(zooms), _bounds(bounds)
{
_name = name;
_url = url;
_block = false;
_zooms = zooms;
_zoom = zooms.max();
_zoom = _zooms.max();
QString path = TILES_DIR + QString("/") + name;
if (!QDir().mkpath(path))
@ -168,8 +165,7 @@ void OnlineMap::clearCache()
QRectF OnlineMap::bounds() const
{
return scaled(QRectF(QPointF(-180, -180), QSizeF(360, 360)),
1.0/zoom2scale(_zoom));
return QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight()));
}
int OnlineMap::limitZoom(int zoom) const
@ -253,14 +249,14 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect)
}
}
QPointF OnlineMap::ll2xy(const Coordinates &c)
QPointF OnlineMap::ll2xy(const Coordinates &c) const
{
qreal scale = zoom2scale(_zoom);
QPointF m = Mercator().ll2xy(c);
return QPointF(m.x() / scale, m.y() / -scale);
}
Coordinates OnlineMap::xy2ll(const QPointF &p)
Coordinates OnlineMap::xy2ll(const QPointF &p) const
{
qreal scale = zoom2scale(_zoom);
QPointF m(p.x() * scale, -p.y() * scale);

View File

@ -1,7 +1,9 @@
#ifndef ONLINEMAP_H
#define ONLINEMAP_H
#include "common/coordinates.h"
#include "common/range.h"
#include "common/rectc.h"
#include "map.h"
#include "tile.h"
@ -13,7 +15,7 @@ class OnlineMap : public Map
public:
OnlineMap(const QString &name, const QString &url, const Range &zooms,
QObject *parent = 0);
const RectC &bounds, QObject *parent = 0);
const QString &name() const {return _name;}
@ -26,8 +28,10 @@ public:
qreal zoomIn();
qreal zoomOut();
QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p);
QPointF ll2xy(const Coordinates &c)
{return static_cast<const OnlineMap &>(*this).ll2xy(c);}
Coordinates xy2ll(const QPointF &p)
{return static_cast<const OnlineMap &>(*this).xy2ll(p);}
void draw(QPainter *painter, const QRectF &rect);
@ -44,6 +48,9 @@ private slots:
void emitLoaded();
private:
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
void fillTile(Tile &tile);
QString tileUrl(const Tile &tile) const;
QString tileFile(const Tile &tile) const;
@ -51,10 +58,11 @@ private:
void loadTilesSync(QList<Tile> &list);
int limitZoom(int zoom) const;
Range _zooms;
int _zoom;
QString _name;
QString _url;
Range _zooms;
RectC _bounds;
int _zoom;
bool _block;
static Downloader *downloader;

195
src/map/pcs.cpp Normal file
View File

@ -0,0 +1,195 @@
#include <QFile>
#include "angularunits.h"
#include "pcs.h"
class PCS::Entry {
public:
Entry(int id, int proj, const PCS &pcs) : _id(id), _proj(proj), _pcs(pcs) {}
int id() const {return _id;}
int proj() const {return _proj;}
const PCS &pcs() const {return _pcs;}
private:
int _id, _proj;
PCS _pcs;
};
QList<PCS::Entry> PCS::_pcss;
static bool parameter(int key, double val, int units, Projection::Setup &setup)
{
switch (key) {
case 8801:
case 8821:
{AngularUnits au(units);
if (au.isNull())
return false;
setup.setLatitudeOrigin(au.toDegrees(val));}
return true;
case 8802:
case 8822:
{AngularUnits au(units);
if (au.isNull())
return false;
setup.setLongitudeOrigin(au.toDegrees(val));}
return true;
case 8805:
setup.setScale(val);
return true;
case 8806:
case 8826:
{LinearUnits lu(units);
if (lu.isNull())
return false;
setup.setFalseEasting(lu.toMeters(val));}
return true;
case 8807:
case 8827:
{LinearUnits lu(units);
if (lu.isNull())
return false;
setup.setFalseNorthing(lu.toMeters(val));}
return true;
case 8823:
{AngularUnits au(units);
if (au.isNull())
return false;
setup.setStandardParallel1(au.toDegrees(val));}
return true;
case 8824:
{AngularUnits au(units);
if (au.isNull())
return false;
setup.setStandardParallel2(au.toDegrees(val));}
return true;
default:
return false;
}
}
static int projectionSetup(const QList<QByteArray> &list,
Projection::Setup &setup)
{
bool r1, r2, r3;
for (int i = 6; i < 24; i += 3) {
QString ks = list[i].trimmed();
if (ks.isEmpty())
break;
int key = ks.toInt(&r1);
double val = list[i+1].trimmed().toDouble(&r2);
int un = list[i+2].trimmed().toInt(&r3);
if (!r1 || !r2 || !r3)
return (i - 6)/3 + 1;
if (!parameter(key, val, un, setup))
return (i - 6)/3 + 1;
}
return 0;
}
const PCS *PCS::pcs(int id)
{
for (int i = 0; i < _pcss.size(); i++)
if (_pcss.at(i).id() == id)
return &(_pcss.at(i).pcs());
return 0;
}
const PCS *PCS::pcs(const GCS *gcs, int proj)
{
for (int i = 0; i < _pcss.size(); i++)
if (_pcss.at(i).proj() == proj && *(_pcss.at(i).pcs().gcs()) == *gcs)
return &(_pcss.at(i).pcs());
return 0;
}
void PCS::loadList(const QString &path)
{
QFile file(path);
bool res;
int ln = 0, pn;
const GCS *gcs;
if (!file.open(QFile::ReadOnly)) {
qWarning("Error opening PCS file: %s: %s", qPrintable(path),
qPrintable(file.errorString()));
return;
}
while (!file.atEnd()) {
ln++;
QByteArray line = file.readLine();
QList<QByteArray> list = line.split(',');
if (list.size() != 24) {
qWarning("%s: %d: Format error", qPrintable(path), ln);
continue;
}
int id = list[1].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid PCS code", qPrintable(path), ln);
continue;
}
int gcsid = list[2].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid GCS code", qPrintable(path), ln);
continue;
}
int proj = list[3].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid projection code", qPrintable(path), ln);
continue;
}
int units = list[4].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid linear units code", qPrintable(path), ln);
continue;
}
int transform = list[5].trimmed().toInt(&res);
if (!res) {
qWarning("%s: %d: Invalid coordinate transformation code",
qPrintable(path), ln);
continue;
}
if (LinearUnits(units).isNull()) {
qWarning("%s: %d: Unknown linear units code", qPrintable(path), ln);
continue;
}
if (Projection::Method(transform).isNull()) {
qWarning("%s: %d: Unknown coordinate transformation code",
qPrintable(path), ln);
continue;
}
if (!(gcs = GCS::gcs(gcsid))) {
qWarning("%s: %d: Unknown GCS code", qPrintable(path), ln);
continue;
}
Projection::Setup setup;
if ((pn = projectionSetup(list, setup))) {
qWarning("%s: %d: Invalid projection parameter #%d",
qPrintable(path), ln, pn);
continue;
}
PCS pcs(gcs, transform, setup, units);
_pcss.append(Entry(id, proj, pcs));
}
}
QDebug operator<<(QDebug dbg, const PCS &pcs)
{
dbg.nospace() << "PCS(" << *pcs.gcs() << ", " << pcs.method() << ", "
<< pcs.units() << ", " << pcs.setup() << ")";
return dbg.space();
}

48
src/map/pcs.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef PCS_H
#define PCS_H
#include <QDebug>
#include <QList>
#include "gcs.h"
#include "linearunits.h"
#include "projection.h"
class PCS
{
public:
PCS() : _gcs(0) {}
PCS(const GCS *gcs, const Projection::Method &method,
const Projection::Setup &setup, const LinearUnits &units)
: _gcs(gcs), _method(method), _setup(setup), _units(units) {}
PCS(const GCS *gcs, int proj);
const GCS *gcs() const {return _gcs;}
const Projection::Method &method() const {return _method;}
const Projection::Setup &setup() const {return _setup;}
const LinearUnits &units() const {return _units;}
bool isNull() const
{return (_gcs->isNull() && _units.isNull() && _method.isNull()
&& _setup.isNull());}
bool isValid() const
{return (_gcs->isValid() && _units.isValid() && _method.isValid());}
static void loadList(const QString &path);
static const PCS *pcs(int id);
static const PCS *pcs(const GCS *gcs, int proj);
private:
class Entry;
const GCS *_gcs;
Projection::Method _method;
Projection::Setup _setup;
LinearUnits _units;
static QList<Entry> _pcss;
static GCS _nullGCS;
};
QDebug operator<<(QDebug dbg, const PCS &pcs);
#endif // PCS_H

73
src/map/primemeridian.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "primemeridian.h"
static double shift(double lon, double offset)
{
double ret = lon + offset;
if (ret > 180.0)
ret -= 360.0;
if (ret < -180)
ret += 360.0;
return ret;
}
PrimeMeridian::PrimeMeridian(int code)
{
switch (code) {
case 8901:
_pm = 0.0;
break;
case 8902:
_pm = -9.1319061111;
break;
case 8903:
_pm = 2.3372291666;
break;
case 8904:
_pm = -74.0809166666;
break;
case 8905:
_pm = -3.6879388888;
break;
case 8906:
_pm = 12.4523333333;
break;
case 8907:
_pm = 7.4395833333;
break;
case 8908:
_pm = 106.8077194444;
break;
case 8909:
_pm = -17.6666666666;
break;
case 8910:
_pm = 4.3679750000;
break;
case 8911:
_pm = 18.0582777777;
break;
case 8913:
_pm = 10.7229166666;
break;
default:
_pm = NAN;
}
}
double PrimeMeridian::toGreenwich(double val) const
{
return shift(val, _pm);
}
double PrimeMeridian::fromGreenwich(double val) const
{
return shift(val, -_pm);
}
QDebug operator<<(QDebug dbg, const PrimeMeridian &pm)
{
dbg.nospace() << "PrimeMeridian(" << pm._pm << ")";
return dbg.space();
}

31
src/map/primemeridian.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef PRIMEMERIDIAN_H
#define PRIMEMERIDIAN_H
#include <cmath>
#include <QDebug>
class PrimeMeridian
{
public:
PrimeMeridian() : _pm(NAN) {}
PrimeMeridian(int code);
bool isNull() const {return std::isnan(_pm);}
bool isValid() const {return !std::isnan(_pm);}
double toGreenwich(double val) const;
double fromGreenwich(double val) const;
friend bool operator==(const PrimeMeridian &pm1, const PrimeMeridian &pm2);
friend QDebug operator<<(QDebug dbg, const PrimeMeridian &pm);
private:
double _pm;
};
inline bool operator==(const PrimeMeridian &pm1, const PrimeMeridian &pm2)
{return (pm1._pm == pm2._pm);}
QDebug operator<<(QDebug dbg, const PrimeMeridian &pm);
#endif // PRIMEMERIDIAN_H

View File

@ -1,89 +1,121 @@
#include "latlon.h"
#include "datum.h"
#include "mercator.h"
#include "transversemercator.h"
#include "utm.h"
#include "lambertconic.h"
#include "albersequal.h"
#include "lambertazimuthal.h"
#include "latlon.h"
#include "gcs.h"
#include "projection.h"
QString Projection::_errorString;
Projection *Projection::projection(const QString &name,
const Ellipsoid &ellipsoid, const Setup &setup)
Projection::Method::Method(int id)
{
if (setup.latitudeOrigin < -90.0 || setup.latitudeOrigin > 90.0
|| setup.longitudeOrigin < -180.0 || setup.longitudeOrigin > 180.0
|| setup.standardParallel1 < -90.0 || setup.standardParallel1 > 90.0
|| setup.standardParallel2 < -90.0 || setup.standardParallel2 > 90.0) {
_errorString = "Invalid projection setup";
return 0;
}
if (name == "Mercator")
return new Mercator();
else if (name == "Transverse Mercator")
return new TransverseMercator(ellipsoid,
setup.latitudeOrigin, setup.longitudeOrigin, setup.scale,
setup.falseEasting, setup.falseNorthing);
else if (name == "Latitude/Longitude")
return new LatLon();
else if (name == "Lambert Conformal Conic")
return new LambertConic(ellipsoid,
setup.standardParallel1, setup.standardParallel2,
setup.latitudeOrigin, setup.longitudeOrigin, setup.scale,
setup.falseEasting, setup.falseNorthing);
else if (name == "Albers Equal Area")
return new AlbersEqual(ellipsoid, setup.standardParallel1,
setup.standardParallel2, setup.latitudeOrigin, setup.longitudeOrigin,
setup.falseEasting, setup.falseNorthing);
else if (name == "(A)Lambert Azimuthual Equal Area")
return new LambertAzimuthal(ellipsoid, setup.latitudeOrigin,
setup.longitudeOrigin, setup.falseEasting, setup.falseNorthing);
else if (name == "(UTM) Universal Transverse Mercator") {
if (setup.zone)
return new UTM(ellipsoid, setup.zone);
else {
_errorString = "Can not determine UTM zone";
return 0;
}
} else if (name == "(NZTM2) New Zealand TM 2000")
return new TransverseMercator(ellipsoid, 0, 173.0, 0.9996,
1600000, 10000000);
else if (name == "(BNG) British National Grid")
return new TransverseMercator(ellipsoid, 49, -2, 0.999601,
400000, -100000);
else if (name == "(IG) Irish Grid")
return new TransverseMercator(ellipsoid, 53.5, -8, 1.000035,
200000, 250000);
else if (name == "(SG) Swedish Grid")
return new TransverseMercator(ellipsoid, 0, 15.808278, 1,
1500000, 0);
else if (name == "(I) France Zone I")
return new LambertConic(ellipsoid, 48.598523, 50.395912,
49.5, 2.337229, 1 /*0.99987734*/, 600000, 1200000);
else if (name == "(II) France Zone II")
return new LambertConic(ellipsoid, 45.898919, 47.696014,
46.8, 2.337229, 1 /*0.99987742*/, 600000, 2200000);
else if (name == "(III) France Zone III")
return new LambertConic(ellipsoid, 43.199291, 44.996094,
44.1, 2.337229, 1 /*0.99987750*/, 600000, 3200000);
else if (name == "(IV) France Zone IV")
return new LambertConic(ellipsoid, 41.560388, 42.767663,
42.165, 2.337229, 1 /*0.99994471*/, 234.358, 4185861.369);
else if (name == "(VICGRID) Victoria Australia")
return new LambertConic(ellipsoid, -36, -38, -37, 145, 1,
2500000, 4500000);
else if (name == "(VG94) VICGRID94 Victoria Australia")
return new LambertConic(ellipsoid, -36, -38, -37, 145, 1,
2500000, 2500000);
else {
_errorString = QString("%1: Unknown map projection").arg(name);
return 0;
switch (id) {
case 1024:
case 9801:
case 9802:
case 9807:
case 9820:
case 9822:
case 9841:
_id = id;
break;
default:
_id = 0;
}
}
const QString &Projection::errorString()
Projection::Projection(const GCS *gcs, const Method &method, const Setup &setup,
const LinearUnits &units) : _gcs(gcs), _units(units)
{
return _errorString;
const Ellipsoid *ellipsoid = _gcs->datum().ellipsoid();
switch (method.id()) {
case 9807:
_ct = new TransverseMercator(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
setup.falseNorthing());
break;
case 1024:
case 9841:
_ct = new Mercator();
break;
case 9802:
_ct = new LambertConic2(ellipsoid, setup.standardParallel1(),
setup.standardParallel2(), setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.falseEasting(),
setup.falseNorthing());
break;
case 9801:
_ct = new LambertConic1(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
setup.falseNorthing());
break;
case 9820:
_ct = new LambertAzimuthal(ellipsoid, setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.falseEasting(),
setup.falseNorthing());
break;
case 9822:
_ct = new AlbersEqual(ellipsoid, setup.standardParallel1(),
setup.standardParallel2(), setup.latitudeOrigin(),
setup.longitudeOrigin(), setup.falseEasting(),
setup.falseNorthing());
break;
default:
_ct = 0;
}
}
Projection::Projection(const GCS *gcs) : _gcs(gcs)
{
_ct = new LatLon(gcs->angularUnits());
_units = LinearUnits(9001);
}
Projection::Projection(const Projection &p)
{
_gcs = p._gcs;
_units = p._units;
_ct = p._ct->clone();
}
Projection::~Projection()
{
delete _ct;
}
Projection &Projection::operator=(const Projection &p)
{
_gcs = p._gcs;
_units = p._units;
_ct = p._ct->clone();
return *this;
}
QPointF Projection::ll2xy(const Coordinates &c) const
{
return _units.fromMeters(_ct->ll2xy(_gcs->fromWGS84(c)));
}
Coordinates Projection::xy2ll(const QPointF &p) const
{
return _gcs->toWGS84(_ct->xy2ll(_units.toMeters(p)));
}
QDebug operator<<(QDebug dbg, const Projection::Setup &setup)
{
dbg.nospace() << "Setup(" << setup.latitudeOrigin() << ", "
<< setup.longitudeOrigin() << ", " << setup.scale() << ", "
<< setup.falseEasting() << ", " << setup.falseNorthing() << ", "
<< setup.standardParallel1() << ", " << setup.standardParallel2() << ")";
return dbg.space();
}
QDebug operator<<(QDebug dbg, const Projection::Method &method)
{
dbg.nospace() << "Method(" << method.id() << ")";
return dbg.space();
}

View File

@ -2,35 +2,91 @@
#define PROJECTION_H
#include <QPointF>
#include <QString>
#include <QDebug>
#include "common/coordinates.h"
#include "linearunits.h"
class Ellipsoid;
class GCS;
class CT;
class AngularUnits;
class Projection {
public:
struct Setup {
double latitudeOrigin;
double longitudeOrigin;
double scale;
double falseEasting;
double falseNorthing;
double standardParallel1;
double standardParallel2;
int zone;
class Setup {
public:
Setup() : _latitudeOrigin(NAN), _longitudeOrigin(NAN), _scale(NAN),
_falseEasting(NAN), _falseNorthing(NAN), _standardParallel1(NAN),
_standardParallel2(NAN) {}
Setup(double latitudeOrigin, double longitudeOrigin, double scale,
double falseEasting, double falseNorthing, double standardParallel1,
double standardParallel2) : _latitudeOrigin(latitudeOrigin),
_longitudeOrigin(longitudeOrigin), _scale(scale),
_falseEasting(falseEasting), _falseNorthing(falseNorthing),
_standardParallel1(standardParallel1),
_standardParallel2(standardParallel2) {}
double latitudeOrigin() const {return _latitudeOrigin;}
double longitudeOrigin() const {return _longitudeOrigin;}
double scale() const {return _scale;}
double falseEasting() const {return _falseEasting;}
double falseNorthing() const {return _falseNorthing;}
double standardParallel1() const {return _standardParallel1;}
double standardParallel2() const {return _standardParallel2;}
void setLatitudeOrigin(double val) {_latitudeOrigin = val;}
void setLongitudeOrigin(double val) {_longitudeOrigin = val;}
void setScale(double val) {_scale = val;}
void setFalseEasting(double val) {_falseEasting = val;}
void setFalseNorthing(double val) {_falseNorthing = val;}
void setStandardParallel1(double val) {_standardParallel1 = val;}
void setStandardParallel2(double val) {_standardParallel2 = val;}
bool isNull() const {return std::isnan(_latitudeOrigin)
&& std::isnan(_longitudeOrigin) && std::isnan(_scale)
&& std::isnan(_falseEasting) && std::isnan(_falseNorthing)
&& std::isnan(_standardParallel1) && std::isnan(_standardParallel2);}
private:
double _latitudeOrigin;
double _longitudeOrigin;
double _scale;
double _falseEasting;
double _falseNorthing;
double _standardParallel1;
double _standardParallel2;
};
virtual ~Projection() {}
class Method {
public:
Method() : _id(0) {}
Method(int id);
virtual QPointF ll2xy(const Coordinates &c) const = 0;
virtual Coordinates xy2ll(const QPointF &p) const = 0;
int id() const {return _id;}
bool isNull() const {return (_id == 0);}
bool isValid() const {return !isNull();}
private:
int _id;
};
static Projection *projection(const QString &name,
const Ellipsoid &ellipsoid, const Setup &setup);
static const QString &errorString();
Projection() : _gcs(0), _ct(0) {}
Projection(const Projection &p);
Projection(const GCS *gcs, const Method &method, const Setup &setup,
const LinearUnits &units);
Projection(const GCS *gcs);
~Projection();
Projection &operator=(const Projection &p);
QPointF ll2xy(const Coordinates &c) const;
Coordinates xy2ll(const QPointF &p) const;
private:
static QString _errorString;
const GCS * _gcs;
CT *_ct;
LinearUnits _units;
};
QDebug operator<<(QDebug dbg, const Projection::Setup &setup);
QDebug operator<<(QDebug dbg, const Projection::Method &method);
#endif // PROJECTION_H

View File

@ -12,6 +12,7 @@ public:
QStringList files() const {return _index.keys();}
QByteArray file(const QString &name);
bool contains(const QString &name) const {return _index.contains(name);}
QString fileName() const {return _file.fileName();}
bool isOpen() const {return _file.isOpen();}

28
src/map/tifffile.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "tifffile.h"
#define TIFF_II 0x4949
#define TIFF_MM 0x4D4D
#define TIFF_MAGIC 42
bool TIFFFile::readHeader(quint32 &ifd)
{
quint16 endian, magic;
if (QFile::read((char*)&endian, sizeof(endian)) < (qint64)sizeof(endian))
return false;
if (endian == TIFF_II)
_be = false;
else if (endian == TIFF_MM)
_be = true;
else
return false;
if (!readValue(magic))
return false;
if (magic != TIFF_MAGIC)
return false;
if (!readValue(ifd))
return false;
return true;
}

43
src/map/tifffile.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef TIFFFILE_H
#define TIFFFILE_H
#include <QFile>
#include <QtEndian>
class TIFFFile : public QFile
{
public:
TIFFFile() : QFile(), _be(false) {}
TIFFFile(const QString &path) : QFile(path), _be(false) {}
bool readHeader(quint32 &ifd);
template<class T> bool readValue(T &val)
{
T data;
if (QFile::read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
return false;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
if (_be)
val = data;
else {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
}
#else
if (_be) {
for (size_t i = 0; i < sizeof(T); i++)
*((char *)&val + i) = *((char*)&data + sizeof(T) - 1 - i);
} else
val = data;
#endif
return true;
}
private:
bool _be;
};
#endif // TIFFFILE_H

View File

@ -24,7 +24,7 @@ private:
inline QDebug operator<<(QDebug dbg, const Tile &tile)
{
dbg.nospace() << "Tile(" << tile.zoom() << ", " << tile.xy() << ")";
return dbg.maybeSpace();
return dbg.space();
}
#endif // TILE_H

80
src/map/transform.cpp Normal file
View File

@ -0,0 +1,80 @@
#include "projection.h"
#include "matrix.h"
#include "transform.h"
void Transform::simple(const QList<ReferencePoint> &points)
{
if (points.at(0).xy.x() == points.at(1).xy.x()
|| points.at(0).xy.y() == points.at(1).xy.y()) {
_errorString = "Invalid reference points tuple";
return;
}
qreal sX, sY, dX, dY;
sX = (points.at(0).xy.x() - points.at(1).xy.x())
/ (points.at(0).pp.x() - points.at(1).pp.x());
sY = (points.at(1).xy.y() - points.at(0).xy.y())
/ (points.at(1).pp.y() - points.at(0).pp.y());
dX = points.at(1).xy.x() - points.at(1).pp.x() * sX;
dY = points.at(0).xy.y() - points.at(0).pp.y() * sY;
_transform = QTransform(sX, 0, 0, sY, dX, dY);
}
void Transform::affine(const QList<ReferencePoint> &points)
{
Matrix c(3, 2);
c.zeroize();
for (size_t i = 0; i < c.h(); i++) {
for (size_t j = 0; j < c.w(); j++) {
for (int k = 0; k < points.size(); k++) {
double f[3], t[2];
f[0] = points.at(k).pp.x();
f[1] = points.at(k).pp.y();
f[2] = 1.0;
t[0] = points.at(k).xy.x();
t[1] = points.at(k).xy.y();
c.m(i,j) += f[i] * t[j];
}
}
}
Matrix Q(3, 3);
Q.zeroize();
for (int qi = 0; qi < points.size(); qi++) {
double v[3];
v[0] = points.at(qi).pp.x();
v[1] = points.at(qi).pp.y();
v[2] = 1.0;
for (size_t i = 0; i < Q.h(); i++)
for (size_t j = 0; j < Q.w(); j++)
Q.m(i,j) += v[i] * v[j];
}
Matrix M = Q.augemented(c);
if (!M.eliminate()) {
_errorString = "Singular transformation matrix";
return;
}
_transform = QTransform(M.m(0,3), M.m(0,4), M.m(1,3), M.m(1,4), M.m(2,3),
M.m(2,4));
}
Transform::Transform(const QList<ReferencePoint> &points)
{
if (points.count() < 2)
_errorString = "Insufficient number of reference points";
else if (points.size() == 2)
simple(points);
else
affine(points);
}
QDebug operator<<(QDebug dbg, const ReferencePoint &p)
{
dbg.nospace() << "ReferencePoint(" << p.xy << ", " << p.pp << ")";
return dbg.space();
}

32
src/map/transform.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef TRANSFORM_H
#define TRANSFORM_H
#include <QTransform>
#include <QList>
#include "common/coordinates.h"
struct ReferencePoint {
QPoint xy;
QPointF pp;
};
class Transform
{
public:
Transform(const QList<ReferencePoint> &points);
bool isNull() {return _transform.type() == QTransform::TxNone;}
const QString &errorString() const {return _errorString;}
const QTransform &transform() const {return _transform;}
private:
void simple(const QList<ReferencePoint> &points);
void affine(const QList<ReferencePoint> &points);
QTransform _transform;
QString _errorString;
};
QDebug operator<<(QDebug dbg, const ReferencePoint &p);
#endif // TRANSFORM_H

View File

@ -47,17 +47,17 @@ Defense.
#define SPHSN(lat) \
((double)(_e.radius() / sqrt(1.e0 - _es * pow(sin(lat), 2))))
((double)(_e->radius() / sqrt(1.e0 - _es * pow(sin(lat), 2))))
#define SPHTMD(lat) \
((double)(_ap * lat - _bp * sin(2.e0 * lat) + _cp * sin(4.e0 * lat) \
- _dp * sin(6.e0 * lat) + _ep * sin(8.e0 * lat)))
#define DENOM(lat) \
((double)(sqrt(1.e0 - _es * pow(sin(lat),2))))
#define SPHSR(lat) \
((double)(_e.radius() * (1.e0 - _es) / pow(DENOM(lat), 3)))
((double)(_e->radius() * (1.e0 - _es) / pow(DENOM(lat), 3)))
TransverseMercator::TransverseMercator(const Ellipsoid &ellipsoid,
TransverseMercator::TransverseMercator(const Ellipsoid *ellipsoid,
double latitudeOrigin, double longitudeOrigin, double scale,
double falseEasting, double falseNorthing)
{
@ -72,24 +72,24 @@ TransverseMercator::TransverseMercator(const Ellipsoid &ellipsoid,
_falseEasting = falseEasting;
_falseNorthing = falseNorthing;
_es = 2 * _e.flattening() - _e.flattening() * _e.flattening();
_es = 2 * _e->flattening() - _e->flattening() * _e->flattening();
_ebs = (1 / (1 - _es)) - 1;
b = _e.radius() * (1 - _e.flattening());
b = _e->radius() * (1 - _e->flattening());
tn = (_e.radius() - b) / (_e.radius() + b);
tn = (_e->radius() - b) / (_e->radius() + b);
tn2 = tn * tn;
tn3 = tn2 * tn;
tn4 = tn3 * tn;
tn5 = tn4 * tn;
_ap = _e.radius() * (1.e0 - tn + 5.e0 * (tn2 - tn3) / 4.e0 + 81.e0
_ap = _e->radius() * (1.e0 - tn + 5.e0 * (tn2 - tn3) / 4.e0 + 81.e0
* (tn4 - tn5) / 64.e0);
_bp = 3.e0 * _e.radius() * (tn - tn2 + 7.e0 * (tn3 - tn4) / 8.e0 + 55.e0
_bp = 3.e0 * _e->radius() * (tn - tn2 + 7.e0 * (tn3 - tn4) / 8.e0 + 55.e0
* tn5 / 64.e0 ) / 2.e0;
_cp = 15.e0 * _e.radius() * (tn2 - tn3 + 3.e0 * (tn4 - tn5 ) / 4.e0) / 16.0;
_dp = 35.e0 * _e.radius() * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
_ep = 315.e0 * _e.radius() * (tn4 - tn5) / 512.e0;
_cp = 15.e0 * _e->radius() * (tn2 - tn3 + 3.e0 * (tn4 - tn5 ) / 4.e0) / 16.0;
_dp = 35.e0 * _e->radius() * (tn3 - tn4 + 11.e0 * tn5 / 16.e0) / 48.e0;
_ep = 315.e0 * _e->radius() * (tn4 - tn5) / 512.e0;
}
QPointF TransverseMercator::ll2xy(const Coordinates &c) const

View File

@ -1,21 +1,23 @@
#ifndef TRANSVERSEMERCATOR_H
#define TRANSVERSEMERCATOR_H
#include "projection.h"
#include "ct.h"
#include "ellipsoid.h"
class TransverseMercator : public Projection
class TransverseMercator : public CT
{
public:
TransverseMercator(const Ellipsoid &ellipsoid, double latitudeOrigin,
TransverseMercator(const Ellipsoid *ellipsoid, double latitudeOrigin,
double longitudeOrigin, double scale, double falseEasting,
double falseNorthing);
virtual CT *clone() const {return new TransverseMercator(*this);}
virtual QPointF ll2xy(const Coordinates &c) const;
virtual Coordinates xy2ll(const QPointF &p) const;
private:
Ellipsoid _e;
const Ellipsoid *_e;
double _longitudeOrigin;
double _latitudeOrigin;
double _scale;

View File

@ -1,10 +1,10 @@
#include "ellipsoid.h"
#include "utm.h"
UTM::UTM(const Ellipsoid &ellipsoid, int zone)
: _tm(ellipsoid, 0, (qAbs(zone) - 1)*6 - 180 + 3, 0.9996, 500000,
zone < 0 ? 10000000 : 0)
Projection::Setup UTM::setup(int zone)
{
return Projection::Setup(0, (qAbs(zone) - 1)*6 - 180 + 3, 0.9996, 500000,
zone < 0 ? 10000000 : 0, 0, 0);
}
int UTM::zone(const Coordinates &c)

View File

@ -2,22 +2,12 @@
#define UTM_H
#include "projection.h"
#include "transversemercator.h"
class UTM : public Projection
class UTM
{
public:
UTM(const Ellipsoid &ellipsoid, int zone);
virtual QPointF ll2xy(const Coordinates &c) const
{return _tm.ll2xy(c);}
virtual Coordinates xy2ll(const QPointF &p) const
{return _tm.xy2ll(p);}
static int zone(const Coordinates &c);
private:
TransverseMercator _tm;
static Projection::Setup setup(int zone);
};
#endif // UTM_H