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