mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added hillshading to vector maps
This commit is contained in:
parent
f21a155f79
commit
cf86fb7557
@ -376,7 +376,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- hillshading -->
|
<!-- hillshading -->
|
||||||
<hillshading />
|
<hillshading zoom-min="10" zoom-max="16"/>
|
||||||
|
|
||||||
|
|
||||||
<!-- buildings -->
|
<!-- buildings -->
|
||||||
|
@ -230,6 +230,7 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/mapsforgemap.h \
|
src/map/mapsforgemap.h \
|
||||||
src/map/worldfilemap.h \
|
src/map/worldfilemap.h \
|
||||||
src/map/imgmap.h \
|
src/map/imgmap.h \
|
||||||
|
src/map/hillshading.h \
|
||||||
src/data/itnparser.h \
|
src/data/itnparser.h \
|
||||||
src/data/link.h \
|
src/data/link.h \
|
||||||
src/data/onmoveparsers.h \
|
src/data/onmoveparsers.h \
|
||||||
@ -435,6 +436,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/aqmmap.cpp \
|
src/map/aqmmap.cpp \
|
||||||
src/map/mapsforgemap.cpp \
|
src/map/mapsforgemap.cpp \
|
||||||
src/map/worldfilemap.cpp \
|
src/map/worldfilemap.cpp \
|
||||||
|
src/map/hillshading.cpp \
|
||||||
src/data/address.cpp \
|
src/data/address.cpp \
|
||||||
src/data/itnparser.cpp \
|
src/data/itnparser.cpp \
|
||||||
src/data/onmoveparsers.cpp \
|
src/data/onmoveparsers.cpp \
|
||||||
|
@ -461,6 +461,11 @@ void GUI::createActions()
|
|||||||
_showDEMTilesAction = new QAction(tr("Show local DEM tiles"), this);
|
_showDEMTilesAction = new QAction(tr("Show local DEM tiles"), this);
|
||||||
_showDEMTilesAction->setMenuRole(QAction::NoRole);
|
_showDEMTilesAction->setMenuRole(QAction::NoRole);
|
||||||
connect(_showDEMTilesAction, &QAction::triggered, this, &GUI::showDEMTiles);
|
connect(_showDEMTilesAction, &QAction::triggered, this, &GUI::showDEMTiles);
|
||||||
|
_drawHillShadingAction = new QAction(tr("Show hillshading"), this);
|
||||||
|
_drawHillShadingAction->setMenuRole(QAction::NoRole);
|
||||||
|
_drawHillShadingAction->setCheckable(true);
|
||||||
|
connect(_drawHillShadingAction, &QAction::triggered, _mapView,
|
||||||
|
&MapView::drawHillShading);
|
||||||
|
|
||||||
// Graph actions
|
// Graph actions
|
||||||
_showGraphsAction = new QAction(QIcon::fromTheme(SHOW_GRAPHS_NAME,
|
_showGraphsAction = new QAction(QIcon::fromTheme(SHOW_GRAPHS_NAME,
|
||||||
@ -711,6 +716,8 @@ void GUI::createMenus()
|
|||||||
QMenu *demMenu = menuBar()->addMenu(tr("DEM"));
|
QMenu *demMenu = menuBar()->addMenu(tr("DEM"));
|
||||||
demMenu->addAction(_showDEMTilesAction);
|
demMenu->addAction(_showDEMTilesAction);
|
||||||
demMenu->addAction(_downloadDEMAction);
|
demMenu->addAction(_downloadDEMAction);
|
||||||
|
demMenu->addSeparator();
|
||||||
|
demMenu->addAction(_drawHillShadingAction);
|
||||||
|
|
||||||
QMenu *positionMenu = menuBar()->addMenu(tr("Position"));
|
QMenu *positionMenu = menuBar()->addMenu(tr("Position"));
|
||||||
positionMenu->addAction(_showPositionCoordinatesAction);
|
positionMenu->addAction(_showPositionCoordinatesAction);
|
||||||
@ -2499,6 +2506,11 @@ void GUI::writeSettings()
|
|||||||
WRITE(useStyles, _useStylesAction->isChecked());
|
WRITE(useStyles, _useStylesAction->isChecked());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
/* DEM */
|
||||||
|
settings.beginGroup(SETTINGS_DEM);
|
||||||
|
WRITE(drawHillShading, _drawHillShadingAction->isChecked());
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
/* Position */
|
/* Position */
|
||||||
settings.beginGroup(SETTINGS_POSITION);
|
settings.beginGroup(SETTINGS_POSITION);
|
||||||
WRITE(showPosition, _showPositionAction->isChecked());
|
WRITE(showPosition, _showPositionAction->isChecked());
|
||||||
@ -2781,6 +2793,14 @@ void GUI::readSettings(QString &activeMap, QStringList &disabledPOIs,
|
|||||||
_hideMarkersAction->setChecked(true);
|
_hideMarkersAction->setChecked(true);
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
/* DEM */
|
||||||
|
settings.beginGroup(SETTINGS_DEM);
|
||||||
|
if (READ(drawHillShading).toBool()) {
|
||||||
|
_drawHillShadingAction->setChecked(true);
|
||||||
|
_mapView->drawHillShading(true);
|
||||||
|
}
|
||||||
|
settings.endGroup();
|
||||||
|
|
||||||
/* Position */
|
/* Position */
|
||||||
settings.beginGroup(SETTINGS_POSITION);
|
settings.beginGroup(SETTINGS_POSITION);
|
||||||
if (READ(showPosition).toBool()) {
|
if (READ(showPosition).toBool()) {
|
||||||
|
@ -291,6 +291,7 @@ private:
|
|||||||
QAction *_openOptionsAction;
|
QAction *_openOptionsAction;
|
||||||
QAction *_downloadDEMAction;
|
QAction *_downloadDEMAction;
|
||||||
QAction *_showDEMTilesAction;
|
QAction *_showDEMTilesAction;
|
||||||
|
QAction *_drawHillShadingAction;
|
||||||
QAction *_mapsEnd;
|
QAction *_mapsEnd;
|
||||||
QAction *_poisEnd;
|
QAction *_poisEnd;
|
||||||
#ifndef Q_OS_ANDROID
|
#ifndef Q_OS_ANDROID
|
||||||
|
@ -64,6 +64,7 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent)
|
|||||||
_outputProjection = PCS::pcs(3857);
|
_outputProjection = PCS::pcs(3857);
|
||||||
_inputProjection = GCS::gcs(4326);
|
_inputProjection = GCS::gcs(4326);
|
||||||
_hidpi = true;
|
_hidpi = true;
|
||||||
|
_hillShading = false;
|
||||||
_map = map;
|
_map = map;
|
||||||
_map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
|
_map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
|
||||||
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
|
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
|
||||||
@ -1114,6 +1115,8 @@ void MapView::drawBackground(QPainter *painter, const QRectF &rect)
|
|||||||
flags = Map::Block;
|
flags = Map::Block;
|
||||||
else if (_opengl)
|
else if (_opengl)
|
||||||
flags = Map::OpenGL;
|
flags = Map::OpenGL;
|
||||||
|
if (_hillShading)
|
||||||
|
flags |= Map::HillShading;
|
||||||
|
|
||||||
_map->draw(painter, ir, flags);
|
_map->draw(painter, ir, flags);
|
||||||
}
|
}
|
||||||
@ -1178,7 +1181,9 @@ void MapView::mouseMoveEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
if (_cursorCoordinates->isVisible()) {
|
if (_cursorCoordinates->isVisible()) {
|
||||||
Coordinates c(_map->xy2ll(mapToScene(event->pos())));
|
Coordinates c(_map->xy2ll(mapToScene(event->pos())));
|
||||||
|
DEM::lock();
|
||||||
_cursorCoordinates->setCoordinates(c, DEM::elevation(c));
|
_cursorCoordinates->setCoordinates(c, DEM::elevation(c));
|
||||||
|
DEM::unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
QGraphicsView::mouseMoveEvent(event);
|
QGraphicsView::mouseMoveEvent(event);
|
||||||
@ -1244,6 +1249,13 @@ void MapView::useAntiAliasing(bool use)
|
|||||||
setRenderHint(QPainter::Antialiasing, use);
|
setRenderHint(QPainter::Antialiasing, use);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MapView::drawHillShading(bool draw)
|
||||||
|
{
|
||||||
|
_hillShading = draw;
|
||||||
|
|
||||||
|
setMap(_map);
|
||||||
|
}
|
||||||
|
|
||||||
void MapView::useStyles(bool use)
|
void MapView::useStyles(bool use)
|
||||||
{
|
{
|
||||||
GraphicsItem::useStyle(use);
|
GraphicsItem::useStyle(use);
|
||||||
|
@ -128,6 +128,7 @@ public slots:
|
|||||||
void followPosition(bool follow);
|
void followPosition(bool follow);
|
||||||
void showMotionInfo(bool show);
|
void showMotionInfo(bool show);
|
||||||
void useStyles(bool use);
|
void useStyles(bool use);
|
||||||
|
void drawHillShading(bool draw);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updatePOI();
|
void updatePOI();
|
||||||
@ -206,6 +207,8 @@ private:
|
|||||||
qreal _areaOpacity;
|
qreal _areaOpacity;
|
||||||
bool _infoBackground;
|
bool _infoBackground;
|
||||||
|
|
||||||
|
bool _hillShading;
|
||||||
|
|
||||||
int _digitalZoom;
|
int _digitalZoom;
|
||||||
bool _plot;
|
bool _plot;
|
||||||
QCursor _cursor;
|
QCursor _cursor;
|
||||||
|
@ -173,6 +173,9 @@ SETTING(positionMarkers, "positionMarkers", true );
|
|||||||
SETTING(markerInfo, "markerInfo", MarkerInfoItem::None );
|
SETTING(markerInfo, "markerInfo", MarkerInfoItem::None );
|
||||||
SETTING(useStyles, "styles", true );
|
SETTING(useStyles, "styles", true );
|
||||||
|
|
||||||
|
/* DEM */
|
||||||
|
SETTING(drawHillShading, "hillshading", true );
|
||||||
|
|
||||||
/* Position */
|
/* Position */
|
||||||
SETTING(showPosition, "show", false );
|
SETTING(showPosition, "show", false );
|
||||||
SETTING(followPosition, "follow", true );
|
SETTING(followPosition, "follow", true );
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#define SETTINGS_GRAPH "Graph"
|
#define SETTINGS_GRAPH "Graph"
|
||||||
#define SETTINGS_POI "POI"
|
#define SETTINGS_POI "POI"
|
||||||
#define SETTINGS_DATA "Data"
|
#define SETTINGS_DATA "Data"
|
||||||
|
#define SETTINGS_DEM "DEM"
|
||||||
#define SETTINGS_POSITION "Position"
|
#define SETTINGS_POSITION "Position"
|
||||||
#define SETTINGS_PDF_EXPORT "Export"
|
#define SETTINGS_PDF_EXPORT "Export"
|
||||||
#define SETTINGS_PNG_EXPORT "PNGExport"
|
#define SETTINGS_PNG_EXPORT "PNGExport"
|
||||||
@ -124,6 +125,9 @@ public:
|
|||||||
static const Setting markerInfo;
|
static const Setting markerInfo;
|
||||||
static const Setting useStyles;
|
static const Setting useStyles;
|
||||||
|
|
||||||
|
/* DEM */
|
||||||
|
static const Setting drawHillShading;
|
||||||
|
|
||||||
/* Position */
|
/* Position */
|
||||||
static const Setting showPosition;
|
static const Setting showPosition;
|
||||||
static const Setting followPosition;
|
static const Setting followPosition;
|
||||||
|
@ -25,11 +25,11 @@ ToolTip WaypointItem::info() const
|
|||||||
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
|
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
|
||||||
tt.insert(qApp->translate("WaypointItem", "Coordinates"),
|
tt.insert(qApp->translate("WaypointItem", "Coordinates"),
|
||||||
Format::coordinates(_waypoint.coordinates(), _format));
|
Format::coordinates(_waypoint.coordinates(), _format));
|
||||||
if (!std::isnan(_waypoint.elevations().first)) {
|
QPair<qreal, qreal> elevations(_waypoint.elevations());
|
||||||
QString val = Format::elevation(_waypoint.elevations().first, _units);
|
if (!std::isnan(elevations.first)) {
|
||||||
if (!std::isnan(_waypoint.elevations().second))
|
QString val = Format::elevation(elevations.first, _units);
|
||||||
val += " (" + Format::elevation(_waypoint.elevations().second,
|
if (!std::isnan(elevations.second))
|
||||||
_units) + ")";
|
val += " (" + Format::elevation(elevations.second, _units) + ")";
|
||||||
tt.insert(qApp->translate("WaypointItem", "Elevation"), val);
|
tt.insert(qApp->translate("WaypointItem", "Elevation"), val);
|
||||||
}
|
}
|
||||||
if (_waypoint.timestamp().isValid())
|
if (_waypoint.timestamp().isValid())
|
||||||
|
@ -69,6 +69,8 @@ static qreal height(const Coordinates &c, const QByteArray *data)
|
|||||||
return interpolate(dx, dy, p0, p1, p2, p3);
|
return interpolate(dx, dy, p0, p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMutex DEM::_lock;
|
||||||
|
|
||||||
QString DEM::Tile::latStr() const
|
QString DEM::Tile::latStr() const
|
||||||
{
|
{
|
||||||
const char ns = (_lat >= 0) ? 'N' : 'S';
|
const char ns = (_lat >= 0) ? 'N' : 'S';
|
||||||
|
@ -4,12 +4,11 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QCache>
|
#include <QCache>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
|
#include <QMutex>
|
||||||
#include "common/hash.h"
|
#include "common/hash.h"
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
|
||||||
class QString;
|
|
||||||
class Coordinates;
|
class Coordinates;
|
||||||
class RectC;
|
|
||||||
|
|
||||||
class DEM
|
class DEM
|
||||||
{
|
{
|
||||||
@ -37,7 +36,10 @@ public:
|
|||||||
static void setCacheSize(int size);
|
static void setCacheSize(int size);
|
||||||
static void setDir(const QString &path);
|
static void setDir(const QString &path);
|
||||||
static void clearCache();
|
static void clearCache();
|
||||||
|
|
||||||
static qreal elevation(const Coordinates &c);
|
static qreal elevation(const Coordinates &c);
|
||||||
|
static void lock() {_lock.lock();}
|
||||||
|
static void unlock() {_lock.unlock();}
|
||||||
|
|
||||||
static QList<Area> tiles();
|
static QList<Area> tiles();
|
||||||
|
|
||||||
@ -48,6 +50,7 @@ private:
|
|||||||
|
|
||||||
static QString _dir;
|
static QString _dir;
|
||||||
static TileCache _data;
|
static TileCache _data;
|
||||||
|
static QMutex _lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline HASH_T qHash(const DEM::Tile &tile)
|
inline HASH_T qHash(const DEM::Tile &tile)
|
||||||
|
@ -55,11 +55,13 @@ Graph Route::demElevation() const
|
|||||||
QDateTime date;
|
QDateTime date;
|
||||||
GraphSegment gs(date);
|
GraphSegment gs(date);
|
||||||
|
|
||||||
|
DEM::lock();
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
qreal dem = DEM::elevation(_data.at(i).coordinates());
|
qreal dem = DEM::elevation(_data.at(i).coordinates());
|
||||||
if (!std::isnan(dem))
|
if (!std::isnan(dem))
|
||||||
gs.append(GraphPoint(_distance.at(i), NAN, dem));
|
gs.append(GraphPoint(_distance.at(i), NAN, dem));
|
||||||
}
|
}
|
||||||
|
DEM::unlock();
|
||||||
|
|
||||||
if (gs.size() >= 2)
|
if (gs.size() >= 2)
|
||||||
graph.append(gs);
|
graph.append(gs);
|
||||||
|
@ -281,6 +281,7 @@ Graph Track::demElevation() const
|
|||||||
{
|
{
|
||||||
Graph ret;
|
Graph ret;
|
||||||
|
|
||||||
|
DEM::lock();
|
||||||
for (int i = 0; i < _data.size(); i++) {
|
for (int i = 0; i < _data.size(); i++) {
|
||||||
const SegmentData &sd = _data.at(i);
|
const SegmentData &sd = _data.at(i);
|
||||||
if (sd.size() < 2)
|
if (sd.size() < 2)
|
||||||
@ -298,6 +299,7 @@ Graph Track::demElevation() const
|
|||||||
if (gs.size() >= 2)
|
if (gs.size() >= 2)
|
||||||
ret.append(filter(gs, _elevationWindow));
|
ret.append(filter(gs, _elevationWindow));
|
||||||
}
|
}
|
||||||
|
DEM::unlock();
|
||||||
|
|
||||||
if (_data.style().color().isValid())
|
if (_data.style().color().isValid())
|
||||||
ret.setColor(_data.style().color());
|
ret.setColor(_data.style().color());
|
||||||
|
@ -10,17 +10,21 @@ QHash<QString, QPixmap> Waypoint::_symbolIcons;
|
|||||||
QPair<qreal, qreal> Waypoint::elevations() const
|
QPair<qreal, qreal> Waypoint::elevations() const
|
||||||
{
|
{
|
||||||
if (_useDEM) {
|
if (_useDEM) {
|
||||||
|
DEM::lock();
|
||||||
qreal dem = DEM::elevation(coordinates());
|
qreal dem = DEM::elevation(coordinates());
|
||||||
|
DEM::unlock();
|
||||||
if (!std::isnan(dem))
|
if (!std::isnan(dem))
|
||||||
return QPair<qreal, qreal>(dem, _show2ndElevation ? elevation()
|
return QPair<qreal, qreal>(dem, _show2ndElevation ? elevation()
|
||||||
: NAN);
|
: NAN);
|
||||||
else
|
else
|
||||||
return QPair<qreal, qreal>(elevation(), NAN);
|
return QPair<qreal, qreal>(elevation(), NAN);
|
||||||
} else {
|
} else {
|
||||||
if (hasElevation())
|
if (hasElevation()) {
|
||||||
return QPair<qreal, qreal>(elevation(), _show2ndElevation
|
DEM::lock();
|
||||||
? DEM::elevation(coordinates()) : NAN);
|
qreal dem = _show2ndElevation ? DEM::elevation(coordinates()) : NAN;
|
||||||
else
|
DEM::unlock();
|
||||||
|
return QPair<qreal, qreal>(elevation(), dem);
|
||||||
|
} else
|
||||||
return QPair<qreal, qreal>(DEM::elevation(coordinates()), NAN);
|
return QPair<qreal, qreal>(DEM::elevation(coordinates()), NAN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
#include "map/textpointitem.h"
|
#include "map/textpointitem.h"
|
||||||
#include "map/bitmapline.h"
|
#include "map/bitmapline.h"
|
||||||
#include "map/rectd.h"
|
#include "map/rectd.h"
|
||||||
|
#include "map/hillshading.h"
|
||||||
|
#include "data/dem.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "lblfile.h"
|
#include "lblfile.h"
|
||||||
#include "rastertile.h"
|
#include "rastertile.h"
|
||||||
@ -292,10 +294,10 @@ void RasterTile::processStreetNames(const QList<MapData::Poly> &lines,
|
|||||||
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const QFont *fnt = _data->style()->font(style.textFontSize(),
|
const QFont *fnt = _data->style()->font(style.text().size(),
|
||||||
Style::Small);
|
Style::Small);
|
||||||
const QColor *color = style.textColor().isValid()
|
const QColor *color = style.text().color().isValid()
|
||||||
? &style.textColor() : 0;
|
? &style.text().color() : 0;
|
||||||
const QColor *hColor = Style::isContourLine(poly.type) ? 0 : &haloColor;
|
const QColor *hColor = Style::isContourLine(poly.type) ? 0 : &haloColor;
|
||||||
const QImage *img = poly.oneway
|
const QImage *img = poly.oneway
|
||||||
? Style::isWaterLine(poly.type)
|
? Style::isWaterLine(poly.type)
|
||||||
@ -353,7 +355,7 @@ void RasterTile::processShields(const QList<MapData::Poly> &lines,
|
|||||||
it != shields.constEnd(); ++it) {
|
it != shields.constEnd(); ++it) {
|
||||||
const QPolygonF &p = it.value();
|
const QPolygonF &p = it.value();
|
||||||
QRectF rect(p.boundingRect() & _rect);
|
QRectF rect(p.boundingRect() & _rect);
|
||||||
if (AREA(rect) < AREA(QRect(0, 0, _pixmap.width()/4, _pixmap.width()/4)))
|
if (AREA(rect) < AREA(QRect(0, 0, _rect.width()/4, _rect.width()/4)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QMap<qreal, int> map;
|
QMap<qreal, int> map;
|
||||||
@ -403,10 +405,10 @@ void RasterTile::processPoints(QList<MapData::Point> &points,
|
|||||||
? 0 : &(point.label.text());
|
? 0 : &(point.label.text());
|
||||||
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
||||||
const QFont *fnt = poi
|
const QFont *fnt = poi
|
||||||
? poiFont(style.textFontSize(), _zoom, point.classLabel)
|
? poiFont(style.text().size(), _zoom, point.classLabel)
|
||||||
: _data->style()->font(style.textFontSize());
|
: _data->style()->font(style.text().size());
|
||||||
const QColor *color = style.textColor().isValid()
|
const QColor *color = style.text().color().isValid()
|
||||||
? &style.textColor() : &textColor;
|
? &style.text().color() : &textColor;
|
||||||
const QColor *hcolor = Style::isDepthPoint(point.type)
|
const QColor *hcolor = Style::isDepthPoint(point.type)
|
||||||
? 0 : &haloColor;
|
? 0 : &haloColor;
|
||||||
|
|
||||||
@ -443,8 +445,29 @@ void RasterTile::fetchData(QList<MapData::Poly> &polygons,
|
|||||||
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix RasterTile::elevation() const
|
||||||
|
{
|
||||||
|
Matrix m(_rect.height() + 2, _rect.width() + 2);
|
||||||
|
|
||||||
|
int left = _rect.left() - 1;
|
||||||
|
int right = _rect.right() + 1;
|
||||||
|
int top = _rect.top() - 1;
|
||||||
|
int bottom = _rect.bottom() + 1;
|
||||||
|
|
||||||
|
DEM::lock();
|
||||||
|
for (int y = top; y <= bottom; y++) {
|
||||||
|
for (int x = left; x <= right; x++)
|
||||||
|
m.m(y - top, x - left) = DEM::elevation(xy2ll(QPointF(x, y)));
|
||||||
|
}
|
||||||
|
DEM::unlock();
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void RasterTile::render()
|
void RasterTile::render()
|
||||||
{
|
{
|
||||||
|
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
QList<MapData::Poly> polygons;
|
QList<MapData::Poly> polygons;
|
||||||
QList<MapData::Poly> lines;
|
QList<MapData::Poly> lines;
|
||||||
QList<MapData::Point> points;
|
QList<MapData::Point> points;
|
||||||
@ -463,21 +486,23 @@ void RasterTile::render()
|
|||||||
processPolygons(polygons, textItems);
|
processPolygons(polygons, textItems);
|
||||||
processLines(lines, textItems, arrows);
|
processLines(lines, textItems, arrows);
|
||||||
|
|
||||||
_pixmap.setDevicePixelRatio(_ratio);
|
img.setDevicePixelRatio(_ratio);
|
||||||
_pixmap.fill(Qt::transparent);
|
img.fill(Qt::transparent);
|
||||||
|
|
||||||
QPainter painter(&_pixmap);
|
QPainter painter(&img);
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.translate(-_rect.x(), -_rect.y());
|
painter.translate(-_rect.x(), -_rect.y());
|
||||||
|
|
||||||
drawPolygons(&painter, polygons);
|
drawPolygons(&painter, polygons);
|
||||||
|
if (_hillShading && _zoom >= 18 && _zoom <= 24)
|
||||||
|
painter.drawImage(_rect.x(), _rect.y(), HillShading::render(elevation()));
|
||||||
drawLines(&painter, lines);
|
drawLines(&painter, lines);
|
||||||
drawTextItems(&painter, textItems);
|
drawTextItems(&painter, textItems);
|
||||||
|
|
||||||
qDeleteAll(textItems);
|
qDeleteAll(textItems);
|
||||||
|
|
||||||
_valid = true;
|
_pixmap = QPixmap::fromImage(img);
|
||||||
|
|
||||||
//painter.setPen(Qt::red);
|
//painter.setPen(Qt::red);
|
||||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
#include "map/projection.h"
|
#include "map/projection.h"
|
||||||
#include "map/transform.h"
|
#include "map/transform.h"
|
||||||
|
#include "map/matrix.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
@ -17,15 +18,14 @@ class RasterTile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RasterTile(const Projection &proj, const Transform &transform, MapData *data,
|
RasterTile(const Projection &proj, const Transform &transform, MapData *data,
|
||||||
int zoom, const QRect &rect, qreal ratio, const QString &key)
|
int zoom, const QRect &rect, qreal ratio, const QString &key,
|
||||||
|
bool hillShading)
|
||||||
: _proj(proj), _transform(transform), _data(data), _zoom(zoom),
|
: _proj(proj), _transform(transform), _data(data), _zoom(zoom),
|
||||||
_rect(rect), _ratio(ratio), _key(key),
|
_rect(rect), _ratio(ratio), _key(key), _hillShading(hillShading) {}
|
||||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
|
|
||||||
|
|
||||||
const QString &key() const {return _key;}
|
const QString &key() const {return _key;}
|
||||||
QPoint xy() const {return _rect.topLeft();}
|
QPoint xy() const {return _rect.topLeft();}
|
||||||
const QPixmap &pixmap() const {return _pixmap;}
|
const QPixmap &pixmap() const {return _pixmap;}
|
||||||
bool isValid() const {return _valid;}
|
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
@ -34,6 +34,8 @@ private:
|
|||||||
QList<MapData::Point> &points);
|
QList<MapData::Point> &points);
|
||||||
QPointF ll2xy(const Coordinates &c) const
|
QPointF ll2xy(const Coordinates &c) const
|
||||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||||
|
Coordinates xy2ll(const QPointF &p) const
|
||||||
|
{return _proj.xy2ll(_transform.img2proj(p));}
|
||||||
void ll2xy(QList<MapData::Poly> &polys);
|
void ll2xy(QList<MapData::Poly> &polys);
|
||||||
void ll2xy(QList<MapData::Point> &points);
|
void ll2xy(QList<MapData::Point> &points);
|
||||||
|
|
||||||
@ -55,6 +57,8 @@ private:
|
|||||||
const QFont *poiFont(Style::FontSize size = Style::Normal,
|
const QFont *poiFont(Style::FontSize size = Style::Normal,
|
||||||
int zoom = -1, bool extended = false);
|
int zoom = -1, bool extended = false);
|
||||||
|
|
||||||
|
Matrix elevation() const;
|
||||||
|
|
||||||
Projection _proj;
|
Projection _proj;
|
||||||
Transform _transform;
|
Transform _transform;
|
||||||
MapData *_data;
|
MapData *_data;
|
||||||
@ -63,7 +67,7 @@ private:
|
|||||||
qreal _ratio;
|
qreal _ratio;
|
||||||
QString _key;
|
QString _key;
|
||||||
QPixmap _pixmap;
|
QPixmap _pixmap;
|
||||||
bool _valid;
|
bool _hillShading;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1332,6 +1332,12 @@ static QString brushColor(const QBrush &brush)
|
|||||||
return (brush == Qt::NoBrush) ? "None" : brush.color().name();
|
return (brush == Qt::NoBrush) ? "None" : brush.color().name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug dbg, const Style::Font &font)
|
||||||
|
{
|
||||||
|
dbg.nospace() << "Font(" << font.color() << ", " << font.size() << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const Style::Polygon &polygon)
|
QDebug operator<<(QDebug dbg, const Style::Polygon &polygon)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Polygon(" << brushColor(polygon.brush()) << ", "
|
dbg.nospace() << "Polygon(" << brushColor(polygon.brush()) << ", "
|
||||||
@ -1342,14 +1348,15 @@ QDebug operator<<(QDebug dbg, const Style::Polygon &polygon)
|
|||||||
QDebug operator<<(QDebug dbg, const Style::Line &line)
|
QDebug operator<<(QDebug dbg, const Style::Line &line)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Line(" << penColor(line.foreground()) << ", "
|
dbg.nospace() << "Line(" << penColor(line.foreground()) << ", "
|
||||||
<< penColor(line.background()) << ", " << !line.img().isNull() << ")";
|
<< penColor(line.background()) << ", " << !line.img().isNull() << ", "
|
||||||
|
<< line.text() << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const Style::Point &point)
|
QDebug operator<<(QDebug dbg, const Style::Point &point)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Point(" << point.textFontSize() << ", "
|
dbg.nospace() << "Point(" << point.text() << ", " << !point.img().isNull()
|
||||||
<< point.textColor() << ", " << !point.img().isNull() << ")";
|
<< ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -23,6 +23,21 @@ public:
|
|||||||
ExtraSmall = 5
|
ExtraSmall = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class Font {
|
||||||
|
public:
|
||||||
|
Font() :_size(NotSet) {}
|
||||||
|
Font(const QColor &color, FontSize size) : _color(color), _size(size) {}
|
||||||
|
|
||||||
|
const QColor &color() const {return _color;}
|
||||||
|
FontSize size() const {return _size;}
|
||||||
|
void setColor(const QColor &color) {_color = color;}
|
||||||
|
void setSize(FontSize size) {_size = size;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QColor _color;
|
||||||
|
FontSize _size;
|
||||||
|
};
|
||||||
|
|
||||||
class Polygon {
|
class Polygon {
|
||||||
public:
|
public:
|
||||||
Polygon() : _brush(Qt::NoBrush), _pen(Qt::NoPen) {}
|
Polygon() : _brush(Qt::NoBrush), _pen(Qt::NoPen) {}
|
||||||
@ -42,49 +57,46 @@ public:
|
|||||||
|
|
||||||
class Line {
|
class Line {
|
||||||
public:
|
public:
|
||||||
Line() : _foreground(Qt::NoPen), _background(Qt::NoPen),
|
Line() : _foreground(Qt::NoPen), _background(Qt::NoPen) {}
|
||||||
_textFontSize(NotSet) {}
|
|
||||||
Line(const QPen &foreground, const QPen &background = Qt::NoPen)
|
Line(const QPen &foreground, const QPen &background = Qt::NoPen)
|
||||||
: _foreground(foreground), _background(background),
|
: _foreground(foreground), _background(background) {}
|
||||||
_textFontSize(NotSet) {}
|
|
||||||
Line(const QImage &img)
|
Line(const QImage &img)
|
||||||
: _foreground(Qt::NoPen), _background(Qt::NoPen),
|
: _foreground(Qt::NoPen), _background(Qt::NoPen),
|
||||||
_textFontSize(NotSet), _img(img.convertToFormat(
|
_img(img.convertToFormat(QImage::Format_ARGB32_Premultiplied)) {}
|
||||||
QImage::Format_ARGB32_Premultiplied)) {}
|
|
||||||
|
|
||||||
void setTextColor(const QColor &color) {_textColor = color;}
|
|
||||||
void setTextFontSize(FontSize size) {_textFontSize = size;}
|
|
||||||
|
|
||||||
const QPen &foreground() const {return _foreground;}
|
const QPen &foreground() const {return _foreground;}
|
||||||
const QPen &background() const {return _background;}
|
const QPen &background() const {return _background;}
|
||||||
const QColor &textColor() const {return _textColor;}
|
const Font &text() const {return _text;}
|
||||||
FontSize textFontSize() const {return _textFontSize;}
|
|
||||||
const QImage &img() const {return _img;}
|
const QImage &img() const {return _img;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class Style;
|
||||||
|
|
||||||
|
void setTextColor(const QColor &color) {_text.setColor(color);}
|
||||||
|
void setTextFontSize(FontSize size) {_text.setSize(size);}
|
||||||
|
|
||||||
QPen _foreground, _background;
|
QPen _foreground, _background;
|
||||||
QColor _textColor;
|
Font _text;
|
||||||
FontSize _textFontSize;
|
|
||||||
QImage _img;
|
QImage _img;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Point {
|
class Point {
|
||||||
public:
|
public:
|
||||||
Point() : _textFontSize(NotSet) {}
|
Point() {}
|
||||||
Point(FontSize fontSize, const QColor &textColor = QColor())
|
Point(FontSize fontSize, const QColor &textColor = QColor())
|
||||||
: _textColor(textColor), _textFontSize(fontSize) {}
|
: _text(textColor, fontSize) {}
|
||||||
Point(const QImage &img) : _textFontSize(NotSet), _img(img) {}
|
Point(const QImage &img) : _img(img) {}
|
||||||
|
|
||||||
void setTextColor(const QColor &color) {_textColor = color;}
|
const Font &text() const {return _text;}
|
||||||
void setTextFontSize(FontSize size) {_textFontSize = size;}
|
|
||||||
|
|
||||||
const QColor &textColor() const {return _textColor;}
|
|
||||||
FontSize textFontSize() const {return _textFontSize;}
|
|
||||||
const QImage &img() const {return _img;}
|
const QImage &img() const {return _img;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QColor _textColor;
|
friend class Style;
|
||||||
FontSize _textFontSize;
|
|
||||||
|
void setTextColor(const QColor &color) {_text.setColor(color);}
|
||||||
|
void setTextFontSize(FontSize size) {_text.setSize(size);}
|
||||||
|
|
||||||
|
Font _text;
|
||||||
QImage _img;
|
QImage _img;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,6 +195,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
|
QDebug operator<<(QDebug dbg, const IMG::Style::Font &font);
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Style::Polygon &polygon);
|
QDebug operator<<(QDebug dbg, const IMG::Style::Polygon &polygon);
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Style::Line &line);
|
QDebug operator<<(QDebug dbg, const IMG::Style::Line &line);
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Style::Point &point);
|
QDebug operator<<(QDebug dbg, const IMG::Style::Point &point);
|
||||||
|
101
src/map/hillshading.cpp
Normal file
101
src/map/hillshading.cpp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include <cmath>
|
||||||
|
#include "hillshading.h"
|
||||||
|
|
||||||
|
struct Constants
|
||||||
|
{
|
||||||
|
double a1;
|
||||||
|
double a2;
|
||||||
|
double a3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubMatrix
|
||||||
|
{
|
||||||
|
double z1;
|
||||||
|
double z2;
|
||||||
|
double z3;
|
||||||
|
double z4;
|
||||||
|
double z6;
|
||||||
|
double z7;
|
||||||
|
double z8;
|
||||||
|
double z9;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derivatives
|
||||||
|
{
|
||||||
|
double dzdx;
|
||||||
|
double dzdy;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void getConstants(double azimuth, double elevation, Constants &c)
|
||||||
|
{
|
||||||
|
double alpha = (M_PI / 180.0) * azimuth;
|
||||||
|
double beta = (M_PI / 180.0) * elevation;
|
||||||
|
|
||||||
|
c.a1 = sin(beta);
|
||||||
|
c.a2 = cos(beta) * sin(alpha);
|
||||||
|
c.a3 = cos(beta) * cos(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getDerivativesHorn(const SubMatrix &sm, double z, Derivatives &d)
|
||||||
|
{
|
||||||
|
d.dzdx = (z * (sm.z3 + 2 * sm.z6 + sm.z9 - sm.z1 - 2 * sm.z4 - sm.z7)) / 8;
|
||||||
|
d.dzdy = (z * (sm.z1 + 2 * sm.z2 + sm.z3 - sm.z7 - 2 * sm.z8 - sm.z9)) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getSubmatrix(int x, int y, const Matrix &m, SubMatrix &sm)
|
||||||
|
{
|
||||||
|
int left = x - 1;
|
||||||
|
int right = x + 1;
|
||||||
|
int top = y - 1;
|
||||||
|
int bottom = y + 1;
|
||||||
|
|
||||||
|
sm.z1 = m.m(top, left);
|
||||||
|
sm.z2 = m.m(top, x);
|
||||||
|
sm.z3 = m.m(top, right);
|
||||||
|
sm.z4 = m.m(y, left);
|
||||||
|
sm.z6 = m.m(y, right);
|
||||||
|
sm.z7 = m.m(bottom, left);
|
||||||
|
sm.z8 = m.m(bottom, x);
|
||||||
|
sm.z9 = m.m(bottom, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage HillShading::render(const Matrix &m, quint8 alpha, double azimuth,
|
||||||
|
double elevation)
|
||||||
|
{
|
||||||
|
QImage img(m.w() - 2, m.h() - 2, QImage::Format_ARGB32_Premultiplied);
|
||||||
|
uchar *bits = img.bits();
|
||||||
|
int bpl = img.bytesPerLine();
|
||||||
|
|
||||||
|
Constants c;
|
||||||
|
SubMatrix sm;
|
||||||
|
Derivatives d;
|
||||||
|
double z = (double)alpha / 0xFF;
|
||||||
|
|
||||||
|
getConstants(azimuth, elevation, c);
|
||||||
|
|
||||||
|
for (int y = 1; y < m.h() - 1; y++) {
|
||||||
|
for (int x = 1; x < m.w() - 1; x++) {
|
||||||
|
getSubmatrix(x, y, m, sm);
|
||||||
|
getDerivativesHorn(sm, z, d);
|
||||||
|
|
||||||
|
double L = (c.a1 - c.a2 * d.dzdx - c.a3 * d.dzdy)
|
||||||
|
/ sqrt(1.0 + d.dzdx * d.dzdx + d.dzdy * d.dzdy);
|
||||||
|
|
||||||
|
quint8 a, val;
|
||||||
|
if (std::isnan(L)) {
|
||||||
|
a = 0;
|
||||||
|
val = 0;
|
||||||
|
} else {
|
||||||
|
if (L < 0)
|
||||||
|
L = 0;
|
||||||
|
val = L * alpha;
|
||||||
|
a = alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 pixel = a<<24 | val<<16 | val<<8 | val;
|
||||||
|
*(quint32*)(bits + (y - 1) * bpl + (x - 1) * 4) = pixel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
14
src/map/hillshading.h
Normal file
14
src/map/hillshading.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef HILLSHADING_H
|
||||||
|
#define HILLSHADING_H
|
||||||
|
|
||||||
|
#include <QImage>
|
||||||
|
#include "map/matrix.h"
|
||||||
|
|
||||||
|
class HillShading
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static QImage render(const Matrix &m, quint8 alpha = 64,
|
||||||
|
double azimuth = 315, double elevation = 25);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HILLSHADING_H
|
@ -201,7 +201,7 @@ void IMGMap::jobFinished(IMGMapJob *job)
|
|||||||
|
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
const IMG::RasterTile &mt = tiles.at(i);
|
const IMG::RasterTile &mt = tiles.at(i);
|
||||||
if (mt.isValid())
|
if (!mt.pixmap().isNull())
|
||||||
QPixmapCache::insert(mt.key(), mt.pixmap());
|
QPixmapCache::insert(mt.key(), mt.pixmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +242,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
else {
|
else {
|
||||||
tiles.append(RasterTile(_projection, _transform, _data.at(n),
|
tiles.append(RasterTile(_projection, _transform, _data.at(n),
|
||||||
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
||||||
key));
|
key, !n && flags & Map::HillShading));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@ public:
|
|||||||
enum Flag {
|
enum Flag {
|
||||||
NoFlags = 0,
|
NoFlags = 0,
|
||||||
Block = 1,
|
Block = 1,
|
||||||
OpenGL = 2
|
OpenGL = 2,
|
||||||
|
HillShading = 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QCache>
|
#include <QCache>
|
||||||
|
#include "data/dem.h"
|
||||||
#include "map/rectd.h"
|
#include "map/rectd.h"
|
||||||
|
#include "map/hillshading.h"
|
||||||
#include "rastertile.h"
|
#include "rastertile.h"
|
||||||
|
|
||||||
using namespace Mapsforge;
|
using namespace Mapsforge;
|
||||||
@ -392,17 +394,27 @@ void RasterTile::circleInstructions(const QList<MapData::Point> &points,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RasterTile::hillShadingInstructions(
|
||||||
|
QVector<RasterTile::RenderInstruction> &instructions) const
|
||||||
|
{
|
||||||
|
const Style::HillShadingRender *hs = _style->hillShading(_zoom);
|
||||||
|
if (hs)
|
||||||
|
instructions.append(RenderInstruction(hs));
|
||||||
|
}
|
||||||
|
|
||||||
void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
||||||
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths)
|
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths)
|
||||||
{
|
{
|
||||||
QVector<RenderInstruction> instructions;
|
QVector<RenderInstruction> instructions;
|
||||||
pathInstructions(paths, painterPaths, instructions);
|
pathInstructions(paths, painterPaths, instructions);
|
||||||
circleInstructions(points, instructions);
|
circleInstructions(points, instructions);
|
||||||
|
hillShadingInstructions(instructions);
|
||||||
std::sort(instructions.begin(), instructions.end());
|
std::sort(instructions.begin(), instructions.end());
|
||||||
|
|
||||||
for (int i = 0; i < instructions.size(); i++) {
|
for (int i = 0; i < instructions.size(); i++) {
|
||||||
const RenderInstruction &is = instructions.at(i);
|
const RenderInstruction &is = instructions.at(i);
|
||||||
PainterPath *path = is.path();
|
PainterPath *path = is.path();
|
||||||
|
const MapData::Point *point = is.point();
|
||||||
|
|
||||||
if (path) {
|
if (path) {
|
||||||
const Style::PathRender *ri = is.pathRender();
|
const Style::PathRender *ri = is.pathRender();
|
||||||
@ -418,13 +430,17 @@ void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
|||||||
painter->drawPath(parallelPath(path->pp, dy));
|
painter->drawPath(parallelPath(path->pp, dy));
|
||||||
else
|
else
|
||||||
painter->drawPath(path->pp);
|
painter->drawPath(path->pp);
|
||||||
} else {
|
} else if (point) {
|
||||||
const Style::CircleRender *ri = is.circleRender();
|
const Style::CircleRender *ri = is.circleRender();
|
||||||
qreal radius = ri->radius(_zoom);
|
qreal radius = ri->radius(_zoom);
|
||||||
|
|
||||||
painter->setPen(ri->pen());
|
painter->setPen(ri->pen());
|
||||||
painter->setBrush(ri->brush());
|
painter->setBrush(ri->brush());
|
||||||
painter->drawEllipse(ll2xy(is.point()->coordinates), radius, radius);
|
painter->drawEllipse(ll2xy(point->coordinates), radius, radius);
|
||||||
|
} else {
|
||||||
|
if (_hillShading)
|
||||||
|
painter->drawImage(_rect.x(), _rect.y(),
|
||||||
|
HillShading::render(elevation()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,8 +471,29 @@ void RasterTile::fetchData(QList<MapData::Path> &paths,
|
|||||||
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Matrix RasterTile::elevation() const
|
||||||
|
{
|
||||||
|
Matrix m(_rect.height() + 2, _rect.width() + 2);
|
||||||
|
|
||||||
|
int left = _rect.left() - 1;
|
||||||
|
int right = _rect.right() + 1;
|
||||||
|
int top = _rect.top() - 1;
|
||||||
|
int bottom = _rect.bottom() + 1;
|
||||||
|
|
||||||
|
DEM::lock();
|
||||||
|
for (int y = top; y <= bottom; y++) {
|
||||||
|
for (int x = left; x <= right; x++)
|
||||||
|
m.m(y - top, x - left) = DEM::elevation(xy2ll(QPointF(x, y)));
|
||||||
|
}
|
||||||
|
DEM::unlock();
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void RasterTile::render()
|
void RasterTile::render()
|
||||||
{
|
{
|
||||||
|
QImage img(_rect.width() * _ratio, _rect.height() * _ratio,
|
||||||
|
QImage::Format_ARGB32_Premultiplied);
|
||||||
QList<MapData::Path> paths;
|
QList<MapData::Path> paths;
|
||||||
QList<MapData::Point> points;
|
QList<MapData::Point> points;
|
||||||
|
|
||||||
@ -465,10 +502,10 @@ void RasterTile::render()
|
|||||||
QList<TextItem*> textItems;
|
QList<TextItem*> textItems;
|
||||||
QVector<PainterPath> renderPaths(paths.size());
|
QVector<PainterPath> renderPaths(paths.size());
|
||||||
|
|
||||||
_pixmap.setDevicePixelRatio(_ratio);
|
img.setDevicePixelRatio(_ratio);
|
||||||
_pixmap.fill(Qt::transparent);
|
img.fill(Qt::transparent);
|
||||||
|
|
||||||
QPainter painter(&_pixmap);
|
QPainter painter(&img);
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||||
painter.translate(-_rect.x(), -_rect.y());
|
painter.translate(-_rect.x(), -_rect.y());
|
||||||
@ -487,5 +524,5 @@ void RasterTile::render()
|
|||||||
|
|
||||||
qDeleteAll(textItems);
|
qDeleteAll(textItems);
|
||||||
|
|
||||||
_valid = true;
|
_pixmap = QPixmap::fromImage(img);
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,18 @@
|
|||||||
#include "map/transform.h"
|
#include "map/transform.h"
|
||||||
#include "map/textpointitem.h"
|
#include "map/textpointitem.h"
|
||||||
#include "map/textpathitem.h"
|
#include "map/textpathitem.h"
|
||||||
|
#include "map/matrix.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define HILLSHADING_RENDER(ptr) \
|
||||||
|
static_cast<const Style::HillShadingRender*>(ptr)
|
||||||
|
#define PATH_RENDER(ptr) \
|
||||||
|
static_cast<const Style::PathRender*>(ptr)
|
||||||
|
#define POINT_RENDER(ptr) \
|
||||||
|
static_cast<const Style::CircleRender*>(ptr)
|
||||||
|
|
||||||
namespace Mapsforge {
|
namespace Mapsforge {
|
||||||
|
|
||||||
class RasterTile
|
class RasterTile
|
||||||
@ -20,14 +29,13 @@ public:
|
|||||||
back in zoom() */
|
back in zoom() */
|
||||||
RasterTile(const Projection &proj, const Transform &transform,
|
RasterTile(const Projection &proj, const Transform &transform,
|
||||||
const Style *style, MapData *data, int zoom, const QRect &rect,
|
const Style *style, MapData *data, int zoom, const QRect &rect,
|
||||||
qreal ratio) : _proj(proj), _transform(transform), _style(style),
|
qreal ratio, bool hillShading)
|
||||||
_data(data), _zoom(zoom - 1), _rect(rect), _ratio(ratio),
|
: _proj(proj), _transform(transform), _style(style), _data(data),
|
||||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
|
_zoom(zoom - 1), _rect(rect), _ratio(ratio), _hillShading(hillShading) {}
|
||||||
|
|
||||||
int zoom() const {return _zoom + 1;}
|
int zoom() const {return _zoom + 1;}
|
||||||
QPoint xy() const {return _rect.topLeft();}
|
QPoint xy() const {return _rect.topLeft();}
|
||||||
const QPixmap &pixmap() const {return _pixmap;}
|
const QPixmap &pixmap() const {return _pixmap;}
|
||||||
bool isValid() const {return _valid;}
|
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
@ -91,6 +99,8 @@ private:
|
|||||||
RenderInstruction(const Style::CircleRender *render,
|
RenderInstruction(const Style::CircleRender *render,
|
||||||
const MapData::Point *point) : _render(render), _path(0),
|
const MapData::Point *point) : _render(render), _path(0),
|
||||||
_point(point) {}
|
_point(point) {}
|
||||||
|
RenderInstruction(const Style::HillShadingRender *render)
|
||||||
|
: _render(render), _path(0), _point(0) {}
|
||||||
|
|
||||||
bool operator<(const RenderInstruction &other) const
|
bool operator<(const RenderInstruction &other) const
|
||||||
{
|
{
|
||||||
@ -101,19 +111,33 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Style::PathRender *pathRender() const
|
const Style::PathRender *pathRender() const
|
||||||
{return static_cast<const Style::PathRender*>(_render);}
|
{return PATH_RENDER(_render);}
|
||||||
const Style::CircleRender *circleRender() const
|
const Style::CircleRender *circleRender() const
|
||||||
{return static_cast<const Style::CircleRender*>(_render);}
|
{return POINT_RENDER(_render);}
|
||||||
|
const Style::HillShadingRender *hillShadingRender() const
|
||||||
|
{return HILLSHADING_RENDER(_render);}
|
||||||
|
|
||||||
PainterPath *path() const {return _path;}
|
PainterPath *path() const {return _path;}
|
||||||
const MapData::Point *point() const {return _point;}
|
const MapData::Point *point() const {return _point;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int layer() const {return _path ? _path->path->layer : _point->layer;}
|
int layer() const
|
||||||
|
{
|
||||||
|
if (_path)
|
||||||
|
return _path->path->layer;
|
||||||
|
else if (_point)
|
||||||
|
return _point->layer;
|
||||||
|
else
|
||||||
|
return HILLSHADING_RENDER(_render)->layer();
|
||||||
|
}
|
||||||
int zOrder() const
|
int zOrder() const
|
||||||
{
|
{
|
||||||
return _path
|
if (_path)
|
||||||
? static_cast<const Style::PathRender*>(_render)->zOrder()
|
return PATH_RENDER(_render)->zOrder();
|
||||||
: static_cast<const Style::CircleRender*>(_render)->zOrder();
|
else if (_point)
|
||||||
|
return POINT_RENDER(_render)->zOrder();
|
||||||
|
else
|
||||||
|
return HILLSHADING_RENDER(_render)->zOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Style::Render *_render;
|
const Style::Render *_render;
|
||||||
@ -178,8 +202,12 @@ private:
|
|||||||
QVector<RasterTile::RenderInstruction> &instructions) const;
|
QVector<RasterTile::RenderInstruction> &instructions) const;
|
||||||
void circleInstructions(const QList<MapData::Point> &points,
|
void circleInstructions(const QList<MapData::Point> &points,
|
||||||
QVector<RasterTile::RenderInstruction> &instructions) const;
|
QVector<RasterTile::RenderInstruction> &instructions) const;
|
||||||
|
void hillShadingInstructions(
|
||||||
|
QVector<RasterTile::RenderInstruction> &instructions) const;
|
||||||
QPointF ll2xy(const Coordinates &c) const
|
QPointF ll2xy(const Coordinates &c) const
|
||||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||||
|
Coordinates xy2ll(const QPointF &p) const
|
||||||
|
{return _proj.xy2ll(_transform.img2proj(p));}
|
||||||
void processPointLabels(const QList<MapData::Point> &points,
|
void processPointLabels(const QList<MapData::Point> &points,
|
||||||
QList<TextItem*> &textItems) const;
|
QList<TextItem*> &textItems) const;
|
||||||
void processAreaLabels(const QVector<PainterPath> &paths,
|
void processAreaLabels(const QVector<PainterPath> &paths,
|
||||||
@ -191,6 +219,8 @@ private:
|
|||||||
void drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
void drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
||||||
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths);
|
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths);
|
||||||
|
|
||||||
|
Matrix elevation() const;
|
||||||
|
|
||||||
Projection _proj;
|
Projection _proj;
|
||||||
Transform _transform;
|
Transform _transform;
|
||||||
const Style *_style;
|
const Style *_style;
|
||||||
@ -199,7 +229,7 @@ private:
|
|||||||
QRect _rect;
|
QRect _rect;
|
||||||
qreal _ratio;
|
qreal _ratio;
|
||||||
QPixmap _pixmap;
|
QPixmap _pixmap;
|
||||||
bool _valid;
|
bool _hillShading;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline HASH_T qHash(const RasterTile::PathKey &key)
|
inline HASH_T qHash(const RasterTile::PathKey &key)
|
||||||
|
@ -179,7 +179,7 @@ bool Style::Rule::match(int zoom, const QVector<MapData::Tag> &tags) const
|
|||||||
void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||||
qreal baseStrokeWidth, const Rule &rule)
|
qreal baseStrokeWidth, const Rule &rule)
|
||||||
{
|
{
|
||||||
PathRender ri(rule, _paths.size() + _circles.size());
|
PathRender ri(rule, _paths.size() + _circles.size() + _hillShading.isValid());
|
||||||
const QXmlStreamAttributes &attr = reader.attributes();
|
const QXmlStreamAttributes &attr = reader.attributes();
|
||||||
QString file;
|
QString file;
|
||||||
QColor fillColor;
|
QColor fillColor;
|
||||||
@ -244,7 +244,7 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
|||||||
void Style::line(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
void Style::line(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
||||||
const Rule &rule)
|
const Rule &rule)
|
||||||
{
|
{
|
||||||
PathRender ri(rule, _paths.size() + _circles.size());
|
PathRender ri(rule, _paths.size() + _circles.size() + _hillShading.isValid());
|
||||||
const QXmlStreamAttributes &attr = reader.attributes();
|
const QXmlStreamAttributes &attr = reader.attributes();
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ void Style::line(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
|||||||
void Style::circle(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
void Style::circle(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
||||||
const Rule &rule)
|
const Rule &rule)
|
||||||
{
|
{
|
||||||
CircleRender ri(rule, _paths.size() + _circles.size());
|
CircleRender ri(rule, _paths.size() + _circles.size() + _hillShading.isValid());
|
||||||
const QXmlStreamAttributes &attr = reader.attributes();
|
const QXmlStreamAttributes &attr = reader.attributes();
|
||||||
bool ok;
|
bool ok;
|
||||||
QColor fillColor, strokeColor;
|
QColor fillColor, strokeColor;
|
||||||
@ -573,6 +573,45 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Style::hillshading(QXmlStreamReader &reader, const QSet<QString> &cats)
|
||||||
|
{
|
||||||
|
Rule r;
|
||||||
|
const QXmlStreamAttributes &attr = reader.attributes();
|
||||||
|
bool ok;
|
||||||
|
int layer = 5;
|
||||||
|
|
||||||
|
if (attr.hasAttribute("cat")
|
||||||
|
&& !cats.contains(attr.value("cat").toString())) {
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (attr.hasAttribute("zoom-min")) {
|
||||||
|
r.setMinZoom(attr.value("zoom-min").toInt(&ok));
|
||||||
|
if (!ok || r._zooms.min() < 0) {
|
||||||
|
reader.raiseError("invalid zoom-min value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attr.hasAttribute("zoom-max")) {
|
||||||
|
r.setMaxZoom(attr.value("zoom-max").toInt(&ok));
|
||||||
|
if (!ok || r._zooms.max() < 0) {
|
||||||
|
reader.raiseError("invalid zoom-max value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attr.hasAttribute("layer")) {
|
||||||
|
layer = attr.value("layer").toInt(&ok);
|
||||||
|
if (!ok || layer < 0) {
|
||||||
|
reader.raiseError("invalid layer value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_hillShading = HillShadingRender(r, _paths.size() + _circles.size(), layer);
|
||||||
|
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
|
||||||
QString Style::cat(QXmlStreamReader &reader)
|
QString Style::cat(QXmlStreamReader &reader)
|
||||||
{
|
{
|
||||||
const QXmlStreamAttributes &attr = reader.attributes();
|
const QXmlStreamAttributes &attr = reader.attributes();
|
||||||
@ -654,6 +693,8 @@ void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
|||||||
while (reader.readNextStartElement()) {
|
while (reader.readNextStartElement()) {
|
||||||
if (reader.name() == QLatin1String("rule"))
|
if (reader.name() == QLatin1String("rule"))
|
||||||
rule(reader, dir, data, ratio, baseStrokeWidth, cats, r);
|
rule(reader, dir, data, ratio, baseStrokeWidth, cats, r);
|
||||||
|
else if (reader.name() == QLatin1String("hillshading"))
|
||||||
|
hillshading(reader, cats);
|
||||||
else if (reader.name() == QLatin1String("stylemenu")) {
|
else if (reader.name() == QLatin1String("stylemenu")) {
|
||||||
Menu menu(stylemenu(reader));
|
Menu menu(stylemenu(reader));
|
||||||
cats = menu.cats();
|
cats = menu.cats();
|
||||||
@ -727,6 +768,12 @@ QList<const Style::CircleRender *> Style::circles(int zoom,
|
|||||||
return ri;
|
return ri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Style::HillShadingRender *Style::hillShading(int zoom) const
|
||||||
|
{
|
||||||
|
return (_hillShading.isValid() && _hillShading.rule()._zooms.contains(zoom))
|
||||||
|
? &_hillShading : 0;
|
||||||
|
}
|
||||||
|
|
||||||
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
|
QList<const Style::TextRender*> Style::pathLabels(int zoom) const
|
||||||
{
|
{
|
||||||
QList<const TextRender*> list;
|
QList<const TextRender*> list;
|
||||||
|
@ -131,6 +131,22 @@ public:
|
|||||||
Rule _rule;
|
Rule _rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HillShadingRender : public Render
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HillShadingRender() : Render(Rule()), _zOrder(-1), _layer(-1) {}
|
||||||
|
HillShadingRender(const Rule &rule, int zOrder, int layer)
|
||||||
|
: Render(rule), _zOrder(zOrder), _layer(layer) {}
|
||||||
|
|
||||||
|
bool isValid() const {return _zOrder >= 0;}
|
||||||
|
int zOrder() const {return _zOrder;}
|
||||||
|
int layer() const {return _layer;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _zOrder;
|
||||||
|
int _layer;
|
||||||
|
};
|
||||||
|
|
||||||
class PathRender : public Render
|
class PathRender : public Render
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -244,6 +260,7 @@ public:
|
|||||||
QList<const Symbol*> pointSymbols(int zoom) const;
|
QList<const Symbol*> pointSymbols(int zoom) const;
|
||||||
QList<const Symbol*> areaSymbols(int zoom) const;
|
QList<const Symbol*> areaSymbols(int zoom) const;
|
||||||
QList<const Symbol*> lineSymbols(int zoom) const;
|
QList<const Symbol*> lineSymbols(int zoom) const;
|
||||||
|
const HillShadingRender *hillShading(int zoom) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Menu {
|
class Menu {
|
||||||
@ -286,6 +303,7 @@ private:
|
|||||||
QList<Layer> _layers;
|
QList<Layer> _layers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
HillShadingRender _hillShading;
|
||||||
QList<PathRender> _paths;
|
QList<PathRender> _paths;
|
||||||
QList<CircleRender> _circles;
|
QList<CircleRender> _circles;
|
||||||
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
||||||
@ -305,6 +323,7 @@ private:
|
|||||||
void line(QXmlStreamReader &reader, qreal baseStrokeWidth, const Rule &rule);
|
void line(QXmlStreamReader &reader, qreal baseStrokeWidth, const Rule &rule);
|
||||||
void circle(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
void circle(QXmlStreamReader &reader, qreal baseStrokeWidth,
|
||||||
const Rule &rule);
|
const Rule &rule);
|
||||||
|
void hillshading(QXmlStreamReader &reader, const QSet<QString> &cats);
|
||||||
void text(QXmlStreamReader &reader, const MapData &data, const Rule &rule,
|
void text(QXmlStreamReader &reader, const MapData &data, const Rule &rule,
|
||||||
QList<QList<TextRender> *> &lists);
|
QList<QList<TextRender> *> &lists);
|
||||||
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||||
|
@ -150,7 +150,7 @@ void MapsforgeMap::jobFinished(MapsforgeMapJob *job)
|
|||||||
|
|
||||||
for (int i = 0; i < tiles.size(); i++) {
|
for (int i = 0; i < tiles.size(); i++) {
|
||||||
const Mapsforge::RasterTile &mt = tiles.at(i);
|
const Mapsforge::RasterTile &mt = tiles.at(i);
|
||||||
if (mt.isValid())
|
if (!mt.pixmap().isNull())
|
||||||
QPixmapCache::insert(key(mt.zoom(), mt.xy()), mt.pixmap());
|
QPixmapCache::insert(key(mt.zoom(), mt.xy()), mt.pixmap());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +188,8 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
painter->drawPixmap(ttl, pm);
|
painter->drawPixmap(ttl, pm);
|
||||||
else {
|
else {
|
||||||
tiles.append(RasterTile(_projection, _transform, &_style, &_data,
|
tiles.append(RasterTile(_projection, _transform, &_style, &_data,
|
||||||
_zoom, QRect(ttl, QSize(tileSize, tileSize)), _tileRatio));
|
_zoom, QRect(ttl, QSize(tileSize, tileSize)), _tileRatio,
|
||||||
|
flags & Map::HillShading));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user