Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
84d5673e17 | |||
e40836e6bb | |||
88aef38f9d | |||
7d8dcec88b | |||
561d8362a9 | |||
7f9fde76e9 | |||
239e571358 | |||
44b28e3d4d | |||
4cef089c81 | |||
05ac5ccedb | |||
22fb6071f7 | |||
2c78772a67 | |||
0f03ef4af7 | |||
351cc49ec9 | |||
743a937f41 | |||
033225502f | |||
75b8b9eab0 | |||
e76e7b71ed | |||
41ea07d020 | |||
4bad086152 | |||
8be088be0a | |||
73021bec01 | |||
7584116168 | |||
59b734c402 | |||
8168d52f09 | |||
74796e3e41 | |||
676024854a | |||
10e1b5c4fb | |||
54570ed97e | |||
07fa377e38 | |||
2b8c3f64ac | |||
a60cccb57e | |||
c2e50e5213 | |||
0ea8e008c2 | |||
082435c83d | |||
e63ad7a244 | |||
32a4365543 | |||
abd1dc2450 | |||
5674534efd | |||
33287f9d76 | |||
1dfe84c4af | |||
7fe8d204bc | |||
5080247e10 | |||
13d6c7c643 | |||
547d7a5f23 | |||
9e03d85b7a | |||
b811132394 | |||
ca33328d99 | |||
41c8a4d935 | |||
acd09400be | |||
16bfd593c7 | |||
9e70a1ffbb | |||
1b590fbf76 | |||
8d52dbf59f | |||
c6fd32fc61 | |||
af6082425e | |||
785123f005 | |||
df3ee11f42 | |||
6af1ff35ab | |||
8423fc1230 | |||
a62d84da67 | |||
2431f432d4 | |||
6c4ebc40ca | |||
0cc6908b30 | |||
becf57e4eb | |||
96733883cb | |||
973c086029 |
@ -1,4 +1,4 @@
|
||||
version: 7.37.{build}
|
||||
version: 7.38.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
27
gpxsee.pro
@ -3,7 +3,7 @@ unix:!macx {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 7.37
|
||||
VERSION = 7.38
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
@ -22,7 +22,9 @@ HEADERS += src/common/config.h \
|
||||
src/GUI/axislabelitem.h \
|
||||
src/GUI/graphicsscene.h \
|
||||
src/GUI/mapaction.h \
|
||||
src/GUI/mapitem.h \
|
||||
src/GUI/marginswidget.h \
|
||||
src/GUI/planeitem.h \
|
||||
src/GUI/popup.h \
|
||||
src/common/garmin.h \
|
||||
src/common/staticassert.h \
|
||||
@ -103,6 +105,9 @@ HEADERS += src/common/config.h \
|
||||
src/map/IMG/rastertile.h \
|
||||
src/map/IMG/textpathitem.h \
|
||||
src/map/IMG/textpointitem.h \
|
||||
src/map/bsbmap.h \
|
||||
src/map/invalidmap.h \
|
||||
src/map/polyconic.h \
|
||||
src/map/projection.h \
|
||||
src/map/ellipsoid.h \
|
||||
src/map/datum.h \
|
||||
@ -206,6 +211,7 @@ HEADERS += src/common/config.h \
|
||||
src/GUI/pngexportdialog.h
|
||||
SOURCES += src/main.cpp \
|
||||
src/GUI/axislabelitem.cpp \
|
||||
src/GUI/mapitem.cpp \
|
||||
src/GUI/marginswidget.cpp \
|
||||
src/GUI/popup.cpp \
|
||||
src/common/coordinates.cpp \
|
||||
@ -271,11 +277,13 @@ SOURCES += src/main.cpp \
|
||||
src/map/IMG/rastertile.cpp \
|
||||
src/map/IMG/textpathitem.cpp \
|
||||
src/map/IMG/textpointitem.cpp \
|
||||
src/map/bsbmap.cpp \
|
||||
src/map/maplist.cpp \
|
||||
src/map/onlinemap.cpp \
|
||||
src/map/downloader.cpp \
|
||||
src/map/emptymap.cpp \
|
||||
src/map/ozimap.cpp \
|
||||
src/map/polyconic.cpp \
|
||||
src/map/tar.cpp \
|
||||
src/map/atlas.cpp \
|
||||
src/map/ozf.cpp \
|
||||
@ -425,7 +433,13 @@ macx {
|
||||
icons/formats/json.icns \
|
||||
icons/formats/cup.icns \
|
||||
icons/formats/gpi.icns \
|
||||
icons/formats/sml.icns
|
||||
icons/formats/sml.icns \
|
||||
icons/formats/img.icns \
|
||||
icons/formats/jnx.icns \
|
||||
icons/formats/kap.icns \
|
||||
icons/formats/mbts.icns \
|
||||
icons/formats/rmap.icns \
|
||||
icons/formats/tba.icns
|
||||
QMAKE_BUNDLE_DATA += locale maps icons csv
|
||||
}
|
||||
|
||||
@ -445,7 +459,14 @@ win32 {
|
||||
icons/formats/json.ico \
|
||||
icons/formats/cup.ico \
|
||||
icons/formats/gpi.ico \
|
||||
icons/formats/sml.ico
|
||||
icons/formats/sml.ico \
|
||||
icons/formats/img.ico \
|
||||
icons/formats/jnx.ico \
|
||||
icons/formats/kap.ico \
|
||||
icons/formats/map.ico \
|
||||
icons/formats/mbts.ico \
|
||||
icons/formats/rmap.ico \
|
||||
icons/formats/tba.ico
|
||||
DEFINES += _USE_MATH_DEFINES \
|
||||
NOGDI
|
||||
}
|
||||
|
BIN
icons/formats/img.icns
Normal file
BIN
icons/formats/img.ico
Normal file
After Width: | Height: | Size: 304 KiB |
BIN
icons/formats/jnx.icns
Normal file
BIN
icons/formats/jnx.ico
Normal file
After Width: | Height: | Size: 304 KiB |
BIN
icons/formats/kap.icns
Normal file
BIN
icons/formats/kap.ico
Normal file
After Width: | Height: | Size: 305 KiB |
BIN
icons/formats/map.icns
Normal file
BIN
icons/formats/map.ico
Normal file
After Width: | Height: | Size: 303 KiB |
BIN
icons/formats/mbts.icns
Normal file
BIN
icons/formats/mbts.ico
Normal file
After Width: | Height: | Size: 305 KiB |
BIN
icons/formats/rmap.icns
Normal file
BIN
icons/formats/rmap.ico
Normal file
After Width: | Height: | Size: 305 KiB |
@ -13,3 +13,10 @@ slf:#881199
|
||||
cup:#20a810
|
||||
gpi:#fca314
|
||||
sml:#6434eb
|
||||
img:#cf0a0a
|
||||
jnx:#aeff00
|
||||
kap:#080045
|
||||
map:#f6ff00
|
||||
mbts:#ff0062
|
||||
rmap:#145cba
|
||||
tba:#367050
|
||||
|
BIN
icons/formats/tba.icns
Normal file
BIN
icons/formats/tba.ico
Normal file
After Width: | Height: | Size: 304 KiB |
465
pkg/Info.plist
@ -42,7 +42,7 @@
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/tcx+xml</string>
|
||||
<string>application/vnd.garmin.tcx+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/tcx.icns</string>
|
||||
@ -74,7 +74,7 @@
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/loc+xml</string>
|
||||
<string>application/vnd.groundspeak.loc+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/loc.icns</string>
|
||||
@ -90,7 +90,7 @@
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/slf+xml</string>
|
||||
<string>application/vnd.sigma.slf+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/slf.icns</string>
|
||||
@ -250,7 +250,7 @@
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/sml+xml</string>
|
||||
<string>application/vnd.suunto.sml+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/sml.icns</string>
|
||||
@ -259,6 +259,193 @@
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>jpeg</string>
|
||||
<string>jpg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>image/jpeg</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>JPEG Image</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>csv</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>text/csv</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Comma-Separated Values (CSV) Files</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>img</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.garmin.img</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/img.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Garmin IMG Map</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>gmap</string>
|
||||
<string>gmapi</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.garmin.gmap</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/img.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Garmin Map Product File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>jnx</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.garmin.jnx</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/jnx.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Garmin JNX Map</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>kap</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.maptech.kap</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/kap.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>BSB Nautical Charts</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>map</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.oziexplorer.map</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/map.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>OziExplorer Map File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>rmap</string>
|
||||
<string>rtmap</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.twonav.rmap</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/rmap.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>TwoNav Raster Map File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>tba</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.trekbuddy.tba</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/tba.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>TrekBuddy Atlas</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>mbtiles</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.mapbox.mbtiles</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
<string>icons/mbts.icns</string>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>MBTiles Map File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>tiff</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>image/tiff</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>GeoTIFF Image</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeExtensions</key>
|
||||
<array>
|
||||
<string>xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeMIMETypes</key>
|
||||
<array>
|
||||
<string>application/vnd.gpxsee.map+xml</string>
|
||||
</array>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>GPXSee Map Definition File</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>UTImportedTypeDeclarations</key>
|
||||
@ -302,7 +489,7 @@
|
||||
<string>tcx</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/tcx+xml</string>
|
||||
<string>application/vnd.garmin.tcx+xml</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
@ -344,7 +531,7 @@
|
||||
<string>loc</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/loc+xml</string>
|
||||
<string>application/vnd.groundspeak.loc+xml</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
@ -365,7 +552,7 @@
|
||||
<string>slf</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/slf+xml</string>
|
||||
<string>application/vnd.sigma.slf+xml</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
@ -575,7 +762,269 @@
|
||||
<string>sml</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/sml+xml</string>
|
||||
<string>application/vnd.suunto.sml+xml</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>public.jpeg</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://www.w3.org/Graphics/JPEG/</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>JPEG Image</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.image</string>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>jpeg</string>
|
||||
<string>jpg</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>image/jpeg</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>public.csv</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://tools.ietf.org/html/rfc4180</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Comma-Separated Values (CSV) Files</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>csv</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>text/csv</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.garmin.img</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://sourceforge.net/projects/garmin-img/</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Garmin IMG map</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>img</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.garmin.img</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.garmin.jnx</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://whiter.brinkster.net/en/JNX.shtml</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Garmin JNX Map</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>jnx</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.garmin.jnx</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.garmin.gmap</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://sourceforge.net/projects/garmin-img/</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>Garmin Map Product File</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.xml</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>xml</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.garmin.gmap</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.maptech.kap</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://libbsb.sourceforge.net/bsb_file_format.html</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>BSB Nautical Charts</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.image</string>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>kap</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>image/vnd.maptech.kap</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.oziexplorer3.map</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://www.oziexplorer3.com/eng/help/map_file_format.html</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>OziExplorer Map File</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>map</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.oziexplorer.map</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.mapbox.mbtiles</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://github.com/mapbox/mbtiles-spec</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>MBTiles Map File</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>mbtiles</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.mapbox.mbtiles</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>com.twonav.rmap</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://wiki.openstreetmap.org/wiki/TwoNav_RMAP</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>TwoNav Raster Map File</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>rmap</string>
|
||||
<string>rtmap</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.twonav.rmap</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>net.trekbuddy.tba</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://github.com/kruhc/trekbuddy</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>TrekBuddy Atlas</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>tba</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.trekbuddy.tba</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>public.tiff</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>https://www.adobe.io/open/standards/TIFF.html</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>TIFF Image</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.image</string>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>tiff</string>
|
||||
<string>tif</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>image/tiff</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UTTypeIdentifier</key>
|
||||
<string>org.gpxsee.map</string>
|
||||
<key>UTTypeReferenceURL</key>
|
||||
<string>http://www.gpxsee.org/map/1.4/</string>
|
||||
<key>UTTypeDescription</key>
|
||||
<string>GPXSee Map Definition File</string>
|
||||
<key>UTTypeConformsTo</key>
|
||||
<array>
|
||||
<string>public.xml</string>
|
||||
</array>
|
||||
<key>UTTypeTagSpecification</key>
|
||||
<dict>
|
||||
<key>public.filename-extension</key>
|
||||
<array>
|
||||
<string>xml</string>
|
||||
</array>
|
||||
<key>public.mime-type</key>
|
||||
<string>application/vnd.gpxsee.map+xml</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</array>
|
||||
|
@ -18,13 +18,14 @@
|
||||
<li>User-definable online maps (OpenStreetMap/Google tiles, WMTS,
|
||||
WMS, TMS, QuadTiles).</li>
|
||||
<li>Offline maps (MBTiles, OziExplorer maps, TrekBuddy maps/atlases,
|
||||
TwoNav RMaps, Garmin IMG & JNX, GeoTIFF images).</li>
|
||||
TwoNav RMaps, Garmin IMG & JNX maps, GeoTIFF images,
|
||||
BSB nautical charts).</li>
|
||||
<li>Elevation, speed, heart rate, cadence, power, temperature and
|
||||
gear ratio graphs.</li>
|
||||
<li>Support for multiple tracks in one view.</li>
|
||||
<li>Support for POI files.</li>
|
||||
<li>Support for DEM files (SRTM HGT).</li>
|
||||
<li>Print/export to PDF.</li>
|
||||
<li>Print/export to PDF & PNG.</li>
|
||||
<li>Full-screen mode.</li>
|
||||
<li>HiDPI/Retina displays & maps support.</li>
|
||||
</ul>
|
||||
@ -58,7 +59,7 @@
|
||||
|
||||
<mimetypes>
|
||||
<mimetype>application/gpx+xml</mimetype>
|
||||
<mimetype>application/tcx+xml</mimetype>
|
||||
<mimetype>application/vnd.garmin.tcx+xml</mimetype>
|
||||
<mimetype>application/vnd.ant.fit</mimetype>
|
||||
<mimetype>application/vnd.google-earth.kml+xml</mimetype>
|
||||
<mimetype>application/vnd.fai.igc</mimetype>
|
||||
@ -66,11 +67,24 @@
|
||||
<mimetype>application/vnd.oziexplorer.plt</mimetype>
|
||||
<mimetype>application/vnd.oziexplorer.rte</mimetype>
|
||||
<mimetype>application/vnd.oziexplorer.wpt</mimetype>
|
||||
<mimetype>application/loc+xml</mimetype>
|
||||
<mimetype>application/slf+xml</mimetype>
|
||||
<mimetype>application/vnd.groundspeak.loc+xml</mimetype>
|
||||
<mimetype>application/vnd.sigma.slf+xml</mimetype>
|
||||
<mimetype>application/geo+json</mimetype>
|
||||
<mimetype>application/vnd.naviter.seeyou.cup</mimetype>
|
||||
<mimetype>application/vnd.garmin.gpi</mimetype>
|
||||
<mimetype>application/sml+xml</mimetype>
|
||||
<mimetype>application/vnd.suunto.sml+xml</mimetype>
|
||||
<mimetype>image/jpeg</mimetype>
|
||||
<mimetype>text/csv</mimetype>
|
||||
<mimetype>application/vnd.garmin.img</mimetype>
|
||||
<mimetype>application/vnd.garmin.jnx</mimetype>
|
||||
<mimetype>application/vnd.garmin.gmap+xml</mimetype>
|
||||
<mimetype>image/vnd.maptech.kap</mimetype>
|
||||
<mimetype>application/vnd.oziexplorer.map</mimetype>
|
||||
<mimetype>application/vnd.mapbox.mbtiles</mimetype>
|
||||
<mimetype>application/vnd.twonav.rmap</mimetype>
|
||||
<mimetype>application/vnd.trekbuddy.tba</mimetype>
|
||||
<mimetype>application/vnd.gpxsee.map+xml</mimetype>
|
||||
<mimetype>application/x-tar</mimetype>
|
||||
<mimetype>image/tiff</mimetype>
|
||||
</mimetypes>
|
||||
</component>
|
||||
|
@ -1887,6 +1887,7 @@ CI1971 / Chatham Islands Map Grid,5518,4672,5517,9001,9807,4500,8801,-44,9110,88
|
||||
CI1979 / Chatham Islands Map Grid,5519,4673,5517,9001,9807,4500,8801,-44,9110,8802,-176.3,9110,8805,1,9201,8806,350000,9001,8807,650000,9001,,,,,,
|
||||
DHDN / 3-degree Gauss-Kruger zone 1,5520,4314,16261,9001,9807,4530,8801,0,9102,8802,3,9102,8805,1,9201,8806,1500000,9001,8807,0,9001,,,,,,
|
||||
WGS 84 / Gabon TM 2011,5523,4326,5522,9001,9807,4499,8801,0,9102,8802,11.3,9110,8805,0.9996,9201,8806,1500000,9001,8807,5500000,9001,,,,,,
|
||||
SAD69(96) / Brazil Polyconic,5530,5527,19941,9001,9818,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
|
||||
SAD69(96) / UTM zone 21S,5531,5527,16121,9001,9807,4400,8801,0,9102,8802,-57,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
SAD69(96) / UTM zone 22S,5532,4618,16122,9001,9807,4400,8801,0,9102,8802,-51,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
SAD69(96) / UTM zone 23S,5533,5527,16123,9001,9807,4400,8801,0,9102,8802,-45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
@ -1970,6 +1971,7 @@ SAD69(96) / UTM zone 18S,5875,5527,16118,9001,9807,4400,8801,0,9102,8802,-75,910
|
||||
SAD69(96) / UTM zone 19S,5876,5527,16119,9001,9807,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
SAD69(96) / UTM zone 20S,5877,5527,16120,9001,9807,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
Cadastre 1997 / UTM zone 38S,5879,4475,16138,9001,9807,4400,8801,0,9102,8802,45,9102,8805,0.9996,9201,8806,500000,9001,8807,10000000,9001,,,,,,
|
||||
SIRGAS 2000 / Brazil Polyconic,5880,4674,19941,9001,9818,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
|
||||
WGS 84 / EPSG Arctic Regional zone A1,5921,4326,5906,9001,9802,4400,8821,81.19020136,9110,8822,-111,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
|
||||
WGS 84 / EPSG Arctic Regional zone A2,5922,4326,5907,9001,9802,4400,8821,81.19020136,9110,8822,-39,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
|
||||
WGS 84 / EPSG Arctic Regional zone A3,5923,4326,5908,9001,9802,4400,8821,81.19020136,9110,8822,33,9102,8823,85,9102,8824,77,9102,8826,0,9001,8827,0,9001,,,
|
||||
@ -3046,6 +3048,8 @@ Pulkovo 1942 / Gauss-Kruger 32N,28492,4284,16332,9001,9807,4530,8801,0,9102,8802
|
||||
Qatar 1974 / Qatar National Grid,28600,4285,19919,9001,9807,4400,8801,24.27,9110,8802,51.13,9110,8805,0.99999,9201,8806,200000,9001,8807,300000,9001,,,,,,
|
||||
Amersfoort / RD Old,28991,4289,19913,9001,9809,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,0,9001,8807,0,9001,,,,,,
|
||||
Amersfoort / RD New,28992,4289,19914,9001,9809,4499,8801,52.0922178,9110,8802,5.23155,9110,8805,0.9999079,9201,8806,155000,9001,8807,463000,9001,,,,,,
|
||||
SAD69 / Brazil Polyconic,29100,4291,19941,9001,9818,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
|
||||
SAD69 / Brazil Polyconic,29101,4618,19941,9001,9818,4499,8801,0,9102,8802,-54,9102,8806,5000000,9001,8807,10000000,9001,,,,,,,,,
|
||||
SAD69 / UTM zone 18N,29118,4291,16018,9001,9807,4400,8801,0,9102,8802,-75,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
SAD69 / UTM zone 19N,29119,4291,16019,9001,9807,4400,8801,0,9102,8802,-69,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
SAD69 / UTM zone 20N,29120,4291,16020,9001,9807,4400,8801,0,9102,8802,-63,9102,8805,0.9996,9201,8806,500000,9001,8807,0,9001,,,,,,
|
||||
|
Can't render this file because it is too large.
|
@ -15,4 +15,4 @@ Icon=gpxsee
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Graphics;Viewer;Education;Geography;Maps;Sports;Qt;
|
||||
MimeType=application/gpx+xml;application/tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/loc+xml;application/slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/sml+xml;
|
||||
MimeType=application/gpx+xml;application/vnd.garmin.tcx+xml;application/vnd.ant.fit;application/vnd.google-earth.kml+xml;application/vnd.fai.igc;application/vnd.nmea.nmea;application/vnd.oziexplorer.plt;application/vnd.oziexplorer.rte;application/vnd.oziexplorer.wpt;application/vnd.groundspeak.loc+xml;application/vnd.sigma.slf+xml;application/geo+json;application/vnd.naviter.seeyou.cup;application/vnd.garmin.gpi;application/vnd.suunto.sml+xml;image/jpeg;text/csv;application/vnd.garmin.img;application/vnd.garmin.jnx;application/vnd.garmin.gmap+xml;image/vnd.maptech.kap;application/vnd.oziexplorer.map;application/vnd.mapbox.mbtiles;application/vnd.twonav.rmap;application/vnd.trekbuddy.tba;application/vnd.gpxsee.map+xml;application/x-tar;image/tiff;
|
||||
|
104
pkg/gpxsee.nsi
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.37"
|
||||
!define VERSION "7.38"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}.exe"
|
||||
@ -109,14 +109,14 @@ Section "GPXSee" SEC_APP
|
||||
|
||||
; Associate file formats
|
||||
DetailPrint "Associating file types..."
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 8
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 9
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 10
|
||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 11
|
||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 12
|
||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 13
|
||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 14
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 15
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 11
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 16
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 17
|
||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 18
|
||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 19
|
||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 20
|
||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 21
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 22
|
||||
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
||||
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
||||
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
||||
@ -124,6 +124,47 @@ Section "GPXSee" SEC_APP
|
||||
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP File" 5
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpi" "Garmin POI File" 6
|
||||
!insertmacro FILE_ASSOCIATION_ADD "sml" "Suunto Markup Language" 7
|
||||
!insertmacro FILE_ASSOCIATION_ADD "img" "Garmin IMG Map" 8
|
||||
!insertmacro FILE_ASSOCIATION_ADD "jnx" "Garmin JNX Map" 9
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kap" "BSB Nautical Chart" 10
|
||||
!insertmacro FILE_ASSOCIATION_ADD "map" "OziExplorer Map File" 12
|
||||
!insertmacro FILE_ASSOCIATION_ADD "mbtiles" "MBTiles Map File" 13
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rmap" "TwoNav Raster Map File" 14
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tba" "TrekBuddy Atlas" 15
|
||||
|
||||
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
|
||||
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tcx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kml\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".fit\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".igc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".nmea\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".plt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rte\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".wpt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".loc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".slf\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".geojson\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".cup\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".gpi\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".sml\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".csv\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".json\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jpg\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jpeg\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".img\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jnx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".map\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".mbtiles\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rtmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tar\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tba\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tif\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tiff\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".xml\OpenWithList" "GPXSee.exe" ""
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
|
||||
SectionEnd
|
||||
@ -210,7 +251,7 @@ Section "Uninstall"
|
||||
Delete "$SMPROGRAMS\$StartMenuFolder\*.*"
|
||||
RMDir "$SMPROGRAMS\$StartMenuFolder"
|
||||
|
||||
; Remove GPX file association
|
||||
; Remove file associations
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tcx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kml"
|
||||
@ -226,6 +267,47 @@ Section "Uninstall"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "sml"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "img"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "jnx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "map"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "mbtiles"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "rmap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tba"
|
||||
|
||||
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".kml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".fit\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".igc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".nmea\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".plt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rte\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".wpt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".loc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".slf\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".geojson\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".cup\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".gpi\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".sml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".csv\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".json\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jpg\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jpeg\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".img\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jnx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".kap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".map\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".mbtiles\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rtmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tar\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tba\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tif\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tiff\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".xml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegKey HKCR "Applications\GPXSee.exe"
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
|
||||
SectionEnd
|
||||
@ -256,4 +338,4 @@ LangString DESC_LOCALIZATION ${LANG_ENGLISH} \
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_MSVC} $(DESC_MSVC)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_APP} $(DESC_APP)
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_LOCALIZATION} $(DESC_LOCALIZATION)
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
118
pkg/gpxsee.xml
@ -1,35 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
|
||||
<!-- Data files -->
|
||||
|
||||
<mime-type type="application/gpx+xml">
|
||||
<comment>GPS Exchange Format</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.topografix.com/GPX/1/0" localName="gpx"/>
|
||||
<root-XML namespaceURI="http://www.topografix.com/GPX/1/1" localName="gpx"/>
|
||||
<glob pattern="*.gpx"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/tcx+xml">
|
||||
<mime-type type="application/vnd.garmin.tcx+xml">
|
||||
<comment>Training Center XML</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" localName="TrainingCenterDatabase"/>
|
||||
<glob pattern="*.tcx"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/kml+xml">
|
||||
<mime-type type="application/vnd.google-earth.kml+xml">
|
||||
<comment>Keyhole Markup Language</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.opengis.net/kml/2.2" localName="kml"/>
|
||||
<glob pattern="*.kml"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/loc+xml">
|
||||
<mime-type type="application/vnd.groundspeak.loc+xml">
|
||||
<comment>Geocaching.com Waypoint File</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<glob pattern="*.loc"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/slf+xml">
|
||||
<mime-type type="application/vnd.sigma.slf+xml">
|
||||
<comment>Sigma Log Format</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
@ -40,6 +46,9 @@
|
||||
<comment>Flexible and Interoperable Data Transfer</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application-octet-stream"/>
|
||||
<magic>
|
||||
<match type="string" offset="8" value=".FIT"/>
|
||||
</magic>
|
||||
<glob pattern="*.fit"/>
|
||||
</mime-type>
|
||||
|
||||
@ -61,6 +70,9 @@
|
||||
<comment>OziExplorer Track Point File</comment>
|
||||
<sub-class-of type="text/plain"/>
|
||||
<generic-icon name="text-plain"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="OziExplorer Track Point File"/>
|
||||
</magic>
|
||||
<glob pattern="*.plt"/>
|
||||
</mime-type>
|
||||
|
||||
@ -68,6 +80,9 @@
|
||||
<comment>OziExplorer Route File</comment>
|
||||
<sub-class-of type="text/plain"/>
|
||||
<generic-icon name="text-plain"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="OziExplorer Route File"/>
|
||||
</magic>
|
||||
<glob pattern="*.rte"/>
|
||||
</mime-type>
|
||||
|
||||
@ -75,6 +90,9 @@
|
||||
<comment>OziExplorer Waypoint File</comment>
|
||||
<sub-class-of type="text/plain"/>
|
||||
<generic-icon name="text-plain"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="OziExplorer Waypoint File"/>
|
||||
</magic>
|
||||
<glob pattern="*.wpt"/>
|
||||
</mime-type>
|
||||
|
||||
@ -96,13 +114,103 @@
|
||||
<comment>Garmin POI File</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application/octet-stream"/>
|
||||
<magic>
|
||||
<match type="string" offset="8" value="GRMREC"/>
|
||||
</magic>
|
||||
<glob pattern="*.gpi"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/sml+xml">
|
||||
<mime-type type="application/vnd.suunto.sml+xml">
|
||||
<comment>Suunto Markup Language</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.suunto.com/schemas/sml" localName="sml"/>
|
||||
<glob pattern="*.sml"/>
|
||||
</mime-type>
|
||||
|
||||
|
||||
<!-- Maps -->
|
||||
|
||||
<mime-type type="application/vnd.garmin.img">
|
||||
<comment>Garmin IMG Map</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application-octet-stream"/>
|
||||
<magic>
|
||||
<match type="string" offset="16" value="DSKIMG"/>
|
||||
</magic>
|
||||
<glob pattern="*.img"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.garmin.jnx">
|
||||
<comment>Garmin JNX Map</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application-octet-stream"/>
|
||||
<glob pattern="*.jnx"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.garmin.gmap+xml">
|
||||
<comment>Garmin Map Product File</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.garmin.com/xmlschemas/MapProduct/v1" localName="MapProduct"/>
|
||||
<root-XML namespaceURI="http://www.garmin.com/xmlschemas/MapProduct/v2" localName="MapProduct"/>
|
||||
<glob pattern="*.xml"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="image/vnd.maptech.kap">
|
||||
<comment>BSB Nautical Chart</comment>
|
||||
<generic-icon name="image-x-generic"/>
|
||||
<glob pattern="*.kap"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.oziexplorer.map">
|
||||
<comment>OziExplorer Map File</comment>
|
||||
<sub-class-of type="text/plain"/>
|
||||
<generic-icon name="text-plain"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="OziExplorer Map Data File"/>
|
||||
</magic>
|
||||
<glob pattern="*.map"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.mapbox.mbtiles">
|
||||
<comment>MBTiles Map File</comment>
|
||||
<sub-class-of type="application/vnd.sqlite3"/>
|
||||
<generic-icon name="application/octet-stream"/>
|
||||
<glob pattern="*.mbtiles"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.twonav.rmap">
|
||||
<comment>TwoNav Raster Map File</comment>
|
||||
<sub-class-of type="application/octet-stream"/>
|
||||
<generic-icon name="application/octet-stream"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="CompeGPSRasterImage"/>
|
||||
</magic>
|
||||
<glob pattern="*.rmap"/>
|
||||
<glob pattern="*.rtmap"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.trekbuddy.tba">
|
||||
<comment>TrekBuddy Atlas</comment>
|
||||
<sub-class-of type="text/plain"/>
|
||||
<generic-icon name="text-plain"/>
|
||||
<magic>
|
||||
<match type="string" offset="0" value="Atlas 1.0"/>
|
||||
</magic>
|
||||
<glob pattern="*.tba"/>
|
||||
</mime-type>
|
||||
|
||||
<mime-type type="application/vnd.gpxsee.map+xml">
|
||||
<comment>GPXSee Map Definition File</comment>
|
||||
<sub-class-of type="application/xml"/>
|
||||
<generic-icon name="application-xml"/>
|
||||
<root-XML namespaceURI="http://www.gpxsee.org/map/1.0" localName="map"/>
|
||||
<root-XML namespaceURI="http://www.gpxsee.org/map/1.1" localName="map"/>
|
||||
<root-XML namespaceURI="http://www.gpxsee.org/map/1.2" localName="map"/>
|
||||
<root-XML namespaceURI="http://www.gpxsee.org/map/1.3" localName="map"/>
|
||||
<root-XML namespaceURI="http://www.gpxsee.org/map/1.4" localName="map"/>
|
||||
<glob pattern="*.xml"/>
|
||||
</mime-type>
|
||||
|
||||
</mime-info>
|
||||
|
102
pkg/gpxsee64.nsi
@ -7,7 +7,7 @@
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "7.37"
|
||||
!define VERSION "7.38"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
@ -116,14 +116,14 @@ Section "GPXSee" SEC_APP
|
||||
|
||||
; Associate file formats
|
||||
DetailPrint "Associating file types..."
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 8
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 9
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 10
|
||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 11
|
||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 12
|
||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 13
|
||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 14
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 15
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpx" "GPS Exchange Format" 11
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tcx" "Training Center XML" 16
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kml" "Keyhole Markup Language" 17
|
||||
!insertmacro FILE_ASSOCIATION_ADD "fit" "Flexible and Interoperable Data Transfer" 18
|
||||
!insertmacro FILE_ASSOCIATION_ADD "igc" "Flight Recorder Data Format" 19
|
||||
!insertmacro FILE_ASSOCIATION_ADD "nmea" "NMEA 0183 Data" 20
|
||||
!insertmacro FILE_ASSOCIATION_ADD "plt" "OziExplorer Track Point File" 21
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rte" "OziExplorer Route File" 22
|
||||
!insertmacro FILE_ASSOCIATION_ADD "wpt" "OziExplorer Waypoint File" 1
|
||||
!insertmacro FILE_ASSOCIATION_ADD "loc" "Geocaching.com Waypoint File" 2
|
||||
!insertmacro FILE_ASSOCIATION_ADD "slf" "Sigma Log File" 3
|
||||
@ -131,6 +131,47 @@ Section "GPXSee" SEC_APP
|
||||
!insertmacro FILE_ASSOCIATION_ADD "cup" "SeeYou CUP File" 5
|
||||
!insertmacro FILE_ASSOCIATION_ADD "gpi" "Garmin POI File" 6
|
||||
!insertmacro FILE_ASSOCIATION_ADD "sml" "Suunto Markup Language" 7
|
||||
!insertmacro FILE_ASSOCIATION_ADD "img" "Garmin IMG Map" 8
|
||||
!insertmacro FILE_ASSOCIATION_ADD "jnx" "Garmin JNX Map" 9
|
||||
!insertmacro FILE_ASSOCIATION_ADD "kap" "BSB Nautical Chart" 10
|
||||
!insertmacro FILE_ASSOCIATION_ADD "map" "OziExplorer Map File" 12
|
||||
!insertmacro FILE_ASSOCIATION_ADD "mbtiles" "MBTiles Map File" 13
|
||||
!insertmacro FILE_ASSOCIATION_ADD "rmap" "TwoNav Raster Map File" 14
|
||||
!insertmacro FILE_ASSOCIATION_ADD "tba" "TrekBuddy Atlas" 15
|
||||
|
||||
WriteRegStr HKCR "Applications\GPXSee.exe\shell\open\command" "" "$\"$INSTDIR\GPXSee.exe$\" $\"%1$\""
|
||||
WriteRegStr HKCR ".gpx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tcx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kml\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".fit\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".igc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".nmea\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".plt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rte\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".wpt\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".loc\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".slf\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".geojson\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".cup\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".gpi\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".sml\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".csv\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".json\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jpg\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jpeg\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".img\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".jnx\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".kap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".map\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".mbtiles\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".rtmap\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tar\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tba\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tif\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".tiff\OpenWithList" "GPXSee.exe" ""
|
||||
WriteRegStr HKCR ".xml\OpenWithList" "GPXSee.exe" ""
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
|
||||
SectionEnd
|
||||
@ -218,7 +259,7 @@ Section "Uninstall"
|
||||
Delete "$SMPROGRAMS\$StartMenuFolder\*.*"
|
||||
RMDir "$SMPROGRAMS\$StartMenuFolder"
|
||||
|
||||
; Remove File associations
|
||||
; Remove file associations
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tcx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kml"
|
||||
@ -234,6 +275,47 @@ Section "Uninstall"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "cup"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "gpi"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "sml"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "img"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "jnx"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "kap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "map"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "mbtiles"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "rmap"
|
||||
!insertmacro FILE_ASSOCIATION_REMOVE "tba"
|
||||
|
||||
DeleteRegValue HKCR ".gpx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tcx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".kml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".fit\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".igc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".nmea\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".plt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rte\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".wpt\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".loc\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".slf\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".geojson\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".cup\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".gpi\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".sml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".csv\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".json\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jpg\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jpeg\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".img\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".jnx\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".kap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".map\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".mbtiles\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".rtmap\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tar\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tba\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tif\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".tiff\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegValue HKCR ".xml\OpenWithList" "GPXSee.exe"
|
||||
DeleteRegKey HKCR "Applications\GPXSee.exe"
|
||||
|
||||
System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)'
|
||||
|
||||
SectionEnd
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "opengl.h"
|
||||
#include "gui.h"
|
||||
#include "settings.h"
|
||||
#include "mapaction.h"
|
||||
#include "app.h"
|
||||
|
||||
|
||||
@ -76,11 +77,25 @@ App::~App()
|
||||
|
||||
int App::run()
|
||||
{
|
||||
MapAction *lastReady = 0;
|
||||
QStringList args(arguments());
|
||||
|
||||
_gui->show();
|
||||
|
||||
QStringList args(arguments());
|
||||
for (int i = 1; i < args.count(); i++)
|
||||
_gui->openFile(args.at(i));
|
||||
for (int i = 1; i < args.count(); i++) {
|
||||
if (!_gui->openFile(args.at(i), true)) {
|
||||
MapAction *a;
|
||||
if (!_gui->loadMap(args.at(i), a, true))
|
||||
_gui->openFile(args.at(i), false);
|
||||
else {
|
||||
if (a)
|
||||
lastReady = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastReady)
|
||||
lastReady->trigger();
|
||||
|
||||
return exec();
|
||||
}
|
||||
@ -89,7 +104,18 @@ bool App::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::FileOpen) {
|
||||
QFileOpenEvent *e = static_cast<QFileOpenEvent *>(event);
|
||||
return _gui->openFile(e->file());
|
||||
|
||||
if (!_gui->openFile(e->file(), true)) {
|
||||
MapAction *a;
|
||||
if (!_gui->loadMap(e->file(), a, true))
|
||||
return _gui->openFile(e->file(), false);
|
||||
else {
|
||||
if (a)
|
||||
a->trigger();
|
||||
return true;
|
||||
}
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
return QApplication::event(event);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include "map/map.h"
|
||||
#include "popup.h"
|
||||
#include "tooltip.h"
|
||||
#include "areaitem.h"
|
||||
|
||||
|
||||
@ -22,7 +23,7 @@ QString AreaItem::info() const
|
||||
}
|
||||
|
||||
AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
|
||||
: GraphicsItem(parent), _area(area)
|
||||
: PlaneItem(parent), _area(area)
|
||||
{
|
||||
_map = map;
|
||||
_digitalZoom = 0;
|
||||
@ -158,7 +159,6 @@ void AreaItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||
Q_UNUSED(event);
|
||||
|
||||
_pen.setWidthF((_width + 1) * pow(2, -_digitalZoom));
|
||||
setZValue(zValue() + 1.0);
|
||||
update();
|
||||
}
|
||||
|
||||
@ -167,12 +167,5 @@ void AreaItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
Q_UNUSED(event);
|
||||
|
||||
_pen.setWidthF(_width * pow(2, -_digitalZoom));
|
||||
setZValue(zValue() - 1.0);
|
||||
update();
|
||||
}
|
||||
|
||||
void AreaItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Popup::show(event->screenPos(), info(), event->widget());
|
||||
QGraphicsItem::mousePressEvent(event);
|
||||
}
|
||||
|
@ -2,12 +2,9 @@
|
||||
#define AREAITEM_H
|
||||
|
||||
#include "data/area.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "tooltip.h"
|
||||
#include "planeitem.h"
|
||||
|
||||
class Map;
|
||||
|
||||
class AreaItem : public GraphicsItem
|
||||
class AreaItem : public PlaneItem
|
||||
{
|
||||
public:
|
||||
AreaItem(const Area &area, Map *map, GraphicsItem *parent = 0);
|
||||
@ -19,6 +16,7 @@ public:
|
||||
|
||||
const Area &area() const {return _area;}
|
||||
|
||||
RectC bounds() const {return _area.boundingRect();}
|
||||
void setMap(Map *map);
|
||||
|
||||
void setColor(const QColor &color);
|
||||
@ -27,17 +25,15 @@ public:
|
||||
void setStyle(Qt::PenStyle style);
|
||||
void setDigitalZoom(int zoom);
|
||||
|
||||
virtual QString info() const;
|
||||
QString info() const;
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
private:
|
||||
QPainterPath painterPath(const Polygon &polygon);
|
||||
void updatePainterPath();
|
||||
ToolTip toolTip() const;
|
||||
|
||||
Area _area;
|
||||
Map *_map;
|
||||
|
409
src/GUI/gui.cpp
@ -51,6 +51,7 @@
|
||||
#include "graphtab.h"
|
||||
#include "graphitem.h"
|
||||
#include "pathitem.h"
|
||||
#include "mapitem.h"
|
||||
#include "mapaction.h"
|
||||
#include "gui.h"
|
||||
|
||||
@ -130,11 +131,17 @@ void GUI::createMapActions()
|
||||
if (mapDir.isNull())
|
||||
return;
|
||||
|
||||
QString unused;
|
||||
QList<Map*> maps(MapList::loadMaps(mapDir, unused));
|
||||
QList<Map*> maps(MapList::loadMaps(mapDir));
|
||||
for (int i = 0; i < maps.count(); i++) {
|
||||
MapAction *a = createMapAction(maps.at(i));
|
||||
connect(a, SIGNAL(loaded()), this, SLOT(mapInitialized()));
|
||||
Map *map = maps.at(i);
|
||||
if (map->isValid()) {
|
||||
MapAction *a = createMapAction(map);
|
||||
connect(a, SIGNAL(loaded()), this, SLOT(mapInitialized()));
|
||||
} else {
|
||||
qWarning("%s: %s", qPrintable(map->path()),
|
||||
qPrintable(map->errorString()));
|
||||
delete map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,7 +166,7 @@ void GUI::mapInitialized()
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
} else {
|
||||
qWarning("%s: %s", qPrintable(map->name()), qPrintable(map->errorString()));
|
||||
qWarning("%s: %s", qPrintable(map->path()), qPrintable(map->errorString()));
|
||||
action->deleteLater();
|
||||
}
|
||||
}
|
||||
@ -306,10 +313,14 @@ void GUI::createActions()
|
||||
this);
|
||||
_loadMapAction->setMenuRole(QAction::NoRole);
|
||||
connect(_loadMapAction, SIGNAL(triggered()), this, SLOT(loadMap()));
|
||||
_loadMapDirAction = new QAction(QIcon(OPEN_FILE_ICON),
|
||||
tr("Load map directory..."), this);
|
||||
_loadMapDirAction->setMenuRole(QAction::NoRole);
|
||||
connect(_loadMapDirAction, SIGNAL(triggered()), this, SLOT(loadMapDir()));
|
||||
_clearMapCacheAction = new QAction(tr("Clear tile cache"), this);
|
||||
_clearMapCacheAction->setEnabled(false);
|
||||
_clearMapCacheAction->setMenuRole(QAction::NoRole);
|
||||
connect(_clearMapCacheAction, SIGNAL(triggered()), _mapView,
|
||||
connect(_clearMapCacheAction, SIGNAL(triggered()), this,
|
||||
SLOT(clearMapCache()));
|
||||
_nextMapAction = new QAction(tr("Next map"), this);
|
||||
_nextMapAction->setMenuRole(QAction::NoRole);
|
||||
@ -519,6 +530,7 @@ void GUI::createMenus()
|
||||
_mapMenu->addActions(_mapsActionGroup->actions());
|
||||
_mapsEnd = _mapMenu->addSeparator();
|
||||
_mapMenu->addAction(_loadMapAction);
|
||||
_mapMenu->addAction(_loadMapDirAction);
|
||||
_mapMenu->addAction(_clearMapCacheAction);
|
||||
_mapMenu->addSeparator();
|
||||
_mapMenu->addAction(_showCoordinatesAction);
|
||||
@ -759,101 +771,45 @@ void GUI::paths()
|
||||
|
||||
void GUI::openFile()
|
||||
{
|
||||
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"),
|
||||
_dataDir, Data::formats());
|
||||
QStringList list = files;
|
||||
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open file"),
|
||||
_dataDir, Data::formats()));
|
||||
|
||||
for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
|
||||
openFile(*it);
|
||||
if (!list.isEmpty())
|
||||
_dataDir = QFileInfo(list.first()).path();
|
||||
for (int i = 0; i < files.size(); i++)
|
||||
openFile(files.at(i));
|
||||
if (!files.isEmpty())
|
||||
_dataDir = QFileInfo(files.last()).path();
|
||||
}
|
||||
|
||||
bool GUI::openFile(const QString &fileName)
|
||||
bool GUI::openFile(const QString &fileName, bool silent)
|
||||
{
|
||||
if (fileName.isEmpty() || _files.contains(fileName))
|
||||
return false;
|
||||
|
||||
if (loadFile(fileName)) {
|
||||
_files.append(fileName);
|
||||
_browser->setCurrent(fileName);
|
||||
_fileActionGroup->setEnabled(true);
|
||||
_navigationActionGroup->setEnabled(true);
|
||||
|
||||
updateNavigationActions();
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
|
||||
if (_files.contains(fileName))
|
||||
return true;
|
||||
} else {
|
||||
if (_files.isEmpty())
|
||||
_fileActionGroup->setEnabled(false);
|
||||
|
||||
if (!loadFile(fileName, silent))
|
||||
return false;
|
||||
}
|
||||
|
||||
_files.append(fileName);
|
||||
_browser->setCurrent(fileName);
|
||||
_fileActionGroup->setEnabled(true);
|
||||
// Explicitly enable the reload action as it may be disabled by loadMapDir()
|
||||
_reloadFileAction->setEnabled(true);
|
||||
_navigationActionGroup->setEnabled(true);
|
||||
|
||||
updateNavigationActions();
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GUI::loadFile(const QString &fileName)
|
||||
bool GUI::loadFile(const QString &fileName, bool silent)
|
||||
{
|
||||
Data data(fileName);
|
||||
QList<QList<GraphItem*> > graphs;
|
||||
QList<PathItem*> paths;
|
||||
Data data(fileName, !silent);
|
||||
|
||||
if (data.isValid()) {
|
||||
for (int i = 0; i < data.tracks().count(); i++) {
|
||||
const Track &track = data.tracks().at(i);
|
||||
_trackDistance += track.distance();
|
||||
_time += track.time();
|
||||
_movingTime += track.movingTime();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
const QDateTime date = track.date().toTimeZone(
|
||||
_options.timeZone.zone());
|
||||
#else // ENABLE_TIMEZONES
|
||||
const QDateTime &date = track.date();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
_dateRange.second = date;
|
||||
}
|
||||
_trackCount += data.tracks().count();
|
||||
|
||||
for (int i = 0; i < data.routes().count(); i++)
|
||||
_routeDistance += data.routes().at(i).distance();
|
||||
_routeCount += data.routes().count();
|
||||
|
||||
_waypointCount += data.waypoints().count();
|
||||
_areaCount += data.areas().count();
|
||||
|
||||
if (_pathName.isNull()) {
|
||||
if (data.tracks().count() == 1 && !data.routes().count())
|
||||
_pathName = data.tracks().first().name();
|
||||
else if (data.routes().count() == 1 && !data.tracks().count())
|
||||
_pathName = data.routes().first().name();
|
||||
} else
|
||||
_pathName = QString();
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++)
|
||||
graphs.append(_tabs.at(i)->loadData(data));
|
||||
if (updateGraphTabs())
|
||||
_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)));
|
||||
}
|
||||
}
|
||||
|
||||
loadData(data);
|
||||
return true;
|
||||
} else {
|
||||
} else if (!silent) {
|
||||
updateNavigationActions();
|
||||
updateStatusBarInfo();
|
||||
updateWindowTitle();
|
||||
@ -865,25 +821,83 @@ bool GUI::loadFile(const QString &fileName)
|
||||
error.append("\n" + tr("Line: %1").arg(data.errorLine()));
|
||||
QMessageBox::critical(this, APP_NAME, error);
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
void GUI::loadData(const Data &data)
|
||||
{
|
||||
QList<QList<GraphItem*> > graphs;
|
||||
QList<PathItem*> paths;
|
||||
|
||||
for (int i = 0; i < data.tracks().count(); i++) {
|
||||
const Track &track = data.tracks().at(i);
|
||||
_trackDistance += track.distance();
|
||||
_time += track.time();
|
||||
_movingTime += track.movingTime();
|
||||
#ifdef ENABLE_TIMEZONES
|
||||
const QDateTime date = track.date().toTimeZone(
|
||||
_options.timeZone.zone());
|
||||
#else // ENABLE_TIMEZONES
|
||||
const QDateTime &date = track.date();
|
||||
#endif // ENABLE_TIMEZONES
|
||||
if (_dateRange.first.isNull() || _dateRange.first > date)
|
||||
_dateRange.first = date;
|
||||
if (_dateRange.second.isNull() || _dateRange.second < date)
|
||||
_dateRange.second = date;
|
||||
}
|
||||
_trackCount += data.tracks().count();
|
||||
|
||||
for (int i = 0; i < data.routes().count(); i++)
|
||||
_routeDistance += data.routes().at(i).distance();
|
||||
_routeCount += data.routes().count();
|
||||
|
||||
_waypointCount += data.waypoints().count();
|
||||
_areaCount += data.areas().count();
|
||||
|
||||
if (_pathName.isNull()) {
|
||||
if (data.tracks().count() == 1 && !data.routes().count())
|
||||
_pathName = data.tracks().first().name();
|
||||
else if (data.routes().count() == 1 && !data.tracks().count())
|
||||
_pathName = data.routes().first().name();
|
||||
} else
|
||||
_pathName = QString();
|
||||
|
||||
for (int i = 0; i < _tabs.count(); i++)
|
||||
graphs.append(_tabs.at(i)->loadData(data));
|
||||
if (updateGraphTabs())
|
||||
_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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::openPOIFile()
|
||||
{
|
||||
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open POI file"),
|
||||
_poiDir, Data::formats());
|
||||
QStringList list = files;
|
||||
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open POI file"),
|
||||
_poiDir, Data::formats()));
|
||||
|
||||
for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
|
||||
openPOIFile(*it);
|
||||
if (!list.isEmpty())
|
||||
_poiDir = QFileInfo(list.first()).path();
|
||||
for (int i = 0; i < files.size(); i++)
|
||||
openPOIFile(files.at(i));
|
||||
if (!files.isEmpty())
|
||||
_poiDir = QFileInfo(files.last()).path();
|
||||
}
|
||||
|
||||
bool GUI::openPOIFile(const QString &fileName)
|
||||
{
|
||||
if (fileName.isEmpty() || _poi->files().contains(fileName))
|
||||
return false;
|
||||
if (_poi->files().contains(fileName))
|
||||
return true;
|
||||
|
||||
if (_poi->loadFile(fileName)) {
|
||||
_mapView->showPOI(true);
|
||||
@ -1227,7 +1241,7 @@ void GUI::plotMainPage(QPainter *painter, const QRectF &rect, qreal ratio,
|
||||
sc = 1;
|
||||
}
|
||||
|
||||
MapView::PlotFlags flags = MapView::NoFlags;
|
||||
MapView::PlotFlags flags;
|
||||
if (_options.hiresPrint)
|
||||
flags |= MapView::HiRes;
|
||||
if (expand)
|
||||
@ -1427,45 +1441,73 @@ void GUI::showGraphSliderInfo(bool show)
|
||||
|
||||
void GUI::loadMap()
|
||||
{
|
||||
QStringList files = QFileDialog::getOpenFileNames(this, tr("Open map file"),
|
||||
_mapDir, MapList::formats());
|
||||
QStringList list = files;
|
||||
QStringList files(QFileDialog::getOpenFileNames(this, tr("Open map file"),
|
||||
_mapDir, MapList::formats()));
|
||||
MapAction *a, *lastReady = 0;
|
||||
|
||||
for (QStringList::Iterator it = list.begin(); it != list.end(); it++)
|
||||
loadMap(*it);
|
||||
if (!list.isEmpty())
|
||||
_mapDir = QFileInfo(list.first()).path();
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
if (loadMap(files.at(i), a) && a)
|
||||
lastReady = a;
|
||||
}
|
||||
if (!files.isEmpty())
|
||||
_mapDir = QFileInfo(files.last()).path();
|
||||
if (lastReady)
|
||||
lastReady->trigger();
|
||||
}
|
||||
|
||||
bool GUI::loadMap(const QString &fileName)
|
||||
static MapAction *findMapAction(const QList<QAction*> &mapActions,
|
||||
const Map *map)
|
||||
{
|
||||
// On OS X fileName may be a directory!
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
QString error;
|
||||
QList<Map*> maps = MapList::loadMaps(fileName, error);
|
||||
if (maps.isEmpty()) {
|
||||
error = tr("Error loading map:") + "\n\n"
|
||||
+ fileName + "\n\n" + error;
|
||||
QMessageBox::critical(this, APP_NAME, error);
|
||||
return false;
|
||||
for (int i = 0; i < mapActions.count(); i++) {
|
||||
const Map *m = mapActions.at(i)->data().value<Map*>();
|
||||
if (map->path() == m->path())
|
||||
return static_cast<MapAction*>(mapActions.at(i));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
|
||||
{
|
||||
QList<Map*> maps(MapList::loadMaps(fileName));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
MapAction *lastReady = 0;
|
||||
bool valid = false;
|
||||
|
||||
for (int i = 0; i < maps.size(); i++) {
|
||||
Map *map = maps.at(i);
|
||||
MapAction *a = createMapAction(map);
|
||||
_mapMenu->insertAction(_mapsEnd, a);
|
||||
if (map->isReady()) {
|
||||
a->trigger();
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
} else
|
||||
connect(a, SIGNAL(loaded()), this, SLOT(mapLoaded()));
|
||||
MapAction *a;
|
||||
|
||||
if (!(a = findMapAction(existingActions, map))) {
|
||||
if (!map->isValid()) {
|
||||
if (!silent)
|
||||
QMessageBox::critical(this, APP_NAME,
|
||||
tr("Error loading map:") + "\n\n" + map->path() + "\n\n"
|
||||
+ map->errorString());
|
||||
delete map;
|
||||
} else {
|
||||
valid = true;
|
||||
a = createMapAction(map);
|
||||
_mapMenu->insertAction(_mapsEnd, a);
|
||||
|
||||
if (map->isReady()) {
|
||||
lastReady = a;
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
} else
|
||||
connect(a, SIGNAL(loaded()), this, SLOT(mapLoaded()));
|
||||
}
|
||||
} else {
|
||||
valid = true;
|
||||
map = a->data().value<Map*>();
|
||||
if (map->isReady())
|
||||
lastReady = a;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
action = lastReady;
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
void GUI::mapLoaded()
|
||||
@ -1478,13 +1520,94 @@ void GUI::mapLoaded()
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
} else {
|
||||
QString error = tr("Error loading map:") + "\n\n"
|
||||
+ map->name() + "\n\n" + map->errorString();
|
||||
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n"
|
||||
+ map->errorString();
|
||||
QMessageBox::critical(this, APP_NAME, error);
|
||||
action->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::mapLoadedDir()
|
||||
{
|
||||
MapAction *action = static_cast<MapAction*>(QObject::sender());
|
||||
Map *map = action->data().value<Map*>();
|
||||
|
||||
if (map->isValid()) {
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
QList<MapAction*> actions;
|
||||
actions.append(action);
|
||||
_mapView->loadMaps(actions);
|
||||
} else {
|
||||
QString error = tr("Error loading map:") + "\n\n" + map->path() + "\n\n"
|
||||
+ map->errorString();
|
||||
QMessageBox::critical(this, APP_NAME, error);
|
||||
action->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void GUI::loadMapDir()
|
||||
{
|
||||
QString dir(QFileDialog::getExistingDirectory(this,
|
||||
tr("Select map directory"), _mapDir, QFileDialog::ShowDirsOnly));
|
||||
if (dir.isEmpty())
|
||||
return;
|
||||
|
||||
QList<Map*> maps(MapList::loadMaps(dir));
|
||||
QList<MapAction*> actions;
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
QFileInfo fi(dir);
|
||||
QMenu *menu = new QMenu(fi.fileName());
|
||||
|
||||
for (int i = 0; i < maps.size(); i++) {
|
||||
Map *map = maps.at(i);
|
||||
MapAction *a;
|
||||
|
||||
if (!(a = findMapAction(existingActions, map))) {
|
||||
if (!map->isValid()) {
|
||||
QMessageBox::critical(this, APP_NAME, tr("Error loading map:")
|
||||
+ "\n\n" + map->path() + "\n\n" + map->errorString());
|
||||
delete map;
|
||||
} else {
|
||||
a = createMapAction(map);
|
||||
menu->addAction(a);
|
||||
|
||||
if (map->isReady()) {
|
||||
_showMapAction->setEnabled(true);
|
||||
_clearMapCacheAction->setEnabled(true);
|
||||
actions.append(a);
|
||||
} else
|
||||
connect(a, SIGNAL(loaded()), this, SLOT(mapLoadedDir()));
|
||||
}
|
||||
} else {
|
||||
map = a->data().value<Map*>();
|
||||
if (map->isReady())
|
||||
actions.append(a);
|
||||
}
|
||||
}
|
||||
|
||||
_mapView->loadMaps(actions);
|
||||
|
||||
if (menu->isEmpty())
|
||||
delete menu;
|
||||
else {
|
||||
menu->setStyleSheet("QMenu { menu-scrollable: 1; }");
|
||||
_mapMenu->insertMenu(_mapsEnd, menu);
|
||||
}
|
||||
|
||||
_mapDir = fi.absolutePath();
|
||||
_areaCount += maps.size();
|
||||
_fileActionGroup->setEnabled(true);
|
||||
_reloadFileAction->setEnabled(false);
|
||||
}
|
||||
|
||||
void GUI::clearMapCache()
|
||||
{
|
||||
if (QMessageBox::question(this, APP_NAME,
|
||||
tr("Clear the map tile cache?")) == QMessageBox::Yes)
|
||||
_mapView->clearMapCache();
|
||||
}
|
||||
|
||||
void GUI::updateStatusBarInfo()
|
||||
{
|
||||
if (_files.count() == 0)
|
||||
@ -1535,7 +1658,7 @@ void GUI::nextMap()
|
||||
if (!checked)
|
||||
return;
|
||||
|
||||
QList<QAction*> maps = _mapsActionGroup->actions();
|
||||
QList<QAction*> maps(_mapsActionGroup->actions());
|
||||
for (int i = 1; i < maps.size(); i++) {
|
||||
int next = (maps.indexOf(checked) + i) % maps.count();
|
||||
if (maps.at(next)->isEnabled()) {
|
||||
@ -1551,7 +1674,7 @@ void GUI::prevMap()
|
||||
if (!checked)
|
||||
return;
|
||||
|
||||
QList<QAction*> maps = _mapsActionGroup->actions();
|
||||
QList<QAction*> maps(_mapsActionGroup->actions());
|
||||
for (int i = 1; i < maps.size(); i++) {
|
||||
int prev = (maps.indexOf(checked) + maps.count() - i) % maps.count();
|
||||
if (maps.at(prev)->isEnabled()) {
|
||||
@ -1777,9 +1900,25 @@ void GUI::dragEnterEvent(QDragEnterEvent *event)
|
||||
|
||||
void GUI::dropEvent(QDropEvent *event)
|
||||
{
|
||||
QList<QUrl> urls = event->mimeData()->urls();
|
||||
for (int i = 0; i < urls.size(); i++)
|
||||
openFile(urls.at(i).toLocalFile());
|
||||
MapAction *lastReady = 0;
|
||||
QList<QUrl> urls(event->mimeData()->urls());
|
||||
|
||||
for (int i = 0; i < urls.size(); i++) {
|
||||
QString file(urls.at(i).toLocalFile());
|
||||
|
||||
if (!openFile(file, true)) {
|
||||
MapAction *a;
|
||||
if (!loadMap(file, a, true))
|
||||
openFile(file, false);
|
||||
else {
|
||||
if (a)
|
||||
lastReady = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastReady)
|
||||
lastReady->trigger();
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
@ -2397,7 +2536,7 @@ void GUI::readSettings()
|
||||
|
||||
QAction *GUI::mapAction(const QString &name)
|
||||
{
|
||||
QList<QAction *> maps = _mapsActionGroup->actions();
|
||||
QList<QAction *> maps(_mapsActionGroup->actions());
|
||||
|
||||
// Last map
|
||||
for (int i = 0; i < maps.count(); i++) {
|
||||
|
@ -30,6 +30,7 @@ class Map;
|
||||
class POI;
|
||||
class QScreen;
|
||||
class MapAction;
|
||||
class Data;
|
||||
|
||||
class GUI : public QMainWindow
|
||||
{
|
||||
@ -38,7 +39,9 @@ class GUI : public QMainWindow
|
||||
public:
|
||||
GUI();
|
||||
|
||||
bool openFile(const QString &fileName);
|
||||
bool openFile(const QString &fileName, bool silent = false);
|
||||
bool loadMap(const QString &fileName, MapAction *&action,
|
||||
bool silent = false);
|
||||
void show();
|
||||
|
||||
private slots:
|
||||
@ -62,9 +65,11 @@ private slots:
|
||||
void showTracks(bool show);
|
||||
void showRoutes(bool show);
|
||||
void loadMap();
|
||||
void loadMapDir();
|
||||
void nextMap();
|
||||
void prevMap();
|
||||
void openOptions();
|
||||
void clearMapCache();
|
||||
|
||||
void mapChanged();
|
||||
void graphChanged(int);
|
||||
@ -91,6 +96,7 @@ private slots:
|
||||
void logicalDotsPerInchChanged(qreal dpi);
|
||||
|
||||
void mapLoaded();
|
||||
void mapLoadedDir();
|
||||
void mapInitialized();
|
||||
|
||||
private:
|
||||
@ -117,8 +123,8 @@ private:
|
||||
void createBrowser();
|
||||
|
||||
bool openPOIFile(const QString &fileName);
|
||||
bool loadFile(const QString &fileName);
|
||||
bool loadMap(const QString &fileName);
|
||||
bool loadFile(const QString &fileName, bool silent = false);
|
||||
void loadData(const Data &data);
|
||||
void updateStatusBarInfo();
|
||||
void updateWindowTitle();
|
||||
void updateNavigationActions();
|
||||
@ -172,6 +178,7 @@ private:
|
||||
QAction *_showMapAction;
|
||||
QAction *_fullscreenAction;
|
||||
QAction *_loadMapAction;
|
||||
QAction *_loadMapDirAction;
|
||||
QAction *_clearMapCacheAction;
|
||||
QAction *_showGraphsAction;
|
||||
QAction *_showGraphGridAction;
|
||||
|
230
src/GUI/mapitem.cpp
Normal file
@ -0,0 +1,230 @@
|
||||
#include <cmath>
|
||||
#include <QCursor>
|
||||
#include <QPainter>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include "map/map.h"
|
||||
#include "mapaction.h"
|
||||
#include "popup.h"
|
||||
#include "tooltip.h"
|
||||
#include "mapitem.h"
|
||||
|
||||
|
||||
static void growLeft(Map *map, const Coordinates &c, QRectF &rect)
|
||||
{
|
||||
QPointF p(map->ll2xy(c));
|
||||
|
||||
if (p.x() < rect.left())
|
||||
rect.setLeft(p.x());
|
||||
}
|
||||
|
||||
static void growRight(Map *map, const Coordinates &c, QRectF &rect)
|
||||
{
|
||||
|
||||
QPointF p(map->ll2xy(c));
|
||||
|
||||
if (p.x() > rect.right())
|
||||
rect.setRight(p.x());
|
||||
}
|
||||
|
||||
static void growTop(Map *map, const Coordinates &c, QRectF &rect)
|
||||
{
|
||||
QPointF p(map->ll2xy(c));
|
||||
|
||||
if (p.y() > rect.top())
|
||||
rect.setTop(p.y());
|
||||
}
|
||||
|
||||
static void growBottom(Map *map, const Coordinates &c, QRectF &rect)
|
||||
{
|
||||
QPointF p(map->ll2xy(c));
|
||||
|
||||
if (p.y() < rect.bottom())
|
||||
rect.setBottom(p.y());
|
||||
}
|
||||
|
||||
static QRectF bbox(const RectC &rect, Map *map, int samples = 100)
|
||||
{
|
||||
if (!rect.isValid())
|
||||
return QRectF();
|
||||
|
||||
double dx = rect.width() / samples;
|
||||
double dy = rect.height() / samples;
|
||||
|
||||
QPointF tl(map->ll2xy(rect.topLeft()));
|
||||
QPointF br(map->ll2xy(rect.bottomRight()));
|
||||
QRectF prect(tl, br);
|
||||
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double x = remainder(rect.left() + i * dx, 360.0);
|
||||
growTop(map, Coordinates(x, rect.bottom()), prect);
|
||||
growBottom(map, Coordinates(x, rect.top()), prect);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double y = rect.bottom() + i * dy;
|
||||
growLeft(map, Coordinates(rect.left(), y), prect);
|
||||
growRight(map, Coordinates(rect.right(), y), prect);
|
||||
}
|
||||
|
||||
return prect;
|
||||
}
|
||||
|
||||
QString MapItem::info() const
|
||||
{
|
||||
ToolTip tt;
|
||||
|
||||
if (!_name.isEmpty())
|
||||
tt.insert(tr("Name"), _name);
|
||||
if (!_fileName.isEmpty())
|
||||
tt.insert(tr("File"), _fileName);
|
||||
|
||||
return tt.toString();
|
||||
}
|
||||
|
||||
MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
|
||||
: PlaneItem(parent)
|
||||
{
|
||||
Map *src = action->data().value<Map*>();
|
||||
Q_ASSERT(map->isReady());
|
||||
|
||||
_name = src->name();
|
||||
_fileName = src->path();
|
||||
_bounds = src->llBounds();
|
||||
|
||||
connect(this, SIGNAL(triggered()), action, SLOT(trigger()));
|
||||
|
||||
_map = map;
|
||||
_digitalZoom = 0;
|
||||
|
||||
_width = 2;
|
||||
_opacity = 0.5;
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
_pen = QPen(brush, _width);
|
||||
|
||||
updatePainterPath();
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
void MapItem::updatePainterPath()
|
||||
{
|
||||
_painterPath = QPainterPath();
|
||||
|
||||
QRectF r(bbox(_bounds, _map));
|
||||
|
||||
if (r.left() > r.right()) {
|
||||
QRectF r1(bbox(RectC(_bounds.topLeft(),
|
||||
Coordinates(180, _bounds.bottomRight().lat())), _map));
|
||||
QRectF r2(bbox(RectC(Coordinates(-180, _bounds.topLeft().lat()),
|
||||
_bounds.bottomRight()), _map));
|
||||
|
||||
_painterPath.addRect(r1);
|
||||
_painterPath.addRect(r2);
|
||||
} else
|
||||
_painterPath.addRect(r);
|
||||
}
|
||||
|
||||
void MapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(option);
|
||||
Q_UNUSED(widget);
|
||||
|
||||
painter->setPen(_width ? _pen : QPen(Qt::NoPen));
|
||||
painter->drawPath(_painterPath);
|
||||
painter->fillPath(_painterPath, _brush);
|
||||
|
||||
//QPen p = QPen(QBrush(Qt::red), 0);
|
||||
//painter->setPen(p);
|
||||
//painter->drawRect(boundingRect());
|
||||
}
|
||||
|
||||
void MapItem::setMap(Map *map)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
_map = map;
|
||||
|
||||
updatePainterPath();
|
||||
}
|
||||
|
||||
void MapItem::setColor(const QColor &color)
|
||||
{
|
||||
if (_pen.color() == color)
|
||||
return;
|
||||
|
||||
QColor bc(color);
|
||||
bc.setAlphaF(_opacity * color.alphaF());
|
||||
|
||||
_pen.setColor(color);
|
||||
_brush = QBrush(bc);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapItem::setOpacity(qreal opacity)
|
||||
{
|
||||
if (_opacity == opacity)
|
||||
return;
|
||||
|
||||
_opacity = opacity;
|
||||
QColor bc(_pen.color());
|
||||
bc.setAlphaF(_opacity * _pen.color().alphaF());
|
||||
_brush = QBrush(bc);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void MapItem::setWidth(qreal width)
|
||||
{
|
||||
if (_width == width)
|
||||
return;
|
||||
|
||||
prepareGeometryChange();
|
||||
|
||||
_width = width;
|
||||
_pen.setWidthF(_width * pow(2, -_digitalZoom));
|
||||
}
|
||||
|
||||
void MapItem::setStyle(Qt::PenStyle style)
|
||||
{
|
||||
if (_pen.style() == style)
|
||||
return;
|
||||
|
||||
_pen.setStyle(style);
|
||||
update();
|
||||
}
|
||||
|
||||
void MapItem::setDigitalZoom(int zoom)
|
||||
{
|
||||
if (_digitalZoom == zoom)
|
||||
return;
|
||||
|
||||
prepareGeometryChange();
|
||||
|
||||
_digitalZoom = zoom;
|
||||
_pen.setWidthF(_width * pow(2, -_digitalZoom));
|
||||
}
|
||||
|
||||
void MapItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
_pen.setWidthF((_width + 1) * pow(2, -_digitalZoom));
|
||||
update();
|
||||
}
|
||||
|
||||
void MapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
_pen.setWidthF(_width * pow(2, -_digitalZoom));
|
||||
update();
|
||||
}
|
||||
|
||||
void MapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
|
||||
emit triggered();
|
||||
}
|
57
src/GUI/mapitem.h
Normal file
@ -0,0 +1,57 @@
|
||||
#ifndef MAPITEM_H
|
||||
#define MAPITEM_H
|
||||
|
||||
#include "planeitem.h"
|
||||
|
||||
class MapAction;
|
||||
|
||||
class MapItem : public QObject, public PlaneItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapItem(MapAction *action, Map *map, GraphicsItem *parent = 0);
|
||||
|
||||
QPainterPath shape() const {return _painterPath;}
|
||||
QRectF boundingRect() const {return _painterPath.boundingRect();}
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget);
|
||||
|
||||
RectC bounds() const {return _bounds;}
|
||||
void setMap(Map *map);
|
||||
|
||||
void setColor(const QColor &color);
|
||||
void setOpacity(qreal opacity);
|
||||
void setWidth(qreal width);
|
||||
void setStyle(Qt::PenStyle style);
|
||||
void setDigitalZoom(int zoom);
|
||||
|
||||
QString info() const;
|
||||
|
||||
signals:
|
||||
void triggered();
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
private:
|
||||
void updatePainterPath();
|
||||
|
||||
RectC _bounds;
|
||||
QString _name;
|
||||
QString _fileName;
|
||||
|
||||
Map *_map;
|
||||
int _digitalZoom;
|
||||
|
||||
qreal _width;
|
||||
QPen _pen;
|
||||
QBrush _brush;
|
||||
qreal _opacity;
|
||||
|
||||
QPainterPath _painterPath;
|
||||
};
|
||||
|
||||
#endif // MAPITEM_H
|
@ -15,8 +15,10 @@
|
||||
#include "areaitem.h"
|
||||
#include "scaleitem.h"
|
||||
#include "coordinatesitem.h"
|
||||
#include "mapitem.h"
|
||||
#include "keys.h"
|
||||
#include "graphicsscene.h"
|
||||
#include "mapaction.h"
|
||||
#include "mapview.h"
|
||||
|
||||
|
||||
@ -27,6 +29,20 @@
|
||||
#define COORDINATES_OFFSET SCALE_OFFSET
|
||||
|
||||
|
||||
template<typename T>
|
||||
static void updateZValues(T &items)
|
||||
{
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const QGraphicsItem *ai = items.at(i);
|
||||
for (int j = 0; j < items.size(); j++) {
|
||||
QGraphicsItem *aj = items[j];
|
||||
if (aj->boundingRect().contains(ai->boundingRect()))
|
||||
aj->setZValue(qMin(ai->zValue() - 1, aj->zValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
: QGraphicsView(parent)
|
||||
{
|
||||
@ -39,7 +55,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
||||
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setRenderHint(QPainter::Antialiasing, true);
|
||||
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
|
||||
setResizeAnchor(QGraphicsView::AnchorViewCenter);
|
||||
setAcceptDrops(false);
|
||||
|
||||
@ -170,18 +186,19 @@ void MapView::addArea(const Area &area)
|
||||
}
|
||||
|
||||
AreaItem *ai = new AreaItem(area, _map);
|
||||
_areas.append(ai);
|
||||
_ar |= ai->area().boundingRect();
|
||||
ai->setColor(_palette.nextColor());
|
||||
ai->setWidth(_areaWidth);
|
||||
ai->setStyle(_areaStyle);
|
||||
ai->setOpacity(_areaOpacity);
|
||||
ai->setDigitalZoom(_digitalZoom);
|
||||
ai->setVisible(_showAreas);
|
||||
|
||||
_scene->addItem(ai);
|
||||
_ar |= ai->bounds();
|
||||
_areas.append(ai);
|
||||
|
||||
if (_showAreas)
|
||||
addPOI(_poi->points(ai->area()));
|
||||
addPOI(_poi->points(ai->bounds()));
|
||||
}
|
||||
|
||||
void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
|
||||
@ -205,6 +222,26 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
|
||||
}
|
||||
}
|
||||
|
||||
MapItem *MapView::addMap(MapAction *map)
|
||||
{
|
||||
MapItem *mi = new MapItem(map, _map);
|
||||
mi->setColor(_palette.nextColor());
|
||||
mi->setWidth(_areaWidth);
|
||||
mi->setStyle(_areaStyle);
|
||||
mi->setOpacity(_areaOpacity);
|
||||
mi->setDigitalZoom(_digitalZoom);
|
||||
mi->setVisible(_showAreas);
|
||||
|
||||
_scene->addItem(mi);
|
||||
_ar |= mi->bounds();
|
||||
_areas.append(mi);
|
||||
|
||||
if (_showAreas)
|
||||
addPOI(_poi->points(mi->bounds()));
|
||||
|
||||
return mi;
|
||||
}
|
||||
|
||||
QList<PathItem *> MapView::loadData(const Data &data)
|
||||
{
|
||||
QList<PathItem *> paths;
|
||||
@ -227,18 +264,37 @@ QList<PathItem *> MapView::loadData(const Data &data)
|
||||
else
|
||||
updatePOIVisibility();
|
||||
|
||||
if (!data.areas().isEmpty())
|
||||
updateZValues(_areas);
|
||||
|
||||
centerOn(contentCenter());
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void MapView::loadMaps(const QList<MapAction *> &maps)
|
||||
{
|
||||
int zoom = _map->zoom();
|
||||
|
||||
for (int i = 0; i < maps.size(); i++)
|
||||
addMap(maps.at(i));
|
||||
|
||||
if (fitMapZoom() != zoom)
|
||||
rescale();
|
||||
else
|
||||
updatePOIVisibility();
|
||||
|
||||
updateZValues(_areas);
|
||||
|
||||
centerOn(contentCenter());
|
||||
}
|
||||
|
||||
int MapView::fitMapZoom() const
|
||||
{
|
||||
RectC br = _tr | _rr | _wr | _ar;
|
||||
|
||||
return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
|
||||
br.isNull() ? RectC(_map->xy2ll(_map->bounds().topLeft()),
|
||||
_map->xy2ll(_map->bounds().bottomRight())) : br);
|
||||
br.isNull() ? _map->llBounds() : br);
|
||||
}
|
||||
|
||||
QPointF MapView::contentCenter() const
|
||||
@ -373,7 +429,7 @@ void MapView::updatePOI()
|
||||
addPOI(_poi->points(_routes.at(i)->path()));
|
||||
if (_showAreas)
|
||||
for (int i = 0; i < _areas.size(); i++)
|
||||
addPOI(_poi->points(_areas.at(i)->area()));
|
||||
addPOI(_poi->points(_areas.at(i)->bounds()));
|
||||
if (_showWaypoints)
|
||||
for (int i = 0; i< _waypoints.size(); i++)
|
||||
addPOI(_poi->points(_waypoints.at(i)->waypoint()));
|
||||
@ -504,6 +560,10 @@ void MapView::wheelEvent(QWheelEvent *event)
|
||||
|
||||
void MapView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QGraphicsView::mouseDoubleClickEvent(event);
|
||||
if (event->isAccepted())
|
||||
return;
|
||||
|
||||
if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
|
||||
return;
|
||||
|
||||
|
@ -29,10 +29,12 @@ class ScaleItem;
|
||||
class CoordinatesItem;
|
||||
class PathItem;
|
||||
class GraphItem;
|
||||
class AreaItem;
|
||||
class PlaneItem;
|
||||
class MapItem;
|
||||
class Area;
|
||||
class GraphicsScene;
|
||||
class QTimeZone;
|
||||
class MapAction;
|
||||
|
||||
class MapView : public QGraphicsView
|
||||
{
|
||||
@ -49,6 +51,7 @@ public:
|
||||
MapView(Map *map, POI *poi, QWidget *parent = 0);
|
||||
|
||||
QList<PathItem *> loadData(const Data &data);
|
||||
void loadMaps(const QList<MapAction*> &maps);
|
||||
|
||||
void setPalette(const Palette &palette);
|
||||
void setPOI(POI *poi);
|
||||
@ -108,6 +111,7 @@ private:
|
||||
|
||||
PathItem *addTrack(const Track &track);
|
||||
PathItem *addRoute(const Route &route);
|
||||
MapItem *addMap(MapAction *map);
|
||||
void addArea(const Area &area);
|
||||
void addWaypoints(const QVector<Waypoint> &waypoints);
|
||||
void addPOI(const QList<Waypoint> &waypoints);
|
||||
@ -140,7 +144,7 @@ private:
|
||||
QList<TrackItem*> _tracks;
|
||||
QList<RouteItem*> _routes;
|
||||
QList<WaypointItem*> _waypoints;
|
||||
QList<AreaItem*> _areas;
|
||||
QList<PlaneItem*> _areas;
|
||||
POIHash _pois;
|
||||
|
||||
RectC _tr, _rr, _wr, _ar;
|
||||
|
24
src/GUI/planeitem.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef PLANEITEM_H
|
||||
#define PLANEITEM_H
|
||||
|
||||
#include "common/rectc.h"
|
||||
#include "graphicsscene.h"
|
||||
|
||||
class Map;
|
||||
|
||||
class PlaneItem : public GraphicsItem
|
||||
{
|
||||
public:
|
||||
PlaneItem(GraphicsItem *parent = 0) : GraphicsItem(parent) {}
|
||||
|
||||
virtual RectC bounds() const = 0;
|
||||
virtual void setMap(Map *map) = 0;
|
||||
|
||||
virtual void setColor(const QColor &color) = 0;
|
||||
virtual void setOpacity(qreal opacity) = 0;
|
||||
virtual void setWidth(qreal width) = 0;
|
||||
virtual void setStyle(Qt::PenStyle style) = 0;
|
||||
virtual void setDigitalZoom(int zoom) = 0;
|
||||
};
|
||||
|
||||
#endif // PLANEITEM_H
|
@ -1,3 +1,4 @@
|
||||
#include <cmath>
|
||||
#include "wgs84.h"
|
||||
#include "rectc.h"
|
||||
|
||||
@ -6,6 +7,16 @@
|
||||
#define MIN_LON deg2rad(-180.0)
|
||||
#define MAX_LON deg2rad(180.0)
|
||||
|
||||
static inline double WLON(double lon)
|
||||
{
|
||||
return remainder(lon, 360.0);
|
||||
}
|
||||
|
||||
static inline double LLAT(double lat)
|
||||
{
|
||||
return (lat < 0.0) ? qMax(lat, -90.0) : qMin(lat, 90.0);
|
||||
}
|
||||
|
||||
RectC::RectC(const Coordinates ¢er, double radius)
|
||||
{
|
||||
double radDist = radius / WGS84_RADIUS;
|
||||
@ -151,6 +162,12 @@ RectC RectC::united(const Coordinates &c) const
|
||||
return RectC(Coordinates(l, t), Coordinates(r, b));
|
||||
}
|
||||
|
||||
RectC RectC::adjusted(double lon1, double lat1, double lon2, double lat2) const
|
||||
{
|
||||
return RectC(Coordinates(WLON(_tl.lon() + lon1), LLAT(_tl.lat() + lat1)),
|
||||
Coordinates(WLON(_br.lon() + lon2), LLAT(_br.lat() + lat2)));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const RectC &rect)
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
{return _tl.isNull() && _br.isNull();}
|
||||
bool isValid() const
|
||||
{return (_tl.isValid() && _br.isValid()
|
||||
&& _tl.lat() > _br.lat() && _tl.lon() < _br.lon());}
|
||||
&& _tl.lat() != _br.lat() && _tl.lon() != _br.lon());}
|
||||
|
||||
Coordinates topLeft() const {return _tl;}
|
||||
Coordinates bottomRight() const {return _br;}
|
||||
@ -24,14 +24,18 @@ public:
|
||||
{return Coordinates((_tl.lon() + _br.lon()) / 2.0,
|
||||
(_tl.lat() + _br.lat()) / 2.0);}
|
||||
|
||||
double width() const
|
||||
{
|
||||
double res = right() - left();
|
||||
return (left() > right()) ? 360.0 - res : res;
|
||||
}
|
||||
double height() const {return (top() - bottom());}
|
||||
|
||||
double top() const {return _tl.lat();}
|
||||
double bottom() const {return _br.lat();}
|
||||
double left() const {return _tl.lon();}
|
||||
double right() const {return _br.lon();}
|
||||
|
||||
double width() const {return (right() - left());}
|
||||
double height() const {return (top() - bottom());}
|
||||
|
||||
void setLeft(double val) {_tl.rlon() = val;}
|
||||
void setRight(double val) {_br.rlon() = val;}
|
||||
void setTop(double val) {_tl.rlat() = val;}
|
||||
@ -43,6 +47,7 @@ public:
|
||||
RectC &operator&=(const RectC &r) {*this = *this & r; return *this;}
|
||||
|
||||
RectC united(const Coordinates &c) const;
|
||||
RectC adjusted(double lon1, double lat1, double lon2, double lat2) const;
|
||||
|
||||
bool intersects(const RectC &r) const
|
||||
{return (right() >= r.left() && bottom() <= r.top() && left() <= r.right()
|
||||
|
@ -8,6 +8,19 @@
|
||||
class Area : public QList<Polygon>
|
||||
{
|
||||
public:
|
||||
Area() {}
|
||||
Area(const RectC &rect)
|
||||
{
|
||||
Polygon polygon;
|
||||
QVector<Coordinates> v(4);
|
||||
v[0] = Coordinates(rect.left(), rect.top());
|
||||
v[1] = Coordinates(rect.right(), rect.top());
|
||||
v[2] = Coordinates(rect.right(), rect.bottom());
|
||||
v[3] = Coordinates(rect.left(), rect.bottom());
|
||||
polygon.append(v);
|
||||
append(polygon);
|
||||
}
|
||||
|
||||
const QString& name() const {return _name;}
|
||||
const QString& description() const {return _desc;}
|
||||
void setName(const QString &name) {_name = name;}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "cupparser.h"
|
||||
#include "gpiparser.h"
|
||||
#include "smlparser.h"
|
||||
#include "map/map.h"
|
||||
#include "data.h"
|
||||
|
||||
|
||||
@ -82,7 +83,7 @@ void Data::processData(QList<TrackData> &trackData, QList<RouteData> &routeData)
|
||||
_routes.append(Route(routeData.at(i)));
|
||||
}
|
||||
|
||||
Data::Data(const QString &fileName)
|
||||
Data::Data(const QString &fileName, bool tryUnknown)
|
||||
{
|
||||
QFile file(fileName);
|
||||
QFileInfo fi(fileName);
|
||||
@ -108,7 +109,7 @@ Data::Data(const QString &fileName)
|
||||
_errorLine = it.value()->errorLine();
|
||||
_errorString = it.value()->errorString();
|
||||
}
|
||||
} else {
|
||||
} else if (tryUnknown) {
|
||||
for (it = _parsers.begin(); it != _parsers.end(); it++) {
|
||||
if (it.value()->parse(&file, trackData, routeData, _polygons,
|
||||
_waypoints)) {
|
||||
|
@ -10,11 +10,10 @@
|
||||
#include "route.h"
|
||||
#include "parser.h"
|
||||
|
||||
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
Data(const QString &fileName);
|
||||
Data(const QString &fileName, bool full = true);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
@ -485,15 +485,8 @@ static quint32 readCamera(QDataStream &stream, QVector<Waypoint> &waypoints,
|
||||
|
||||
waypoints.append(Coordinates(toWGS24(lon), toWGS24(lat)));
|
||||
|
||||
Area area;
|
||||
Polygon polygon;
|
||||
QVector<Coordinates> v(4);
|
||||
v[0] = Coordinates(toWGS24(left), toWGS24(top));
|
||||
v[1] = Coordinates(toWGS24(right), toWGS24(top));
|
||||
v[2] = Coordinates(toWGS24(right), toWGS24(bottom));
|
||||
v[3] = Coordinates(toWGS24(left), toWGS24(bottom));
|
||||
polygon.append(v);
|
||||
area.append(polygon);
|
||||
Area area(RectC(Coordinates(toWGS24(left), toWGS24(top)),
|
||||
Coordinates(toWGS24(right), toWGS24(bottom))));
|
||||
|
||||
switch (type) {
|
||||
case 8:
|
||||
|
@ -80,12 +80,25 @@ void POI::search(const RectC &rect, QSet<int> &set) const
|
||||
{
|
||||
qreal min[2], max[2];
|
||||
|
||||
min[0] = rect.topLeft().lon();
|
||||
min[1] = rect.bottomRight().lat();
|
||||
max[0] = rect.bottomRight().lon();
|
||||
max[1] = rect.topLeft().lat();
|
||||
if (rect.left() > rect.right()) {
|
||||
min[0] = rect.topLeft().lon();
|
||||
min[1] = rect.bottomRight().lat();
|
||||
max[0] = 180.0;
|
||||
max[1] = rect.topLeft().lat();
|
||||
_tree.Search(min, max, cb, &set);
|
||||
|
||||
_tree.Search(min, max, cb, &set);
|
||||
min[0] = -180.0;
|
||||
min[1] = rect.bottomRight().lat();
|
||||
max[0] = rect.bottomRight().lon();
|
||||
max[1] = rect.topLeft().lat();
|
||||
_tree.Search(min, max, cb, &set);
|
||||
} else {
|
||||
min[0] = rect.topLeft().lon();
|
||||
min[1] = rect.bottomRight().lat();
|
||||
max[0] = rect.bottomRight().lon();
|
||||
max[1] = rect.topLeft().lat();
|
||||
_tree.Search(min, max, cb, &set);
|
||||
}
|
||||
}
|
||||
|
||||
QList<Waypoint> POI::points(const Path &path) const
|
||||
@ -130,16 +143,10 @@ QList<Waypoint> POI::points(const Waypoint &point) const
|
||||
{
|
||||
QList<Waypoint> ret;
|
||||
QSet<int> set;
|
||||
qreal min[2], max[2];
|
||||
QSet<int>::const_iterator it;
|
||||
|
||||
RectC br(point.coordinates(), _radius);
|
||||
min[0] = br.topLeft().lon();
|
||||
min[1] = br.bottomRight().lat();
|
||||
max[0] = br.bottomRight().lon();
|
||||
max[1] = br.topLeft().lat();
|
||||
|
||||
_tree.Search(min, max, cb, &set);
|
||||
search(br, set);
|
||||
|
||||
for (it = set.constBegin(); it != set.constEnd(); ++it)
|
||||
ret.append(_data.at(*it));
|
||||
@ -147,22 +154,15 @@ QList<Waypoint> POI::points(const Waypoint &point) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<Waypoint> POI::points(const Area &area) const
|
||||
QList<Waypoint> POI::points(const RectC &rect) const
|
||||
{
|
||||
QList<Waypoint> ret;
|
||||
qreal min[2], max[2];
|
||||
QSet<int> set;
|
||||
QSet<int>::const_iterator it;
|
||||
|
||||
RectC br(area.boundingRect());
|
||||
double offset = rad2deg(_radius / WGS84_RADIUS);
|
||||
|
||||
min[0] = br.topLeft().lon() - offset;
|
||||
min[1] = br.bottomRight().lat() - offset;
|
||||
max[0] = br.bottomRight().lon() + offset;
|
||||
max[1] = br.topLeft().lat() + offset;
|
||||
|
||||
_tree.Search(min, max, cb, &set);
|
||||
RectC br(rect.adjusted(-offset, offset, offset, -offset));
|
||||
search(br, set);
|
||||
|
||||
for (it = set.constBegin(); it != set.constEnd(); ++it)
|
||||
ret.append(_data.at(*it));
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "waypoint.h"
|
||||
|
||||
class Path;
|
||||
class Area;
|
||||
class RectC;
|
||||
|
||||
class POI : public QObject
|
||||
@ -29,7 +28,7 @@ public:
|
||||
|
||||
QList<Waypoint> points(const Path &path) const;
|
||||
QList<Waypoint> points(const Waypoint &point) const;
|
||||
QList<Waypoint> points(const Area &area) const;
|
||||
QList<Waypoint> points(const RectC &rect) const;
|
||||
|
||||
const QStringList &files() const {return _files;}
|
||||
void enableFile(const QString &fileName, bool enable);
|
||||
|
@ -454,4 +454,3 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ void Atlas::computeBounds()
|
||||
}
|
||||
|
||||
Atlas::Atlas(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _zoom(0), _mapIndex(-1), _valid(false)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QByteArray ba;
|
||||
|
465
src/map/bsbmap.cpp
Normal file
@ -0,0 +1,465 @@
|
||||
#include <cctype>
|
||||
#include <QFileInfo>
|
||||
#include <QPainter>
|
||||
#include "image.h"
|
||||
#include "gcs.h"
|
||||
#include "pcs.h"
|
||||
#include "calibrationpoint.h"
|
||||
#include "color.h"
|
||||
#include "bsbmap.h"
|
||||
|
||||
|
||||
#define LINE_LIMIT 1024
|
||||
|
||||
static inline bool isEOH(const QByteArray &line)
|
||||
{
|
||||
return (line.size() >= 2 && line.at(line.size() - 2) == 0x1A
|
||||
&& line.at(line.size() -1) == 0);
|
||||
}
|
||||
|
||||
static inline bool isType(const QByteArray &line, const QByteArray &type)
|
||||
{
|
||||
return (line.left(4) == type);
|
||||
}
|
||||
|
||||
static inline QByteArray hdrData(const QByteArray &line)
|
||||
{
|
||||
return line.right(line.size() - 4);
|
||||
}
|
||||
|
||||
static bool readHeaderLine(QFile &file, QByteArray &line)
|
||||
{
|
||||
char c;
|
||||
|
||||
while (file.getChar(&c) && line.size() < LINE_LIMIT) {
|
||||
if (c == '\0') {
|
||||
line.append(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (c == '\r')
|
||||
continue;
|
||||
|
||||
if (c == '\n') {
|
||||
if (!file.getChar(&c))
|
||||
return false;
|
||||
if (c == ' ') {
|
||||
do {
|
||||
if (!file.getChar(&c))
|
||||
return false;
|
||||
} while (c == ' ');
|
||||
line.append(',');
|
||||
file.ungetChar(c);
|
||||
continue;
|
||||
} else {
|
||||
file.ungetChar(c);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
line.append(c);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool isSplitter(const QByteArray &line, int i)
|
||||
{
|
||||
return (line.at(i) == ',' && line.size() - i > 3 && isupper(line.at(i+1))
|
||||
&& (isupper(line.at(i+2)) || isdigit(line.at(i+2))) && line.at(i+3) == '=');
|
||||
}
|
||||
|
||||
static QList<QByteArray> split(const QByteArray &line)
|
||||
{
|
||||
QList<QByteArray> list;
|
||||
int ls = 0;
|
||||
|
||||
for (int i = 0; i < line.size(); i++) {
|
||||
if (isSplitter(line, i)) {
|
||||
list.append(line.mid(ls, i - ls));
|
||||
ls = i + 1;
|
||||
}
|
||||
}
|
||||
list.append(line.mid(ls, line.size() - ls));
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static QMap<QByteArray, QByteArray> kvMap(const QByteArray &line)
|
||||
{
|
||||
QMap<QByteArray, QByteArray> map;
|
||||
QList<QByteArray> parts(split(line));
|
||||
|
||||
for (int i = 0; i < parts.size(); i++) {
|
||||
QList<QByteArray> ba = parts.at(i).split('=');
|
||||
if (ba.size() != 2)
|
||||
continue;
|
||||
map.insert(ba.at(0), ba.at(1));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
static double parameter(const QString &str, bool *res)
|
||||
{
|
||||
if (str.isEmpty() || str == "NOT_APPLICABLE" || str == "UNKNOWN") {
|
||||
*res = true;
|
||||
return NAN;
|
||||
}
|
||||
|
||||
return str.toDouble(res);
|
||||
}
|
||||
|
||||
|
||||
bool BSBMap::parseBSB(const QByteArray &line)
|
||||
{
|
||||
QMap<QByteArray, QByteArray> map(kvMap(line));
|
||||
|
||||
_name = QString::fromLatin1(map.value("NA"));
|
||||
if (_name.isEmpty()) {
|
||||
_errorString = "Invalid/missing BSB NA field";
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QByteArray> sv(map.value("RA").split(','));
|
||||
unsigned w, h;
|
||||
bool wok = false, hok = false;
|
||||
if (sv.size() == 2) {
|
||||
w = sv.at(0).toUInt(&wok);
|
||||
h = sv.at(1).toUInt(&hok);
|
||||
}
|
||||
if (!wok || !hok || !w || !h) {
|
||||
_errorString = "Invalid BSB RA field";
|
||||
return false;
|
||||
}
|
||||
|
||||
_size = QSize(w, h);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BSBMap::parseKNP(const QByteArray &line, QString &datum, QString &proj,
|
||||
double &pp)
|
||||
{
|
||||
QMap<QByteArray, QByteArray> map(kvMap(line));
|
||||
bool ok;
|
||||
|
||||
if (!(map.contains("PR") && map.contains("GD") && map.contains("PP"))) {
|
||||
_errorString = "Missing KNP PR/GD/PP field";
|
||||
return false;
|
||||
}
|
||||
|
||||
proj = map.value("PR");
|
||||
datum = map.value("GD");
|
||||
|
||||
pp = parameter(map.value("PP"), &ok);
|
||||
if (!ok) {
|
||||
_errorString = "Invalid KNP PP field";
|
||||
return false;
|
||||
}
|
||||
_skew = parameter(map.value("SK"), &ok);
|
||||
if (!ok) {
|
||||
_errorString = "Invalid KNP SK field";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BSBMap::parseKNQ(const QByteArray &line, double params[9])
|
||||
{
|
||||
QMap<QByteArray, QByteArray> map(kvMap(line));
|
||||
bool ok;
|
||||
|
||||
for (int i = 1; i <= 8; i++) {
|
||||
params[i] = parameter(map.value(QString("P%1").arg(i).toLatin1()), &ok);
|
||||
if (!ok) {
|
||||
_errorString = QString("Invalid KNQ P%1 parameter").arg(i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BSBMap::parseREF(const QByteArray &line, const QString &datum,
|
||||
const QString &proj, double params[9], QList<ReferencePoint> &points)
|
||||
{
|
||||
QList<QByteArray> fields(line.split(','));
|
||||
|
||||
if (fields.size() == 5) {
|
||||
bool xok, yok, lonok, latok;
|
||||
Coordinates c(fields.at(4).toDouble(&lonok),
|
||||
fields.at(3).toDouble(&latok));
|
||||
if (lonok && latok && c.isValid()) {
|
||||
if (_projection.isNull()) {
|
||||
if (!createProjection(datum, proj, params, c))
|
||||
return false;
|
||||
}
|
||||
CalibrationPoint p(PointD(fields.at(1).toDouble(&xok),
|
||||
fields.at(2).toDouble(&yok)), c);
|
||||
if (xok && yok) {
|
||||
points.append(p.rp(_projection));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_errorString = QString(line) + ": Invalid reference point entry";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BSBMap::parseRGB(const QByteArray &line)
|
||||
{
|
||||
QList<QByteArray> fields(line.split(','));
|
||||
bool iok, rok, gok, bok;
|
||||
int i = fields.at(0).toUInt(&iok);
|
||||
|
||||
if (iok && fields.size() == 4 && i > 0 && i < 256) {
|
||||
_palette[i-1] = Color::rgb(fields.at(1).toUInt(&rok),
|
||||
fields.at(2).toUInt(&gok), fields.at(3).toUInt(&bok));
|
||||
if (rok && gok && bok)
|
||||
return true;
|
||||
}
|
||||
|
||||
_errorString = QString(line) + ": Invalid RGB entry";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BSBMap::readHeader(QFile &file)
|
||||
{
|
||||
QByteArray line;
|
||||
QString datum, proj;
|
||||
double params[9];
|
||||
QList<ReferencePoint> points;
|
||||
|
||||
while (readHeaderLine(file, line)) {
|
||||
if (isEOH(line)) {
|
||||
if (!_size.isValid() || !_projection.isValid()) {
|
||||
_errorString = "Invalid KAP file header";
|
||||
return false;
|
||||
}
|
||||
return createTransform(points);
|
||||
}
|
||||
|
||||
if (isType(line, "BSB/") && !parseBSB(hdrData(line)))
|
||||
return false;
|
||||
else if (isType(line, "KNP/")
|
||||
&& !parseKNP(hdrData(line), datum, proj, params[0]))
|
||||
return false;
|
||||
else if (isType(line, "KNQ/") && !parseKNQ(hdrData(line), params))
|
||||
return false;
|
||||
else if (isType(line, "REF/")
|
||||
&& !parseREF(hdrData(line), datum, proj, params, points))
|
||||
return false;
|
||||
else if (isType(line, "RGB/") && !parseRGB(hdrData(line)))
|
||||
return false;
|
||||
|
||||
line.clear();
|
||||
}
|
||||
|
||||
_errorString = "Not a KAP file";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BSBMap::createTransform(QList<ReferencePoint> &points)
|
||||
{
|
||||
if (_skew > 0.0 && _skew < 360.0) {
|
||||
QTransform matrix;
|
||||
matrix.rotate(-_skew);
|
||||
QTransform t(QImage::trueMatrix(matrix, _size.width(), _size.height()));
|
||||
|
||||
for (int i = 0; i < points.size(); i++)
|
||||
points[i].setXY(t.map(points.at(i).xy().toPointF()));
|
||||
|
||||
QPolygonF a(QRectF(0, 0, _size.width(), _size.height()));
|
||||
a = t.map(a);
|
||||
_skewSize = a.boundingRect().toAlignedRect().size();
|
||||
}
|
||||
|
||||
_transform = Transform(points);
|
||||
if (!_transform.isValid()) {
|
||||
_errorString = _transform.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BSBMap::createProjection(const QString &datum, const QString &proj,
|
||||
double params[9], const Coordinates &c)
|
||||
{
|
||||
const GCS *gcs = 0;
|
||||
PCS pcs;
|
||||
|
||||
if (datum.isEmpty())
|
||||
gcs = GCS::gcs(4326);
|
||||
else
|
||||
gcs = GCS::gcs(datum);
|
||||
if (!gcs) {
|
||||
_errorString = datum + ": Unknown datum";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!proj.compare("MERCATOR", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, c.lon(), NAN, 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9804, setup, 9001);
|
||||
} else if (!proj.compare("TRANSVERSE MERCATOR", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[1], params[2], 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9807, setup, 9001);
|
||||
} else if (!proj.compare("UNIVERSAL TRANSVERSE MERCATOR",
|
||||
Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], 0.9996, 500000, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9807, setup, 9001);
|
||||
} else if (!proj.compare("LAMBERT CONFORMAL CONIC", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], NAN, 0, 0, params[2], params[3]);
|
||||
pcs = PCS(gcs, 9802, setup, 9001);
|
||||
} else if (!proj.compare("POLYCONIC", Qt::CaseInsensitive)) {
|
||||
Projection::Setup setup(0, params[0], NAN, 0, 0, NAN, NAN);
|
||||
pcs = PCS(gcs, 9818, setup, 9001);
|
||||
} else {
|
||||
_errorString = proj + ": Unknown/missing projection";
|
||||
return false;
|
||||
}
|
||||
|
||||
_projection = Projection(&pcs);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BSBMap::readRow(QFile &file, char bits, uchar *buf)
|
||||
{
|
||||
char c;
|
||||
int multiplier;
|
||||
int pixel = 1, written = 0;
|
||||
static const char mask[] = {0, 63, 31, 15, 7, 3, 1, 0};
|
||||
|
||||
do {
|
||||
if (!file.getChar(&c))
|
||||
return false;
|
||||
} while ((uchar)c >= 0x80);
|
||||
|
||||
while (true) {
|
||||
if (!file.getChar(&c))
|
||||
return false;
|
||||
if (c == '\0')
|
||||
break;
|
||||
|
||||
pixel = (c & 0x7f) >> (7 - bits);
|
||||
multiplier = c & mask[(int)bits];
|
||||
|
||||
while ((uchar)c >= 0x80) {
|
||||
if (!file.getChar(&c))
|
||||
return false;
|
||||
multiplier = (multiplier << 7) + (c & 0x7f);
|
||||
}
|
||||
multiplier++;
|
||||
if (written + multiplier > _size.width())
|
||||
multiplier = _size.width() - written;
|
||||
memset(buf + written, pixel - 1, multiplier);
|
||||
written += multiplier;
|
||||
}
|
||||
|
||||
while (written < _size.width())
|
||||
buf[written++] = pixel - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QImage BSBMap::readImage()
|
||||
{
|
||||
QFile file(_fileName);
|
||||
char bits;
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
return QImage();
|
||||
file.seek(_dataOffset);
|
||||
if (!file.getChar(&bits))
|
||||
return QImage();
|
||||
|
||||
QImage img(_size, QImage::Format_Indexed8);
|
||||
img.setColorTable(_palette);
|
||||
|
||||
for (int row = 0; row < _size.height(); row++) {
|
||||
uchar *bsb_row = img.scanLine(row);
|
||||
if (!readRow(file, bits, bsb_row))
|
||||
return QImage();
|
||||
}
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
BSBMap::BSBMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _fileName(fileName), _img(0), _ratio(1.0),
|
||||
_dataOffset(-1), _valid(false)
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = fileName + ": " + file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
_palette.resize(256);
|
||||
if (!readHeader(file))
|
||||
return;
|
||||
_dataOffset = file.pos();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
BSBMap::~BSBMap()
|
||||
{
|
||||
delete _img;
|
||||
}
|
||||
|
||||
QPointF BSBMap::ll2xy(const Coordinates &c)
|
||||
{
|
||||
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _ratio;
|
||||
}
|
||||
|
||||
Coordinates BSBMap::xy2ll(const QPointF &p)
|
||||
{
|
||||
return _projection.xy2ll(_transform.img2proj(p * _ratio));
|
||||
}
|
||||
|
||||
QRectF BSBMap::bounds()
|
||||
{
|
||||
return _skewSize.isValid()
|
||||
? QRectF(QPointF(0, 0), _skewSize / _ratio)
|
||||
: QRectF(QPointF(0, 0), _size / _ratio);
|
||||
}
|
||||
|
||||
void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
if (_img)
|
||||
_img->draw(painter, rect, flags);
|
||||
}
|
||||
|
||||
void BSBMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
|
||||
_ratio = mapRatio;
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
|
||||
void BSBMap::load()
|
||||
{
|
||||
if (!_img) {
|
||||
if (_skew > 0.0 && _skew < 360.0) {
|
||||
QTransform matrix;
|
||||
matrix.rotate(-_skew);
|
||||
_img = new Image(readImage().transformed(matrix));
|
||||
} else
|
||||
_img = new Image(readImage());
|
||||
}
|
||||
}
|
||||
|
||||
void BSBMap::unload()
|
||||
{
|
||||
delete _img;
|
||||
_img = 0;
|
||||
}
|
66
src/map/bsbmap.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef BSBMAP_H
|
||||
#define BSBMAP_H
|
||||
|
||||
#include <QColor>
|
||||
#include "transform.h"
|
||||
#include "projection.h"
|
||||
#include "map.h"
|
||||
|
||||
class QFile;
|
||||
class Image;
|
||||
|
||||
class BSBMap : public Map
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BSBMap(const QString &fileName, QObject *parent = 0);
|
||||
~BSBMap();
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
bool parseBSB(const QByteArray &line);
|
||||
bool parseKNP(const QByteArray &line, QString &datum, QString &proj,
|
||||
double &pp);
|
||||
bool parseKNQ(const QByteArray &line, double params[9]);
|
||||
bool parseREF(const QByteArray &line, const QString &datum,
|
||||
const QString &proj, double params[9], QList<ReferencePoint> &points);
|
||||
bool parseRGB(const QByteArray &line);
|
||||
bool readHeader(QFile &file);
|
||||
bool createProjection(const QString &datum, const QString &proj,
|
||||
double params[9], const Coordinates &c);
|
||||
bool createTransform(QList<ReferencePoint> &points);
|
||||
QImage readImage();
|
||||
bool readRow(QFile &file, char bits, uchar *buf);
|
||||
|
||||
QString _fileName;
|
||||
QString _name;
|
||||
Projection _projection;
|
||||
Transform _transform;
|
||||
qreal _skew;
|
||||
Image *_img;
|
||||
QSize _size;
|
||||
QSize _skewSize;
|
||||
qreal _ratio;
|
||||
qint64 _dataOffset;
|
||||
QVector<QRgb> _palette;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // BSBMAP_H
|
@ -1,6 +1,7 @@
|
||||
#ifndef CALIBRATIONPOINT_H
|
||||
#define CALIBRATIONPOINT_H
|
||||
|
||||
#include <QDebug>
|
||||
#include "transform.h"
|
||||
#include "projection.h"
|
||||
|
||||
@ -22,10 +23,21 @@ public:
|
||||
: ReferencePoint(_xy, _pp);
|
||||
}
|
||||
|
||||
friend QDebug operator<<(QDebug dbg, const CalibrationPoint &p);
|
||||
|
||||
private:
|
||||
PointD _xy;
|
||||
PointD _pp;
|
||||
Coordinates _ll;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const CalibrationPoint &p)
|
||||
{
|
||||
dbg.nospace() << "CalibrationPoint(" << p._xy << ", " << p._pp << ", "
|
||||
<< p._ll << ")";
|
||||
return dbg.space();
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
#endif // CALIBRATIONPOINT_H
|
||||
|
@ -13,6 +13,11 @@ namespace Color
|
||||
|
||||
return (0xFF000000 | r << 16 | g << 8 | b);
|
||||
}
|
||||
|
||||
inline QRgb rgb(quint32 r, quint32 g, quint32 b)
|
||||
{
|
||||
return (0xFF000000 | r << 16 | g << 8 | b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // COLOR_H
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <QtGlobal>
|
||||
#include <QPainter>
|
||||
#include "common/rectc.h"
|
||||
#include "osm.h"
|
||||
#include "emptymap.h"
|
||||
|
||||
|
||||
@ -18,7 +17,7 @@ static int limitZoom(int zoom)
|
||||
}
|
||||
|
||||
|
||||
EmptyMap::EmptyMap(QObject *parent) : Map(parent)
|
||||
EmptyMap::EmptyMap(QObject *parent) : Map(QString(), parent)
|
||||
{
|
||||
_zoom = OSM::ZOOMS.max();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef EMPTYMAP_H
|
||||
#define EMPTYMAP_H
|
||||
|
||||
#include "osm.h"
|
||||
#include "map.h"
|
||||
|
||||
class EmptyMap : public Map
|
||||
@ -13,6 +14,7 @@ public:
|
||||
QString name() const {return QString();}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return OSM::BOUNDS;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
|
@ -54,6 +54,7 @@ QList<GCS::Entry> GCS::defaults()
|
||||
{
|
||||
QList<GCS::Entry> list;
|
||||
list.append(GCS::Entry(4326, 6326, "WGS 84", WGS84()));
|
||||
list.append(GCS::Entry(4326, 6326, "WGS84", WGS84()));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define CT_AlbersEqualArea 11
|
||||
#define CT_PolarStereographic 15
|
||||
#define CT_ObliqueStereographic 16
|
||||
#define CT_Polyconic 22
|
||||
|
||||
|
||||
#define IS_SET(map, key) \
|
||||
@ -344,6 +345,8 @@ Projection::Method GeoTIFF::method(QMap<quint16, Value> &kv)
|
||||
return Projection::Method(9829);
|
||||
case CT_ObliqueStereographic:
|
||||
return Projection::Method(9809);
|
||||
case CT_Polyconic:
|
||||
return Projection::Method(9818);
|
||||
default:
|
||||
_errorString = QString("%1: unknown coordinate transformation method")
|
||||
.arg(kv.value(ProjCoordTransGeoKey).SHORT);
|
||||
|
@ -1,14 +1,14 @@
|
||||
#include <QFileInfo>
|
||||
#include <QPainter>
|
||||
#include <QImageReader>
|
||||
#include "common/config.h"
|
||||
#include "geotiff.h"
|
||||
#include "image.h"
|
||||
#include "geotiffmap.h"
|
||||
|
||||
|
||||
GeoTIFFMap::GeoTIFFMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _fileName(fileName), _img(0), _ratio(1.0), _valid(false)
|
||||
: Map(fileName, parent), _fileName(fileName), _img(0), _ratio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
QImageReader ir(fileName);
|
||||
if (!ir.canRead()) {
|
||||
|
@ -1,15 +1,10 @@
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include "common/config.h"
|
||||
#include "image.h"
|
||||
|
||||
|
||||
#define TILE_SIZE 256
|
||||
|
||||
Image::Image(const QString &fileName) : _img(fileName), _fileName(fileName)
|
||||
{
|
||||
}
|
||||
|
||||
void Image::draw(QPainter *painter, const QRectF &rect, Map::Flags flags)
|
||||
{
|
||||
#ifdef ENABLE_HIDPI
|
||||
@ -19,26 +14,30 @@ void Image::draw(QPainter *painter, const QRectF &rect, Map::Flags flags)
|
||||
#endif // ENABLE_HIDPI
|
||||
QRectF sr(rect.topLeft() * ratio, rect.size() * ratio);
|
||||
|
||||
/* When OpenGL is used, big images are rendered incredibly slow or not at
|
||||
all using the QPainter::drawImage() function with a source rect set. So
|
||||
we have to tile the image ourself before it can be drawn.
|
||||
|
||||
We have to use a list of dynamically allocated pixmaps as QPainter
|
||||
rendering is broken in yet another way with OpenGL and drawPixmap() does
|
||||
access already deleted image instances when reusing a single pixmap. */
|
||||
if (flags & Map::OpenGL) {
|
||||
QList<QPixmap *> list;
|
||||
|
||||
for (int i = sr.left()/TILE_SIZE; i <= sr.right()/TILE_SIZE; i++) {
|
||||
for (int j = sr.top()/TILE_SIZE; j <= sr.bottom()/TILE_SIZE; j++) {
|
||||
QString key = _fileName + "-" + QString::number(i) + "_"
|
||||
+ QString::number(j);
|
||||
QPoint tl(i * TILE_SIZE, j * TILE_SIZE);
|
||||
QPixmap pm;
|
||||
|
||||
if (!QPixmapCache::find(key, &pm)) {
|
||||
QRect tile(tl, QSize(TILE_SIZE, TILE_SIZE));
|
||||
pm = QPixmap::fromImage(_img.copy(tile));
|
||||
if (!pm.isNull())
|
||||
QPixmapCache::insert(key, pm);
|
||||
}
|
||||
QRect tile(tl, QSize(TILE_SIZE, TILE_SIZE));
|
||||
QPixmap *pm = new QPixmap(QPixmap::fromImage(_img.copy(tile)));
|
||||
list.append(pm);
|
||||
#ifdef ENABLE_HIDPI
|
||||
pm.setDevicePixelRatio(ratio);
|
||||
pm->setDevicePixelRatio(ratio);
|
||||
#endif // ENABLE_HIDPI
|
||||
painter->drawPixmap(tl/ratio, pm);
|
||||
painter->drawPixmap(tl/ratio, *pm);
|
||||
}
|
||||
}
|
||||
|
||||
qDeleteAll(list);
|
||||
} else
|
||||
painter->drawImage(rect.topLeft(), _img, sr);
|
||||
}
|
||||
|
@ -9,14 +9,14 @@ class QPainter;
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
Image(const QString &fileName);
|
||||
Image(const QString &fileName) : _img(fileName) {}
|
||||
Image(const QImage &img) : _img(img) {}
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Map::Flags flags);
|
||||
void setDevicePixelRatio(qreal ratio);
|
||||
|
||||
private:
|
||||
QImage _img;
|
||||
QString _fileName;
|
||||
};
|
||||
|
||||
#endif // IMAGE_H
|
||||
|
@ -44,7 +44,7 @@ static QList<MapData*> overlays(const QString &fileName)
|
||||
}
|
||||
|
||||
IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _projection(PCS::pcs(3857)), _valid(false)
|
||||
: Map(fileName, parent), _projection(PCS::pcs(3857)), _valid(false)
|
||||
{
|
||||
if (GMAP::isGMAP(fileName))
|
||||
_data.append(new GMAP(fileName));
|
||||
@ -171,7 +171,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
polyRect &= bounds();
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
_data.at(n)->polys(polyRectD.toRectC(_projection, 4), _zoom,
|
||||
_data.at(n)->polys(polyRectD.toRectC(_projection, 20), _zoom,
|
||||
&polygons, &lines);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
@ -180,7 +180,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
pointRect &= bounds();
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data.at(n)->points(pointRectD.toRectC(_projection, 4),
|
||||
_data.at(n)->points(pointRectD.toRectC(_projection, 20),
|
||||
_zoom, &points);
|
||||
|
||||
tiles.append(RasterTile(this, _data.at(n)->style(), _zoom,
|
||||
@ -212,10 +212,18 @@ void IMGMap::setProjection(const Projection &projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
// Limit the bounds for some well known Mercator projections
|
||||
// Limit the bounds for some well known projections
|
||||
// (world maps have N/S bounds up to 90/-90!)
|
||||
_dataBounds = (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395))
|
||||
? _data.first()->bounds() & OSM::BOUNDS : _data.first()->bounds();
|
||||
if (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395))
|
||||
_dataBounds = _data.first()->bounds() & OSM::BOUNDS;
|
||||
else if (_projection == PCS::pcs(3031) || _projection == PCS::pcs(3976))
|
||||
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, -60),
|
||||
Coordinates(180, -90));
|
||||
else if (_projection == PCS::pcs(3995) || _projection == PCS::pcs(3413))
|
||||
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, 90),
|
||||
Coordinates(180, 60));
|
||||
else
|
||||
_dataBounds = _data.first()->bounds();
|
||||
|
||||
updateTransform();
|
||||
QPixmapCache::clear();
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
QString name() const {return _data.first()->name();}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds() {return _dataBounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
|
31
src/map/invalidmap.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef INVALIDMAP_H
|
||||
#define INVALIDMAP_H
|
||||
|
||||
#include "map.h"
|
||||
|
||||
class InvalidMap : public Map
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InvalidMap(const QString &fileName, const QString &error, QObject *parent = 0)
|
||||
: Map(fileName, parent), _errorString(error) {}
|
||||
|
||||
QString name() const {return QString();}
|
||||
|
||||
QRectF bounds() {return QRectF();}
|
||||
|
||||
QPointF ll2xy(const Coordinates &) {return QPointF();}
|
||||
Coordinates xy2ll(const QPointF &) {return Coordinates();}
|
||||
|
||||
void draw(QPainter *, const QRectF &, Flags) {}
|
||||
|
||||
bool isValid() const {return false;}
|
||||
bool isReady() const {return false;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
private:
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // INVALIDMAP_H
|
@ -139,12 +139,13 @@ bool JNXMap::readTiles()
|
||||
}
|
||||
|
||||
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _file(fileName), _zoom(0), _mapRatio(1.0), _valid(false)
|
||||
: Map(fileName, parent), _file(fileName), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
_name = QFileInfo(fileName).fileName();
|
||||
|
||||
if (!_file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = QString("%1: Error opening file").arg(fileName);
|
||||
_errorString = fileName + ": " + _file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom) {_zoom = zoom;}
|
||||
|
@ -1,6 +1,67 @@
|
||||
#include <cmath>
|
||||
#include <QLineF>
|
||||
#include "map.h"
|
||||
|
||||
|
||||
#define SAMPLES 100
|
||||
|
||||
void Map::growLeft(const QPointF &p, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lon() < rect.left())
|
||||
rect.setLeft(c.lon());
|
||||
}
|
||||
|
||||
void Map::growRight(const QPointF &p, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lon() > rect.right())
|
||||
rect.setRight(c.lon());
|
||||
}
|
||||
|
||||
void Map::growTop(const QPointF &p, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lat() > rect.top())
|
||||
rect.setTop(c.lat());
|
||||
}
|
||||
|
||||
void Map::growBottom(const QPointF &p, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lat() < rect.bottom())
|
||||
rect.setBottom(c.lat());
|
||||
}
|
||||
|
||||
RectC Map::llBounds()
|
||||
{
|
||||
QRectF b(bounds());
|
||||
double dx = b.width() / SAMPLES;
|
||||
double dy = b.height() / SAMPLES;
|
||||
|
||||
Coordinates tl(xy2ll(b.topLeft()));
|
||||
Coordinates br(xy2ll(b.bottomRight()));
|
||||
RectC rect(tl, br);
|
||||
|
||||
for (int i = 0; i <= SAMPLES; i++) {
|
||||
double x = b.left() + i * dx;
|
||||
growBottom(QPointF(x, b.bottom()), rect);
|
||||
growTop(QPointF(x, b.top()), rect);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= SAMPLES; i++) {
|
||||
double y = b.top() + i * dy;
|
||||
growLeft(QPointF(b.left(), y), rect);
|
||||
growRight(QPointF(b.right(), y), rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
qreal Map::resolution(const QRectF &rect)
|
||||
{
|
||||
qreal cy = rect.center().y();
|
||||
|
@ -5,11 +5,10 @@
|
||||
#include <QString>
|
||||
#include <QRectF>
|
||||
#include <QFlags>
|
||||
#include "common/coordinates.h"
|
||||
#include "common/rectc.h"
|
||||
|
||||
|
||||
class QPainter;
|
||||
class RectC;
|
||||
class Projection;
|
||||
|
||||
class Map : public QObject
|
||||
@ -24,11 +23,14 @@ public:
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
Map(QObject *parent = 0) : QObject(parent) {}
|
||||
Map(const QString &path, QObject *parent = 0)
|
||||
: QObject(parent), _path(path) {}
|
||||
virtual ~Map() {}
|
||||
|
||||
const QString &path() const {return _path;}
|
||||
virtual QString name() const = 0;
|
||||
|
||||
virtual RectC llBounds();
|
||||
virtual QRectF bounds() = 0;
|
||||
virtual qreal resolution(const QRectF &rect);
|
||||
|
||||
@ -56,6 +58,14 @@ public:
|
||||
signals:
|
||||
void tilesLoaded();
|
||||
void mapLoaded();
|
||||
|
||||
private:
|
||||
void growLeft(const QPointF &p, RectC &rect);
|
||||
void growRight(const QPointF &p, RectC &rect);
|
||||
void growTop(const QPointF &p, RectC &rect);
|
||||
void growBottom(const QPointF &p, RectC &rect);
|
||||
|
||||
QString _path;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Map*)
|
||||
|
@ -190,6 +190,8 @@ bool MapFile::createProjection(const GCS *gcs, const QString &name,
|
||||
pcs = PCS(gcs, 9822, setup, 9001);
|
||||
else if (name == "(A)Lambert Azimuthual Equal Area")
|
||||
pcs = PCS(gcs, 9820, setup, 9001);
|
||||
else if (name == "Polyconic (American)")
|
||||
pcs = PCS(gcs, 9818, setup, 9001);
|
||||
else if (name == "(NZTM2) New Zealand TM 2000")
|
||||
pcs = PCS(gcs, 9807, Projection::Setup(0, 173.0, 0.9996, 1600000,
|
||||
10000000, NAN, NAN), 9001);
|
||||
|
@ -10,11 +10,12 @@
|
||||
#include "rmap.h"
|
||||
#include "imgmap.h"
|
||||
#include "IMG/gmap.h"
|
||||
#include "bsbmap.h"
|
||||
#include "invalidmap.h"
|
||||
#include "maplist.h"
|
||||
|
||||
|
||||
Map *MapList::loadFile(const QString &path, QString &errorString,
|
||||
bool *terminate)
|
||||
Map *MapList::loadFile(const QString &path, bool *terminate)
|
||||
{
|
||||
QFileInfo fi(path);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
@ -26,12 +27,11 @@ Map *MapList::loadFile(const QString &path, QString &errorString,
|
||||
map = new Atlas(path);
|
||||
} else if (suffix == "xml") {
|
||||
if (MapSource::isMap(path)) {
|
||||
if (!(map = MapSource::loadMap(path, errorString)))
|
||||
return 0;
|
||||
map = MapSource::loadMap(path);
|
||||
} else if (GMAP::isGMAP(path)) {
|
||||
map = new IMGMap(path);
|
||||
if (terminate)
|
||||
*terminate = true;
|
||||
map = new IMGMap(path);
|
||||
}
|
||||
} else if (suffix == "jnx")
|
||||
map = new JNXMap(path);
|
||||
@ -45,17 +45,13 @@ Map *MapList::loadFile(const QString &path, QString &errorString,
|
||||
map = new IMGMap(path);
|
||||
else if (suffix == "map" || suffix == "tar")
|
||||
map = new OziMap(path);
|
||||
else if (suffix == "kap")
|
||||
map = new BSBMap(path);
|
||||
|
||||
if (map && map->isValid())
|
||||
return map;
|
||||
else {
|
||||
errorString = (map) ? map->errorString() : "Unknown file format";
|
||||
delete map;
|
||||
return 0;
|
||||
}
|
||||
return map ? map : new InvalidMap(path, "Unknown file format");
|
||||
}
|
||||
|
||||
QList<Map*> MapList::loadDir(const QString &path, QString &errorString)
|
||||
QList<Map*> MapList::loadDir(const QString &path)
|
||||
{
|
||||
QDir md(path);
|
||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -69,14 +65,9 @@ QList<Map*> MapList::loadDir(const QString &path, QString &errorString)
|
||||
bool terminate = false;
|
||||
|
||||
if (fi.isDir() && fi.fileName() != "set")
|
||||
list.append(loadDir(fi.absoluteFilePath(), errorString));
|
||||
list.append(loadDir(fi.absoluteFilePath()));
|
||||
else if (filter().contains("*." + suffix)) {
|
||||
Map *map = loadFile(fi.absoluteFilePath(), errorString, &terminate);
|
||||
if (map)
|
||||
list.append(map);
|
||||
else
|
||||
qWarning("%s: %s", qPrintable(fi.absoluteFilePath()),
|
||||
qPrintable(errorString));
|
||||
list.append(loadFile(fi.absoluteFilePath(), &terminate));
|
||||
if (terminate)
|
||||
break;
|
||||
}
|
||||
@ -85,15 +76,13 @@ QList<Map*> MapList::loadDir(const QString &path, QString &errorString)
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<Map*> MapList::loadMaps(const QString &path, QString &errorString)
|
||||
QList<Map*> MapList::loadMaps(const QString &path)
|
||||
{
|
||||
if (QFileInfo(path).isDir())
|
||||
return loadDir(path, errorString);
|
||||
return loadDir(path);
|
||||
else {
|
||||
QList<Map*> list;
|
||||
Map *map = loadFile(path, errorString, 0);
|
||||
if (map)
|
||||
list.append(map);
|
||||
list.append(loadFile(path, 0));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@ -106,6 +95,7 @@ QString MapList::formats()
|
||||
+ qApp->translate("MapList", "Garmin IMG maps")
|
||||
+ " (*.gmap *.gmapi *.img *.xml);;"
|
||||
+ qApp->translate("MapList", "Garmin JNX maps") + " (*.jnx);;"
|
||||
+ qApp->translate("MapList", "BSB nautical charts") + " (*.kap);;"
|
||||
+ qApp->translate("MapList", "OziExplorer maps") + " (*.map);;"
|
||||
+ qApp->translate("MapList", "MBTiles maps") + " (*.mbtiles);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||
@ -117,7 +107,7 @@ QString MapList::formats()
|
||||
QStringList MapList::filter()
|
||||
{
|
||||
QStringList filter;
|
||||
filter << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.map"
|
||||
filter << "*.gmap" << "*.gmapi" << "*.img" << "*.jnx" << "*.kap" << "*.map"
|
||||
<< "*.mbtiles" << "*.rmap" << "*.rtmap" << "*.tar" << "*.tba" << "*.tif"
|
||||
<< "*.tiff" << "*.xml";
|
||||
return filter;
|
||||
|
@ -8,14 +8,13 @@ class Map;
|
||||
class MapList
|
||||
{
|
||||
public:
|
||||
static QList<Map*> loadMaps(const QString &path, QString &errorString);
|
||||
static QList<Map*> loadMaps(const QString &path);
|
||||
static QString formats();
|
||||
static QStringList filter();
|
||||
|
||||
private:
|
||||
static Map *loadFile(const QString &path, QString &errorString,
|
||||
bool *terminate);
|
||||
static QList<Map*> loadDir(const QString &path, QString &errorString);
|
||||
static Map *loadFile(const QString &path, bool *terminate);
|
||||
static QList<Map*> loadDir(const QString &path);
|
||||
};
|
||||
|
||||
#endif // MAPLIST_H
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "wmtsmap.h"
|
||||
#include "wmsmap.h"
|
||||
#include "osm.h"
|
||||
#include "invalidmap.h"
|
||||
#include "mapsource.h"
|
||||
|
||||
|
||||
@ -236,16 +237,14 @@ bool MapSource::isMap(const QString &path)
|
||||
return false;
|
||||
}
|
||||
|
||||
Map *MapSource::loadMap(const QString &path, QString &errorString)
|
||||
Map *MapSource::loadMap(const QString &path)
|
||||
{
|
||||
Config config;
|
||||
QFile file(path);
|
||||
|
||||
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||
errorString = file.errorString();
|
||||
return 0;
|
||||
}
|
||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||
return new InvalidMap(path, file.errorString());
|
||||
|
||||
QXmlStreamReader reader(&file);
|
||||
if (reader.readNextStartElement()) {
|
||||
@ -254,66 +253,53 @@ Map *MapSource::loadMap(const QString &path, QString &errorString)
|
||||
else
|
||||
reader.raiseError("Not an online map source file");
|
||||
}
|
||||
if (reader.error()) {
|
||||
errorString = QString("%1: %2").arg(reader.lineNumber())
|
||||
.arg(reader.errorString());
|
||||
return 0;
|
||||
}
|
||||
if (reader.error())
|
||||
return new InvalidMap(path, QString("%1: %2").arg(reader.lineNumber())
|
||||
.arg(reader.errorString()));
|
||||
|
||||
if (config.name.isEmpty()) {
|
||||
errorString = "Missing name definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.url.isEmpty()) {
|
||||
errorString = "Missing URL definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.name.isEmpty())
|
||||
return new InvalidMap(path, "Missing name definition");
|
||||
if (config.url.isEmpty())
|
||||
return new InvalidMap(path, "Missing URL definition");
|
||||
if (config.type == WMTS || config.type == WMS) {
|
||||
if (config.layer.isEmpty()) {
|
||||
errorString = "Missing layer definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.format.isEmpty()) {
|
||||
errorString = "Missing format definition";
|
||||
return 0;
|
||||
}
|
||||
if (config.layer.isEmpty())
|
||||
return new InvalidMap(path, "Missing layer definition");
|
||||
if (config.format.isEmpty())
|
||||
return new InvalidMap(path, "Missing format definition");
|
||||
}
|
||||
if (config.type == WMTS) {
|
||||
if (config.set.isEmpty()) {
|
||||
errorString = "Missing set definiton";
|
||||
return 0;
|
||||
}
|
||||
if (config.set.isEmpty())
|
||||
return new InvalidMap(path, "Missing set definiton");
|
||||
}
|
||||
if (config.type == WMS) {
|
||||
if (config.crs.isEmpty()) {
|
||||
errorString = "Missing CRS definiton";
|
||||
return 0;
|
||||
}
|
||||
if (config.crs.isEmpty())
|
||||
return new InvalidMap(path, "Missing CRS definiton");
|
||||
}
|
||||
|
||||
switch (config.type) {
|
||||
case WMTS:
|
||||
return new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
|
||||
config.set, config.style, config.format, config.rest,
|
||||
return new WMTSMap(path, config.name, WMTS::Setup(config.url,
|
||||
config.layer, config.set, config.style, config.format, config.rest,
|
||||
config.coordinateSystem, config.dimensions, config.authorization),
|
||||
config.tileRatio);
|
||||
case WMS:
|
||||
return new WMSMap(config.name, WMS::Setup(config.url, config.layer,
|
||||
config.style, config.format, config.crs, config.coordinateSystem,
|
||||
config.dimensions, config.authorization), config.tileSize);
|
||||
return new WMSMap(path, config.name, WMS::Setup(config.url,
|
||||
config.layer, config.style, config.format, config.crs,
|
||||
config.coordinateSystem, config.dimensions, config.authorization),
|
||||
config.tileSize);
|
||||
case TMS:
|
||||
return new OnlineMap(config.name, config.url, config.zooms,
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.tileSize, config.scalable, true, false);
|
||||
case OSM:
|
||||
return new OnlineMap(config.name, config.url, config.zooms,
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.tileSize, config.scalable, false, false);
|
||||
case QuadTiles:
|
||||
return new OnlineMap(config.name, config.url, config.zooms,
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.tileSize, config.scalable, false, true);
|
||||
default:
|
||||
return 0;
|
||||
return new InvalidMap(path, "Invalid map type");
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ class QXmlStreamReader;
|
||||
class MapSource
|
||||
{
|
||||
public:
|
||||
static Map *loadMap(const QString &path, QString &errorString);
|
||||
static Map *loadMap(const QString &path);
|
||||
static bool isMap(const QString &path);
|
||||
|
||||
private:
|
||||
|
@ -55,7 +55,7 @@ static double index2mercator(int index, int zoom)
|
||||
}
|
||||
|
||||
MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _fileName(fileName), _mapRatio(1.0), _tileRatio(1.0),
|
||||
: Map(fileName, parent), _fileName(fileName), _mapRatio(1.0), _tileRatio(1.0),
|
||||
_scalable(false), _scaledSize(0), _valid(false)
|
||||
{
|
||||
_db = QSqlDatabase::addDatabase("QSQLITE", fileName);
|
||||
|
@ -14,6 +14,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
|
@ -8,11 +8,11 @@
|
||||
#include "onlinemap.h"
|
||||
|
||||
|
||||
OnlineMap::OnlineMap(const QString &name, const QString &url,
|
||||
const Range &zooms, const RectC &bounds, qreal tileRatio,
|
||||
OnlineMap::OnlineMap(const QString &fileName, const QString &name,
|
||||
const QString &url, const Range &zooms, const RectC &bounds, qreal tileRatio,
|
||||
const Authorization &authorization, int tileSize, bool scalable, bool invertY,
|
||||
bool quadTiles, QObject *parent)
|
||||
: Map(parent), _name(name), _zooms(zooms), _bounds(bounds),
|
||||
: Map(fileName, parent), _name(name), _zooms(zooms), _bounds(bounds),
|
||||
_zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio),
|
||||
_tileSize(tileSize), _scalable(scalable), _invertY(invertY)
|
||||
{
|
||||
|
@ -11,14 +11,15 @@ class OnlineMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OnlineMap(const QString &name, const QString &url, const Range &zooms,
|
||||
const RectC &bounds, qreal tileRatio, const Authorization &authorization,
|
||||
int tileSize, bool scalable, bool invertY, bool quadTiles,
|
||||
QObject *parent = 0);
|
||||
OnlineMap(const QString &fileName, const QString &name, const QString &url,
|
||||
const Range &zooms, const RectC &bounds, qreal tileRatio,
|
||||
const Authorization &authorization, int tileSize, bool scalable,
|
||||
bool invertY, bool quadTiles, QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
|
@ -17,7 +17,8 @@
|
||||
|
||||
|
||||
OziMap::OziMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString suffix = fi.suffix().toLower();
|
||||
@ -79,7 +80,8 @@ OziMap::OziMap(const QString &fileName, QObject *parent)
|
||||
}
|
||||
|
||||
OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
: Map(parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0), _valid(false)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QFileInfo map(fi.absolutePath());
|
||||
|
@ -199,5 +199,5 @@ bool PolarStereographic::operator==(const CT &ct) const
|
||||
&& _originLongitude == other->_originLongitude
|
||||
&& _falseEasting == other->_falseEasting
|
||||
&& _falseNorthing == other->_falseNorthing && _two_a == other->_two_a
|
||||
&& _es == other->_es);
|
||||
&& _es == other->_es && _southernHemisphere == other->_southernHemisphere);
|
||||
}
|
||||
|
211
src/map/polyconic.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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 "polyconic.h"
|
||||
|
||||
#define POLY_COEFF_TIMES_SIN(coeff, x, latit) \
|
||||
(coeff * (sin (x * latit)))
|
||||
#define POLY_M(c0lat, c1s2lat, c2s4lat, c3s6lat) \
|
||||
(_a * (c0lat - c1s2lat + c2s4lat - c3s6lat))
|
||||
#define FLOAT_EQ(x, v, epsilon) \
|
||||
(((v - epsilon) < x) && (x < (v + epsilon)))
|
||||
|
||||
Polyconic::Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing)
|
||||
{
|
||||
double j, three_es4;
|
||||
double lat, sin2lat, sin4lat, sin6lat;
|
||||
double a2;
|
||||
double b2;
|
||||
|
||||
_longitudeOrigin = deg2rad(longitudeOrigin);
|
||||
_latitudeOrigin = deg2rad(latitudeOrigin);
|
||||
_a = ellipsoid->radius();
|
||||
_b = ellipsoid->b();
|
||||
if (_longitudeOrigin > M_PI)
|
||||
_longitudeOrigin -= 2 * M_PI;
|
||||
_falseNorthing = falseNorthing;
|
||||
_falseEasting = falseEasting;
|
||||
a2 = _a * _a;
|
||||
b2 = _b * _b;
|
||||
_es2 = (a2 - b2) / a2;
|
||||
_es4 = _es2 * _es2;
|
||||
_es6 = _es4 * _es2;
|
||||
|
||||
j = 45.0 * _es6 / 1024.0;
|
||||
three_es4 = 3.0 * _es4;
|
||||
_c0 = 1.0 - _es2 / 4.0 - three_es4 / 64.0 - 5.0 * _es6 / 256.0;
|
||||
_c1 = 3.0 * _es2 / 8.0 + three_es4 / 32.0 + j;
|
||||
_c2 = 15.0 * _es4 / 256.0 + j;
|
||||
_c3 = 35.0 * _es6 / 3072.0;
|
||||
|
||||
lat = _c0 * _latitudeOrigin;
|
||||
sin2lat = POLY_COEFF_TIMES_SIN(_c1, 2.0, _latitudeOrigin);
|
||||
sin4lat = POLY_COEFF_TIMES_SIN(_c2, 4.0, _latitudeOrigin);
|
||||
sin6lat = POLY_COEFF_TIMES_SIN(_c3, 6.0, _latitudeOrigin);
|
||||
_M0 = POLY_M(lat, sin2lat, sin4lat, sin6lat);
|
||||
}
|
||||
|
||||
PointD Polyconic::ll2xy(const Coordinates &c) const
|
||||
{
|
||||
double Longitude = deg2rad(c.lon());
|
||||
double Latitude = deg2rad(c.lat());
|
||||
double slat = sin(Latitude);
|
||||
double lat, sin2lat, sin4lat, sin6lat;
|
||||
double dlam;
|
||||
double NN;
|
||||
double NN_OVER_tlat;
|
||||
double MM;
|
||||
double EE;
|
||||
|
||||
dlam = Longitude - _longitudeOrigin;
|
||||
if (dlam > M_PI)
|
||||
dlam -= 2 * M_PI;
|
||||
if (dlam < -M_PI)
|
||||
dlam += 2 * M_PI;
|
||||
|
||||
if (Latitude == 0.0) {
|
||||
return PointD(_a * dlam + _falseEasting,
|
||||
-_M0 + _falseNorthing);
|
||||
} else {
|
||||
NN = _a / sqrt(1.0 - _es2 * (slat * slat));
|
||||
NN_OVER_tlat = NN / tan(Latitude);
|
||||
lat = _c0 * Latitude;
|
||||
sin2lat = POLY_COEFF_TIMES_SIN(_c1, 2.0, Latitude);
|
||||
sin4lat = POLY_COEFF_TIMES_SIN(_c2, 4.0, Latitude);
|
||||
sin6lat = POLY_COEFF_TIMES_SIN(_c3, 6.0, Latitude);
|
||||
MM = POLY_M(lat, sin2lat, sin4lat, sin6lat);
|
||||
EE = dlam * slat;
|
||||
return PointD(NN_OVER_tlat * sin(EE) + _falseEasting,
|
||||
MM - _M0 + NN_OVER_tlat * (1.0 - cos(EE)) + _falseNorthing);
|
||||
}
|
||||
}
|
||||
|
||||
Coordinates Polyconic::xy2ll(const PointD &p) const
|
||||
{
|
||||
double dx;
|
||||
double dy;
|
||||
double dx_OVER_Poly_a;
|
||||
double AA;
|
||||
double BB;
|
||||
double CC = 0.0;
|
||||
double PHIn, Delta_PHI = 1.0;
|
||||
double sin_PHIn;
|
||||
double PHI, sin2PHI, sin4PHI, sin6PHI;
|
||||
double Mn, Mn_prime, Ma;
|
||||
double AA_Ma;
|
||||
double Ma2_PLUS_BB;
|
||||
double AA_MINUS_Ma;
|
||||
double tolerance = 1.0e-12;
|
||||
double Latitude;
|
||||
double Longitude;
|
||||
|
||||
|
||||
dy = p.y() - _falseNorthing;
|
||||
dx = p.x() - _falseEasting;
|
||||
dx_OVER_Poly_a = dx / _a;
|
||||
|
||||
if (FLOAT_EQ(dy,-_M0,1)) {
|
||||
Latitude = 0.0;
|
||||
Longitude = dx_OVER_Poly_a + _longitudeOrigin;
|
||||
} else {
|
||||
AA = (_M0 + dy) / _a;
|
||||
BB = dx_OVER_Poly_a * dx_OVER_Poly_a + (AA * AA);
|
||||
PHIn = AA;
|
||||
|
||||
while (fabs(Delta_PHI) > tolerance) {
|
||||
sin_PHIn = sin(PHIn);
|
||||
CC = sqrt(1.0 - _es2 * sin_PHIn * sin_PHIn) * tan(PHIn);
|
||||
PHI = _c0 * PHIn;
|
||||
sin2PHI = POLY_COEFF_TIMES_SIN(_c1, 2.0, PHIn);
|
||||
sin4PHI = POLY_COEFF_TIMES_SIN(_c2, 4.0, PHIn);
|
||||
sin6PHI = POLY_COEFF_TIMES_SIN(_c3, 6.0, PHIn);
|
||||
Mn = POLY_M(PHI, sin2PHI, sin4PHI, sin6PHI);
|
||||
Mn_prime = _c0 - 2.0 * _c1 * cos(2.0 * PHIn) + 4.0 * _c2
|
||||
* cos(4.0 * PHIn) - 6.0 * _c3 * cos(6.0 * PHIn);
|
||||
Ma = Mn / _a;
|
||||
AA_Ma = AA * Ma;
|
||||
Ma2_PLUS_BB = Ma * Ma + BB;
|
||||
AA_MINUS_Ma = AA - Ma;
|
||||
Delta_PHI = (AA_Ma * CC + AA_MINUS_Ma - 0.5 * (Ma2_PLUS_BB) * CC) /
|
||||
(_es2 * sin2PHI * (Ma2_PLUS_BB - 2.0 * AA_Ma) / 4.0 * CC
|
||||
+ (AA_MINUS_Ma) * (CC * Mn_prime - 2.0 / sin2PHI) - Mn_prime);
|
||||
PHIn -= Delta_PHI;
|
||||
}
|
||||
Latitude = PHIn;
|
||||
|
||||
if (Latitude > M_PI_2)
|
||||
Latitude = M_PI_2;
|
||||
else if (Latitude < -M_PI_2)
|
||||
Latitude = -M_PI_2;
|
||||
|
||||
if (FLOAT_EQ(fabs(Latitude), M_PI_2, 0.00001) || (Latitude == 0))
|
||||
Longitude = _longitudeOrigin;
|
||||
else
|
||||
Longitude = (asin(dx_OVER_Poly_a * CC)) / sin(Latitude)
|
||||
+ _longitudeOrigin;
|
||||
}
|
||||
|
||||
if (Longitude > M_PI)
|
||||
Longitude -= 2 * M_PI;
|
||||
if (Longitude < -M_PI)
|
||||
Longitude += 2 *M_PI;
|
||||
|
||||
if (Longitude > M_PI)
|
||||
Longitude = M_PI;
|
||||
else if (Longitude < -M_PI)
|
||||
Longitude = -M_PI;
|
||||
|
||||
return Coordinates(rad2deg(Longitude), rad2deg(Latitude));
|
||||
}
|
||||
|
||||
bool Polyconic::operator==(const CT &ct) const
|
||||
{
|
||||
const Polyconic *other = dynamic_cast<const Polyconic*>(&ct);
|
||||
return (other != 0 && _a == other->_a && _b == other->_b
|
||||
&& _latitudeOrigin == other->_latitudeOrigin
|
||||
&& _longitudeOrigin == other->_longitudeOrigin
|
||||
&& _falseNorthing == other->_falseNorthing
|
||||
&& _falseEasting == other->_falseEasting);
|
||||
}
|
37
src/map/polyconic.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef POLYCONIC_H
|
||||
#define POLYCONIC_H
|
||||
|
||||
#include "ct.h"
|
||||
|
||||
class Ellipsoid;
|
||||
|
||||
class Polyconic : public CT
|
||||
{
|
||||
public:
|
||||
Polyconic(const Ellipsoid *ellipsoid, double latitudeOrigin,
|
||||
double longitudeOrigin, double falseEasting, double falseNorthing);
|
||||
|
||||
virtual CT *clone() const {return new Polyconic(*this);}
|
||||
virtual bool operator==(const CT &ct) const;
|
||||
|
||||
virtual PointD ll2xy(const Coordinates &c) const;
|
||||
virtual Coordinates xy2ll(const PointD &p) const;
|
||||
|
||||
private:
|
||||
double _a;
|
||||
double _b;
|
||||
double _es2;
|
||||
double _es4;
|
||||
double _es6;
|
||||
double _M0;
|
||||
double _c0;
|
||||
double _c1;
|
||||
double _c2;
|
||||
double _c3;
|
||||
double _longitudeOrigin;
|
||||
double _latitudeOrigin;
|
||||
double _falseEasting;
|
||||
double _falseNorthing;
|
||||
};
|
||||
|
||||
#endif // POLYCONIC_H
|
@ -8,6 +8,7 @@
|
||||
#include "krovak.h"
|
||||
#include "polarstereographic.h"
|
||||
#include "obliquestereographic.h"
|
||||
#include "polyconic.h"
|
||||
#include "latlon.h"
|
||||
#include "gcs.h"
|
||||
#include "pcs.h"
|
||||
@ -25,6 +26,7 @@ Projection::Method::Method(int id)
|
||||
case 9807:
|
||||
case 9809:
|
||||
case 9815:
|
||||
case 9818:
|
||||
case 9819:
|
||||
case 9820:
|
||||
case 9822:
|
||||
@ -85,6 +87,11 @@ Projection::Projection(const PCS *pcs) : _gcs(0), _ct(0), _geographic(false)
|
||||
setup.longitudeOrigin(), setup.scale(), setup.falseEasting(),
|
||||
setup.falseNorthing());
|
||||
break;
|
||||
case 9818:
|
||||
_ct = new Polyconic(ellipsoid, setup.latitudeOrigin(),
|
||||
setup.longitudeOrigin(), setup.falseEasting(),
|
||||
setup.falseNorthing());
|
||||
break;
|
||||
case 9819:
|
||||
_ct = new Krovak(ellipsoid, setup.standardParallel1(),
|
||||
setup.standardParallel2(), setup.scale(), setup.latitudeOrigin(),
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <cmath>
|
||||
#include "common/rectc.h"
|
||||
#include "projection.h"
|
||||
#include "rectd.h"
|
||||
@ -5,67 +6,54 @@
|
||||
|
||||
static void growRect(const Projection &proj, const Coordinates &c, RectD &rect)
|
||||
{
|
||||
if (c.isNull())
|
||||
return;
|
||||
|
||||
PointD p(proj.ll2xy(c));
|
||||
|
||||
if (rect.isNull())
|
||||
rect = RectD(p, p);
|
||||
else {
|
||||
if (p.x() < rect.left())
|
||||
rect.setLeft(p.x());
|
||||
if (p.x() > rect.right())
|
||||
rect.setRight(p.x());
|
||||
if (p.y() < rect.bottom())
|
||||
rect.setBottom(p.y());
|
||||
if (p.y() > rect.top())
|
||||
rect.setTop(p.y());
|
||||
}
|
||||
if (p.x() < rect.left())
|
||||
rect.setLeft(p.x());
|
||||
if (p.x() > rect.right())
|
||||
rect.setRight(p.x());
|
||||
if (p.y() > rect.top())
|
||||
rect.setTop(p.y());
|
||||
if (p.y() < rect.bottom())
|
||||
rect.setBottom(p.y());
|
||||
}
|
||||
|
||||
static void growRect(const Projection &proj, const PointD &p, RectC &rect)
|
||||
{
|
||||
if (p.isNull())
|
||||
return;
|
||||
|
||||
Coordinates c(proj.xy2ll(p));
|
||||
|
||||
if (rect.isNull())
|
||||
rect = RectC(c, c);
|
||||
else {
|
||||
if (c.lon() < rect.left())
|
||||
rect.setLeft(c.lon());
|
||||
if (c.lon() > rect.right())
|
||||
rect.setRight(c.lon());
|
||||
if (c.lat() < rect.bottom())
|
||||
rect.setBottom(c.lat());
|
||||
if (c.lat() > rect.top())
|
||||
rect.setTop(c.lat());
|
||||
}
|
||||
if (c.lon() < rect.left())
|
||||
rect.setLeft(c.lon());
|
||||
if (c.lon() > rect.right())
|
||||
rect.setRight(c.lon());
|
||||
if (c.lat() > rect.top())
|
||||
rect.setTop(c.lat());
|
||||
if (c.lat() < rect.bottom())
|
||||
rect.setBottom(c.lat());
|
||||
}
|
||||
|
||||
RectD::RectD(const RectC &rect, const Projection &proj, int samples)
|
||||
{
|
||||
RectD prect;
|
||||
double dx = (rect.right() - rect.left()) / samples;
|
||||
double dy = (rect.top() - rect.bottom()) / samples;
|
||||
if (!rect.isValid())
|
||||
return;
|
||||
|
||||
growRect(proj, rect.topLeft(), prect);
|
||||
double dx = rect.width() / samples;
|
||||
double dy = rect.height() / samples;
|
||||
|
||||
if (dx > 0) {
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double x = rect.left() + i * dx;
|
||||
growRect(proj, Coordinates(x, rect.bottom()), prect);
|
||||
growRect(proj, Coordinates(x, rect.top()), prect);
|
||||
}
|
||||
PointD tl(proj.ll2xy(rect.topLeft()));
|
||||
PointD br(proj.ll2xy(rect.bottomRight()));
|
||||
RectD prect(tl, br);
|
||||
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double x = remainder(rect.left() + i * dx, 360.0);
|
||||
growRect(proj, Coordinates(x, rect.bottom()), prect);
|
||||
growRect(proj, Coordinates(x, rect.top()), prect);
|
||||
}
|
||||
if (dy > 0) {
|
||||
for (int i = 0; i <= samples; i++ ) {
|
||||
double y = rect.bottom() + i * dy;
|
||||
growRect(proj, Coordinates(rect.left(), y), prect);
|
||||
growRect(proj, Coordinates(rect.right(), y), prect);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double y = rect.bottom() + i * dy;
|
||||
growRect(proj, Coordinates(rect.left(), y), prect);
|
||||
growRect(proj, Coordinates(rect.right(), y), prect);
|
||||
}
|
||||
|
||||
*this = prect;
|
||||
@ -73,26 +61,26 @@ RectD::RectD(const RectC &rect, const Projection &proj, int samples)
|
||||
|
||||
RectC RectD::toRectC(const Projection &proj, int samples) const
|
||||
{
|
||||
RectC ret;
|
||||
double dx = (right() - left()) / samples;
|
||||
double dy = (top() - bottom()) / samples;
|
||||
if (!isValid())
|
||||
return RectC();
|
||||
|
||||
growRect(proj, topLeft(), ret);
|
||||
double dx = width() / samples;
|
||||
double dy = height() / samples;
|
||||
|
||||
if (dx > 0) {
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double x = left() + i * dx;
|
||||
growRect(proj, PointD(x, bottom()), ret);
|
||||
growRect(proj, PointD(x, top()), ret);
|
||||
}
|
||||
}
|
||||
if (dy > 0) {
|
||||
for (int i = 0; i <= samples; i++ ) {
|
||||
double y = bottom() + i * dy;
|
||||
growRect(proj, PointD(left(), y), ret);
|
||||
growRect(proj, PointD(right(), y), ret);
|
||||
}
|
||||
Coordinates c(proj.xy2ll(center()));
|
||||
RectC rect(c, c);
|
||||
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double x = left() + i * dx;
|
||||
growRect(proj, PointD(x, bottom()), rect);
|
||||
growRect(proj, PointD(x, top()), rect);
|
||||
}
|
||||
|
||||
return ret;
|
||||
for (int i = 0; i <= samples; i++) {
|
||||
double y = bottom() + i * dy;
|
||||
growRect(proj, PointD(left(), y), rect);
|
||||
growRect(proj, PointD(right(), y), rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
@ -16,6 +16,9 @@ public:
|
||||
|
||||
PointD topLeft() const {return _tl;}
|
||||
PointD bottomRight() const {return _br;}
|
||||
PointD center() const
|
||||
{return PointD((_tl.x() + _br.x()) / 2.0,
|
||||
(_tl.y() + _br.y()) / 2.0);}
|
||||
|
||||
double left() const {return _tl.x();}
|
||||
double right() const {return _br.x();}
|
||||
@ -35,7 +38,9 @@ public:
|
||||
&& p.y() >= bottom());}
|
||||
|
||||
bool isNull() const {return _tl.isNull() && _br.isNull();}
|
||||
bool isValid() const {return !(_tl.isNull() || _br.isNull());}
|
||||
bool isValid() const
|
||||
{return (_tl.isValid() && _br.isValid()
|
||||
&& _tl.x() != _br.x() && _tl.y() != _br.y());}
|
||||
|
||||
RectC toRectC(const Projection &proj, int samples = 100) const;
|
||||
|
||||
|
@ -161,7 +161,8 @@ bool RMap::parseIMP(const QByteArray &data)
|
||||
}
|
||||
|
||||
RMap::RMap(const QString &fileName, QObject *parent)
|
||||
: Map(parent), _mapRatio(1.0), _fileName(fileName), _zoom(0), _valid(false)
|
||||
: Map(fileName, parent), _mapRatio(1.0), _fileName(fileName), _zoom(0),
|
||||
_valid(false)
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
|
@ -67,8 +67,9 @@ void WMSMap::updateTransform()
|
||||
PointD(pixelSpan, pixelSpan));
|
||||
}
|
||||
|
||||
WMSMap::WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
|
||||
QObject *parent) : Map(parent), _name(name), _tileLoader(0), _zoom(0),
|
||||
WMSMap::WMSMap(const QString &fileName, const QString &name,
|
||||
const WMS::Setup &setup, int tileSize, QObject *parent)
|
||||
: Map(fileName, parent), _name(name), _tileLoader(0), _zoom(0),
|
||||
_tileSize(tileSize), _mapRatio(1.0)
|
||||
{
|
||||
QString tilesDir(QDir(ProgramPaths::tilesDir()).filePath(_name));
|
||||
|
@ -14,12 +14,13 @@ class WMSMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WMSMap(const QString &name, const WMS::Setup &setup, int tileSize,
|
||||
QObject *parent = 0);
|
||||
WMSMap(const QString &fileName, const QString &name, const WMS::Setup &setup,
|
||||
int tileSize, QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _wms->bbox();}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
|
@ -12,9 +12,10 @@
|
||||
|
||||
#define CAPABILITIES_FILE "capabilities.xml"
|
||||
|
||||
WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio,
|
||||
QObject *parent) : Map(parent), _name(name), _tileLoader(0), _zoom(0),
|
||||
_mapRatio(1.0), _tileRatio(tileRatio)
|
||||
WMTSMap::WMTSMap(const QString &fileName, const QString &name,
|
||||
const WMTS::Setup &setup, qreal tileRatio,
|
||||
QObject *parent) : Map(fileName, parent), _name(name), _tileLoader(0),
|
||||
_zoom(0), _mapRatio(1.0), _tileRatio(tileRatio)
|
||||
{
|
||||
QString tilesDir(QDir(ProgramPaths::tilesDir()).filePath(_name));
|
||||
|
||||
@ -54,9 +55,9 @@ double WMTSMap::sd2res(double scaleDenominator) const
|
||||
* _wmts->projection().units().fromMeters(1.0);
|
||||
}
|
||||
|
||||
void WMTSMap::updateTransform()
|
||||
Transform WMTSMap::transform(int zoom) const
|
||||
{
|
||||
const WMTS::Zoom &z = _wmts->zooms().at(_zoom);
|
||||
const WMTS::Zoom &z = _wmts->zooms().at(zoom);
|
||||
|
||||
PointD topLeft = (_wmts->cs().axisOrder() == CoordinateSystem::YX)
|
||||
? PointD(z.topLeft().y(), z.topLeft().x()) : z.topLeft();
|
||||
@ -64,27 +65,50 @@ void WMTSMap::updateTransform()
|
||||
double pixelSpan = sd2res(z.scaleDenominator());
|
||||
if (_wmts->projection().isGeographic())
|
||||
pixelSpan /= deg2rad(WGS84_RADIUS);
|
||||
_transform = Transform(ReferencePoint(PointD(0, 0), topLeft),
|
||||
return Transform(ReferencePoint(PointD(0, 0), topLeft),
|
||||
PointD(pixelSpan, pixelSpan));
|
||||
}
|
||||
|
||||
QRectF WMTSMap::bounds()
|
||||
QRectF WMTSMap::tileBounds(int zoom) const
|
||||
{
|
||||
const WMTS::Zoom &z = _wmts->zooms().at(_zoom);
|
||||
QRectF tileBounds, bounds;
|
||||
const WMTS::Zoom &z = _wmts->zooms().at(zoom);
|
||||
|
||||
tileBounds = (z.limits().isNull()) ?
|
||||
QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(),
|
||||
return (z.limits().isNull())
|
||||
? QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(),
|
||||
z.tile().height() * z.matrix().height()))
|
||||
: QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top()
|
||||
* z.tile().height()), QSize(z.tile().width() * z.limits().width(),
|
||||
z.tile().height() * z.limits().height()));
|
||||
}
|
||||
|
||||
if (_bounds.isValid())
|
||||
bounds = QRectF(_transform.proj2img(_bounds.topLeft())
|
||||
/ coordinatesRatio(), _transform.proj2img(
|
||||
_bounds.bottomRight()) / coordinatesRatio());
|
||||
return bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds;
|
||||
void WMTSMap::updateTransform()
|
||||
{
|
||||
_transform = transform(_zoom);
|
||||
}
|
||||
|
||||
QRectF WMTSMap::bounds()
|
||||
{
|
||||
QRectF tb(tileBounds(_zoom));
|
||||
QRectF lb = _bounds.isValid()
|
||||
? QRectF(_transform.proj2img(_bounds.topLeft()) / coordinatesRatio(),
|
||||
_transform.proj2img(_bounds.bottomRight()) / coordinatesRatio())
|
||||
: QRectF();
|
||||
|
||||
return lb.isValid() ? lb & tb : tb;
|
||||
}
|
||||
|
||||
RectC WMTSMap::llBounds()
|
||||
{
|
||||
if (_wmts->bbox().isValid())
|
||||
return _wmts->bbox();
|
||||
else {
|
||||
int maxZoom = _wmts->zooms().size() - 1;
|
||||
QRectF tb(tileBounds(maxZoom));
|
||||
Transform t(transform(maxZoom));
|
||||
RectD rect(t.img2proj(tb.topLeft() * coordinatesRatio()),
|
||||
t.img2proj(tb.bottomRight() * coordinatesRatio()));
|
||||
return rect.toRectC(_wmts->projection());
|
||||
}
|
||||
}
|
||||
|
||||
int WMTSMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
|
@ -14,12 +14,13 @@ class WMTSMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio,
|
||||
QObject *parent = 0);
|
||||
WMTSMap(const QString &fileName, const QString &name,
|
||||
const WMTS::Setup &setup, qreal tileRatio, QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds();
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -45,6 +46,8 @@ private slots:
|
||||
|
||||
private:
|
||||
double sd2res(double scaleDenominator) const;
|
||||
Transform transform(int zoom) const;
|
||||
QRectF tileBounds(int zoom) const;
|
||||
void updateTransform();
|
||||
QSizeF tileSize(const WMTS::Zoom &zoom) const;
|
||||
qreal coordinatesRatio() const;
|
||||
|