From 0ee28d7f45de1a9038a0a0d27e4031db36e802d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 6 Feb 2025 01:10:44 +0100 Subject: [PATCH] Colored lights + sector lights in ENC maps --- gpxsee.qrc | 3 + icons/map/marine/light-green.png | Bin 0 -> 466 bytes icons/map/marine/light-red.png | Bin 0 -> 417 bytes icons/map/marine/light-yellow.png | Bin 0 -> 470 bytes src/map/ENC/attributes.h | 5 + src/map/ENC/mapdata.cpp | 359 +++++++++++++----------------- src/map/ENC/mapdata.h | 51 ++--- src/map/ENC/objects.h | 1 + src/map/ENC/rastertile.cpp | 70 ++++-- src/map/ENC/rastertile.h | 20 +- src/map/ENC/style.cpp | 51 ++++- src/map/ENC/style.h | 11 +- 12 files changed, 319 insertions(+), 252 deletions(-) create mode 100644 icons/map/marine/light-green.png create mode 100644 icons/map/marine/light-red.png create mode 100644 icons/map/marine/light-yellow.png diff --git a/gpxsee.qrc b/gpxsee.qrc index b75d8f19..ff3134f2 100644 --- a/gpxsee.qrc +++ b/gpxsee.qrc @@ -193,6 +193,9 @@ 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/building.png icons/map/marine/fog-signal.png icons/map/marine/construction.png diff --git a/icons/map/marine/light-green.png b/icons/map/marine/light-green.png new file mode 100644 index 0000000000000000000000000000000000000000..af48f5d174b2fc0592b3c0f37580fd8e34b7530b GIT binary patch literal 466 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9c!3HGfPKx~mq*&4&eH|GXHuiJ>Nn{1`8HI(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!tD z$=lrpNCUx7=iMOPoCO|{#XzgCgD|6$#_S59@tU44jv*GO*IwDHeY8;I_{Zyexz?vpM`s$qr(vm~aRj9;L`rYX!E&wtYS(p;69I+G$)4xhjL;NJbc z7LP6G-+TVqcJ6z{SD*POx=zmUzVa#jf>4o#uy40kJ@cuC6{5>m9O86iWq)d=wByL3 z>UFZ!i&6t)EBl1PuUa_W-u_EhjWv5|vrvS3nf=_lqgKaQ&5zFiCV0>;tnR|sM@}Y+ zt31l5>{xZwau&CV{gI9bODr@ROOrRB@QB;cVR}PiwaJnYzKr@=RJ#>P5Dypb-9>LRNhb4Rhr$J03Jm3ktCoRjpl;*q-6y-k8Xr za%z|8MT=*FpXZ%S_Si66^Y;gp+42Sb$p^LfFur`@pj36oVkam>Jzf1=);T3K0RRYb BuMPkJ literal 0 HcmV?d00001 diff --git a/icons/map/marine/light-red.png b/icons/map/marine/light-red.png new file mode 100644 index 0000000000000000000000000000000000000000..199b7ece6de44496947559901cfdfa50240b86b2 GIT binary patch literal 417 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9c!3HGfPKx~mq*&4&eH|GXHuiJ>Nn{1`8HI(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!tD z$=lrpNCUx7=iMOPoCO|{#XzgCgD|6$#_S59;15q1#}JFtYp?9pYD<)0|1kgh@df6o z2B(rX&Ya+?wz`N<&62^-fv;gs)7hkrCsP)rBq%;*sB!&yJlAkf=kv;nyQTTz`+wJ$ z#@;=&sNO=ir?uJO-c*sOhZ;8RTQ6MaH4}_;=3Jh*N;>DUu+~G}oYsZ=9he`kVb*?V zrt_C|_CKHCeRuX6{EE(bF1@0qeS=ihY^S#cf0@G$70$@%(hYG?Rmo{PsCFZdH|$X8 zjOKY<87$K!)>VFH{am_on)DK_#QmP#zj+t@p2v1U;@rh`8r3;h9sk}**t_h_2Xp%) z-}rNF&F`(|D^Rs5RS-|yR`e%ycE9AEhfC&{|6sUMdftBjoLNnv0P=M8b6Mw<&;$TN Co1fMI literal 0 HcmV?d00001 diff --git a/icons/map/marine/light-yellow.png b/icons/map/marine/light-yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..6181322491cd0c0247b2aff9af4bdeacaa291a15 GIT binary patch literal 470 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9c!3HGfPKx~mq*&4&eH|GXHuiJ>Nn{1`8HI(3)EF2VS{N990fib~Fff!FFfhDIU|_JC!N4G1FlSew4N!tD z$=lrpNCUx7=iMOPoCO|{#XzgCgD|6$#_S59@w%Qajv*GO*IwD{H78Ku*vI>NQ5}vO zHu!akBv1E?*4`+rBA&q2{D8GXFDr9ttNfAZ4O;{bYKgH4akx1i_d0UPZBfSJq|aS&UeB-xiRsVx7aP2CXk*OAZ{C`8%gq8C9FLW~3^nKWS zSGu#HX{poihWwe=jK6MS)k@-XuYWn&;+#p?&Mo#6GZ}uL7djxeOerRWNpu6R&!5B9 zy=>Q%Y(g0KYI@aNSNX~B<6@D)sg-c}M&`vy)jG+FhjN1h7;hgrK1ptVqRpY}VGHc$ zEZWXe*1oW6^JR|dGuD0h6gy-6)SX7T$xDuW+a0I)SS9b&vyCDm4`nv1ZrfXRG&Jhy zbg{E}S8m<>;1e9-Qm#1nQE *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,143 @@ 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; + + _type = SUBTYPE(type, _attr.value(subtype).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 +662,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 +786,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 +833,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..e75c5a5b 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 SECTOR_RADIUS 40 static const float C1 = 0.866025f; /* sqrt(3)/2 */ static const QColor tsslptPen = QColor(0xeb, 0x49, 0xeb); @@ -145,7 +145,7 @@ void RasterTile::drawArrows(QPainter *painter, 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()); } } @@ -213,10 +213,42 @@ void RasterTile::drawTextItems(QPainter *painter, } } -void RasterTile::processPoints(QList &points, - QList &textItems, QList &lights) +void RasterTile::drawSectorLights(QPainter *painter, + const QList &lights) { - PointSet lightsSet, signalsSet; + for (int i = 0; i < lights.size(); i++) { + const SectorLight &l = lights.at(i); + QPointF pos(ll2xy(l.pos)); + QRectF rect(pos.x() - SECTOR_RADIUS, pos.y() - SECTOR_RADIUS, + 2*SECTOR_RADIUS, 2*SECTOR_RADIUS); + double a1 = -(l.end + 90); + double a2 = -(l.start + 90); + if (a1 > a2) + a2 += 360; + + if (l.visibility == 3 || l.visibility >= 6) + painter->setPen(QPen(Qt::black, 1, Qt::DashLine)); + else + painter->setPen(QPen(Style::color(l.color), 5, Qt::SolidLine, + Qt::FlatCap)); + + painter->drawArc(rect, a1 * 16, (a2 - a1) * 16); + + QLineF ln(pos, QPointF(pos.x() + 2*SECTOR_RADIUS, 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; int i; std::sort(points.begin(), points.end()); @@ -224,9 +256,18 @@ 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()); + + if (attr.contains(SECTR1)) { + sectorLights.append(SectorLight(point.pos(), color, + attr.value(LITVIS).toUInt(), attr.value(SECTR1).toDouble(), + attr.value(SECTR2).toDouble())); + } else + lightsMap.insert(point.pos(), color); + } else if (point.type()>>16 == FOGSIG) signalsSet.insert(point.pos()); else break; @@ -245,7 +286,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; @@ -256,9 +297,9 @@ void RasterTile::processPoints(QList &points, color, hColor, 0, 2, rotate); if (item->isValid() && !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 +367,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 +386,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..4a1af69f 100644 --- a/src/map/ENC/rastertile.h +++ b/src/map/ENC/rastertile.h @@ -34,6 +34,22 @@ public: void render(); private: + struct SectorLight + { + SectorLight(const Coordinates pos, Style::Color color, uint visibility, + double start, double end) : pos(pos), color(color), + visibility(visibility), start(start), end(end) {} + + Coordinates pos; + Style::Color color; + uint visibility; + 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,7 +60,8 @@ 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, @@ -53,6 +70,7 @@ private: void drawPolygons(QPainter *painter, const QList &polygons); void drawLines(QPainter *painter, const QList &lines); void drawTextItems(QPainter *painter, const QList &textItems); + void drawSectorLights(QPainter *painter, const QList &lights); 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; };