diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 839668a0..5662a151 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -118,7 +118,7 @@ bool RGNFile::init(Handle &hdl) bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, - Handle &netHdl, QList *polys, bool line) const + Handle &netHdl, QList *polys) const { if (!seek(hdl, segment.start())) return false; @@ -172,7 +172,7 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, if (!rect.intersects(br)) continue; - if (line && lbl && (labelPtr & 0x3FFFFF)) { + if (lbl && (labelPtr & 0x3FFFFF)) { if (labelPtr & 0x800000) { quint32 lblOff; if (net && net->lblOffset(netHdl, labelPtr & 0x3FFFFF, lblOff) @@ -278,7 +278,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, if (!rect.intersects(br)) continue; - if (line && lbl && (labelPtr & 0x3FFFFF)) + if (lbl && (labelPtr & 0x3FFFFF)) poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF); polys->append(poly); @@ -409,12 +409,12 @@ void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, case Segment::Line: if (lines) polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net, - netHdl, lines, true); + netHdl, lines); break; case Segment::Polygon: if (polygons) polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net, - netHdl, polygons, false); + netHdl, polygons); break; case Segment::RoadReference: break; diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index 0d8735c9..d1533a5b 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -62,7 +62,7 @@ private: QVector segments(Handle &hdl, const SubDiv *subdiv) const; bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, - Handle &netHdl, QList *polys, bool line) const; + Handle &netHdl, QList *polys) const; bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, Handle &lblHdl, QList *points) const; diff --git a/src/map/IMG/style.cpp b/src/map/IMG/style.cpp index 5e2f5d7d..0c4de37e 100644 --- a/src/map/IMG/style.cpp +++ b/src/map/IMG/style.cpp @@ -33,7 +33,7 @@ void Style::defaultPolygonStyle() Qt::BDiagPattern)); _polygons[TYPE(0x17)] = Style::Polygon(QBrush("#d4ebb8")); _polygons[TYPE(0x18)] = Style::Polygon(QBrush("#d4ebb8")); - _polygons[TYPE(0x19)] = Style::Polygon(QBrush("#d6d4ce")); + _polygons[TYPE(0x19)] = Style::Polygon(QBrush("#e3edc6"), QPen("#c9d3a5")); _polygons[TYPE(0x1a)] = Style::Polygon(QBrush("#000000", Qt::Dense6Pattern), QPen(QColor("#cdccc4"), 1)); _polygons[TYPE(0x1e)] = Style::Polygon(QBrush(QColor("#9ac269"), @@ -980,6 +980,22 @@ bool Style::isContourLine(quint32 type) || (type & 0xffff00) == TYPE(0x109)); } +bool Style::isWaterArea(quint32 type) +{ + return (type >= TYPE(0x3c) && type <= TYPE(0x44)); +} + +bool Style::isMilitaryArea(quint32 type) +{ + return (type == TYPE(0x04)); +} + +bool Style::isInfrastructureArea(quint32 type) +{ + return ((type >= TYPE(0x07) && type <= TYPE(0xc)) || type == TYPE(0x13) + || type == TYPE(0x1a) || type == TYPE(0x19)); +} + bool Style::isSpot(quint32 type) { return (type == TYPE(0x62) || type == TYPE(0x63)); diff --git a/src/map/IMG/style.h b/src/map/IMG/style.h index 86d7f108..dc0acfce 100644 --- a/src/map/IMG/style.h +++ b/src/map/IMG/style.h @@ -47,6 +47,7 @@ public: private: QBrush _brush; QPen _pen; + QColor _textColor; }; class Line { @@ -109,6 +110,9 @@ public: static bool isSpot(quint32 type); static bool isSummit(quint32 type); static bool isMajorRoad(quint32 type); + static bool isWaterArea(quint32 type); + static bool isMilitaryArea(quint32 type); + static bool isInfrastructureArea(quint32 type); static POIClass poiClass(quint32 type); private: diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index 2d7a24a1..20af7e33 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -43,10 +43,10 @@ public: { QList textItems; - _map->processPolygons(_polygons); + QRect tileRect(_xy, QSize(TILE_SIZE, TILE_SIZE)); + _map->processPolygons(_polygons, textItems); _map->processPoints(_points, textItems); - _map->processLines(_lines, QRect(_xy, QSize(TILE_SIZE, TILE_SIZE)), - textItems); + _map->processLines(_lines, tileRect, textItems); _img.fill(Qt::transparent); @@ -186,6 +186,49 @@ static int minShieldZoom(Label::Shield::Type type) } } +static qreal area(const QVector &polygon) +{ + qreal area = 0; + + for (int i = 0; i < polygon.size(); i++) { + int j = (i + 1) % polygon.size(); + area += polygon.at(i).x() * polygon.at(j).y(); + area -= polygon.at(i).y() * polygon.at(j).x(); + } + area /= 2.0; + + return area; +} + +static QPointF centroid(const QVector polygon) +{ + qreal cx = 0, cy = 0, factor = 0; + qreal A = area(polygon); + + for (int i = 0; i < polygon.size(); i++) { + int j = (i + 1) % polygon.size(); + factor=(polygon.at(i).x() * polygon.at(j).y() - polygon[j].x() + * polygon[i].y()); + cx+=(polygon[i].x() + polygon[j].x()) * factor; + cy+=(polygon[i].y() + polygon[j].y()) * factor; + } + + A *= 6.0f; + factor = 1/A; + cx *= factor; + cy *= factor; + + return QPointF(cx, cy); +} + +static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect) +{ + return (polygon.boundingRect().contains(rect) + && (polygon.containsPoint(rect.topLeft(), Qt::OddEvenFill) + || polygon.containsPoint(rect.topRight(), Qt::OddEvenFill) + || polygon.containsPoint(rect.bottomLeft(), Qt::OddEvenFill) + || polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill))); +} IMGMap::IMGMap(const QString &fileName, QObject *parent) : Map(parent), _img(fileName), _projection(PCS::pcs(3857)), _valid(false) @@ -335,7 +378,8 @@ void IMGMap::drawTextItems(QPainter *painter, const QList &textItems) } -void IMGMap::processPolygons(QList &polygons) +void IMGMap::processPolygons(QList &polygons, + QList &textItems) { for (int i = 0; i < polygons.size(); i++) { IMG::Poly &poly = polygons[i]; @@ -343,6 +387,22 @@ void IMGMap::processPolygons(QList &polygons) QPointF &p = poly.points[j]; p = ll2xy(Coordinates(p.x(), p.y())); } + + if (poly.label.text().isEmpty()) + continue; + + if (Style::isWaterArea(poly.type) || Style::isMilitaryArea(poly.type) + || Style::isInfrastructureArea(poly.type)) { + const Style::Polygon &style = _img.style()->polygon(poly.type); + TextPointItem *item = new TextPointItem( + centroid(poly.points).toPoint(), &poly.label.text(), + poiFont(), 0, &style.brush().color(), 0); + if (item->isValid() && !item->collides(textItems) + && rectNearPolygon(poly.points, item->boundingRect())) + textItems.append(item); + else + delete item; + } } } diff --git a/src/map/imgmap.h b/src/map/imgmap.h index 47834daa..36b7dee8 100644 --- a/src/map/imgmap.h +++ b/src/map/imgmap.h @@ -47,7 +47,8 @@ private: void drawLines(QPainter *painter, const QList &lines); void drawTextItems(QPainter *painter, const QList &textItems); - void processPolygons(QList &polygons); + void processPolygons(QList &polygons, + QList &textItems); void processLines(QList &lines, const QRect &tileRect, QList &textItems); void processPoints(QList &points, QList &textItems);