Marble

PlacemarkLayer.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2006-2007 Torsten Rahn <[email protected]>
4 // SPDX-FileCopyrightText: 2007-2008 Inge Wallin <[email protected]>
5 // SPDX-FileCopyrightText: 2011-2012 Bernhard Beschow <[email protected]>
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 
24 using namespace Marble;
25 
26 PlacemarkLayer::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 
40 PlacemarkLayer::~PlacemarkLayer()
41 {
42 }
43 
44 QStringList PlacemarkLayer::renderPosition() const
45 {
46  return QStringList(QStringLiteral("PLACEMARKS"));
47 }
48 
49 qreal PlacemarkLayer::zValue() const
50 {
51  return 2.0;
52 }
53 
54 bool PlacemarkLayer::render( GeoPainter *geoPainter, ViewportParams *viewport,
55  const QString &renderPos, GeoSceneLayer *layer )
56 {
57  Q_UNUSED( renderPos )
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();
63  QVector<VisiblePlacemark*>::const_iterator itEnd = visiblePlacemarks.constBegin();
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() );
92  QPoint symbolPos( mark->symbolPosition().toPoint());
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();
107  QPainter::PixmapFragment pixmapFragment = QPainter::PixmapFragment::create(QPointF(symbolPos+symbolRect.center()),QRectF(symbolRect));
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();
132  QPainter::PixmapFragment pixmapFragment = QPainter::PixmapFragment::create(QPointF(symbolPos+symbolRect.center()),QRectF(symbolRect));
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);
173  QPainter pixpainter;
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 
190 RenderState PlacemarkLayer::renderState() const
191 {
192  return RenderState(QStringLiteral("Placemarks"));
193 }
194 
195 QString PlacemarkLayer::runtimeTrace() const
196 {
197  return m_layout.runtimeTrace();
198 }
199 
200 QVector<const GeoDataFeature *> PlacemarkLayer::whichPlacemarkAt( const QPoint &pos )
201 {
202  return m_layout.whichPlacemarkAt( pos );
203 }
204 
205 bool PlacemarkLayer::hasPlacemarkAt(const QPoint &pos)
206 {
207  return m_layout.hasPlacemarkAt(pos);
208 }
209 
210 bool PlacemarkLayer::isDebugModeEnabled() const
211 {
212  return m_debugModeEnabled;
213 }
214 
215 void PlacemarkLayer::setDebugModeEnabled(bool enabled)
216 {
217  m_debugModeEnabled = enabled;
218 }
219 
220 void PlacemarkLayer::setShowPlaces( bool show )
221 {
222  m_layout.setShowPlaces( show );
223 }
224 
225 void PlacemarkLayer::setShowCities( bool show )
226 {
227  m_layout.setShowCities( show );
228 }
229 
230 void PlacemarkLayer::setShowTerrain( bool show )
231 {
232  m_layout.setShowTerrain( show );
233 }
234 
235 void PlacemarkLayer::setShowOtherPlaces( bool show )
236 {
237  m_layout.setShowOtherPlaces( show );
238 }
239 
240 void PlacemarkLayer::setShowLandingSites( bool show )
241 {
242  m_layout.setShowLandingSites( show );
243 }
244 
245 void PlacemarkLayer::setShowCraters( bool show )
246 {
247  m_layout.setShowCraters( show );
248 }
249 
250 void PlacemarkLayer::setShowMaria( bool show )
251 {
252  m_layout.setShowMaria( show );
253 }
254 
255 void PlacemarkLayer::requestStyleReset()
256 {
257  m_layout.requestStyleReset();
258 }
259 
260 void PlacemarkLayer::setTileLevel(int tileLevel)
261 {
262  m_tileLevel = tileLevel;
263 }
264 
265 void 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 
272  using Placemarks = QSet<VisiblePlacemark *>;
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 
308 void PlacemarkLayer::setLevelTagDebugModeEnabled(bool enabled)
309 {
310  if (m_levelTagDebugModeEnabled != enabled) {
311  m_levelTagDebugModeEnabled = enabled;
312  emit repaintNeeded();
313  }
314 }
315 
316 bool PlacemarkLayer::levelTagDebugModeEnabled() const
317 {
318  return m_levelTagDebugModeEnabled;
319 }
320 
321 void 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 
QRect rect() const const
const T value(const Key &key) const const
const QPixmap & symbolPixmap() const
Returns the pixmap of the place mark symbol.
QString section(QChar sep, int start, int end, QString::SectionFlags flags) const const
A class which represents the visible place marks on a map.
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
const QPixmap & labelPixmap()
Returns the pixmap of the place mark name label.
const QRectF & labelRect() const
Returns the area covered by the place mark name label on the map.
QRect toRect() const const
QHash::iterator begin()
QHash::iterator find(const Key &key)
QStringView level(QStringView ifopt)
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::const_iterator constEnd() const const
Layer of a GeoScene document.
Definition: GeoSceneLayer.h:28
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QHash::iterator insert(const Key &key, const T &value)
PixmapFragment create(const QPointF &pos, const QRectF &sourceRect, qreal scaleX, qreal scaleY, qreal rotation, qreal opacity)
bool begin(QPaintDevice *device)
bool end()
A public class that controls what is visible in the viewport of a Marble map.
const GeoDataPlacemark * placemark() const
Returns the index of the place mark model which is associated with this visible place mark.
int length() const const
void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints)
QFontMetrics fontMetrics() const const
bool contains(const T &value) const const
QPoint center() const const
Binds a QML item to a specific geodetic location in screen coordinates.
A painter that allows to draw geometric primitives on the map.
Definition: GeoPainter.h:88
QString & remove(int position, int n)
const QString & symbolId() const
Returns the id for the place mark symbol.
bool isNull() const const
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...
Definition: GeoPainter.cpp:284
const QPointF & symbolPosition() const
Returns the position of the place mark symbol on the map.
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.
void setBrush(Qt::BrushStyle style)
QPoint toPoint() const const
void restore()
void save()
QVector::const_iterator constBegin() const const
void setFont(const QFont &font)
int height() const const
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...
Definition: GeoPainter.cpp:927
QHash::iterator end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Sep 21 2023 04:12:27 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.