mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-05 23:22:51 +02:00
Compare commits
127 Commits
Author | SHA1 | Date | |
---|---|---|---|
3ce3de119b | |||
872ecdfa58 | |||
121a262ea1 | |||
06c9fbd849 | |||
aa928d96e0 | |||
004e9bfef3 | |||
34de55cf0c | |||
c0e458a437 | |||
33739acafe | |||
fe4eed8aa2 | |||
f5ca757348 | |||
476f26752f | |||
588859ca3a | |||
cc8d237786 | |||
5dde297210 | |||
d1469290cf | |||
51d4284ebe | |||
531eb256f1 | |||
79388aa753 | |||
2980299a2a | |||
796e61ada4 | |||
90473300e0 | |||
5706cdcfa1 | |||
d794ee4b22 | |||
262ee5bb5f | |||
5547cf668e | |||
dd9e42ad27 | |||
e192116191 | |||
67c8602efd | |||
a324698a67 | |||
23bf3397b8 | |||
db2d0b63e8 | |||
e7cfeb0d1a | |||
366e84c9fc | |||
3424b3e265 | |||
cb80389d74 | |||
40276e8b95 | |||
106904a763 | |||
e21d89e998 | |||
a432ff3461 | |||
201256d882 | |||
b2a34bd10f | |||
63cf4c039a | |||
ca97ca392e | |||
ec5ad67a3e | |||
569ded1e25 | |||
8e713a1f06 | |||
f07173ab22 | |||
cf6d27b1f5 | |||
fc18283172 | |||
1cd726691e | |||
24835db090 | |||
2352827d9b | |||
c5a060ed6b | |||
026cc68bf2 | |||
ec247d5d1d | |||
815cb6cb91 | |||
ca7016176f | |||
2c816a509b | |||
58e752a022 | |||
7d412a274d | |||
6bee2a46f1 | |||
eeab6a399e | |||
9e04bf0fa7 | |||
2842c6c125 | |||
bafd0b6af2 | |||
eb89ef2f2b | |||
f9822b7c78 | |||
e4feeae064 | |||
31ff81576c | |||
0d879e61a9 | |||
ba7074f902 | |||
f371500570 | |||
7324535bfc | |||
59c95e53c4 | |||
a66ca7b3a8 | |||
273a918ed9 | |||
7198d610c5 | |||
a6389f0174 | |||
d9c922aa47 | |||
0156d2fbc0 | |||
650eb1c302 | |||
33919c501c | |||
be9da5aabe | |||
f341219613 | |||
a486f9e78d | |||
b3940283a8 | |||
74aebce357 | |||
0cd6a82a0f | |||
81a5c712c6 | |||
025a403c73 | |||
a762445bce | |||
e1a87c84f3 | |||
5f47383648 | |||
7a702be012 | |||
abfb0c637a | |||
c9cedebeb0 | |||
be1c7fa4c2 | |||
2b421f3b63 | |||
80f13d7057 | |||
ab05014896 | |||
c8433f7b55 | |||
bb52003743 | |||
22ea1b0bca | |||
adb407dcf5 | |||
3b0a4a30bb | |||
792ec17a20 | |||
bd6c6ef344 | |||
dfb48d17bf | |||
362d065020 | |||
b0f4f2294a | |||
4463241e50 | |||
abc987cb0c | |||
81f0c40bec | |||
cf81e42f52 | |||
1aedc1de93 | |||
beb966c58f | |||
9eb2e38499 | |||
247eef5261 | |||
9c125a0583 | |||
bcff05c37c | |||
266a1d037e | |||
2b0989438a | |||
f8c92cf036 | |||
2fb9a59bf0 | |||
566f3185f9 | |||
62962b5de2 |
@ -1,14 +1,14 @@
|
|||||||
version: 5.9.{build}
|
version: 5.16.{build}
|
||||||
configuration: Release
|
configuration: Release
|
||||||
platform: Any CPU
|
platform: Any CPU
|
||||||
environment:
|
environment:
|
||||||
NSISDIR: C:\Program Files (x86)\NSIS
|
NSISDIR: C:\Program Files (x86)\NSIS
|
||||||
matrix:
|
matrix:
|
||||||
- QTDIR: C:\Qt\5.9\msvc2015
|
- QTDIR: C:\Qt\5.11\msvc2015
|
||||||
PLATFORM: x86
|
PLATFORM: x86
|
||||||
NSI: gpxsee.nsi
|
NSI: gpxsee.nsi
|
||||||
OPENSSLDIR: C:\OpenSSL-Win32\bin
|
OPENSSLDIR: C:\OpenSSL-Win32\bin
|
||||||
- QTDIR: C:\Qt\5.9\msvc2015_64
|
- QTDIR: C:\Qt\5.11\msvc2015_64
|
||||||
PLATFORM: x86_amd64
|
PLATFORM: x86_amd64
|
||||||
NSI: gpxsee64.nsi
|
NSI: gpxsee64.nsi
|
||||||
OPENSSLDIR: C:\OpenSSL-Win64\bin
|
OPENSSLDIR: C:\OpenSSL-Win64\bin
|
||||||
|
@ -4,8 +4,8 @@ KML, FIT, IGC, NMEA and OziExplorer files.
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
* User-definable online maps (OSM/Google tiles, WMTS, WMS).
|
* User-definable online maps (OSM/Google tiles, WMTS, WMS).
|
||||||
* Offline maps (OziExplorer maps, TrekBuddy maps/atlases, GeoTIFF images).
|
* Offline maps (OziExplorer maps, TrekBuddy maps/atlases, Garmin JNX maps, GeoTIFF images).
|
||||||
* Elevation, speed, heart rate, cadence, power and temperature graphs.
|
* Elevation, speed, heart rate, cadence, power, temperature and gear ratio/shifts graphs.
|
||||||
* Support for multiple tracks in one view.
|
* Support for multiple tracks in one view.
|
||||||
* Support for POI files.
|
* Support for POI files.
|
||||||
* Print/export to PDF.
|
* Print/export to PDF.
|
||||||
|
43
gpxsee.pro
43
gpxsee.pro
@ -1,12 +1,16 @@
|
|||||||
TARGET = GPXSee
|
TARGET = GPXSee
|
||||||
VERSION = 5.9
|
VERSION = 5.16
|
||||||
|
|
||||||
QT += core \
|
QT += core \
|
||||||
gui \
|
gui \
|
||||||
network
|
network
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||||
greaterThan(QT_MAJOR_VERSION, 4): QT += printsupport
|
QT += widgets
|
||||||
lessThan(QT_VERSION, 5.4): QT += opengl
|
QT += printsupport
|
||||||
macx: QT += opengl
|
}
|
||||||
|
lessThan(QT_MAJOR_VERSION, 5) {QT += opengl}
|
||||||
|
equals(QT_MAJOR_VERSION, 5) : lessThan(QT_MINOR_VERSION, 4) {QT += opengl}
|
||||||
|
|
||||||
INCLUDEPATH += ./src
|
INCLUDEPATH += ./src
|
||||||
HEADERS += src/config.h \
|
HEADERS += src/config.h \
|
||||||
src/common/staticassert.h \
|
src/common/staticassert.h \
|
||||||
@ -15,6 +19,7 @@ HEADERS += src/config.h \
|
|||||||
src/common/rectc.h \
|
src/common/rectc.h \
|
||||||
src/common/wgs84.h \
|
src/common/wgs84.h \
|
||||||
src/common/str2int.h \
|
src/common/str2int.h \
|
||||||
|
src/common/rtree.h \
|
||||||
src/GUI/app.h \
|
src/GUI/app.h \
|
||||||
src/GUI/icons.h \
|
src/GUI/icons.h \
|
||||||
src/GUI/gui.h \
|
src/GUI/gui.h \
|
||||||
@ -48,6 +53,7 @@ HEADERS += src/config.h \
|
|||||||
src/GUI/format.h \
|
src/GUI/format.h \
|
||||||
src/GUI/cadencegraph.h \
|
src/GUI/cadencegraph.h \
|
||||||
src/GUI/powergraph.h \
|
src/GUI/powergraph.h \
|
||||||
|
src/GUI/gearratiograph.h \
|
||||||
src/GUI/optionsdialog.h \
|
src/GUI/optionsdialog.h \
|
||||||
src/GUI/colorbox.h \
|
src/GUI/colorbox.h \
|
||||||
src/GUI/stylecombobox.h \
|
src/GUI/stylecombobox.h \
|
||||||
@ -60,6 +66,7 @@ HEADERS += src/config.h \
|
|||||||
src/GUI/temperaturegraphitem.h \
|
src/GUI/temperaturegraphitem.h \
|
||||||
src/GUI/cadencegraphitem.h \
|
src/GUI/cadencegraphitem.h \
|
||||||
src/GUI/powergraphitem.h \
|
src/GUI/powergraphitem.h \
|
||||||
|
src/GUI/gearratiographitem.h \
|
||||||
src/GUI/oddspinbox.h \
|
src/GUI/oddspinbox.h \
|
||||||
src/GUI/settings.h \
|
src/GUI/settings.h \
|
||||||
src/GUI/nicenum.h \
|
src/GUI/nicenum.h \
|
||||||
@ -69,7 +76,7 @@ HEADERS += src/config.h \
|
|||||||
src/map/projection.h \
|
src/map/projection.h \
|
||||||
src/map/ellipsoid.h \
|
src/map/ellipsoid.h \
|
||||||
src/map/datum.h \
|
src/map/datum.h \
|
||||||
src/map/mercator.h \
|
src/map/webmercator.h \
|
||||||
src/map/transversemercator.h \
|
src/map/transversemercator.h \
|
||||||
src/map/latlon.h \
|
src/map/latlon.h \
|
||||||
src/map/utm.h \
|
src/map/utm.h \
|
||||||
@ -117,7 +124,6 @@ HEADERS += src/config.h \
|
|||||||
src/data/trackdata.h \
|
src/data/trackdata.h \
|
||||||
src/data/routedata.h \
|
src/data/routedata.h \
|
||||||
src/data/path.h \
|
src/data/path.h \
|
||||||
src/data/rtree.h \
|
|
||||||
src/data/gpxparser.h \
|
src/data/gpxparser.h \
|
||||||
src/data/tcxparser.h \
|
src/data/tcxparser.h \
|
||||||
src/data/csvparser.h \
|
src/data/csvparser.h \
|
||||||
@ -125,7 +131,13 @@ HEADERS += src/config.h \
|
|||||||
src/data/fitparser.h \
|
src/data/fitparser.h \
|
||||||
src/data/igcparser.h \
|
src/data/igcparser.h \
|
||||||
src/data/nmeaparser.h \
|
src/data/nmeaparser.h \
|
||||||
src/data/oziparsers.h
|
src/data/oziparsers.h \
|
||||||
|
src/map/rectd.h \
|
||||||
|
src/map/geocentric.h \
|
||||||
|
src/map/mercator.h \
|
||||||
|
src/map/jnxmap.h \
|
||||||
|
src/map/krovak.h \
|
||||||
|
src/GUI/kv.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/common/coordinates.cpp \
|
src/common/coordinates.cpp \
|
||||||
src/common/rectc.cpp \
|
src/common/rectc.cpp \
|
||||||
@ -159,6 +171,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/format.cpp \
|
src/GUI/format.cpp \
|
||||||
src/GUI/cadencegraph.cpp \
|
src/GUI/cadencegraph.cpp \
|
||||||
src/GUI/powergraph.cpp \
|
src/GUI/powergraph.cpp \
|
||||||
|
src/GUI/gearratiograph.cpp \
|
||||||
src/GUI/optionsdialog.cpp \
|
src/GUI/optionsdialog.cpp \
|
||||||
src/GUI/colorbox.cpp \
|
src/GUI/colorbox.cpp \
|
||||||
src/GUI/stylecombobox.cpp \
|
src/GUI/stylecombobox.cpp \
|
||||||
@ -170,6 +183,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/temperaturegraphitem.cpp \
|
src/GUI/temperaturegraphitem.cpp \
|
||||||
src/GUI/cadencegraphitem.cpp \
|
src/GUI/cadencegraphitem.cpp \
|
||||||
src/GUI/powergraphitem.cpp \
|
src/GUI/powergraphitem.cpp \
|
||||||
|
src/GUI/gearratiographitem.cpp \
|
||||||
src/GUI/nicenum.cpp \
|
src/GUI/nicenum.cpp \
|
||||||
src/GUI/mapview.cpp \
|
src/GUI/mapview.cpp \
|
||||||
src/map/maplist.cpp \
|
src/map/maplist.cpp \
|
||||||
@ -183,7 +197,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/matrix.cpp \
|
src/map/matrix.cpp \
|
||||||
src/map/ellipsoid.cpp \
|
src/map/ellipsoid.cpp \
|
||||||
src/map/datum.cpp \
|
src/map/datum.cpp \
|
||||||
src/map/mercator.cpp \
|
src/map/webmercator.cpp \
|
||||||
src/map/transversemercator.cpp \
|
src/map/transversemercator.cpp \
|
||||||
src/map/utm.cpp \
|
src/map/utm.cpp \
|
||||||
src/map/lambertconic.cpp \
|
src/map/lambertconic.cpp \
|
||||||
@ -219,7 +233,13 @@ SOURCES += src/main.cpp \
|
|||||||
src/data/fitparser.cpp \
|
src/data/fitparser.cpp \
|
||||||
src/data/igcparser.cpp \
|
src/data/igcparser.cpp \
|
||||||
src/data/nmeaparser.cpp \
|
src/data/nmeaparser.cpp \
|
||||||
src/data/oziparsers.cpp
|
src/data/oziparsers.cpp \
|
||||||
|
src/map/geocentric.cpp \
|
||||||
|
src/map/mercator.cpp \
|
||||||
|
src/map/jnxmap.cpp \
|
||||||
|
src/map/krovak.cpp \
|
||||||
|
src/map/map.cpp
|
||||||
|
|
||||||
RESOURCES += gpxsee.qrc
|
RESOURCES += gpxsee.qrc
|
||||||
TRANSLATIONS = lang/gpxsee_cs.ts \
|
TRANSLATIONS = lang/gpxsee_cs.ts \
|
||||||
lang/gpxsee_sv.ts \
|
lang/gpxsee_sv.ts \
|
||||||
@ -228,6 +248,7 @@ TRANSLATIONS = lang/gpxsee_cs.ts \
|
|||||||
lang/gpxsee_fi.ts \
|
lang/gpxsee_fi.ts \
|
||||||
lang/gpxsee_fr.ts \
|
lang/gpxsee_fr.ts \
|
||||||
lang/gpxsee_pl.ts
|
lang/gpxsee_pl.ts
|
||||||
|
|
||||||
macx {
|
macx {
|
||||||
ICON = icons/gpxsee.icns
|
ICON = icons/gpxsee.icns
|
||||||
QMAKE_INFO_PLIST = pkg/Info.plist
|
QMAKE_INFO_PLIST = pkg/Info.plist
|
||||||
@ -266,5 +287,7 @@ win32 {
|
|||||||
icons/plt.ico \
|
icons/plt.ico \
|
||||||
icons/rte.ico \
|
icons/rte.ico \
|
||||||
icons/wpt.ico
|
icons/wpt.ico
|
||||||
|
DEFINES += _USE_MATH_DEFINES
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
DEFINES += APP_VERSION=\\\"$$VERSION\\\"
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ Modified Airy,7002,6377340.189,299.3249646
|
|||||||
Australian National,7003,6378160.0,298.25
|
Australian National,7003,6378160.0,298.25
|
||||||
Bessel 1841,7004,6377397.155,299.1528128
|
Bessel 1841,7004,6377397.155,299.1528128
|
||||||
Bessel 1841 (Norway),7005,6377492.0176,299.1528
|
Bessel 1841 (Norway),7005,6377492.0176,299.1528
|
||||||
|
Clarke 1858,7007,6378293.645,294.26
|
||||||
Clarke 1866,7008,6378206.4,294.9786982
|
Clarke 1866,7008,6378206.4,294.9786982
|
||||||
Clarke 1880 (Palestine),7010,6378300.789,293.466
|
Clarke 1880 (Palestine),7010,6378300.789,293.466
|
||||||
Clarke 1880 (IGN),7011,6378249.2,293.466021
|
Clarke 1880 (IGN),7011,6378249.2,293.466021
|
||||||
@ -11,9 +12,17 @@ Everest 1830 (1937 Adjustment),7015,6377276.345,300.8017
|
|||||||
Everest 1830 Modified,7018,6377304.063,300.8017
|
Everest 1830 Modified,7018,6377304.063,300.8017
|
||||||
GRS 80,7019,6378137.0,298.257222101
|
GRS 80,7019,6378137.0,298.257222101
|
||||||
Helmert 1906,7020,6378200.0,298.3
|
Helmert 1906,7020,6378200.0,298.3
|
||||||
|
Indonesian National Spheroid,7021,6378160.0,298.247
|
||||||
International 1924,7022,6378388.0,297.0
|
International 1924,7022,6378388.0,297.0
|
||||||
Krassovsky 1940,7024,6378245.0,298.3
|
Krassovsky 1940,7024,6378245.0,298.3
|
||||||
|
War Office,7029,6378300.0,296.0
|
||||||
South American 1969,7036,6378160.0,298.25
|
South American 1969,7036,6378160.0,298.25
|
||||||
WGS 72,7043,6378135.0,298.26
|
WGS 72,7043,6378135.0,298.26
|
||||||
|
Everest 1830 (1962 Definition),7044,6377301.243,300.8017255
|
||||||
|
Everest 1830 (1975 Definition),7045,6377299.151,300.8017255
|
||||||
Bessel 1841 (Namibia),7046,6377483.865,299.1528128
|
Bessel 1841 (Namibia),7046,6377483.865,299.1528128
|
||||||
|
GRS 1967 Modified,7050,6378160.0,298.25
|
||||||
|
Danish 1876,7051,6377019.27,300.0
|
||||||
Hough 1960,7053,6378270.0,297.0
|
Hough 1960,7053,6378270.0,297.0
|
||||||
|
Clarke 1880 (international foot),7055,6378306.370,293.4663077
|
||||||
|
PZ-90,7054,6378136.0,298.257839303
|
||||||
|
|
497
pkg/csv/gcs.csv
497
pkg/csv/gcs.csv
@ -1,123 +1,374 @@
|
|||||||
Adindan,4201,6201,9122,7012,8901,9603,-162,-12,206
|
HD1909,3819,1024,9122,7004,8901,9607,595.48,121.69,515.35,-4.115,2.9383,-0.853,-3.408
|
||||||
Afgooye,4205,6205,9122,7024,8901,9603,-43,-163,45
|
TWD97,3824,1026,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Ain el Abd 1970,4204,6204,9122,7022,8901,9603,-150,-251,-2
|
IGRS,3889,1029,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Anna 1 Astro 1965,4708,6708,9122,7003,8901,9603,-491,-22,435
|
Hermannskogel,3906,1031,9122,7004,8901,9603,653,-212,449,,,,
|
||||||
Arc 1950,4209,6209,9122,7012,8901,9603,-143,-90,-294
|
MOLDREF99,4023,1032,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Arc 1960,4210,6210,9122,7012,8901,9603,-160,-8,-300
|
RGRDC 2005,4046,1033,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Ascension Island 1958,4712,6712,9122,7022,8901,9603,-207,107,52
|
SREF98,4075,1034,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Astro B4 Sorol Atoll,4707,6707,9122,7022,8901,9603,114,-116,-333
|
REGCAN95,4081,1035,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Astro Beacon 1945,4709,6709,9122,7022,8901,9603,145,75,-272
|
GGRS 87,4121,6121,9122,7019,8901,9603,-199.87,74.79,246.62,,,,
|
||||||
Astro DOS 71/4,4710,6710,9122,7022,8901,9603,-320,550,-494
|
Finland Hayford,4123,6123,9122,7022,8901,9603,-78,-231,-97,,,,
|
||||||
Astronomic Stn 1952,4711,6711,9122,7022,8901,9603,124,-234,-25
|
RT 90,4124,6124,9122,7004,8901,9603,498,-36,568,,,,
|
||||||
Australian Geodetic 1966,4202,6202,9122,7003,8901,9603,-133,-48,148
|
Samboja,4125,6125,9108,7004,8901,9603,-404.78,685.68,45.47,,,,
|
||||||
Australian Geodetic 1984,4203,6203,9122,7003,8901,9603,-134,-48,149
|
Tete,4127,6127,9122,7008,8901,9603,-80,-100,-228,,,,
|
||||||
Australian Geocentric 1994 (GDA94),4283,6283,9122,7019,8901,9603,0,0,0
|
Observatario,4129,6129,9122,7008,8901,9603,-132,-110,-335,,,,
|
||||||
Austrian,4312,6312,9122,7004,8901,9603,594,84,471
|
Moznet,4130,6130,9122,7030,8901,9607,0,0,0,0,0,0,0
|
||||||
Bellevue (IGN),4714,6714,9122,7022,8901,9603,-127,-769,472
|
Indian 1960,4131,6131,9122,7015,8901,9603,198,881,317,,,,
|
||||||
Bermuda 1957,4216,6216,9122,7008,8901,9603,-73,213,296
|
FD58,4132,6132,9122,7012,8901,9603,-241.54,-163.64,396.06,,,,
|
||||||
Bogota Observatory,4218,6218,9122,7022,8901,9603,307,304,-318
|
EST92,4133,6133,9122,7019,8901,9607,0.055,-0.541,-0.185,-0.0183,0.0003,0.007,-0.014
|
||||||
Campo Inchauspe,4221,6221,9122,7022,8901,9603,-148,136,90
|
PSD93,4134,6134,9122,7012,8901,9606,-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.71006
|
||||||
Canton Astro 1966,4716,6716,9122,7022,8901,9603,298,-304,-375
|
Old Hawaiian,4135,6135,9122,7008,8901,9603,61,-285,-181,,,,
|
||||||
Cape,4222,6222,9122,7012,8901,9603,-136,-108,-292
|
Puerto Rico,4139,6139,9122,7008,8901,9603,11,72,-101,,,,
|
||||||
Cape Canaveral,4717,6717,9122,7008,8901,9603,-2,150,181
|
NAD83(CSRS98),4140,6140,9108,7019,8901,9603,0,0,0,,,,
|
||||||
Carthage,4223,6223,9122,7012,8901,9603,-263,6,431
|
Israel 1993,4141,6141,9122,7019,8901,9603,-48,55,52,,,,
|
||||||
CH-1903,4149,6149,9122,7004,8901,9603,674.374,15.056,405.343
|
Locodjo 1965,4142,6142,9122,7012,8901,9603,-125,53,467,,,,
|
||||||
Chatham 1971,4672,6672,9122,7022,8901,9603,175,-38,113
|
Abidjan 1987,4143,6143,9122,7012,8901,9603,-124.76,53,466.79,,,,
|
||||||
Chua Astro,4224,6224,9122,7022,8901,9603,-134,229,-29
|
Kalianpur 1937,4144,6144,9122,7015,8901,9603,214,804,268,,,,
|
||||||
Corrego Alegre,4225,6225,9122,7022,8901,9603,-206,172,-6
|
Kalianpur 1962,4145,6145,9122,7044,8901,9603,283,682,231,,,,
|
||||||
Djakarta (Batavia),4211,6211,9122,7004,8901,9603,-377,681,-50
|
Kalianpur 1975,4146,6146,9122,7045,8901,9603,295,736,257,,,,
|
||||||
DOS 1968,,,9122,7022,8901,9603,230,-199,-752
|
Hanoi 1972,4147,6147,9122,7024,8901,9603,-17.51,-108.32,-62.39,,,,
|
||||||
Easter Island 1967,4719,6719,9122,7022,8901,9603,211,147,111
|
Hartebeeshoek94,4148,6148,9122,7030,8901,9603,0,0,0,,,,
|
||||||
Egypt,4199,6199,9122,7022,8901,9603,-130,-117,-151
|
CH-1903,4149,6149,9122,7004,8901,9603,674.374,15.056,405.343,,,,
|
||||||
ETRS 89,4258,6258,9122,7019,8901,9603,0,0,0
|
CH1903+,4150,6150,9122,7004,8901,9603,674.374,15.056,405.346,,,,
|
||||||
European 1950,4230,6230,9122,7022,8901,9603,-87,-98,-121
|
CHTRF95,4151,6151,9122,7019,8901,9603,0,0,0,,,,
|
||||||
European 1950 (Mean France),,,9122,7022,8901,9603,-87,-96,-120
|
NAD83(HARN),4152,6152,9122,7019,8901,9603,0,0,0,,,,
|
||||||
European 1950 (Spain and Portugal),,,9122,7022,8901,9603,-84,-107,-120
|
Rassadiran,4153,6153,9122,7022,8901,9603,-133.63,-157.5,-158.62,,,,
|
||||||
European 1979,4668,6668,9122,7022,8901,9603,-86,-98,-119
|
ED50(ED77),4154,6154,9122,7022,8901,9603,-117,-132,-164,,,,
|
||||||
Finland Hayford,4123,6123,9122,7022,8901,9603,-78,-231,-97
|
Dabola 1981,4155,6155,9122,7011,8901,9603,-83,37,124,,,,
|
||||||
Gandajika Base,4233,6233,9122,7022,8901,9603,-133,-321,50
|
S-JTSK,4156,6156,9122,7004,8901,9603,589,76,480,,,,
|
||||||
Geodetic Datum 1949,4272,6272,9122,7022,8901,9603,84,-22,209
|
Naparima 1955,4158,6158,9122,7022,8901,9603,-0.465,372.095,171.736,,,,
|
||||||
GGRS 87,4121,6121,9122,7019,8901,9603,-199.87,74.79,246.62
|
ELD79,4159,6159,9122,7022,8901,9603,-115.8543,-99.0583,-152.4616,,,,
|
||||||
Guam 1963,4675,6675,9122,7008,8901,9603,-100,-248,259
|
Pampa del Castillo,4161,6161,9122,7022,8901,9603,27.5,14,186.4,,,,
|
||||||
GUX 1 Astro,4718,6718,9122,7022,8901,9603,252,-209,-751
|
Yemen NGN96,4163,6163,9122,7030,8901,9603,0,0,0,,,,
|
||||||
Hartebeeshoek94,4148,6148,9122,7030,8901,9603,0,0,0
|
South Yemen,4164,6164,9122,7024,8901,9603,-76,-138,67,,,,
|
||||||
Hermannskogel,3906,1031,9122,7004,8901,9603,653,-212,449
|
Bissau,4165,6165,9122,7022,8901,9603,-173,253,27,,,,
|
||||||
Hjorsey 1955,4658,6658,9122,7022,8901,9603,-73,46,-86
|
Korean 1995,4166,6166,9122,7030,8901,9603,0,0,0,,,,
|
||||||
Hong Kong 1963,4739,6739,9122,7022,8901,9603,-156,-271,-189
|
NZGD2000,4167,6167,9122,7030,8901,9603,0,0,0,,,,
|
||||||
Hu-Tzu-Shan,4236,6236,9122,7022,8901,9603,-634,-549,-201
|
Accra,4168,6168,9122,7029,8901,9603,-199,32,322,,,,
|
||||||
Indian Bangladesh,4682,6682,9122,7015,8901,9603,289,734,257
|
American Samoa 1962,4169,6169,9122,7008,8901,9603,-115,118,426,,,,
|
||||||
Indian Thailand,4240,6240,9122,7015,8901,9603,214,836,303
|
SIRGAS 1995,4170,6170,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Israeli,4281,6281,9122,7010,8901,9603,-235,-85,264
|
RGF93,4171,6171,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Ireland 1965,4299,6299,9122,7002,8901,9603,506,-122,611
|
POSGAR,4172,6172,9108,7019,8901,9603,0,0,0,,,,
|
||||||
ISTS 073 Astro 1969,4724,6724,9122,7022,8901,9603,208,-435,-229
|
IRENET95,4173,6173,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Johnston Island,4725,6725,9122,7022,8901,9603,191,-77,-204
|
Sierra Leone 1968,4175,6175,9122,7012,8901,9603,-88,4,101,,,,
|
||||||
Kandawala,4244,6244,9122,7015,8901,9603,-97,787,86
|
Australian Antarctic,4176,6176,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Kerguelen Island,4698,6698,9122,7022,8901,9603,145,-187,103
|
S42 (83),4178,6178,9122,7024,8901,9603,26,-121,-78,,,,
|
||||||
Kertau 1948,4245,6245,9122,7018,8901,9603,-11,851,5
|
S42,4179,6179,9122,7024,8901,9603,28,-121,-77,,,,
|
||||||
L.C. 5 Astro,4726,6726,9122,7008,8901,9603,42,124,147
|
EST97,4180,6180,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Liberia 1964,4251,6251,9122,7012,8901,9603,-90,40,88
|
Luxembourg 1930,4181,6181,9122,7022,8901,9607,-189.6806,18.3463,-42.7695,0.33746,3.09264,-2.53861,0.4598
|
||||||
Luzon Mindanao,,,9122,7008,8901,9603,-133,-79,-72
|
Observatorio 1966,4182,6182,9122,7022,8901,9603,-425,-169,81,,,,
|
||||||
Luzon Philippines,4253,6253,9122,7008,8901,9603,-133,-77,-51
|
Southwest Base,4183,6183,9122,7022,8901,9603,-104,167,-38,,,,
|
||||||
Mahe 1971,4256,6256,9122,7012,8901,9603,41,-220,-134
|
Sao Braz,4184,6184,9122,7022,8901,9603,-203,141,53,,,,
|
||||||
Marco Astro,4616,6616,9122,7022,8901,9603,-289,-124,60
|
OSNI 1952,4188,6188,9122,7001,8901,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
|
||||||
Massawa,4262,6262,9122,7004,8901,9603,639,405,60
|
REGVEN,4189,6189,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Merchich,4261,6261,9122,7012,8901,9603,31,146,47
|
POSGAR 98,4190,6190,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Midway Astro 1961,4727,6727,9122,7022,8901,9603,912,-58,1227
|
Albanian 1987,4191,6191,9122,7024,8901,9607,-44.183,-0.58,-38.489,-2.3867,-2.7072,3.5196,-8.2703
|
||||||
Minna,4263,6263,9122,7012,8901,9603,-92,-93,122
|
Douala 1948,4192,6192,9122,7022,8901,9603,-206.1,-174.7,-87.7,,,,
|
||||||
NAD27 Alaska,,,9122,7008,8901,9603,-5,135,172
|
Manoca 1962,4193,6193,9122,7011,8901,9603,-70.9,-151.8,-41.4,,,,
|
||||||
NAD27 Bahamas,,,9122,7008,8901,9603,-4,154,178
|
Qornoq 1927,4194,6194,9122,7022,8901,9603,164,138,-189,,,,
|
||||||
NAD27 Canada,,,9122,7008,8901,9603,-10,158,187
|
Scoresbysund 1952,4195,6195,9122,7022,8901,9606,105,326,-102.5,0,0,0.814,-0.6
|
||||||
NAD27 Canal Zone,,,9122,7008,8901,9603,0,125,201
|
Ammassalik 1958,4196,6196,9122,7022,8901,9606,-45,417,-3.5,0,0,0.814,-0.6
|
||||||
NAD27 Caribbean,,,9122,7008,8901,9603,-3,142,183
|
Egypt,4199,6199,9122,7022,8901,9603,-130,-117,-151,,,,
|
||||||
NAD27 Central,,,9122,7008,8901,9603,0,125,194
|
Pulkovo 1995,4200,6200,9122,7024,8901,9607,24.47,-130.89,-81.56,0,0,-0.13,-0.22
|
||||||
NAD27 CONUS,4267,6267,9122,7008,8901,9603,-8,160,176
|
Adindan,4201,6201,9122,7012,8901,9603,-162,-12,206,,,,
|
||||||
NAD27 Cuba,,,9122,7008,8901,9603,-9,152,178
|
Australian Geodetic 1966,4202,6202,9122,7003,8901,9603,-133,-48,148,,,,
|
||||||
NAD27 Greenland,,,9122,7008,8901,9603,11,114,195
|
Australian Geodetic 1984,4203,6203,9122,7003,8901,9603,-134,-48,149,,,,
|
||||||
NAD27 Mexico,,,9122,7008,8901,9603,-12,130,190
|
Ain el Abd 1970,4204,6204,9122,7022,8901,9603,-150,-251,-2,,,,
|
||||||
NAD27 San Salvador,,,9122,7008,8901,9603,1,140,165
|
Afgooye,4205,6205,9122,7024,8901,9603,-43,-163,45,,,,
|
||||||
NAD83,4269,6269,9122,7019,8901,9603,0,0,0
|
Lisbon,4207,6207,9122,7022,8901,9603,-304.046,-60.576,103.64,,,,
|
||||||
Nahrwn Masirah Ilnd,,,9122,7012,8901,9603,-247,-148,369
|
Aratu,4208,6208,9122,7022,8901,9603,-151.99,287.04,-147.45,,,,
|
||||||
Nahrwn Saudi Arbia,,,9122,7012,8901,9603,-231,-196,482
|
Arc 1950,4209,6209,9122,7012,8901,9603,-143,-90,-294,,,,
|
||||||
Nahrwn United Arab,4270,6270,9122,7012,8901,9603,-249,-156,381
|
Arc 1960,4210,6210,9122,7012,8901,9603,-160,-8,-300,,,,
|
||||||
Naparima BWI,4271,6271,9122,7022,8901,9603,-2,374,172
|
Djakarta (Batavia),4211,6211,9122,7004,8901,9603,-377,681,-50,,,,
|
||||||
NGO1948,4273,6273,9122,7005,8901,9603,315,-217,528
|
Barbados 1938,4212,6212,9122,7012,8901,9603,31.95,300.99,419.19,,,,
|
||||||
NTF France,4275,6275,9122,7011,8901,9603,-168,-60,320
|
Beduaram,4213,6213,9122,7011,8901,9603,-106,-87,188,,,,
|
||||||
Norsk,4817,6817,9122,7005,8913,9603,278,93,474
|
Beijing 1954,4214,6214,9122,7024,8901,9603,15.8,-154.4,-82.3,,,,
|
||||||
NZGD1949,4272,6272,9122,7022,8901,9603,84,-22,209
|
Bermuda 1957,4216,6216,9122,7008,8901,9603,-73,213,296,,,,
|
||||||
NZGD2000,4167,6167,9122,7030,8901,9603,0,0,0
|
Bogota Observatory,4218,6218,9122,7022,8901,9603,307,304,-318,,,,
|
||||||
Observatorio 1966,4182,6182,9122,7022,8901,9603,-425,-169,81
|
Bukit Rimpah,4219,6219,9122,7004,8901,9603,-384,664,-48,,,,
|
||||||
Old Egyptian,4229,6229,9122,7020,8901,9603,-130,110,-13
|
Camacupa,4220,6220,9122,7012,8901,9603,-50.9,-347.6,-231,,,,
|
||||||
Old Hawaiian,4135,6135,9122,7008,8901,9603,61,-285,-181
|
Campo Inchauspe,4221,6221,9122,7022,8901,9603,-148,136,90,,,,
|
||||||
Oman,4232,6232,9122,7012,8901,9603,-346,-1,224
|
Cape,4222,6222,9122,7012,8901,9603,-136,-108,-292,,,,
|
||||||
Ord Srvy Grt Britn,4277,6277,9122,7001,8901,9603,375,-111,431
|
Carthage,4223,6223,9122,7012,8901,9603,-263,6,431,,,,
|
||||||
Pico De Las Nieves,4728,6728,9122,7022,8901,9603,-307,-92,127
|
Chua Astro,4224,6224,9122,7022,8901,9603,-134,229,-29,,,,
|
||||||
Pitcairn Astro 1967,4729,6729,9122,7022,8901,9603,185,165,42
|
Corrego Alegre,4225,6225,9122,7022,8901,9603,-206,172,-6,,,,
|
||||||
Potsdam Rauenberg DHDN,4314,6314,9122,7004,8901,9603,606,23,413
|
Deir ez Zor,4227,6227,9122,7011,8901,9603,-190.421,8.532,238.69,,,,
|
||||||
Prov So Amrican 1956,4248,6248,9122,7022,8901,9603,-288,175,-376
|
Old Egyptian,4229,6229,9122,7020,8901,9603,-130,110,-13,,,,
|
||||||
Prov So Chilean 1963,4254,6254,9122,7022,8901,9603,16,196,93
|
European 1950,4230,6230,9122,7022,8901,9603,-87,-98,-121,,,,
|
||||||
Puerto Rico,4139,6139,9122,7008,8901,9603,11,72,-101
|
ED87,4231,6231,9122,7022,8901,9606,-83.11,-97.38,-117.22,0.005693,-0.044698,0.044285,0.1218
|
||||||
Pulkovo 1942 (1),4284,6284,9122,7024,8901,9603,28,-130,-95
|
Oman,4232,6232,9122,7012,8901,9603,-346,-1,224,,,,
|
||||||
Pulkovo 1942 (2),,,9122,7024,8901,9603,28,-130,-95
|
Gandajika Base,4233,6233,9122,7022,8901,9603,-133,-321,50,,,,
|
||||||
Qatar National,4285,6285,9122,7022,8901,9603,-128,-283,22
|
Hu-Tzu-Shan,4236,6236,9122,7022,8901,9603,-634,-549,-201,,,,
|
||||||
Qornoq,4287,6287,9108,7022,8901,9603,164,138,-189
|
HD72,4237,6237,9122,7036,8901,9603,52.17,-71.82,-14.9,,,,
|
||||||
Reunion,4626,6626,9122,7022,8901,9603,94,-948,-1262
|
ID74,4238,6238,9122,7021,8901,9603,-24,-15,5,,,,
|
||||||
Rijksdriehoeksmeting,4289,6289,9122,7004,8901,9603,593,26,478
|
Indian 1954,4239,6239,9122,7015,8901,9603,217,823,299,,,,
|
||||||
Rome 1940,4806,6806,9122,7022,8906,9603,-225,-65,9
|
Indian Thailand,4240,6240,9122,7015,8901,9603,214,836,303,,,,
|
||||||
RT 90,4124,6124,9122,7004,8901,9603,498,-36,568
|
JAD69,4242,6242,9122,7008,8901,9603,70,207,389.5,,,,
|
||||||
S42,4179,6179,9122,7024,8901,9603,28,-121,-77
|
Kandawala,4244,6244,9122,7015,8901,9603,-97,787,86,,,,
|
||||||
S42 (83),4178,6178,9122,7024,8901,9603,26,-121,-78
|
Kertau 1948,4245,6245,9122,7018,8901,9603,-11,851,5,,,,
|
||||||
Santo (DOS),4730,6730,9122,7022,8901,9603,170,42,84
|
KOC,4246,6246,9122,7012,8901,9603,-294.7,-200.1,525.5,,,,
|
||||||
Sao Braz,4184,6184,9122,7022,8901,9603,-203,141,53
|
La Canoa,4247,6247,9122,7022,8901,9603,-273.5,110.6,-357.9,,,,
|
||||||
Sapper Hill 1943,4292,6292,9122,7022,8901,9603,-355,16,74
|
Prov So Amrican 1956,4248,6248,9122,7022,8901,9603,-288,175,-376,,,,
|
||||||
Schwarzeck,4293,6293,9122,7046,8901,9603,616,97,-251
|
Leigon,4250,6250,9122,7012,8901,9603,-130,29,364,,,,
|
||||||
South American 1969,4291,6291,9108,7036,8901,9603,-57,1,-41
|
Liberia 1964,4251,6251,9122,7012,8901,9603,-90,40,88,,,,
|
||||||
Southeast Base,4615,6615,9122,7022,8901,9603,-499,-249,314
|
Luzon Philippines,4253,6253,9122,7008,8901,9603,-133,-77,-51,,,,
|
||||||
Southwest Base,4183,6183,9122,7022,8901,9603,-104,167,-38
|
Prov So Chilean 1963,4254,6254,9122,7022,8901,9603,16,196,93,,,,
|
||||||
Timbalai 1948,4298,6298,9122,7015,8901,9603,-689,691,-46
|
Herat North,4255,6255,9122,7022,8901,9603,-333,-222,114,,,,
|
||||||
Tokyo,4301,6301,9122,7004,8901,9603,-128,481,664
|
Mahe 1971,4256,6256,9122,7012,8901,9603,41,-220,-134,,,,
|
||||||
Tristan Astro 1968,4734,6734,9122,7022,8901,9603,-632,438,-609
|
Makassar,4257,6257,9122,7004,8901,9603,-587.8,519.75,145.76,,,,
|
||||||
Viti Levu 1916,4731,6731,9122,7012,8901,9603,51,391,-36
|
ETRS 89,4258,6258,9122,7019,8901,9603,0,0,0,,,,
|
||||||
Wake-Eniwetok 1960,4732,6732,9122,7053,8901,9603,101,52,-39
|
Malongo 1987,4259,6259,9122,7022,8901,9603,-254.1,-5.36,-100.29,,,,
|
||||||
WGS 72,4322,6322,9122,7043,8901,9603,0,0,5
|
Manoca,4260,6260,9108,7012,8901,9603,-70.9,-151.8,-41.4,,,,
|
||||||
Yacare,4309,6309,9122,7022,8901,9603,-155,171,37
|
Merchich,4261,6261,9122,7012,8901,9603,31,146,47,,,,
|
||||||
Zanderij,4311,6311,9122,7022,8901,9603,-265,120,-358
|
Massawa,4262,6262,9122,7004,8901,9603,639,405,60,,,,
|
||||||
|
Minna,4263,6263,9122,7012,8901,9603,-92,-93,122,,,,
|
||||||
|
Mhast,4264,6264,9122,7022,8901,9603,-252.95,-4.11,-96.38,,,,
|
||||||
|
Monte Mario,4265,6265,9122,7022,8901,9606,-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68
|
||||||
|
M'poraloko,4266,6266,9122,7011,8901,9603,-74,-130,42,,,,
|
||||||
|
NAD27 CONUS,4267,6267,9122,7008,8901,9603,-8,160,176,,,,
|
||||||
|
NAD83,4269,6269,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Nahrwn United Arab,4270,6270,9122,7012,8901,9603,-249,-156,381,,,,
|
||||||
|
Naparima BWI,4271,6271,9122,7022,8901,9603,-2,374,172,,,,
|
||||||
|
Geodetic Datum 1949,4272,6272,9122,7022,8901,9603,84,-22,209,,,,
|
||||||
|
NZGD1949,4272,6272,9122,7022,8901,9603,84,-22,209,,,,
|
||||||
|
NGO1948,4273,6273,9122,7005,8901,9603,315,-217,528,,,,
|
||||||
|
Datum 73,4274,6274,9122,7022,8901,9603,-223.237,110.193,36.649,,,,
|
||||||
|
NTF France,4275,6275,9122,7011,8901,9603,-168,-60,320,,,,
|
||||||
|
Ord Srvy Grt Britn,4277,6277,9122,7001,8901,9603,375,-111,431,,,,
|
||||||
|
Israeli,4281,6281,9122,7010,8901,9603,-235,-85,264,,,,
|
||||||
|
Pointe Noire,4282,6282,9122,7011,8901,9603,-148,51,-291,,,,
|
||||||
|
Australian Geocentric 1994 (GDA94),4283,6283,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Pulkovo 1942 (1),4284,6284,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,,,,
|
||||||
|
Rijksdriehoeksmeting,4289,6289,9122,7004,8901,9603,593,26,478,,,,
|
||||||
|
South American 1969,4291,6291,9108,7036,8901,9603,-57,1,-41,,,,
|
||||||
|
Sapper Hill 1943,4292,6292,9122,7022,8901,9603,-355,16,74,,,,
|
||||||
|
Schwarzeck,4293,6293,9122,7046,8901,9603,616,97,-251,,,,
|
||||||
|
Segora,4294,6294,9108,7004,8901,9603,-403,684,41,,,,
|
||||||
|
Tananarive,4297,6297,9122,7022,8901,9603,-189,-242,-91,,,,
|
||||||
|
Timbalai 1948,4298,6298,9122,7015,8901,9603,-689,691,-46,,,,
|
||||||
|
Ireland 1965,4299,6299,9122,7002,8901,9603,506,-122,611,,,,
|
||||||
|
TM75,4300,6300,9122,7002,8901,9606,482.5,-130.6,564.6,-1.042,-0.214,-0.631,8.15
|
||||||
|
Tokyo,4301,6301,9122,7004,8901,9603,-128,481,664,,,,
|
||||||
|
Trinidad 1903,4302,6302,9122,7007,8901,9603,-61.702,284.488,472.052,,,,
|
||||||
|
Voirol 1875,4304,6304,9122,7011,8901,9603,-73,-247,227,,,,
|
||||||
|
Nord Sahara 1959,4307,6307,9122,7012,8901,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547
|
||||||
|
Yacare,4309,6309,9122,7022,8901,9603,-155,171,37,,,,
|
||||||
|
Yoff,4310,6310,9122,7011,8901,9603,-30,190,89,,,,
|
||||||
|
Zanderij,4311,6311,9122,7022,8901,9603,-265,120,-358,,,,
|
||||||
|
Austrian,4312,6312,9122,7004,8901,9603,594,84,471,,,,
|
||||||
|
Belge 1972,4313,6313,9122,7022,8901,9607,-106.8686,52.2978,-103.7239,-0.3366,0.457,-1.8422,-1.2747
|
||||||
|
Potsdam Rauenberg DHDN,4314,6314,9122,7004,8901,9603,606,23,413,,,,
|
||||||
|
Conakry 1905,4315,6315,9122,7011,8901,9603,-23,259,-9,,,,
|
||||||
|
Dealul Piscului 1930,4316,6316,9122,7022,8901,9603,103.25,-100.4,-307.19,,,,
|
||||||
|
Dealul Piscului 1970,4317,6317,9122,7024,8901,9603,28,-121,-77,,,,
|
||||||
|
NGN,4318,6318,9122,7030,8901,9603,-3.2,-5.7,2.8,,,,
|
||||||
|
KUDAMS,4319,6319,9122,7019,8901,9603,-20.8,11.3,2.4,,,,
|
||||||
|
WGS 72,4322,6322,9122,7043,8901,9603,0,0,5,,,,
|
||||||
|
WGS 72BE,4324,6324,9122,7043,8901,9606,0,0,1.9,0,0,0.814,-0.38
|
||||||
|
RGSPM06,4463,1038,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
RGM04,4470,1036,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Cadastre 1997,4475,1037,9122,7022,8901,9603,-381.788,-57.501,-256.673,,,,
|
||||||
|
Mexico ITRF92,4483,1042,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
RRAF 1991,4558,1047,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Antigua 1943,4601,6601,9122,7012,8901,9603,-255,-15,71,,,,
|
||||||
|
Dominica 1945,4602,6602,9122,7012,8901,9603,725,685,536,,,,
|
||||||
|
Grenada 1953,4603,6603,9122,7012,8901,9603,72,213.7,93,,,,
|
||||||
|
Montserrat 1958,4604,6604,9122,7012,8901,9603,174,359,365,,,,
|
||||||
|
St. Kitts 1955,4605,6605,9122,7012,8901,9603,9,183,236,,,,
|
||||||
|
St. Lucia 1955,4606,6606,9122,7012,8901,9603,-149,128,296,,,,
|
||||||
|
St. Vincent 1945,4607,6607,9122,7012,8901,9603,195.671,332.517,274.607,,,,
|
||||||
|
Hong Kong 1980,4611,6611,9122,7022,8901,9606,-162.619,-276.959,-161.764,0.067753,-2.243649,-1.158827,-1.094246
|
||||||
|
JGD2000,4612,6612,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Segara,4613,6613,9122,7004,8901,9603,-403,684,41,,,,
|
||||||
|
QND95,4614,6614,9122,7022,8901,9606,-119.4248,-303.65872,-11.00061,1.164298,0.174458,1.096259,3.657065
|
||||||
|
Southeast Base,4615,6615,9122,7022,8901,9603,-499,-249,314,,,,
|
||||||
|
Marco Astro,4616,6616,9122,7022,8901,9603,-289,-124,60,,,,
|
||||||
|
NAD83(CSRS),4617,6140,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
SAD69,4618,6618,9122,7050,8901,9603,-66.87,4.37,-38.52,,,,
|
||||||
|
SWEREF99,4619,6619,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Point 58,4620,6620,9122,7012,8901,9603,-106,-129,165,,,,
|
||||||
|
Fort Marigot,4621,6621,9122,7022,8901,9603,137,248,-430,,,,
|
||||||
|
Guadeloupe 1948,4622,6622,9122,7022,8901,9603,-467,-16,-300,,,,
|
||||||
|
CSG67,4623,6623,9122,7022,8901,9603,-186,230,110,,,,
|
||||||
|
RGFG95,4624,6624,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Martinique 1938,4625,6625,9122,7022,8901,9603,186,482,151,,,,
|
||||||
|
Reunion,4626,6626,9122,7022,8901,9603,94,-948,-1262,,,,
|
||||||
|
RGR92,4627,6627,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Tahiti 52,4628,6628,9122,7022,8901,9603,162,117,154,,,,
|
||||||
|
Tahaa 54,4629,6629,9122,7022,8901,9607,72.438,345.918,79.486,-1.6045,-0.8823,-0.5565,1.3746
|
||||||
|
IGN72 Nuku Hiva,4630,6630,9122,7022,8901,9603,84,274,65,,,,
|
||||||
|
K0 1949,4631,6631,9122,7022,8901,9603,145,-187,103,,,,
|
||||||
|
Combani 1950,4632,6632,9122,7022,8901,9603,-382,-59,-262,,,,
|
||||||
|
IGN56 Lifou,4633,6633,9122,7022,8901,9603,335.47,222.58,-230.94,,,,
|
||||||
|
IGN72 Grand Terre,4634,6634,9108,7022,8901,9603,-13,-348,292,,,,
|
||||||
|
ST87 Ouvea,4635,6635,9122,7022,8901,9606,-122.383,-188.696,103.344,3.5107,-4.9668,-5.7047,4.4798
|
||||||
|
Petrels 1972,4636,6636,9122,7022,8901,9603,365,194,166,,,,
|
||||||
|
Perroud 1950,4637,6637,9122,7022,8901,9603,325,154,172,,,,
|
||||||
|
Saint Pierre et Miquelon 1950,4638,6638,9122,7008,8901,9603,30,430,368,,,,
|
||||||
|
MOP78,4639,6639,9122,7022,8901,9603,253,-132,-127,,,,
|
||||||
|
RRAF 1991,4640,6640,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
IGN53 Mare,4641,6641,9122,7022,8901,9603,287.58,177.78,-135.41,,,,
|
||||||
|
ST84 Ile des Pins,4642,6642,9122,7022,8901,9603,-13,-348,292,,,,
|
||||||
|
ST71 Belep,4643,6643,9122,7022,8901,9606,-480.26,-438.32,-643.429,16.3119,20.1721,-4.0349,-111.7002
|
||||||
|
NEA74 Noumea,4644,6644,9122,7022,8901,9603,-10.18,-350.43,291.37,,,,
|
||||||
|
RGNC 1991,4645,6645,9122,7022,8901,9603,0,0,0,,,,
|
||||||
|
Grand Comoros,4646,6646,9122,7022,8901,9603,-963,510,-359,,,,
|
||||||
|
Reykjavik 1900,4657,6657,9122,7051,8901,9603,-28,199,5,,,,
|
||||||
|
Hjorsey 1955,4658,6658,9122,7022,8901,9603,-73,46,-86,,,,
|
||||||
|
ISN93,4659,6659,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Helle 1954,4660,6660,9122,7022,8901,9606,982.6087,552.753,-540.873,6.6816266,-31.6114924,-19.84816,16.805
|
||||||
|
LKS92,4661,6661,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
IGN72 Grande Terre,4662,6634,9122,7022,8901,9603,-11.64,-348.6,291.98,,,,
|
||||||
|
Porto Santo 1995,4663,6663,9122,7022,8901,9603,-502.862,-247.438,312.724,,,,
|
||||||
|
Azores Oriental 1995,4664,6664,9122,7022,8901,9603,-204.619,140.176,55.226,,,,
|
||||||
|
Azores Central 1995,4665,6665,9122,7022,8901,9603,-106.226,166.366,-37.893,,,,
|
||||||
|
Lisbon 1890,4666,6666,9122,7004,8901,9603,508.088,-191.042,565.223,,,,
|
||||||
|
IKBD-92,4667,6667,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
European 1979,4668,6668,9122,7022,8901,9603,-86,-98,-119,,,,
|
||||||
|
LKS94,4669,6126,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
IGM95,4670,6670,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
Chatham 1971,4672,6672,9122,7022,8901,9603,175,-38,113,,,,
|
||||||
|
Chatham Islands 1979,4673,6673,9122,7022,8901,9607,174.05,-25.49,112.57,0,0,-0.554,0.2263
|
||||||
|
SIRGAS 2000,4674,6674,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Guam 1963,4675,6675,9122,7008,8901,9603,-100,-248,259,,,,
|
||||||
|
Lao 1997,4678,6678,9122,7024,8901,9603,44.585,-131.212,-39.544,,,,
|
||||||
|
Jouik 1961,4679,6679,9122,7012,8901,9603,-80.01,253.26,291.19,,,,
|
||||||
|
Nouakchott 1965,4680,6680,9122,7012,8901,9603,124.5,-63.5,-281,,,,
|
||||||
|
Indian Bangladesh,4682,6682,9122,7015,8901,9603,289,734,257,,,,
|
||||||
|
PRS92,4683,6683,9122,7008,8901,9607,-127.62,-67.24,-47.04,3.068,-4.903,-1.578,-1.06
|
||||||
|
Gan 1970,4684,6684,9122,7022,8901,9603,-133,-321,50,,,,
|
||||||
|
MAGNA-SIRGAS,4686,6686,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
RGPF,4687,6687,9122,7019,8901,9607,0.072,-0.507,-0.245,0.0183,-0.0003,0.007,-0.0093
|
||||||
|
Fatu Iva 72,4688,6688,9122,7022,8901,9607,347.103,1078.125,2623.922,33.8875,-70.6773,9.3943,186.074
|
||||||
|
IGN63 Hiva Oa,4689,6689,9122,7022,8901,9607,410.721,55.049,80.746,-2.5779,-2.3514,-0.6664,17.3311
|
||||||
|
Tahiti 79,4690,6690,9122,7022,8901,9607,221.525,152.948,176.768,2.3847,1.3896,0.877,11.4741
|
||||||
|
Moorea 87,4691,6691,9122,7022,8901,9607,215.525,149.593,176.229,3.2624,1.692,1.1571,10.4773
|
||||||
|
Maupiti 83,4692,6692,9122,7022,8901,9603,217.037,86.959,23.956,,,,
|
||||||
|
Nakhl-e Ghanem,4693,6693,9122,7030,8901,9603,0,-0.15,0.68,,,,
|
||||||
|
POSGAR 94,4694,6694,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
Katanga 1955,4695,6695,9122,7008,8901,9603,-103.746,-9.614,-255.95,,,,
|
||||||
|
Kerguelen Island,4698,6698,9122,7022,8901,9603,145,-187,103,,,,
|
||||||
|
Le Pouce 1934,4699,6699,9122,7012,8901,9603,-770.1,158.4,-498.2,,,,
|
||||||
|
IGCB 1955,4701,6701,9122,7012,8901,9603,-79.9,-158,-168.9,,,,
|
||||||
|
Mauritania 1999,4702,6702,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Egypt Gulf of Suez S-650 TL,4706,6706,9122,7020,8901,9603,-146.21,112.63,4.05,,,,
|
||||||
|
Astro B4 Sorol Atoll,4707,6707,9122,7022,8901,9603,114,-116,-333,,,,
|
||||||
|
Anna 1 Astro 1965,4708,6708,9122,7003,8901,9603,-491,-22,435,,,,
|
||||||
|
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,,,,
|
||||||
|
Ascension Island 1958,4712,6712,9122,7022,8901,9603,-207,107,52,,,,
|
||||||
|
Ayabelle Lighthouse,4713,6713,9122,7012,8901,9603,-77,-128,142,,,,
|
||||||
|
Bellevue (IGN),4714,6714,9122,7022,8901,9603,-127,-769,472,,,,
|
||||||
|
Camp Area Astro,4715,6715,9122,7022,8901,9603,-104,-129,239,,,,
|
||||||
|
Canton Astro 1966,4716,6716,9122,7022,8901,9603,298,-304,-375,,,,
|
||||||
|
Cape Canaveral,4717,6717,9122,7008,8901,9603,-2,150,181,,,,
|
||||||
|
GUX 1 Astro,4718,6718,9122,7022,8901,9603,252,-209,-751,,,,
|
||||||
|
Easter Island 1967,4719,6719,9122,7022,8901,9603,211,147,111,,,,
|
||||||
|
Fiji 1986,4720,6720,9122,7043,8901,9606,0,0,4.5,0,0,0.554,0.2263
|
||||||
|
Fiji 1956,4721,6721,9122,7022,8901,9603,265.025,384.929,-194.046,,,,
|
||||||
|
South Georgia 1968,4722,6722,9122,7022,8901,9603,-794,119,-298,,,,
|
||||||
|
GCGD59,4723,6723,9122,7008,8901,9607,-179.483,-69.379,-27.584,7.862,-8.163,-6.042,-13.925
|
||||||
|
ISTS 073 Astro 1969,4724,6724,9122,7022,8901,9603,208,-435,-229,,,,
|
||||||
|
Johnston Island,4725,6725,9122,7022,8901,9603,191,-77,-204,,,,
|
||||||
|
L.C. 5 Astro,4726,6726,9122,7008,8901,9603,42,124,147,,,,
|
||||||
|
Midway Astro 1961,4727,6727,9122,7022,8901,9603,912,-58,1227,,,,
|
||||||
|
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,,,,
|
||||||
|
Santo (DOS),4730,6730,9122,7022,8901,9603,170,42,84,,,,
|
||||||
|
Viti Levu 1916,4731,6731,9122,7012,8901,9603,51,391,-36,,,,
|
||||||
|
Wake-Eniwetok 1960,4732,6732,9122,7053,8901,9603,101,52,-39,,,,
|
||||||
|
Wake Island 1952,4733,6733,9122,7022,8901,9603,276,-57,149,,,,
|
||||||
|
Tristan Astro 1968,4734,6734,9122,7022,8901,9603,-632,438,-609,,,,
|
||||||
|
Kusaie 1951,4735,6735,9122,7022,8901,9603,647,1777,-1124,,,,
|
||||||
|
Deception Island,4736,6736,9122,7012,8901,9603,260,12,-147,,,,
|
||||||
|
Korea 2000,4737,6737,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Hong Kong 1963,4739,6739,9122,7022,8901,9603,-156,-271,-189,,,,
|
||||||
|
PZ-90,4740,6740,9122,7054,8901,9607,0,0,1.5,0,0,-0.076,0
|
||||||
|
Karbala 1979,4743,6743,9122,7012,8901,9603,70.995,-335.916,262.898,,,,
|
||||||
|
Nahrwan 1934,4744,6744,9122,7012,8901,9603,-242.2,-144.9,370.3,,,,
|
||||||
|
GR96,4747,6747,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Vanua Levu 1915,4748,6748,9122,7055,8901,9603,51,391,-36,,,,
|
||||||
|
RGNC91-93,4749,6749,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
ST87 Ouvea,4750,6750,9122,7030,8901,9603,-56.263,16.136,-22.856,,,,
|
||||||
|
Viti Levu 1912,4752,6752,9122,7055,8901,9603,98,390,-22,,,,
|
||||||
|
LGD2006,4754,6754,9122,7022,8901,9603,-208.4058,-109.8777,-2.5764,,,,
|
||||||
|
DGN95,4755,6755,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
VN-2000,4756,6756,9122,7030,8901,9607,-191.90441429,-39.30318279,-111.45032835,-0.00928836,0.01975479,-0.00427372,0.252906278
|
||||||
|
JAD2001,4758,6758,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
NAD83(NSRS2007),4759,6759,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
HTRS96,4761,6761,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
BDA2000,4762,6762,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
Pitcairn 2006,4763,6763,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
RSRGD2000,4764,6764,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Slovenia 1996,4765,6765,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Bern 1898 (Bern),4801,6801,9122,7004,8907,9603,674.374,15.056,405.346,,,,
|
||||||
|
Bogota 1975 (Bogota),4802,6802,9122,7022,8904,9603,307,304,-318,,,,
|
||||||
|
Lisbon (Lisbon),4803,6803,9122,7022,8902,9603,-304.046,-60.576,103.64,,,,
|
||||||
|
Makassar (Jakarta),4804,6804,9122,7004,8908,9603,-587.8,519.75,145.76,,,,
|
||||||
|
MGI (Ferro),4805,6805,9122,7004,8909,9603,682,-203,480,,,,
|
||||||
|
Rome 1940,4806,6806,9122,7022,8906,9603,-225,-65,9,,,,
|
||||||
|
NTF (Paris),4807,6807,9105,7011,8903,9603,-168,-60,320,,,,
|
||||||
|
Tananarive (Paris),4810,6810,9105,7022,8903,9603,-189,-242,-91,,,,
|
||||||
|
Voirol 1875 (Paris),4811,6811,9105,7011,8903,9603,-73,-247,227,,,,
|
||||||
|
Batavia (Jakarta),4813,6813,9122,7004,8908,9603,-377,681,-50,,,,
|
||||||
|
Carthage (Paris),4816,6816,9105,7011,8903,9603,-263,6,431,,,,
|
||||||
|
Norsk,4817,6817,9122,7005,8913,9603,278,93,474,,,,
|
||||||
|
S-JTSK (Ferro),4818,6818,9122,7004,8909,9603,589,76,480,,,,
|
||||||
|
Nord Sahara 1959 (Paris),4819,6819,9105,7012,8903,9606,-209.3622,-87.8162,404.6198,0.0046,3.4784,0.5805,-1.4547
|
||||||
|
Segara (Jakarta),4820,6820,9122,7004,8908,9603,-403,684,41,,,,
|
||||||
|
Lisbon 1890 (Lisbon),4904,6904,9122,7004,8902,9603,508.088,-191.042,565.223,,,,
|
||||||
|
PTRA08,5013,1041,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
S-JTSK/05,5228,1052,9122,7004,8901,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378
|
||||||
|
S-JTSK/05 (Ferro),5229,1055,9122,7004,8909,9607,572.213,85.334,461.94,-4.9732,-1.529,-5.2484,3.5378
|
||||||
|
SLD99,5233,1053,9122,7015,8901,9607,-0.293,766.95,87.713,-0.195704,-1.695068,-3.473016,-0.039338
|
||||||
|
GDBD2009,5246,1056,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
TUREF,5252,1057,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
DRUKREF 03,5264,1058,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
ISN2004,5324,1060,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
POSGAR 2007,5340,1062,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
MARGEN,5354,1063,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
SIRGAS-Chile,5360,1064,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
CR05,5365,1065,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
MACARIO SOLIS,5371,1066,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Peru96,5373,1067,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
SIRGAS-ROU98,5381,1068,9122,7030,8901,9603,0,0,0,,,,
|
||||||
|
SIRGAS_ES2007.8,5393,1069,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Ocotepeque 1935,5451,1070,9122,7008,8901,9603,205,96,-98,,,,
|
||||||
|
RGAF09,5489,1073,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
SAD69(96),5527,1075,9122,7050,8901,9603,-67.35,3.88,-38.22,,,,
|
||||||
|
PNG94,5546,1076,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
UCS-2000,5561,1077,9122,7024,8901,9607,25,-141,-78.5,0,-0.35,-0.736,0
|
||||||
|
FEH2010,5593,1078,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
CIGD11,6135,1100,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Nepal 1981,6207,1111,9122,7015,8901,9603,293.17,726.18,245.36,,,,
|
||||||
|
CGRS93,6311,1112,9122,7030,8901,9607,8.846,-4.394,-1.122,0.00237,0.146528,-0.130428,0.783926
|
||||||
|
Mexico ITRF2008,6365,1120,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
RDN2008,6706,1132,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
Aden 1925,6881,1135,9122,7012,8901,9603,-24,-203,268,,,,
|
||||||
|
Bekaa Valley 1920,6882,1137,9122,7012,8901,9603,-183,-15,273,,,,
|
||||||
|
Bioko,6883,1136,9122,7022,8901,9603,-235,-110,393,,,,
|
||||||
|
South East Island 1943,6892,1138,9122,7012,8901,9603,-43.685,-179.785,-267.721,,,,
|
||||||
|
Gambia,6894,1139,9122,7012,8901,9603,-63,176,185,,,,
|
||||||
|
ONGD14,7373,1147,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
St. Helena Tritan,7881,1173,9122,7030,8901,9603,-0.077,0.079,0.086,,,,
|
||||||
|
SHGD2015,7886,1174,9122,7019,8901,9603,0,0,0,,,,
|
||||||
|
DOS 1968,,,9122,7022,8901,9603,230,-199,-752,,,,
|
||||||
|
European 1950 (Mean France),,,9122,7022,8901,9603,-87,-96,-120,,,,
|
||||||
|
European 1950 (Spain and Portugal),,,9122,7022,8901,9603,-84,-107,-120,,,,
|
||||||
|
Luzon Mindanao,,,9122,7008,8901,9603,-133,-79,-72,,,,
|
||||||
|
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 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,,,,
|
||||||
|
Nahrwn Masirah Ilnd,,,9122,7012,8901,9603,-247,-148,369,,,,
|
||||||
|
Nahrwn Saudi Arbia,,,9122,7012,8901,9603,-231,-196,482,,,,
|
||||||
|
Pulkovo 1942 (2),,,9122,7024,8901,9603,28,-130,-95,,,,
|
||||||
|
|
1895
pkg/csv/pcs.csv
1895
pkg/csv/pcs.csv
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ Name=GPXSee
|
|||||||
Comment=GPS log file viewer and analyzer
|
Comment=GPS log file viewer and analyzer
|
||||||
Comment[cz]=Prohlížeč a analyzátor GPS logů
|
Comment[cz]=Prohlížeč a analyzátor GPS logů
|
||||||
Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
|
Comment[fi]=Ohjelma GPS-lokien katseluun ja analysointiin
|
||||||
|
Comment[pl]=Przeglądarka i analizator plików dziennika GPS
|
||||||
Comment[ru]=Программа для просмотра и анализа GPS логов
|
Comment[ru]=Программа для просмотра и анализа GPS логов
|
||||||
Comment[sv]=GPS-loggfilsläsare och analysator
|
Comment[sv]=GPS-loggfilsläsare och analysator
|
||||||
Exec=gpxsee %F
|
Exec=gpxsee %F
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
; The name of the installer
|
; The name of the installer
|
||||||
Name "GPXSee"
|
Name "GPXSee"
|
||||||
; Program version
|
; Program version
|
||||||
!define VERSION "5.9"
|
!define VERSION "5.16"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}.exe"
|
OutFile "GPXSee-${VERSION}.exe"
|
||||||
@ -167,6 +167,7 @@ Section "QT framework" SEC_QT
|
|||||||
File /r "platforms"
|
File /r "platforms"
|
||||||
File /r "imageformats"
|
File /r "imageformats"
|
||||||
File /r "printsupport"
|
File /r "printsupport"
|
||||||
|
File /r "styles"
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
; The name of the installer
|
; The name of the installer
|
||||||
Name "GPXSee"
|
Name "GPXSee"
|
||||||
; Program version
|
; Program version
|
||||||
!define VERSION "5.9"
|
!define VERSION "5.16"
|
||||||
|
|
||||||
; The file to write
|
; The file to write
|
||||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||||
@ -174,6 +174,7 @@ Section "QT framework" SEC_QT
|
|||||||
File /r "platforms"
|
File /r "platforms"
|
||||||
File /r "imageformats"
|
File /r "imageformats"
|
||||||
File /r "printsupport"
|
File /r "printsupport"
|
||||||
|
File /r "styles"
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map xmlns="http://www.gpxsee.org/map/1">
|
<map xmlns="http://www.gpxsee.org/map/1">
|
||||||
<name>4UMaps</name>
|
<name>4UMaps</name>
|
||||||
<url>http://4umaps.eu/$z/$x/$y.png</url>
|
<url>https://4umaps.com/$z/$x/$y.png</url>
|
||||||
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
|
<copyright>Map data: © OpenStreetMap contributors (ODbL) | Rendering: © 4UMaps.eu</copyright>
|
||||||
<zoom min="2" max="15"/>
|
<zoom min="2" max="15"/>
|
||||||
<bounds bottom="-65"/>
|
<bounds bottom="-65"/>
|
||||||
|
@ -3,10 +3,8 @@
|
|||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
#include <QFileOpenEvent>
|
#include <QFileOpenEvent>
|
||||||
#include <QNetworkProxyFactory>
|
#include <QNetworkProxyFactory>
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
#include <QLibraryInfo>
|
#include <QLibraryInfo>
|
||||||
#include "map/wmts.h"
|
|
||||||
#include "map/wms.h"
|
|
||||||
#include "map/tileloader.h"
|
|
||||||
#include "map/downloader.h"
|
#include "map/downloader.h"
|
||||||
#include "map/ellipsoid.h"
|
#include "map/ellipsoid.h"
|
||||||
#include "map/gcs.h"
|
#include "map/gcs.h"
|
||||||
@ -38,10 +36,7 @@ App::App(int &argc, char **argv) : QApplication(argc, argv),
|
|||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
|
|
||||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||||
Downloader *dl = new Downloader(this);
|
Downloader::setNetworkAccessManager(new QNetworkAccessManager(this));
|
||||||
TileLoader::setDownloader(dl);
|
|
||||||
WMTS::setDownloader(dl);
|
|
||||||
WMS::setDownloader(dl);
|
|
||||||
OPENGL_SET_SAMPLES(4);
|
OPENGL_SET_SAMPLES(4);
|
||||||
loadDatums();
|
loadDatums();
|
||||||
loadPCSs();
|
loadPCSs();
|
||||||
|
@ -11,23 +11,28 @@
|
|||||||
#define XTICKS 15
|
#define XTICKS 15
|
||||||
#define YTICKS 10
|
#define YTICKS 10
|
||||||
|
|
||||||
struct Label {
|
class Ticks
|
||||||
double min;
|
{
|
||||||
double max;
|
public:
|
||||||
double d;
|
Ticks(double minValue, double maxValue, int maxCount);
|
||||||
|
|
||||||
|
int count() const {return ((int)((_max - _min) / _d)) + 1;}
|
||||||
|
double val(int i) const {return _min + i * _d;}
|
||||||
|
double min() const {return _min;}
|
||||||
|
double max() const {return _max;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double _min;
|
||||||
|
double _max;
|
||||||
|
double _d;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct Label label(double min, double max, int ticks)
|
Ticks::Ticks(double minValue, double maxValue, int maxCount)
|
||||||
{
|
{
|
||||||
double range;
|
double range = niceNum(maxValue - minValue, 0);
|
||||||
struct Label l;
|
_d = niceNum(range / maxCount, 1);
|
||||||
|
_min = ceil(minValue / _d) * _d;
|
||||||
range = niceNum(max - min, 0);
|
_max = floor(maxValue / _d) * _d;
|
||||||
l.d = niceNum(range / ticks, 1);
|
|
||||||
l.min = ceil(min / l.d) * l.d;
|
|
||||||
l.max = floor(max / l.d) * l.d;
|
|
||||||
|
|
||||||
return l;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +41,9 @@ AxisItem::AxisItem(Type type, QGraphicsItem *parent) : QGraphicsItem(parent)
|
|||||||
_type = type;
|
_type = type;
|
||||||
_size = 0;
|
_size = 0;
|
||||||
|
|
||||||
|
_font.setPixelSize(FONT_SIZE);
|
||||||
|
_font.setFamily(FONT_FAMILY);
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
@ -45,6 +53,16 @@ void AxisItem::setRange(const RangeF &range)
|
|||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_range = range;
|
_range = range;
|
||||||
|
|
||||||
|
QFontMetrics fm(_font);
|
||||||
|
Ticks ticks(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
||||||
|
_ticks = QVector<Tick>(ticks.count());
|
||||||
|
for (int i = 0; i < ticks.count(); i++) {
|
||||||
|
Tick &t = _ticks[i];
|
||||||
|
t.value = ticks.val(i);
|
||||||
|
t.boundingBox = fm.tightBoundingRect(QString::number(t.value));
|
||||||
|
}
|
||||||
|
|
||||||
updateBoundingRect();
|
updateBoundingRect();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@ -60,42 +78,28 @@ void AxisItem::setSize(qreal size)
|
|||||||
void AxisItem::setLabel(const QString& label)
|
void AxisItem::setLabel(const QString& label)
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
|
QFontMetrics fm(_font);
|
||||||
_label = label;
|
_label = label;
|
||||||
|
_labelBB = fm.tightBoundingRect(label);
|
||||||
updateBoundingRect();
|
updateBoundingRect();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AxisItem::updateBoundingRect()
|
void AxisItem::updateBoundingRect()
|
||||||
{
|
{
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
|
||||||
font.setFamily(FONT_FAMILY);
|
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
|
||||||
QFontMetrics fm(font);
|
QRect ls(_labelBB);
|
||||||
QRect ss, es, ls;
|
|
||||||
struct Label l;
|
|
||||||
|
|
||||||
|
|
||||||
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
|
||||||
es = fm.tightBoundingRect(QString::number(l.max));
|
|
||||||
ss = fm.tightBoundingRect(QString::number(l.min));
|
|
||||||
ls = fm.tightBoundingRect(_label);
|
|
||||||
|
|
||||||
if (_type == X) {
|
if (_type == X) {
|
||||||
_boundingRect = QRectF(-ss.width()/2, -TICK/2,
|
_boundingRect = QRectF(-ss.width()/2, -TICK/2, _size + es.width()/2
|
||||||
_size + es.width()/2 + ss.width()/2,
|
+ ss.width()/2, ls.height() + es.height() - fm.descent() + TICK
|
||||||
ls.height() + es.height() - fm.descent() + TICK + 2*PADDING + 1);
|
+ 2*PADDING + 1);
|
||||||
} else {
|
} else {
|
||||||
int mtw = 0;
|
int mtw = 0;
|
||||||
QRect ts;
|
for (int i = 0; i < _ticks.count(); i++)
|
||||||
qreal val;
|
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
|
||||||
|
|
||||||
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
|
||||||
val = l.min + i * l.d;
|
|
||||||
QString str = QString::number(val);
|
|
||||||
ts = fm.tightBoundingRect(str);
|
|
||||||
mtw = qMax(ts.width(), mtw);
|
|
||||||
}
|
|
||||||
|
|
||||||
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING + TICK/2),
|
_boundingRect = QRectF(-(ls.height() + mtw + 2*PADDING + TICK/2),
|
||||||
-(_size + es.height()/2 + fm.descent()), ls.height() + mtw + 2*PADDING
|
-(_size + es.height()/2 + fm.descent()), ls.height() + mtw + 2*PADDING
|
||||||
+ TICK, _size + es.height()/2 + fm.descent() + ss.height()/2);
|
+ TICK, _size + es.height()/2 + fm.descent() + ss.height()/2);
|
||||||
@ -107,60 +111,50 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget);
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
QRect ts;
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect ts, ls;
|
|
||||||
struct Label l;
|
|
||||||
qreal range = _range.size();
|
|
||||||
qreal val;
|
|
||||||
QPen pen = QPen(Qt::black, AXIS_WIDTH);
|
|
||||||
|
|
||||||
|
|
||||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||||
painter->setFont(font);
|
painter->setFont(_font);
|
||||||
painter->setPen(pen);
|
painter->setPen(QPen(Qt::black, AXIS_WIDTH));
|
||||||
|
|
||||||
ls = fm.tightBoundingRect(_label);
|
|
||||||
|
|
||||||
if (_type == X) {
|
if (_type == X) {
|
||||||
painter->drawLine(0, 0, _size, 0);
|
painter->drawLine(0, 0, _size, 0);
|
||||||
|
|
||||||
l = label(_range.min(), _range.max(), XTICKS);
|
for (int i = 0; i < _ticks.count(); i++) {
|
||||||
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
qreal val = _ticks.at(i).value;
|
||||||
val = l.min + i * l.d;
|
ts = _ticks.at(i).boundingBox;
|
||||||
QString str = QString::number(val);
|
|
||||||
|
|
||||||
painter->drawLine((_size/range) * (val - _range.min()), TICK/2,
|
painter->drawLine((_size/_range.size()) * (val - _range.min()),
|
||||||
(_size/range) * (val - _range.min()), -TICK/2);
|
TICK/2, (_size/_range.size()) * (val - _range.min()), -TICK/2);
|
||||||
ts = fm.tightBoundingRect(str);
|
painter->drawText(((_size/_range.size()) * (val - _range.min()))
|
||||||
painter->drawText(((_size/range) * (val - _range.min()))
|
- (ts.width()/2), ts.height() + TICK/2 + PADDING,
|
||||||
- (ts.width()/2), ts.height() + TICK/2 + PADDING, str);
|
QString::number(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->drawText(_size/2 - ls.width()/2, ls.height() + ts.height()
|
painter->drawText(_size/2 - _labelBB.width()/2, _labelBB.height()
|
||||||
- 2*fm.descent() + TICK/2 + 2*PADDING, _label);
|
+ ts.height() - 2*fm.descent() + TICK/2 + 2*PADDING, _label);
|
||||||
} else {
|
} else {
|
||||||
painter->drawLine(0, 0, 0, -_size);
|
painter->drawLine(0, 0, 0, -_size);
|
||||||
|
|
||||||
l = label(_range.min(), _range.max(), YTICKS);
|
|
||||||
int mtw = 0;
|
int mtw = 0;
|
||||||
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
for (int i = 0; i < _ticks.count(); i++) {
|
||||||
val = l.min + i * l.d;
|
qreal val = _ticks.at(i).value;
|
||||||
QString str = QString::number(val);
|
ts = _ticks.at(i).boundingBox;
|
||||||
|
|
||||||
painter->drawLine(TICK/2, -((_size/range) * (val - _range.min())),
|
|
||||||
-TICK/2, -((_size/range) * (val - _range.min())));
|
|
||||||
ts = fm.tightBoundingRect(str);
|
|
||||||
mtw = qMax(ts.width(), mtw);
|
mtw = qMax(ts.width(), mtw);
|
||||||
painter->drawText(-(ts.width() + PADDING + TICK/2), -((_size/range)
|
|
||||||
* (val - _range.min())) + (ts.height()/2), str);
|
painter->drawLine(TICK/2, -((_size/_range.size())
|
||||||
|
* (val - _range.min())), -TICK/2, -((_size/_range.size())
|
||||||
|
* (val - _range.min())));
|
||||||
|
painter->drawText(-(ts.width() + PADDING + TICK/2),
|
||||||
|
-((_size/_range.size()) * (val - _range.min())) + (ts.height()/2),
|
||||||
|
QString::number(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->rotate(-90);
|
painter->rotate(-90);
|
||||||
painter->drawText(_size/2 - ls.width()/2, -(mtw + 2*PADDING + TICK/2),
|
painter->drawText(_size/2 - _labelBB.width()/2, -(mtw + 2*PADDING
|
||||||
_label);
|
+ TICK/2), _label);
|
||||||
painter->rotate(90);
|
painter->rotate(90);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,46 +166,28 @@ void AxisItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
|||||||
|
|
||||||
QSizeF AxisItem::margin() const
|
QSizeF AxisItem::margin() const
|
||||||
{
|
{
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect ss, es, ls;
|
|
||||||
struct Label l;
|
|
||||||
|
|
||||||
|
|
||||||
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
|
||||||
es = fm.tightBoundingRect(QString::number(l.max));
|
|
||||||
ss = fm.tightBoundingRect(QString::number(l.min));
|
|
||||||
ls = fm.tightBoundingRect(_label);
|
|
||||||
|
|
||||||
if (_type == X) {
|
if (_type == X) {
|
||||||
return QSizeF(es.width()/2,
|
return QSizeF(es.width()/2, _labelBB.height() + es.height()
|
||||||
ls.height() + es.height() - fm.descent() + TICK/2 + 2*PADDING);
|
- fm.descent() + TICK/2 + 2*PADDING);
|
||||||
} else {
|
} else {
|
||||||
int mtw = 0;
|
int mtw = 0;
|
||||||
QRect ts;
|
for (int i = 0; i < _ticks.count(); i++)
|
||||||
qreal val;
|
mtw = qMax(_ticks.at(i).boundingBox.width(), mtw);
|
||||||
|
|
||||||
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++) {
|
return QSizeF(_labelBB.height() -fm.descent() + mtw + 2*PADDING
|
||||||
val = l.min + i * l.d;
|
|
||||||
QString str = QString::number(val);
|
|
||||||
ts = fm.tightBoundingRect(str);
|
|
||||||
mtw = qMax(ts.width(), mtw);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QSizeF(ls.height() -fm.descent() + mtw + 2*PADDING
|
|
||||||
+ TICK/2, es.height()/2 + fm.descent());
|
+ TICK/2, es.height()/2 + fm.descent());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<qreal> AxisItem::ticks() const
|
QList<qreal> AxisItem::ticks() const
|
||||||
{
|
{
|
||||||
struct Label l;
|
|
||||||
QList<qreal> list;
|
QList<qreal> list;
|
||||||
|
|
||||||
l = label(_range.min(), _range.max(), (_type == X) ? XTICKS : YTICKS);
|
for (int i = 0; i < _ticks.count(); i++)
|
||||||
for (int i = 0; i < ((l.max - l.min) / l.d) + 1; i++)
|
list.append(((_size/_range.size()) * (_ticks.at(i).value
|
||||||
list.append(((_size/_range.size()) * ((l.min + i * l.d)
|
|
||||||
- _range.min())));
|
- _range.min())));
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define AXISITEM_H
|
#define AXISITEM_H
|
||||||
|
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
|
#include <QVector>
|
||||||
#include "common/range.h"
|
#include "common/range.h"
|
||||||
|
|
||||||
class AxisItem : public QGraphicsItem
|
class AxisItem : public QGraphicsItem
|
||||||
@ -23,13 +24,21 @@ public:
|
|||||||
QList<qreal> ticks() const;
|
QList<qreal> ticks() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Tick {
|
||||||
|
double value;
|
||||||
|
QRect boundingBox;
|
||||||
|
};
|
||||||
|
|
||||||
void updateBoundingRect();
|
void updateBoundingRect();
|
||||||
|
|
||||||
Type _type;
|
Type _type;
|
||||||
RangeF _range;
|
RangeF _range;
|
||||||
qreal _size;
|
qreal _size;
|
||||||
QString _label;
|
QString _label;
|
||||||
|
QRect _labelBB;
|
||||||
|
QVector<Tick> _ticks;
|
||||||
QRectF _boundingRect;
|
QRectF _boundingRect;
|
||||||
|
QFont _font;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AXISITEM_H
|
#endif // AXISITEM_H
|
||||||
|
@ -24,28 +24,33 @@ void CadenceGraph::setInfo()
|
|||||||
clearInfo();
|
clearInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CadenceGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> CadenceGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
const Graph &graph = data.tracks().at(i)->cadence();
|
const Graph &graph = data.tracks().at(i)->cadence();
|
||||||
|
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
continue;
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
CadenceGraphItem *gi = new CadenceGraphItem(graph, _graphType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
||||||
|
graphs.append(gi);
|
||||||
}
|
}
|
||||||
|
|
||||||
CadenceGraphItem *gi = new CadenceGraphItem(graph, _graphType);
|
|
||||||
GraphView::addGraph(gi, paths.at(i));
|
|
||||||
|
|
||||||
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
skipColor();
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal CadenceGraph::avg() const
|
qreal CadenceGraph::avg() const
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
CadenceGraph(QWidget *parent = 0);
|
CadenceGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Cadence");}
|
QString label() const {return tr("Cadence");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void showTracks(bool show);
|
void showTracks(bool show);
|
||||||
void showRoutes(bool show) {Q_UNUSED(show);}
|
void showRoutes(bool show) {Q_UNUSED(show);}
|
||||||
|
@ -65,15 +65,15 @@ void ElevationGraph::setInfo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElevationGraph::loadGraph(const Graph &graph, Type type, PathItem *path)
|
GraphItem *ElevationGraph::loadGraph(const Graph &graph, Type type)
|
||||||
{
|
{
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ElevationGraphItem *gi = new ElevationGraphItem(graph, _graphType);
|
ElevationGraphItem *gi = new ElevationGraphItem(graph, _graphType);
|
||||||
GraphView::addGraph(gi, path, type);
|
GraphView::addGraph(gi, type);
|
||||||
|
|
||||||
if (type == Track) {
|
if (type == Track) {
|
||||||
_trackAscent += gi->ascent();
|
_trackAscent += gi->ascent();
|
||||||
@ -86,20 +86,23 @@ void ElevationGraph::loadGraph(const Graph &graph, Type type, PathItem *path)
|
|||||||
_routeMax = nMax(_routeMax, gi->max());
|
_routeMax = nMax(_routeMax, gi->max());
|
||||||
_routeMin = nMin(_routeMin, gi->min());
|
_routeMin = nMin(_routeMin, gi->min());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return gi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElevationGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> ElevationGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
int p = 0;
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++)
|
for (int i = 0; i < data.tracks().count(); i++)
|
||||||
loadGraph(data.tracks().at(i)->elevation(), Track, paths.at(p++));
|
graphs.append(loadGraph(data.tracks().at(i)->elevation(), Track));
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++)
|
||||||
loadGraph(data.routes().at(i)->elevation(), Route, paths.at(p++));
|
graphs.append(loadGraph(data.routes().at(i)->elevation(), Route));
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ElevationGraph::clear()
|
void ElevationGraph::clear()
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
ElevationGraph(QWidget *parent = 0);
|
ElevationGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Elevation");}
|
QString label() const {return tr("Elevation");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void setUnits(enum Units units);
|
void setUnits(enum Units units);
|
||||||
void showTracks(bool show);
|
void showTracks(bool show);
|
||||||
@ -28,7 +28,7 @@ private:
|
|||||||
void setYUnits(Units units);
|
void setYUnits(Units units);
|
||||||
void setInfo();
|
void setInfo();
|
||||||
|
|
||||||
void loadGraph(const Graph &graph, Type type, PathItem *path);
|
GraphItem *loadGraph(const Graph &graph, Type type);
|
||||||
|
|
||||||
qreal _trackAscent, _trackDescent;
|
qreal _trackAscent, _trackDescent;
|
||||||
qreal _routeAscent, _routeDescent;
|
qreal _routeAscent, _routeDescent;
|
||||||
|
@ -42,9 +42,9 @@ ExportDialog::ExportDialog(Export *exp, QWidget *parent)
|
|||||||
_paperSize->setCurrentIndex(index);
|
_paperSize->setCurrentIndex(index);
|
||||||
|
|
||||||
_resolution = new QComboBox();
|
_resolution = new QComboBox();
|
||||||
|
_resolution->addItem("150 DPI", 150);
|
||||||
_resolution->addItem("300 DPI", 300);
|
_resolution->addItem("300 DPI", 300);
|
||||||
_resolution->addItem("600 DPI", 600);
|
_resolution->addItem("600 DPI", 600);
|
||||||
_resolution->addItem("1200 DPI", 1200);
|
|
||||||
if ((index = _resolution->findData(_export->resolution)) >= 0)
|
if ((index = _resolution->findData(_export->resolution)) >= 0)
|
||||||
_resolution->setCurrentIndex(index);
|
_resolution->setCurrentIndex(index);
|
||||||
|
|
||||||
|
@ -13,11 +13,6 @@ FileBrowser::FileBrowser(QObject *parent) : QObject(parent)
|
|||||||
_index = -1;
|
_index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBrowser::~FileBrowser()
|
|
||||||
{
|
|
||||||
delete _watcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileBrowser::setCurrent(const QString &path)
|
void FileBrowser::setCurrent(const QString &path)
|
||||||
{
|
{
|
||||||
QFileInfo file(path);
|
QFileInfo file(path);
|
||||||
|
@ -13,7 +13,6 @@ class FileBrowser : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FileBrowser(QObject *parent = 0);
|
FileBrowser(QObject *parent = 0);
|
||||||
~FileBrowser();
|
|
||||||
|
|
||||||
void setFilter(const QStringList &filter);
|
void setFilter(const QStringList &filter);
|
||||||
void setCurrent(const QString &path);
|
void setCurrent(const QString &path);
|
||||||
|
94
src/GUI/gearratiograph.cpp
Normal file
94
src/GUI/gearratiograph.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#include "data/data.h"
|
||||||
|
#include "gearratiographitem.h"
|
||||||
|
#include "gearratiograph.h"
|
||||||
|
|
||||||
|
|
||||||
|
GearRatioGraph::GearRatioGraph(QWidget *parent) : GraphTab(parent)
|
||||||
|
{
|
||||||
|
_showTracks = true;
|
||||||
|
|
||||||
|
GraphView::setYUnits("");
|
||||||
|
setYLabel(tr("Gear ratio"));
|
||||||
|
|
||||||
|
setSliderPrecision(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearRatioGraph::setInfo()
|
||||||
|
{
|
||||||
|
if (_showTracks) {
|
||||||
|
GraphView::addInfo(tr("Most used"), QString::number(top() * yScale(),
|
||||||
|
'f', 2) + UNIT_SPACE + yUnits());
|
||||||
|
GraphView::addInfo(tr("Minimum"), QString::number(min() * yScale(), 'f',
|
||||||
|
2) + UNIT_SPACE + yUnits());
|
||||||
|
GraphView::addInfo(tr("Maximum"), QString::number(max() * yScale(), 'f',
|
||||||
|
2) + UNIT_SPACE + yUnits());
|
||||||
|
} else
|
||||||
|
clearInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<GraphItem*> GearRatioGraph::loadData(const Data &data)
|
||||||
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
|
const Graph &graph = data.tracks().at(i)->ratio();
|
||||||
|
|
||||||
|
if (graph.size() < 2) {
|
||||||
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
GearRatioGraphItem *gi = new GearRatioGraphItem(graph, _graphType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
|
||||||
|
for (QMap<qreal, qreal>::const_iterator it = gi->map().constBegin();
|
||||||
|
it != gi->map().constEnd(); ++it)
|
||||||
|
_map.insert(it.key(), _map.value(it.key()) + it.value());
|
||||||
|
graphs.append(gi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
setInfo();
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal GearRatioGraph::top() const
|
||||||
|
{
|
||||||
|
qreal key = NAN, val = NAN;
|
||||||
|
|
||||||
|
for (QMap<qreal, qreal>::const_iterator it = _map.constBegin();
|
||||||
|
it != _map.constEnd(); ++it) {
|
||||||
|
if (it == _map.constBegin()) {
|
||||||
|
val = it.value();
|
||||||
|
key = it.key();
|
||||||
|
} else if (it.value() > val) {
|
||||||
|
val = it.value();
|
||||||
|
key = it.key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearRatioGraph::clear()
|
||||||
|
{
|
||||||
|
_map.clear();
|
||||||
|
|
||||||
|
GraphView::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearRatioGraph::showTracks(bool show)
|
||||||
|
{
|
||||||
|
_showTracks = show;
|
||||||
|
|
||||||
|
showGraph(show);
|
||||||
|
setInfo();
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
30
src/GUI/gearratiograph.h
Normal file
30
src/GUI/gearratiograph.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef GEARRATIOGRAPH_H
|
||||||
|
#define GEARRATIOGRAPH_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include "graphtab.h"
|
||||||
|
|
||||||
|
class GearRatioGraph : public GraphTab
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GearRatioGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
|
QString label() const {return tr("Gear ratio");}
|
||||||
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
|
void clear();
|
||||||
|
void showTracks(bool show);
|
||||||
|
|
||||||
|
private:
|
||||||
|
qreal top() const;
|
||||||
|
qreal min() const {return bounds().top();}
|
||||||
|
qreal max() const {return bounds().bottom();}
|
||||||
|
void setInfo();
|
||||||
|
|
||||||
|
QMap<qreal, qreal> _map;
|
||||||
|
|
||||||
|
bool _showTracks;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GEARRATIOGRAPH_H
|
39
src/GUI/gearratiographitem.cpp
Normal file
39
src/GUI/gearratiographitem.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include <QMap>
|
||||||
|
#include "tooltip.h"
|
||||||
|
#include "gearratiographitem.h"
|
||||||
|
|
||||||
|
GearRatioGraphItem::GearRatioGraphItem(const Graph &graph, GraphType type,
|
||||||
|
QGraphicsItem *parent) : GraphItem(graph, type, parent), _top(NAN)
|
||||||
|
{
|
||||||
|
qreal val = NAN;
|
||||||
|
|
||||||
|
for (int j = 1; j < graph.size(); j++) {
|
||||||
|
const GraphPoint &p = graph.at(j);
|
||||||
|
qreal val = _map.value(p.y());
|
||||||
|
_map.insert(p.y(), val + (p.s() - graph.at(j-1).s()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QMap<qreal, qreal>::const_iterator it = _map.constBegin();
|
||||||
|
it != _map.constEnd(); ++it) {
|
||||||
|
if (it == _map.constBegin()) {
|
||||||
|
val = it.value();
|
||||||
|
_top = it.key();
|
||||||
|
} else if (it.value() > val) {
|
||||||
|
val = it.value();
|
||||||
|
_top = it.key();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setToolTip(toolTip());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GearRatioGraphItem::toolTip() const
|
||||||
|
{
|
||||||
|
ToolTip tt;
|
||||||
|
|
||||||
|
tt.insert(tr("Minimum"), QString::number(min(), 'f', 2));
|
||||||
|
tt.insert(tr("Maximum"), QString::number(max(), 'f', 2));
|
||||||
|
tt.insert(tr("Most used"), QString::number(top(), 'f', 2));
|
||||||
|
|
||||||
|
return tt.toString();
|
||||||
|
}
|
28
src/GUI/gearratiographitem.h
Normal file
28
src/GUI/gearratiographitem.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef GEARRATIOGRAPHITEM_H
|
||||||
|
#define GEARRATIOGRAPHITEM_H
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
#include "graphitem.h"
|
||||||
|
|
||||||
|
class GearRatioGraphItem : public GraphItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GearRatioGraphItem(const Graph &graph, GraphType type,
|
||||||
|
QGraphicsItem *parent = 0);
|
||||||
|
|
||||||
|
qreal min() const {return -bounds().bottom();}
|
||||||
|
qreal max() const {return -bounds().top();}
|
||||||
|
qreal top() const {return _top;}
|
||||||
|
|
||||||
|
const QMap<qreal, qreal> &map() const {return _map;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString toolTip() const;
|
||||||
|
|
||||||
|
QMap<qreal, qreal> _map;
|
||||||
|
qreal _top;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GEARRATIOGRAPHITEM_H
|
@ -7,7 +7,7 @@
|
|||||||
#include "timetype.h"
|
#include "timetype.h"
|
||||||
|
|
||||||
class Data;
|
class Data;
|
||||||
class PathItem;
|
class GraphItem;
|
||||||
|
|
||||||
class GraphTab : public GraphView
|
class GraphTab : public GraphView
|
||||||
{
|
{
|
||||||
@ -19,7 +19,7 @@ public:
|
|||||||
virtual ~GraphTab() {}
|
virtual ~GraphTab() {}
|
||||||
|
|
||||||
virtual QString label() const = 0;
|
virtual QString label() const = 0;
|
||||||
virtual void loadData(const Data &data, const QList<PathItem *> &paths) = 0;
|
virtual QList<GraphItem*> loadData(const Data &data) = 0;
|
||||||
virtual void clear() {GraphView::clear();}
|
virtual void clear() {GraphView::clear();}
|
||||||
virtual void setUnits(enum Units units) {GraphView::setUnits(units);}
|
virtual void setUnits(enum Units units) {GraphView::setUnits(units);}
|
||||||
virtual void setGraphType(GraphType type) {GraphView::setGraphType(type);}
|
virtual void setGraphType(GraphType type) {GraphView::setGraphType(type);}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QPaintEngine>
|
#include <QPaintEngine>
|
||||||
#include <QPaintDevice>
|
#include <QPaintDevice>
|
||||||
|
#include <QGraphicsSimpleTextItem>
|
||||||
|
#include <QPalette>
|
||||||
#include "data/graph.h"
|
#include "data/graph.h"
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -41,6 +43,9 @@ GraphView::GraphView(QWidget *parent)
|
|||||||
_sliderInfo->setZValue(3.0);
|
_sliderInfo->setZValue(3.0);
|
||||||
_info = new InfoItem();
|
_info = new InfoItem();
|
||||||
_grid = new GridItem();
|
_grid = new GridItem();
|
||||||
|
_message = new QGraphicsSimpleTextItem(tr("Data not available"));
|
||||||
|
_message->setBrush(QPalette().brush(QPalette::Disabled,
|
||||||
|
QPalette::WindowText));
|
||||||
|
|
||||||
connect(_slider, SIGNAL(positionChanged(const QPointF&)), this,
|
connect(_slider, SIGNAL(positionChanged(const QPointF&)), this,
|
||||||
SLOT(emitSliderPositionChanged(const QPointF&)));
|
SLOT(emitSliderPositionChanged(const QPointF&)));
|
||||||
@ -63,30 +68,27 @@ GraphView::GraphView(QWidget *parent)
|
|||||||
|
|
||||||
GraphView::~GraphView()
|
GraphView::~GraphView()
|
||||||
{
|
{
|
||||||
if (_xAxis->scene() != _scene)
|
delete _xAxis;
|
||||||
delete _xAxis;
|
delete _yAxis;
|
||||||
if (_yAxis->scene() != _scene)
|
delete _slider;
|
||||||
delete _yAxis;
|
delete _info;
|
||||||
if (_slider->scene() != _scene)
|
delete _grid;
|
||||||
delete _slider;
|
delete _message;
|
||||||
if (_info->scene() != _scene)
|
|
||||||
delete _info;
|
|
||||||
if (_grid->scene() != _scene)
|
|
||||||
delete _grid;
|
|
||||||
|
|
||||||
for (int i = 0; i < _graphs.count(); i++)
|
for (int i = 0; i < _graphs.count(); i++)
|
||||||
if (_graphs.at(i)->scene() != _scene)
|
delete _graphs[i];
|
||||||
delete _graphs[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::createXLabel()
|
void GraphView::createXLabel()
|
||||||
{
|
{
|
||||||
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel, _xUnits));
|
_xAxis->setLabel(QString("%1 [%2]").arg(_xLabel,
|
||||||
|
_xUnits.isEmpty() ? "-" : _xUnits));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::createYLabel()
|
void GraphView::createYLabel()
|
||||||
{
|
{
|
||||||
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel, _yUnits));
|
_yAxis->setLabel(QString("%1 [%2]").arg(_yLabel,
|
||||||
|
_yUnits.isEmpty() ? "-" : _yUnits));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::setYLabel(const QString &label)
|
void GraphView::setYLabel(const QString &label)
|
||||||
@ -163,9 +165,16 @@ void GraphView::setGraphType(GraphType type)
|
|||||||
_bounds = QRectF();
|
_bounds = QRectF();
|
||||||
|
|
||||||
for (int i = 0; i < _graphs.count(); i++) {
|
for (int i = 0; i < _graphs.count(); i++) {
|
||||||
_graphs.at(i)->setGraphType(type);
|
GraphItem *gi = _graphs.at(i);
|
||||||
if (_graphs.at(i)->scene() == _scene)
|
gi->setGraphType(type);
|
||||||
_bounds |= _graphs.at(i)->bounds();
|
if (!_hide.contains(gi->id())) {
|
||||||
|
if (gi->bounds().width() > 0)
|
||||||
|
addItem(gi);
|
||||||
|
else
|
||||||
|
removeItem(gi);
|
||||||
|
}
|
||||||
|
if (gi->scene() == _scene)
|
||||||
|
_bounds |= gi->bounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == Distance)
|
if (type == Distance)
|
||||||
@ -187,7 +196,7 @@ void GraphView::showSliderInfo(bool show)
|
|||||||
_sliderInfo->setVisible(show);
|
_sliderInfo->setVisible(show);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::addGraph(GraphItem *graph, PathItem *path, int id)
|
void GraphView::addGraph(GraphItem *graph, int id)
|
||||||
{
|
{
|
||||||
QColor color(_palette.nextColor());
|
QColor color(_palette.nextColor());
|
||||||
color.setAlpha(255);
|
color.setAlpha(255);
|
||||||
@ -199,17 +208,15 @@ void GraphView::addGraph(GraphItem *graph, PathItem *path, int id)
|
|||||||
|
|
||||||
connect(this, SIGNAL(sliderPositionChanged(qreal)), graph,
|
connect(this, SIGNAL(sliderPositionChanged(qreal)), graph,
|
||||||
SLOT(emitSliderPositionChanged(qreal)));
|
SLOT(emitSliderPositionChanged(qreal)));
|
||||||
connect(graph, SIGNAL(sliderPositionChanged(qreal)), path,
|
|
||||||
SLOT(moveMarker(qreal)));
|
|
||||||
connect(path, SIGNAL(selected(bool)), graph, SLOT(hover(bool)));
|
|
||||||
connect(graph, SIGNAL(selected(bool)), path, SLOT(hover(bool)));
|
|
||||||
|
|
||||||
_graphs.append(graph);
|
_graphs.append(graph);
|
||||||
|
|
||||||
if (!_hide.contains(id)) {
|
if (!_hide.contains(id)) {
|
||||||
_visible.append(graph);
|
_visible.append(graph);
|
||||||
_scene->addItem(graph);
|
if (graph->bounds().width() > 0) {
|
||||||
_bounds |= graph->bounds();
|
_scene->addItem(graph);
|
||||||
|
_bounds |= graph->bounds();
|
||||||
|
}
|
||||||
setXUnits();
|
setXUnits();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,13 +243,15 @@ void GraphView::showGraph(bool show, int id)
|
|||||||
_visible.clear();
|
_visible.clear();
|
||||||
_bounds = QRectF();
|
_bounds = QRectF();
|
||||||
for (int i = 0; i < _graphs.count(); i++) {
|
for (int i = 0; i < _graphs.count(); i++) {
|
||||||
GraphItem* gi = _graphs.at(i);
|
GraphItem *gi = _graphs.at(i);
|
||||||
if (_hide.contains(gi->id()))
|
if (_hide.contains(gi->id()))
|
||||||
removeItem(gi);
|
removeItem(gi);
|
||||||
else {
|
else {
|
||||||
addItem(gi);
|
|
||||||
_visible.append(gi);
|
_visible.append(gi);
|
||||||
_bounds |= gi->bounds();
|
if (gi->bounds().width() > 0) {
|
||||||
|
addItem(gi);
|
||||||
|
_bounds |= gi->bounds();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,7 +265,8 @@ QRectF GraphView::bounds() const
|
|||||||
|
|
||||||
void GraphView::redraw()
|
void GraphView::redraw()
|
||||||
{
|
{
|
||||||
redraw(viewport()->size() - QSizeF(MARGIN, MARGIN));
|
if (!_graphs.isEmpty())
|
||||||
|
redraw(viewport()->size() - QSizeF(MARGIN, MARGIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::redraw(const QSizeF &size)
|
void GraphView::redraw(const QSizeF &size)
|
||||||
@ -267,16 +277,18 @@ void GraphView::redraw(const QSizeF &size)
|
|||||||
qreal sx, sy;
|
qreal sx, sy;
|
||||||
|
|
||||||
|
|
||||||
if (_visible.isEmpty() || _bounds.isNull()) {
|
if (_bounds.isNull()) {
|
||||||
removeItem(_xAxis);
|
removeItem(_xAxis);
|
||||||
removeItem(_yAxis);
|
removeItem(_yAxis);
|
||||||
removeItem(_slider);
|
removeItem(_slider);
|
||||||
removeItem(_info);
|
removeItem(_info);
|
||||||
removeItem(_grid);
|
removeItem(_grid);
|
||||||
_scene->setSceneRect(QRectF());
|
addItem(_message);
|
||||||
|
_scene->setSceneRect(_scene->itemsBoundingRect());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeItem(_message);
|
||||||
addItem(_xAxis);
|
addItem(_xAxis);
|
||||||
addItem(_yAxis);
|
addItem(_yAxis);
|
||||||
addItem(_slider);
|
addItem(_slider);
|
||||||
@ -312,6 +324,7 @@ void GraphView::redraw(const QSizeF &size)
|
|||||||
if (r.height() < _minYRange * sy)
|
if (r.height() < _minYRange * sy)
|
||||||
r.adjust(0, -(_minYRange/2 * sy - r.height()/2), 0,
|
r.adjust(0, -(_minYRange/2 * sy - r.height()/2), 0,
|
||||||
(_minYRange/2) * sy - r.height()/2);
|
(_minYRange/2) * sy - r.height()/2);
|
||||||
|
r = r.toRect();
|
||||||
|
|
||||||
_xAxis->setSize(r.width());
|
_xAxis->setSize(r.width());
|
||||||
_yAxis->setSize(r.height());
|
_yAxis->setSize(r.height());
|
||||||
@ -333,9 +346,11 @@ void GraphView::redraw(const QSizeF &size)
|
|||||||
_scene->setSceneRect(_scene->itemsBoundingRect());
|
_scene->setSceneRect(_scene->itemsBoundingRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::resizeEvent(QResizeEvent *)
|
void GraphView::resizeEvent(QResizeEvent *e)
|
||||||
{
|
{
|
||||||
redraw();
|
redraw(e->size() - QSizeF(MARGIN, MARGIN));
|
||||||
|
|
||||||
|
QGraphicsView::resizeEvent(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphView::mousePressEvent(QMouseEvent *e)
|
void GraphView::mousePressEvent(QMouseEvent *e)
|
||||||
|
@ -7,15 +7,16 @@
|
|||||||
#include "data/graph.h"
|
#include "data/graph.h"
|
||||||
#include "palette.h"
|
#include "palette.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "infoitem.h"
|
||||||
|
|
||||||
|
|
||||||
class AxisItem;
|
class AxisItem;
|
||||||
class SliderItem;
|
class SliderItem;
|
||||||
class SliderInfoItem;
|
class SliderInfoItem;
|
||||||
class InfoItem;
|
|
||||||
class GraphItem;
|
class GraphItem;
|
||||||
class PathItem;
|
class PathItem;
|
||||||
class GridItem;
|
class GridItem;
|
||||||
|
class QGraphicsSimpleTextItem;
|
||||||
|
|
||||||
class GraphView : public QGraphicsView
|
class GraphView : public QGraphicsView
|
||||||
{
|
{
|
||||||
@ -26,6 +27,7 @@ public:
|
|||||||
~GraphView();
|
~GraphView();
|
||||||
|
|
||||||
bool isEmpty() const {return _graphs.isEmpty();}
|
bool isEmpty() const {return _graphs.isEmpty();}
|
||||||
|
const QList<KV> &info() const {return _info->info();}
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void plot(QPainter *painter, const QRectF &target, qreal scale);
|
void plot(QPainter *painter, const QRectF &target, qreal scale);
|
||||||
@ -44,7 +46,7 @@ signals:
|
|||||||
void sliderPositionChanged(qreal);
|
void sliderPositionChanged(qreal);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void addGraph(GraphItem *graph, PathItem *path, int id = 0);
|
void addGraph(GraphItem *graph, int id = 0);
|
||||||
|
|
||||||
void showGraph(bool show, int id = 0);
|
void showGraph(bool show, int id = 0);
|
||||||
void setGraphType(GraphType type);
|
void setGraphType(GraphType type);
|
||||||
@ -64,7 +66,6 @@ protected:
|
|||||||
|
|
||||||
QRectF bounds() const;
|
QRectF bounds() const;
|
||||||
void redraw();
|
void redraw();
|
||||||
void redraw(const QSizeF &size);
|
|
||||||
void addInfo(const QString &key, const QString &value);
|
void addInfo(const QString &key, const QString &value);
|
||||||
void clearInfo();
|
void clearInfo();
|
||||||
void skipColor() {_palette.nextColor();}
|
void skipColor() {_palette.nextColor();}
|
||||||
@ -77,6 +78,7 @@ private slots:
|
|||||||
void newSliderPosition(const QPointF &pos);
|
void newSliderPosition(const QPointF &pos);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void redraw(const QSizeF &size);
|
||||||
void setXUnits();
|
void setXUnits();
|
||||||
void createXLabel();
|
void createXLabel();
|
||||||
void createYLabel();
|
void createYLabel();
|
||||||
@ -85,8 +87,8 @@ private:
|
|||||||
void removeItem(QGraphicsItem *item);
|
void removeItem(QGraphicsItem *item);
|
||||||
void addItem(QGraphicsItem *item);
|
void addItem(QGraphicsItem *item);
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent *);
|
void resizeEvent(QResizeEvent *e);
|
||||||
void mousePressEvent(QMouseEvent *);
|
void mousePressEvent(QMouseEvent *e);
|
||||||
|
|
||||||
Units _units;
|
Units _units;
|
||||||
qreal _xScale, _yScale;
|
qreal _xScale, _yScale;
|
||||||
@ -104,6 +106,7 @@ private:
|
|||||||
SliderInfoItem *_sliderInfo;
|
SliderInfoItem *_sliderInfo;
|
||||||
InfoItem *_info;
|
InfoItem *_info;
|
||||||
GridItem *_grid;
|
GridItem *_grid;
|
||||||
|
QGraphicsSimpleTextItem *_message;
|
||||||
|
|
||||||
QList<GraphItem*> _visible;
|
QList<GraphItem*> _visible;
|
||||||
QSet<int> _hide;
|
QSet<int> _hide;
|
||||||
|
@ -4,13 +4,6 @@
|
|||||||
|
|
||||||
#define GRID_WIDTH 0
|
#define GRID_WIDTH 0
|
||||||
|
|
||||||
GridItem::GridItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_MAC
|
|
||||||
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
|
||||||
#endif // Q_OS_MAC
|
|
||||||
}
|
|
||||||
|
|
||||||
void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void GridItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
QWidget *widget)
|
QWidget *widget)
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
class GridItem : public QGraphicsItem
|
class GridItem : public QGraphicsItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GridItem(QGraphicsItem *parent = 0);
|
GridItem(QGraphicsItem *parent = 0): QGraphicsItem(parent) {}
|
||||||
|
|
||||||
QRectF boundingRect() const {return _boundingRect;}
|
QRectF boundingRect() const {return _boundingRect;}
|
||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
|
272
src/GUI/gui.cpp
272
src/GUI/gui.cpp
@ -23,8 +23,10 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include "data/data.h"
|
#include "data/data.h"
|
||||||
|
#include "data/poi.h"
|
||||||
#include "map/maplist.h"
|
#include "map/maplist.h"
|
||||||
#include "map/emptymap.h"
|
#include "map/emptymap.h"
|
||||||
|
#include "map/downloader.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "icons.h"
|
#include "icons.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
@ -35,11 +37,14 @@
|
|||||||
#include "temperaturegraph.h"
|
#include "temperaturegraph.h"
|
||||||
#include "cadencegraph.h"
|
#include "cadencegraph.h"
|
||||||
#include "powergraph.h"
|
#include "powergraph.h"
|
||||||
|
#include "gearratiograph.h"
|
||||||
#include "mapview.h"
|
#include "mapview.h"
|
||||||
#include "trackinfo.h"
|
#include "trackinfo.h"
|
||||||
#include "filebrowser.h"
|
#include "filebrowser.h"
|
||||||
#include "cpuarch.h"
|
#include "cpuarch.h"
|
||||||
#include "graphtab.h"
|
#include "graphtab.h"
|
||||||
|
#include "graphitem.h"
|
||||||
|
#include "pathitem.h"
|
||||||
#include "gui.h"
|
#include "gui.h"
|
||||||
|
|
||||||
|
|
||||||
@ -57,15 +62,15 @@ GUI::GUI()
|
|||||||
|
|
||||||
createBrowser();
|
createBrowser();
|
||||||
|
|
||||||
QSplitter *splitter = new QSplitter();
|
_splitter = new QSplitter();
|
||||||
splitter->setOrientation(Qt::Vertical);
|
_splitter->setOrientation(Qt::Vertical);
|
||||||
splitter->setChildrenCollapsible(false);
|
_splitter->setChildrenCollapsible(false);
|
||||||
splitter->addWidget(_mapView);
|
_splitter->addWidget(_mapView);
|
||||||
splitter->addWidget(_graphTabWidget);
|
_splitter->addWidget(_graphTabWidget);
|
||||||
splitter->setContentsMargins(0, 0, 0, 0);
|
_splitter->setContentsMargins(0, 0, 0, 0);
|
||||||
splitter->setStretchFactor(0, 255);
|
_splitter->setStretchFactor(0, 255);
|
||||||
splitter->setStretchFactor(1, 1);
|
_splitter->setStretchFactor(1, 1);
|
||||||
setCentralWidget(splitter);
|
setCentralWidget(_splitter);
|
||||||
|
|
||||||
setWindowIcon(QIcon(QPixmap(APP_ICON)));
|
setWindowIcon(QIcon(QPixmap(APP_ICON)));
|
||||||
setWindowTitle(APP_NAME);
|
setWindowTitle(APP_NAME);
|
||||||
@ -93,14 +98,6 @@ GUI::GUI()
|
|||||||
updateStatusBarInfo();
|
updateStatusBarInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI::~GUI()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _tabs.size(); i++) {
|
|
||||||
if (_graphTabWidget->indexOf(_tabs.at(i)) < 0)
|
|
||||||
delete _tabs.at(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUI::loadMaps()
|
void GUI::loadMaps()
|
||||||
{
|
{
|
||||||
_ml = new MapList(this);
|
_ml = new MapList(this);
|
||||||
@ -145,6 +142,7 @@ void GUI::createMapActions()
|
|||||||
|
|
||||||
for (int i = 0; i < _ml->maps().count(); i++) {
|
for (int i = 0; i < _ml->maps().count(); i++) {
|
||||||
QAction *a = new QAction(_ml->maps().at(i)->name(), this);
|
QAction *a = new QAction(_ml->maps().at(i)->name(), this);
|
||||||
|
a->setMenuRole(QAction::NoRole);
|
||||||
a->setCheckable(true);
|
a->setCheckable(true);
|
||||||
a->setActionGroup(_mapsActionGroup);
|
a->setActionGroup(_mapsActionGroup);
|
||||||
|
|
||||||
@ -173,6 +171,7 @@ QAction *GUI::createPOIFileAction(int index)
|
|||||||
{
|
{
|
||||||
QAction *a = new QAction(QFileInfo(_poi->files().at(index)).fileName(),
|
QAction *a = new QAction(QFileInfo(_poi->files().at(index)).fileName(),
|
||||||
this);
|
this);
|
||||||
|
a->setMenuRole(QAction::NoRole);
|
||||||
a->setCheckable(true);
|
a->setCheckable(true);
|
||||||
|
|
||||||
_poiFilesSignalMapper->setMapping(a, index);
|
_poiFilesSignalMapper->setMapping(a, index);
|
||||||
@ -204,8 +203,10 @@ void GUI::createActions()
|
|||||||
|
|
||||||
// Help & About
|
// Help & About
|
||||||
_pathsAction = new QAction(tr("Paths"), this);
|
_pathsAction = new QAction(tr("Paths"), this);
|
||||||
|
_pathsAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_pathsAction, SIGNAL(triggered()), this, SLOT(paths()));
|
connect(_pathsAction, SIGNAL(triggered()), this, SLOT(paths()));
|
||||||
_keysAction = new QAction(tr("Keyboard controls"), this);
|
_keysAction = new QAction(tr("Keyboard controls"), this);
|
||||||
|
_keysAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_keysAction, SIGNAL(triggered()), this, SLOT(keys()));
|
connect(_keysAction, SIGNAL(triggered()), this, SLOT(keys()));
|
||||||
_aboutAction = new QAction(QIcon(QPixmap(APP_ICON)),
|
_aboutAction = new QAction(QIcon(QPixmap(APP_ICON)),
|
||||||
tr("About GPXSee"), this);
|
tr("About GPXSee"), this);
|
||||||
@ -215,50 +216,66 @@ void GUI::createActions()
|
|||||||
// File actions
|
// File actions
|
||||||
_openFileAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
_openFileAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
||||||
tr("Open..."), this);
|
tr("Open..."), this);
|
||||||
|
_openFileAction->setMenuRole(QAction::NoRole);
|
||||||
_openFileAction->setShortcut(OPEN_SHORTCUT);
|
_openFileAction->setShortcut(OPEN_SHORTCUT);
|
||||||
connect(_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
|
connect(_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
|
||||||
addAction(_openFileAction);
|
addAction(_openFileAction);
|
||||||
_printFileAction = new QAction(QIcon(QPixmap(PRINT_FILE_ICON)),
|
_printFileAction = new QAction(QIcon(QPixmap(PRINT_FILE_ICON)),
|
||||||
tr("Print..."), this);
|
tr("Print..."), this);
|
||||||
|
_printFileAction->setMenuRole(QAction::NoRole);
|
||||||
_printFileAction->setActionGroup(_fileActionGroup);
|
_printFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
|
connect(_printFileAction, SIGNAL(triggered()), this, SLOT(printFile()));
|
||||||
addAction(_printFileAction);
|
addAction(_printFileAction);
|
||||||
_exportFileAction = new QAction(QIcon(QPixmap(EXPORT_FILE_ICON)),
|
_exportFileAction = new QAction(QIcon(QPixmap(EXPORT_FILE_ICON)),
|
||||||
tr("Export to PDF..."), this);
|
tr("Export to PDF..."), this);
|
||||||
|
_exportFileAction->setMenuRole(QAction::NoRole);
|
||||||
_exportFileAction->setShortcut(EXPORT_SHORTCUT);
|
_exportFileAction->setShortcut(EXPORT_SHORTCUT);
|
||||||
_exportFileAction->setActionGroup(_fileActionGroup);
|
_exportFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
|
connect(_exportFileAction, SIGNAL(triggered()), this, SLOT(exportFile()));
|
||||||
addAction(_exportFileAction);
|
addAction(_exportFileAction);
|
||||||
_closeFileAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)),
|
_closeFileAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)),
|
||||||
tr("Close"), this);
|
tr("Close"), this);
|
||||||
|
_closeFileAction->setMenuRole(QAction::NoRole);
|
||||||
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
|
_closeFileAction->setShortcut(CLOSE_SHORTCUT);
|
||||||
_closeFileAction->setActionGroup(_fileActionGroup);
|
_closeFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_closeFileAction, SIGNAL(triggered()), this, SLOT(closeAll()));
|
connect(_closeFileAction, SIGNAL(triggered()), this, SLOT(closeAll()));
|
||||||
addAction(_closeFileAction);
|
addAction(_closeFileAction);
|
||||||
_reloadFileAction = new QAction(QIcon(QPixmap(RELOAD_FILE_ICON)),
|
_reloadFileAction = new QAction(QIcon(QPixmap(RELOAD_FILE_ICON)),
|
||||||
tr("Reload"), this);
|
tr("Reload"), this);
|
||||||
|
_reloadFileAction->setMenuRole(QAction::NoRole);
|
||||||
_reloadFileAction->setShortcut(RELOAD_SHORTCUT);
|
_reloadFileAction->setShortcut(RELOAD_SHORTCUT);
|
||||||
_reloadFileAction->setActionGroup(_fileActionGroup);
|
_reloadFileAction->setActionGroup(_fileActionGroup);
|
||||||
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFile()));
|
connect(_reloadFileAction, SIGNAL(triggered()), this, SLOT(reloadFile()));
|
||||||
addAction(_reloadFileAction);
|
addAction(_reloadFileAction);
|
||||||
|
_statisticsAction = new QAction(tr("Statistics..."), this);
|
||||||
|
_statisticsAction->setMenuRole(QAction::NoRole);
|
||||||
|
_statisticsAction->setShortcut(STATISTICS_SHORTCUT);
|
||||||
|
_statisticsAction->setActionGroup(_fileActionGroup);
|
||||||
|
connect(_statisticsAction, SIGNAL(triggered()), this, SLOT(statistics()));
|
||||||
|
addAction(_statisticsAction);
|
||||||
|
|
||||||
// POI actions
|
// POI actions
|
||||||
_openPOIAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
_openPOIAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
||||||
tr("Load POI file..."), this);
|
tr("Load POI file..."), this);
|
||||||
|
_openPOIAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile()));
|
connect(_openPOIAction, SIGNAL(triggered()), this, SLOT(openPOIFile()));
|
||||||
_closePOIAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)),
|
_closePOIAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)),
|
||||||
tr("Close POI files"), this);
|
tr("Close POI files"), this);
|
||||||
|
_closePOIAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_closePOIAction, SIGNAL(triggered()), this, SLOT(closePOIFiles()));
|
connect(_closePOIAction, SIGNAL(triggered()), this, SLOT(closePOIFiles()));
|
||||||
_overlapPOIAction = new QAction(tr("Overlap POIs"), this);
|
_overlapPOIAction = new QAction(tr("Overlap POIs"), this);
|
||||||
|
_overlapPOIAction->setMenuRole(QAction::NoRole);
|
||||||
_overlapPOIAction->setCheckable(true);
|
_overlapPOIAction->setCheckable(true);
|
||||||
connect(_overlapPOIAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_overlapPOIAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
SLOT(setPOIOverlap(bool)));
|
SLOT(setPOIOverlap(bool)));
|
||||||
_showPOILabelsAction = new QAction(tr("Show POI labels"), this);
|
_showPOILabelsAction = new QAction(tr("Show POI labels"), this);
|
||||||
|
_showPOILabelsAction->setMenuRole(QAction::NoRole);
|
||||||
_showPOILabelsAction->setCheckable(true);
|
_showPOILabelsAction->setCheckable(true);
|
||||||
connect(_showPOILabelsAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showPOILabelsAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
SLOT(showPOILabels(bool)));
|
SLOT(showPOILabels(bool)));
|
||||||
_showPOIAction = new QAction(QIcon(QPixmap(SHOW_POI_ICON)),
|
_showPOIAction = new QAction(QIcon(QPixmap(SHOW_POI_ICON)),
|
||||||
tr("Show POIs"), this);
|
tr("Show POIs"), this);
|
||||||
|
_showPOIAction->setMenuRole(QAction::NoRole);
|
||||||
_showPOIAction->setCheckable(true);
|
_showPOIAction->setCheckable(true);
|
||||||
_showPOIAction->setShortcut(SHOW_POI_SHORTCUT);
|
_showPOIAction->setShortcut(SHOW_POI_SHORTCUT);
|
||||||
connect(_showPOIAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showPOIAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
@ -269,6 +286,7 @@ void GUI::createActions()
|
|||||||
// Map actions
|
// Map actions
|
||||||
_showMapAction = new QAction(QIcon(QPixmap(SHOW_MAP_ICON)), tr("Show map"),
|
_showMapAction = new QAction(QIcon(QPixmap(SHOW_MAP_ICON)), tr("Show map"),
|
||||||
this);
|
this);
|
||||||
|
_showMapAction->setMenuRole(QAction::NoRole);
|
||||||
_showMapAction->setCheckable(true);
|
_showMapAction->setCheckable(true);
|
||||||
_showMapAction->setShortcut(SHOW_MAP_SHORTCUT);
|
_showMapAction->setShortcut(SHOW_MAP_SHORTCUT);
|
||||||
connect(_showMapAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showMapAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
@ -276,16 +294,20 @@ void GUI::createActions()
|
|||||||
addAction(_showMapAction);
|
addAction(_showMapAction);
|
||||||
_loadMapAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
_loadMapAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
|
||||||
tr("Load map..."), this);
|
tr("Load map..."), this);
|
||||||
|
_loadMapAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap()));
|
connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap()));
|
||||||
_clearMapCacheAction = new QAction(tr("Clear tile cache"), this);
|
_clearMapCacheAction = new QAction(tr("Clear tile cache"), this);
|
||||||
|
_clearMapCacheAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_clearMapCacheAction, SIGNAL(triggered()), _mapView,
|
connect(_clearMapCacheAction, SIGNAL(triggered()), _mapView,
|
||||||
SLOT(clearMapCache()));
|
SLOT(clearMapCache()));
|
||||||
createMapActions();
|
createMapActions();
|
||||||
_nextMapAction = new QAction(tr("Next map"), this);
|
_nextMapAction = new QAction(tr("Next map"), this);
|
||||||
|
_nextMapAction->setMenuRole(QAction::NoRole);
|
||||||
_nextMapAction->setShortcut(NEXT_MAP_SHORTCUT);
|
_nextMapAction->setShortcut(NEXT_MAP_SHORTCUT);
|
||||||
connect(_nextMapAction, SIGNAL(triggered()), this, SLOT(nextMap()));
|
connect(_nextMapAction, SIGNAL(triggered()), this, SLOT(nextMap()));
|
||||||
addAction(_nextMapAction);
|
addAction(_nextMapAction);
|
||||||
_prevMapAction = new QAction(tr("Next map"), this);
|
_prevMapAction = new QAction(tr("Next map"), this);
|
||||||
|
_prevMapAction->setMenuRole(QAction::NoRole);
|
||||||
_prevMapAction->setShortcut(PREV_MAP_SHORTCUT);
|
_prevMapAction->setShortcut(PREV_MAP_SHORTCUT);
|
||||||
connect(_prevMapAction, SIGNAL(triggered()), this, SLOT(prevMap()));
|
connect(_prevMapAction, SIGNAL(triggered()), this, SLOT(prevMap()));
|
||||||
addAction(_prevMapAction);
|
addAction(_prevMapAction);
|
||||||
@ -296,22 +318,27 @@ void GUI::createActions()
|
|||||||
|
|
||||||
// Data actions
|
// Data actions
|
||||||
_showTracksAction = new QAction(tr("Show tracks"), this);
|
_showTracksAction = new QAction(tr("Show tracks"), this);
|
||||||
|
_showTracksAction->setMenuRole(QAction::NoRole);
|
||||||
_showTracksAction->setCheckable(true);
|
_showTracksAction->setCheckable(true);
|
||||||
connect(_showTracksAction, SIGNAL(triggered(bool)), this,
|
connect(_showTracksAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(showTracks(bool)));
|
SLOT(showTracks(bool)));
|
||||||
_showRoutesAction = new QAction(tr("Show routes"), this);
|
_showRoutesAction = new QAction(tr("Show routes"), this);
|
||||||
|
_showRoutesAction->setMenuRole(QAction::NoRole);
|
||||||
_showRoutesAction->setCheckable(true);
|
_showRoutesAction->setCheckable(true);
|
||||||
connect(_showRoutesAction, SIGNAL(triggered(bool)), this,
|
connect(_showRoutesAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(showRoutes(bool)));
|
SLOT(showRoutes(bool)));
|
||||||
_showWaypointsAction = new QAction(tr("Show waypoints"), this);
|
_showWaypointsAction = new QAction(tr("Show waypoints"), this);
|
||||||
|
_showWaypointsAction->setMenuRole(QAction::NoRole);
|
||||||
_showWaypointsAction->setCheckable(true);
|
_showWaypointsAction->setCheckable(true);
|
||||||
connect(_showWaypointsAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showWaypointsAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
SLOT(showWaypoints(bool)));
|
SLOT(showWaypoints(bool)));
|
||||||
_showWaypointLabelsAction = new QAction(tr("Waypoint labels"), this);
|
_showWaypointLabelsAction = new QAction(tr("Waypoint labels"), this);
|
||||||
|
_showWaypointLabelsAction->setMenuRole(QAction::NoRole);
|
||||||
_showWaypointLabelsAction->setCheckable(true);
|
_showWaypointLabelsAction->setCheckable(true);
|
||||||
connect(_showWaypointLabelsAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showWaypointLabelsAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
SLOT(showWaypointLabels(bool)));
|
SLOT(showWaypointLabels(bool)));
|
||||||
_showRouteWaypointsAction = new QAction(tr("Route waypoints"), this);
|
_showRouteWaypointsAction = new QAction(tr("Route waypoints"), this);
|
||||||
|
_showRouteWaypointsAction->setMenuRole(QAction::NoRole);
|
||||||
_showRouteWaypointsAction->setCheckable(true);
|
_showRouteWaypointsAction->setCheckable(true);
|
||||||
connect(_showRouteWaypointsAction, SIGNAL(triggered(bool)), _mapView,
|
connect(_showRouteWaypointsAction, SIGNAL(triggered(bool)), _mapView,
|
||||||
SLOT(showRouteWaypoints(bool)));
|
SLOT(showRouteWaypoints(bool)));
|
||||||
@ -319,6 +346,7 @@ void GUI::createActions()
|
|||||||
// Graph actions
|
// Graph actions
|
||||||
_showGraphsAction = new QAction(QIcon(QPixmap(SHOW_GRAPHS_ICON)),
|
_showGraphsAction = new QAction(QIcon(QPixmap(SHOW_GRAPHS_ICON)),
|
||||||
tr("Show graphs"), this);
|
tr("Show graphs"), this);
|
||||||
|
_showGraphsAction->setMenuRole(QAction::NoRole);
|
||||||
_showGraphsAction->setCheckable(true);
|
_showGraphsAction->setCheckable(true);
|
||||||
_showGraphsAction->setShortcut(SHOW_GRAPHS_SHORTCUT);
|
_showGraphsAction->setShortcut(SHOW_GRAPHS_SHORTCUT);
|
||||||
connect(_showGraphsAction, SIGNAL(triggered(bool)), this,
|
connect(_showGraphsAction, SIGNAL(triggered(bool)), this,
|
||||||
@ -327,39 +355,46 @@ void GUI::createActions()
|
|||||||
ag = new QActionGroup(this);
|
ag = new QActionGroup(this);
|
||||||
ag->setExclusive(true);
|
ag->setExclusive(true);
|
||||||
_distanceGraphAction = new QAction(tr("Distance"), this);
|
_distanceGraphAction = new QAction(tr("Distance"), this);
|
||||||
|
_distanceGraphAction->setMenuRole(QAction::NoRole);
|
||||||
_distanceGraphAction->setCheckable(true);
|
_distanceGraphAction->setCheckable(true);
|
||||||
_distanceGraphAction->setActionGroup(ag);
|
_distanceGraphAction->setActionGroup(ag);
|
||||||
connect(_distanceGraphAction, SIGNAL(triggered()), this,
|
connect(_distanceGraphAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setDistanceGraph()));
|
SLOT(setDistanceGraph()));
|
||||||
addAction(_distanceGraphAction);
|
addAction(_distanceGraphAction);
|
||||||
_timeGraphAction = new QAction(tr("Time"), this);
|
_timeGraphAction = new QAction(tr("Time"), this);
|
||||||
|
_timeGraphAction->setMenuRole(QAction::NoRole);
|
||||||
_timeGraphAction->setCheckable(true);
|
_timeGraphAction->setCheckable(true);
|
||||||
_timeGraphAction->setActionGroup(ag);
|
_timeGraphAction->setActionGroup(ag);
|
||||||
connect(_timeGraphAction, SIGNAL(triggered()), this,
|
connect(_timeGraphAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setTimeGraph()));
|
SLOT(setTimeGraph()));
|
||||||
addAction(_timeGraphAction);
|
addAction(_timeGraphAction);
|
||||||
_showGraphGridAction = new QAction(tr("Show grid"), this);
|
_showGraphGridAction = new QAction(tr("Show grid"), this);
|
||||||
|
_showGraphGridAction->setMenuRole(QAction::NoRole);
|
||||||
_showGraphGridAction->setCheckable(true);
|
_showGraphGridAction->setCheckable(true);
|
||||||
connect(_showGraphGridAction, SIGNAL(triggered(bool)), this,
|
connect(_showGraphGridAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(showGraphGrids(bool)));
|
SLOT(showGraphGrids(bool)));
|
||||||
_showGraphSliderInfoAction = new QAction(tr("Show slider info"), this);
|
_showGraphSliderInfoAction = new QAction(tr("Show slider info"), this);
|
||||||
|
_showGraphSliderInfoAction->setMenuRole(QAction::NoRole);
|
||||||
_showGraphSliderInfoAction->setCheckable(true);
|
_showGraphSliderInfoAction->setCheckable(true);
|
||||||
connect(_showGraphSliderInfoAction, SIGNAL(triggered(bool)), this,
|
connect(_showGraphSliderInfoAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(showGraphSliderInfo(bool)));
|
SLOT(showGraphSliderInfo(bool)));
|
||||||
|
|
||||||
// Settings actions
|
// Settings actions
|
||||||
_showToolbarsAction = new QAction(tr("Show toolbars"), this);
|
_showToolbarsAction = new QAction(tr("Show toolbars"), this);
|
||||||
|
_showToolbarsAction->setMenuRole(QAction::NoRole);
|
||||||
_showToolbarsAction->setCheckable(true);
|
_showToolbarsAction->setCheckable(true);
|
||||||
connect(_showToolbarsAction, SIGNAL(triggered(bool)), this,
|
connect(_showToolbarsAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(showToolbars(bool)));
|
SLOT(showToolbars(bool)));
|
||||||
ag = new QActionGroup(this);
|
ag = new QActionGroup(this);
|
||||||
ag->setExclusive(true);
|
ag->setExclusive(true);
|
||||||
_totalTimeAction = new QAction(tr("Total time"), this);
|
_totalTimeAction = new QAction(tr("Total time"), this);
|
||||||
|
_totalTimeAction->setMenuRole(QAction::NoRole);
|
||||||
_totalTimeAction->setCheckable(true);
|
_totalTimeAction->setCheckable(true);
|
||||||
_totalTimeAction->setActionGroup(ag);
|
_totalTimeAction->setActionGroup(ag);
|
||||||
connect(_totalTimeAction, SIGNAL(triggered()), this,
|
connect(_totalTimeAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setTotalTime()));
|
SLOT(setTotalTime()));
|
||||||
_movingTimeAction = new QAction(tr("Moving time"), this);
|
_movingTimeAction = new QAction(tr("Moving time"), this);
|
||||||
|
_movingTimeAction->setMenuRole(QAction::NoRole);
|
||||||
_movingTimeAction->setCheckable(true);
|
_movingTimeAction->setCheckable(true);
|
||||||
_movingTimeAction->setActionGroup(ag);
|
_movingTimeAction->setActionGroup(ag);
|
||||||
connect(_movingTimeAction, SIGNAL(triggered()), this,
|
connect(_movingTimeAction, SIGNAL(triggered()), this,
|
||||||
@ -367,16 +402,19 @@ void GUI::createActions()
|
|||||||
ag = new QActionGroup(this);
|
ag = new QActionGroup(this);
|
||||||
ag->setExclusive(true);
|
ag->setExclusive(true);
|
||||||
_metricUnitsAction = new QAction(tr("Metric"), this);
|
_metricUnitsAction = new QAction(tr("Metric"), this);
|
||||||
|
_metricUnitsAction->setMenuRole(QAction::NoRole);
|
||||||
_metricUnitsAction->setCheckable(true);
|
_metricUnitsAction->setCheckable(true);
|
||||||
_metricUnitsAction->setActionGroup(ag);
|
_metricUnitsAction->setActionGroup(ag);
|
||||||
connect(_metricUnitsAction, SIGNAL(triggered()), this,
|
connect(_metricUnitsAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setMetricUnits()));
|
SLOT(setMetricUnits()));
|
||||||
_imperialUnitsAction = new QAction(tr("Imperial"), this);
|
_imperialUnitsAction = new QAction(tr("Imperial"), this);
|
||||||
|
_imperialUnitsAction->setMenuRole(QAction::NoRole);
|
||||||
_imperialUnitsAction->setCheckable(true);
|
_imperialUnitsAction->setCheckable(true);
|
||||||
_imperialUnitsAction->setActionGroup(ag);
|
_imperialUnitsAction->setActionGroup(ag);
|
||||||
connect(_imperialUnitsAction, SIGNAL(triggered()), this,
|
connect(_imperialUnitsAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setImperialUnits()));
|
SLOT(setImperialUnits()));
|
||||||
_nauticalUnitsAction = new QAction(tr("Nautical"), this);
|
_nauticalUnitsAction = new QAction(tr("Nautical"), this);
|
||||||
|
_nauticalUnitsAction->setMenuRole(QAction::NoRole);
|
||||||
_nauticalUnitsAction->setCheckable(true);
|
_nauticalUnitsAction->setCheckable(true);
|
||||||
_nauticalUnitsAction->setActionGroup(ag);
|
_nauticalUnitsAction->setActionGroup(ag);
|
||||||
connect(_nauticalUnitsAction, SIGNAL(triggered()), this,
|
connect(_nauticalUnitsAction, SIGNAL(triggered()), this,
|
||||||
@ -384,22 +422,26 @@ void GUI::createActions()
|
|||||||
ag = new QActionGroup(this);
|
ag = new QActionGroup(this);
|
||||||
ag->setExclusive(true);
|
ag->setExclusive(true);
|
||||||
_decimalDegreesAction = new QAction(tr("Decimal degrees (DD)"), this);
|
_decimalDegreesAction = new QAction(tr("Decimal degrees (DD)"), this);
|
||||||
|
_decimalDegreesAction->setMenuRole(QAction::NoRole);
|
||||||
_decimalDegreesAction->setCheckable(true);
|
_decimalDegreesAction->setCheckable(true);
|
||||||
_decimalDegreesAction->setActionGroup(ag);
|
_decimalDegreesAction->setActionGroup(ag);
|
||||||
connect(_decimalDegreesAction, SIGNAL(triggered()), this,
|
connect(_decimalDegreesAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setDecimalDegrees()));
|
SLOT(setDecimalDegrees()));
|
||||||
_degreesMinutesAction = new QAction(tr("Degrees and decimal minutes (DMM)"),
|
_degreesMinutesAction = new QAction(tr("Degrees and decimal minutes (DMM)"),
|
||||||
this);
|
this);
|
||||||
|
_degreesMinutesAction->setMenuRole(QAction::NoRole);
|
||||||
_degreesMinutesAction->setCheckable(true);
|
_degreesMinutesAction->setCheckable(true);
|
||||||
_degreesMinutesAction->setActionGroup(ag);
|
_degreesMinutesAction->setActionGroup(ag);
|
||||||
connect(_degreesMinutesAction, SIGNAL(triggered()), this,
|
connect(_degreesMinutesAction, SIGNAL(triggered()), this,
|
||||||
SLOT(setDegreesMinutes()));
|
SLOT(setDegreesMinutes()));
|
||||||
_DMSAction = new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
|
_DMSAction = new QAction(tr("Degrees, minutes, seconds (DMS)"), this);
|
||||||
|
_DMSAction->setMenuRole(QAction::NoRole);
|
||||||
_DMSAction->setCheckable(true);
|
_DMSAction->setCheckable(true);
|
||||||
_DMSAction->setActionGroup(ag);
|
_DMSAction->setActionGroup(ag);
|
||||||
connect(_DMSAction, SIGNAL(triggered()), this, SLOT(setDMS()));
|
connect(_DMSAction, SIGNAL(triggered()), this, SLOT(setDMS()));
|
||||||
_fullscreenAction = new QAction(QIcon(QPixmap(FULLSCREEN_ICON)),
|
_fullscreenAction = new QAction(QIcon(QPixmap(FULLSCREEN_ICON)),
|
||||||
tr("Fullscreen mode"), this);
|
tr("Fullscreen mode"), this);
|
||||||
|
_fullscreenAction->setMenuRole(QAction::NoRole);
|
||||||
_fullscreenAction->setCheckable(true);
|
_fullscreenAction->setCheckable(true);
|
||||||
_fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT);
|
_fullscreenAction->setShortcut(FULLSCREEN_SHORTCUT);
|
||||||
connect(_fullscreenAction, SIGNAL(triggered(bool)), this,
|
connect(_fullscreenAction, SIGNAL(triggered(bool)), this,
|
||||||
@ -413,16 +455,20 @@ void GUI::createActions()
|
|||||||
// Navigation actions
|
// Navigation actions
|
||||||
_nextAction = new QAction(QIcon(QPixmap(NEXT_FILE_ICON)), tr("Next"), this);
|
_nextAction = new QAction(QIcon(QPixmap(NEXT_FILE_ICON)), tr("Next"), this);
|
||||||
_nextAction->setActionGroup(_navigationActionGroup);
|
_nextAction->setActionGroup(_navigationActionGroup);
|
||||||
|
_nextAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_nextAction, SIGNAL(triggered()), this, SLOT(next()));
|
connect(_nextAction, SIGNAL(triggered()), this, SLOT(next()));
|
||||||
_prevAction = new QAction(QIcon(QPixmap(PREV_FILE_ICON)), tr("Previous"),
|
_prevAction = new QAction(QIcon(QPixmap(PREV_FILE_ICON)), tr("Previous"),
|
||||||
this);
|
this);
|
||||||
|
_prevAction->setMenuRole(QAction::NoRole);
|
||||||
_prevAction->setActionGroup(_navigationActionGroup);
|
_prevAction->setActionGroup(_navigationActionGroup);
|
||||||
connect(_prevAction, SIGNAL(triggered()), this, SLOT(prev()));
|
connect(_prevAction, SIGNAL(triggered()), this, SLOT(prev()));
|
||||||
_lastAction = new QAction(QIcon(QPixmap(LAST_FILE_ICON)), tr("Last"), this);
|
_lastAction = new QAction(QIcon(QPixmap(LAST_FILE_ICON)), tr("Last"), this);
|
||||||
|
_lastAction->setMenuRole(QAction::NoRole);
|
||||||
_lastAction->setActionGroup(_navigationActionGroup);
|
_lastAction->setActionGroup(_navigationActionGroup);
|
||||||
connect(_lastAction, SIGNAL(triggered()), this, SLOT(last()));
|
connect(_lastAction, SIGNAL(triggered()), this, SLOT(last()));
|
||||||
_firstAction = new QAction(QIcon(QPixmap(FIRST_FILE_ICON)), tr("First"),
|
_firstAction = new QAction(QIcon(QPixmap(FIRST_FILE_ICON)), tr("First"),
|
||||||
this);
|
this);
|
||||||
|
_firstAction->setMenuRole(QAction::NoRole);
|
||||||
_firstAction->setActionGroup(_navigationActionGroup);
|
_firstAction->setActionGroup(_navigationActionGroup);
|
||||||
connect(_firstAction, SIGNAL(triggered()), this, SLOT(first()));
|
connect(_firstAction, SIGNAL(triggered()), this, SLOT(first()));
|
||||||
}
|
}
|
||||||
@ -435,8 +481,9 @@ void GUI::createMenus()
|
|||||||
fileMenu->addAction(_printFileAction);
|
fileMenu->addAction(_printFileAction);
|
||||||
fileMenu->addAction(_exportFileAction);
|
fileMenu->addAction(_exportFileAction);
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
fileMenu->addAction(_reloadFileAction);
|
fileMenu->addAction(_statisticsAction);
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
|
fileMenu->addAction(_reloadFileAction);
|
||||||
fileMenu->addAction(_closeFileAction);
|
fileMenu->addAction(_closeFileAction);
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
fileMenu->addSeparator();
|
fileMenu->addSeparator();
|
||||||
@ -554,12 +601,13 @@ void GUI::createGraphTabs()
|
|||||||
_graphTabWidget->setDocumentMode(true);
|
_graphTabWidget->setDocumentMode(true);
|
||||||
#endif // Q_OS_WIN32
|
#endif // Q_OS_WIN32
|
||||||
|
|
||||||
_tabs.append(new ElevationGraph);
|
_tabs.append(new ElevationGraph(_graphTabWidget));
|
||||||
_tabs.append(new SpeedGraph);
|
_tabs.append(new SpeedGraph(_graphTabWidget));
|
||||||
_tabs.append(new HeartRateGraph);
|
_tabs.append(new HeartRateGraph(_graphTabWidget));
|
||||||
_tabs.append(new CadenceGraph);
|
_tabs.append(new CadenceGraph(_graphTabWidget));
|
||||||
_tabs.append(new PowerGraph);
|
_tabs.append(new PowerGraph(_graphTabWidget));
|
||||||
_tabs.append(new TemperatureGraph);
|
_tabs.append(new TemperatureGraph(_graphTabWidget));
|
||||||
|
_tabs.append(new GearRatioGraph(_graphTabWidget));
|
||||||
|
|
||||||
for (int i = 0; i < _tabs.count(); i++)
|
for (int i = 0; i < _tabs.count(); i++)
|
||||||
connect(_tabs.at(i), SIGNAL(sliderPositionChanged(qreal)), this,
|
connect(_tabs.at(i), SIGNAL(sliderPositionChanged(qreal)), this,
|
||||||
@ -643,19 +691,19 @@ void GUI::paths()
|
|||||||
msgBox.setWindowTitle(tr("Paths"));
|
msgBox.setWindowTitle(tr("Paths"));
|
||||||
msgBox.setText("<h3>" + tr("Paths") + "</h3>");
|
msgBox.setText("<h3>" + tr("Paths") + "</h3>");
|
||||||
msgBox.setInformativeText(
|
msgBox.setInformativeText(
|
||||||
"<style>td {white-space: pre; padding-right: 1em;}</style>"
|
"<style>td {white-space: pre; padding-right: 1em;}</style><h4>"
|
||||||
"<div><table><tr><td>" + tr("Map directory:") + "</td><td><code>"
|
+ tr("Global") + "</h4><table><tr><td>" + tr("Map directory:")
|
||||||
+ QDir::cleanPath(GLOBAL_MAP_DIR) + "</code></td></tr><tr><td>"
|
+ "</td><td><code>" + QDir::cleanPath(GLOBAL_MAP_DIR)
|
||||||
+ tr("POI directory:") + "</td><td><code>"
|
+ "</code></td></tr><tr><td>" + tr("POI directory:") + "</td><td><code>"
|
||||||
+ QDir::cleanPath(GLOBAL_POI_DIR) + "</code></td></tr><tr><td>"
|
+ QDir::cleanPath(GLOBAL_POI_DIR) + "</code></td></tr><tr><td>"
|
||||||
+ tr("GCS file:") + "</td><td><code>" + QDir::cleanPath(GLOBAL_GCS_FILE)
|
+ tr("GCS/PCS directory:") + "</td><td><code>"
|
||||||
+ "</code></td></tr><tr><td>" + tr("PCS file:") + "</td><td><code>"
|
+ QDir::cleanPath(GLOBAL_CSV_DIR) + "</code></td></tr></table>"
|
||||||
+ QDir::cleanPath(GLOBAL_PCS_FILE) + "</code></td></tr><tr><td>"
|
+ "<h4>" + tr("User-specific") + "</h4><table><tr><td>"
|
||||||
+ tr("Ellipsoids file:") + "</td><td><code>"
|
+ tr("Map directory:") + "</td><td><code>" + QDir::cleanPath(USER_MAP_DIR)
|
||||||
+ QDir::cleanPath(GLOBAL_ELLIPSOID_FILE) + "</code></td></tr>"
|
+ "</code></td></tr><tr><td>" + tr("POI directory:") + "</td><td><code>"
|
||||||
+ "<tr><td></td><td></td></tr></table></div><div><table><tr><td>"
|
+ QDir::cleanPath(USER_POI_DIR) + "</code></td></tr><tr><td>"
|
||||||
+ tr("User override directory:") + "</td><td><code>"
|
+ tr("GCS/PCS directory:") + "</td><td><code>"
|
||||||
+ QDir::cleanPath(USER_DIR) + "</td></tr></table></div>"
|
+ QDir::cleanPath(USER_CSV_DIR) + "</code></td></tr></table>"
|
||||||
);
|
);
|
||||||
|
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
@ -687,8 +735,6 @@ bool GUI::openFile(const QString &fileName)
|
|||||||
updateNavigationActions();
|
updateNavigationActions();
|
||||||
updateStatusBarInfo();
|
updateStatusBarInfo();
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
updateGraphTabs();
|
|
||||||
updateMapView();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -702,13 +748,10 @@ bool GUI::openFile(const QString &fileName)
|
|||||||
bool GUI::loadFile(const QString &fileName)
|
bool GUI::loadFile(const QString &fileName)
|
||||||
{
|
{
|
||||||
Data data;
|
Data data;
|
||||||
|
QList<QList<GraphItem*> > graphs;
|
||||||
QList<PathItem*> paths;
|
QList<PathItem*> paths;
|
||||||
|
|
||||||
if (data.loadFile(fileName)) {
|
if (data.loadFile(fileName)) {
|
||||||
paths = _mapView->loadData(data);
|
|
||||||
for (int i = 0; i < _tabs.count(); i++)
|
|
||||||
_tabs.at(i)->loadData(data, paths);
|
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
_trackDistance += data.tracks().at(i)->distance();
|
_trackDistance += data.tracks().at(i)->distance();
|
||||||
_time += data.tracks().at(i)->time();
|
_time += data.tracks().at(i)->time();
|
||||||
@ -735,6 +778,25 @@ bool GUI::loadFile(const QString &fileName)
|
|||||||
} else
|
} else
|
||||||
_pathName = QString();
|
_pathName = QString();
|
||||||
|
|
||||||
|
for (int i = 0; i < _tabs.count(); i++)
|
||||||
|
graphs.append(_tabs.at(i)->loadData(data));
|
||||||
|
if (updateGraphTabs() | updateMapView())
|
||||||
|
_splitter->refresh();
|
||||||
|
paths = _mapView->loadData(data);
|
||||||
|
|
||||||
|
for (int i = 0; i < paths.count(); i++) {
|
||||||
|
const PathItem *pi = paths.at(i);
|
||||||
|
for (int j = 0; j < graphs.count(); j++) {
|
||||||
|
const GraphItem *gi = graphs.at(j).at(i);
|
||||||
|
if (!gi)
|
||||||
|
continue;
|
||||||
|
connect(gi, SIGNAL(sliderPositionChanged(qreal)), pi,
|
||||||
|
SLOT(moveMarker(qreal)));
|
||||||
|
connect(pi, SIGNAL(selected(bool)), gi, SLOT(hover(bool)));
|
||||||
|
connect(gi, SIGNAL(selected(bool)), pi, SLOT(hover(bool)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
updateNavigationActions();
|
updateNavigationActions();
|
||||||
@ -850,11 +912,18 @@ void GUI::openOptions()
|
|||||||
SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
|
SET_TRACK_OPTION(outlierEliminate, setOutlierElimination);
|
||||||
SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
|
SET_TRACK_OPTION(pauseSpeed, setPauseSpeed);
|
||||||
SET_TRACK_OPTION(pauseInterval, setPauseInterval);
|
SET_TRACK_OPTION(pauseInterval, setPauseInterval);
|
||||||
|
SET_TRACK_OPTION(useReportedSpeed, useReportedSpeed);
|
||||||
|
|
||||||
if (options.poiRadius != _options.poiRadius)
|
if (options.poiRadius != _options.poiRadius)
|
||||||
_poi->setRadius(options.poiRadius);
|
_poi->setRadius(options.poiRadius);
|
||||||
if (options.pixmapCache != _options.pixmapCache)
|
if (options.pixmapCache != _options.pixmapCache)
|
||||||
QPixmapCache::setCacheLimit(options.pixmapCache * 1024);
|
QPixmapCache::setCacheLimit(options.pixmapCache * 1024);
|
||||||
|
if (options.connectionTimeout != _options.connectionTimeout)
|
||||||
|
Downloader::setTimeout(options.connectionTimeout);
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
if (options.enableHTTP2 != _options.enableHTTP2)
|
||||||
|
Downloader::enableHTTP2(options.enableHTTP2);
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
if (reload)
|
if (reload)
|
||||||
reloadFile();
|
reloadFile();
|
||||||
@ -893,14 +962,78 @@ void GUI::exportFile()
|
|||||||
plot(&printer);
|
plot(&printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI::statistics()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
QString text = "<style>td {white-space: pre; padding-right: 4em;}"
|
||||||
|
"th {text-align: left; padding-top: 0.5em;}</style><table>";
|
||||||
|
#else // Q_OS_WIN32
|
||||||
|
QString text = "<style>td {white-space: pre; padding-right: 2em;}"
|
||||||
|
"th {text-align: left; padding-top: 0.5em;}</style><table>";
|
||||||
|
#endif // Q_OS_WIN32
|
||||||
|
|
||||||
|
if (_showTracksAction->isChecked() && _trackCount > 1)
|
||||||
|
text.append("<tr><td>" + tr("Tracks") + ":</td><td>"
|
||||||
|
+ QString::number(_trackCount) + "</td></tr>");
|
||||||
|
if (_showRoutesAction->isChecked() && _routeCount > 1)
|
||||||
|
text.append("<tr><td>" + tr("Routes") + ":</td><td>"
|
||||||
|
+ QString::number(_routeCount) + "</td></tr>");
|
||||||
|
if (_showWaypointsAction->isChecked() && _waypointCount > 1)
|
||||||
|
text.append("<tr><td>" + tr("Waypoints") + ":</td><td>"
|
||||||
|
+ QString::number(_waypointCount) + "</td></tr>");
|
||||||
|
|
||||||
|
if (_dateRange.first.isValid()) {
|
||||||
|
if (_dateRange.first == _dateRange.second) {
|
||||||
|
QString format = QLocale::system().dateFormat(QLocale::LongFormat);
|
||||||
|
text.append("<tr><td>" + tr("Date") + ":</td><td>"
|
||||||
|
+ _dateRange.first.toString(format) + "</td></tr>");
|
||||||
|
} else {
|
||||||
|
QString format = QLocale::system().dateFormat(QLocale::ShortFormat);
|
||||||
|
text.append("<tr><td>" + tr("Date") + ":</td><td>"
|
||||||
|
+ QString("%1 - %2").arg(_dateRange.first.toString(format),
|
||||||
|
_dateRange.second.toString(format)) + "</td></tr>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance() > 0)
|
||||||
|
text.append("<tr><td>" + tr("Distance") + ":</td><td>"
|
||||||
|
+ Format::distance(distance(), units()) + "</td></tr>");
|
||||||
|
if (time() > 0) {
|
||||||
|
text.append("<tr><td>" + tr("Time") + ":</td><td>"
|
||||||
|
+ Format::timeSpan(time()) + "</td></tr>");
|
||||||
|
text.append("<tr><td>" + tr("Moving time") + ":</td><td>"
|
||||||
|
+ Format::timeSpan(movingTime()) + "</td></tr>");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _tabs.count(); i++) {
|
||||||
|
const GraphTab *tab = _tabs.at(i);
|
||||||
|
if (tab->isEmpty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
text.append("<tr><th colspan=\"2\">" + tab->label() + "</th></tr>");
|
||||||
|
for (int j = 0; j < tab->info().size(); j++) {
|
||||||
|
const KV &kv = tab->info().at(j);
|
||||||
|
text.append("<tr><td>" + kv.key() + ":</td><td>" + kv.value()
|
||||||
|
+ "</td></tr>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
text.append("</table>");
|
||||||
|
|
||||||
|
|
||||||
|
QMessageBox msgBox(this);
|
||||||
|
msgBox.setWindowTitle(tr("Statistics"));
|
||||||
|
msgBox.setText("<h3>" + tr("Statistics") + "</h3>");
|
||||||
|
msgBox.setInformativeText(text);
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
|
||||||
void GUI::plot(QPrinter *printer)
|
void GUI::plot(QPrinter *printer)
|
||||||
{
|
{
|
||||||
QPainter p(printer);
|
QPainter p(printer);
|
||||||
TrackInfo info;
|
TrackInfo info;
|
||||||
qreal ih, gh, mh, ratio;
|
qreal ih, gh, mh, ratio;
|
||||||
qreal d = distance();
|
|
||||||
qreal t = time();
|
|
||||||
qreal tm = movingTime();
|
|
||||||
|
|
||||||
if (!_pathName.isNull() && _options.printName)
|
if (!_pathName.isNull() && _options.printName)
|
||||||
info.insert(tr("Name"), _pathName);
|
info.insert(tr("Name"), _pathName);
|
||||||
@ -910,7 +1043,7 @@ void GUI::plot(QPrinter *printer)
|
|||||||
info.insert(tr("Tracks"), QString::number(_trackCount));
|
info.insert(tr("Tracks"), QString::number(_trackCount));
|
||||||
if (_showRoutesAction->isChecked() && _routeCount > 1)
|
if (_showRoutesAction->isChecked() && _routeCount > 1)
|
||||||
info.insert(tr("Routes"), QString::number(_routeCount));
|
info.insert(tr("Routes"), QString::number(_routeCount));
|
||||||
if (_showWaypointsAction->isChecked() && _waypointCount > 2)
|
if (_showWaypointsAction->isChecked() && _waypointCount > 1)
|
||||||
info.insert(tr("Waypoints"), QString::number(_waypointCount));
|
info.insert(tr("Waypoints"), QString::number(_waypointCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,12 +1059,12 @@ void GUI::plot(QPrinter *printer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d > 0 && _options.printDistance)
|
if (distance() > 0 && _options.printDistance)
|
||||||
info.insert(tr("Distance"), Format::distance(d, units()));
|
info.insert(tr("Distance"), Format::distance(distance(), units()));
|
||||||
if (t > 0 && _options.printTime)
|
if (time() > 0 && _options.printTime)
|
||||||
info.insert(tr("Time"), Format::timeSpan(t));
|
info.insert(tr("Time"), Format::timeSpan(time()));
|
||||||
if (tm > 0 && _options.printMovingTime)
|
if (movingTime() > 0 && _options.printMovingTime)
|
||||||
info.insert(tr("Moving time"), Format::timeSpan(tm));
|
info.insert(tr("Moving time"), Format::timeSpan(movingTime()));
|
||||||
|
|
||||||
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
|
qreal fsr = 1085.0 / (qMax(printer->width(), printer->height())
|
||||||
/ (qreal)printer->resolution());
|
/ (qreal)printer->resolution());
|
||||||
@ -1007,8 +1140,6 @@ void GUI::reloadFile()
|
|||||||
|
|
||||||
updateStatusBarInfo();
|
updateStatusBarInfo();
|
||||||
updateWindowTitle();
|
updateWindowTitle();
|
||||||
updateGraphTabs();
|
|
||||||
updateMapView();
|
|
||||||
if (_files.isEmpty())
|
if (_files.isEmpty())
|
||||||
_fileActionGroup->setEnabled(false);
|
_fileActionGroup->setEnabled(false);
|
||||||
else
|
else
|
||||||
@ -1149,6 +1280,7 @@ bool GUI::loadMap(const QString &fileName)
|
|||||||
|
|
||||||
if (_ml->loadFile(fileName)) {
|
if (_ml->loadFile(fileName)) {
|
||||||
QAction *a = new QAction(_ml->maps().last()->name(), this);
|
QAction *a = new QAction(_ml->maps().last()->name(), this);
|
||||||
|
a->setMenuRole(QAction::NoRole);
|
||||||
a->setCheckable(true);
|
a->setCheckable(true);
|
||||||
a->setActionGroup(_mapsActionGroup);
|
a->setActionGroup(_mapsActionGroup);
|
||||||
_mapsSignalMapper->setMapping(a, _ml->maps().size() - 1);
|
_mapsSignalMapper->setMapping(a, _ml->maps().size() - 1);
|
||||||
@ -1273,10 +1405,11 @@ void GUI::updateNavigationActions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::updateGraphTabs()
|
bool GUI::updateGraphTabs()
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
GraphTab *tab;
|
GraphTab *tab;
|
||||||
|
bool hidden = _graphTabWidget->isHidden();
|
||||||
|
|
||||||
for (int i = 0; i < _tabs.size(); i++) {
|
for (int i = 0; i < _tabs.size(); i++) {
|
||||||
tab = _tabs.at(i);
|
tab = _tabs.at(i);
|
||||||
@ -1300,14 +1433,20 @@ void GUI::updateGraphTabs()
|
|||||||
_graphTabWidget->setHidden(true);
|
_graphTabWidget->setHidden(true);
|
||||||
_showGraphsAction->setEnabled(false);
|
_showGraphsAction->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (hidden != _graphTabWidget->isHidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::updateMapView()
|
bool GUI::updateMapView()
|
||||||
{
|
{
|
||||||
|
bool hidden = _mapView->isHidden();
|
||||||
|
|
||||||
if (_options.alwaysShowMap)
|
if (_options.alwaysShowMap)
|
||||||
_mapView->setHidden(false);
|
_mapView->setHidden(false);
|
||||||
else
|
else
|
||||||
_mapView->setHidden(!(_trackCount + _routeCount + _waypointCount));
|
_mapView->setHidden(!(_trackCount + _routeCount + _waypointCount));
|
||||||
|
|
||||||
|
return (hidden != _mapView->isHidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::setTimeType(TimeType type)
|
void GUI::setTimeType(TimeType type)
|
||||||
@ -1614,12 +1753,20 @@ void GUI::writeSettings()
|
|||||||
settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
|
settings.setValue(PAUSE_SPEED_SETTING, _options.pauseSpeed);
|
||||||
if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
|
if (_options.pauseInterval != PAUSE_INTERVAL_DEFAULT)
|
||||||
settings.setValue(PAUSE_INTERVAL_SETTING, _options.pauseInterval);
|
settings.setValue(PAUSE_INTERVAL_SETTING, _options.pauseInterval);
|
||||||
|
if (_options.useReportedSpeed != USE_REPORTED_SPEED_DEFAULT)
|
||||||
|
settings.setValue(USE_REPORTED_SPEED_SETTING, _options.useReportedSpeed);
|
||||||
if (_options.poiRadius != POI_RADIUS_DEFAULT)
|
if (_options.poiRadius != POI_RADIUS_DEFAULT)
|
||||||
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
|
settings.setValue(POI_RADIUS_SETTING, _options.poiRadius);
|
||||||
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
|
if (_options.useOpenGL != USE_OPENGL_DEFAULT)
|
||||||
settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL);
|
settings.setValue(USE_OPENGL_SETTING, _options.useOpenGL);
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
if (_options.enableHTTP2 != ENABLE_HTTP2_DEFAULT)
|
||||||
|
settings.setValue(ENABLE_HTTP2_SETTING, _options.enableHTTP2);
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
if (_options.pixmapCache != PIXMAP_CACHE_DEFAULT)
|
if (_options.pixmapCache != PIXMAP_CACHE_DEFAULT)
|
||||||
settings.setValue(PIXMAP_CACHE_SETTING, _options.pixmapCache);
|
settings.setValue(PIXMAP_CACHE_SETTING, _options.pixmapCache);
|
||||||
|
if (_options.connectionTimeout != CONNECTION_TIMEOUT_DEFAULT)
|
||||||
|
settings.setValue(CONNECTION_TIMEOUT_SETTING, _options.connectionTimeout);
|
||||||
if (_options.hiresPrint != HIRES_PRINT_DEFAULT)
|
if (_options.hiresPrint != HIRES_PRINT_DEFAULT)
|
||||||
settings.setValue(HIRES_PRINT_SETTING, _options.hiresPrint);
|
settings.setValue(HIRES_PRINT_SETTING, _options.hiresPrint);
|
||||||
if (_options.printName != PRINT_NAME_DEFAULT)
|
if (_options.printName != PRINT_NAME_DEFAULT)
|
||||||
@ -1840,14 +1987,22 @@ void GUI::readSettings()
|
|||||||
OUTLIER_ELIMINATE_DEFAULT).toBool();
|
OUTLIER_ELIMINATE_DEFAULT).toBool();
|
||||||
_options.pauseSpeed = settings.value(PAUSE_SPEED_SETTING,
|
_options.pauseSpeed = settings.value(PAUSE_SPEED_SETTING,
|
||||||
PAUSE_SPEED_DEFAULT).toFloat();
|
PAUSE_SPEED_DEFAULT).toFloat();
|
||||||
|
_options.useReportedSpeed = settings.value(USE_REPORTED_SPEED_SETTING,
|
||||||
|
USE_REPORTED_SPEED_DEFAULT).toBool();
|
||||||
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
_options.pauseInterval = settings.value(PAUSE_INTERVAL_SETTING,
|
||||||
PAUSE_INTERVAL_DEFAULT).toInt();
|
PAUSE_INTERVAL_DEFAULT).toInt();
|
||||||
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
|
_options.poiRadius = settings.value(POI_RADIUS_SETTING, POI_RADIUS_DEFAULT)
|
||||||
.toInt();
|
.toInt();
|
||||||
_options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT)
|
_options.useOpenGL = settings.value(USE_OPENGL_SETTING, USE_OPENGL_DEFAULT)
|
||||||
.toBool();
|
.toBool();
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
_options.enableHTTP2 = settings.value(ENABLE_HTTP2_SETTING,
|
||||||
|
ENABLE_HTTP2_DEFAULT).toBool();
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
_options.pixmapCache = settings.value(PIXMAP_CACHE_SETTING,
|
_options.pixmapCache = settings.value(PIXMAP_CACHE_SETTING,
|
||||||
PIXMAP_CACHE_DEFAULT).toInt();
|
PIXMAP_CACHE_DEFAULT).toInt();
|
||||||
|
_options.connectionTimeout = settings.value(CONNECTION_TIMEOUT_SETTING,
|
||||||
|
CONNECTION_TIMEOUT_DEFAULT).toInt();
|
||||||
_options.hiresPrint = settings.value(HIRES_PRINT_SETTING,
|
_options.hiresPrint = settings.value(HIRES_PRINT_SETTING,
|
||||||
HIRES_PRINT_DEFAULT).toBool();
|
HIRES_PRINT_DEFAULT).toBool();
|
||||||
_options.printName = settings.value(PRINT_NAME_SETTING, PRINT_NAME_DEFAULT)
|
_options.printName = settings.value(PRINT_NAME_SETTING, PRINT_NAME_DEFAULT)
|
||||||
@ -1903,10 +2058,15 @@ void GUI::readSettings()
|
|||||||
Track::setOutlierElimination(_options.outlierEliminate);
|
Track::setOutlierElimination(_options.outlierEliminate);
|
||||||
Track::setPauseSpeed(_options.pauseSpeed);
|
Track::setPauseSpeed(_options.pauseSpeed);
|
||||||
Track::setPauseInterval(_options.pauseInterval);
|
Track::setPauseInterval(_options.pauseInterval);
|
||||||
|
Track::useReportedSpeed(_options.useReportedSpeed);
|
||||||
|
|
||||||
_poi->setRadius(_options.poiRadius);
|
_poi->setRadius(_options.poiRadius);
|
||||||
|
|
||||||
QPixmapCache::setCacheLimit(_options.pixmapCache * 1024);
|
QPixmapCache::setCacheLimit(_options.pixmapCache * 1024);
|
||||||
|
Downloader::setTimeout(_options.connectionTimeout);
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
Downloader::enableHTTP2(_options.enableHTTP2);
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <QDate>
|
#include <QDate>
|
||||||
#include <QPrinter>
|
#include <QPrinter>
|
||||||
#include "data/graph.h"
|
#include "data/graph.h"
|
||||||
#include "data/poi.h"
|
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
#include "timetype.h"
|
#include "timetype.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
@ -20,6 +19,7 @@ class QTabWidget;
|
|||||||
class QActionGroup;
|
class QActionGroup;
|
||||||
class QAction;
|
class QAction;
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
class QSplitter;
|
||||||
class QSignalMapper;
|
class QSignalMapper;
|
||||||
class QPrinter;
|
class QPrinter;
|
||||||
class FileBrowser;
|
class FileBrowser;
|
||||||
@ -27,6 +27,7 @@ class GraphTab;
|
|||||||
class MapView;
|
class MapView;
|
||||||
class Map;
|
class Map;
|
||||||
class MapList;
|
class MapList;
|
||||||
|
class POI;
|
||||||
|
|
||||||
class GUI : public QMainWindow
|
class GUI : public QMainWindow
|
||||||
{
|
{
|
||||||
@ -34,7 +35,6 @@ class GUI : public QMainWindow
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GUI();
|
GUI();
|
||||||
~GUI();
|
|
||||||
|
|
||||||
bool openFile(const QString &fileName);
|
bool openFile(const QString &fileName);
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ private slots:
|
|||||||
void openFile();
|
void openFile();
|
||||||
void closeAll();
|
void closeAll();
|
||||||
void reloadFile();
|
void reloadFile();
|
||||||
|
void statistics();
|
||||||
void openPOIFile();
|
void openPOIFile();
|
||||||
void closePOIFiles();
|
void closePOIFiles();
|
||||||
void showGraphs(bool show);
|
void showGraphs(bool show);
|
||||||
@ -109,8 +110,8 @@ private:
|
|||||||
void updateStatusBarInfo();
|
void updateStatusBarInfo();
|
||||||
void updateWindowTitle();
|
void updateWindowTitle();
|
||||||
void updateNavigationActions();
|
void updateNavigationActions();
|
||||||
void updateGraphTabs();
|
bool updateGraphTabs();
|
||||||
void updateMapView();
|
bool updateMapView();
|
||||||
|
|
||||||
TimeType timeType() const;
|
TimeType timeType() const;
|
||||||
Units units() const;
|
Units units() const;
|
||||||
@ -150,6 +151,7 @@ private:
|
|||||||
QAction *_openFileAction;
|
QAction *_openFileAction;
|
||||||
QAction *_closeFileAction;
|
QAction *_closeFileAction;
|
||||||
QAction *_reloadFileAction;
|
QAction *_reloadFileAction;
|
||||||
|
QAction *_statisticsAction;
|
||||||
QAction *_openPOIAction;
|
QAction *_openPOIAction;
|
||||||
QAction *_closePOIAction;
|
QAction *_closePOIAction;
|
||||||
QAction *_showPOIAction;
|
QAction *_showPOIAction;
|
||||||
@ -196,6 +198,7 @@ private:
|
|||||||
QLabel *_distanceLabel;
|
QLabel *_distanceLabel;
|
||||||
QLabel *_timeLabel;
|
QLabel *_timeLabel;
|
||||||
|
|
||||||
|
QSplitter *_splitter;
|
||||||
MapView *_mapView;
|
MapView *_mapView;
|
||||||
QTabWidget *_graphTabWidget;
|
QTabWidget *_graphTabWidget;
|
||||||
QList<GraphTab*> _tabs;
|
QList<GraphTab*> _tabs;
|
||||||
|
@ -24,28 +24,33 @@ void HeartRateGraph::setInfo()
|
|||||||
clearInfo();
|
clearInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeartRateGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> HeartRateGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
const Graph &graph = data.tracks().at(i)->heartRate();
|
const Graph &graph = data.tracks().at(i)->heartRate();
|
||||||
|
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
continue;
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
HeartRateGraphItem *gi = new HeartRateGraphItem(graph, _graphType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
||||||
|
graphs.append(gi);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeartRateGraphItem *gi = new HeartRateGraphItem(graph, _graphType);
|
|
||||||
GraphView::addGraph(gi, paths.at(i));
|
|
||||||
|
|
||||||
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
skipColor();
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal HeartRateGraph::avg() const
|
qreal HeartRateGraph::avg() const
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
HeartRateGraph(QWidget *parent = 0);
|
HeartRateGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Heart rate");}
|
QString label() const {return tr("Heart rate");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void showTracks(bool show);
|
void showTracks(bool show);
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
||||||
{
|
{
|
||||||
|
_font.setPixelSize(FONT_SIZE);
|
||||||
|
_font.setFamily(FONT_FAMILY);
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
@ -14,16 +17,14 @@ InfoItem::InfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
|||||||
|
|
||||||
void InfoItem::updateBoundingRect()
|
void InfoItem::updateBoundingRect()
|
||||||
{
|
{
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QList<KV>::const_iterator i;
|
|
||||||
qreal width = 0;
|
qreal width = 0;
|
||||||
|
|
||||||
for (i = _list.constBegin(); i != _list.constEnd(); i++) {
|
for (QList<KV>::const_iterator i = _list.constBegin();
|
||||||
width += fm.width(i->key + ": ");
|
i != _list.constEnd(); i++) {
|
||||||
width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
|
width += fm.width(i->key() + ": ");
|
||||||
|
width += fm.width(i->value()) + ((i == _list.constEnd() - 1)
|
||||||
|
? 0 : PADDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
_boundingRect = QRectF(0, 0, width, _list.isEmpty() ? 0 : fm.height());
|
_boundingRect = QRectF(0, 0, width, _list.isEmpty() ? 0 : fm.height());
|
||||||
@ -34,22 +35,19 @@ void InfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget);
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
painter->setFont(font);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QList<KV>::const_iterator i;
|
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
|
||||||
|
painter->setFont(_font);
|
||||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
|
||||||
for (i = _list.constBegin(); i != _list.constEnd(); i++) {
|
for (QList<KV>::const_iterator i = _list.constBegin();
|
||||||
painter->drawText(width, fm.height() - fm.descent(), i->key + ": ");
|
i != _list.constEnd(); i++) {
|
||||||
width += fm.width(i->key + ": ");
|
painter->drawText(width, fm.height() - fm.descent(), i->key() + ": ");
|
||||||
painter->drawText(width, fm.height() - fm.descent(), i->value);
|
width += fm.width(i->key() + ": ");
|
||||||
width += fm.width(i->value) + ((i == _list.constEnd() - 1) ? 0 : PADDING);
|
painter->drawText(width, fm.height() - fm.descent(), i->value());
|
||||||
|
width += fm.width(i->value()) + ((i == _list.constEnd() - 1)
|
||||||
|
? 0 : PADDING);
|
||||||
if (i != _list.constEnd() - 1) {
|
if (i != _list.constEnd() - 1) {
|
||||||
painter->save();
|
painter->save();
|
||||||
painter->setPen(Qt::gray);
|
painter->setPen(Qt::gray);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <QGraphicsItem>
|
#include <QGraphicsItem>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include "kv.h"
|
||||||
|
|
||||||
class InfoItem : public QGraphicsItem
|
class InfoItem : public QGraphicsItem
|
||||||
{
|
{
|
||||||
@ -13,6 +14,8 @@ public:
|
|||||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
QWidget *widget);
|
QWidget *widget);
|
||||||
|
|
||||||
|
const QList<KV> &info() const {return _list;}
|
||||||
|
|
||||||
void insert(const QString &key, const QString &value);
|
void insert(const QString &key, const QString &value);
|
||||||
void clear();
|
void clear();
|
||||||
bool isEmpty() {return _list.isEmpty();}
|
bool isEmpty() {return _list.isEmpty();}
|
||||||
@ -20,19 +23,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
void updateBoundingRect();
|
void updateBoundingRect();
|
||||||
|
|
||||||
class KV {
|
|
||||||
public:
|
|
||||||
QString key;
|
|
||||||
QString value;
|
|
||||||
|
|
||||||
KV(const QString &k, const QString &v)
|
|
||||||
{key = k; value = v;}
|
|
||||||
bool operator==(const KV &other) const
|
|
||||||
{return this->key == other.key;}
|
|
||||||
};
|
|
||||||
|
|
||||||
QList<KV> _list;
|
QList<KV> _list;
|
||||||
QRectF _boundingRect;
|
QRectF _boundingRect;
|
||||||
|
QFont _font;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // INFOITEM_H
|
#endif // INFOITEM_H
|
||||||
|
@ -9,10 +9,8 @@
|
|||||||
#define FIRST_KEY Qt::Key_Home
|
#define FIRST_KEY Qt::Key_Home
|
||||||
#define LAST_KEY Qt::Key_End
|
#define LAST_KEY Qt::Key_End
|
||||||
#define MODIFIER Qt::ShiftModifier
|
#define MODIFIER Qt::ShiftModifier
|
||||||
|
#define ZOOM_IN Qt::Key_Plus
|
||||||
#define ZOOM_IN QKeySequence::ZoomIn
|
#define ZOOM_OUT Qt::Key_Minus
|
||||||
#define ZOOM_OUT QKeySequence::ZoomOut
|
|
||||||
|
|
||||||
#define TOGGLE_GRAPH_TYPE_KEY Qt::Key_X
|
#define TOGGLE_GRAPH_TYPE_KEY Qt::Key_X
|
||||||
#define TOGGLE_TIME_TYPE_KEY Qt::Key_T
|
#define TOGGLE_TIME_TYPE_KEY Qt::Key_T
|
||||||
|
|
||||||
@ -26,6 +24,7 @@
|
|||||||
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)
|
#define NEXT_MAP_SHORTCUT QKeySequence(QKeySequence::Forward)
|
||||||
#define PREV_MAP_SHORTCUT QKeySequence(QKeySequence::Back)
|
#define PREV_MAP_SHORTCUT QKeySequence(QKeySequence::Back)
|
||||||
#define SHOW_GRAPHS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_G)
|
#define SHOW_GRAPHS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_G)
|
||||||
|
#define STATISTICS_SHORTCUT QKeySequence(Qt::CTRL + Qt::Key_S)
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#define FULLSCREEN_SHORTCUT QKeySequence(Qt::META + Qt::CTRL + Qt::Key_F)
|
#define FULLSCREEN_SHORTCUT QKeySequence(Qt::META + Qt::CTRL + Qt::Key_F)
|
||||||
|
21
src/GUI/kv.h
Normal file
21
src/GUI/kv.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef KV_H
|
||||||
|
#define KV_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class KV {
|
||||||
|
public:
|
||||||
|
KV(const QString &key, const QString &value) : _key(key), _value(value) {}
|
||||||
|
|
||||||
|
const QString &key() const {return _key;}
|
||||||
|
const QString &value() const {return _value;}
|
||||||
|
|
||||||
|
bool operator==(const KV &other) const
|
||||||
|
{return this->key() == other.key();}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _key;
|
||||||
|
QString _value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KV_H
|
@ -75,7 +75,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
|||||||
_plot = false;
|
_plot = false;
|
||||||
_digitalZoom = 0;
|
_digitalZoom = 0;
|
||||||
|
|
||||||
_map->setBackgroundColor(_backgroundColor);
|
|
||||||
_res = _map->resolution(_map->bounds());
|
_res = _map->resolution(_map->bounds());
|
||||||
_scene->setSceneRect(_map->bounds());
|
_scene->setSceneRect(_map->bounds());
|
||||||
|
|
||||||
@ -267,7 +266,6 @@ void MapView::setMap(Map *map)
|
|||||||
|
|
||||||
_map = map;
|
_map = map;
|
||||||
_map->load();
|
_map->load();
|
||||||
_map->setBackgroundColor(_backgroundColor);
|
|
||||||
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
||||||
|
|
||||||
digitalZoom(0);
|
digitalZoom(0);
|
||||||
@ -421,7 +419,7 @@ void MapView::digitalZoom(int zoom)
|
|||||||
_mapScale->setDigitalZoom(_digitalZoom);
|
_mapScale->setDigitalZoom(_digitalZoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::zoom(int zoom, const QPoint &pos, const Coordinates &c)
|
void MapView::zoom(int zoom, const QPoint &pos)
|
||||||
{
|
{
|
||||||
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
||||||
|
|
||||||
@ -433,9 +431,9 @@ void MapView::zoom(int zoom, const QPoint &pos, const Coordinates &c)
|
|||||||
|
|
||||||
digitalZoom(zoom);
|
digitalZoom(zoom);
|
||||||
} else {
|
} else {
|
||||||
qreal os, ns;
|
Coordinates c = _map->xy2ll(mapToScene(pos));
|
||||||
os = _map->zoom();
|
qreal os = _map->zoom();
|
||||||
ns = (zoom > 0) ? _map->zoomIn() : _map->zoomOut();
|
qreal ns = (zoom > 0) ? _map->zoomIn() : _map->zoomOut();
|
||||||
|
|
||||||
if (ns != os) {
|
if (ns != os) {
|
||||||
rescale();
|
rescale();
|
||||||
@ -456,8 +454,7 @@ void MapView::wheelEvent(QWheelEvent *event)
|
|||||||
return;
|
return;
|
||||||
deg = 0;
|
deg = 0;
|
||||||
|
|
||||||
Coordinates c = _map->xy2ll(mapToScene(event->pos()));
|
zoom((event->delta() > 0) ? 1 : -1, event->pos());
|
||||||
zoom((event->delta() > 0) ? 1 : -1, event->pos(), c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::mouseDoubleClickEvent(QMouseEvent *event)
|
void MapView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
@ -465,8 +462,7 @@ void MapView::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
|
if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Coordinates c = _map->xy2ll(mapToScene(event->pos()));
|
zoom((event->button() == Qt::LeftButton) ? 1 : -1, event->pos());
|
||||||
zoom((event->button() == Qt::LeftButton) ? 1 : -1, event->pos(), c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::keyPressEvent(QKeyEvent *event)
|
void MapView::keyPressEvent(QKeyEvent *event)
|
||||||
@ -474,11 +470,10 @@ void MapView::keyPressEvent(QKeyEvent *event)
|
|||||||
int z;
|
int z;
|
||||||
|
|
||||||
QPoint pos = viewport()->rect().center();
|
QPoint pos = viewport()->rect().center();
|
||||||
Coordinates c = _map->xy2ll(mapToScene(pos));
|
|
||||||
|
|
||||||
if (event->matches(ZOOM_IN))
|
if (event->key() == ZOOM_IN)
|
||||||
z = 1;
|
z = 1;
|
||||||
else if (event->matches(ZOOM_OUT))
|
else if (event->key() == ZOOM_OUT)
|
||||||
z = -1;
|
z = -1;
|
||||||
else if (_digitalZoom && event->key() == Qt::Key_Escape) {
|
else if (_digitalZoom && event->key() == Qt::Key_Escape) {
|
||||||
digitalZoom(0);
|
digitalZoom(0);
|
||||||
@ -488,7 +483,7 @@ void MapView::keyPressEvent(QKeyEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
zoom(z, pos, c);
|
zoom(z, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||||
@ -497,13 +492,12 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
QRect orig, adj;
|
QRect orig, adj;
|
||||||
qreal ratio, diff, q;
|
qreal ratio, diff, q;
|
||||||
QPointF origScene, origPos;
|
QPointF origScene, origPos;
|
||||||
RectC origC;
|
int zoom;
|
||||||
|
|
||||||
|
|
||||||
// Enter plot mode
|
// Enter plot mode
|
||||||
setUpdatesEnabled(false);
|
setUpdatesEnabled(false);
|
||||||
_plot = true;
|
_plot = true;
|
||||||
_map->setBlockingMode(true);
|
|
||||||
|
|
||||||
// Compute sizes & ratios
|
// Compute sizes & ratios
|
||||||
orig = viewport()->rect();
|
orig = viewport()->rect();
|
||||||
@ -522,8 +516,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
|
|
||||||
// Adjust the view for printing
|
// Adjust the view for printing
|
||||||
if (hires) {
|
if (hires) {
|
||||||
|
zoom = _map->zoom();
|
||||||
QRectF vr(mapToScene(orig).boundingRect());
|
QRectF vr(mapToScene(orig).boundingRect());
|
||||||
origC = RectC(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
|
||||||
origScene = vr.center();
|
origScene = vr.center();
|
||||||
|
|
||||||
QPointF s(painter->device()->logicalDpiX()
|
QPointF s(painter->device()->logicalDpiX()
|
||||||
@ -538,12 +532,12 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
centerOn(center);
|
centerOn(center);
|
||||||
adj.moveCenter(mapFromScene(center));
|
adj.moveCenter(mapFromScene(center));
|
||||||
|
|
||||||
_mapScale->setDigitalZoom(-log2(s.x() / q));
|
_mapScale->setDigitalZoom(_digitalZoom - log2(s.x() / q));
|
||||||
_mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
|
_mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
|
||||||
-(SCALE_OFFSET + _mapScale->boundingRect().width()) * (s.x() / q),
|
-(SCALE_OFFSET + _mapScale->boundingRect().width()) * (s.x() / q),
|
||||||
-(SCALE_OFFSET + _mapScale->boundingRect().height()) * (s.x() / q)))));
|
-(SCALE_OFFSET + _mapScale->boundingRect().height()) * (s.x() / q)))));
|
||||||
} else {
|
} else {
|
||||||
_mapScale->setDigitalZoom(-log2(1.0 / q));
|
_mapScale->setDigitalZoom(_digitalZoom - log2(1.0 / q));
|
||||||
_mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
|
_mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
|
||||||
-(SCALE_OFFSET + _mapScale->boundingRect().width()) / q ,
|
-(SCALE_OFFSET + _mapScale->boundingRect().width()) / q ,
|
||||||
-(SCALE_OFFSET + _mapScale->boundingRect().height()) / q))));
|
-(SCALE_OFFSET + _mapScale->boundingRect().height()) / q))));
|
||||||
@ -554,15 +548,14 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
|||||||
|
|
||||||
// Revert view changes to display mode
|
// Revert view changes to display mode
|
||||||
if (hires) {
|
if (hires) {
|
||||||
_map->zoomFit(orig.size(), origC);
|
_map->setZoom(zoom);
|
||||||
rescale();
|
rescale();
|
||||||
centerOn(origScene);
|
centerOn(origScene);
|
||||||
}
|
}
|
||||||
_mapScale->setDigitalZoom(0);
|
_mapScale->setDigitalZoom(_digitalZoom);
|
||||||
_mapScale->setPos(origPos);
|
_mapScale->setPos(origPos);
|
||||||
|
|
||||||
// Exit plot mode
|
// Exit plot mode
|
||||||
_map->setBlockingMode(false);
|
|
||||||
_plot = false;
|
_plot = false;
|
||||||
setUpdatesEnabled(true);
|
setUpdatesEnabled(true);
|
||||||
}
|
}
|
||||||
@ -751,7 +744,6 @@ void MapView::setMapOpacity(int opacity)
|
|||||||
void MapView::setBackgroundColor(const QColor &color)
|
void MapView::setBackgroundColor(const QColor &color)
|
||||||
{
|
{
|
||||||
_backgroundColor = color;
|
_backgroundColor = color;
|
||||||
_map->setBackgroundColor(color);
|
|
||||||
resetCachedContent();
|
resetCachedContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -763,7 +755,7 @@ void MapView::drawBackground(QPainter *painter, const QRectF &rect)
|
|||||||
QRectF ir = rect.intersected(_map->bounds());
|
QRectF ir = rect.intersected(_map->bounds());
|
||||||
if (_opacity < 1.0)
|
if (_opacity < 1.0)
|
||||||
painter->setOpacity(_opacity);
|
painter->setOpacity(_opacity);
|
||||||
_map->draw(painter, ir);
|
_map->draw(painter, ir, _plot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ class RouteItem;
|
|||||||
class WaypointItem;
|
class WaypointItem;
|
||||||
class ScaleItem;
|
class ScaleItem;
|
||||||
class PathItem;
|
class PathItem;
|
||||||
|
class GraphItem;
|
||||||
|
|
||||||
class MapView : public QGraphicsView
|
class MapView : public QGraphicsView
|
||||||
{
|
{
|
||||||
@ -30,7 +31,7 @@ class MapView : public QGraphicsView
|
|||||||
public:
|
public:
|
||||||
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
||||||
|
|
||||||
QList<PathItem*> loadData(const Data &data);
|
QList<PathItem *> loadData(const Data &data);
|
||||||
|
|
||||||
void setPalette(const Palette &palette);
|
void setPalette(const Palette &palette);
|
||||||
void setPOI(POI *poi);
|
void setPOI(POI *poi);
|
||||||
@ -84,7 +85,7 @@ private:
|
|||||||
QPointF contentCenter() const;
|
QPointF contentCenter() const;
|
||||||
void rescale();
|
void rescale();
|
||||||
void centerOn(const QPointF &pos);
|
void centerOn(const QPointF &pos);
|
||||||
void zoom(int zoom, const QPoint &pos, const Coordinates &c);
|
void zoom(int zoom, const QPoint &pos);
|
||||||
void digitalZoom(int zoom);
|
void digitalZoom(int zoom);
|
||||||
void updatePOIVisibility();
|
void updatePOIVisibility();
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) || defined(Q_OS_MAC)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <QGLFormat>
|
#include <QGLFormat>
|
||||||
#else
|
#else
|
||||||
@ -7,13 +7,13 @@
|
|||||||
#include <QSurfaceFormat>
|
#include <QSurfaceFormat>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) || defined(Q_OS_MAC)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
|
||||||
#define OPENGL_WIDGET QGLWidget
|
#define OPENGL_WIDGET QGLWidget
|
||||||
#else
|
#else
|
||||||
#define OPENGL_WIDGET QOpenGLWidget
|
#define OPENGL_WIDGET QOpenGLWidget
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0) || defined(Q_OS_MAC)
|
#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
|
||||||
#define OPENGL_SET_SAMPLES(samples) \
|
#define OPENGL_SET_SAMPLES(samples) \
|
||||||
{QGLFormat fmt; \
|
{QGLFormat fmt; \
|
||||||
fmt.setSamples(samples); \
|
fmt.setSamples(samples); \
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QSysInfo>
|
#include <QSysInfo>
|
||||||
#include "config.h"
|
|
||||||
#include "icons.h"
|
#include "icons.h"
|
||||||
#include "colorbox.h"
|
#include "colorbox.h"
|
||||||
#include "stylecombobox.h"
|
#include "stylecombobox.h"
|
||||||
@ -311,9 +310,25 @@ QWidget *OptionsDialog::createDataPage()
|
|||||||
pauseTab->setLayout(pauseLayout);
|
pauseTab->setLayout(pauseLayout);
|
||||||
|
|
||||||
|
|
||||||
|
_computed = new QRadioButton(tr("Computed from distance/time"));
|
||||||
|
_reported = new QRadioButton(tr("Recorded by device"));
|
||||||
|
if (_options->useReportedSpeed)
|
||||||
|
_reported->setChecked(true);
|
||||||
|
else
|
||||||
|
_computed->setChecked(true);
|
||||||
|
|
||||||
|
QFormLayout *sourceLayout = new QFormLayout();
|
||||||
|
sourceLayout->addWidget(_computed);
|
||||||
|
sourceLayout->addWidget(_reported);
|
||||||
|
|
||||||
|
QWidget *sourceTab = new QWidget();
|
||||||
|
sourceTab->setLayout(sourceLayout);
|
||||||
|
|
||||||
|
|
||||||
QTabWidget *filterPage = new QTabWidget();
|
QTabWidget *filterPage = new QTabWidget();
|
||||||
filterPage->addTab(filterTab, tr("Filtering"));
|
filterPage->addTab(filterTab, tr("Filtering"));
|
||||||
filterPage->addTab(pauseTab, tr("Pause detection"));
|
filterPage->addTab(pauseTab, tr("Pause detection"));
|
||||||
|
filterPage->addTab(sourceTab, tr("Speed"));
|
||||||
|
|
||||||
return filterPage;
|
return filterPage;
|
||||||
}
|
}
|
||||||
@ -424,6 +439,10 @@ QWidget *OptionsDialog::createSystemPage()
|
|||||||
{
|
{
|
||||||
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
|
_useOpenGL = new QCheckBox(tr("Use OpenGL"));
|
||||||
_useOpenGL->setChecked(_options->useOpenGL);
|
_useOpenGL->setChecked(_options->useOpenGL);
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
_enableHTTP2 = new QCheckBox(tr("Enable HTTP/2"));
|
||||||
|
_enableHTTP2->setChecked(_options->enableHTTP2);
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
_pixmapCache = new QSpinBox();
|
_pixmapCache = new QSpinBox();
|
||||||
_pixmapCache->setMinimum(16);
|
_pixmapCache->setMinimum(16);
|
||||||
@ -431,16 +450,26 @@ QWidget *OptionsDialog::createSystemPage()
|
|||||||
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
|
_pixmapCache->setSuffix(UNIT_SPACE + tr("MB"));
|
||||||
_pixmapCache->setValue(_options->pixmapCache);
|
_pixmapCache->setValue(_options->pixmapCache);
|
||||||
|
|
||||||
QFormLayout *cacheLayout = new QFormLayout();
|
_connectionTimeout = new QSpinBox();
|
||||||
cacheLayout->addRow(tr("Image cache size:"), _pixmapCache);
|
_connectionTimeout->setMinimum(30);
|
||||||
|
_connectionTimeout->setMaximum(120);
|
||||||
|
_connectionTimeout->setSuffix(UNIT_SPACE + tr("s"));
|
||||||
|
_connectionTimeout->setValue(_options->connectionTimeout);
|
||||||
|
|
||||||
QFormLayout *openGLLayout = new QFormLayout();
|
QFormLayout *formLayout = new QFormLayout();
|
||||||
openGLLayout->addWidget(_useOpenGL);
|
formLayout->addRow(tr("Image cache size:"), _pixmapCache);
|
||||||
|
formLayout->addRow(tr("Connection timeout:"), _connectionTimeout);
|
||||||
|
|
||||||
|
QFormLayout *checkboxLayout = new QFormLayout();
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
checkboxLayout->addWidget(_enableHTTP2);
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
checkboxLayout->addWidget(_useOpenGL);
|
||||||
|
|
||||||
QWidget *systemTab = new QWidget();
|
QWidget *systemTab = new QWidget();
|
||||||
QVBoxLayout *systemTabLayout = new QVBoxLayout();
|
QVBoxLayout *systemTabLayout = new QVBoxLayout();
|
||||||
systemTabLayout->addLayout(cacheLayout);
|
systemTabLayout->addLayout(formLayout);
|
||||||
systemTabLayout->addLayout(openGLLayout);
|
systemTabLayout->addLayout(checkboxLayout);
|
||||||
systemTabLayout->addStretch();
|
systemTabLayout->addStretch();
|
||||||
systemTab->setLayout(systemTabLayout);
|
systemTab->setLayout(systemTabLayout);
|
||||||
|
|
||||||
@ -536,6 +565,7 @@ void OptionsDialog::accept()
|
|||||||
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
|
if (qAbs(pauseSpeed - _options->pauseSpeed) > 0.01)
|
||||||
_options->pauseSpeed = pauseSpeed;
|
_options->pauseSpeed = pauseSpeed;
|
||||||
_options->pauseInterval = _pauseInterval->value();
|
_options->pauseInterval = _pauseInterval->value();
|
||||||
|
_options->useReportedSpeed = _reported->isChecked();
|
||||||
|
|
||||||
qreal poiRadius = (_options->units == Imperial)
|
qreal poiRadius = (_options->units == Imperial)
|
||||||
? _poiRadius->value() * MIINM : (_options->units == Nautical)
|
? _poiRadius->value() * MIINM : (_options->units == Nautical)
|
||||||
@ -544,7 +574,11 @@ void OptionsDialog::accept()
|
|||||||
_options->poiRadius = poiRadius;
|
_options->poiRadius = poiRadius;
|
||||||
|
|
||||||
_options->useOpenGL = _useOpenGL->isChecked();
|
_options->useOpenGL = _useOpenGL->isChecked();
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
_options->enableHTTP2 = _enableHTTP2->isChecked();
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
_options->pixmapCache = _pixmapCache->value();
|
_options->pixmapCache = _pixmapCache->value();
|
||||||
|
_options->connectionTimeout = _connectionTimeout->value();
|
||||||
|
|
||||||
_options->hiresPrint = _hires->isChecked();
|
_options->hiresPrint = _hires->isChecked();
|
||||||
_options->printName = _name->isChecked();
|
_options->printName = _name->isChecked();
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include "palette.h"
|
#include "palette.h"
|
||||||
#include "units.h"
|
#include "units.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
class ColorBox;
|
class ColorBox;
|
||||||
class StyleComboBox;
|
class StyleComboBox;
|
||||||
@ -43,11 +45,16 @@ struct Options {
|
|||||||
bool outlierEliminate;
|
bool outlierEliminate;
|
||||||
qreal pauseSpeed;
|
qreal pauseSpeed;
|
||||||
int pauseInterval;
|
int pauseInterval;
|
||||||
|
bool useReportedSpeed;
|
||||||
// POI
|
// POI
|
||||||
int poiRadius;
|
int poiRadius;
|
||||||
// System
|
// System
|
||||||
bool useOpenGL;
|
bool useOpenGL;
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
bool enableHTTP2;
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
int pixmapCache;
|
int pixmapCache;
|
||||||
|
int connectionTimeout;
|
||||||
// Print/Export
|
// Print/Export
|
||||||
bool hiresPrint;
|
bool hiresPrint;
|
||||||
bool printName;
|
bool printName;
|
||||||
@ -109,11 +116,17 @@ private:
|
|||||||
QCheckBox *_outlierEliminate;
|
QCheckBox *_outlierEliminate;
|
||||||
QDoubleSpinBox *_pauseSpeed;
|
QDoubleSpinBox *_pauseSpeed;
|
||||||
QSpinBox *_pauseInterval;
|
QSpinBox *_pauseInterval;
|
||||||
|
QRadioButton *_computed;
|
||||||
|
QRadioButton *_reported;
|
||||||
// POI
|
// POI
|
||||||
QDoubleSpinBox *_poiRadius;
|
QDoubleSpinBox *_poiRadius;
|
||||||
// System
|
// System
|
||||||
QSpinBox *_pixmapCache;
|
QSpinBox *_pixmapCache;
|
||||||
|
QSpinBox *_connectionTimeout;
|
||||||
QCheckBox *_useOpenGL;
|
QCheckBox *_useOpenGL;
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
QCheckBox *_enableHTTP2;
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
// Print/Export
|
// Print/Export
|
||||||
QRadioButton *_wysiwyg;
|
QRadioButton *_wysiwyg;
|
||||||
QRadioButton *_hires;
|
QRadioButton *_hires;
|
||||||
|
@ -175,10 +175,10 @@ void PathItem::setMarkerColor(const QColor &color)
|
|||||||
void PathItem::hover(bool hover)
|
void PathItem::hover(bool hover)
|
||||||
{
|
{
|
||||||
if (hover) {
|
if (hover) {
|
||||||
_pen.setWidth(_width + 1);
|
_pen.setWidth((_width + 1) * pow(2, -_digitalZoom));
|
||||||
setZValue(zValue() + 1.0);
|
setZValue(zValue() + 1.0);
|
||||||
} else {
|
} else {
|
||||||
_pen.setWidth(_width);
|
_pen.setWidth(_width * pow(2, -_digitalZoom));
|
||||||
setZValue(zValue() - 1.0);
|
setZValue(zValue() - 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,28 +24,33 @@ void PowerGraph::setInfo()
|
|||||||
clearInfo();
|
clearInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> PowerGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
const Graph &graph = data.tracks().at(i)->power();
|
const Graph &graph = data.tracks().at(i)->power();
|
||||||
|
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
continue;
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
PowerGraphItem *gi = new PowerGraphItem(graph, _graphType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
||||||
|
graphs.append(gi);
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerGraphItem *gi = new PowerGraphItem(graph, _graphType);
|
|
||||||
GraphView::addGraph(gi, paths.at(i));
|
|
||||||
|
|
||||||
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
skipColor();
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal PowerGraph::avg() const
|
qreal PowerGraph::avg() const
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
PowerGraph(QWidget *parent = 0);
|
PowerGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Power");}
|
QString label() const {return tr("Power");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void showTracks(bool show);
|
void showTracks(bool show);
|
||||||
|
|
||||||
|
@ -18,52 +18,34 @@ ScaleItem::ScaleItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
|||||||
_res = 1.0;
|
_res = 1.0;
|
||||||
_digitalZoom = 0;
|
_digitalZoom = 0;
|
||||||
|
|
||||||
|
_font.setPixelSize(FONT_SIZE);
|
||||||
|
_font.setFamily(FONT_FAMILY);
|
||||||
|
|
||||||
#ifndef Q_OS_MAC
|
#ifndef Q_OS_MAC
|
||||||
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
setCacheMode(QGraphicsItem::DeviceCoordinateCache);
|
||||||
#endif // Q_OS_MAC
|
#endif // Q_OS_MAC
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleItem::updateBoundingRect()
|
|
||||||
{
|
|
||||||
QFont font;
|
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect ss, es, us;
|
|
||||||
|
|
||||||
ss = fm.tightBoundingRect(QString::number(0));
|
|
||||||
es = fm.tightBoundingRect(QString::number(_length * SEGMENTS));
|
|
||||||
us = fm.tightBoundingRect(units());
|
|
||||||
|
|
||||||
_boundingRect = QRectF(-ss.width()/2, 0, _width * SEGMENTS + ss.width()/2
|
|
||||||
+ qMax(us.width() + PADDING, es.width()/2) + 1, SCALE_HEIGHT + PADDING
|
|
||||||
+ ss.height() + 2*fm.descent());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
QWidget *widget)
|
QWidget *widget)
|
||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget);
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect br;
|
QRect br;
|
||||||
QPen pen = QPen(Qt::black, BORDER_WIDTH);
|
|
||||||
|
|
||||||
|
|
||||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||||
painter->setFont(font);
|
painter->setFont(_font);
|
||||||
painter->setPen(pen);
|
painter->setPen(QPen(Qt::black, BORDER_WIDTH));
|
||||||
|
|
||||||
for (int i = 0; i <= SEGMENTS; i++) {
|
for (int i = 0; i < _ticks.size(); i++) {
|
||||||
QString label = QString::number(_length * i);
|
br = _ticks.at(i).boundingBox;
|
||||||
br = fm.tightBoundingRect(label);
|
painter->drawText(_width * i - br.width()/2, br.height() + 1,
|
||||||
painter->drawText(_width * i - br.width()/2, br.height() + 1, label);
|
QString::number(_ticks.at(i).value));
|
||||||
}
|
}
|
||||||
painter->drawText(_width * SEGMENTS + PADDING, SCALE_HEIGHT + PADDING
|
painter->drawText(_width * SEGMENTS + PADDING, SCALE_HEIGHT + PADDING
|
||||||
+ br.height() + fm.descent(), units());
|
+ br.height() + fm.descent(), _unitsStr);
|
||||||
|
|
||||||
painter->drawRect(QRectF(0, br.height() + PADDING, SEGMENTS * _width,
|
painter->drawRect(QRectF(0, br.height() + PADDING, SEGMENTS * _width,
|
||||||
SCALE_HEIGHT));
|
SCALE_HEIGHT));
|
||||||
@ -77,19 +59,6 @@ void ScaleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ScaleItem::units() const
|
|
||||||
{
|
|
||||||
if (_units == Imperial)
|
|
||||||
return _scale ? qApp->translate("ScaleItem", "mi")
|
|
||||||
: qApp->translate("ScaleItem", "ft");
|
|
||||||
else if (_units == Nautical)
|
|
||||||
return _scale ? qApp->translate("ScaleItem", "nmi")
|
|
||||||
: qApp->translate("ScaleItem", "ft");
|
|
||||||
else
|
|
||||||
return _scale ? qApp->translate("ScaleItem", "km")
|
|
||||||
: qApp->translate("ScaleItem", "m");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScaleItem::computeScale()
|
void ScaleItem::computeScale()
|
||||||
{
|
{
|
||||||
qreal res = _res * pow(2, -_digitalZoom);
|
qreal res = _res * pow(2, -_digitalZoom);
|
||||||
@ -127,21 +96,50 @@ void ScaleItem::computeScale()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScaleItem::updateCache()
|
||||||
|
{
|
||||||
|
QFontMetrics fm(_font);
|
||||||
|
|
||||||
|
_ticks = QVector<Tick>(SEGMENTS + 1);
|
||||||
|
for (int i = 0; i < _ticks.size(); i++) {
|
||||||
|
Tick &t = _ticks[i];
|
||||||
|
t.value = _length * i;
|
||||||
|
t.boundingBox = fm.tightBoundingRect(QString::number(t.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_units == Imperial)
|
||||||
|
_unitsStr = _scale ? qApp->translate("ScaleItem", "mi")
|
||||||
|
: qApp->translate("ScaleItem", "ft");
|
||||||
|
else if (_units == Nautical)
|
||||||
|
_unitsStr = _scale ? qApp->translate("ScaleItem", "nmi")
|
||||||
|
: qApp->translate("ScaleItem", "ft");
|
||||||
|
else
|
||||||
|
_unitsStr = _scale ? qApp->translate("ScaleItem", "km")
|
||||||
|
: qApp->translate("ScaleItem", "m");
|
||||||
|
_unitsBB = fm.tightBoundingRect(_unitsStr);
|
||||||
|
|
||||||
|
QRect ss = _ticks.isEmpty() ? QRect() : _ticks.first().boundingBox;
|
||||||
|
QRect es = _ticks.isEmpty() ? QRect() : _ticks.last().boundingBox;
|
||||||
|
_boundingRect = QRectF(-ss.width()/2, 0, _width * SEGMENTS + ss.width()/2
|
||||||
|
+ qMax(_unitsBB.width() + PADDING, es.width()/2) + 1, SCALE_HEIGHT
|
||||||
|
+ PADDING + ss.height() + 2*fm.descent());
|
||||||
|
}
|
||||||
|
|
||||||
void ScaleItem::setResolution(qreal res)
|
void ScaleItem::setResolution(qreal res)
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_res = res;
|
_res = res;
|
||||||
computeScale();
|
computeScale();
|
||||||
updateBoundingRect();
|
updateCache();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScaleItem::setUnits(enum Units units)
|
void ScaleItem::setUnits(Units units)
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_units = units;
|
_units = units;
|
||||||
computeScale();
|
computeScale();
|
||||||
updateBoundingRect();
|
updateCache();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,7 +148,7 @@ void ScaleItem::setDigitalZoom(qreal zoom)
|
|||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_digitalZoom = zoom;
|
_digitalZoom = zoom;
|
||||||
computeScale();
|
computeScale();
|
||||||
updateBoundingRect();
|
updateCache();
|
||||||
update();
|
update();
|
||||||
|
|
||||||
setScale(pow(2, -_digitalZoom));
|
setScale(pow(2, -_digitalZoom));
|
||||||
|
@ -14,23 +14,29 @@ public:
|
|||||||
QWidget *widget);
|
QWidget *widget);
|
||||||
|
|
||||||
void setResolution(qreal res);
|
void setResolution(qreal res);
|
||||||
void setUnits(enum Units units);
|
void setUnits(Units units);
|
||||||
void setDigitalZoom(qreal zoom);
|
void setDigitalZoom(qreal zoom);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateBoundingRect();
|
struct Tick {
|
||||||
|
double value;
|
||||||
|
QRect boundingBox;
|
||||||
|
};
|
||||||
|
|
||||||
void computeScale();
|
void computeScale();
|
||||||
QString units() const;
|
void updateCache();
|
||||||
|
|
||||||
qreal _res;
|
qreal _res;
|
||||||
qreal _width;
|
qreal _width;
|
||||||
qreal _length;
|
qreal _length;
|
||||||
Units _units;
|
Units _units;
|
||||||
bool _scale;
|
bool _scale;
|
||||||
|
|
||||||
qreal _digitalZoom;
|
qreal _digitalZoom;
|
||||||
|
|
||||||
QRectF _boundingRect;
|
QRectF _boundingRect;
|
||||||
|
QFont _font;
|
||||||
|
QVector<Tick> _ticks;
|
||||||
|
QRect _unitsBB;
|
||||||
|
QString _unitsStr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SCALEITEM_H
|
#endif // SCALEITEM_H
|
||||||
|
@ -124,12 +124,18 @@
|
|||||||
#define PAUSE_SPEED_DEFAULT 0.5 /* m/s */
|
#define PAUSE_SPEED_DEFAULT 0.5 /* m/s */
|
||||||
#define PAUSE_INTERVAL_SETTING "pauseInterval"
|
#define PAUSE_INTERVAL_SETTING "pauseInterval"
|
||||||
#define PAUSE_INTERVAL_DEFAULT 10 /* s */
|
#define PAUSE_INTERVAL_DEFAULT 10 /* s */
|
||||||
|
#define USE_REPORTED_SPEED_SETTING "useReportedSpeed"
|
||||||
|
#define USE_REPORTED_SPEED_DEFAULT false
|
||||||
#define POI_RADIUS_SETTING "poiRadius"
|
#define POI_RADIUS_SETTING "poiRadius"
|
||||||
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
|
#define POI_RADIUS_DEFAULT (int)(IMPERIAL_UNITS() ? MIINM : KMINM)
|
||||||
#define USE_OPENGL_SETTING "useOpenGL"
|
#define USE_OPENGL_SETTING "useOpenGL"
|
||||||
#define USE_OPENGL_DEFAULT false
|
#define USE_OPENGL_DEFAULT false
|
||||||
|
#define ENABLE_HTTP2_SETTING "enableHTTP2"
|
||||||
|
#define ENABLE_HTTP2_DEFAULT true
|
||||||
#define PIXMAP_CACHE_SETTING "pixmapCache"
|
#define PIXMAP_CACHE_SETTING "pixmapCache"
|
||||||
#define PIXMAP_CACHE_DEFAULT 64 /* MB */
|
#define PIXMAP_CACHE_DEFAULT 64 /* MB */
|
||||||
|
#define CONNECTION_TIMEOUT_SETTING "connectionTimeout"
|
||||||
|
#define CONNECTION_TIMEOUT_DEFAULT 30 /* s */
|
||||||
#define HIRES_PRINT_SETTING "hiresPrint"
|
#define HIRES_PRINT_SETTING "hiresPrint"
|
||||||
#define HIRES_PRINT_DEFAULT false
|
#define HIRES_PRINT_DEFAULT false
|
||||||
#define PRINT_NAME_SETTING "printName"
|
#define PRINT_NAME_SETTING "printName"
|
||||||
|
@ -9,14 +9,14 @@ SliderInfoItem::SliderInfoItem(QGraphicsItem *parent) : QGraphicsItem(parent)
|
|||||||
{
|
{
|
||||||
_side = Right;
|
_side = Right;
|
||||||
_color = Qt::red;
|
_color = Qt::red;
|
||||||
|
|
||||||
|
_font.setPixelSize(FONT_SIZE);
|
||||||
|
_font.setFamily(FONT_FAMILY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SliderInfoItem::updateBoundingRect()
|
void SliderInfoItem::updateBoundingRect()
|
||||||
{
|
{
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
|
|
||||||
qreal width = qMax(fm.width(_x), fm.width(_y));
|
qreal width = qMax(fm.width(_x), fm.width(_y));
|
||||||
qreal height = 2 * fm.height() - 2*fm.descent();
|
qreal height = 2 * fm.height() - 2*fm.descent();
|
||||||
@ -31,10 +31,7 @@ void SliderInfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
|
|||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget);
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FONT_SIZE);
|
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRectF rx, ry;
|
QRectF rx, ry;
|
||||||
|
|
||||||
|
|
||||||
@ -57,7 +54,7 @@ void SliderInfoItem::paint(QPainter *painter, const QStyleOptionGraphicsItem
|
|||||||
painter->drawRect(rx);
|
painter->drawRect(rx);
|
||||||
painter->setBrush(Qt::NoBrush);
|
painter->setBrush(Qt::NoBrush);
|
||||||
|
|
||||||
painter->setFont(font);
|
painter->setFont(_font);
|
||||||
painter->setRenderHint(QPainter::Antialiasing, false);
|
painter->setRenderHint(QPainter::Antialiasing, false);
|
||||||
painter->setPen(_color);
|
painter->setPen(_color);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ private:
|
|||||||
QString _x, _y;
|
QString _x, _y;
|
||||||
QRectF _boundingRect;
|
QRectF _boundingRect;
|
||||||
QColor _color;
|
QColor _color;
|
||||||
|
QFont _font;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SLIDERINFOITEM_H
|
#endif // SLIDERINFOITEM_H
|
||||||
|
@ -34,32 +34,37 @@ void SpeedGraph::setInfo()
|
|||||||
clearInfo();
|
clearInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeedGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> SpeedGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
const Track *track = data.tracks().at(i);
|
const Track *track = data.tracks().at(i);
|
||||||
const Graph &graph = track->speed();
|
const Graph &graph = track->speed();
|
||||||
|
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
continue;
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
SpeedGraphItem *gi = new SpeedGraphItem(graph, _graphType,
|
||||||
|
track->movingTime());
|
||||||
|
gi->setTimeType(_timeType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
_avg.append(QPointF(track->distance(), gi->avg()));
|
||||||
|
_mavg.append(QPointF(track->distance(), gi->mavg()));
|
||||||
|
graphs.append(gi);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeedGraphItem *gi = new SpeedGraphItem(graph, _graphType,
|
|
||||||
track->movingTime());
|
|
||||||
gi->setTimeType(_timeType);
|
|
||||||
GraphView::addGraph(gi, paths.at(i));
|
|
||||||
|
|
||||||
_avg.append(QPointF(track->distance(), gi->avg()));
|
|
||||||
_mavg.append(QPointF(track->distance(), gi->mavg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
skipColor();
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal SpeedGraph::avg() const
|
qreal SpeedGraph::avg() const
|
||||||
|
@ -12,7 +12,7 @@ public:
|
|||||||
SpeedGraph(QWidget *parent = 0);
|
SpeedGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Speed");}
|
QString label() const {return tr("Speed");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void setUnits(Units units);
|
void setUnits(Units units);
|
||||||
void setTimeType(TimeType type);
|
void setTimeType(TimeType type);
|
||||||
|
@ -26,28 +26,34 @@ void TemperatureGraph::setInfo()
|
|||||||
clearInfo();
|
clearInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemperatureGraph::loadData(const Data &data, const QList<PathItem *> &paths)
|
QList<GraphItem*> TemperatureGraph::loadData(const Data &data)
|
||||||
{
|
{
|
||||||
|
QList<GraphItem*> graphs;
|
||||||
|
|
||||||
for (int i = 0; i < data.tracks().count(); i++) {
|
for (int i = 0; i < data.tracks().count(); i++) {
|
||||||
const Graph &graph = data.tracks().at(i)->temperature();
|
const Graph &graph = data.tracks().at(i)->temperature();
|
||||||
|
|
||||||
if (graph.size() < 2) {
|
if (graph.size() < 2) {
|
||||||
skipColor();
|
skipColor();
|
||||||
continue;
|
graphs.append(0);
|
||||||
|
} else {
|
||||||
|
TemperatureGraphItem *gi = new TemperatureGraphItem(graph,
|
||||||
|
_graphType);
|
||||||
|
GraphView::addGraph(gi);
|
||||||
|
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
||||||
|
graphs.append(gi);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemperatureGraphItem *gi = new TemperatureGraphItem(graph, _graphType);
|
|
||||||
GraphView::addGraph(gi, paths.at(i));
|
|
||||||
|
|
||||||
_avg.append(QPointF(data.tracks().at(i)->distance(), gi->avg()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < data.routes().count(); i++)
|
for (int i = 0; i < data.routes().count(); i++) {
|
||||||
skipColor();
|
skipColor();
|
||||||
|
graphs.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
setInfo();
|
setInfo();
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
|
|
||||||
|
return graphs;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal TemperatureGraph::avg() const
|
qreal TemperatureGraph::avg() const
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
TemperatureGraph(QWidget *parent = 0);
|
TemperatureGraph(QWidget *parent = 0);
|
||||||
|
|
||||||
QString label() const {return tr("Temperature");}
|
QString label() const {return tr("Temperature");}
|
||||||
void loadData(const Data &data, const QList<PathItem *> &paths);
|
QList<GraphItem*> loadData(const Data &data);
|
||||||
void clear();
|
void clear();
|
||||||
void setUnits(enum Units units);
|
void setUnits(enum Units units);
|
||||||
void showTracks(bool show);
|
void showTracks(bool show);
|
||||||
|
@ -36,11 +36,13 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
|||||||
{
|
{
|
||||||
_waypoint = waypoint;
|
_waypoint = waypoint;
|
||||||
_showLabel = true;
|
_showLabel = true;
|
||||||
_hover = false;
|
|
||||||
_size = 8;
|
_size = 8;
|
||||||
_color = Qt::black;
|
_color = Qt::black;
|
||||||
|
|
||||||
updateShape();
|
_font.setPixelSize(FS(_size));
|
||||||
|
_font.setFamily(FONT_FAMILY);
|
||||||
|
|
||||||
|
updateCache();
|
||||||
|
|
||||||
setPos(map->ll2xy(waypoint.coordinates()));
|
setPos(map->ll2xy(waypoint.coordinates()));
|
||||||
setToolTip(toolTip(Metric, DecimalDegrees));
|
setToolTip(toolTip(Metric, DecimalDegrees));
|
||||||
@ -48,23 +50,18 @@ WaypointItem::WaypointItem(const Waypoint &waypoint, Map *map,
|
|||||||
setAcceptHoverEvents(true);
|
setAcceptHoverEvents(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointItem::updateShape()
|
void WaypointItem::updateCache()
|
||||||
{
|
{
|
||||||
QPainterPath p;
|
QPainterPath p;
|
||||||
qreal pointSize = _hover ? HS(_size) : _size;
|
qreal pointSize = _font.bold() ? HS(_size) : _size;
|
||||||
|
|
||||||
if (_showLabel) {
|
if (_showLabel) {
|
||||||
QFont font;
|
QFontMetrics fm(_font);
|
||||||
font.setPixelSize(FS(_size));
|
_labelBB = fm.tightBoundingRect(_waypoint.name());
|
||||||
font.setFamily(FONT_FAMILY);
|
|
||||||
if (_hover)
|
|
||||||
font.setBold(true);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect ts = fm.tightBoundingRect(_waypoint.name());
|
|
||||||
|
|
||||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||||
p.addRect(pointSize/2, pointSize/2,
|
p.addRect(pointSize/2, pointSize/2, _labelBB.width(), _labelBB.height()
|
||||||
ts.width(), ts.height() + fm.descent());
|
+ fm.descent());
|
||||||
} else
|
} else
|
||||||
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
p.addRect(-pointSize/2, -pointSize/2, pointSize, pointSize);
|
||||||
|
|
||||||
@ -76,23 +73,14 @@ void WaypointItem::paint(QPainter *painter,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(option);
|
Q_UNUSED(option);
|
||||||
Q_UNUSED(widget);
|
Q_UNUSED(widget);
|
||||||
|
qreal pointSize = _font.bold() ? HS(_size) : _size;
|
||||||
qreal pointSize = _hover ? HS(_size) : _size;
|
|
||||||
|
|
||||||
painter->setPen(_color);
|
painter->setPen(_color);
|
||||||
|
|
||||||
if (_showLabel) {
|
if (_showLabel) {
|
||||||
QFont font;
|
painter->setFont(_font);
|
||||||
font.setPixelSize(FS(_size));
|
painter->drawText(pointSize/2 - qMax(_labelBB.x(), 0), pointSize/2
|
||||||
font.setFamily(FONT_FAMILY);
|
+ _labelBB.height(), _waypoint.name());
|
||||||
if (_hover)
|
|
||||||
font.setBold(true);
|
|
||||||
QFontMetrics fm(font);
|
|
||||||
QRect ts = fm.tightBoundingRect(_waypoint.name());
|
|
||||||
|
|
||||||
painter->setFont(font);
|
|
||||||
painter->drawText(pointSize/2 - qMax(ts.x(), 0), pointSize/2
|
|
||||||
+ ts.height(), _waypoint.name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
painter->setBrush(QBrush(_color, Qt::SolidPattern));
|
painter->setBrush(QBrush(_color, Qt::SolidPattern));
|
||||||
@ -112,7 +100,8 @@ void WaypointItem::setSize(int size)
|
|||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_size = size;
|
_size = size;
|
||||||
updateShape();
|
_font.setPixelSize(FS(_size));
|
||||||
|
updateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointItem::setColor(const QColor &color)
|
void WaypointItem::setColor(const QColor &color)
|
||||||
@ -136,7 +125,7 @@ void WaypointItem::showLabel(bool show)
|
|||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_showLabel = show;
|
_showLabel = show;
|
||||||
updateShape();
|
updateCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaypointItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
void WaypointItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||||
@ -144,8 +133,8 @@ void WaypointItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_hover = true;
|
_font.setBold(true);
|
||||||
updateShape();
|
updateCache();
|
||||||
setZValue(zValue() + 1.0);
|
setZValue(zValue() + 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +143,7 @@ void WaypointItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
|
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
_hover = false;
|
_font.setBold(false);
|
||||||
updateShape();
|
updateCache();
|
||||||
setZValue(zValue() - 1.0);
|
setZValue(zValue() - 1.0);
|
||||||
}
|
}
|
||||||
|
@ -31,16 +31,16 @@ private:
|
|||||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||||
|
|
||||||
void updateShape();
|
void updateCache();
|
||||||
QString toolTip(Units units, CoordinatesFormat format);
|
QString toolTip(Units units, CoordinatesFormat format);
|
||||||
|
|
||||||
QPainterPath _shape;
|
|
||||||
Waypoint _waypoint;
|
Waypoint _waypoint;
|
||||||
|
QPainterPath _shape;
|
||||||
QColor _color;
|
QColor _color;
|
||||||
int _size;
|
int _size;
|
||||||
bool _hover;
|
|
||||||
bool _showLabel;
|
bool _showLabel;
|
||||||
|
QFont _font;
|
||||||
|
QRect _labelBB;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WAYPOINTITEM_H
|
#endif // WAYPOINTITEM_H
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#ifndef M_PI
|
|
||||||
#define M_PI 3.14159265358979323846
|
|
||||||
#endif // M_PI
|
|
||||||
#define deg2rad(d) (((d)*M_PI)/180.0)
|
#define deg2rad(d) (((d)*M_PI)/180.0)
|
||||||
#define rad2deg(d) (((d)*180.0)/M_PI)
|
#define rad2deg(d) (((d)*180.0)/M_PI)
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ RectC::RectC(const Coordinates ¢er, double radius)
|
|||||||
double deltaLon = asin(sin(radDist) / cos(radlat));
|
double deltaLon = asin(sin(radDist) / cos(radlat));
|
||||||
minLon = radLon - deltaLon;
|
minLon = radLon - deltaLon;
|
||||||
if (minLon < MIN_LON)
|
if (minLon < MIN_LON)
|
||||||
minLon += 2.0 * M_PI;
|
minLon += M_2_PI;
|
||||||
maxLon = radLon + deltaLon;
|
maxLon = radLon + deltaLon;
|
||||||
if (maxLon > MAX_LON)
|
if (maxLon > MAX_LON)
|
||||||
maxLon -= 2.0 * M_PI;
|
maxLon -= M_2_PI;
|
||||||
} else {
|
} else {
|
||||||
// a pole is within the distance
|
// a pole is within the distance
|
||||||
minLat = qMax(minLat, MIN_LAT);
|
minLat = qMax(minLat, MIN_LAT);
|
||||||
|
@ -3,15 +3,9 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cassert>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
#define ASSERT assert // RTree uses ASSERT( condition )
|
|
||||||
|
|
||||||
#define Max(a,b) \
|
|
||||||
(((a) > (b)) ? (a) : (b))
|
|
||||||
#define Min(a,b) \
|
|
||||||
(((a) < (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, \
|
#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, \
|
||||||
class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
|
class ELEMTYPEREAL, int TMAXNODES, int TMINNODES>
|
||||||
@ -129,7 +123,7 @@ public:
|
|||||||
/// Access the current data element.
|
/// Access the current data element.
|
||||||
DATATYPE& operator*()
|
DATATYPE& operator*()
|
||||||
{
|
{
|
||||||
ASSERT(IsNotNull());
|
Q_ASSERT(IsNotNull());
|
||||||
StackElement& curTos = m_stack[m_tos - 1];
|
StackElement& curTos = m_stack[m_tos - 1];
|
||||||
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
|
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
|
||||||
}
|
}
|
||||||
@ -137,7 +131,7 @@ public:
|
|||||||
/// Access the current data element.
|
/// Access the current data element.
|
||||||
const DATATYPE& operator*() const
|
const DATATYPE& operator*() const
|
||||||
{
|
{
|
||||||
ASSERT(IsNotNull());
|
Q_ASSERT(IsNotNull());
|
||||||
StackElement& curTos = m_stack[m_tos - 1];
|
StackElement& curTos = m_stack[m_tos - 1];
|
||||||
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
|
return curTos.m_node->m_branch[curTos.m_branchIndex].m_data;
|
||||||
}
|
}
|
||||||
@ -148,7 +142,7 @@ public:
|
|||||||
/// Get the bounds for this node
|
/// Get the bounds for this node
|
||||||
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
|
void GetBounds(ELEMTYPE a_min[NUMDIMS], ELEMTYPE a_max[NUMDIMS])
|
||||||
{
|
{
|
||||||
ASSERT(IsNotNull());
|
Q_ASSERT(IsNotNull());
|
||||||
StackElement& curTos = m_stack[m_tos - 1];
|
StackElement& curTos = m_stack[m_tos - 1];
|
||||||
Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
|
Branch& curBranch = curTos.m_node->m_branch[curTos.m_branchIndex];
|
||||||
|
|
||||||
@ -206,13 +200,13 @@ public:
|
|||||||
m_stack[m_tos].m_node = a_node;
|
m_stack[m_tos].m_node = a_node;
|
||||||
m_stack[m_tos].m_branchIndex = a_branchIndex;
|
m_stack[m_tos].m_branchIndex = a_branchIndex;
|
||||||
++m_tos;
|
++m_tos;
|
||||||
ASSERT(m_tos <= MAX_STACK);
|
Q_ASSERT(m_tos <= MAX_STACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop element off iteration stack
|
// Pop element off iteration stack
|
||||||
StackElement& Pop()
|
StackElement& Pop()
|
||||||
{
|
{
|
||||||
ASSERT(m_tos > 0);
|
Q_ASSERT(m_tos > 0);
|
||||||
--m_tos;
|
--m_tos;
|
||||||
return m_stack[m_tos];
|
return m_stack[m_tos];
|
||||||
}
|
}
|
||||||
@ -356,12 +350,12 @@ protected:
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
RTREE_QUAL::RTree()
|
RTREE_QUAL::RTree()
|
||||||
{
|
{
|
||||||
ASSERT(MAXNODES > MINNODES);
|
Q_ASSERT(MAXNODES > MINNODES);
|
||||||
ASSERT(MINNODES > 0);
|
Q_ASSERT(MINNODES > 0);
|
||||||
|
|
||||||
// We only support machine word size simple data type eg. integer index or
|
// We only support machine word size simple data type eg. integer index or
|
||||||
// object pointer. Since we are storing as union with non data branch
|
// object pointer. Since we are storing as union with non data branch
|
||||||
ASSERT(sizeof(DATATYPE) == sizeof(void*) || sizeof(DATATYPE) == sizeof(int));
|
Q_ASSERT(sizeof(DATATYPE) == sizeof(void*) || sizeof(DATATYPE) == sizeof(int));
|
||||||
|
|
||||||
// Precomputed volumes of the unit spheres for the first few dimensions
|
// Precomputed volumes of the unit spheres for the first few dimensions
|
||||||
const float UNIT_SPHERE_VOLUMES[] = {
|
const float UNIT_SPHERE_VOLUMES[] = {
|
||||||
@ -393,7 +387,7 @@ void RTREE_QUAL::Insert(const ELEMTYPE a_min[NUMDIMS],
|
|||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
for (int index=0; index<NUMDIMS; ++index)
|
for (int index=0; index<NUMDIMS; ++index)
|
||||||
ASSERT(a_min[index] <= a_max[index]);
|
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||||
#endif //_DEBUG
|
#endif //_DEBUG
|
||||||
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -413,7 +407,7 @@ void RTREE_QUAL::Remove(const ELEMTYPE a_min[NUMDIMS],
|
|||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
for (int index=0; index<NUMDIMS; ++index)
|
for (int index=0; index<NUMDIMS; ++index)
|
||||||
ASSERT(a_min[index] <= a_max[index]);
|
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||||
#endif //_DEBUG
|
#endif //_DEBUG
|
||||||
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -433,7 +427,7 @@ int RTREE_QUAL::Search(const ELEMTYPE a_min[NUMDIMS], const ELEMTYPE a_max[NUMDI
|
|||||||
{
|
{
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
for (int index=0; index<NUMDIMS; ++index)
|
for (int index=0; index<NUMDIMS; ++index)
|
||||||
ASSERT(a_min[index] <= a_max[index]);
|
Q_ASSERT(a_min[index] <= a_max[index]);
|
||||||
#endif //_DEBUG
|
#endif //_DEBUG
|
||||||
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -502,8 +496,8 @@ void RTREE_QUAL::Reset()
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::RemoveAllRec(Node* a_node)
|
void RTREE_QUAL::RemoveAllRec(Node* a_node)
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
ASSERT(a_node->m_level >= 0);
|
Q_ASSERT(a_node->m_level >= 0);
|
||||||
|
|
||||||
if (a_node->IsInternalNode()) { // This is an internal node in the tree
|
if (a_node->IsInternalNode()) { // This is an internal node in the tree
|
||||||
for (int index=0; index < a_node->m_count; ++index)
|
for (int index=0; index < a_node->m_count; ++index)
|
||||||
@ -530,7 +524,7 @@ typename RTREE_QUAL::Node* RTREE_QUAL::AllocNode()
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::FreeNode(Node* a_node)
|
void RTREE_QUAL::FreeNode(Node* a_node)
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
|
|
||||||
#ifdef RTREE_DONT_USE_MEMPOOLS
|
#ifdef RTREE_DONT_USE_MEMPOOLS
|
||||||
delete a_node;
|
delete a_node;
|
||||||
@ -593,8 +587,8 @@ RTREE_TEMPLATE
|
|||||||
bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
||||||
Node** a_newNode, int a_level)
|
Node** a_newNode, int a_level)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect && a_node && a_newNode);
|
Q_ASSERT(a_rect && a_node && a_newNode);
|
||||||
ASSERT(a_level >= 0 && a_level <= a_node->m_level);
|
Q_ASSERT(a_level >= 0 && a_level <= a_node->m_level);
|
||||||
|
|
||||||
int index;
|
int index;
|
||||||
Branch branch;
|
Branch branch;
|
||||||
@ -621,7 +615,7 @@ bool RTREE_QUAL::InsertRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
|||||||
return AddBranch(&branch, a_node, a_newNode);
|
return AddBranch(&branch, a_node, a_newNode);
|
||||||
} else {
|
} else {
|
||||||
// Should never occur
|
// Should never occur
|
||||||
ASSERT(0);
|
Q_ASSERT(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -638,11 +632,11 @@ RTREE_TEMPLATE
|
|||||||
bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
|
bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
|
||||||
int a_level)
|
int a_level)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect && a_root);
|
Q_ASSERT(a_rect && a_root);
|
||||||
ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
|
Q_ASSERT(a_level >= 0 && a_level <= (*a_root)->m_level);
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
for (int index=0; index < NUMDIMS; ++index)
|
for (int index=0; index < NUMDIMS; ++index)
|
||||||
ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
|
Q_ASSERT(a_rect->m_min[index] <= a_rect->m_max[index]);
|
||||||
#endif //_DEBUG
|
#endif //_DEBUG
|
||||||
|
|
||||||
Node* newRoot;
|
Node* newRoot;
|
||||||
@ -672,7 +666,7 @@ bool RTREE_QUAL::InsertRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root,
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
|
typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
|
|
||||||
int firstTime = true;
|
int firstTime = true;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -698,8 +692,8 @@ typename RTREE_QUAL::Rect RTREE_QUAL::NodeCover(Node* a_node)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
|
bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
|
||||||
{
|
{
|
||||||
ASSERT(a_branch);
|
Q_ASSERT(a_branch);
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
|
|
||||||
if (a_node->m_count < MAXNODES) { // Split won't be necessary
|
if (a_node->m_count < MAXNODES) { // Split won't be necessary
|
||||||
a_node->m_branch[a_node->m_count] = *a_branch;
|
a_node->m_branch[a_node->m_count] = *a_branch;
|
||||||
@ -707,7 +701,7 @@ bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
ASSERT(a_newNode);
|
Q_ASSERT(a_newNode);
|
||||||
|
|
||||||
SplitNode(a_node, a_branch, a_newNode);
|
SplitNode(a_node, a_branch, a_newNode);
|
||||||
return true;
|
return true;
|
||||||
@ -721,8 +715,8 @@ bool RTREE_QUAL::AddBranch(Branch* a_branch, Node* a_node, Node** a_newNode)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
|
void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
|
||||||
{
|
{
|
||||||
ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
|
Q_ASSERT(a_node && (a_index >= 0) && (a_index < MAXNODES));
|
||||||
ASSERT(a_node->m_count > 0);
|
Q_ASSERT(a_node->m_count > 0);
|
||||||
|
|
||||||
// Remove element by swapping with the last element to prevent gaps in array
|
// Remove element by swapping with the last element to prevent gaps in array
|
||||||
a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
|
a_node->m_branch[a_index] = a_node->m_branch[a_node->m_count - 1];
|
||||||
@ -739,7 +733,7 @@ void RTREE_QUAL::DisconnectBranch(Node* a_node, int a_index)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
int RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node)
|
int RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect && a_node);
|
Q_ASSERT(a_rect && a_node);
|
||||||
|
|
||||||
bool firstTime = true;
|
bool firstTime = true;
|
||||||
ELEMTYPEREAL increase;
|
ELEMTYPEREAL increase;
|
||||||
@ -774,13 +768,13 @@ int RTREE_QUAL::PickBranch(Rect* a_rect, Node* a_node)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB)
|
typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB)
|
||||||
{
|
{
|
||||||
ASSERT(a_rectA && a_rectB);
|
Q_ASSERT(a_rectA && a_rectB);
|
||||||
|
|
||||||
Rect newRect;
|
Rect newRect;
|
||||||
|
|
||||||
for (int index = 0; index < NUMDIMS; ++index) {
|
for (int index = 0; index < NUMDIMS; ++index) {
|
||||||
newRect.m_min[index] = Min(a_rectA->m_min[index], a_rectB->m_min[index]);
|
newRect.m_min[index] = qMin(a_rectA->m_min[index], a_rectB->m_min[index]);
|
||||||
newRect.m_max[index] = Max(a_rectA->m_max[index], a_rectB->m_max[index]);
|
newRect.m_max[index] = qMax(a_rectA->m_max[index], a_rectB->m_max[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return newRect;
|
return newRect;
|
||||||
@ -795,8 +789,8 @@ typename RTREE_QUAL::Rect RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
|
void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
ASSERT(a_branch);
|
Q_ASSERT(a_branch);
|
||||||
|
|
||||||
// Could just use local here, but member or external is faster since it is
|
// Could just use local here, but member or external is faster since it is
|
||||||
// reused
|
// reused
|
||||||
@ -816,7 +810,7 @@ void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
|
|||||||
(*a_newNode)->m_level = a_node->m_level = level;
|
(*a_newNode)->m_level = a_node->m_level = level;
|
||||||
LoadNodes(a_node, *a_newNode, parVars);
|
LoadNodes(a_node, *a_newNode, parVars);
|
||||||
|
|
||||||
ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
|
Q_ASSERT((a_node->m_count + (*a_newNode)->m_count) == parVars->m_total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -824,14 +818,14 @@ void RTREE_QUAL::SplitNode(Node* a_node, Branch* a_branch, Node** a_newNode)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
|
ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect);
|
Q_ASSERT(a_rect);
|
||||||
|
|
||||||
ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
|
ELEMTYPEREAL volume = (ELEMTYPEREAL)1;
|
||||||
|
|
||||||
for (int index=0; index<NUMDIMS; ++index)
|
for (int index=0; index<NUMDIMS; ++index)
|
||||||
volume *= a_rect->m_max[index] - a_rect->m_min[index];
|
volume *= a_rect->m_max[index] - a_rect->m_min[index];
|
||||||
|
|
||||||
ASSERT(volume >= (ELEMTYPEREAL)0);
|
Q_ASSERT(volume >= (ELEMTYPEREAL)0);
|
||||||
|
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
@ -841,7 +835,7 @@ ELEMTYPEREAL RTREE_QUAL::RectVolume(Rect* a_rect)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
|
ELEMTYPEREAL RTREE_QUAL::RectSphericalVolume(Rect* a_rect)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect);
|
Q_ASSERT(a_rect);
|
||||||
|
|
||||||
ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
|
ELEMTYPEREAL sumOfSquares = (ELEMTYPEREAL)0;
|
||||||
ELEMTYPEREAL radius;
|
ELEMTYPEREAL radius;
|
||||||
@ -881,10 +875,10 @@ RTREE_TEMPLATE
|
|||||||
void RTREE_QUAL::GetBranches(Node* a_node, Branch* a_branch,
|
void RTREE_QUAL::GetBranches(Node* a_node, Branch* a_branch,
|
||||||
PartitionVars* a_parVars)
|
PartitionVars* a_parVars)
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
ASSERT(a_branch);
|
Q_ASSERT(a_branch);
|
||||||
|
|
||||||
ASSERT(a_node->m_count == MAXNODES);
|
Q_ASSERT(a_node->m_count == MAXNODES);
|
||||||
|
|
||||||
// Load the branch buffer
|
// Load the branch buffer
|
||||||
for (int index=0; index < MAXNODES; ++index)
|
for (int index=0; index < MAXNODES; ++index)
|
||||||
@ -917,7 +911,7 @@ void RTREE_QUAL::GetBranches(Node* a_node, Branch* a_branch,
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
|
void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
|
||||||
{
|
{
|
||||||
ASSERT(a_parVars);
|
Q_ASSERT(a_parVars);
|
||||||
|
|
||||||
ELEMTYPEREAL biggestDiff;
|
ELEMTYPEREAL biggestDiff;
|
||||||
int group, chosen = 0, betterGroup = 0;
|
int group, chosen = 0, betterGroup = 0;
|
||||||
@ -973,8 +967,8 @@ void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
|
Q_ASSERT((a_parVars->m_count[0] + a_parVars->m_count[1]) == a_parVars->m_total);
|
||||||
ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
|
Q_ASSERT((a_parVars->m_count[0] >= a_parVars->m_minFill) &&
|
||||||
(a_parVars->m_count[1] >= a_parVars->m_minFill));
|
(a_parVars->m_count[1] >= a_parVars->m_minFill));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,12 +977,12 @@ void RTREE_QUAL::ChoosePartition(PartitionVars* a_parVars, int a_minFill)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
|
void RTREE_QUAL::LoadNodes(Node* a_nodeA, Node* a_nodeB, PartitionVars* a_parVars)
|
||||||
{
|
{
|
||||||
ASSERT(a_nodeA);
|
Q_ASSERT(a_nodeA);
|
||||||
ASSERT(a_nodeB);
|
Q_ASSERT(a_nodeB);
|
||||||
ASSERT(a_parVars);
|
Q_ASSERT(a_parVars);
|
||||||
|
|
||||||
for (int index=0; index < a_parVars->m_total; ++index) {
|
for (int index=0; index < a_parVars->m_total; ++index) {
|
||||||
ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
|
Q_ASSERT(a_parVars->m_partition[index] == 0 || a_parVars->m_partition[index] == 1);
|
||||||
|
|
||||||
if (a_parVars->m_partition[index] == 0)
|
if (a_parVars->m_partition[index] == 0)
|
||||||
AddBranch(&a_parVars->m_branchBuf[index], a_nodeA, NULL);
|
AddBranch(&a_parVars->m_branchBuf[index], a_nodeA, NULL);
|
||||||
@ -1003,7 +997,7 @@ RTREE_TEMPLATE
|
|||||||
void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects,
|
void RTREE_QUAL::InitParVars(PartitionVars* a_parVars, int a_maxRects,
|
||||||
int a_minFill)
|
int a_minFill)
|
||||||
{
|
{
|
||||||
ASSERT(a_parVars);
|
Q_ASSERT(a_parVars);
|
||||||
|
|
||||||
a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
|
a_parVars->m_count[0] = a_parVars->m_count[1] = 0;
|
||||||
a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
|
a_parVars->m_area[0] = a_parVars->m_area[1] = (ELEMTYPEREAL)0;
|
||||||
@ -1049,8 +1043,8 @@ void RTREE_QUAL::PickSeeds(PartitionVars* a_parVars)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
|
void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
|
||||||
{
|
{
|
||||||
ASSERT(a_parVars);
|
Q_ASSERT(a_parVars);
|
||||||
ASSERT(!a_parVars->m_taken[a_index]);
|
Q_ASSERT(!a_parVars->m_taken[a_index]);
|
||||||
|
|
||||||
a_parVars->m_partition[a_index] = a_group;
|
a_parVars->m_partition[a_index] = a_group;
|
||||||
a_parVars->m_taken[a_index] = true;
|
a_parVars->m_taken[a_index] = true;
|
||||||
@ -1073,8 +1067,8 @@ void RTREE_QUAL::Classify(int a_index, int a_group, PartitionVars* a_parVars)
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
|
bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect && a_root);
|
Q_ASSERT(a_rect && a_root);
|
||||||
ASSERT(*a_root);
|
Q_ASSERT(*a_root);
|
||||||
|
|
||||||
Node* tempNode;
|
Node* tempNode;
|
||||||
ListNode* reInsertList = NULL;
|
ListNode* reInsertList = NULL;
|
||||||
@ -1100,7 +1094,7 @@ bool RTREE_QUAL::RemoveRect(Rect* a_rect, const DATATYPE& a_id, Node** a_root)
|
|||||||
if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode()) {
|
if ((*a_root)->m_count == 1 && (*a_root)->IsInternalNode()) {
|
||||||
tempNode = (*a_root)->m_branch[0].m_child;
|
tempNode = (*a_root)->m_branch[0].m_child;
|
||||||
|
|
||||||
ASSERT(tempNode);
|
Q_ASSERT(tempNode);
|
||||||
FreeNode(*a_root);
|
FreeNode(*a_root);
|
||||||
*a_root = tempNode;
|
*a_root = tempNode;
|
||||||
}
|
}
|
||||||
@ -1119,8 +1113,8 @@ RTREE_TEMPLATE
|
|||||||
bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
||||||
ListNode** a_listNode)
|
ListNode** a_listNode)
|
||||||
{
|
{
|
||||||
ASSERT(a_rect && a_node && a_listNode);
|
Q_ASSERT(a_rect && a_node && a_listNode);
|
||||||
ASSERT(a_node->m_level >= 0);
|
Q_ASSERT(a_node->m_level >= 0);
|
||||||
|
|
||||||
if (a_node->IsInternalNode()) { // not a leaf node
|
if (a_node->IsInternalNode()) { // not a leaf node
|
||||||
for (int index = 0; index < a_node->m_count; ++index) {
|
for (int index = 0; index < a_node->m_count; ++index) {
|
||||||
@ -1160,7 +1154,7 @@ bool RTREE_QUAL::RemoveRectRec(Rect* a_rect, const DATATYPE& a_id, Node* a_node,
|
|||||||
RTREE_TEMPLATE
|
RTREE_TEMPLATE
|
||||||
bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
|
bool RTREE_QUAL::Overlap(Rect* a_rectA, Rect* a_rectB) const
|
||||||
{
|
{
|
||||||
ASSERT(a_rectA && a_rectB);
|
Q_ASSERT(a_rectA && a_rectB);
|
||||||
|
|
||||||
for (int index=0; index < NUMDIMS; ++index) {
|
for (int index=0; index < NUMDIMS; ++index) {
|
||||||
if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
|
if (a_rectA->m_min[index] > a_rectB->m_max[index] ||
|
||||||
@ -1193,9 +1187,9 @@ bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount,
|
|||||||
bool (*a_resultCallback)(DATATYPE a_data, void* a_context),
|
bool (*a_resultCallback)(DATATYPE a_data, void* a_context),
|
||||||
void* a_context) const
|
void* a_context) const
|
||||||
{
|
{
|
||||||
ASSERT(a_node);
|
Q_ASSERT(a_node);
|
||||||
ASSERT(a_node->m_level >= 0);
|
Q_ASSERT(a_node->m_level >= 0);
|
||||||
ASSERT(a_rect);
|
Q_ASSERT(a_rect);
|
||||||
|
|
||||||
if (a_node->IsInternalNode()) { // This is an internal node in the tree
|
if (a_node->IsInternalNode()) { // This is an internal node in the tree
|
||||||
for (int index=0; index < a_node->m_count; ++index) {
|
for (int index=0; index < a_node->m_count; ++index) {
|
25
src/config.h
25
src/config.h
@ -12,11 +12,12 @@
|
|||||||
#define FONT_FAMILY "Arial"
|
#define FONT_FAMILY "Arial"
|
||||||
#define FONT_SIZE 12 // px
|
#define FONT_SIZE 12 // px
|
||||||
|
|
||||||
#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 MAP_DIR QString("maps")
|
||||||
#define POI_DIR QString("POI")
|
#define POI_DIR QString("POI")
|
||||||
|
#define CSV_DIR QString("csv")
|
||||||
|
#define ELLIPSOID_FILE QString("ellipsoids.csv")
|
||||||
|
#define GCS_FILE QString("gcs.csv")
|
||||||
|
#define PCS_FILE QString("pcs.csv")
|
||||||
|
|
||||||
#if defined(Q_OS_WIN32)
|
#if defined(Q_OS_WIN32)
|
||||||
#define USER_DIR QDir::homePath() + QString("/GPXSee")
|
#define USER_DIR QDir::homePath() + QString("/GPXSee")
|
||||||
@ -30,17 +31,23 @@
|
|||||||
#define GLOBAL_DIR QString("/usr/share/gpxsee")
|
#define GLOBAL_DIR QString("/usr/share/gpxsee")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define USER_ELLIPSOID_FILE USER_DIR + QString("/") + ELLIPSOID_FILE
|
#define USER_CSV_DIR USER_DIR + QString("/") + CSV_DIR
|
||||||
#define USER_GCS_FILE USER_DIR + QString("/") + GCS_FILE
|
#define USER_ELLIPSOID_FILE USER_CSV_DIR + QString("/") + ELLIPSOID_FILE
|
||||||
#define USER_PCS_FILE USER_DIR + QString("/") + PCS_FILE
|
#define USER_GCS_FILE USER_CSV_DIR + QString("/") + GCS_FILE
|
||||||
|
#define USER_PCS_FILE USER_CSV_DIR + QString("/") + PCS_FILE
|
||||||
#define USER_MAP_DIR USER_DIR + QString("/") + MAP_DIR
|
#define USER_MAP_DIR USER_DIR + QString("/") + MAP_DIR
|
||||||
#define USER_POI_DIR USER_DIR + QString("/") + POI_DIR
|
#define USER_POI_DIR USER_DIR + QString("/") + POI_DIR
|
||||||
#define GLOBAL_ELLIPSOID_FILE GLOBAL_DIR + QString("/") + ELLIPSOID_FILE
|
#define GLOBAL_CSV_DIR GLOBAL_DIR + QString("/") + CSV_DIR
|
||||||
#define GLOBAL_GCS_FILE GLOBAL_DIR + QString("/") + GCS_FILE
|
#define GLOBAL_ELLIPSOID_FILE GLOBAL_CSV_DIR + QString("/") + ELLIPSOID_FILE
|
||||||
#define GLOBAL_PCS_FILE GLOBAL_DIR + QString("/") + PCS_FILE
|
#define GLOBAL_GCS_FILE GLOBAL_CSV_DIR + QString("/") + GCS_FILE
|
||||||
|
#define GLOBAL_PCS_FILE GLOBAL_CSV_DIR + QString("/") + PCS_FILE
|
||||||
#define GLOBAL_MAP_DIR GLOBAL_DIR + QString("/") + MAP_DIR
|
#define GLOBAL_MAP_DIR GLOBAL_DIR + QString("/") + MAP_DIR
|
||||||
#define GLOBAL_POI_DIR GLOBAL_DIR + QString("/") + POI_DIR
|
#define GLOBAL_POI_DIR GLOBAL_DIR + QString("/") + POI_DIR
|
||||||
#define TILES_DIR USER_DIR + QString("/tiles")
|
#define TILES_DIR USER_DIR + QString("/tiles")
|
||||||
#define TRANSLATIONS_DIR GLOBAL_DIR + QString("/translations")
|
#define TRANSLATIONS_DIR GLOBAL_DIR + QString("/translations")
|
||||||
|
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 1))
|
||||||
|
#define ENABLE_HTTP2
|
||||||
|
#endif // QT >= 5.10.1
|
||||||
|
|
||||||
#endif /* CONFIG_H */
|
#endif /* CONFIG_H */
|
||||||
|
@ -1,48 +1,72 @@
|
|||||||
#include <cstring>
|
|
||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
#include "common/staticassert.h"
|
#include "common/staticassert.h"
|
||||||
#include "fitparser.h"
|
#include "fitparser.h"
|
||||||
|
|
||||||
|
|
||||||
const quint32 FIT_MAGIC = 0x5449462E; // .FIT
|
#define FIT_MAGIC 0x5449462E // .FIT
|
||||||
|
|
||||||
#define RECORD_MESSAGE 20
|
#define RECORD_MESSAGE 20
|
||||||
|
#define EVENT_MESSAGE 21
|
||||||
#define TIMESTAMP_FIELD 253
|
#define TIMESTAMP_FIELD 253
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
Event() : id(0), type(0), data(0) {}
|
||||||
|
|
||||||
FITParser::FITParser()
|
quint8 id;
|
||||||
{
|
quint8 type;
|
||||||
memset(_defs, 0, sizeof(_defs));
|
quint32 data;
|
||||||
|
};
|
||||||
|
|
||||||
_device = 0;
|
struct FileHeader {
|
||||||
_endian = 0;
|
quint8 headerSize;
|
||||||
_timestamp = 0;
|
quint8 protocolVersion;
|
||||||
_len = 0;
|
quint16 profileVersion;
|
||||||
}
|
quint32 dataSize;
|
||||||
|
quint32 magic;
|
||||||
|
};
|
||||||
|
|
||||||
void FITParser::clearDefinitions()
|
struct FITParser::Field {
|
||||||
{
|
quint8 id;
|
||||||
for (int i = 0; i < 16; i++) {
|
quint8 size;
|
||||||
if (_defs[i].fields)
|
quint8 type;
|
||||||
delete[] _defs[i].fields;
|
};
|
||||||
if (_defs[i].devFields)
|
|
||||||
delete[] _defs[i].devFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(_defs, 0, sizeof(_defs));
|
class FITParser::MessageDefinition {
|
||||||
}
|
public:
|
||||||
|
MessageDefinition() : endian(0), globalId(0), numFields(0), fields(0),
|
||||||
|
numDevFields(0), devFields(0) {}
|
||||||
|
~MessageDefinition() {delete[] fields; delete[] devFields;}
|
||||||
|
|
||||||
void FITParser::warning(const char *text) const
|
quint8 endian;
|
||||||
{
|
quint16 globalId;
|
||||||
const QFile *file = static_cast<QFile *>(_device);
|
quint8 numFields;
|
||||||
qWarning("%s:%d: %s\n", qPrintable(file->fileName()), _len, text);
|
Field *fields;
|
||||||
}
|
quint8 numDevFields;
|
||||||
|
Field *devFields;
|
||||||
|
};
|
||||||
|
|
||||||
bool FITParser::readData(char *data, size_t size)
|
class FITParser::CTX {
|
||||||
|
public:
|
||||||
|
CTX(QFile *file) : file(file), len(0), endian(0), timestamp(0),
|
||||||
|
lastWrite(0), ratio(NAN) {}
|
||||||
|
|
||||||
|
QFile *file;
|
||||||
|
quint32 len;
|
||||||
|
quint8 endian;
|
||||||
|
quint32 timestamp, lastWrite;
|
||||||
|
MessageDefinition defs[16];
|
||||||
|
qreal ratio;
|
||||||
|
Trackpoint trackpoint;
|
||||||
|
TrackData track;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool FITParser::readData(QFile *file, char *data, size_t size)
|
||||||
{
|
{
|
||||||
qint64 n;
|
qint64 n;
|
||||||
|
|
||||||
n = _device->read(data, size);
|
n = file->read(data, size);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
_errorString = "I/O error";
|
_errorString = "I/O error";
|
||||||
return false;
|
return false;
|
||||||
@ -54,17 +78,17 @@ bool FITParser::readData(char *data, size_t size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> bool FITParser::readValue(T &val)
|
template<class T> bool FITParser::readValue(CTX &ctx, T &val)
|
||||||
{
|
{
|
||||||
T data;
|
T data;
|
||||||
|
|
||||||
if (!readData((char*)&data, sizeof(T)))
|
if (!readData(ctx.file, (char*)&data, sizeof(T)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_len -= sizeof(T);
|
ctx.len -= sizeof(T);
|
||||||
|
|
||||||
if (sizeof(T) > 1) {
|
if (sizeof(T) > 1) {
|
||||||
if (_endian)
|
if (ctx.endian)
|
||||||
val = qFromBigEndian(data);
|
val = qFromBigEndian(data);
|
||||||
else
|
else
|
||||||
val = qFromLittleEndian(data);
|
val = qFromLittleEndian(data);
|
||||||
@ -74,22 +98,16 @@ template<class T> bool FITParser::readValue(T &val)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::skipValue(size_t size)
|
bool FITParser::skipValue(CTX &ctx, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
ctx.len -= size;
|
||||||
quint8 val;
|
return ctx.file->seek(ctx.file->pos() + size);
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
|
||||||
if (!readValue(val))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseDefinitionMessage(quint8 header)
|
bool FITParser::parseDefinitionMessage(CTX &ctx, quint8 header)
|
||||||
{
|
{
|
||||||
int local_id = header & 0x0f;
|
int local_id = header & 0x0f;
|
||||||
MessageDefinition* def = &_defs[local_id];
|
MessageDefinition *def = &(ctx.defs[local_id]);
|
||||||
quint8 i;
|
quint8 i;
|
||||||
|
|
||||||
|
|
||||||
@ -103,54 +121,56 @@ bool FITParser::parseDefinitionMessage(quint8 header)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reserved/unused
|
// reserved/unused
|
||||||
if (!readValue(i))
|
if (!readValue(ctx, i))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// endianness
|
// endianness
|
||||||
if (!readValue(def->endian))
|
if (!readValue(ctx, def->endian))
|
||||||
return false;
|
return false;
|
||||||
if (def->endian > 1) {
|
if (def->endian > 1) {
|
||||||
_errorString = "Bad endian field";
|
_errorString = "Bad endian field";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_endian = def->endian;
|
ctx.endian = def->endian;
|
||||||
|
|
||||||
// global message number
|
// global message number
|
||||||
if (!readValue(def->globalId))
|
if (!readValue(ctx, def->globalId))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// number of records
|
// number of records
|
||||||
if (!readValue(def->numFields))
|
if (!readValue(ctx, def->numFields))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// definition records
|
// definition records
|
||||||
def->fields = new Field[def->numFields];
|
def->fields = new Field[def->numFields];
|
||||||
for (i = 0; i < def->numFields; i++) {
|
for (i = 0; i < def->numFields; i++) {
|
||||||
STATIC_ASSERT(sizeof(def->fields[i]) == 3);
|
STATIC_ASSERT(sizeof(def->fields[i]) == 3);
|
||||||
if (!readData((char*)&(def->fields[i]), sizeof(def->fields[i])))
|
if (!readData(ctx.file, (char*)&(def->fields[i]),
|
||||||
|
sizeof(def->fields[i])))
|
||||||
return false;
|
return false;
|
||||||
_len -= sizeof(def->fields[i]);
|
ctx.len -= sizeof(def->fields[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// developer definition records
|
// developer definition records
|
||||||
if (header & 0x20) {
|
if (header & 0x20) {
|
||||||
if (!readValue(def->numDevFields))
|
if (!readValue(ctx, def->numDevFields))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
def->devFields = new Field[def->numDevFields];
|
def->devFields = new Field[def->numDevFields];
|
||||||
for (i = 0; i < def->numDevFields; i++) {
|
for (i = 0; i < def->numDevFields; i++) {
|
||||||
STATIC_ASSERT(sizeof(def->devFields[i]) == 3);
|
STATIC_ASSERT(sizeof(def->devFields[i]) == 3);
|
||||||
if (!readData((char*)&(def->devFields[i]),
|
if (!readData(ctx.file, (char*)&(def->devFields[i]),
|
||||||
sizeof(def->devFields[i])))
|
sizeof(def->devFields[i])))
|
||||||
return false;
|
return false;
|
||||||
_len -= sizeof(def->devFields[i]);
|
ctx.len -= sizeof(def->devFields[i]);
|
||||||
}
|
}
|
||||||
}
|
} else
|
||||||
|
def->numDevFields = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::readField(Field *f, quint32 &val)
|
bool FITParser::readField(CTX &ctx, Field *field, quint32 &val)
|
||||||
{
|
{
|
||||||
quint8 v8 = (quint8)-1;
|
quint8 v8 = (quint8)-1;
|
||||||
quint16 v16 = (quint16)-1;
|
quint16 v16 = (quint16)-1;
|
||||||
@ -158,46 +178,44 @@ bool FITParser::readField(Field *f, quint32 &val)
|
|||||||
|
|
||||||
val = (quint32)-1;
|
val = (quint32)-1;
|
||||||
|
|
||||||
switch (f->type) {
|
switch (field->type) {
|
||||||
|
case 0: // enum
|
||||||
case 1: // sint8
|
case 1: // sint8
|
||||||
case 2: // uint8
|
case 2: // uint8
|
||||||
if (f->size == 1) {
|
if (field->size == 1) {
|
||||||
ret = readValue(v8);
|
ret = readValue(ctx, v8);
|
||||||
val = v8;
|
val = v8;
|
||||||
} else
|
} else
|
||||||
ret = skipValue(f->size);
|
ret = skipValue(ctx, field->size);
|
||||||
break;
|
break;
|
||||||
case 0x83: // sint16
|
case 0x83: // sint16
|
||||||
case 0x84: // uint16
|
case 0x84: // uint16
|
||||||
if (f->size == 2) {
|
if (field->size == 2) {
|
||||||
ret = readValue(v16);
|
ret = readValue(ctx, v16);
|
||||||
val = v16;
|
val = v16;
|
||||||
} else
|
} else
|
||||||
ret = skipValue(f->size);
|
ret = skipValue(ctx, field->size);
|
||||||
break;
|
break;
|
||||||
case 0x85: // sint32
|
case 0x85: // sint32
|
||||||
case 0x86: // uint32
|
case 0x86: // uint32
|
||||||
if (f->size == 4)
|
if (field->size == 4)
|
||||||
ret = readValue(val);
|
ret = readValue(ctx, val);
|
||||||
else
|
else
|
||||||
ret = skipValue(f->size);
|
ret = skipValue(ctx, field->size);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = skipValue(f->size);
|
ret = skipValue(ctx, field->size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseData(TrackData &track, MessageDefinition *def,
|
bool FITParser::parseData(CTX &ctx, const MessageDefinition *def)
|
||||||
quint8 offset)
|
|
||||||
{
|
{
|
||||||
Field *field;
|
Field *field;
|
||||||
quint32 timestamp = _timestamp + offset;
|
Event event;
|
||||||
quint32 val;
|
quint32 val;
|
||||||
Trackpoint trackpoint;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
if (!def->fields && !def->devFields) {
|
if (!def->fields && !def->devFields) {
|
||||||
@ -205,133 +223,149 @@ bool FITParser::parseData(TrackData &track, MessageDefinition *def,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_endian = def->endian;
|
ctx.endian = def->endian;
|
||||||
|
|
||||||
for (i = 0; i < def->numFields; i++) {
|
for (int i = 0; i < def->numFields; i++) {
|
||||||
field = &def->fields[i];
|
field = &def->fields[i];
|
||||||
if (!readField(field, val))
|
if (!readField(ctx, field, val))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (field->id == TIMESTAMP_FIELD)
|
if (field->id == TIMESTAMP_FIELD)
|
||||||
_timestamp = timestamp = val;
|
ctx.timestamp = val;
|
||||||
else if (def->globalId == RECORD_MESSAGE) {
|
else if (def->globalId == RECORD_MESSAGE) {
|
||||||
switch (field->id) {
|
switch (field->id) {
|
||||||
case 0:
|
case 0:
|
||||||
if (val != 0x7fffffff)
|
if (val != 0x7fffffff)
|
||||||
trackpoint.rcoordinates().setLat(
|
ctx.trackpoint.rcoordinates().setLat(
|
||||||
((qint32)val / (double)0x7fffffff) * 180);
|
((qint32)val / (double)0x7fffffff) * 180);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (val != 0x7fffffff)
|
if (val != 0x7fffffff)
|
||||||
trackpoint.rcoordinates().setLon(
|
ctx.trackpoint.rcoordinates().setLon(
|
||||||
((qint32)val / (double)0x7fffffff) * 180);
|
((qint32)val / (double)0x7fffffff) * 180);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (val != 0xffff)
|
if (val != 0xffff)
|
||||||
trackpoint.setElevation((val / 5.0) - 500);
|
ctx.trackpoint.setElevation((val / 5.0) - 500);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (val != 0xff)
|
if (val != 0xff)
|
||||||
trackpoint.setHeartRate(val);
|
ctx.trackpoint.setHeartRate(val);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
if (val != 0xff)
|
if (val != 0xff)
|
||||||
trackpoint.setCadence(val);
|
ctx.trackpoint.setCadence(val);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
if (val != 0xffff)
|
if (val != 0xffff)
|
||||||
trackpoint.setSpeed(val / 1000.0f);
|
ctx.trackpoint.setSpeed(val / 1000.0f);
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
if (val != 0xffff)
|
if (val != 0xffff)
|
||||||
trackpoint.setPower(val);
|
ctx.trackpoint.setPower(val);
|
||||||
break;
|
break;
|
||||||
case 13:
|
case 13:
|
||||||
if (val != 0x7f)
|
if (val != 0x7f)
|
||||||
trackpoint.setTemperature((qint8)val);
|
ctx.trackpoint.setTemperature((qint8)val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
} else if (def->globalId == EVENT_MESSAGE) {
|
||||||
|
switch (field->id) {
|
||||||
|
case 0:
|
||||||
|
event.id = val;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
event.type = val;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
event.data = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < def->numDevFields; i++) {
|
for (int i = 0; i < def->numDevFields; i++) {
|
||||||
field = &def->devFields[i];
|
field = &def->devFields[i];
|
||||||
if (!readField(field, val))
|
if (!readField(ctx, field, val))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (def->globalId == RECORD_MESSAGE) {
|
if (def->globalId == EVENT_MESSAGE) {
|
||||||
if (trackpoint.coordinates().isValid()) {
|
if ((event.id == 42 || event.id == 43) && event.type == 3) {
|
||||||
trackpoint.setTimestamp(QDateTime::fromTime_t(timestamp
|
quint32 front = ((event.data & 0xFF000000) >> 24);
|
||||||
|
quint32 rear = ((event.data & 0x0000FF00) >> 8);
|
||||||
|
ctx.ratio = ((qreal)front / (qreal)rear);
|
||||||
|
}
|
||||||
|
} else if (def->globalId == RECORD_MESSAGE) {
|
||||||
|
if (ctx.timestamp > ctx.lastWrite
|
||||||
|
&& ctx.trackpoint.coordinates().isValid()) {
|
||||||
|
ctx.trackpoint.setTimestamp(QDateTime::fromTime_t(ctx.timestamp
|
||||||
+ 631065600));
|
+ 631065600));
|
||||||
track.append(trackpoint);
|
ctx.trackpoint.setRatio(ctx.ratio);
|
||||||
} else {
|
ctx.track.append(ctx.trackpoint);
|
||||||
if (trackpoint.coordinates().isNull())
|
ctx.trackpoint = Trackpoint();
|
||||||
warning("Missing coordinates");
|
ctx.lastWrite = ctx.timestamp;
|
||||||
else {
|
|
||||||
_errorString = "Invalid coordinates";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseDataMessage(TrackData &track, quint8 header)
|
bool FITParser::parseDataMessage(CTX &ctx, quint8 header)
|
||||||
{
|
{
|
||||||
int local_id = header & 0xf;
|
int local_id = header & 0xf;
|
||||||
MessageDefinition* def = &_defs[local_id];
|
MessageDefinition *def = &(ctx.defs[local_id]);
|
||||||
return parseData(track, def, 0);
|
return parseData(ctx, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseCompressedMessage(TrackData &track, quint8 header)
|
bool FITParser::parseCompressedMessage(CTX &ctx, quint8 header)
|
||||||
{
|
{
|
||||||
int local_id = (header >> 5) & 3;
|
int local_id = (header >> 5) & 3;
|
||||||
MessageDefinition* def = &_defs[local_id];
|
MessageDefinition *def = &(ctx.defs[local_id]);
|
||||||
return parseData(track, def, header & 0x1f);
|
ctx.timestamp += header & 0x1f;
|
||||||
|
return parseData(ctx, def);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseRecord(TrackData &track)
|
bool FITParser::parseRecord(CTX &ctx)
|
||||||
{
|
{
|
||||||
quint8 header;
|
quint8 header;
|
||||||
|
|
||||||
if (!readValue(header))
|
if (!readValue(ctx, header))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (header & 0x80)
|
if (header & 0x80)
|
||||||
return parseCompressedMessage(track, header);
|
return parseCompressedMessage(ctx, header);
|
||||||
else if (header & 0x40)
|
else if (header & 0x40)
|
||||||
return parseDefinitionMessage(header);
|
return parseDefinitionMessage(ctx, header);
|
||||||
else
|
else
|
||||||
return parseDataMessage(track, header);
|
return parseDataMessage(ctx, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FITParser::parseHeader()
|
bool FITParser::parseHeader(CTX &ctx)
|
||||||
{
|
{
|
||||||
FileHeader hdr;
|
FileHeader hdr;
|
||||||
quint16 crc;
|
quint16 crc;
|
||||||
qint64 len;
|
qint64 len;
|
||||||
|
|
||||||
STATIC_ASSERT(sizeof(hdr) == 12);
|
STATIC_ASSERT(sizeof(hdr) == 12);
|
||||||
len = _device->read((char*)&hdr, sizeof(hdr));
|
len = ctx.file->read((char*)&hdr, sizeof(hdr));
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
_errorString = "I/O error";
|
_errorString = "I/O error";
|
||||||
return false;
|
return false;
|
||||||
} else if ((size_t)len < sizeof(hdr)
|
} else if ((size_t)len < sizeof(hdr)
|
||||||
|| hdr.magic != qToLittleEndian(FIT_MAGIC)) {
|
|| hdr.magic != qToLittleEndian((quint32)FIT_MAGIC)) {
|
||||||
_errorString = "Not a FIT file";
|
_errorString = "Not a FIT file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_len = qFromLittleEndian(hdr.dataSize);
|
ctx.len = qFromLittleEndian(hdr.dataSize);
|
||||||
|
|
||||||
if (hdr.headerSize > sizeof(hdr))
|
if (hdr.headerSize > sizeof(hdr))
|
||||||
if (!readData((char *)&crc, sizeof(crc)))
|
if (!readData(ctx.file, (char *)&crc, sizeof(crc)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -342,23 +376,17 @@ bool FITParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
{
|
{
|
||||||
Q_UNUSED(routes);
|
Q_UNUSED(routes);
|
||||||
Q_UNUSED(waypoints);
|
Q_UNUSED(waypoints);
|
||||||
bool ret = true;
|
CTX ctx(file);
|
||||||
|
|
||||||
_device = file;
|
|
||||||
_endian = 0;
|
|
||||||
_timestamp = 0;
|
|
||||||
|
|
||||||
if (!parseHeader())
|
if (!parseHeader(ctx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
tracks.append(TrackData());
|
while (ctx.len)
|
||||||
TrackData &track = tracks.last();
|
if (!parseRecord(ctx))
|
||||||
|
return false;
|
||||||
|
|
||||||
while (_len)
|
tracks.append(ctx.track);
|
||||||
if ((ret = parseRecord(track)) == false)
|
|
||||||
break;
|
|
||||||
|
|
||||||
clearDefinitions();
|
return true;
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
@ -3,63 +3,34 @@
|
|||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
class QFile;
|
||||||
|
|
||||||
class FITParser : public Parser
|
class FITParser : public Parser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FITParser();
|
|
||||||
|
|
||||||
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
|
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
|
||||||
QList<Waypoint> &waypoints);
|
QList<Waypoint> &waypoints);
|
||||||
QString errorString() const {return _errorString;}
|
QString errorString() const {return _errorString;}
|
||||||
int errorLine() const {return 0;}
|
int errorLine() const {return 0;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FileHeader {
|
struct Field;
|
||||||
quint8 headerSize;
|
class MessageDefinition;
|
||||||
quint8 protocolVersion;
|
class CTX;
|
||||||
quint16 profileVersion;
|
|
||||||
quint32 dataSize;
|
|
||||||
quint32 magic;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Field {
|
bool readData(QFile *file, char *data, size_t size);
|
||||||
quint8 id;
|
template<class T> bool readValue(CTX &ctx, T &val);
|
||||||
quint8 size;
|
bool skipValue(CTX &ctx, size_t size);
|
||||||
quint8 type;
|
bool readField(CTX &ctx, Field *field, quint32 &val);
|
||||||
};
|
|
||||||
|
|
||||||
struct MessageDefinition {
|
bool parseHeader(CTX &ctx);
|
||||||
quint8 endian;
|
bool parseRecord(CTX &ctx);
|
||||||
quint16 globalId;
|
bool parseDefinitionMessage(CTX &ctx, quint8 header);
|
||||||
quint8 numFields;
|
bool parseCompressedMessage(CTX &ctx, quint8 header);
|
||||||
Field *fields;
|
bool parseDataMessage(CTX &ctx, quint8 header);
|
||||||
quint8 numDevFields;
|
bool parseData(CTX &ctx, const MessageDefinition *def);
|
||||||
Field *devFields;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void warning(const char *text) const;
|
|
||||||
void clearDefinitions();
|
|
||||||
|
|
||||||
bool readData(char *data, size_t size);
|
|
||||||
template<class T> bool readValue(T &val);
|
|
||||||
bool skipValue(size_t size);
|
|
||||||
|
|
||||||
bool parseHeader();
|
|
||||||
bool parseRecord(TrackData &track);
|
|
||||||
bool parseDefinitionMessage(quint8 header);
|
|
||||||
bool parseCompressedMessage(TrackData &track, quint8 header);
|
|
||||||
bool parseDataMessage(TrackData &track, quint8 header);
|
|
||||||
bool parseData(TrackData &track, MessageDefinition *def, quint8 offset);
|
|
||||||
bool readField(Field *f, quint32 &val);
|
|
||||||
|
|
||||||
QIODevice *_device;
|
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
|
|
||||||
quint32 _len;
|
|
||||||
quint8 _endian;
|
|
||||||
quint32 _timestamp;
|
|
||||||
MessageDefinition _defs[16];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FITPARSER_H
|
#endif // FITPARSER_H
|
||||||
|
@ -51,6 +51,15 @@ Coordinates GPXParser::coordinates()
|
|||||||
return Coordinates(lon, lat);
|
return Coordinates(lon, lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPXParser::rpExtension(TrackData *autoRoute)
|
||||||
|
{
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == "rpt")
|
||||||
|
autoRoute->append(Trackpoint(coordinates()));
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GPXParser::tpExtension(Trackpoint &trackpoint)
|
void GPXParser::tpExtension(Trackpoint &trackpoint)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
@ -63,7 +72,17 @@ void GPXParser::tpExtension(Trackpoint &trackpoint)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::extensions(Trackpoint &trackpoint)
|
void GPXParser::rteptExtensions(TrackData *autoRoute)
|
||||||
|
{
|
||||||
|
while (_reader.readNextStartElement()) {
|
||||||
|
if (_reader.name() == "RoutePointExtension")
|
||||||
|
rpExtension(autoRoute);
|
||||||
|
else
|
||||||
|
_reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GPXParser::trkptExtensions(Trackpoint &trackpoint)
|
||||||
{
|
{
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == "speed")
|
if (_reader.name() == "speed")
|
||||||
@ -95,7 +114,7 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
|
|||||||
else if (_reader.name() == "geoidheight")
|
else if (_reader.name() == "geoidheight")
|
||||||
gh = number();
|
gh = number();
|
||||||
else if (_reader.name() == "extensions")
|
else if (_reader.name() == "extensions")
|
||||||
extensions(trackpoint);
|
trkptExtensions(trackpoint);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@ -104,7 +123,7 @@ void GPXParser::trackpointData(Trackpoint &trackpoint)
|
|||||||
trackpoint.setElevation(trackpoint.elevation() - gh);
|
trackpoint.setElevation(trackpoint.elevation() - gh);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::waypointData(Waypoint &waypoint)
|
void GPXParser::waypointData(Waypoint &waypoint, TrackData *autoRoute)
|
||||||
{
|
{
|
||||||
qreal gh = NAN;
|
qreal gh = NAN;
|
||||||
|
|
||||||
@ -119,6 +138,8 @@ void GPXParser::waypointData(Waypoint &waypoint)
|
|||||||
gh = number();
|
gh = number();
|
||||||
else if (_reader.name() == "time")
|
else if (_reader.name() == "time")
|
||||||
waypoint.setTimestamp(time());
|
waypoint.setTimestamp(time());
|
||||||
|
else if (autoRoute && _reader.name() == "extensions")
|
||||||
|
rteptExtensions(autoRoute);
|
||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
@ -138,12 +159,14 @@ void GPXParser::trackpoints(TrackData &track)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::routepoints(RouteData &route)
|
void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
|
||||||
{
|
{
|
||||||
|
TrackData autoRoute;
|
||||||
|
|
||||||
while (_reader.readNextStartElement()) {
|
while (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == "rtept") {
|
if (_reader.name() == "rtept") {
|
||||||
route.append(Waypoint(coordinates()));
|
route.append(Waypoint(coordinates()));
|
||||||
waypointData(route.last());
|
waypointData(route.last(), &autoRoute);
|
||||||
} else if (_reader.name() == "name")
|
} else if (_reader.name() == "name")
|
||||||
route.setName(_reader.readElementText());
|
route.setName(_reader.readElementText());
|
||||||
else if (_reader.name() == "desc")
|
else if (_reader.name() == "desc")
|
||||||
@ -151,6 +174,12 @@ void GPXParser::routepoints(RouteData &route)
|
|||||||
else
|
else
|
||||||
_reader.skipCurrentElement();
|
_reader.skipCurrentElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!autoRoute.isEmpty()) {
|
||||||
|
autoRoute.setName(route.name());
|
||||||
|
autoRoute.setDescription(route.description());
|
||||||
|
tracks.append(autoRoute);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPXParser::track(TrackData &track)
|
void GPXParser::track(TrackData &track)
|
||||||
@ -176,7 +205,7 @@ void GPXParser::gpx(QList<TrackData> &tracks, QList<RouteData> &routes,
|
|||||||
track(tracks.back());
|
track(tracks.back());
|
||||||
} else if (_reader.name() == "rte") {
|
} else if (_reader.name() == "rte") {
|
||||||
routes.append(RouteData());
|
routes.append(RouteData());
|
||||||
routepoints(routes.back());
|
routepoints(routes.back(), tracks);
|
||||||
} else if (_reader.name() == "wpt") {
|
} else if (_reader.name() == "wpt") {
|
||||||
waypoints.append(Waypoint(coordinates()));
|
waypoints.append(Waypoint(coordinates()));
|
||||||
waypointData(waypoints.last());
|
waypointData(waypoints.last());
|
||||||
@ -190,6 +219,7 @@ bool GPXParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
{
|
{
|
||||||
_reader.clear();
|
_reader.clear();
|
||||||
_reader.setDevice(file);
|
_reader.setDevice(file);
|
||||||
|
_reader.setNamespaceProcessing(false);
|
||||||
|
|
||||||
if (_reader.readNextStartElement()) {
|
if (_reader.readNextStartElement()) {
|
||||||
if (_reader.name() == "gpx")
|
if (_reader.name() == "gpx")
|
||||||
|
@ -18,11 +18,13 @@ private:
|
|||||||
QList<Waypoint> &waypoints);
|
QList<Waypoint> &waypoints);
|
||||||
void track(TrackData &track);
|
void track(TrackData &track);
|
||||||
void trackpoints(TrackData &track);
|
void trackpoints(TrackData &track);
|
||||||
void routepoints(RouteData &route);
|
void routepoints(RouteData &route, QList<TrackData> &tracks);
|
||||||
|
void rpExtension(TrackData *autoRoute);
|
||||||
void tpExtension(Trackpoint &trackpoint);
|
void tpExtension(Trackpoint &trackpoint);
|
||||||
void extensions(Trackpoint &trackpoint);
|
void trkptExtensions(Trackpoint &trackpoint);
|
||||||
|
void rteptExtensions(TrackData *autoRoute);
|
||||||
void trackpointData(Trackpoint &trackpoint);
|
void trackpointData(Trackpoint &trackpoint);
|
||||||
void waypointData(Waypoint &waypoint);
|
void waypointData(Waypoint &waypoint, TrackData *autoRoute = 0);
|
||||||
qreal number();
|
qreal number();
|
||||||
QDateTime time();
|
QDateTime time();
|
||||||
Coordinates coordinates();
|
Coordinates coordinates();
|
||||||
|
@ -6,6 +6,26 @@ static qint64 delphi2unixMS(double date)
|
|||||||
return (qint64)((date - 25569.0) * 86400000);
|
return (qint64)((date - 25569.0) * 86400000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isASCII(const QByteArray &ba)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ba.size(); i++) {
|
||||||
|
quint8 c = (quint8)ba.at(i);
|
||||||
|
if (c > 0x7f && c != 0xD1)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QByteArray &decode(QByteArray &ba)
|
||||||
|
{
|
||||||
|
if (isASCII(ba))
|
||||||
|
ba.replace('\xD1', ',');
|
||||||
|
|
||||||
|
return ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||||
QList<RouteData> &routes, QList<Waypoint> &waypoints)
|
QList<RouteData> &routes, QList<Waypoint> &waypoints)
|
||||||
{
|
{
|
||||||
@ -24,7 +44,8 @@ bool PLTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
QByteArray line = file->readLine();
|
QByteArray line = file->readLine();
|
||||||
|
|
||||||
if (_errorLine == 1) {
|
if (_errorLine == 1) {
|
||||||
if (!line.trimmed().startsWith("OziExplorer Track Point File")) {
|
QString fileType(QString::fromUtf8(line).trimmed());
|
||||||
|
if (!fileType.startsWith("OziExplorer Track Point File")) {
|
||||||
_errorString = "Not a PLT file";
|
_errorString = "Not a PLT file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -107,7 +128,8 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
QByteArray line = file->readLine();
|
QByteArray line = file->readLine();
|
||||||
|
|
||||||
if (_errorLine == 1) {
|
if (_errorLine == 1) {
|
||||||
if (!line.trimmed().startsWith("OziExplorer Route File")) {
|
QString fileType(QString::fromUtf8(line).trimmed());
|
||||||
|
if (!fileType.startsWith("OziExplorer Route File")) {
|
||||||
_errorString = "Not a RTE file";
|
_errorString = "Not a RTE file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -127,12 +149,14 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
routes.append(RouteData());
|
routes.append(RouteData());
|
||||||
record = true;
|
record = true;
|
||||||
|
|
||||||
if (list.size() >= 3)
|
if (list.size() >= 3) {
|
||||||
routes.last().setName(list.at(2).trimmed()
|
QByteArray name(list.at(2).trimmed());
|
||||||
.replace('\xD1', ','));
|
routes.last().setName(decode(name));
|
||||||
if (list.size() >= 4)
|
}
|
||||||
routes.last().setDescription(list.at(3).trimmed()
|
if (list.size() >= 4) {
|
||||||
.replace('\xD1', ','));
|
QByteArray description(list.at(3).trimmed());
|
||||||
|
routes.last().setDescription(decode(description));
|
||||||
|
}
|
||||||
} else if (list.at(0).trimmed() == "W") {
|
} else if (list.at(0).trimmed() == "W") {
|
||||||
if (!record || list.size() < 7) {
|
if (!record || list.size() < 7) {
|
||||||
_errorString = "Parse error";
|
_errorString = "Parse error";
|
||||||
@ -152,9 +176,9 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
|
|
||||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
||||||
|
|
||||||
QString name(list.at(4).trimmed().replace('\xD1', ','));
|
QByteArray name(list.at(4).trimmed());
|
||||||
if (!name.isEmpty())
|
if (!name.isEmpty())
|
||||||
wp.setName(name);
|
wp.setName(decode(name));
|
||||||
if (list.size() >= 8) {
|
if (list.size() >= 8) {
|
||||||
QByteArray field(list.at(7).trimmed());
|
QByteArray field(list.at(7).trimmed());
|
||||||
if (!field.isEmpty()) {
|
if (!field.isEmpty()) {
|
||||||
@ -168,9 +192,9 @@ bool RTEParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (list.size() >= 14) {
|
if (list.size() >= 14) {
|
||||||
QString desc(list.at(13).trimmed().replace('\xD1', ','));
|
QByteArray description(list.at(13).trimmed());
|
||||||
if (!desc.isEmpty())
|
if (!description.isEmpty())
|
||||||
wp.setDescription(desc);
|
wp.setDescription(decode(description));
|
||||||
}
|
}
|
||||||
|
|
||||||
routes.last().append(wp);
|
routes.last().append(wp);
|
||||||
@ -201,7 +225,8 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
QByteArray line = file->readLine();
|
QByteArray line = file->readLine();
|
||||||
|
|
||||||
if (_errorLine == 1) {
|
if (_errorLine == 1) {
|
||||||
if (!line.trimmed().startsWith("OziExplorer Waypoint File")) {
|
QString fileType(QString::fromUtf8(line).trimmed());
|
||||||
|
if (!fileType.startsWith("OziExplorer Waypoint File")) {
|
||||||
_errorString = "Not a WPT file";
|
_errorString = "Not a WPT file";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -230,9 +255,9 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
|
|
||||||
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
Waypoint wp(gcs->toWGS84(Coordinates(lon, lat)));
|
||||||
|
|
||||||
QString name(list.at(1).trimmed().replace('\xD1', ','));
|
QByteArray name(list.at(1).trimmed());
|
||||||
if (!name.isEmpty())
|
if (!name.isEmpty())
|
||||||
wp.setName(name);
|
wp.setName(decode(name));
|
||||||
if (list.size() >= 5) {
|
if (list.size() >= 5) {
|
||||||
QByteArray field(list.at(4).trimmed());
|
QByteArray field(list.at(4).trimmed());
|
||||||
if (!field.isEmpty()) {
|
if (!field.isEmpty()) {
|
||||||
@ -246,9 +271,9 @@ bool WPTParser::parse(QFile *file, QList<TrackData> &tracks,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (list.size() >= 11) {
|
if (list.size() >= 11) {
|
||||||
QString desc(list.at(10).trimmed().replace('\xD1', ','));
|
QByteArray description(list.at(10).trimmed());
|
||||||
if (!desc.isEmpty())
|
if (!description.isEmpty())
|
||||||
wp.setDescription(desc);
|
wp.setDescription(decode(description));
|
||||||
}
|
}
|
||||||
if (list.size() >= 15) {
|
if (list.size() >= 15) {
|
||||||
QByteArray field(list.at(14).trimmed());
|
QByteArray field(list.at(14).trimmed());
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include "rtree.h"
|
#include "common/rtree.h"
|
||||||
#include "waypoint.h"
|
#include "waypoint.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "track.h"
|
#include "track.h"
|
||||||
|
|
||||||
#define OUTLIER_WINDOW 21
|
|
||||||
|
|
||||||
int Track::_elevationWindow = 3;
|
int Track::_elevationWindow = 3;
|
||||||
int Track::_speedWindow = 5;
|
int Track::_speedWindow = 5;
|
||||||
int Track::_heartRateWindow = 3;
|
int Track::_heartRateWindow = 3;
|
||||||
@ -12,15 +10,16 @@ qreal Track::_pauseSpeed = 0.5;
|
|||||||
int Track::_pauseInterval = 10;
|
int Track::_pauseInterval = 10;
|
||||||
|
|
||||||
bool Track::_outlierEliminate = true;
|
bool Track::_outlierEliminate = true;
|
||||||
|
bool Track::_useReportedSpeed = false;
|
||||||
|
|
||||||
|
|
||||||
static qreal median(QVector<qreal> v)
|
static qreal median(QVector<qreal> &v)
|
||||||
{
|
{
|
||||||
qSort(v.begin(), v.end());
|
qSort(v.begin(), v.end());
|
||||||
return v.at(v.size() / 2);
|
return v.at(v.size() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static qreal MAD(QVector<qreal> v, qreal m)
|
static qreal MAD(QVector<qreal> &v, qreal m)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < v.size(); i++)
|
for (int i = 0; i < v.size(); i++)
|
||||||
v[i] = qAbs(v.at(i) - m);
|
v[i] = qAbs(v.at(i) - m);
|
||||||
@ -28,21 +27,17 @@ static qreal MAD(QVector<qreal> v, qreal m)
|
|||||||
return v.at(v.size() / 2);
|
return v.at(v.size() / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSet<int> eliminate(const QVector<qreal> &v, int window)
|
static QSet<int> eliminate(const QVector<qreal> &v)
|
||||||
{
|
{
|
||||||
QSet<int> rm;
|
QSet<int> rm;
|
||||||
qreal m, M;
|
|
||||||
|
|
||||||
|
QVector<qreal> w(v);
|
||||||
|
qreal m = median(w);
|
||||||
|
qreal M = MAD(w, m);
|
||||||
|
|
||||||
if (v.size() < window)
|
for (int i = 0; i < v.size(); i++)
|
||||||
return rm;
|
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 5)
|
||||||
|
|
||||||
for (int i = window/2; i < v.size() - window/2; i++) {
|
|
||||||
m = median(v.mid(i - window/2, window));
|
|
||||||
M = MAD(v.mid(i - window/2, window), m);
|
|
||||||
if (qAbs((0.6745 * (v.at(i) - m)) / M) > 3.5)
|
|
||||||
rm.insert(i);
|
rm.insert(i);
|
||||||
}
|
|
||||||
|
|
||||||
return rm;
|
return rm;
|
||||||
}
|
}
|
||||||
@ -74,37 +69,33 @@ static Graph filter(const Graph &g, int window)
|
|||||||
|
|
||||||
Track::Track(const TrackData &data) : _data(data)
|
Track::Track(const TrackData &data) : _data(data)
|
||||||
{
|
{
|
||||||
qreal dt, ds, total;
|
QVector<qreal> acceleration;
|
||||||
int last;
|
qreal ds, dt;
|
||||||
|
|
||||||
|
|
||||||
_time.append(0);
|
_time.append(0);
|
||||||
_distance.append(0);
|
_distance.append(0);
|
||||||
_speed.append(0);
|
_speed.append(0);
|
||||||
|
acceleration.append(0);
|
||||||
last = 0;
|
|
||||||
|
|
||||||
for (int i = 1; i < _data.count(); i++) {
|
for (int i = 1; i < _data.count(); i++) {
|
||||||
ds = _data.at(i).coordinates().distanceTo(_data.at(i-1).coordinates());
|
ds = _data.at(i).coordinates().distanceTo(_data.at(i-1).coordinates());
|
||||||
_distance.append(ds);
|
_distance.append(_distance.at(i-1) + ds);
|
||||||
|
|
||||||
if (_data.first().hasTimestamp() && _data.at(i).hasTimestamp()
|
if (_data.first().hasTimestamp() && _data.at(i).hasTimestamp()
|
||||||
&& _data.at(i).timestamp() > _data.at(last).timestamp()) {
|
&& _data.at(i).timestamp() >= _data.at(i-1).timestamp())
|
||||||
_time.append(_data.first().timestamp().msecsTo(
|
_time.append(_data.first().timestamp().msecsTo(
|
||||||
_data.at(i).timestamp()) / 1000.0);
|
_data.at(i).timestamp()) / 1000.0);
|
||||||
last = i;
|
else
|
||||||
} else
|
|
||||||
_time.append(NAN);
|
_time.append(NAN);
|
||||||
|
|
||||||
if (std::isnan(_time.at(i)) || std::isnan(_time.at(i-1)))
|
dt = _time.at(i) - _time.at(i-1);
|
||||||
_speed.append(NAN);
|
if (dt < 1e-3) {
|
||||||
else {
|
_speed.append(_speed.at(i-1));
|
||||||
dt = _time.at(i) - _time.at(i-1);
|
acceleration.append(acceleration.at(i-1));
|
||||||
if (dt < 1e-3) {
|
} else {
|
||||||
_speed.append(_speed.at(i-1));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
_speed.append(ds / dt);
|
_speed.append(ds / dt);
|
||||||
|
qreal dv = _speed.at(i) - _speed.at(i-1);
|
||||||
|
acceleration.append(dv / dt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,20 +109,37 @@ Track::Track(const TrackData &data) : _data(data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_outlierEliminate)
|
if (!_outlierEliminate)
|
||||||
_outliers = eliminate(_speed, OUTLIER_WINDOW);
|
return;
|
||||||
|
|
||||||
|
_outliers = eliminate(acceleration);
|
||||||
|
|
||||||
QSet<int>::const_iterator it;
|
QSet<int>::const_iterator it;
|
||||||
for (it = _stop.constBegin(); it != _stop.constEnd(); ++it)
|
for (it = _stop.constBegin(); it != _stop.constEnd(); ++it)
|
||||||
_outliers.remove(*it);
|
_outliers.remove(*it);
|
||||||
|
|
||||||
total = 0;
|
int last = 0;
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
|
if (_outliers.contains(i))
|
||||||
|
last++;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = last + 1; i < _data.size(); i++) {
|
||||||
if (_outliers.contains(i))
|
if (_outliers.contains(i))
|
||||||
continue;
|
continue;
|
||||||
if (!discardStopPoint(i))
|
if (discardStopPoint(i)) {
|
||||||
total += _distance.at(i);
|
_distance[i] = _distance.at(last);
|
||||||
_distance[i] = total;
|
_speed[i] = 0;
|
||||||
|
} else {
|
||||||
|
ds = _data.at(i).coordinates().distanceTo(
|
||||||
|
_data.at(last).coordinates());
|
||||||
|
_distance[i] = _distance.at(last) + ds;
|
||||||
|
|
||||||
|
dt = _time.at(i) - _time.at(last);
|
||||||
|
_speed[i] = (dt < 1e-3) ? _speed.at(last) : ds / dt;
|
||||||
|
}
|
||||||
|
last = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,14 +159,15 @@ Graph Track::speed() const
|
|||||||
{
|
{
|
||||||
Graph raw, filtered;
|
Graph raw, filtered;
|
||||||
qreal v;
|
qreal v;
|
||||||
QSet<int> stop;
|
QList<int> stop;
|
||||||
|
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
if (_stop.contains(i) && (!std::isnan(_speed.at(i))
|
if (_stop.contains(i) && (!std::isnan(_speed.at(i))
|
||||||
|| _data.at(i).hasSpeed())) {
|
|| _data.at(i).hasSpeed())) {
|
||||||
v = 0;
|
v = 0;
|
||||||
stop.insert(raw.size());
|
stop.append(raw.size());
|
||||||
} else if (_data.at(i).hasSpeed() && !_outliers.contains(i))
|
} else if (_useReportedSpeed && _data.at(i).hasSpeed()
|
||||||
|
&& !_outliers.contains(i))
|
||||||
v = _data.at(i).speed();
|
v = _data.at(i).speed();
|
||||||
else if (!std::isnan(_speed.at(i)) && !_outliers.contains(i))
|
else if (!std::isnan(_speed.at(i)) && !_outliers.contains(i))
|
||||||
v = _speed.at(i);
|
v = _speed.at(i);
|
||||||
@ -170,9 +179,8 @@ Graph Track::speed() const
|
|||||||
|
|
||||||
filtered = filter(raw, _speedWindow);
|
filtered = filter(raw, _speedWindow);
|
||||||
|
|
||||||
QSet<int>::const_iterator it;
|
for (int i = 0; i < stop.size(); i++)
|
||||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
filtered[stop.at(i)].setY(0);
|
||||||
filtered[*it].setY(0);
|
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
@ -201,16 +209,28 @@ Graph Track::temperature() const
|
|||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Graph Track::ratio() const
|
||||||
|
{
|
||||||
|
Graph raw;
|
||||||
|
|
||||||
|
for (int i = 0; i < _data.size(); i++)
|
||||||
|
if (_data.at(i).hasRatio() && !_outliers.contains(i))
|
||||||
|
raw.append(GraphPoint(_distance.at(i), _time.at(i),
|
||||||
|
_data.at(i).ratio()));
|
||||||
|
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
Graph Track::cadence() const
|
Graph Track::cadence() const
|
||||||
{
|
{
|
||||||
Graph raw, filtered;
|
Graph raw, filtered;
|
||||||
QSet<int> stop;
|
QList<int> stop;
|
||||||
qreal c;
|
qreal c;
|
||||||
|
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
if (_data.at(i).hasCadence() && _stop.contains(i)) {
|
if (_data.at(i).hasCadence() && _stop.contains(i)) {
|
||||||
c = 0;
|
c = 0;
|
||||||
stop.insert(raw.size());
|
stop.append(raw.size());
|
||||||
} else if (_data.at(i).hasCadence() && !_outliers.contains(i))
|
} else if (_data.at(i).hasCadence() && !_outliers.contains(i))
|
||||||
c = _data.at(i).cadence();
|
c = _data.at(i).cadence();
|
||||||
else
|
else
|
||||||
@ -221,9 +241,8 @@ Graph Track::cadence() const
|
|||||||
|
|
||||||
filtered = filter(raw, _cadenceWindow);
|
filtered = filter(raw, _cadenceWindow);
|
||||||
|
|
||||||
QSet<int>::const_iterator it;
|
for (int i = 0; i < stop.size(); i++)
|
||||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
filtered[stop.at(i)].setY(0);
|
||||||
filtered[*it].setY(0);
|
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
@ -231,13 +250,13 @@ Graph Track::cadence() const
|
|||||||
Graph Track::power() const
|
Graph Track::power() const
|
||||||
{
|
{
|
||||||
Graph raw, filtered;
|
Graph raw, filtered;
|
||||||
QSet<int> stop;
|
QList<int> stop;
|
||||||
qreal p;
|
qreal p;
|
||||||
|
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
if (_data.at(i).hasPower() && _stop.contains(i)) {
|
if (_data.at(i).hasPower() && _stop.contains(i)) {
|
||||||
p = 0;
|
p = 0;
|
||||||
stop.insert(raw.size());
|
stop.append(raw.size());
|
||||||
} else if (_data.at(i).hasPower() && !_outliers.contains(i))
|
} else if (_data.at(i).hasPower() && !_outliers.contains(i))
|
||||||
p = _data.at(i).power();
|
p = _data.at(i).power();
|
||||||
else
|
else
|
||||||
@ -248,22 +267,29 @@ Graph Track::power() const
|
|||||||
|
|
||||||
filtered = filter(raw, _powerWindow);
|
filtered = filter(raw, _powerWindow);
|
||||||
|
|
||||||
QSet<int>::const_iterator it;
|
for (int i = 0; i < stop.size(); i++)
|
||||||
for (it = stop.constBegin(); it != stop.constEnd(); ++it)
|
filtered[stop.at(i)].setY(0);
|
||||||
filtered[*it].setY(0);
|
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Track::distance() const
|
qreal Track::distance() const
|
||||||
{
|
{
|
||||||
return _distance.isEmpty() ? 0 : _distance.last();
|
for (int i = _distance.size() - 1; i >= 0; i--)
|
||||||
|
if (!_outliers.contains(i))
|
||||||
|
return _distance.at(i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Track::time() const
|
qreal Track::time() const
|
||||||
{
|
{
|
||||||
return (_data.size() < 2) ? 0 :
|
for (int i = _data.size() - 1; i >= 0; i--)
|
||||||
(_data.first().timestamp().msecsTo(_data.last().timestamp()) / 1000.0);
|
if (!_outliers.contains(i))
|
||||||
|
return _data.first().timestamp().msecsTo(_data.at(i).timestamp())
|
||||||
|
/ 1000.0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Track::movingTime() const
|
qreal Track::movingTime() const
|
||||||
|
@ -22,6 +22,7 @@ public:
|
|||||||
Graph temperature() const;
|
Graph temperature() const;
|
||||||
Graph cadence() const;
|
Graph cadence() const;
|
||||||
Graph power() const;
|
Graph power() const;
|
||||||
|
Graph ratio() const;
|
||||||
|
|
||||||
qreal distance() const;
|
qreal distance() const;
|
||||||
qreal time() const;
|
qreal time() const;
|
||||||
@ -42,6 +43,7 @@ public:
|
|||||||
static void setPauseInterval(int interval) {_pauseInterval = interval;}
|
static void setPauseInterval(int interval) {_pauseInterval = interval;}
|
||||||
static void setOutlierElimination(bool eliminate)
|
static void setOutlierElimination(bool eliminate)
|
||||||
{_outlierEliminate = eliminate;}
|
{_outlierEliminate = eliminate;}
|
||||||
|
static void useReportedSpeed(bool use) {_useReportedSpeed = use;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool discardStopPoint(int i) const;
|
bool discardStopPoint(int i) const;
|
||||||
@ -58,15 +60,14 @@ private:
|
|||||||
qreal _pause;
|
qreal _pause;
|
||||||
|
|
||||||
static bool _outlierEliminate;
|
static bool _outlierEliminate;
|
||||||
|
|
||||||
static int _elevationWindow;
|
static int _elevationWindow;
|
||||||
static int _speedWindow;
|
static int _speedWindow;
|
||||||
static int _heartRateWindow;
|
static int _heartRateWindow;
|
||||||
static int _cadenceWindow;
|
static int _cadenceWindow;
|
||||||
static int _powerWindow;
|
static int _powerWindow;
|
||||||
|
|
||||||
static qreal _pauseSpeed;
|
static qreal _pauseSpeed;
|
||||||
static int _pauseInterval;
|
static int _pauseInterval;
|
||||||
|
static bool _useReportedSpeed;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TRACK_H
|
#endif // TRACK_H
|
||||||
|
@ -11,10 +11,10 @@ class Trackpoint
|
|||||||
public:
|
public:
|
||||||
Trackpoint()
|
Trackpoint()
|
||||||
{_elevation = NAN; _speed = NAN; _heartRate = NAN; _temperature = NAN;
|
{_elevation = NAN; _speed = NAN; _heartRate = NAN; _temperature = NAN;
|
||||||
_cadence = NAN; _power = NAN;}
|
_cadence = NAN; _power = NAN; _ratio = NAN;}
|
||||||
Trackpoint(const Coordinates &coordinates) : _coordinates(coordinates)
|
Trackpoint(const Coordinates &coordinates) : _coordinates(coordinates)
|
||||||
{_elevation = NAN; _speed = NAN; _heartRate = NAN; _temperature = NAN;
|
{_elevation = NAN; _speed = NAN; _heartRate = NAN; _temperature = NAN;
|
||||||
_cadence = NAN; _power = NAN;}
|
_cadence = NAN; _power = NAN; _ratio = NAN;}
|
||||||
|
|
||||||
const Coordinates &coordinates() const {return _coordinates;}
|
const Coordinates &coordinates() const {return _coordinates;}
|
||||||
Coordinates &rcoordinates() {return _coordinates;}
|
Coordinates &rcoordinates() {return _coordinates;}
|
||||||
@ -25,6 +25,7 @@ public:
|
|||||||
qreal temperature() const {return _temperature;}
|
qreal temperature() const {return _temperature;}
|
||||||
qreal cadence() const {return _cadence;}
|
qreal cadence() const {return _cadence;}
|
||||||
qreal power() const {return _power;}
|
qreal power() const {return _power;}
|
||||||
|
qreal ratio() const {return _ratio;}
|
||||||
|
|
||||||
void setCoordinates(const Coordinates &coordinates)
|
void setCoordinates(const Coordinates &coordinates)
|
||||||
{_coordinates = coordinates;}
|
{_coordinates = coordinates;}
|
||||||
@ -35,6 +36,7 @@ public:
|
|||||||
void setTemperature(qreal temperature) {_temperature = temperature;}
|
void setTemperature(qreal temperature) {_temperature = temperature;}
|
||||||
void setCadence(qreal cadence) {_cadence = cadence;}
|
void setCadence(qreal cadence) {_cadence = cadence;}
|
||||||
void setPower(qreal power) {_power = power;}
|
void setPower(qreal power) {_power = power;}
|
||||||
|
void setRatio(qreal ratio) {_ratio = ratio;}
|
||||||
|
|
||||||
bool hasTimestamp() const {return !_timestamp.isNull();}
|
bool hasTimestamp() const {return !_timestamp.isNull();}
|
||||||
bool hasElevation() const {return !std::isnan(_elevation);}
|
bool hasElevation() const {return !std::isnan(_elevation);}
|
||||||
@ -43,6 +45,7 @@ public:
|
|||||||
bool hasTemperature() const {return !std::isnan(_temperature);}
|
bool hasTemperature() const {return !std::isnan(_temperature);}
|
||||||
bool hasCadence() const {return !std::isnan(_cadence);}
|
bool hasCadence() const {return !std::isnan(_cadence);}
|
||||||
bool hasPower() const {return !std::isnan(_power);}
|
bool hasPower() const {return !std::isnan(_power);}
|
||||||
|
bool hasRatio() const {return !std::isnan(_ratio);}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Coordinates _coordinates;
|
Coordinates _coordinates;
|
||||||
@ -53,6 +56,7 @@ private:
|
|||||||
qreal _temperature;
|
qreal _temperature;
|
||||||
qreal _cadence;
|
qreal _cadence;
|
||||||
qreal _power;
|
qreal _power;
|
||||||
|
qreal _ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(Trackpoint, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(Trackpoint, Q_MOVABLE_TYPE);
|
||||||
@ -63,7 +67,8 @@ inline QDebug operator<<(QDebug dbg, const Trackpoint &trackpoint)
|
|||||||
dbg.nospace() << "Trackpoint(" << trackpoint.coordinates() << ", "
|
dbg.nospace() << "Trackpoint(" << trackpoint.coordinates() << ", "
|
||||||
<< trackpoint.timestamp() << ", " << trackpoint.elevation() << ", "
|
<< trackpoint.timestamp() << ", " << trackpoint.elevation() << ", "
|
||||||
<< trackpoint.speed() << ", " << trackpoint.heartRate() << ", "
|
<< trackpoint.speed() << ", " << trackpoint.heartRate() << ", "
|
||||||
<< trackpoint.temperature() << ")";
|
<< trackpoint.temperature() << ", " << trackpoint.cadence() << ", "
|
||||||
|
<< trackpoint.power() << ", " << trackpoint.ratio() << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -45,16 +45,12 @@ Defense.
|
|||||||
#include "albersequal.h"
|
#include "albersequal.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef M_PI_2
|
|
||||||
#define M_PI_2 1.57079632679489661923
|
|
||||||
#endif // M_PI_2
|
|
||||||
|
|
||||||
#define ONE_MINUS_SQR(x) (1.0 - (x) * (x))
|
#define ONE_MINUS_SQR(x) (1.0 - (x) * (x))
|
||||||
#define ALBERS_Q(slat, one_minus_sqr_es_sin, es_sin) \
|
#define ALBERS_Q(slat, one_minus_sqr_e_sin, es_sin) \
|
||||||
(_one_minus_es2 * ((slat) / (one_minus_sqr_es_sin) - \
|
(_one_minus_es * ((slat) / (one_minus_sqr_e_sin) - \
|
||||||
(1 / (_two_es)) * log((1 - (es_sin)) / (1 + (es_sin)))))
|
(1 / (_two_e)) * log((1 - (es_sin)) / (1 + (es_sin)))))
|
||||||
#define ALBERS_M(clat, one_minus_sqr_es_sin) \
|
#define ALBERS_M(clat, one_minus_sqr_e_sin) \
|
||||||
((clat) / sqrt(one_minus_sqr_es_sin))
|
((clat) / sqrt(one_minus_sqr_e_sin))
|
||||||
|
|
||||||
|
|
||||||
AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
||||||
@ -64,8 +60,8 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
|||||||
double sin_lat, sin_lat1, sin_lat2, cos_lat1, cos_lat2;
|
double sin_lat, sin_lat1, sin_lat2, cos_lat1, cos_lat2;
|
||||||
double m1, m2, sqr_m1, sqr_m2;
|
double m1, m2, sqr_m1, sqr_m2;
|
||||||
double q0, q1, q2;
|
double q0, q1, q2;
|
||||||
double es_sin, es_sin1, es_sin2;
|
double e_sin, e_sin1, e_sin2;
|
||||||
double one_minus_sqr_es_sin1, one_minus_sqr_es_sin2;
|
double one_minus_sqr_e_sin1, one_minus_sqr_e_sin2;
|
||||||
double nq0;
|
double nq0;
|
||||||
double sp1, sp2;
|
double sp1, sp2;
|
||||||
|
|
||||||
@ -79,31 +75,30 @@ AlbersEqual::AlbersEqual(const Ellipsoid *ellipsoid, double standardParallel1,
|
|||||||
sp2 = deg2rad(standardParallel2);
|
sp2 = deg2rad(standardParallel2);
|
||||||
|
|
||||||
_a2 = ellipsoid->radius() * ellipsoid->radius();
|
_a2 = ellipsoid->radius() * ellipsoid->radius();
|
||||||
_es2 = 2 * ellipsoid->flattening() - ellipsoid->flattening()
|
_es = ellipsoid->es();
|
||||||
* ellipsoid->flattening();
|
_e = sqrt(_es);
|
||||||
_es = sqrt(_es2);
|
_one_minus_es = 1 - _es;
|
||||||
_one_minus_es2 = 1 - _es2;
|
_two_e = 2 * _e;
|
||||||
_two_es = 2 * _es;
|
|
||||||
|
|
||||||
sin_lat = sin(_latitudeOrigin);
|
sin_lat = sin(_latitudeOrigin);
|
||||||
es_sin = _es * sin_lat;
|
e_sin = _e * sin_lat;
|
||||||
q0 = ALBERS_Q(sin_lat, ONE_MINUS_SQR(es_sin), es_sin);
|
q0 = ALBERS_Q(sin_lat, ONE_MINUS_SQR(e_sin), e_sin);
|
||||||
|
|
||||||
sin_lat1 = sin(sp1);
|
sin_lat1 = sin(sp1);
|
||||||
cos_lat1 = cos(sp1);
|
cos_lat1 = cos(sp1);
|
||||||
es_sin1 = _es * sin_lat1;
|
e_sin1 = _e * sin_lat1;
|
||||||
one_minus_sqr_es_sin1 = ONE_MINUS_SQR(es_sin1);
|
one_minus_sqr_e_sin1 = ONE_MINUS_SQR(e_sin1);
|
||||||
m1 = ALBERS_M(cos_lat1, one_minus_sqr_es_sin1);
|
m1 = ALBERS_M(cos_lat1, one_minus_sqr_e_sin1);
|
||||||
q1 = ALBERS_Q(sin_lat1, one_minus_sqr_es_sin1, es_sin1);
|
q1 = ALBERS_Q(sin_lat1, one_minus_sqr_e_sin1, e_sin1);
|
||||||
|
|
||||||
sqr_m1 = m1 * m1;
|
sqr_m1 = m1 * m1;
|
||||||
if (fabs(sp1 - sp2) > 1.0e-10) {
|
if (fabs(sp1 - sp2) > 1.0e-10) {
|
||||||
sin_lat2 = sin(sp2);
|
sin_lat2 = sin(sp2);
|
||||||
cos_lat2 = cos(sp2);
|
cos_lat2 = cos(sp2);
|
||||||
es_sin2 = _es * sin_lat2;
|
e_sin2 = _e * sin_lat2;
|
||||||
one_minus_sqr_es_sin2 = ONE_MINUS_SQR(es_sin2);
|
one_minus_sqr_e_sin2 = ONE_MINUS_SQR(e_sin2);
|
||||||
m2 = ALBERS_M(cos_lat2, one_minus_sqr_es_sin2);
|
m2 = ALBERS_M(cos_lat2, one_minus_sqr_e_sin2);
|
||||||
q2 = ALBERS_Q(sin_lat2, one_minus_sqr_es_sin2, es_sin2);
|
q2 = ALBERS_Q(sin_lat2, one_minus_sqr_e_sin2, e_sin2);
|
||||||
sqr_m2 = m2 * m2;
|
sqr_m2 = m2 * m2;
|
||||||
_n = (sqr_m1 - sqr_m2) / (q2 - q1);
|
_n = (sqr_m1 - sqr_m2) / (q2 - q1);
|
||||||
} else
|
} else
|
||||||
@ -119,7 +114,7 @@ PointD AlbersEqual::ll2xy(const Coordinates &c) const
|
|||||||
{
|
{
|
||||||
double dlam;
|
double dlam;
|
||||||
double sin_lat;
|
double sin_lat;
|
||||||
double es_sin;
|
double e_sin;
|
||||||
double q;
|
double q;
|
||||||
double rho;
|
double rho;
|
||||||
double theta;
|
double theta;
|
||||||
@ -128,13 +123,13 @@ PointD AlbersEqual::ll2xy(const Coordinates &c) const
|
|||||||
|
|
||||||
dlam = deg2rad(c.lon()) - _longitudeOrigin;
|
dlam = deg2rad(c.lon()) - _longitudeOrigin;
|
||||||
if (dlam > M_PI)
|
if (dlam > M_PI)
|
||||||
dlam -= 2.0 * M_PI;
|
dlam -= M_2_PI;
|
||||||
if (dlam < -M_PI)
|
if (dlam < -M_PI)
|
||||||
dlam += 2.0 * M_PI;
|
dlam += M_2_PI;
|
||||||
|
|
||||||
sin_lat = sin(deg2rad(c.lat()));
|
sin_lat = sin(deg2rad(c.lat()));
|
||||||
es_sin = _es * sin_lat;
|
e_sin = _e * sin_lat;
|
||||||
q = ALBERS_Q(sin_lat, ONE_MINUS_SQR(es_sin), es_sin);
|
q = ALBERS_Q(sin_lat, ONE_MINUS_SQR(e_sin), e_sin);
|
||||||
nq = _n * q;
|
nq = _n * q;
|
||||||
rho = (_C < nq) ? 0 : _a_over_n * sqrt(_C - nq);
|
rho = (_C < nq) ? 0 : _a_over_n * sqrt(_C - nq);
|
||||||
theta = _n * dlam;
|
theta = _n * dlam;
|
||||||
@ -151,7 +146,7 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
|
|||||||
double rho, rho_n;
|
double rho, rho_n;
|
||||||
double phi, delta_phi = 1.0;
|
double phi, delta_phi = 1.0;
|
||||||
double sin_phi;
|
double sin_phi;
|
||||||
double es_sin, one_minus_sqr_es_sin;
|
double e_sin, one_minus_sqr_e_sin;
|
||||||
double theta = 0.0;
|
double theta = 0.0;
|
||||||
int count = 30;
|
int count = 30;
|
||||||
double tolerance = 4.85e-10;
|
double tolerance = 4.85e-10;
|
||||||
@ -174,7 +169,7 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
|
|||||||
theta = atan2(dx, rho0_minus_dy);
|
theta = atan2(dx, rho0_minus_dy);
|
||||||
rho_n = rho * _n;
|
rho_n = rho * _n;
|
||||||
q = (_C - (rho_n * rho_n) / _a2) / _n;
|
q = (_C - (rho_n * rho_n) / _a2) / _n;
|
||||||
qc = 1 - ((_one_minus_es2) / (_two_es)) * log((1.0 - _es) / (1.0 + _es));
|
qc = 1 - ((_one_minus_es) / (_two_e)) * log((1.0 - _e) / (1.0 + _e));
|
||||||
if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) {
|
if (fabs(fabs(qc) - fabs(q)) > 1.0e-6) {
|
||||||
q_over_2 = q / 2.0;
|
q_over_2 = q / 2.0;
|
||||||
if (q_over_2 > 1.0)
|
if (q_over_2 > 1.0)
|
||||||
@ -183,17 +178,17 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
|
|||||||
lat = -M_PI_2;
|
lat = -M_PI_2;
|
||||||
else {
|
else {
|
||||||
phi = asin(q_over_2);
|
phi = asin(q_over_2);
|
||||||
if (_es < 1.0e-10)
|
if (_e < 1.0e-10)
|
||||||
lat = phi;
|
lat = phi;
|
||||||
else {
|
else {
|
||||||
while ((fabs(delta_phi) > tolerance) && count) {
|
while ((fabs(delta_phi) > tolerance) && count) {
|
||||||
sin_phi = sin(phi);
|
sin_phi = sin(phi);
|
||||||
es_sin = _es * sin_phi;
|
e_sin = _e * sin_phi;
|
||||||
one_minus_sqr_es_sin = ONE_MINUS_SQR(es_sin);
|
one_minus_sqr_e_sin = ONE_MINUS_SQR(e_sin);
|
||||||
delta_phi = (one_minus_sqr_es_sin * one_minus_sqr_es_sin)
|
delta_phi = (one_minus_sqr_e_sin * one_minus_sqr_e_sin)
|
||||||
/ (2.0 * cos(phi)) * (q / (_one_minus_es2) - sin_phi
|
/ (2.0 * cos(phi)) * (q / (_one_minus_es) - sin_phi
|
||||||
/ one_minus_sqr_es_sin + (log((1.0 - es_sin)
|
/ one_minus_sqr_e_sin + (log((1.0 - e_sin)
|
||||||
/ (1.0 + es_sin)) / (_two_es)));
|
/ (1.0 + e_sin)) / (_two_e)));
|
||||||
phi += delta_phi;
|
phi += delta_phi;
|
||||||
count --;
|
count --;
|
||||||
}
|
}
|
||||||
@ -216,9 +211,9 @@ Coordinates AlbersEqual::xy2ll(const PointD &p) const
|
|||||||
lon = _longitudeOrigin + theta / _n;
|
lon = _longitudeOrigin + theta / _n;
|
||||||
|
|
||||||
if (lon > M_PI)
|
if (lon > M_PI)
|
||||||
lon -= M_PI * 2;
|
lon -= M_2_PI;
|
||||||
if (lon < -M_PI)
|
if (lon < -M_PI)
|
||||||
lon += M_PI * 2;
|
lon += M_2_PI;
|
||||||
|
|
||||||
if (lon > M_PI)
|
if (lon > M_PI)
|
||||||
lon = M_PI;
|
lon = M_PI;
|
||||||
|
@ -27,11 +27,11 @@ private:
|
|||||||
double _rho0;
|
double _rho0;
|
||||||
double _C;
|
double _C;
|
||||||
double _n;
|
double _n;
|
||||||
|
double _e;
|
||||||
double _es;
|
double _es;
|
||||||
double _es2;
|
|
||||||
double _a_over_n;
|
double _a_over_n;
|
||||||
double _one_minus_es2;
|
double _one_minus_es;
|
||||||
double _two_es;
|
double _two_e;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ALBERSEQUAL_H
|
#endif // ALBERSEQUAL_H
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#define TL(m) ((m)->xy2pp((m)->bounds().topLeft()))
|
#define TL(m) ((m)->xy2pp((m)->bounds().topLeft()))
|
||||||
#define BR(m) ((m)->xy2pp((m)->bounds().bottomRight()))
|
#define BR(m) ((m)->xy2pp((m)->bounds().bottomRight()))
|
||||||
|
|
||||||
static bool resCmp(const OfflineMap *m1, const OfflineMap *m2)
|
static bool resCmp(OfflineMap *m1, OfflineMap *m2)
|
||||||
{
|
{
|
||||||
qreal r1, r2;
|
qreal r1, r2;
|
||||||
|
|
||||||
@ -22,12 +22,12 @@ static bool resCmp(const OfflineMap *m1, const OfflineMap *m2)
|
|||||||
return r1 > r2;
|
return r1 > r2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool xCmp(const OfflineMap *m1, const OfflineMap *m2)
|
static bool xCmp(OfflineMap *m1, OfflineMap *m2)
|
||||||
{
|
{
|
||||||
return TL(m1).x() < TL(m2).x();
|
return TL(m1).x() < TL(m2).x();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool yCmp(const OfflineMap *m1, const OfflineMap *m2)
|
static bool yCmp(OfflineMap *m1, OfflineMap *m2)
|
||||||
{
|
{
|
||||||
return TL(m1).y() > TL(m2).y();
|
return TL(m1).y() > TL(m2).y();
|
||||||
}
|
}
|
||||||
@ -36,13 +36,13 @@ void Atlas::computeZooms()
|
|||||||
{
|
{
|
||||||
qSort(_maps.begin(), _maps.end(), resCmp);
|
qSort(_maps.begin(), _maps.end(), resCmp);
|
||||||
|
|
||||||
_zooms.append(QPair<int, int>(0, _maps.count() - 1));
|
_zooms.append(Zoom(0, _maps.count() - 1));
|
||||||
for (int i = 1; i < _maps.count(); i++) {
|
for (int i = 1; i < _maps.count(); i++) {
|
||||||
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds());
|
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds());
|
||||||
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
|
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
|
||||||
if (cur < last * ZOOM_THRESHOLD) {
|
if (cur < last * ZOOM_THRESHOLD) {
|
||||||
_zooms.last().second = i-1;
|
_zooms.last().last = i-1;
|
||||||
_zooms.append(QPair<int, int>(i, _maps.count() - 1));
|
_zooms.append(Zoom(i, _maps.count() - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ void Atlas::computeBounds()
|
|||||||
|
|
||||||
for (int z = 0; z < _zooms.count(); z++) {
|
for (int z = 0; z < _zooms.count(); z++) {
|
||||||
QList<OfflineMap*> m;
|
QList<OfflineMap*> m;
|
||||||
for (int i = _zooms.at(z).first; i <= _zooms.at(z).second; i++)
|
for (int i = _zooms.at(z).first; i <= _zooms.at(z).last; i++)
|
||||||
m.append(_maps.at(i));
|
m.append(_maps.at(i));
|
||||||
|
|
||||||
qSort(m.begin(), m.end(), xCmp);
|
qSort(m.begin(), m.end(), xCmp);
|
||||||
@ -75,9 +75,8 @@ void Atlas::computeBounds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _maps.count(); i++)
|
for (int i = 0; i < _maps.count(); i++)
|
||||||
_bounds.append(QPair<QRectF, QRectF>(QRectF(TL(_maps.at(i)).toPointF(),
|
_bounds.append(Bounds(RectD(TL(_maps.at(i)), BR(_maps.at(i))),
|
||||||
BR(_maps.at(i)).toPointF()), QRectF(offsets.at(i),
|
QRectF(offsets.at(i), _maps.at(i)->bounds().size())));
|
||||||
_maps.at(i)->bounds().size())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Atlas::Atlas(const QString &fileName, QObject *parent)
|
Atlas::Atlas(const QString &fileName, QObject *parent)
|
||||||
@ -148,35 +147,20 @@ Atlas::Atlas(const QString &fileName, QObject *parent)
|
|||||||
_valid = true;
|
_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF Atlas::bounds() const
|
QRectF Atlas::bounds()
|
||||||
{
|
{
|
||||||
QSizeF s(0, 0);
|
QSizeF s(0, 0);
|
||||||
|
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
if (_bounds.at(i).second.right() > s.width())
|
if (_bounds.at(i).xy.right() > s.width())
|
||||||
s.setWidth(_bounds.at(i).second.right());
|
s.setWidth(_bounds.at(i).xy.right());
|
||||||
if (_bounds.at(i).second.bottom() > s.height())
|
if (_bounds.at(i).xy.bottom() > s.height())
|
||||||
s.setHeight(_bounds.at(i).second.bottom());
|
s.setHeight(_bounds.at(i).xy.bottom());
|
||||||
}
|
}
|
||||||
|
|
||||||
return QRectF(QPointF(0, 0), s);
|
return QRectF(QPointF(0, 0), s);
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal Atlas::resolution(const QRectF &rect) const
|
|
||||||
{
|
|
||||||
int idx = _zooms.at(_zoom).first;
|
|
||||||
|
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
|
||||||
if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(rect.center())
|
|
||||||
.toPointF())) {
|
|
||||||
idx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _maps.at(idx)->resolution(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Atlas::zoomFit(const QSize &size, const RectC &br)
|
int Atlas::zoomFit(const QSize &size, const RectC &br)
|
||||||
{
|
{
|
||||||
_zoom = 0;
|
_zoom = 0;
|
||||||
@ -188,9 +172,8 @@ int Atlas::zoomFit(const QSize &size, const RectC &br)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int z = 0; z < _zooms.count(); z++) {
|
for (int z = 0; z < _zooms.count(); z++) {
|
||||||
for (int i = _zooms.at(z).first; i <= _zooms.at(z).second; i++) {
|
for (int i = _zooms.at(z).first; i <= _zooms.at(z).last; i++) {
|
||||||
if (!_bounds.at(i).first.contains(_maps.at(i)->ll2pp(br.center())
|
if (!_bounds.at(i).pp.contains(_maps.at(i)->ll2pp(br.center())))
|
||||||
.toPointF()))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QRect sbr = QRectF(_maps.at(i)->ll2xy(br.topLeft()),
|
QRect sbr = QRectF(_maps.at(i)->ll2xy(br.topLeft()),
|
||||||
@ -208,6 +191,12 @@ int Atlas::zoomFit(const QSize &size, const RectC &br)
|
|||||||
return _zoom;
|
return _zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Atlas::setZoom(int zoom)
|
||||||
|
{
|
||||||
|
_mapIndex = -1;
|
||||||
|
_zoom = zoom;
|
||||||
|
}
|
||||||
|
|
||||||
int Atlas::zoomIn()
|
int Atlas::zoomIn()
|
||||||
{
|
{
|
||||||
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
|
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
|
||||||
@ -226,15 +215,15 @@ int Atlas::zoomOut()
|
|||||||
|
|
||||||
QPointF Atlas::ll2xy(const Coordinates &c)
|
QPointF Atlas::ll2xy(const Coordinates &c)
|
||||||
{
|
{
|
||||||
QPointF pp;
|
PointD pp;
|
||||||
|
|
||||||
if (_mapIndex >= 0)
|
if (_mapIndex >= 0)
|
||||||
pp = _maps.at(_mapIndex)->ll2pp(c).toPointF();
|
pp = _maps.at(_mapIndex)->ll2pp(c);
|
||||||
if (_mapIndex < 0 || !_bounds.at(_mapIndex).first.contains(pp)) {
|
if (_mapIndex < 0 || !_bounds.at(_mapIndex).pp.contains(pp)) {
|
||||||
_mapIndex = _zooms.at(_zoom).first;
|
_mapIndex = _zooms.at(_zoom).first;
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
pp = _maps.at(i)->ll2pp(c).toPointF();
|
pp = _maps.at(i)->ll2pp(c);
|
||||||
if (_bounds.at(i).first.contains(pp)) {
|
if (_bounds.at(i).pp.contains(pp)) {
|
||||||
_mapIndex = i;
|
_mapIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -242,38 +231,39 @@ QPointF Atlas::ll2xy(const Coordinates &c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPointF p = _maps.at(_mapIndex)->pp2xy(pp);
|
QPointF p = _maps.at(_mapIndex)->pp2xy(pp);
|
||||||
return p + _bounds.at(_mapIndex).second.topLeft();
|
return p + _bounds.at(_mapIndex).xy.topLeft();
|
||||||
}
|
}
|
||||||
|
|
||||||
Coordinates Atlas::xy2ll(const QPointF &p)
|
Coordinates Atlas::xy2ll(const QPointF &p)
|
||||||
{
|
{
|
||||||
int idx = _zooms.at(_zoom).first;
|
int idx = _zooms.at(_zoom).first;
|
||||||
|
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
if (_bounds.at(i).second.contains(_maps.at(i)->xy2pp(p).toPointF())) {
|
if (_bounds.at(i).xy.contains(p)) {
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF p2 = p - _bounds.at(idx).second.topLeft();
|
QPointF p2 = p - _bounds.at(idx).xy.topLeft();
|
||||||
return _maps.at(idx)->xy2ll(p2);
|
return _maps.at(idx)->xy2ll(p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Atlas::draw(QPainter *painter, const QRectF &rect)
|
void Atlas::draw(QPainter *painter, const QRectF &rect, bool block)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(block);
|
||||||
|
|
||||||
// All in one map
|
// All in one map
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
if (_bounds.at(i).second.contains(rect)) {
|
if (_bounds.at(i).xy.contains(rect)) {
|
||||||
draw(painter, rect, i);
|
draw(painter, rect, i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiple maps
|
// Multiple maps
|
||||||
painter->fillRect(rect, _backgroundColor);
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).second; i++) {
|
QRectF ir = rect.intersected(_bounds.at(i).xy);
|
||||||
QRectF ir = rect.intersected(_bounds.at(i).second);
|
|
||||||
if (!ir.isNull())
|
if (!ir.isNull())
|
||||||
draw(painter, ir, i);
|
draw(painter, ir, i);
|
||||||
}
|
}
|
||||||
@ -282,13 +272,13 @@ void Atlas::draw(QPainter *painter, const QRectF &rect)
|
|||||||
void Atlas::draw(QPainter *painter, const QRectF &rect, int mapIndex)
|
void Atlas::draw(QPainter *painter, const QRectF &rect, int mapIndex)
|
||||||
{
|
{
|
||||||
OfflineMap *map = _maps.at(mapIndex);
|
OfflineMap *map = _maps.at(mapIndex);
|
||||||
const QPointF offset = _bounds.at(mapIndex).second.topLeft();
|
const QPointF offset = _bounds.at(mapIndex).xy.topLeft();
|
||||||
QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
|
QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
|
||||||
|
|
||||||
map->load();
|
map->load();
|
||||||
|
|
||||||
painter->translate(offset);
|
painter->translate(offset);
|
||||||
map->draw(painter, pr);
|
map->draw(painter, pr, true);
|
||||||
painter->translate(-offset);
|
painter->translate(-offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define ATLAS_H
|
#define ATLAS_H
|
||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "rectd.h"
|
||||||
|
|
||||||
class OfflineMap;
|
class OfflineMap;
|
||||||
|
|
||||||
@ -12,12 +13,12 @@ class Atlas : public Map
|
|||||||
public:
|
public:
|
||||||
Atlas(const QString &fileName, QObject *parent = 0);
|
Atlas(const QString &fileName, QObject *parent = 0);
|
||||||
|
|
||||||
const QString &name() const {return _name;}
|
QString name() const {return _name;}
|
||||||
|
|
||||||
QRectF bounds() const;
|
QRectF bounds();
|
||||||
qreal resolution(const QRectF &rect) const;
|
|
||||||
|
|
||||||
int zoom() const {return _zoom;}
|
int zoom() const {return _zoom;}
|
||||||
|
void setZoom(int zoom);
|
||||||
int zoomFit(const QSize &size, const RectC &br);
|
int zoomFit(const QSize &size, const RectC &br);
|
||||||
int zoomIn();
|
int zoomIn();
|
||||||
int zoomOut();
|
int zoomOut();
|
||||||
@ -25,7 +26,7 @@ public:
|
|||||||
QPointF ll2xy(const Coordinates &c);
|
QPointF ll2xy(const Coordinates &c);
|
||||||
Coordinates xy2ll(const QPointF &p);
|
Coordinates xy2ll(const QPointF &p);
|
||||||
|
|
||||||
void draw(QPainter *painter, const QRectF &rect);
|
void draw(QPainter *painter, const QRectF &rect, bool block);
|
||||||
|
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
@ -35,6 +36,22 @@ public:
|
|||||||
static bool isAtlas(const QString &path);
|
static bool isAtlas(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Zoom {
|
||||||
|
int first;
|
||||||
|
int last;
|
||||||
|
|
||||||
|
Zoom() : first(-1), last(-1) {}
|
||||||
|
Zoom(int first, int last) : first(first), last(last) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Bounds {
|
||||||
|
RectD pp;
|
||||||
|
QRectF xy;
|
||||||
|
|
||||||
|
Bounds() {}
|
||||||
|
Bounds(const RectD &pp, const QRectF &xy) : pp(pp), xy(xy) {}
|
||||||
|
};
|
||||||
|
|
||||||
void draw(QPainter *painter, const QRectF &rect, int mapIndex);
|
void draw(QPainter *painter, const QRectF &rect, int mapIndex);
|
||||||
void computeZooms();
|
void computeZooms();
|
||||||
void computeBounds();
|
void computeBounds();
|
||||||
@ -42,8 +59,8 @@ private:
|
|||||||
QString _name;
|
QString _name;
|
||||||
|
|
||||||
QList<OfflineMap*> _maps;
|
QList<OfflineMap*> _maps;
|
||||||
QVector<QPair<int, int> > _zooms;
|
QVector<Zoom> _zooms;
|
||||||
QVector<QPair<QRectF, QRectF> > _bounds;
|
QVector<Bounds> _bounds;
|
||||||
int _zoom;
|
int _zoom;
|
||||||
int _mapIndex;
|
int _mapIndex;
|
||||||
|
|
||||||
|
@ -7,6 +7,9 @@ CoordinateSystem::CoordinateSystem(int code)
|
|||||||
case 1035:
|
case 1035:
|
||||||
case 1039:
|
case 1039:
|
||||||
case 4400:
|
case 4400:
|
||||||
|
case 4402:
|
||||||
|
case 4404:
|
||||||
|
case 4405:
|
||||||
case 4409:
|
case 4409:
|
||||||
case 4463:
|
case 4463:
|
||||||
case 4464:
|
case 4464:
|
||||||
@ -26,6 +29,7 @@ CoordinateSystem::CoordinateSystem(int code)
|
|||||||
case 4530:
|
case 4530:
|
||||||
case 4531:
|
case 4531:
|
||||||
case 4532:
|
case 4532:
|
||||||
|
case 6501:
|
||||||
_axisOrder = YX;
|
_axisOrder = YX;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -12,6 +12,7 @@ public:
|
|||||||
CoordinateSystem(AxisOrder axisOrder) : _axisOrder(axisOrder) {}
|
CoordinateSystem(AxisOrder axisOrder) : _axisOrder(axisOrder) {}
|
||||||
CoordinateSystem(int code);
|
CoordinateSystem(int code);
|
||||||
|
|
||||||
|
bool isNull() const {return (_axisOrder == Unknown);}
|
||||||
bool isValid() const {return (_axisOrder != Unknown);}
|
bool isValid() const {return (_axisOrder != Unknown);}
|
||||||
|
|
||||||
AxisOrder axisOrder() const {return _axisOrder;}
|
AxisOrder axisOrder() const {return _axisOrder;}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <cmath>
|
|
||||||
#include "common/wgs84.h"
|
#include "common/wgs84.h"
|
||||||
#include "datum.h"
|
#include "datum.h"
|
||||||
|
|
||||||
static Ellipsoid WGS84e = Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING);
|
|
||||||
static Datum WGS84 = Datum(&WGS84e, 0.0, 0.0, 0.0);
|
|
||||||
|
|
||||||
// Abridged Molodensky transformation
|
#define as2rad(x) ((x) * (M_PI/648000.0))
|
||||||
|
#define rad2as(x) ((x) * (648000.0/M_PI))
|
||||||
|
#define ds2scale(x) (1.0 + (x) * 1e-6)
|
||||||
|
#define scale2ds(x) (((x) - 1.0) / 1e-6)
|
||||||
|
|
||||||
static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
||||||
const Datum &to)
|
const Datum &to)
|
||||||
{
|
{
|
||||||
@ -32,40 +33,96 @@ static Coordinates molodensky(const Coordinates &c, const Datum &from,
|
|||||||
double adb = 1.0 / (1.0 - from_f);
|
double adb = 1.0 / (1.0 - from_f);
|
||||||
double rn = from_a / sqrt(1 - from_esq * ssqlat);
|
double rn = from_a / sqrt(1 - from_esq * ssqlat);
|
||||||
double rm = from_a * (1 - from_esq) / pow((1 - from_esq * ssqlat), 1.5);
|
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
|
* rn * from_esq * slat * clat / from_a + df * (rm * adb + rn / adb) * slat
|
||||||
* clat) / (rm + from_h);
|
* clat) / rm;
|
||||||
|
|
||||||
double dlon = (-dx * slon + dy * clon) / ((rn + from_h) * clat);
|
double dlon = (-dx * slon + dy * clon) / (rn * clat);
|
||||||
|
|
||||||
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
|
return Coordinates(c.lon() + rad2deg(dlon), c.lat() + rad2deg(dlat));
|
||||||
}
|
}
|
||||||
|
|
||||||
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
|
const Datum &Datum::WGS84()
|
||||||
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz)
|
|
||||||
{
|
{
|
||||||
_WGS84 = (_ellipsoid->radius() == WGS84_RADIUS
|
static Datum d(&Ellipsoid::WGS84(), 0.0, 0.0, 0.0);
|
||||||
&& _ellipsoid->flattening() == WGS84_FLATTENING && _dx == 0.0
|
return d;
|
||||||
&& _dy == 0.0 && _dz == 0.0) ? true : false;
|
}
|
||||||
|
|
||||||
|
Point3D Datum::helmert(const Point3D &p) const
|
||||||
|
{
|
||||||
|
return Point3D(_scale * (p.x() + _rz * p.y() -_ry * p.z()) + _dx,
|
||||||
|
_scale * (-_rz * p.x() + p.y() + _rx * p.z()) + _dy,
|
||||||
|
_scale * (_ry * p.x() -_rx * p.y() + p.z()) + _dz);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point3D Datum::helmertr(const Point3D &p) const
|
||||||
|
{
|
||||||
|
double x = (p.x() - _dx) / _scale;
|
||||||
|
double y = (p.y() - _dy) / _scale;
|
||||||
|
double z = (p.z() - _dz) / _scale;
|
||||||
|
|
||||||
|
return Point3D(x -_rz * y + _ry * z, _rz * x + y + -_rx * z, -_ry * x + _rx
|
||||||
|
* y + z);
|
||||||
|
}
|
||||||
|
|
||||||
|
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
||||||
|
double rx, double ry, double rz, double ds)
|
||||||
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(as2rad(rx)),
|
||||||
|
_ry(as2rad(ry)), _rz(as2rad(rz)), _scale(ds2scale(ds))
|
||||||
|
{
|
||||||
|
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
||||||
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0
|
||||||
|
&& _rx == 0.0 && _ry == 0.0 && _rz == 0.0 && ds == 0.0)
|
||||||
|
_transformation = None;
|
||||||
|
else
|
||||||
|
_transformation = Helmert;
|
||||||
|
}
|
||||||
|
|
||||||
|
Datum::Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz)
|
||||||
|
: _ellipsoid(ellipsoid), _dx(dx), _dy(dy), _dz(dz), _rx(0.0), _ry(0.0),
|
||||||
|
_rz(0.0), _scale(1.0)
|
||||||
|
{
|
||||||
|
if (_ellipsoid->radius() == WGS84_RADIUS && _ellipsoid->flattening()
|
||||||
|
== WGS84_FLATTENING && _dx == 0.0 && _dy == 0.0 && _dz == 0.0)
|
||||||
|
_transformation = None;
|
||||||
|
else
|
||||||
|
_transformation = Molodensky;
|
||||||
}
|
}
|
||||||
|
|
||||||
Coordinates Datum::toWGS84(const Coordinates &c) const
|
Coordinates Datum::toWGS84(const Coordinates &c) const
|
||||||
{
|
{
|
||||||
return _WGS84 ? c : molodensky(c, *this, WGS84);
|
switch (_transformation) {
|
||||||
|
case Helmert:
|
||||||
|
return Geocentric::toGeodetic(helmert(Geocentric::fromGeodetic(c,
|
||||||
|
ellipsoid())), WGS84().ellipsoid());
|
||||||
|
case Molodensky:
|
||||||
|
return molodensky(c, *this, WGS84());
|
||||||
|
default:
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Coordinates Datum::fromWGS84(const Coordinates &c) const
|
Coordinates Datum::fromWGS84(const Coordinates &c) const
|
||||||
{
|
{
|
||||||
return _WGS84 ? c : molodensky(c, WGS84, *this);
|
switch (_transformation) {
|
||||||
|
case Helmert:
|
||||||
|
return Geocentric::toGeodetic(helmertr(Geocentric::fromGeodetic(c,
|
||||||
|
WGS84().ellipsoid())), ellipsoid());
|
||||||
|
case Molodensky:
|
||||||
|
return molodensky(c, WGS84(), *this);
|
||||||
|
default:
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const Datum &datum)
|
QDebug operator<<(QDebug dbg, const Datum &datum)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
|
dbg.nospace() << "Datum(" << *datum.ellipsoid() << ", " << datum.dx()
|
||||||
<< ", " << datum.dy() << ", " << datum.dz() << ")";
|
<< ", " << datum.dy() << ", " << datum.dz() << ", " << rad2as(datum.rx())
|
||||||
|
<< ", " << rad2as(datum.ry()) << ", " << rad2as(datum.rz()) << ", "
|
||||||
|
<< scale2ds(datum.scale()) << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -2,42 +2,60 @@
|
|||||||
#define DATUM_H
|
#define DATUM_H
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QList>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "ellipsoid.h"
|
|
||||||
#include "common/coordinates.h"
|
#include "common/coordinates.h"
|
||||||
|
#include "ellipsoid.h"
|
||||||
|
#include "geocentric.h"
|
||||||
|
|
||||||
class Datum
|
class Datum
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Datum() : _ellipsoid(0), _dx(NAN), _dy(NAN), _dz(NAN),
|
Datum() : _ellipsoid(0), _transformation(None), _dx(NAN), _dy(NAN),
|
||||||
_WGS84(false) {}
|
_dz(NAN), _rx(NAN), _ry(NAN), _rz(NAN), _scale(NAN) {}
|
||||||
|
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz,
|
||||||
|
double rx, double ry, double rz, double ds);
|
||||||
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz);
|
Datum(const Ellipsoid *ellipsoid, double dx, double dy, double dz);
|
||||||
|
|
||||||
const Ellipsoid *ellipsoid() const {return _ellipsoid;}
|
const Ellipsoid *ellipsoid() const {return _ellipsoid;}
|
||||||
double dx() const {return _dx;}
|
double dx() const {return _dx;}
|
||||||
double dy() const {return _dy;}
|
double dy() const {return _dy;}
|
||||||
double dz() const {return _dz;}
|
double dz() const {return _dz;}
|
||||||
|
double rx() const {return _rx;}
|
||||||
|
double ry() const {return _ry;}
|
||||||
|
double rz() const {return _rz;}
|
||||||
|
double scale() const {return _scale;}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{return (!_ellipsoid && std::isnan(_dx) && std::isnan(_dy)
|
{return !_ellipsoid;}
|
||||||
&& std::isnan(_dz));}
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{return (_ellipsoid && !std::isnan(_dx) && !std::isnan(_dy)
|
{return (_ellipsoid && !std::isnan(_dx) && !std::isnan(_dy)
|
||||||
&& !std::isnan(_dz));}
|
&& !std::isnan(_dz) && !std::isnan(_scale) && !std::isnan(_rx)
|
||||||
|
&& !std::isnan(_ry) && !std::isnan(_rz));}
|
||||||
|
|
||||||
Coordinates toWGS84(const Coordinates &c) const;
|
Coordinates toWGS84(const Coordinates &c) const;
|
||||||
Coordinates fromWGS84(const Coordinates &c) const;
|
Coordinates fromWGS84(const Coordinates &c) const;
|
||||||
|
|
||||||
|
static const Datum &WGS84();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum TransformationType {
|
||||||
|
None,
|
||||||
|
Molodensky,
|
||||||
|
Helmert
|
||||||
|
};
|
||||||
|
|
||||||
|
Point3D helmert(const Point3D &p) const;
|
||||||
|
Point3D helmertr(const Point3D &p) const;
|
||||||
|
|
||||||
const Ellipsoid *_ellipsoid;
|
const Ellipsoid *_ellipsoid;
|
||||||
double _dx, _dy, _dz;
|
TransformationType _transformation;
|
||||||
bool _WGS84;
|
double _dx, _dy, _dz, _rx, _ry, _rz, _scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const Datum &d1, const Datum &d2)
|
inline bool operator==(const Datum &d1, const Datum &d2)
|
||||||
{return (d1.ellipsoid() == d2.ellipsoid() && d1.dx() == d2.dx()
|
{return (*d1.ellipsoid() == *d2.ellipsoid() && d1.dx() == d2.dx()
|
||||||
&& d1.dy() == d2.dy() && d1.dz() == d2.dz());}
|
&& d1.dy() == d2.dy() && d1.dz() == d2.dz() && d1.rx() == d2.rx()
|
||||||
|
&& d1.ry() == d2.ry() && d1.rz() == d2.rz() && d1.scale() == d2.scale());}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const Datum &datum);
|
QDebug operator<<(QDebug dbg, const Datum &datum);
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QNetworkReply>
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include "config.h"
|
|
||||||
#include "downloader.h"
|
#include "downloader.h"
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +24,7 @@
|
|||||||
#define ATTR_LEVEL (QNetworkRequest::Attribute)(QNetworkRequest::User + 2)
|
#define ATTR_LEVEL (QNetworkRequest::Attribute)(QNetworkRequest::User + 2)
|
||||||
|
|
||||||
#define MAX_REDIRECT_LEVEL 5
|
#define MAX_REDIRECT_LEVEL 5
|
||||||
#define TIMEOUT 30 /* s */
|
#define RETRIES 3
|
||||||
|
|
||||||
|
|
||||||
Authorization::Authorization(const QString &username, const QString &password)
|
Authorization::Authorization(const QString &username, const QString &password)
|
||||||
@ -80,11 +78,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Downloader::Downloader(QObject *parent) : QObject(parent)
|
QNetworkAccessManager *Downloader::_manager = 0;
|
||||||
{
|
int Downloader::_timeout = 30;
|
||||||
connect(&_manager, SIGNAL(finished(QNetworkReply*)),
|
#ifdef ENABLE_HTTP2
|
||||||
SLOT(downloadFinished(QNetworkReply*)));
|
bool Downloader::_http2 = true;
|
||||||
}
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
bool Downloader::doDownload(const Download &dl,
|
bool Downloader::doDownload(const Download &dl,
|
||||||
const QByteArray &authorization, const Redirect *redirect)
|
const QByteArray &authorization, const Redirect *redirect)
|
||||||
@ -93,10 +91,12 @@ bool Downloader::doDownload(const Download &dl,
|
|||||||
|
|
||||||
if (!url.isValid() || !(url.scheme() == "http" || url.scheme() == "https")) {
|
if (!url.isValid() || !(url.scheme() == "http" || url.scheme() == "https")) {
|
||||||
qWarning("%s: Invalid URL\n", qPrintable(url.toString()));
|
qWarning("%s: Invalid URL\n", qPrintable(url.toString()));
|
||||||
|
if (redirect)
|
||||||
|
_errorDownloads.insert(redirect->origin(), RETRIES);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_errorDownloads.contains(url))
|
if (_errorDownloads.value(url) >= RETRIES)
|
||||||
return false;
|
return false;
|
||||||
if (_currentDownloads.contains(url) && !redirect)
|
if (_currentDownloads.contains(url) && !redirect)
|
||||||
return false;
|
return false;
|
||||||
@ -110,11 +110,16 @@ bool Downloader::doDownload(const Download &dl,
|
|||||||
request.setRawHeader("User-Agent", USER_AGENT);
|
request.setRawHeader("User-Agent", USER_AGENT);
|
||||||
if (!authorization.isNull())
|
if (!authorization.isNull())
|
||||||
request.setRawHeader("Authorization", authorization);
|
request.setRawHeader("Authorization", authorization);
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute,
|
||||||
|
QVariant(_http2));
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
|
||||||
QNetworkReply *reply = _manager.get(request);
|
QNetworkReply *reply = _manager->get(request);
|
||||||
if (reply && reply->isRunning()) {
|
if (reply && reply->isRunning()) {
|
||||||
_currentDownloads.insert(url);
|
_currentDownloads.insert(url);
|
||||||
ReplyTimeout::setTimeout(reply, TIMEOUT);
|
ReplyTimeout::setTimeout(reply, _timeout);
|
||||||
|
connect(reply, SIGNAL(finished()), this, SLOT(emitFinished()));
|
||||||
} else if (reply)
|
} else if (reply)
|
||||||
downloadFinished(reply);
|
downloadFinished(reply);
|
||||||
else
|
else
|
||||||
@ -123,6 +128,11 @@ bool Downloader::doDownload(const Download &dl,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downloader::emitFinished()
|
||||||
|
{
|
||||||
|
downloadFinished(static_cast<QNetworkReply*>(sender()));
|
||||||
|
}
|
||||||
|
|
||||||
bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
|
bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
|
||||||
{
|
{
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
@ -139,18 +149,27 @@ bool Downloader::saveToDisk(const QString &filename, QIODevice *data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Downloader::insertError(const QUrl &url, QNetworkReply::NetworkError error)
|
||||||
|
{
|
||||||
|
if (error == QNetworkReply::OperationCanceledError)
|
||||||
|
_errorDownloads.insert(url, _errorDownloads.value(url) + 1);
|
||||||
|
else
|
||||||
|
_errorDownloads.insert(url, RETRIES);
|
||||||
|
}
|
||||||
|
|
||||||
void Downloader::downloadFinished(QNetworkReply *reply)
|
void Downloader::downloadFinished(QNetworkReply *reply)
|
||||||
{
|
{
|
||||||
QUrl url = reply->request().url();
|
QUrl url = reply->request().url();
|
||||||
|
QNetworkReply::NetworkError error = reply->error();
|
||||||
|
|
||||||
if (reply->error()) {
|
if (error) {
|
||||||
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
|
QUrl origin = reply->request().attribute(ATTR_ORIGIN).toUrl();
|
||||||
if (origin.isEmpty()) {
|
if (origin.isEmpty()) {
|
||||||
_errorDownloads.insert(url);
|
insertError(url, error);
|
||||||
qWarning("Error downloading file: %s: %s\n",
|
qWarning("Error downloading file: %s: %s\n",
|
||||||
url.toEncoded().constData(), qPrintable(reply->errorString()));
|
url.toEncoded().constData(), qPrintable(reply->errorString()));
|
||||||
} else {
|
} else {
|
||||||
_errorDownloads.insert(origin);
|
insertError(origin, error);
|
||||||
qWarning("Error downloading file: %s -> %s: %s\n",
|
qWarning("Error downloading file: %s -> %s: %s\n",
|
||||||
origin.toEncoded().constData(), url.toEncoded().constData(),
|
origin.toEncoded().constData(), url.toEncoded().constData(),
|
||||||
qPrintable(reply->errorString()));
|
qPrintable(reply->errorString()));
|
||||||
@ -165,7 +184,7 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
|||||||
int level = reply->request().attribute(ATTR_LEVEL).toInt();
|
int level = reply->request().attribute(ATTR_LEVEL).toInt();
|
||||||
|
|
||||||
if (level >= MAX_REDIRECT_LEVEL) {
|
if (level >= MAX_REDIRECT_LEVEL) {
|
||||||
_errorDownloads.insert(origin);
|
_errorDownloads.insert(origin, RETRIES);
|
||||||
qWarning("Error downloading file: %s: "
|
qWarning("Error downloading file: %s: "
|
||||||
"redirect level limit reached (redirect loop?)\n",
|
"redirect level limit reached (redirect loop?)\n",
|
||||||
origin.toEncoded().constData());
|
origin.toEncoded().constData());
|
||||||
@ -180,13 +199,13 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
|||||||
|
|
||||||
Redirect redirect(origin.isEmpty() ? url : origin, level + 1);
|
Redirect redirect(origin.isEmpty() ? url : origin, level + 1);
|
||||||
Download dl(redirectUrl, filename);
|
Download dl(redirectUrl, filename);
|
||||||
if (!doDownload(dl, reply->request().rawHeader("Authorization"),
|
doDownload(dl, reply->request().rawHeader("Authorization"),
|
||||||
&redirect))
|
&redirect);
|
||||||
_errorDownloads.insert(origin.isEmpty() ? url : origin);
|
|
||||||
}
|
}
|
||||||
} else
|
} else {
|
||||||
if (!saveToDisk(filename, reply))
|
if (!saveToDisk(filename, reply))
|
||||||
_errorDownloads.insert(url);
|
_errorDownloads.insert(url, RETRIES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentDownloads.remove(url);
|
_currentDownloads.remove(url);
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#ifndef DOWNLOADER_H
|
#ifndef DOWNLOADER_H
|
||||||
#define DOWNLOADER_H
|
#define DOWNLOADER_H
|
||||||
|
|
||||||
#include <QNetworkAccessManager>
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
#include <QHash>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
class QNetworkReply;
|
|
||||||
|
|
||||||
class Download
|
class Download
|
||||||
{
|
{
|
||||||
@ -38,29 +40,43 @@ class Downloader : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Downloader(QObject *parent = 0);
|
Downloader(QObject *parent = 0) : QObject(parent) {}
|
||||||
|
|
||||||
bool get(const QList<Download> &list, const Authorization &authorization
|
bool get(const QList<Download> &list, const Authorization &authorization
|
||||||
= Authorization());
|
= Authorization());
|
||||||
void clearErrors() {_errorDownloads.clear();}
|
void clearErrors() {_errorDownloads.clear();}
|
||||||
|
|
||||||
|
static void setTimeout(int timeout) {_timeout = timeout;}
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
static void enableHTTP2(bool enable) {_http2 = enable;}
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
static void setNetworkAccessManager(QNetworkAccessManager *manager)
|
||||||
|
{_manager = manager;}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void finished();
|
void finished();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void emitFinished();
|
||||||
void downloadFinished(QNetworkReply *reply);
|
void downloadFinished(QNetworkReply *reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Redirect;
|
class Redirect;
|
||||||
class ReplyTimeout;
|
class ReplyTimeout;
|
||||||
|
|
||||||
|
void insertError(const QUrl &url, QNetworkReply::NetworkError error);
|
||||||
bool doDownload(const Download &dl, const QByteArray &authorization,
|
bool doDownload(const Download &dl, const QByteArray &authorization,
|
||||||
const Redirect *redirect = 0);
|
const Redirect *redirect = 0);
|
||||||
bool saveToDisk(const QString &filename, QIODevice *data);
|
bool saveToDisk(const QString &filename, QIODevice *data);
|
||||||
|
|
||||||
QNetworkAccessManager _manager;
|
|
||||||
QSet<QUrl> _currentDownloads;
|
QSet<QUrl> _currentDownloads;
|
||||||
QSet<QUrl> _errorDownloads;
|
QHash<QUrl, int> _errorDownloads;
|
||||||
|
|
||||||
|
static int _timeout;
|
||||||
|
#ifdef ENABLE_HTTP2
|
||||||
|
static bool _http2;
|
||||||
|
#endif // ENABLE_HTTP2
|
||||||
|
static QNetworkAccessManager *_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DOWNLOADER_H
|
#endif // DOWNLOADER_H
|
||||||
|
@ -3,12 +3,18 @@
|
|||||||
#include "common/wgs84.h"
|
#include "common/wgs84.h"
|
||||||
#include "ellipsoid.h"
|
#include "ellipsoid.h"
|
||||||
|
|
||||||
QMap<int, Ellipsoid> Ellipsoid::_ellipsoids = WGS84();
|
QMap<int, Ellipsoid> Ellipsoid::_ellipsoids = defaults();
|
||||||
|
|
||||||
QMap<int, Ellipsoid> Ellipsoid::WGS84()
|
const Ellipsoid &Ellipsoid::WGS84()
|
||||||
|
{
|
||||||
|
static Ellipsoid e(WGS84_RADIUS, WGS84_FLATTENING);
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<int, Ellipsoid> Ellipsoid::defaults()
|
||||||
{
|
{
|
||||||
QMap<int, Ellipsoid> map;
|
QMap<int, Ellipsoid> map;
|
||||||
map.insert(7030, Ellipsoid(WGS84_RADIUS, WGS84_FLATTENING));
|
map.insert(7030, WGS84());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +72,14 @@ void Ellipsoid::loadList(const QString &path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ellipsoid::Ellipsoid(double radius, double flattening)
|
||||||
|
: _radius(radius), _flattening(flattening)
|
||||||
|
{
|
||||||
|
_es = 2.0 * flattening - flattening * flattening;
|
||||||
|
_e2s = (1.0 / (1.0 - _es)) - 1.0;
|
||||||
|
_b = radius * (1.0 - flattening);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid)
|
QDebug operator<<(QDebug dbg, const Ellipsoid &ellipsoid)
|
||||||
{
|
{
|
||||||
|
@ -9,26 +9,30 @@
|
|||||||
class Ellipsoid
|
class Ellipsoid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Ellipsoid() : _radius(NAN), _flattening(NAN) {}
|
Ellipsoid() : _radius(NAN), _flattening(NAN), _es(NAN), _b(NAN) {}
|
||||||
Ellipsoid(double radius, double flattening)
|
Ellipsoid(double radius, double flattening);
|
||||||
: _radius(radius), _flattening(flattening) {}
|
|
||||||
|
|
||||||
double radius() const {return _radius;}
|
double radius() const {return _radius;}
|
||||||
double flattening() const {return _flattening;}
|
double flattening() const {return _flattening;}
|
||||||
|
double es() const {return _es;}
|
||||||
|
double e2s() const {return _e2s;}
|
||||||
|
double b() const {return _b;}
|
||||||
|
|
||||||
bool isNull() const
|
bool isNull() const
|
||||||
{return (std::isnan(_radius) && std::isnan(_flattening));}
|
{return (std::isnan(_radius) && std::isnan(_flattening));}
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{return !(std::isnan(_radius) || std::isnan(_flattening));}
|
{return !(std::isnan(_radius) || std::isnan(_flattening));}
|
||||||
|
|
||||||
|
static const Ellipsoid &WGS84();
|
||||||
static const Ellipsoid *ellipsoid(int id);
|
static const Ellipsoid *ellipsoid(int id);
|
||||||
static void loadList(const QString &path);
|
static void loadList(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double _radius;
|
double _radius;
|
||||||
double _flattening;
|
double _flattening;
|
||||||
|
double _es, _e2s, _b;
|
||||||
|
|
||||||
static QMap<int, Ellipsoid> WGS84();
|
static QMap<int, Ellipsoid> defaults();
|
||||||
static QMap<int, Ellipsoid> _ellipsoids;
|
static QMap<int, Ellipsoid> _ellipsoids;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,12 +12,12 @@
|
|||||||
|
|
||||||
static QPointF ll2m(const Coordinates &c)
|
static QPointF ll2m(const Coordinates &c)
|
||||||
{
|
{
|
||||||
return QPointF(c.lon(), rad2deg(log(tan(M_PI/4.0 + deg2rad(c.lat())/2.0))));
|
return QPointF(c.lon(), rad2deg(log(tan(M_PI_4 + deg2rad(c.lat())/2.0))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Coordinates m2ll(const QPointF &p)
|
static Coordinates m2ll(const QPointF &p)
|
||||||
{
|
{
|
||||||
return Coordinates(p.x(), rad2deg(2 * atan(exp(deg2rad(p.y()))) - M_PI/2));
|
return Coordinates(p.x(), rad2deg(2.0 * atan(exp(deg2rad(p.y()))) - M_PI_2));
|
||||||
}
|
}
|
||||||
|
|
||||||
static qreal zoom2scale(int zoom)
|
static qreal zoom2scale(int zoom)
|
||||||
@ -46,7 +46,7 @@ EmptyMap::EmptyMap(QObject *parent) : Map(parent)
|
|||||||
_zoom = ZOOM_MAX;
|
_zoom = ZOOM_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF EmptyMap::bounds() const
|
QRectF EmptyMap::bounds()
|
||||||
{
|
{
|
||||||
return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85)));
|
return QRectF(ll2xy(Coordinates(-180, 85)), ll2xy(Coordinates(180, -85)));
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ int EmptyMap::zoomFit(const QSize &size, const RectC &rect)
|
|||||||
return _zoom;
|
return _zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal EmptyMap::resolution(const QRectF &rect) const
|
qreal EmptyMap::resolution(const QRectF &rect)
|
||||||
{
|
{
|
||||||
qreal scale = zoom2scale(_zoom);
|
qreal scale = zoom2scale(_zoom);
|
||||||
|
|
||||||
@ -85,19 +85,21 @@ int EmptyMap::zoomOut()
|
|||||||
return _zoom;
|
return _zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmptyMap::draw(QPainter *painter, const QRectF &rect)
|
void EmptyMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
||||||
{
|
{
|
||||||
painter->fillRect(rect, _backgroundColor);
|
Q_UNUSED(painter);
|
||||||
|
Q_UNUSED(rect);
|
||||||
|
Q_UNUSED(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF EmptyMap::ll2xy(const Coordinates &c) const
|
QPointF EmptyMap::ll2xy(const Coordinates &c)
|
||||||
{
|
{
|
||||||
qreal scale = zoom2scale(_zoom);
|
qreal scale = zoom2scale(_zoom);
|
||||||
QPointF m = ll2m(c);
|
QPointF m = ll2m(c);
|
||||||
return QPointF(m.x() / scale, m.y() / -scale);
|
return QPointF(m.x() / scale, m.y() / -scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
Coordinates EmptyMap::xy2ll(const QPointF &p) const
|
Coordinates EmptyMap::xy2ll(const QPointF &p)
|
||||||
{
|
{
|
||||||
qreal scale = zoom2scale(_zoom);
|
qreal scale = zoom2scale(_zoom);
|
||||||
return m2ll(QPointF(p.x() * scale, -p.y() * scale));
|
return m2ll(QPointF(p.x() * scale, -p.y() * scale));
|
||||||
|
@ -10,28 +10,23 @@ class EmptyMap : public Map
|
|||||||
public:
|
public:
|
||||||
EmptyMap(QObject *parent = 0);
|
EmptyMap(QObject *parent = 0);
|
||||||
|
|
||||||
const QString &name() const {return _name;}
|
QString name() const {return QString();}
|
||||||
|
|
||||||
QRectF bounds() const;
|
QRectF bounds();
|
||||||
qreal resolution(const QRectF &rect) const;
|
qreal resolution(const QRectF &rect);
|
||||||
|
|
||||||
int zoom() const {return _zoom;}
|
int zoom() const {return _zoom;}
|
||||||
|
void setZoom(int zoom) {_zoom = zoom;}
|
||||||
int zoomFit(const QSize &size, const RectC &rect);
|
int zoomFit(const QSize &size, const RectC &rect);
|
||||||
int zoomIn();
|
int zoomIn();
|
||||||
int zoomOut();
|
int zoomOut();
|
||||||
|
|
||||||
QPointF ll2xy(const Coordinates &c)
|
QPointF ll2xy(const Coordinates &c);
|
||||||
{return static_cast<const EmptyMap &>(*this).ll2xy(c);}
|
Coordinates xy2ll(const QPointF &p);
|
||||||
Coordinates xy2ll(const QPointF &p)
|
|
||||||
{return static_cast<const EmptyMap &>(*this).xy2ll(p);}
|
|
||||||
|
|
||||||
void draw(QPainter *painter, const QRectF &rect);
|
void draw(QPainter *painter, const QRectF &rect, bool block);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointF ll2xy(const Coordinates &c) const;
|
|
||||||
Coordinates xy2ll(const QPointF &p) const;
|
|
||||||
|
|
||||||
QString _name;
|
|
||||||
int _zoom;
|
int _zoom;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,9 +19,6 @@ private:
|
|||||||
GCS _gcs;
|
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)
|
static int parameter(const QString &str, bool *res)
|
||||||
{
|
{
|
||||||
QString field = str.trimmed();
|
QString field = str.trimmed();
|
||||||
@ -33,12 +30,30 @@ static int parameter(const QString &str, bool *res)
|
|||||||
return field.toInt(res);
|
return field.toInt(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<GCS::Entry> GCS::_gcss = WGS84();
|
static double parameterd(const QString &str, bool *res)
|
||||||
|
{
|
||||||
|
QString field = str.trimmed();
|
||||||
|
if (field.isEmpty()) {
|
||||||
|
*res = true;
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
QList<GCS::Entry> GCS::WGS84()
|
return field.toDouble(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList<GCS::Entry> GCS::_gcss = defaults();
|
||||||
|
|
||||||
|
const GCS &GCS::WGS84()
|
||||||
|
{
|
||||||
|
static GCS g(Datum::WGS84(), 8901, 9122);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<GCS::Entry> GCS::defaults()
|
||||||
{
|
{
|
||||||
QList<GCS::Entry> list;
|
QList<GCS::Entry> list;
|
||||||
list.append(GCS::Entry(4326, 6326, "WGS 84", GCS(WGS84d, 8901, 9122)));
|
list.append(GCS::Entry(4326, 6326, "WGS 84", WGS84()));
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +106,7 @@ void GCS::loadList(const QString &path)
|
|||||||
|
|
||||||
QByteArray line = file.readLine();
|
QByteArray line = file.readLine();
|
||||||
QList<QByteArray> list = line.split(',');
|
QList<QByteArray> list = line.split(',');
|
||||||
if (list.size() < 10) {
|
if (list.size() != 14) {
|
||||||
qWarning("%s:%d: Format error", qPrintable(path), ln);
|
qWarning("%s:%d: Format error", qPrintable(path), ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -145,6 +160,26 @@ void GCS::loadList(const QString &path)
|
|||||||
qWarning("%s:%d: Invalid dz", qPrintable(path), ln);
|
qWarning("%s:%d: Invalid dz", qPrintable(path), ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
double rx = parameterd(list[10], &res);
|
||||||
|
if (!res) {
|
||||||
|
qWarning("%s:%d: Invalid rx", qPrintable(path), ln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double ry = parameterd(list[11], &res);
|
||||||
|
if (!res) {
|
||||||
|
qWarning("%s:%d: Invalid ry", qPrintable(path), ln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double rz = parameterd(list[12], &res);
|
||||||
|
if (!res) {
|
||||||
|
qWarning("%s:%d: Invalid rz", qPrintable(path), ln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double ds = parameterd(list[13], &res);
|
||||||
|
if (!res) {
|
||||||
|
qWarning("%s:%d: Invalid ds", qPrintable(path), ln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(e = Ellipsoid::ellipsoid(el))) {
|
if (!(e = Ellipsoid::ellipsoid(el))) {
|
||||||
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
|
qWarning("%s:%d: Unknown ellipsoid code", qPrintable(path), ln);
|
||||||
@ -156,11 +191,22 @@ void GCS::loadList(const QString &path)
|
|||||||
case 9603:
|
case 9603:
|
||||||
datum = Datum(e, dx, dy, dz);
|
datum = Datum(e, dx, dy, dz);
|
||||||
break;
|
break;
|
||||||
|
case 9606:
|
||||||
|
datum = Datum(e, dx, dy, dz, -rx, -ry, -rz, ds);
|
||||||
|
break;
|
||||||
|
case 9607:
|
||||||
|
datum = Datum(e, dx, dy, dz, rx, ry, rz, ds);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
qWarning("%s:%d: Unknown coordinates transformation method",
|
qWarning("%s:%d: Unknown coordinates transformation method",
|
||||||
qPrintable(path), ln);
|
qPrintable(path), ln);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!datum.isValid()) {
|
||||||
|
qWarning("%s:%d: Invalid coordinates transformation parameters",
|
||||||
|
qPrintable(path), ln);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
GCS gcs(datum, pm, au);
|
GCS gcs(datum, pm, au);
|
||||||
if (gcs.isValid())
|
if (gcs.isValid())
|
||||||
|
@ -29,13 +29,14 @@ public:
|
|||||||
static const GCS *gcs(int geodeticDatum, int primeMeridian,
|
static const GCS *gcs(int geodeticDatum, int primeMeridian,
|
||||||
int angularUnits);
|
int angularUnits);
|
||||||
static const GCS *gcs(const QString &name);
|
static const GCS *gcs(const QString &name);
|
||||||
|
static const GCS &WGS84();
|
||||||
|
|
||||||
static void loadList(const QString &path);
|
static void loadList(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Entry;
|
class Entry;
|
||||||
|
|
||||||
static QList<Entry> WGS84();
|
static QList<Entry> defaults();
|
||||||
|
|
||||||
Datum _datum;
|
Datum _datum;
|
||||||
PrimeMeridian _primeMeridian;
|
PrimeMeridian _primeMeridian;
|
||||||
|
106
src/map/geocentric.cpp
Normal file
106
src/map/geocentric.cpp
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* 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 "ellipsoid.h"
|
||||||
|
#include "geocentric.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define AD_C 1.0026000
|
||||||
|
|
||||||
|
Point3D Geocentric::fromGeodetic(const Coordinates &c, const Ellipsoid *e)
|
||||||
|
{
|
||||||
|
double lat = deg2rad(c.lat());
|
||||||
|
double lon = deg2rad(c.lon());
|
||||||
|
double slat = sin(lat);
|
||||||
|
double slat2 = slat * slat;
|
||||||
|
double clat = cos(lat);
|
||||||
|
double Rn = e->radius() / (sqrt(1.0 - e->es() * slat2));
|
||||||
|
|
||||||
|
if (lon > M_PI)
|
||||||
|
lon -= M_2_PI;
|
||||||
|
|
||||||
|
return Point3D(Rn * clat * cos(lon), Rn * clat * sin(lon),
|
||||||
|
(Rn * (1 - e->es())) * slat);
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates Geocentric::toGeodetic(const Point3D &p, const Ellipsoid *e)
|
||||||
|
{
|
||||||
|
bool pole = false;
|
||||||
|
double lat, lon;
|
||||||
|
|
||||||
|
if (p.x() == 0.0) {
|
||||||
|
if (p.y() > 0)
|
||||||
|
lon = M_PI_2;
|
||||||
|
else if (p.y() < 0)
|
||||||
|
lon = -M_PI_2;
|
||||||
|
else {
|
||||||
|
pole = true;
|
||||||
|
lon = 0.0;
|
||||||
|
if (p.z() > 0.0)
|
||||||
|
lat = M_PI_2;
|
||||||
|
else if (p.z() < 0.0)
|
||||||
|
lat = -M_PI_2;
|
||||||
|
else
|
||||||
|
return Coordinates(rad2deg(lon), rad2deg(M_PI_2));
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
lon = atan2(p.y(), p.x());
|
||||||
|
|
||||||
|
double W2 = p.x()*p.x() + p.y()*p.y();
|
||||||
|
double W = sqrt(W2);
|
||||||
|
double T0 = p.z() * AD_C;
|
||||||
|
double S0 = sqrt(T0 * T0 + W2);
|
||||||
|
double Sin_B0 = T0 / S0;
|
||||||
|
double Cos_B0 = W / S0;
|
||||||
|
double Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0;
|
||||||
|
double T1 = p.z() + e->b() * e->e2s() * Sin3_B0;
|
||||||
|
double Sum = W - e->radius() * e->es() * Cos_B0 * Cos_B0 * Cos_B0;
|
||||||
|
double S1 = sqrt(T1*T1 + Sum * Sum);
|
||||||
|
double Sin_p1 = T1 / S1;
|
||||||
|
double Cos_p1 = Sum / S1;
|
||||||
|
|
||||||
|
if (!pole)
|
||||||
|
lat = atan(Sin_p1 / Cos_p1);
|
||||||
|
|
||||||
|
return Coordinates(rad2deg(lon), rad2deg(lat));
|
||||||
|
}
|
29
src/map/geocentric.h
Normal file
29
src/map/geocentric.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef GEOCENTRIC_H
|
||||||
|
#define GEOCENTRIC_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include "common/coordinates.h"
|
||||||
|
|
||||||
|
class Ellipsoid;
|
||||||
|
|
||||||
|
class Point3D {
|
||||||
|
public:
|
||||||
|
Point3D() : _x(NAN), _y(NAN), _z(NAN) {}
|
||||||
|
Point3D(double x, double y, double z) : _x(x), _y(y), _z(z) {}
|
||||||
|
|
||||||
|
double x() const {return _x;}
|
||||||
|
double y() const {return _y;}
|
||||||
|
double z() const {return _z;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double _x;
|
||||||
|
double _y;
|
||||||
|
double _z;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Geocentric {
|
||||||
|
Point3D fromGeodetic(const Coordinates &c, const Ellipsoid *e);
|
||||||
|
Coordinates toGeodetic(const Point3D &p, const Ellipsoid *e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GEOCENTRIC_H
|
@ -1,5 +1,3 @@
|
|||||||
#include <QFileInfo>
|
|
||||||
#include <QtEndian>
|
|
||||||
#include "pcs.h"
|
#include "pcs.h"
|
||||||
#include "tifffile.h"
|
#include "tifffile.h"
|
||||||
#include "geotiff.h"
|
#include "geotiff.h"
|
||||||
@ -9,48 +7,54 @@
|
|||||||
#define TIFF_SHORT 3
|
#define TIFF_SHORT 3
|
||||||
#define TIFF_LONG 4
|
#define TIFF_LONG 4
|
||||||
|
|
||||||
#define ModelPixelScaleTag 33550
|
#define ModelPixelScaleTag 33550
|
||||||
#define ModelTiepointTag 33922
|
#define ModelTiepointTag 33922
|
||||||
#define ModelTransformationTag 34264
|
#define ModelTransformationTag 34264
|
||||||
#define GeoKeyDirectoryTag 34735
|
#define GeoKeyDirectoryTag 34735
|
||||||
#define GeoDoubleParamsTag 34736
|
#define GeoDoubleParamsTag 34736
|
||||||
|
|
||||||
#define GTModelTypeGeoKey 1024
|
#define GTModelTypeGeoKey 1024
|
||||||
#define GTRasterTypeGeoKey 1025
|
#define GTRasterTypeGeoKey 1025
|
||||||
#define GeographicTypeGeoKey 2048
|
#define GeographicTypeGeoKey 2048
|
||||||
#define GeogGeodeticDatumGeoKey 2050
|
#define GeogGeodeticDatumGeoKey 2050
|
||||||
#define GeogPrimeMeridianGeoKey 2051
|
#define GeogPrimeMeridianGeoKey 2051
|
||||||
#define GeogAngularUnitsGeoKey 2054
|
#define GeogAngularUnitsGeoKey 2054
|
||||||
#define GeogEllipsoidGeoKey 2056
|
#define GeogEllipsoidGeoKey 2056
|
||||||
#define GeogAzimuthUnitsGeoKey 2060
|
#define GeogAzimuthUnitsGeoKey 2060
|
||||||
#define ProjectedCSTypeGeoKey 3072
|
#define ProjectedCSTypeGeoKey 3072
|
||||||
#define ProjectionGeoKey 3074
|
#define ProjectionGeoKey 3074
|
||||||
#define ProjCoordTransGeoKey 3075
|
#define ProjCoordTransGeoKey 3075
|
||||||
#define ProjLinearUnitsGeoKey 3076
|
#define ProjLinearUnitsGeoKey 3076
|
||||||
#define ProjStdParallel1GeoKey 3078
|
#define ProjStdParallel1GeoKey 3078
|
||||||
#define ProjStdParallel2GeoKey 3079
|
#define ProjStdParallel2GeoKey 3079
|
||||||
#define ProjNatOriginLongGeoKey 3080
|
#define ProjNatOriginLongGeoKey 3080
|
||||||
#define ProjNatOriginLatGeoKey 3081
|
#define ProjNatOriginLatGeoKey 3081
|
||||||
#define ProjFalseEastingGeoKey 3082
|
#define ProjFalseEastingGeoKey 3082
|
||||||
#define ProjFalseNorthingGeoKey 3083
|
#define ProjFalseNorthingGeoKey 3083
|
||||||
#define ProjCenterLongGeoKey 3088
|
#define ProjFalseOriginLongGeoKey 3084
|
||||||
#define ProjCenterLatGeoKey 3089
|
#define ProjFalseOriginLatGeoKey 3085
|
||||||
#define ProjScaleAtNatOriginGeoKey 3092
|
#define ProjFalseOriginEastingGeoKey 3086
|
||||||
#define ProjScaleAtCenterGeoKey 3093
|
#define ProjFalseOriginNorthingGeoKey 3087
|
||||||
#define ProjAzimuthAngleGeoKey 3094
|
#define ProjCenterLongGeoKey 3088
|
||||||
#define ProjRectifiedGridAngleGeoKey 3096
|
#define ProjCenterLatGeoKey 3089
|
||||||
|
#define ProjCenterEastingGeoKey 3090
|
||||||
|
#define ProjCenterNorthingGeoKey 3091
|
||||||
|
#define ProjScaleAtNatOriginGeoKey 3092
|
||||||
|
#define ProjScaleAtCenterGeoKey 3093
|
||||||
|
#define ProjAzimuthAngleGeoKey 3094
|
||||||
|
#define ProjRectifiedGridAngleGeoKey 3096
|
||||||
|
|
||||||
#define ModelTypeProjected 1
|
#define ModelTypeProjected 1
|
||||||
#define ModelTypeGeographic 2
|
#define ModelTypeGeographic 2
|
||||||
#define ModelTypeGeocentric 3
|
#define ModelTypeGeocentric 3
|
||||||
|
|
||||||
#define CT_TransverseMercator 1
|
#define CT_TransverseMercator 1
|
||||||
#define CT_ObliqueMercator 3
|
#define CT_ObliqueMercator 3
|
||||||
#define CT_Mercator 7
|
#define CT_Mercator 7
|
||||||
#define CT_LambertConfConic_2SP 8
|
#define CT_LambertConfConic_2SP 8
|
||||||
#define CT_LambertConfConic_1SP 9
|
#define CT_LambertConfConic_1SP 9
|
||||||
#define CT_LambertAzimEqualArea 10
|
#define CT_LambertAzimEqualArea 10
|
||||||
#define CT_AlbersEqualArea 11
|
#define CT_AlbersEqualArea 11
|
||||||
|
|
||||||
|
|
||||||
#define IS_SET(map, key) \
|
#define IS_SET(map, key) \
|
||||||
@ -251,6 +255,12 @@ bool GeoTIFF::readKeys(TIFFFile &file, Ctx &ctx, QMap<quint16, Value> &kv) const
|
|||||||
case ProjScaleAtCenterGeoKey:
|
case ProjScaleAtCenterGeoKey:
|
||||||
case ProjAzimuthAngleGeoKey:
|
case ProjAzimuthAngleGeoKey:
|
||||||
case ProjRectifiedGridAngleGeoKey:
|
case ProjRectifiedGridAngleGeoKey:
|
||||||
|
case ProjFalseOriginLongGeoKey:
|
||||||
|
case ProjFalseOriginLatGeoKey:
|
||||||
|
case ProjCenterEastingGeoKey:
|
||||||
|
case ProjCenterNorthingGeoKey:
|
||||||
|
case ProjFalseOriginEastingGeoKey:
|
||||||
|
case ProjFalseOriginNorthingGeoKey:
|
||||||
if (!readGeoValue(file, ctx.values, entry.ValueOffset,
|
if (!readGeoValue(file, ctx.values, entry.ValueOffset,
|
||||||
value.DOUBLE))
|
value.DOUBLE))
|
||||||
return false;
|
return false;
|
||||||
@ -303,9 +313,7 @@ const GCS *GeoTIFF::gcs(QMap<quint16, Value> &kv)
|
|||||||
|
|
||||||
if (!(gcs = GCS::gcs(gd, pm, au)))
|
if (!(gcs = GCS::gcs(gd, pm, au)))
|
||||||
_errorString = QString("%1+%2: unknown geodetic datum + prime"
|
_errorString = QString("%1+%2: unknown geodetic datum + prime"
|
||||||
" meridian combination")
|
" meridian combination").arg(gd).arg(pm);
|
||||||
.arg(kv.value(GeogGeodeticDatumGeoKey).SHORT)
|
|
||||||
.arg(kv.value(GeogPrimeMeridianGeoKey).SHORT);
|
|
||||||
} else
|
} else
|
||||||
_errorString = "Can not determine GCS";
|
_errorString = "Can not determine GCS";
|
||||||
|
|
||||||
@ -325,7 +333,7 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
|
|||||||
case CT_ObliqueMercator:
|
case CT_ObliqueMercator:
|
||||||
return Projection::Method(9815);
|
return Projection::Method(9815);
|
||||||
case CT_Mercator:
|
case CT_Mercator:
|
||||||
return Projection::Method(1024);
|
return Projection::Method(9804);
|
||||||
case CT_LambertConfConic_2SP:
|
case CT_LambertConfConic_2SP:
|
||||||
return Projection::Method(9802);
|
return Projection::Method(9802);
|
||||||
case CT_LambertConfConic_1SP:
|
case CT_LambertConfConic_1SP:
|
||||||
@ -389,12 +397,16 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
|||||||
lat0 = au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE);
|
lat0 = au.toDegrees(kv.value(ProjNatOriginLatGeoKey).DOUBLE);
|
||||||
else if (kv.contains(ProjCenterLatGeoKey))
|
else if (kv.contains(ProjCenterLatGeoKey))
|
||||||
lat0 = au.toDegrees(kv.value(ProjCenterLatGeoKey).DOUBLE);
|
lat0 = au.toDegrees(kv.value(ProjCenterLatGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjFalseOriginLatGeoKey))
|
||||||
|
lat0 = au.toDegrees(kv.value(ProjFalseOriginLatGeoKey).DOUBLE);
|
||||||
else
|
else
|
||||||
lat0 = NAN;
|
lat0 = NAN;
|
||||||
if (kv.contains(ProjNatOriginLongGeoKey))
|
if (kv.contains(ProjNatOriginLongGeoKey))
|
||||||
lon0 = au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE);
|
lon0 = au.toDegrees(kv.value(ProjNatOriginLongGeoKey).DOUBLE);
|
||||||
else if (kv.contains(ProjCenterLongGeoKey))
|
else if (kv.contains(ProjCenterLongGeoKey))
|
||||||
lon0 = au.toDegrees(kv.value(ProjCenterLongGeoKey).DOUBLE);
|
lon0 = au.toDegrees(kv.value(ProjCenterLongGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjFalseOriginLongGeoKey))
|
||||||
|
lon0 = au.toDegrees(kv.value(ProjFalseOriginLongGeoKey).DOUBLE);
|
||||||
else
|
else
|
||||||
lon0 = NAN;
|
lon0 = NAN;
|
||||||
if (kv.contains(ProjScaleAtNatOriginGeoKey))
|
if (kv.contains(ProjScaleAtNatOriginGeoKey))
|
||||||
@ -417,10 +429,18 @@ bool GeoTIFF::projectedModel(QMap<quint16, Value> &kv)
|
|||||||
sp2 = NAN;
|
sp2 = NAN;
|
||||||
if (kv.contains(ProjFalseNorthingGeoKey))
|
if (kv.contains(ProjFalseNorthingGeoKey))
|
||||||
fn = lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE);
|
fn = lu.toMeters(kv.value(ProjFalseNorthingGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjCenterNorthingGeoKey))
|
||||||
|
fn = lu.toMeters(kv.value(ProjCenterNorthingGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjFalseOriginNorthingGeoKey))
|
||||||
|
fn = lu.toMeters(kv.value(ProjFalseOriginNorthingGeoKey).DOUBLE);
|
||||||
else
|
else
|
||||||
fn = NAN;
|
fn = NAN;
|
||||||
if (kv.contains(ProjFalseEastingGeoKey))
|
if (kv.contains(ProjFalseEastingGeoKey))
|
||||||
fe = lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE);
|
fe = lu.toMeters(kv.value(ProjFalseEastingGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjCenterEastingGeoKey))
|
||||||
|
fe = lu.toMeters(kv.value(ProjCenterEastingGeoKey).DOUBLE);
|
||||||
|
else if (kv.contains(ProjFalseOriginEastingGeoKey))
|
||||||
|
fe = lu.toMeters(kv.value(ProjFalseOriginEastingGeoKey).DOUBLE);
|
||||||
else
|
else
|
||||||
fe = NAN;
|
fe = NAN;
|
||||||
|
|
||||||
|
253
src/map/jnxmap.cpp
Normal file
253
src/map/jnxmap.cpp
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
#include <QtEndian>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QPixmapCache>
|
||||||
|
#include "rectd.h"
|
||||||
|
#include "gcs.h"
|
||||||
|
#include "pcs.h"
|
||||||
|
#include "jnxmap.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ic2dc(x) ((x) * 180.0 / 0x7FFFFFFF)
|
||||||
|
|
||||||
|
struct Level {
|
||||||
|
quint32 count;
|
||||||
|
quint32 offset;
|
||||||
|
quint32 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ctx {
|
||||||
|
QPainter *painter;
|
||||||
|
QFile *file;
|
||||||
|
|
||||||
|
Ctx(QPainter *painter, QFile *file) : painter(painter), file(file) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class T> bool JNXMap::readValue(T &val)
|
||||||
|
{
|
||||||
|
T data;
|
||||||
|
|
||||||
|
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sizeof(T) > 1)
|
||||||
|
val = qFromLittleEndian(data);
|
||||||
|
else
|
||||||
|
val = data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::readString(QByteArray& ba)
|
||||||
|
{
|
||||||
|
char byte;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_file.getChar(&byte))
|
||||||
|
return false;
|
||||||
|
else if (!byte)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
ba += byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::readTiles()
|
||||||
|
{
|
||||||
|
qint32 lat1, lon2, lat2, lon1;
|
||||||
|
quint32 version, dummy, levels;
|
||||||
|
|
||||||
|
if (!(readValue(version) && readValue(dummy) && readValue(lat1)
|
||||||
|
&& readValue(lon2) && readValue(lat2) && readValue(lon1)
|
||||||
|
&& readValue(levels)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_bounds = RectC(Coordinates(ic2dc(lon1), ic2dc(lat1)),
|
||||||
|
Coordinates(ic2dc(lon2), ic2dc(lat2)));
|
||||||
|
if (!levels || !_bounds.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!_file.seek(version > 3 ? 0x34 : 0x30))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QVector<Level> lh(levels);
|
||||||
|
for (int i = 0; i < lh.count(); i++) {
|
||||||
|
Level &l = lh[i];
|
||||||
|
|
||||||
|
if (!(readValue(l.count) && readValue(l.offset) && readValue(l.scale)))
|
||||||
|
return false;
|
||||||
|
if (version > 3) {
|
||||||
|
QByteArray ba;
|
||||||
|
if (!(readValue(dummy) && readString(ba)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray guid;
|
||||||
|
if (!(readValue(dummy) && readString(guid)))
|
||||||
|
return false;
|
||||||
|
/* Use WebMercator projection for nakarte.tk maps */
|
||||||
|
if (guid == "12345678-1234-1234-1234-123456789ABC")
|
||||||
|
_projection = Projection(PCS::pcs(3857));
|
||||||
|
else
|
||||||
|
_projection = Projection(GCS::gcs(4326));
|
||||||
|
|
||||||
|
_zooms = QVector<Zoom>(lh.size());
|
||||||
|
for (int i = 0; i < lh.count(); i++) {
|
||||||
|
Zoom &z = _zooms[i];
|
||||||
|
const Level &l = lh.at(i);
|
||||||
|
|
||||||
|
if (!_file.seek(l.offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
z.tiles = QVector<Tile>(l.count);
|
||||||
|
for (quint32 j = 0; j < l.count; j++) {
|
||||||
|
Tile &tile = z.tiles[j];
|
||||||
|
qint32 top, right, bottom, left;
|
||||||
|
quint16 width, height;
|
||||||
|
|
||||||
|
if (!(readValue(top) && readValue(right) && readValue(bottom)
|
||||||
|
&& readValue(left) && readValue(width)
|
||||||
|
&& readValue(height) && readValue(tile.size)
|
||||||
|
&& readValue(tile.offset)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RectD rect(_projection.ll2xy(Coordinates(ic2dc(left), ic2dc(top))),
|
||||||
|
_projection.ll2xy(Coordinates(ic2dc(right), ic2dc(bottom))));
|
||||||
|
|
||||||
|
if (j == 0) {
|
||||||
|
ReferencePoint tl(PointD(0, 0), rect.topLeft());
|
||||||
|
ReferencePoint br(PointD(width, height), rect.bottomRight());
|
||||||
|
z.transform = Transform(tl, br);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF trect(z.transform.proj2img(rect.topLeft()),
|
||||||
|
z.transform.proj2img(rect.bottomRight()));
|
||||||
|
tile.pos = trect.topLeft();
|
||||||
|
|
||||||
|
qreal min[2], max[2];
|
||||||
|
min[0] = trect.left();
|
||||||
|
min[1] = trect.top();
|
||||||
|
max[0] = trect.right();
|
||||||
|
max[1] = trect.bottom();
|
||||||
|
z.tree.Insert(min, max, &tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
||||||
|
: Map(parent), _file(fileName), _zoom(0), _valid(false)
|
||||||
|
{
|
||||||
|
_name = QFileInfo(fileName).fileName();
|
||||||
|
|
||||||
|
if (!_file.open(QIODevice::ReadOnly)) {
|
||||||
|
_errorString = QString("%1: Error opening file").arg(fileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readTiles()) {
|
||||||
|
_errorString = "JNX file format error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JNXMap::ll2xy(const Coordinates &c)
|
||||||
|
{
|
||||||
|
const Zoom &z = _zooms.at(_zoom);
|
||||||
|
return z.transform.proj2img(_projection.ll2xy(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates JNXMap::xy2ll(const QPointF &p)
|
||||||
|
{
|
||||||
|
const Zoom &z = _zooms.at(_zoom);
|
||||||
|
return _projection.xy2ll(z.transform.img2proj(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF JNXMap::bounds()
|
||||||
|
{
|
||||||
|
return QRectF(ll2xy(_bounds.topLeft()), ll2xy(_bounds.bottomRight()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomFit(const QSize &size, const RectC &rect)
|
||||||
|
{
|
||||||
|
if (!rect.isValid())
|
||||||
|
_zoom = _zooms.size() - 1;
|
||||||
|
else {
|
||||||
|
for (int i = 1; i < _zooms.count(); i++) {
|
||||||
|
_zoom = i;
|
||||||
|
QRect sbr(QPoint(ll2xy(rect.topLeft()).toPoint()),
|
||||||
|
QPoint(ll2xy(rect.bottomRight()).toPoint()));
|
||||||
|
if (sbr.size().width() >= size.width() || sbr.size().height()
|
||||||
|
>= size.height()) {
|
||||||
|
_zoom--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomIn()
|
||||||
|
{
|
||||||
|
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomOut()
|
||||||
|
{
|
||||||
|
_zoom = qMax(_zoom - 1, 0);
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap JNXMap::pixmap(const Tile *tile, QFile *file)
|
||||||
|
{
|
||||||
|
QPixmap pm;
|
||||||
|
|
||||||
|
QString key = file->fileName() + "-" + QString::number(tile->offset);
|
||||||
|
if (!QPixmapCache::find(key, &pm)) {
|
||||||
|
QByteArray ba;
|
||||||
|
ba.resize(tile->size + 2);
|
||||||
|
ba[0] = (char)0xFF;
|
||||||
|
ba[1] = (char)0xD8;
|
||||||
|
char *data = ba.data() + 2;
|
||||||
|
|
||||||
|
if (!file->seek(tile->offset))
|
||||||
|
return QPixmap();
|
||||||
|
if (!file->read(data, tile->size))
|
||||||
|
return QPixmap();
|
||||||
|
pm = QPixmap::fromImage(QImage::fromData(ba));
|
||||||
|
|
||||||
|
if (!pm.isNull())
|
||||||
|
QPixmapCache::insert(key, pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pm;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::cb(Tile *tile, void *context)
|
||||||
|
{
|
||||||
|
Ctx *ctx = static_cast<Ctx*>(context);
|
||||||
|
ctx->painter->drawPixmap(tile->pos, pixmap(tile, ctx->file));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNXMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
||||||
|
{
|
||||||
|
Q_UNUSED(block);
|
||||||
|
const RTree<Tile*, qreal, 2> &tree = _zooms.at(_zoom).tree;
|
||||||
|
Ctx ctx(painter, &_file);
|
||||||
|
|
||||||
|
qreal min[2], max[2];
|
||||||
|
min[0] = rect.left();
|
||||||
|
min[1] = rect.top();
|
||||||
|
max[0] = rect.right();
|
||||||
|
max[1] = rect.bottom();
|
||||||
|
tree.Search(min, max, cb, &ctx);
|
||||||
|
}
|
69
src/map/jnxmap.h
Normal file
69
src/map/jnxmap.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef JNXMAP_H
|
||||||
|
#define JNXMAP_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QVector>
|
||||||
|
#include "common/rtree.h"
|
||||||
|
#include "common/rectc.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "projection.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
class JNXMap : public Map
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
JNXMap(const QString &fileName, QObject *parent = 0);
|
||||||
|
|
||||||
|
QString name() const {return _name;}
|
||||||
|
|
||||||
|
QRectF bounds();
|
||||||
|
|
||||||
|
int zoom() const {return _zoom;}
|
||||||
|
void setZoom(int zoom) {_zoom = zoom;}
|
||||||
|
int zoomFit(const QSize &size, const RectC &rect);
|
||||||
|
int zoomIn();
|
||||||
|
int zoomOut();
|
||||||
|
|
||||||
|
QPointF ll2xy(const Coordinates &c);
|
||||||
|
Coordinates xy2ll(const QPointF &p);
|
||||||
|
|
||||||
|
void draw(QPainter *painter, const QRectF &rect, bool block);
|
||||||
|
|
||||||
|
bool isValid() const {return _valid;}
|
||||||
|
QString errorString() const {return _errorString;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Tile {
|
||||||
|
QPointF pos;
|
||||||
|
quint32 size;
|
||||||
|
quint32 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Zoom {
|
||||||
|
Transform transform;
|
||||||
|
QVector<Tile> tiles;
|
||||||
|
RTree<Tile*, qreal, 2> tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T> bool readValue(T &val);
|
||||||
|
bool readString(QByteArray &ba);
|
||||||
|
bool readTiles();
|
||||||
|
|
||||||
|
static bool cb(Tile *tile, void *context);
|
||||||
|
static QPixmap pixmap(const Tile *tile, QFile *file);
|
||||||
|
|
||||||
|
QString _name;
|
||||||
|
QFile _file;
|
||||||
|
QVector<Zoom> _zooms;
|
||||||
|
int _zoom;
|
||||||
|
RectC _bounds;
|
||||||
|
Projection _projection;
|
||||||
|
|
||||||
|
bool _valid;
|
||||||
|
QString _errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JNXMAP_H
|
70
src/map/krovak.cpp
Normal file
70
src/map/krovak.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include "ellipsoid.h"
|
||||||
|
#include "krovak.h"
|
||||||
|
|
||||||
|
Krovak::Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
||||||
|
double azimuth, double scale, double centerLatitude, double longitudeOrigin,
|
||||||
|
double falseEasting, double falseNorthing)
|
||||||
|
{
|
||||||
|
double phiC = deg2rad(centerLatitude);
|
||||||
|
double sinPhiC = sin(phiC);
|
||||||
|
double sinPhiC2 = sinPhiC * sinPhiC;
|
||||||
|
double cosPhiC = cos(phiC);
|
||||||
|
double cosPhiC2 = cosPhiC * cosPhiC;
|
||||||
|
double cosPhiC4 = cosPhiC2 * cosPhiC2;
|
||||||
|
double alphaC = deg2rad(azimuth);
|
||||||
|
|
||||||
|
_phiP = deg2rad(standardParallel);
|
||||||
|
_e = sqrt(ellipsoid->es());
|
||||||
|
_A = ellipsoid->radius() * sqrt(1.0 - ellipsoid->es())
|
||||||
|
/ (1.0 - ellipsoid->es() * sinPhiC2);
|
||||||
|
_B = sqrt(1.0 + (ellipsoid->es() * cosPhiC4 / (1.0 - ellipsoid->es())));
|
||||||
|
double gamma0 = asin(sinPhiC / _B);
|
||||||
|
_t0 = tan(M_PI_4 + gamma0 / 2.0) * pow((1.0 + _e * sinPhiC) /
|
||||||
|
(1.0 - _e * sinPhiC), _e*_B / 2.0) / pow(tan(M_PI_4 + phiC/2.0), _B);
|
||||||
|
_n = sin(_phiP);
|
||||||
|
_r0 = scale * _A / tan(_phiP);
|
||||||
|
_FE = falseEasting;
|
||||||
|
_FN = falseNorthing;
|
||||||
|
_cosAlphaC = cos(alphaC);
|
||||||
|
_sinAlphaC = sin(alphaC);
|
||||||
|
_lambda0 = deg2rad(longitudeOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointD Krovak::ll2xy(const Coordinates &c) const
|
||||||
|
{
|
||||||
|
double phi = deg2rad(c.lat());
|
||||||
|
double lambda = deg2rad(c.lon());
|
||||||
|
double eSinPhi = _e * sin(phi);
|
||||||
|
double U = 2.0 * (atan(_t0 * pow(tan(phi/2.0 + M_PI_4), _B)
|
||||||
|
/ pow((1.0 + eSinPhi) / (1.0 - eSinPhi), _e * _B/2.0)) - M_PI_4);
|
||||||
|
double cosU = cos(U);
|
||||||
|
double V = _B * (_lambda0 - lambda);
|
||||||
|
double T = asin(_cosAlphaC * sin(U) + _sinAlphaC * cosU * cos(V));
|
||||||
|
double D = asin(cosU * sin(V) / cos(T));
|
||||||
|
double theta = _n * D;
|
||||||
|
double r = _r0 * pow(tan(M_PI_4 + _phiP/2.0), _n)
|
||||||
|
/ pow(tan(T/2.0 + M_PI_4), _n);
|
||||||
|
|
||||||
|
return PointD(r * sin(theta) + _FE, r * cos(theta) + _FN);
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates Krovak::xy2ll(const PointD &p) const
|
||||||
|
{
|
||||||
|
double Xp = p.y() - _FN;
|
||||||
|
double Yp = p.x() - _FE;
|
||||||
|
double Xp2 = Xp * Xp;
|
||||||
|
double Yp2 = Yp * Yp;
|
||||||
|
double r = sqrt(Xp2 + Yp2);
|
||||||
|
double theta = atan(Yp / Xp);
|
||||||
|
double D = theta / sin(_phiP);
|
||||||
|
double T = 2.0 * (atan(pow(_r0 / r, 1.0/_n) * tan(M_PI_4 + _phiP/2.0))
|
||||||
|
- M_PI_4);
|
||||||
|
double U = asin(_cosAlphaC * sin(T) - _sinAlphaC * cos(T) * cos(D));
|
||||||
|
double V = asin(cos(T) * sin(D) / cos(U));
|
||||||
|
double phi = U;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
phi = 2.0 * (atan(pow(_t0, -1.0/_B) * pow(tan(U/2.0 + M_PI_4), 1.0/_B)
|
||||||
|
* pow((1.0 + _e * sin(phi))/(1.0 - _e * sin(phi)), _e/2.0)) - M_PI_4);
|
||||||
|
|
||||||
|
return Coordinates(rad2deg(_lambda0 - V/_B), rad2deg(phi));
|
||||||
|
}
|
45
src/map/krovak.h
Normal file
45
src/map/krovak.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#ifndef KROVAK_H
|
||||||
|
#define KROVAK_H
|
||||||
|
|
||||||
|
#include "ct.h"
|
||||||
|
|
||||||
|
class Ellipsoid;
|
||||||
|
|
||||||
|
class Krovak : public CT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Krovak(const Ellipsoid *ellipsoid, double standardParallel,
|
||||||
|
double azimuth, double scale, double centerLatitude,
|
||||||
|
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||||
|
|
||||||
|
virtual CT *clone() const {return new Krovak(*this);}
|
||||||
|
|
||||||
|
virtual PointD ll2xy(const Coordinates &c) const;
|
||||||
|
virtual Coordinates xy2ll(const PointD &p) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double _e, _A, _B, _t0, _n, _r0, _phiP;
|
||||||
|
double _cosAlphaC, _sinAlphaC, _lambda0, _FE, _FN;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KrovakNE : public CT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KrovakNE(const Ellipsoid *ellipsoid, double standardParallel,
|
||||||
|
double azimuth, double scale, double centerLatitude,
|
||||||
|
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||||
|
: _k(ellipsoid, standardParallel, azimuth, scale, centerLatitude,
|
||||||
|
longitudeOrigin, falseEasting, falseNorthing) {}
|
||||||
|
|
||||||
|
virtual CT *clone() const {return new KrovakNE(*this);}
|
||||||
|
|
||||||
|
virtual PointD ll2xy(const Coordinates &c) const
|
||||||
|
{PointD p(_k.ll2xy(c)); return PointD(-p.x(), -p.y());}
|
||||||
|
virtual Coordinates xy2ll(const PointD &p) const
|
||||||
|
{return _k.xy2ll(PointD(-p.x(), -p.y()));}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Krovak _k;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KROVAK_H
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user