diff --git a/gpxsee.pro b/gpxsee.pro index 4a02f5c8..901882c8 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -29,6 +29,7 @@ HEADERS += src/common/config.h \ src/GUI/pluginparameters.h \ src/common/garmin.h \ src/common/coordinates.h \ + src/common/linec.h \ src/common/range.h \ src/common/rectc.h \ src/common/textcodec.h \ diff --git a/src/common/linec.h b/src/common/linec.h new file mode 100644 index 00000000..749d330b --- /dev/null +++ b/src/common/linec.h @@ -0,0 +1,25 @@ +#ifndef LINEC_H +#define LINEC_H + +#include "coordinates.h" + +class LineC +{ +public: + LineC(const Coordinates &c1, const Coordinates &c2) : _c1(c1), _c2(c2) {} + + const Coordinates &c1() const {return _c1;} + const Coordinates &c2() const {return _c2;} + + Coordinates pointAt(double t) const + { + return Coordinates( + _c1.lon() + (_c2.lon() - _c1.lon()) * t, + _c1.lat() + (_c2.lat() - _c1.lat()) * t); + } + +private: + Coordinates _c1, _c2; +}; + +#endif // LINEC_H diff --git a/src/map/ENC/attributes.h b/src/map/ENC/attributes.h index 41941c53..e90cf4fb 100644 --- a/src/map/ENC/attributes.h +++ b/src/map/ENC/attributes.h @@ -12,6 +12,7 @@ #define DRVAL1 87 #define ELEVAT 90 #define OBJNAM 116 +#define ORIENT 117 #define RESTRN 131 #define VALDCO 174 #define WATLEV 187 diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 0065f90f..97fd2b70 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -479,6 +479,9 @@ MapData::Attr MapData::polyAttr(const ISO8211::Record &r, uint OBJL) else if (OBJL == RESARE && key == RESTRN) { if (av.at(1).toString().toUInt() == 1) subtype = 2; + } else if (OBJL == TSSLPT && key == ORIENT) { + double angle = av.at(1).toString().toDouble(); + subtype = (uint)(angle * 10); } } diff --git a/src/map/ENC/objects.h b/src/map/ENC/objects.h index 37bb29eb..0474b9d8 100644 --- a/src/map/ENC/objects.h +++ b/src/map/ENC/objects.h @@ -43,6 +43,7 @@ #define PILPNT 90 #define PIPSOL 94 #define PONTON 95 +#define PRCARE 96 #define RAILWY 106 #define RECTRC 109 #define RESARE 112 @@ -53,6 +54,7 @@ #define SOUNDG 129 #define TSELNE 145 #define TSSBND 146 +#define TSSLPT 148 #define TSEZNE 150 #define UWTROC 153 #define UNSARE 154 diff --git a/src/map/ENC/rastertile.cpp b/src/map/ENC/rastertile.cpp index df8ae219..e7d9c014 100644 --- a/src/map/ENC/rastertile.cpp +++ b/src/map/ENC/rastertile.cpp @@ -1,4 +1,6 @@ +#include #include +#include "common/linec.h" #include "map/bitmapline.h" #include "map/textpointitem.h" #include "map/textpathitem.h" @@ -8,9 +10,12 @@ using namespace ENC; #define ICON_PADDING 2 +#define ARROW_SIZE 0.005 #define ECDIS(x) (((x)>TYPE(17000))?((x)-TYPE(17000)):(x)) +const float C1 = 0.866025f; /* sqrt(3)/2 */ + static const QColor haloColor(Qt::white); static struct { @@ -51,6 +56,36 @@ static const Style& style() return s; } +static double area(const QVector &polygon) +{ + double area = 0; + + for (int i = 0; i < polygon.size(); i++) { + int j = (i + 1) % polygon.size(); + area += polygon.at(i).lon() * polygon.at(j).lat(); + area -= polygon.at(i).lat() * polygon.at(j).lon(); + } + area /= 2.0; + + return area; +} + +static Coordinates centroid(const QVector &polygon) +{ + double cx = 0, cy = 0; + double factor = 1.0 / (6.0 * area(polygon)); + + for (int i = 0; i < polygon.size(); i++) { + int j = (i + 1) % polygon.size(); + qreal f = (polygon.at(i).lon() * polygon.at(j).lat() + - polygon.at(j).lon() * polygon.at(i).lat()); + cx += (polygon.at(i).lon() + polygon.at(j).lon()) * f; + cy += (polygon.at(i).lat() + polygon.at(j).lat()) * f; + } + + return Coordinates(cx * factor, cy * factor); +} + QPainterPath RasterTile::painterPath(const Polygon &polygon) const { QPainterPath path; @@ -77,6 +112,48 @@ QPolygonF RasterTile::polyline(const QVector &path) const return polygon; } +QPolygonF RasterTile::arrow(const Coordinates &c, qreal angle) const +{ + Coordinates t[3], r[4]; + QPolygonF polygon; + + t[0] = c; + t[1] = Coordinates(t[0].lon() - qCos(angle - M_PI/3) * ARROW_SIZE, + t[0].lat() - qSin(angle - M_PI/3) * ARROW_SIZE); + t[2] = Coordinates(t[0].lon() - qCos(angle - M_PI + M_PI/3) * ARROW_SIZE, + t[0].lat() - qSin(angle - M_PI + M_PI/3) * ARROW_SIZE); + + LineC l(t[1], t[2]); + r[0] = l.pointAt(0.25); + r[1] = l.pointAt(0.75); + r[2] = Coordinates(r[0].lon() - C1 * ARROW_SIZE * qCos(angle - M_PI/2), + r[0].lat() - C1 * ARROW_SIZE * qSin(angle - M_PI/2)); + r[3] = Coordinates(r[1].lon() - C1 * ARROW_SIZE * qCos(angle - M_PI/2), + r[1].lat() - C1 * ARROW_SIZE * qSin(angle - M_PI/2)); + + polygon << ll2xy(t[0]) << ll2xy(t[2]) << ll2xy(r[1]) << ll2xy(r[3]) + << ll2xy(r[2]) << ll2xy(r[0]) << ll2xy(t[1]); + + return polygon; +} + +void RasterTile::drawArrows(QPainter *painter) +{ + painter->setPen(QPen(QColor("#eb49eb"), 1)); + painter->setBrush(QBrush("#80eb49eb")); + + for (int i = 0; i < _polygons.size(); i++) { + const MapData::Poly *poly = _polygons.at(i); + + if (poly->type()>>16 == TSSLPT) { + qreal angle = (poly->type() & 0xFFFF) / 10.0; + QPolygonF polygon(arrow(centroid(poly->path().first()), + deg2rad(180 - angle))); + painter->drawPolygon(polygon); + } + } +} + void RasterTile::drawPolygons(QPainter *painter) { const Style &s = style(); @@ -198,6 +275,7 @@ void RasterTile::render() drawPolygons(&painter); drawLines(&painter); + drawArrows(&painter); drawTextItems(&painter, textItems); diff --git a/src/map/ENC/rastertile.h b/src/map/ENC/rastertile.h index d47d9593..8186ab51 100644 --- a/src/map/ENC/rastertile.h +++ b/src/map/ENC/rastertile.h @@ -32,10 +32,12 @@ private: {return _transform.proj2img(_proj.ll2xy(c));} QPainterPath painterPath(const Polygon &polygon) const; QPolygonF polyline(const QVector &path) const; + QPolygonF arrow(const Coordinates &c, qreal angle) const; void processPoints(QList &textItems); void processLines(QList &textItems); void drawBitmapPath(QPainter *painter, const QImage &img, const Polygon &polygon); + void drawArrows(QPainter *painter); void drawPolygons(QPainter *painter); void drawLines(QPainter *painter); void drawTextItems(QPainter *painter, const QList &textItems); diff --git a/src/map/ENC/style.cpp b/src/map/ENC/style.cpp index 3bc8c226..73a4fdfd 100644 --- a/src/map/ENC/style.cpp +++ b/src/map/ENC/style.cpp @@ -52,9 +52,10 @@ void Style::defaultPolygonStyle() _polygons[TYPE(UNSARE)] = Polygon(QBrush("#999999")); _polygons[SUBTYPE(RESARE, 9)] = Polygon(QBrush(QColor("#ff0000"), Qt::BDiagPattern)); - _polygons[SUBTYPE(RESARE, 2)] = Polygon(QImage(":/marine/noanchor-line.png")); _polygons[SUBTYPE(ACHARE, 1)] = Polygon(QImage(":/marine/anchor-line.png")); + _polygons[TYPE(PRCARE)] = Polygon(QBrush(QColor("#eb49eb"), + Qt::BDiagPattern)); _drawOrder << TYPE(M_COVR) << TYPE(LNDARE) << SUBTYPE(DEPARE, 0) @@ -64,7 +65,8 @@ void Style::defaultPolygonStyle() << TYPE(RIVERS) << TYPE(DRGARE) << TYPE(FAIRWY) << TYPE(BUAARE) << TYPE(BUISGL) << TYPE(AIRARE) << TYPE(BRIDGE) << TYPE(SLCONS) << TYPE(PONTON) << TYPE(DMPGRD) << TYPE(TSEZNE) << TYPE(OBSTRN) - << SUBTYPE(ACHARE, 1) << SUBTYPE(RESARE, 9) << SUBTYPE(RESARE, 2); + << SUBTYPE(ACHARE, 1) << SUBTYPE(RESARE, 9) << SUBTYPE(RESARE, 2) + << TYPE(PRCARE); } void Style::defaultLineStyle()