diff --git a/gpxsee.pro b/gpxsee.pro index 9c512cca..4b279f37 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -118,6 +118,7 @@ HEADERS += src/common/config.h \ src/data/gpsdumpparser.h \ src/data/style.h \ src/data/twonavparser.h \ + src/map/IMG/lights.h \ src/map/downloader.h \ src/map/demloader.h \ src/map/ENC/attributes.h \ diff --git a/gpxsee.qrc b/gpxsee.qrc index b75d8f19..8eca235c 100644 --- a/gpxsee.qrc +++ b/gpxsee.qrc @@ -193,6 +193,10 @@ icons/map/marine/overfalls.png icons/map/marine/boarding-place.png icons/map/marine/light.png + icons/map/marine/light-red.png + icons/map/marine/light-green.png + icons/map/marine/light-yellow.png + icons/map/marine/light-white.png icons/map/marine/building.png icons/map/marine/fog-signal.png icons/map/marine/construction.png diff --git a/icons/map/marine/anchorage.png b/icons/map/marine/anchorage.png index 9b8f2de6..e87bb9f5 100644 Binary files a/icons/map/marine/anchorage.png and b/icons/map/marine/anchorage.png differ diff --git a/icons/map/marine/anchoring-prohibited.png b/icons/map/marine/anchoring-prohibited.png index b17d2317..3463fa39 100644 Binary files a/icons/map/marine/anchoring-prohibited.png and b/icons/map/marine/anchoring-prohibited.png differ diff --git a/icons/map/marine/light-green.png b/icons/map/marine/light-green.png new file mode 100644 index 00000000..af48f5d1 Binary files /dev/null and b/icons/map/marine/light-green.png differ diff --git a/icons/map/marine/light-red.png b/icons/map/marine/light-red.png new file mode 100644 index 00000000..199b7ece Binary files /dev/null and b/icons/map/marine/light-red.png differ diff --git a/icons/map/marine/light-white.png b/icons/map/marine/light-white.png new file mode 100644 index 00000000..a0e2d062 Binary files /dev/null and b/icons/map/marine/light-white.png differ diff --git a/icons/map/marine/light-yellow.png b/icons/map/marine/light-yellow.png new file mode 100644 index 00000000..4b7ca018 Binary files /dev/null and b/icons/map/marine/light-yellow.png differ diff --git a/icons/map/marine/pipeline.png b/icons/map/marine/pipeline.png index 23072601..55ff9b58 100644 Binary files a/icons/map/marine/pipeline.png and b/icons/map/marine/pipeline.png differ diff --git a/src/map/ENC/attributes.h b/src/map/ENC/attributes.h index c2f7bf3b..01ee9b91 100644 --- a/src/map/ENC/attributes.h +++ b/src/map/ENC/attributes.h @@ -6,6 +6,7 @@ #define CATDIS 21 #define CATHAF 30 #define CATLMK 35 +#define CATLIT 37 #define CATMFA 38 #define CATMOR 40 #define CATTRK 54 @@ -16,16 +17,21 @@ #define CATWAT 69 #define CATWED 70 #define CATWRK 71 +#define COLOUR 75 #define COMCHA 77 #define CURVEL 84 #define DRVAL1 87 #define ELEVAT 90 #define FUNCTN 94 +#define LITVIS 108 #define OBJNAM 116 #define ORIENT 117 #define RESTRN 131 +#define SECTR1 136 +#define SECTR2 137 #define TRAFIC 172 #define VALDCO 174 +#define VALNMR 178 #define VERCLR 181 #define WATLEV 187 diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 79fd75f6..41c594e2 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -173,19 +173,31 @@ static bool polygonCb(const MapData::Poly *polygon, void *context) static bool polygonPointCb(const MapData::Poly *polygon, void *context) { QList *points = (QList*)context; - uint baseType = polygon->type()>>16; + uint type = polygon->type(); + uint baseType = type>>16; - if (!polygon->label().isEmpty() || baseType == TSSLPT || baseType == RCTLPT - || baseType == I_TRNBSN - || polygon->type() == SUBTYPE(ACHARE, 2) - || polygon->type() == SUBTYPE(ACHARE, 3) - || polygon->type() == SUBTYPE(ACHARE, 9) - || polygon->type() == SUBTYPE(I_ACHARE, 2) - || polygon->type() == SUBTYPE(I_ACHARE, 3) - || polygon->type() == SUBTYPE(I_ACHARE, 9) - || polygon->type() == SUBTYPE(I_BERTHS, 6)) - points->append(MapData::Point(polygon->type(), polygon->bounds().center(), - polygon->label(), polygon->param())); + if (baseType == TSSLPT || baseType == RCTLPT || baseType == I_TRNBSN + || baseType == BRIDGE || baseType == I_BRIDGE || baseType == BUAARE + || baseType == RESARE || baseType == I_RESARE || baseType == LNDARE + || baseType == LNDRGN + || type == SUBTYPE(ACHARE, 2) || type == SUBTYPE(ACHARE, 3) + || type == SUBTYPE(ACHARE, 9) || type == SUBTYPE(I_ACHARE, 2) + || type == SUBTYPE(I_ACHARE, 3) || type == SUBTYPE(I_ACHARE, 9) + || type == SUBTYPE(I_BERTHS, 6)) + points->append(MapData::Point(baseType, polygon->bounds().center(), + polygon->attributes(), polygon->HUNI())); + + return true; +} + +static bool linePointCb(const MapData::Line *line, void *context) +{ + QList *points = (QList*)context; + uint baseType = line->type()>>16; + + if (baseType == RDOCAL || baseType == I_RDOCAL) + points->append(MapData::Point(baseType, line->bounds().center(), + line->attributes(), 1)); return true; } @@ -207,10 +219,8 @@ static Coordinates point(const ISO8211::Record &r, uint COMF) return coordinates(x, y, COMF); } -static uint depthLevel(const QByteArray &ba) +static uint depthLevel(double minDepth) { - double minDepth = ba.isEmpty() ? -1 : ba.toDouble(); - if (minDepth < 0) return 0; else if (minDepth < 2) @@ -275,72 +285,145 @@ static QString weed(uint type) } } -MapData::Point::Point(uint type, const Coordinates &c, const QString &label, - const QVector ¶ms) : _type(type), _pos(c), _label(label) +MapData::Point::Point(uint type, const Coordinates &c, const QString &label) + : _type(SUBTYPE(type, 0)), _pos(c), _label(label) { - _id = ((quint64)order(type))<<32 | (uint)qHash(c); + _id = ((quint64)order(_type))<<32 | (uint)qHash(c); +} - if (type>>16 == I_DISMAR && params.size()) { - _label = hUnits((type>>8)&0xFF) + " " + QString::fromLatin1(params.at(0)); - _type = SUBTYPE(I_DISMAR, type & 0xFF); - } else if ((type>>16 == I_RDOCAL || type>>16 == RDOCAL) && params.size() > 1) { - if (!params.at(1).isEmpty()) - _label = QString("VHF ") + QString::fromLatin1(params.at(1)); - _param = QVariant(params.at(0).toDouble()); - } else if (type>>16 == CURENT && params.size() > 1) { - if (!params.at(1).isEmpty()) - _label = QString::fromLatin1(params.at(1)) - + QString::fromUtf8("\xE2\x80\x89kt"); - _param = QVariant(params.at(0).toDouble()); - } else if (type>>16 == I_SISTAT || type>>16 == SISTAT) { +MapData::Point::Point(uint type, const Coordinates &c, const Attributes &attr, + uint HUNI) : _pos(c), _attr(attr) +{ + uint subtype = 0; + + if (type == HRBFAC) + subtype = CATHAF; + else if (type == I_HRBFAC) + subtype = I_CATHAF; + else if (type == LNDMRK) + subtype = CATLMK; + else if (type == WRECKS) + subtype = CATWRK; + else if (type == MORFAC) + subtype = CATMOR; + else if (type == UWTROC) + subtype = WATLEV; + else if (type == BUAARE) + subtype = CATBUA; + else if (type == SMCFAC) + subtype = CATSCF; + else if (type == BUISGL) + subtype = FUNCTN; + else if (type == WATTUR) + subtype = CATWAT; + else if (type == RDOCAL) + subtype = TRAFIC; + else if (type == I_RDOCAL) + subtype = TRAFIC; + else if (type == SILTNK) + subtype = CATSIL; + else if (type == WEDKLP) + subtype = CATWED; + else if (type == LIGHTS) + subtype = CATLIT; + else if (type == I_DISMAR) + subtype = CATDIS; + + QList list(_attr.value(subtype).split(',')); + std::sort(list.begin(), list.end()); + _type = SUBTYPE(type, list.first().toUInt()); + _id = ((quint64)order(_type))<<32 | (uint)qHash(c); + _label = QString::fromLatin1(_attr.value(OBJNAM)); + + if (type == I_DISMAR) { + if (_attr.contains(I_WTWDIS) && _attr.contains(I_HUNITS)) + _label = hUnits(_attr.value(I_HUNITS).toUInt()) + " " + + QString::fromLatin1(_attr.value(I_WTWDIS)); + } else if (type == I_RDOCAL || type == RDOCAL) { + QByteArray cc(_attr.value(COMCHA)); + if (!cc.isEmpty()) + _label = QString("VHF ") + QString::fromLatin1(cc); + } else if (type == CURENT) { + QByteArray cv(_attr.value(CURVEL)); + if (!cv.isEmpty()) + _label = QString::fromLatin1(cv) + QString::fromUtf8("\xE2\x80\x89kt"); + } else if (type == SISTAT) { + if (_label.isEmpty() && _attr.contains(CATSIT)) + _label = sistat(_attr.value(CATSIT).toUInt()); + } else if (type == I_SISTAT) { + if (_label.isEmpty() && _attr.contains(I_CATSIT)) + _label = sistat(_attr.value(I_CATSIT).toUInt()); + } else if (type == WEDKLP) { if (_label.isEmpty()) - _label = sistat(type & 0xFF); - _type = TYPE(SISTAT); - } else if (type>>16 == WEDKLP) { + _label = weed(_type & 0xFF); + } else if (type == LNDELV) { if (_label.isEmpty()) - _label = weed(type & 0xFF); - } else if (type>>16 == LNDELV && params.size()) { - if (_label.isEmpty()) - _label = QString::fromLatin1(params.at(0)) + _label = QString::fromLatin1(_attr.value(ELEVAT)) + QString::fromUtf8("\xE2\x80\x89m"); else - _label += "\n(" + QString::fromLatin1(params.at(0)) + _label += "\n(" + QString::fromLatin1(_attr.value(ELEVAT)) + "\xE2\x80\x89m)"; - } else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size()) - _param = QVariant(params.at(0).toDouble()); -} - -MapData::Point::Point(uint type, const Coordinates &c, const QString &label, - const QVariant ¶m) : _type(type), _pos(c), _label(label), _param(param) -{ - _id = ((quint64)order(type))<<32 | (uint)qHash(c); -} - -MapData::Poly::Poly(uint type, const Polygon &path, const QString &label, - const QVector ¶ms, uint HUNI) : _type(type), _path(path) -{ - if (type == TYPE(DEPARE) && params.size()) - _type = SUBTYPE(DEPARE, depthLevel(params.at(0))); - else if ((type == TYPE(TSSLPT) || type == TYPE(RCTLPT)) && params.size()) - _param = QVariant(params.at(0).toDouble()); - else if ((type == TYPE(BRIDGE) || type == TYPE(I_BRIDGE)) - && params.size()) { - double clr = params.at(0).toDouble(); + } else if (type == BRIDGE || type == I_BRIDGE) { + double clr = _attr.value(VERCLR).toDouble(); if (clr > 0) { _label = QString::fromUtf8("\xE2\x86\x95") + UNIT_SPACE + QString::number(clr) + UNIT_SPACE + hUnits(HUNI); } - } else if (type>>16 == LNDARE || type>>16 == SEAARE || type>>16 == BERTHS - || type>>16 == I_BERTHS || type>>16 == BUAARE) - _label = label; + } +} + +MapData::Poly::Poly(uint type, const Polygon &path, const Attributes &attr, + uint HUNI) : _path(path), _attr(attr), _HUNI(HUNI) +{ + uint subtype = 0; + + if (type == RESARE || type == I_RESARE) + subtype = CATREA; + else if (type == ACHARE) + subtype = CATACH; + else if (type == I_ACHARE) + subtype = I_CATACH; + else if (type == HRBFAC) + subtype = CATHAF; + else if (type == MARKUL) + subtype = CATMFA; + else if (type == I_BERTHS) + subtype = I_CATBRT; + else if (type == RESARE || type == I_RESARE) { + uint restr = _attr.value((type == RESARE) ? RESTRN : I_RESTRN).toUInt(); + if (restr == 1) + subtype = 2; + else if (restr == 7) + subtype = 17; + } + + _type = (type == DEPARE) + ? SUBTYPE(DEPARE, depthLevel(_attr.value(DRVAL1).toDouble())) + : SUBTYPE(type, _attr.value(subtype).toUInt()); } MapData::Line::Line(uint type, const QVector &path, - const QString &label, const QVector ¶ms) - : _type(type), _path(path), _label(label) + const Attributes &attr) : _path(path), _attr(attr) { - if ((type == TYPE(DEPCNT) || type == TYPE(LNDELV)) && params.size()) - _label = QString::fromLatin1(params.at(0)); + uint subtype = 0; + + if (type == RECTRC) + subtype = CATTRK; + else if (type == RCRTCL) + subtype = CATTRK; + else if (type == RDOCAL) + subtype = TRAFIC; + else if (type == I_RDOCAL) + subtype = TRAFIC; + + _type = SUBTYPE(type, _attr.value(subtype).toUInt()); + + if (type == DEPCNT) + _label = QString::fromLatin1(_attr.value(VALDCO)); + else if (type == LNDELV) + _label = QString::fromLatin1(_attr.value(ELEVAT)); + else + _label = QString::fromLatin1(_attr.value(OBJNAM)); } RectC MapData::Line::bounds() const @@ -581,169 +664,46 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc, return path; } -MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL) +MapData::Attributes MapData::attributes(const ISO8211::Record &r) { - QString label; - QVector params(2); - uint subtype = 0; + Attributes attr; const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF"); if (!(ATTF && ATTF->data().at(0).size() == 2)) - return Attr(); + return attr; for (int i = 0; i < ATTF->data().size(); i++) { const QVector &av = ATTF->data().at(i); - uint key = av.at(0).toUInt(); - - if (key == OBJNAM) - label = QString::fromLatin1(av.at(1).toByteArray()); - - if ((OBJL == HRBFAC && key == CATHAF) - || (OBJL == I_HRBFAC && key == I_CATHAF) - || (OBJL == LNDMRK && key == CATLMK) - || (OBJL == WRECKS && key == CATWRK) - || (OBJL == MORFAC && key == CATMOR) - || (OBJL == UWTROC && key == WATLEV) - || (OBJL == BUAARE && key == CATBUA) - || (OBJL == SMCFAC && key == CATSCF) - || (OBJL == BUISGL && key == FUNCTN) - || (OBJL == WATTUR && key == CATWAT) - || (OBJL == SISTAT && key == CATSIT) - || (OBJL == I_SISTAT && key == I_CATSIT) - || (OBJL == RDOCAL && key == TRAFIC) - || (OBJL == I_RDOCAL && key == TRAFIC) - || (OBJL == SILTNK && key == CATSIL) - || (OBJL == WEDKLP && key == CATWED)) - subtype = av.at(1).toByteArray().toUInt(); - else if (OBJL == I_DISMAR && key == CATDIS) - subtype |= av.at(1).toByteArray().toUInt(); - else if (OBJL == I_DISMAR && key == I_HUNITS) - subtype |= av.at(1).toByteArray().toUInt() << 8; - - if ((OBJL == I_DISMAR && key == I_WTWDIS) - || (OBJL == RDOCAL && key == ORIENT) - || (OBJL == I_RDOCAL && key == ORIENT) - || (OBJL == CURENT && key == ORIENT) - || (OBJL == LNDELV && key == ELEVAT) - || (OBJL == TSSLPT && key == ORIENT) - || (OBJL == RCTLPT && key == ORIENT)) - params[0] = av.at(1).toByteArray(); - if ((OBJL == I_RDOCAL && key == COMCHA) - || (OBJL == RDOCAL && key == COMCHA) - || (OBJL == CURENT && key == CURVEL)) - params[1] = av.at(1).toByteArray(); + attr.insert(av.at(0).toUInt(), av.at(1).toByteArray()); } - return Attr(subtype, label, params); -} - -MapData::Attr MapData::lineAttr(const ISO8211::Record &r, uint OBJL) -{ - QString label; - QVector params(1); - uint subtype = 0; - - const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF"); - if (!(ATTF && ATTF->data().at(0).size() == 2)) - return Attr(); - - for (int i = 0; i < ATTF->data().size(); i++) { - const QVector &av = ATTF->data().at(i); - uint key = av.at(0).toUInt(); - - if (key == OBJNAM) - label = QString::fromLatin1(av.at(1).toByteArray()); - - if ((OBJL == RECTRC || OBJL == RCRTCL) && key == CATTRK) - subtype = av.at(1).toByteArray().toUInt(); - - if ((OBJL == DEPCNT && key == VALDCO) - || (OBJL == LNDELV && key == ELEVAT)) - params[0] = av.at(1).toByteArray(); - } - - return Attr(subtype, label, params); -} - -MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL) -{ - QString label; - QVector params(1); - uint subtype = 0; - - const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF"); - if (!(ATTF && ATTF->data().at(0).size() == 2)) - return Attr(); - - for (int i = 0; i < ATTF->data().size(); i++) { - const QVector &av = ATTF->data().at(i); - uint key = av.at(0).toUInt(); - - if (key == OBJNAM) - label = QString::fromLatin1(av.at(1).toByteArray()); - - if ((OBJL == RESARE && key == CATREA) - || (OBJL == I_RESARE && key == CATREA) - || (OBJL == ACHARE && key == CATACH) - || (OBJL == I_ACHARE && key == I_CATACH) - || (OBJL == HRBFAC && key == CATHAF) - || (OBJL == MARKUL && key == CATMFA) - || (OBJL == I_BERTHS && key == I_CATBRT)) - subtype = av.at(1).toByteArray().toUInt(); - else if ((OBJL == RESARE && key == RESTRN) - || (OBJL == I_RESARE && key == I_RESTRN)) { - if (av.at(1).toByteArray().toUInt() == 1) - subtype = 2; - if (av.at(1).toByteArray().toUInt() == 7) - subtype = 17; - } - - if ((OBJL == TSSLPT && key == ORIENT) - || (OBJL == RCTLPT && key == ORIENT) - || (OBJL == DEPARE && key == DRVAL1)) - params[0] = av.at(1).toByteArray(); - if ((OBJL == BRIDGE && key == VERCLR) - || (OBJL == I_BRIDGE && key == VERCLR)) - params[0] = av.at(1).toByteArray(); - } - - return Attr(subtype, label, params); + return attr; } MapData::Point *MapData::pointObject(const Sounding &s) { - return new Point(TYPE(SOUNDG), s.c, QString::number(s.depth), - QVector()); + return new Point(SOUNDG, s.c, QString::number(s.depth)); } MapData::Point *MapData::pointObject(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL) + const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL, uint HUNI) { Coordinates c(pointGeometry(r, vi, vc, COMF)); - Attr attr(pointAttr(r, OBJL)); - - return (c.isNull() ? 0 : new Point(SUBTYPE(OBJL,attr.subtype()), c, - attr.label(), attr.params())); + return (c.isNull() ? 0 : new Point(OBJL, c, attributes(r), HUNI)); } MapData::Line *MapData::lineObject(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL) { QVector path(lineGeometry(r, vc, ve, COMF)); - Attr attr(lineAttr(r, OBJL)); - - return (path.isEmpty() ? 0 : new Line(SUBTYPE(OBJL, attr.subtype()), path, - attr.label(), attr.params())); + return (path.isEmpty() ? 0 : new Line(OBJL, path, attributes(r))); } MapData::Poly *MapData::polyObject(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI) { Polygon path(polyGeometry(r, vc, ve, COMF)); - Attr attr(polyAttr(r, OBJL)); - - return (path.isEmpty() ? 0 : new Poly(SUBTYPE(OBJL, attr.subtype()), path, - attr.label(), attr.params(), HUNI)); + return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI)); } bool MapData::processRecord(const ISO8211::Record &record, @@ -828,7 +788,7 @@ MapData::MapData(const QString &path) _points.Insert(min, max, point); } } else { - if ((point = pointObject(r, vi, vc, COMF, OBJL))) { + if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) { pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } else @@ -875,6 +835,7 @@ void MapData::points(const RectC &rect, QList *points) const rectcBounds(rect, min, max); _points.Search(min, max, pointCb, points); _areas.Search(min, max, polygonPointCb, points); + _lines.Search(min, max, linePointCb, points); } void MapData::lines(const RectC &rect, QList *lines) const diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index 9dc46d33..92e1b137 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -11,51 +11,51 @@ namespace ENC { class MapData { public: + typedef QMap Attributes; + class Poly { public: - Poly(uint type, const Polygon &path, const QString &label, - const QVector ¶ms, uint HUNI); + Poly(uint type, const Polygon &path, const Attributes &attr, uint HUNI); RectC bounds() const {return _path.boundingRect();} const Polygon &path() const {return _path;} uint type() const {return _type;} - const QString &label() const {return _label;} - const QVariant ¶m() const {return _param;} + const Attributes &attributes() const {return _attr;} + uint HUNI() const {return _HUNI;} private: uint _type; Polygon _path; - QString _label; - QVariant _param; + Attributes _attr; + uint _HUNI; }; class Line { public: - Line(uint type, const QVector &path, const QString &label, - const QVector ¶ms); + Line(uint type, const QVector &path, const Attributes &attr); RectC bounds() const; const QVector &path() const {return _path;} uint type() const {return _type;} const QString &label() const {return _label;} + const Attributes &attributes() const {return _attr;} private: uint _type; QVector _path; QString _label; + Attributes _attr; }; class Point { public: - Point(uint type, const Coordinates &c, const QString &label, - const QVector ¶ms); - Point(uint type, const Coordinates &c, const QString &label, - const QVariant ¶m); + Point(uint type, const Coordinates &c, const Attributes &attr, uint HUNI); + Point(uint type, const Coordinates &s, const QString &label); const Coordinates &pos() const {return _pos;} uint type() const {return _type;} const QString &label() const {return _label;} - const QVariant ¶m() const {return _param;} + const Attributes &attributes() const {return _attr;} bool operator<(const Point &other) const {return _id < other._id;} @@ -65,7 +65,7 @@ public: Coordinates _pos; QString _label; quint64 _id; - QVariant _param; + Attributes _attr; }; MapData(const QString &path); @@ -76,23 +76,6 @@ public: void points(const RectC &rect, QList *points) const; private: - class Attr { - public: - Attr() : _subtype(0) {} - Attr(uint subtype, const QString &label, - const QVector ¶ms) - : _subtype(subtype), _label(label), _params(params) {} - - unsigned subtype() const {return _subtype;} - const QString &label() const {return _label;} - const QVector ¶ms() const {return _params;} - - private: - unsigned _subtype; - QString _label; - QVector _params; - }; - struct Sounding { Sounding() : depth(NAN) {} Sounding(const Coordinates &c, double depth) : c(c), depth(depth) {} @@ -117,12 +100,10 @@ private: const RecordMap &vc, const RecordMap &ve, uint COMF); static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint COMF); - static Attr pointAttr(const ISO8211::Record &r, uint OBJL); - static Attr lineAttr(const ISO8211::Record &r, uint OBJL); - static Attr polyAttr(const ISO8211::Record &r, uint OBJL); + static Attributes attributes(const ISO8211::Record &r); static Point *pointObject(const Sounding &s); static Point *pointObject(const ISO8211::Record &r, const RecordMap &vi, - const RecordMap &vc, uint COMF, uint OBJL); + const RecordMap &vc, uint COMF, uint OBJL, uint HUNI); static Line *lineObject(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL); static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc, diff --git a/src/map/ENC/objects.h b/src/map/ENC/objects.h index 580a5bf6..8f1aa498 100644 --- a/src/map/ENC/objects.h +++ b/src/map/ENC/objects.h @@ -51,6 +51,7 @@ #define LAKARE 69 #define LNDARE 71 #define LNDELV 72 +#define LNDRGN 73 #define LNDMRK 74 #define LIGHTS 75 #define LOKBSN 79 diff --git a/src/map/ENC/rastertile.cpp b/src/map/ENC/rastertile.cpp index 8d2ac9f2..fe84dc3c 100644 --- a/src/map/ENC/rastertile.cpp +++ b/src/map/ENC/rastertile.cpp @@ -5,6 +5,7 @@ #include "map/textpointitem.h" #include "map/rectd.h" #include "objects.h" +#include "attributes.h" #include "style.h" #include "rastertile.h" @@ -12,8 +13,7 @@ using namespace ENC; #define TEXT_EXTENT 160 #define TSSLPT_SIZE 24 - -typedef QSet PointSet; +#define RANGE_FACTOR 4 static const float C1 = 0.866025f; /* sqrt(3)/2 */ static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb); @@ -138,21 +138,21 @@ static void drawArrow(QPainter *painter, const QPolygonF &polygon, uint type) } void RasterTile::drawArrows(QPainter *painter, - const QList &points) + const QList &points) const { for (int i = 0; i < points.size(); i++) { const MapData::Point &point = points.at(i); if (point.type()>>16 == TSSLPT || point.type()>>16 == RCTLPT) { QPolygonF polygon(tsslptArrow(ll2xy(point.pos()), - deg2rad(point.param().toDouble()))); + deg2rad(point.attributes().value(ORIENT).toDouble()))); drawArrow(painter, polygon, point.type()); } } } void RasterTile::drawPolygons(QPainter *painter, - const QList &polygons) + const QList &polygons) const { for (int n = 0; n < _style->drawOrder().size(); n++) { for (int i = 0; i < polygons.size(); i++) { @@ -184,7 +184,7 @@ void RasterTile::drawPolygons(QPainter *painter, } } -void RasterTile::drawLines(QPainter *painter, const QList &lines) +void RasterTile::drawLines(QPainter *painter, const QList &lines) const { painter->setBrush(Qt::NoBrush); @@ -202,7 +202,7 @@ void RasterTile::drawLines(QPainter *painter, const QList &lines) } void RasterTile::drawTextItems(QPainter *painter, - const QList &textItems) + const QList &textItems) const { QRectF rect(_rect); @@ -213,10 +213,56 @@ void RasterTile::drawTextItems(QPainter *painter, } } -void RasterTile::processPoints(QList &points, - QList &textItems, QList &lights) +static QRectF lightRect(const QPointF &pos, double range) { - PointSet lightsSet, signalsSet; + return QRectF(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR, + 2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR); +} + +void RasterTile::drawSectorLights(QPainter *painter, + const QList &lights) const +{ + for (int i = 0; i < lights.size(); i++) { + const SectorLight &l = lights.at(i); + QPointF pos(ll2xy(l.pos)); + QRectF rect(lightRect(pos, (l.range == 0) ? 6 : l.range)); + double a1 = -(l.end + 90); + double a2 = -(l.start + 90); + if (a1 > a2) + a2 += 360; + double as = (a2 - a1); + if (as == 0) + as = 360; + + if (l.visibility == 3 || l.visibility >= 6) + painter->setPen(QPen(Qt::black, 1, Qt::DashLine)); + else { + painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap)); + painter->drawArc(rect, a1 * 16, as * 16); + painter->setPen(QPen(Style::color(l.color), 4, Qt::SolidLine, + Qt::FlatCap)); + } + + painter->drawArc(rect, a1 * 16, as * 16); + + if (a2 - a1 != 0) { + QLineF ln(pos, QPointF(pos.x() + rect.width(), pos.y())); + ln.setAngle(a1); + painter->setPen(QPen(Qt::black, 1, Qt::DashLine)); + painter->drawLine(ln); + ln.setAngle(a2); + painter->drawLine(ln); + } + } +} + +void RasterTile::processPoints(QList &points, + QList &textItems, QList &lights, + QList §orLights) +{ + LightMap lightsMap; + SignalSet signalsSet; + QSet slMap; int i; std::sort(points.begin(), points.end()); @@ -224,9 +270,22 @@ void RasterTile::processPoints(QList &points, /* Lights & Signals */ for (i = 0; i < points.size(); i++) { const MapData::Point &point = points.at(i); - if (point.type()>>16 == LIGHTS) - lightsSet.insert(point.pos()); - else if (point.type()>>16 == FOGSIG) + + if (point.type()>>16 == LIGHTS) { + const MapData::Attributes &attr = point.attributes(); + Style::Color color = (Style::Color)(attr.value(COLOUR).toUInt()); + double range = attr.value(VALNMR).toDouble(); + + if (attr.contains(SECTR1) + || (range >= 6 && !(point.type() & 0xFFFF))) { + sectorLights.append(SectorLight(point.pos(), color, + attr.value(LITVIS).toUInt(), range, + attr.value(SECTR1).toDouble(), attr.value(SECTR2).toDouble())); + slMap.insert(point.pos()); + qDebug() << attr; + } else + lightsMap.insert(point.pos(), color); + } else if (point.type()>>16 == FOGSIG) signalsSet.insert(point.pos()); else break; @@ -245,7 +304,7 @@ void RasterTile::processPoints(QList &points, const QColor *color = &style.textColor(); const QColor *hColor = style.haloColor().isValid() ? &style.haloColor() : 0; - double rotate = angle(point.type(), point.param()); + double rotate = angle(point.type(), point.attributes().value(ORIENT)); if ((!label || !fnt) && !img) continue; @@ -254,11 +313,12 @@ void RasterTile::processPoints(QList &points, TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img, color, hColor, 0, 2, rotate); - if (item->isValid() && !item->collides(textItems)) { + if (item->isValid() && (slMap.contains(point.pos()) + || !item->collides(textItems))) { textItems.append(item); - if (lightsSet.contains(point.pos())) + if (lightsMap.contains(point.pos())) lights.append(new TextPointItem(pos + _style->lightOffset(), - 0, 0, _style->light(), 0, 0, 0, 0)); + 0, 0, _style->light(lightsMap.value(point.pos())), 0, 0, 0, 0)); if (signalsSet.contains(point.pos())) lights.append(new TextPointItem(pos + _style->signalOffset(), 0, 0, _style->signal(), 0, 0, 0, 0)); @@ -326,13 +386,14 @@ void RasterTile::render() QList polygons; QList points; QList textItems, lights; + QList sectorLights; img.setDevicePixelRatio(_ratio); img.fill(Qt::transparent); fetchData(polygons, lines, points); - processPoints(points, textItems, lights); + processPoints(points, textItems, lights, sectorLights); processLines(lines, textItems); QPainter painter(&img); @@ -344,7 +405,9 @@ void RasterTile::render() drawLines(&painter, lines); drawArrows(&painter, points); + drawTextItems(&painter, lights); + drawSectorLights(&painter, sectorLights); drawTextItems(&painter, textItems); qDeleteAll(textItems); diff --git a/src/map/ENC/rastertile.h b/src/map/ENC/rastertile.h index 2d17a6dd..259ca72b 100644 --- a/src/map/ENC/rastertile.h +++ b/src/map/ENC/rastertile.h @@ -34,6 +34,23 @@ public: void render(); private: + struct SectorLight + { + SectorLight(const Coordinates &pos, Style::Color color, uint visibility, + double range, double start, double end) : pos(pos), color(color), + visibility(visibility), range(range), start(start), end(end) {} + + Coordinates pos; + Style::Color color; + uint visibility; + double range; + double start; + double end; + }; + + typedef QMap LightMap; + typedef QSet SignalSet; + void fetchData(QList &polygons, QList &lines, QList &points); QPointF ll2xy(const Coordinates &c) const @@ -44,15 +61,15 @@ private: QPolygonF tsslptArrow(const QPointF &p, qreal angle) const; QPointF centroid(const QVector &polygon) const; void processPoints(QList &points, - QList &textItems, QList &lights); + QList &textItems, QList &lights, + QList §orLights); void processLines(const QList &lines, QList &textItems); - void drawBitmapPath(QPainter *painter, const QImage &img, - const Polygon &polygon); - void drawArrows(QPainter *painter, const QList &points); - void drawPolygons(QPainter *painter, const QList &polygons); - void drawLines(QPainter *painter, const QList &lines); - void drawTextItems(QPainter *painter, const QList &textItems); + void drawArrows(QPainter *painter, const QList &points) const; + void drawPolygons(QPainter *painter, const QList &polygons) const; + void drawLines(QPainter *painter, const QList &lines) const; + void drawTextItems(QPainter *painter, const QList &textItems) const; + void drawSectorLights(QPainter *painter, const QList &lights) const; static bool polyCb(MapData *data, void *context); static bool pointCb(MapData *data, void *context); diff --git a/src/map/ENC/style.cpp b/src/map/ENC/style.cpp index 1f94eb2f..f39631c3 100644 --- a/src/map/ENC/style.cpp +++ b/src/map/ENC/style.cpp @@ -222,6 +222,14 @@ void Style::lineStyle(qreal ratio) _lines[TYPE(PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png")); _lines[TYPE(I_PIPOHD)] = Line(QImage(":/marine/pipeline-overhead.png")); _lines[TYPE(CANALS)] = Line(QPen(QColor(0x9f, 0xc4, 0xe1), 2)); + _lines[SUBTYPE(RDOCAL, 1)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1, + Qt::DashLine)); + _lines[SUBTYPE(RDOCAL, 2)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1, + Qt::DashLine)); + _lines[SUBTYPE(RDOCAL, 3)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1, + Qt::DashLine)); + _lines[SUBTYPE(RDOCAL, 4)] = Line(QPen(QColor(0xeb, 0x49, 0xeb), 1, + Qt::DashLine)); } void Style::pointStyle(qreal ratio) @@ -302,7 +310,9 @@ void Style::pointStyle(qreal ratio) _points[SUBTYPE(I_HRBFAC, 5)] = Point(QImage(":/marine/yacht-harbor.png")); _points[SUBTYPE(I_HRBFAC, 9)] = Point(QImage(":/marine/shipyard.png")); _points[TYPE(ACHBRT)] = Point(QImage(":/marine/anchorage.png")); - _points[TYPE(I_ACHBRT)] = Point(QImage(":/marine/anchorage.png")); + _points[TYPE(ACHBRT)].setTextColor(QColor(0xeb, 0x49, 0xeb)); + _points[TYPE(ACHBRT)].setHaloColor(QColor()); + _points[TYPE(I_ACHBRT)] = _points[TYPE(ACHBRT)]; _points[TYPE(OFSPLF)] = Point(QImage(":/marine/platform.png")); _points[TYPE(PILPNT)] = Point(QImage(":/marine/pile.png"), Small); _points[SUBTYPE(MORFAC, 1)] = Point(QImage(":/marine/pile.png"), Small); @@ -366,6 +376,8 @@ void Style::pointStyle(qreal ratio) _points[SUBTYPE(WEDKLP, 0)] = Point(QImage(":/marine/kelp.png")); _points[SUBTYPE(WEDKLP, 1)] = Point(QImage(":/marine/kelp.png")); _points[TYPE(SEAARE)].setHaloColor(QColor()); + _points[TYPE(LNDARE)].setHaloColor(QColor()); + _points[TYPE(LNDRGN)].setHaloColor(QColor()); _points[TYPE(RADRFL)] = Point(QImage(":/marine/radar-reflector.png")); _points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"), @@ -427,6 +439,9 @@ void Style::pointStyle(qreal ratio) Style::Style(qreal ratio) { _light = QImage(":/marine/light.png"); + _lightRed = QImage(":/marine/light-red.png"); + _lightGreen = QImage(":/marine/light-green.png"); + _lightYellow = QImage(":/marine/light-yellow.png"); _lightOffset = QPoint(11, 11); _signal = QImage(":/marine/fog-signal.png"); _signalOffset = QPoint(-9, 9); @@ -477,3 +492,37 @@ const QFont *Style::font(Style::FontSize size) const return &_normal; } } + +const QImage *Style::light(Color color) const +{ + switch (color) { + case Red: + return &_lightRed; + case Green: + return &_lightGreen; + case White: + case Yellow: + case Amber: + case Orange: + return &_lightYellow; + default: + return &_light; + } +} + +QColor Style::color(Style::Color c) +{ + switch (c) { + case Red: + return Qt::red; + case Green: + return Qt::green; + case White: + case Yellow: + case Amber: + case Orange: + return Qt::yellow; + default: + return Qt::magenta; + } +} diff --git a/src/map/ENC/style.h b/src/map/ENC/style.h index ef62d38e..9d6edf7c 100644 --- a/src/map/ENC/style.h +++ b/src/map/ENC/style.h @@ -89,6 +89,11 @@ public: QPoint _offset; }; + enum Color { + Unknown, White, Black, Red, Green, Blue, Yellow, Gray, + Brown, Amber, Violet, Orange, Magenta, Pink + }; + Style(qreal ratio); const Line &line(uint type) const; @@ -97,11 +102,13 @@ public: const QVector &drawOrder() const {return _drawOrder;} const QFont *font(Style::FontSize size) const; - const QImage *light() const {return &_light;} + const QImage *light(Color color) const; const QImage *signal() const {return &_signal;} const QPoint &lightOffset() const {return _lightOffset;} const QPoint &signalOffset() const {return _signalOffset;} + static QColor color(Color c); + private: void polygonStyle(); void lineStyle(qreal ratio); @@ -114,7 +121,7 @@ private: /* Fonts and images must be initialized after QGuiApplication! */ QFont _small, _normal, _large; - QImage _light, _signal; + QImage _light, _lightRed, _lightGreen, _lightYellow, _signal; QPoint _lightOffset, _signalOffset; }; diff --git a/src/map/IMG/lights.h b/src/map/IMG/lights.h new file mode 100644 index 00000000..c722f73e --- /dev/null +++ b/src/map/IMG/lights.h @@ -0,0 +1,51 @@ +#ifndef IMG_LIGHTS_H +#define IMG_LIGHTS_H + +#include +#include + +namespace IMG { + +class Lights +{ +public: + enum Color {None, Red, Green, White, Blue, Yellow, Violet, Amber}; + + struct Sector + { + Sector() : color(None), angle(0), range(0) {} + Sector(Color color, quint32 angle, quint32 range) + : color(color), angle(angle), range(range) {} + + Color color; + quint32 angle; + quint32 range; + }; + + Lights() : color(None), range(0) {} + bool isSectorLight() const {return ((color && range) || !sectors.isEmpty());} + + Color color; + quint32 range; + QVector sectors; +}; + +} + +#ifndef QT_NO_DEBUG +inline QDebug operator<<(QDebug dbg, const IMG::Lights::Sector §or) +{ + dbg.nospace() << "Sector(" << sector.color << ", " << sector.angle + << ", " << sector.range << ")"; + return dbg.space(); +} + +inline QDebug operator<<(QDebug dbg, const IMG::Lights &lights) +{ + dbg.nospace() << "Lights(" << lights.color << ", " << lights.range << ", " + << lights.sectors << ")"; + return dbg.space(); +} +#endif // QT_NO_DEBUG + +#endif // IMG_LIGHTS_H diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h index a1cd688f..4f591e98 100644 --- a/src/map/IMG/mapdata.h +++ b/src/map/IMG/mapdata.h @@ -14,6 +14,7 @@ #include "map/matrix.h" #include "label.h" #include "raster.h" +#include "lights.h" #include "zoom.h" namespace IMG { @@ -51,11 +52,11 @@ public: enum Flags { NoFlag = 0, ClassLabel = 1, - Light = 2 }; Coordinates coordinates; Label label; + Lights lights; quint64 id; quint32 type; quint32 flags; diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index be67893b..515065fd 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -18,13 +18,13 @@ using namespace IMG; #define TEXT_EXTENT 160 #define ICON_PADDING 2 +#define RANGE_FACTOR 4 +#define ROAD 0 +#define WATER 1 #define AREA(rect) \ (rect.size().width() * rect.size().height()) -#define ROAD 0 -#define WATER 1 - static const QColor textColor(Qt::black); static const QColor haloColor(Qt::white); static const QColor shieldColor(Qt::white); @@ -226,6 +226,67 @@ void RasterTile::drawTextItems(QPainter *painter, } } +static QRect lightRect(const QPoint &pos, quint32 range) +{ + return QRect(pos.x() - range * RANGE_FACTOR, pos.y() - range * RANGE_FACTOR, + 2*range * RANGE_FACTOR, 2*range * RANGE_FACTOR); +} + +void RasterTile::drawSectorLights(QPainter *painter, + const QList &lights) const +{ + for (int i = 0; i < lights.size(); i++) { + const MapData::Point *p = lights.at(i); + QPoint pos(p->coordinates.lon(), p->coordinates.lat()); + + if (p->lights.sectors.size()) { + for (int j = 0; j < p->lights.sectors.size(); j++) { + const Lights::Sector &start = p->lights.sectors.at(j); + const Lights::Sector &end = (j == p->lights.sectors.size() - 1) + ? p->lights.sectors.at(0) : p->lights.sectors.at(j+1); + + if (start.color) { + double a1 = -(end.angle / 10.0 + 90.0); + double a2 = -(start.angle / 10.0 + 90.0); + if (a1 > a2) + a2 += 360; + double as = (a2 - a1); + if (as == 0) + as = 360; + + QRect rect(lightRect(pos, start.range ? start.range : 6)); + + painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, + Qt::FlatCap)); + painter->drawArc(rect, a1 * 16, as * 16); + painter->setPen(QPen(Style::color(start.color), 4, + Qt::SolidLine, Qt::FlatCap)); + painter->drawArc(rect, a1 * 16, as * 16); + + if (a2 - a1 != 0) { + QLineF ln(pos, QPointF(pos.x() + rect.width(), pos.y())); + ln.setAngle(a1); + painter->setPen(QPen(Qt::black, 1, Qt::DashLine)); + painter->drawLine(ln); + ln.setAngle(a2); + painter->drawLine(ln); + } + } + } + } else { + if (p->lights.color && p->lights.range) { + QRect rect(lightRect(pos, p->lights.range)); + + painter->setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap)); + painter->drawArc(rect, 0, 360 * 16); + painter->setPen(QPen(Style::color(p->lights.color), 4, + Qt::SolidLine, Qt::FlatCap)); + painter->drawArc(rect, 0, 360 * 16); + } + } + } +} + static void removeDuplicitLabel(QList &labels, const QString &text, const QRectF &tileRect) { @@ -398,7 +459,7 @@ void RasterTile::processShields(const QList &lines, } void RasterTile::processPoints(QList &points, - QList &textItems) + QList &textItems, QList &lights) { std::sort(points.begin(), points.end()); @@ -408,6 +469,9 @@ void RasterTile::processPoints(QList &points, const Style::Point &ps = style->point(point.type); bool poi = Style::isPOI(point.type); + if (point.lights.isSectorLight()) + lights.append(&point); + const QString *label = point.label.text().isEmpty() ? 0 : &(point.label.text()); const QImage *img = ps.img().isNull() ? 0 : &ps.img(); @@ -428,11 +492,12 @@ void RasterTile::processPoints(QList &points, TextPointItem *item = new TextPointItem(pos + offset, label, fnt, img, color, hcolor, 0, ICON_PADDING); - if (item->isValid() && !item->collides(textItems)) { + if (item->isValid() && (point.lights.isSectorLight() + || !item->collides(textItems))) { textItems.append(item); - if (Style::isLight(point.type) || point.flags & MapData::Point::Light) + if (point.lights.color && !point.lights.isSectorLight()) textItems.append(new TextPointItem(pos + style->lightOffset(), - 0, 0, style->light(), 0, 0, 0, 0)); + 0, 0, style->light(point.lights.color), 0, 0, 0, 0)); } else delete item; } @@ -521,6 +586,7 @@ void RasterTile::render() QList lines; QList points; QList textItems; + QList lights; QImage arrows[2]; arrows[ROAD] = Util::svg2img(":/symbols/oneway.svg", _ratio); @@ -531,7 +597,7 @@ void RasterTile::render() ll2xy(lines); ll2xy(points); - processPoints(points, textItems); + processPoints(points, textItems, lights); processPolygons(polygons, textItems); processLines(lines, textItems, arrows); @@ -546,6 +612,7 @@ void RasterTile::render() drawPolygons(&painter, polygons); drawHillShading(&painter); drawLines(&painter, lines); + drawSectorLights(&painter, lights); drawTextItems(&painter, textItems); qDeleteAll(textItems); diff --git a/src/map/IMG/rastertile.h b/src/map/IMG/rastertile.h index c394a841..84c29052 100644 --- a/src/map/IMG/rastertile.h +++ b/src/map/IMG/rastertile.h @@ -34,7 +34,8 @@ public: private: typedef RTree DEMTRee; - struct ElevationCTX { + struct ElevationCTX + { ElevationCTX(const DEMTRee &tree, const Coordinates &c, double &ele) : tree(tree), c(c), ele(ele) {} @@ -42,7 +43,8 @@ private: const Coordinates &c; double &ele; }; - struct EdgeCTX { + struct EdgeCTX + { EdgeCTX(const Coordinates &c, double &ele) : c(c), ele(ele) {} const Coordinates &c; @@ -62,13 +64,14 @@ private: void drawLines(QPainter *painter, const QList &lines) const; void drawTextItems(QPainter *painter, const QList &textItems) const; void drawHillShading(QPainter *painter) const; + void drawSectorLights(QPainter *painter, const QList &lights) const; void processPolygons(const QList &polygons, QList &textItems); void processLines(QList &lines, QList &textItems, const QImage (&arrows)[2]); - void processPoints(QList &points, - QList &textItems); + void processPoints(QList &points, QList &textItems, + QList &lights); void processShields(const QList &lines, QList &textItems); void processStreetNames(const QList &lines, diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index ef629710..06760059 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -107,7 +107,8 @@ bool RGNFile::readObstructionInfo(Handle &hdl, quint8 flags, quint32 size, return true; } -bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const +bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, quint32 size, + MapData::Point *point) const { quint16 val; quint8 lc; @@ -115,7 +116,7 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con if ((flags & 0xe0) != 0xe0) return true; - if (!readUInt16(hdl, val)) + if (!(size >= 2 && readUInt16(hdl, val))) return false; lc = (val >> 10) & 0x0f; @@ -123,7 +124,105 @@ bool RGNFile::readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) con lc = (val >> 6) & 7; if (lc) - point->flags |= MapData::Point::Light; + point->lights.color = (Lights::Color)lc; + + return true; +} + +bool RGNFile::readLightInfo(Handle &hdl, quint8 flags, quint32 size, + MapData::Point *point) const +{ + quint16 flags1; + quint8 flags2; + quint32 unused; + + if (!(size >= 3 && readUInt16(hdl, flags1) && readUInt8(hdl, flags2))) + return false; + size -= 3; + if (flags2 >> 6) { + if (!(size >= (flags2 >> 6) && readVUInt32(hdl, (flags2 >> 6), unused))) + return false; + size -= (flags2 >> 6); + } + if (flags2 >> 2 & 3) { + if (!(size >= (flags2 >> 2 & 3) + && readVUInt32(hdl, (flags2 >> 2 & 3), unused))) + return false; + size -= (flags2 >> 2 & 3); + } + if (flags1 & 0xc0) { + if (flags1 & 0x80) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + unused |= ((flags1 & 0x40) << 2); + size--; + } else { + if (!(size >= 2 && readUInt16(hdl, unused))) + return false; + size -= 2; + } + } + if (flags & 2) { + if (!(size >= 3 && readUInt24(hdl, unused))) + return false; + size -= 3; + } + if (flags & 4) { + if (!(size >= 3 && readUInt24(hdl, unused))) + return false; + size -= 3; + } + if (flags & 8) { + if (!(size >= 3 && readUInt24(hdl, unused))) + return false; + size -= 3; + } + if (flags1 & 0x200) { + if (!(size >= 2 && readUInt16(hdl, unused))) + return false; + size -= 2; + } + if (flags1 & 0x400) { + if (!(size >= 1 && readUInt8(hdl, unused))) + return false; + size--; + } + if (flags1 & 0x800) { + quint16 la; + quint8 cf, range = 0; + + do { + if (!(size >= 2 && readUInt16(hdl, la))) + return false; + size -= 2; + + cf = la >> 8; + Lights::Color c = (Lights::Color)(cf >> 4 & 7); + if (c) { + if (!(size >= 1 && readUInt8(hdl, range))) + return false; + size--; + } + point->lights.sectors.append(Lights::Sector(c, la & 0xfff, range)); + } while (!(cf >> 7)); + } else { + quint8 v1, v2, range; + + if (!(size >= 1 && readUInt8(hdl, v1))) + return false; + size--; + + range = v1 & 0x1f; + if ((v1 & 0x1f) == 0x1f) { + if (!(size >= 1 && readUInt8(hdl, v2))) + return false; + size--; + range += v2; + } + + point->lights.color = (Lights::Color)(v1 >> 5); + point->lights.range = range; + } return true; } @@ -183,7 +282,9 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, if (point && Style::isObstructionPoint(point->type)) readObstructionInfo(hdl, flags, rs, point); if (point && Style::isBuoy(point->type)) - readBuoyInfo(hdl, flags, point); + readBuoyInfo(hdl, flags, rs, point); + if (point && Style::isLight(point->type)) + readLightInfo(hdl, flags, rs, point); return seek(hdl, off + rs); } diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index 7040250c..fc739010 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -64,7 +64,10 @@ private: MapData::Point *point) const; bool readObstructionInfo(Handle &hdl, quint8 flags, quint32 size, MapData::Point *point) const; - bool readBuoyInfo(Handle &hdl, quint8 flags, MapData::Point *point) const; + bool readBuoyInfo(Handle &hdl, quint8 flags, quint32 size, + MapData::Point *point) const; + bool readLightInfo(Handle &hdl, quint8 flags, quint32 size, + MapData::Point *point) const; bool readLabel(Handle &hdl, LBLFile *lbl, Handle &lblHdl, quint8 flags, quint32 size, MapData::Point *point) const; diff --git a/src/map/IMG/style.cpp b/src/map/IMG/style.cpp index 7014d2e6..1c215dce 100644 --- a/src/map/IMG/style.cpp +++ b/src/map/IMG/style.cpp @@ -1319,6 +1319,10 @@ Style::Style(qreal ratio, SubFile *typ) _extraSmall = pixelSizeFont(10); _light = QImage(":/marine/light.png"); + _lightRed = QImage(":/marine/light-red.png"); + _lightGreen = QImage(":/marine/light-green.png"); + _lightYellow = QImage(":/marine/light-yellow.png"); + _lightWhite = QImage(":/marine/light-white.png"); _lightOffset = QPoint(11, 11); defaultLineStyle(ratio); @@ -1373,6 +1377,40 @@ const QFont *Style::font(Style::FontSize size, Style::FontSize defaultSize) cons } } +const QImage *Style::light(Lights::Color color) const +{ + switch (color) { + case Lights::Red: + return &_lightRed; + case Lights::Green: + return &_lightGreen; + case Lights::White: + return &_lightWhite; + case Lights::Yellow: + case Lights::Amber: + return &_lightYellow; + default: + return &_light; + } +} + +QColor Style::color(Lights::Color c) +{ + switch (c) { + case Lights::Red: + return Qt::red; + case Lights::Green: + return Qt::green; + case Lights::White: + return Qt::white; + case Lights::Yellow: + case Lights::Amber: + return Qt::yellow; + default: + return Qt::magenta; + } +} + #ifndef QT_NO_DEBUG static QString penColor(const QPen &pen) { diff --git a/src/map/IMG/style.h b/src/map/IMG/style.h index 88fae052..a3f21fad 100644 --- a/src/map/IMG/style.h +++ b/src/map/IMG/style.h @@ -5,6 +5,7 @@ #include #include #include +#include "lights.h" #include "subfile.h" #define TYPE(t) ((t)<<8) @@ -112,8 +113,7 @@ public: const QList &drawOrder() const {return _drawOrder;} const QFont *font(Style::FontSize size, Style::FontSize defaultSize = Style::Normal) const; - - const QImage *light() const {return &_light;} + const QImage *light(Lights::Color color) const; const QPoint &lightOffset() const {return _lightOffset;} static bool isPOI(quint32 type) @@ -157,6 +157,8 @@ public: static bool isMarina(quint32 type) {return type == 0x10703;} + static QColor color(Lights::Color c); + private: struct Section { quint32 offset; @@ -203,7 +205,7 @@ private: /* Fonts and images must be initialized after QGuiApplication! */ QFont _large, _normal, _small, _extraSmall; - QImage _light; + QImage _light, _lightRed, _lightGreen, _lightYellow, _lightWhite; QPoint _lightOffset; };