From 42e4b0769f7aa0d51d99a7d0e0d2e5895b5ad9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sat, 15 Feb 2020 11:46:16 +0100 Subject: [PATCH] Fixed broken tile/subdivs/polygon bounds/coordinates + do the coordinates left shift in a C++ standard defined way --- src/common/garmin.h | 6 ++++-- src/map/IMG/rgnfile.cpp | 42 +++++++++++++++++++++++------------------ src/map/IMG/trefile.cpp | 19 ++++++++++++------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/common/garmin.h b/src/common/garmin.h index 380a4fe6..487e2ff5 100644 --- a/src/common/garmin.h +++ b/src/common/garmin.h @@ -3,14 +3,16 @@ #include +#define LS(val, bits) ((qint32)(((quint32)(val))<<(bits))) + inline double toWGS32(qint32 v) { - return (double)(((double)v / (double)(1U<<31)) * (double)180); + return ((double)v / (double)(1U<<31)) * 180.0; } inline double toWGS24(qint32 v) { - return toWGS32(v<<8); + return toWGS32(LS(v, 8)); } #endif // GARMIN_H diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 7221bfb6..6ae48f39 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -154,8 +154,8 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv, ? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8; - QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), - subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); + QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()), + subdiv->lat() + LS(lat, 24-subdiv->bits())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); @@ -164,8 +164,10 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv, DeltaStream stream(*this, hdl, len, bitstreamInfo, labelPtr & 0x400000, false); while (stream.readNext(lonDelta, latDelta)) { - pos.rx() += lonDelta<<(24-subdiv->bits()); - pos.ry() += latDelta<<(24-subdiv->bits()); + pos.rx() += LS(lonDelta, (24-subdiv->bits())); + if (pos.rx() >= 0x800000 && subdiv->lon() >= 0) + pos.rx() = 0x7fffff; + pos.ry() += LS(latDelta, (24-subdiv->bits())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); @@ -219,8 +221,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, labelPtr = 0; if (!_huffmanTable.isNull()) { - pos = QPoint((subdiv->lon()<<8) + ((qint32)lon<<(32-subdiv->bits())), - (subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits()))); + pos = QPoint(LS(subdiv->lon(), 8) + LS(lon, 32-subdiv->bits()), + LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits()))); qint32 lonDelta, latDelta; HuffmanStream stream(*this, hdl, len, _huffmanTable, @@ -229,16 +231,18 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, if (shift) { if (!stream.readOffset(lonDelta, latDelta)) return false; - pos = QPoint(pos.x() | lonDelta<<(32-subdiv->bits()-shift), - pos.y() | latDelta<<(32-subdiv->bits()-shift)); + pos = QPoint(pos.x() | LS(lonDelta, 32-subdiv->bits()-shift), + pos.y() | LS(latDelta, 32-subdiv->bits()-shift)); } Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); while (stream.readNext(lonDelta, latDelta)) { - pos.rx() += lonDelta<<(32-subdiv->bits()-shift); - pos.ry() += latDelta<<(32-subdiv->bits()-shift); + pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift); + if (pos.rx() < 0 && subdiv->lon() >= 0) + pos.rx() = 0x7fffffff; + pos.ry() += LS(latDelta, 32-subdiv->bits()-shift); Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); @@ -248,8 +252,8 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, if (!(stream.atEnd() && stream.flush())) return false; } else { - pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), - subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); + pos = QPoint(subdiv->lon() + LS(lon, 24-subdiv->bits()), + subdiv->lat() + LS(lat, 24-subdiv->bits())); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); @@ -262,8 +266,10 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, DeltaStream stream(*this, hdl, len - 1, bitstreamInfo, false, true); while (stream.readNext(lonDelta, latDelta)) { - pos.rx() += lonDelta<<(24-subdiv->bits()); - pos.ry() += latDelta<<(24-subdiv->bits()); + pos.rx() += LS(lonDelta, 24-subdiv->bits()); + if (pos.rx() >= 0x800000 && subdiv->lon() >= 0) + pos.rx() = 0x7fffff; + pos.ry() += LS(latDelta, 24-subdiv->bits()); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); @@ -319,8 +325,8 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv, point.type = (quint16)type<<8 | subtype; - qint32 lonOffset = lon<<(24-subdiv->bits()); - qint32 latOffset = lat<<(24-subdiv->bits()); + qint32 lonOffset = LS(lon, 24-subdiv->bits()); + qint32 latOffset = LS(lat, 24-subdiv->bits()); point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset), toWGS24(subdiv->lat() + latOffset)); @@ -361,8 +367,8 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F); - qint32 lonOffset = lon<<(24-subdiv->bits()); - qint32 latOffset = lat<<(24-subdiv->bits()); + qint32 lonOffset = LS(lon, 24-subdiv->bits()); + qint32 latOffset = LS(lat, 24-subdiv->bits()); point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset), toWGS24(subdiv->lat() + latOffset)); labelPtr = 0; diff --git a/src/map/IMG/trefile.cpp b/src/map/IMG/trefile.cpp index 53df9ae3..6854cbf0 100644 --- a/src/map/IMG/trefile.cpp +++ b/src/map/IMG/trefile.cpp @@ -3,6 +3,11 @@ #include "trefile.h" +static inline double RB(qint32 val) +{ + return (val == -0x800000 || val == 0x800000) ? 180.0 : toWGS24(val); +} + static void demangle(quint8 *data, quint32 size, quint32 key) { static const unsigned char shuf[] = { @@ -53,7 +58,8 @@ bool TREFile::init(bool baseMap) && readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west))) return false; _bounds = RectC(Coordinates(toWGS24(west), toWGS24(north)), - Coordinates(toWGS24(east), toWGS24(south))); + Coordinates(RB(east), toWGS24(south))); + Q_ASSERT(_bounds.left() <= _bounds.right()); // Levels & subdivs info quint32 levelsOffset, levelsSize, subdivSize; @@ -149,17 +155,16 @@ bool TREFile::load(int idx) s->setEnd(offset); width &= 0x7FFF; - width <<= (24 - _levels.at(idx).bits); - height <<= (24 - _levels.at(idx).bits); - + width = LS(width, 24 - _levels.at(idx).bits); + height = LS(height, 24 - _levels.at(idx).bits); s = new SubDiv(offset, lon, lat, _levels.at(idx).bits, objects); sl.append(s); double min[2], max[2]; - RectC bounds(Coordinates(toWGS24(lon - width), - toWGS24(lat + height + 1)), Coordinates(toWGS24(lon + width + 1), - toWGS24(lat - height))); + RectC bounds(Coordinates(toWGS24(lon - width), toWGS24(lat + height)), + Coordinates(RB(lon + width), toWGS24(lat - height))); + Q_ASSERT(bounds.left() <= bounds.right()); min[0] = bounds.left(); min[1] = bounds.bottom();