QGIS API Documentation  2.0.1-Dufour
 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 "qgsdistancearea.h"
29 #include "qgsproject.h"
30 #include "qgsvectorlayer.h"
31 
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  return true;
120 }
121 
122 
123 
124 void QgsMapRenderer::setOutputSize( QSize size, int dpi )
125 {
126  mSize = QSizeF( size.width(), size.height() );
127  mScaleCalculator->setDpi( dpi );
129 }
130 
131 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
132 {
133  mSize = size;
134  mScaleCalculator->setDpi( dpi );
136 }
137 
139 {
140  return mScaleCalculator->dpi();
141 }
142 
144 {
145  return mSize.toSize();
146 }
147 
149 {
150  return mSize;
151 }
152 
154 {
155  double myHeight = mSize.height();
156  double myWidth = mSize.width();
157 
158  QgsMapToPixel newCoordXForm;
159 
160  if ( !myWidth || !myHeight )
161  {
162  mScale = 1.0;
163  newCoordXForm.setParameters( 0, 0, 0, 0 );
164  return;
165  }
166 
167  // calculate the translation and scaling parameters
168  // mapUnitsPerPixel = map units per pixel
169  double mapUnitsPerPixelY = mExtent.height() / myHeight;
170  double mapUnitsPerPixelX = mExtent.width() / myWidth;
171  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
172 
173  // calculate the actual extent of the mapCanvas
174  double dxmin, dxmax, dymin, dymax, whitespace;
175 
176  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
177  {
178  dymin = mExtent.yMinimum();
179  dymax = mExtent.yMaximum();
180  whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
181  dxmin = mExtent.xMinimum() - whitespace;
182  dxmax = mExtent.xMaximum() + whitespace;
183  }
184  else
185  {
186  dxmin = mExtent.xMinimum();
187  dxmax = mExtent.xMaximum();
188  whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
189  dymin = mExtent.yMinimum() - whitespace;
190  dymax = mExtent.yMaximum() + whitespace;
191  }
192 
193  QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ) ).arg( qgsDoubleToString( mapUnitsPerPixelY ) ) );
194  QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( myWidth ) ).arg( qgsDoubleToString( myHeight ) ) );
195  QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ) ).arg( qgsDoubleToString( mExtent.height() ) ) );
197 
198  // update extent
199  mExtent.setXMinimum( dxmin );
200  mExtent.setXMaximum( dxmax );
201  mExtent.setYMinimum( dymin );
202  mExtent.setYMaximum( dymax );
203 
204  QgsDebugMsg( QString( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / myWidth ) ).arg( qgsDoubleToString( mExtent.height() / myHeight ) ) );
205 
206  QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / mMapUnitsPerPixel ) ).arg( qgsDoubleToString( mExtent.height() / mMapUnitsPerPixel ) ) );
207 
208  // update the scale
209  updateScale();
210 
211  QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
212 
213  newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
214  mRenderContext.setMapToPixel( newCoordXForm );
216 }
217 
218 
219 void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
220 {
221  //Lock render method for concurrent threads (e.g. from globe)
222  QMutexLocker renderLock( &mRenderMutex );
223 
224  //flag to see if the render context has changed
225  //since the last time we rendered. If it hasnt changed we can
226  //take some shortcuts with rendering
227  bool mySameAsLastFlag = true;
228 
229  QgsDebugMsg( "========== Rendering ==========" );
230 
231  if ( mExtent.isEmpty() )
232  {
233  QgsDebugMsg( "empty extent... not rendering" );
234  return;
235  }
236 
237  if ( mSize.width() == 1 && mSize.height() == 1 )
238  {
239  QgsDebugMsg( "size 1x1... not rendering" );
240  return;
241  }
242 
243  QPaintDevice* thePaintDevice = painter->device();
244  if ( !thePaintDevice )
245  {
246  return;
247  }
248 
249  // wait
250  if ( mDrawing )
251  {
252  QgsDebugMsg( "already rendering" );
253  QCoreApplication::processEvents();
254  }
255 
256  if ( mDrawing )
257  {
258  QgsDebugMsg( "still rendering - skipping" );
259  return;
260  }
261 
262  mDrawing = true;
263 
264  const QgsCoordinateTransform* ct;
265 
266 #ifdef QGISDEBUG
267  QgsDebugMsg( "Starting to render layer stack." );
268  QTime renderTime;
269  renderTime.start();
270 #endif
271 
272  if ( mOverview )
274 
275  mRenderContext.setPainter( painter );
277  //this flag is only for stopping during the current rendering progress,
278  //so must be false at every new render operation
280 
281  // set selection color
283  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
284  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
285  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
286  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
287  mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
288 
289  //calculate scale factor
290  //use the specified dpi and not those from the paint device
291  //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene)
292  double sceneDpi = mScaleCalculator->dpi();
293  double scaleFactor = 1.0;
295  {
296  if ( forceWidthScale )
297  {
298  scaleFactor = *forceWidthScale;
299  }
300  else
301  {
302  scaleFactor = sceneDpi / 25.4;
303  }
304  }
305  double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
307  {
308  mRenderContext.setRasterScaleFactor( rasterScaleFactor );
309  mySameAsLastFlag = false;
310  }
311  if ( mRenderContext.scaleFactor() != scaleFactor )
312  {
313  mRenderContext.setScaleFactor( scaleFactor );
314  mySameAsLastFlag = false;
315  }
317  {
318  //add map scale to render context
320  mySameAsLastFlag = false;
321  }
322  if ( mLastExtent != mExtent )
323  {
325  mySameAsLastFlag = false;
326  }
327 
329  if ( mLabelingEngine )
330  mLabelingEngine->init( this );
331 
332  // know we know if this render is just a repeat of the last time, we
333  // can clear caches if it has changed
334  if ( !mySameAsLastFlag )
335  {
336  //clear the cache pixmap if we changed resolution / extent
337  QSettings mySettings;
338  if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() )
339  {
341  }
342  }
343 
344  // render all layers in the stack, starting at the base
345  QListIterator<QString> li( mLayerSet );
346  li.toBack();
347 
348  QgsRectangle r1, r2;
349 
350  while ( li.hasPrevious() )
351  {
353  {
354  break;
355  }
356 
357  // Store the painter in case we need to swap it out for the
358  // cache painter
359  QPainter * mypContextPainter = mRenderContext.painter();
360  // Flattened image for drawing when a blending mode is set
361  QImage * mypFlattenedImage = 0;
362 
363  QString layerId = li.previous();
364 
365  QgsDebugMsg( "Rendering at layer item " + layerId );
366 
367  // This call is supposed to cause the progress bar to
368  // advance. However, it seems that updating the progress bar is
369  // incompatible with having a QPainter active (the one that is
370  // passed into this function), as Qt produces a number of errors
371  // when try to do so. I'm (Gavin) not sure how to fix this, but
372  // added these comments and debug statement to help others...
373  QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
374 
375  //emit drawingProgress(myRenderCounter++, mLayerSet.size());
377 
378  if ( !ml )
379  {
380  QgsDebugMsg( "Layer not found in registry!" );
381  continue;
382  }
383 
384  QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
385  .arg( ml->name() )
386  .arg( ml->minimumScale() )
387  .arg( ml->maximumScale() )
388  .arg( ml->hasScaleBasedVisibility() )
389  .arg( ml->extent().toString() )
390  .arg( ml->blendMode() )
391  );
392 
394  {
395  // Set the QPainter composition mode so that this layer is rendered using
396  // the desired blending mode
397  mypContextPainter->setCompositionMode( ml->blendMode() );
398  }
399 
400  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() <= mScale && mScale < ml->maximumScale() ) || mOverview )
401  {
402  connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
403 
404  //
405  // Now do the call to the layer that actually does
406  // the rendering work!
407  //
408 
409  bool split = false;
410 
411  if ( hasCrsTransformEnabled() )
412  {
413  r1 = mExtent;
414  split = splitLayersExtent( ml, r1, r2 );
417  QgsDebugMsg( " extent 1: " + r1.toString() );
418  QgsDebugMsg( " extent 2: " + r2.toString() );
419  if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
420  {
421  continue;
422  }
423  }
424  else
425  {
426  ct = NULL;
427  }
428 
430 
431  //decide if we have to scale the raster
432  //this is necessary in case QGraphicsScene is used
433  bool scaleRaster = false;
434  QgsMapToPixel rasterMapToPixel;
435  QgsMapToPixel bk_mapToPixel;
436 
437  if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 )
438  {
439  scaleRaster = true;
440  }
441 
442  // Force render of layers that are being edited
443  // or if there's a labeling engine that needs the layer to register features
444  if ( ml->type() == QgsMapLayer::VectorLayer )
445  {
446  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
447  if ( vl->isEditable() ||
449  {
450  ml->setCacheImage( 0 );
451  }
452  }
453 
454  QSettings mySettings;
455  bool useRenderCaching = false;
456  if ( ! split )//render caching does not yet cater for split extents
457  {
458  if ( mySettings.value( "/qgis/enable_render_caching", false ).toBool() )
459  {
460  useRenderCaching = true;
461  if ( !mySameAsLastFlag || ml->cacheImage() == 0 )
462  {
463  QgsDebugMsg( "Caching enabled but layer redraw forced by extent change or empty cache" );
464  QImage * mypImage = new QImage( mRenderContext.painter()->device()->width(),
465  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
466  if ( mypImage->isNull() )
467  {
468  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) );
469  emit drawError( ml );
470  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
471  return;
472  }
473  mypImage->fill( 0 );
474  ml->setCacheImage( mypImage ); //no need to delete the old one, maplayer does it for you
475  QPainter * mypPainter = new QPainter( ml->cacheImage() );
476  // Changed to enable anti aliasing by default in QGIS 1.7
477  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
478  {
479  mypPainter->setRenderHint( QPainter::Antialiasing );
480  }
481  mRenderContext.setPainter( mypPainter );
482  }
483  else if ( mySameAsLastFlag )
484  {
485  //draw from cached image
486  QgsDebugMsg( "Caching enabled --- drawing layer from cached image" );
487  mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
488  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
489  //short circuit as there is nothing else to do...
490  continue;
491  }
492  }
493  }
494 
495  // If we are drawing with an alternative blending mode then we need to render to a separate image
496  // before compositing this on the map. This effectively flattens the layer and prevents
497  // blending occuring between objects on the layer
498  // (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
499  bool flattenedLayer = false;
501  {
502  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
503  if (( !useRenderCaching )
504  && (( vl->blendMode() != QPainter::CompositionMode_SourceOver )
505  || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
506  || ( vl->layerTransparency() != 0 ) ) )
507  {
508  flattenedLayer = true;
509  mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
510  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
511  if ( mypFlattenedImage->isNull() )
512  {
513  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + "x" + QString::number( mRenderContext.painter()->device()->height() ) );
514  emit drawError( ml );
515  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
516  return;
517  }
518  mypFlattenedImage->fill( 0 );
519  QPainter * mypPainter = new QPainter( mypFlattenedImage );
520  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
521  {
522  mypPainter->setRenderHint( QPainter::Antialiasing );
523  }
524  mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
525  mRenderContext.setPainter( mypPainter );
526  }
527  }
528 
529  // Per feature blending mode
531  {
532  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
533  if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
534  {
535  // set the painter to the feature blend mode, so that features drawn
536  // on this layer will interact and blend with each other
537  mRenderContext.painter()->setCompositionMode( vl->featureBlendMode() );
538  }
539  }
540 
541  if ( scaleRaster )
542  {
543  bk_mapToPixel = mRenderContext.mapToPixel();
544  rasterMapToPixel = mRenderContext.mapToPixel();
546  rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
547  mRenderContext.setMapToPixel( rasterMapToPixel );
548  mRenderContext.painter()->save();
549  mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
550  }
551 
552  if ( !ml->draw( mRenderContext ) )
553  {
554  emit drawError( ml );
555  }
556  else
557  {
558  QgsDebugMsg( "Layer rendered without issues" );
559  }
560 
561  if ( split )
562  {
564  if ( !ml->draw( mRenderContext ) )
565  {
566  emit drawError( ml );
567  }
568  }
569 
570  if ( scaleRaster )
571  {
572  mRenderContext.setMapToPixel( bk_mapToPixel );
573  mRenderContext.painter()->restore();
574  }
575 
576  //apply layer transparency for vector layers
578  {
579  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
580  if ( vl->layerTransparency() != 0 )
581  {
582  // a layer transparency has been set, so update the alpha for the flattened layer
583  // by combining it with the layer transparency
584  QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
585  // use destination in composition mode to merge source's alpha with destination
586  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
587  mRenderContext.painter()->fillRect( 0, 0, mRenderContext.painter()->device()->width(),
588  mRenderContext.painter()->device()->height(), transparentFillColor );
589  }
590  }
591 
592  if ( useRenderCaching )
593  {
594  // composite the cached image into our view and then clean up from caching
595  // by reinstating the painter as it was swapped out for caching renders
596  delete mRenderContext.painter();
597  mRenderContext.setPainter( mypContextPainter );
598  //draw from cached image that we created further up
599  if ( ml->cacheImage() )
600  mypContextPainter->drawImage( 0, 0, *( ml->cacheImage() ) );
601  }
602  else if ( flattenedLayer )
603  {
604  // If we flattened this layer for alternate blend modes, composite it now
605  delete mRenderContext.painter();
606  mRenderContext.setPainter( mypContextPainter );
607  mypContextPainter->save();
608  mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
609  mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) );
610  mypContextPainter->restore();
611  delete mypFlattenedImage;
612  mypFlattenedImage = 0;
613  }
614 
615  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
616  }
617  else // layer not visible due to scale
618  {
619  QgsDebugMsg( "Layer not rendered because it is not within the defined "
620  "visibility scale range" );
621  }
622 
623  } // while (li.hasPrevious())
624 
625  QgsDebugMsg( "Done rendering map layers" );
626 
627  // Reset the composition mode before rendering the labels
628  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_SourceOver );
629 
630  if ( !mOverview )
631  {
632  // render all labels for vector layers in the stack, starting at the base
633  li.toBack();
634  while ( li.hasPrevious() )
635  {
637  {
638  break;
639  }
640 
641  QString layerId = li.previous();
642 
643  // TODO: emit drawingProgress((myRenderCounter++),zOrder.size());
645 
646  if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
647  {
648  // only make labels if the layer is visible
649  // after scale dep viewing settings are checked
650  if ( !ml->hasScaleBasedVisibility() || ( ml->minimumScale() < mScale && mScale < ml->maximumScale() ) )
651  {
652  bool split = false;
653 
654  if ( hasCrsTransformEnabled() )
655  {
656  QgsRectangle r1 = mExtent;
657  split = splitLayersExtent( ml, r1, r2 );
658  ct = new QgsCoordinateTransform( ml->crs(), *mDestCRS );
660  }
661  else
662  {
663  ct = NULL;
664  }
665 
667 
668  ml->drawLabels( mRenderContext );
669  if ( split )
670  {
672  ml->drawLabels( mRenderContext );
673  }
674  }
675  }
676  }
677  } // if (!mOverview)
678 
679  // make sure progress bar arrives at 100%!
680  emit drawingProgress( 1, 1 );
681 
682  if ( mLabelingEngine )
683  {
684  // set correct extent
687 
690  }
691 
692  QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
693 
694  mDrawing = false;
695 }
696 
698 {
700 
701  // Since the map units have changed, force a recalculation of the scale.
702  updateScale();
703 
704  emit mapUnitsChanged();
705 }
706 
708 {
709  return mScaleCalculator->mapUnits();
710 }
711 
712 void QgsMapRenderer::onDrawingProgress( int current, int total )
713 {
714  Q_UNUSED( current );
715  Q_UNUSED( total );
716  // TODO: emit signal with progress
717 // QgsDebugMsg(QString("onDrawingProgress: %1 / %2").arg(current).arg(total));
718  emit updateMap();
719 }
720 
722 {
723  if ( mProjectionsEnabled != enabled )
724  {
725  mProjectionsEnabled = enabled;
726  QgsDebugMsg( "Adjusting DistArea projection on/off" );
727  mDistArea->setEllipsoidalMode( enabled );
730  emit hasCrsTransformEnabled( enabled );
731  }
732 }
733 
735 {
736  return mProjectionsEnabled;
737 }
738 
740 {
741  QgsDebugMsg( "* Setting destCRS : = " + crs.toProj4() );
742  QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( crs.srsid() ) );
743  if ( *mDestCRS != crs )
744  {
745  QgsRectangle rect;
746  if ( !mExtent.isEmpty() )
747  {
748  QgsCoordinateTransform transform( *mDestCRS, crs );
749  rect = transform.transformBoundingBox( mExtent );
750  }
751 
752  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
753  mDistArea->setSourceCrs( crs.srsid() );
754  *mDestCRS = crs;
756 
757  if ( !rect.isEmpty() )
758  {
759  setExtent( rect );
760  }
761 
762  emit destinationSrsChanged();
763  }
764 }
765 
767 {
768  QgsDebugMsgLevel( "* Returning destCRS", 3 );
769  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
770  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
771  return *mDestCRS;
772 }
773 
774 
776 {
777  bool split = false;
778 
779  if ( hasCrsTransformEnabled() )
780  {
781  try
782  {
783 #ifdef QGISDEBUG
784  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
785 #endif
786  // Split the extent into two if the source CRS is
787  // geographic and the extent crosses the split in
788  // geographic coordinates (usually +/- 180 degrees,
789  // and is assumed to be so here), and draw each
790  // extent separately.
791  static const double splitCoord = 180.0;
792 
793  if ( layer->crs().geographicFlag() )
794  {
795  // Note: ll = lower left point
796  // and ur = upper right point
797  QgsPoint ll = tr( layer )->transform( extent.xMinimum(), extent.yMinimum(),
799 
800  QgsPoint ur = tr( layer )->transform( extent.xMaximum(), extent.yMaximum(),
802 
804 
805  if ( ll.x() > ur.x() )
806  {
807  r2 = extent;
808  extent.setXMinimum( splitCoord );
809  r2.setXMaximum( splitCoord );
810  split = true;
811  }
812  }
813  else // can't cross 180
814  {
816  }
817  }
818  catch ( QgsCsException &cse )
819  {
820  Q_UNUSED( cse );
821  QgsDebugMsg( "Transform error caught" );
822  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
823  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
824  }
825  }
826  return split;
827 }
828 
830 {
831  QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
832  QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
833  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
834  if ( hasCrsTransformEnabled() )
835  {
836  try
837  {
838  extent = tr( theLayer )->transformBoundingBox( extent );
839  }
840  catch ( QgsCsException &cse )
841  {
842  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
843  }
844  }
845 
846  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
847 
848  return extent;
849 }
850 
852 {
853  QgsDebugMsg( QString( "layer sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
854  QgsDebugMsg( QString( "layer destCRS = " + tr( theLayer )->destCRS().authid() ) );
855  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
856  if ( hasCrsTransformEnabled() )
857  {
858  try
859  {
860  extent = tr( theLayer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
861  }
862  catch ( QgsCsException &cse )
863  {
864  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
865  }
866  }
867 
868  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
869 
870  return extent;
871 }
872 
874 {
875  if ( hasCrsTransformEnabled() )
876  {
877  try
878  {
879  point = tr( theLayer )->transform( point, QgsCoordinateTransform::ForwardTransform );
880  }
881  catch ( QgsCsException &cse )
882  {
883  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
884  }
885  }
886  else
887  {
888  // leave point without transformation
889  }
890  return point;
891 }
892 
894 {
895  if ( hasCrsTransformEnabled() )
896  {
897  try
898  {
899  rect = tr( theLayer )->transform( rect, QgsCoordinateTransform::ForwardTransform );
900  }
901  catch ( QgsCsException &cse )
902  {
903  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
904  }
905  }
906  else
907  {
908  // leave point without transformation
909  }
910  return rect;
911 }
912 
914 {
915  if ( hasCrsTransformEnabled() )
916  {
917  try
918  {
919  point = tr( theLayer )->transform( point, QgsCoordinateTransform::ReverseTransform );
920  }
921  catch ( QgsCsException &cse )
922  {
923  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
924  }
925  }
926  else
927  {
928  // leave point without transformation
929  }
930  return point;
931 }
932 
934 {
935  if ( hasCrsTransformEnabled() )
936  {
937  try
938  {
939  rect = tr( theLayer )->transform( rect, QgsCoordinateTransform::ReverseTransform );
940  }
941  catch ( QgsCsException &cse )
942  {
943  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
944  }
945  }
946  return rect;
947 }
948 
949 
951 {
952  QgsDebugMsg( "called." );
954 
955  // reset the map canvas extent since the extent may now be smaller
956  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
958 
959  // iterate through the map layers and test each layers extent
960  // against the current min and max values
961  QStringList::iterator it = mLayerSet.begin();
962  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
963  while ( it != mLayerSet.end() )
964  {
965  QgsMapLayer * lyr = registry->mapLayer( *it );
966  if ( lyr == NULL )
967  {
968  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( *it ) );
969  }
970  else
971  {
972  QgsDebugMsg( "Updating extent using " + lyr->name() );
973  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
974 
975  if ( lyr->extent().isEmpty() )
976  {
977  it++;
978  continue;
979  }
980 
981  // Layer extents are stored in the coordinate system (CS) of the
982  // layer. The extent must be projected to the canvas CS
984 
985  QgsDebugMsg( "Output extent: " + extent.toString() );
986  mFullExtent.unionRect( extent );
987 
988  }
989  it++;
990  }
991 
992  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
993  {
994  // If all of the features are at the one point, buffer the
995  // rectangle a bit. If they are all at zero, do something a bit
996  // more crude.
997 
998  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
999  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
1000  {
1001  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
1002  }
1003  else
1004  {
1005  const double padFactor = 1e-8;
1006  double widthPad = mFullExtent.xMinimum() * padFactor;
1007  double heightPad = mFullExtent.yMinimum() * padFactor;
1008  double xmin = mFullExtent.xMinimum() - widthPad;
1009  double xmax = mFullExtent.xMaximum() + widthPad;
1010  double ymin = mFullExtent.yMinimum() - heightPad;
1011  double ymax = mFullExtent.yMaximum() + heightPad;
1012  mFullExtent.set( xmin, ymin, xmax, ymax );
1013  }
1014  }
1015 
1016  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
1017 }
1018 
1020 {
1021  updateFullExtent();
1022  return mFullExtent;
1023 }
1024 
1025 void QgsMapRenderer::setLayerSet( const QStringList& layers )
1026 {
1027  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
1028  mLayerSet = layers;
1029  updateFullExtent();
1030 }
1031 
1033 {
1034  return mLayerSet;
1035 }
1036 
1037 bool QgsMapRenderer::readXML( QDomNode & theNode )
1038 {
1039  QDomNode myNode = theNode.namedItem( "units" );
1040  QDomElement element = myNode.toElement();
1041 
1042  // set units
1043  QGis::UnitType units;
1044  if ( "meters" == element.text() )
1045  {
1046  units = QGis::Meters;
1047  }
1048  else if ( "feet" == element.text() )
1049  {
1050  units = QGis::Feet;
1051  }
1052  else if ( "degrees" == element.text() )
1053  {
1054  units = QGis::Degrees;
1055  }
1056  else if ( "unknown" == element.text() )
1057  {
1058  units = QGis::UnknownUnit;
1059  }
1060  else
1061  {
1062  QgsDebugMsg( "Unknown map unit type " + element.text() );
1063  units = QGis::Degrees;
1064  }
1065  setMapUnits( units );
1066 
1067  // set projections flag
1068  QDomNode projNode = theNode.namedItem( "projections" );
1069  element = projNode.toElement();
1070  setProjectionsEnabled( element.text().toInt() );
1071 
1072  // set destination CRS
1074  QDomNode srsNode = theNode.namedItem( "destinationsrs" );
1075  srs.readXML( srsNode );
1076  setDestinationCrs( srs );
1077 
1078  // set extent
1079  QgsRectangle aoi;
1080  QDomNode extentNode = theNode.namedItem( "extent" );
1081 
1082  QDomNode xminNode = extentNode.namedItem( "xmin" );
1083  QDomNode yminNode = extentNode.namedItem( "ymin" );
1084  QDomNode xmaxNode = extentNode.namedItem( "xmax" );
1085  QDomNode ymaxNode = extentNode.namedItem( "ymax" );
1086 
1087  QDomElement exElement = xminNode.toElement();
1088  double xmin = exElement.text().toDouble();
1089  aoi.setXMinimum( xmin );
1090 
1091  exElement = yminNode.toElement();
1092  double ymin = exElement.text().toDouble();
1093  aoi.setYMinimum( ymin );
1094 
1095  exElement = xmaxNode.toElement();
1096  double xmax = exElement.text().toDouble();
1097  aoi.setXMaximum( xmax );
1098 
1099  exElement = ymaxNode.toElement();
1100  double ymax = exElement.text().toDouble();
1101  aoi.setYMaximum( ymax );
1102 
1103  setExtent( aoi );
1104  return true;
1105 }
1106 
1107 bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc )
1108 {
1109  // units
1110 
1111  QDomElement unitsNode = theDoc.createElement( "units" );
1112  theNode.appendChild( unitsNode );
1113 
1114  QString unitsString;
1115 
1116  switch ( mapUnits() )
1117  {
1118  case QGis::Meters:
1119  unitsString = "meters";
1120  break;
1121  case QGis::Feet:
1122  unitsString = "feet";
1123  break;
1124  case QGis::Degrees:
1125  unitsString = "degrees";
1126  break;
1127  case QGis::UnknownUnit:
1128  default:
1129  unitsString = "unknown";
1130  break;
1131  }
1132  QDomText unitsText = theDoc.createTextNode( unitsString );
1133  unitsNode.appendChild( unitsText );
1134 
1135 
1136  // Write current view extents
1137  QDomElement extentNode = theDoc.createElement( "extent" );
1138  theNode.appendChild( extentNode );
1139 
1140  QDomElement xMin = theDoc.createElement( "xmin" );
1141  QDomElement yMin = theDoc.createElement( "ymin" );
1142  QDomElement xMax = theDoc.createElement( "xmax" );
1143  QDomElement yMax = theDoc.createElement( "ymax" );
1144 
1145  QgsRectangle r = extent();
1146  QDomText xMinText = theDoc.createTextNode( qgsDoubleToString( r.xMinimum() ) );
1147  QDomText yMinText = theDoc.createTextNode( qgsDoubleToString( r.yMinimum() ) );
1148  QDomText xMaxText = theDoc.createTextNode( qgsDoubleToString( r.xMaximum() ) );
1149  QDomText yMaxText = theDoc.createTextNode( qgsDoubleToString( r.yMaximum() ) );
1150 
1151  xMin.appendChild( xMinText );
1152  yMin.appendChild( yMinText );
1153  xMax.appendChild( xMaxText );
1154  yMax.appendChild( yMaxText );
1155 
1156  extentNode.appendChild( xMin );
1157  extentNode.appendChild( yMin );
1158  extentNode.appendChild( xMax );
1159  extentNode.appendChild( yMax );
1160 
1161  // projections enabled
1162  QDomElement projNode = theDoc.createElement( "projections" );
1163  theNode.appendChild( projNode );
1164 
1165  QDomText projText = theDoc.createTextNode( QString::number( hasCrsTransformEnabled() ) );
1166  projNode.appendChild( projText );
1167 
1168  // destination CRS
1169  QDomElement srsNode = theDoc.createElement( "destinationsrs" );
1170  theNode.appendChild( srsNode );
1171  destinationCrs().writeXML( srsNode, theDoc );
1172 
1173  return true;
1174 }
1175 
1177 {
1178  if ( mLabelingEngine )
1179  delete mLabelingEngine;
1180 
1181  mLabelingEngine = iface;
1182 }
1183 
1185 {
1186  if ( !layer || !mDestCRS )
1187  {
1188  return 0;
1189  }
1191 }
1192 
1195 QPainter::CompositionMode QgsMapRenderer::getCompositionMode( const QgsMapRenderer::BlendMode blendMode )
1196 {
1197  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1198  switch ( blendMode )
1199  {
1201  return QPainter::CompositionMode_SourceOver;
1203  return QPainter::CompositionMode_Lighten;
1205  return QPainter::CompositionMode_Screen;
1207  return QPainter::CompositionMode_ColorDodge;
1209  return QPainter::CompositionMode_Plus;
1211  return QPainter::CompositionMode_Darken;
1213  return QPainter::CompositionMode_Multiply;
1215  return QPainter::CompositionMode_ColorBurn;
1217  return QPainter::CompositionMode_Overlay;
1219  return QPainter::CompositionMode_SoftLight;
1221  return QPainter::CompositionMode_HardLight;
1223  return QPainter::CompositionMode_Difference;
1225  return QPainter::CompositionMode_Exclusion;
1226  default:
1227  return QPainter::CompositionMode_SourceOver;
1228  }
1229 }
1230 
1231 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( const QPainter::CompositionMode blendMode )
1232 {
1233  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1234  switch ( blendMode )
1235  {
1236  case QPainter::CompositionMode_SourceOver:
1238  case QPainter::CompositionMode_Lighten:
1240  case QPainter::CompositionMode_Screen:
1242  case QPainter::CompositionMode_ColorDodge:
1244  case QPainter::CompositionMode_Plus:
1246  case QPainter::CompositionMode_Darken:
1248  case QPainter::CompositionMode_Multiply:
1250  case QPainter::CompositionMode_ColorBurn:
1252  case QPainter::CompositionMode_Overlay:
1254  case QPainter::CompositionMode_SoftLight:
1256  case QPainter::CompositionMode_HardLight:
1258  case QPainter::CompositionMode_Difference:
1260  case QPainter::CompositionMode_Exclusion:
1262  default:
1264  }
1265 }
1266 
1267 bool QgsMapRenderer::mDrawing = false;
virtual void exit()=0
called when we're done with rendering
void setMapUnits(QGis::UnitType mapUnits)
Set the map units.
void unionRect(const QgsRectangle &rect)
updates rectangle to include passed argument
void setRenderingStopped(bool stopped)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:45
void render(QPainter *painter, double *forceWidthScale=0)
starts rendering @ param forceWidthScale Force a specific scale factor for line widths and marker siz...
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.
virtual void drawLabels(QgsRenderContext &rendererContext)
Draw labels.
static QgsMapRenderer::BlendMode getBlendModeEnum(const QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode Added in 1.9.
void setYMaximum(double ymax)
Set maximum y value.
void drawError(QgsMapLayer *)
emitted when layer's draw() returned false
void setCacheImage(QImage *thepImage)
Set the QImage used for caching render operations.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:160
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:185
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
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:250
void setRendererScale(double scale)
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.
QImage * cacheImage()
Get the QImage used for caching render operations.
Definition: qgsmaplayer.h:365
void setProjectionsEnabled(bool enabled)
sets whether to use projections for this layer set
static bool mDrawing
indicates drawing in progress
static QPainter::CompositionMode getCompositionMode(const QgsMapRenderer::BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode Added in 1.9.
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
static QgsCoordinateTransformCache * instance()
Definition: qgscrscache.cpp:23
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
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
double x() const
Definition: qgspoint.h:110
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 setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
sets destination coordinate reference system
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints. The rectangle is.
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
void setSelectionColor(const QColor &color)
Added in QGIS v2.0.
const QgsCoordinateTransform * transform(const QString &srcAuthId, const QString &destAuthId)
Returns coordinate transformation.
Definition: qgscrscache.cpp:42
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.
void adjustExtentToSize()
adjust extent to fit the pixmap size
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:190
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:175
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
bool renderingStopped() const
bool hasCrsTransformEnabled() const
returns true if projections are enabled for this layer set
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:165
void setDrawEditingInformation(bool b)
bool setExtent(const QgsRectangle &extent)
sets extent and checks whether suitable (returns false if not)
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:316
bool hasScaleBasedVisibility()
void destinationSrsChanged()
void setPainter(QPainter *p)
double rasterScaleFactor() const
Reads and writes project states.
Definition: qgsproject.h:64
bool mOverview
indicates whether it's map image for overview
const QgsCoordinateTransform * tr(QgsMapLayer *layer)
QgsPoint transform(const QgsPoint p, TransformDirection direction=ForwardTransform) const
double mapUnitsPerPixel() const
Return current map units per pixel.
void setOutputSize(QSize size, int dpi)
float minimumScale()
void mapUnitsChanged()
A class to represent a point geometry.
Definition: qgspoint.h:63
float maximumScale()
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...
double rasterScaleFactor
Definition: qgssvgcache.cpp:78
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.
General purpose distance and area calculator.
QgsRectangle fullExtent()
returns current extent of layer set
QString what() const
Definition: qgsexception.h:35
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
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 setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:170
void onDrawingProgress(int current, int total)
called by signal from layer current being drawn
void setLabelingEngine(QgsLabelingEngineInterface *iface)
Added in QGIS v1.4.
double mScale
Map scale denominator at its current zoom level.
static QgsProject * instance()
access to canonical QgsProject instance
Definition: qgsproject.cpp:358
Class for storing a coordinate reference system (CRS)
void setMapToPixel(const QgsMapToPixel &mtp)
Class for doing transforms between two map coordinate systems.
UnitType
Map units that qgis supports.
Definition: qgis.h:188
const QgsMapToPixel & mapToPixel() const
void clearAllLayerCaches()
Clears all layer caches, resetting them to zero and freeing up any memory they may have been using...
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.
virtual bool willUseLayer(QgsVectorLayer *layer)=0
called to find out whether the layer is used for labeling
void updateScale()
Recalculate the map scale.
QStringList mLayerSet
stores array of layers to be rendered (identified by string)
void setRasterScaleFactor(double factor)
virtual void init(QgsMapRenderer *mp)=0
called when we're going to start with rendering
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:195
void setMapUnitsPerPixel(double mapUnitsPerPixel)
virtual bool isEditable() const
Returns true if the provider is in editing mode.
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:75
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:180
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:155
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
QgsLabelingEngineInterface * labelingEngine() const
Added in QGIS v1.4.
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:200
QString toProj4() const
Get the Proj Proj4 string representation of this srs.