diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 06c82092..0509be85 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -893,7 +893,7 @@ void MapData::clear() _points.RemoveAll(); } -void MapData::points(const RectC &rect, QList *points) +void MapData::points(const RectC &rect, QList *points) const { double min[2], max[2]; @@ -901,7 +901,7 @@ void MapData::points(const RectC &rect, QList *points) _points.Search(min, max, pointCb, points); } -void MapData::lines(const RectC &rect, QList *lines) +void MapData::lines(const RectC &rect, QList *lines) const { double min[2], max[2]; @@ -909,7 +909,7 @@ void MapData::lines(const RectC &rect, QList *lines) _lines.Search(min, max, lineCb, lines); } -void MapData::polygons(const RectC &rect, QList *polygons) +void MapData::polygons(const RectC &rect, QList *polygons) const { double min[2], max[2]; diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index 7a88ec23..662e1327 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -72,9 +72,9 @@ public: RectC bounds() const {return _bounds;} Range zooms() const; - void polygons(const RectC &rect, QList *polygons); - void lines(const RectC &rect, QList *lines); - void points(const RectC &rect, QList *points); + void polygons(const RectC &rect, QList *polygons) const; + void lines(const RectC &rect, QList *lines) const; + void points(const RectC &rect, QList *points) const; void load(); void clear(); diff --git a/src/map/ENC/rastertile.cpp b/src/map/ENC/rastertile.cpp index 9a4c5ac4..94754d0e 100644 --- a/src/map/ENC/rastertile.cpp +++ b/src/map/ENC/rastertile.cpp @@ -3,11 +3,14 @@ #include "common/linec.h" #include "map/bitmapline.h" #include "map/textpathitem.h" +#include "map/rectd.h" #include "style.h" #include "rastertile.h" using namespace ENC; +#define TEXT_EXTENT 160 + #define TSSLPT_SIZE 0.005 /* ll */ #define RDOCAL_SIZE 12 /* px */ #define CURENT_SIZE 12 /* px */ @@ -227,10 +230,11 @@ QPolygonF RasterTile::tsslptArrow(const Coordinates &c, qreal angle) const return polygon; } -void RasterTile::drawArrows(QPainter *painter) +void RasterTile::drawArrows(QPainter *painter, + const QList &polygons) { - for (int i = 0; i < _polygons.size(); i++) { - const MapData::Poly *poly = _polygons.at(i); + for (int i = 0; i < polygons.size(); i++) { + const MapData::Poly *poly = polygons.at(i); if (poly->type()>>16 == TSSLPT) { QPolygonF polygon(tsslptArrow(centroid(poly->path().first()), @@ -243,13 +247,14 @@ void RasterTile::drawArrows(QPainter *painter) } } -void RasterTile::drawPolygons(QPainter *painter) +void RasterTile::drawPolygons(QPainter *painter, + const QList &polygons) { const Style &s = style(); for (int n = 0; n < s.drawOrder().size(); n++) { - for (int i = 0; i < _polygons.size(); i++) { - const MapData::Poly *poly = _polygons.at(i); + for (int i = 0; i < polygons.size(); i++) { + const MapData::Poly *poly = polygons.at(i); if (poly->type() != s.drawOrder().at(n)) continue; const Style::Polygon &style = s.polygon(poly->type()); @@ -267,14 +272,14 @@ void RasterTile::drawPolygons(QPainter *painter) } } -void RasterTile::drawLines(QPainter *painter) +void RasterTile::drawLines(QPainter *painter, const QList &lines) { const Style &s = style(); painter->setBrush(Qt::NoBrush); - for (int i = 0; i < _lines.size(); i++) { - const MapData::Line *line = _lines.at(i); + for (int i = 0; i < lines.size(); i++) { + const MapData::Line *line = lines.at(i); const Style::Line &style = s.line(line->type()); if (!style.img().isNull()) { @@ -293,12 +298,13 @@ void RasterTile::drawTextItems(QPainter *painter, textItems.at(i)->paint(painter); } -void RasterTile::processPolygons(QList &textItems) +void RasterTile::processPolygons(const QList &polygons, + QList &textItems) { const Style &s = style(); - for (int i = 0; i < _polygons.size(); i++) { - const MapData::Poly *poly = _polygons.at(i); + for (int i = 0; i < polygons.size(); i++) { + const MapData::Poly *poly = polygons.at(i); uint type = poly->type()>>16; if (!(type == HRBFAC || type == I_TRNBSN @@ -319,18 +325,18 @@ void RasterTile::processPolygons(QList &textItems) } } -void RasterTile::processPoints(QList &textItems, - QList &lights) +void RasterTile::processPoints(QList &points, + QList &textItems, QList &lights) { const Style &s = style(); PointMap lightsMap, signalsMap; int i; - std::sort(_points.begin(), _points.end(), pointLess); + std::sort(points.begin(), points.end(), pointLess); /* Lights & Signals */ - for (i = 0; i < _points.size(); i++) { - const MapData::Point *point = _points.at(i); + for (i = 0; i < points.size(); i++) { + const MapData::Point *point = points.at(i); if (point->type()>>16 == LIGHTS) lightsMap.insert(point->pos(), point); else if (point->type()>>16 == FOGSIG) @@ -340,8 +346,8 @@ void RasterTile::processPoints(QList &textItems, } /* Everything else */ - for ( ; i < _points.size(); i++) { - const MapData::Point *point = _points.at(i); + for ( ; i < points.size(); i++) { + const MapData::Point *point = points.at(i); QPoint pos(ll2xy(point->pos()).toPoint()); const Style::Point &style = s.point(point->type()); @@ -349,7 +355,7 @@ void RasterTile::processPoints(QList &textItems, QImage *rimg = style.img().isNull() ? image(point->type(), point->param()) : 0; const QImage *img = style.img().isNull() ? rimg : &style.img(); - const QFont *fnt = showLabel(img, _zooms, _zoom, point->type()) + const QFont *fnt = showLabel(img, _data->zooms(), _zoom, point->type()) ? font(style.textFontSize()) : 0; const QColor *color = &style.textColor(); const QColor *hColor = style.haloColor().isValid() @@ -371,12 +377,13 @@ void RasterTile::processPoints(QList &textItems, } } -void RasterTile::processLines(QList &textItems) +void RasterTile::processLines(const QList &lines, + QList &textItems) { const Style &s = style(); - for (int i = 0; i < _lines.size(); i++) { - const MapData::Line *line = _lines.at(i); + for (int i = 0; i < lines.size(); i++) { + const MapData::Line *line = lines.at(i); const Style::Line &style = s.line(line->type()); if (style.img().isNull() && style.pen() == Qt::NoPen) @@ -396,25 +403,51 @@ void RasterTile::processLines(QList &textItems) } } +void RasterTile::fetchData(QList &polygons, + QList &lines, QList &points) +{ + QPoint ttl(_rect.topLeft()); + + QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y() + + _rect.height())); + RectD polyRectD(_transform.img2proj(polyRect.topLeft()), + _transform.img2proj(polyRect.bottomRight())); + RectC polyRectC(polyRectD.toRectC(_proj, 20)); + _data->lines(polyRectC, &lines); + _data->polygons(polyRectC, &polygons); + + QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT), + QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height() + + TEXT_EXTENT)); + RectD pointRectD(_transform.img2proj(pointRect.topLeft()), + _transform.img2proj(pointRect.bottomRight())); + _data->points(pointRectD.toRectC(_proj, 20), &points); +} + void RasterTile::render() { + QList lines; + QList polygons; + QList points; QList textItems, lights; _pixmap.setDevicePixelRatio(_ratio); _pixmap.fill(Qt::transparent); - processPolygons(textItems); - processPoints(textItems, lights); - processLines(textItems); + fetchData(polygons, lines, points); + + processPolygons(polygons, textItems); + processPoints(points, textItems, lights); + processLines(lines, textItems); QPainter painter(&_pixmap); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::Antialiasing); painter.translate(-_rect.x(), -_rect.y()); - drawPolygons(&painter); - drawLines(&painter); - drawArrows(&painter); + drawPolygons(&painter, polygons); + drawLines(&painter, lines); + drawArrows(&painter, polygons); drawTextItems(&painter, lights); drawTextItems(&painter, textItems); diff --git a/src/map/ENC/rastertile.h b/src/map/ENC/rastertile.h index 718793ca..06bf3556 100644 --- a/src/map/ENC/rastertile.h +++ b/src/map/ENC/rastertile.h @@ -15,13 +15,10 @@ class RasterTile { public: RasterTile(const Projection &proj, const Transform &transform, - const Range &zooms, int zoom, const QRect &rect, qreal ratio, - const QList &lines, const QList &polygons, - const QList &points) - : _proj(proj), _transform(transform), _zooms(zooms), _zoom(zoom), + const MapData *data, int zoom, const QRect &rect, qreal ratio) + : _proj(proj), _transform(transform), _data(data), _zoom(zoom), _rect(rect), _ratio(ratio), - _pixmap(rect.width() * ratio, rect.height() * ratio), _lines(lines), - _polygons(polygons), _points(points), _valid(false) {} + _pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {} int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} @@ -44,31 +41,33 @@ private: const QImage *_rimg; }; + void fetchData(QList &polygons, QList &lines, + QList &points); QPointF ll2xy(const Coordinates &c) const {return _transform.proj2img(_proj.ll2xy(c));} QPainterPath painterPath(const Polygon &polygon) const; QPolygonF polyline(const QVector &path) const; QPolygonF tsslptArrow(const Coordinates &c, qreal angle) const; - void processPoints(QList &textItems, QList &lights); - void processLines(QList &textItems); - void processPolygons(QList &textItems); + void processPoints(QList &points, + QList &textItems, QList &lights); + void processLines(const QList &lines, + QList &textItems); + void processPolygons(const QList &polygons, + 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 drawArrows(QPainter *painter, const QList &polygons); + void drawPolygons(QPainter *painter, const QList &polygons); + void drawLines(QPainter *painter, const QList &lines); void drawTextItems(QPainter *painter, const QList &textItems); Projection _proj; Transform _transform; - Range _zooms; + const MapData *_data; int _zoom; QRect _rect; qreal _ratio; QPixmap _pixmap; - QList _lines; - QList _polygons; - QList _points; bool _valid; }; diff --git a/src/map/IMG/mapdata.cpp b/src/map/IMG/mapdata.cpp index 16c55934..8f6e06b2 100644 --- a/src/map/IMG/mapdata.cpp +++ b/src/map/IMG/mapdata.cpp @@ -53,7 +53,9 @@ void MapData::polys(const RectC &rect, int bits, QList *polygons, max[0] = rect.right(); max[1] = rect.top(); + _lock.lock(); _tileTree.Search(min, max, polyCb, &ctx); + _lock.unlock(); } void MapData::points(const RectC &rect, int bits, QList *points) @@ -66,7 +68,9 @@ void MapData::points(const RectC &rect, int bits, QList *points) max[0] = rect.right(); max[1] = rect.top(); + _lock.lock(); _tileTree.Search(min, max, pointCb, &ctx); + _lock.unlock(); } void MapData::load() diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h index b8c6c037..e3c0fd02 100644 --- a/src/map/IMG/mapdata.h +++ b/src/map/IMG/mapdata.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include "common/rectc.h" #include "common/rtree.h" @@ -97,11 +98,14 @@ private: QList lines; }; + typedef QCache PolyCache; + typedef QCache > PointCache; + struct PolyCTX { PolyCTX(const RectC &rect, const Zoom &zoom, QList *polygons, QList *lines, - QCache *polyCache) + PolyCache *polyCache) : rect(rect), zoom(zoom), polygons(polygons), lines(lines), polyCache(polyCache) {} @@ -109,20 +113,19 @@ private: const Zoom &zoom; QList *polygons; QList *lines; - QCache *polyCache; + PolyCache *polyCache; }; struct PointCTX { PointCTX(const RectC &rect, const Zoom &zoom, - QList *points, - QCache > *pointCache) + QList *points, PointCache *pointCache) : rect(rect), zoom(zoom), points(points), pointCache(pointCache) {} const RectC ▭ const Zoom &zoom; QList *points; - QCache > *pointCache; + PointCache *pointCache; }; const Zoom &zoom(int bits) const; @@ -130,8 +133,9 @@ private: static bool polyCb(VectorTile *tile, void *context); static bool pointCb(VectorTile *tile, void *context); - QCache _polyCache; - QCache > _pointCache; + PolyCache _polyCache; + PointCache _pointCache; + QMutex _lock; friend class VectorTile; }; diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index 4fcb2be4..42896aa4 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -5,12 +5,14 @@ #include "map/textpathitem.h" #include "map/textpointitem.h" #include "map/bitmapline.h" +#include "map/rectd.h" #include "style.h" #include "lblfile.h" #include "rastertile.h" using namespace IMG; +#define TEXT_EXTENT 160 #define ICON_PADDING 2 #define AREA(rect) \ @@ -147,40 +149,6 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect) || polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill))); } - -void RasterTile::render() -{ - QList textItems; - - ll2xy(_polygons); - ll2xy(_lines); - ll2xy(_points); - - processPoints(textItems); - processPolygons(textItems); - processLines(textItems); - - _pixmap.setDevicePixelRatio(_ratio); - _pixmap.fill(Qt::transparent); - - QPainter painter(&_pixmap); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.setRenderHint(QPainter::Antialiasing); - painter.translate(-_rect.x(), -_rect.y()); - - drawPolygons(&painter); - drawLines(&painter); - drawTextItems(&painter, textItems); - - qDeleteAll(textItems); - - _valid = true; - - //painter.setPen(Qt::red); - //painter.setRenderHint(QPainter::Antialiasing, false); - //painter.drawRect(QRect(_xy, _pixmap.size())); -} - void RasterTile::ll2xy(QList &polys) { for (int i = 0; i < polys.size(); i++) { @@ -200,14 +168,15 @@ void RasterTile::ll2xy(QList &points) } } -void RasterTile::drawPolygons(QPainter *painter) +void RasterTile::drawPolygons(QPainter *painter, + const QList &polygons) { QCache hc(16); - for (int n = 0; n < _style->drawOrder().size(); n++) { - for (int i = 0; i < _polygons.size(); i++) { - const MapData::Poly &poly = _polygons.at(i); - if (poly.type != _style->drawOrder().at(n)) + for (int n = 0; n < _data->style()->drawOrder().size(); n++) { + for (int i = 0; i < polygons.size(); i++) { + const MapData::Poly &poly = polygons.at(i); + if (poly.type != _data->style()->drawOrder().at(n)) continue; if (poly.raster.isValid()) { @@ -237,7 +206,7 @@ void RasterTile::drawPolygons(QPainter *painter) //painter->setBrush(Qt::NoBrush); //painter->drawRect(QRectF(tl, br)); } else { - const Style::Polygon &style = _style->polygon(poly.type); + const Style::Polygon &style = _data->style()->polygon(poly.type); painter->setPen(style.pen()); painter->setBrush(style.brush()); @@ -247,13 +216,13 @@ void RasterTile::drawPolygons(QPainter *painter) } } -void RasterTile::drawLines(QPainter *painter) +void RasterTile::drawLines(QPainter *painter, const QList &lines) { painter->setBrush(Qt::NoBrush); - for (int i = 0; i < _lines.size(); i++) { - const MapData::Poly &poly = _lines.at(i); - const Style::Line &style = _style->line(poly.type); + for (int i = 0; i < lines.size(); i++) { + const MapData::Poly &poly = lines.at(i); + const Style::Line &style = _data->style()->line(poly.type); if (style.background() == Qt::NoPen) continue; @@ -262,9 +231,9 @@ void RasterTile::drawLines(QPainter *painter) painter->drawPolyline(poly.points); } - for (int i = 0; i < _lines.size(); i++) { - const MapData::Poly &poly = _lines.at(i); - const Style::Line &style = _style->line(poly.type); + for (int i = 0; i < lines.size(); i++) { + const MapData::Poly &poly = lines.at(i); + const Style::Line &style = _data->style()->line(poly.type); if (!style.img().isNull()) BitmapLine::draw(painter, poly.points, style.img()); @@ -295,13 +264,14 @@ static void removeDuplicitLabel(QList &labels, const QString &text, } } -void RasterTile::processPolygons(QList &textItems) +void RasterTile::processPolygons(const QList &polygons, + QList &textItems) { QSet set; QList labels; - for (int i = 0; i < _polygons.size(); i++) { - const MapData::Poly &poly = _polygons.at(i); + for (int i = 0; i < polygons.size(); i++) { + const MapData::Poly &poly = polygons.at(i); bool exists = set.contains(poly.label.text()); if (poly.label.text().isEmpty()) @@ -310,7 +280,7 @@ void RasterTile::processPolygons(QList &textItems) if (_zoom <= 23 && (Style::isWaterArea(poly.type) || Style::isMilitaryArea(poly.type) || Style::isNatureReserve(poly.type))) { - const Style::Polygon &style = _style->polygon(poly.type); + const Style::Polygon &style = _data->style()->polygon(poly.type); TextPointItem *item = new TextPointItem( centroid(poly.points).toPoint(), &poly.label.text(), poiFont(), 0, &style.brush().color(), &haloColor); @@ -331,20 +301,22 @@ void RasterTile::processPolygons(QList &textItems) textItems.append(labels); } -void RasterTile::processLines(QList &textItems) +void RasterTile::processLines(QList &lines, + QList &textItems) { - std::stable_sort(_lines.begin(), _lines.end()); + std::stable_sort(lines.begin(), lines.end()); if (_zoom >= 22) - processStreetNames(textItems); - processShields(textItems); + processStreetNames(lines, textItems); + processShields(lines, textItems); } -void RasterTile::processStreetNames(QList &textItems) +void RasterTile::processStreetNames(const QList &lines, + QList &textItems) { - for (int i = 0; i < _lines.size(); i++) { - const MapData::Poly &poly = _lines.at(i); - const Style::Line &style = _style->line(poly.type); + for (int i = 0; i < lines.size(); i++) { + const MapData::Poly &poly = lines.at(i); + const Style::Line &style = _data->style()->line(poly.type); if (style.img().isNull() && style.foreground() == Qt::NoPen) continue; @@ -366,7 +338,8 @@ void RasterTile::processStreetNames(QList &textItems) } } -void RasterTile::processShields(QList &textItems) +void RasterTile::processShields(const QList &lines, + QList &textItems) { for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) { if (minShieldZoom(static_cast(type)) > _zoom) @@ -375,8 +348,8 @@ void RasterTile::processShields(QList &textItems) QHash shields; QHash sp; - for (int i = 0; i < _lines.size(); i++) { - const MapData::Poly &poly = _lines.at(i); + for (int i = 0; i < lines.size(); i++) { + const MapData::Poly &poly = lines.at(i); const Shield &shield = poly.label.shield(); if (!shield.isValid() || shield.type() != type || !Style::isMajorRoad(poly.type)) @@ -429,13 +402,14 @@ void RasterTile::processShields(QList &textItems) } } -void RasterTile::processPoints(QList &textItems) +void RasterTile::processPoints(QList &points, + QList &textItems) { - std::sort(_points.begin(), _points.end()); + std::sort(points.begin(), points.end()); - for (int i = 0; i < _points.size(); i++) { - const MapData::Point &point = _points.at(i); - const Style::Point &style = _style->point(point.type); + for (int i = 0; i < points.size(); i++) { + const MapData::Point &point = points.at(i); + const Style::Point &style = _data->style()->point(point.type); bool poi = Style::isPOI(point.type); const QString *label = point.label.text().isEmpty() @@ -461,3 +435,60 @@ void RasterTile::processPoints(QList &textItems) delete item; } } + +void RasterTile::fetchData(QList &polygons, + QList &lines, QList &points) +{ + QPoint ttl(_rect.topLeft()); + + QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y() + + _rect.height())); + RectD polyRectD(_transform.img2proj(polyRect.topLeft()), + _transform.img2proj(polyRect.bottomRight())); + _data->polys(polyRectD.toRectC(_proj, 20), _zoom, + &polygons, &lines); + + QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT), + QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height() + + TEXT_EXTENT)); + RectD pointRectD(_transform.img2proj(pointRect.topLeft()), + _transform.img2proj(pointRect.bottomRight())); + _data->points(pointRectD.toRectC(_proj, 20), _zoom, &points); +} + +void RasterTile::render() +{ + QList polygons; + QList lines; + QList points; + QList textItems; + + fetchData(polygons, lines, points); + ll2xy(polygons); + ll2xy(lines); + ll2xy(points); + + processPoints(points, textItems); + processPolygons(polygons, textItems); + processLines(lines, textItems); + + _pixmap.setDevicePixelRatio(_ratio); + _pixmap.fill(Qt::transparent); + + QPainter painter(&_pixmap); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.setRenderHint(QPainter::Antialiasing); + painter.translate(-_rect.x(), -_rect.y()); + + drawPolygons(&painter, polygons); + drawLines(&painter, lines); + drawTextItems(&painter, textItems); + + qDeleteAll(textItems); + + _valid = true; + + //painter.setPen(Qt::red); + //painter.setRenderHint(QPainter::Antialiasing, false); + //painter.drawRect(QRect(_xy, _pixmap.size())); +} diff --git a/src/map/IMG/rastertile.h b/src/map/IMG/rastertile.h index 5dc4fbfe..8002c8b8 100644 --- a/src/map/IMG/rastertile.h +++ b/src/map/IMG/rastertile.h @@ -17,14 +17,11 @@ class Style; class RasterTile { public: - RasterTile(const Projection &proj, const Transform &transform, - const Style *style, int zoom, const QRect &rect, qreal ratio, - const QString &key, const QList &polygons, - const QList &lines, QList &points) - : _proj(proj), _transform(transform), _style(style), _zoom(zoom), - _rect(rect), _ratio(ratio), _key(key), - _pixmap(rect.width() * ratio, rect.height() * ratio), _polygons(polygons), - _lines(lines), _points(points), _valid(false) {} + RasterTile(const Projection &proj, const Transform &transform, MapData *data, + int zoom, const QRect &rect, qreal ratio, const QString &key) + : _proj(proj), _transform(transform), _data(data), _zoom(zoom), + _rect(rect), _ratio(ratio), _key(key), + _pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {} const QString &key() const {return _key;} QPoint xy() const {return _rect.topLeft();} @@ -34,32 +31,36 @@ public: void render(); private: + void fetchData(QList &polygons, QList &lines, + QList &points); QPointF ll2xy(const Coordinates &c) const {return _transform.proj2img(_proj.ll2xy(c));} void ll2xy(QList &polys); void ll2xy(QList &points); - void drawPolygons(QPainter *painter); - void drawLines(QPainter *painter); + void drawPolygons(QPainter *painter, const QList &polygons); + void drawLines(QPainter *painter, const QList &lines); void drawTextItems(QPainter *painter, const QList &textItems); - void processPolygons(QList &textItems); - void processLines(QList &textItems); - void processPoints(QList &textItems); - void processShields(QList &textItems); - void processStreetNames(QList &textItems); + void processPolygons(const QList &polygons, + QList &textItems); + void processLines(QList &lines, + QList &textItems); + void processPoints(QList &points, + QList &textItems); + void processShields(const QList &lines, + QList &textItems); + void processStreetNames(const QList &lines, + QList &textItems); Projection _proj; Transform _transform; - const Style *_style; + MapData *_data; int _zoom; QRect _rect; qreal _ratio; QString _key; QPixmap _pixmap; - QList _polygons; - QList _lines; - QList _points; bool _valid; }; diff --git a/src/map/IMG/vectortile.cpp b/src/map/IMG/vectortile.cpp index 7da1edd5..3435e65c 100644 --- a/src/map/IMG/vectortile.cpp +++ b/src/map/IMG/vectortile.cpp @@ -102,13 +102,16 @@ void VectorTile::clear() void VectorTile::polys(const RectC &rect, const Zoom &zoom, QList *polygons, QList *lines, - QCache *polyCache) + MapData::PolyCache *polyCache) { SubFile::Handle *rgnHdl = 0, *lblHdl = 0, *netHdl = 0, *nodHdl = 0, *nodHdl2 = 0; if (_loaded < 0) return; + + //polyCache->lock.lock(); + if (!_loaded) { rgnHdl = new SubFile::Handle(_rgn); lblHdl = new SubFile::Handle(_lbl); @@ -116,6 +119,7 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom, nodHdl = new SubFile::Handle(_nod); if (!load(*rgnHdl, *lblHdl, *netHdl, *nodHdl)) { + //polyCache->lock.unlock(); delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl; return; } @@ -166,6 +170,8 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom, } } + //polyCache->lock.unlock(); + delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl; delete nodHdl2; } diff --git a/src/map/IMG/vectortile.h b/src/map/IMG/vectortile.h index 55369df7..9e617434 100644 --- a/src/map/IMG/vectortile.h +++ b/src/map/IMG/vectortile.h @@ -29,7 +29,7 @@ public: void polys(const RectC &rect, const Zoom &zoom, QList *polygons, QList *lines, - QCache *polyCache); + MapData::PolyCache *polyCache); void points(const RectC &rect, const Zoom &zoom, QList *points, QCache > *pointCache); diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index bd92e766..18df7624 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -6,11 +6,10 @@ #include "pcs.h" #include "encmap.h" -#define TILE_SIZE 512 -#define TEXT_EXTENT 160 using namespace ENC; +#define TILE_SIZE 512 ENCMap::ENCMap(const QString &fileName, QObject *parent) : Map(fileName, parent), _data(fileName), _projection(PCS::pcs(3857)), @@ -180,32 +179,9 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags) QPixmap pm; if (QPixmapCache::find(key(_zoom, ttl), &pm)) painter->drawPixmap(ttl, pm); - else { - QList polygons; - QList lines; - QList points; - - QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE, - ttl.y() + TILE_SIZE)); - polyRect &= _bounds; - RectD polyRectD(_transform.img2proj(polyRect.topLeft()), - _transform.img2proj(polyRect.bottomRight())); - RectC polyRectC(polyRectD.toRectC(_projection, 20)); - _data.lines(polyRectC, &lines); - _data.polygons(polyRectC, &polygons); - - QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, - ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE - + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)); - pointRect &= _bounds; - RectD pointRectD(_transform.img2proj(pointRect.topLeft()), - _transform.img2proj(pointRect.bottomRight())); - _data.points(pointRectD.toRectC(_projection, 20), &points); - - tiles.append(RasterTile(_projection, _transform, _data.zooms(), - _zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, - lines, polygons, points)); - } + else + tiles.append(RasterTile(_projection, _transform, &_data, + _zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio)); } } diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index 28c18105..be4d242d 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -16,7 +16,6 @@ using namespace IMG; #define TILE_SIZE 384 -#define TEXT_EXTENT 160 static RectC limitBounds(const RectC &bounds, const Projection &proj) { @@ -241,30 +240,9 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) if (QPixmapCache::find(key, &pm)) painter->drawPixmap(ttl, pm); else { - QList polygons, lines; - QList points; - - QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE, - ttl.y() + TILE_SIZE)); - polyRect &= _bounds; - RectD polyRectD(_transform.img2proj(polyRect.topLeft()), - _transform.img2proj(polyRect.bottomRight())); - _data.at(n)->polys(polyRectD.toRectC(_projection, 20), _zoom, - &polygons, &lines); - - QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, - ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE - + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)); - pointRect &= _bounds; - RectD pointRectD(_transform.img2proj(pointRect.topLeft()), - _transform.img2proj(pointRect.bottomRight())); - _data.at(n)->points(pointRectD.toRectC(_projection, 20), - _zoom, &points); - - tiles.append(RasterTile(_projection, _transform, - _data.at(n)->style(), _zoom, - QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, key, - polygons, lines, points)); + tiles.append(RasterTile(_projection, _transform, _data.at(n), + _zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, + key)); } } } diff --git a/src/map/mapsforge/mapdata.cpp b/src/map/mapsforge/mapdata.cpp index 0fa6785e..466be650 100644 --- a/src/map/mapsforge/mapdata.cpp +++ b/src/map/mapsforge/mapdata.cpp @@ -208,13 +208,15 @@ bool MapData::readTags(SubFile &subfile, int count, bool MapData::readSubFiles() { - QDataStream stream(&_file); + /* both _pointFile and _pathFile can be used here */ + QDataStream stream(&_pointFile); for (int i = 0; i < _subFiles.size(); i++) { const SubFileInfo &f = _subFiles.at(i); quint64 offset, nextOffset; - stream.device()->seek(f.offset); + if (!stream.device()->seek(f.offset)) + return false; QPoint tl(OSM::ll2tile(_bounds.topLeft(), f.base)); QPoint br(OSM::ll2tile(_bounds.bottomRight(), f.base)); @@ -359,7 +361,7 @@ bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap) return true; } -bool MapData::readHeader() +bool MapData::readHeader(QFile &file) { char magic[MAGIC_SIZE]; quint32 hdrSize; @@ -367,18 +369,18 @@ bool MapData::readHeader() bool debugMap; - if (_file.read(magic, MAGIC_SIZE) < (qint64)MAGIC_SIZE + if (file.read(magic, MAGIC_SIZE) < (qint64)MAGIC_SIZE || memcmp(magic, MAGIC, MAGIC_SIZE)) { _errorString = "Not a Mapsforge map"; return false; } - if (_file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) { + if (file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) { _errorString = "Unexpected EOF"; return false; } - SubFile hdr(_file, MAGIC_SIZE, qFromBigEndian(hdrSize)); + SubFile hdr(file, MAGIC_SIZE, qFromBigEndian(hdrSize)); if (!readMapInfo(hdr, projection, debugMap)) { _errorString = "Error reading map info"; @@ -407,18 +409,19 @@ bool MapData::readHeader() return true; } -MapData::MapData(const QString &fileName) : _file(fileName), _valid(false) +MapData::MapData(const QString &fileName) + : _pointFile(fileName), _pathFile(fileName), _valid(false) { - if (!_file.open(QFile::ReadOnly | QIODevice::Unbuffered)) { - _errorString = _file.errorString(); + QFile file(fileName); + + if (!file.open(QFile::ReadOnly | QIODevice::Unbuffered)) { + _errorString = file.errorString(); return; } - if (!readHeader()) + if (!readHeader(file)) return; - _file.close(); - _pathCache.setMaxCost(256); _pointCache.setMaxCost(256); @@ -444,13 +447,16 @@ RectC MapData::bounds() const void MapData::load() { - if (_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) - readSubFiles(); + _pointFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + _pathFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered); + + readSubFiles(); } void MapData::clear() { - _file.close(); + _pointFile.close(); + _pathFile.close(); _pathCache.clear(); _pointCache.clear(); @@ -516,6 +522,9 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom, QList *list) { Key key(tile, zoom); + + _pointLock.lock(); + QList *cached = _pointCache.object(key); if (!cached) { @@ -527,6 +536,8 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom, delete p; } else copyPoints(rect, cached, list); + + _pointLock.unlock(); } void MapData::paths(const RectC &rect, int zoom, QList *list) @@ -550,6 +561,9 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom, QList *list) { Key key(tile, zoom); + + _pathLock.lock(); + QList *cached = _pathCache.object(key); if (!cached) { @@ -561,12 +575,14 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom, delete p; } else copyPaths(rect, cached, list); + + _pathLock.unlock(); } bool MapData::readPaths(const VectorTile *tile, int zoom, QList *list) { const SubFileInfo &info = _subFiles.at(level(zoom)); - SubFile subfile(_file, info.offset, info.size); + SubFile subfile(_pathFile, info.offset, info.size); int rows = info.max - info.min + 1; QVector paths(rows); quint32 blocks, unused, val, cnt = 0; @@ -652,7 +668,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList *list) bool MapData::readPoints(const VectorTile *tile, int zoom, QList *list) { const SubFileInfo &info = _subFiles.at(level(zoom)); - SubFile subfile(_file, info.offset, info.size); + SubFile subfile(_pointFile, info.offset, info.size); int rows = info.max - info.min + 1; QVector points(rows); quint32 val, unused, cnt = 0; diff --git a/src/map/mapsforge/mapdata.h b/src/map/mapsforge/mapdata.h index a8bffa0a..cc1efb05 100644 --- a/src/map/mapsforge/mapdata.h +++ b/src/map/mapsforge/mapdata.h @@ -3,6 +3,7 @@ #include #include +#include #include "common/hash.h" #include "common/rectc.h" #include "common/rtree.h" @@ -138,7 +139,7 @@ private: bool readTagInfo(SubFile &hdr); bool readTagInfo(SubFile &hdr, QVector &tags); bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap); - bool readHeader(); + bool readHeader(QFile &file); bool readSubFiles(); void clearTiles(); @@ -157,7 +158,7 @@ private: friend HASH_T qHash(const MapData::Key &key); - QFile _file; + QFile _pointFile, _pathFile; RectC _bounds; quint16 _tileSize; QVector _subFiles; @@ -167,6 +168,7 @@ private: QCache > _pathCache; QCache > _pointCache; + QMutex _pathLock, _pointLock; bool _valid; QString _errorString; diff --git a/src/map/mapsforge/rastertile.cpp b/src/map/mapsforge/rastertile.cpp index 3ac43f0a..aea46555 100644 --- a/src/map/mapsforge/rastertile.cpp +++ b/src/map/mapsforge/rastertile.cpp @@ -1,10 +1,13 @@ #include #include #include "common/programpaths.h" +#include "map/rectd.h" #include "rastertile.h" using namespace Mapsforge; +#define TEXT_EXTENT 160 + static qreal area(const QPainterPath &polygon) { qreal area = 0; @@ -52,14 +55,15 @@ static const QColor *haloColor(const Style::TextRender *ti) ? &ti->strokeColor() : 0; } -void RasterTile::processPointLabels(QList &textItems) +void RasterTile::processPointLabels(const QList &points, + QList &textItems) { QList labels(_style->pointLabels(_zoom)); QList symbols(_style->pointSymbols(_zoom)); - QList points; + QList painterPoints; - for (int i = 0; i < _points.size(); i++) { - const MapData::Point &point = _points.at(i); + for (int i = 0; i < points.size(); i++) { + const MapData::Point &point = points.at(i); const QByteArray *lbl = 0; const Style::TextRender *ti = 0; const Style::Symbol *si = 0; @@ -83,13 +87,13 @@ void RasterTile::processPointLabels(QList &textItems) } if (ti || si) - points.append(PainterPoint(&point, lbl, si, ti)); + painterPoints.append(PainterPoint(&point, lbl, si, ti)); } - std::sort(points.begin(), points.end()); + std::sort(painterPoints.begin(), painterPoints.end()); - for (int i = 0; i < points.size(); i++) { - const PainterPoint &p = points.at(i); + for (int i = 0; i < painterPoints.size(); i++) { + const PainterPoint &p = painterPoints.at(i); const QImage *img = p.si ? &p.si->img() : 0; const QFont *font = p.ti ? &p.ti->font() : 0; const QColor *color = p.ti ? &p.ti->fillColor() : 0; @@ -238,15 +242,16 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const return path; } -void RasterTile::pathInstructions(QVector &paths, +void RasterTile::pathInstructions(const QList &paths, + QVector &painterPaths, QVector &instructions) { QCache > cache(8192); QList *ri; - for (int i = 0; i < _paths.size(); i++) { - const MapData::Path &path = _paths.at(i); - PainterPath &rp = paths[i]; + for (int i = 0; i < paths.size(); i++) { + const MapData::Path &path = paths.at(i); + PainterPath &rp = painterPaths[i]; PathKey key(_zoom, path.closed, path.tags); rp.path = &path; @@ -264,14 +269,14 @@ void RasterTile::pathInstructions(QVector &paths, } } -void RasterTile::circleInstructions( +void RasterTile::circleInstructions(const QList &points, QVector &instructions) { QCache > cache(8192); QList *ri; - for (int i = 0; i < _points.size(); i++) { - const MapData::Point &point = _points.at(i); + for (int i = 0; i < points.size(); i++) { + const MapData::Point &point = points.at(i); PointKey key(_zoom, point.tags); if (!(ri = cache.object(key))) { @@ -287,11 +292,12 @@ void RasterTile::circleInstructions( } } -void RasterTile::drawPaths(QPainter *painter, QVector &paths) +void RasterTile::drawPaths(QPainter *painter, const QList &paths, + const QList &points, QVector &painterPaths) { QVector instructions; - pathInstructions(paths, instructions); - circleInstructions(instructions); + pathInstructions(paths, painterPaths, instructions); + circleInstructions(points, instructions); std::sort(instructions.begin(), instructions.end()); for (int i = 0; i < instructions.size(); i++) { @@ -318,10 +324,37 @@ void RasterTile::drawPaths(QPainter *painter, QVector &paths) } } +void RasterTile::fetchData(QList &paths, + QList &points) +{ + QPoint ttl(_rect.topLeft()); + + /* Add a "sub-pixel" margin to assure the tile areas do not + overlap on the border lines. This prevents areas overlap + artifacts at least when using the EPSG:3857 projection. */ + QRectF pathRect(QPointF(ttl.x() + 0.5, ttl.y() + 0.5), + QPointF(ttl.x() + _rect.width() - 0.5, ttl.y() + _rect.height() - 0.5)); + RectD pathRectD(_transform.img2proj(pathRect.topLeft()), + _transform.img2proj(pathRect.bottomRight())); + _data->paths(pathRectD.toRectC(_proj, 20), _zoom, &paths); + + QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT), + QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height() + + TEXT_EXTENT)); + RectD pointRectD(_transform.img2proj(pointRect.topLeft()), + _transform.img2proj(pointRect.bottomRight())); + _data->points(pointRectD.toRectC(_proj, 20), _zoom, &points); +} + void RasterTile::render() { + QList paths; + QList points; + + fetchData(paths, points); + QList textItems; - QVector renderPaths(_paths.size()); + QVector renderPaths(paths.size()); _pixmap.setDevicePixelRatio(_ratio); _pixmap.fill(Qt::transparent); @@ -330,9 +363,9 @@ void RasterTile::render() painter.setRenderHint(QPainter::Antialiasing); painter.translate(-_rect.x(), -_rect.y()); - drawPaths(&painter, renderPaths); + drawPaths(&painter, paths, points, renderPaths); - processPointLabels(textItems); + processPointLabels(points, textItems); processAreaLabels(textItems, renderPaths); processLineLabels(textItems, renderPaths); drawTextItems(&painter, textItems); diff --git a/src/map/mapsforge/rastertile.h b/src/map/mapsforge/rastertile.h index 22308c29..ee3b159c 100644 --- a/src/map/mapsforge/rastertile.h +++ b/src/map/mapsforge/rastertile.h @@ -15,11 +15,10 @@ class RasterTile { public: RasterTile(const Projection &proj, const Transform &transform, - const Style *style, int zoom, const QRect &rect, qreal ratio, - const QList &paths, const QList &points) - : _proj(proj), _transform(transform), _style(style), - _zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio, - rect.height() * ratio), _paths(paths), _points(points), _valid(false) {} + const Style *style, MapData *data, int zoom, const QRect &rect, + qreal ratio) : _proj(proj), _transform(transform), _style(style), + _data(data), _zoom(zoom), _rect(rect), _ratio(ratio), + _pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {} int zoom() const {return _zoom;} QPoint xy() const {return _rect.topLeft();} @@ -147,31 +146,33 @@ private: friend HASH_T qHash(const RasterTile::PathKey &key); friend HASH_T qHash(const RasterTile::PointKey &key); - void pathInstructions(QVector &paths, + void fetchData(QList &paths, QList &points); + void pathInstructions(const QList &paths, + QVector &painterPaths, + QVector &instructions); + void circleInstructions(const QList &points, QVector &instructions); - void circleInstructions(QVector &instructions); QPointF ll2xy(const Coordinates &c) const {return _transform.proj2img(_proj.ll2xy(c));} - void processPointLabels(QList &textItems); + void processPointLabels(const QList &points, + QList &textItems); void processAreaLabels(QList &textItems, QVector &paths); void processLineLabels(QList &textItems, QVector &paths); QPainterPath painterPath(const Polygon &polygon, bool curve) const; void drawTextItems(QPainter *painter, const QList &textItems); - void drawPaths(QPainter *painter, QVector &paths); - + void drawPaths(QPainter *painter, const QList &paths, + const QList &points, QVector &painterPaths); Projection _proj; Transform _transform; const Style *_style; + MapData *_data; int _zoom; QRect _rect; qreal _ratio; QPixmap _pixmap; - QList _paths; - QList _points; - bool _valid; }; diff --git a/src/map/mapsforgemap.cpp b/src/map/mapsforgemap.cpp index cd4bdf22..3f3053b7 100644 --- a/src/map/mapsforgemap.cpp +++ b/src/map/mapsforgemap.cpp @@ -2,15 +2,13 @@ #include #include "common/wgs84.h" #include "common/util.h" -#include "pcs.h" #include "rectd.h" +#include "pcs.h" #include "mapsforgemap.h" using namespace Mapsforge; -#define TEXT_EXTENT 160 - MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent) : Map(fileName, parent), _data(fileName), _zoom(0), _projection(PCS::pcs(3857)), _tileRatio(1.0) @@ -188,33 +186,9 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) if (QPixmapCache::find(key(_zoom, ttl), &pm)) painter->drawPixmap(ttl, pm); else { - QList paths; - QList points; - - /* Add a "sub-pixel" margin to assure the tile areas do not - overlap on the border lines. This prevents areas overlap - artifacts at least when using the EPSG:3857 projection. */ - QRectF pathRect(QPointF(ttl.x() + 0.5, ttl.y() + 0.5), - QPointF(ttl.x() + _data.tileSize() - 0.5, ttl.y() - + _data.tileSize() - 0.5)); - pathRect &= _bounds; - RectD pathRectD(_transform.img2proj(pathRect.topLeft()), - _transform.img2proj(pathRect.bottomRight())); - _data.paths(pathRectD.toRectC(_projection, 20), _zoom, &paths); - - QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - - TEXT_EXTENT), QPointF(ttl.x() + _data.tileSize() - + TEXT_EXTENT, ttl.y() + _data.tileSize() + TEXT_EXTENT)); - pointRect &= _bounds; - RectD pointRectD(_transform.img2proj(pointRect.topLeft()), - _transform.img2proj(pointRect.bottomRight())); - _data.points(pointRectD.toRectC(_projection, 20), _zoom, - &points); - - if (paths.size() || points.size()) - tiles.append(RasterTile(_projection, _transform, &_style, - _zoom, QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), - _tileRatio, paths, points)); + tiles.append(RasterTile(_projection, _transform, &_style, &_data, + _zoom, QRect(ttl, QSize(_data.tileSize(), _data.tileSize())), + _tileRatio)); } } }