mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-07-14 19:04:23 +02:00
Compare commits
68 Commits
Author | SHA1 | Date | |
---|---|---|---|
66036f6cd7 | |||
dfda3a6630 | |||
96e762beb5 | |||
b4be5ea206 | |||
56c77df176 | |||
1871f85acc | |||
3ec636632f | |||
5e1af275b8 | |||
cd220216dd | |||
0d6b02f466 | |||
059c515175 | |||
1dc963b133 | |||
f0036bfd28 | |||
688861bf65 | |||
c449024584 | |||
41188360bf | |||
1086a74f99 | |||
7b5a1c701d | |||
9afeaf672a | |||
5ddd63e697 | |||
88fa1ed786 | |||
1233d20a21 | |||
1746eddb8d | |||
ecda5103c8 | |||
50b0ff1c56 | |||
2b300fab54 | |||
961061b643 | |||
8bebea53ad | |||
c3b484bb75 | |||
d6d43baec5 | |||
c6c3e0978c | |||
320b04c3fa | |||
ab7185bd25 | |||
822a0c2866 | |||
a92d6efec6 | |||
4615709b99 | |||
8a72b20af8 | |||
f86aa8c012 | |||
e351eb6370 | |||
81e967f20d | |||
dbf5828e65 | |||
cf81a90865 | |||
37d408c953 | |||
61c3ed60d7 | |||
04c203625f | |||
d0cea97c90 | |||
ddc7eb7149 | |||
bb22ad95b7 | |||
682fcc09cc | |||
60e83b24f9 | |||
c30501185c | |||
9b3c11cc68 | |||
61f77ef19e | |||
c0834491d3 | |||
e6fdd0f53d | |||
fe444e88a3 | |||
d9c0770b51 | |||
3a0e9bb733 | |||
ca6c7247c0 | |||
0b25cb9f81 | |||
190a961242 | |||
ccfb748404 | |||
b19c3a83f3 | |||
a4a54101a3 | |||
728361ad7b | |||
af58893cbe | |||
97e12d809f | |||
f5e3e5bd21 |
@ -1,23 +1,23 @@
|
||||
version: 13.0.{build}
|
||||
version: 13.5.{build}
|
||||
|
||||
configuration:
|
||||
- Release
|
||||
|
||||
image:
|
||||
- Visual Studio 2019
|
||||
- Visual Studio 2022
|
||||
|
||||
environment:
|
||||
NSISDIR: C:\Program Files (x86)\NSIS
|
||||
OPENSSLDIR: C:\OpenSSL-v111-Win64\bin
|
||||
matrix:
|
||||
- QTDIR: C:\Qt\5.15\msvc2019_64
|
||||
- QTDIR: C:\Qt\6.4\msvc2019_64
|
||||
- QTDIR: C:\Qt\6.5\msvc2019_64
|
||||
NSISDEF: /DQT6
|
||||
|
||||
install:
|
||||
- cmd: |-
|
||||
set PATH=%QTDIR%\bin;%NSISDIR%;%PATH%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat
|
||||
|
||||
build_script:
|
||||
- cmd: |-
|
||||
|
4
.github/workflows/osx.yml
vendored
4
.github/workflows/osx.yml
vendored
@ -39,12 +39,12 @@ jobs:
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.4.3'
|
||||
version: '6.5.1'
|
||||
modules: qtpositioning qt5compat qtserialport
|
||||
- name: Create localization
|
||||
run: lrelease gpxsee.pro
|
||||
- name: Configure build
|
||||
run: qmake gpxsee.pro
|
||||
run: qmake gpxsee.pro QMAKE_APPLE_DEVICE_ARCHS="x86_64h arm64"
|
||||
- name: Build project
|
||||
run: make -j3
|
||||
- name: Create DMG
|
||||
|
@ -3,7 +3,8 @@ unix:!macx:!android {
|
||||
} else {
|
||||
TARGET = GPXSee
|
||||
}
|
||||
VERSION = 13.0
|
||||
VERSION = 13.5
|
||||
|
||||
|
||||
QT += core \
|
||||
gui \
|
||||
|
@ -55,6 +55,11 @@
|
||||
<file alias="transform-move_32@2x.png">icons/GUI/transform-move_32@2x.png</file>
|
||||
</qresource>
|
||||
|
||||
<!-- Common map stuff -->
|
||||
<qresource prefix="/map">
|
||||
<file alias="arrow.png">icons/map/arrow.png</file>
|
||||
</qresource>
|
||||
|
||||
<!-- POIs (IMG & ENC style) -->
|
||||
<qresource prefix="/POI">
|
||||
<file alias="airfield-11.png">icons/map/POI/airfield-11.png</file>
|
||||
@ -198,6 +203,9 @@
|
||||
<file alias="building.png">icons/map/marine/building.png</file>
|
||||
<file alias="fog-signal.png">icons/map/marine/fog-signal.png</file>
|
||||
<file alias="construction.png">icons/map/marine/construction.png</file>
|
||||
<file alias="radio-call.png">icons/map/marine/radio-call.png</file>
|
||||
<file alias="current.png">icons/map/marine/current.png</file>
|
||||
<file alias="rescue-station.png">icons/map/marine/rescue-station.png</file>
|
||||
</qresource>
|
||||
|
||||
<!-- Mapsforge rendertheme -->
|
||||
|
BIN
icons/map/arrow.png
Normal file
BIN
icons/map/arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 B |
BIN
icons/map/marine/current.png
Normal file
BIN
icons/map/marine/current.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 B |
BIN
icons/map/marine/radio-call.png
Normal file
BIN
icons/map/marine/radio-call.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 214 B |
BIN
icons/map/marine/rescue-station.png
Normal file
BIN
icons/map/marine/rescue-station.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 228 B |
@ -866,7 +866,7 @@
|
||||
<location filename="../src/GUI/gui.cpp" line="907"/>
|
||||
<location filename="../src/GUI/gui.cpp" line="925"/>
|
||||
<source>CRS directory:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Directori CRS:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="909"/>
|
||||
@ -1020,6 +1020,7 @@
|
||||
<translation>
|
||||
<numerusform>%n fitxer</numerusform>
|
||||
<numerusform>%n fitxers</numerusform>
|
||||
<numerusform>%n fitxers</numerusform>
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
|
@ -712,7 +712,7 @@
|
||||
<location filename="../src/GUI/gui.cpp" line="907"/>
|
||||
<location filename="../src/GUI/gui.cpp" line="925"/>
|
||||
<source>CRS directory:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>CRS-katalog:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="913"/>
|
||||
|
@ -958,7 +958,7 @@
|
||||
<location filename="../src/GUI/gui.cpp" line="907"/>
|
||||
<location filename="../src/GUI/gui.cpp" line="925"/>
|
||||
<source>CRS directory:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Dossier CRS :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="915"/>
|
||||
@ -1427,12 +1427,12 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="70"/>
|
||||
<source>Select the proper coordinate reference system (CRS) of maps without a CRS definition (JNX, KMZ and World file maps).</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation type="unfinished">Sélectionnez le système de référence de coordonnée (CRS) approprié pour les cartes sans définition de CRS (JNX, KMZ et World file maps).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="73"/>
|
||||
<source>Select the desired projection of vector maps (IMG, Mapsforge and ENC maps). The projection must be valid for the whole map area.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Sélectionnez la projection désirée de la carte vectorielle (IMG, Mapsforge et carte ENC). La projection doit être valide pour la totalité de la zone de la carte.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="77"/>
|
||||
@ -1912,7 +1912,7 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="758"/>
|
||||
<source>DEM cache size:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Taille du cache DEM :</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="778"/>
|
||||
|
@ -712,7 +712,7 @@
|
||||
<location filename="../src/GUI/gui.cpp" line="907"/>
|
||||
<location filename="../src/GUI/gui.cpp" line="925"/>
|
||||
<source>CRS directory:</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>CRS-mappe:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/gui.cpp" line="913"/>
|
||||
@ -1718,12 +1718,12 @@
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="70"/>
|
||||
<source>Select the proper coordinate reference system (CRS) of maps without a CRS definition (JNX, KMZ and World file maps).</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Velg riktig koordinatreferansesystem (CRS) for kart uten en CRS-definisjon (JNX, KMZ og World-file kart).</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="73"/>
|
||||
<source>Select the desired projection of vector maps (IMG, Mapsforge and ENC maps). The projection must be valid for the whole map area.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
<translation>Velg ønsket projeksjon for vektorkart (IMG, Mapsforge og ENC-kart). Projeksjonen må være gyldig for hele kartområdet.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/GUI/optionsdialog.cpp" line="104"/>
|
||||
|
@ -37,7 +37,7 @@ Unicode true
|
||||
; The name of the installer
|
||||
Name "GPXSee"
|
||||
; Program version
|
||||
!define VERSION "13.0"
|
||||
!define VERSION "13.5"
|
||||
|
||||
; The file to write
|
||||
OutFile "GPXSee-${VERSION}_x64.exe"
|
||||
|
@ -25,7 +25,6 @@ ToolTip AreaItem::info() const
|
||||
AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
|
||||
: PlaneItem(parent), _area(area)
|
||||
{
|
||||
_map = map;
|
||||
_digitalZoom = 0;
|
||||
_width = 2;
|
||||
_opacity = 0.5;
|
||||
@ -35,34 +34,34 @@ AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
|
||||
_pen = QPen(strokeColor(), width());
|
||||
_brush = QBrush(fillColor());
|
||||
|
||||
updatePainterPath();
|
||||
updatePainterPath(map);
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
QPainterPath AreaItem::painterPath(const Polygon &polygon)
|
||||
QPainterPath AreaItem::painterPath(Map *map, const Polygon &polygon)
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
|
||||
path.moveTo(_map->ll2xy(subpath.first()));
|
||||
path.moveTo(map->ll2xy(subpath.first()));
|
||||
for (int j = 1; j < subpath.size(); j++)
|
||||
path.lineTo(_map->ll2xy(subpath.at(j)));
|
||||
path.lineTo(map->ll2xy(subpath.at(j)));
|
||||
path.closeSubpath();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void AreaItem::updatePainterPath()
|
||||
void AreaItem::updatePainterPath(Map *map)
|
||||
{
|
||||
_painterPath = QPainterPath();
|
||||
|
||||
for (int i = 0; i < _area.polygons().size(); i++)
|
||||
_painterPath.addPath(painterPath(_area.polygons().at(i)));
|
||||
_painterPath.addPath(painterPath(map, _area.polygons().at(i)));
|
||||
}
|
||||
|
||||
void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
@ -85,10 +84,7 @@ void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
void AreaItem::setMap(Map *map)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
_map = map;
|
||||
|
||||
updatePainterPath();
|
||||
updatePainterPath(map);
|
||||
}
|
||||
|
||||
const QColor &AreaItem::strokeColor() const
|
||||
|
@ -33,8 +33,8 @@ protected:
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
|
||||
|
||||
private:
|
||||
QPainterPath painterPath(const Polygon &polygon);
|
||||
void updatePainterPath();
|
||||
QPainterPath painterPath(Map *map, const Polygon &polygon);
|
||||
void updatePainterPath(Map *map);
|
||||
void updateColor();
|
||||
void updateWidth();
|
||||
void updatePenStyle();
|
||||
@ -45,8 +45,6 @@ private:
|
||||
|
||||
Area _area;
|
||||
|
||||
Map *_map;
|
||||
|
||||
qreal _width;
|
||||
QColor _color;
|
||||
qreal _opacity;
|
||||
|
@ -224,6 +224,12 @@ qreal GraphItem::timeAtDistance(qreal distance) const
|
||||
return l.pointAt((distance - l.p1().x()) / (l.p2().x() - l.p1().x())).y();
|
||||
}
|
||||
|
||||
GraphItem::SegmentTime GraphItem::date(qreal x)
|
||||
{
|
||||
const GraphSegment *seg = segment(x, _type);
|
||||
return seg ? SegmentTime(seg->start(), seg->first().t()) : SegmentTime();
|
||||
}
|
||||
|
||||
void GraphItem::hover(bool hover)
|
||||
{
|
||||
if (hover) {
|
||||
|
@ -12,6 +12,16 @@ class GraphItem : public QObject, public GraphicsItem
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct SegmentTime
|
||||
{
|
||||
SegmentTime() : time(NAN) {}
|
||||
SegmentTime(const QDateTime &date, qreal time)
|
||||
: date(date), time(time) {}
|
||||
|
||||
QDateTime date;
|
||||
qreal time;
|
||||
};
|
||||
|
||||
GraphItem(const Graph &graph, GraphType type, int width,
|
||||
const QColor &color, Qt::PenStyle style, QGraphicsItem *parent = 0);
|
||||
virtual ~GraphItem() {}
|
||||
@ -43,6 +53,7 @@ public:
|
||||
qreal yAtX(qreal x) const;
|
||||
qreal distanceAtTime(qreal time) const;
|
||||
qreal timeAtDistance(qreal distance) const;
|
||||
SegmentTime date(qreal x);
|
||||
|
||||
void redraw();
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <QGraphicsScene>
|
||||
#include <QEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QGestureEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QGraphicsSimpleTextItem>
|
||||
#include <QPalette>
|
||||
@ -37,6 +38,8 @@ GraphView::GraphView(QWidget *parent)
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
setBackgroundBrush(QBrush(palette().brush(QPalette::Base)));
|
||||
viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
|
||||
grabGesture(Qt::PinchGesture);
|
||||
|
||||
_xAxis = new AxisItem(AxisItem::X);
|
||||
_xAxis->setZValue(1.0);
|
||||
@ -381,6 +384,27 @@ void GraphView::wheelEvent(QWheelEvent *e)
|
||||
QGraphicsView::wheelEvent(e);
|
||||
}
|
||||
|
||||
void GraphView::pinchGesture(QPinchGesture *gesture)
|
||||
{
|
||||
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
|
||||
|
||||
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
|
||||
QPointF pos = mapToScene(gesture->centerPoint().toPoint());
|
||||
QRectF gr(_grid->boundingRect());
|
||||
QPointF r(pos.x() / gr.width(), pos.y() / gr.height());
|
||||
|
||||
_zoom = qMax(_zoom * gesture->scaleFactor(), 1.0);
|
||||
redraw();
|
||||
|
||||
QRectF ngr(_grid->boundingRect());
|
||||
QPointF npos(mapFromScene(QPointF(r.x() * ngr.width(),
|
||||
r.y() * ngr.height())));
|
||||
QScrollBar *sb = horizontalScrollBar();
|
||||
sb->setSliderPosition(sb->sliderPosition() + npos.x()
|
||||
- gesture->centerPoint().x());
|
||||
}
|
||||
}
|
||||
|
||||
void GraphView::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QRectF viewRect(mapToScene(rect()).boundingRect());
|
||||
@ -577,3 +601,19 @@ void GraphView::changeEvent(QEvent *e)
|
||||
|
||||
QGraphicsView::changeEvent(e);
|
||||
}
|
||||
|
||||
bool GraphView::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::Gesture)
|
||||
return gestureEvent(static_cast<QGestureEvent*>(event));
|
||||
|
||||
return QGraphicsView::event(event);
|
||||
}
|
||||
|
||||
bool GraphView::gestureEvent(QGestureEvent *event)
|
||||
{
|
||||
if (QGesture *pinch = event->gesture(Qt::PinchGesture))
|
||||
pinchGesture(static_cast<QPinchGesture *>(pinch));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ class PathItem;
|
||||
class GridItem;
|
||||
class QGraphicsSimpleTextItem;
|
||||
class GraphicsScene;
|
||||
class QGestureEvent;
|
||||
class QPinchGesture;
|
||||
|
||||
class GraphView : public QGraphicsView
|
||||
{
|
||||
@ -59,6 +61,7 @@ protected:
|
||||
void wheelEvent(QWheelEvent *e);
|
||||
void changeEvent(QEvent *e);
|
||||
void paintEvent(QPaintEvent *e);
|
||||
bool event(QEvent *event);
|
||||
|
||||
const QString &yLabel() const {return _yLabel;}
|
||||
const QString &yUnits() const {return _yUnits;}
|
||||
@ -94,6 +97,8 @@ private:
|
||||
void removeItem(QGraphicsItem *item);
|
||||
void addItem(QGraphicsItem *item);
|
||||
bool singleGraph() const;
|
||||
bool gestureEvent(QGestureEvent *event);
|
||||
void pinchGesture(QPinchGesture *gesture);
|
||||
|
||||
GraphicsScene *_scene;
|
||||
|
||||
|
@ -1721,8 +1721,7 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
|
||||
|
||||
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
|
||||
{
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(fileName));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
|
||||
return loadMapNode(maps, action, silent, existingActions);
|
||||
@ -1812,8 +1811,7 @@ void GUI::loadMapDir()
|
||||
return;
|
||||
|
||||
QFileInfo fi(dir);
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(dir));
|
||||
QList<QAction*> existingActions(_mapsActionGroup->actions());
|
||||
QList<MapAction*> actions;
|
||||
QMenu *menu = new QMenu(maps.name());
|
||||
@ -2741,13 +2739,9 @@ void GUI::loadOptions()
|
||||
_mapView->setPOIColor(_options.poiColor);
|
||||
_mapView->setRenderHint(QPainter::Antialiasing, _options.pathAntiAliasing);
|
||||
_mapView->setMarkerColor(_options.sliderColor);
|
||||
if (_options.useOpenGL)
|
||||
_mapView->useOpenGL(true);
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
_mapView->setOutputProjection(CRS::projection(4326,
|
||||
_options.outputProjection));
|
||||
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
|
||||
_mapView->useOpenGL(_options.useOpenGL);
|
||||
_mapView->setMapConfig(CRS::projection(_options.inputProjection),
|
||||
CRS::projection(4326, _options.outputProjection), _options.hidpiMap);
|
||||
_mapView->setTimeZone(_options.timeZone.zone());
|
||||
_mapView->setPositionSource(_positionSource);
|
||||
|
||||
@ -2856,14 +2850,12 @@ void GUI::updateOptions(const Options &options)
|
||||
_positionSource = source;
|
||||
}
|
||||
|
||||
if (options.hidpiMap != _options.hidpiMap)
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
if (options.outputProjection != _options.outputProjection)
|
||||
_mapView->setOutputProjection(CRS::projection(4326,
|
||||
options.outputProjection));
|
||||
if (options.inputProjection != _options.inputProjection)
|
||||
_mapView->setInputProjection(CRS::projection(options.inputProjection));
|
||||
if (options.hidpiMap != _options.hidpiMap
|
||||
|| options.outputProjection != _options.outputProjection
|
||||
|| options.inputProjection != _options.inputProjection)
|
||||
_mapView->setMapConfig(CRS::projection(options.inputProjection),
|
||||
CRS::projection(4326, options.outputProjection), options.hidpiMap);
|
||||
|
||||
if (options.timeZone != _options.timeZone) {
|
||||
_mapView->setTimeZone(options.timeZone.zone());
|
||||
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
|
||||
@ -2941,8 +2933,7 @@ void GUI::loadInitialMaps(const QString &selected)
|
||||
if (mapDir.isNull())
|
||||
return;
|
||||
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir,
|
||||
CRS::projection(_options.inputProjection)));
|
||||
TreeNode<Map*> maps(MapList::loadMaps(mapDir));
|
||||
createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd);
|
||||
|
||||
// Select the active map according to the user settings
|
||||
@ -3044,8 +3035,7 @@ void GUI::show()
|
||||
|
||||
void GUI::screenChanged(QScreen *screen)
|
||||
{
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF());
|
||||
|
||||
disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this,
|
||||
SLOT(logicalDotsPerInchChanged(qreal)));
|
||||
@ -3057,6 +3047,5 @@ void GUI::logicalDotsPerInchChanged(qreal dpi)
|
||||
{
|
||||
Q_UNUSED(dpi)
|
||||
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF(),
|
||||
_options.hidpiMap ? devicePixelRatioF() : 1.0);
|
||||
_mapView->setDevicePixelRatio(devicePixelRatioF());
|
||||
}
|
||||
|
@ -81,19 +81,18 @@ ToolTip MapItem::info() const
|
||||
return tt;
|
||||
}
|
||||
|
||||
MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
|
||||
: PlaneItem(parent)
|
||||
MapItem::MapItem(MapAction *action, Map *map, const Projection &proj,
|
||||
GraphicsItem *parent) : PlaneItem(parent)
|
||||
{
|
||||
Map *src = action->data().value<Map*>();
|
||||
Q_ASSERT(map->isReady());
|
||||
|
||||
_name = src->name();
|
||||
_fileName = src->path();
|
||||
_bounds = src->llBounds();
|
||||
_bounds = src->llBounds(proj);
|
||||
|
||||
connect(this, &MapItem::triggered, action, &MapAction::trigger);
|
||||
|
||||
_map = map;
|
||||
_digitalZoom = 0;
|
||||
|
||||
_width = 2;
|
||||
@ -101,23 +100,23 @@ MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
|
||||
QBrush brush(Qt::SolidPattern);
|
||||
_pen = QPen(brush, _width);
|
||||
|
||||
updatePainterPath();
|
||||
updatePainterPath(map);
|
||||
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
|
||||
void MapItem::updatePainterPath()
|
||||
void MapItem::updatePainterPath(Map *map)
|
||||
{
|
||||
_painterPath = QPainterPath();
|
||||
|
||||
QRectF r(bbox(_bounds, _map));
|
||||
QRectF r(bbox(_bounds, map));
|
||||
|
||||
if (r.left() > r.right()) {
|
||||
QRectF r1(bbox(RectC(_bounds.topLeft(),
|
||||
Coordinates(180, _bounds.bottomRight().lat())), _map));
|
||||
Coordinates(180, _bounds.bottomRight().lat())), map));
|
||||
QRectF r2(bbox(RectC(Coordinates(-180, _bounds.topLeft().lat()),
|
||||
_bounds.bottomRight()), _map));
|
||||
_bounds.bottomRight()), map));
|
||||
|
||||
_painterPath.addRect(r1);
|
||||
_painterPath.addRect(r2);
|
||||
@ -143,10 +142,7 @@ void MapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
void MapItem::setMap(Map *map)
|
||||
{
|
||||
prepareGeometryChange();
|
||||
|
||||
_map = map;
|
||||
|
||||
updatePainterPath();
|
||||
updatePainterPath(map);
|
||||
}
|
||||
|
||||
void MapItem::setColor(const QColor &color)
|
||||
|
@ -4,13 +4,15 @@
|
||||
#include "planeitem.h"
|
||||
|
||||
class MapAction;
|
||||
class Projection;
|
||||
|
||||
class MapItem : public QObject, public PlaneItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MapItem(MapAction *action, Map *map, GraphicsItem *parent = 0);
|
||||
MapItem(MapAction *action, Map *map, const Projection &proj,
|
||||
GraphicsItem *parent = 0);
|
||||
|
||||
QPainterPath shape() const {return _painterPath;}
|
||||
QRectF boundingRect() const {return _painterPath.boundingRect();}
|
||||
@ -37,13 +39,12 @@ protected:
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
|
||||
|
||||
private:
|
||||
void updatePainterPath();
|
||||
void updatePainterPath(Map *map);
|
||||
|
||||
RectC _bounds;
|
||||
QString _name;
|
||||
QString _fileName;
|
||||
|
||||
Map *_map;
|
||||
int _digitalZoom;
|
||||
|
||||
qreal _width;
|
||||
|
@ -60,12 +60,12 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent)
|
||||
_cursorCoordinates->setVisible(false);
|
||||
_scene->addItem(_cursorCoordinates);
|
||||
|
||||
_deviceRatio = devicePixelRatioF();
|
||||
_outputProjection = PCS::pcs(3857);
|
||||
_inputProjection = GCS::gcs(4326);
|
||||
_hidpi = true;
|
||||
_map = map;
|
||||
_map->load();
|
||||
_map->setOutputProjection(_outputProjection);
|
||||
_map->setInputProjection(_inputProjection);
|
||||
_map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
|
||||
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
|
||||
|
||||
_poi = poi;
|
||||
@ -119,8 +119,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent)
|
||||
_showPositionCoordinates = false;
|
||||
_showMotionInfo = false;
|
||||
|
||||
_deviceRatio = 1.0;
|
||||
_mapRatio = 1.0;
|
||||
_opengl = false;
|
||||
_plot = false;
|
||||
_digitalZoom = 0;
|
||||
@ -247,7 +245,7 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
|
||||
|
||||
MapItem *MapView::addMap(MapAction *map)
|
||||
{
|
||||
MapItem *mi = new MapItem(map, _map);
|
||||
MapItem *mi = new MapItem(map, _map, _inputProjection);
|
||||
mi->setColor(_palette.nextColor());
|
||||
mi->setWidth(_areaWidth);
|
||||
mi->setPenStyle(_areaStyle);
|
||||
@ -328,7 +326,7 @@ int MapView::fitMapZoom() const
|
||||
RectC br = _tr | _rr | _wr | _ar;
|
||||
|
||||
return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
|
||||
br.isNull() ? _map->llBounds() : br);
|
||||
br.isNull() ? _map->llBounds(_inputProjection) : br);
|
||||
}
|
||||
|
||||
QPointF MapView::contentCenter() const
|
||||
@ -402,36 +400,18 @@ void MapView::setMap(Map *map)
|
||||
.intersected(_map->bounds()));
|
||||
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
||||
|
||||
_map->unload();
|
||||
disconnect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
|
||||
_map->unload();
|
||||
|
||||
_map = map;
|
||||
_map->load();
|
||||
_map->setOutputProjection(_outputProjection);
|
||||
_map->setInputProjection(_inputProjection);
|
||||
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
|
||||
_map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
|
||||
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
|
||||
|
||||
digitalZoom(0);
|
||||
|
||||
_map->zoomFit(viewport()->rect().size(), cr);
|
||||
_scene->setSceneRect(_map->bounds());
|
||||
|
||||
for (int i = 0; i < _tracks.size(); i++)
|
||||
_tracks.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _routes.size(); i++)
|
||||
_routes.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _areas.size(); i++)
|
||||
_areas.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _waypoints.size(); i++)
|
||||
_waypoints.at(i)->setMap(_map);
|
||||
|
||||
for (POIHash::const_iterator it = _pois.constBegin();
|
||||
it != _pois.constEnd(); it++)
|
||||
it.value()->setMap(_map);
|
||||
updatePOIVisibility();
|
||||
|
||||
_crosshair->setMap(_map);
|
||||
rescale();
|
||||
|
||||
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
|
||||
_map->ll2xy(cr.bottomRight())).center();
|
||||
@ -702,8 +682,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
PlotFlags flags)
|
||||
{
|
||||
QRect orig, adj;
|
||||
qreal mapRatio, ratio, diff, q, p;
|
||||
qreal ratio, diff, q, p;
|
||||
QPointF scenePos, scalePos, posPos, motionPos;
|
||||
bool hidpi = _hidpi && _deviceRatio > 1.0;
|
||||
int zoom;
|
||||
|
||||
|
||||
@ -728,8 +709,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
}
|
||||
|
||||
// Expand the view if plotting into a bitmap
|
||||
mapRatio = _mapRatio;
|
||||
setDevicePixelRatio(_deviceRatio, 1.0);
|
||||
if (hidpi)
|
||||
setHidpi(false);
|
||||
|
||||
if (flags & Expand) {
|
||||
qreal xdiff = (target.width() - adj.width()) / 2.0;
|
||||
@ -784,7 +765,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
|
||||
centerOn(scenePos);
|
||||
}
|
||||
|
||||
setDevicePixelRatio(_deviceRatio, mapRatio);
|
||||
if (hidpi)
|
||||
setHidpi(true);
|
||||
|
||||
_mapScale->setDigitalZoom(_digitalZoom);
|
||||
_mapScale->setPos(scalePos);
|
||||
@ -1236,6 +1218,9 @@ bool MapView::gestureEvent(QGestureEvent *event)
|
||||
|
||||
void MapView::useOpenGL(bool use)
|
||||
{
|
||||
if (_opengl == use)
|
||||
return;
|
||||
|
||||
_opengl = use;
|
||||
|
||||
if (use)
|
||||
@ -1286,60 +1271,21 @@ void MapView::reloadMap()
|
||||
_scene->invalidate();
|
||||
}
|
||||
|
||||
void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
void MapView::setMapConfig(const Projection &in, const Projection &out,
|
||||
bool hidpi)
|
||||
{
|
||||
if (_deviceRatio == deviceRatio && _mapRatio == mapRatio)
|
||||
return;
|
||||
_inputProjection = in;
|
||||
_outputProjection = out;
|
||||
_hidpi = hidpi;
|
||||
|
||||
_deviceRatio = deviceRatio;
|
||||
_mapRatio = mapRatio;
|
||||
|
||||
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
|
||||
.intersected(_map->bounds()));
|
||||
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
||||
|
||||
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
|
||||
_scene->setSceneRect(_map->bounds());
|
||||
|
||||
for (int i = 0; i < _tracks.size(); i++)
|
||||
_tracks.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _routes.size(); i++)
|
||||
_routes.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _areas.size(); i++)
|
||||
_areas.at(i)->setMap(_map);
|
||||
for (int i = 0; i < _waypoints.size(); i++)
|
||||
_waypoints.at(i)->setMap(_map);
|
||||
|
||||
for (POIHash::const_iterator it = _pois.constBegin();
|
||||
it != _pois.constEnd(); it++)
|
||||
it.value()->setMap(_map);
|
||||
updatePOIVisibility();
|
||||
|
||||
_crosshair->setMap(_map);
|
||||
|
||||
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
|
||||
_map->ll2xy(cr.bottomRight())).center();
|
||||
centerOn(nc);
|
||||
|
||||
reloadMap();
|
||||
setMap(_map);
|
||||
}
|
||||
|
||||
void MapView::setOutputProjection(const Projection &proj)
|
||||
void MapView::setDevicePixelRatio(qreal ratio)
|
||||
{
|
||||
_outputProjection = proj;
|
||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
||||
_map->setOutputProjection(_outputProjection);
|
||||
rescale();
|
||||
centerOn(_map->ll2xy(center));
|
||||
}
|
||||
_deviceRatio = ratio;
|
||||
|
||||
void MapView::setInputProjection(const Projection &proj)
|
||||
{
|
||||
_inputProjection = proj;
|
||||
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
|
||||
_map->setInputProjection(_inputProjection);
|
||||
rescale();
|
||||
centerOn(_map->ll2xy(center));
|
||||
setMap(_map);
|
||||
}
|
||||
|
||||
void MapView::fitContentToSize()
|
||||
@ -1436,3 +1382,20 @@ void MapView::drawInfoBackground(bool draw)
|
||||
_positionCoordinates->drawBackground(draw);
|
||||
_motionInfo->drawBackground(draw);
|
||||
}
|
||||
|
||||
void MapView::setHidpi(bool hidpi)
|
||||
{
|
||||
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
|
||||
.intersected(_map->bounds()));
|
||||
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
|
||||
|
||||
_map->unload();
|
||||
_map->load(_inputProjection, _outputProjection, _deviceRatio, hidpi);
|
||||
rescale();
|
||||
|
||||
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
|
||||
_map->ll2xy(cr.bottomRight())).center();
|
||||
centerOn(nc);
|
||||
|
||||
reloadMap();
|
||||
}
|
||||
|
@ -92,9 +92,8 @@ public:
|
||||
void useAntiAliasing(bool use);
|
||||
void setCoordinatesFormat(CoordinatesFormat format);
|
||||
void setTimeZone(const QTimeZone &zone);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void setOutputProjection(const Projection &proj);
|
||||
void setInputProjection(const Projection &proj);
|
||||
void setMapConfig(const Projection &in, const Projection &out, bool hidpi);
|
||||
void setDevicePixelRatio(qreal ratio);
|
||||
void clearMapCache();
|
||||
void fitContentToSize();
|
||||
|
||||
@ -156,6 +155,7 @@ private:
|
||||
bool gestureEvent(QGestureEvent *event);
|
||||
void pinchGesture(QPinchGesture *gesture);
|
||||
void skipColor() {_palette.nextColor();}
|
||||
void setHidpi(bool hidpi);
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
@ -209,7 +209,7 @@ private:
|
||||
QCursor _cursor;
|
||||
|
||||
qreal _deviceRatio;
|
||||
qreal _mapRatio;
|
||||
bool _hidpi;
|
||||
bool _opengl;
|
||||
|
||||
int _pinchZoom;
|
||||
|
@ -334,12 +334,18 @@ void PathItem::setMarkerPosition(qreal pos)
|
||||
void PathItem::setMarkerInfo(qreal pos)
|
||||
{
|
||||
if (_markerInfoType == MarkerInfoItem::Date) {
|
||||
qreal time = _graph
|
||||
? (_graph->graphType() == Time) ? pos : _graph->timeAtDistance(pos)
|
||||
: NAN;
|
||||
QDateTime d(date());
|
||||
if (!std::isnan(time) && d.isValid())
|
||||
_markerInfo->setDate(d.addSecs(time).toTimeZone(_timeZone));
|
||||
QDateTime date;
|
||||
|
||||
if (_graph) {
|
||||
qreal time = (_graph->graphType() == Time)
|
||||
? pos : _graph->timeAtDistance(pos);
|
||||
GraphItem::SegmentTime st(_graph->date(pos));
|
||||
if (st.date.isValid() && !std::isnan(time))
|
||||
date = st.date.addSecs(time - st.time);
|
||||
}
|
||||
|
||||
if (date.isValid())
|
||||
_markerInfo->setDate(date.toTimeZone(_timeZone));
|
||||
else
|
||||
_markerInfo->setDate(QDateTime());
|
||||
} else if (_markerInfoType == MarkerInfoItem::Position)
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <QDebug>
|
||||
#include "hash.h"
|
||||
|
||||
#define deg2rad(d) (((d)*M_PI)/180.0)
|
||||
#define rad2deg(d) (((d)*180.0)/M_PI)
|
||||
@ -48,6 +49,11 @@ inline bool operator<(const Coordinates &c1, const Coordinates &c2)
|
||||
return (c1.lat() < c2.lat());
|
||||
}
|
||||
|
||||
inline HASH_T qHash(const Coordinates &c)
|
||||
{
|
||||
return qHash(QPair<double, double>(c.lon(), c.lat()));
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
QDebug operator<<(QDebug dbg, const Coordinates &c);
|
||||
#endif // QT_NO_DEBUG
|
||||
|
@ -53,7 +53,7 @@ Authorization::Authorization(const QString &username, const QString &password)
|
||||
{
|
||||
QString concatenated = username + ":" + password;
|
||||
QByteArray data = concatenated.toLocal8Bit().toBase64();
|
||||
_header = "Basic " + data;
|
||||
_header = HTTPHeader("Authorization", "Basic " + data);
|
||||
}
|
||||
|
||||
NetworkTimeout::NetworkTimeout(int timeout, QNetworkReply *reply)
|
||||
@ -83,9 +83,10 @@ QNetworkAccessManager *Downloader::_manager = 0;
|
||||
int Downloader::_timeout = 30;
|
||||
bool Downloader::_http2 = true;
|
||||
|
||||
bool Downloader::doDownload(const Download &dl, const Authorization &auth)
|
||||
bool Downloader::doDownload(const Download &dl, const QList<HTTPHeader> &headers)
|
||||
{
|
||||
const QUrl &url = dl.url();
|
||||
bool userAgent = false;
|
||||
|
||||
if (!url.isValid() || !(url.scheme() == QLatin1String("http")
|
||||
|| url.scheme() == QLatin1String("https"))) {
|
||||
@ -103,9 +104,15 @@ bool Downloader::doDownload(const Download &dl, const Authorization &auth)
|
||||
request.setAttribute(ATTR_REDIRECT_POLICY,
|
||||
QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||
request.setAttribute(ATTR_HTTP2_ALLOWED, QVariant(_http2));
|
||||
request.setRawHeader("User-Agent", USER_AGENT);
|
||||
if (!auth.isNull())
|
||||
request.setRawHeader("Authorization", auth.header());
|
||||
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
const HTTPHeader &hdr = headers.at(i);
|
||||
request.setRawHeader(hdr.key(), hdr.value());
|
||||
if (hdr.key() == "User-Agent")
|
||||
userAgent = true;
|
||||
}
|
||||
if (!userAgent)
|
||||
request.setRawHeader("User-Agent", USER_AGENT);
|
||||
|
||||
QFile *file = new QFile(tmpName(dl.file()));
|
||||
if (!file->open(QIODevice::WriteOnly)) {
|
||||
@ -183,12 +190,12 @@ void Downloader::downloadFinished(QNetworkReply *reply)
|
||||
}
|
||||
|
||||
bool Downloader::get(const QList<Download> &list,
|
||||
const Authorization &authorization)
|
||||
const QList<HTTPHeader> &headers)
|
||||
{
|
||||
bool finishEmitted = false;
|
||||
|
||||
for (int i = 0; i < list.count(); i++)
|
||||
finishEmitted |= doDownload(list.at(i), authorization);
|
||||
finishEmitted |= doDownload(list.at(i), headers);
|
||||
|
||||
return finishEmitted;
|
||||
}
|
||||
|
@ -7,9 +7,12 @@
|
||||
#include <QUrl>
|
||||
#include <QList>
|
||||
#include <QHash>
|
||||
#include "common/kv.h"
|
||||
|
||||
class QFile;
|
||||
|
||||
typedef KV<QByteArray, QByteArray> HTTPHeader;
|
||||
|
||||
class Download
|
||||
{
|
||||
public:
|
||||
@ -29,11 +32,11 @@ public:
|
||||
Authorization() {}
|
||||
Authorization(const QString &username, const QString &password);
|
||||
|
||||
bool isNull() const {return _header.isNull();}
|
||||
const QByteArray &header() const {return _header;}
|
||||
const HTTPHeader &header() const {return _header;}
|
||||
bool isNull() const {return _header.key().isNull();}
|
||||
|
||||
private:
|
||||
QByteArray _header;
|
||||
HTTPHeader _header;
|
||||
};
|
||||
|
||||
class NetworkTimeout : public QObject
|
||||
@ -60,8 +63,7 @@ class Downloader : public QObject
|
||||
public:
|
||||
Downloader(QObject *parent = 0) : QObject(parent) {}
|
||||
|
||||
bool get(const QList<Download> &list, const Authorization &authorization
|
||||
= Authorization());
|
||||
bool get(const QList<Download> &list, const QList<HTTPHeader> &headers);
|
||||
void clearErrors() {_errorDownloads.clear();}
|
||||
|
||||
static void setNetworkManager(QNetworkAccessManager *manager)
|
||||
@ -80,7 +82,7 @@ private:
|
||||
class ReplyTimeout;
|
||||
|
||||
void insertError(const QUrl &url, QNetworkReply::NetworkError error);
|
||||
bool doDownload(const Download &dl, const Authorization &auth);
|
||||
bool doDownload(const Download &dl, const QList<HTTPHeader> &headers);
|
||||
void downloadFinished(QNetworkReply *reply);
|
||||
void readData(QNetworkReply *reply);
|
||||
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
#define HASH_T uint
|
||||
|
||||
inline uint qHash(const QPoint &p)
|
||||
{
|
||||
return qHash(QPair<int, int>(p.x(), p.y()));
|
||||
}
|
||||
#else // QT6
|
||||
#define HASH_T size_t
|
||||
#endif // QT6
|
||||
|
||||
inline HASH_T qHash(const QPoint &p)
|
||||
{
|
||||
return ::qHash(p.x()) ^ ::qHash(p.y());
|
||||
}
|
||||
|
||||
#endif // HASH_H
|
||||
|
@ -4,6 +4,7 @@
|
||||
template <class KEY, class VALUE>
|
||||
class KV {
|
||||
public:
|
||||
KV() {}
|
||||
KV(const KEY &key, const VALUE &value) : _key(key), _value(value) {}
|
||||
|
||||
const KEY &key() const {return _key;}
|
||||
|
@ -64,7 +64,7 @@ bool DEMLoader::loadTiles(const RectC &rect)
|
||||
}
|
||||
}
|
||||
|
||||
return _downloader->get(dl, _authorization);
|
||||
return _downloader->get(dl, _headers);
|
||||
}
|
||||
|
||||
bool DEMLoader::checkTiles(const RectC &rect) const
|
||||
@ -97,3 +97,11 @@ QString DEMLoader::tileFile(const DEM::Tile &tile) const
|
||||
{
|
||||
return _dir.absoluteFilePath(tile.baseName());
|
||||
}
|
||||
|
||||
void DEMLoader::setAuthorization(const Authorization &authorization)
|
||||
{
|
||||
QList<HTTPHeader> headers;
|
||||
if (!authorization.isNull())
|
||||
headers.append(authorization.header());
|
||||
_headers = headers;
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ public:
|
||||
DEMLoader(const QString &dir, QObject *parent = 0);
|
||||
|
||||
void setUrl(const QString &url) {_url = url;}
|
||||
void setAuthorization(const Authorization &authorization)
|
||||
{_authorization = authorization;}
|
||||
void setAuthorization(const Authorization &authorization);
|
||||
|
||||
bool loadTiles(const RectC &rect);
|
||||
bool checkTiles(const RectC &rect) const;
|
||||
@ -34,7 +33,7 @@ private:
|
||||
Downloader *_downloader;
|
||||
QString _url;
|
||||
QDir _dir;
|
||||
Authorization _authorization;
|
||||
QList<HTTPHeader> _headers;
|
||||
};
|
||||
|
||||
#endif // DEMLOADER_H
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <QColor>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <cmath>
|
||||
|
||||
@ -41,7 +42,19 @@ inline QDebug operator<<(QDebug dbg, const GraphPoint &point)
|
||||
}
|
||||
#endif // QT_NO_DEBUG
|
||||
|
||||
typedef QVector<GraphPoint> GraphSegment;
|
||||
class GraphSegment : public QVector<GraphPoint>
|
||||
{
|
||||
public:
|
||||
GraphSegment(const QDateTime &start)
|
||||
: _start(start) {}
|
||||
GraphSegment(int size, const QDateTime &start)
|
||||
: QVector<GraphPoint>(size), _start(start) {}
|
||||
|
||||
const QDateTime &start() const {return _start;}
|
||||
|
||||
private:
|
||||
QDateTime _start;
|
||||
};
|
||||
|
||||
class Graph : public QList<GraphSegment>
|
||||
{
|
||||
|
@ -33,13 +33,16 @@ Path Route::path() const
|
||||
Graph Route::gpsElevation() const
|
||||
{
|
||||
Graph graph;
|
||||
graph.append(GraphSegment());
|
||||
GraphSegment &gs = graph.last();
|
||||
QDateTime date;
|
||||
GraphSegment gs(date);
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
if (_data.at(i).hasElevation())
|
||||
gs.append(GraphPoint(_distance.at(i), NAN, _data.at(i).elevation()));
|
||||
|
||||
if (gs.size() >= 2)
|
||||
graph.append(gs);
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
graph.setColor(_data.style().color());
|
||||
|
||||
@ -49,8 +52,8 @@ Graph Route::gpsElevation() const
|
||||
Graph Route::demElevation() const
|
||||
{
|
||||
Graph graph;
|
||||
graph.append(GraphSegment());
|
||||
GraphSegment &gs = graph.last();
|
||||
QDateTime date;
|
||||
GraphSegment gs(date);
|
||||
|
||||
for (int i = 0; i < _data.size(); i++) {
|
||||
qreal dem = DEM::elevation(_data.at(i).coordinates());
|
||||
@ -58,6 +61,9 @@ Graph Route::demElevation() const
|
||||
gs.append(GraphPoint(_distance.at(i), NAN, dem));
|
||||
}
|
||||
|
||||
if (gs.size() >= 2)
|
||||
graph.append(gs);
|
||||
|
||||
if (_data.style().color().isValid())
|
||||
graph.setColor(_data.style().color());
|
||||
|
||||
|
@ -66,10 +66,10 @@ static QSet<int> eliminate(const QVector<qreal> &v)
|
||||
static GraphSegment filter(const GraphSegment &g, int window)
|
||||
{
|
||||
if (g.size() < window || window < 2)
|
||||
return GraphSegment(g);
|
||||
return g;
|
||||
|
||||
qreal acc = 0;
|
||||
GraphSegment ret(g.size());
|
||||
GraphSegment ret(g.size(), g.start());
|
||||
|
||||
for (int i = 0; i < window; i++)
|
||||
acc += g.at(i).y();
|
||||
@ -131,6 +131,7 @@ Track::Track(const TrackData &data) : _pause(0)
|
||||
|
||||
Segment &seg = _segments.last();
|
||||
|
||||
seg.start = sd.first().timestamp();
|
||||
seg.distance.append(lastDistance(i));
|
||||
seg.time.append(sd.first().hasTimestamp() ? lastTime(i) : NAN);
|
||||
seg.speed.append(sd.first().hasTimestamp() ? 0 : NAN);
|
||||
@ -257,7 +258,7 @@ Graph Track::gpsElevation() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.size(); j++) {
|
||||
if (!sd.at(j).hasElevation() || seg.outliers.contains(j))
|
||||
@ -285,7 +286,7 @@ Graph Track::demElevation() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.size(); j++) {
|
||||
qreal dem = DEM::elevation(sd.at(j).coordinates());
|
||||
@ -328,7 +329,7 @@ Graph Track::computedSpeed() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
QList<int> stop;
|
||||
qreal v;
|
||||
|
||||
@ -368,7 +369,7 @@ Graph Track::reportedSpeed() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
QList<int> stop;
|
||||
qreal v;
|
||||
|
||||
@ -423,7 +424,7 @@ Graph Track::heartRate() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.size(); j++)
|
||||
if (sd.at(j).hasHeartRate() && !seg.outliers.contains(j))
|
||||
@ -449,7 +450,7 @@ Graph Track::temperature() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.count(); j++) {
|
||||
if (sd.at(j).hasTemperature() && !seg.outliers.contains(j))
|
||||
@ -476,7 +477,7 @@ Graph Track::ratio() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.size(); j++)
|
||||
if (sd.at(j).hasRatio() && !seg.outliers.contains(j))
|
||||
@ -502,7 +503,7 @@ Graph Track::cadence() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
QList<int> stop;
|
||||
qreal c;
|
||||
|
||||
@ -545,7 +546,7 @@ Graph Track::power() const
|
||||
if (sd.size() < 2)
|
||||
continue;
|
||||
const Segment &seg = _segments.at(i);
|
||||
GraphSegment gs;
|
||||
GraphSegment gs(seg.start);
|
||||
|
||||
for (int j = 0; j < sd.size(); j++) {
|
||||
if (sd.at(j).hasPower() && seg.stop.contains(j)) {
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
|
||||
private:
|
||||
struct Segment {
|
||||
QDateTime start;
|
||||
QVector<qreal> distance;
|
||||
QVector<qreal> time;
|
||||
QVector<qreal> speed;
|
||||
|
@ -23,6 +23,7 @@ static QMap<uint,uint> orderMapInit()
|
||||
map.insert(TYPE(FOGSIG), 0);
|
||||
|
||||
map.insert(TYPE(CGUSTA), 1);
|
||||
map.insert(TYPE(RSCSTA), 1);
|
||||
map.insert(SUBTYPE(BUAARE, 1), 2);
|
||||
map.insert(SUBTYPE(BUAARE, 5), 3);
|
||||
map.insert(SUBTYPE(BUAARE, 4), 4);
|
||||
@ -264,6 +265,13 @@ MapData::Point::Point(uint type, const Coordinates &c, const QString &label,
|
||||
if (_label.isEmpty())
|
||||
_label = sistat(type & 0xFF);
|
||||
_type = TYPE(SISTAT);
|
||||
} else if (type>>16 == LNDELV && params.size()) {
|
||||
if (_label.isEmpty())
|
||||
_label = QString::fromLatin1(params.at(0))
|
||||
+ QString::fromUtf8("\xE2\x80\x89m");
|
||||
else
|
||||
_label += "\n(" + QString::fromLatin1(params.at(0))
|
||||
+ "\xE2\x80\x89m)";
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +560,8 @@ MapData::Attr MapData::pointAttr(const ISO8211::Record &r, uint OBJL)
|
||||
if ((OBJL == I_DISMAR && key == I_WTWDIS)
|
||||
|| (OBJL == RDOCAL && key == ORIENT)
|
||||
|| (OBJL == I_RDOCAL && key == ORIENT)
|
||||
|| (OBJL == CURENT && key == ORIENT))
|
||||
|| (OBJL == CURENT && key == ORIENT)
|
||||
|| (OBJL == LNDELV && key == ELEVAT))
|
||||
params[0] = av.at(1).toByteArray();
|
||||
if ((OBJL == I_RDOCAL && key == COMCHA)
|
||||
|| (OBJL == RDOCAL && key == COMCHA)
|
||||
@ -893,7 +902,7 @@ void MapData::clear()
|
||||
_points.RemoveAll();
|
||||
}
|
||||
|
||||
void MapData::points(const RectC &rect, QList<Point*> *points)
|
||||
void MapData::points(const RectC &rect, QList<Point*> *points) const
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
@ -901,7 +910,7 @@ void MapData::points(const RectC &rect, QList<Point*> *points)
|
||||
_points.Search(min, max, pointCb, points);
|
||||
}
|
||||
|
||||
void MapData::lines(const RectC &rect, QList<Line*> *lines)
|
||||
void MapData::lines(const RectC &rect, QList<Line*> *lines) const
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
@ -909,7 +918,7 @@ void MapData::lines(const RectC &rect, QList<Line*> *lines)
|
||||
_lines.Search(min, max, lineCb, lines);
|
||||
}
|
||||
|
||||
void MapData::polygons(const RectC &rect, QList<Poly*> *polygons)
|
||||
void MapData::polygons(const RectC &rect, QList<Poly*> *polygons) const
|
||||
{
|
||||
double min[2], max[2];
|
||||
|
||||
|
@ -72,9 +72,9 @@ public:
|
||||
RectC bounds() const {return _bounds;}
|
||||
Range zooms() const;
|
||||
|
||||
void polygons(const RectC &rect, QList<Poly*> *polygons);
|
||||
void lines(const RectC &rect, QList<Line*> *lines);
|
||||
void points(const RectC &rect, QList<Point*> *points);
|
||||
void polygons(const RectC &rect, QList<Poly*> *polygons) const;
|
||||
void lines(const RectC &rect, QList<Line*> *lines) const;
|
||||
void points(const RectC &rect, QList<Point*> *points) const;
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
|
@ -70,6 +70,7 @@
|
||||
#define RAILWY 106
|
||||
#define RCRTCL 108
|
||||
#define RECTRC 109
|
||||
#define RSCSTA 111
|
||||
#define RESARE 112
|
||||
#define RIVERS 114
|
||||
#define ROADWY 116
|
||||
|
@ -3,19 +3,18 @@
|
||||
#include "common/linec.h"
|
||||
#include "map/bitmapline.h"
|
||||
#include "map/textpathitem.h"
|
||||
#include "map/rectd.h"
|
||||
#include "style.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace ENC;
|
||||
|
||||
#define TEXT_EXTENT 160
|
||||
#define TSSLPT_SIZE 0.005 /* ll */
|
||||
#define RDOCAL_SIZE 12 /* px */
|
||||
#define CURENT_SIZE 12 /* px */
|
||||
|
||||
typedef QMap<Coordinates, const MapData::Point*> PointMap;
|
||||
|
||||
const float C1 = 0.866025f; /* sqrt(3)/2 */
|
||||
|
||||
static const float C1 = 0.866025f; /* sqrt(3)/2 */
|
||||
static const QColor haloColor(Qt::white);
|
||||
|
||||
static struct {
|
||||
@ -102,67 +101,12 @@ static Coordinates centroid(const QVector<Coordinates> &polygon)
|
||||
return Coordinates(cx * factor, cy * factor);
|
||||
}
|
||||
|
||||
static QImage *rdocalArrow(qreal angle)
|
||||
static double angle(uint type, const QVariant ¶m)
|
||||
{
|
||||
QImage *img = new QImage(RDOCAL_SIZE*2, RDOCAL_SIZE*2,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
img->fill(Qt::transparent);
|
||||
QPainter p(img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(QPen(QColor("#eb49eb"), 1));
|
||||
uint bt = type>>16;
|
||||
|
||||
QPointF arrow[3];
|
||||
arrow[0] = QPointF(img->width()/2, img->height()/2);
|
||||
arrow[1] = arrow[0] + QPointF(qSin(angle - M_PI/3) * RDOCAL_SIZE,
|
||||
qCos(angle - M_PI/3) * RDOCAL_SIZE);
|
||||
arrow[2] = arrow[0] + QPointF(qSin(angle - M_PI + M_PI/3) * RDOCAL_SIZE,
|
||||
qCos(angle - M_PI + M_PI/3) * RDOCAL_SIZE);
|
||||
|
||||
QLineF l(arrow[1], arrow[2]);
|
||||
QPointF pt(l.pointAt(0.5));
|
||||
|
||||
p.translate(arrow[0] - pt);
|
||||
p.drawPolyline(QPolygonF() << arrow[1] << arrow[0] << arrow[2]);
|
||||
p.drawEllipse(pt, RDOCAL_SIZE/2, RDOCAL_SIZE/2);
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
static QImage *currentArrow(qreal angle)
|
||||
{
|
||||
QImage *img = new QImage(CURENT_SIZE*2, CURENT_SIZE*2,
|
||||
QImage::Format_ARGB32_Premultiplied);
|
||||
img->fill(Qt::transparent);
|
||||
QPainter p(img);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
p.setPen(QPen(Qt::black, 1));
|
||||
|
||||
QPointF arrow[3];
|
||||
arrow[0] = QPointF(img->width()/2, img->height()/2);
|
||||
arrow[1] = arrow[0] + QPointF(qSin(angle - M_PI/3) * CURENT_SIZE,
|
||||
qCos(angle - M_PI/3) * CURENT_SIZE);
|
||||
arrow[2] = arrow[0] + QPointF(qSin(angle - M_PI + M_PI/3) * CURENT_SIZE,
|
||||
qCos(angle - M_PI + M_PI/3) * CURENT_SIZE);
|
||||
|
||||
QLineF l(arrow[1], arrow[2]);
|
||||
QPointF pt(l.pointAt(0.5));
|
||||
QLineF l2(arrow[0], pt);
|
||||
|
||||
p.translate(arrow[0] - pt);
|
||||
p.drawPolyline(QPolygonF() << arrow[1] << arrow[0] << arrow[2]);
|
||||
p.drawLine(arrow[0], l2.pointAt(2));
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
static QImage *image(uint type, const QVariant ¶m)
|
||||
{
|
||||
if (type>>16 == RDOCAL || type>>16 == I_RDOCAL)
|
||||
return rdocalArrow(deg2rad(90 - param.toDouble()));
|
||||
else if (type>>16 == CURENT)
|
||||
return currentArrow(deg2rad(90 - param.toDouble()));
|
||||
else
|
||||
return 0;
|
||||
return (bt == RDOCAL || bt == I_RDOCAL || bt == CURENT)
|
||||
? 90 + param.toDouble() : NAN;
|
||||
}
|
||||
|
||||
static bool showLabel(const QImage *img, const Range &range, int zoom, int type)
|
||||
@ -183,9 +127,10 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon) const
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
|
||||
path.moveTo(ll2xy(subpath.first()));
|
||||
for (int j = 1; j < subpath.size(); j++)
|
||||
path.lineTo(ll2xy(subpath.at(j)));
|
||||
QVector<QPointF> p(subpath.size());
|
||||
for (int j = 0; j < subpath.size(); j++)
|
||||
p[j] = ll2xy(subpath.at(j));
|
||||
path.addPolygon(p);
|
||||
}
|
||||
|
||||
return path;
|
||||
@ -227,10 +172,11 @@ QPolygonF RasterTile::tsslptArrow(const Coordinates &c, qreal angle) const
|
||||
return polygon;
|
||||
}
|
||||
|
||||
void RasterTile::drawArrows(QPainter *painter)
|
||||
void RasterTile::drawArrows(QPainter *painter,
|
||||
const QList<MapData::Poly*> &polygons)
|
||||
{
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly *poly = _polygons.at(i);
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly *poly = polygons.at(i);
|
||||
|
||||
if (poly->type()>>16 == TSSLPT) {
|
||||
QPolygonF polygon(tsslptArrow(centroid(poly->path().first()),
|
||||
@ -243,13 +189,14 @@ void RasterTile::drawArrows(QPainter *painter)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawPolygons(QPainter *painter)
|
||||
void RasterTile::drawPolygons(QPainter *painter,
|
||||
const QList<MapData::Poly*> &polygons)
|
||||
{
|
||||
const Style &s = style();
|
||||
|
||||
for (int n = 0; n < s.drawOrder().size(); n++) {
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly *poly = _polygons.at(i);
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly *poly = polygons.at(i);
|
||||
if (poly->type() != s.drawOrder().at(n))
|
||||
continue;
|
||||
const Style::Polygon &style = s.polygon(poly->type());
|
||||
@ -267,14 +214,14 @@ void RasterTile::drawPolygons(QPainter *painter)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawLines(QPainter *painter)
|
||||
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Line*> &lines)
|
||||
{
|
||||
const Style &s = style();
|
||||
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Line *line = _lines.at(i);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Line *line = lines.at(i);
|
||||
const Style::Line &style = s.line(line->type());
|
||||
|
||||
if (!style.img().isNull()) {
|
||||
@ -293,12 +240,13 @@ void RasterTile::drawTextItems(QPainter *painter,
|
||||
textItems.at(i)->paint(painter);
|
||||
}
|
||||
|
||||
void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
void RasterTile::processPolygons(const QList<MapData::Poly*> &polygons,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
const Style &s = style();
|
||||
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly *poly = _polygons.at(i);
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly *poly = polygons.at(i);
|
||||
uint type = poly->type()>>16;
|
||||
|
||||
if (!(type == HRBFAC || type == I_TRNBSN
|
||||
@ -319,18 +267,18 @@ void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<TextItem*> &textItems,
|
||||
QList<TextItem*> &lights)
|
||||
void RasterTile::processPoints(QList<MapData::Point*> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem*> &lights)
|
||||
{
|
||||
const Style &s = style();
|
||||
PointMap lightsMap, signalsMap;
|
||||
int i;
|
||||
|
||||
std::sort(_points.begin(), _points.end(), pointLess);
|
||||
std::sort(points.begin(), points.end(), pointLess);
|
||||
|
||||
/* Lights & Signals */
|
||||
for (i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point *point = _points.at(i);
|
||||
for (i = 0; i < points.size(); i++) {
|
||||
const MapData::Point *point = points.at(i);
|
||||
if (point->type()>>16 == LIGHTS)
|
||||
lightsMap.insert(point->pos(), point);
|
||||
else if (point->type()>>16 == FOGSIG)
|
||||
@ -340,26 +288,25 @@ void RasterTile::processPoints(QList<TextItem*> &textItems,
|
||||
}
|
||||
|
||||
/* Everything else */
|
||||
for ( ; i < _points.size(); i++) {
|
||||
const MapData::Point *point = _points.at(i);
|
||||
for ( ; i < points.size(); i++) {
|
||||
const MapData::Point *point = points.at(i);
|
||||
QPoint pos(ll2xy(point->pos()).toPoint());
|
||||
const Style::Point &style = s.point(point->type());
|
||||
|
||||
const QString *label = point->label().isEmpty() ? 0 : &(point->label());
|
||||
QImage *rimg = style.img().isNull()
|
||||
? image(point->type(), point->param()) : 0;
|
||||
const QImage *img = style.img().isNull() ? rimg : &style.img();
|
||||
const QFont *fnt = showLabel(img, _zooms, _zoom, point->type())
|
||||
const QImage *img = style.img().isNull() ? 0 : &style.img();
|
||||
const QFont *fnt = showLabel(img, _data->zooms(), _zoom, point->type())
|
||||
? font(style.textFontSize()) : 0;
|
||||
const QColor *color = &style.textColor();
|
||||
const QColor *hColor = style.haloColor().isValid()
|
||||
? &style.haloColor() : 0;
|
||||
double rotate = angle(point->type(), point->param());
|
||||
|
||||
if ((!label || !fnt) && !img)
|
||||
continue;
|
||||
|
||||
PointItem *item = new PointItem(pos, label, fnt, img, rimg, color,
|
||||
hColor);
|
||||
TextPointItem *item = new TextPointItem(pos, label, fnt, img, color,
|
||||
hColor, 0, 2, rotate);
|
||||
if (item->isValid() && !item->collides(textItems)) {
|
||||
textItems.append(item);
|
||||
if (lightsMap.contains(point->pos()))
|
||||
@ -371,12 +318,13 @@ void RasterTile::processPoints(QList<TextItem*> &textItems,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processLines(QList<TextItem*> &textItems)
|
||||
void RasterTile::processLines(const QList<MapData::Line*> &lines,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
const Style &s = style();
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Line *line = _lines.at(i);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Line *line = lines.at(i);
|
||||
const Style::Line &style = s.line(line->type());
|
||||
|
||||
if (style.img().isNull() && style.pen() == Qt::NoPen)
|
||||
@ -396,25 +344,51 @@ void RasterTile::processLines(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::fetchData(QList<MapData::Poly*> &polygons,
|
||||
QList<MapData::Line*> &lines, QList<MapData::Point*> &points)
|
||||
{
|
||||
QPoint ttl(_rect.topLeft());
|
||||
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y()
|
||||
+ _rect.height()));
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
RectC polyRectC(polyRectD.toRectC(_proj, 20));
|
||||
_data->lines(polyRectC, &lines);
|
||||
_data->polygons(polyRectC, &polygons);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT),
|
||||
QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height()
|
||||
+ TEXT_EXTENT));
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data->points(pointRectD.toRectC(_proj, 20), &points);
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<MapData::Line*> lines;
|
||||
QList<MapData::Poly*> polygons;
|
||||
QList<MapData::Point*> points;
|
||||
QList<TextItem*> textItems, lights;
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
||||
processPolygons(textItems);
|
||||
processPoints(textItems, lights);
|
||||
processLines(textItems);
|
||||
fetchData(polygons, lines, points);
|
||||
|
||||
processPolygons(polygons, textItems);
|
||||
processPoints(points, textItems, lights);
|
||||
processLines(lines, textItems);
|
||||
|
||||
QPainter painter(&_pixmap);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPolygons(&painter);
|
||||
drawLines(&painter);
|
||||
drawArrows(&painter);
|
||||
drawPolygons(&painter, polygons);
|
||||
drawLines(&painter, lines);
|
||||
drawArrows(&painter, polygons);
|
||||
|
||||
drawTextItems(&painter, lights);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
@ -15,13 +15,10 @@ class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Range &zooms, int zoom, const QRect &rect, qreal ratio,
|
||||
const QList<MapData::Line*> &lines, const QList<MapData::Poly*> &polygons,
|
||||
const QList<MapData::Point*> &points)
|
||||
: _proj(proj), _transform(transform), _zooms(zooms), _zoom(zoom),
|
||||
const MapData *data, int zoom, const QRect &rect, qreal ratio)
|
||||
: _proj(proj), _transform(transform), _data(data), _zoom(zoom),
|
||||
_rect(rect), _ratio(ratio),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _lines(lines),
|
||||
_polygons(polygons), _points(points), _valid(false) {}
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
QPoint xy() const {return _rect.topLeft();}
|
||||
@ -31,44 +28,33 @@ public:
|
||||
void render();
|
||||
|
||||
private:
|
||||
class PointItem : public TextPointItem
|
||||
{
|
||||
public:
|
||||
PointItem(const QPoint &point, const QString *text, const QFont *font,
|
||||
const QImage *img, const QImage *rimg, const QColor *color,
|
||||
const QColor *haloColor) : TextPointItem(point, text, font, img, color,
|
||||
haloColor, 0, 2), _rimg(rimg) {}
|
||||
~PointItem() {delete _rimg;}
|
||||
|
||||
private:
|
||||
const QImage *_rimg;
|
||||
};
|
||||
|
||||
void fetchData(QList<MapData::Poly*> &polygons, QList<MapData::Line*> &lines,
|
||||
QList<MapData::Point*> &points);
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
QPainterPath painterPath(const Polygon &polygon) const;
|
||||
QPolygonF polyline(const QVector<Coordinates> &path) const;
|
||||
QPolygonF tsslptArrow(const Coordinates &c, qreal angle) const;
|
||||
void processPoints(QList<TextItem*> &textItems, QList<TextItem *> &lights);
|
||||
void processLines(QList<TextItem*> &textItems);
|
||||
void processPolygons(QList<TextItem*> &textItems);
|
||||
void processPoints(QList<MapData::Point *> &points,
|
||||
QList<TextItem*> &textItems, QList<TextItem *> &lights);
|
||||
void processLines(const QList<MapData::Line *> &lines,
|
||||
QList<TextItem*> &textItems);
|
||||
void processPolygons(const QList<MapData::Poly *> &polygons,
|
||||
QList<TextItem*> &textItems);
|
||||
void drawBitmapPath(QPainter *painter, const QImage &img,
|
||||
const Polygon &polygon);
|
||||
void drawArrows(QPainter *painter);
|
||||
void drawPolygons(QPainter *painter);
|
||||
void drawLines(QPainter *painter);
|
||||
void drawArrows(QPainter *painter, const QList<MapData::Poly*> &polygons);
|
||||
void drawPolygons(QPainter *painter, const QList<MapData::Poly *> &polygons);
|
||||
void drawLines(QPainter *painter, const QList<MapData::Line *> &lines);
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
Range _zooms;
|
||||
const MapData *_data;
|
||||
int _zoom;
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
QPixmap _pixmap;
|
||||
QList<MapData::Line*> _lines;
|
||||
QList<MapData::Poly*> _polygons;
|
||||
QList<MapData::Point*> _points;
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
|
@ -248,6 +248,7 @@ void Style::pointStyle()
|
||||
_points[SUBTYPE(I_DISMAR, 3)] = _points[SUBTYPE(I_DISMAR, 2)];
|
||||
_points[SUBTYPE(I_DISMAR, 4)] = _points[SUBTYPE(I_DISMAR, 2)];
|
||||
_points[TYPE(CGUSTA)] = Point(QImage(":/marine/coast-guard.png"));
|
||||
_points[TYPE(RSCSTA)] = Point(QImage(":/marine/rescue-station.png"));
|
||||
_points[TYPE(RDOSTA)] = Point(QImage(":/marine/radio.png"));
|
||||
_points[TYPE(RADSTA)] = Point(QImage(":/marine/radar.png"));
|
||||
_points[TYPE(RTPBCN)] = Point(QImage(":/marine/radar-transponder.png"));
|
||||
@ -255,7 +256,9 @@ void Style::pointStyle()
|
||||
_points[TYPE(I_TRNBSN)] = Point(QImage(":/marine/turning-basin.png"));
|
||||
_points[TYPE(I_TRNBSN)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(I_WTWGAG)] = Point(QImage(":/marine/gauge.png"), Small);
|
||||
_points[TYPE(RDOCAL)] = Point(QImage(":/marine/radio-call.png"));
|
||||
_points[TYPE(RDOCAL)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(I_RDOCAL)] = Point(QImage(":/marine/radio-call.png"));
|
||||
_points[TYPE(I_RDOCAL)].setTextColor(QColor("#eb49eb"));
|
||||
_points[TYPE(PYLONS)] = Point(QImage(":/marine/pylon.png"));
|
||||
_points[SUBTYPE(I_BERTHS, 6)] = Point(QImage(":/marine/fleeting-area.png"));
|
||||
@ -265,6 +268,7 @@ void Style::pointStyle()
|
||||
_points[TYPE(PILBOP)] = Point(QImage(":/marine/boarding-place.png"));
|
||||
_points[TYPE(SISTAT)] = Point(QImage(":/marine/pylon.png"));
|
||||
_points[TYPE(SLCONS)] = Point(QImage(":/marine/construction.png"), Small);
|
||||
_points[TYPE(CURENT)] = Point(QImage(":/marine/current.png"));
|
||||
|
||||
_points[SUBTYPE(SMCFAC, 7)] = Point(QImage(":/POI/restaurant-11.png"), Small);
|
||||
_points[SUBTYPE(SMCFAC, 11)] = Point(QImage(":/POI/pharmacy-11.png"), Small);
|
||||
|
@ -13,14 +13,14 @@ bool MapData::polyCb(VectorTile *tile, void *context)
|
||||
{
|
||||
PolyCTX *ctx = (PolyCTX*)context;
|
||||
tile->polys(ctx->rect, ctx->zoom, ctx->polygons, ctx->lines,
|
||||
ctx->polyCache);
|
||||
ctx->polyCache, ctx->lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapData::pointCb(VectorTile *tile, void *context)
|
||||
{
|
||||
PointCTX *ctx = (PointCTX*)context;
|
||||
tile->points(ctx->rect, ctx->zoom, ctx->points, ctx->pointCache);
|
||||
tile->points(ctx->rect, ctx->zoom, ctx->points, ctx->pointCache, ctx->lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ MapData::~MapData()
|
||||
void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
QList<Poly> *lines)
|
||||
{
|
||||
PolyCTX ctx(rect, zoom(bits), polygons, lines, &_polyCache);
|
||||
PolyCTX ctx(rect, zoom(bits), polygons, lines, &_polyCache, &_lock);
|
||||
double min[2], max[2];
|
||||
|
||||
min[0] = rect.left();
|
||||
@ -58,7 +58,7 @@ void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||
|
||||
void MapData::points(const RectC &rect, int bits, QList<Point> *points)
|
||||
{
|
||||
PointCTX ctx(rect, zoom(bits), points, &_pointCache);
|
||||
PointCTX ctx(rect, zoom(bits), points, &_pointCache, &_lock);
|
||||
double min[2], max[2];
|
||||
|
||||
min[0] = rect.left();
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QList>
|
||||
#include <QPointF>
|
||||
#include <QCache>
|
||||
#include <QMutex>
|
||||
#include <QDebug>
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
@ -24,6 +25,8 @@ class MapData
|
||||
{
|
||||
public:
|
||||
struct Poly {
|
||||
Poly() : oneway(false) {}
|
||||
|
||||
/* QPointF insted of Coordinates for performance reasons (no need to
|
||||
duplicate all the vectors for drawing). Note, that we do not want to
|
||||
ll2xy() the points in the MapData class as this can not be done in
|
||||
@ -33,6 +36,7 @@ public:
|
||||
Raster raster;
|
||||
quint32 type;
|
||||
RectC boundingRect;
|
||||
bool oneway;
|
||||
|
||||
bool operator<(const Poly &other) const
|
||||
{return type > other.type;}
|
||||
@ -97,32 +101,37 @@ private:
|
||||
QList<Poly> lines;
|
||||
};
|
||||
|
||||
typedef QCache<const SubDiv*, Polys> PolyCache;
|
||||
typedef QCache<const SubDiv*, QList<Point> > PointCache;
|
||||
|
||||
struct PolyCTX
|
||||
{
|
||||
PolyCTX(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
|
||||
QCache<const SubDiv*, MapData::Polys> *polyCache)
|
||||
PolyCache *polyCache, QMutex *lock)
|
||||
: rect(rect), zoom(zoom), polygons(polygons), lines(lines),
|
||||
polyCache(polyCache) {}
|
||||
polyCache(polyCache), lock(lock) {}
|
||||
|
||||
const RectC ▭
|
||||
const Zoom &zoom;
|
||||
QList<MapData::Poly> *polygons;
|
||||
QList<MapData::Poly> *lines;
|
||||
QCache<const SubDiv*, MapData::Polys> *polyCache;
|
||||
PolyCache *polyCache;
|
||||
QMutex *lock;
|
||||
};
|
||||
|
||||
struct PointCTX
|
||||
{
|
||||
PointCTX(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Point> *points,
|
||||
QCache<const SubDiv*, QList<MapData::Point> > *pointCache)
|
||||
: rect(rect), zoom(zoom), points(points), pointCache(pointCache) {}
|
||||
QList<MapData::Point> *points, PointCache *pointCache, QMutex *lock)
|
||||
: rect(rect), zoom(zoom), points(points), pointCache(pointCache),
|
||||
lock(lock) {}
|
||||
|
||||
const RectC ▭
|
||||
const Zoom &zoom;
|
||||
QList<MapData::Point> *points;
|
||||
QCache<const SubDiv*, QList<MapData::Point> > *pointCache;
|
||||
PointCache *pointCache;
|
||||
QMutex *lock;
|
||||
};
|
||||
|
||||
const Zoom &zoom(int bits) const;
|
||||
@ -130,8 +139,9 @@ private:
|
||||
static bool polyCb(VectorTile *tile, void *context);
|
||||
static bool pointCb(VectorTile *tile, void *context);
|
||||
|
||||
QCache<const SubDiv*, Polys> _polyCache;
|
||||
QCache<const SubDiv*, QList<Point> > _pointCache;
|
||||
PolyCache _polyCache;
|
||||
PointCache _pointCache;
|
||||
QMutex _lock;
|
||||
|
||||
friend class VectorTile;
|
||||
};
|
||||
|
@ -479,6 +479,8 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl,
|
||||
|
||||
if (lbl)
|
||||
linkLabel(hdl, linkOffset, lbl, lblHdl, poly.label);
|
||||
if ((linkInfo.flags >> 3) & 1)
|
||||
poly.oneway = true;
|
||||
|
||||
lines->append(poly);
|
||||
|
||||
|
@ -5,12 +5,14 @@
|
||||
#include "map/textpathitem.h"
|
||||
#include "map/textpointitem.h"
|
||||
#include "map/bitmapline.h"
|
||||
#include "map/rectd.h"
|
||||
#include "style.h"
|
||||
#include "lblfile.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace IMG;
|
||||
|
||||
#define TEXT_EXTENT 160
|
||||
#define ICON_PADDING 2
|
||||
|
||||
#define AREA(rect) \
|
||||
@ -23,6 +25,12 @@ static const QColor shieldBgColor1("#dd3e3e");
|
||||
static const QColor shieldBgColor2("#379947");
|
||||
static const QColor shieldBgColor3("#4a7fc1");
|
||||
|
||||
static const QImage *arrow()
|
||||
{
|
||||
static QImage img(":/map/arrow.png");
|
||||
return &img;
|
||||
}
|
||||
|
||||
static QFont pixelSizeFont(int pixelSize)
|
||||
{
|
||||
QFont f;
|
||||
@ -147,40 +155,6 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
|
||||
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
|
||||
}
|
||||
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<TextItem*> textItems;
|
||||
|
||||
ll2xy(_polygons);
|
||||
ll2xy(_lines);
|
||||
ll2xy(_points);
|
||||
|
||||
processPoints(textItems);
|
||||
processPolygons(textItems);
|
||||
processLines(textItems);
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&_pixmap);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPolygons(&painter);
|
||||
drawLines(&painter);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
|
||||
_valid = true;
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
//painter.drawRect(QRect(_xy, _pixmap.size()));
|
||||
}
|
||||
|
||||
void RasterTile::ll2xy(QList<MapData::Poly> &polys)
|
||||
{
|
||||
for (int i = 0; i < polys.size(); i++) {
|
||||
@ -200,14 +174,15 @@ void RasterTile::ll2xy(QList<MapData::Point> &points)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawPolygons(QPainter *painter)
|
||||
void RasterTile::drawPolygons(QPainter *painter,
|
||||
const QList<MapData::Poly> &polygons)
|
||||
{
|
||||
QCache<const LBLFile *, SubFile::Handle> hc(16);
|
||||
|
||||
for (int n = 0; n < _style->drawOrder().size(); n++) {
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly &poly = _polygons.at(i);
|
||||
if (poly.type != _style->drawOrder().at(n))
|
||||
for (int n = 0; n < _data->style()->drawOrder().size(); n++) {
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly &poly = polygons.at(i);
|
||||
if (poly.type != _data->style()->drawOrder().at(n))
|
||||
continue;
|
||||
|
||||
if (poly.raster.isValid()) {
|
||||
@ -237,7 +212,7 @@ void RasterTile::drawPolygons(QPainter *painter)
|
||||
//painter->setBrush(Qt::NoBrush);
|
||||
//painter->drawRect(QRectF(tl, br));
|
||||
} else {
|
||||
const Style::Polygon &style = _style->polygon(poly.type);
|
||||
const Style::Polygon &style = _data->style()->polygon(poly.type);
|
||||
|
||||
painter->setPen(style.pen());
|
||||
painter->setBrush(style.brush());
|
||||
@ -247,13 +222,13 @@ void RasterTile::drawPolygons(QPainter *painter)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawLines(QPainter *painter)
|
||||
void RasterTile::drawLines(QPainter *painter, const QList<MapData::Poly> &lines)
|
||||
{
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Poly &poly = lines.at(i);
|
||||
const Style::Line &style = _data->style()->line(poly.type);
|
||||
|
||||
if (style.background() == Qt::NoPen)
|
||||
continue;
|
||||
@ -262,9 +237,9 @@ void RasterTile::drawLines(QPainter *painter)
|
||||
painter->drawPolyline(poly.points);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Poly &poly = lines.at(i);
|
||||
const Style::Line &style = _data->style()->line(poly.type);
|
||||
|
||||
if (!style.img().isNull())
|
||||
BitmapLine::draw(painter, poly.points, style.img());
|
||||
@ -295,13 +270,14 @@ static void removeDuplicitLabel(QList<TextItem *> &labels, const QString &text,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
void RasterTile::processPolygons(const QList<MapData::Poly> &polygons,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
QSet<QString> set;
|
||||
QList<TextItem *> labels;
|
||||
|
||||
for (int i = 0; i < _polygons.size(); i++) {
|
||||
const MapData::Poly &poly = _polygons.at(i);
|
||||
for (int i = 0; i < polygons.size(); i++) {
|
||||
const MapData::Poly &poly = polygons.at(i);
|
||||
bool exists = set.contains(poly.label.text());
|
||||
|
||||
if (poly.label.text().isEmpty())
|
||||
@ -310,7 +286,7 @@ void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
if (_zoom <= 23 && (Style::isWaterArea(poly.type)
|
||||
|| Style::isMilitaryArea(poly.type)
|
||||
|| Style::isNatureReserve(poly.type))) {
|
||||
const Style::Polygon &style = _style->polygon(poly.type);
|
||||
const Style::Polygon &style = _data->style()->polygon(poly.type);
|
||||
TextPointItem *item = new TextPointItem(
|
||||
centroid(poly.points).toPoint(), &poly.label.text(), poiFont(),
|
||||
0, &style.brush().color(), &haloColor);
|
||||
@ -331,20 +307,22 @@ void RasterTile::processPolygons(QList<TextItem*> &textItems)
|
||||
textItems.append(labels);
|
||||
}
|
||||
|
||||
void RasterTile::processLines(QList<TextItem*> &textItems)
|
||||
void RasterTile::processLines(QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
std::stable_sort(_lines.begin(), _lines.end());
|
||||
std::stable_sort(lines.begin(), lines.end());
|
||||
|
||||
if (_zoom >= 22)
|
||||
processStreetNames(textItems);
|
||||
processShields(textItems);
|
||||
processStreetNames(lines, textItems);
|
||||
processShields(lines, textItems);
|
||||
}
|
||||
|
||||
void RasterTile::processStreetNames(QList<TextItem*> &textItems)
|
||||
void RasterTile::processStreetNames(const QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
const Style::Line &style = _style->line(poly.type);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Poly &poly = lines.at(i);
|
||||
const Style::Line &style = _data->style()->line(poly.type);
|
||||
|
||||
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
||||
continue;
|
||||
@ -355,18 +333,30 @@ void RasterTile::processStreetNames(QList<TextItem*> &textItems)
|
||||
const QFont *fnt = font(style.textFontSize(), Style::Small);
|
||||
const QColor *color = style.textColor().isValid()
|
||||
? &style.textColor() : 0;
|
||||
const QColor *hColor = Style::isContourLine(poly.type) ? 0 : &haloColor;
|
||||
const QImage *img = poly.oneway ? arrow() : 0;
|
||||
|
||||
TextPathItem *item = new TextPathItem(poly.points,
|
||||
&poly.label.text(), _rect, fnt, color, Style::isContourLine(poly.type)
|
||||
? 0 : &haloColor);
|
||||
&poly.label.text(), _rect, fnt, color, hColor, img);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
else {
|
||||
delete item;
|
||||
|
||||
if (img) {
|
||||
TextPathItem *item = new TextPathItem(poly.points, 0, _rect, 0,
|
||||
0, 0, img);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processShields(QList<TextItem*> &textItems)
|
||||
void RasterTile::processShields(const QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
|
||||
if (minShieldZoom(static_cast<Shield::Type>(type)) > _zoom)
|
||||
@ -375,8 +365,8 @@ void RasterTile::processShields(QList<TextItem*> &textItems)
|
||||
QHash<Shield, QPolygonF> shields;
|
||||
QHash<Shield, const Shield*> sp;
|
||||
|
||||
for (int i = 0; i < _lines.size(); i++) {
|
||||
const MapData::Poly &poly = _lines.at(i);
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
const MapData::Poly &poly = lines.at(i);
|
||||
const Shield &shield = poly.label.shield();
|
||||
if (!shield.isValid() || shield.type() != type
|
||||
|| !Style::isMajorRoad(poly.type))
|
||||
@ -429,13 +419,14 @@ void RasterTile::processShields(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
void RasterTile::processPoints(QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems)
|
||||
{
|
||||
std::sort(_points.begin(), _points.end());
|
||||
std::sort(points.begin(), points.end());
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point &point = _points.at(i);
|
||||
const Style::Point &style = _style->point(point.type);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
const Style::Point &style = _data->style()->point(point.type);
|
||||
bool poi = Style::isPOI(point.type);
|
||||
|
||||
const QString *label = point.label.text().isEmpty()
|
||||
@ -446,12 +437,14 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
: font(style.textFontSize());
|
||||
const QColor *color = style.textColor().isValid()
|
||||
? &style.textColor() : &textColor;
|
||||
const QColor *hcolor = Style::isDepthPoint(point.type)
|
||||
? 0 : &haloColor;
|
||||
|
||||
if ((!label || !fnt) && !img)
|
||||
continue;
|
||||
|
||||
TextPointItem *item = new TextPointItem(QPoint(point.coordinates.lon(),
|
||||
point.coordinates.lat()), label, fnt, img, color, &haloColor, 0,
|
||||
point.coordinates.lat()), label, fnt, img, color, hcolor, 0,
|
||||
ICON_PADDING);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
@ -459,3 +452,60 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::fetchData(QList<MapData::Poly> &polygons,
|
||||
QList<MapData::Poly> &lines, QList<MapData::Point> &points)
|
||||
{
|
||||
QPoint ttl(_rect.topLeft());
|
||||
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + _rect.width(), ttl.y()
|
||||
+ _rect.height()));
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
_data->polys(polyRectD.toRectC(_proj, 20), _zoom,
|
||||
&polygons, &lines);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT),
|
||||
QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height()
|
||||
+ TEXT_EXTENT));
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<MapData::Poly> polygons;
|
||||
QList<MapData::Poly> lines;
|
||||
QList<MapData::Point> points;
|
||||
QList<TextItem*> textItems;
|
||||
|
||||
fetchData(polygons, lines, points);
|
||||
ll2xy(polygons);
|
||||
ll2xy(lines);
|
||||
ll2xy(points);
|
||||
|
||||
processPoints(points, textItems);
|
||||
processPolygons(polygons, textItems);
|
||||
processLines(lines, textItems);
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&_pixmap);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPolygons(&painter, polygons);
|
||||
drawLines(&painter, lines);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
|
||||
_valid = true;
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
//painter.drawRect(_rect);
|
||||
}
|
||||
|
@ -17,14 +17,11 @@ class Style;
|
||||
class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Style *style, int zoom, const QRect &rect, qreal ratio,
|
||||
const QString &key, const QList<MapData::Poly> &polygons,
|
||||
const QList<MapData::Poly> &lines, QList<MapData::Point> &points)
|
||||
: _proj(proj), _transform(transform), _style(style), _zoom(zoom),
|
||||
_rect(rect), _ratio(ratio), _key(key),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _polygons(polygons),
|
||||
_lines(lines), _points(points), _valid(false) {}
|
||||
RasterTile(const Projection &proj, const Transform &transform, MapData *data,
|
||||
int zoom, const QRect &rect, qreal ratio, const QString &key)
|
||||
: _proj(proj), _transform(transform), _data(data), _zoom(zoom),
|
||||
_rect(rect), _ratio(ratio), _key(key),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
|
||||
|
||||
const QString &key() const {return _key;}
|
||||
QPoint xy() const {return _rect.topLeft();}
|
||||
@ -34,32 +31,36 @@ public:
|
||||
void render();
|
||||
|
||||
private:
|
||||
void fetchData(QList<MapData::Poly> &polygons, QList<MapData::Poly> &lines,
|
||||
QList<MapData::Point> &points);
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
void ll2xy(QList<MapData::Poly> &polys);
|
||||
void ll2xy(QList<MapData::Point> &points);
|
||||
|
||||
void drawPolygons(QPainter *painter);
|
||||
void drawLines(QPainter *painter);
|
||||
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
|
||||
void drawLines(QPainter *painter, const QList<MapData::Poly> &lines);
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
|
||||
void processPolygons(QList<TextItem *> &textItems);
|
||||
void processLines(QList<TextItem*> &textItems);
|
||||
void processPoints(QList<TextItem*> &textItems);
|
||||
void processShields(QList<TextItem*> &textItems);
|
||||
void processStreetNames(QList<TextItem*> &textItems);
|
||||
void processPolygons(const QList<MapData::Poly> &polygons,
|
||||
QList<TextItem *> &textItems);
|
||||
void processLines(QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems);
|
||||
void processPoints(QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems);
|
||||
void processShields(const QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems);
|
||||
void processStreetNames(const QList<MapData::Poly> &lines,
|
||||
QList<TextItem*> &textItems);
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
const Style *_style;
|
||||
MapData *_data;
|
||||
int _zoom;
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
QString _key;
|
||||
QPixmap _pixmap;
|
||||
QList<MapData::Poly> _polygons;
|
||||
QList<MapData::Poly> _lines;
|
||||
QList<MapData::Point> _points;
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "common/rectc.h"
|
||||
#include "common/garmin.h"
|
||||
#include "common/hash.h"
|
||||
#include "deltastream.h"
|
||||
#include "huffmanstream.h"
|
||||
#include "style.h"
|
||||
@ -13,12 +14,10 @@ using namespace IMG;
|
||||
|
||||
#define MASK(bits) ((1U << (bits)) - 1U)
|
||||
|
||||
static quint64 pointId(const QPoint &pos, quint32 type)
|
||||
static quint64 pointId(const QPoint &pos, quint32 type, const QString &label)
|
||||
{
|
||||
quint64 id;
|
||||
|
||||
uint hash = (uint)qHash(QPair<int, int>(pos.x(), pos.y()));
|
||||
id = ((quint64)type)<<32 | hash;
|
||||
quint64 hash = qHash(pos) ^ qHash(label);
|
||||
quint64 id = ((quint64)type)<<40 | (hash & 0xFFFFFFFFFF);
|
||||
|
||||
// Increase rendering priorities for some special items
|
||||
if (!Style::isCountry(type) && !Style::isMarina(type))
|
||||
@ -293,6 +292,8 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
|
||||
poly.type = (segmentType == Polygon)
|
||||
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
|
||||
if (segmentType == Line && type & 0x40)
|
||||
poly.oneway = true;
|
||||
|
||||
|
||||
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
|
||||
@ -484,11 +485,11 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
|
||||
point.type = (quint16)type<<8 | subtype;
|
||||
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||
point.id = pointId(pos, point.type);
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF,
|
||||
labelPtr & 0x400000, !(Style::isCountry(point.type)
|
||||
|| Style::isState(point.type)), Style::isSpot(point.type));
|
||||
point.id = pointId(pos, point.type, point.label.text());
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
@ -537,9 +538,9 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||
continue;
|
||||
|
||||
point.coordinates = Coordinates(toWGS24(p.x()), toWGS24(p.y()));
|
||||
point.id = pointId(p, point.type);
|
||||
if (lbl && (labelPtr & 0x3FFFFF))
|
||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
||||
point.id = pointId(p, point.type, point.label.text());
|
||||
|
||||
points->append(point);
|
||||
}
|
||||
|
@ -102,13 +102,18 @@ void VectorTile::clear()
|
||||
|
||||
void VectorTile::polys(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
|
||||
QCache<const SubDiv *, MapData::Polys> *polyCache)
|
||||
MapData::PolyCache *polyCache, QMutex *lock)
|
||||
{
|
||||
SubFile::Handle *rgnHdl = 0, *lblHdl = 0, *netHdl = 0, *nodHdl = 0,
|
||||
*nodHdl2 = 0;
|
||||
|
||||
if (_loaded < 0)
|
||||
lock->lock();
|
||||
|
||||
if (_loaded < 0) {
|
||||
lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_loaded) {
|
||||
rgnHdl = new SubFile::Handle(_rgn);
|
||||
lblHdl = new SubFile::Handle(_lbl);
|
||||
@ -116,6 +121,7 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom,
|
||||
nodHdl = new SubFile::Handle(_nod);
|
||||
|
||||
if (!load(*rgnHdl, *lblHdl, *netHdl, *nodHdl)) {
|
||||
lock->unlock();
|
||||
delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl;
|
||||
return;
|
||||
}
|
||||
@ -166,17 +172,24 @@ void VectorTile::polys(const RectC &rect, const Zoom &zoom,
|
||||
}
|
||||
}
|
||||
|
||||
lock->unlock();
|
||||
|
||||
delete rgnHdl; delete lblHdl; delete netHdl; delete nodHdl; delete nodHdl2;
|
||||
}
|
||||
|
||||
void VectorTile::points(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Point> *points, QCache<const SubDiv *,
|
||||
QList<MapData::Point> > *pointCache)
|
||||
QList<MapData::Point> > *pointCache, QMutex *lock)
|
||||
{
|
||||
SubFile::Handle *rgnHdl = 0, *lblHdl = 0;
|
||||
|
||||
if (_loaded < 0)
|
||||
lock->lock();
|
||||
|
||||
if (_loaded < 0) {
|
||||
lock->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_loaded) {
|
||||
rgnHdl = new SubFile::Handle(_rgn);
|
||||
lblHdl = new SubFile::Handle(_lbl);
|
||||
@ -184,6 +197,7 @@ void VectorTile::points(const RectC &rect, const Zoom &zoom,
|
||||
SubFile::Handle netHdl(_net);
|
||||
|
||||
if (!load(*rgnHdl, *lblHdl, netHdl, nodHdl)) {
|
||||
lock->unlock();
|
||||
delete rgnHdl; delete lblHdl;
|
||||
return;
|
||||
}
|
||||
@ -217,6 +231,8 @@ void VectorTile::points(const RectC &rect, const Zoom &zoom,
|
||||
copyPoints(rect, pl, points);
|
||||
}
|
||||
|
||||
lock->unlock();
|
||||
|
||||
delete rgnHdl; delete lblHdl;
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,10 @@ public:
|
||||
|
||||
void polys(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Poly> *polygons, QList<MapData::Poly> *lines,
|
||||
QCache<const SubDiv *, MapData::Polys> *polyCache);
|
||||
MapData::PolyCache *polyCache, QMutex *lock);
|
||||
void points(const RectC &rect, const Zoom &zoom,
|
||||
QList<MapData::Point> *points, QCache<const SubDiv*,
|
||||
QList<MapData::Point> > *pointCache);
|
||||
QList<MapData::Point> > *pointCache, QMutex *lock);
|
||||
|
||||
static bool isTileFile(SubFile::Type type)
|
||||
{
|
||||
|
@ -252,8 +252,13 @@ AQMMap::AQMMap(const QString &fileName, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void AQMMap::load()
|
||||
void AQMMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
@ -305,12 +310,6 @@ int AQMMap::zoomOut()
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
void AQMMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
_mapRatio = mapRatio;
|
||||
}
|
||||
|
||||
QPointF AQMMap::ll2xy(const Coordinates &c)
|
||||
{
|
||||
const Zoom &z = _zooms.at(_zoom);
|
||||
@ -406,7 +405,7 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
}
|
||||
|
||||
Map *AQMMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *AQMMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -17,7 +17,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -26,9 +26,9 @@ public:
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
@ -38,7 +38,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct File {
|
||||
|
@ -14,12 +14,7 @@
|
||||
|
||||
static bool resCmp(OziMap *m1, OziMap *m2)
|
||||
{
|
||||
qreal r1, r2;
|
||||
|
||||
r1 = m1->resolution(m1->bounds());
|
||||
r2 = m2->resolution(m2->bounds());
|
||||
|
||||
return r1 > r2;
|
||||
return m1->resolution(m1->bounds()) > m2->resolution(m2->bounds());
|
||||
}
|
||||
|
||||
static bool xCmp(OziMap *m1, OziMap *m2)
|
||||
@ -38,7 +33,7 @@ void Atlas::computeZooms()
|
||||
|
||||
_zooms.append(Zoom(0, _maps.count() - 1));
|
||||
for (int i = 1; i < _maps.count(); i++) {
|
||||
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds());
|
||||
qreal last = _maps.at(i-1)->resolution(_maps.at(i-1)->bounds());
|
||||
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
|
||||
if (cur < last * ZOOM_THRESHOLD) {
|
||||
_zooms.last().last = i-1;
|
||||
@ -136,18 +131,17 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
computeZooms();
|
||||
computeBounds();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void Atlas::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
RectC Atlas::llBounds(const Projection &proj)
|
||||
{
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
_maps[i]->setDevicePixelRatio(deviceRatio, mapRatio);
|
||||
RectC bounds;
|
||||
|
||||
computeBounds();
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
bounds |= _maps.at(i)->llBounds(proj);
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
QRectF Atlas::bounds()
|
||||
@ -277,20 +271,31 @@ void Atlas::draw(QPainter *painter, const QRectF &rect, int mapIndex,
|
||||
const QPointF offset = _bounds.at(mapIndex).xy.topLeft();
|
||||
QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
|
||||
|
||||
map->load();
|
||||
|
||||
painter->translate(offset);
|
||||
map->draw(painter, pr, flags);
|
||||
painter->translate(-offset);
|
||||
}
|
||||
|
||||
void Atlas::load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi)
|
||||
{
|
||||
for (int i = 0; i < _maps.count(); i++)
|
||||
_maps.at(i)->load(in, out, deviceRatio, hidpi);
|
||||
|
||||
computeZooms();
|
||||
computeBounds();
|
||||
}
|
||||
|
||||
void Atlas::unload()
|
||||
{
|
||||
for (int i = 0; i < _maps.count(); i++)
|
||||
_maps.at(i)->unload();
|
||||
|
||||
_zooms.clear();
|
||||
_bounds.clear();
|
||||
}
|
||||
|
||||
Map *Atlas::createTAR(const QString &path, const Projection &, bool *isDir)
|
||||
Map *Atlas::createTAR(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
@ -298,7 +303,7 @@ Map *Atlas::createTAR(const QString &path, const Projection &, bool *isDir)
|
||||
return new Atlas(path, true);
|
||||
}
|
||||
|
||||
Map *Atlas::createTBA(const QString &path, const Projection &, bool *isDir)
|
||||
Map *Atlas::createTBA(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "map.h"
|
||||
#include "rectd.h"
|
||||
#include "projection.h"
|
||||
|
||||
class OziMap;
|
||||
|
||||
@ -16,6 +17,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds(const Projection &proj);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -28,14 +30,15 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *createTAR(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *createTBA(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *createTAR(const QString &path, bool *isDir);
|
||||
static Map *createTBA(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Zoom {
|
||||
|
@ -390,7 +390,7 @@ QImage BSBMap::readImage()
|
||||
}
|
||||
|
||||
BSBMap::BSBMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _ratio(1.0), _dataOffset(-1), _valid(false)
|
||||
: Map(fileName, parent), _img(0), _mapRatio(1.0), _dataOffset(-1), _valid(false)
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
@ -414,19 +414,19 @@ BSBMap::~BSBMap()
|
||||
|
||||
QPointF BSBMap::ll2xy(const Coordinates &c)
|
||||
{
|
||||
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _ratio;
|
||||
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _mapRatio;
|
||||
}
|
||||
|
||||
Coordinates BSBMap::xy2ll(const QPointF &p)
|
||||
{
|
||||
return _projection.xy2ll(_transform.img2proj(p * _ratio));
|
||||
return _projection.xy2ll(_transform.img2proj(p * _mapRatio));
|
||||
}
|
||||
|
||||
QRectF BSBMap::bounds()
|
||||
{
|
||||
return _skewSize.isValid()
|
||||
? QRectF(QPointF(0, 0), _skewSize / _ratio)
|
||||
: QRectF(QPointF(0, 0), _size / _ratio);
|
||||
? QRectF(QPointF(0, 0), _skewSize / _mapRatio)
|
||||
: QRectF(QPointF(0, 0), _size / _mapRatio);
|
||||
}
|
||||
|
||||
void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
@ -435,17 +435,14 @@ void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
_img->draw(painter, rect, flags);
|
||||
}
|
||||
|
||||
void BSBMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
void BSBMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_ratio = mapRatio;
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
void BSBMap::load()
|
||||
{
|
||||
if (!_img) {
|
||||
if (_skew > 0.0 && _skew < 360.0) {
|
||||
QTransform matrix;
|
||||
@ -454,6 +451,9 @@ void BSBMap::load()
|
||||
} else
|
||||
_img = new Image(readImage());
|
||||
}
|
||||
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_mapRatio);
|
||||
}
|
||||
|
||||
void BSBMap::unload()
|
||||
@ -462,7 +462,7 @@ void BSBMap::unload()
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
Map *BSBMap::create(const QString &path, const Projection &, bool *isMap)
|
||||
Map *BSBMap::create(const QString &path, bool *isMap)
|
||||
{
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
@ -25,14 +25,14 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isMap);
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
|
||||
private:
|
||||
bool parseBSB(const QByteArray &line);
|
||||
@ -56,7 +56,7 @@ private:
|
||||
Image *_img;
|
||||
QSize _size;
|
||||
QSize _skewSize;
|
||||
qreal _ratio;
|
||||
qreal _mapRatio;
|
||||
qint64 _dataOffset;
|
||||
QVector<QRgb> _palette;
|
||||
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
QString name() const {return QString();}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return OSM::BOUNDS;}
|
||||
RectC llBounds(const Projection &) {return OSM::BOUNDS;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
|
@ -6,11 +6,10 @@
|
||||
#include "pcs.h"
|
||||
#include "encmap.h"
|
||||
|
||||
#define TILE_SIZE 512
|
||||
#define TEXT_EXTENT 160
|
||||
|
||||
using namespace ENC;
|
||||
|
||||
#define TILE_SIZE 512
|
||||
|
||||
ENCMap::ENCMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _data(fileName), _projection(PCS::pcs(3857)),
|
||||
@ -22,9 +21,16 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent)
|
||||
}
|
||||
}
|
||||
|
||||
void ENCMap::load()
|
||||
void ENCMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(hidpi);
|
||||
|
||||
_tileRatio = deviceRatio;
|
||||
_projection = out;
|
||||
_data.load();
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void ENCMap::unload()
|
||||
@ -173,32 +179,9 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
QPixmap pm;
|
||||
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
||||
painter->drawPixmap(ttl, pm);
|
||||
else {
|
||||
QList<MapData::Poly*> polygons;
|
||||
QList<MapData::Line*> lines;
|
||||
QList<MapData::Point*> points;
|
||||
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE,
|
||||
ttl.y() + TILE_SIZE));
|
||||
polyRect &= _bounds;
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
RectC polyRectC(polyRectD.toRectC(_projection, 20));
|
||||
_data.lines(polyRectC, &lines);
|
||||
_data.polygons(polyRectC, &polygons);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE
|
||||
+ TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT));
|
||||
pointRect &= _bounds;
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data.points(pointRectD.toRectC(_projection, 20), &points);
|
||||
|
||||
tiles.append(RasterTile(_projection, _transform, _data.zooms(),
|
||||
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
||||
lines, polygons, points));
|
||||
}
|
||||
else
|
||||
tiles.append(RasterTile(_projection, _transform, &_data,
|
||||
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio));
|
||||
}
|
||||
}
|
||||
|
||||
@ -218,24 +201,7 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
void ENCMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(mapRatio);
|
||||
|
||||
_tileRatio = deviceRatio;
|
||||
}
|
||||
|
||||
void ENCMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
updateTransform();
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
Map *ENCMap::create(const QString &path, const Projection &, bool *isMap)
|
||||
Map *ENCMap::create(const QString &path, bool *isMap)
|
||||
{
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
@ -53,7 +53,7 @@ public:
|
||||
QString name() const {return _data.name();}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds() {return _llBounds;}
|
||||
RectC llBounds(const Projection &) {return _llBounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -61,10 +61,9 @@ public:
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setOutputProjection(const Projection &projection);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
QPointF ll2xy(const Coordinates &c)
|
||||
{return _transform.proj2img(_projection.ll2xy(c));}
|
||||
@ -76,7 +75,7 @@ public:
|
||||
bool isValid() const {return _data.isValid();}
|
||||
QString errorString() const {return _data.errorString();}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isMap);
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
|
||||
private slots:
|
||||
void jobFinished(ENCMapJob *job);
|
||||
|
@ -182,8 +182,13 @@ Coordinates GEMFMap::xy2ll(const QPointF &p)
|
||||
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
|
||||
}
|
||||
|
||||
void GEMFMap::load()
|
||||
void GEMFMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
@ -296,7 +301,7 @@ void GEMFMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
|
||||
painter->drawPixmap(tp, pixmap);
|
||||
}
|
||||
|
||||
Map *GEMFMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *GEMFMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
GEMFMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
|
||||
int zoom() const {return _zi;}
|
||||
void setZoom(int zoom) {_zi = zoom;}
|
||||
@ -26,18 +26,16 @@ public:
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
|
||||
{_mapRatio = mapRatio;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Region {
|
||||
|
@ -54,28 +54,26 @@ void GeoTIFFMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
_img->draw(painter, rect, flags);
|
||||
}
|
||||
|
||||
void GeoTIFFMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
void GeoTIFFMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_ratio = mapRatio;
|
||||
_ratio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
_img = new Image(path());
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
|
||||
void GeoTIFFMap::load()
|
||||
{
|
||||
if (!_img)
|
||||
_img = new Image(path());
|
||||
}
|
||||
|
||||
void GeoTIFFMap::unload()
|
||||
{
|
||||
delete _img;
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
Map *GeoTIFFMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *GeoTIFFMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -21,14 +21,15 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
Projection _projection;
|
||||
|
@ -16,7 +16,21 @@
|
||||
using namespace IMG;
|
||||
|
||||
#define TILE_SIZE 384
|
||||
#define TEXT_EXTENT 160
|
||||
|
||||
static RectC limitBounds(const RectC &bounds, const Projection &proj)
|
||||
{
|
||||
/* Limit the bounds for some well known projections
|
||||
(world maps have N/S bounds up to 90/-90!) */
|
||||
|
||||
if (proj == PCS::pcs(3857) || proj == PCS::pcs(3395))
|
||||
return bounds & OSM::BOUNDS;
|
||||
else if (proj == PCS::pcs(3031) || proj == PCS::pcs(3976))
|
||||
return bounds & RectC(Coordinates(-180, -60), Coordinates(180, -90));
|
||||
else if (proj == PCS::pcs(3995) || proj == PCS::pcs(3413))
|
||||
return bounds & RectC(Coordinates(-180, 90), Coordinates(180, 60));
|
||||
else
|
||||
return bounds;
|
||||
}
|
||||
|
||||
static QList<MapData*> overlays(const QString &fileName)
|
||||
{
|
||||
@ -56,17 +70,27 @@ IMGMap::IMGMap(const QString &fileName, bool GMAP, QObject *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
_dataBounds = _data.first()->bounds() & OSM::BOUNDS;
|
||||
_zoom = _data.first()->zooms().min();
|
||||
updateTransform();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void IMGMap::load()
|
||||
void IMGMap::load(const Projection &in, const Projection &out,
|
||||
qreal devicelRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(hidpi);
|
||||
|
||||
_tileRatio = devicelRatio;
|
||||
_projection = out;
|
||||
_dataBounds = limitBounds(_data.first()->bounds(), _projection);
|
||||
|
||||
for (int i = 0; i < _data.size(); i++)
|
||||
_data.at(i)->load();
|
||||
|
||||
updateTransform();
|
||||
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void IMGMap::unload()
|
||||
@ -216,30 +240,9 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
if (QPixmapCache::find(key, &pm))
|
||||
painter->drawPixmap(ttl, pm);
|
||||
else {
|
||||
QList<MapData::Poly> polygons, lines;
|
||||
QList<MapData::Point> points;
|
||||
|
||||
QRectF polyRect(ttl, QPointF(ttl.x() + TILE_SIZE,
|
||||
ttl.y() + TILE_SIZE));
|
||||
polyRect &= _bounds;
|
||||
RectD polyRectD(_transform.img2proj(polyRect.topLeft()),
|
||||
_transform.img2proj(polyRect.bottomRight()));
|
||||
_data.at(n)->polys(polyRectD.toRectC(_projection, 20), _zoom,
|
||||
&polygons, &lines);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT,
|
||||
ttl.y() - TEXT_EXTENT), QPointF(ttl.x() + TILE_SIZE
|
||||
+ TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT));
|
||||
pointRect &= _bounds;
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data.at(n)->points(pointRectD.toRectC(_projection, 20),
|
||||
_zoom, &points);
|
||||
|
||||
tiles.append(RasterTile(_projection, _transform,
|
||||
_data.at(n)->style(), _zoom,
|
||||
QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio, key,
|
||||
polygons, lines, points));
|
||||
tiles.append(RasterTile(_projection, _transform, _data.at(n),
|
||||
_zoom, QRect(ttl, QSize(TILE_SIZE, TILE_SIZE)), _tileRatio,
|
||||
key));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -261,37 +264,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(mapRatio);
|
||||
|
||||
_tileRatio = deviceRatio;
|
||||
}
|
||||
|
||||
void IMGMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
// Limit the bounds for some well known projections
|
||||
// (world maps have N/S bounds up to 90/-90!)
|
||||
if (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395))
|
||||
_dataBounds = _data.first()->bounds() & OSM::BOUNDS;
|
||||
else if (_projection == PCS::pcs(3031) || _projection == PCS::pcs(3976))
|
||||
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, -60),
|
||||
Coordinates(180, -90));
|
||||
else if (_projection == PCS::pcs(3995) || _projection == PCS::pcs(3413))
|
||||
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, 90),
|
||||
Coordinates(180, 60));
|
||||
else
|
||||
_dataBounds = _data.first()->bounds();
|
||||
|
||||
updateTransform();
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
Map* IMGMap::createIMG(const QString &path, const Projection &, bool *isDir)
|
||||
Map* IMGMap::createIMG(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
@ -299,7 +272,7 @@ Map* IMGMap::createIMG(const QString &path, const Projection &, bool *isDir)
|
||||
return new IMGMap(path, false);
|
||||
}
|
||||
|
||||
Map* IMGMap::createGMAP(const QString &path, const Projection &, bool *isDir)
|
||||
Map* IMGMap::createGMAP(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
QString name() const {return _data.first()->name();}
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds() {return _dataBounds;}
|
||||
RectC llBounds(const Projection &) {return _data.first()->bounds();}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -70,17 +70,15 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setOutputProjection(const Projection &projection);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal devicelRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map* createIMG(const QString &path, const Projection &, bool *isDir);
|
||||
static Map* createGMAP(const QString &path, const Projection &, bool *isDir);
|
||||
static Map* createIMG(const QString &path, bool *isDir);
|
||||
static Map* createGMAP(const QString &path, bool *isDir);
|
||||
|
||||
private slots:
|
||||
void jobFinished(IMGMapJob *job);
|
||||
|
@ -11,22 +11,6 @@
|
||||
|
||||
#define ic2dc(x) ((x) * 180.0 / 0x7FFFFFFF)
|
||||
|
||||
struct Level {
|
||||
quint32 count;
|
||||
quint32 offset;
|
||||
quint32 scale;
|
||||
};
|
||||
|
||||
struct Ctx {
|
||||
QPainter *painter;
|
||||
QFile *file;
|
||||
qreal ratio;
|
||||
|
||||
Ctx(QPainter *painter, QFile *file, qreal ratio)
|
||||
: painter(painter), file(file), ratio(ratio) {}
|
||||
};
|
||||
|
||||
|
||||
template<class T> bool JNXMap::readValue(T &val)
|
||||
{
|
||||
T data;
|
||||
@ -53,7 +37,7 @@ bool JNXMap::readString(QByteArray& ba)
|
||||
}
|
||||
}
|
||||
|
||||
bool JNXMap::readTiles()
|
||||
bool JNXMap::readHeader()
|
||||
{
|
||||
qint32 lat1, lon2, lat2, lon1;
|
||||
quint32 version, dummy, levels;
|
||||
@ -88,16 +72,22 @@ bool JNXMap::readTiles()
|
||||
}
|
||||
|
||||
_zooms.reserve(lh.size());
|
||||
for (int i = 0; i < lh.count(); i++) {
|
||||
_zooms.append(new Zoom());
|
||||
Zoom *z = _zooms.last();
|
||||
const Level &l = lh.at(i);
|
||||
for (int i = 0; i < lh.count(); i++)
|
||||
_zooms.append(new Zoom(lh.at(i)));
|
||||
|
||||
if (!_file.seek(l.offset))
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JNXMap::readTiles()
|
||||
{
|
||||
for (int i = 0; i < _zooms.size(); i++) {
|
||||
Zoom *z = _zooms[i];
|
||||
|
||||
if (!_file.seek(z->level.offset))
|
||||
return false;
|
||||
|
||||
z->tiles = QVector<Tile>(l.count);
|
||||
for (quint32 j = 0; j < l.count; j++) {
|
||||
z->tiles = QVector<Tile>(z->level.count);
|
||||
for (quint32 j = 0; j < z->level.count; j++) {
|
||||
Tile &tile = z->tiles[j];
|
||||
|
||||
if (!(readValue(tile.top) && readValue(tile.right)
|
||||
@ -134,16 +124,25 @@ bool JNXMap::readTiles()
|
||||
return true;
|
||||
}
|
||||
|
||||
JNXMap::JNXMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||
: Map(fileName, parent), _file(fileName), _zoom(0), _projection(proj),
|
||||
_mapRatio(1.0), _valid(false)
|
||||
void JNXMap::clearTiles()
|
||||
{
|
||||
for (int i = 0; i < _zooms.size(); i++) {
|
||||
Zoom *z = _zooms[i];
|
||||
z->tiles.clear();
|
||||
z->tree.RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _file(fileName), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
if (!_file.open(QIODevice::ReadOnly)) {
|
||||
_errorString = fileName + ": " + _file.errorString();
|
||||
_errorString = _file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readTiles()) {
|
||||
if (!readHeader()) {
|
||||
_errorString = "JNX file format error";
|
||||
return;
|
||||
}
|
||||
@ -158,14 +157,22 @@ JNXMap::~JNXMap()
|
||||
qDeleteAll(_zooms);
|
||||
}
|
||||
|
||||
void JNXMap::load()
|
||||
void JNXMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_projection = in;
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
if (_file.open(QIODevice::ReadOnly))
|
||||
readTiles();
|
||||
}
|
||||
|
||||
void JNXMap::unload()
|
||||
{
|
||||
_file.close();
|
||||
clearTiles();
|
||||
}
|
||||
|
||||
QPointF JNXMap::ll2xy(const Coordinates &c)
|
||||
@ -267,51 +274,10 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
tree.Search(min, max, cb, &ctx);
|
||||
}
|
||||
|
||||
void JNXMap::setInputProjection(const Projection &projection)
|
||||
{
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
||||
for (int i = 0; i < _zooms.size(); i++) {
|
||||
Zoom *z = _zooms[i];
|
||||
|
||||
z->tree.RemoveAll();
|
||||
|
||||
for (int j = 0; j < z->tiles.size(); j++) {
|
||||
Tile &tile = z->tiles[j];
|
||||
|
||||
RectC llrect(Coordinates(ic2dc(tile.left), ic2dc(tile.top)),
|
||||
Coordinates(ic2dc(tile.right), ic2dc(tile.bottom)));
|
||||
RectD rect(_projection.ll2xy(llrect.topLeft()),
|
||||
_projection.ll2xy(llrect.bottomRight()));
|
||||
|
||||
if (j == 0) {
|
||||
ReferencePoint tl(PointD(0, 0), rect.topLeft());
|
||||
ReferencePoint br(PointD(tile.width, tile.height),
|
||||
rect.bottomRight());
|
||||
z->transform = Transform(tl, br);
|
||||
}
|
||||
|
||||
QRectF trect(z->transform.proj2img(rect.topLeft()),
|
||||
z->transform.proj2img(rect.bottomRight()));
|
||||
tile.pos = trect.topLeft();
|
||||
|
||||
qreal min[2], max[2];
|
||||
min[0] = trect.left();
|
||||
min[1] = trect.top();
|
||||
max[0] = trect.right();
|
||||
max[1] = trect.bottom();
|
||||
z->tree.Insert(min, max, &tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map *JNXMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
Map *JNXMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new JNXMap(path, proj);
|
||||
return new JNXMap(path);
|
||||
}
|
||||
|
@ -15,11 +15,11 @@ public:
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JNXMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||
JNXMap(const QString &fileName, QObject *parent = 0);
|
||||
~JNXMap();
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom) {_zoom = zoom;}
|
||||
@ -30,19 +30,16 @@ public:
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setInputProjection(const Projection &projection);
|
||||
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
|
||||
{_mapRatio = mapRatio;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Tile {
|
||||
@ -54,15 +51,37 @@ private:
|
||||
QPointF pos;
|
||||
};
|
||||
|
||||
struct Level {
|
||||
quint32 count;
|
||||
quint32 offset;
|
||||
quint32 scale;
|
||||
};
|
||||
|
||||
struct Zoom {
|
||||
Zoom() {}
|
||||
Zoom(const Level &level) : level(level) {}
|
||||
|
||||
Level level;
|
||||
Transform transform;
|
||||
QVector<Tile> tiles;
|
||||
RTree<Tile*, qreal, 2> tree;
|
||||
};
|
||||
|
||||
struct Ctx {
|
||||
QPainter *painter;
|
||||
QFile *file;
|
||||
qreal ratio;
|
||||
|
||||
Ctx(QPainter *painter, QFile *file, qreal ratio)
|
||||
: painter(painter), file(file), ratio(ratio) {}
|
||||
};
|
||||
|
||||
|
||||
template<class T> bool readValue(T &val);
|
||||
bool readString(QByteArray &ba);
|
||||
bool readHeader();
|
||||
bool readTiles();
|
||||
void clearTiles();
|
||||
|
||||
static bool cb(Tile *tile, void *context);
|
||||
static QPixmap pixmap(const Tile *tile, QFile *file);
|
||||
|
@ -13,14 +13,12 @@
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
#include <QImageReader>
|
||||
#include <QPainter>
|
||||
#include <QPixmapCache>
|
||||
#include <private/qzipreader_p.h>
|
||||
#include"common/util.h"
|
||||
#include "pcs.h"
|
||||
#include "image.h"
|
||||
#include "common/util.h"
|
||||
#include "kmzmap.h"
|
||||
|
||||
|
||||
@ -29,162 +27,140 @@
|
||||
#define TL(m) ((m).bbox().topLeft())
|
||||
#define BR(m) ((m).bbox().bottomRight())
|
||||
|
||||
|
||||
KMZMap::Overlay::Overlay(const QString &path, const QSize &size,
|
||||
const RectC &bbox, double rotation, const Projection *proj, qreal ratio)
|
||||
: _path(path), _size(size), _bbox(bbox), _rotation(rotation), _img(0),
|
||||
_proj(proj), _ratio(ratio)
|
||||
bool KMZMap::resCmp(const Tile &m1, const Tile &m2)
|
||||
{
|
||||
ReferencePoint tl(PointD(0, 0), _proj->ll2xy(bbox.topLeft()));
|
||||
ReferencePoint br(PointD(size.width(), size.height()),
|
||||
_proj->ll2xy(bbox.bottomRight()));
|
||||
|
||||
QTransform t;
|
||||
t.rotate(-rotation);
|
||||
QRectF b(0, 0, size.width(), size.height());
|
||||
QPolygonF ma = t.map(b);
|
||||
_bounds = ma.boundingRect();
|
||||
|
||||
_transform = Transform(tl, br);
|
||||
return m1.resolution() > m2.resolution();
|
||||
}
|
||||
|
||||
qreal KMZMap::Overlay::resolution(const QRectF &rect) const
|
||||
{
|
||||
qreal cy = rect.center().y();
|
||||
QPointF cl(rect.left(), cy);
|
||||
QPointF cr(rect.right(), cy);
|
||||
|
||||
qreal ds = xy2ll(cl).distanceTo(xy2ll(cr));
|
||||
qreal ps = QLineF(cl, cr).length();
|
||||
|
||||
return ds/ps;
|
||||
}
|
||||
|
||||
void KMZMap::Overlay::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
if (_img) {
|
||||
QRectF rr(rect.topLeft() / _ratio, rect.size());
|
||||
|
||||
if (_rotation) {
|
||||
painter->save();
|
||||
painter->rotate(-_rotation);
|
||||
_img->draw(painter, rr, flags);
|
||||
painter->restore();
|
||||
} else
|
||||
_img->draw(painter, rr, flags);
|
||||
}
|
||||
|
||||
//painter->setPen(Qt::red);
|
||||
//painter->drawRect(_bounds);
|
||||
}
|
||||
|
||||
void KMZMap::Overlay::load(QZipReader *zip)
|
||||
{
|
||||
if (!_img) {
|
||||
QByteArray ba(zip->fileData(_path));
|
||||
_img = new Image(QImage::fromData(ba));
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
void KMZMap::Overlay::unload()
|
||||
{
|
||||
delete _img;
|
||||
_img = 0;
|
||||
}
|
||||
|
||||
void KMZMap::Overlay::setProjection(const Projection *proj)
|
||||
{
|
||||
_proj = proj;
|
||||
|
||||
ReferencePoint tl(PointD(0, 0), _proj->ll2xy(_bbox.topLeft()));
|
||||
ReferencePoint br(PointD(_size.width(), _size.height()),
|
||||
_proj->ll2xy(_bbox.bottomRight()));
|
||||
|
||||
QTransform t;
|
||||
t.rotate(-_rotation);
|
||||
QRectF b(0, 0, _size.width(), _size.height());
|
||||
QPolygonF ma = t.map(b);
|
||||
_bounds = ma.boundingRect();
|
||||
|
||||
_transform = Transform(tl, br);
|
||||
}
|
||||
|
||||
void KMZMap::Overlay::setDevicePixelRatio(qreal ratio)
|
||||
{
|
||||
_ratio = ratio;
|
||||
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_ratio);
|
||||
}
|
||||
|
||||
|
||||
bool KMZMap::resCmp(const Overlay &m1, const Overlay &m2)
|
||||
{
|
||||
qreal r1, r2;
|
||||
|
||||
r1 = m1.resolution(m1.bounds());
|
||||
r2 = m2.resolution(m2.bounds());
|
||||
|
||||
return r1 > r2;
|
||||
}
|
||||
|
||||
bool KMZMap::xCmp(const Overlay &m1, const Overlay &m2)
|
||||
bool KMZMap::xCmp(const Tile &m1, const Tile &m2)
|
||||
{
|
||||
return TL(m1).lon() < TL(m2).lon();
|
||||
}
|
||||
|
||||
bool KMZMap::yCmp(const Overlay &m1, const Overlay &m2)
|
||||
bool KMZMap::yCmp(const Tile &m1, const Tile &m2)
|
||||
{
|
||||
return TL(m1).lat() > TL(m2).lat();
|
||||
}
|
||||
|
||||
|
||||
KMZMap::Tile::Tile(const Overlay &overlay, QZipReader &zip)
|
||||
: _overlay(overlay)
|
||||
{
|
||||
QByteArray ba(zip.fileData(overlay.path()));
|
||||
QBuffer img(&ba);
|
||||
QImageReader ir(&img);
|
||||
_size = ir.size();
|
||||
}
|
||||
|
||||
void KMZMap::Tile::configure(const Projection &proj)
|
||||
{
|
||||
ReferencePoint tl(PointD(0, 0), proj.ll2xy(bbox().topLeft()));
|
||||
ReferencePoint br(PointD(_size.width(), _size.height()),
|
||||
proj.ll2xy(bbox().bottomRight()));
|
||||
_transform = Transform(tl, br);
|
||||
}
|
||||
|
||||
QRectF KMZMap::Tile::bounds() const
|
||||
{
|
||||
QTransform t;
|
||||
t.rotate(-rotation());
|
||||
QRectF b(0, 0, _size.width(), _size.height());
|
||||
QPolygonF ma(t.map(b));
|
||||
return ma.boundingRect();
|
||||
}
|
||||
|
||||
qreal KMZMap::Tile::resolution() const
|
||||
{
|
||||
QRectF d(0, 0, _size.width(), _size.height());
|
||||
qreal dy = d.center().y();
|
||||
QPointF dl(d.left(), dy);
|
||||
QPointF dr(d.right(), dy);
|
||||
|
||||
double cy = bbox().center().lat();
|
||||
Coordinates cl(bbox().left(), cy);
|
||||
Coordinates cr(bbox().right(), cy);
|
||||
|
||||
qreal ds = cl.distanceTo(cr);
|
||||
qreal ps = QLineF(dl, dr).length();
|
||||
|
||||
return ds/ps;
|
||||
}
|
||||
|
||||
bool KMZMap::createTiles(const QList<Overlay> &overlays, QZipReader &zip)
|
||||
{
|
||||
if (overlays.isEmpty()) {
|
||||
_errorString = "No usable overlay found";
|
||||
return false;
|
||||
}
|
||||
|
||||
_tiles.reserve(overlays.size());
|
||||
|
||||
for (int i = 0; i < overlays.size(); i++) {
|
||||
const Overlay &ol = overlays.at(i);
|
||||
Tile tile(ol, zip);
|
||||
if (tile.isValid())
|
||||
_tiles.append(tile);
|
||||
else {
|
||||
_errorString = ol.path() + ": invalid/missing overlay image";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KMZMap::computeLLBounds()
|
||||
{
|
||||
for (int i = 0; i < _tiles.size(); i++)
|
||||
_llbounds |= _tiles.at(i).bbox();
|
||||
}
|
||||
|
||||
void KMZMap::computeZooms()
|
||||
{
|
||||
std::sort(_maps.begin(), _maps.end(), resCmp);
|
||||
std::sort(_tiles.begin(), _tiles.end(), resCmp);
|
||||
|
||||
_zooms.append(Zoom(0, _maps.count() - 1));
|
||||
for (int i = 1; i < _maps.count(); i++) {
|
||||
qreal last = _maps.at(i-1).resolution(_maps.at(i).bounds());
|
||||
qreal cur = _maps.at(i).resolution(_maps.at(i).bounds());
|
||||
_zooms.append(Zoom(0, _tiles.count() - 1));
|
||||
for (int i = 1; i < _tiles.count(); i++) {
|
||||
qreal last = _tiles.at(i-1).resolution();
|
||||
qreal cur = _tiles.at(i).resolution();
|
||||
if (cur < last * ZOOM_THRESHOLD) {
|
||||
_zooms.last().last = i-1;
|
||||
_zooms.append(Zoom(i, _maps.count() - 1));
|
||||
_zooms.append(Zoom(i, _tiles.count() - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KMZMap::computeBounds()
|
||||
{
|
||||
QVector<QPointF> offsets(_maps.count());
|
||||
QVector<QPointF> offsets(_tiles.count());
|
||||
|
||||
for (int z = 0; z < _zooms.count(); z++) {
|
||||
QList<Overlay> m;
|
||||
QList<Tile> m;
|
||||
for (int i = _zooms.at(z).first; i <= _zooms.at(z).last; i++)
|
||||
m.append(_maps.at(i));
|
||||
m.append(_tiles.at(i));
|
||||
|
||||
std::sort(m.begin(), m.end(), xCmp);
|
||||
offsets[_maps.indexOf(m.first())].setX(m.first().bounds().left());
|
||||
offsets[_tiles.indexOf(m.first())].setX(m.first().bounds().left());
|
||||
for (int i = 1; i < m.size(); i++) {
|
||||
qreal w = m.first().ll2xy(TL(m.at(i))).x();
|
||||
offsets[_maps.indexOf(m.at(i))].setX(w + m.at(i).bounds().left());
|
||||
qreal w = ll2xy(TL(m.at(i)), m.first().transform()).x();
|
||||
offsets[_tiles.indexOf(m.at(i))].setX(w + m.at(i).bounds().left());
|
||||
}
|
||||
|
||||
std::sort(m.begin(), m.end(), yCmp);
|
||||
offsets[_maps.indexOf(m.first())].setY(m.first().bounds().top());
|
||||
offsets[_tiles.indexOf(m.first())].setY(m.first().bounds().top());
|
||||
for (int i = 1; i < m.size(); i++) {
|
||||
qreal h = m.first().ll2xy(TL(m.at(i))).y();
|
||||
offsets[_maps.indexOf(m.at(i))].setY(h + m.at(i).bounds().top());
|
||||
qreal h = ll2xy(TL(m.at(i)), m.first().transform()).y();
|
||||
offsets[_tiles.indexOf(m.at(i))].setY(h + m.at(i).bounds().top());
|
||||
}
|
||||
}
|
||||
|
||||
_adjust = 0;
|
||||
_bounds = QVector<Bounds>(_maps.count());
|
||||
for (int i = 0; i < _maps.count(); i++) {
|
||||
QRectF xy(offsets.at(i), _maps.at(i).bounds().size());
|
||||
_bounds[i] = Bounds(_maps.at(i).bbox(), xy);
|
||||
_adjust = qMin(qMin(_maps.at(i).bounds().left(),
|
||||
_maps.at(i).bounds().top()), _adjust);
|
||||
_bounds = QVector<Bounds>(_tiles.count());
|
||||
for (int i = 0; i < _tiles.count(); i++) {
|
||||
QRectF xy(offsets.at(i), _tiles.at(i).bounds().size() / _mapRatio);
|
||||
_bounds[i] = Bounds(_tiles.at(i).bbox(), xy);
|
||||
_adjust = qMin(qMin(_tiles.at(i).bounds().left(),
|
||||
_tiles.at(i).bounds().top()), _adjust);
|
||||
}
|
||||
_adjust = -_adjust;
|
||||
}
|
||||
@ -236,7 +212,7 @@ RectC KMZMap::latLonBox(QXmlStreamReader &reader, double *rotation)
|
||||
return RectC(Coordinates(left, top), Coordinates(right, bottom));
|
||||
}
|
||||
|
||||
void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip)
|
||||
void KMZMap::groundOverlay(QXmlStreamReader &reader, QList<Overlay> &overlays)
|
||||
{
|
||||
QString image;
|
||||
RectC rect;
|
||||
@ -251,93 +227,87 @@ void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip)
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
if (rect.isValid()) {
|
||||
QByteArray ba(zip.fileData(image));
|
||||
QBuffer img(&ba);
|
||||
QImageReader ir(&img);
|
||||
QSize size(ir.size());
|
||||
|
||||
if (size.isValid())
|
||||
_maps.append(Overlay(image, size, rect, rotation, &_projection,
|
||||
_ratio));
|
||||
else
|
||||
reader.raiseError(image + ": Invalid image file");
|
||||
} else
|
||||
if (rect.isValid())
|
||||
overlays.append(Overlay(image, rect, rotation));
|
||||
else
|
||||
reader.raiseError("Invalid LatLonBox");
|
||||
}
|
||||
|
||||
void KMZMap::document(QXmlStreamReader &reader, QZipReader &zip)
|
||||
void KMZMap::document(QXmlStreamReader &reader, QList<Overlay> &overlays)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("Document"))
|
||||
document(reader, zip);
|
||||
document(reader, overlays);
|
||||
else if (reader.name() == QLatin1String("GroundOverlay"))
|
||||
groundOverlay(reader, zip);
|
||||
groundOverlay(reader, overlays);
|
||||
else if (reader.name() == QLatin1String("Folder"))
|
||||
folder(reader, zip);
|
||||
folder(reader, overlays);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMZMap::folder(QXmlStreamReader &reader, QZipReader &zip)
|
||||
void KMZMap::folder(QXmlStreamReader &reader, QList<Overlay> &overlays)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("GroundOverlay"))
|
||||
groundOverlay(reader, zip);
|
||||
groundOverlay(reader, overlays);
|
||||
else if (reader.name() == QLatin1String("Folder"))
|
||||
folder(reader, zip);
|
||||
folder(reader, overlays);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip)
|
||||
void KMZMap::kml(QXmlStreamReader &reader, QList<Overlay> &overlays)
|
||||
{
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("Document"))
|
||||
document(reader, zip);
|
||||
document(reader, overlays);
|
||||
else if (reader.name() == QLatin1String("GroundOverlay"))
|
||||
groundOverlay(reader, zip);
|
||||
groundOverlay(reader, overlays);
|
||||
else if (reader.name() == QLatin1String("Folder"))
|
||||
folder(reader, zip);
|
||||
folder(reader, overlays);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KMZMap::KMZMap(const QString &fileName, const Projection &proj, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _projection(proj),
|
||||
_ratio(1.0), _valid(false)
|
||||
KMZMap::KMZMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
{
|
||||
QZipReader zip(fileName, QIODevice::ReadOnly);
|
||||
QByteArray xml(zip.fileData("doc.kml"));
|
||||
QXmlStreamReader reader(xml);
|
||||
QList<Overlay> overlays;
|
||||
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("kml"))
|
||||
kml(reader, zip);
|
||||
kml(reader, overlays);
|
||||
else
|
||||
reader.raiseError("Not a KMZ file");
|
||||
}
|
||||
|
||||
if (reader.error()) {
|
||||
_errorString = "doc.kml:" + QString::number(reader.lineNumber()) + ": "
|
||||
+ reader.errorString();
|
||||
return;
|
||||
}
|
||||
if (_maps.isEmpty()) {
|
||||
_errorString = "No usable GroundOverlay found";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!createTiles(overlays, zip))
|
||||
return;
|
||||
computeLLBounds();
|
||||
computeZooms();
|
||||
computeBounds();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
KMZMap::~KMZMap()
|
||||
{
|
||||
delete _zip;
|
||||
}
|
||||
|
||||
QRectF KMZMap::bounds()
|
||||
{
|
||||
QRectF rect;
|
||||
@ -364,8 +334,9 @@ int KMZMap::zoomFit(const QSize &size, const RectC &br)
|
||||
if (!_bounds.at(i).ll.contains(br.center()))
|
||||
continue;
|
||||
|
||||
QRect sbr = QRectF(_maps.at(i).ll2xy(br.topLeft()),
|
||||
_maps.at(i).ll2xy(br.bottomRight())).toRect().normalized();
|
||||
QRect sbr = QRectF(ll2xy(br.topLeft(), _tiles.at(i).transform()),
|
||||
ll2xy(br.bottomRight(), _tiles.at(i).transform()))
|
||||
.toRect().normalized();
|
||||
|
||||
if (sbr.size().width() > size.width()
|
||||
|| sbr.size().height() > size.height())
|
||||
@ -413,10 +384,10 @@ QPointF KMZMap::ll2xy(const Coordinates &c)
|
||||
}
|
||||
}
|
||||
|
||||
QPointF p = _maps.at(_mapIndex).ll2xy(c);
|
||||
if (_maps.at(_mapIndex).rotation()) {
|
||||
QPointF p = ll2xy(c, _tiles.at(_mapIndex).transform());
|
||||
if (_tiles.at(_mapIndex).rotation()) {
|
||||
QTransform matrix;
|
||||
matrix.rotate(-_maps.at(_mapIndex).rotation());
|
||||
matrix.rotate(-_tiles.at(_mapIndex).rotation());
|
||||
return matrix.map(p) + _bounds.at(_mapIndex).xy.topLeft();
|
||||
} else
|
||||
return p + _bounds.at(_mapIndex).xy.topLeft();
|
||||
@ -434,90 +405,89 @@ Coordinates KMZMap::xy2ll(const QPointF &p)
|
||||
}
|
||||
|
||||
QPointF p2 = p - _bounds.at(idx).xy.topLeft();
|
||||
if (_maps.at(idx).rotation()) {
|
||||
if (_tiles.at(idx).rotation()) {
|
||||
QTransform matrix;
|
||||
matrix.rotate(_maps.at(idx).rotation());
|
||||
return _maps.at(idx).xy2ll(matrix.map(p2));
|
||||
matrix.rotate(_tiles.at(idx).rotation());
|
||||
return xy2ll(matrix.map(p2), _tiles.at(idx).transform());
|
||||
} else
|
||||
return _maps.at(idx).xy2ll(p2);
|
||||
return xy2ll(p2, _tiles.at(idx).transform());
|
||||
}
|
||||
|
||||
void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
QRectF er = rect.adjusted(-_adjust * _ratio, -_adjust * _ratio,
|
||||
_adjust * _ratio, _adjust * _ratio);
|
||||
Q_UNUSED(flags);
|
||||
|
||||
QRectF er = rect.adjusted(-_adjust * _mapRatio, -_adjust * _mapRatio,
|
||||
_adjust * _mapRatio, _adjust * _mapRatio);
|
||||
|
||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||
QRectF ir = er.intersected(_bounds.at(i).xy);
|
||||
if (!ir.isNull())
|
||||
draw(painter, ir, i, flags);
|
||||
draw(painter, ir, i);
|
||||
}
|
||||
}
|
||||
|
||||
void KMZMap::load()
|
||||
void KMZMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(out);
|
||||
|
||||
_projection = in;
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
for (int i = 0; i < _tiles.size(); i++)
|
||||
_tiles[i].configure(_projection);
|
||||
|
||||
computeBounds();
|
||||
|
||||
Q_ASSERT(!_zip);
|
||||
_zip = new QZipReader(path(), QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
void KMZMap::unload()
|
||||
{
|
||||
for (int i = 0; i < _maps.count(); i++)
|
||||
_maps[i].unload();
|
||||
_bounds.clear();
|
||||
|
||||
delete _zip;
|
||||
_zip = 0;
|
||||
}
|
||||
|
||||
void KMZMap::setInputProjection(const Projection &projection)
|
||||
void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex)
|
||||
{
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
_maps[i].setProjection(&_projection);
|
||||
|
||||
_bounds.clear();
|
||||
computeBounds();
|
||||
}
|
||||
|
||||
void KMZMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
|
||||
if (mapRatio == _ratio)
|
||||
return;
|
||||
|
||||
_ratio = mapRatio;
|
||||
|
||||
for (int i = 0; i < _maps.size(); i++)
|
||||
_maps[i].setDevicePixelRatio(_ratio);
|
||||
|
||||
_bounds.clear();
|
||||
computeBounds();
|
||||
}
|
||||
|
||||
void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex,
|
||||
Flags flags)
|
||||
{
|
||||
Overlay &map = _maps[mapIndex];
|
||||
const Tile &map = _tiles.at(mapIndex);
|
||||
const QPointF offset = _bounds.at(mapIndex).xy.topLeft();
|
||||
QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
|
||||
|
||||
map.load(_zip);
|
||||
QRectF sr(pr.topLeft() * _mapRatio, pr.size() * _mapRatio);
|
||||
QString key(path() + "/" + map.path());
|
||||
QPixmap pm;
|
||||
|
||||
painter->save();
|
||||
painter->translate(offset);
|
||||
map.draw(painter, pr, flags);
|
||||
if (map.rotation())
|
||||
painter->rotate(-map.rotation());
|
||||
|
||||
if (QPixmapCache::find(key, &pm)) {
|
||||
pm.setDevicePixelRatio(_mapRatio);
|
||||
painter->drawPixmap(pr.topLeft(), pm, sr);
|
||||
} else {
|
||||
QByteArray ba(_zip->fileData(map.path()));
|
||||
QImage img(QImage::fromData(ba));
|
||||
pm = QPixmap::fromImage(img);
|
||||
pm.setDevicePixelRatio(_mapRatio);
|
||||
painter->drawPixmap(pr.topLeft(), pm, sr);
|
||||
QPixmapCache::insert(key, pm);
|
||||
}
|
||||
|
||||
//painter->setPen(Qt::red);
|
||||
//painter->drawRect(map.bounds());
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
Map *KMZMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new KMZMap(path, proj);
|
||||
return new KMZMap(path);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef KMZMAP_H
|
||||
#define KMZMAP_H
|
||||
|
||||
#include <QImage>
|
||||
#include "projection.h"
|
||||
#include "transform.h"
|
||||
#include "rectd.h"
|
||||
@ -8,15 +9,16 @@
|
||||
|
||||
class QXmlStreamReader;
|
||||
class QZipReader;
|
||||
class Image;
|
||||
|
||||
class KMZMap : public Map
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KMZMap(const QString &fileName, const Projection &proj, QObject *parent = 0);
|
||||
KMZMap(const QString &fileName, QObject *parent = 0);
|
||||
~KMZMap();
|
||||
|
||||
RectC llBounds(const Projection &) {return _llbounds;}
|
||||
QRectF bounds();
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -30,54 +32,52 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
void setInputProjection(const Projection &projection);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
class Overlay {
|
||||
public:
|
||||
Overlay(const QString &path, const QSize &size, const RectC &bbox,
|
||||
double rotation, const Projection *proj, qreal ratio);
|
||||
bool operator==(const Overlay &other) const
|
||||
{return _path == other._path;}
|
||||
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return QPointF(_transform.proj2img(_proj->ll2xy(c))) / _ratio;}
|
||||
Coordinates xy2ll(const QPointF &p) const
|
||||
{return _proj->xy2ll(_transform.img2proj(p * _ratio));}
|
||||
Overlay(const QString &path, const RectC &bbox, double rotation)
|
||||
: _path(path), _bbox(bbox), _rotation(rotation) {}
|
||||
|
||||
const QString &path() const {return _path;}
|
||||
const RectC &bbox() const {return _bbox;}
|
||||
const QRectF &bounds() const {return _bounds;}
|
||||
qreal resolution(const QRectF &rect) const;
|
||||
qreal rotation() const {return _rotation;}
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load(QZipReader *zip);
|
||||
void unload();
|
||||
|
||||
void setProjection(const Projection *proj);
|
||||
void setDevicePixelRatio(qreal ratio);
|
||||
|
||||
private:
|
||||
QString _path;
|
||||
QSize _size;
|
||||
QRectF _bounds;
|
||||
RectC _bbox;
|
||||
qreal _rotation;
|
||||
Image *_img;
|
||||
const Projection *_proj;
|
||||
};
|
||||
|
||||
class Tile {
|
||||
public:
|
||||
Tile(const Overlay &overlay, QZipReader &zip);
|
||||
|
||||
bool operator==(const Tile &other) const
|
||||
{return _overlay.path() == other._overlay.path();}
|
||||
|
||||
bool isValid() const {return _size.isValid();}
|
||||
const QString &path() const {return _overlay.path();}
|
||||
qreal rotation() const {return _overlay.rotation();}
|
||||
const RectC &bbox() const {return _overlay.bbox();}
|
||||
const Transform &transform() const {return _transform;}
|
||||
QRectF bounds() const;
|
||||
qreal resolution() const;
|
||||
|
||||
void configure(const Projection &proj);
|
||||
|
||||
private:
|
||||
Overlay _overlay;
|
||||
QSize _size;
|
||||
Transform _transform;
|
||||
qreal _ratio;
|
||||
};
|
||||
|
||||
struct Zoom {
|
||||
@ -96,23 +96,32 @@ private:
|
||||
Bounds(const RectC &ll, const QRectF &xy) : ll(ll), xy(xy) {}
|
||||
};
|
||||
|
||||
void kml(QXmlStreamReader &reader, QZipReader &zip);
|
||||
void document(QXmlStreamReader &reader, QZipReader &zip);
|
||||
void folder(QXmlStreamReader &reader, QZipReader &zip);
|
||||
void groundOverlay(QXmlStreamReader &reader, QZipReader &zip);
|
||||
void kml(QXmlStreamReader &reader, QList<Overlay> &overlays);
|
||||
void document(QXmlStreamReader &reader, QList<Overlay> &overlays);
|
||||
void folder(QXmlStreamReader &reader, QList<Overlay> &overlays);
|
||||
void groundOverlay(QXmlStreamReader &reader, QList<Overlay> &overlays);
|
||||
RectC latLonBox(QXmlStreamReader &reader, double *rotation);
|
||||
QString icon(QXmlStreamReader &reader);
|
||||
double number(QXmlStreamReader &reader);
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, int mapIndex, Flags flags);
|
||||
void draw(QPainter *painter, const QRectF &rect, int mapIndex);
|
||||
|
||||
bool createTiles(const QList<Overlay> &overlays, QZipReader &zip);
|
||||
void computeZooms();
|
||||
void computeBounds();
|
||||
void computeLLBounds();
|
||||
|
||||
static bool resCmp(const Overlay &m1, const Overlay &m2);
|
||||
static bool xCmp(const Overlay &m1, const Overlay &m2);
|
||||
static bool yCmp(const Overlay &m1, const Overlay &m2);
|
||||
QPointF ll2xy(const Coordinates &c, const Transform &transform) const
|
||||
{return QPointF(transform.proj2img(_projection.ll2xy(c))) / _mapRatio;}
|
||||
Coordinates xy2ll(const QPointF &p, const Transform &transform) const
|
||||
{return _projection.xy2ll(transform.img2proj(p * _mapRatio));}
|
||||
|
||||
QList<Overlay> _maps;
|
||||
static bool resCmp(const Tile &m1, const Tile &m2);
|
||||
static bool xCmp(const Tile &m1, const Tile &m2);
|
||||
static bool yCmp(const Tile &m1, const Tile &m2);
|
||||
|
||||
RectC _llbounds;
|
||||
QList<Tile> _tiles;
|
||||
QVector<Zoom> _zooms;
|
||||
QVector<Bounds> _bounds;
|
||||
int _zoom;
|
||||
@ -120,7 +129,7 @@ private:
|
||||
QZipReader *_zip;
|
||||
qreal _adjust;
|
||||
Projection _projection;
|
||||
qreal _ratio;
|
||||
qreal _mapRatio;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
@ -5,40 +5,36 @@
|
||||
|
||||
#define SAMPLES 100
|
||||
|
||||
void Map::growLeft(const QPointF &p, RectC &rect)
|
||||
static void growLeft(const Coordinates &c, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lon() < rect.left())
|
||||
rect.setLeft(c.lon());
|
||||
}
|
||||
|
||||
void Map::growRight(const QPointF &p, RectC &rect)
|
||||
static void growRight(const Coordinates &c, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lon() > rect.right())
|
||||
rect.setRight(c.lon());
|
||||
}
|
||||
|
||||
void Map::growTop(const QPointF &p, RectC &rect)
|
||||
static void growTop(const Coordinates &c, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lat() > rect.top())
|
||||
rect.setTop(c.lat());
|
||||
}
|
||||
|
||||
void Map::growBottom(const QPointF &p, RectC &rect)
|
||||
static void growBottom(const Coordinates &c, RectC &rect)
|
||||
{
|
||||
Coordinates c(xy2ll(p));
|
||||
|
||||
if (c.lat() < rect.bottom())
|
||||
rect.setBottom(c.lat());
|
||||
}
|
||||
|
||||
RectC Map::llBounds()
|
||||
RectC Map::llBounds(const Projection &proj)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
|
||||
/* We use bounds() and xy2ll() here as this fallback implementation is
|
||||
used ONLY for maps providing those functions since map creation. */
|
||||
QRectF b(bounds());
|
||||
double dx = b.width() / SAMPLES;
|
||||
double dy = b.height() / SAMPLES;
|
||||
@ -49,14 +45,14 @@ RectC Map::llBounds()
|
||||
|
||||
for (int i = 0; i <= SAMPLES; i++) {
|
||||
double x = b.left() + i * dx;
|
||||
growBottom(QPointF(x, b.bottom()), rect);
|
||||
growTop(QPointF(x, b.top()), rect);
|
||||
growBottom(xy2ll(QPointF(x, b.bottom())), rect);
|
||||
growTop(xy2ll(QPointF(x, b.top())), rect);
|
||||
}
|
||||
|
||||
for (int i = 0; i <= SAMPLES; i++) {
|
||||
double y = b.top() + i * dy;
|
||||
growLeft(QPointF(b.left(), y), rect);
|
||||
growRight(QPointF(b.right(), y), rect);
|
||||
growLeft(xy2ll(QPointF(b.left(), y)), rect);
|
||||
growRight(xy2ll(QPointF(b.right(), y)), rect);
|
||||
}
|
||||
|
||||
return rect;
|
||||
|
@ -28,10 +28,19 @@ public:
|
||||
: QObject(parent), _path(path) {}
|
||||
virtual ~Map() {}
|
||||
|
||||
/* Functions available since map creation */
|
||||
const QString &path() const {return _path;}
|
||||
virtual QString name() const {return Util::file2name(path());}
|
||||
virtual RectC llBounds(const Projection &proj);
|
||||
|
||||
virtual bool isValid() const {return true;}
|
||||
virtual bool isReady() const {return true;}
|
||||
virtual QString errorString() const {return QString();}
|
||||
|
||||
/* Functions that shall be called after load() */
|
||||
virtual void load(const Projection &, const Projection &, qreal, bool) {}
|
||||
virtual void unload() {}
|
||||
|
||||
virtual RectC llBounds();
|
||||
virtual QRectF bounds() = 0;
|
||||
virtual qreal resolution(const QRectF &rect);
|
||||
|
||||
@ -47,26 +56,12 @@ public:
|
||||
virtual void draw(QPainter *painter, const QRectF &rect, Flags flags) = 0;
|
||||
|
||||
virtual void clearCache() {}
|
||||
virtual void load() {}
|
||||
virtual void unload() {}
|
||||
virtual void setDevicePixelRatio(qreal, qreal) {}
|
||||
virtual void setOutputProjection(const Projection &) {}
|
||||
virtual void setInputProjection(const Projection &) {}
|
||||
|
||||
virtual bool isValid() const {return true;}
|
||||
virtual bool isReady() const {return true;}
|
||||
virtual QString errorString() const {return QString();}
|
||||
|
||||
signals:
|
||||
void tilesLoaded();
|
||||
void mapLoaded();
|
||||
|
||||
private:
|
||||
void growLeft(const QPointF &p, RectC &rect);
|
||||
void growRight(const QPointF &p, RectC &rect);
|
||||
void growTop(const QPointF &p, RectC &rect);
|
||||
void growBottom(const QPointF &p, RectC &rect);
|
||||
|
||||
QString _path;
|
||||
};
|
||||
|
||||
|
@ -62,7 +62,7 @@ MapList::ParserMap MapList::parsers()
|
||||
|
||||
MapList::ParserMap MapList::_parsers = parsers();
|
||||
|
||||
Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
Map *MapList::loadFile(const QString &path, bool *isDir)
|
||||
{
|
||||
ParserMap::iterator it;
|
||||
QFileInfo fi(path);
|
||||
@ -73,7 +73,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
if ((it = _parsers.find(suffix)) != _parsers.end()) {
|
||||
while (it != _parsers.end() && it.key() == suffix) {
|
||||
delete map;
|
||||
map = it.value()(path, proj, isDir);
|
||||
map = it.value()(path, isDir);
|
||||
if (map->isValid())
|
||||
return map;
|
||||
else
|
||||
@ -82,7 +82,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
}
|
||||
} else {
|
||||
for (it = _parsers.begin(); it != _parsers.end(); it++) {
|
||||
map = it.value()(path, proj, isDir);
|
||||
map = it.value()(path, isDir);
|
||||
if (map->isValid())
|
||||
return map;
|
||||
else {
|
||||
@ -100,8 +100,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
|
||||
return map ? map : new InvalidMap(path, "Unknown file format");
|
||||
}
|
||||
|
||||
TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map *> *parent)
|
||||
TreeNode<Map*> MapList::loadDir(const QString &path, TreeNode<Map*> *parent)
|
||||
{
|
||||
QDir md(path);
|
||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
@ -118,12 +117,12 @@ TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
|
||||
QString suffix = fi.suffix().toLower();
|
||||
|
||||
if (fi.isDir()) {
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), proj, &tree));
|
||||
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), &tree));
|
||||
if (!child.isEmpty())
|
||||
tree.addChild(child);
|
||||
} else if (filter().contains("*." + suffix)) {
|
||||
bool isDir = false;
|
||||
Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir);
|
||||
Map *map = loadFile(fi.absoluteFilePath(), &isDir);
|
||||
if (isDir) {
|
||||
if (parent)
|
||||
parent->addItem(map);
|
||||
@ -138,13 +137,13 @@ TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
|
||||
return tree;
|
||||
}
|
||||
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path, const Projection &proj)
|
||||
TreeNode<Map *> MapList::loadMaps(const QString &path)
|
||||
{
|
||||
if (QFileInfo(path).isDir())
|
||||
return loadDir(path, proj);
|
||||
return loadDir(path);
|
||||
else {
|
||||
TreeNode<Map*> tree;
|
||||
tree.addItem(loadFile(path, proj));
|
||||
tree.addItem(loadFile(path));
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
@ -10,18 +10,16 @@ class Projection;
|
||||
class MapList
|
||||
{
|
||||
public:
|
||||
static TreeNode<Map*> loadMaps(const QString &path, const Projection &proj);
|
||||
static TreeNode<Map*> loadMaps(const QString &path);
|
||||
static QString formats();
|
||||
static QStringList filter();
|
||||
|
||||
private:
|
||||
typedef Map*(*ParserCb)(const QString &, const Projection &, bool *isDir);
|
||||
typedef Map*(*ParserCb)(const QString &, bool *isDir);
|
||||
typedef QMultiMap<QString, ParserCb> ParserMap;
|
||||
|
||||
static Map *loadFile(const QString &path, const Projection &proj,
|
||||
bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
|
||||
TreeNode<Map *> *parent = 0);
|
||||
static Map *loadFile(const QString &path, bool *isDir = 0);
|
||||
static TreeNode<Map*> loadDir(const QString &path, TreeNode<Map*> *parent = 0);
|
||||
|
||||
static ParserMap parsers();
|
||||
static ParserMap _parsers;
|
||||
|
@ -23,17 +23,21 @@ using namespace Mapsforge;
|
||||
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
||||
QList<MapData::Path> *dst)
|
||||
{
|
||||
for (int i = 0; i < src->size(); i++)
|
||||
if (rect.intersects(src->at(i).poly.boundingRect()))
|
||||
dst->append(src->at(i));
|
||||
for (int i = 0; i < src->size(); i++) {
|
||||
const MapData::Path &path = src->at(i);
|
||||
if (rect.intersects(path.poly.boundingRect()))
|
||||
dst->append(path);
|
||||
}
|
||||
}
|
||||
|
||||
static void copyPoints(const RectC &rect, const QList<MapData::Point> *src,
|
||||
QList<MapData::Point> *dst)
|
||||
{
|
||||
for (int i = 0; i < src->size(); i++)
|
||||
if (rect.contains(src->at(i).coordinates))
|
||||
dst->append(src->at(i));
|
||||
for (int i = 0; i < src->size(); i++) {
|
||||
const MapData::Point &point = src->at(i);
|
||||
if (rect.contains(point.coordinates))
|
||||
dst->append(point);
|
||||
}
|
||||
}
|
||||
|
||||
static double distance(const Coordinates &c1, const Coordinates &c2)
|
||||
@ -208,13 +212,15 @@ bool MapData::readTags(SubFile &subfile, int count,
|
||||
|
||||
bool MapData::readSubFiles()
|
||||
{
|
||||
QDataStream stream(&_file);
|
||||
/* both _pointFile and _pathFile can be used here */
|
||||
QDataStream stream(&_pointFile);
|
||||
|
||||
for (int i = 0; i < _subFiles.size(); i++) {
|
||||
const SubFileInfo &f = _subFiles.at(i);
|
||||
quint64 offset, nextOffset;
|
||||
|
||||
stream.device()->seek(f.offset);
|
||||
if (!stream.device()->seek(f.offset))
|
||||
return false;
|
||||
|
||||
QPoint tl(OSM::ll2tile(_bounds.topLeft(), f.base));
|
||||
QPoint br(OSM::ll2tile(_bounds.bottomRight(), f.base));
|
||||
@ -359,7 +365,7 @@ bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapData::readHeader()
|
||||
bool MapData::readHeader(QFile &file)
|
||||
{
|
||||
char magic[MAGIC_SIZE];
|
||||
quint32 hdrSize;
|
||||
@ -367,18 +373,18 @@ bool MapData::readHeader()
|
||||
bool debugMap;
|
||||
|
||||
|
||||
if (_file.read(magic, MAGIC_SIZE) < (qint64)MAGIC_SIZE
|
||||
if (file.read(magic, MAGIC_SIZE) < (qint64)MAGIC_SIZE
|
||||
|| memcmp(magic, MAGIC, MAGIC_SIZE)) {
|
||||
_errorString = "Not a Mapsforge map";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) {
|
||||
if (file.read((char*)&hdrSize, sizeof(hdrSize)) < (qint64)sizeof(hdrSize)) {
|
||||
_errorString = "Unexpected EOF";
|
||||
return false;
|
||||
}
|
||||
|
||||
SubFile hdr(_file, MAGIC_SIZE, qFromBigEndian(hdrSize));
|
||||
SubFile hdr(file, MAGIC_SIZE, qFromBigEndian(hdrSize));
|
||||
|
||||
if (!readMapInfo(hdr, projection, debugMap)) {
|
||||
_errorString = "Error reading map info";
|
||||
@ -407,18 +413,19 @@ bool MapData::readHeader()
|
||||
return true;
|
||||
}
|
||||
|
||||
MapData::MapData(const QString &fileName) : _file(fileName), _valid(false)
|
||||
MapData::MapData(const QString &fileName)
|
||||
: _pointFile(fileName), _pathFile(fileName), _valid(false)
|
||||
{
|
||||
if (!_file.open(QFile::ReadOnly | QIODevice::Unbuffered)) {
|
||||
_errorString = _file.errorString();
|
||||
QFile file(fileName);
|
||||
|
||||
if (!file.open(QFile::ReadOnly | QIODevice::Unbuffered)) {
|
||||
_errorString = file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!readHeader())
|
||||
if (!readHeader(file))
|
||||
return;
|
||||
|
||||
_file.close();
|
||||
|
||||
_pathCache.setMaxCost(256);
|
||||
_pointCache.setMaxCost(256);
|
||||
|
||||
@ -444,13 +451,16 @@ RectC MapData::bounds() const
|
||||
|
||||
void MapData::load()
|
||||
{
|
||||
if (_file.open(QIODevice::ReadOnly | QIODevice::Unbuffered))
|
||||
readSubFiles();
|
||||
_pointFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
_pathFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
||||
|
||||
readSubFiles();
|
||||
}
|
||||
|
||||
void MapData::clear()
|
||||
{
|
||||
_file.close();
|
||||
_pointFile.close();
|
||||
_pathFile.close();
|
||||
|
||||
_pathCache.clear();
|
||||
_pointCache.clear();
|
||||
@ -497,6 +507,9 @@ int MapData::level(int zoom) const
|
||||
|
||||
void MapData::points(const RectC &rect, int zoom, QList<Point> *list)
|
||||
{
|
||||
if (!rect.isValid())
|
||||
return;
|
||||
|
||||
int l(level(zoom));
|
||||
PointCTX ctx(this, rect, zoom, list);
|
||||
double min[2], max[2];
|
||||
@ -513,6 +526,9 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
QList<Point> *list)
|
||||
{
|
||||
Key key(tile, zoom);
|
||||
|
||||
_pointLock.lock();
|
||||
|
||||
QList<Point> *cached = _pointCache.object(key);
|
||||
|
||||
if (!cached) {
|
||||
@ -524,18 +540,24 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
delete p;
|
||||
} else
|
||||
copyPoints(rect, cached, list);
|
||||
|
||||
_pointLock.unlock();
|
||||
}
|
||||
|
||||
void MapData::paths(const RectC &rect, int zoom, QList<Path> *list)
|
||||
void MapData::paths(const RectC &searchRect, const RectC &boundsRect, int zoom,
|
||||
QList<Path> *list)
|
||||
{
|
||||
if (!searchRect.isValid())
|
||||
return;
|
||||
|
||||
int l(level(zoom));
|
||||
PathCTX ctx(this, rect, zoom, list);
|
||||
PathCTX ctx(this, boundsRect, zoom, list);
|
||||
double min[2], max[2];
|
||||
|
||||
min[0] = rect.left();
|
||||
min[1] = rect.bottom();
|
||||
max[0] = rect.right();
|
||||
max[1] = rect.top();
|
||||
min[0] = searchRect.left();
|
||||
min[1] = searchRect.bottom();
|
||||
max[0] = searchRect.right();
|
||||
max[1] = searchRect.top();
|
||||
|
||||
_tiles.at(l)->Search(min, max, pathCb, &ctx);
|
||||
}
|
||||
@ -544,6 +566,9 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
QList<Path> *list)
|
||||
{
|
||||
Key key(tile, zoom);
|
||||
|
||||
_pathLock.lock();
|
||||
|
||||
QList<Path> *cached = _pathCache.object(key);
|
||||
|
||||
if (!cached) {
|
||||
@ -555,12 +580,14 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||
delete p;
|
||||
} else
|
||||
copyPaths(rect, cached, list);
|
||||
|
||||
_pathLock.unlock();
|
||||
}
|
||||
|
||||
bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
{
|
||||
const SubFileInfo &info = _subFiles.at(level(zoom));
|
||||
SubFile subfile(_file, info.offset, info.size);
|
||||
SubFile subfile(_pathFile, info.offset, info.size);
|
||||
int rows = info.max - info.min + 1;
|
||||
QVector<unsigned> paths(rows);
|
||||
quint32 blocks, unused, val, cnt = 0;
|
||||
@ -584,8 +611,10 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
if (!subfile.seek(subfile.pos() + val))
|
||||
return false;
|
||||
|
||||
paths.reserve(paths[zoom - info.min]);
|
||||
|
||||
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
||||
Path p(subfile.offset() + subfile.pos());
|
||||
Path p;
|
||||
qint32 lon = 0, lat = 0;
|
||||
|
||||
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
||||
@ -644,7 +673,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
||||
{
|
||||
const SubFileInfo &info = _subFiles.at(level(zoom));
|
||||
SubFile subfile(_file, info.offset, info.size);
|
||||
SubFile subfile(_pointFile, info.offset, info.size);
|
||||
int rows = info.max - info.min + 1;
|
||||
QVector<unsigned> points(rows);
|
||||
quint32 val, unused, cnt = 0;
|
||||
@ -665,6 +694,8 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
||||
if (!subfile.readVUInt32(unused))
|
||||
return false;
|
||||
|
||||
list->reserve(points[zoom - info.min]);
|
||||
|
||||
for (unsigned i = 0; i < points[zoom - info.min]; i++) {
|
||||
qint32 lat, lon;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QFile>
|
||||
#include <QCache>
|
||||
#include <QMutex>
|
||||
#include "common/hash.h"
|
||||
#include "common/rectc.h"
|
||||
#include "common/rtree.h"
|
||||
@ -36,10 +37,7 @@ public:
|
||||
};
|
||||
|
||||
struct Point {
|
||||
Point(const Coordinates &c) : coordinates(c)
|
||||
{
|
||||
id = (quint64)qHash(QPair<double, double>(c.lon(), c.lat()));
|
||||
}
|
||||
Point(const Coordinates &c) : id(qHash(c)), coordinates(c) {}
|
||||
|
||||
quint64 id;
|
||||
Coordinates coordinates;
|
||||
@ -48,9 +46,6 @@ public:
|
||||
};
|
||||
|
||||
struct Path {
|
||||
Path(quint64 id) : id(id) {}
|
||||
|
||||
quint64 id;
|
||||
Polygon poly;
|
||||
QVector<Tag> tags;
|
||||
Coordinates labelPos;
|
||||
@ -59,8 +54,6 @@ public:
|
||||
|
||||
bool operator<(const Path &other) const
|
||||
{return layer < other.layer;}
|
||||
bool operator==(const Path &other) const
|
||||
{return (id == other.id);}
|
||||
};
|
||||
|
||||
RectC bounds() const;
|
||||
@ -69,7 +62,8 @@ public:
|
||||
int tileSize() const {return _tileSize;}
|
||||
|
||||
void points(const RectC &rect, int zoom, QList<Point> *list);
|
||||
void paths(const RectC &rect, int zoom, QList<Path> *set);
|
||||
void paths(const RectC &searchRect, const RectC &boundsRect, int zoom,
|
||||
QList<Path> *set);
|
||||
unsigned tagId(const QByteArray &name) const {return _keys.value(name);}
|
||||
|
||||
void load();
|
||||
@ -146,7 +140,7 @@ private:
|
||||
bool readTagInfo(SubFile &hdr);
|
||||
bool readTagInfo(SubFile &hdr, QVector<TagSource> &tags);
|
||||
bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap);
|
||||
bool readHeader();
|
||||
bool readHeader(QFile &file);
|
||||
bool readSubFiles();
|
||||
void clearTiles();
|
||||
|
||||
@ -165,7 +159,7 @@ private:
|
||||
|
||||
friend HASH_T qHash(const MapData::Key &key);
|
||||
|
||||
QFile _file;
|
||||
QFile _pointFile, _pathFile;
|
||||
RectC _bounds;
|
||||
quint16 _tileSize;
|
||||
QVector<SubFileInfo> _subFiles;
|
||||
@ -175,6 +169,7 @@ private:
|
||||
|
||||
QCache<Key, QList<Path> > _pathCache;
|
||||
QCache<Key, QList<Point> > _pointCache;
|
||||
QMutex _pathLock, _pointLock;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
@ -190,11 +185,6 @@ inline HASH_T qHash(const MapData::Tag &tag)
|
||||
return ::qHash(tag.key) ^ ::qHash(tag.value);
|
||||
}
|
||||
|
||||
inline HASH_T qHash(const MapData::Path &path)
|
||||
{
|
||||
return ::qHash(path.id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG
|
||||
|
@ -1,10 +1,17 @@
|
||||
#include <cmath>
|
||||
#include <QPainter>
|
||||
#include <QCache>
|
||||
#include "common/programpaths.h"
|
||||
#include "map/rectd.h"
|
||||
#include "rastertile.h"
|
||||
|
||||
using namespace Mapsforge;
|
||||
|
||||
#define TEXT_EXTENT 160
|
||||
#define PATHS_EXTENT 20
|
||||
#define SEARCH_EXTENT -0.5
|
||||
|
||||
static double limit = cos(deg2rad(170));
|
||||
|
||||
static qreal area(const QPainterPath &polygon)
|
||||
{
|
||||
qreal area = 0;
|
||||
@ -52,44 +59,89 @@ static const QColor *haloColor(const Style::TextRender *ti)
|
||||
? &ti->strokeColor() : 0;
|
||||
}
|
||||
|
||||
void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
static QPainterPath parallelPath(const QPainterPath &p, double dy)
|
||||
{
|
||||
int n = p.elementCount() - 1;
|
||||
QVector<QPointF> u(n);
|
||||
QPainterPath h;
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
h.reserve(p.elementCount());
|
||||
#endif // QT 5.13
|
||||
|
||||
for (int k = 0; k < n; k++) {
|
||||
qreal c = p.elementAt(k + 1).x - p.elementAt(k).x;
|
||||
qreal s = p.elementAt(k + 1).y - p.elementAt(k).y;
|
||||
qreal l = sqrt(c * c + s * s);
|
||||
|
||||
u[k] = (l == 0) ? QPointF(0, 0) : QPointF(c / l, s / l);
|
||||
|
||||
if (k == 0)
|
||||
continue;
|
||||
if (u.at(k).x() * u.at(k-1).x() + u.at(k).y() * u.at(k-1).y() < limit)
|
||||
return p;
|
||||
}
|
||||
|
||||
h.moveTo(QPointF(p.elementAt(0).x - dy * u.at(0).y(),
|
||||
p.elementAt(0).y + dy * u.at(0).x()));
|
||||
|
||||
for (int k = 1; k < n; k++) {
|
||||
qreal l = dy / (1 + u.at(k).x() * u.at(k-1).x()
|
||||
+ u.at(k).y() * u.at(k-1).y());
|
||||
QPainterPath::Element e(p.elementAt(k));
|
||||
|
||||
h.lineTo(QPointF(e.x - l * (u.at(k).y() + u.at(k-1).y()),
|
||||
e.y + l * (u.at(k).x() + u.at(k-1).x())));
|
||||
}
|
||||
|
||||
h.lineTo(QPointF(p.elementAt(n).x - dy * u.at(n-1).y(),
|
||||
p.elementAt(n).y + dy * u.at(n-1).x()));
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
void RasterTile::processPointLabels(const QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems) const
|
||||
{
|
||||
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
|
||||
QList<PainterPoint> points;
|
||||
QList<PointText> items;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point &point = _points.at(i);
|
||||
const QByteArray *lbl = 0;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
const QByteArray *lbl = 0;
|
||||
|
||||
for (int j = 0; j < symbols.size(); j++) {
|
||||
const Style::Symbol *ri = symbols.at(j);
|
||||
|
||||
if (ri->rule().match(point.tags))
|
||||
if (!si || si->priority() < ri->priority())
|
||||
si = ri;
|
||||
}
|
||||
|
||||
for (int j = 0; j < labels.size(); j++) {
|
||||
const Style::TextRender *ri = labels.at(j);
|
||||
if (ri->rule().match(point.tags)) {
|
||||
if ((lbl = label(ri->key(), point.tags))) {
|
||||
if (si && si->id() != ri->symbolId())
|
||||
continue;
|
||||
|
||||
ti = ri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < symbols.size(); j++) {
|
||||
const Style::Symbol *ri = symbols.at(j);
|
||||
if (ri->rule().match(point.tags)) {
|
||||
si = ri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ti || si)
|
||||
points.append(PainterPoint(&point, lbl, si, ti));
|
||||
items.append(PointText(&point, lbl, si, ti));
|
||||
}
|
||||
|
||||
std::sort(points.begin(), points.end());
|
||||
std::sort(items.begin(), items.end());
|
||||
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const PainterPoint &p = points.at(i);
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const PointText &p = items.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;
|
||||
@ -104,14 +156,15 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
void RasterTile::processAreaLabels(const QVector<PainterPath> &paths,
|
||||
QList<TextItem*> &textItems) const
|
||||
{
|
||||
QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(_style->areaSymbols(_zoom));
|
||||
QList<PathText> items;
|
||||
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
const PainterPath &path = paths.at(i);
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
const QByteArray *lbl = 0;
|
||||
@ -119,6 +172,69 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
if (!path.path->closed)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < symbols.size(); j++) {
|
||||
const Style::Symbol *ri = symbols.at(j);
|
||||
|
||||
if (ri->rule().match(path.path->closed, path.path->tags))
|
||||
if (!si || si->priority() < ri->priority())
|
||||
si = ri;
|
||||
}
|
||||
|
||||
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)) {
|
||||
if ((lbl = label(ri->key(), path.path->tags))) {
|
||||
if (si && si->id() != ri->symbolId())
|
||||
continue;
|
||||
|
||||
ti = ri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ti || si)
|
||||
items.append(PathText(&path, lbl, si, ti));
|
||||
}
|
||||
|
||||
std::sort(items.begin(), items.end());
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const PathText &p = items.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;
|
||||
QPointF pos = p.p->path->labelPos.isNull()
|
||||
? centroid(p.p->pp) : ll2xy(p.p->path->labelPos);
|
||||
|
||||
PointItem *item = new PointItem(pos.toPoint(), p.lbl, font, img, color,
|
||||
hColor);
|
||||
if (item->isValid() && _rect.contains(item->boundingRect().toRect())
|
||||
&& !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
|
||||
QList<TextItem*> &textItems) const
|
||||
{
|
||||
QList<const Style::TextRender*> labels(_style->pathLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(_style->lineSymbols(_zoom));
|
||||
QList<PathText> items;
|
||||
QSet<QByteArray> set;
|
||||
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
const PainterPath &path = paths.at(i);
|
||||
const Style::TextRender *ti = 0;
|
||||
const Style::Symbol *si = 0;
|
||||
const QByteArray *lbl = 0;
|
||||
|
||||
if (path.path->closed)
|
||||
continue;
|
||||
|
||||
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)) {
|
||||
@ -130,61 +246,50 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
|
||||
for (int j = 0; j < symbols.size(); j++) {
|
||||
const Style::Symbol *ri = symbols.at(j);
|
||||
if (ri->rule().match(path.path->tags)) {
|
||||
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||
si = ri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ti && !si)
|
||||
continue;
|
||||
|
||||
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;
|
||||
QPointF pos = path.path->labelPos.isNull()
|
||||
? centroid(path.pp) : ll2xy(path.path->labelPos);
|
||||
|
||||
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);
|
||||
else
|
||||
delete item;
|
||||
if (ti || si)
|
||||
items.append(PathText(&path, lbl, si, ti));
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
QList<const Style::TextRender*> instructions(_style->pathLabels(_zoom));
|
||||
QSet<QByteArray> set;
|
||||
std::sort(items.begin(), items.end());
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
const Style::TextRender *ri = instructions.at(i);
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
const PathText &p = items.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;
|
||||
bool rotate = p.si ? p.si->rotate() : false;
|
||||
bool limit = false;
|
||||
|
||||
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() == ID_ELE || ri->key() == ID_REF);
|
||||
if (limit && set.contains(*lbl))
|
||||
if (p.ti) {
|
||||
limit = (p.ti->key() == ID_ELE || p.ti->key() == ID_REF);
|
||||
if (limit && set.contains(*p.lbl))
|
||||
continue;
|
||||
}
|
||||
|
||||
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)
|
||||
set.insert(*lbl);
|
||||
} else
|
||||
delete item;
|
||||
PathItem *item = new PathItem(p.p->pp, p.lbl, img, _rect, font, color,
|
||||
hColor, rotate);
|
||||
if (item->isValid() && !item->collides(textItems)) {
|
||||
textItems.append(item);
|
||||
if (limit)
|
||||
set.insert(*p.lbl);
|
||||
} else {
|
||||
delete item;
|
||||
|
||||
if (img && p.lbl) {
|
||||
PathItem *item = new PathItem(p.p->pp, 0, img, _rect, 0, 0, 0,
|
||||
rotate);
|
||||
if (item->isValid() && !item->collides(textItems))
|
||||
textItems.append(item);
|
||||
else
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -200,17 +305,17 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
if (curve) {
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
|
||||
int size = 0;
|
||||
for (int i = 0; i < polygon.size(); i++)
|
||||
size += polygon.at(i).size();
|
||||
path.reserve(size);
|
||||
int size = 0;
|
||||
for (int i = 0; i < polygon.size(); i++)
|
||||
size += polygon.at(i).size();
|
||||
path.reserve(size);
|
||||
#endif // QT 5.13
|
||||
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
|
||||
if (curve) {
|
||||
QPointF p1(ll2xy(subpath.first()));
|
||||
QPointF p2(0, 0);
|
||||
QPointF p3(0, 0);
|
||||
@ -223,25 +328,31 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
|
||||
p1 = p3;
|
||||
}
|
||||
path.quadTo(p2, p3);
|
||||
} else {
|
||||
path.moveTo(ll2xy(subpath.first()));
|
||||
for (int j = 1; j < subpath.size(); j++)
|
||||
path.lineTo(ll2xy(subpath.at(j)));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < polygon.size(); i++) {
|
||||
const QVector<Coordinates> &subpath = polygon.at(i);
|
||||
|
||||
QVector<QPointF> p(subpath.size());
|
||||
for (int j = 0; j < subpath.size(); j++)
|
||||
p[j] = ll2xy(subpath.at(j));
|
||||
path.addPolygon(p);
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
void RasterTile::pathInstructions(const QList<MapData::Path> &paths,
|
||||
QVector<PainterPath> &painterPaths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions) const
|
||||
{
|
||||
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
|
||||
QList<const Style::PathRender*> *ri;
|
||||
|
||||
for (int i = 0; i < _paths.size(); i++) {
|
||||
const MapData::Path &path = _paths.at(i);
|
||||
PainterPath &rp = paths[i];
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
const MapData::Path &path = paths.at(i);
|
||||
PainterPath &rp = painterPaths[i];
|
||||
PathKey key(_zoom, path.closed, path.tags);
|
||||
|
||||
rp.path = &path;
|
||||
@ -259,14 +370,14 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::circleInstructions(
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
void RasterTile::circleInstructions(const QList<MapData::Point> &points,
|
||||
QVector<RasterTile::RenderInstruction> &instructions) const
|
||||
{
|
||||
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
|
||||
QList<const Style::CircleRender*> *ri;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
const MapData::Point &point = _points.at(i);
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
const MapData::Point &point = points.at(i);
|
||||
PointKey key(_zoom, point.tags);
|
||||
|
||||
if (!(ri = cache.object(key))) {
|
||||
@ -282,11 +393,12 @@ void RasterTile::circleInstructions(
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
|
||||
void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
||||
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths)
|
||||
{
|
||||
QVector<RenderInstruction> instructions;
|
||||
pathInstructions(paths, instructions);
|
||||
circleInstructions(instructions);
|
||||
pathInstructions(paths, painterPaths, instructions);
|
||||
circleInstructions(points, instructions);
|
||||
std::sort(instructions.begin(), instructions.end());
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
@ -295,13 +407,18 @@ void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
|
||||
|
||||
if (path) {
|
||||
const Style::PathRender *ri = is.pathRender();
|
||||
qreal dy = ri->dy(_zoom);
|
||||
|
||||
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);
|
||||
|
||||
if (dy != 0)
|
||||
painter->drawPath(parallelPath(path->pp, dy));
|
||||
else
|
||||
painter->drawPath(path->pp);
|
||||
} else {
|
||||
const Style::CircleRender *ri = is.circleRender();
|
||||
qreal radius = ri->radius(_zoom);
|
||||
@ -313,28 +430,61 @@ void RasterTile::drawPaths(QPainter *painter, QVector<PainterPath> &paths)
|
||||
}
|
||||
}
|
||||
|
||||
void RasterTile::fetchData(QList<MapData::Path> &paths,
|
||||
QList<MapData::Point> &points) const
|
||||
{
|
||||
QPoint ttl(_rect.topLeft());
|
||||
|
||||
QRectF pathRect(QPointF(ttl.x() - PATHS_EXTENT, ttl.y() - PATHS_EXTENT),
|
||||
QPointF(ttl.x() + _rect.width() + PATHS_EXTENT, ttl.y() + _rect.height()
|
||||
+ PATHS_EXTENT));
|
||||
QRectF searchRect(QPointF(ttl.x() - SEARCH_EXTENT, ttl.y() - SEARCH_EXTENT),
|
||||
QPointF(ttl.x() + _rect.width() + SEARCH_EXTENT, ttl.y() + _rect.height()
|
||||
+ SEARCH_EXTENT));
|
||||
RectD pathRectD(_transform.img2proj(pathRect.topLeft()),
|
||||
_transform.img2proj(pathRect.bottomRight()));
|
||||
RectD searchRectD(_transform.img2proj(searchRect.topLeft()),
|
||||
_transform.img2proj(searchRect.bottomRight()));
|
||||
_data->paths(searchRectD.toRectC(_proj, 20), pathRectD.toRectC(_proj, 20),
|
||||
_zoom, &paths);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT),
|
||||
QPointF(ttl.x() + _rect.width() + TEXT_EXTENT, ttl.y() + _rect.height()
|
||||
+ TEXT_EXTENT));
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data->points(pointRectD.toRectC(_proj, 20), _zoom, &points);
|
||||
}
|
||||
|
||||
void RasterTile::render()
|
||||
{
|
||||
QList<MapData::Path> paths;
|
||||
QList<MapData::Point> points;
|
||||
|
||||
fetchData(paths, points);
|
||||
|
||||
QList<TextItem*> textItems;
|
||||
QVector<PainterPath> renderPaths(_paths.size());
|
||||
QVector<PainterPath> renderPaths(paths.size());
|
||||
|
||||
_pixmap.setDevicePixelRatio(_ratio);
|
||||
_pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&_pixmap);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
painter.translate(-_rect.x(), -_rect.y());
|
||||
|
||||
drawPaths(&painter, renderPaths);
|
||||
drawPaths(&painter, paths, points, renderPaths);
|
||||
|
||||
processPointLabels(textItems);
|
||||
processAreaLabels(textItems, renderPaths);
|
||||
processLineLabels(textItems, renderPaths);
|
||||
processPointLabels(points, textItems);
|
||||
processAreaLabels(renderPaths, textItems);
|
||||
processLineLabels(renderPaths, textItems);
|
||||
drawTextItems(&painter, textItems);
|
||||
|
||||
//painter.setPen(Qt::red);
|
||||
//painter.setBrush(Qt::NoBrush);
|
||||
//painter.drawRect(QRect(_rect.topLeft(), _pixmap.size()));
|
||||
//painter.setRenderHint(QPainter::Antialiasing, false);
|
||||
//painter.drawRect(_rect);
|
||||
|
||||
qDeleteAll(textItems);
|
||||
|
||||
|
@ -15,11 +15,10 @@ class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Style *style, int zoom, const QRect &rect, qreal ratio,
|
||||
const QList<MapData::Path> &paths, const QList<MapData::Point> &points)
|
||||
: _proj(proj), _transform(transform), _style(style),
|
||||
_zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio,
|
||||
rect.height() * ratio), _paths(paths), _points(points), _valid(false) {}
|
||||
const Style *style, MapData *data, int zoom, const QRect &rect,
|
||||
qreal ratio) : _proj(proj), _transform(transform), _style(style),
|
||||
_data(data), _zoom(zoom), _rect(rect), _ratio(ratio),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _valid(false) {}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
QPoint xy() const {return _rect.topLeft();}
|
||||
@ -36,15 +35,15 @@ private:
|
||||
const MapData::Path *path;
|
||||
};
|
||||
|
||||
struct PainterPoint {
|
||||
PainterPoint(const MapData::Point *p, const QByteArray *lbl,
|
||||
struct PointText {
|
||||
PointText(const MapData::Point *p, const QByteArray *lbl,
|
||||
const Style::Symbol *si, const Style::TextRender *ti)
|
||||
: p(p), lbl(lbl), ti(ti), si(si)
|
||||
{
|
||||
Q_ASSERT(si || ti);
|
||||
}
|
||||
|
||||
bool operator<(const PainterPoint &other) const
|
||||
bool operator<(const PointText &other) const
|
||||
{
|
||||
if (priority() == other.priority())
|
||||
return p->id < other.p->id;
|
||||
@ -59,6 +58,26 @@ private:
|
||||
const Style::Symbol *si;
|
||||
};
|
||||
|
||||
struct PathText {
|
||||
PathText(const PainterPath *p, const QByteArray *lbl,
|
||||
const Style::Symbol *si, const Style::TextRender *ti)
|
||||
: p(p), lbl(lbl), ti(ti), si(si)
|
||||
{
|
||||
Q_ASSERT(si || ti);
|
||||
}
|
||||
|
||||
bool operator<(const PathText &other) const
|
||||
{
|
||||
return (priority() > other.priority());
|
||||
}
|
||||
int priority() const {return si ? si->priority() : ti->priority();}
|
||||
|
||||
const PainterPath *p;
|
||||
const QByteArray *lbl;
|
||||
const Style::TextRender *ti;
|
||||
const Style::Symbol *si;
|
||||
};
|
||||
|
||||
class RenderInstruction
|
||||
{
|
||||
public:
|
||||
@ -138,40 +157,44 @@ private:
|
||||
{
|
||||
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) {}
|
||||
const QImage *img, const QRect &tileRect, const QFont *font,
|
||||
const QColor *color, const QColor *haloColor, bool rotate)
|
||||
: TextPathItem(line, label ? new QString(*label) : 0, tileRect, font,
|
||||
color, haloColor, img, rotate) {}
|
||||
~PathItem() {delete _text;}
|
||||
};
|
||||
|
||||
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);
|
||||
void fetchData(QList<MapData::Path> &paths,
|
||||
QList<MapData::Point> &points) const;
|
||||
void pathInstructions(const QList<MapData::Path> &paths,
|
||||
QVector<PainterPath> &painterPaths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions) const;
|
||||
void circleInstructions(const QList<MapData::Point> &points,
|
||||
QVector<RasterTile::RenderInstruction> &instructions) const;
|
||||
QPointF ll2xy(const Coordinates &c) const
|
||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||
void processPointLabels(QList<TextItem*> &textItems);
|
||||
void processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths);
|
||||
void processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths);
|
||||
void processPointLabels(const QList<MapData::Point> &points,
|
||||
QList<TextItem*> &textItems) const;
|
||||
void processAreaLabels(const QVector<PainterPath> &paths,
|
||||
QList<TextItem*> &textItems) const;
|
||||
void processLineLabels(const QVector<PainterPath> &paths,
|
||||
QList<TextItem*> &textItems) const;
|
||||
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
|
||||
|
||||
void drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
||||
const QList<MapData::Point> &points, QVector<PainterPath> &painterPaths);
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
const Style *_style;
|
||||
MapData *_data;
|
||||
int _zoom;
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
QPixmap _pixmap;
|
||||
QList<MapData::Path> _paths;
|
||||
QList<MapData::Point> _points;
|
||||
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
|
@ -17,18 +17,26 @@ static QString resourcePath(const QString &src, const QString &dir)
|
||||
return dir + "/" + url.toLocalFile();
|
||||
}
|
||||
|
||||
static QImage image(const QString &path, int width, int height, qreal ratio)
|
||||
static QImage image(const QString &path, int width, int height, int percent,
|
||||
qreal ratio)
|
||||
{
|
||||
QImageReader ir(path, "svg");
|
||||
|
||||
if (ir.canRead()) {
|
||||
QSize s(ir.size());
|
||||
|
||||
if (!height && !width) {
|
||||
height = 20;
|
||||
width = 20;
|
||||
} else if (!width) {
|
||||
width = ir.size().height() / (ir.size().height() / (double)height);
|
||||
width = s.height() / (s.height() / (double)height);
|
||||
} else if (!height)
|
||||
height = ir.size().width() / (ir.size().width() / (double)width);
|
||||
height = s.width() / (s.width() / (double)width);
|
||||
|
||||
if (percent != 100) {
|
||||
width *= percent / 100.0;
|
||||
height *= percent / 100.0;
|
||||
}
|
||||
|
||||
ir.setScaledSize(QSize(width * ratio, height * ratio));
|
||||
QImage img(ir.read());
|
||||
@ -69,6 +77,42 @@ static QList<QByteArray> valList(const QList<QByteArray> &in)
|
||||
return out;
|
||||
}
|
||||
|
||||
const Style::Menu::Layer *Style::Menu::findLayer(const QString &id) const
|
||||
{
|
||||
for (int i = 0; i < _layers.size(); i++)
|
||||
if (_layers.at(i).id() == id)
|
||||
return &_layers.at(i);
|
||||
|
||||
qWarning("%s: layer not found", qPrintable(id));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Style::Menu::addCats(const Layer *layer, QSet<QString> &cats) const
|
||||
{
|
||||
if (!layer)
|
||||
return;
|
||||
|
||||
if (!layer->parent().isNull())
|
||||
addCats(findLayer(layer->parent()), cats);
|
||||
|
||||
for (int i = 0; i < layer->cats().size(); i++)
|
||||
cats.insert(layer->cats().at(i));
|
||||
|
||||
for (int i = 0; i < layer->overlays().size(); i++) {
|
||||
const Layer *overlay = findLayer(layer->overlays().at(i));
|
||||
if (overlay && overlay->enabled())
|
||||
addCats(overlay, cats);
|
||||
}
|
||||
}
|
||||
|
||||
QSet<QString> Style::Menu::cats() const
|
||||
{
|
||||
QSet<QString> c;
|
||||
addCats(findLayer(_defaultvalue), c);
|
||||
return c;
|
||||
}
|
||||
|
||||
Style::Rule::Filter::Filter(const MapData &data, const QList<QByteArray> &keys,
|
||||
const QList<QByteArray> &vals) : _neg(false)
|
||||
{
|
||||
@ -139,7 +183,7 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
QString file;
|
||||
QColor fillColor;
|
||||
int height = 0, width = 0;
|
||||
int height = 0, width = 0, percent = 100;
|
||||
bool ok;
|
||||
|
||||
ri._area = true;
|
||||
@ -154,6 +198,13 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("scale")) {
|
||||
QString scale(attr.value("scale").toString());
|
||||
if (scale == "all")
|
||||
ri._scale = PathRender::Scale::All;
|
||||
else if (scale == "none")
|
||||
ri._scale = PathRender::Scale::None;
|
||||
}
|
||||
if (attr.hasAttribute("src"))
|
||||
file = resourcePath(attr.value("src").toString(), dir);
|
||||
if (attr.hasAttribute("symbol-height")) {
|
||||
@ -170,9 +221,16 @@ void Style::area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("symbol-percent")) {
|
||||
percent = attr.value("symbol-percent").toInt(&ok);
|
||||
if (!ok || percent < 0) {
|
||||
reader.raiseError("invalid symbol-percent value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!file.isNull())
|
||||
ri._brush = QBrush(image(file, width, height, ratio));
|
||||
ri._brush = QBrush(image(file, width, height, percent, ratio));
|
||||
else if (fillColor.isValid())
|
||||
ri._brush = QBrush(fillColor);
|
||||
|
||||
@ -188,6 +246,8 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool ok;
|
||||
|
||||
ri._brush = Qt::NoBrush;
|
||||
|
||||
if (attr.hasAttribute("stroke"))
|
||||
ri._strokeColor = QColor(attr.value("stroke").toString());
|
||||
if (attr.hasAttribute("stroke-width")) {
|
||||
@ -226,11 +286,25 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule)
|
||||
else if (join == "bevel")
|
||||
ri._strokeJoin = Qt::BevelJoin;
|
||||
}
|
||||
if (attr.hasAttribute("scale")) {
|
||||
QString scale(attr.value("scale").toString());
|
||||
if (scale == "all")
|
||||
ri._scale = PathRender::Scale::All;
|
||||
else if (scale == "none")
|
||||
ri._scale = PathRender::Scale::None;
|
||||
}
|
||||
if (attr.hasAttribute("curve")) {
|
||||
QString curve(attr.value("curve").toString());
|
||||
if (curve == "cubic")
|
||||
ri._curve = true;
|
||||
}
|
||||
if (attr.hasAttribute("dy")) {
|
||||
ri._dy = attr.value("dy").toDouble(&ok);
|
||||
if (!ok) {
|
||||
reader.raiseError("invalid dy value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ri.rule()._type == Rule::AnyType || ri.rule()._type == Rule::WayType)
|
||||
_paths.append(ri);
|
||||
@ -347,6 +421,8 @@ void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("symbol-id"))
|
||||
ri._symbolId = attr.value("symbol-id").toString();
|
||||
|
||||
ri._font.setFamily(fontFamily);
|
||||
ri._font.setPixelSize(fontSize);
|
||||
@ -362,12 +438,12 @@ void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule
|
||||
}
|
||||
|
||||
void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule)
|
||||
const Rule &rule, QList<Symbol> &list)
|
||||
{
|
||||
Symbol ri(rule);
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
QString file;
|
||||
int height = 0, width = 0;
|
||||
int height = 0, width = 0, percent = 100;
|
||||
bool ok;
|
||||
|
||||
if (attr.hasAttribute("src"))
|
||||
@ -390,6 +466,13 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("symbol-percent")) {
|
||||
percent = attr.value("symbol-percent").toInt(&ok);
|
||||
if (!ok || percent < 0) {
|
||||
reader.raiseError("invalid symbol-percent value");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("priority")) {
|
||||
ri._priority = attr.value("priority").toInt(&ok);
|
||||
if (!ok) {
|
||||
@ -397,10 +480,16 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (attr.hasAttribute("rotate")) {
|
||||
if (attr.value("rotate").toString() == "false")
|
||||
ri._rotate = false;
|
||||
}
|
||||
if (attr.hasAttribute("id"))
|
||||
ri._id = attr.value("id").toString();
|
||||
|
||||
ri._img = image(file, width, height, ratio);
|
||||
ri._img = image(file, width, height, percent, ratio);
|
||||
|
||||
_symbols.append(ri);
|
||||
list.append(ri);
|
||||
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
@ -472,42 +561,73 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir,
|
||||
text(reader, data, r, list);
|
||||
}
|
||||
else if (reader.name() == QLatin1String("symbol"))
|
||||
symbol(reader, dir, ratio, r);
|
||||
symbol(reader, dir, ratio, r, _symbols);
|
||||
else if (reader.name() == QLatin1String("lineSymbol"))
|
||||
symbol(reader, dir, ratio, r, _lineSymbols);
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
|
||||
void Style::cat(QXmlStreamReader &reader, QSet<QString> &cats)
|
||||
QString Style::cat(QXmlStreamReader &reader)
|
||||
{
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
|
||||
cats.insert(attr.value("id").toString());
|
||||
if (!attr.hasAttribute("id")) {
|
||||
reader.raiseError("Missing id attribute");
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString id(attr.value("id").toString());
|
||||
reader.skipCurrentElement();
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void Style::layer(QXmlStreamReader &reader, QSet<QString> &cats)
|
||||
Style::Menu::Layer Style::layer(QXmlStreamReader &reader)
|
||||
{
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
bool enabled = (attr.value("enabled").toString() == "true");
|
||||
if (!attr.hasAttribute("id")) {
|
||||
reader.raiseError("Missing id attribute");
|
||||
return Menu::Layer();
|
||||
}
|
||||
|
||||
Menu::Layer l(attr.value("id").toString(),
|
||||
attr.value("enabled").toString() == "true");
|
||||
|
||||
if (attr.hasAttribute("parent"))
|
||||
l.setParent(attr.value("parent").toString());
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (enabled && reader.name() == QLatin1String("cat"))
|
||||
cat(reader, cats);
|
||||
if (reader.name() == QLatin1String("cat"))
|
||||
l.addCat(cat(reader));
|
||||
else if (reader.name() == QLatin1String("overlay"))
|
||||
l.addOverlay(cat(reader));
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void Style::stylemenu(QXmlStreamReader &reader, QSet<QString> &cats)
|
||||
Style::Menu Style::stylemenu(QXmlStreamReader &reader)
|
||||
{
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
if (!attr.hasAttribute("defaultvalue")) {
|
||||
reader.raiseError("Missing defaultvalue attribute");
|
||||
return Menu();
|
||||
}
|
||||
|
||||
Style::Menu menu(attr.value("defaultvalue").toString());
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("layer"))
|
||||
layer(reader, cats);
|
||||
menu.addLayer(layer(reader));
|
||||
else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
@ -519,9 +639,10 @@ void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("rule"))
|
||||
rule(reader, dir, data, ratio, cats, r);
|
||||
else if (reader.name() == QLatin1String("stylemenu"))
|
||||
stylemenu(reader, cats);
|
||||
else
|
||||
else if (reader.name() == QLatin1String("stylemenu")) {
|
||||
Menu menu(stylemenu(reader));
|
||||
cats = menu.cats();
|
||||
} else
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
@ -629,7 +750,7 @@ QList<const Style::Symbol*> Style::pointSymbols(int zoom) const
|
||||
|
||||
for (int i = 0; i < _symbols.size(); i++) {
|
||||
const Symbol &symbol = _symbols.at(i);
|
||||
const Rule & rule = symbol.rule();
|
||||
const Rule &rule = symbol.rule();
|
||||
if (rule._zooms.contains(zoom) && (rule._type == Rule::AnyType
|
||||
|| rule._type == Rule::NodeType))
|
||||
list.append(&symbol);
|
||||
@ -638,6 +759,19 @@ QList<const Style::Symbol*> Style::pointSymbols(int zoom) const
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<const Style::Symbol*> Style::lineSymbols(int zoom) const
|
||||
{
|
||||
QList<const Symbol*> list;
|
||||
|
||||
for (int i = 0; i < _lineSymbols.size(); i++) {
|
||||
const Symbol &symbol = _lineSymbols.at(i);
|
||||
if (symbol.rule()._zooms.contains(zoom))
|
||||
list.append(&symbol);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
QList<const Style::Symbol*> Style::areaSymbols(int zoom) const
|
||||
{
|
||||
QList<const Symbol*> list;
|
||||
@ -656,14 +790,18 @@ QList<const Style::Symbol*> Style::areaSymbols(int zoom) const
|
||||
QPen Style::PathRender::pen(int zoom) const
|
||||
{
|
||||
if (_strokeColor.isValid()) {
|
||||
qreal width = (zoom >= 12)
|
||||
qreal width = (_scale > None && zoom >= 12)
|
||||
? pow(1.5, zoom - 12) * _strokeWidth : _strokeWidth;
|
||||
QPen p(QBrush(_strokeColor), width, Qt::SolidLine, _strokeCap,
|
||||
_strokeJoin);
|
||||
if (!_strokeDasharray.isEmpty()) {
|
||||
QVector<qreal>pattern(_strokeDasharray);
|
||||
for (int i = 0; i < _strokeDasharray.size(); i++)
|
||||
for (int i = 0; i < _strokeDasharray.size(); i++) {
|
||||
if (_scale > Stroke && zoom >= 12)
|
||||
pattern[i] = (pow(1.5, zoom - 12) * pattern[i]);
|
||||
// QPainter pattern is specified in units of the pens width!
|
||||
pattern[i] /= width;
|
||||
}
|
||||
p.setDashPattern(pattern);
|
||||
}
|
||||
return p;
|
||||
@ -671,6 +809,11 @@ QPen Style::PathRender::pen(int zoom) const
|
||||
return Qt::NoPen;
|
||||
}
|
||||
|
||||
qreal Style::PathRender::dy(int zoom) const
|
||||
{
|
||||
return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _dy : _dy;
|
||||
}
|
||||
|
||||
qreal Style::CircleRender::radius(int zoom) const
|
||||
{
|
||||
return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _radius : _radius;
|
||||
|
@ -136,17 +136,21 @@ public:
|
||||
public:
|
||||
PathRender(const Rule &rule, int zOrder) : Render(rule),
|
||||
_zOrder(zOrder), _strokeWidth(0), _strokeCap(Qt::RoundCap),
|
||||
_strokeJoin(Qt::RoundJoin), _area(false), _curve(false) {}
|
||||
_strokeJoin(Qt::RoundJoin), _area(false), _curve(false),
|
||||
_scale(Stroke), _dy(0) {}
|
||||
|
||||
int zOrder() const {return _zOrder;}
|
||||
QPen pen(int zoom) const;
|
||||
const QBrush &brush() const {return _brush;}
|
||||
bool area() const {return _area;}
|
||||
bool curve() const {return _curve;}
|
||||
qreal dy(int zoom) const;
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
enum Scale {None, Stroke, All};
|
||||
|
||||
int _zOrder;
|
||||
QColor _strokeColor;
|
||||
qreal _strokeWidth;
|
||||
@ -155,6 +159,8 @@ public:
|
||||
Qt::PenJoinStyle _strokeJoin;
|
||||
QBrush _brush;
|
||||
bool _area, _curve;
|
||||
Scale _scale;
|
||||
qreal _dy;
|
||||
};
|
||||
|
||||
class CircleRender : public Render
|
||||
@ -186,6 +192,7 @@ public:
|
||||
: Render(rule), _priority(0), _fillColor(Qt::black),
|
||||
_strokeColor(Qt::black), _strokeWidth(0) {}
|
||||
|
||||
const QString &symbolId() const {return _symbolId;}
|
||||
const QFont &font() const {return _font;}
|
||||
const QColor &fillColor() const {return _fillColor;}
|
||||
const QColor &strokeColor() const {return _strokeColor;}
|
||||
@ -196,6 +203,7 @@ public:
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
QString _symbolId;
|
||||
int _priority;
|
||||
QColor _fillColor, _strokeColor;
|
||||
qreal _strokeWidth;
|
||||
@ -206,15 +214,20 @@ public:
|
||||
class Symbol : public Render
|
||||
{
|
||||
public:
|
||||
Symbol(const Rule &rule) : Render(rule), _priority(0) {}
|
||||
Symbol(const Rule &rule)
|
||||
: Render(rule), _priority(0), _rotate(true) {}
|
||||
|
||||
const QString &id() const {return _id;}
|
||||
const QImage &img() const {return _img;}
|
||||
bool rotate() const {return _rotate;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
friend class Style;
|
||||
|
||||
QString _id;
|
||||
int _priority;
|
||||
bool _rotate;
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
@ -230,19 +243,60 @@ public:
|
||||
QList<const TextRender*> areaLabels(int zoom) const;
|
||||
QList<const Symbol*> pointSymbols(int zoom) const;
|
||||
QList<const Symbol*> areaSymbols(int zoom) const;
|
||||
QList<const Symbol*> lineSymbols(int zoom) const;
|
||||
|
||||
private:
|
||||
class Menu {
|
||||
public:
|
||||
class Layer {
|
||||
public:
|
||||
Layer() : _enabled(false) {}
|
||||
Layer(const QString &id, bool enabled)
|
||||
: _id(id), _enabled(enabled) {}
|
||||
|
||||
const QStringList &cats() const {return _cats;}
|
||||
const QStringList &overlays() const {return _overlays;}
|
||||
const QString &id() const {return _id;}
|
||||
const QString &parent() const {return _parent;}
|
||||
bool enabled() const {return _enabled;}
|
||||
|
||||
void setParent(const QString &parent) {_parent = parent;}
|
||||
void addCat(const QString &cat) {_cats.append(cat);}
|
||||
void addOverlay(const QString &overlay) {_overlays.append(overlay);}
|
||||
|
||||
private:
|
||||
QStringList _cats;
|
||||
QStringList _overlays;
|
||||
QString _id;
|
||||
QString _parent;
|
||||
bool _enabled;
|
||||
};
|
||||
|
||||
Menu() {}
|
||||
Menu(const QString &defaultValue) : _defaultvalue(defaultValue) {}
|
||||
|
||||
void addLayer(const Layer &layer) {_layers.append(layer);}
|
||||
QSet<QString> cats() const;
|
||||
|
||||
private:
|
||||
const Layer *findLayer(const QString &id) const;
|
||||
void addCats(const Layer *layer, QSet<QString> &cats) const;
|
||||
|
||||
QString _defaultvalue;
|
||||
QList<Layer> _layers;
|
||||
};
|
||||
|
||||
QList<PathRender> _paths;
|
||||
QList<CircleRender> _circles;
|
||||
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
||||
QList<Symbol> _symbols;
|
||||
QList<Symbol> _symbols, _lineSymbols;
|
||||
|
||||
bool loadXml(const QString &path, const MapData &data, qreal ratio);
|
||||
void rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
const MapData &data, qreal ratio);
|
||||
void layer(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
void stylemenu(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
void cat(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
Menu::Layer layer(QXmlStreamReader &reader);
|
||||
Menu stylemenu(QXmlStreamReader &reader);
|
||||
QString cat(QXmlStreamReader &reader);
|
||||
void rule(QXmlStreamReader &reader, const QString &dir, const MapData &data,
|
||||
qreal ratio, const QSet<QString> &cats, const Rule &parent);
|
||||
void area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
@ -252,7 +306,7 @@ private:
|
||||
void text(QXmlStreamReader &reader, const MapData &data, const Rule &rule,
|
||||
QList<QList<TextRender> *> &lists);
|
||||
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule);
|
||||
const Rule &rule, QList<Symbol> &list);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ public:
|
||||
: _file(file), _offset(offset), _size(size), _pos(-1),
|
||||
_blockNum(-1), _blockPos(-1) {}
|
||||
|
||||
quint64 offset() const {return _offset;}
|
||||
quint64 pos() const {return _pos;}
|
||||
bool seek(quint64 pos);
|
||||
|
||||
|
@ -2,29 +2,36 @@
|
||||
#include <QPixmapCache>
|
||||
#include "common/wgs84.h"
|
||||
#include "common/util.h"
|
||||
#include "pcs.h"
|
||||
#include "rectd.h"
|
||||
#include "pcs.h"
|
||||
#include "mapsforgemap.h"
|
||||
|
||||
|
||||
using namespace Mapsforge;
|
||||
|
||||
#define TEXT_EXTENT 160
|
||||
|
||||
MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _data(fileName), _zoom(0),
|
||||
_projection(PCS::pcs(3857)), _tileRatio(1.0)
|
||||
{
|
||||
if (_data.isValid()) {
|
||||
if (_data.isValid())
|
||||
_zoom = _data.zooms().min();
|
||||
updateTransform();
|
||||
}
|
||||
}
|
||||
|
||||
void MapsforgeMap::load()
|
||||
void MapsforgeMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(hidpi);
|
||||
|
||||
_tileRatio = deviceRatio;
|
||||
_projection = out;
|
||||
|
||||
_data.load();
|
||||
_style.load(_data, _tileRatio);
|
||||
|
||||
updateTransform();
|
||||
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
void MapsforgeMap::unload()
|
||||
@ -160,18 +167,19 @@ void MapsforgeMap::cancelJobs(bool wait)
|
||||
|
||||
void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
{
|
||||
QPointF tl(floor(rect.left() / _data.tileSize()) * _data.tileSize(),
|
||||
floor(rect.top() / _data.tileSize()) * _data.tileSize());
|
||||
int tileSize = (_data.tileSize() < 384)
|
||||
? _data.tileSize() << 1 : _data.tileSize();
|
||||
QPointF tl(floor(rect.left() / tileSize) * tileSize,
|
||||
floor(rect.top() / tileSize) * tileSize);
|
||||
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
|
||||
int width = ceil(s.width() / _data.tileSize());
|
||||
int height = ceil(s.height() / _data.tileSize());
|
||||
int width = ceil(s.width() / tileSize);
|
||||
int height = ceil(s.height() / tileSize);
|
||||
|
||||
QList<RasterTile> tiles;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
for (int j = 0; j < height; j++) {
|
||||
QPoint ttl(tl.x() + i * _data.tileSize(), tl.y() + j
|
||||
* _data.tileSize());
|
||||
QPoint ttl(tl.x() + i * tileSize, tl.y() + j * tileSize);
|
||||
if (isRunning(_zoom, ttl))
|
||||
continue;
|
||||
|
||||
@ -179,32 +187,8 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
||||
painter->drawPixmap(ttl, pm);
|
||||
else {
|
||||
QList<MapData::Path> paths;
|
||||
QList<MapData::Point> points;
|
||||
|
||||
/* Add a "sub-pixel" margin to assure the tile areas do not
|
||||
overlap on the border lines. This prevents areas overlap
|
||||
artifacts at least when using the EPSG:3857 projection. */
|
||||
QRectF pathRect(QPointF(ttl.x() + 0.5, ttl.y() + 0.5),
|
||||
QPointF(ttl.x() + _data.tileSize() - 0.5, ttl.y()
|
||||
+ _data.tileSize() - 0.5));
|
||||
pathRect &= _bounds;
|
||||
RectD pathRectD(_transform.img2proj(pathRect.topLeft()),
|
||||
_transform.img2proj(pathRect.bottomRight()));
|
||||
_data.paths(pathRectD.toRectC(_projection, 20), _zoom, &paths);
|
||||
|
||||
QRectF pointRect(QPointF(ttl.x() - TEXT_EXTENT, ttl.y()
|
||||
- TEXT_EXTENT), QPointF(ttl.x() + _data.tileSize()
|
||||
+ TEXT_EXTENT, ttl.y() + _data.tileSize() + TEXT_EXTENT));
|
||||
pointRect &= _bounds;
|
||||
RectD pointRectD(_transform.img2proj(pointRect.topLeft()),
|
||||
_transform.img2proj(pointRect.bottomRight()));
|
||||
_data.points(pointRectD.toRectC(_projection, 20), _zoom,
|
||||
&points);
|
||||
|
||||
tiles.append(RasterTile(_projection, _transform, &_style, _zoom,
|
||||
QRect(ttl, QSize(_data.tileSize(), _data.tileSize())),
|
||||
_tileRatio, paths, points));
|
||||
tiles.append(RasterTile(_projection, _transform, &_style, &_data,
|
||||
_zoom, QRect(ttl, QSize(tileSize, tileSize)), _tileRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -225,24 +209,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(mapRatio);
|
||||
|
||||
_tileRatio = deviceRatio;
|
||||
}
|
||||
|
||||
void MapsforgeMap::setOutputProjection(const Projection &projection)
|
||||
{
|
||||
if (!projection.isValid() || projection == _projection)
|
||||
return;
|
||||
|
||||
_projection = projection;
|
||||
updateTransform();
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
Map *MapsforgeMap::create(const QString &path, const Projection &, bool *isMap)
|
||||
Map *MapsforgeMap::create(const QString &path, bool *isMap)
|
||||
{
|
||||
if (isMap)
|
||||
*isMap = false;
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
MapsforgeMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds() {return _bounds;}
|
||||
RectC llBounds() {return _data.bounds();}
|
||||
RectC llBounds(const Projection &) {return _data.bounds();}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
void setZoom(int zoom);
|
||||
@ -60,10 +60,9 @@ public:
|
||||
int zoomIn();
|
||||
int zoomOut();
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setOutputProjection(const Projection &projection);
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
QPointF ll2xy(const Coordinates &c)
|
||||
{return _transform.proj2img(_projection.ll2xy(c));}
|
||||
@ -75,7 +74,7 @@ public:
|
||||
bool isValid() const {return _data.isValid();}
|
||||
QString errorString() const {return _data.errorString();}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isMap);
|
||||
static Map *create(const QString &path, bool *isMap);
|
||||
|
||||
private slots:
|
||||
void jobFinished(MapsforgeMapJob *job);
|
||||
|
@ -189,14 +189,22 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
||||
else
|
||||
config.dimensions.append(KV<QString, QString>
|
||||
(attr.value("id").toString(), reader.readElementText()));
|
||||
} else if (reader.name() == QLatin1String("header")) {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
if (!attr.hasAttribute("name"))
|
||||
reader.raiseError("Missing header name");
|
||||
else
|
||||
config.headers.append(HTTPHeader(
|
||||
attr.value("name").toString().toLatin1(),
|
||||
reader.readElementText().toLatin1()));
|
||||
} else if (reader.name() == QLatin1String("crs")) {
|
||||
config.coordinateSystem = coordinateSystem(reader);
|
||||
config.crs = reader.readElementText();
|
||||
} else if (reader.name() == QLatin1String("authorization")) {
|
||||
QXmlStreamAttributes attr = reader.attributes();
|
||||
config.authorization = Authorization(
|
||||
attr.value("username").toString(),
|
||||
Authorization auth(attr.value("username").toString(),
|
||||
attr.value("password").toString());
|
||||
config.headers.append(auth.header());
|
||||
reader.skipCurrentElement();
|
||||
} else if (reader.name() == QLatin1String("tile")) {
|
||||
tile(reader, config);
|
||||
@ -206,9 +214,8 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
||||
}
|
||||
}
|
||||
|
||||
Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
Map *MapSource::create(const QString &path, bool *isDir)
|
||||
{
|
||||
Q_UNUSED(proj);
|
||||
Config config;
|
||||
QFile file(path);
|
||||
|
||||
@ -253,24 +260,24 @@ Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir)
|
||||
case WMTS:
|
||||
return new WMTSMap(path, config.name, WMTS::Setup(config.url,
|
||||
config.layer, config.set, config.style, config.format, config.rest,
|
||||
config.coordinateSystem, config.dimensions, config.authorization),
|
||||
config.coordinateSystem, config.dimensions, config.headers),
|
||||
config.tileRatio);
|
||||
case WMS:
|
||||
return new WMSMap(path, config.name, WMS::Setup(config.url,
|
||||
config.layer, config.style, config.format, config.crs,
|
||||
config.coordinateSystem, config.dimensions, config.authorization),
|
||||
config.coordinateSystem, config.dimensions, config.headers),
|
||||
config.tileSize);
|
||||
case TMS:
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.bounds, config.tileRatio, config.headers,
|
||||
config.tileSize, config.scalable, true, false);
|
||||
case OSM:
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.bounds, config.tileRatio, config.headers,
|
||||
config.tileSize, config.scalable, false, false);
|
||||
case QuadTiles:
|
||||
return new OnlineMap(path, config.name, config.url, config.zooms,
|
||||
config.bounds, config.tileRatio, config.authorization,
|
||||
config.bounds, config.tileRatio, config.headers,
|
||||
config.tileSize, config.scalable, false, true);
|
||||
default:
|
||||
return new InvalidMap(path, "Invalid map type");
|
||||
|
@ -15,7 +15,7 @@ class Projection;
|
||||
class MapSource
|
||||
{
|
||||
public:
|
||||
static Map *create(const QString &path, const Projection &proj, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
@ -40,7 +40,7 @@ private:
|
||||
CoordinateSystem coordinateSystem;
|
||||
bool rest;
|
||||
QList<KV<QString, QString> > dimensions;
|
||||
Authorization authorization;
|
||||
QList<HTTPHeader> headers;
|
||||
qreal tileRatio;
|
||||
int tileSize;
|
||||
bool scalable;
|
||||
|
@ -165,8 +165,19 @@ MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void MBTilesMap::load()
|
||||
void MBTilesMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
if (_scalable) {
|
||||
_scaledSize = _tileSize * deviceRatio;
|
||||
_tileRatio = deviceRatio;
|
||||
}
|
||||
|
||||
_db.open();
|
||||
}
|
||||
|
||||
@ -218,16 +229,6 @@ int MBTilesMap::zoomOut()
|
||||
return _zi;
|
||||
}
|
||||
|
||||
void MBTilesMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
_mapRatio = mapRatio;
|
||||
|
||||
if (_scalable) {
|
||||
_scaledSize = _tileSize * deviceRatio;
|
||||
_tileRatio = deviceRatio;
|
||||
}
|
||||
}
|
||||
|
||||
qreal MBTilesMap::coordinatesRatio() const
|
||||
{
|
||||
return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0;
|
||||
@ -337,7 +338,7 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p)
|
||||
* coordinatesRatio());
|
||||
}
|
||||
|
||||
Map *MBTilesMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *MBTilesMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -13,7 +13,7 @@ public:
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zi;}
|
||||
@ -27,14 +27,14 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
qreal tileSize() const;
|
||||
|
@ -10,17 +10,16 @@
|
||||
|
||||
OnlineMap::OnlineMap(const QString &fileName, const QString &name,
|
||||
const QString &url, const Range &zooms, const RectC &bounds, qreal tileRatio,
|
||||
const Authorization &authorization, int tileSize, bool scalable, bool invertY,
|
||||
const QList<HTTPHeader> &headers, int tileSize, bool scalable, bool invertY,
|
||||
bool quadTiles, QObject *parent)
|
||||
: Map(fileName, parent), _name(name), _zooms(zooms), _bounds(bounds),
|
||||
_zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio),
|
||||
_tileSize(tileSize), _scalable(scalable), _invertY(invertY)
|
||||
_zoom(_zooms.max()), _tileSize(tileSize), _mapRatio(1.0),
|
||||
_tileRatio(tileRatio), _scalable(scalable), _invertY(invertY)
|
||||
{
|
||||
_tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name),
|
||||
this);
|
||||
_tileLoader->setUrl(url);
|
||||
_tileLoader->setAuthorization(authorization);
|
||||
_tileLoader->setQuadTiles(quadTiles);
|
||||
_tileLoader->setUrl(url, quadTiles ? TileLoader::QuadTiles : TileLoader::XYZ);
|
||||
_tileLoader->setHeaders(headers);
|
||||
connect(_tileLoader, &TileLoader::finished, this, &OnlineMap::tilesLoaded);
|
||||
}
|
||||
|
||||
@ -70,9 +69,13 @@ int OnlineMap::zoomOut()
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
void OnlineMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
void OnlineMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
_mapRatio = mapRatio;
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
if (_scalable) {
|
||||
_tileLoader->setScaledSize(_tileSize * deviceRatio);
|
||||
|
@ -13,13 +13,13 @@ class OnlineMap : public Map
|
||||
public:
|
||||
OnlineMap(const QString &fileName, const QString &name, const QString &url,
|
||||
const Range &zooms, const RectC &bounds, qreal tileRatio,
|
||||
const Authorization &authorization, int tileSize, bool scalable,
|
||||
const QList<HTTPHeader> &headers, int tileSize, bool scalable,
|
||||
bool invertY, bool quadTiles, QObject *parent = 0);
|
||||
|
||||
QString name() const {return _name;}
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -33,7 +33,8 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void clearCache() {_tileLoader->clearCache();}
|
||||
|
||||
private:
|
||||
@ -47,8 +48,8 @@ private:
|
||||
Range _zooms;
|
||||
RectC _bounds;
|
||||
int _zoom;
|
||||
qreal _mapRatio, _tileRatio;
|
||||
int _tileSize;
|
||||
qreal _mapRatio, _tileRatio;
|
||||
bool _scalable;
|
||||
bool _invertY;
|
||||
};
|
||||
|
@ -487,8 +487,14 @@ int OruxMap::zoomOut()
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
void OruxMap::load()
|
||||
void OruxMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
if (_db.isValid())
|
||||
_db.open();
|
||||
}
|
||||
@ -499,12 +505,6 @@ void OruxMap::unload()
|
||||
_db.close();
|
||||
}
|
||||
|
||||
void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
_mapRatio = mapRatio;
|
||||
}
|
||||
|
||||
QPixmap OruxMap::tile(const Zoom &z, int x, int y) const
|
||||
{
|
||||
if (_db.isValid()) {
|
||||
@ -590,7 +590,7 @@ Coordinates OruxMap::xy2ll(const QPointF &p)
|
||||
return z.projection.xy2ll(z.transform.img2proj(p * _mapRatio));
|
||||
}
|
||||
|
||||
Map *OruxMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *OruxMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = true;
|
||||
|
@ -33,14 +33,14 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Zoom {
|
||||
|
@ -152,8 +152,13 @@ OsmdroidMap::OsmdroidMap(const QString &fileName, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void OsmdroidMap::load()
|
||||
void OsmdroidMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
_db.open();
|
||||
}
|
||||
|
||||
@ -208,12 +213,6 @@ int OsmdroidMap::zoomOut()
|
||||
return _zoom;
|
||||
}
|
||||
|
||||
void OsmdroidMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
_mapRatio = mapRatio;
|
||||
}
|
||||
|
||||
qreal OsmdroidMap::tileSize() const
|
||||
{
|
||||
return (_tileSize / _mapRatio);
|
||||
@ -310,7 +309,7 @@ Coordinates OsmdroidMap::xy2ll(const QPointF &p)
|
||||
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
|
||||
}
|
||||
|
||||
Map *OsmdroidMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *OsmdroidMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -11,7 +11,7 @@ public:
|
||||
OsmdroidMap(const QString &fileName, QObject *parent = 0);
|
||||
|
||||
QRectF bounds();
|
||||
RectC llBounds() {return _bounds;}
|
||||
RectC llBounds(const Projection &) {return _bounds;}
|
||||
qreal resolution(const QRectF &rect);
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
@ -25,14 +25,14 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
int limitZoom(int zoom) const;
|
||||
|
@ -182,6 +182,9 @@ bool OZF::open()
|
||||
if (!_file.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
if (!_zooms.isEmpty())
|
||||
return true;
|
||||
|
||||
if (!readHeaders()) {
|
||||
qWarning("%s: Invalid header", qPrintable(_file.fileName()));
|
||||
_file.close();
|
||||
@ -232,7 +235,6 @@ QPixmap OZF::tile(int zoom, int x, int y)
|
||||
|
||||
QSize OZF::size(int zoom) const
|
||||
{
|
||||
Q_ASSERT(_file.isOpen());
|
||||
Q_ASSERT(0 <= zoom && zoom < _zooms.count());
|
||||
|
||||
return _zooms.at(zoom).size;
|
||||
|
@ -16,6 +16,7 @@ public:
|
||||
_file(name) {}
|
||||
|
||||
bool open();
|
||||
void close() {_file.close();}
|
||||
|
||||
QString fileName() const {return _file.fileName();}
|
||||
bool isOpen() const {return _file.isOpen();}
|
||||
|
@ -50,6 +50,8 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
|
||||
if (!setTileInfo(_tar->files()))
|
||||
return;
|
||||
|
||||
_tar->close();
|
||||
} else {
|
||||
QFile file(fileName);
|
||||
MapFile mf(file);
|
||||
@ -105,6 +107,16 @@ OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
_transform = mf.transform();
|
||||
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
|
||||
|
||||
if (!_tar->open()) {
|
||||
_errorString = _tar->fileName() + ": error reading tar file";
|
||||
return;
|
||||
}
|
||||
if (!setTileInfo(_tar->files())) {
|
||||
_errorString = _tar->fileName() + ": " + _errorString;
|
||||
return;
|
||||
}
|
||||
_tar->close();
|
||||
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
@ -144,6 +156,7 @@ bool OziMap::setImageInfo(const QString &path)
|
||||
return false;
|
||||
}
|
||||
_scale = _ozf->scale(_zoom);
|
||||
_ozf->close();
|
||||
} else {
|
||||
QImageReader ir(_map.path);
|
||||
if (!ir.canRead()) {
|
||||
@ -192,28 +205,42 @@ bool OziMap::setTileInfo(const QStringList &tiles, const QString &path)
|
||||
return false;
|
||||
}
|
||||
|
||||
void OziMap::load()
|
||||
void OziMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
if (_tar && !_tar->isOpen()) {
|
||||
if (!_tar->open()) {
|
||||
qWarning("%s: error loading tar file",
|
||||
qPrintable(_tar->fileName()));
|
||||
return;
|
||||
}
|
||||
if (!setTileInfo(_tar->files()))
|
||||
qWarning("%s: %s", qPrintable(_tar->fileName()),
|
||||
qPrintable(_errorString));
|
||||
return;
|
||||
}
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
if (!_tile.isValid() && !_ozf && !_img)
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
|
||||
if (_tar) {
|
||||
Q_ASSERT(!_tar->isOpen());
|
||||
if (!_tar->open())
|
||||
return;
|
||||
}
|
||||
if (_ozf) {
|
||||
Q_ASSERT(!_ozf->isOpen());
|
||||
if (!_ozf->open())
|
||||
return;
|
||||
}
|
||||
if (!_tile.isValid() && !_ozf) {
|
||||
Q_ASSERT(!_img);
|
||||
_img = new Image(_map.path);
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_mapRatio);
|
||||
}
|
||||
}
|
||||
|
||||
void OziMap::unload()
|
||||
{
|
||||
delete _img;
|
||||
_img = 0;
|
||||
|
||||
if (_tar && _tar->isOpen())
|
||||
_tar->close();
|
||||
|
||||
if (_ozf && _ozf->isOpen())
|
||||
_ozf->close();
|
||||
}
|
||||
|
||||
void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const
|
||||
@ -368,16 +395,7 @@ void OziMap::rescale(int zoom)
|
||||
_scale = _ozf->scale(zoom);
|
||||
}
|
||||
|
||||
void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
|
||||
_mapRatio = mapRatio;
|
||||
if (_img)
|
||||
_img->setDevicePixelRatio(_mapRatio);
|
||||
}
|
||||
|
||||
Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir)
|
||||
Map *OziMap::createTAR(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
@ -385,7 +403,7 @@ Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir)
|
||||
return new OziMap(path, true);
|
||||
}
|
||||
|
||||
Map *OziMap::createMAP(const QString &path, const Projection &, bool *isDir)
|
||||
Map *OziMap::createMAP(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -33,8 +33,8 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
@ -47,8 +47,8 @@ public:
|
||||
QPointF pp2xy(const PointD &p) const
|
||||
{return _transform.proj2img(p) / _mapRatio;}
|
||||
|
||||
static Map *createTAR(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *createMAP(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *createTAR(const QString &path, bool *isDir);
|
||||
static Map *createMAP(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct ImageInfo {
|
||||
|
@ -354,8 +354,13 @@ QCTMap::QCTMap(const QString &fileName, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
void QCTMap::load()
|
||||
void QCTMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
@ -486,7 +491,7 @@ void QCTMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
Map *QCTMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *QCTMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -21,16 +21,14 @@ public:
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
|
||||
{_mapRatio = mapRatio;}
|
||||
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
bool readName(QDataStream &stream);
|
||||
|
@ -355,8 +355,13 @@ Coordinates RMap::xy2ll(const QPointF &p)
|
||||
p.y() / scale.y()) * _mapRatio));
|
||||
}
|
||||
|
||||
void RMap::load()
|
||||
void RMap::load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
_file.open(QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
@ -455,13 +460,7 @@ void RMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
}
|
||||
}
|
||||
|
||||
void RMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
|
||||
{
|
||||
Q_UNUSED(deviceRatio);
|
||||
_mapRatio = mapRatio;
|
||||
}
|
||||
|
||||
Map *RMap::create(const QString &path, const Projection &, bool *isDir)
|
||||
Map *RMap::create(const QString &path, bool *isDir)
|
||||
{
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
@ -25,8 +25,8 @@ public:
|
||||
QPointF ll2xy(const Coordinates &c);
|
||||
Coordinates xy2ll(const QPointF &p);
|
||||
|
||||
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
|
||||
void load();
|
||||
void load(const Projection &in, const Projection &out, qreal deviceRatio,
|
||||
bool hidpi);
|
||||
void unload();
|
||||
|
||||
void draw(QPainter *painter, const QRectF &rect, Flags flags);
|
||||
@ -34,7 +34,7 @@ public:
|
||||
bool isValid() const {return _valid;}
|
||||
QString errorString() const {return _errorString;}
|
||||
|
||||
static Map *create(const QString &path, const Projection &, bool *isDir);
|
||||
static Map *create(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
struct Header {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user