mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added support for GPI speed/red light cameras
This commit is contained in:
parent
6d6dc9f316
commit
db7e60bdfb
@ -21,6 +21,7 @@ INCLUDEPATH += ./src
|
||||
HEADERS += src/common/config.h \
|
||||
src/GUI/graphicsscene.h \
|
||||
src/GUI/popup.h \
|
||||
src/common/garmin.h \
|
||||
src/common/staticassert.h \
|
||||
src/common/coordinates.h \
|
||||
src/common/range.h \
|
||||
@ -178,7 +179,6 @@ HEADERS += src/common/config.h \
|
||||
src/map/IMG/lblfile.h \
|
||||
src/map/IMG/vectortile.h \
|
||||
src/map/IMG/subdiv.h \
|
||||
src/map/IMG/units.h \
|
||||
src/map/IMG/style.h \
|
||||
src/map/IMG/netfile.h \
|
||||
src/GUI/limitedcombobox.h \
|
||||
|
18
src/common/garmin.h
Normal file
18
src/common/garmin.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef GARMIN_H
|
||||
#define GARMIN_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
inline double toWGS32(qint32 v)
|
||||
{
|
||||
return (double)(((double)v / (double)(1<<31)) * (double)180);
|
||||
}
|
||||
|
||||
inline double toWGS24(qint32 coord)
|
||||
{
|
||||
return (coord < 0x800000)
|
||||
? (double)coord * 360.0 / (double)(1<<24)
|
||||
: (double)(coord - 0x1000000) * 360.0 / (double)(1<<24);
|
||||
}
|
||||
|
||||
#endif // GARMIN_H
|
@ -10,6 +10,7 @@
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
#include <QTemporaryDir>
|
||||
#endif // QT_VERSION >= 5
|
||||
#include "common/garmin.h"
|
||||
#include "gpiparser.h"
|
||||
|
||||
|
||||
@ -112,9 +113,15 @@ qint64 CryptDevice::readData(char *data, qint64 maxSize)
|
||||
return ts;
|
||||
}
|
||||
|
||||
static inline double toWGS(qint32 v)
|
||||
|
||||
static qint32 readInt24(QDataStream &stream)
|
||||
{
|
||||
return (double)(((double)v / (double)(1U<<31)) * (double)180);
|
||||
unsigned char data[3];
|
||||
quint32 val;
|
||||
|
||||
stream.readRawData((char*)data, sizeof(data));
|
||||
val = data[0] | ((quint32)data[1]) << 8 | ((quint32)data[2]) << 16;
|
||||
return (val > 0x7FFFFF) ? (val & 0x7FFFFF) - 0x800000 : val;
|
||||
}
|
||||
|
||||
static quint16 nextHeaderType(QDataStream &stream)
|
||||
@ -415,6 +422,85 @@ static quint32 readImageInfo(QDataStream &stream, Waypoint &waypoint,
|
||||
}
|
||||
#endif // QT_VERSION >= 5
|
||||
|
||||
static int speed(quint8 flags)
|
||||
{
|
||||
switch (flags >> 4) {
|
||||
case 0x8:
|
||||
return 40;
|
||||
case 0x9:
|
||||
return 30;
|
||||
case 0xA:
|
||||
return 50;
|
||||
case 0xB:
|
||||
return 70;
|
||||
case 0xC:
|
||||
return 80;
|
||||
case 0xD:
|
||||
return 90;
|
||||
case 0xE:
|
||||
return 100;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static quint32 readCamera(QDataStream &stream, QVector<Waypoint> &waypoints,
|
||||
QList<Area> &polygons)
|
||||
{
|
||||
RecordHeader rh;
|
||||
quint8 flags, type, s7, rs;
|
||||
qint32 top, right, bottom, left;
|
||||
|
||||
|
||||
rs = readRecordHeader(stream, rh);
|
||||
top = readInt24(stream);
|
||||
right = readInt24(stream);
|
||||
bottom = readInt24(stream);
|
||||
left = readInt24(stream);
|
||||
|
||||
stream >> flags >> type >> s7;
|
||||
|
||||
if (s7) {
|
||||
int skip = s7 + 2 + s7/4;
|
||||
stream.skipRawData(skip);
|
||||
qint32 lat = readInt24(stream);
|
||||
qint32 lon = readInt24(stream);
|
||||
stream.skipRawData(rh.size - 12 - 3 - skip - 6);
|
||||
|
||||
waypoints.append(Coordinates(toWGS24(lon), toWGS24(lat)));
|
||||
} else
|
||||
stream.skipRawData(rh.size - 15);
|
||||
|
||||
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);
|
||||
|
||||
switch (type) {
|
||||
case 8:
|
||||
area.setDescription(QString("%1 mi/h")
|
||||
.arg(speed(flags)));
|
||||
break;
|
||||
case 9:
|
||||
area.setDescription(QString("%1 km/h")
|
||||
.arg(speed(flags)));
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
area.setDescription("Red light camera");
|
||||
break;
|
||||
}
|
||||
|
||||
polygons.append(area);
|
||||
|
||||
return rs + rh.size;
|
||||
}
|
||||
|
||||
static quint32 readPOI(QDataStream &stream, QTextCodec *codec,
|
||||
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId)
|
||||
{
|
||||
@ -431,7 +517,7 @@ static quint32 readPOI(QDataStream &stream, QTextCodec *codec,
|
||||
ds = 10 + s3;
|
||||
ds += readTranslatedObjects(stream, codec, obj);
|
||||
|
||||
waypoints.append(Waypoint(Coordinates(toWGS(lon), toWGS(lat))));
|
||||
waypoints.append(Waypoint(Coordinates(toWGS32(lon), toWGS32(lat))));
|
||||
if (!obj.isEmpty())
|
||||
waypoints.last().setName(obj.first().str());
|
||||
|
||||
@ -466,7 +552,8 @@ static quint32 readPOI(QDataStream &stream, QTextCodec *codec,
|
||||
}
|
||||
|
||||
static quint32 readSpatialIndex(QDataStream &stream, QTextCodec *codec,
|
||||
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId)
|
||||
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||
int &imgId)
|
||||
{
|
||||
RecordHeader rh;
|
||||
quint32 ds, s5;
|
||||
@ -485,8 +572,11 @@ static quint32 readSpatialIndex(QDataStream &stream, QTextCodec *codec,
|
||||
ds += readPOI(stream, codec, waypoints, fileName, imgId);
|
||||
break;
|
||||
case 8:
|
||||
ds += readSpatialIndex(stream, codec, waypoints, fileName,
|
||||
imgId);
|
||||
ds += readSpatialIndex(stream, codec, waypoints, polygons,
|
||||
fileName, imgId);
|
||||
break;
|
||||
case 19:
|
||||
ds += readCamera(stream, waypoints, polygons);
|
||||
break;
|
||||
default:
|
||||
ds += skipRecord(stream);
|
||||
@ -501,7 +591,8 @@ static quint32 readSpatialIndex(QDataStream &stream, QTextCodec *codec,
|
||||
}
|
||||
|
||||
static void readPOIDatabase(QDataStream &stream, QTextCodec *codec,
|
||||
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId)
|
||||
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||
int &imgId)
|
||||
{
|
||||
RecordHeader rh;
|
||||
QList<TranslatedString> obj;
|
||||
@ -509,7 +600,7 @@ static void readPOIDatabase(QDataStream &stream, QTextCodec *codec,
|
||||
|
||||
readRecordHeader(stream, rh);
|
||||
ds = readTranslatedObjects(stream, codec, obj);
|
||||
ds += readSpatialIndex(stream, codec, waypoints, fileName, imgId);
|
||||
ds += readSpatialIndex(stream, codec, waypoints, polygons, fileName, imgId);
|
||||
if (rh.flags & 0x8) {
|
||||
while (stream.status() == QDataStream::Ok && ds < rh.size) {
|
||||
switch(nextHeaderType(stream)) {
|
||||
@ -526,12 +617,14 @@ static void readPOIDatabase(QDataStream &stream, QTextCodec *codec,
|
||||
}
|
||||
|
||||
bool GPIParser::readData(QDataStream &stream, QTextCodec *codec,
|
||||
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId)
|
||||
QVector<Waypoint> &waypoints, QList<Area> &polygons, const QString &fileName,
|
||||
int &imgId)
|
||||
{
|
||||
while (stream.status() == QDataStream::Ok) {
|
||||
switch (nextHeaderType(stream)) {
|
||||
case 0x09: // POI database
|
||||
readPOIDatabase(stream, codec, waypoints, fileName, imgId);
|
||||
readPOIDatabase(stream, codec, waypoints, polygons, fileName,
|
||||
imgId);
|
||||
break;
|
||||
case 0xffff: // EOF
|
||||
skipRecord(stream);
|
||||
@ -631,7 +724,9 @@ bool GPIParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||
CryptDevice dev(stream.device(), 0xf870b5, ebs);
|
||||
QDataStream cryptStream(&dev);
|
||||
cryptStream.setByteOrder(QDataStream::LittleEndian);
|
||||
return readData(cryptStream, codec, waypoints, file->fileName(), imgId);
|
||||
return readData(cryptStream, codec, waypoints, polygons, file->fileName(),
|
||||
imgId);
|
||||
} else
|
||||
return readData(stream, codec, waypoints, file->fileName(), imgId);
|
||||
return readData(stream, codec, waypoints, polygons, file->fileName(),
|
||||
imgId);
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ private:
|
||||
bool readFileHeader(QDataStream &stream, quint32 &ebs);
|
||||
bool readGPIHeader(QDataStream &stream, QTextCodec **codec);
|
||||
bool readData(QDataStream &stream, QTextCodec *codec,
|
||||
QVector<Waypoint> &waypoints, const QString &fileName, int &imgId);
|
||||
QVector<Waypoint> &waypoints, QList<Area> &polygons,
|
||||
const QString &fileName, int &imgId);
|
||||
|
||||
QString _errorString;
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "common/rectc.h"
|
||||
#include "units.h"
|
||||
#include "common/garmin.h"
|
||||
#include "lblfile.h"
|
||||
#include "netfile.h"
|
||||
#include "rgnfile.h"
|
||||
@ -193,7 +193,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
RectC br(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
@ -204,7 +204,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
@ -259,7 +259,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
|
||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
RectC br(c, c);
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
|
||||
@ -269,7 +269,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
||||
pos.rx() += lonDelta<<(24-subdiv->bits());
|
||||
pos.ry() += latDelta<<(24-subdiv->bits());
|
||||
|
||||
Coordinates c(toWGS84(pos.x()), toWGS84(pos.y()));
|
||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||
br = br.united(c);
|
||||
}
|
||||
@ -321,8 +321,8 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
||||
toWGS84(subdiv->lat() + latOffset));
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
|
||||
if (!rect.contains(point.coordinates))
|
||||
continue;
|
||||
@ -367,8 +367,8 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
||||
|
||||
qint16 lonOffset = lon<<(24-subdiv->bits());
|
||||
qint16 latOffset = lat<<(24-subdiv->bits());
|
||||
point.coordinates = Coordinates(toWGS84(subdiv->lon() + lonOffset),
|
||||
toWGS84(subdiv->lat() + latOffset));
|
||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||
toWGS24(subdiv->lat() + latOffset));
|
||||
|
||||
if (subtype & 0x20) {
|
||||
if (!readUInt24(hdl, labelPtr))
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include <QtGlobal>
|
||||
#include "common/coordinates.h"
|
||||
#include "units.h"
|
||||
#include "common/garmin.h"
|
||||
|
||||
class SubDiv {
|
||||
public:
|
||||
@ -51,7 +51,7 @@ private:
|
||||
#ifndef QT_NO_DEBUG
|
||||
inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv)
|
||||
{
|
||||
Coordinates c(toWGS84(subdiv.lon()), toWGS84(subdiv.lat()));
|
||||
Coordinates c(toWGS24(subdiv.lon()), toWGS24(subdiv.lat()));
|
||||
dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset()
|
||||
<< ", " << subdiv.end() << ", " << subdiv.objects() << ")";
|
||||
return dbg.space();
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "common/garmin.h"
|
||||
#include "subdiv.h"
|
||||
#include "units.h"
|
||||
#include "trefile.h"
|
||||
|
||||
|
||||
@ -52,8 +52,8 @@ bool TREFile::init()
|
||||
if (!(seek(hdl, _gmpOffset + 0x15) && readInt24(hdl, north)
|
||||
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
|
||||
return false;
|
||||
_bounds = RectC(Coordinates(toWGS84(west), toWGS84(north)),
|
||||
Coordinates(toWGS84(east), toWGS84(south)));
|
||||
_bounds = RectC(Coordinates(toWGS24(west), toWGS24(north)),
|
||||
Coordinates(toWGS24(east), toWGS24(south)));
|
||||
|
||||
// Levels & subdivs info
|
||||
quint32 levelsOffset, levelsSize, subdivSize;
|
||||
@ -150,9 +150,9 @@ bool TREFile::load(int idx)
|
||||
sl.append(s);
|
||||
|
||||
double min[2], max[2];
|
||||
RectC bounds(Coordinates(toWGS84(lon - width),
|
||||
toWGS84(lat + height + 1)), Coordinates(toWGS84(lon + width + 1),
|
||||
toWGS84(lat - height)));
|
||||
RectC bounds(Coordinates(toWGS24(lon - width),
|
||||
toWGS24(lat + height + 1)), Coordinates(toWGS24(lon + width + 1),
|
||||
toWGS24(lat - height)));
|
||||
|
||||
min[0] = bounds.left();
|
||||
min[1] = bounds.bottom();
|
||||
|
@ -1,11 +0,0 @@
|
||||
#ifndef UNITS_H
|
||||
#define UNITS_H
|
||||
|
||||
inline double toWGS84(qint32 coord)
|
||||
{
|
||||
return (coord < 0x800000)
|
||||
? (double)coord * 360.0 / (double)(1<<24)
|
||||
: (double)(coord - 0x1000000) * 360.0 / (double)(1<<24);
|
||||
}
|
||||
|
||||
#endif // UNITS_H
|
Loading…
Reference in New Issue
Block a user