mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-30 02:14:23 +02:00
Compare commits
6 Commits
84dc58da71
...
12.4
Author | SHA1 | Date | |
---|---|---|---|
aec052edaf | |||
1bbc57173e | |||
52ea52ff4e | |||
b6ca28e159 | |||
648627b17f | |||
2aa759a4bc |
@ -47,7 +47,7 @@ QList<GraphItem*> CadenceGraph::loadData(const Data &data)
|
||||
const Track &track = data.tracks().at(i);
|
||||
const Graph &graph = track.cadence();
|
||||
|
||||
if (!graph.isValid()) {
|
||||
if (graph.isEmpty()) {
|
||||
_palette.nextColor();
|
||||
graphs.append(0);
|
||||
} else {
|
||||
|
@ -85,7 +85,7 @@ void ElevationGraph::setInfo()
|
||||
GraphItem *ElevationGraph::loadGraph(const Graph &graph, PathType type,
|
||||
const QColor &color, bool primary)
|
||||
{
|
||||
if (!graph.isValid())
|
||||
if (graph.isEmpty())
|
||||
return 0;
|
||||
|
||||
ElevationGraphItem *gi = new ElevationGraphItem(graph, _graphType, _width,
|
||||
|
@ -50,7 +50,7 @@ QList<GraphItem*> GearRatioGraph::loadData(const Data &data)
|
||||
for (int i = 0; i < data.tracks().count(); i++) {
|
||||
const Graph &graph = data.tracks().at(i).ratio();
|
||||
|
||||
if (!graph.isValid()) {
|
||||
if (graph.isEmpty()) {
|
||||
_palette.nextColor();
|
||||
graphs.append(0);
|
||||
} else {
|
||||
|
@ -8,8 +8,6 @@ GraphItem::GraphItem(const Graph &graph, GraphType type, int width,
|
||||
const QColor &color, Qt::PenStyle style, QGraphicsItem *parent)
|
||||
: GraphicsItem(parent), _graph(graph), _type(type), _secondaryGraph(0)
|
||||
{
|
||||
Q_ASSERT(_graph.isValid());
|
||||
|
||||
_units = Metric;
|
||||
_sx = 0; _sy = 0;
|
||||
_color = color;
|
||||
|
@ -47,7 +47,7 @@ QList<GraphItem*> HeartRateGraph::loadData(const Data &data)
|
||||
const Track &track = data.tracks().at(i);
|
||||
const Graph &graph = track.heartRate();
|
||||
|
||||
if (!graph.isValid()) {
|
||||
if (graph.isEmpty()) {
|
||||
_palette.nextColor();
|
||||
graphs.append(0);
|
||||
} else {
|
||||
|
@ -47,7 +47,7 @@ QList<GraphItem*> PowerGraph::loadData(const Data &data)
|
||||
const Track &track = data.tracks().at(i);
|
||||
const Graph &graph = track.power();
|
||||
|
||||
if (!graph.isValid()) {
|
||||
if (graph.isEmpty()) {
|
||||
_palette.nextColor();
|
||||
graphs.append(0);
|
||||
} else {
|
||||
|
@ -50,7 +50,7 @@ void SpeedGraph::setInfo()
|
||||
GraphItem *SpeedGraph::loadGraph(const Graph &graph, const Track &track,
|
||||
const QColor &color, bool primary)
|
||||
{
|
||||
if (!graph.isValid())
|
||||
if (graph.isEmpty())
|
||||
return 0;
|
||||
|
||||
SpeedGraphItem *gi = new SpeedGraphItem(graph, _graphType, _width,
|
||||
|
@ -51,7 +51,7 @@ QList<GraphItem*> TemperatureGraph::loadData(const Data &data)
|
||||
const Track &track = data.tracks().at(i);
|
||||
const Graph &graph = track.temperature();
|
||||
|
||||
if (!graph.isValid()) {
|
||||
if (graph.isEmpty()) {
|
||||
_palette.nextColor();
|
||||
graphs.append(0);
|
||||
} else {
|
||||
|
@ -46,16 +46,6 @@ typedef QVector<GraphPoint> GraphSegment;
|
||||
class Graph : public QList<GraphSegment>
|
||||
{
|
||||
public:
|
||||
bool isValid() const
|
||||
{
|
||||
if (isEmpty())
|
||||
return false;
|
||||
for (int i = 0; i < size(); i++)
|
||||
if (at(i).size() < 2)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hasTime() const
|
||||
{
|
||||
for (int i = 0; i < size(); i++) {
|
||||
|
@ -68,16 +68,14 @@ GraphPair Route::elevation() const
|
||||
{
|
||||
if (_useDEM) {
|
||||
Graph dem(demElevation());
|
||||
if (dem.isValid())
|
||||
return GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
|
||||
else
|
||||
return GraphPair(gpsElevation(), Graph());
|
||||
return (dem.isEmpty())
|
||||
? GraphPair(gpsElevation(), Graph())
|
||||
: GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
|
||||
} else {
|
||||
Graph gps(gpsElevation());
|
||||
if (gps.isValid())
|
||||
return GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
|
||||
else
|
||||
return GraphPair(demElevation(), Graph());
|
||||
return (gps.isEmpty())
|
||||
? GraphPair(demElevation(), Graph())
|
||||
: GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,24 @@ static GraphSegment filter(const GraphSegment &g, int window)
|
||||
}
|
||||
|
||||
|
||||
qreal Track::lastDistance(int seg)
|
||||
{
|
||||
for (int i = seg - 1; i >= 0; i--)
|
||||
if (!_segments.at(i).distance.isEmpty())
|
||||
return _segments.at(i).distance.last();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
qreal Track::lastTime(int seg)
|
||||
{
|
||||
for (int i = seg - 1; i >= 0; i--)
|
||||
if (!_segments.at(i).time.isEmpty())
|
||||
return _segments.at(i).time.last();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Track::Track(const TrackData &data) : _pause(0)
|
||||
{
|
||||
qreal ds, dt;
|
||||
@ -113,11 +131,8 @@ Track::Track(const TrackData &data) : _pause(0)
|
||||
|
||||
Segment &seg = _segments.last();
|
||||
|
||||
seg.distance.append(i && !_segments.at(i-1).distance.isEmpty()
|
||||
? _segments.at(i-1).distance.last() : 0);
|
||||
seg.time.append(i && !_segments.at(i-1).time.isEmpty()
|
||||
? _segments.at(i-1).time.last() :
|
||||
sd.first().hasTimestamp() ? 0 : NAN);
|
||||
seg.distance.append(lastDistance(i));
|
||||
seg.time.append(sd.first().hasTimestamp() ? lastTime(i) : NAN);
|
||||
seg.speed.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||
acceleration.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||
bool hasTime = !std::isnan(seg.time.first());
|
||||
@ -251,7 +266,8 @@ Graph Track::gpsElevation() const
|
||||
sd.at(j).elevation()));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _elevationWindow));
|
||||
if (gs.size() >= 2)
|
||||
ret.append(filter(gs, _elevationWindow));
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -278,7 +294,8 @@ Graph Track::demElevation() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), dem));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _elevationWindow));
|
||||
if (gs.size() >= 2)
|
||||
ret.append(filter(gs, _elevationWindow));
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -291,16 +308,14 @@ GraphPair Track::elevation() const
|
||||
{
|
||||
if (_useDEM) {
|
||||
Graph dem(demElevation());
|
||||
if (dem.isValid())
|
||||
return GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
|
||||
else
|
||||
return GraphPair(gpsElevation(), Graph());
|
||||
return (dem.isEmpty())
|
||||
? GraphPair(gpsElevation(), Graph())
|
||||
: GraphPair(dem, _show2ndElevation ? gpsElevation() : Graph());
|
||||
} else {
|
||||
Graph gps(gpsElevation());
|
||||
if (gps.isValid())
|
||||
return GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
|
||||
else
|
||||
return GraphPair(demElevation(), Graph());
|
||||
return (gps.isEmpty())
|
||||
? GraphPair(demElevation(), Graph())
|
||||
: GraphPair(gps, _show2ndElevation ? demElevation() : Graph());
|
||||
}
|
||||
}
|
||||
|
||||
@ -329,11 +344,13 @@ Graph Track::computedSpeed() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), v));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _speedWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
if (gs.size() >= 2) {
|
||||
ret.append(filter(gs, _speedWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -367,11 +384,13 @@ Graph Track::reportedSpeed() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), v));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _speedWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
if (gs.size() >= 2) {
|
||||
ret.append(filter(gs, _speedWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -384,18 +403,14 @@ GraphPair Track::speed() const
|
||||
{
|
||||
if (_useReportedSpeed) {
|
||||
Graph reported(reportedSpeed());
|
||||
if (reported.isValid())
|
||||
return GraphPair(reported, _show2ndSpeed ? computedSpeed()
|
||||
: Graph());
|
||||
else
|
||||
return GraphPair(computedSpeed(), Graph());
|
||||
return (reported.isEmpty())
|
||||
? GraphPair(computedSpeed(), Graph())
|
||||
: GraphPair(reported, _show2ndSpeed ? computedSpeed() : Graph());
|
||||
} else {
|
||||
Graph computed(computedSpeed());
|
||||
if (computed.isValid())
|
||||
return GraphPair(computed, _show2ndSpeed ? reportedSpeed()
|
||||
: Graph());
|
||||
else
|
||||
return GraphPair(reportedSpeed(), Graph());
|
||||
return (computed.isEmpty())
|
||||
? GraphPair(reportedSpeed(), Graph())
|
||||
: GraphPair(computed, _show2ndSpeed ? reportedSpeed() : Graph());
|
||||
}
|
||||
}
|
||||
|
||||
@ -415,7 +430,8 @@ Graph Track::heartRate() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j),
|
||||
sd.at(j).heartRate()));
|
||||
|
||||
ret.append(filter(gs, _heartRateWindow));
|
||||
if (gs.size() >= 2)
|
||||
ret.append(filter(gs, _heartRateWindow));
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -441,7 +457,8 @@ Graph Track::temperature() const
|
||||
sd.at(j).temperature()));
|
||||
}
|
||||
|
||||
ret.append(gs);
|
||||
if (gs.size() >= 2)
|
||||
ret.append(gs);
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -466,7 +483,8 @@ Graph Track::ratio() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j),
|
||||
sd.at(j).ratio()));
|
||||
|
||||
ret.append(gs);
|
||||
if (gs.size() >= 2)
|
||||
ret.append(gs);
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -500,11 +518,13 @@ Graph Track::cadence() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), c));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _cadenceWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
if (gs.size() >= 2) {
|
||||
ret.append(filter(gs, _cadenceWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
@ -539,11 +559,13 @@ Graph Track::power() const
|
||||
gs.append(GraphPoint(seg.distance.at(j), seg.time.at(j), p));
|
||||
}
|
||||
|
||||
ret.append(filter(gs, _powerWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
if (gs.size() >= 2) {
|
||||
ret.append(filter(gs, _powerWindow));
|
||||
GraphSegment &filtered = ret.last();
|
||||
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
for (int j = 0; j < stop.size(); j++)
|
||||
filtered[stop.at(j)].setY(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
|
@ -63,6 +63,8 @@ private:
|
||||
QSet<int> stop;
|
||||
};
|
||||
|
||||
qreal lastDistance(int seg);
|
||||
qreal lastTime(int seg);
|
||||
bool discardStopPoint(const Segment &seg, int i) const;
|
||||
|
||||
Graph demElevation() const;
|
||||
|
@ -15,42 +15,12 @@ using namespace Mapsforge;
|
||||
#define MD(val) ((val) / 1e6)
|
||||
#define OFFSET_MASK 0x7FFFFFFFFFL
|
||||
|
||||
static quint8 pointType(const QVector<MapData::Tag> &tags)
|
||||
{
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
const MapData::Tag &tag = tags.at(i);
|
||||
if (tag.key == "place") {
|
||||
if (tag.value == "country")
|
||||
return 4;
|
||||
else if (tag.value == "city")
|
||||
return 3;
|
||||
else if (tag.value == "town")
|
||||
return 2;
|
||||
else if (tag.value == "village")
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setPointId(MapData::Point &p)
|
||||
{
|
||||
HASH_T hash = qHash(QPair<double, double>(p.coordinates.lon(),
|
||||
p.coordinates.lat()));
|
||||
quint8 type = pointType(p.tags);
|
||||
|
||||
p.id = ((quint64)type)<<56 | (quint64)hash;
|
||||
}
|
||||
|
||||
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
||||
QSet<MapData::Path> *dst)
|
||||
QList<MapData::Path> *dst)
|
||||
{
|
||||
for (int i = 0; i < src->size(); i++)
|
||||
if (rect.intersects(src->at(i).poly.boundingRect()))
|
||||
dst->insert(src->at(i));
|
||||
dst->append(src->at(i));
|
||||
}
|
||||
|
||||
static void copyPoints(const RectC &rect, const QList<MapData::Point> *src,
|
||||
@ -494,7 +464,7 @@ void MapData::clearTiles()
|
||||
bool MapData::pathCb(VectorTile *tile, void *context)
|
||||
{
|
||||
PathCTX *ctx = (PathCTX*)context;
|
||||
ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->set);
|
||||
ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->list);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -545,10 +515,10 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
copyPoints(rect, cached, list);
|
||||
}
|
||||
|
||||
void MapData::paths(const RectC &rect, int zoom, QSet<Path> *set)
|
||||
void MapData::paths(const RectC &rect, int zoom, QList<Path> *list)
|
||||
{
|
||||
int l(level(zoom));
|
||||
PathCTX ctx(this, rect, zoom, set);
|
||||
PathCTX ctx(this, rect, zoom, list);
|
||||
double min[2], max[2];
|
||||
|
||||
min[0] = rect.left();
|
||||
@ -560,7 +530,7 @@ void MapData::paths(const RectC &rect, int zoom, QSet<Path> *set)
|
||||
}
|
||||
|
||||
void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
QSet<Path> *set)
|
||||
QList<Path> *list)
|
||||
{
|
||||
Key key(tile, zoom);
|
||||
QList<Path> *cached = _pathCache.object(key);
|
||||
@ -568,12 +538,12 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
if (!cached) {
|
||||
QList<Path> *p = new QList<Path>();
|
||||
if (readPaths(tile, zoom, p)) {
|
||||
copyPaths(rect, p, set);
|
||||
copyPaths(rect, p, list);
|
||||
_pathCache.insert(key, p);
|
||||
} else
|
||||
delete p;
|
||||
} else
|
||||
copyPaths(rect, cached, set);
|
||||
copyPaths(rect, cached, list);
|
||||
}
|
||||
|
||||
bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
@ -719,8 +689,6 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
||||
p.tags.append(Tag("ele", QByteArray::number(elevation)));
|
||||
}
|
||||
|
||||
setPointId(p);
|
||||
|
||||
list->append(p);
|
||||
}
|
||||
|
||||
|
@ -41,15 +41,15 @@ public:
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point(const Coordinates &c) : coordinates(c) {}
|
||||
Point(const Coordinates &c) : coordinates(c)
|
||||
{
|
||||
id = (quint64)qHash(QPair<double, double>(c.lon(), c.lat()));
|
||||
}
|
||||
|
||||
quint64 id;
|
||||
Coordinates coordinates;
|
||||
QVector<Tag> tags;
|
||||
int layer;
|
||||
|
||||
bool operator<(const Point &other) const
|
||||
{return id > other.id;}
|
||||
};
|
||||
|
||||
struct Path {
|
||||
@ -74,7 +74,7 @@ public:
|
||||
int tileSize() const {return _tileSize;}
|
||||
|
||||
void points(const RectC &rect, int zoom, QList<Point> *list);
|
||||
void paths(const RectC &rect, int zoom, QSet<Path> *set);
|
||||
void paths(const RectC &rect, int zoom, QList<Path> *set);
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
@ -100,13 +100,13 @@ private:
|
||||
};
|
||||
|
||||
struct PathCTX {
|
||||
PathCTX(MapData *data, const RectC &rect, int zoom, QSet<Path> *set)
|
||||
: data(data), rect(rect), zoom(zoom), set(set) {}
|
||||
PathCTX(MapData *data, const RectC &rect, int zoom, QList<Path> *list)
|
||||
: data(data), rect(rect), zoom(zoom), list(list) {}
|
||||
|
||||
MapData *data;
|
||||
const RectC ▭
|
||||
int zoom;
|
||||
QSet<Path> *set;
|
||||
QList<Path> *list;
|
||||
};
|
||||
|
||||
struct PointCTX {
|
||||
@ -139,7 +139,7 @@ private:
|
||||
|
||||
int level(int zoom) const;
|
||||
void paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
QSet<Path> *set);
|
||||
QList<Path> *list);
|
||||
void points(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
QList<Point> *list);
|
||||
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
|
||||
|
@ -1,8 +1,6 @@
|
||||
#include <QPainter>
|
||||
#include <QCache>
|
||||
#include "common/programpaths.h"
|
||||
#include "map/mapsforgemap.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace Mapsforge;
|
||||
@ -61,15 +59,15 @@ static const QColor *haloColor(const Style::TextRender *ti)
|
||||
? &ti->strokeColor() : 0;
|
||||
}
|
||||
|
||||
|
||||
void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.pointLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.pointSymbols(_zoom));
|
||||
QList<PainterPoint> points;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
MapData::Point &point = _points[i];
|
||||
const MapData::Point &point = _points.at(i);
|
||||
const QByteArray *lbl = 0;
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
@ -92,16 +90,21 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ti && !si)
|
||||
continue;
|
||||
if (ti || si)
|
||||
points.append(PainterPoint(&point, lbl, si, ti));
|
||||
}
|
||||
|
||||
const QImage *img = si ? &si->img() : 0;
|
||||
const QFont *font = ti ? &ti->font() : 0;
|
||||
const QColor *color = ti ? &ti->fillColor() : 0;
|
||||
const QColor *hColor = ti ? haloColor(ti) : 0;
|
||||
std::sort(points.begin(), points.end());
|
||||
|
||||
PointItem *item = new PointItem(ll2xy(point.coordinates).toPoint(),
|
||||
lbl ? new QString(*lbl) : 0, font, img, color, hColor);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const PainterPoint &p = points.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;
|
||||
const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
|
||||
|
||||
PointItem *item = new PointItem(ll2xy(p.p->coordinates).toPoint(),
|
||||
p.lbl, font, img, color, hColor);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
@ -110,16 +113,17 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
|
||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<RenderPath> &renderPaths)
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
|
||||
|
||||
for (int i = 0; i < renderPaths.size(); i++) {
|
||||
RenderPath &path = renderPaths[i];
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
const QByteArray *lbl = 0;
|
||||
|
||||
if (!path.path->closed)
|
||||
continue;
|
||||
@ -127,11 +131,8 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
for (int j = 0; j < labels.size(); j++) {
|
||||
const Style::TextRender *ri = labels.at(j);
|
||||
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||
const QByteArray *lbl;
|
||||
if ((lbl = label(ri->key(), path.path->tags))) {
|
||||
path.label = *lbl;
|
||||
if ((lbl = label(ri->key(), path.path->tags)))
|
||||
ti = ri;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -154,8 +155,8 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
QPointF pos = path.path->labelPos.isNull()
|
||||
? centroid(path.pp) : ll2xy(path.path->labelPos);
|
||||
|
||||
TextPointItem *item = new TextPointItem(pos.toPoint(), &path.label,
|
||||
font, img, color, hColor, 0);
|
||||
PointItem *item = new PointItem(pos.toPoint(), lbl, font, img, color,
|
||||
hColor);
|
||||
if (item->isValid() && _rect.contains(item->boundingRect().toRect())
|
||||
&& !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
@ -165,7 +166,7 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
}
|
||||
|
||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<RenderPath> &renderPaths)
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
|
||||
@ -174,22 +175,22 @@ void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
const Style::TextRender *ri = instructions.at(i);
|
||||
|
||||
for (int i = 0; i < renderPaths.size(); i++) {
|
||||
RenderPath &path = renderPaths[i];
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
const QByteArray *lbl = label(ri->key(), path.path->tags);
|
||||
|
||||
if (!lbl)
|
||||
continue;
|
||||
if (!ri->rule().match(path.path->closed, path.path->tags))
|
||||
continue;
|
||||
bool limit = (ri->key() == "ref");
|
||||
bool limit = (ri->key() == "ref" || ri->key() == "ele"
|
||||
|| ri->key() == "ref_hike" || ri->key() == "ref_cycle"
|
||||
|| ri->key() == "ref_mtb");
|
||||
if (limit && set.contains(*lbl))
|
||||
continue;
|
||||
|
||||
path.label = *lbl;
|
||||
|
||||
TextPathItem *item = new TextPathItem(path.pp, &path.label, _rect,
|
||||
&ri->font(), &ri->fillColor(), haloColor(ri));
|
||||
PathItem *item = new PathItem(path.pp, lbl, _rect, &ri->font(),
|
||||
&ri->fillColor(), haloColor(ri));
|
||||
if (item->isValid() && !item->collides(textItems)) {
|
||||
textItems.append(item);
|
||||
if (limit)
|
||||
@ -237,66 +238,91 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
|
||||
return path;
|
||||
}
|
||||
|
||||
QVector<RasterTile::PathInstruction> RasterTile::pathInstructions(
|
||||
QVector<RenderPath> &renderPaths)
|
||||
void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QCache<Key, QList<const Style::PathRender *> > cache(8192);
|
||||
QVector<PathInstruction> instructions;
|
||||
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::PathRender*> *ri;
|
||||
int i = 0;
|
||||
|
||||
for (QSet<MapData::Path>::const_iterator it = _paths.cbegin();
|
||||
it != _paths.cend(); ++it) {
|
||||
const MapData::Path &path = *it;
|
||||
RenderPath &rp = renderPaths[i];
|
||||
Key key(_zoom, path.closed, path.tags);
|
||||
for (int i = 0; i < _paths.size(); i++) {
|
||||
const MapData::Path &path = _paths.at(i);
|
||||
PainterPath &rp = paths[i];
|
||||
PathKey key(_zoom, path.closed, path.tags);
|
||||
|
||||
rp.path = &path;
|
||||
|
||||
if (!(ri = cache.object(key))) {
|
||||
ri = new QList<const Style::PathRender*>(s.paths(_zoom,
|
||||
path.closed, path.tags));
|
||||
ri = new QList<const Style::PathRender*>(s.paths(_zoom, path.closed,
|
||||
path.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(PathInstruction(ri->at(j), &rp));
|
||||
instructions.append(RenderInstruction(ri->at(j), &rp));
|
||||
cache.insert(key, ri);
|
||||
} else {
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(PathInstruction(ri->at(j), &rp));
|
||||
instructions.append(RenderInstruction(ri->at(j), &rp));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
std::sort(instructions.begin(), instructions.end());
|
||||
|
||||
return instructions;
|
||||
}
|
||||
|
||||
void RasterTile::drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths)
|
||||
void RasterTile::circleInstructions(
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QVector<PathInstruction> instructions(pathInstructions(renderPaths));
|
||||
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::CircleRender*> *ri;
|
||||
|
||||
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))) {
|
||||
ri = new QList<const Style::CircleRender*>(s.circles(_zoom, point.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &point));
|
||||
cache.insert(key, ri);
|
||||
} else {
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
|
||||
{
|
||||
QVector<RenderInstruction> instructions;
|
||||
pathInstructions(paths, instructions);
|
||||
circleInstructions(instructions);
|
||||
std::sort(instructions.begin(), instructions.end());
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
const PathInstruction &is = instructions.at(i);
|
||||
const Style::PathRender *ri = is.render();
|
||||
RenderPath *path = is.path();
|
||||
const RenderInstruction &is = instructions.at(i);
|
||||
PainterPath *path = is.path();
|
||||
|
||||
if (!path->pp.elementCount())
|
||||
path->pp = painterPath(path->path->poly, ri->curve());
|
||||
if (path) {
|
||||
const Style::PathRender *ri = is.pathRender();
|
||||
|
||||
painter->setPen(ri->pen(_zoom));
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawPath(path->pp);
|
||||
if (!path->pp.elementCount())
|
||||
path->pp = painterPath(path->path->poly, ri->curve());
|
||||
|
||||
painter->setPen(ri->pen(_zoom));
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawPath(path->pp);
|
||||
} else {
|
||||
const Style::CircleRender *ri = is.circleRender();
|
||||
qreal radius = ri->radius(_zoom);
|
||||
|
||||
painter->setPen(ri->pen());
|
||||
painter->setBrush(ri->brush());
|
||||
painter->drawEllipse(ll2xy(is.point()->coordinates), radius, radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
std::sort(_points.begin(), _points.end());
|
||||
|
||||
QList<TextItem*> textItems;
|
||||
QVector<RenderPath> renderPaths(_paths.size());
|
||||
QVector<PainterPath> renderPaths(_paths.size());
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
@ -5,19 +5,17 @@
|
||||
#include "map/projection.h"
|
||||
#include "map/transform.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "style.h"
|
||||
#include "mapdata.h"
|
||||
|
||||
class MapsforgeMap;
|
||||
class TextItem;
|
||||
|
||||
namespace Mapsforge {
|
||||
|
||||
class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform, int zoom,
|
||||
const QRect &rect, qreal ratio, const QSet<MapData::Path> &paths,
|
||||
const QRect &rect, qreal ratio, const QList<MapData::Path> &paths,
|
||||
const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
|
||||
_zoom(zoom), _rect(rect), _ratio(ratio),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
|
||||
@ -31,41 +29,77 @@ public:
|
||||
void render();
|
||||
|
||||
private:
|
||||
struct RenderPath {
|
||||
RenderPath() : path(0) {}
|
||||
struct PainterPath {
|
||||
PainterPath() : path(0) {}
|
||||
|
||||
QPainterPath pp;
|
||||
QString label;
|
||||
const MapData::Path *path;
|
||||
};
|
||||
|
||||
class PathInstruction
|
||||
{
|
||||
public:
|
||||
PathInstruction() : _render(0), _path(0) {}
|
||||
PathInstruction(const Style::PathRender *render, RenderPath *path)
|
||||
: _render(render), _path(path) {}
|
||||
|
||||
bool operator<(const PathInstruction &other) const
|
||||
struct PainterPoint {
|
||||
PainterPoint(const MapData::Point *p, const QByteArray *lbl,
|
||||
const Style::Symbol *si, const Style::TextRender *ti)
|
||||
: p(p), lbl(lbl), ti(ti), si(si)
|
||||
{
|
||||
if (_path->path->layer == other._path->path->layer)
|
||||
return _render->zOrder() < other._render->zOrder();
|
||||
else
|
||||
return (_path->path->layer < other._path->path->layer);
|
||||
Q_ASSERT(si || ti);
|
||||
}
|
||||
|
||||
const Style::PathRender *render() const {return _render;}
|
||||
RenderPath *path() const {return _path;}
|
||||
bool operator<(const PainterPoint &other) const
|
||||
{
|
||||
if (priority() == other.priority())
|
||||
return p->id < other.p->id;
|
||||
else
|
||||
return (priority() > other.priority());
|
||||
}
|
||||
int priority() const {return si ? si->priority() : ti->priority();}
|
||||
|
||||
private:
|
||||
const Style::PathRender *_render;
|
||||
RenderPath *_path;
|
||||
const MapData::Point *p;
|
||||
const QByteArray *lbl;
|
||||
const Style::TextRender *ti;
|
||||
const Style::Symbol *si;
|
||||
};
|
||||
|
||||
struct Key {
|
||||
Key(int zoom, bool closed, const QVector<MapData::Tag> &tags)
|
||||
class RenderInstruction
|
||||
{
|
||||
public:
|
||||
RenderInstruction() : _pathRender(0), _circleRender(0), _path(0),
|
||||
_point(0) {}
|
||||
RenderInstruction(const Style::PathRender *render, PainterPath *path)
|
||||
: _pathRender(render), _circleRender(0), _path(path), _point(0) {}
|
||||
RenderInstruction(const Style::CircleRender *render,
|
||||
const MapData::Point *point) : _pathRender(0), _circleRender(render),
|
||||
_path(0), _point(point) {}
|
||||
|
||||
bool operator<(const RenderInstruction &other) const
|
||||
{
|
||||
if (layer() == other.layer())
|
||||
return zOrder() < other.zOrder();
|
||||
else
|
||||
return (layer() < other.layer());
|
||||
}
|
||||
|
||||
const Style::PathRender *pathRender() const {return _pathRender;}
|
||||
const Style::CircleRender *circleRender() const {return _circleRender;}
|
||||
PainterPath *path() const {return _path;}
|
||||
const MapData::Point *point() const {return _point;}
|
||||
|
||||
private:
|
||||
int layer() const {return _path ? _path->path->layer : _point->layer;}
|
||||
int zOrder() const
|
||||
{
|
||||
return _pathRender ? _pathRender->zOrder() : _circleRender->zOrder();
|
||||
}
|
||||
|
||||
const Style::PathRender *_pathRender;
|
||||
const Style::CircleRender *_circleRender;
|
||||
PainterPath *_path;
|
||||
const MapData::Point *_point;
|
||||
};
|
||||
|
||||
struct PathKey {
|
||||
PathKey(int zoom, bool closed, const QVector<MapData::Tag> &tags)
|
||||
: zoom(zoom), closed(closed), tags(tags) {}
|
||||
bool operator==(const Key &other) const
|
||||
bool operator==(const PathKey &other) const
|
||||
{
|
||||
return zoom == other.zoom && closed == other.closed
|
||||
&& tags == other.tags;
|
||||
@ -76,32 +110,54 @@ private:
|
||||
const QVector<MapData::Tag> &tags;
|
||||
};
|
||||
|
||||
struct PointKey {
|
||||
PointKey(int zoom, const QVector<MapData::Tag> &tags)
|
||||
: zoom(zoom), tags(tags) {}
|
||||
bool operator==(const PointKey &other) const
|
||||
{
|
||||
return zoom == other.zoom && tags == other.tags;
|
||||
}
|
||||
|
||||
int zoom;
|
||||
const QVector<MapData::Tag> &tags;
|
||||
};
|
||||
|
||||
class PointItem : public TextPointItem
|
||||
{
|
||||
public:
|
||||
PointItem(const QPoint &point, QString *text, const QFont *font,
|
||||
const QImage *img, const QColor *color, const QColor *haloColor)
|
||||
: TextPointItem(point, text, font, img, color, haloColor, 0),
|
||||
_label(text) {}
|
||||
~PointItem() {delete _label;}
|
||||
|
||||
private:
|
||||
QString *_label;
|
||||
PointItem(const QPoint &point, const QByteArray *label,
|
||||
const QFont *font, const QImage *img, const QColor *color,
|
||||
const QColor *haloColor) : TextPointItem(point,
|
||||
label ? new QString(*label) : 0, font, img, color, haloColor, 0) {}
|
||||
~PointItem() {delete _text;}
|
||||
};
|
||||
|
||||
friend HASH_T qHash(const RasterTile::Key &key);
|
||||
class PathItem : public TextPathItem
|
||||
{
|
||||
public:
|
||||
PathItem(const QPainterPath &line, const QByteArray *label,
|
||||
const QRect &tileRect, const QFont *font, const QColor *color,
|
||||
const QColor *haloColor) : TextPathItem(line,
|
||||
label ? new QString(*label) : 0, tileRect, font, color, haloColor) {}
|
||||
~PathItem() {delete _text;}
|
||||
};
|
||||
|
||||
QVector<PathInstruction> pathInstructions(QVector<RenderPath> &renderPaths);
|
||||
friend HASH_T qHash(const RasterTile::PathKey &key);
|
||||
friend HASH_T qHash(const RasterTile::PointKey &key);
|
||||
|
||||
void pathInstructions(QVector<PainterPath> &paths,
|
||||
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 processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<RenderPath> &renderPaths);
|
||||
QVector<PainterPath> &paths);
|
||||
void processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<RenderPath> &renderPaths);
|
||||
QVector<PainterPath> &paths);
|
||||
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
void drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths);
|
||||
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
@ -109,13 +165,18 @@ private:
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
QPixmap _pixmap;
|
||||
QSet<MapData::Path> _paths;
|
||||
QList<MapData::Path> _paths;
|
||||
QList<MapData::Point> _points;
|
||||
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
inline HASH_T qHash(const RasterTile::Key &key)
|
||||
inline HASH_T qHash(const RasterTile::PathKey &key)
|
||||
{
|
||||
return ::qHash(key.zoom) ^ ::qHash(key.tags);
|
||||
}
|
||||
|
||||
inline HASH_T qHash(const RasterTile::PointKey &key)
|
||||
{
|
||||
return ::qHash(key.zoom) ^ ::qHash(key.tags);
|
||||
}
|
||||
|
@ -79,10 +79,24 @@ bool Style::Rule::match(int zoom, bool closed,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Style::Rule::match(int zoom, const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
if (_type && NodeType != _type)
|
||||
return false;
|
||||
if (!_zooms.contains(zoom))
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < _filters.size(); i++)
|
||||
if (!_filters.at(i).match(tags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule)
|
||||
{
|
||||
PathRender ri(rule, _paths.size());
|
||||
PathRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
QString file;
|
||||
int height = 0, width = 0;
|
||||
@ -127,7 +141,7 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
|
||||
void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
{
|
||||
PathRender ri(rule, _paths.size());
|
||||
PathRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool ok;
|
||||
|
||||
@ -180,6 +194,49 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::circle(QXmlStreamReader &reader, const Rule &rule)
|
||||
{
|
||||
CircleRender ri(rule, _paths.size() + _circles.size());
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool ok;
|
||||
QColor fillColor, strokeColor;
|
||||
qreal strokeWidth = 0;
|
||||
|
||||
if (attr.hasAttribute("fill"))
|
||||
fillColor = QColor(attr.value("fill").toString());
|
||||
if (attr.hasAttribute("stroke"))
|
||||
strokeColor = QColor(attr.value("stroke").toString());
|
||||
if (attr.hasAttribute("stroke-width")) {
|
||||
strokeWidth = attr.value("stroke-width").toFloat(&ok);
|
||||
if (!ok || strokeWidth < 0) {
|
||||
reader.raiseError("invalid stroke-width value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("radius")) {
|
||||
ri._radius = attr.value("radius").toDouble(&ok);
|
||||
if (!ok || ri._radius <= 0) {
|
||||
reader.raiseError("invalid radius value");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
reader.raiseError("missing radius");
|
||||
return;
|
||||
}
|
||||
if (attr.hasAttribute("scale-radius")) {
|
||||
if (attr.value("scale-radius").toString() == "true")
|
||||
ri._scale = true;
|
||||
}
|
||||
|
||||
ri._pen = (strokeColor.isValid() && strokeWidth > 0)
|
||||
? QPen(QBrush(strokeColor), strokeWidth) : Qt::NoPen;
|
||||
ri._brush = fillColor.isValid() ? QBrush(fillColor) : Qt::NoBrush;
|
||||
|
||||
_circles.append(ri);
|
||||
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
QList<QList<TextRender>*> &lists)
|
||||
{
|
||||
@ -238,6 +295,13 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
else if (transform == "capitalize")
|
||||
capitalization = QFont::Capitalize;
|
||||
}
|
||||
if (attr.hasAttribute("priority")) {
|
||||
ri._priority = attr.value("priority").toInt(&ok);
|
||||
if (!ok) {
|
||||
reader.raiseError("invalid priority value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ri._font.setFamily(fontFamily);
|
||||
ri._font.setPixelSize(fontSize);
|
||||
@ -277,6 +341,13 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("priority")) {
|
||||
ri._priority = attr.value("priority").toInt(&ok);
|
||||
if (!ok) {
|
||||
reader.raiseError("invalid priority value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.isNull())
|
||||
ri._img = image(file, width, height, ratio);
|
||||
@ -337,6 +408,8 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
area(reader, dir, ratio, r);
|
||||
else if (reader.name() == QLatin1String("line"))
|
||||
line(reader, r);
|
||||
else if (reader.name() == QLatin1String("circle"))
|
||||
circle(reader, r);
|
||||
else if (reader.name() == QLatin1String("pathText")) {
|
||||
QList<QList<TextRender>*> list;
|
||||
list.append(&_pathLabels);
|
||||
@ -444,6 +517,18 @@ QList<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||
return ri;
|
||||
}
|
||||
|
||||
QList<const Style::CircleRender *> Style::circles(int zoom,
|
||||
const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
QList<const CircleRender*> ri;
|
||||
|
||||
for (int i = 0; i < _circles.size(); i++)
|
||||
if (_circles.at(i).rule().match(zoom, tags))
|
||||
ri.append(&_circles.at(i));
|
||||
|
||||
return ri;
|
||||
}
|
||||
|
||||
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
|
||||
{
|
||||
QList<const TextRender*> list;
|
||||
@ -535,3 +620,8 @@ QBrush Style::PathRender::brush() const
|
||||
else
|
||||
return Qt::NoBrush;
|
||||
}
|
||||
|
||||
qreal Style::CircleRender::radius(int zoom) const
|
||||
{
|
||||
return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _radius : _radius;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
bool match(bool closed, const QVector<MapData::Tag> &tags) const;
|
||||
bool match(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
bool match(int zoom, const QVector<MapData::Tag> &tags) const;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
@ -184,22 +185,46 @@ public:
|
||||
bool _area, _curve;
|
||||
};
|
||||
|
||||
class CircleRender : public Render
|
||||
{
|
||||
public:
|
||||
CircleRender(const Rule &rule, int zOrder) : Render(rule),
|
||||
_zOrder(zOrder), _pen(Qt::NoPen), _brush(Qt::NoBrush),
|
||||
_scale(false) {}
|
||||
|
||||
int zOrder() const {return _zOrder;}
|
||||
const QPen &pen() const {return _pen;}
|
||||
const QBrush &brush() const {return _brush;}
|
||||
qreal radius(int zoom) const;
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _zOrder;
|
||||
QPen _pen;
|
||||
QBrush _brush;
|
||||
qreal _radius;
|
||||
bool _scale;
|
||||
};
|
||||
|
||||
class TextRender : public Render
|
||||
{
|
||||
public:
|
||||
TextRender(const Rule &rule)
|
||||
: Render(rule), _fillColor(Qt::black), _strokeColor(Qt::black),
|
||||
_strokeWidth(0) {}
|
||||
: Render(rule), _priority(0), _fillColor(Qt::black),
|
||||
_strokeColor(Qt::black), _strokeWidth(0) {}
|
||||
|
||||
const QFont &font() const {return _font;}
|
||||
const QColor &fillColor() const {return _fillColor;}
|
||||
const QColor &strokeColor() const {return _strokeColor;}
|
||||
qreal strokeWidth() const {return _strokeWidth;}
|
||||
const QByteArray &key() const {return _key;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _priority;
|
||||
QColor _fillColor, _strokeColor;
|
||||
qreal _strokeWidth;
|
||||
QFont _font;
|
||||
@ -209,13 +234,15 @@ public:
|
||||
class Symbol : public Render
|
||||
{
|
||||
public:
|
||||
Symbol(const Rule &rule) : Render(rule) {}
|
||||
Symbol(const Rule &rule) : Render(rule), _priority(0) {}
|
||||
|
||||
const QImage &img() const {return _img;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
int _priority;
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
@ -223,6 +250,8 @@ public:
|
||||
|
||||
QList<const PathRender *> paths(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
QList<const CircleRender *> circles(int zoom,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
QList<const TextRender*> pathLabels(int zoom) const;
|
||||
QList<const TextRender*> pointLabels(int zoom) const;
|
||||
QList<const TextRender*> areaLabels(int zoom) const;
|
||||
@ -231,6 +260,7 @@ public:
|
||||
|
||||
private:
|
||||
QList<PathRender> _paths;
|
||||
QList<CircleRender> _circles;
|
||||
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
||||
QList<Symbol> _symbols;
|
||||
|
||||
@ -244,6 +274,7 @@ private:
|
||||
void area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule);
|
||||
void line(QXmlStreamReader &reader, const Rule &rule);
|
||||
void circle(QXmlStreamReader &reader, const Rule &rule);
|
||||
void text(QXmlStreamReader &reader, const Rule &rule,
|
||||
QList<QList<TextRender> *> &lists);
|
||||
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
|
@ -175,7 +175,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
||||
painter->drawPixmap(ttl, pm);
|
||||
else {
|
||||
QSet<MapData::Path> paths;
|
||||
QList<MapData::Path> paths;
|
||||
QList<MapData::Point> points;
|
||||
|
||||
/* Add a "sub-pixel" margin to assure the tile areas do not
|
||||
|
Reference in New Issue
Block a user