QGIS API Documentation  3.27.0-Master (0e23467727)
qgsmapsettings.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmapsettings.cpp
3  --------------------------------------
4  Date : December 2013
5  Copyright : (C) 2013 by Martin Dobias
6  Email : wonder dot 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 "qgsmapsettings.h"
17 
18 #include "qgsscalecalculator.h"
19 #include "qgsmaprendererjob.h"
20 #include "qgsmaptopixel.h"
21 #include "qgslogger.h"
22 
23 #include "qgsmessagelog.h"
24 #include "qgsmaplayer.h"
25 #include "qgsmaplayerlistutils_p.h"
26 #include "qgsproject.h"
27 #include "qgsxmlutils.h"
28 #include "qgsexception.h"
29 #include "qgsgeometry.h"
30 #include "qgsgrouplayer.h"
31 
32 Q_GUI_EXPORT extern int qt_defaultDpiX();
33 
34 
36  : mDpi( qt_defaultDpiX() ) // DPI that will be used by default for QImage instances
37  , mSize( QSize( 0, 0 ) )
38  , mBackgroundColor( Qt::white )
39  , mSelectionColor( Qt::yellow )
40  , mFlags( Qgis::MapSettingsFlag::Antialiasing | Qgis::MapSettingsFlag::UseAdvancedEffects | Qgis::MapSettingsFlag::DrawLabeling | Qgis::MapSettingsFlag::DrawSelection )
41  , mSegmentationTolerance( M_PI_2 / 90 )
42 {
45 
46  updateDerived();
47 }
48 
49 void QgsMapSettings::setMagnificationFactor( double factor, const QgsPointXY *center )
50 {
51  const double ratio = mMagnificationFactor / factor;
52 
53  mMagnificationFactor = factor;
54 
55  const double rot = rotation();
56  setRotation( 0.0 );
57 
59  ext.scale( ratio, center );
60 
61  mRotation = rot;
62  mExtent = ext;
63  mDpi = mDpi / ratio;
64 
65  QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1 dpi: %2 ratio: %3" ).arg( factor ).arg( mDpi ).arg( ratio ), 3 );
66 
67  updateDerived();
68 }
69 
71 {
72  return mMagnificationFactor;
73 }
74 
76 {
77  return mExtent;
78 }
79 
80 void QgsMapSettings::setExtent( const QgsRectangle &extent, bool magnified )
81 {
82  QgsRectangle magnifiedExtent = extent;
83 
84  if ( !magnified )
85  magnifiedExtent.scale( 1 / mMagnificationFactor );
86 
87  mExtent = magnifiedExtent;
88 
89  updateDerived();
90 }
91 
93 {
94  return mExtentBuffer;
95 }
96 
97 void QgsMapSettings::setExtentBuffer( const double buffer )
98 {
99  mExtentBuffer = buffer;
100 }
101 
103 {
104  return mRotation;
105 }
106 
107 void QgsMapSettings::setRotation( double degrees )
108 {
109  if ( qgsDoubleNear( mRotation, degrees ) )
110  return;
111 
112  mRotation = degrees;
113 
114  // TODO: update extent while keeping scale ?
115  updateDerived();
116 }
117 
118 
120 {
121  const QgsRectangle extent = mExtent;
122 
123  if ( extent.isEmpty() || !extent.isFinite() )
124  {
125  mValid = false;
126  return;
127  }
128 
129  // Don't allow zooms where the current extent is so small that it
130  // can't be accurately represented using a double (which is what
131  // currentExtent uses). Excluding 0 avoids a divide by zero and an
132  // infinite loop when rendering to a new canvas. Excluding extents
133  // greater than 1 avoids doing unnecessary calculations.
134 
135  // The scheme is to compare the width against the mean x coordinate
136  // (and height against mean y coordinate) and only allow zooms where
137  // the ratio indicates that there is more than about 12 significant
138  // figures (there are about 16 significant figures in a double).
139 
140  if ( extent.width() > 0 &&
141  extent.height() > 0 &&
142  extent.width() < 1 &&
143  extent.height() < 1 )
144  {
145  // Use abs() on the extent to avoid the case where the extent is
146  // symmetrical about 0.
147  const double xMean = ( std::fabs( extent.xMinimum() ) + std::fabs( extent.xMaximum() ) ) * 0.5;
148  const double yMean = ( std::fabs( extent.yMinimum() ) + std::fabs( extent.yMaximum() ) ) * 0.5;
149 
150  const double xRange = extent.width() / xMean;
151  const double yRange = extent.height() / yMean;
152 
153  static const double MIN_PROPORTION = 1e-12;
154  if ( xRange < MIN_PROPORTION || yRange < MIN_PROPORTION )
155  {
156  mValid = false;
157  return;
158  }
159  }
160 
161  const double myHeight = mSize.height();
162  const double myWidth = mSize.width();
163 
164  if ( !myWidth || !myHeight )
165  {
166  mValid = false;
167  return;
168  }
169 
170  // calculate the translation and scaling parameters
171  const double mapUnitsPerPixelY = mExtent.height() / myHeight;
172  const double mapUnitsPerPixelX = mExtent.width() / myWidth;
173  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
174 
175  // calculate the actual extent of the mapCanvas
176  double dxmin = mExtent.xMinimum(), dxmax = mExtent.xMaximum(),
177  dymin = mExtent.yMinimum(), dymax = mExtent.yMaximum(), whitespace;
178 
179  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
180  {
181  whitespace = ( ( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
182  dxmin -= whitespace;
183  dxmax += whitespace;
184  }
185  else
186  {
187  whitespace = ( ( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
188  dymin -= whitespace;
189  dymax += whitespace;
190  }
191 
192  mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
193 
194  // update the scale
197 
198  bool ok = true;
201  visibleExtent().center().x(),
202  visibleExtent().center().y(),
203  outputSize().width(),
204  outputSize().height(),
205  mRotation, &ok );
206 
207  mValid = ok;
208 
209 #if 1 // set visible extent taking rotation in consideration
210  if ( mRotation )
211  {
212  const QgsPointXY p1 = mMapToPixel.toMapCoordinates( QPoint( 0, 0 ) );
213  const QgsPointXY p2 = mMapToPixel.toMapCoordinates( QPoint( 0, myHeight ) );
214  const QgsPointXY p3 = mMapToPixel.toMapCoordinates( QPoint( myWidth, 0 ) );
215  const QgsPointXY p4 = mMapToPixel.toMapCoordinates( QPoint( myWidth, myHeight ) );
216  dxmin = std::min( p1.x(), std::min( p2.x(), std::min( p3.x(), p4.x() ) ) );
217  dymin = std::min( p1.y(), std::min( p2.y(), std::min( p3.y(), p4.y() ) ) );
218  dxmax = std::max( p1.x(), std::max( p2.x(), std::max( p3.x(), p4.x() ) ) );
219  dymax = std::max( p1.y(), std::max( p2.y(), std::max( p3.y(), p4.y() ) ) );
220  mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
221  }
222 #endif
223 
224  QgsDebugMsgLevel( QStringLiteral( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ), 5 );
225  QgsDebugMsgLevel( QStringLiteral( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mSize.width() ), qgsDoubleToString( mSize.height() ) ), 5 );
226  QgsDebugMsgLevel( QStringLiteral( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ), 5 );
228  QgsDebugMsgLevel( QStringLiteral( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / myWidth ), qgsDoubleToString( mVisibleExtent.height() / myHeight ) ), 5 );
229  QgsDebugMsgLevel( QStringLiteral( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ), 5 );
230  QgsDebugMsgLevel( QStringLiteral( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ), 5 );
231  QgsDebugMsgLevel( QStringLiteral( "Rotation: %1 degrees" ).arg( mRotation ), 5 );
232  QgsDebugMsgLevel( QStringLiteral( "Extent: %1" ).arg( mExtent.asWktCoordinates() ), 5 );
233  QgsDebugMsgLevel( QStringLiteral( "Visible Extent: %1" ).arg( mVisibleExtent.asWktCoordinates() ), 5 );
234  QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1" ).arg( mMagnificationFactor ), 5 );
235 
236 }
237 
238 
240 {
241  return mSize;
242 }
243 
245 {
246  mSize = size;
247 
248  updateDerived();
249 }
250 
252 {
253  return mDevicePixelRatio;
254 }
255 
257 {
258  mDevicePixelRatio = dpr;
259  updateDerived();
260 }
261 
263 {
264  return outputSize() * mDevicePixelRatio;
265 }
266 
268 {
269  return mDpi;
270 }
271 
273 {
274  mDpi = dpi;
275 
276  updateDerived();
277 }
278 
280 {
281  return mDpiTarget;
282 }
283 
285 {
286  mDpiTarget = dpi;
287 }
288 
289 QStringList QgsMapSettings::layerIds( bool expandGroupLayers ) const
290 {
291  const QList<QgsMapLayer * > mapLayers = layers( expandGroupLayers );
292  QStringList res;
293  res.reserve( mapLayers.size() );
294  for ( const QgsMapLayer *layer : mapLayers )
295  res << layer->id();
296  return res;
297 }
298 
299 QList<QgsMapLayer *> QgsMapSettings::layers( bool expandGroupLayers ) const
300 {
301  const QList<QgsMapLayer *> actualLayers = _qgis_listQPointerToRaw( mLayers );
302  if ( !expandGroupLayers )
303  return actualLayers;
304 
305  QList< QgsMapLayer * > result;
306 
307  std::function< void( const QList< QgsMapLayer * >& layers ) > expandLayers;
308  expandLayers = [&result, &expandLayers]( const QList< QgsMapLayer * > &layers )
309  {
310  for ( QgsMapLayer *layer : layers )
311  {
312  if ( QgsGroupLayer *groupLayer = qobject_cast< QgsGroupLayer * >( layer ) )
313  {
314  expandLayers( groupLayer->childLayers() );
315  }
316  else
317  {
318  result << layer;
319  }
320  }
321  };
322 
323  expandLayers( actualLayers );
324  return result;
325 }
326 
327 void QgsMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
328 {
329  // filter list, removing null layers and non-spatial layers
330  auto filteredList = layers;
331  filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(),
332  []( QgsMapLayer * layer )
333  {
334  return !layer || !layer->isSpatial();
335  } ), filteredList.end() );
336 
337  mLayers = _qgis_listRawToQPointer( filteredList );
338 }
339 
340 QMap<QString, QString> QgsMapSettings::layerStyleOverrides() const
341 {
342  return mLayerStyleOverrides;
343 }
344 
345 void QgsMapSettings::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
346 {
347  mLayerStyleOverrides = overrides;
348 }
349 
351 {
352  mDestCRS = crs;
354  // Since the map units have changed, force a recalculation of the scale.
355  updateDerived();
356 }
357 
359 {
360  return mDestCRS;
361 }
362 
363 bool QgsMapSettings::setEllipsoid( const QString &ellipsoid )
364 {
366  if ( !params.valid )
367  {
368  return false;
369  }
370  else
371  {
373  return true;
374  }
375 }
376 
377 void QgsMapSettings::setFlags( Qgis::MapSettingsFlags flags )
378 {
379  mFlags = flags;
380 }
381 
383 {
384  if ( on )
385  mFlags |= flag;
386  else
387  mFlags &= ~( static_cast< int >( flag ) );
388 }
389 
390 Qgis::MapSettingsFlags QgsMapSettings::flags() const
391 {
392  return mFlags;
393 }
394 
396 {
397  return mFlags.testFlag( flag );
398 }
399 
401 {
402  return mScaleCalculator.mapUnits();
403 }
404 
405 
407 {
408  return mValid;
409 }
410 
412 {
413  return mVisibleExtent;
414 }
415 
417 {
418  QPolygonF poly;
419 
420  const QSize &sz = outputSize();
421  const QgsMapToPixel &m2p = mapToPixel();
422 
423  poly << m2p.toMapCoordinates( 0.0, 0.0 ).toQPointF();
424  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), 0.0 ).toQPointF();
425  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), static_cast<double>( sz.height() ) ).toQPointF();
426  poly << m2p.toMapCoordinates( 0.0, static_cast<double>( sz.height() ) ).toQPointF();
427 
428  return poly;
429 }
430 
432 {
433  QPolygonF poly;
434 
435  const QSize &sz = outputSize();
436  const QgsMapToPixel &m2p = mapToPixel();
437 
438  // Transform tilebuffer in pixel.
439  // Original tilebuffer is in pixel and transformed only according
440  // extent width (see QgsWmsRenderContext::mapTileBuffer)
441 
442  const double mapUnitsPerPixel = mExtent.width() / sz.width();
443  const double buffer = mExtentBuffer / mapUnitsPerPixel;
444 
445  poly << m2p.toMapCoordinates( -buffer, -buffer ).toQPointF();
446  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() + buffer ), -buffer ).toQPointF();
447  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() + buffer ), static_cast<double>( sz.height() + buffer ) ).toQPointF();
448  poly << m2p.toMapCoordinates( -buffer, static_cast<double>( sz.height() + buffer ) ).toQPointF();
449 
450  return poly;
451 }
452 
454 {
455  return mMapUnitsPerPixel;
456 }
457 
458 double QgsMapSettings::scale() const
459 {
460  return mScale;
461 }
462 
464 {
465 #ifdef QGISDEBUG
466  if ( !mHasTransformContext )
467  QgsDebugMsgLevel( QStringLiteral( "No QgsCoordinateTransformContext context set for transform" ), 4 );
468 #endif
469 
470  return mTransformContext;
471 }
472 
474 {
475  mTransformContext = context;
476 #ifdef QGISDEBUG
477  mHasTransformContext = true;
478 #endif
479 }
480 
482 {
483  if ( !layer )
484  return QgsCoordinateTransform();
485 
487 }
488 
490 {
491  // Output width in inches
492  const double outputWidthInInches = outputSize().width() / outputDpi();
493 
494  // Desired visible width (honouring scale)
495  const double scaledWidthInInches = outputWidthInInches * scale;
496 
498  {
499  // Start with some fraction of the current extent around the center
500  const double delta = mExtent.width() / 100.;
501  QgsRectangle ext( center.x() - delta, center.y() - delta, center.x() + delta, center.y() + delta );
502  // Get scale at extent, and then scale extent to the desired scale
503  const double testScale = mScaleCalculator.calculate( ext, outputSize().width() );
504  ext.scale( scale / testScale );
505  return ext;
506  }
507  else
508  {
509  // Conversion from inches to mapUnits - this is safe to use, because we know here that the map units AREN'T in degrees
510  const double conversionFactor = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceFeet, mapUnits() ) / 12;
511 
512  const double delta = 0.5 * scaledWidthInInches * conversionFactor;
513  return QgsRectangle( center.x() - delta, center.y() - delta, center.x() + delta, center.y() + delta );
514  }
515 }
516 
518 {
519  return mScaleCalculator.calculate( extent, outputSize().width() );
520 }
521 
522 double QgsMapSettings::layerToMapUnits( const QgsMapLayer *layer, const QgsRectangle &referenceExtent ) const
523 {
524  return layerTransform( layer ).scaleFactor( referenceExtent );
525 }
526 
527 
529 {
530  try
531  {
533  if ( ct.isValid() )
534  {
535  QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
536  QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
537  QgsDebugMsgLevel( QStringLiteral( "extent %1" ).arg( extent.toString() ), 3 );
540  }
541  }
542  catch ( QgsCsException &cse )
543  {
544  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
545  }
546 
547  QgsDebugMsgLevel( QStringLiteral( "proj extent = %1 " ).arg( extent.toString() ), 3 );
548 
549  return extent;
550 }
551 
552 
554 {
555  try
556  {
559  if ( ct.isValid() )
560  {
561  QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
562  QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
563  QgsDebugMsgLevel( QStringLiteral( "extent = %1" ).arg( extent.toString() ), 3 );
564  extent = ct.transformBoundingBox( extent, Qgis::TransformDirection::Reverse );
565  }
566  }
567  catch ( QgsCsException &cse )
568  {
569  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
570  }
571 
572  QgsDebugMsgLevel( QStringLiteral( "proj extent = %1" ).arg( extent.toString() ), 3 );
573 
574  return extent;
575 }
576 
577 
579 {
580  try
581  {
582  const QgsCoordinateTransform ct = layerTransform( layer );
583  if ( ct.isValid() )
584  point = ct.transform( point, Qgis::TransformDirection::Forward );
585  }
586  catch ( QgsCsException &cse )
587  {
588  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
589  }
590 
591  return point;
592 }
593 
595 {
596  double x = point.x();
597  double y = point.y();
598  double z = point.z();
599  const double m = point.m();
600 
601  try
602  {
603  const QgsCoordinateTransform ct = layerTransform( layer );
604  if ( ct.isValid() )
605  ct.transformInPlace( x, y, z, Qgis::TransformDirection::Forward );
606  }
607  catch ( QgsCsException &cse )
608  {
609  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
610  }
611 
612  return QgsPoint( x, y, z, m );
613 }
614 
615 
617 {
618  try
619  {
620  const QgsCoordinateTransform ct = layerTransform( layer );
621  if ( ct.isValid() )
622  rect = ct.transform( rect, Qgis::TransformDirection::Forward );
623  }
624  catch ( QgsCsException &cse )
625  {
626  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
627  }
628 
629  return rect;
630 }
631 
632 
634 {
635  try
636  {
637  const QgsCoordinateTransform ct = layerTransform( layer );
638  if ( ct.isValid() )
639  point = ct.transform( point, Qgis::TransformDirection::Reverse );
640  }
641  catch ( QgsCsException &cse )
642  {
643  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
644  }
645 
646  return point;
647 }
648 
650 {
651  double x = point.x();
652  double y = point.y();
653  double z = point.z();
654  const double m = point.m();
655 
656  try
657  {
658  const QgsCoordinateTransform ct = layerTransform( layer );
659  if ( ct.isValid() )
660  ct.transformInPlace( x, y, z, Qgis::TransformDirection::Reverse );
661  }
662  catch ( QgsCsException &cse )
663  {
664  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
665  }
666 
667  return QgsPoint( x, y, z, m );
668 }
669 
670 
672 {
673  try
674  {
675  const QgsCoordinateTransform ct = layerTransform( layer );
676  if ( ct.isValid() )
677  rect = ct.transform( rect, Qgis::TransformDirection::Reverse );
678  }
679  catch ( QgsCsException &cse )
680  {
681  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
682  }
683 
684  return rect;
685 }
686 
687 
688 
690 {
691  // reset the map canvas extent since the extent may now be smaller
692  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
695 
696  // iterate through the map layers and test each layers extent
697  // against the current min and max values
698  QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( mLayers.count() ), 5 );
699  const auto constMLayers = mLayers;
700  for ( const QgsWeakMapLayerPointer &layerPtr : constMLayers )
701  {
702  if ( QgsMapLayer *lyr = layerPtr.data() )
703  {
704  QgsDebugMsgLevel( "Updating extent using " + lyr->name(), 5 );
705  QgsDebugMsgLevel( "Input extent: " + lyr->extent().toString(), 5 );
706 
707  if ( lyr->extent().isNull() )
708  continue;
709 
710  // Layer extents are stored in the coordinate system (CS) of the
711  // layer. The extent must be projected to the canvas CS
712  const QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() );
713 
714  QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
716  }
717  }
718 
719  if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
720  {
721  // If all of the features are at the one point, buffer the
722  // rectangle a bit. If they are all at zero, do something a bit
723  // more crude.
724 
725  if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
726  fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
727  {
728  fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
729  }
730  else
731  {
732  const double padFactor = 1e-8;
733  const double widthPad = fullExtent.xMinimum() * padFactor;
734  const double heightPad = fullExtent.yMinimum() * padFactor;
735  const double xmin = fullExtent.xMinimum() - widthPad;
736  const double xmax = fullExtent.xMaximum() + widthPad;
737  const double ymin = fullExtent.yMinimum() - heightPad;
738  const double ymax = fullExtent.yMaximum() + heightPad;
739  fullExtent.set( xmin, ymin, xmax, ymax );
740  }
741  }
742 
743  QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
744  return fullExtent;
745 }
746 
747 
748 void QgsMapSettings::readXml( QDomNode &node )
749 {
750  // set destination CRS
752  const QDomNode srsNode = node.namedItem( QStringLiteral( "destinationsrs" ) );
753  if ( !srsNode.isNull() )
754  {
755  srs.readXml( srsNode );
756  }
757  setDestinationCrs( srs );
758 
759  // set extent
760  const QDomNode extentNode = node.namedItem( QStringLiteral( "extent" ) );
761  const QgsRectangle aoi = QgsXmlUtils::readRectangle( extentNode.toElement() );
762  setExtent( aoi );
763 
764  // set rotation
765  const QDomNode rotationNode = node.namedItem( QStringLiteral( "rotation" ) );
766  const QString rotationVal = rotationNode.toElement().text();
767  if ( ! rotationVal.isEmpty() )
768  {
769  const double rot = rotationVal.toDouble();
770  setRotation( rot );
771  }
772 
773  //render map tile
774  const QDomElement renderMapTileElem = node.firstChildElement( QStringLiteral( "rendermaptile" ) );
775  if ( !renderMapTileElem.isNull() )
776  {
777  setFlag( Qgis::MapSettingsFlag::RenderMapTile, renderMapTileElem.text() == QLatin1String( "1" ) );
778  }
779 }
780 
781 
782 
783 void QgsMapSettings::writeXml( QDomNode &node, QDomDocument &doc )
784 {
785  // units
786  node.appendChild( QgsXmlUtils::writeMapUnits( mapUnits(), doc ) );
787 
788  // Write current view extents
789  node.appendChild( QgsXmlUtils::writeRectangle( extent(), doc ) );
790 
791  // Write current view rotation
792  QDomElement rotNode = doc.createElement( QStringLiteral( "rotation" ) );
793  rotNode.appendChild(
794  doc.createTextNode( qgsDoubleToString( rotation() ) )
795  );
796  node.appendChild( rotNode );
797 
798  // destination CRS
799  if ( mDestCRS.isValid() )
800  {
801  QDomElement srsNode = doc.createElement( QStringLiteral( "destinationsrs" ) );
802  node.appendChild( srsNode );
803  mDestCRS.writeXml( srsNode, doc );
804  }
805 
806  //render map tile
807  QDomElement renderMapTileElem = doc.createElement( QStringLiteral( "rendermaptile" ) );
808  const QDomText renderMapTileText = doc.createTextNode( testFlag( Qgis::MapSettingsFlag::RenderMapTile ) ? "1" : "0" );
809  renderMapTileElem.appendChild( renderMapTileText );
810  node.appendChild( renderMapTileElem );
811 }
812 
814 {
815  return mLabelBoundaryGeometry;
816 }
817 
819 {
820  mLabelBoundaryGeometry = boundary;
821 }
822 
824 {
825  mClippingRegions.append( region );
826 }
827 
828 void QgsMapSettings::setClippingRegions( const QList<QgsMapClippingRegion> &regions )
829 {
830  mClippingRegions = regions;
831 }
832 
833 QList<QgsMapClippingRegion> QgsMapSettings::clippingRegions() const
834 {
835  return mClippingRegions;
836 }
837 
839 {
840  mRenderedFeatureHandlers.append( handler );
841 }
842 
843 QList<QgsRenderedFeatureHandlerInterface *> QgsMapSettings::renderedFeatureHandlers() const
844 {
845  return mRenderedFeatureHandlers;
846 }
847 
849 {
850  return mZRange;
851 }
852 
854 {
855  mZRange = zRange;
856 }
857 
859 {
860  return mRendererUsage;
861 }
862 
864 {
866 }
867 
869 {
870  return mFrameRate;
871 }
872 
873 void QgsMapSettings::setFrameRate( double rate )
874 {
875  mFrameRate = rate;
876 }
877 
879 {
880  return mCurrentFrame;
881 }
882 
883 void QgsMapSettings::setCurrentFrame( long long frame )
884 {
885  mCurrentFrame = frame;
886 }
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:72
RendererUsage
Usage of the renderer.
Definition: qgis.h:1666
MapSettingsFlag
Coordinate transformation flags.
Definition: qgis.h:1287
@ RenderMapTile
Draw map such that there are no problems between adjacent tiles.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Class for doing transforms between two map coordinate systems.
QgsCoordinateReferenceSystem sourceCrs() const
Returns the source coordinate reference system, which the transform will transform coordinates from.
void setBallparkTransformsAreAppropriate(bool appropriate)
Sets whether approximate "ballpark" results are appropriate for this coordinate transform.
double scaleFactor(const QgsRectangle &referenceExtent) const
Computes an estimated conversion factor between source and destination units:
bool isValid() const
Returns true if the coordinate transform is valid, ie both the source and destination CRS have been s...
void transformInPlace(double &x, double &y, double &z, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transforms an array of x, y and z double coordinates in place, from the source CRS to the destination...
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system, which the transform will transform coordinates t...
QgsRectangle transformBoundingBox(const QgsRectangle &rectangle, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool handle180Crossover=false) const SIP_THROW(QgsCsException)
Transforms a rectangle from the source CRS to the destination CRS.
QgsPointXY transform(const QgsPointXY &point, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
QgsRange which stores a range of double values.
Definition: qgsrange.h:203
static EllipsoidParameters ellipsoidParameters(const QString &ellipsoid)
Returns the parameters for the specified ellipsoid.
QString what() const
Definition: qgsexception.h:48
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
A map layer which consists of a set of child layers, where all component layers are rendered as a sin...
Definition: qgsgrouplayer.h:42
A map clipping region (in map coordinates and CRS).
Base class for all map layer types.
Definition: qgsmaplayer.h:73
QgsCoordinateReferenceSystem crs
Definition: qgsmaplayer.h:79
QSize deviceOutputSize() const
Returns the device output size of the map render.
Qgis::RendererUsage rendererUsage() const
Returns the rendering usage.
QgsVectorSimplifyMethod mSimplifyMethod
void addClippingRegion(const QgsMapClippingRegion &region)
Adds a new clipping region to the map settings.
void writeXml(QDomNode &node, QDomDocument &doc)
QgsPointXY layerToMapCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from layer's CRS to output CRS
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
Qgis::RendererUsage mRendererUsage
QgsRectangle mVisibleExtent
Extent with some additional white space that matches the output aspect ratio.
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
void addRenderedFeatureHandler(QgsRenderedFeatureHandlerInterface *handler)
Adds a rendered feature handler to use while rendering the map settings.
void setLayers(const QList< QgsMapLayer * > &layers)
Sets the list of layers to render in the map.
double scale() const
Returns the calculated map scale.
void setFrameRate(double rate)
Sets the frame rate of the map (in frames per second), for maps which are part of an animation.
void setFlags(Qgis::MapSettingsFlags flags)
Sets combination of flags that will be used for rendering.
Qgis::MapSettingsFlags mFlags
QgsCoordinateTransform layerTransform(const QgsMapLayer *layer) const
Returns the coordinate transform from layer's CRS to destination CRS.
QgsRectangle layerExtentToOutputExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from layer's CRS to output CRS
QgsDoubleRange zRange() const
Returns the range of z-values which will be visible in the map.
bool setEllipsoid(const QString &ellipsoid)
Sets the ellipsoid by its acronym.
void setDpiTarget(double dpi)
Sets the target dpi (dots per inch) to be taken into consideration when rendering.
double magnificationFactor() const
Returns the magnification factor.
double mMapUnitsPerPixel
QgsGeometry labelBoundaryGeometry() const
Returns the label boundary geometry, which restricts where in the rendered map labels are permitted t...
QList< QgsRenderedFeatureHandlerInterface * > renderedFeatureHandlers() const
Returns the list of rendered feature handlers to use while rendering the map settings.
QStringList layerIds(bool expandGroupLayers=false) const
Returns the list of layer IDs which will be rendered in the map.
void setDevicePixelRatio(float dpr)
Sets the device pixel ratio.
QString mEllipsoid
ellipsoid acronym (from table tbl_ellipsoids)
void setZRange(const QgsDoubleRange &range)
Sets the range of z-values which will be visible in the map.
double dpiTarget() const
Returns the target DPI (dots per inch) to be taken into consideration when rendering.
long long currentFrame() const
Returns the current frame number of the map, for maps which are part of an animation.
bool mValid
Whether the actual settings are valid (set in updateDerived())
void setOutputDpi(double dpi)
Sets the dpi (dots per inch) used for conversion between real world units (e.g.
double mapUnitsPerPixel() const
Returns the distance in geographical coordinates that equals to one pixel in the map.
void setRendererUsage(Qgis::RendererUsage rendererUsage)
Sets the rendering usage.
float devicePixelRatio() const
Returns the device pixel ratio.
QgsRectangle mExtent
QSize outputSize() const
Returns the size of the resulting map image, in pixels.
QgsRectangle extent() const
Returns geographical coordinates of the rectangle that should be rendered.
QMap< QString, QString > mLayerStyleOverrides
QgsGeometry mLabelBoundaryGeometry
void setLayerStyleOverrides(const QMap< QString, QString > &overrides)
Sets the map of map layer style overrides (key: layer ID, value: style name) where a different style ...
QgsCoordinateTransformContext mTransformContext
void setExtent(const QgsRectangle &rect, bool magnified=true)
Sets the coordinates of the rectangle which should be rendered.
void setClippingRegions(const QList< QgsMapClippingRegion > &regions)
Sets the list of clipping regions to apply to the map.
double layerToMapUnits(const QgsMapLayer *layer, const QgsRectangle &referenceExtent=QgsRectangle()) const
Computes an estimated conversion factor between layer and map units: layerUnits * layerToMapUnits = m...
double extentBuffer() const
Returns the buffer in map units to use around the visible extent for rendering symbols whose correspo...
QgsScaleCalculator mScaleCalculator
Qgis::MapSettingsFlags flags() const
Returns combination of flags used for rendering.
QgsUnitTypes::DistanceUnit mapUnits() const
Returns the units of the map's geographical coordinates - used for scale calculation.
double frameRate() const
Returns the frame rate of the map (in frames per second), for maps which are part of an animation.
const QgsMapToPixel & mapToPixel() const
void setExtentBuffer(double buffer)
Sets the buffer in map units to use around the visible extent for rendering symbols whose correspondi...
QgsRectangle visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
QgsRectangle outputExtentToLayerExtent(const QgsMapLayer *layer, QgsRectangle extent) const
transform bounding box from output CRS to layer's CRS
QgsRectangle fullExtent() const
returns current extent of layer set
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the coordinate transform context, which stores various information regarding which datum transfo...
void setRotation(double rotation)
Sets the rotation of the resulting map image, in degrees clockwise.
double computeScaleForExtent(const QgsRectangle &extent) const
Compute the scale that corresponds to the specified extent.
QString ellipsoid() const
Returns ellipsoid's acronym.
double mMagnificationFactor
void setCurrentFrame(long long frame)
Sets the current frame of the map, for maps which are part of an animation.
QgsCoordinateReferenceSystem mDestCRS
double outputDpi() const
Returns the DPI (dots per inch) used for conversion between real world units (e.g.
void setLabelBoundaryGeometry(const QgsGeometry &boundary)
Sets the label boundary geometry, which restricts where in the rendered map labels are permitted to b...
QgsMapToPixel mMapToPixel
bool testFlag(Qgis::MapSettingsFlag flag) const
Check whether a particular flag is enabled.
QMap< QString, QString > layerStyleOverrides() const
Returns the map of map layer style overrides (key: layer ID, value: style name) where a different sty...
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
QList< QgsMapClippingRegion > clippingRegions() const
Returns the list of clipping regions to apply to the map.
bool hasValidSettings() const
Check whether the map settings are valid and can be used for rendering.
QgsWeakMapLayerPointerList mLayers
list of layers to be rendered (stored as weak pointers)
void setOutputSize(QSize size)
Sets the size of the resulting map image, in pixels.
QgsPointXY mapToLayerCoordinates(const QgsMapLayer *layer, QgsPointXY point) const
transform point coordinates from output CRS to layer's CRS
long long mCurrentFrame
QgsCoordinateReferenceSystem destinationCrs() const
Returns the destination coordinate reference system for the map render.
QPolygonF visiblePolygonWithBuffer() const
Returns the visible area as a polygon (may be rotated) with extent buffer included.
void setFlag(Qgis::MapSettingsFlag flag, bool on=true)
Enable or disable a particular flag (other flags are not affected)
void setDestinationCrs(const QgsCoordinateReferenceSystem &crs)
Sets the destination crs (coordinate reference system) for the map render.
void readXml(QDomNode &node)
QgsRectangle computeExtentForScale(const QgsPointXY &center, double scale) const
Compute the extent such that its center is at the specified position (mapped to the destinatonCrs) an...
void setMagnificationFactor(double factor, const QgsPointXY *center=nullptr)
Set the magnification factor.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context, which stores various information regarding which datum tran...
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
QgsPointXY toMapCoordinates(int x, int y) const
Transforms device coordinates to map (world) coordinates.
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Sets parameters for use in transforming coordinates.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
A class to represent a 2D point.
Definition: qgspointxy.h:59
double y
Definition: qgspointxy.h:63
Q_GADGET double x
Definition: qgspointxy.h:62
QPointF toQPointF() const
Converts a point to a QPointF.
Definition: qgspointxy.h:169
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double z
Definition: qgspoint.h:54
double m
Definition: qgspoint.h:55
double y
Definition: qgspoint.h:53
A rectangle specified with double values.
Definition: qgsrectangle.h:42
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
Definition: qgsrectangle.h:256
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
QString asWktCoordinates() const
Returns a string representation of the rectangle in WKT format.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
Definition: qgsrectangle.h:230
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
Definition: qgsrectangle.h:122
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
Definition: qgsrectangle.h:172
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
Definition: qgsrectangle.h:391
bool isEmpty() const
Returns true if the rectangle is empty.
Definition: qgsrectangle.h:469
bool isFinite() const
Returns true if the rectangle has finite boundaries.
Definition: qgsrectangle.h:559
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
An interface for classes which provider custom handlers for features rendered as part of a map render...
double calculate(const QgsRectangle &mapExtent, double canvasWidth) const
Calculate the scale denominator.
void setDpi(double dpi)
Sets the dpi (dots per inch) for the output resolution, to be used in scale calculations.
void setMapUnits(QgsUnitTypes::DistanceUnit mapUnits)
Set the map units.
QgsUnitTypes::DistanceUnit mapUnits() const
Returns current map units.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:68
@ DistanceDegrees
Degrees, for planar geographic CRS distance measurements.
Definition: qgsunittypes.h:75
@ DistanceUnknownUnit
Unknown distance unit.
Definition: qgsunittypes.h:78
@ DistanceFeet
Imperial feet.
Definition: qgsunittypes.h:71
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
void setSimplifyHints(SimplifyHints simplifyHints)
Sets the simplification hints of the vector layer managed.
@ NoSimplification
No simplification can be applied.
static QDomElement writeRectangle(const QgsRectangle &rect, QDomDocument &doc, const QString &elementName=QStringLiteral("extent"))
Encodes a rectangle to a DOM element.
Definition: qgsxmlutils.cpp:81
static QDomElement writeMapUnits(QgsUnitTypes::DistanceUnit units, QDomDocument &doc)
Encodes a distance unit to a DOM element.
Definition: qgsxmlutils.cpp:69
static QgsRectangle readRectangle(const QDomElement &element)
Definition: qgsxmlutils.cpp:39
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:2199
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2260
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:2146
Q_GUI_EXPORT int qt_defaultDpiX()
const QgsCoordinateReferenceSystem & crs
Contains parameters for an ellipsoid.
bool valid
Whether ellipsoid parameters are valid.