QGIS API Documentation  2.7.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( 0, 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  rect = transform.transformBoundingBox( mExtent );
688  }
689 
690  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
691  mDistArea->setSourceCrs( crs.srsid() );
692  *mDestCRS = crs;
694 
695  if ( !rect.isEmpty() )
696  {
697  setExtent( rect );
698  }
699 
700  emit destinationSrsChanged();
701  }
702 }
703 
705 {
706  QgsDebugMsgLevel( "* Returning destCRS", 3 );
707  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
708  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
709  return *mDestCRS;
710 }
711 
712 
714 {
715  bool split = false;
716 
717  if ( hasCrsTransformEnabled() )
718  {
719  try
720  {
721 #ifdef QGISDEBUG
722  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
723 #endif
724  // Split the extent into two if the source CRS is
725  // geographic and the extent crosses the split in
726  // geographic coordinates (usually +/- 180 degrees,
727  // and is assumed to be so here), and draw each
728  // extent separately.
729  static const double splitCoord = 180.0;
730 
731  const QgsCoordinateTransform *transform = transformation( layer );
732  if ( layer->crs().geographicFlag() )
733  {
734  // Note: ll = lower left point
735  // and ur = upper right point
736 
737  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
738  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
739 
740  if ( transform )
741  {
742  ll = transform->transform( ll.x(), ll.y(),
744  ur = transform->transform( ur.x(), ur.y(),
746  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
747  }
748 
749  if ( ll.x() > ur.x() )
750  {
751  r2 = extent;
752  extent.setXMinimum( splitCoord );
753  r2.setXMaximum( splitCoord );
754  split = true;
755  }
756  }
757  else // can't cross 180
758  {
759  if ( transform )
760  {
761  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
762  }
763  }
764  }
765  catch ( QgsCsException &cse )
766  {
767  Q_UNUSED( cse );
768  QgsDebugMsg( "Transform error caught" );
769  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
770  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
771  }
772  }
773  return split;
774 }
775 
777 {
778  //QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
779  //QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
780  //QgsDebugMsg( QString( "extent = " + extent.toString() ) );
781  if ( hasCrsTransformEnabled() )
782  {
783  try
784  {
785  const QgsCoordinateTransform *transform = transformation( theLayer );
786  if ( transform )
787  {
788  extent = transform->transformBoundingBox( extent );
789  }
790  }
791  catch ( QgsCsException &cse )
792  {
793  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
794  }
795  }
796 
797  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
798 
799  return extent;
800 }
801 
803 {
804 #if QGISDEBUG
805  const QgsCoordinateTransform *transform = transformation( theLayer );
806  QgsDebugMsg( QString( "layer sourceCrs = " + ( transform ? transform->sourceCrs().authid() : "none" ) ) );
807  QgsDebugMsg( QString( "layer destCRS = " + ( transform ? transform->destCRS().authid() : "none" ) ) );
808  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
809 #endif
810  if ( hasCrsTransformEnabled() )
811  {
812  try
813  {
814  const QgsCoordinateTransform *transform = transformation( theLayer );
815  if ( transform )
816  {
817  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
818  }
819  }
820  catch ( QgsCsException &cse )
821  {
822  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
823  }
824  }
825 
826  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
827 
828  return extent;
829 }
830 
832 {
833  if ( hasCrsTransformEnabled() )
834  {
835  try
836  {
837  const QgsCoordinateTransform *transform = transformation( theLayer );
838  if ( transform )
839  {
840  point = transform->transform( point, QgsCoordinateTransform::ForwardTransform );
841  }
842  }
843  catch ( QgsCsException &cse )
844  {
845  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
846  }
847  }
848  else
849  {
850  // leave point without transformation
851  }
852  return point;
853 }
854 
856 {
857  if ( hasCrsTransformEnabled() )
858  {
859  try
860  {
861  const QgsCoordinateTransform *transform = transformation( theLayer );
862  if ( transform )
863  {
864  rect = transform->transform( rect, QgsCoordinateTransform::ForwardTransform );
865  }
866  }
867  catch ( QgsCsException &cse )
868  {
869  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
870  }
871  }
872  else
873  {
874  // leave point without transformation
875  }
876  return rect;
877 }
878 
880 {
881  if ( hasCrsTransformEnabled() )
882  {
883  try
884  {
885  const QgsCoordinateTransform *transform = transformation( theLayer );
886  if ( transform )
887  point = transform->transform( point, QgsCoordinateTransform::ReverseTransform );
888  }
889  catch ( QgsCsException &cse )
890  {
891  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
892  }
893  }
894  else
895  {
896  // leave point without transformation
897  }
898  return point;
899 }
900 
902 {
903  if ( hasCrsTransformEnabled() )
904  {
905  try
906  {
907  const QgsCoordinateTransform *transform = transformation( theLayer );
908  if ( transform )
909  rect = transform->transform( rect, QgsCoordinateTransform::ReverseTransform );
910  }
911  catch ( QgsCsException &cse )
912  {
913  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
914  }
915  }
916  return rect;
917 }
918 
919 
921 {
922  QgsDebugMsg( "called." );
924 
925  // reset the map canvas extent since the extent may now be smaller
926  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
928 
929  // iterate through the map layers and test each layers extent
930  // against the current min and max values
931  QStringList::iterator it = mLayerSet.begin();
932  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
933  while ( it != mLayerSet.end() )
934  {
935  QgsMapLayer * lyr = registry->mapLayer( *it );
936  if ( lyr == NULL )
937  {
938  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) );
939  }
940  else
941  {
942  QgsDebugMsg( "Updating extent using " + lyr->name() );
943  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
944 
945  if ( lyr->extent().isNull() )
946  {
947  ++it;
948  continue;
949  }
950 
951  // Layer extents are stored in the coordinate system (CS) of the
952  // layer. The extent must be projected to the canvas CS
954 
955  QgsDebugMsg( "Output extent: " + extent.toString() );
956  mFullExtent.unionRect( extent );
957 
958  }
959  ++it;
960  }
961 
962  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
963  {
964  // If all of the features are at the one point, buffer the
965  // rectangle a bit. If they are all at zero, do something a bit
966  // more crude.
967 
968  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
969  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
970  {
971  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
972  }
973  else
974  {
975  const double padFactor = 1e-8;
976  double widthPad = mFullExtent.xMinimum() * padFactor;
977  double heightPad = mFullExtent.yMinimum() * padFactor;
978  double xmin = mFullExtent.xMinimum() - widthPad;
979  double xmax = mFullExtent.xMaximum() + widthPad;
980  double ymin = mFullExtent.yMinimum() - heightPad;
981  double ymax = mFullExtent.yMaximum() + heightPad;
982  mFullExtent.set( xmin, ymin, xmax, ymax );
983  }
984  }
985 
986  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
987 }
988 
990 {
992  return mFullExtent;
993 }
994 
995 void QgsMapRenderer::setLayerSet( const QStringList& layers )
996 {
997  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
998  mLayerSet = layers;
1000 }
1001 
1003 {
1004  return mLayerSet;
1005 }
1006 
1007 
1008 bool QgsMapRenderer::readXML( QDomNode & theNode )
1009 {
1010  QgsMapSettings tmpSettings;
1011  tmpSettings.readXML( theNode );
1012  //load coordinate transform into
1014  QDomElement layerCoordTransformInfoElem = theNode.firstChildElement( "layer_coordinate_transform_info" );
1015  if ( !layerCoordTransformInfoElem.isNull() )
1016  {
1017  QDomNodeList layerCoordinateTransformList = layerCoordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
1018  QDomElement layerCoordTransformElem;
1019  for ( int i = 0; i < layerCoordinateTransformList.size(); ++i )
1020  {
1021  layerCoordTransformElem = layerCoordinateTransformList.at( i ).toElement();
1022  QString layerId = layerCoordTransformElem.attribute( "layerid" );
1023  if ( layerId.isEmpty() )
1024  {
1025  continue;
1026  }
1027 
1029  lct.srcAuthId = layerCoordTransformElem.attribute( "srcAuthId" );
1030  lct.destAuthId = layerCoordTransformElem.attribute( "destAuthId" );
1031  lct.srcDatumTransform = layerCoordTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
1032  lct.destDatumTransform = layerCoordTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
1033  mLayerCoordinateTransformInfo.insert( layerId, lct );
1034  }
1035  }
1036 
1037 
1038  setMapUnits( tmpSettings.mapUnits() );
1039  setExtent( tmpSettings.extent() );
1041  setDestinationCrs( tmpSettings.destinationCrs() );
1042 
1043 
1044  return true;
1045 }
1046 
1047 bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc )
1048 {
1049  QgsMapSettings tmpSettings;
1050  tmpSettings.setOutputDpi( outputDpi() );
1051  tmpSettings.setOutputSize( outputSize() );
1052  tmpSettings.setMapUnits( mapUnits() );
1053  tmpSettings.setExtent( extent() );
1055  tmpSettings.setDestinationCrs( destinationCrs() );
1056 
1057  tmpSettings.writeXML( theNode, theDoc );
1058  // layer coordinate transform infos
1059  QDomElement layerCoordTransformInfo = theDoc.createElement( "layer_coordinate_transform_info" );
1060  QHash< QString, QgsLayerCoordinateTransform >::const_iterator coordIt = mLayerCoordinateTransformInfo.constBegin();
1061  for ( ; coordIt != mLayerCoordinateTransformInfo.constEnd(); ++coordIt )
1062  {
1063  QDomElement layerCoordTransformElem = theDoc.createElement( "layer_coordinate_transform" );
1064  layerCoordTransformElem.setAttribute( "layerid", coordIt.key() );
1065  layerCoordTransformElem.setAttribute( "srcAuthId", coordIt->srcAuthId );
1066  layerCoordTransformElem.setAttribute( "destAuthId", coordIt->destAuthId );
1067  layerCoordTransformElem.setAttribute( "srcDatumTransform", QString::number( coordIt->srcDatumTransform ) );
1068  layerCoordTransformElem.setAttribute( "destDatumTransform", QString::number( coordIt->destDatumTransform ) );
1069  layerCoordTransformInfo.appendChild( layerCoordTransformElem );
1070  }
1071  theNode.appendChild( layerCoordTransformInfo );
1072  return true;
1073 }
1074 
1076 {
1077  if ( mLabelingEngine )
1078  delete mLabelingEngine;
1079 
1080  mLabelingEngine = iface;
1081 }
1082 
1084 {
1085  if ( !layer || !mDestCRS )
1086  {
1087  return 0;
1088  }
1089 
1090  if ( layer->crs().authid() == mDestCRS->authid() )
1091  {
1092  return 0;
1093  }
1094 
1095  QHash< QString, QgsLayerCoordinateTransform >::const_iterator ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1096  if ( ctIt != mLayerCoordinateTransformInfo.constEnd()
1097  && ctIt->srcAuthId == layer->crs().authid()
1098  && ctIt->destAuthId == mDestCRS->authid() )
1099  {
1100  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1101  }
1102  else
1103  {
1104  emit datumTransformInfoRequested( layer, layer->crs().authid(), mDestCRS->authid() );
1105  }
1106 
1107  //still not present? get coordinate transformation with -1/-1 datum transform as default
1108  ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1109  if ( ctIt == mLayerCoordinateTransformInfo.constEnd()
1110  || ctIt->srcAuthId == layer->crs().authid()
1111  || ctIt->destAuthId == mDestCRS->authid()
1112  )
1113  {
1114  return QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mDestCRS->authid(), -1, -1 );
1115  }
1116  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1117 }
1118 
1121 QPainter::CompositionMode QgsMapRenderer::getCompositionMode( const QgsMapRenderer::BlendMode &blendMode )
1122 {
1123  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1124  switch ( blendMode )
1125  {
1127  return QPainter::CompositionMode_SourceOver;
1129  return QPainter::CompositionMode_Lighten;
1131  return QPainter::CompositionMode_Screen;
1133  return QPainter::CompositionMode_ColorDodge;
1135  return QPainter::CompositionMode_Plus;
1137  return QPainter::CompositionMode_Darken;
1139  return QPainter::CompositionMode_Multiply;
1141  return QPainter::CompositionMode_ColorBurn;
1143  return QPainter::CompositionMode_Overlay;
1145  return QPainter::CompositionMode_SoftLight;
1147  return QPainter::CompositionMode_HardLight;
1149  return QPainter::CompositionMode_Difference;
1151  return QPainter::CompositionMode_Exclusion;
1153  return QPainter::CompositionMode_Source;
1155  return QPainter::CompositionMode_DestinationOver;
1157  return QPainter::CompositionMode_Clear;
1159  return QPainter::CompositionMode_Destination;
1161  return QPainter::CompositionMode_SourceIn;
1163  return QPainter::CompositionMode_DestinationIn;
1165  return QPainter::CompositionMode_SourceOut;
1167  return QPainter::CompositionMode_DestinationOut;
1169  return QPainter::CompositionMode_SourceAtop;
1171  return QPainter::CompositionMode_DestinationAtop;
1173  return QPainter::CompositionMode_Xor;
1174  default:
1175  QgsDebugMsg( QString( "Blend mode %1 mapped to SourceOver" ).arg( blendMode ) );
1176  return QPainter::CompositionMode_SourceOver;
1177  }
1178 }
1179 
1180 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::CompositionMode &blendMode )
1181 {
1182  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1183  switch ( blendMode )
1184  {
1185  case QPainter::CompositionMode_SourceOver:
1187  case QPainter::CompositionMode_Lighten:
1189  case QPainter::CompositionMode_Screen:
1191  case QPainter::CompositionMode_ColorDodge:
1193  case QPainter::CompositionMode_Plus:
1195  case QPainter::CompositionMode_Darken:
1197  case QPainter::CompositionMode_Multiply:
1199  case QPainter::CompositionMode_ColorBurn:
1201  case QPainter::CompositionMode_Overlay:
1203  case QPainter::CompositionMode_SoftLight:
1205  case QPainter::CompositionMode_HardLight:
1207  case QPainter::CompositionMode_Difference:
1209  case QPainter::CompositionMode_Exclusion:
1211  case QPainter::CompositionMode_Source:
1213  case QPainter::CompositionMode_DestinationOver:
1215  case QPainter::CompositionMode_Clear:
1217  case QPainter::CompositionMode_Destination:
1219  case QPainter::CompositionMode_SourceIn:
1221  case QPainter::CompositionMode_DestinationIn:
1223  case QPainter::CompositionMode_SourceOut:
1225  case QPainter::CompositionMode_DestinationOut:
1227  case QPainter::CompositionMode_SourceAtop:
1229  case QPainter::CompositionMode_DestinationAtop:
1231  case QPainter::CompositionMode_Xor:
1232  return QgsMapRenderer::BlendXor;
1233  default:
1234  QgsDebugMsg( QString( "Composition mode %1 mapped to Normal" ).arg( blendMode ) );
1236  }
1237 }
1238 
1239 Q_GUI_EXPORT extern int qt_defaultDpiX();
1240 
1242 {
1243  // make sure the settings object is up-to-date
1251  return mMapSettings;
1252 }
1253 
1254 void QgsMapRenderer::addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform, int destDatumTransform )
1255 {
1257  lt.srcAuthId = srcAuthId;
1258  lt.destAuthId = destAuthId;
1259  lt.srcDatumTransform = srcDatumTransform;
1260  lt.destDatumTransform = destDatumTransform;
1261  mLayerCoordinateTransformInfo.insert( layerId, lt );
1262 }
1263 
1265 {
1267 }
1268 
1269 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: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 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:439
void drawingProgress(int current, int total)
~QgsMapRenderer()
destructor
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
void setYMaximum(double yMax)
Set maximum y value.
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
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:385
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
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:317
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: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...
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: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.
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)