1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-07-22 14:54:24 +02:00

Compare commits

...

10 Commits

Author SHA1 Message Date
822a0c2866 Tile search can be done lock-free 2023-05-21 09:14:19 +02:00
a92d6efec6 Do not do any time consuming actions in the mapview redraw callback
On all vector maps (ENC, IMG and Mapsforge), do the data loading
asynchronous like the tile rendering.
2023-05-19 19:33:22 +02:00
4615709b99 Merge branch 'origin/master' into Weblate. 2023-05-19 01:31:46 +02:00
8a72b20af8 Added support for all paths scaling modes 2023-05-19 01:30:54 +02:00
f86aa8c012 Merge branch 'origin/master' into Weblate. 2023-05-17 23:15:09 +02:00
e351eb6370 Only preallocate the memory when usin moveto/lineto 2023-05-17 23:10:45 +02:00
81e967f20d Only fetch data when the rect is valid 2023-05-17 23:08:17 +02:00
dbf5828e65 Merge branch 'origin/master' into Weblate. 2023-05-16 23:03:34 +02:00
37d408c953 Translated using Weblate (Danish)
Currently translated at 100.0% (467 of 467 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/da/
2023-05-16 21:51:52 +02:00
61c3ed60d7 Translated using Weblate (French)
Currently translated at 99.7% (466 of 467 strings)

Translation: GPXSee/Translations
Translate-URL: https://hosted.weblate.org/projects/gpxsee/translations/fr/
2023-05-14 00:53:09 +02:00
21 changed files with 407 additions and 307 deletions

View File

@ -712,7 +712,7 @@
<location filename="../src/GUI/gui.cpp" line="907"/>
<location filename="../src/GUI/gui.cpp" line="925"/>
<source>CRS directory:</source>
<translation type="unfinished"></translation>
<translation>CRS-katalog:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="913"/>

View File

@ -958,7 +958,7 @@
<location filename="../src/GUI/gui.cpp" line="907"/>
<location filename="../src/GUI/gui.cpp" line="925"/>
<source>CRS directory:</source>
<translation type="unfinished"></translation>
<translation>Dossier CRS:</translation>
</message>
<message>
<location filename="../src/GUI/gui.cpp" line="915"/>
@ -1427,12 +1427,12 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="70"/>
<source>Select the proper coordinate reference system (CRS) of maps without a CRS definition (JNX, KMZ and World file maps).</source>
<translation type="unfinished"></translation>
<translation type="unfinished">Sélectionnez le système de référence de coordonnée (CRS) approprié pour les cartes sans définition de CRS (JNX, KMZ et World file maps).</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="73"/>
<source>Select the desired projection of vector maps (IMG, Mapsforge and ENC maps). The projection must be valid for the whole map area.</source>
<translation type="unfinished"></translation>
<translation>Sélectionnez la projection désirée de la carte vectorielle (IMG, Mapsforge et carte ENC). La projection doit être valide pour la totalité de la zone de la carte.</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="77"/>
@ -1912,7 +1912,7 @@
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="758"/>
<source>DEM cache size:</source>
<translation type="unfinished"></translation>
<translation>Taille du cache DEM :</translation>
</message>
<message>
<location filename="../src/GUI/optionsdialog.cpp" line="778"/>

View File

@ -893,7 +893,7 @@ void MapData::clear()
_points.RemoveAll();
}
void MapData::points(const RectC &rect, QList<Point*> *points)
void MapData::points(const RectC &rect, QList<Point*> *points) const
{
double min[2], max[2];
@ -901,7 +901,7 @@ void MapData::points(const RectC &rect, QList<Point*> *points)
_points.Search(min, max, pointCb, points);
}
void MapData::lines(const RectC &rect, QList<Line*> *lines)
void MapData::lines(const RectC &rect, QList<Line*> *lines) const
{
double min[2], max[2];
@ -909,7 +909,7 @@ void MapData::lines(const RectC &rect, QList<Line*> *lines)
_lines.Search(min, max, lineCb, lines);
}
void MapData::polygons(const RectC &rect, QList<Poly*> *polygons)
void MapData::polygons(const RectC &rect, QList<Poly*> *polygons) const
{
double min[2], max[2];

View File

@ -72,9 +72,9 @@ public:
RectC bounds() const {return _bounds;}
Range zooms() const;
void polygons(const RectC &rect, QList<Poly*> *polygons);
void lines(const RectC &rect, QList<Line*> *lines);
void points(const RectC &rect, QList<Point*> *points);
void polygons(const RectC &rect, QList<Poly*> *polygons) const;
void lines(const RectC &rect, QList<Line*> *lines) const;
void points(const RectC &rect, QList<Point*> *points) const;
void load();
void clear();

View File

@ -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<MapData::Poly*> &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<MapData::Poly*> &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<MapData::Line*> &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<TextItem*> &textItems)
void RasterTile::processPolygons(const QList<MapData::Poly*> &polygons,
QList<TextItem*> &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<TextItem*> &textItems)
}
}
void RasterTile::processPoints(QList<TextItem*> &textItems,
QList<TextItem*> &lights)
void RasterTile::processPoints(QList<MapData::Point*> &points,
QList<TextItem*> &textItems, QList<TextItem*> &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<TextItem*> &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<TextItem*> &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<TextItem*> &textItems,
}
}
void RasterTile::processLines(QList<TextItem*> &textItems)
void RasterTile::processLines(const QList<MapData::Line*> &lines,
QList<TextItem*> &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<TextItem*> &textItems)
}
}
void RasterTile::fetchData(QList<MapData::Poly*> &polygons,
QList<MapData::Line*> &lines, QList<MapData::Point*> &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<MapData::Line*> lines;
QList<MapData::Poly*> polygons;
QList<MapData::Point*> points;
QList<TextItem*> 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);

View File

@ -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<MapData::Line*> &lines, const QList<MapData::Poly*> &polygons,
const QList<MapData::Point*> &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<MapData::Poly*> &polygons, QList<MapData::Line*> &lines,
QList<MapData::Point*> &points);
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
QPainterPath painterPath(const Polygon &polygon) const;
QPolygonF polyline(const QVector<Coordinates> &path) const;
QPolygonF tsslptArrow(const Coordinates &c, qreal angle) const;
void processPoints(QList<TextItem*> &textItems, QList<TextItem *> &lights);
void processLines(QList<TextItem*> &textItems);
void processPolygons(QList<TextItem*> &textItems);
void processPoints(QList<MapData::Point *> &points,
QList<TextItem*> &textItems, QList<TextItem *> &lights);
void processLines(const QList<MapData::Line *> &lines,
QList<TextItem*> &textItems);
void processPolygons(const QList<MapData::Poly *> &polygons,
QList<TextItem*> &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<MapData::Poly*> &polygons);
void drawPolygons(QPainter *painter, const QList<MapData::Poly *> &polygons);
void drawLines(QPainter *painter, const QList<MapData::Line *> &lines);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
Projection _proj;
Transform _transform;
Range _zooms;
const MapData *_data;
int _zoom;
QRect _rect;
qreal _ratio;
QPixmap _pixmap;
QList<MapData::Line*> _lines;
QList<MapData::Poly*> _polygons;
QList<MapData::Point*> _points;
bool _valid;
};

View File

@ -13,14 +13,14 @@ bool MapData::polyCb(VectorTile *tile, void *context)
{
PolyCTX *ctx = (PolyCTX*)context;
tile->polys(ctx->rect, ctx->zoom, ctx->polygons, ctx->lines,
ctx->polyCache);
ctx->polyCache, ctx->lock);
return true;
}
bool MapData::pointCb(VectorTile *tile, void *context)
{
PointCTX *ctx = (PointCTX*)context;
tile->points(ctx->rect, ctx->zoom, ctx->points, ctx->pointCache);
tile->points(ctx->rect, ctx->zoom, ctx->points, ctx->pointCache, ctx->lock);
return true;
}
@ -45,7 +45,7 @@ MapData::~MapData()
void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines)
{
PolyCTX ctx(rect, zoom(bits), polygons, lines, &_polyCache);
PolyCTX ctx(rect, zoom(bits), polygons, lines, &_polyCache, &_lock);
double min[2], max[2];
min[0] = rect.left();
@ -58,7 +58,7 @@ void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
void MapData::points(const RectC &rect, int bits, QList<Point> *points)
{
PointCTX ctx(rect, zoom(bits), points, &_pointCache);
PointCTX ctx(rect, zoom(bits), points, &_pointCache, &_lock);
double min[2], max[2];
min[0] = rect.left();

View File

@ -4,6 +4,7 @@
#include <QList>
#include <QPointF>
#include <QCache>
#include <QMutex>
#include <QDebug>
#include "common/rectc.h"
#include "common/rtree.h"
@ -97,32 +98,37 @@ private:
QList<Poly> lines;
};
typedef QCache<const SubDiv*, Polys> PolyCache;
typedef QCache<const SubDiv*, QList<Point> > PointCache;
struct PolyCTX
{
PolyCTX(const RectC &rect, const Zoom &zoom,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv*, MapData::Polys> *polyCache)
PolyCache *polyCache, QMutex *lock)
: rect(rect), zoom(zoom), polygons(polygons), lines(lines),
polyCache(polyCache) {}
polyCache(polyCache), lock(lock) {}
const RectC &rect;
const Zoom &zoom;
QList<MapData::Poly> *polygons;
QList<MapData::Poly> *lines;
QCache<const SubDiv*, MapData::Polys> *polyCache;
PolyCache *polyCache;
QMutex *lock;
};
struct PointCTX
{
PointCTX(const RectC &rect, const Zoom &zoom,
QList<MapData::Point> *points,
QCache<const SubDiv*, QList<MapData::Point> > *pointCache)
: rect(rect), zoom(zoom), points(points), pointCache(pointCache) {}
QList<MapData::Point> *points, PointCache *pointCache, QMutex *lock)
: rect(rect), zoom(zoom), points(points), pointCache(pointCache),
lock(lock) {}
const RectC &rect;
const Zoom &zoom;
QList<MapData::Point> *points;
QCache<const SubDiv*, QList<MapData::Point> > *pointCache;
PointCache *pointCache;
QMutex *lock;
};
const Zoom &zoom(int bits) const;
@ -130,8 +136,9 @@ private:
static bool polyCb(VectorTile *tile, void *context);
static bool pointCb(VectorTile *tile, void *context);
QCache<const SubDiv*, Polys> _polyCache;
QCache<const SubDiv*, QList<Point> > _pointCache;
PolyCache _polyCache;
PointCache _pointCache;
QMutex _lock;
friend class VectorTile;
};

View File

@ -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<TextItem*> 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<MapData::Poly> &polys)
{
for (int i = 0; i < polys.size(); i++) {
@ -200,14 +168,15 @@ void RasterTile::ll2xy(QList<MapData::Point> &points)
}
}
void RasterTile::drawPolygons(QPainter *painter)
void RasterTile::drawPolygons(QPainter *painter,
const QList<MapData::Poly> &polygons)
{
QCache<const LBLFile *, SubFile::Handle> 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<MapData::Poly> &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<TextItem *> &labels, const QString &text,
}
}
void RasterTile::processPolygons(QList<TextItem*> &textItems)
void RasterTile::processPolygons(const QList<MapData::Poly> &polygons,
QList<TextItem*> &textItems)
{
QSet<QString> set;
QList<TextItem *> 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<TextItem*> &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<TextItem*> &textItems)
textItems.append(labels);
}
void RasterTile::processLines(QList<TextItem*> &textItems)
void RasterTile::processLines(QList<MapData::Poly> &lines,
QList<TextItem*> &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<TextItem*> &textItems)
void RasterTile::processStreetNames(const QList<MapData::Poly> &lines,
QList<TextItem*> &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<TextItem*> &textItems)
}
}
void RasterTile::processShields(QList<TextItem*> &textItems)
void RasterTile::processShields(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems)
{
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
if (minShieldZoom(static_cast<Shield::Type>(type)) > _zoom)
@ -375,8 +348,8 @@ void RasterTile::processShields(QList<TextItem*> &textItems)
QHash<Shield, QPolygonF> shields;
QHash<Shield, const Shield*> 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<TextItem*> &textItems)
}
}
void RasterTile::processPoints(QList<TextItem*> &textItems)
void RasterTile::processPoints(QList<MapData::Point> &points,
QList<TextItem*> &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<TextItem*> &textItems)
delete item;
}
}
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
QList<MapData::Poly> &lines, QList<MapData::Point> &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<MapData::Poly> polygons;
QList<MapData::Poly> lines;
QList<MapData::Point> points;
QList<TextItem*> 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()));
}

View File

@ -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<MapData::Poly> &polygons,
const QList<MapData::Poly> &lines, QList<MapData::Point> &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<MapData::Poly> &polygons, QList<MapData::Poly> &lines,
QList<MapData::Point> &points);
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
void ll2xy(QList<MapData::Poly> &polys);
void ll2xy(QList<MapData::Point> &points);
void drawPolygons(QPainter *painter);
void drawLines(QPainter *painter);
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
void drawLines(QPainter *painter, const QList<MapData::Poly> &lines);
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void processPolygons(QList<TextItem *> &textItems);
void processLines(QList<TextItem*> &textItems);
void processPoints(QList<TextItem*> &textItems);
void processShields(QList<TextItem*> &textItems);
void processStreetNames(QList<TextItem*> &textItems);
void processPolygons(const QList<MapData::Poly> &polygons,
QList<TextItem *> &textItems);
void processLines(QList<MapData::Poly> &lines,
QList<TextItem*> &textItems);
void processPoints(QList<MapData::Point> &points,
QList<TextItem*> &textItems);
void processShields(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems);
void processStreetNames(const QList<MapData::Poly> &lines,
QList<TextItem*> &textItems);
Projection _proj;
Transform _transform;
const Style *_style;
MapData *_data;
int _zoom;
QRect _rect;
qreal _ratio;
QString _key;
QPixmap _pixmap;
QList<MapData::Poly> _polygons;
QList<MapData::Poly> _lines;
QList<MapData::Point> _points;
bool _valid;
};

View File

@ -102,13 +102,18 @@ void VectorTile::clear()
void VectorTile::polys(const RectC &rect, const Zoom &zoom,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache)
MapData::PolyCache *polyCache, QMutex *lock)
{
SubFile::Handle *rgnHdl = 0, *lblHdl = 0, *netHdl = 0, *nodHdl = 0,
*nodHdl2 = 0;
if (_loaded < 0)
lock->lock();
if (_loaded < 0) {
lock->unlock();
return;
}
if (!_loaded) {
rgnHdl = new SubFile::Handle(_rgn);
lblHdl = new SubFile::Handle(_lbl);
@ -116,6 +121,7 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom,
nodHdl = new SubFile::Handle(_nod);
if (!load(*rgnHdl, *lblHdl, *netHdl, *nodHdl)) {
lock->unlock();
delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl;
return;
}
@ -166,17 +172,24 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom,
}
}
lock->unlock();
delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl; delete nodHdl2;
}
void VectorTile::points(const RectC &rect, const Zoom &zoom,
QList<MapData::Point> *points, QCache<const SubDiv *,
QList<MapData::Point> > *pointCache)
QList<MapData::Point> > *pointCache, QMutex *lock)
{
SubFile::Handle *rgnHdl = 0, *lblHdl = 0;
if (_loaded < 0)
lock->lock();
if (_loaded < 0) {
lock->unlock();
return;
}
if (!_loaded) {
rgnHdl = new SubFile::Handle(_rgn);
lblHdl = new SubFile::Handle(_lbl);
@ -184,6 +197,7 @@ void VectorTile::points(const RectC &rect, const Zoom &zoom,
SubFile::Handle netHdl(_net);
if (!load(*rgnHdl, *lblHdl, netHdl, nodHdl)) {
lock->unlock();
delete rgnHdl; delete lblHdl;
return;
}
@ -217,6 +231,8 @@ void VectorTile::points(const RectC &rect, const Zoom &zoom,
copyPoints(rect, pl, points);
}
lock->unlock();
delete rgnHdl; delete lblHdl;
}

View File

@ -29,10 +29,10 @@ public:
void polys(const RectC &rect, const Zoom &zoom,
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
QCache<const SubDiv *, MapData::Polys> *polyCache);
MapData::PolyCache *polyCache, QMutex *lock);
void points(const RectC &rect, const Zoom &zoom,
QList<MapData::Point> *points, QCache<const SubDiv*,
QList<MapData::Point> > *pointCache);
QList<MapData::Point> > *pointCache, QMutex *lock);
static bool isTileFile(SubFile::Type type)
{

View File

@ -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<MapData::Poly*> polygons;
QList<MapData::Line*> lines;
QList<MapData::Point*> 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));
}
}

View File

@ -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<MapData::Poly> polygons, lines;
QList<MapData::Point> 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));
}
}
}

View File

@ -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();
@ -497,6 +503,9 @@ int MapData::level(int zoom) const
void MapData::points(const RectC &rect, int zoom, QList<Point> *list)
{
if (!rect.isValid())
return;
int l(level(zoom));
PointCTX ctx(this, rect, zoom, list);
double min[2], max[2];
@ -513,6 +522,9 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
QList<Point> *list)
{
Key key(tile, zoom);
_pointLock.lock();
QList<Point> *cached = _pointCache.object(key);
if (!cached) {
@ -524,10 +536,15 @@ 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<Path> *list)
{
if (!rect.isValid())
return;
int l(level(zoom));
PathCTX ctx(this, rect, zoom, list);
double min[2], max[2];
@ -544,6 +561,9 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
QList<Path> *list)
{
Key key(tile, zoom);
_pathLock.lock();
QList<Path> *cached = _pathCache.object(key);
if (!cached) {
@ -555,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<Path> *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<unsigned> paths(rows);
quint32 blocks, unused, val, cnt = 0;
@ -646,7 +668,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *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<unsigned> points(rows);
quint32 val, unused, cnt = 0;

View File

@ -3,6 +3,7 @@
#include <QFile>
#include <QCache>
#include <QMutex>
#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<TagSource> &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<SubFileInfo> _subFiles;
@ -167,6 +168,7 @@ private:
QCache<Key, QList<Path> > _pathCache;
QCache<Key, QList<Point> > _pointCache;
QMutex _pathLock, _pointLock;
bool _valid;
QString _errorString;

View File

@ -1,10 +1,13 @@
#include <QPainter>
#include <QCache>
#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<TextItem*> &textItems)
void RasterTile::processPointLabels(const QList<MapData::Point> &points,
QList<TextItem*> &textItems)
{
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
QList<PainterPoint> points;
QList<PainterPoint> 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<TextItem*> &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;
@ -200,17 +204,17 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
{
QPainterPath path;
if (curve) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
int size = 0;
for (int i = 0; i < polygon.size(); i++)
size += polygon.at(i).size();
path.reserve(size);
int size = 0;
for (int i = 0; i < polygon.size(); i++)
size += polygon.at(i).size();
path.reserve(size);
#endif // QT 5.13
for (int i = 0; i < polygon.size(); i++) {
const QVector<Coordinates> &subpath = polygon.at(i);
for (int i = 0; i < polygon.size(); i++) {
const QVector<Coordinates> &subpath = polygon.at(i);
if (curve) {
QPointF p1(ll2xy(subpath.first()));
QPointF p2(0, 0);
QPointF p3(0, 0);
@ -223,7 +227,11 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
p1 = p3;
}
path.quadTo(p2, p3);
} else {
}
} else {
for (int i = 0; i < polygon.size(); i++) {
const QVector<Coordinates> &subpath = polygon.at(i);
QVector<QPointF> p(subpath.size());
for (int j = 0; j < subpath.size(); j++)
p[j] = ll2xy(subpath.at(j));
@ -234,15 +242,16 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
return path;
}
void RasterTile::pathInstructions(QVector<PainterPath> &paths,
void RasterTile::pathInstructions(const QList<MapData::Path> &paths,
QVector<PainterPath> &painterPaths,
QVector<RasterTile::RenderInstruction> &instructions)
{
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
QList<const Style::PathRender*> *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;
@ -260,14 +269,14 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
}
}
void RasterTile::circleInstructions(
void RasterTile::circleInstructions(const QList<MapData::Point> &points,
QVector<RasterTile::RenderInstruction> &instructions)
{
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
QList<const Style::CircleRender*> *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))) {
@ -283,11 +292,12 @@ void RasterTile::circleInstructions(
}
}
void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths)
{
QVector<RenderInstruction> 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++) {
@ -314,10 +324,37 @@ void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
}
}
void RasterTile::fetchData(QList<MapData::Path> &paths,
QList<MapData::Point> &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<MapData::Path> paths;
QList<MapData::Point> points;
fetchData(paths, points);
QList<TextItem*> textItems;
QVector<PainterPath> renderPaths(_paths.size());
QVector<PainterPath> renderPaths(paths.size());
_pixmap.setDevicePixelRatio(_ratio);
_pixmap.fill(Qt::transparent);
@ -326,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);

View File

@ -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<MapData::Path> &paths, const QList<MapData::Point> &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<PainterPath> &paths,
void fetchData(QList<MapData::Path> &paths, QList<MapData::Point> &points);
void pathInstructions(const QList<MapData::Path> &paths,
QVector<PainterPath> &painterPaths,
QVector<RasterTile::RenderInstruction> &instructions);
void circleInstructions(const QList<MapData::Point> &points,
QVector<RasterTile::RenderInstruction> &instructions);
void circleInstructions(QVector<RasterTile::RenderInstruction> &instructions);
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
void processPointLabels(QList<TextItem*> &textItems);
void processPointLabels(const QList<MapData::Point> &points,
QList<TextItem*> &textItems);
void processAreaLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths);
void processLineLabels(QList<TextItem*> &textItems,
QVector<PainterPath> &paths);
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
void drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths);
Projection _proj;
Transform _transform;
const Style *_style;
MapData *_data;
int _zoom;
QRect _rect;
qreal _ratio;
QPixmap _pixmap;
QList<MapData::Path> _paths;
QList<MapData::Point> _points;
bool _valid;
};

View File

@ -154,6 +154,13 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
return;
}
}
if (attr.hasAttribute("scale")) {
QString scale(attr.value("scale").toString());
if (scale == "all")
ri._scale = PathRender::Scale::All;
else if (scale == "none")
ri._scale = PathRender::Scale::None;
}
if (attr.hasAttribute("src"))
file = resourcePath(attr.value("src").toString(), dir);
if (attr.hasAttribute("symbol-height")) {
@ -226,6 +233,13 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
else if (join == "bevel")
ri._strokeJoin = Qt::BevelJoin;
}
if (attr.hasAttribute("scale")) {
QString scale(attr.value("scale").toString());
if (scale == "all")
ri._scale = PathRender::Scale::All;
else if (scale == "none")
ri._scale = PathRender::Scale::None;
}
if (attr.hasAttribute("curve")) {
QString curve(attr.value("curve").toString());
if (curve == "cubic")
@ -656,14 +670,18 @@ QList<const Style::Symbol*> Style::areaSymbols(int zoom) const
QPen Style::PathRender::pen(int zoom) const
{
if (_strokeColor.isValid()) {
qreal width = (zoom >= 12)
qreal width = (_scale > None && zoom >= 12)
? pow(1.5, zoom - 12) * _strokeWidth : _strokeWidth;
QPen p(QBrush(_strokeColor), width, Qt::SolidLine, _strokeCap,
_strokeJoin);
if (!_strokeDasharray.isEmpty()) {
QVector<qreal>pattern(_strokeDasharray);
for (int i = 0; i < _strokeDasharray.size(); i++)
for (int i = 0; i < _strokeDasharray.size(); i++) {
if (_scale > Stroke && zoom >= 12)
pattern[i] = (pow(1.5, zoom - 12) * pattern[i]);
// QPainter pattern is specified in units of the pens width!
pattern[i] /= width;
}
p.setDashPattern(pattern);
}
return p;

View File

@ -136,7 +136,8 @@ public:
public:
PathRender(const Rule &rule, int zOrder) : Render(rule),
_zOrder(zOrder), _strokeWidth(0), _strokeCap(Qt::RoundCap),
_strokeJoin(Qt::RoundJoin), _area(false), _curve(false) {}
_strokeJoin(Qt::RoundJoin), _area(false), _curve(false),
_scale(Stroke) {}
int zOrder() const {return _zOrder;}
QPen pen(int zoom) const;
@ -147,6 +148,8 @@ public:
private:
friend class Style;
enum Scale {None, Stroke, All};
int _zOrder;
QColor _strokeColor;
qreal _strokeWidth;
@ -155,6 +158,7 @@ public:
Qt::PenJoinStyle _strokeJoin;
QBrush _brush;
bool _area, _curve;
Scale _scale;
};
class CircleRender : public Render

View File

@ -2,15 +2,13 @@
#include <QPixmapCache>
#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,32 +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<MapData::Path> paths;
QList<MapData::Point> 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);
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));
}
}
}