QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups 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;
47 
48  mDrawing = false;
49  mOverview = false;
50 
51  // set default map units - we use WGS 84 thus use degrees
53 
54  mSize = QSize( 0, 0 );
55 
56  mProjectionsEnabled = false;
58 
60 
61  mLabelingEngine = NULL;
62 }
63 
65 {
66  delete mScaleCalculator;
67  delete mDistArea;
68  delete mDestCRS;
69  delete mLabelingEngine;
70 }
71 
73 {
74  return mExtent;
75 }
76 
78 {
80 }
81 
83 {
84  //remember the previous extent
86 
87  // Don't allow zooms where the current extent is so small that it
88  // can't be accurately represented using a double (which is what
89  // currentExtent uses). Excluding 0 avoids a divide by zero and an
90  // infinite loop when rendering to a new canvas. Excluding extents
91  // greater than 1 avoids doing unnecessary calculations.
92 
93  // The scheme is to compare the width against the mean x coordinate
94  // (and height against mean y coordinate) and only allow zooms where
95  // the ratio indicates that there is more than about 12 significant
96  // figures (there are about 16 significant figures in a double).
97 
98  if ( extent.width() > 0 &&
99  extent.height() > 0 &&
100  extent.width() < 1 &&
101  extent.height() < 1 )
102  {
103  // Use abs() on the extent to avoid the case where the extent is
104  // symmetrical about 0.
105  double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5;
106  double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5;
107 
108  double xRange = extent.width() / xMean;
109  double yRange = extent.height() / yMean;
110 
111  static const double minProportion = 1e-12;
112  if ( xRange < minProportion || yRange < minProportion )
113  return false;
114  }
115 
116  mExtent = extent;
117  if ( !extent.isEmpty() )
119 
120  emit extentsChanged();
121  return true;
122 }
123 
124 
125 
126 void QgsMapRenderer::setOutputSize( QSize size, int dpi )
127 {
128  mSize = QSizeF( size.width(), size.height() );
129  mScaleCalculator->setDpi( dpi );
131 }
132 
133 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
134 {
135  mSize = size;
136  mScaleCalculator->setDpi( dpi );
138 }
139 
141 {
142  return mScaleCalculator->dpi();
143 }
144 
146 {
147  return mSize.toSize();
148 }
149 
151 {
152  return mSize;
153 }
154 
156 {
157  double myHeight = mSize.height();
158  double myWidth = mSize.width();
159 
160  QgsMapToPixel newCoordXForm;
161 
162  if ( !myWidth || !myHeight )
163  {
164  mScale = 1.0;
165  newCoordXForm.setParameters( 0, 0, 0, 0 );
166  return;
167  }
168 
169  // calculate the translation and scaling parameters
170  // mapUnitsPerPixel = map units per pixel
171  double mapUnitsPerPixelY = mExtent.height() / myHeight;
172  double mapUnitsPerPixelX = mExtent.width() / myWidth;
173  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
174 
175  // calculate the actual extent of the mapCanvas
176  double dxmin, dxmax, dymin, dymax, whitespace;
177 
178  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
179  {
180  dymin = mExtent.yMinimum();
181  dymax = mExtent.yMaximum();
182  whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
183  dxmin = mExtent.xMinimum() - whitespace;
184  dxmax = mExtent.xMaximum() + whitespace;
185  }
186  else
187  {
188  dxmin = mExtent.xMinimum();
189  dxmax = mExtent.xMaximum();
190  whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
191  dymin = mExtent.yMinimum() - whitespace;
192  dymax = mExtent.yMaximum() + whitespace;
193  }
194 
195  QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ) ).arg( qgsDoubleToString( mapUnitsPerPixelY ) ) );
196  QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( myWidth ) ).arg( qgsDoubleToString( myHeight ) ) );
197  QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ) ).arg( qgsDoubleToString( mExtent.height() ) ) );
199 
200  // update extent
201  mExtent.setXMinimum( dxmin );
202  mExtent.setXMaximum( dxmax );
203  mExtent.setYMinimum( dymin );
204  mExtent.setYMaximum( dymax );
205 
206  QgsDebugMsg( QString( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / myWidth ) ).arg( qgsDoubleToString( mExtent.height() / myHeight ) ) );
207 
208  QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / mMapUnitsPerPixel ) ).arg( qgsDoubleToString( mExtent.height() / mMapUnitsPerPixel ) ) );
209 
210  // update the scale
211  updateScale();
212 
213  QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
214 
215  newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
216  mRenderContext.setMapToPixel( newCoordXForm );
218 }
219 
220 
221 void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
222 {
223  //Lock render method for concurrent threads (e.g. from globe)
224  QMutexLocker renderLock( &mRenderMutex );
225 
226  QgsDebugMsg( "========== Rendering ==========" );
227 
228  if ( mExtent.isEmpty() )
229  {
230  QgsDebugMsg( "empty extent... not rendering" );
231  return;
232  }
233 
234  if ( mSize.width() == 1 && mSize.height() == 1 )
235  {
236  QgsDebugMsg( "size 1x1... not rendering" );
237  return;
238  }
239 
240  QPaintDevice* thePaintDevice = painter->device();
241  if ( !thePaintDevice )
242  {
243  return;
244  }
245 
246  // wait
247  if ( mDrawing )
248  {
249  QgsDebugMsg( "already rendering" );
250  QCoreApplication::processEvents();
251  }
252 
253  if ( mDrawing )
254  {
255  QgsDebugMsg( "still rendering - skipping" );
256  return;
257  }
258 
259  mDrawing = true;
260 
261  const QgsCoordinateTransform *ct;
262 
263 #ifdef QGISDEBUG
264  QgsDebugMsg( "Starting to render layer stack." );
265  QTime renderTime;
266  renderTime.start();
267 #endif
268 
269  if ( mOverview )
271 
272  mRenderContext.setPainter( painter );
274  //this flag is only for stopping during the current rendering progress,
275  //so must be false at every new render operation
277 
278  // set selection color
280  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
281  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
282  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
283  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
284  mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
285 
286  //calculate scale factor
287  //use the specified dpi and not those from the paint device
288  //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene)
289  double sceneDpi = mScaleCalculator->dpi();
290  double scaleFactor = 1.0;
292  {
293  if ( forceWidthScale )
294  {
295  scaleFactor = *forceWidthScale;
296  }
297  else
298  {
299  scaleFactor = sceneDpi / 25.4;
300  }
301  }
302  double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
304  {
305  mRenderContext.setRasterScaleFactor( rasterScaleFactor );
306  }
307  if ( mRenderContext.scaleFactor() != scaleFactor )
308  {
309  mRenderContext.setScaleFactor( scaleFactor );
310  }
312  {
313  //add map scale to render context
315  }
316  if ( mLastExtent != mExtent )
317  {
319  }
320 
322  if ( mLabelingEngine )
324 
325  // render all layers in the stack, starting at the base
326  QListIterator<QString> li( mLayerSet );
327  li.toBack();
328 
329  QgsRectangle r1, r2;
330 
331  while ( li.hasPrevious() )
332  {
334  {
335  break;
336  }
337 
338  // Store the painter in case we need to swap it out for the
339  // cache painter
340  QPainter * mypContextPainter = mRenderContext.painter();
341  // Flattened image for drawing when a blending mode is set
342  QImage * mypFlattenedImage = 0;
343 
344  QString layerId = li.previous();
345 
346  QgsDebugMsg( "Rendering at layer item " + layerId );
347 
348  // This call is supposed to cause the progress bar to
349  // advance. However, it seems that updating the progress bar is
350  // incompatible with having a QPainter active (the one that is
351  // passed into this function), as Qt produces a number of errors
352  // when try to do so. I'm (Gavin) not sure how to fix this, but
353  // added these comments and debug statement to help others...
354  QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
355 
356  //emit drawingProgress(myRenderCounter++, mLayerSet.size());
358 
359  if ( !ml )
360  {
361  QgsDebugMsg( "Layer not found in registry!" );
362  continue;
363  }
364 
365  QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
366  .arg( ml->name() )
367  .arg( ml->minimumScale() )
368  .arg( ml->maximumScale() )
369  .arg( ml->hasScaleBasedVisibility() )
370  .arg( ml->extent().toString() )
371  .arg( ml->blendMode() )
372  );
373 
375  {
376  // Set the QPainter composition mode so that this layer is rendered using
377  // the desired blending mode
378  mypContextPainter->setCompositionMode( ml->blendMode() );
379  }
380 
381  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview )
382  {
383  connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
384 
385  //
386  // Now do the call to the layer that actually does
387  // the rendering work!
388  //
389 
390  bool split = false;
391 
392  if ( hasCrsTransformEnabled() )
393  {
394  r1 = mExtent;
395  split = splitLayersExtent( ml, r1, r2 );
396  ct = transformation( ml );
398  QgsDebugMsg( " extent 1: " + r1.toString() );
399  QgsDebugMsg( " extent 2: " + r2.toString() );
400  if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
401  {
402  continue;
403  }
404  }
405  else
406  {
407  ct = NULL;
408  }
409 
411 
412  //decide if we have to scale the raster
413  //this is necessary in case QGraphicsScene is used
414  bool scaleRaster = false;
415  QgsMapToPixel rasterMapToPixel;
416  QgsMapToPixel bk_mapToPixel;
417 
418  if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 )
419  {
420  scaleRaster = true;
421  }
422 
423  QSettings mySettings;
424 
425  // If we are drawing with an alternative blending mode then we need to render to a separate image
426  // before compositing this on the map. This effectively flattens the layer and prevents
427  // blending occuring between objects on the layer
428  // (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
429  bool flattenedLayer = false;
431  {
432  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
433  if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver )
434  || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
435  || ( vl->layerTransparency() != 0 ) ) )
436  {
437  flattenedLayer = true;
438  mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
439  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
440  if ( mypFlattenedImage->isNull() )
441  {
442  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) );
443  emit drawError( ml );
444  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
445  return;
446  }
447  mypFlattenedImage->fill( 0 );
448  QPainter * mypPainter = new QPainter( mypFlattenedImage );
449  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
450  {
451  mypPainter->setRenderHint( QPainter::Antialiasing );
452  }
453  mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
454  mRenderContext.setPainter( mypPainter );
455  }
456  }
457 
458  // Per feature blending mode
460  {
461  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
462  if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
463  {
464  // set the painter to the feature blend mode, so that features drawn
465  // on this layer will interact and blend with each other
466  mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() );
467  }
468  }
469 
470  if ( scaleRaster )
471  {
472  bk_mapToPixel = mRenderContext.mapToPixel();
473  rasterMapToPixel = mRenderContext.mapToPixel();
475  rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
476  mRenderContext.setMapToPixel( rasterMapToPixel );
477  mRenderContext.painter()->save();
478  mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
479  }
480 
481  if ( !ml->draw( mRenderContext ) )
482  {
483  emit drawError( ml );
484  }
485  else
486  {
487  QgsDebugMsg( "Layer rendered without issues" );
488  }
489 
490  if ( split )
491  {
493  if ( !ml->draw( mRenderContext ) )
494  {
495  emit drawError( ml );
496  }
497  }
498 
499  if ( scaleRaster )
500  {
501  mRenderContext.setMapToPixel( bk_mapToPixel );
502  mRenderContext.painter()->restore();
503  }
504 
505  //apply layer transparency for vector layers
507  {
508  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
509  if ( vl->layerTransparency() != 0 )
510  {
511  // a layer transparency has been set, so update the alpha for the flattened layer
512  // by combining it with the layer transparency
513  QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
514  // use destination in composition mode to merge source's alpha with destination
515  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
516  mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(),
517  mRenderContext.painter()->device()->height(), transparentFillColor );
518  }
519  }
520 
521  if ( flattenedLayer )
522  {
523  // If we flattened this layer for alternate blend modes, composite it now
524  delete mRenderContext.painter();
525  mRenderContext.setPainter( mypContextPainter );
526  mypContextPainter->save();
527  mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
528  mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) );
529  mypContextPainter->restore();
530  delete mypFlattenedImage;
531  mypFlattenedImage = 0;
532  }
533 
534  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
535  }
536  else // layer not visible due to scale
537  {
538  QgsDebugMsg( "Layer not rendered because it is not within the defined "
539  "visibility scale range" );
540  }
541 
542  } // while (li.hasPrevious())
543 
544  QgsDebugMsg( "Done rendering map layers" );
545 
546  // Reset the composition mode before rendering the labels
547  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_SourceOver );
548 
549  if ( !mOverview )
550  {
551  // render all labels for vector layers in the stack, starting at the base
552  li.toBack();
553  while ( li.hasPrevious() )
554  {
556  {
557  break;
558  }
559 
560  QString layerId = li.previous();
561 
562  // TODO: emit drawingProgress((myRenderCounter++),zOrder.size());
564 
565  if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
566  {
567  // only make labels if the layer is visible
568  // after scale dep viewing settings are checked
569  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) )
570  {
571  bool split = false;
572 
573  if ( hasCrsTransformEnabled() )
574  {
575  QgsRectangle r1 = mExtent;
576  split = splitLayersExtent( ml, r1, r2 );
577  ct = transformation( ml );
579  }
580  else
581  {
582  ct = NULL;
583  }
584 
586 
587  ml->drawLabels( mRenderContext );
588  if ( split )
589  {
591  ml->drawLabels( mRenderContext );
592  }
593  }
594  }
595  }
596  } // if (!mOverview)
597 
598  // make sure progress bar arrives at 100%!
599  emit drawingProgress( 1, 1 );
600 
601  if ( mLabelingEngine )
602  {
603  // set correct extent
606 
609  }
610 
611  QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
612 
613  mDrawing = false;
614 }
615 
617 {
619 
620  // Since the map units have changed, force a recalculation of the scale.
621  updateScale();
622 
623  emit mapUnitsChanged();
624 }
625 
627 {
628  return mScaleCalculator->mapUnits();
629 }
630 
631 void QgsMapRenderer::onDrawingProgress( int current, int total )
632 {
633  Q_UNUSED( current );
634  Q_UNUSED( total );
635 }
636 
638 {
639  if ( mProjectionsEnabled != enabled )
640  {
641  mProjectionsEnabled = enabled;
642  QgsDebugMsg( "Adjusting DistArea projection on/off" );
643  mDistArea->setEllipsoidalMode( enabled );
646 
648  emit hasCrsTransformEnabled( enabled ); // deprecated
650 
651  emit hasCrsTransformEnabledChanged( enabled );
652  }
653 }
654 
656 {
657  return mProjectionsEnabled;
658 }
659 
660 void QgsMapRenderer::setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo, bool transformExtent )
661 {
662  QgsDebugMsg( "* Setting destCRS : = " + crs.toProj4() );
663  QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( crs.srsid() ) );
664  if ( *mDestCRS != crs )
665  {
666  if ( refreshCoordinateTransformInfo )
667  {
669  }
670  QgsRectangle rect;
671  if ( transformExtent && !mExtent.isEmpty() )
672  {
673  QgsCoordinateTransform transform( *mDestCRS, crs );
674  rect = transform.transformBoundingBox( mExtent );
675  }
676 
677  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
678  mDistArea->setSourceCrs( crs.srsid() );
679  *mDestCRS = crs;
681 
682  if ( !rect.isEmpty() )
683  {
684  setExtent( rect );
685  }
686 
687  emit destinationSrsChanged();
688  }
689 }
690 
692 {
693  QgsDebugMsgLevel( "* Returning destCRS", 3 );
694  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
695  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
696  return *mDestCRS;
697 }
698 
699 
701 {
702  bool split = false;
703 
704  if ( hasCrsTransformEnabled() )
705  {
706  try
707  {
708 #ifdef QGISDEBUG
709  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
710 #endif
711  // Split the extent into two if the source CRS is
712  // geographic and the extent crosses the split in
713  // geographic coordinates (usually +/- 180 degrees,
714  // and is assumed to be so here), and draw each
715  // extent separately.
716  static const double splitCoord = 180.0;
717 
718  const QgsCoordinateTransform *transform = transformation( layer );
719  if ( layer->crs().geographicFlag() )
720  {
721  // Note: ll = lower left point
722  // and ur = upper right point
723 
724  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
725  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
726 
727  if ( transform )
728  {
729  ll = transform->transform( ll.x(), ll.y(),
731  ur = transform->transform( ur.x(), ur.y(),
733  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
734  }
735 
736  if ( ll.x() > ur.x() )
737  {
738  r2 = extent;
739  extent.setXMinimum( splitCoord );
740  r2.setXMaximum( splitCoord );
741  split = true;
742  }
743  }
744  else // can't cross 180
745  {
746  if ( transform )
747  {
748  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
749  }
750  }
751  }
752  catch ( QgsCsException &cse )
753  {
754  Q_UNUSED( cse );
755  QgsDebugMsg( "Transform error caught" );
756  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
757  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
758  }
759  }
760  return split;
761 }
762 
764 {
765  //QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
766  //QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
767  //QgsDebugMsg( QString( "extent = " + extent.toString() ) );
768  if ( hasCrsTransformEnabled() )
769  {
770  try
771  {
772  const QgsCoordinateTransform *transform = transformation( theLayer );
773  if ( transform )
774  {
775  extent = transform->transformBoundingBox( extent );
776  }
777  }
778  catch ( QgsCsException &cse )
779  {
780  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
781  }
782  }
783 
784  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
785 
786  return extent;
787 }
788 
790 {
791 #if QGISDEBUG
792  const QgsCoordinateTransform *transform = transformation( theLayer );
793  QgsDebugMsg( QString( "layer sourceCrs = " + ( transform ? transform->sourceCrs().authid() : "none" ) ) );
794  QgsDebugMsg( QString( "layer destCRS = " + ( transform ? transform->destCRS().authid() : "none" ) ) );
795  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
796 #endif
797  if ( hasCrsTransformEnabled() )
798  {
799  try
800  {
801  const QgsCoordinateTransform *transform = transformation( theLayer );
802  if ( transform )
803  {
804  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
805  }
806  }
807  catch ( QgsCsException &cse )
808  {
809  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
810  }
811  }
812 
813  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
814 
815  return extent;
816 }
817 
819 {
820  if ( hasCrsTransformEnabled() )
821  {
822  try
823  {
824  const QgsCoordinateTransform *transform = transformation( theLayer );
825  if ( transform )
826  {
827  point = transform->transform( point, QgsCoordinateTransform::ForwardTransform );
828  }
829  }
830  catch ( QgsCsException &cse )
831  {
832  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
833  }
834  }
835  else
836  {
837  // leave point without transformation
838  }
839  return point;
840 }
841 
843 {
844  if ( hasCrsTransformEnabled() )
845  {
846  try
847  {
848  const QgsCoordinateTransform *transform = transformation( theLayer );
849  if ( transform )
850  {
851  rect = transform->transform( rect, QgsCoordinateTransform::ForwardTransform );
852  }
853  }
854  catch ( QgsCsException &cse )
855  {
856  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
857  }
858  }
859  else
860  {
861  // leave point without transformation
862  }
863  return rect;
864 }
865 
867 {
868  if ( hasCrsTransformEnabled() )
869  {
870  try
871  {
872  const QgsCoordinateTransform *transform = transformation( theLayer );
873  if ( transform )
874  point = transform->transform( point, QgsCoordinateTransform::ReverseTransform );
875  }
876  catch ( QgsCsException &cse )
877  {
878  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
879  }
880  }
881  else
882  {
883  // leave point without transformation
884  }
885  return point;
886 }
887 
889 {
890  if ( hasCrsTransformEnabled() )
891  {
892  try
893  {
894  const QgsCoordinateTransform *transform = transformation( theLayer );
895  if ( transform )
896  rect = transform->transform( rect, QgsCoordinateTransform::ReverseTransform );
897  }
898  catch ( QgsCsException &cse )
899  {
900  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
901  }
902  }
903  return rect;
904 }
905 
906 
908 {
909  QgsDebugMsg( "called." );
911 
912  // reset the map canvas extent since the extent may now be smaller
913  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
915 
916  // iterate through the map layers and test each layers extent
917  // against the current min and max values
918  QStringList::iterator it = mLayerSet.begin();
919  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
920  while ( it != mLayerSet.end() )
921  {
922  QgsMapLayer * lyr = registry->mapLayer( *it );
923  if ( lyr == NULL )
924  {
925  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) );
926  }
927  else
928  {
929  QgsDebugMsg( "Updating extent using " + lyr->name() );
930  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
931 
932  if ( lyr->extent().isNull() )
933  {
934  ++it;
935  continue;
936  }
937 
938  // Layer extents are stored in the coordinate system (CS) of the
939  // layer. The extent must be projected to the canvas CS
941 
942  QgsDebugMsg( "Output extent: " + extent.toString() );
943  mFullExtent.unionRect( extent );
944 
945  }
946  ++it;
947  }
948 
949  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
950  {
951  // If all of the features are at the one point, buffer the
952  // rectangle a bit. If they are all at zero, do something a bit
953  // more crude.
954 
955  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
956  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
957  {
958  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
959  }
960  else
961  {
962  const double padFactor = 1e-8;
963  double widthPad = mFullExtent.xMinimum() * padFactor;
964  double heightPad = mFullExtent.yMinimum() * padFactor;
965  double xmin = mFullExtent.xMinimum() - widthPad;
966  double xmax = mFullExtent.xMaximum() + widthPad;
967  double ymin = mFullExtent.yMinimum() - heightPad;
968  double ymax = mFullExtent.yMaximum() + heightPad;
969  mFullExtent.set( xmin, ymin, xmax, ymax );
970  }
971  }
972 
973  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
974 }
975 
977 {
979  return mFullExtent;
980 }
981 
982 void QgsMapRenderer::setLayerSet( const QStringList& layers )
983 {
984  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
985  mLayerSet = layers;
987 }
988 
990 {
991  return mLayerSet;
992 }
993 
994 
995 bool QgsMapRenderer::readXML( QDomNode & theNode )
996 {
997  QgsMapSettings tmpSettings;
998  tmpSettings.readXML( theNode );
999  //load coordinate transform into
1001  QDomElement layerCoordTransformInfoElem = theNode.firstChildElement( "layer_coordinate_transform_info" );
1002  if ( !layerCoordTransformInfoElem.isNull() )
1003  {
1004  QDomNodeList layerCoordinateTransformList = layerCoordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
1005  QDomElement layerCoordTransformElem;
1006  for ( int i = 0; i < layerCoordinateTransformList.size(); ++i )
1007  {
1008  layerCoordTransformElem = layerCoordinateTransformList.at( i ).toElement();
1009  QString layerId = layerCoordTransformElem.attribute( "layerid" );
1010  if ( layerId.isEmpty() )
1011  {
1012  continue;
1013  }
1014 
1016  lct.srcAuthId = layerCoordTransformElem.attribute( "srcAuthId" );
1017  lct.destAuthId = layerCoordTransformElem.attribute( "destAuthId" );
1018  lct.srcDatumTransform = layerCoordTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
1019  lct.destDatumTransform = layerCoordTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
1020  mLayerCoordinateTransformInfo.insert( layerId, lct );
1021  }
1022  }
1023 
1024 
1025  setMapUnits( tmpSettings.mapUnits() );
1026  setExtent( tmpSettings.extent() );
1028  setDestinationCrs( tmpSettings.destinationCrs() );
1029 
1030 
1031  return true;
1032 }
1033 
1034 bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc )
1035 {
1036  QgsMapSettings tmpSettings;
1037  tmpSettings.setOutputDpi( outputDpi() );
1038  tmpSettings.setOutputSize( outputSize() );
1039  tmpSettings.setMapUnits( mapUnits() );
1040  tmpSettings.setExtent( extent() );
1042  tmpSettings.setDestinationCrs( destinationCrs() );
1043 
1044  tmpSettings.writeXML( theNode, theDoc );
1045  // layer coordinate transform infos
1046  QDomElement layerCoordTransformInfo = theDoc.createElement( "layer_coordinate_transform_info" );
1047  QHash< QString, QgsLayerCoordinateTransform >::const_iterator coordIt = mLayerCoordinateTransformInfo.constBegin();
1048  for ( ; coordIt != mLayerCoordinateTransformInfo.constEnd(); ++coordIt )
1049  {
1050  QDomElement layerCoordTransformElem = theDoc.createElement( "layer_coordinate_transform" );
1051  layerCoordTransformElem.setAttribute( "layerid", coordIt.key() );
1052  layerCoordTransformElem.setAttribute( "srcAuthId", coordIt->srcAuthId );
1053  layerCoordTransformElem.setAttribute( "destAuthId", coordIt->destAuthId );
1054  layerCoordTransformElem.setAttribute( "srcDatumTransform", QString::number( coordIt->srcDatumTransform ) );
1055  layerCoordTransformElem.setAttribute( "destDatumTransform", QString::number( coordIt->destDatumTransform ) );
1056  layerCoordTransformInfo.appendChild( layerCoordTransformElem );
1057  }
1058  theNode.appendChild( layerCoordTransformInfo );
1059  return true;
1060 }
1061 
1063 {
1064  if ( mLabelingEngine )
1065  delete mLabelingEngine;
1066 
1067  mLabelingEngine = iface;
1068 }
1069 
1071 {
1072  if ( !layer || !mDestCRS )
1073  {
1074  return 0;
1075  }
1076 
1077  if ( layer->crs().authid() == mDestCRS->authid() )
1078  {
1079  return 0;
1080  }
1081 
1082  QHash< QString, QgsLayerCoordinateTransform >::const_iterator ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1083  if ( ctIt != mLayerCoordinateTransformInfo.constEnd()
1084  && ctIt->srcAuthId == layer->crs().authid()
1085  && ctIt->destAuthId == mDestCRS->authid() )
1086  {
1087  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1088  }
1089  else
1090  {
1091  emit datumTransformInfoRequested( layer, layer->crs().authid(), mDestCRS->authid() );
1092  }
1093 
1094  //still not present? get coordinate transformation with -1/-1 datum transform as default
1095  ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1096  if ( ctIt == mLayerCoordinateTransformInfo.constEnd()
1097  || ctIt->srcAuthId == layer->crs().authid()
1098  || ctIt->destAuthId == mDestCRS->authid()
1099  )
1100  {
1101  return QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mDestCRS->authid(), -1, -1 );
1102  }
1103  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1104 }
1105 
1108 QPainter::CompositionMode QgsMapRenderer::getCompositionMode( const QgsMapRenderer::BlendMode &blendMode )
1109 {
1110  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1111  switch ( blendMode )
1112  {
1114  return QPainter::CompositionMode_SourceOver;
1116  return QPainter::CompositionMode_Lighten;
1118  return QPainter::CompositionMode_Screen;
1120  return QPainter::CompositionMode_ColorDodge;
1122  return QPainter::CompositionMode_Plus;
1124  return QPainter::CompositionMode_Darken;
1126  return QPainter::CompositionMode_Multiply;
1128  return QPainter::CompositionMode_ColorBurn;
1130  return QPainter::CompositionMode_Overlay;
1132  return QPainter::CompositionMode_SoftLight;
1134  return QPainter::CompositionMode_HardLight;
1136  return QPainter::CompositionMode_Difference;
1138  return QPainter::CompositionMode_Exclusion;
1139  default:
1140  return QPainter::CompositionMode_SourceOver;
1141  }
1142 }
1143 
1144 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::CompositionMode &blendMode )
1145 {
1146  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1147  switch ( blendMode )
1148  {
1149  case QPainter::CompositionMode_SourceOver:
1151  case QPainter::CompositionMode_Lighten:
1153  case QPainter::CompositionMode_Screen:
1155  case QPainter::CompositionMode_ColorDodge:
1157  case QPainter::CompositionMode_Plus:
1159  case QPainter::CompositionMode_Darken:
1161  case QPainter::CompositionMode_Multiply:
1163  case QPainter::CompositionMode_ColorBurn:
1165  case QPainter::CompositionMode_Overlay:
1167  case QPainter::CompositionMode_SoftLight:
1169  case QPainter::CompositionMode_HardLight:
1171  case QPainter::CompositionMode_Difference:
1173  case QPainter::CompositionMode_Exclusion:
1175  default:
1177  }
1178 }
1179 
1180 Q_GUI_EXPORT extern int qt_defaultDpiX();
1181 
1183 {
1184  // make sure the settings object is up-to-date
1192  return mMapSettings;
1193 }
1194 
1195 void QgsMapRenderer::addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform, int destDatumTransform )
1196 {
1198  lt.srcAuthId = srcAuthId;
1199  lt.destAuthId = destAuthId;
1200  lt.srcDatumTransform = srcDatumTransform;
1201  lt.destDatumTransform = destDatumTransform;
1202  mLayerCoordinateTransformInfo.insert( layerId, lt );
1203 }
1204 
1206 {
1208 }
1209 
1210 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 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:48
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:89
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 setYMaximum(double ymax)
Set maximum y value.
void drawError(QgsMapLayer *)
emitted when layer's draw() returned false
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:169
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:194
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
void setOutputDpi(int dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
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
QString qgsDoubleToString(const double &a)
Definition: qgis.h:316
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
void setRendererScale(double scale)
float minimumScale() const
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:439
void drawingProgress(int current, int total)
~QgsMapRenderer()
destructor
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
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...
double scaleFactor() const
void setLayerSet(const QStringList &layers)
change current layer set
double outputDpi()
accessor for output dpi
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.
static QgsCoordinateTransformCache * instance()
Definition: qgscrscache.cpp:22
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
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
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.
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:33
const QgsCoordinateTransform * transform(const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
Returns coordinate transformation.
Definition: qgscrscache.cpp:37
void setSelectionColor(const QColor &color)
Added in QGIS v2.0.
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
void adjustExtentToSize()
adjust extent to fit the pixmap size
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:199
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:184
void hasCrsTransformEnabledChanged(bool flag)
This signal is emitted when CRS transformation is enabled/disabled.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
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
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:174
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:384
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:95
Reads and writes project states.
Definition: qgsproject.h:67
bool mOverview
indicates whether it's map image for overview
QgsPoint transform(const QgsPoint p, TransformDirection direction=ForwardTransform) const
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 geometry.
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...
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs, bool refreshCoordinateTransformInfo=true, bool transformExtent=true)
sets destination coordinate reference system
double rasterScaleFactor
Definition: qgssvgcache.cpp:80
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 Added in 1.9.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:440
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...
QgsRectangle transformBoundingBox(const QgsRectangle theRect, TransformDirection direction=ForwardTransform) const
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
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:179
Q_DECL_DEPRECATED void onDrawingProgress(int current, int total)
void setLabelingEngine(QgsLabelingEngineInterface *iface)
Added in QGIS v1.4.
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:362
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.
UnitType
Map units that qgis supports.
Definition: qgis.h:229
const QgsMapToPixel & mapToPixel() const
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
void setParameters(double mapUnitsPerPixel, double xmin, double ymin, double ymax)
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 Added in 1.9.
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:204
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:189
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:164
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:209
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)