QGIS API Documentation  2.15.0-Master (5773d0d)
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 
62 
63  mLabelingEngine = nullptr;
64  readDefaultDatumTransformations();
65 }
66 
68 {
69  delete mScaleCalculator;
70  delete mDistArea;
71  delete mDestCRS;
72  delete mLabelingEngine;
73 }
74 
76 {
77  return mExtent;
78 }
79 
81 {
83 }
84 
86 {
87  //remember the previous extent
89 
90  // Don't allow zooms where the current extent is so small that it
91  // can't be accurately represented using a double (which is what
92  // currentExtent uses). Excluding 0 avoids a divide by zero and an
93  // infinite loop when rendering to a new canvas. Excluding extents
94  // greater than 1 avoids doing unnecessary calculations.
95 
96  // The scheme is to compare the width against the mean x coordinate
97  // (and height against mean y coordinate) and only allow zooms where
98  // the ratio indicates that there is more than about 12 significant
99  // figures (there are about 16 significant figures in a double).
100 
101  if ( extent.width() > 0 &&
102  extent.height() > 0 &&
103  extent.width() < 1 &&
104  extent.height() < 1 )
105  {
106  // Use abs() on the extent to avoid the case where the extent is
107  // symmetrical about 0.
108  double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5;
109  double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5;
110 
111  double xRange = extent.width() / xMean;
112  double yRange = extent.height() / yMean;
113 
114  static const double minProportion = 1e-12;
115  if ( xRange < minProportion || yRange < minProportion )
116  return false;
117  }
118 
119  mExtent = extent;
120  if ( !extent.isEmpty() )
122 
123  emit extentsChanged();
124  return true;
125 }
126 
128 {
130  // TODO: adjust something ?
131 
132  emit rotationChanged( rotation );
133 }
134 
136 {
137  return mRotation;
138 }
139 
140 
141 void QgsMapRenderer::setOutputSize( QSize size, double dpi )
142 {
143  mSize = QSizeF( size.width(), size.height() );
144  mScaleCalculator->setDpi( dpi );
146 }
147 
148 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
149 {
150  mSize = size;
151  mScaleCalculator->setDpi( dpi );
153 }
154 
156 {
157  return mScaleCalculator->dpi();
158 }
159 
161 {
162  return mSize.toSize();
163 }
164 
166 {
167  return mSize;
168 }
169 
171 {
172  double myHeight = mSize.height();
173  double myWidth = mSize.width();
174 
175  QgsMapToPixel newCoordXForm;
176 
177  if ( !myWidth || !myHeight )
178  {
179  mScale = 1.0;
180  newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
181  return;
182  }
183 
184  // calculate the translation and scaling parameters
185  // mapUnitsPerPixel = map units per pixel
186  double mapUnitsPerPixelY = mExtent.height() / myHeight;
187  double mapUnitsPerPixelX = mExtent.width() / myWidth;
188  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
189 
190  // calculate the actual extent of the mapCanvas
191  double dxmin, dxmax, dymin, dymax, whitespace;
192 
193  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
194  {
195  dymin = mExtent.yMinimum();
196  dymax = mExtent.yMaximum();
197  whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
198  dxmin = mExtent.xMinimum() - whitespace;
199  dxmax = mExtent.xMaximum() + whitespace;
200  }
201  else
202  {
203  dxmin = mExtent.xMinimum();
204  dxmax = mExtent.xMaximum();
205  whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
206  dymin = mExtent.yMinimum() - whitespace;
207  dymax = mExtent.yMaximum() + whitespace;
208  }
209 
210  QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ) );
211  QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( myWidth ), qgsDoubleToString( myHeight ) ) );
212  QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ) );
214 
215  // update extent
216  mExtent.setXMinimum( dxmin );
217  mExtent.setXMaximum( dxmax );
218  mExtent.setYMinimum( dymin );
219  mExtent.setYMaximum( dymax );
220 
221  QgsDebugMsg( QString( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / myWidth ), qgsDoubleToString( mExtent.height() / myHeight ) ) );
222 
223  QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mExtent.height() / mMapUnitsPerPixel ) ) );
224 
225  // update the scale
226  updateScale();
227 
228  QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
229 
231  newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
233  mRenderContext.setMapToPixel( newCoordXForm );
235 }
236 
237 
238 void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
239 {
240  //Lock render method for concurrent threads (e.g. from globe)
241  QMutexLocker renderLock( &mRenderMutex );
242 
243  QgsDebugMsg( "========== Rendering ==========" );
244 
245  if ( mExtent.isEmpty() )
246  {
247  QgsDebugMsg( "empty extent... not rendering" );
248  return;
249  }
250 
251  if ( qgsDoubleNear( mSize.width(), 1.0 ) && qgsDoubleNear( mSize.height(), 1.0 ) )
252  {
253  QgsDebugMsg( "size 1x1... not rendering" );
254  return;
255  }
256 
257  QPaintDevice* thePaintDevice = painter->device();
258  if ( !thePaintDevice )
259  {
260  return;
261  }
262 
263  // wait
264  if ( mDrawing )
265  {
266  QgsDebugMsg( "already rendering" );
268  }
269 
270  if ( mDrawing )
271  {
272  QgsDebugMsg( "still rendering - skipping" );
273  return;
274  }
275 
276  mDrawing = true;
277 
278  const QgsCoordinateTransform *ct;
279 
280 #ifdef QGISDEBUG
281  QgsDebugMsg( "Starting to render layer stack." );
282  QTime renderTime;
283  renderTime.start();
284 #endif
285 
286  if ( mOverview )
288 
289  mRenderContext.setPainter( painter );
291  //this flag is only for stopping during the current rendering progress,
292  //so must be false at every new render operation
294 
295  // set selection color
297  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
298  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
299  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
300  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
301  mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
302 
303  //calculate scale factor
304  //use the specified dpi and not those from the paint device
305  //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene)
306  double sceneDpi = mScaleCalculator->dpi();
307  double scaleFactor = 1.0;
309  {
310  if ( forceWidthScale )
311  {
312  scaleFactor = *forceWidthScale;
313  }
314  else
315  {
316  scaleFactor = sceneDpi / 25.4;
317  }
318  }
319  double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
320  if ( !qgsDoubleNear( mRenderContext.rasterScaleFactor(), rasterScaleFactor ) )
321  {
322  mRenderContext.setRasterScaleFactor( rasterScaleFactor );
323  }
324  if ( !qgsDoubleNear( mRenderContext.scaleFactor(), scaleFactor ) )
325  {
326  mRenderContext.setScaleFactor( scaleFactor );
327  }
329  {
330  //add map scale to render context
332  }
333  if ( mLastExtent != mExtent )
334  {
336  }
337 
339  if ( mLabelingEngine )
341 
342  // render all layers in the stack, starting at the base
344  li.toBack();
345 
346  QgsRectangle r1, r2;
347 
348  while ( li.hasPrevious() )
349  {
351  {
352  break;
353  }
354 
355  // Store the painter in case we need to swap it out for the
356  // cache painter
357  QPainter * mypContextPainter = mRenderContext.painter();
358  // Flattened image for drawing when a blending mode is set
359  QImage * mypFlattenedImage = nullptr;
360 
361  QString layerId = li.previous();
362 
363  QgsDebugMsg( "Rendering at layer item " + layerId );
364 
365  // This call is supposed to cause the progress bar to
366  // advance. However, it seems that updating the progress bar is
367  // incompatible with having a QPainter active (the one that is
368  // passed into this function), as Qt produces a number of errors
369  // when try to do so. I'm (Gavin) not sure how to fix this, but
370  // added these comments and debug statement to help others...
371  QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
372 
373  //emit drawingProgress(myRenderCounter++, mLayerSet.size());
375 
376  if ( !ml )
377  {
378  QgsDebugMsg( "Layer not found in registry!" );
379  continue;
380  }
381 
382  QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
383  .arg( ml->name() )
384  .arg( ml->minimumScale() )
385  .arg( ml->maximumScale() )
386  .arg( ml->hasScaleBasedVisibility() )
387  .arg( ml->extent().toString() )
388  .arg( ml->blendMode() )
389  );
390 
392  {
393  // Set the QPainter composition mode so that this layer is rendered using
394  // the desired blending mode
395  mypContextPainter->setCompositionMode( ml->blendMode() );
396  }
397 
398  if ( ml->isInScaleRange( mScale ) || mOverview )
399  {
400  connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
401 
402  //
403  // Now do the call to the layer that actually does
404  // the rendering work!
405  //
406 
407  bool split = false;
408 
409  if ( hasCrsTransformEnabled() )
410  {
411  r1 = mExtent;
412  split = splitLayersExtent( ml, r1, r2 );
413  ct = transformation( ml );
415  QgsDebugMsg( " extent 1: " + r1.toString() );
416  QgsDebugMsg( " extent 2: " + r2.toString() );
417  if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
418  {
419  continue;
420  }
421  }
422  else
423  {
424  ct = nullptr;
425  }
426 
428 
429  //decide if we have to scale the raster
430  //this is necessary in case QGraphicsScene is used
431  bool scaleRaster = false;
432  QgsMapToPixel rasterMapToPixel;
433  QgsMapToPixel bk_mapToPixel;
434 
435  if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 )
436  {
437  scaleRaster = true;
438  }
439 
440  QSettings mySettings;
441 
442  // If we are drawing with an alternative blending mode then we need to render to a separate image
443  // before compositing this on the map. This effectively flattens the layer and prevents
444  // blending occurring between objects on the layer
445  // (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
446  bool flattenedLayer = false;
448  {
449  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
450  if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver )
451  || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
452  || ( vl->layerTransparency() != 0 ) ) )
453  {
454  flattenedLayer = true;
455  mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
456  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
457  if ( mypFlattenedImage->isNull() )
458  {
459  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + 'x' + QString::number( mRenderContext.painter()->device()->height() ) );
460  emit drawError( ml );
461  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
462  return;
463  }
464  mypFlattenedImage->fill( 0 );
465  QPainter * mypPainter = new QPainter( mypFlattenedImage );
466  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
467  {
468  mypPainter->setRenderHint( QPainter::Antialiasing );
469  }
470  mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
471  mRenderContext.setPainter( mypPainter );
472  }
473  }
474 
475  // Per feature blending mode
477  {
478  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
479  if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
480  {
481  // set the painter to the feature blend mode, so that features drawn
482  // on this layer will interact and blend with each other
484  }
485  }
486 
487  if ( scaleRaster )
488  {
489  bk_mapToPixel = mRenderContext.mapToPixel();
490  rasterMapToPixel = mRenderContext.mapToPixel();
491  rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor );
493  rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
495  mRenderContext.setMapToPixel( rasterMapToPixel );
497  mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
498  }
499 
500  if ( !ml->draw( mRenderContext ) )
501  {
502  emit drawError( ml );
503  }
504  else
505  {
506  QgsDebugMsg( "Layer rendered without issues" );
507  }
508 
509  if ( split )
510  {
512  if ( !ml->draw( mRenderContext ) )
513  {
514  emit drawError( ml );
515  }
516  }
517 
518  if ( scaleRaster )
519  {
520  mRenderContext.setMapToPixel( bk_mapToPixel );
522  }
523 
524  //apply layer transparency for vector layers
526  {
527  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
528  if ( vl->layerTransparency() != 0 )
529  {
530  // a layer transparency has been set, so update the alpha for the flattened layer
531  // by combining it with the layer transparency
532  QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
533  // use destination in composition mode to merge source's alpha with destination
534  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
536  mRenderContext.painter()->device()->height(), transparentFillColor );
537  }
538  }
539 
540  if ( flattenedLayer )
541  {
542  // If we flattened this layer for alternate blend modes, composite it now
543  delete mRenderContext.painter();
544  mRenderContext.setPainter( mypContextPainter );
545  mypContextPainter->save();
546  mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
547  mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) );
548  mypContextPainter->restore();
549  delete mypFlattenedImage;
550  mypFlattenedImage = nullptr;
551  }
552 
553  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
554  }
555  else // layer not visible due to scale
556  {
557  QgsDebugMsg( "Layer not rendered because it is not within the defined "
558  "visibility scale range" );
559  }
560 
561  } // while (li.hasPrevious())
562 
563  QgsDebugMsg( "Done rendering map layers" );
564 
565  // Reset the composition mode before rendering the labels
566  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_SourceOver );
567 
568  if ( !mOverview )
569  {
570  // render all labels for vector layers in the stack, starting at the base
571  li.toBack();
572  while ( li.hasPrevious() )
573  {
575  {
576  break;
577  }
578 
579  QString layerId = li.previous();
580 
581  // TODO: emit drawingProgress((myRenderCounter++),zOrder.size());
583 
584  if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
585  {
586  // only make labels if the layer is visible
587  // after scale dep viewing settings are checked
588  if ( ml->isInScaleRange( mScale ) )
589  {
590  bool split = false;
591 
592  if ( hasCrsTransformEnabled() )
593  {
594  QgsRectangle r1 = mExtent;
595  split = splitLayersExtent( ml, r1, r2 );
596  ct = transformation( ml );
598  }
599  else
600  {
601  ct = nullptr;
602  }
603 
605 
606  ml->drawLabels( mRenderContext );
607  if ( split )
608  {
610  ml->drawLabels( mRenderContext );
611  }
612  }
613  }
614  }
615  } // if (!mOverview)
616 
617  // make sure progress bar arrives at 100%!
618  emit drawingProgress( 1, 1 );
619 
620  if ( mLabelingEngine )
621  {
622  // set correct extent
625 
628  }
629 
630  QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
631 
632  mDrawing = false;
633 }
634 
636 {
638 
639  // Since the map units have changed, force a recalculation of the scale.
640  updateScale();
641 
642  emit mapUnitsChanged();
643 }
644 
646 {
647  return mScaleCalculator->mapUnits();
648 }
649 
650 void QgsMapRenderer::onDrawingProgress( int current, int total )
651 {
652  Q_UNUSED( current );
653  Q_UNUSED( total );
654 }
655 
657 {
658  if ( mProjectionsEnabled != enabled )
659  {
660  mProjectionsEnabled = enabled;
661  QgsDebugMsg( "Adjusting DistArea projection on/off" );
662  mDistArea->setEllipsoidalMode( enabled );
665 
667  emit hasCrsTransformEnabled( enabled ); // deprecated
669 
670  emit hasCrsTransformEnabledChanged( enabled );
671  }
672 }
673 
675 {
676  return mProjectionsEnabled;
677 }
678 
679 void QgsMapRenderer::setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo, bool transformExtent )
680 {
681  QgsDebugMsg( "* Setting destCRS : = " + crs.toProj4() );
682  QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( crs.srsid() ) );
683  if ( *mDestCRS != crs )
684  {
685  if ( refreshCoordinateTransformInfo )
686  {
688  }
689  QgsRectangle rect;
690  if ( transformExtent && !mExtent.isEmpty() )
691  {
692  QgsCoordinateTransform transform( *mDestCRS, crs );
693  try
694  {
695  rect = transform.transformBoundingBox( mExtent );
696  }
697  catch ( QgsCsException &e )
698  {
699  Q_UNUSED( e );
700  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
701  }
702  }
703 
704  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
705  mDistArea->setSourceCrs( crs.srsid() );
706  *mDestCRS = crs;
708 
709  if ( !rect.isEmpty() )
710  {
711  setExtent( rect );
712  }
713 
714  emit destinationSrsChanged();
715  }
716 }
717 
719 {
720  QgsDebugMsgLevel( "* Returning destCRS", 3 );
721  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
722  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
723  return *mDestCRS;
724 }
725 
726 
728 {
729  bool split = false;
730 
731  if ( hasCrsTransformEnabled() )
732  {
733  try
734  {
735 #ifdef QGISDEBUG
736  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
737 #endif
738  // Split the extent into two if the source CRS is
739  // geographic and the extent crosses the split in
740  // geographic coordinates (usually +/- 180 degrees,
741  // and is assumed to be so here), and draw each
742  // extent separately.
743  static const double splitCoord = 180.0;
744 
745  const QgsCoordinateTransform *transform = transformation( layer );
746  if ( layer->crs().geographicFlag() )
747  {
748  // Note: ll = lower left point
749  // and ur = upper right point
750 
751  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
752  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
753 
754  if ( transform )
755  {
756  ll = transform->transform( ll.x(), ll.y(),
758  ur = transform->transform( ur.x(), ur.y(),
760  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
761  }
762 
763  if ( ll.x() > ur.x() )
764  {
765  r2 = extent;
766  extent.setXMinimum( splitCoord );
767  r2.setXMaximum( splitCoord );
768  split = true;
769  }
770  }
771  else // can't cross 180
772  {
773  if ( transform )
774  {
775  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
776  }
777  }
778  }
779  catch ( QgsCsException &cse )
780  {
781  Q_UNUSED( cse );
782  QgsDebugMsg( "Transform error caught" );
783  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
784  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
785  }
786  }
787  return split;
788 }
789 
791 {
792  //QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
793  //QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
794  //QgsDebugMsg( QString( "extent = " + extent.toString() ) );
795  if ( hasCrsTransformEnabled() )
796  {
797  try
798  {
799  const QgsCoordinateTransform *transform = transformation( theLayer );
800  if ( transform )
801  {
802  extent = transform->transformBoundingBox( extent );
803  }
804  }
805  catch ( QgsCsException &cse )
806  {
807  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
808  }
809  }
810 
811  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
812 
813  return extent;
814 }
815 
817 {
818 #if QGISDEBUG
819  const QgsCoordinateTransform *transform = transformation( theLayer );
820  QgsDebugMsg( QString( "layer sourceCrs = " + ( transform ? transform->sourceCrs().authid() : "none" ) ) );
821  QgsDebugMsg( QString( "layer destCRS = " + ( transform ? transform->destCRS().authid() : "none" ) ) );
822  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
823 #endif
824  if ( hasCrsTransformEnabled() )
825  {
826  try
827  {
828  const QgsCoordinateTransform *transform = transformation( theLayer );
829  if ( transform )
830  {
831  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
832  }
833  }
834  catch ( QgsCsException &cse )
835  {
836  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
837  }
838  }
839 
840  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
841 
842  return extent;
843 }
844 
846 {
847  if ( hasCrsTransformEnabled() )
848  {
849  try
850  {
851  const QgsCoordinateTransform *transform = transformation( theLayer );
852  if ( transform )
853  {
854  point = transform->transform( point, QgsCoordinateTransform::ForwardTransform );
855  }
856  }
857  catch ( QgsCsException &cse )
858  {
859  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
860  }
861  }
862  else
863  {
864  // leave point without transformation
865  }
866  return point;
867 }
868 
870 {
871  if ( hasCrsTransformEnabled() )
872  {
873  try
874  {
875  const QgsCoordinateTransform *transform = transformation( theLayer );
876  if ( transform )
877  {
878  rect = transform->transform( rect, QgsCoordinateTransform::ForwardTransform );
879  }
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 rect;
891 }
892 
894 {
895  if ( hasCrsTransformEnabled() )
896  {
897  try
898  {
899  const QgsCoordinateTransform *transform = transformation( theLayer );
900  if ( transform )
901  point = transform->transform( point, QgsCoordinateTransform::ReverseTransform );
902  }
903  catch ( QgsCsException &cse )
904  {
905  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
906  }
907  }
908  else
909  {
910  // leave point without transformation
911  }
912  return point;
913 }
914 
916 {
917  if ( hasCrsTransformEnabled() )
918  {
919  try
920  {
921  const QgsCoordinateTransform *transform = transformation( theLayer );
922  if ( transform )
923  rect = transform->transform( rect, QgsCoordinateTransform::ReverseTransform );
924  }
925  catch ( QgsCsException &cse )
926  {
927  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
928  }
929  }
930  return rect;
931 }
932 
934 {
936 }
937 
939 {
940  QgsDebugMsg( "called." );
941 
942  if ( !mFullExtent.isNull() )
943  return mFullExtent;
944 
946 
947  // iterate through the map layers and test each layers extent
948  // against the current min and max values
949  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
950  Q_FOREACH ( const QString layerId, mLayerSet )
951  {
952  QgsMapLayer * lyr = registry->mapLayer( layerId );
953  if ( !lyr )
954  {
955  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( layerId ) );
956  }
957  else
958  {
959  QgsDebugMsg( "Updating extent using " + lyr->name() );
960  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
961 
962  if ( lyr->extent().isNull() )
963  {
964  continue;
965  }
966 
967  // Layer extents are stored in the coordinate system (CS) of the
968  // layer. The extent must be projected to the canvas CS
970 
971  QgsDebugMsg( "Output extent: " + extent.toString() );
972  mFullExtent.unionRect( extent );
973 
974  }
975  }
976 
977  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
978  {
979  // If all of the features are at the one point, buffer the
980  // rectangle a bit. If they are all at zero, do something a bit
981  // more crude.
982 
983  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
984  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
985  {
986  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
987  }
988  else
989  {
990  const double padFactor = 1e-8;
991  double widthPad = mFullExtent.xMinimum() * padFactor;
992  double heightPad = mFullExtent.yMinimum() * padFactor;
993  double xmin = mFullExtent.xMinimum() - widthPad;
994  double xmax = mFullExtent.xMaximum() + widthPad;
995  double ymin = mFullExtent.yMinimum() - heightPad;
996  double ymax = mFullExtent.yMaximum() + heightPad;
997  mFullExtent.set( xmin, ymin, xmax, ymax );
998  }
999  }
1000 
1001  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
1002 
1003  return mFullExtent;
1004 }
1005 
1007 {
1008  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
1009  mLayerSet = layers;
1010  updateFullExtent();
1011 }
1012 
1014 {
1015  return mLayerSet;
1016 }
1017 
1019 {
1020  QgsMapSettings tmpSettings;
1021  tmpSettings.readXML( theNode );
1022  //load coordinate transform into
1024  QDomElement layerCoordTransformInfoElem = theNode.firstChildElement( "layer_coordinate_transform_info" );
1025  if ( !layerCoordTransformInfoElem.isNull() )
1026  {
1027  QDomNodeList layerCoordinateTransformList = layerCoordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
1028  QDomElement layerCoordTransformElem;
1029  for ( int i = 0; i < layerCoordinateTransformList.size(); ++i )
1030  {
1031  layerCoordTransformElem = layerCoordinateTransformList.at( i ).toElement();
1032  QString layerId = layerCoordTransformElem.attribute( "layerid" );
1033  if ( layerId.isEmpty() )
1034  {
1035  continue;
1036  }
1037 
1039  lct.srcAuthId = layerCoordTransformElem.attribute( "srcAuthId" );
1040  lct.destAuthId = layerCoordTransformElem.attribute( "destAuthId" );
1041  lct.srcDatumTransform = layerCoordTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
1042  lct.destDatumTransform = layerCoordTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
1043  mLayerCoordinateTransformInfo.insert( layerId, lct );
1044  }
1045  }
1046 
1047 
1048  setMapUnits( tmpSettings.mapUnits() );
1049  setExtent( tmpSettings.extent() );
1051  setDestinationCrs( tmpSettings.destinationCrs() );
1052 
1053 
1054  return true;
1055 }
1056 
1058 {
1059  QgsMapSettings tmpSettings;
1060  tmpSettings.setOutputDpi( outputDpi() );
1061  tmpSettings.setOutputSize( outputSize() );
1062  tmpSettings.setMapUnits( mapUnits() );
1063  tmpSettings.setExtent( extent() );
1065  tmpSettings.setDestinationCrs( destinationCrs() );
1066 
1067  tmpSettings.writeXML( theNode, theDoc );
1068  // layer coordinate transform infos
1069  QDomElement layerCoordTransformInfo = theDoc.createElement( "layer_coordinate_transform_info" );
1071  for ( ; coordIt != mLayerCoordinateTransformInfo.constEnd(); ++coordIt )
1072  {
1073  QDomElement layerCoordTransformElem = theDoc.createElement( "layer_coordinate_transform" );
1074  layerCoordTransformElem.setAttribute( "layerid", coordIt.key() );
1075  layerCoordTransformElem.setAttribute( "srcAuthId", coordIt->srcAuthId );
1076  layerCoordTransformElem.setAttribute( "destAuthId", coordIt->destAuthId );
1077  layerCoordTransformElem.setAttribute( "srcDatumTransform", QString::number( coordIt->srcDatumTransform ) );
1078  layerCoordTransformElem.setAttribute( "destDatumTransform", QString::number( coordIt->destDatumTransform ) );
1079  layerCoordTransformInfo.appendChild( layerCoordTransformElem );
1080  }
1081  theNode.appendChild( layerCoordTransformInfo );
1082  return true;
1083 }
1084 
1086 {
1087  if ( mLabelingEngine )
1088  delete mLabelingEngine;
1089 
1090  mLabelingEngine = iface;
1091 }
1092 
1094 {
1095  if ( !layer || !mDestCRS )
1096  {
1097  return nullptr;
1098  }
1099 
1100  if ( layer->crs().authid() == mDestCRS->authid() )
1101  {
1102  return nullptr;
1103  }
1104 
1107  && ctIt->srcAuthId == layer->crs().authid()
1108  && ctIt->destAuthId == mDestCRS->authid() )
1109  {
1110  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1111  }
1112  else
1113  {
1114  //is there a defined datum transformation?
1115  QHash< QPair< QString, QString >, QPair< int, int > >::const_iterator it = mDefaultDatumTransformations.find( qMakePair( layer->crs().authid(), mDestCRS->authid() ) );
1116  if ( it != mDefaultDatumTransformations.constEnd() )
1117  {
1118  return QgsCoordinateTransformCache::instance()->transform( it.key().first, it.key().second, it.value().first, it.value().second );
1119  }
1120  emit datumTransformInfoRequested( layer, layer->crs().authid(), mDestCRS->authid() );
1121  }
1122 
1123  //still not present? get coordinate transformation with -1/-1 datum transform as default
1124  ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1126  || ctIt->srcAuthId == layer->crs().authid()
1127  || ctIt->destAuthId == mDestCRS->authid()
1128  )
1129  {
1131  }
1132  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1133 }
1134 
1138 {
1139  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1140  switch ( blendMode )
1141  {
1143  return QPainter::CompositionMode_SourceOver;
1145  return QPainter::CompositionMode_Lighten;
1147  return QPainter::CompositionMode_Screen;
1149  return QPainter::CompositionMode_ColorDodge;
1151  return QPainter::CompositionMode_Plus;
1153  return QPainter::CompositionMode_Darken;
1155  return QPainter::CompositionMode_Multiply;
1157  return QPainter::CompositionMode_ColorBurn;
1159  return QPainter::CompositionMode_Overlay;
1161  return QPainter::CompositionMode_SoftLight;
1163  return QPainter::CompositionMode_HardLight;
1165  return QPainter::CompositionMode_Difference;
1167  return QPainter::CompositionMode_Exclusion;
1169  return QPainter::CompositionMode_Source;
1171  return QPainter::CompositionMode_DestinationOver;
1173  return QPainter::CompositionMode_Clear;
1175  return QPainter::CompositionMode_Destination;
1177  return QPainter::CompositionMode_SourceIn;
1179  return QPainter::CompositionMode_DestinationIn;
1181  return QPainter::CompositionMode_SourceOut;
1183  return QPainter::CompositionMode_DestinationOut;
1185  return QPainter::CompositionMode_SourceAtop;
1187  return QPainter::CompositionMode_DestinationAtop;
1189  return QPainter::CompositionMode_Xor;
1190  default:
1191  QgsDebugMsg( QString( "Blend mode %1 mapped to SourceOver" ).arg( blendMode ) );
1192  return QPainter::CompositionMode_SourceOver;
1193  }
1194 }
1195 
1196 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( QPainter::CompositionMode blendMode )
1197 {
1198  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1199  switch ( blendMode )
1200  {
1201  case QPainter::CompositionMode_SourceOver:
1203  case QPainter::CompositionMode_Lighten:
1205  case QPainter::CompositionMode_Screen:
1207  case QPainter::CompositionMode_ColorDodge:
1209  case QPainter::CompositionMode_Plus:
1211  case QPainter::CompositionMode_Darken:
1213  case QPainter::CompositionMode_Multiply:
1215  case QPainter::CompositionMode_ColorBurn:
1217  case QPainter::CompositionMode_Overlay:
1219  case QPainter::CompositionMode_SoftLight:
1221  case QPainter::CompositionMode_HardLight:
1223  case QPainter::CompositionMode_Difference:
1225  case QPainter::CompositionMode_Exclusion:
1227  case QPainter::CompositionMode_Source:
1229  case QPainter::CompositionMode_DestinationOver:
1231  case QPainter::CompositionMode_Clear:
1233  case QPainter::CompositionMode_Destination:
1235  case QPainter::CompositionMode_SourceIn:
1237  case QPainter::CompositionMode_DestinationIn:
1239  case QPainter::CompositionMode_SourceOut:
1241  case QPainter::CompositionMode_DestinationOut:
1243  case QPainter::CompositionMode_SourceAtop:
1245  case QPainter::CompositionMode_DestinationAtop:
1247  case QPainter::CompositionMode_Xor:
1248  return QgsMapRenderer::BlendXor;
1249  default:
1250  QgsDebugMsg( QString( "Composition mode %1 mapped to Normal" ).arg( blendMode ) );
1252  }
1253 }
1254 
1255 Q_GUI_EXPORT extern int qt_defaultDpiX();
1256 
1258 {
1259  // make sure the settings object is up-to-date
1267  return mMapSettings;
1268 }
1269 
1270 void QgsMapRenderer::addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform, int destDatumTransform )
1271 {
1273  lt.srcAuthId = srcAuthId;
1274  lt.destAuthId = destAuthId;
1275  lt.srcDatumTransform = srcDatumTransform;
1276  lt.destDatumTransform = destDatumTransform;
1277  mLayerCoordinateTransformInfo.insert( layerId, lt );
1278 }
1279 
1281 {
1283 }
1284 
1285 void QgsMapRenderer::readDefaultDatumTransformations()
1286 {
1287  const char* envChar = getenv( "DEFAULT_DATUM_TRANSFORM" );
1288  if ( envChar )
1289  {
1290  QString envString( envChar );
1291  QStringList transformSplit = envString.split( ";" );
1292  for ( int i = 0; i < transformSplit.size(); ++i )
1293  {
1294  QStringList slashSplit = transformSplit.at( i ).split( "/" );
1295  if ( slashSplit.size() < 4 )
1296  {
1297  continue;
1298  }
1299 
1300  mDefaultDatumTransformations.insert( qMakePair( slashSplit.at( 0 ), slashSplit.at( 1 ) ), qMakePair( slashSplit.at( 2 ).toInt(), slashSplit.at( 3 ).toInt() ) );
1301  }
1302  }
1303 }
1304 
1305 bool QgsMapRenderer::mDrawing = false;
const QgsMapSettings & mapSettings()
bridge to QgsMapSettings
virtual void exit()=0
called when we&#39;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.
QDomNodeList elementsByTagName(const QString &tagname) const
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&#39;re going to start with rendering
void setRenderingStopped(bool stopped)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
Base class for all map layer types.
Definition: qgsmaplayer.h:49
void clearLayerCoordinateTransforms()
void setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
void setLabelingEngine(QgsLabelingEngineInterface *iface)
Set labeling engine.
bool isEmpty() const
test if rectangle is empty.
iterator insert(const Key &key, const T &value)
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:97
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
int width() const
virtual void drawLabels(QgsRenderContext &rendererContext)
Draw labels.
bool end()
const Key key(const T &value) const
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(CompositionMode mode)
void drawError(QgsMapLayer *)
emitted when layer&#39;s draw() returned false
QString name() const
Get the display name of the layer.
void setRenderHint(RenderHint hint, bool on)
QDomNode appendChild(const QDomNode &newChild)
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:172
void readXML(QDomNode &theNode)
const T & previous()
OutputUnits mOutputUnits
Output units.
QString attribute(const QString &name, const QString &defValue) const
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:197
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
long srsid() const
Returns the SrsId, if available.
bool mProjectionsEnabled
detemines whether on the fly projection support is enabled
double maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
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 scale(qreal sx, qreal sy)
void addLayerCoordinateTransform(const QString &layerId, const QString &srcAuthId, const QString &destAuthId, int srcDatumTransform=-1, int destDatumTransform=-1)
void setRendererScale(double scale)
const T & at(int i) const
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
void setOutputDpi(double dpi)
Set DPI used for conversion between real world units (e.g. mm) and pixels.
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:514
void drawingProgress(int current, int total)
static QgsMapRenderer::BlendMode getBlendModeEnum(QPainter::CompositionMode blendMode)
Returns a BlendMode corresponding to a QPainter::CompositionMode.
~QgsMapRenderer()
destructor
void save()
void setDpi(double dpi)
Set the dpi to be used in scale calculations.
Q_DECL_DEPRECATED void setParameters(double mapUnitsPerPixel, double xmin, double ymin, double height)
Set parameters for use in transforming coordinates.
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
Transform the point from Source Coordinate System to Destination Coordinate System If the direction i...
QString join(const QString &separator) const
double scaleFactor() const
bool isNull() const
QHash< QPair< QString, QString >, QPair< int, int > > mDefaultDatumTransformations
void setLayerSet(const QStringList &layers)
change current layer set
double outputDpi()
accessor for output dpi
Q_DECL_DEPRECATED void setYMaximum(double yMax)
Set maximum y value.
QgsPoint mapToLayerCoordinates(QgsMapLayer *theLayer, QgsPoint point)
transform point coordinates from output CRS to layer&#39;s CRS
void setLayers(const QStringList &layers)
Set list of layer IDs for map rendering.
static QgsCoordinateTransformCache * instance()
Definition: qgscrscache.cpp:22
QgsRectangle outputExtentToLayerExtent(QgsMapLayer *theLayer, QgsRectangle extent)
transform bounding box from output CRS to layer&#39;s CRS
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setExtent(const QgsRectangle &extent)
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:352
const QgsCoordinateTransform * transformation(const QgsMapLayer *layer) const
BlendMode
Blending modes enum defining the available composition modes that can be used when rendering a layer...
QgsRectangle mExtent
current extent to be drawn
int size() const
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
QgsMapRenderer()
constructor
QgsPoint layerToMapCoordinates(QgsMapLayer *theLayer, QgsPoint point)
transform point coordinates from layer&#39;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.
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.
int width() const
QDomElement toElement() const
double mRotation
Map rotation.
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:41
void setSelectionColor(const QColor &color)
int elapsed() const
QString number(int n, int base)
int count(const T &value) const
void extentsChanged()
emitted when the current extent gets changed
QPainter::CompositionMode blendMode() const
Returns the current blending mode for a layer.
void processEvents(QFlags< QEventLoop::ProcessEventsFlag > flags)
void setOutputSize(QSize size)
Set the size of the resulting map image.
QgsCoordinateReferenceSystem * mDestCRS
destination spatial reference system of the projection
void setScaleFactor(double factor)
QgsDistanceArea * mDistArea
tool for measuring
QPainter::CompositionMode featureBlendMode() const
Returns the current blending mode for features.
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
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
const_iterator constEnd() const
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
void fill(uint pixelValue)
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
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 setAttribute(const QString &name, const QString &value)
QSize toSize() const
void setMapUnits(QGis::UnitType u)
Set units of map&#39;s geographical coordinates - used for scale calculation.
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
const QgsCoordinateReferenceSystem & destinationCrs() const
returns CRS of destination coordinate reference system
int toInt(bool *ok, int base) const
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:340
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:177
void setDrawEditingInformation(bool b)
bool isEmpty() const
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:460
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QPaintDevice * device() const
void destinationSrsChanged()
void setPainter(QPainter *p)
double rasterScaleFactor() const
QString id() const
Get this layer&#39;s unique ID, this ID is used to access this layer from map layer registry.
Reads and writes project states.
Definition: qgsproject.h:72
bool mOverview
indicates whether it&#39;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&#39;s geographical coordinates - used for scale calculation.
void mapUnitsChanged()
static QPainter::CompositionMode getCompositionMode(BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
A class to represent a point.
Definition: qgspoint.h:117
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
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...
int logicalDpiX() const
int logicalDpiY() const
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs, bool refreshCoordinateTransformInfo=true, bool transformExtent=true)
sets destination coordinate reference system
void clear()
const T value(const Key &key) const
void setOutputSize(QSize size, double dpi)
Sets the desired size of the rendered map image.
void setRotation(double degrees)
sets rotation value in clockwise degrees
iterator find(const Key &key)
int readNumEntry(const QString &scope, const QString &key, int def=0, bool *ok=nullptr) const
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
Returns the current transparency for the vector layer.
bool isNull() const
void restore()
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:515
General purpose distance and area calculator.
QSizeF outputSizeF() const
Returns the size which the map will be rendered at.
QgsRectangle fullExtent()
returns current extent of layer set
QString what() const
Definition: qgsexception.h:36
QVariant value(const QString &key, const QVariant &defaultValue) const
const_iterator constBegin() const
bool hasPrevious() const
QgsMapSettings mMapSettings
map settings - used only for export in mapSettings() for use in classes that deal with QgsMapSettings...
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void drawImage(const QRectF &target, const QImage &image, const QRectF &source, QFlags< Qt::ImageConversionFlag > flags)
QPainter * painter()
QSize outputSize() const
Returns the size which the map will be rendered at.
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:182
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:391
QDomElement firstChildElement(const QString &tagName) const
Class for storing a coordinate reference system (CRS)
int height() const
void setMapToPixel(const QgsMapToPixel &mtp)
QgsRectangle extent() const
Return geographical coordinates of the rectangle that should be rendered.
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
Class for doing transforms between two map coordinate systems.
bool toBool() const
UnitType
Map units that qgis supports.
Definition: qgis.h:159
const QgsMapToPixel & mapToPixel() const
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
void start()
void updateScale()
Recalculate the map scale.
QStringList mLayerSet
stores array of layers to be rendered (identified by string)
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
int size() const
Labeling engine interface.
int height() const
QgsRenderContext mRenderContext
Encapsulates context of rendering.
QDomElement createElement(const QString &tagName)
qreal height() const
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void setMapUnitsPerPixel(double mapUnitsPerPixel)
Set map units per pixel.
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.
QgsLabelingEngineInterface * mLabelingEngine
Labeling engine (nullptr by default)
bool geographicFlag() const
Returns whether the CRS is a geographic CRS.
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:192
QStringList & layerSet()
returns current layer set
void render(QPainter *painter, double *forceWidthScale=nullptr)
starts rendering
qreal width() const
QgsRectangle mFullExtent
full extent of the layer set
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:167
QgsRectangle transformBoundingBox(const QgsRectangle &theRect, TransformDirection direction=ForwardTransform, const bool handle180Crossover=false) const
Transform a QgsRectangle to the dest Coordinate system If the direction is ForwardTransform then coor...
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&#39;s CRS to output CRS
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
void setCrsTransformEnabled(bool enabled)
sets whether to use projections for this layer set
QDomNode at(int index) const
QString toProj4() const
Returns a Proj4 string representation of this CRS.
void writeXML(QDomNode &theNode, QDomDocument &theDoc)