QGIS API Documentation  2.9.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsmaprenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmaprender.cpp - class for rendering map layer set
3  ----------------------
4  begin : January 2006
5  copyright : (C) 2006 by Martin Dobias
6  email : wonder.sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <cmath>
17 #include <cfloat>
18 
19 #include "qgscoordinatetransform.h"
20 #include "qgscrscache.h"
21 #include "qgslogger.h"
22 #include "qgsmessagelog.h"
23 #include "qgsmaprenderer.h"
24 #include "qgsscalecalculator.h"
25 #include "qgsmaptopixel.h"
26 #include "qgsmaplayer.h"
27 #include "qgsmaplayerregistry.h"
28 #include "qgsmapsettings.h"
29 #include "qgsdistancearea.h"
30 #include "qgsproject.h"
31 #include "qgsvectorlayer.h"
32 
33 #include <QDomDocument>
34 #include <QDomNode>
35 #include <QMutexLocker>
36 #include <QPainter>
37 #include <QListIterator>
38 #include <QSettings>
39 #include <QTime>
40 #include <QCoreApplication>
41 
43 {
44  mScale = 1.0;
45  mRotation = 0.0;
48 
49  mDrawing = false;
50  mOverview = false;
51 
52  // set default map units - we use WGS 84 thus use degrees
54 
55  mSize = QSize( 0, 0 );
56 
57  mProjectionsEnabled = false;
59 
61 
62  mLabelingEngine = NULL;
63 }
64 
66 {
67  delete mScaleCalculator;
68  delete mDistArea;
69  delete mDestCRS;
70  delete mLabelingEngine;
71 }
72 
74 {
75  return mExtent;
76 }
77 
79 {
81 }
82 
84 {
85  //remember the previous extent
87 
88  // Don't allow zooms where the current extent is so small that it
89  // can't be accurately represented using a double (which is what
90  // currentExtent uses). Excluding 0 avoids a divide by zero and an
91  // infinite loop when rendering to a new canvas. Excluding extents
92  // greater than 1 avoids doing unnecessary calculations.
93 
94  // The scheme is to compare the width against the mean x coordinate
95  // (and height against mean y coordinate) and only allow zooms where
96  // the ratio indicates that there is more than about 12 significant
97  // figures (there are about 16 significant figures in a double).
98 
99  if ( extent.width() > 0 &&
100  extent.height() > 0 &&
101  extent.width() < 1 &&
102  extent.height() < 1 )
103  {
104  // Use abs() on the extent to avoid the case where the extent is
105  // symmetrical about 0.
106  double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5;
107  double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5;
108 
109  double xRange = extent.width() / xMean;
110  double yRange = extent.height() / yMean;
111 
112  static const double minProportion = 1e-12;
113  if ( xRange < minProportion || yRange < minProportion )
114  return false;
115  }
116 
117  mExtent = extent;
118  if ( !extent.isEmpty() )
120 
121  emit extentsChanged();
122  return true;
123 }
124 
125 void QgsMapRenderer::setRotation( double rotation )
126 {
128  // TODO: adjust something ?
129 
130  emit rotationChanged( rotation );
131 }
132 
134 {
135  return mRotation;
136 }
137 
138 
139 void QgsMapRenderer::setOutputSize( QSize size, int dpi )
140 {
141  mSize = QSizeF( size.width(), size.height() );
142  mScaleCalculator->setDpi( dpi );
144 }
145 
146 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
147 {
148  mSize = size;
149  mScaleCalculator->setDpi( dpi );
151 }
152 
154 {
155  return mScaleCalculator->dpi();
156 }
157 
159 {
160  return mSize.toSize();
161 }
162 
164 {
165  return mSize;
166 }
167 
169 {
170  double myHeight = mSize.height();
171  double myWidth = mSize.width();
172 
173  QgsMapToPixel newCoordXForm;
174 
175  if ( !myWidth || !myHeight )
176  {
177  mScale = 1.0;
178  newCoordXForm.setParameters( 1, 0, 0, 0 );
179  return;
180  }
181 
182  // calculate the translation and scaling parameters
183  // mapUnitsPerPixel = map units per pixel
184  double mapUnitsPerPixelY = mExtent.height() / myHeight;
185  double mapUnitsPerPixelX = mExtent.width() / myWidth;
186  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
187 
188  // calculate the actual extent of the mapCanvas
189  double dxmin, dxmax, dymin, dymax, whitespace;
190 
191  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
192  {
193  dymin = mExtent.yMinimum();
194  dymax = mExtent.yMaximum();
195  whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
196  dxmin = mExtent.xMinimum() - whitespace;
197  dxmax = mExtent.xMaximum() + whitespace;
198  }
199  else
200  {
201  dxmin = mExtent.xMinimum();
202  dxmax = mExtent.xMaximum();
203  whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
204  dymin = mExtent.yMinimum() - whitespace;
205  dymax = mExtent.yMaximum() + whitespace;
206  }
207 
208  QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ) ).arg( qgsDoubleToString( mapUnitsPerPixelY ) ) );
209  QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( myWidth ) ).arg( qgsDoubleToString( myHeight ) ) );
210  QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ) ).arg( qgsDoubleToString( mExtent.height() ) ) );
212 
213  // update extent
214  mExtent.setXMinimum( dxmin );
215  mExtent.setXMaximum( dxmax );
216  mExtent.setYMinimum( dymin );
217  mExtent.setYMaximum( dymax );
218 
219  QgsDebugMsg( QString( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / myWidth ) ).arg( qgsDoubleToString( mExtent.height() / myHeight ) ) );
220 
221  QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / mMapUnitsPerPixel ) ).arg( qgsDoubleToString( mExtent.height() / mMapUnitsPerPixel ) ) );
222 
223  // update the scale
224  updateScale();
225 
226  QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
227 
228  newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
229  mRenderContext.setMapToPixel( newCoordXForm );
231 }
232 
233 
234 void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
235 {
236  //Lock render method for concurrent threads (e.g. from globe)
237  QMutexLocker renderLock( &mRenderMutex );
238 
239  QgsDebugMsg( "========== Rendering ==========" );
240 
241  if ( mExtent.isEmpty() )
242  {
243  QgsDebugMsg( "empty extent... not rendering" );
244  return;
245  }
246 
247  if ( mSize.width() == 1 && mSize.height() == 1 )
248  {
249  QgsDebugMsg( "size 1x1... not rendering" );
250  return;
251  }
252 
253  QPaintDevice* thePaintDevice = painter->device();
254  if ( !thePaintDevice )
255  {
256  return;
257  }
258 
259  // wait
260  if ( mDrawing )
261  {
262  QgsDebugMsg( "already rendering" );
263  QCoreApplication::processEvents();
264  }
265 
266  if ( mDrawing )
267  {
268  QgsDebugMsg( "still rendering - skipping" );
269  return;
270  }
271 
272  mDrawing = true;
273 
274  const QgsCoordinateTransform *ct;
275 
276 #ifdef QGISDEBUG
277  QgsDebugMsg( "Starting to render layer stack." );
278  QTime renderTime;
279  renderTime.start();
280 #endif
281 
282  if ( mOverview )
284 
285  mRenderContext.setPainter( painter );
287  //this flag is only for stopping during the current rendering progress,
288  //so must be false at every new render operation
290 
291  // set selection color
293  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
294  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
295  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
296  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
297  mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
298 
299  //calculate scale factor
300  //use the specified dpi and not those from the paint device
301  //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene)
302  double sceneDpi = mScaleCalculator->dpi();
303  double scaleFactor = 1.0;
305  {
306  if ( forceWidthScale )
307  {
308  scaleFactor = *forceWidthScale;
309  }
310  else
311  {
312  scaleFactor = sceneDpi / 25.4;
313  }
314  }
315  double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
317  {
318  mRenderContext.setRasterScaleFactor( rasterScaleFactor );
319  }
320  if ( mRenderContext.scaleFactor() != scaleFactor )
321  {
322  mRenderContext.setScaleFactor( scaleFactor );
323  }
325  {
326  //add map scale to render context
328  }
329  if ( mLastExtent != mExtent )
330  {
332  }
333 
335  if ( mLabelingEngine )
337 
338  // render all layers in the stack, starting at the base
339  QListIterator<QString> li( mLayerSet );
340  li.toBack();
341 
342  QgsRectangle r1, r2;
343 
344  while ( li.hasPrevious() )
345  {
347  {
348  break;
349  }
350 
351  // Store the painter in case we need to swap it out for the
352  // cache painter
353  QPainter * mypContextPainter = mRenderContext.painter();
354  // Flattened image for drawing when a blending mode is set
355  QImage * mypFlattenedImage = 0;
356 
357  QString layerId = li.previous();
358 
359  QgsDebugMsg( "Rendering at layer item " + layerId );
360 
361  // This call is supposed to cause the progress bar to
362  // advance. However, it seems that updating the progress bar is
363  // incompatible with having a QPainter active (the one that is
364  // passed into this function), as Qt produces a number of errors
365  // when try to do so. I'm (Gavin) not sure how to fix this, but
366  // added these comments and debug statement to help others...
367  QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
368 
369  //emit drawingProgress(myRenderCounter++, mLayerSet.size());
371 
372  if ( !ml )
373  {
374  QgsDebugMsg( "Layer not found in registry!" );
375  continue;
376  }
377 
378  QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
379  .arg( ml->name() )
380  .arg( ml->minimumScale() )
381  .arg( ml->maximumScale() )
382  .arg( ml->hasScaleBasedVisibility() )
383  .arg( ml->extent().toString() )
384  .arg( ml->blendMode() )
385  );
386 
388  {
389  // Set the QPainter composition mode so that this layer is rendered using
390  // the desired blending mode
391  mypContextPainter->setCompositionMode( ml->blendMode() );
392  }
393 
394  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview )
395  {
396  connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
397 
398  //
399  // Now do the call to the layer that actually does
400  // the rendering work!
401  //
402 
403  bool split = false;
404 
405  if ( hasCrsTransformEnabled() )
406  {
407  r1 = mExtent;
408  split = splitLayersExtent( ml, r1, r2 );
409  ct = transformation( ml );
411  QgsDebugMsg( " extent 1: " + r1.toString() );
412  QgsDebugMsg( " extent 2: " + r2.toString() );
413  if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
414  {
415  continue;
416  }
417  }
418  else
419  {
420  ct = NULL;
421  }
422 
424 
425  //decide if we have to scale the raster
426  //this is necessary in case QGraphicsScene is used
427  bool scaleRaster = false;
428  QgsMapToPixel rasterMapToPixel;
429  QgsMapToPixel bk_mapToPixel;
430 
431  if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 )
432  {
433  scaleRaster = true;
434  }
435 
436  QSettings mySettings;
437 
438  // If we are drawing with an alternative blending mode then we need to render to a separate image
439  // before compositing this on the map. This effectively flattens the layer and prevents
440  // blending occuring between objects on the layer
441  // (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
442  bool flattenedLayer = false;
444  {
445  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
446  if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver )
447  || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
448  || ( vl->layerTransparency() != 0 ) ) )
449  {
450  flattenedLayer = true;
451  mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
452  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
453  if ( mypFlattenedImage->isNull() )
454  {
455  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) );
456  emit drawError( ml );
457  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
458  return;
459  }
460  mypFlattenedImage->fill( 0 );
461  QPainter * mypPainter = new QPainter( mypFlattenedImage );
462  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
463  {
464  mypPainter->setRenderHint( QPainter::Antialiasing );
465  }
466  mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
467  mRenderContext.setPainter( mypPainter );
468  }
469  }
470 
471  // Per feature blending mode
473  {
474  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
475  if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
476  {
477  // set the painter to the feature blend mode, so that features drawn
478  // on this layer will interact and blend with each other
479  mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() );
480  }
481  }
482 
483  if ( scaleRaster )
484  {
485  bk_mapToPixel = mRenderContext.mapToPixel();
486  rasterMapToPixel = mRenderContext.mapToPixel();
488  rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
489  mRenderContext.setMapToPixel( rasterMapToPixel );
490  mRenderContext.painter()->save();
491  mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
492  }
493 
494  if ( !ml->draw( mRenderContext ) )
495  {
496  emit drawError( ml );
497  }
498  else
499  {
500  QgsDebugMsg( "Layer rendered without issues" );
501  }
502 
503  if ( split )
504  {
506  if ( !ml->draw( mRenderContext ) )
507  {
508  emit drawError( ml );
509  }
510  }
511 
512  if ( scaleRaster )
513  {
514  mRenderContext.setMapToPixel( bk_mapToPixel );
515  mRenderContext.painter()->restore();
516  }
517 
518  //apply layer transparency for vector layers
520  {
521  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
522  if ( vl->layerTransparency() != 0 )
523  {
524  // a layer transparency has been set, so update the alpha for the flattened layer
525  // by combining it with the layer transparency
526  QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
527  // use destination in composition mode to merge source's alpha with destination
528  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
529  mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(),
530  mRenderContext.painter()->device()->height(), transparentFillColor );
531  }
532  }
533 
534  if ( flattenedLayer )
535  {
536  // If we flattened this layer for alternate blend modes, composite it now
537  delete mRenderContext.painter();
538  mRenderContext.setPainter( mypContextPainter );
539  mypContextPainter->save();
540  mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
541  mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) );
542  mypContextPainter->restore();
543  delete mypFlattenedImage;
544  mypFlattenedImage = 0;
545  }
546 
547  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
548  }
549  else // layer not visible due to scale
550  {
551  QgsDebugMsg( "Layer not rendered because it is not within the defined "
552  "visibility scale range" );
553  }
554 
555  } // while (li.hasPrevious())
556 
557  QgsDebugMsg( "Done rendering map layers" );
558 
559  // Reset the composition mode before rendering the labels
560  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_SourceOver );
561 
562  if ( !mOverview )
563  {
564  // render all labels for vector layers in the stack, starting at the base
565  li.toBack();
566  while ( li.hasPrevious() )
567  {
569  {
570  break;
571  }
572 
573  QString layerId = li.previous();
574 
575  // TODO: emit drawingProgress((myRenderCounter++),zOrder.size());
577 
578  if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
579  {
580  // only make labels if the layer is visible
581  // after scale dep viewing settings are checked
582  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) )
583  {
584  bool split = false;
585 
586  if ( hasCrsTransformEnabled() )
587  {
588  QgsRectangle r1 = mExtent;
589  split = splitLayersExtent( ml, r1, r2 );
590  ct = transformation( ml );
592  }
593  else
594  {
595  ct = NULL;
596  }
597 
599 
600  ml->drawLabels( mRenderContext );
601  if ( split )
602  {
604  ml->drawLabels( mRenderContext );
605  }
606  }
607  }
608  }
609  } // if (!mOverview)
610 
611  // make sure progress bar arrives at 100%!
612  emit drawingProgress( 1, 1 );
613 
614  if ( mLabelingEngine )
615  {
616  // set correct extent
619 
622  }
623 
624  QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
625 
626  mDrawing = false;
627 }
628 
630 {
632 
633  // Since the map units have changed, force a recalculation of the scale.
634  updateScale();
635 
636  emit mapUnitsChanged();
637 }
638 
640 {
641  return mScaleCalculator->mapUnits();
642 }
643 
644 void QgsMapRenderer::onDrawingProgress( int current, int total )
645 {
646  Q_UNUSED( current );
647  Q_UNUSED( total );
648 }
649 
651 {
652  if ( mProjectionsEnabled != enabled )
653  {
654  mProjectionsEnabled = enabled;
655  QgsDebugMsg( "Adjusting DistArea projection on/off" );
656  mDistArea->setEllipsoidalMode( enabled );
659 
661  emit hasCrsTransformEnabled( enabled ); // deprecated
663 
664  emit hasCrsTransformEnabledChanged( enabled );
665  }
666 }
667 
669 {
670  return mProjectionsEnabled;
671 }
672 
673 void QgsMapRenderer::setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo, bool transformExtent )
674 {
675  QgsDebugMsg( "* Setting destCRS : = " + crs.toProj4() );
676  QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( crs.srsid() ) );
677  if ( *mDestCRS != crs )
678  {
679  if ( refreshCoordinateTransformInfo )
680  {
682  }
683  QgsRectangle rect;
684  if ( transformExtent && !mExtent.isEmpty() )
685  {
686  QgsCoordinateTransform transform( *mDestCRS, crs );
687  try
688  {
689  rect = transform.transformBoundingBox( mExtent );
690  }
691  catch ( QgsCsException &e )
692  {
693  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
694  }
695  }
696 
697  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
698  mDistArea->setSourceCrs( crs.srsid() );
699  *mDestCRS = crs;
701 
702  if ( !rect.isEmpty() )
703  {
704  setExtent( rect );
705  }
706 
707  emit destinationSrsChanged();
708  }
709 }
710 
712 {
713  QgsDebugMsgLevel( "* Returning destCRS", 3 );
714  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
715  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
716  return *mDestCRS;
717 }
718 
719 
721 {
722  bool split = false;
723 
724  if ( hasCrsTransformEnabled() )
725  {
726  try
727  {
728 #ifdef QGISDEBUG
729  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
730 #endif
731  // Split the extent into two if the source CRS is
732  // geographic and the extent crosses the split in
733  // geographic coordinates (usually +/- 180 degrees,
734  // and is assumed to be so here), and draw each
735  // extent separately.
736  static const double splitCoord = 180.0;
737 
738  const QgsCoordinateTransform *transform = transformation( layer );
739  if ( layer->crs().geographicFlag() )
740  {
741  // Note: ll = lower left point
742  // and ur = upper right point
743 
744  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
745  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
746 
747  if ( transform )
748  {
749  ll = transform->transform( ll.x(), ll.y(),
751  ur = transform->transform( ur.x(), ur.y(),
753  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
754  }
755 
756  if ( ll.x() > ur.x() )
757  {
758  r2 = extent;
759  extent.setXMinimum( splitCoord );
760  r2.setXMaximum( splitCoord );
761  split = true;
762  }
763  }
764  else // can't cross 180
765  {
766  if ( transform )
767  {
768  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
769  }
770  }
771  }
772  catch ( QgsCsException &cse )
773  {
774  Q_UNUSED( cse );
775  QgsDebugMsg( "Transform error caught" );
776  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
777  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
778  }
779  }
780  return split;
781 }
782 
784 {
785  //QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
786  //QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
787  //QgsDebugMsg( QString( "extent = " + extent.toString() ) );
788  if ( hasCrsTransformEnabled() )
789  {
790  try
791  {
792  const QgsCoordinateTransform *transform = transformation( theLayer );
793  if ( transform )
794  {
795  extent = transform->transformBoundingBox( extent );
796  }
797  }
798  catch ( QgsCsException &cse )
799  {
800  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
801  }
802  }
803 
804  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
805 
806  return extent;
807 }
808 
810 {
811 #if QGISDEBUG
812  const QgsCoordinateTransform *transform = transformation( theLayer );
813  QgsDebugMsg( QString( "layer sourceCrs = " + ( transform ? transform->sourceCrs().authid() : "none" ) ) );
814  QgsDebugMsg( QString( "layer destCRS = " + ( transform ? transform->destCRS().authid() : "none" ) ) );
815  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
816 #endif
817  if ( hasCrsTransformEnabled() )
818  {
819  try
820  {
821  const QgsCoordinateTransform *transform = transformation( theLayer );
822  if ( transform )
823  {
824  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
825  }
826  }
827  catch ( QgsCsException &cse )
828  {
829  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
830  }
831  }
832 
833  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
834 
835  return extent;
836 }
837 
839 {
840  if ( hasCrsTransformEnabled() )
841  {
842  try
843  {
844  const QgsCoordinateTransform *transform = transformation( theLayer );
845  if ( transform )
846  {
847  point = transform->transform( point, QgsCoordinateTransform::ForwardTransform );
848  }
849  }
850  catch ( QgsCsException &cse )
851  {
852  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
853  }
854  }
855  else
856  {
857  // leave point without transformation
858  }
859  return point;
860 }
861 
863 {
864  if ( hasCrsTransformEnabled() )
865  {
866  try
867  {
868  const QgsCoordinateTransform *transform = transformation( theLayer );
869  if ( transform )
870  {
871  rect = transform->transform( rect, QgsCoordinateTransform::ForwardTransform );
872  }
873  }
874  catch ( QgsCsException &cse )
875  {
876  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
877  }
878  }
879  else
880  {
881  // leave point without transformation
882  }
883  return rect;
884 }
885 
887 {
888  if ( hasCrsTransformEnabled() )
889  {
890  try
891  {
892  const QgsCoordinateTransform *transform = transformation( theLayer );
893  if ( transform )
894  point = transform->transform( point, QgsCoordinateTransform::ReverseTransform );
895  }
896  catch ( QgsCsException &cse )
897  {
898  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
899  }
900  }
901  else
902  {
903  // leave point without transformation
904  }
905  return point;
906 }
907 
909 {
910  if ( hasCrsTransformEnabled() )
911  {
912  try
913  {
914  const QgsCoordinateTransform *transform = transformation( theLayer );
915  if ( transform )
916  rect = transform->transform( rect, QgsCoordinateTransform::ReverseTransform );
917  }
918  catch ( QgsCsException &cse )
919  {
920  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
921  }
922  }
923  return rect;
924 }
925 
926 
928 {
929  QgsDebugMsg( "called." );
931 
932  // reset the map canvas extent since the extent may now be smaller
933  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
935 
936  // iterate through the map layers and test each layers extent
937  // against the current min and max values
938  QStringList::iterator it = mLayerSet.begin();
939  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
940  while ( it != mLayerSet.end() )
941  {
942  QgsMapLayer * lyr = registry->mapLayer( *it );
943  if ( lyr == NULL )
944  {
945  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) );
946  }
947  else
948  {
949  QgsDebugMsg( "Updating extent using " + lyr->name() );
950  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
951 
952  if ( lyr->extent().isNull() )
953  {
954  ++it;
955  continue;
956  }
957 
958  // Layer extents are stored in the coordinate system (CS) of the
959  // layer. The extent must be projected to the canvas CS
961 
962  QgsDebugMsg( "Output extent: " + extent.toString() );
963  mFullExtent.unionRect( extent );
964 
965  }
966  ++it;
967  }
968 
969  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
970  {
971  // If all of the features are at the one point, buffer the
972  // rectangle a bit. If they are all at zero, do something a bit
973  // more crude.
974 
975  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
976  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
977  {
978  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
979  }
980  else
981  {
982  const double padFactor = 1e-8;
983  double widthPad = mFullExtent.xMinimum() * padFactor;
984  double heightPad = mFullExtent.yMinimum() * padFactor;
985  double xmin = mFullExtent.xMinimum() - widthPad;
986  double xmax = mFullExtent.xMaximum() + widthPad;
987  double ymin = mFullExtent.yMinimum() - heightPad;
988  double ymax = mFullExtent.yMaximum() + heightPad;
989  mFullExtent.set( xmin, ymin, xmax, ymax );
990  }
991  }
992 
993  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
994 }
995 
997 {
999  return mFullExtent;
1000 }
1001 
1002 void QgsMapRenderer::setLayerSet( const QStringList& layers )
1003 {
1004  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
1005  mLayerSet = layers;
1006  updateFullExtent();
1007 }
1008 
1010 {
1011  return mLayerSet;
1012 }
1013 
1014 
1015 bool QgsMapRenderer::readXML( QDomNode & theNode )
1016 {
1017  QgsMapSettings tmpSettings;
1018  tmpSettings.readXML( theNode );
1019  //load coordinate transform into
1021  QDomElement layerCoordTransformInfoElem = theNode.firstChildElement( "layer_coordinate_transform_info" );
1022  if ( !layerCoordTransformInfoElem.isNull() )
1023  {
1024  QDomNodeList layerCoordinateTransformList = layerCoordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
1025  QDomElement layerCoordTransformElem;
1026  for ( int i = 0; i < layerCoordinateTransformList.size(); ++i )
1027  {
1028  layerCoordTransformElem = layerCoordinateTransformList.at( i ).toElement();
1029  QString layerId = layerCoordTransformElem.attribute( "layerid" );
1030  if ( layerId.isEmpty() )
1031  {
1032  continue;
1033  }
1034 
1036  lct.srcAuthId = layerCoordTransformElem.attribute( "srcAuthId" );
1037  lct.destAuthId = layerCoordTransformElem.attribute( "destAuthId" );
1038  lct.srcDatumTransform = layerCoordTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
1039  lct.destDatumTransform = layerCoordTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
1040  mLayerCoordinateTransformInfo.insert( layerId, lct );
1041  }
1042  }
1043 
1044 
1045  setMapUnits( tmpSettings.mapUnits() );
1046  setExtent( tmpSettings.extent() );
1048  setDestinationCrs( tmpSettings.destinationCrs() );
1049 
1050 
1051  return true;
1052 }
1053 
1054 bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc )
1055 {
1056  QgsMapSettings tmpSettings;
1057  tmpSettings.setOutputDpi( outputDpi() );
1058  tmpSettings.setOutputSize( outputSize() );
1059  tmpSettings.setMapUnits( mapUnits() );
1060  tmpSettings.setExtent( extent() );
1062  tmpSettings.setDestinationCrs( destinationCrs() );
1063 
1064  tmpSettings.writeXML( theNode, theDoc );
1065  // layer coordinate transform infos
1066  QDomElement layerCoordTransformInfo = theDoc.createElement( "layer_coordinate_transform_info" );
1067  QHash< QString, QgsLayerCoordinateTransform >::const_iterator coordIt = mLayerCoordinateTransformInfo.constBegin();
1068  for ( ; coordIt != mLayerCoordinateTransformInfo.constEnd(); ++coordIt )
1069  {
1070  QDomElement layerCoordTransformElem = theDoc.createElement( "layer_coordinate_transform" );
1071  layerCoordTransformElem.setAttribute( "layerid", coordIt.key() );
1072  layerCoordTransformElem.setAttribute( "srcAuthId", coordIt->srcAuthId );
1073  layerCoordTransformElem.setAttribute( "destAuthId", coordIt->destAuthId );
1074  layerCoordTransformElem.setAttribute( "srcDatumTransform", QString::number( coordIt->srcDatumTransform ) );
1075  layerCoordTransformElem.setAttribute( "destDatumTransform", QString::number( coordIt->destDatumTransform ) );
1076  layerCoordTransformInfo.appendChild( layerCoordTransformElem );
1077  }
1078  theNode.appendChild( layerCoordTransformInfo );
1079  return true;
1080 }
1081 
1083 {
1084  if ( mLabelingEngine )
1085  delete mLabelingEngine;
1086 
1087  mLabelingEngine = iface;
1088 }
1089 
1091 {
1092  if ( !layer || !mDestCRS )
1093  {
1094  return 0;
1095  }
1096 
1097  if ( layer->crs().authid() == mDestCRS->authid() )
1098  {
1099  return 0;
1100  }
1101 
1102  QHash< QString, QgsLayerCoordinateTransform >::const_iterator ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1103  if ( ctIt != mLayerCoordinateTransformInfo.constEnd()
1104  && ctIt->srcAuthId == layer->crs().authid()
1105  && ctIt->destAuthId == mDestCRS->authid() )
1106  {
1107  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1108  }
1109  else
1110  {
1111  emit datumTransformInfoRequested( layer, layer->crs().authid(), mDestCRS->authid() );
1112  }
1113 
1114  //still not present? get coordinate transformation with -1/-1 datum transform as default
1115  ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1116  if ( ctIt == mLayerCoordinateTransformInfo.constEnd()
1117  || ctIt->srcAuthId == layer->crs().authid()
1118  || ctIt->destAuthId == mDestCRS->authid()
1119  )
1120  {
1122  }
1123  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1124 }
1125 
1128 QPainter::CompositionMode QgsMapRenderer::getCompositionMode( const QgsMapRenderer::BlendMode &blendMode )
1129 {
1130  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1131  switch ( blendMode )
1132  {
1134  return QPainter::CompositionMode_SourceOver;
1136  return QPainter::CompositionMode_Lighten;
1138  return QPainter::CompositionMode_Screen;
1140  return QPainter::CompositionMode_ColorDodge;
1142  return QPainter::CompositionMode_Plus;
1144  return QPainter::CompositionMode_Darken;
1146  return QPainter::CompositionMode_Multiply;
1148  return QPainter::CompositionMode_ColorBurn;
1150  return QPainter::CompositionMode_Overlay;
1152  return QPainter::CompositionMode_SoftLight;
1154  return QPainter::CompositionMode_HardLight;
1156  return QPainter::CompositionMode_Difference;
1158  return QPainter::CompositionMode_Exclusion;
1160  return QPainter::CompositionMode_Source;
1162  return QPainter::CompositionMode_DestinationOver;
1164  return QPainter::CompositionMode_Clear;
1166  return QPainter::CompositionMode_Destination;
1168  return QPainter::CompositionMode_SourceIn;
1170  return QPainter::CompositionMode_DestinationIn;
1172  return QPainter::CompositionMode_SourceOut;
1174  return QPainter::CompositionMode_DestinationOut;
1176  return QPainter::CompositionMode_SourceAtop;
1178  return QPainter::CompositionMode_DestinationAtop;
1180  return QPainter::CompositionMode_Xor;
1181  default:
1182  QgsDebugMsg( QString( "Blend mode %1 mapped to SourceOver" ).arg( blendMode ) );
1183  return QPainter::CompositionMode_SourceOver;
1184  }
1185 }
1186 
1187 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::CompositionMode &blendMode )
1188 {
1189  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1190  switch ( blendMode )
1191  {
1192  case QPainter::CompositionMode_SourceOver:
1194  case QPainter::CompositionMode_Lighten:
1196  case QPainter::CompositionMode_Screen:
1198  case QPainter::CompositionMode_ColorDodge:
1200  case QPainter::CompositionMode_Plus:
1202  case QPainter::CompositionMode_Darken:
1204  case QPainter::CompositionMode_Multiply:
1206  case QPainter::CompositionMode_ColorBurn:
1208  case QPainter::CompositionMode_Overlay:
1210  case QPainter::CompositionMode_SoftLight:
1212  case QPainter::CompositionMode_HardLight:
1214  case QPainter::CompositionMode_Difference:
1216  case QPainter::CompositionMode_Exclusion:
1218  case QPainter::CompositionMode_Source:
1220  case QPainter::CompositionMode_DestinationOver:
1222  case QPainter::CompositionMode_Clear:
1224  case QPainter::CompositionMode_Destination:
1226  case QPainter::CompositionMode_SourceIn:
1228  case QPainter::CompositionMode_DestinationIn:
1230  case QPainter::CompositionMode_SourceOut:
1232  case QPainter::CompositionMode_DestinationOut:
1234  case QPainter::CompositionMode_SourceAtop:
1236  case QPainter::CompositionMode_DestinationAtop:
1238  case QPainter::CompositionMode_Xor:
1239  return QgsMapRenderer::BlendXor;
1240  default:
1241  QgsDebugMsg( QString( "Composition mode %1 mapped to Normal" ).arg( blendMode ) );
1243  }
1244 }
1245 
1246 Q_GUI_EXPORT extern int qt_defaultDpiX();
1247 
1249 {
1250  // make sure the settings object is up-to-date
1258  return mMapSettings;
1259 }
1260 
1261 void QgsMapRenderer::addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform, int destDatumTransform )
1262 {
1264  lt.srcAuthId = srcAuthId;
1265  lt.destAuthId = destAuthId;
1266  lt.srcDatumTransform = srcDatumTransform;
1267  lt.destDatumTransform = destDatumTransform;
1268  mLayerCoordinateTransformInfo.insert( layerId, lt );
1269 }
1270 
1272 {
1274 }
1275 
1276 bool QgsMapRenderer::mDrawing = false;
const QgsMapSettings & mapSettings()
bridge to QgsMapSettings
virtual void exit()=0
called when we're done with rendering
void setMapUnits(QGis::UnitType mapUnits)
Set the map units.
const QgsCoordinateReferenceSystem & sourceCrs() const
void unionRect(const QgsRectangle &rect)
updates rectangle to include passed argument
void rotationChanged(double)
emitted when the current rotation gets changed
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
virtual Q_DECL_DEPRECATED void init(QgsMapRenderer *mp)=0
called when we're going to start with rendering
void setRenderingStopped(bool stopped)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void clearLayerCoordinateTransforms()
void render(QPainter *painter, double *forceWidthScale=0)
starts rendering
void setLabelingEngine(QgsLabelingEngineInterface *iface)
Set labeling engine.
bool isEmpty() const
test if rectangle is empty.
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:92
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
virtual void drawLabels(QgsRenderContext &rendererContext)
Draw labels.
void drawError(QgsMapLayer *)
emitted when layer's draw() returned false
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:163
void readXML(QDomNode &theNode)
OutputUnits mOutputUnits
Output units.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:188
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
void setOutputDpi(int dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
UnitType
Map units that qgis supports.
Definition: qgis.h:229
bool mProjectionsEnabled
detemines whether on the fly projection support is enabled
QgsRectangle mLastExtent
Last extent to we drew so we know if we can used layer render caching or not.
void setSourceCrs(long srsid)
sets source spatial reference system (by QGIS CRS)
double rendererScale() const
QgsScaleCalculator * mScaleCalculator
scale calculator
QgsRectangle extent() const
returns current extent
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
void setRendererScale(double scale)
static QgsMapLayerRegistry * instance()
Definition: qgssingleton.h:23
float minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:461
void drawingProgress(int current, int total)
~QgsMapRenderer()
destructor
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
Q_DECL_DEPRECATED void setParameters(double mapUnitsPerPixel, double xmin, double ymin, double height)
QGis::UnitType mapUnits() const
Returns current map units.
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
void setProjectionsEnabled(bool enabled)
sets whether to use projections for this layer set
static bool mDrawing
indicates drawing in progress
bool splitLayersExtent(QgsMapLayer *layer, QgsRectangle &extent, QgsRectangle &r2)
Convenience function to project an extent into the layer source CRS, but also split it into two exten...
QgsPoint transform(const QgsPoint &p, TransformDirection direction=ForwardTransform) const
double scaleFactor() const
void setLayerSet(const QStringList &layers)
change current layer set
double outputDpi()
accessor for output dpi
Q_DECL_DEPRECATED void setYMaximum(double yMax)
Set maximum y value.
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point)
transform point coordinates from output CRS to layer's CRS
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
QgsRectangle outputExtentToLayerExtent(QgsMapLayer *theLayer, QgsRectangle extent)
transform bounding box from output CRS to layer's CRS
void setExtent(const QgsRectangle &extent)
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=0) const
const QgsCoordinateTransform * transformation(const QgsMapLayer *layer) const
QgsRectangle mExtent
current extent to be drawn
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QgsMapRenderer()
constructor
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point)
transform point coordinates from layer's CRS to output CRS
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
The QgsMapSettings class contains configuration for rendering of the map.
void setCoordinateTransform(const QgsCoordinateTransform *t)
Sets coordinate transformation.
QSize outputSize()
accessor for output size
virtual bool draw(QgsRenderContext &rendererContext)
This is the method that does the actual work of drawing the layer onto a paint device.
bool useAdvancedEffects() const
Returns true if advanced effects such as blend modes such be used.
double mRotation
Map rotation.
const QString & name() const
Get the display name of the layer.
QMutex mRenderMutex
Locks rendering loop for concurrent draws.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:34
const QgsCoordinateTransform * transform(const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
Returns coordinate transformation.
Definition: qgscrscache.cpp:32
void setSelectionColor(const QColor &color)
void extentsChanged()
emitted when the current extent gets changed
QPainter::CompositionMode blendMode() const
Read blend mode for layer.
QgsCoordinateReferenceSystem * mDestCRS
destination spatial reference system of the projection
void setScaleFactor(double factor)
QgsDistanceArea * mDistArea
tool for measuring
QPainter::CompositionMode featureBlendMode() const
Read blend mode for layer.
double calculate(const QgsRectangle &mapExtent, int canvasWidth)
Calculate the scale denominator.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
void adjustExtentToSize()
adjust extent to fit the pixmap size
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:193
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:178
void hasCrsTransformEnabledChanged(bool flag)
This signal is emitted when CRS transformation is enabled/disabled.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
bool renderingStopped() const
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
void setMapUnits(QGis::UnitType u)
Set units of map's geographical coordinates - used for scale calculation.
float maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:168
void setDrawEditingInformation(bool b)
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
Q_GUI_EXPORT int qt_defaultDpiX()
void setMapUnits(QGis::UnitType u)
const long GEOCRS_ID
Magic number for a geographic coord sys in QGIS srs.db tbl_srs.srs_id.
Definition: qgis.h:407
void destinationSrsChanged()
void setPainter(QPainter *p)
double rasterScaleFactor() const
QString id() const
Get this layer's unique ID, this ID is used to access this layer from map layer registry.
Definition: qgsmaplayer.cpp:98
Reads and writes project states.
Definition: qgsproject.h:67
bool mOverview
indicates whether it's map image for overview
double rotation() const
returns current rotation in clockwise degrees
double mapUnitsPerPixel() const
Return current map units per pixel.
QGis::UnitType mapUnits() const
Get units of map's geographical coordinates - used for scale calculation.
void setOutputSize(QSize size, int dpi)
void mapUnitsChanged()
A class to represent a point.
Definition: qgspoint.h:63
void updateFullExtent()
updates extent of the layer set
This class tracks map layers that are currently loaded and provides a means to fetch a pointer to a m...
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs, bool refreshCoordinateTransformInfo=true, bool transformExtent=true)
sets destination coordinate reference system
double rasterScaleFactor
Definition: qgssvgcache.cpp:80
void setRotation(double degrees)
sets rotation value in clockwise degrees
QString qgsDoubleToString(const double &a, const int &precision=17)
Definition: qgis.h:339
double dpi()
Accessor for dpi used in scale calculations.
bool writeXML(QDomNode &theNode, QDomDocument &theDoc)
write settings
Calculates scale for a given combination of canvas size, map extent, and monitor dpi.
int layerTransparency() const
Read transparency for layer.
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode &blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:462
General purpose distance and area calculator.
QgsRectangle fullExtent()
returns current extent of layer set
QString what() const
Definition: qgsexception.h:35
QgsMapSettings mMapSettings
map settings - used only for export in mapSettings() for use in classes that deal with QgsMapSettings...
QPainter * painter()
virtual void drawLabeling(QgsRenderContext &context)=0
called when the map is drawn and labels should be placed
void setOutputSize(const QSize &size)
Set the size of the resulting map image.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:173
Q_DECL_DEPRECATED void onDrawingProgress(int current, int total)
void setLabelingEngine(QgsLabelingEngineInterface *iface)
double mScale
Map scale denominator at its current zoom level.
QHash< QString, QgsLayerCoordinateTransform > mLayerCoordinateTransformInfo
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:351
Class for storing a coordinate reference system (CRS)
void setExtent(const QgsRectangle &rect)
Set coordinates of the rectangle which should be rendered.
void setMapToPixel(const QgsMapToPixel &mtp)
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
Class for doing transforms between two map coordinate systems.
const QgsMapToPixel & mapToPixel() const
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
QgsMapLayer * mapLayer(QString theLayerId)
Retrieve a pointer to a loaded layer by id.
void updateScale()
Recalculate the map scale.
QStringList mLayerSet
stores array of layers to be rendered (identified by string)
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode &blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
void setRasterScaleFactor(double factor)
void datumTransformInfoRequested(const QgsMapLayer *ml, const QString &srcAuthId, const QString &destAuthId) const
Notifies higher level components to show the datum transform dialog and add a QgsLayerCoordinateTrans...
Custom exception class for Coordinate Reference System related exceptions.
double mMapUnitsPerPixel
map units per pixel
Labeling engine interface.
QgsRenderContext mRenderContext
Encapsulates context of rendering.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:198
void setMapUnitsPerPixel(double mapUnitsPerPixel)
const QgsCoordinateReferenceSystem & destCRS() const
virtual QgsRectangle extent()
Return the extent of the layer.
QGis::UnitType mapUnits() const
Represents a vector layer which manages a vector based data sets.
double size
Definition: qgssvgcache.cpp:77
QgsLabelingEngineInterface * mLabelingEngine
Labeling engine (NULL by default)
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
bool readXML(QDomNode &theNode)
read settings
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:183
QStringList & layerSet()
returns current layer set
QgsRectangle mFullExtent
full extent of the layer set
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:158
QgsRectangle transformBoundingBox(const QgsRectangle &theRect, TransformDirection direction=ForwardTransform, const bool handle180Crossover=false) const
void setEllipsoidalMode(bool flag)
sets whether coordinates must be projected to ellipsoid before measuring
QgsRectangle layerExtentToOutputExtent(QgsMapLayer *theLayer, QgsRectangle extent)
transform bounding box from layer's CRS to output CRS
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:203
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
#define tr(sourceText)
void writeXML(QDomNode &theNode, QDomDocument &theDoc)