• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
GeoPainter.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2009 Torsten Rahn <tackat@kde.org>
9 
10 
11 #include "GeoPainter.h"
12 #include "GeoPainter_p.h"
13 
14 #include <QList>
15 #include <QPainterPath>
16 #include <QRegion>
17 
18 #include "MarbleDebug.h"
19 
20 #include "GeoDataCoordinates.h"
21 #include "GeoDataLineString.h"
22 #include "GeoDataLinearRing.h"
23 #include "GeoDataPoint.h"
24 #include "GeoDataPolygon.h"
25 
26 #include "MarbleGlobal.h"
27 #include "ViewportParams.h"
28 
29 // #define MARBLE_DEBUG
30 
31 using namespace Marble;
32 
33 GeoPainterPrivate::GeoPainterPrivate( const ViewportParams *viewport, MapQuality mapQuality )
34  : m_viewport( viewport ),
35  m_mapQuality( mapQuality ),
36  m_x( new qreal[100] )
37 {
38 }
39 
40 GeoPainterPrivate::~GeoPainterPrivate()
41 {
42  delete[] m_x;
43 }
44 
45 void GeoPainterPrivate::createAnnotationLayout ( qreal x, qreal y,
46  QSizeF bubbleSize,
47  qreal bubbleOffsetX, qreal bubbleOffsetY,
48  qreal xRnd, qreal yRnd,
49  QPainterPath& path, QRectF& rect )
50 {
51  // TODO: MOVE this into an own Annotation class
52  qreal arrowPosition = 0.3;
53  qreal arrowWidth = 12.0;
54 
55  qreal width = bubbleSize.width();
56  qreal height = bubbleSize.height();
57 
58  qreal dx = ( bubbleOffsetX > 0 ) ? 1.0 : -1.0; // x-Mirror
59  qreal dy = ( bubbleOffsetY < 0 ) ? 1.0 : -1.0; // y-Mirror
60 
61  qreal x0 = ( x + bubbleOffsetX ) - dx * ( 1.0 - arrowPosition ) * ( width - 2.0 * xRnd ) - xRnd *dx;
62  qreal x1 = ( x + bubbleOffsetX ) - dx * ( 1.0 - arrowPosition ) * ( width - 2.0 * xRnd );
63  qreal x2 = ( x + bubbleOffsetX ) - dx * ( 1.0 - arrowPosition ) * ( width - 2.0 * xRnd ) + xRnd * dx;
64  qreal x3 = ( x + bubbleOffsetX ) - dx * arrowWidth / 2.0;
65  qreal x4 = ( x + bubbleOffsetX ) + dx * arrowWidth / 2.0;
66  qreal x5 = ( x + bubbleOffsetX ) + dx * arrowPosition * ( width - 2.0 * xRnd )- xRnd * dx;
67  qreal x6 = ( x + bubbleOffsetX ) + dx * arrowPosition * ( width - 2.0 * xRnd );
68  qreal x7 = ( x + bubbleOffsetX ) + dx * arrowPosition * ( width - 2.0 * xRnd ) + xRnd * dx;
69 
70  qreal y0 = ( y + bubbleOffsetY );
71  qreal y1 = ( y + bubbleOffsetY ) - dy * yRnd;
72  qreal y2 = ( y + bubbleOffsetY ) - dy * 2 * yRnd;
73  qreal y5 = ( y + bubbleOffsetY ) - dy * ( height - 2 * yRnd );
74  qreal y6 = ( y + bubbleOffsetY ) - dy * ( height - yRnd );
75  qreal y7 = ( y + bubbleOffsetY ) - dy * height;
76 
77  QPointF p1 ( x, y ); // pointing point
78  QPointF p2 ( x4, y0 );
79  QPointF p3 ( x6, y0 );
80  QPointF p4 ( x7, y1 );
81  QPointF p5 ( x7, y6 );
82  QPointF p6 ( x6, y7 );
83  QPointF p7 ( x1, y7 );
84  QPointF p8 ( x0, y6 );
85  QPointF p9 ( x0, y1 );
86  QPointF p10( x1, y0 );
87  QPointF p11( x3, y0 );
88 
89  QRectF bubbleBoundingBox( QPointF( x0, y7 ), QPointF( x7, y0 ) );
90 
91  path.moveTo( p1 );
92  path.lineTo( p2 );
93 
94  path.lineTo( p3 );
95  QRectF bottomRight( QPointF( x5, y2 ), QPointF( x7, y0 ) );
96  path.arcTo( bottomRight, 270.0, 90.0 );
97 
98  path.lineTo( p5 );
99  QRectF topRight( QPointF( x5, y7 ), QPointF( x7, y5 ) );
100  path.arcTo( topRight, 0.0, 90.0 );
101 
102  path.lineTo( p7 );
103  QRectF topLeft( QPointF( x0, y7 ), QPointF( x2, y5 ) );
104  path.arcTo( topLeft, 90.0, 90.0 );
105 
106  path.lineTo( p9 );
107  QRectF bottomLeft( QPointF( x0, y2 ), QPointF( x2, y0 ) );
108  path.arcTo( bottomLeft, 180.0, 90.0 );
109 
110  path.lineTo( p10 );
111  path.lineTo( p11 );
112  path.lineTo( p1 );
113 
114  qreal left = ( dx > 0 ) ? x1 : x6;
115  qreal right = ( dx > 0 ) ? x6 : x1;
116  qreal top = ( dy > 0 ) ? y6 : y1;
117  qreal bottom = ( dy > 0 ) ? y1 : y6;
118 
119  rect.setTopLeft( QPointF( left, top ) );
120  rect.setBottomRight( QPointF( right, bottom ) );
121 }
122 
123 GeoDataLinearRing GeoPainterPrivate::createLinearRingFromGeoRect( const GeoDataCoordinates & centerCoordinates,
124  qreal width, qreal height )
125 {
126  qreal lon = 0.0;
127  qreal lat = 0.0;
128  qreal altitude = centerCoordinates.altitude();
129  centerCoordinates.geoCoordinates( lon, lat, GeoDataCoordinates::Degree );
130 
131  lon = GeoDataCoordinates::normalizeLon( lon, GeoDataCoordinates::Degree );
132  lat = GeoDataCoordinates::normalizeLat( lat, GeoDataCoordinates::Degree );
133 
134  qreal west = GeoDataCoordinates::normalizeLon( lon - width * 0.5, GeoDataCoordinates::Degree );
135  qreal east = GeoDataCoordinates::normalizeLon( lon + width * 0.5, GeoDataCoordinates::Degree );
136 
137  qreal north = GeoDataCoordinates::normalizeLat( lat + height * 0.5, GeoDataCoordinates::Degree );
138  qreal south = GeoDataCoordinates::normalizeLat( lat - height * 0.5, GeoDataCoordinates::Degree );
139 
140  GeoDataCoordinates southWest( west, south,
141  altitude, GeoDataCoordinates::Degree );
142  GeoDataCoordinates southEast( east, south,
143  altitude, GeoDataCoordinates::Degree );
144  GeoDataCoordinates northEast( east, north,
145  altitude, GeoDataCoordinates::Degree );
146  GeoDataCoordinates northWest( west, north,
147  altitude, GeoDataCoordinates::Degree );
148 
149  GeoDataLinearRing rectangle( Tessellate | RespectLatitudeCircle );
150 
151  // If the width of the rect is larger as 180 degree, we have to enforce the long way.
152  if ( width >= 180 ) {
153  qreal center = lon;
154  GeoDataCoordinates southCenter( center, south, altitude, GeoDataCoordinates::Degree );
155  GeoDataCoordinates northCenter( center, north, altitude, GeoDataCoordinates::Degree );
156 
157  rectangle << southWest << southCenter << southEast << northEast << northCenter << northWest;
158  }
159  else {
160  rectangle << southWest << southEast << northEast << northWest;
161  }
162 
163  return rectangle;
164 }
165 
166 bool GeoPainterPrivate::doClip( const ViewportParams *viewport )
167 {
168  if ( viewport->projection() != Spherical )
169  return true;
170 
171  return ( viewport->radius() > viewport->width() / 2 || viewport->radius() > viewport->height() / 2 );
172 }
173 
174 // -------------------------------------------------------------------------------------------------
175 
176 GeoPainter::GeoPainter( QPaintDevice* pd, const ViewportParams *viewport, MapQuality mapQuality )
177  : ClipPainter( pd, GeoPainterPrivate::doClip( viewport ) ),
178  d( new GeoPainterPrivate( viewport, mapQuality ) )
179 {
180  const bool antialiased = mapQuality == HighQuality || mapQuality == PrintQuality;
181  setRenderHint( QPainter::Antialiasing, antialiased );
182 }
183 
184 
185 GeoPainter::~GeoPainter()
186 {
187  delete d;
188 }
189 
190 
191 MapQuality GeoPainter::mapQuality() const
192 {
193  return d->m_mapQuality;
194 }
195 
196 
197 void GeoPainter::drawAnnotation( const GeoDataCoordinates & position,
198  const QString & text, QSizeF bubbleSize,
199  qreal bubbleOffsetX, qreal bubbleOffsetY,
200  qreal xRnd, qreal yRnd )
201 {
202  int pointRepeatNum;
203  qreal y;
204  bool globeHidesPoint;
205 
206  if ( bubbleSize.height() <= 0 ) {
207  QRectF rect = QRectF( QPointF( 0.0, 0.0 ), bubbleSize - QSizeF( 2 * xRnd, 0.0 ) );
208  qreal idealTextHeight = boundingRect( rect, Qt::TextWordWrap, text ).height();
209  bubbleSize.setHeight( 2 * yRnd + idealTextHeight );
210  }
211 
212  bool visible = d->m_viewport->screenCoordinates( position, d->m_x, y, pointRepeatNum, QSizeF(), globeHidesPoint );
213 
214  if ( visible ) {
215  // Draw all the x-repeat-instances of the point on the screen
216  for( int it = 0; it < pointRepeatNum; ++it ) {
217  QPainterPath path;
218  QRectF rect;
219  d->createAnnotationLayout( d->m_x[it], y, bubbleSize, bubbleOffsetX, bubbleOffsetY, xRnd, yRnd, path, rect );
220  QPainter::drawPath( path );
221  QPainter::drawText( rect, Qt::TextWordWrap, text, &rect );
222  }
223  }
224 }
225 
226 
227 void GeoPainter::drawPoint ( const GeoDataCoordinates & position )
228 {
229  int pointRepeatNum;
230  qreal y;
231  bool globeHidesPoint;
232 
233  bool visible = d->m_viewport->screenCoordinates( position, d->m_x, y, pointRepeatNum, QSizeF(), globeHidesPoint );
234 
235  if ( visible ) {
236  // Draw all the x-repeat-instances of the point on the screen
237  for( int it = 0; it < pointRepeatNum; ++it ) {
238  QPainter::drawPoint( d->m_x[it], y );
239  }
240  }
241 }
242 
243 
244 QRegion GeoPainter::regionFromPoint ( const GeoDataCoordinates & position,
245  qreal width ) const
246 {
247  return regionFromRect( position, width, width, false, 3 );
248 }
249 
250 
251 void GeoPainter::drawPoint( const GeoDataPoint & point )
252 {
253  drawPoint( point.coordinates() );
254 }
255 
256 
257 QRegion GeoPainter::regionFromPoint ( const GeoDataPoint & point,
258  qreal width ) const
259 {
260  return regionFromRect( point.coordinates(), width, width, false, 3 );
261 }
262 
263 
264 void GeoPainter::drawText ( const GeoDataCoordinates & position,
265  const QString & text )
266 {
267  // Of course in theory we could have the "isGeoProjected" parameter used
268  // for drawText as well. However this would require us to convert all
269  // glyphs to PainterPaths / QPolygons. From QPolygons we could create
270  // GeoDataPolygons which could get painted on screen. Any patches appreciated ;-)
271 
272  int pointRepeatNum;
273  qreal y;
274  bool globeHidesPoint;
275 
276  QSizeF textSize( fontMetrics().width( text ), fontMetrics().height() );
277 
278  bool visible = d->m_viewport->screenCoordinates( position, d->m_x, y, pointRepeatNum, textSize, globeHidesPoint );
279 
280  if ( visible ) {
281  // Draw all the x-repeat-instances of the point on the screen
282  for( int it = 0; it < pointRepeatNum; ++it ) {
283  QPainter::drawText( d->m_x[it], y, text );
284  }
285  }
286 }
287 
288 
289 void GeoPainter::drawEllipse ( const GeoDataCoordinates & centerPosition,
290  qreal width, qreal height,
291  bool isGeoProjected )
292 {
293  if ( !isGeoProjected ) {
294  int pointRepeatNum;
295  qreal y;
296  bool globeHidesPoint;
297 
298  bool visible = d->m_viewport->screenCoordinates( centerPosition, d->m_x, y, pointRepeatNum, QSizeF( width, height ), globeHidesPoint );
299 
300  if ( visible ) {
301  // Draw all the x-repeat-instances of the point on the screen
302  for( int it = 0; it < pointRepeatNum; ++it ) {
303  QPainter::drawEllipse( d->m_x[it] - width / 2.0,
304  y - height / 2.0, width, height );
305  }
306  }
307  }
308  else {
309  // Initialize variables
310  const qreal centerLon = centerPosition.longitude( GeoDataCoordinates::Degree );
311  const qreal centerLat = centerPosition.latitude( GeoDataCoordinates::Degree );
312  const qreal altitude = centerPosition.altitude();
313 
314  // Ensure a valid latitude range:
315  if ( centerLat + 0.5 * height > 90.0 || centerLat - 0.5 * height < -90.0 ) {
316  return;
317  }
318 
319  // Don't show the ellipse if it's too small:
320  GeoDataLatLonBox ellipseBox( centerLat + 0.5 * height, centerLat - 0.5 * height,
321  centerLon + 0.5 * width, centerLon - 0.5 * width,
322  GeoDataCoordinates::Degree );
323  if ( !d->m_viewport->viewLatLonAltBox().intersects( ellipseBox ) ||
324  !d->m_viewport->resolves( ellipseBox ) ) return;
325 
326  GeoDataLinearRing ellipse;
327 
328  // Optimizing the precision by determining the size which the
329  // ellipse covers on the screen:
330  const qreal degreeResolution = d->m_viewport->angularResolution() * RAD2DEG;
331  // To create a circle shape even for very small precision we require uneven numbers:
332  const int precision = qMin<qreal>( width / degreeResolution / 8 + 1, 81 );
333 
334  // Calculate the shape of the upper half of the ellipse:
335  for ( int i = 0; i <= precision; ++i ) {
336  const qreal t = 1.0 - 2.0 * (qreal)(i) / (qreal)(precision);
337  const qreal lat = centerLat + 0.5 * height * sqrt( 1.0 - t * t );
338  const qreal lon = centerLon + 0.5 * width * t;
339  ellipse << GeoDataCoordinates( lon, lat, altitude, GeoDataCoordinates::Degree );
340  }
341  // Calculate the shape of the lower half of the ellipse:
342  for ( int i = 0; i <= precision; ++i ) {
343  const qreal t = 2.0 * (qreal)(i) / (qreal)(precision) - 1.0;
344  const qreal lat = centerLat - 0.5 * height * sqrt( 1.0 - t * t );
345  const qreal lon = centerLon + 0.5 * width * t;
346  ellipse << GeoDataCoordinates( lon, lat, altitude, GeoDataCoordinates::Degree );
347  }
348 
349  drawPolygon( ellipse );
350 
351  }
352 
353 }
354 
355 
356 QRegion GeoPainter::regionFromEllipse ( const GeoDataCoordinates & centerPosition,
357  qreal width, qreal height,
358  bool isGeoProjected,
359  qreal strokeWidth ) const
360 {
361  if ( !isGeoProjected ) {
362  int pointRepeatNum;
363  qreal y;
364  bool globeHidesPoint;
365 
366  bool visible = d->m_viewport->screenCoordinates( centerPosition, d->m_x, y, pointRepeatNum, QSizeF( width, height ), globeHidesPoint );
367 
368  QRegion regions;
369 
370  if ( visible ) {
371  // Draw all the x-repeat-instances of the point on the screen
372  for( int it = 0; it < pointRepeatNum; ++it ) {
373  regions += QRegion( d->m_x[it] - width / 2.0,
374  y - height / 2.0,
375  width + strokeWidth,
376  height + strokeWidth,
377  QRegion::Ellipse );
378  }
379  }
380  return regions;
381  }
382  else {
383  // Initialize variables
384  const qreal centerLon = centerPosition.longitude( GeoDataCoordinates::Degree );
385  const qreal centerLat = centerPosition.latitude( GeoDataCoordinates::Degree );
386  const qreal altitude = centerPosition.altitude();
387 
388  // Ensure a valid latitude range:
389  if ( centerLat + 0.5 * height > 90.0 || centerLat - 0.5 * height < -90.0 ) {
390  return QRegion();
391  }
392 
393  // Don't show the ellipse if it's too small:
394  GeoDataLatLonBox ellipseBox( centerLat + 0.5 * height, centerLat - 0.5 * height,
395  centerLon + 0.5 * width, centerLon - 0.5 * width,
396  GeoDataCoordinates::Degree );
397  if ( !d->m_viewport->viewLatLonAltBox().intersects( ellipseBox ) ||
398  !d->m_viewport->resolves( ellipseBox ) ) return QRegion();
399 
400  GeoDataLinearRing ellipse;
401 
402  // Optimizing the precision by determining the size which the
403  // ellipse covers on the screen:
404  const qreal degreeResolution = d->m_viewport->angularResolution() * RAD2DEG;
405  // To create a circle shape even for very small precision we require uneven numbers:
406  const int precision = qMin<qreal>( width / degreeResolution / 8 + 1, 81 );
407 
408  // Calculate the shape of the upper half of the ellipse:
409  for ( int i = 0; i <= precision; ++i ) {
410  const qreal t = 1.0 - 2.0 * (qreal)(i) / (qreal)(precision);
411  const qreal lat = centerLat + 0.5 * height * sqrt( 1.0 - t * t );
412  const qreal lon = centerLon + 0.5 * width * t;
413  ellipse << GeoDataCoordinates( lon, lat, altitude, GeoDataCoordinates::Degree );
414  }
415  // Calculate the shape of the lower half of the ellipse:
416  for ( int i = 0; i <= precision; ++i ) {
417  const qreal t = 2.0 * (qreal)(i) / (qreal)(precision) - 1.0;
418  const qreal lat = centerLat - 0.5 * height * sqrt( 1.0 - t * t );
419  const qreal lon = centerLon + 0.5 * width * t;
420  ellipse << GeoDataCoordinates( lon, lat, altitude, GeoDataCoordinates::Degree );
421  }
422 
423  return regionFromPolygon( ellipse, Qt::OddEvenFill, strokeWidth );
424  }
425 }
426 
427 
428 void GeoPainter::drawImage ( const GeoDataCoordinates & centerPosition,
429  const QImage & image /*, bool isGeoProjected */ )
430 {
431  // isGeoProjected = true would project the image/pixmap onto the globe. This
432  // requires to deal with the TextureMapping classes -> should get
433  // implemented later on
434 
435  int pointRepeatNum;
436  qreal y;
437  bool globeHidesPoint;
438 
439 // if ( !isGeoProjected ) {
440  bool visible = d->m_viewport->screenCoordinates( centerPosition, d->m_x, y, pointRepeatNum, image.size(), globeHidesPoint );
441 
442  if ( visible ) {
443  // Draw all the x-repeat-instances of the point on the screen
444  for( int it = 0; it < pointRepeatNum; ++it ) {
445  QPainter::drawImage( d->m_x[it] - ( image.width() / 2 ), y - ( image.height() / 2 ), image );
446  }
447  }
448 // }
449 }
450 
451 
452 void GeoPainter::drawPixmap ( const GeoDataCoordinates & centerPosition,
453  const QPixmap & pixmap /* , bool isGeoProjected */ )
454 {
455  int pointRepeatNum;
456  qreal y;
457  bool globeHidesPoint;
458 
459 // if ( !isGeoProjected ) {
460  // FIXME: Better visibility detection that takes the circle geometry into account
461  bool visible = d->m_viewport->screenCoordinates( centerPosition, d->m_x, y, pointRepeatNum, pixmap.size(), globeHidesPoint );
462 
463  if ( visible ) {
464  // Draw all the x-repeat-instances of the point on the screen
465  for( int it = 0; it < pointRepeatNum; ++it ) {
466  QPainter::drawPixmap( d->m_x[it] - ( pixmap.width() / 2 ),
467  y - ( pixmap.height() / 2 ), pixmap );
468  }
469  }
470 // }
471 }
472 
473 
474 void GeoPainter::drawPolyline ( const GeoDataLineString & lineString,
475  const QString& labelText,
476  LabelPositionFlags labelPositionFlags )
477 {
478  // Immediately leave this method now if:
479  // - the object is not visible in the viewport or if
480  // - the size of the object is below the resolution of the viewport
481  if ( ! d->m_viewport->viewLatLonAltBox().intersects( lineString.latLonAltBox() ) ||
482  ! d->m_viewport->resolves( lineString.latLonAltBox() )
483  )
484  {
485  // mDebug() << "LineString doesn't get displayed on the viewport";
486  return;
487  }
488 
489  QVector<QPolygonF*> polygons;
490  d->m_viewport->screenCoordinates( lineString, polygons );
491 
492  if ( labelText.isEmpty() || labelPositionFlags.testFlag( NoLabel ) ) {
493  foreach( QPolygonF* itPolygon, polygons ) {
494  ClipPainter::drawPolyline( *itPolygon );
495  }
496  }
497  else {
498  int labelWidth = fontMetrics().width( labelText );
499  int labelAscent = fontMetrics().ascent();
500 
501  QVector<QPointF> labelNodes;
502  foreach( QPolygonF* itPolygon, polygons ) {
503  labelNodes.clear();
504  ClipPainter::drawPolyline( *itPolygon, labelNodes, labelPositionFlags );
505  if ( !labelNodes.isEmpty() ) {
506  foreach ( const QPointF& labelNode, labelNodes ) {
507  QPointF labelPosition = labelNode + QPointF( 3.0, -2.0 );
508 
509  // FIXME: This is a Q&D fix.
510  qreal xmax = viewport().width() - 10.0 - labelWidth;
511  if ( labelPosition.x() > xmax ) labelPosition.setX( xmax );
512  qreal ymin = 10.0 + labelAscent;
513  if ( labelPosition.y() < ymin ) labelPosition.setY( ymin );
514  qreal ymax = viewport().height() - 10.0 - labelAscent;
515  if ( labelPosition.y() > ymax ) labelPosition.setY( ymax );
516 
517  drawText( QRectF( labelPosition, fontMetrics().size( 0, labelText) ), labelText );
518  }
519  }
520  }
521  }
522  qDeleteAll( polygons );
523 }
524 
525 
526 QRegion GeoPainter::regionFromPolyline ( const GeoDataLineString & lineString,
527  qreal strokeWidth ) const
528 {
529  // Immediately leave this method now if:
530  // - the object is not visible in the viewport or if
531  // - the size of the object is below the resolution of the viewport
532  if ( ! d->m_viewport->viewLatLonAltBox().intersects( lineString.latLonAltBox() ) ||
533  ! d->m_viewport->resolves( lineString.latLonAltBox() )
534  )
535  {
536  // mDebug() << "LineString doesn't get displayed on the viewport";
537  return QRegion();
538  }
539 
540  QList<QRegion> regions;
541  QPainterPath painterPath;
542 
543  QVector<QPolygonF*> polygons;
544  d->m_viewport->screenCoordinates( lineString, polygons );
545 
546  foreach( QPolygonF* itPolygon, polygons ) {
547  painterPath.addPolygon( *itPolygon );
548  }
549 
550  qDeleteAll( polygons );
551 
552  QPainterPathStroker stroker;
553  stroker.setWidth( strokeWidth );
554  QPainterPath strokePath = stroker.createStroke( painterPath );
555 
556  return QRegion( strokePath.toFillPolygon().toPolygon(), Qt::WindingFill );
557 }
558 
559 
560 void GeoPainter::drawPolygon ( const GeoDataLinearRing & linearRing,
561  Qt::FillRule fillRule )
562 {
563  // Immediately leave this method now if:
564  // - the object is not visible in the viewport or if
565  // - the size of the object is below the resolution of the viewport
566  if ( ! d->m_viewport->viewLatLonAltBox().intersects( linearRing.latLonAltBox() ) ||
567  ! d->m_viewport->resolves( linearRing.latLonAltBox() )
568  )
569  {
570  // mDebug() << "Polygon doesn't get displayed on the viewport";
571  return;
572  }
573 
574  QVector<QPolygonF*> polygons;
575  d->m_viewport->screenCoordinates( linearRing, polygons );
576 
577  foreach( QPolygonF* itPolygon, polygons ) {
578  ClipPainter::drawPolygon( *itPolygon, fillRule );
579  }
580 
581  qDeleteAll( polygons );
582 }
583 
584 
585 QRegion GeoPainter::regionFromPolygon ( const GeoDataLinearRing & linearRing,
586  Qt::FillRule fillRule, qreal strokeWidth ) const
587 {
588  // Immediately leave this method now if:
589  // - the object is not visible in the viewport or if
590  // - the size of the object is below the resolution of the viewport
591  if ( ! d->m_viewport->viewLatLonAltBox().intersects( linearRing.latLonAltBox() ) ||
592  ! d->m_viewport->resolves( linearRing.latLonAltBox() )
593  )
594  {
595  return QRegion();
596  }
597 
598  QRegion regions;
599 
600  QVector<QPolygonF*> polygons;
601  d->m_viewport->screenCoordinates( linearRing, polygons );
602 
603  if ( strokeWidth == 0 ) {
604  // This is the faster way
605  foreach( QPolygonF* itPolygon, polygons ) {
606  regions += QRegion ( (*itPolygon).toPolygon(), fillRule );
607  }
608  }
609  else {
610  QPainterPath painterPath;
611  foreach( QPolygonF* itPolygon, polygons ) {
612  painterPath.addPolygon( *itPolygon );
613  }
614 
615  QPainterPathStroker stroker;
616  stroker.setWidth( strokeWidth );
617  QPainterPath strokePath = stroker.createStroke( painterPath );
618  painterPath = painterPath.united( strokePath );
619  regions = QRegion( painterPath.toFillPolygon().toPolygon() );
620  }
621 
622  qDeleteAll( polygons );
623 
624  return regions;
625 }
626 
627 
628 void GeoPainter::drawPolygon ( const GeoDataPolygon & polygon,
629  Qt::FillRule fillRule )
630 {
631  // If the object is not visible in the viewport return
632  if ( ! d->m_viewport->viewLatLonAltBox().intersects( polygon.outerBoundary().latLonAltBox() ) ||
633  // If the size of the object is below the resolution of the viewport then return
634  ! d->m_viewport->resolves( polygon.outerBoundary().latLonAltBox() )
635  )
636  {
637  // mDebug() << "Polygon doesn't get displayed on the viewport";
638  return;
639  }
640  // mDebug() << "Drawing Polygon";
641 
642  // Creating the outer screen polygons first
643  QVector<QPolygonF*> outerPolygons;
644  d->m_viewport->screenCoordinates( polygon.outerBoundary(), outerPolygons );
645 
646  // Now creating the "holes" by cutting away the inner boundaries:
647 
648  // In QPathClipper We Trust ...
649  // ... and in the speed of a threesome of nested foreachs!
650 
651  QVector<QPolygonF> outline;
652  QPen const oldPen = pen();
653  // When inner boundaries exist, the outline of the polygon must be painted
654  // separately to avoid connections between the outer and inner boundaries
655  // To avoid performance penalties the separate painting is only done when
656  // it's really needed. See review 105019 for details.
657  bool const needOutlineWorkaround = !polygon.innerBoundaries().isEmpty();
658  if ( needOutlineWorkaround ) {
659  foreach( QPolygonF* polygon, outerPolygons ) {
660  outline << *polygon;
661  }
662  setPen( QPen( Qt::NoPen ) );
663  }
664 
665 
666  QVector<GeoDataLinearRing> innerBoundaries = polygon.innerBoundaries();
667  foreach( const GeoDataLinearRing& itInnerBoundary, innerBoundaries ) {
668  QVector<QPolygonF*> innerPolygons;
669  d->m_viewport->screenCoordinates( itInnerBoundary, innerPolygons );
670 
671  if ( needOutlineWorkaround ) {
672  foreach( QPolygonF* polygon, innerPolygons ) {
673  outline << *polygon;
674  }
675  }
676 
677  foreach( QPolygonF* itOuterPolygon, outerPolygons ) {
678  foreach( QPolygonF* itInnerPolygon, innerPolygons ) {
679  *itOuterPolygon = itOuterPolygon->subtracted( *itInnerPolygon );
680  }
681  }
682  qDeleteAll( innerPolygons );
683  }
684 
685  foreach( QPolygonF* itOuterPolygon, outerPolygons ) {
686  ClipPainter::drawPolygon( *itOuterPolygon, fillRule );
687  }
688 
689  if ( needOutlineWorkaround ) {
690  setPen( oldPen );
691  foreach( const QPolygonF &polygon, outline ) {
692  ClipPainter::drawPolyline( polygon );
693  }
694  }
695 
696  qDeleteAll( outerPolygons );
697 }
698 
699 
700 void GeoPainter::drawRect ( const GeoDataCoordinates & centerCoordinates,
701  qreal width, qreal height,
702  bool isGeoProjected )
703 {
704  if ( !isGeoProjected ) {
705  int pointRepeatNum;
706  qreal y;
707  bool globeHidesPoint;
708 
709  bool visible = d->m_viewport->screenCoordinates( centerCoordinates,
710  d->m_x, y, pointRepeatNum, QSizeF( width, height ), globeHidesPoint );
711 
712  if ( visible ) {
713  // Draw all the x-repeat-instances of the point on the screen
714  for( int it = 0; it < pointRepeatNum; ++it ) {
715  QPainter::drawRect( d->m_x[it] - ( width / 2.0 ), y - ( height / 2.0 ), width, height );
716  }
717  }
718  }
719  else {
720  drawPolygon( d->createLinearRingFromGeoRect( centerCoordinates, width, height ),
721  Qt::OddEvenFill );
722  }
723 }
724 
725 
726 QRegion GeoPainter::regionFromRect ( const GeoDataCoordinates & centerCoordinates,
727  qreal width, qreal height,
728  bool isGeoProjected,
729  qreal strokeWidth ) const
730 {
731  if ( !isGeoProjected ) {
732  int pointRepeatNum;
733  qreal y;
734  bool globeHidesPoint;
735 
736  bool visible = d->m_viewport->screenCoordinates( centerCoordinates,
737  d->m_x, y, pointRepeatNum, QSizeF( width, height ), globeHidesPoint );
738 
739  QRegion regions;
740 
741  if ( visible ) {
742  // Draw all the x-repeat-instances of the point on the screen
743  for( int it = 0; it < pointRepeatNum; ++it ) {
744  regions += QRegion( d->m_x[it] - ( ( width + strokeWidth ) / 2.0 ),
745  y - ( ( height + strokeWidth ) / 2.0 ),
746  width + strokeWidth,
747  height + strokeWidth );
748  }
749  }
750  return regions;
751  }
752  else {
753  return regionFromPolygon( d->createLinearRingFromGeoRect( centerCoordinates, width, height ),
754  Qt::OddEvenFill, strokeWidth );
755  }
756 }
757 
758 
759 void GeoPainter::drawRoundRect ( const GeoDataCoordinates &centerPosition,
760  int width, int height,
761  int xRnd, int yRnd )
762 {
763  int pointRepeatNum;
764  qreal y;
765  bool globeHidesPoint;
766 
767  // FIXME: Better visibility detection that takes the circle geometry into account
768  bool visible = d->m_viewport->screenCoordinates( centerPosition, d->m_x, y, pointRepeatNum, QSizeF( width, height ), globeHidesPoint );
769 
770  if ( visible ) {
771  // Draw all the x-repeat-instances of the point on the screen
772  for( int it = 0; it < pointRepeatNum; ++it ) {
773  QPainter::drawRoundRect( d->m_x[it] - ( width / 2 ), y - ( height / 2 ), width, height, xRnd, yRnd );
774  }
775  }
776 }
Marble::GeoDataPoint
A Geometry object representing a 3d point.
Definition: GeoDataPoint.h:47
QPainterPathStroker::setWidth
void setWidth(qreal width)
GeoDataCoordinates.h
Marble::RAD2DEG
const qreal RAD2DEG
Definition: MarbleGlobal.h:220
Marble::GeoPainter::regionFromRect
QRegion regionFromRect(const GeoDataCoordinates &centerPosition, qreal width, qreal height, bool isGeoProjected=false, qreal strokeWidth=3) const
Creates a region for a rectangle at a given position.
Definition: GeoPainter.cpp:726
QPixmap::size
QSize size() const
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
QPolygonF::toPolygon
QPolygon toPolygon() const
Marble::GeoDataLatLonAltBox::intersects
virtual bool intersects(const GeoDataLatLonAltBox &) const
Check if this GeoDataLatLonAltBox intersects with the given one.
Definition: GeoDataLatLonAltBox.cpp:196
QFontMetrics::ascent
int ascent() const
Marble::GeoPainter::drawPolygon
void drawPolygon(const GeoDataLinearRing &linearRing, Qt::FillRule fillRule=Qt::OddEvenFill)
Draws a given linear ring (a "polygon without holes").
Definition: GeoPainter.cpp:560
QPixmap::width
int width() const
QPolygonF::subtracted
QPolygonF subtracted(const QPolygonF &r) const
Marble::GeoDataLinearRing
A LinearRing that allows to store a closed, contiguous set of line segments.
Definition: GeoDataLinearRing.h:68
QPainter::setRenderHint
void setRenderHint(RenderHint hint, bool on)
QPainter::strokePath
void strokePath(const QPainterPath &path, const QPen &pen)
GeoDataPolygon.h
QPaintDevice
Marble::GeoPainterPrivate::m_x
qreal *const m_x
Definition: GeoPainter_p.h:50
Marble::GeoDataCoordinates::normalizeLon
static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
Definition: GeoDataCoordinates.cpp:776
Marble::ViewportParams::angularResolution
qreal angularResolution() const
Definition: ViewportParams.cpp:322
Marble::ViewportParams::viewLatLonAltBox
const GeoDataLatLonAltBox & viewLatLonAltBox() const
Definition: ViewportParams.cpp:305
Marble::GeoPainterPrivate::doClip
static bool doClip(const ViewportParams *viewport)
Definition: GeoPainter.cpp:166
QPainterPath::moveTo
void moveTo(const QPointF &point)
QRect::height
int height() const
Marble::GeoPainter::drawPolyline
void drawPolyline(const GeoDataLineString &lineString, const QString &labelText=QString(), LabelPositionFlags labelPositionFlags=LineCenter)
Draws a given line string (a "polyline").
Definition: GeoPainter.cpp:474
Marble::PrintQuality
Print quality.
Definition: MarbleGlobal.h:87
Marble::ViewportParams::projection
Projection projection() const
Definition: ViewportParams.cpp:129
Marble::MapQuality
MapQuality
This enum is used to choose the map quality shown in the view.
Definition: MarbleGlobal.h:82
Marble::GeoPainter::~GeoPainter
~GeoPainter()
Destroys the geo painter.
Definition: GeoPainter.cpp:185
QPainterPath::toFillPolygon
QPolygonF toFillPolygon(const QMatrix &matrix) const
Marble::GeoPainter::regionFromPolyline
QRegion regionFromPolyline(const GeoDataLineString &lineString, qreal strokeWidth=3) const
Creates a region for a given line string (a "polyline").
Definition: GeoPainter.cpp:526
Marble::GeoDataCoordinates::latitude
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Definition: GeoDataCoordinates.cpp:751
Marble::GeoPainter::drawEllipse
void drawEllipse(const GeoDataCoordinates &centerPosition, qreal width, qreal height, bool isGeoProjected=false)
Draws an ellipse at the given position. The ellipse is placed with its center located at the given ce...
Definition: GeoPainter.cpp:289
Marble::GeoPainter::regionFromEllipse
QRegion regionFromEllipse(const GeoDataCoordinates &centerPosition, qreal width, qreal height, bool isGeoProjected=false, qreal strokeWidth=3) const
Creates a region for an ellipse at a given position.
Definition: GeoPainter.cpp:356
Marble::GeoPainterPrivate::m_viewport
const ViewportParams *const m_viewport
Definition: GeoPainter_p.h:48
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::ClipPainter::drawPolygon
void drawPolygon(const QPolygonF &, Qt::FillRule fillRule=Qt::OddEvenFill)
Definition: ClipPainter.cpp:136
Marble::ViewportParams::height
int height() const
Definition: ViewportParams.cpp:255
Marble::GeoPainterPrivate
Definition: GeoPainter_p.h:29
QPointF
Marble::GeoDataCoordinates::altitude
qreal altitude() const
return the altitude of the Point in meters
Definition: GeoDataCoordinates.cpp:1197
QPainter::drawRect
void drawRect(const QRectF &rectangle)
QVector::clear
void clear()
QPointF::x
qreal x() const
QPointF::y
qreal y() const
QPainterPath::addPolygon
void addPolygon(const QPolygonF &polygon)
Marble::GeoDataCoordinates::geoCoordinates
void geoCoordinates(qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
use this function to get the longitude and latitude with one call - use the unit parameter to switch ...
Definition: GeoDataCoordinates.cpp:715
Marble::ViewportParams::width
int width() const
Definition: ViewportParams.cpp:250
QPainter::drawPoint
void drawPoint(const QPointF &position)
QPainterPath::united
QPainterPath united(const QPainterPath &p) const
Marble::GeoPainter::drawRect
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:700
QPainter::boundingRect
QRectF boundingRect(const QRectF &rectangle, int flags, const QString &text)
QPainter::setPen
void setPen(const QColor &color)
QImage::width
int width() const
QPainter::drawEllipse
void drawEllipse(const QRectF &rectangle)
QPainterPath::lineTo
void lineTo(const QPointF &endPoint)
QPainter::drawPixmap
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
Marble::GeoDataPolygon
A polygon that can have "holes".
Definition: GeoDataPolygon.h:81
Marble::GeoPainter::drawRoundRect
void drawRoundRect(const GeoDataCoordinates &centerPosition, int width, int height, int xRnd=25, int yRnd=25)
Draws a rectangle with rounded corners at the given position. The rectangle is placed with its center...
Definition: GeoPainter.cpp:759
QString::isEmpty
bool isEmpty() const
Marble::GeoPainter::GeoPainter
GeoPainter(QPaintDevice *paintDevice, const ViewportParams *viewportParams, MapQuality mapQuality=NormalQuality)
Creates a new geo painter.
Definition: GeoPainter.cpp:176
Marble::GeoPainterPrivate::GeoPainterPrivate
GeoPainterPrivate(const ViewportParams *viewport, MapQuality mapQuality)
Definition: GeoPainter.cpp:33
QPainterPathStroker
GeoDataLineString.h
Marble::GeoPainter::regionFromPoint
QRegion regionFromPoint(const GeoDataCoordinates &position, qreal strokeWidth=3) const
Creates a region for a given geographic position.
Definition: GeoPainter.cpp:244
Marble::GeoPainterPrivate::~GeoPainterPrivate
~GeoPainterPrivate()
Definition: GeoPainter.cpp:40
Marble::ClipPainter
Definition: ClipPainter.h:51
Marble::GeoPainterPrivate::createLinearRingFromGeoRect
static GeoDataLinearRing createLinearRingFromGeoRect(const GeoDataCoordinates &centerCoordinates, qreal width, qreal height)
Definition: GeoPainter.cpp:123
Marble::GeoPainter::drawAnnotation
void drawAnnotation(const GeoDataCoordinates &position, const QString &text, QSizeF bubbleSize=QSizeF(130, 100), qreal bubbleOffsetX=-10, qreal bubbleOffsetY=-30, qreal xRnd=5, qreal yRnd=5)
Draws a text annotation that points to a geodesic position.
Definition: GeoPainter.cpp:197
QPainter::drawText
void drawText(const QPointF &position, const QString &text)
Marble::NoLabel
Definition: MarbleGlobal.h:111
QPainterPathStroker::createStroke
QPainterPath createStroke(const QPainterPath &path) const
Marble::ViewportParams::screenCoordinates
bool screenCoordinates(const qreal lon, const qreal lat, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the map.
Definition: ViewportParams.cpp:357
Marble::GeoDataCoordinates::normalizeLat
static qreal normalizeLat(qreal lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize latitude to always be in -M_PI / 2.
Definition: GeoDataCoordinates.cpp:799
QString
QList< QRegion >
GeoPainter.h
MarbleGlobal.h
Marble::GeoPainterPrivate::createAnnotationLayout
static void createAnnotationLayout(qreal x, qreal y, QSizeF bubbleSize, qreal bubbleOffsetX, qreal bubbleOffsetY, qreal xRnd, qreal yRnd, QPainterPath &path, QRectF &rect)
Definition: GeoPainter.cpp:45
QPainter::drawRoundRect
void drawRoundRect(const QRectF &r, int xRnd, int yRnd)
GeoPainter_p.h
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::GeoDataPolygon::outerBoundary
GeoDataLinearRing & outerBoundary()
Returns the outer boundary that is represented as a LinearRing.
Definition: GeoDataPolygon.cpp:123
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
QPixmap
Marble::GeoPainter::drawImage
void drawImage(const GeoDataCoordinates &centerPosition, const QImage &image)
Draws an image at the given position. The image is placed with its center located at the given center...
Definition: GeoPainter.cpp:428
Marble::GeoDataCoordinates::longitude
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Definition: GeoDataCoordinates.cpp:739
QPixmap::height
int height() const
GeoDataLinearRing.h
QFontMetrics::width
int width(const QString &text, int len) const
ViewportParams.h
This file contains the headers for ViewportParams.
QRectF::setTopLeft
void setTopLeft(const QPointF &position)
QImage
QPainter::viewport
QRect viewport() const
Marble::RespectLatitudeCircle
Definition: MarbleGlobal.h:33
Marble::GeoPainter::drawText
void drawText(const GeoDataCoordinates &position, const QString &text)
Draws the given text at a given geographic position. The text is drawn starting at the given position...
Definition: GeoPainter.cpp:264
Marble::GeoPainter::regionFromPolygon
QRegion regionFromPolygon(const GeoDataLinearRing &linearRing, Qt::FillRule fillRule, qreal strokeWidth=3) const
Creates a region for a given linear ring (a "polygon without holes").
Definition: GeoPainter.cpp:585
QPainterPath
Marble::GeoDataPolygon::innerBoundaries
QVector< GeoDataLinearRing > & innerBoundaries()
Returns a set of inner boundaries which are represented as LinearRings.
Definition: GeoDataPolygon.cpp:139
QRect::width
int width() const
QPainter::drawImage
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
GeoDataPoint.h
QPainter::drawPath
void drawPath(const QPainterPath &path)
QVector
QSizeF
Marble::ViewportParams::radius
int radius() const
Definition: ViewportParams.cpp:195
Marble::HighQuality
High quality (e.g. antialiasing for lines)
Definition: MarbleGlobal.h:86
Marble::ClipPainter::drawPolyline
void drawPolyline(const QPolygonF &)
Definition: ClipPainter.cpp:166
QVector::isEmpty
bool isEmpty() const
QRectF
QPainter::fontMetrics
QFontMetrics fontMetrics() const
QPointF::setX
void setX(qreal x)
QPointF::setY
void setY(qreal y)
Marble::ViewportParams::resolves
bool resolves(const GeoDataLatLonBox &latLonBox) const
Definition: ViewportParams.cpp:330
Marble::GeoPainterPrivate::m_mapQuality
const MapQuality m_mapQuality
Definition: GeoPainter_p.h:49
QImage::size
QSize size() const
Marble::GeoDataPoint::coordinates
const GeoDataCoordinates & coordinates() const
Definition: GeoDataPoint.cpp:81
QPen
QRectF::height
qreal height() const
QImage::height
int height() const
Marble::GeoPainter::mapQuality
MapQuality mapQuality() const
Returns the map quality.
Definition: GeoPainter.cpp:191
Marble::GeoPainter::drawPoint
void drawPoint(const GeoDataCoordinates &position)
Draws a single point at a given geographic position. The point is drawn using the painter's pen color...
Definition: GeoPainter.cpp:227
QSizeF::height
qreal height() const
Marble::Tessellate
Definition: MarbleGlobal.h:32
Marble::Spherical
Spherical projection.
Definition: MarbleGlobal.h:45
QSizeF::setHeight
void setHeight(qreal height)
QRectF::setBottomRight
void setBottomRight(const QPointF &position)
QPainterPath::arcTo
void arcTo(const QRectF &rectangle, qreal startAngle, qreal sweepLength)
QPainter::pen
const QPen & pen() const
Marble::GeoPainter::drawPixmap
void drawPixmap(const GeoDataCoordinates &centerPosition, const QPixmap &pixmap)
Draws a pixmap at the given position. The pixmap is placed with its center located at the given cente...
Definition: GeoPainter.cpp:452
Marble::GeoDataLineString::latLonAltBox
virtual const GeoDataLatLonAltBox & latLonAltBox() const
Returns the smallest latLonAltBox that contains the LineString.
Definition: GeoDataLineString.cpp:580
QSizeF::width
qreal width() const
QRegion
Marble::GeoDataLatLonBox
A class that defines a 2D bounding box for geographic data.
Definition: GeoDataLatLonBox.h:51
QPolygonF
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal