QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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;
58  mDestCRS = new QgsCoordinateReferenceSystem( QgsCRSCache::instance()->crsBySrsId( GEOCRS_ID ) ); //WGS 84
59 
62 
63  mLabelingEngine = nullptr;
64  readDefaultDatumTransformations();
65 
66  mTileRenderMode = false;
67 }
68 
70 {
71  delete mScaleCalculator;
72  delete mDistArea;
73  delete mDestCRS;
74  delete mLabelingEngine;
75 }
76 
78 {
79  return mExtent;
80 }
81 
83 {
85 }
86 
88 {
89  //remember the previous extent
91 
92  // Don't allow zooms where the current extent is so small that it
93  // can't be accurately represented using a double (which is what
94  // currentExtent uses). Excluding 0 avoids a divide by zero and an
95  // infinite loop when rendering to a new canvas. Excluding extents
96  // greater than 1 avoids doing unnecessary calculations.
97 
98  // The scheme is to compare the width against the mean x coordinate
99  // (and height against mean y coordinate) and only allow zooms where
100  // the ratio indicates that there is more than about 12 significant
101  // figures (there are about 16 significant figures in a double).
102 
103  if ( extent.width() > 0 &&
104  extent.height() > 0 &&
105  extent.width() < 1 &&
106  extent.height() < 1 )
107  {
108  // Use abs() on the extent to avoid the case where the extent is
109  // symmetrical about 0.
110  double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5;
111  double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5;
112 
113  double xRange = extent.width() / xMean;
114  double yRange = extent.height() / yMean;
115 
116  static const double minProportion = 1e-12;
117  if ( xRange < minProportion || yRange < minProportion )
118  return false;
119  }
120 
121  mExtent = extent;
122  if ( !extent.isEmpty() )
124 
125  emit extentsChanged();
126  return true;
127 }
128 
130 {
132  // TODO: adjust something ?
133 
134  emit rotationChanged( rotation );
135 }
136 
138 {
139  return mRotation;
140 }
141 
142 
143 void QgsMapRenderer::setOutputSize( QSize size, double dpi )
144 {
145  mSize = QSizeF( size.width(), size.height() );
146  mScaleCalculator->setDpi( dpi );
148 }
149 
150 void QgsMapRenderer::setOutputSize( QSizeF size, double dpi )
151 {
152  mSize = size;
153  mScaleCalculator->setDpi( dpi );
155 }
156 
158 {
159  return mScaleCalculator->dpi();
160 }
161 
163 {
164  return mSize.toSize();
165 }
166 
168 {
169  return mSize;
170 }
171 
173 {
174  double myHeight = mSize.height();
175  double myWidth = mSize.width();
176 
177  QgsMapToPixel newCoordXForm;
178 
179  if ( !myWidth || !myHeight )
180  {
181  mScale = 1.0;
182  newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
183  return;
184  }
185 
186  // calculate the translation and scaling parameters
187  // mapUnitsPerPixel = map units per pixel
188  double mapUnitsPerPixelY = mExtent.height() / myHeight;
189  double mapUnitsPerPixelX = mExtent.width() / myWidth;
190  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
191 
192  // calculate the actual extent of the mapCanvas
193  double dxmin, dxmax, dymin, dymax, whitespace;
194 
195  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
196  {
197  dymin = mExtent.yMinimum();
198  dymax = mExtent.yMaximum();
199  whitespace = (( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
200  dxmin = mExtent.xMinimum() - whitespace;
201  dxmax = mExtent.xMaximum() + whitespace;
202  }
203  else
204  {
205  dxmin = mExtent.xMinimum();
206  dxmax = mExtent.xMaximum();
207  whitespace = (( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
208  dymin = mExtent.yMinimum() - whitespace;
209  dymax = mExtent.yMaximum() + whitespace;
210  }
211 
212  QgsDebugMsg( QString( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ) );
213  QgsDebugMsg( QString( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( myWidth ), qgsDoubleToString( myHeight ) ) );
214  QgsDebugMsg( QString( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ) );
216 
217  // update extent
218  mExtent.setXMinimum( dxmin );
219  mExtent.setXMaximum( dxmax );
220  mExtent.setYMinimum( dymin );
221  mExtent.setYMaximum( dymax );
222 
223  QgsDebugMsg( QString( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / myWidth ), qgsDoubleToString( mExtent.height() / myHeight ) ) );
224 
225  QgsDebugMsg( QString( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mExtent.height() / mMapUnitsPerPixel ) ) );
226 
227  // update the scale
228  updateScale();
229 
230  QgsDebugMsg( QString( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ) );
231 
233  newCoordXForm.setParameters( mMapUnitsPerPixel, dxmin, dymin, myHeight );
235  mRenderContext.setMapToPixel( newCoordXForm );
237 }
238 
239 
240 void QgsMapRenderer::render( QPainter* painter, double* forceWidthScale )
241 {
242  //Lock render method for concurrent threads (e.g. from globe)
243  QMutexLocker renderLock( &mRenderMutex );
244 
245  QgsDebugMsg( "========== Rendering ==========" );
246 
247  if ( mExtent.isEmpty() )
248  {
249  QgsDebugMsg( "empty extent... not rendering" );
250  return;
251  }
252 
253  if ( qgsDoubleNear( mSize.width(), 1.0 ) && qgsDoubleNear( mSize.height(), 1.0 ) )
254  {
255  QgsDebugMsg( "size 1x1... not rendering" );
256  return;
257  }
258 
259  QPaintDevice* thePaintDevice = painter->device();
260  if ( !thePaintDevice )
261  {
262  return;
263  }
264 
265  // wait
266  if ( mDrawing )
267  {
268  QgsDebugMsg( "already rendering" );
270  }
271 
272  if ( mDrawing )
273  {
274  QgsDebugMsg( "still rendering - skipping" );
275  return;
276  }
277 
278  mDrawing = true;
279 
280  const QgsCoordinateTransform *ct;
281 
282 #ifdef QGISDEBUG
283  QgsDebugMsg( "Starting to render layer stack." );
284  QTime renderTime;
285  renderTime.start();
286 #endif
287 
288  if ( mOverview )
290 
291  mRenderContext.setPainter( painter );
293  //this flag is only for stopping during the current rendering progress,
294  //so must be false at every new render operation
296 
297  // set selection color
299  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
300  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
301  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
302  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
303  mRenderContext.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
304 
305  //calculate scale factor
306  //use the specified dpi and not those from the paint device
307  //because sometimes QPainter units are in a local coord sys (e.g. in case of QGraphicsScene)
308  double sceneDpi = mScaleCalculator->dpi();
309  double scaleFactor = 1.0;
311  {
312  if ( forceWidthScale )
313  {
314  scaleFactor = *forceWidthScale;
315  }
316  else
317  {
318  scaleFactor = sceneDpi / 25.4;
319  }
320  }
321  double rasterScaleFactor = ( thePaintDevice->logicalDpiX() + thePaintDevice->logicalDpiY() ) / 2.0 / sceneDpi;
322  if ( !qgsDoubleNear( mRenderContext.rasterScaleFactor(), rasterScaleFactor ) )
323  {
324  mRenderContext.setRasterScaleFactor( rasterScaleFactor );
325  }
326  if ( !qgsDoubleNear( mRenderContext.scaleFactor(), scaleFactor ) )
327  {
328  mRenderContext.setScaleFactor( scaleFactor );
329  }
331  {
332  //add map scale to render context
334  }
335  if ( mLastExtent != mExtent )
336  {
338  }
339 
341  if ( mLabelingEngine )
343 
344  // render all layers in the stack, starting at the base
346  li.toBack();
347 
349 
350  QgsRectangle r1, r2;
351 
352  while ( li.hasPrevious() )
353  {
355  {
356  break;
357  }
358 
359  // Store the painter in case we need to swap it out for the
360  // cache painter
361  QPainter * mypContextPainter = mRenderContext.painter();
362  // Flattened image for drawing when a blending mode is set
363  QImage * mypFlattenedImage = nullptr;
364 
365  QString layerId = li.previous();
366 
367  QgsDebugMsg( "Rendering at layer item " + layerId );
368 
369  // This call is supposed to cause the progress bar to
370  // advance. However, it seems that updating the progress bar is
371  // incompatible with having a QPainter active (the one that is
372  // passed into this function), as Qt produces a number of errors
373  // when try to do so. I'm (Gavin) not sure how to fix this, but
374  // added these comments and debug statement to help others...
375  QgsDebugMsg( "If there is a QPaintEngine error here, it is caused by an emit call" );
376 
377  //emit drawingProgress(myRenderCounter++, mLayerSet.size());
379 
380  if ( !ml )
381  {
382  QgsDebugMsg( "Layer not found in registry!" );
383  continue;
384  }
385 
386  QgsDebugMsg( QString( "layer %1: minscale:%2 maxscale:%3 scaledepvis:%4 extent:%5 blendmode:%6" )
387  .arg( ml->name() )
388  .arg( ml->minimumScale() )
389  .arg( ml->maximumScale() )
390  .arg( ml->hasScaleBasedVisibility() )
391  .arg( ml->extent().toString() )
392  .arg( ml->blendMode() )
393  );
394 
396  {
397  // Set the QPainter composition mode so that this layer is rendered using
398  // the desired blending mode
399  mypContextPainter->setCompositionMode( ml->blendMode() );
400  }
401 
402  if ( ml->isInScaleRange( mScale ) || mOverview )
403  {
404  connect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
405 
406  //
407  // Now do the call to the layer that actually does
408  // the rendering work!
409  //
410 
411  bool split = false;
412 
413  if ( hasCrsTransformEnabled() )
414  {
415  r1 = mExtent;
416  split = splitLayersExtent( ml, r1, r2 );
417  ct = transformation( ml );
419  QgsDebugMsg( " extent 1: " + r1.toString() );
420  QgsDebugMsg( " extent 2: " + r2.toString() );
421  if ( !r1.isFinite() || !r2.isFinite() ) //there was a problem transforming the extent. Skip the layer
422  {
423  continue;
424  }
425  }
426  else
427  {
428  ct = nullptr;
429  }
430 
432 
433  //decide if we have to scale the raster
434  //this is necessary in case QGraphicsScene is used
435  bool scaleRaster = false;
436  QgsMapToPixel rasterMapToPixel;
437  QgsMapToPixel bk_mapToPixel;
438 
439  if ( ml->type() == QgsMapLayer::RasterLayer && qAbs( rasterScaleFactor - 1.0 ) > 0.000001 )
440  {
441  scaleRaster = true;
442  }
443 
444  QSettings mySettings;
445 
446  // If we are drawing with an alternative blending mode then we need to render to a separate image
447  // before compositing this on the map. This effectively flattens the layer and prevents
448  // blending occurring between objects on the layer
449  // (this is not required for raster layers or when layer caching is enabled, since that has the same effect)
450  bool flattenedLayer = false;
452  {
453  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
454  if ((( vl->blendMode() != QPainter::CompositionMode_SourceOver )
455  || ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
456  || ( vl->layerTransparency() != 0 ) ) )
457  {
458  flattenedLayer = true;
459  mypFlattenedImage = new QImage( mRenderContext.painter()->device()->width(),
460  mRenderContext.painter()->device()->height(), QImage::Format_ARGB32 );
461  if ( mypFlattenedImage->isNull() )
462  {
463  QgsDebugMsg( "insufficient memory for image " + QString::number( mRenderContext.painter()->device()->width() ) + 'x' + QString::number( mRenderContext.painter()->device()->height() ) );
464  emit drawError( ml );
465  painter->end(); // drawError is not caught by anyone, so we end painting to notify caller
466  return;
467  }
468  mypFlattenedImage->fill( 0 );
469  QPainter * mypPainter = new QPainter( mypFlattenedImage );
470  if ( mySettings.value( "/qgis/enable_anti_aliasing", true ).toBool() )
471  {
472  mypPainter->setRenderHint( QPainter::Antialiasing );
473  }
474  mypPainter->scale( rasterScaleFactor, rasterScaleFactor );
475  mRenderContext.setPainter( mypPainter );
476  }
477  }
478 
479  // Per feature blending mode
481  {
482  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
483  if ( vl->featureBlendMode() != QPainter::CompositionMode_SourceOver )
484  {
485  // set the painter to the feature blend mode, so that features drawn
486  // on this layer will interact and blend with each other
488  }
489  }
490 
491  if ( scaleRaster )
492  {
493  bk_mapToPixel = mRenderContext.mapToPixel();
494  rasterMapToPixel = mRenderContext.mapToPixel();
495  rasterMapToPixel.setMapUnitsPerPixel( mRenderContext.mapToPixel().mapUnitsPerPixel() / rasterScaleFactor );
497  rasterMapToPixel.setYMaximum( mSize.height() * rasterScaleFactor );
499  mRenderContext.setMapToPixel( rasterMapToPixel );
501  mRenderContext.painter()->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
502  }
503 
504  if ( !ml->draw( mRenderContext ) )
505  {
506  emit drawError( ml );
507  }
508  else
509  {
510  QgsDebugMsg( "Layer rendered without issues" );
511  }
512 
513  if ( split )
514  {
516  if ( !ml->draw( mRenderContext ) )
517  {
518  emit drawError( ml );
519  }
520  }
521 
522  if ( scaleRaster )
523  {
524  mRenderContext.setMapToPixel( bk_mapToPixel );
526  }
527 
528  //apply layer transparency for vector layers
530  {
531  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer *>( ml );
532  if ( vl->layerTransparency() != 0 )
533  {
534  // a layer transparency has been set, so update the alpha for the flattened layer
535  // by combining it with the layer transparency
536  QColor transparentFillColor = QColor( 0, 0, 0, 255 - ( 255 * vl->layerTransparency() / 100 ) );
537  // use destination in composition mode to merge source's alpha with destination
538  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_DestinationIn );
540  mRenderContext.painter()->device()->height(), transparentFillColor );
541  }
542  }
543 
544  if ( flattenedLayer )
545  {
546  // If we flattened this layer for alternate blend modes, composite it now
547  delete mRenderContext.painter();
548  mRenderContext.setPainter( mypContextPainter );
549  mypContextPainter->save();
550  mypContextPainter->scale( 1.0 / rasterScaleFactor, 1.0 / rasterScaleFactor );
551  mypContextPainter->drawImage( 0, 0, *( mypFlattenedImage ) );
552  mypContextPainter->restore();
553  delete mypFlattenedImage;
554  mypFlattenedImage = nullptr;
555  }
556 
557  disconnect( ml, SIGNAL( drawingProgress( int, int ) ), this, SLOT( onDrawingProgress( int, int ) ) );
558  }
559  else // layer not visible due to scale
560  {
561  QgsDebugMsg( "Layer not rendered because it is not within the defined "
562  "visibility scale range" );
563  }
564 
565  } // while (li.hasPrevious())
566 
567  QgsDebugMsg( "Done rendering map layers" );
568 
569  // Reset the composition mode before rendering the labels
570  mRenderContext.painter()->setCompositionMode( QPainter::CompositionMode_SourceOver );
571 
572  if ( !mOverview )
573  {
574  // render all labels for vector layers in the stack, starting at the base
575  li.toBack();
576  while ( li.hasPrevious() )
577  {
579  {
580  break;
581  }
582 
583  QString layerId = li.previous();
584 
585  // TODO: emit drawingProgress((myRenderCounter++),zOrder.size());
587 
588  if ( ml && ( ml->type() != QgsMapLayer::RasterLayer ) )
589  {
590  // only make labels if the layer is visible
591  // after scale dep viewing settings are checked
592  if ( ml->isInScaleRange( mScale ) )
593  {
594  bool split = false;
595 
596  if ( hasCrsTransformEnabled() )
597  {
598  QgsRectangle r1 = mExtent;
599  split = splitLayersExtent( ml, r1, r2 );
600  ct = transformation( ml );
602  }
603  else
604  {
605  ct = nullptr;
606  }
607 
609 
610  ml->drawLabels( mRenderContext );
611  if ( split )
612  {
614  ml->drawLabels( mRenderContext );
615  }
616  }
617  }
618  }
619  } // if (!mOverview)
620 
621  // make sure progress bar arrives at 100%!
622  emit drawingProgress( 1, 1 );
623 
624  if ( mLabelingEngine )
625  {
626  // set correct extent
629 
632  }
633 
634  QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
635 
636  mDrawing = false;
637 }
638 
640 {
642 
643  // Since the map units have changed, force a recalculation of the scale.
644  updateScale();
645 
646  emit mapUnitsChanged();
647 }
648 
650 {
651  return mScaleCalculator->mapUnits();
652 }
653 
654 void QgsMapRenderer::onDrawingProgress( int current, int total )
655 {
656  Q_UNUSED( current );
657  Q_UNUSED( total );
658 }
659 
661 {
662  if ( mProjectionsEnabled != enabled )
663  {
664  mProjectionsEnabled = enabled;
665  QgsDebugMsg( "Adjusting DistArea projection on/off" );
666  mDistArea->setEllipsoidalMode( enabled );
669 
671  emit hasCrsTransformEnabled( enabled ); // deprecated
673 
674  emit hasCrsTransformEnabledChanged( enabled );
675  }
676 }
677 
679 {
680  return mProjectionsEnabled;
681 }
682 
683 void QgsMapRenderer::setDestinationCrs( const QgsCoordinateReferenceSystem& crs, bool refreshCoordinateTransformInfo, bool transformExtent )
684 {
685  QgsDebugMsg( "* Setting destCRS : = " + crs.toProj4() );
686  QgsDebugMsg( "* DestCRS.srsid() = " + QString::number( crs.srsid() ) );
687  if ( *mDestCRS != crs )
688  {
689  if ( refreshCoordinateTransformInfo )
690  {
692  }
693  QgsRectangle rect;
694  if ( transformExtent && !mExtent.isEmpty() )
695  {
696  QgsCoordinateTransform transform( *mDestCRS, crs );
697  try
698  {
699  rect = transform.transformBoundingBox( mExtent );
700  }
701  catch ( QgsCsException &e )
702  {
703  Q_UNUSED( e );
704  QgsDebugMsg( QString( "Transform error caught: %1" ).arg( e.what() ) );
705  }
706  }
707 
708  QgsDebugMsg( "Setting DistArea CRS to " + QString::number( crs.srsid() ) );
709  mDistArea->setSourceCrs( crs.srsid() );
710  *mDestCRS = crs;
712 
713  if ( !rect.isEmpty() )
714  {
715  setExtent( rect );
716  }
717 
718  emit destinationSrsChanged();
719  }
720 }
721 
723 {
724  QgsDebugMsgLevel( "* Returning destCRS", 3 );
725  QgsDebugMsgLevel( "* DestCRS.srsid() = " + QString::number( mDestCRS->srsid() ), 3 );
726  QgsDebugMsgLevel( "* DestCRS.proj4() = " + mDestCRS->toProj4(), 3 );
727  return *mDestCRS;
728 }
729 
730 
732 {
733  bool split = false;
734 
735  if ( hasCrsTransformEnabled() )
736  {
737  try
738  {
739 #ifdef QGISDEBUG
740  // QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
741 #endif
742  // Split the extent into two if the source CRS is
743  // geographic and the extent crosses the split in
744  // geographic coordinates (usually +/- 180 degrees,
745  // and is assumed to be so here), and draw each
746  // extent separately.
747  static const double splitCoord = 180.0;
748 
749  const QgsCoordinateTransform *transform = transformation( layer );
750  if ( layer->crs().geographicFlag() )
751  {
752  // Note: ll = lower left point
753  // and ur = upper right point
754 
755  QgsPoint ll( extent.xMinimum(), extent.yMinimum() );
756  QgsPoint ur( extent.xMaximum(), extent.yMaximum() );
757 
758  if ( transform )
759  {
760  ll = transform->transform( ll.x(), ll.y(),
762  ur = transform->transform( ur.x(), ur.y(),
764  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
765  }
766 
767  if ( ll.x() > ur.x() )
768  {
769  r2 = extent;
770  extent.setXMinimum( splitCoord );
771  r2.setXMaximum( splitCoord );
772  split = true;
773  }
774  }
775  else // can't cross 180
776  {
777  if ( transform )
778  {
779  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
780  }
781  }
782  }
783  catch ( QgsCsException &cse )
784  {
785  Q_UNUSED( cse );
786  QgsDebugMsg( "Transform error caught" );
787  extent = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
788  r2 = QgsRectangle( -DBL_MAX, -DBL_MAX, DBL_MAX, DBL_MAX );
789  }
790  }
791  return split;
792 }
793 
795 {
796  //QgsDebugMsg( QString( "sourceCrs = " + tr( theLayer )->sourceCrs().authid() ) );
797  //QgsDebugMsg( QString( "destCRS = " + tr( theLayer )->destCRS().authid() ) );
798  //QgsDebugMsg( QString( "extent = " + extent.toString() ) );
799  if ( hasCrsTransformEnabled() )
800  {
801  try
802  {
803  const QgsCoordinateTransform *transform = transformation( theLayer );
804  if ( transform )
805  {
806  extent = transform->transformBoundingBox( extent );
807  }
808  }
809  catch ( QgsCsException &cse )
810  {
811  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
812  }
813  }
814 
815  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
816 
817  return extent;
818 }
819 
821 {
822 #if QGISDEBUG
823  const QgsCoordinateTransform *transform = transformation( theLayer );
824  QgsDebugMsg( QString( "layer sourceCrs = " + ( transform ? transform->sourceCrs().authid() : "none" ) ) );
825  QgsDebugMsg( QString( "layer destCRS = " + ( transform ? transform->destCRS().authid() : "none" ) ) );
826  QgsDebugMsg( QString( "extent = " + extent.toString() ) );
827 #endif
828  if ( hasCrsTransformEnabled() )
829  {
830  try
831  {
832  const QgsCoordinateTransform *transform = transformation( theLayer );
833  if ( transform )
834  {
835  extent = transform->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
836  }
837  }
838  catch ( QgsCsException &cse )
839  {
840  QgsMessageLog::logMessage( tr( "Transform error caught: %1" ).arg( cse.what() ), tr( "CRS" ) );
841  }
842  }
843 
844  QgsDebugMsg( QString( "proj extent = " + extent.toString() ) );
845 
846  return extent;
847 }
848 
850 {
851  if ( hasCrsTransformEnabled() )
852  {
853  try
854  {
855  const QgsCoordinateTransform *transform = transformation( theLayer );
856  if ( transform )
857  {
858  point = transform->transform( point, QgsCoordinateTransform::ForwardTransform );
859  }
860  }
861  catch ( QgsCsException &cse )
862  {
863  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
864  }
865  }
866  else
867  {
868  // leave point without transformation
869  }
870  return point;
871 }
872 
874 {
875  if ( hasCrsTransformEnabled() )
876  {
877  try
878  {
879  const QgsCoordinateTransform *transform = transformation( theLayer );
880  if ( transform )
881  {
882  rect = transform->transform( rect, QgsCoordinateTransform::ForwardTransform );
883  }
884  }
885  catch ( QgsCsException &cse )
886  {
887  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
888  }
889  }
890  else
891  {
892  // leave point without transformation
893  }
894  return rect;
895 }
896 
898 {
899  if ( hasCrsTransformEnabled() )
900  {
901  try
902  {
903  const QgsCoordinateTransform *transform = transformation( theLayer );
904  if ( transform )
905  point = transform->transform( point, QgsCoordinateTransform::ReverseTransform );
906  }
907  catch ( QgsCsException &cse )
908  {
909  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
910  }
911  }
912  else
913  {
914  // leave point without transformation
915  }
916  return point;
917 }
918 
920 {
921  if ( hasCrsTransformEnabled() )
922  {
923  try
924  {
925  const QgsCoordinateTransform *transform = transformation( theLayer );
926  if ( transform )
927  rect = transform->transform( rect, QgsCoordinateTransform::ReverseTransform );
928  }
929  catch ( QgsCsException &cse )
930  {
931  QgsMessageLog::logMessage( QString( "Transform error caught: %1" ).arg( cse.what() ) );
932  }
933  }
934  return rect;
935 }
936 
938 {
940 }
941 
943 {
944  QgsDebugMsg( "called." );
945 
946  if ( !mFullExtent.isNull() )
947  return mFullExtent;
948 
950 
951  // iterate through the map layers and test each layers extent
952  // against the current min and max values
953  QgsDebugMsg( QString( "Layer count: %1" ).arg( mLayerSet.count() ) );
954  Q_FOREACH ( const QString layerId, mLayerSet )
955  {
956  QgsMapLayer * lyr = registry->mapLayer( layerId );
957  if ( !lyr )
958  {
959  QgsDebugMsg( QString( "WARNING: layer '%1' not found in map layer registry!" ).arg( layerId ) );
960  }
961  else
962  {
963  QgsDebugMsg( "Updating extent using " + lyr->name() );
964  QgsDebugMsg( "Input extent: " + lyr->extent().toString() );
965 
966  if ( lyr->extent().isNull() )
967  {
968  continue;
969  }
970 
971  // Layer extents are stored in the coordinate system (CS) of the
972  // layer. The extent must be projected to the canvas CS
974 
975  QgsDebugMsg( "Output extent: " + extent.toString() );
976  mFullExtent.unionRect( extent );
977 
978  }
979  }
980 
981  if ( mFullExtent.width() == 0.0 || mFullExtent.height() == 0.0 )
982  {
983  // If all of the features are at the one point, buffer the
984  // rectangle a bit. If they are all at zero, do something a bit
985  // more crude.
986 
987  if ( mFullExtent.xMinimum() == 0.0 && mFullExtent.xMaximum() == 0.0 &&
988  mFullExtent.yMinimum() == 0.0 && mFullExtent.yMaximum() == 0.0 )
989  {
990  mFullExtent.set( -1.0, -1.0, 1.0, 1.0 );
991  }
992  else
993  {
994  const double padFactor = 1e-8;
995  double widthPad = mFullExtent.xMinimum() * padFactor;
996  double heightPad = mFullExtent.yMinimum() * padFactor;
997  double xmin = mFullExtent.xMinimum() - widthPad;
998  double xmax = mFullExtent.xMaximum() + widthPad;
999  double ymin = mFullExtent.yMinimum() - heightPad;
1000  double ymax = mFullExtent.yMaximum() + heightPad;
1001  mFullExtent.set( xmin, ymin, xmax, ymax );
1002  }
1003  }
1004 
1005  QgsDebugMsg( "Full extent: " + mFullExtent.toString() );
1006 
1007  return mFullExtent;
1008 }
1009 
1011 {
1012  QgsDebugMsg( QString( "Entering: %1" ).arg( layers.join( ", " ) ) );
1013  mLayerSet = layers;
1014  updateFullExtent();
1015 }
1016 
1018 {
1019  return mLayerSet;
1020 }
1021 
1023 {
1024  QgsMapSettings tmpSettings;
1025  tmpSettings.readXML( theNode );
1026  //load coordinate transform into
1028  QDomElement layerCoordTransformInfoElem = theNode.firstChildElement( "layer_coordinate_transform_info" );
1029  if ( !layerCoordTransformInfoElem.isNull() )
1030  {
1031  QDomNodeList layerCoordinateTransformList = layerCoordTransformInfoElem.elementsByTagName( "layer_coordinate_transform" );
1032  QDomElement layerCoordTransformElem;
1033  for ( int i = 0; i < layerCoordinateTransformList.size(); ++i )
1034  {
1035  layerCoordTransformElem = layerCoordinateTransformList.at( i ).toElement();
1036  QString layerId = layerCoordTransformElem.attribute( "layerid" );
1037  if ( layerId.isEmpty() )
1038  {
1039  continue;
1040  }
1041 
1043  lct.srcAuthId = layerCoordTransformElem.attribute( "srcAuthId" );
1044  lct.destAuthId = layerCoordTransformElem.attribute( "destAuthId" );
1045  lct.srcDatumTransform = layerCoordTransformElem.attribute( "srcDatumTransform", "-1" ).toInt();
1046  lct.destDatumTransform = layerCoordTransformElem.attribute( "destDatumTransform", "-1" ).toInt();
1047  mLayerCoordinateTransformInfo.insert( layerId, lct );
1048  }
1049  }
1050 
1051 
1052  setMapUnits( tmpSettings.mapUnits() );
1053  setExtent( tmpSettings.extent() );
1055  setDestinationCrs( tmpSettings.destinationCrs() );
1056 
1057 
1058  return true;
1059 }
1060 
1062 {
1063  QgsMapSettings tmpSettings;
1064  tmpSettings.setOutputDpi( outputDpi() );
1065  tmpSettings.setOutputSize( outputSize() );
1066  tmpSettings.setMapUnits( mapUnits() );
1067  tmpSettings.setExtent( extent() );
1069  tmpSettings.setDestinationCrs( destinationCrs() );
1070 
1071  tmpSettings.writeXML( theNode, theDoc );
1072  // layer coordinate transform infos
1073  QDomElement layerCoordTransformInfo = theDoc.createElement( "layer_coordinate_transform_info" );
1075  for ( ; coordIt != mLayerCoordinateTransformInfo.constEnd(); ++coordIt )
1076  {
1077  QDomElement layerCoordTransformElem = theDoc.createElement( "layer_coordinate_transform" );
1078  layerCoordTransformElem.setAttribute( "layerid", coordIt.key() );
1079  layerCoordTransformElem.setAttribute( "srcAuthId", coordIt->srcAuthId );
1080  layerCoordTransformElem.setAttribute( "destAuthId", coordIt->destAuthId );
1081  layerCoordTransformElem.setAttribute( "srcDatumTransform", QString::number( coordIt->srcDatumTransform ) );
1082  layerCoordTransformElem.setAttribute( "destDatumTransform", QString::number( coordIt->destDatumTransform ) );
1083  layerCoordTransformInfo.appendChild( layerCoordTransformElem );
1084  }
1085  theNode.appendChild( layerCoordTransformInfo );
1086  return true;
1087 }
1088 
1090 {
1091  if ( mLabelingEngine )
1092  delete mLabelingEngine;
1093 
1094  mLabelingEngine = iface;
1095 }
1096 
1098 {
1099  if ( !layer || !mDestCRS )
1100  {
1101  return nullptr;
1102  }
1103 
1104  if ( layer->crs().authid() == mDestCRS->authid() )
1105  {
1106  return nullptr;
1107  }
1108 
1111  && ctIt->srcAuthId == layer->crs().authid()
1112  && ctIt->destAuthId == mDestCRS->authid() )
1113  {
1114  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1115  }
1116  else
1117  {
1118  //is there a defined datum transformation?
1119  QHash< QPair< QString, QString >, QPair< int, int > >::const_iterator it = mDefaultDatumTransformations.find( qMakePair( layer->crs().authid(), mDestCRS->authid() ) );
1120  if ( it != mDefaultDatumTransformations.constEnd() )
1121  {
1122  return QgsCoordinateTransformCache::instance()->transform( it.key().first, it.key().second, it.value().first, it.value().second );
1123  }
1124  emit datumTransformInfoRequested( layer, layer->crs().authid(), mDestCRS->authid() );
1125  }
1126 
1127  //still not present? get coordinate transformation with -1/-1 datum transform as default
1128  ctIt = mLayerCoordinateTransformInfo.find( layer->id() );
1130  || ctIt->srcAuthId == layer->crs().authid()
1131  || ctIt->destAuthId == mDestCRS->authid()
1132  )
1133  {
1135  }
1136  return QgsCoordinateTransformCache::instance()->transform( ctIt->srcAuthId, ctIt->destAuthId, ctIt->srcDatumTransform, ctIt->destDatumTransform );
1137 }
1138 
1142 {
1143  // Map QgsMapRenderer::BlendNormal to QPainter::CompositionMode
1144  switch ( blendMode )
1145  {
1147  return QPainter::CompositionMode_SourceOver;
1149  return QPainter::CompositionMode_Lighten;
1151  return QPainter::CompositionMode_Screen;
1153  return QPainter::CompositionMode_ColorDodge;
1155  return QPainter::CompositionMode_Plus;
1157  return QPainter::CompositionMode_Darken;
1159  return QPainter::CompositionMode_Multiply;
1161  return QPainter::CompositionMode_ColorBurn;
1163  return QPainter::CompositionMode_Overlay;
1165  return QPainter::CompositionMode_SoftLight;
1167  return QPainter::CompositionMode_HardLight;
1169  return QPainter::CompositionMode_Difference;
1171  return QPainter::CompositionMode_Exclusion;
1173  return QPainter::CompositionMode_Source;
1175  return QPainter::CompositionMode_DestinationOver;
1177  return QPainter::CompositionMode_Clear;
1179  return QPainter::CompositionMode_Destination;
1181  return QPainter::CompositionMode_SourceIn;
1183  return QPainter::CompositionMode_DestinationIn;
1185  return QPainter::CompositionMode_SourceOut;
1187  return QPainter::CompositionMode_DestinationOut;
1189  return QPainter::CompositionMode_SourceAtop;
1191  return QPainter::CompositionMode_DestinationAtop;
1193  return QPainter::CompositionMode_Xor;
1194  default:
1195  QgsDebugMsg( QString( "Blend mode %1 mapped to SourceOver" ).arg( blendMode ) );
1196  return QPainter::CompositionMode_SourceOver;
1197  }
1198 }
1199 
1200 QgsMapRenderer::BlendMode QgsMapRenderer::getBlendModeEnum( QPainter::CompositionMode blendMode )
1201 {
1202  // Map QPainter::CompositionMode to QgsMapRenderer::BlendNormal
1203  switch ( blendMode )
1204  {
1205  case QPainter::CompositionMode_SourceOver:
1207  case QPainter::CompositionMode_Lighten:
1209  case QPainter::CompositionMode_Screen:
1211  case QPainter::CompositionMode_ColorDodge:
1213  case QPainter::CompositionMode_Plus:
1215  case QPainter::CompositionMode_Darken:
1217  case QPainter::CompositionMode_Multiply:
1219  case QPainter::CompositionMode_ColorBurn:
1221  case QPainter::CompositionMode_Overlay:
1223  case QPainter::CompositionMode_SoftLight:
1225  case QPainter::CompositionMode_HardLight:
1227  case QPainter::CompositionMode_Difference:
1229  case QPainter::CompositionMode_Exclusion:
1231  case QPainter::CompositionMode_Source:
1233  case QPainter::CompositionMode_DestinationOver:
1235  case QPainter::CompositionMode_Clear:
1237  case QPainter::CompositionMode_Destination:
1239  case QPainter::CompositionMode_SourceIn:
1241  case QPainter::CompositionMode_DestinationIn:
1243  case QPainter::CompositionMode_SourceOut:
1245  case QPainter::CompositionMode_DestinationOut:
1247  case QPainter::CompositionMode_SourceAtop:
1249  case QPainter::CompositionMode_DestinationAtop:
1251  case QPainter::CompositionMode_Xor:
1252  return QgsMapRenderer::BlendXor;
1253  default:
1254  QgsDebugMsg( QString( "Composition mode %1 mapped to Normal" ).arg( blendMode ) );
1256  }
1257 }
1258 
1259 Q_GUI_EXPORT extern int qt_defaultDpiX();
1260 
1262 {
1263  // make sure the settings object is up-to-date
1271 
1272  // set selection color
1274  int myRed = prj->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
1275  int myGreen = prj->readNumEntry( "Gui", "/SelectionColorGreenPart", 255 );
1276  int myBlue = prj->readNumEntry( "Gui", "/SelectionColorBluePart", 0 );
1277  int myAlpha = prj->readNumEntry( "Gui", "/SelectionColorAlphaPart", 255 );
1278  mMapSettings.setSelectionColor( QColor( myRed, myGreen, myBlue, myAlpha ) );
1279 
1280  return mMapSettings;
1281 }
1282 
1283 void QgsMapRenderer::addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform, int destDatumTransform )
1284 {
1286  lt.srcAuthId = srcAuthId;
1287  lt.destAuthId = destAuthId;
1288  lt.srcDatumTransform = srcDatumTransform;
1289  lt.destDatumTransform = destDatumTransform;
1290  mLayerCoordinateTransformInfo.insert( layerId, lt );
1291 }
1292 
1294 {
1296 }
1297 
1298 void QgsMapRenderer::readDefaultDatumTransformations()
1299 {
1300  const char* envChar = getenv( "DEFAULT_DATUM_TRANSFORM" );
1301  if ( envChar )
1302  {
1303  QString envString( envChar );
1304  QStringList transformSplit = envString.split( ";" );
1305  for ( int i = 0; i < transformSplit.size(); ++i )
1306  {
1307  QStringList slashSplit = transformSplit.at( i ).split( "/" );
1308  if ( slashSplit.size() < 4 )
1309  {
1310  continue;
1311  }
1312 
1313  mDefaultDatumTransformations.insert( qMakePair( slashSplit.at( 0 ), slashSplit.at( 1 ) ), qMakePair( slashSplit.at( 2 ).toInt(), slashSplit.at( 3 ).toInt() ) );
1314  }
1315  }
1316 }
1317 
1318 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 setExtent(const QgsRectangle &rect, bool magnified=true)
Set coordinates of the rectangle which should be rendered.
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.
QSizeF outputSizeF() const
Returns the size which the map will be rendered at.
QString attribute(const QString &name, const QString &defValue) const
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
bool mProjectionsEnabled
detemines whether on the fly projection support is enabled
QgsMapLayer * mapLayer(const QString &theLayerId) const
Retrieve a pointer to a registered layer by layer ID.
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)
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 T & at(int i) const
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
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:515
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.
bool isInScaleRange(double scale) const
Tests whether the layer should be visible at the specified scale.
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
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)
QgsMapLayer::LayerType type() const
Get the type of the layer.
Definition: qgsmaplayer.cpp:99
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:353
QSize outputSize() const
Returns the size which the map will be rendered at.
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
int size() const
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.
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
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.
bool mTileRenderMode
Tell the render system we are rendering a map tile.
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)
Returns a string representation of a double.
Definition: qgis.h:341
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:461
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:71
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.
double minimumScale() const
Returns the minimum scale denominator at which the layer is visible.
void mapUnitsChanged()
double mapUnitsPerPixel() const
Return current map units per pixel.
double maximumScale() const
Returns the maximum scale denominator at which the layer is visible.
static QPainter::CompositionMode getCompositionMode(BlendMode blendMode)
Returns a QPainter::CompositionMode corresponding to a BlendMode.
A class to represent a point.
Definition: qgspoint.h:117
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 various methods to retrieve match...
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()
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
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:516
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
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
void setSelectionColor(const QColor &color)
Set color that is used for drawing of selected vector features.
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()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
QDomElement firstChildElement(const QString &tagName) const
Class for storing a coordinate reference system (CRS)
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:159
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
void setFlag(Flag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void start()
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
QString name
Read property of QString layerName.
Definition: qgsmaplayer.h:53
void updateScale()
Recalculate the map scale.
QStringList mLayerSet
stores array of layers to be rendered (identified by string)
void setRasterScaleFactor(double factor)
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.
Draw map such that there are no problems between adjacent tiles.
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
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
Definition: qgscrscache.cpp:91
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)