Marble

PlacemarkLayer.cpp
1// SPDX-License-Identifier: LGPL-2.1-or-later
2//
3// SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <tackat@kde.org>
4// SPDX-FileCopyrightText: 2007-2008 Inge Wallin <ingwa@kde.org>
5// SPDX-FileCopyrightText: 2011-2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
6//
7
8#include "PlacemarkLayer.h"
9
10#include <QPoint>
11
12#include "MarbleDebug.h"
13#include "AbstractProjection.h"
14#include "GeoDataStyle.h"
15#include "GeoPainter.h"
16#include "GeoDataLatLonAltBox.h"
17#include "ViewportParams.h"
18#include "VisiblePlacemark.h"
19#include "RenderState.h"
20#include "osm/OsmPlacemarkData.h"
21
22#define BATCH_RENDERING
23
24using namespace Marble;
25
26PlacemarkLayer::PlacemarkLayer(QAbstractItemModel *placemarkModel,
27 QItemSelectionModel *selectionModel,
28 MarbleClock *clock, const StyleBuilder *styleBuilder,
29 QObject *parent ) :
30 QObject( parent ),
31 m_layout( placemarkModel, selectionModel, clock, styleBuilder ),
32 m_debugModeEnabled(false),
33 m_levelTagDebugModeEnabled(false),
34 m_tileLevel(0),
35 m_debugLevelTag(0)
36{
37 connect( &m_layout, SIGNAL(repaintNeeded()), SIGNAL(repaintNeeded()) );
38}
39
40PlacemarkLayer::~PlacemarkLayer()
41{
42}
43
44QStringList PlacemarkLayer::renderPosition() const
45{
46 return QStringList(QStringLiteral("PLACEMARKS"));
47}
48
49qreal PlacemarkLayer::zValue() const
50{
51 return 2.0;
52}
53
54bool PlacemarkLayer::render( GeoPainter *geoPainter, ViewportParams *viewport,
55 const QString &renderPos, GeoSceneLayer *layer )
56{
58 Q_UNUSED( layer )
59
60 QVector<VisiblePlacemark*> visiblePlacemarks = m_layout.generateLayout( viewport, m_tileLevel );
61 // draw placemarks less important first
62 QVector<VisiblePlacemark*>::const_iterator visit = visiblePlacemarks.constEnd();
64
65 QPainter *const painter = geoPainter;
66
67 bool const repeatableX = viewport->currentProjection()->repeatableX();
68 int const radius4 = 4 * viewport->radius();
69
70#ifdef BATCH_RENDERING
72#endif
73
74 while ( visit != itEnd ) {
75 --visit;
76
77 VisiblePlacemark *const mark = *visit;
78 if (m_levelTagDebugModeEnabled) {
79 if (mark->placemark()->hasOsmData()) {
80 QHash<QString, QString>::const_iterator tagIter = mark->placemark()->osmData().findTag(QStringLiteral("level"));
81 if (tagIter != mark->placemark()->osmData().tagsEnd()) {
82 const int val = tagIter.value().toInt();
83 if (val != m_debugLevelTag) {
84 continue;
85 }
86 }
87 }
88 }
89
90 // Intentionally converting positions from floating point to pixel aligned screen grid below
91 QRect labelRect( mark->labelRect().toRect() );
93
94 // when the map is such zoomed out that a given place
95 // appears many times, we draw one placemark at each
96 if (repeatableX) {
97 const int symbolX = symbolPos.x();
98 const int textX = labelRect.x();
99
100 for (int i = symbolX % radius4, width = viewport->width(); i <= width; i += radius4) {
101 labelRect.moveLeft(i - symbolX + textX);
102 symbolPos.setX(i);
103
104 if (!mark->symbolPixmap().isNull()) {
105#ifdef BATCH_RENDERING
106 QRect symbolRect = mark->symbolPixmap().rect();
108
109 auto iter = hash.find(mark->symbolId());
110 if (iter == hash.end()) {
111 Fragment fragment;
112 fragment.pixmap = mark->symbolPixmap();
113 fragment.fragments << pixmapFragment;
114 hash.insert(mark->symbolId(), fragment);
115 } else {
116 auto & fragment = iter.value();
117 fragment.fragments << pixmapFragment;
118 }
119#else
120 painter->drawPixmap( symbolPos, mark->symbolPixmap() );
121#endif
122 }
123 if (!mark->labelPixmap().isNull()) {
124 painter->drawPixmap( labelRect, mark->labelPixmap() );
125 }
126 }
127 } else { // simple case, one draw per placemark
128
129 if (!mark->symbolPixmap().isNull()) {
130#ifdef BATCH_RENDERING
131 QRect symbolRect = mark->symbolPixmap().rect();
133
134 auto iter = hash.find(mark->symbolId());
135 if (iter == hash.end()) {
136 Fragment fragment;
137 fragment.pixmap = mark->symbolPixmap();
138 fragment.fragments << pixmapFragment;
139 hash.insert(mark->symbolId(), fragment);
140 }
141 else {
142 auto & fragment = iter.value();
143 fragment.fragments << pixmapFragment;
144 }
145#else
146 painter->drawPixmap( symbolPos, mark->symbolPixmap() );
147#endif
148 }
149 if (!mark->labelPixmap().isNull()) {
150 painter->drawPixmap( labelRect, mark->labelPixmap() );
151 }
152 }
153 }
154
155#ifdef BATCH_RENDERING
156 for (auto iter = hash.begin(), end = hash.end(); iter != end; ++iter) {
157 auto const & fragment = iter.value();
158 if (m_debugModeEnabled) {
159 QPixmap debugPixmap(fragment.pixmap.size());
160 QColor backgroundColor;
161 QString idStr = iter.key().section('/', -1);
162 if (idStr.length() > 2) {
163 idStr.remove("shop_");
164 backgroundColor = QColor(
165 (10 * (int)(idStr[0].toLatin1()))%255,
166 (10 * (int)(idStr[1].toLatin1()))%255,
167 (10 * (int)(idStr[2].toLatin1()))%255 );
168 }
169 else {
170 backgroundColor = QColor((quint64)(&iter.key()));
171 }
172 debugPixmap.fill(backgroundColor);
174 pixpainter.begin(&debugPixmap);
175 pixpainter.drawPixmap(0, 0, fragment.pixmap);
176 pixpainter.end();
177 iter.value().pixmap = debugPixmap;
178 }
179 painter->drawPixmapFragments(fragment.fragments.data(), fragment.fragments.size(), fragment.pixmap);
180 }
181#endif
182
183 if (m_debugModeEnabled) {
184 renderDebug(geoPainter, viewport, visiblePlacemarks);
185 }
186
187 return true;
188}
189
190RenderState PlacemarkLayer::renderState() const
191{
192 return RenderState(QStringLiteral("Placemarks"));
193}
194
195QString PlacemarkLayer::runtimeTrace() const
196{
197 return m_layout.runtimeTrace();
198}
199
200QVector<const GeoDataFeature *> PlacemarkLayer::whichPlacemarkAt( const QPoint &pos )
201{
202 return m_layout.whichPlacemarkAt( pos );
203}
204
205bool PlacemarkLayer::hasPlacemarkAt(const QPoint &pos)
206{
207 return m_layout.hasPlacemarkAt(pos);
208}
209
210bool PlacemarkLayer::isDebugModeEnabled() const
211{
212 return m_debugModeEnabled;
213}
214
215void PlacemarkLayer::setDebugModeEnabled(bool enabled)
216{
217 m_debugModeEnabled = enabled;
218}
219
220void PlacemarkLayer::setShowPlaces( bool show )
221{
222 m_layout.setShowPlaces( show );
223}
224
225void PlacemarkLayer::setShowCities( bool show )
226{
227 m_layout.setShowCities( show );
228}
229
230void PlacemarkLayer::setShowTerrain( bool show )
231{
232 m_layout.setShowTerrain( show );
233}
234
235void PlacemarkLayer::setShowOtherPlaces( bool show )
236{
237 m_layout.setShowOtherPlaces( show );
238}
239
240void PlacemarkLayer::setShowLandingSites( bool show )
241{
242 m_layout.setShowLandingSites( show );
243}
244
245void PlacemarkLayer::setShowCraters( bool show )
246{
247 m_layout.setShowCraters( show );
248}
249
250void PlacemarkLayer::setShowMaria( bool show )
251{
252 m_layout.setShowMaria( show );
253}
254
255void PlacemarkLayer::requestStyleReset()
256{
257 m_layout.requestStyleReset();
258}
259
260void PlacemarkLayer::setTileLevel(int tileLevel)
261{
262 m_tileLevel = tileLevel;
263}
264
265void PlacemarkLayer::renderDebug(GeoPainter *painter, ViewportParams *viewport, const QVector<VisiblePlacemark *> &placemarks) const
266{
267 painter->save();
268 painter->setFont(QFont(QStringLiteral("Sans Serif"), 7));
269 painter->setBrush(QBrush(Qt::NoBrush));
270 auto const latLonAltBox = viewport->viewLatLonAltBox();
271
273 const auto visiblePlacemarks = m_layout.visiblePlacemarks();
274 Placemarks const hidden = Placemarks(visiblePlacemarks.constBegin(), visiblePlacemarks.constEnd())
275 .subtract(Placemarks(placemarks.constBegin(), placemarks.constEnd()));
276
277 for (auto placemark: hidden) {
278 bool const inside = latLonAltBox.contains(placemark->coordinates());
279 painter->setPen(QPen(QColor(inside ? Qt::red : Qt::darkYellow)));
280 painter->drawRect(placemark->boundingBox());
281 }
282
283 painter->setPen(QPen(QColor(Qt::blue)));
284 for (auto placemark: placemarks) {
285 painter->drawRect(placemark->boundingBox());
286 }
287
288 painter->setPen(QPen(QColor(Qt::green)));
289 for (auto placemark: placemarks) {
290 painter->drawRect(placemark->labelRect());
291 painter->drawRect(placemark->symbolRect());
292 }
293
294 auto const height = painter->fontMetrics().height();
295 painter->setPen(QPen(QColor(Qt::black)));
296 for (auto placemark: placemarks) {
297 QPoint position = placemark->symbolRect().bottomLeft().toPoint() + QPoint(0, qRound(0.8 * height));
298 auto const popularity = placemark->placemark()->popularity();
299 painter->drawText(position, QStringLiteral("p: %1").arg(popularity));
300 position -= QPoint(0, placemark->symbolRect().height() + height);
301 auto const zoomLevel = placemark->placemark()->zoomLevel();
302 painter->drawText(position, QStringLiteral("z: %1").arg(zoomLevel));
303 }
304
305 painter->restore();
306}
307
308void PlacemarkLayer::setLevelTagDebugModeEnabled(bool enabled)
309{
310 if (m_levelTagDebugModeEnabled != enabled) {
311 m_levelTagDebugModeEnabled = enabled;
312 emit repaintNeeded();
313 }
314}
315
316bool PlacemarkLayer::levelTagDebugModeEnabled() const
317{
318 return m_levelTagDebugModeEnabled;
319}
320
321void PlacemarkLayer::setDebugLevelTag(int level)
322{
323 if (m_debugLevelTag != level) {
324 m_debugLevelTag = level;
325 emit repaintNeeded();
326 }
327}
328
329#include "moc_PlacemarkLayer.cpp"
330
This file contains the headers for AbstractProjection.
This file contains the headers for ViewportParams.
virtual bool repeatableX() const
Returns whether the projection allows for wrapping in x direction (along the longitude scale).
OsmPlacemarkData & osmData()
Quick, safe accessor to the placemark's OsmPlacemarkData stored within it's ExtendedData.
A painter that allows to draw geometric primitives on the map.
Definition GeoPainter.h:89
void drawText(const GeoDataCoordinates &position, const QString &text, qreal xOffset=0.0, qreal yOffset=0.0, qreal width=0.0, qreal height=0.0, const QTextOption &option=QTextOption())
Draws the given text at a given geographic position. The text is drawn starting at the given position...
void drawRect(const GeoDataCoordinates &centerPosition, qreal width, qreal height, bool isGeoProjected=false)
Draws a rectangle at the given position. The rectangle is placed with its center located at the given...
Layer of a GeoScene document.
QHash< QString, QString >::const_iterator findTag(const QString &key) const
tagValue returns a pointer to the tag that has key as key or the end iterator if there is no such tag
QVector< VisiblePlacemark * > generateLayout(const ViewportParams *viewport, int tileLevel)
QVector< const GeoDataFeature * > whichPlacemarkAt(const QPoint &pos)
Returns a list of model indexes that are at position pos.
A public class that controls what is visible in the viewport of a Marble map.
A class which represents the visible place marks on a map.
const QPointF & symbolPosition() const
Returns the position of the place mark symbol on the map.
const QPixmap & labelPixmap()
Returns the pixmap of the place mark name label.
const QString & symbolId() const
Returns the id for the place mark symbol.
const GeoDataPlacemark * placemark() const
Returns the index of the place mark model which is associated with this visible place mark.
const QPixmap & symbolPixmap() const
Returns the pixmap of the place mark symbol.
const QRectF & labelRect() const
Returns the area covered by the place mark name label on the map.
QStringView level(QStringView ifopt)
const QList< QKeySequence > & end()
Binds a QML item to a specific geodetic location in screen coordinates.
int height() const const
iterator begin()
iterator end()
iterator find(const Key &key)
iterator insert(const Key &key, const T &value)
const_iterator constBegin() const const
const_iterator constEnd() const const
T qobject_cast(QObject *object)
PixmapFragment create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX, qreal scaleY, qreal rotation, qreal opacity)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void drawPixmapFragments(const PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, PixmapFragmentHints hints)
QFontMetrics fontMetrics() const const
void restore()
void save()
void setFont(const QFont &font)
bool isNull() const const
QRect rect() const const
QSize size() const const
QPoint toPoint() const const
QPoint center() const const
QRect toRect() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:17 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.