QGIS API Documentation  3.21.0-Master (5b68dc587e)
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.h"
26 #include "qgsproject.h"
27 #include "qgsxmlutils.h"
28 #include "qgsexception.h"
29 #include "qgsgeometry.h"
30 
31 Q_GUI_EXPORT extern int qt_defaultDpiX();
32 
33 
35  : mDpi( qt_defaultDpiX() ) // DPI that will be used by default for QImage instances
36  , mSize( QSize( 0, 0 ) )
37  , mBackgroundColor( Qt::white )
38  , mSelectionColor( Qt::yellow )
39  , mFlags( Qgis::MapSettingsFlag::Antialiasing | Qgis::MapSettingsFlag::UseAdvancedEffects | Qgis::MapSettingsFlag::DrawLabeling | Qgis::MapSettingsFlag::DrawSelection )
40  , mSegmentationTolerance( M_PI_2 / 90 )
41 {
44 
45  updateDerived();
46 }
47 
48 void QgsMapSettings::setMagnificationFactor( double factor, const QgsPointXY *center )
49 {
50  const double ratio = mMagnificationFactor / factor;
51 
52  mMagnificationFactor = factor;
53 
54  const double rot = rotation();
55  setRotation( 0.0 );
56 
58  ext.scale( ratio, center );
59 
60  mRotation = rot;
61  mExtent = ext;
62  mDpi = mDpi / ratio;
63 
64  QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1 dpi: %2 ratio: %3" ).arg( factor ).arg( mDpi ).arg( ratio ), 3 );
65 
66  updateDerived();
67 }
68 
70 {
71  return mMagnificationFactor;
72 }
73 
75 {
76  return mExtent;
77 }
78 
79 void QgsMapSettings::setExtent( const QgsRectangle &extent, bool magnified )
80 {
81  QgsRectangle magnifiedExtent = extent;
82 
83  if ( !magnified )
84  magnifiedExtent.scale( 1 / mMagnificationFactor );
85 
86  mExtent = magnifiedExtent;
87 
88  updateDerived();
89 }
90 
92 {
93  return mExtentBuffer;
94 }
95 
96 void QgsMapSettings::setExtentBuffer( const double buffer )
97 {
98  mExtentBuffer = buffer;
99 }
100 
102 {
103  return mRotation;
104 }
105 
106 void QgsMapSettings::setRotation( double degrees )
107 {
108  if ( qgsDoubleNear( mRotation, degrees ) )
109  return;
110 
111  mRotation = degrees;
112 
113  // TODO: update extent while keeping scale ?
114  updateDerived();
115 }
116 
117 
119 {
120  const QgsRectangle extent = mExtent;
121 
122  if ( extent.isEmpty() || !extent.isFinite() )
123  {
124  mValid = false;
125  return;
126  }
127 
128  // Don't allow zooms where the current extent is so small that it
129  // can't be accurately represented using a double (which is what
130  // currentExtent uses). Excluding 0 avoids a divide by zero and an
131  // infinite loop when rendering to a new canvas. Excluding extents
132  // greater than 1 avoids doing unnecessary calculations.
133 
134  // The scheme is to compare the width against the mean x coordinate
135  // (and height against mean y coordinate) and only allow zooms where
136  // the ratio indicates that there is more than about 12 significant
137  // figures (there are about 16 significant figures in a double).
138 
139  if ( extent.width() > 0 &&
140  extent.height() > 0 &&
141  extent.width() < 1 &&
142  extent.height() < 1 )
143  {
144  // Use abs() on the extent to avoid the case where the extent is
145  // symmetrical about 0.
146  const double xMean = ( std::fabs( extent.xMinimum() ) + std::fabs( extent.xMaximum() ) ) * 0.5;
147  const double yMean = ( std::fabs( extent.yMinimum() ) + std::fabs( extent.yMaximum() ) ) * 0.5;
148 
149  const double xRange = extent.width() / xMean;
150  const double yRange = extent.height() / yMean;
151 
152  static const double MIN_PROPORTION = 1e-12;
153  if ( xRange < MIN_PROPORTION || yRange < MIN_PROPORTION )
154  {
155  mValid = false;
156  return;
157  }
158  }
159 
160  const double myHeight = mSize.height();
161  const double myWidth = mSize.width();
162 
163  if ( !myWidth || !myHeight )
164  {
165  mValid = false;
166  return;
167  }
168 
169  // calculate the translation and scaling parameters
170  const double mapUnitsPerPixelY = mExtent.height() / myHeight;
171  const double mapUnitsPerPixelX = mExtent.width() / myWidth;
172  mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
173 
174  // calculate the actual extent of the mapCanvas
175  double dxmin = mExtent.xMinimum(), dxmax = mExtent.xMaximum(),
176  dymin = mExtent.yMinimum(), dymax = mExtent.yMaximum(), whitespace;
177 
178  if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
179  {
180  whitespace = ( ( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
181  dxmin -= whitespace;
182  dxmax += whitespace;
183  }
184  else
185  {
186  whitespace = ( ( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
187  dymin -= whitespace;
188  dymax += whitespace;
189  }
190 
191  mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
192 
193  // update the scale
196 
197  bool ok = true;
200  visibleExtent().center().x(),
201  visibleExtent().center().y(),
202  outputSize().width(),
203  outputSize().height(),
204  mRotation, &ok );
205 
206  mValid = ok;
207 
208 #if 1 // set visible extent taking rotation in consideration
209  if ( mRotation )
210  {
211  const QgsPointXY p1 = mMapToPixel.toMapCoordinates( QPoint( 0, 0 ) );
212  const QgsPointXY p2 = mMapToPixel.toMapCoordinates( QPoint( 0, myHeight ) );
213  const QgsPointXY p3 = mMapToPixel.toMapCoordinates( QPoint( myWidth, 0 ) );
214  const QgsPointXY p4 = mMapToPixel.toMapCoordinates( QPoint( myWidth, myHeight ) );
215  dxmin = std::min( p1.x(), std::min( p2.x(), std::min( p3.x(), p4.x() ) ) );
216  dymin = std::min( p1.y(), std::min( p2.y(), std::min( p3.y(), p4.y() ) ) );
217  dxmax = std::max( p1.x(), std::max( p2.x(), std::max( p3.x(), p4.x() ) ) );
218  dymax = std::max( p1.y(), std::max( p2.y(), std::max( p3.y(), p4.y() ) ) );
219  mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
220  }
221 #endif
222 
223  QgsDebugMsgLevel( QStringLiteral( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ), 5 );
224  QgsDebugMsgLevel( QStringLiteral( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mSize.width() ), qgsDoubleToString( mSize.height() ) ), 5 );
225  QgsDebugMsgLevel( QStringLiteral( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ), 5 );
227  QgsDebugMsgLevel( QStringLiteral( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / myWidth ), qgsDoubleToString( mVisibleExtent.height() / myHeight ) ), 5 );
228  QgsDebugMsgLevel( QStringLiteral( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ), 5 );
229  QgsDebugMsgLevel( QStringLiteral( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ), 5 );
230  QgsDebugMsgLevel( QStringLiteral( "Rotation: %1 degrees" ).arg( mRotation ), 5 );
231  QgsDebugMsgLevel( QStringLiteral( "Extent: %1" ).arg( mExtent.asWktCoordinates() ), 5 );
232  QgsDebugMsgLevel( QStringLiteral( "Visible Extent: %1" ).arg( mVisibleExtent.asWktCoordinates() ), 5 );
233  QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1" ).arg( mMagnificationFactor ), 5 );
234 
235 }
236 
237 
239 {
240  return mSize;
241 }
242 
244 {
245  mSize = size;
246 
247  updateDerived();
248 }
249 
251 {
252  return mDevicePixelRatio;
253 }
254 
256 {
257  mDevicePixelRatio = dpr;
258  updateDerived();
259 }
260 
262 {
263  return outputSize() * mDevicePixelRatio;
264 }
265 
267 {
268  return mDpi;
269 }
270 
272 {
273  mDpi = dpi;
274 
275  updateDerived();
276 }
277 
279 {
280  return mDpiTarget;
281 }
282 
284 {
285  mDpiTarget = dpi;
286 }
287 
288 QStringList QgsMapSettings::layerIds() const
289 {
290  return _qgis_listQPointerToIDs( mLayers );
291 }
292 
293 
294 QList<QgsMapLayer *> QgsMapSettings::layers() const
295 {
296  return _qgis_listQPointerToRaw( mLayers );
297 }
298 
299 void QgsMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
300 {
301  // filter list, removing null layers and non-spatial layers
302  auto filteredList = layers;
303  filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(),
304  []( QgsMapLayer * layer )
305  {
306  return !layer || !layer->isSpatial();
307  } ), filteredList.end() );
308 
309  mLayers = _qgis_listRawToQPointer( filteredList );
310 }
311 
312 QMap<QString, QString> QgsMapSettings::layerStyleOverrides() const
313 {
314  return mLayerStyleOverrides;
315 }
316 
317 void QgsMapSettings::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
318 {
319  mLayerStyleOverrides = overrides;
320 }
321 
323 {
324  mDestCRS = crs;
326  // Since the map units have changed, force a recalculation of the scale.
327  updateDerived();
328 }
329 
331 {
332  return mDestCRS;
333 }
334 
335 bool QgsMapSettings::setEllipsoid( const QString &ellipsoid )
336 {
338  if ( !params.valid )
339  {
340  return false;
341  }
342  else
343  {
345  return true;
346  }
347 }
348 
349 void QgsMapSettings::setFlags( Qgis::MapSettingsFlags flags )
350 {
351  mFlags = flags;
352 }
353 
355 {
356  if ( on )
357  mFlags |= flag;
358  else
359  mFlags &= ~( static_cast< int >( flag ) );
360 }
361 
362 Qgis::MapSettingsFlags QgsMapSettings::flags() const
363 {
364  return mFlags;
365 }
366 
368 {
369  return mFlags.testFlag( flag );
370 }
371 
373 {
374  return mScaleCalculator.mapUnits();
375 }
376 
377 
379 {
380  return mValid;
381 }
382 
384 {
385  return mVisibleExtent;
386 }
387 
389 {
390  QPolygonF poly;
391 
392  const QSize &sz = outputSize();
393  const QgsMapToPixel &m2p = mapToPixel();
394 
395  poly << m2p.toMapCoordinates( 0.0, 0.0 ).toQPointF();
396  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), 0.0 ).toQPointF();
397  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), static_cast<double>( sz.height() ) ).toQPointF();
398  poly << m2p.toMapCoordinates( 0.0, static_cast<double>( sz.height() ) ).toQPointF();
399 
400  return poly;
401 }
402 
404 {
405  QPolygonF poly;
406 
407  const QSize &sz = outputSize();
408  const QgsMapToPixel &m2p = mapToPixel();
409 
410  // Transform tilebuffer in pixel.
411  // Original tilebuffer is in pixel and transformed only according
412  // extent width (see QgsWmsRenderContext::mapTileBuffer)
413 
414  const double mapUnitsPerPixel = mExtent.width() / sz.width();
415  const double buffer = mExtentBuffer / mapUnitsPerPixel;
416 
417  poly << m2p.toMapCoordinates( -buffer, -buffer ).toQPointF();
418  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() + buffer ), -buffer ).toQPointF();
419  poly << m2p.toMapCoordinates( static_cast<double>( sz.width() + buffer ), static_cast<double>( sz.height() + buffer ) ).toQPointF();
420  poly << m2p.toMapCoordinates( -buffer, static_cast<double>( sz.height() + buffer ) ).toQPointF();
421 
422  return poly;
423 }
424 
426 {
427  return mMapUnitsPerPixel;
428 }
429 
430 double QgsMapSettings::scale() const
431 {
432  return mScale;
433 }
434 
436 {
437 #ifdef QGISDEBUG
438  if ( !mHasTransformContext )
439  QgsDebugMsgLevel( QStringLiteral( "No QgsCoordinateTransformContext context set for transform" ), 4 );
440 #endif
441 
442  return mTransformContext;
443 }
444 
446 {
447  mTransformContext = context;
448 #ifdef QGISDEBUG
449  mHasTransformContext = true;
450 #endif
451 }
452 
454 {
455  if ( !layer )
456  return QgsCoordinateTransform();
457 
459 }
460 
462 {
463  // Output width in inches
464  const double outputWidthInInches = outputSize().width() / outputDpi();
465 
466  // Desired visible width (honouring scale)
467  const double scaledWidthInInches = outputWidthInInches * scale;
468 
470  {
471  // Start with some fraction of the current extent around the center
472  const double delta = mExtent.width() / 100.;
473  QgsRectangle ext( center.x() - delta, center.y() - delta, center.x() + delta, center.y() + delta );
474  // Get scale at extent, and then scale extent to the desired scale
475  const double testScale = mScaleCalculator.calculate( ext, outputSize().width() );
476  ext.scale( scale / testScale );
477  return ext;
478  }
479  else
480  {
481  // Conversion from inches to mapUnits - this is safe to use, because we know here that the map units AREN'T in degrees
482  const double conversionFactor = QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::DistanceFeet, mapUnits() ) / 12;
483 
484  const double delta = 0.5 * scaledWidthInInches * conversionFactor;
485  return QgsRectangle( center.x() - delta, center.y() - delta, center.x() + delta, center.y() + delta );
486  }
487 }
488 
490 {
491  return mScaleCalculator.calculate( extent, outputSize().width() );
492 }
493 
494 double QgsMapSettings::layerToMapUnits( const QgsMapLayer *layer, const QgsRectangle &referenceExtent ) const
495 {
496  return layerTransform( layer ).scaleFactor( referenceExtent );
497 }
498 
499 
501 {
502  try
503  {
505  if ( ct.isValid() )
506  {
507  QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
508  QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
509  QgsDebugMsgLevel( QStringLiteral( "extent %1" ).arg( extent.toString() ), 3 );
512  }
513  }
514  catch ( QgsCsException &cse )
515  {
516  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
517  }
518 
519  QgsDebugMsgLevel( QStringLiteral( "proj extent = %1 " ).arg( extent.toString() ), 3 );
520 
521  return extent;
522 }
523 
524 
526 {
527  try
528  {
531  if ( ct.isValid() )
532  {
533  QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
534  QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
535  QgsDebugMsgLevel( QStringLiteral( "extent = %1" ).arg( extent.toString() ), 3 );
536  extent = ct.transformBoundingBox( extent, Qgis::TransformDirection::Reverse );
537  }
538  }
539  catch ( QgsCsException &cse )
540  {
541  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
542  }
543 
544  QgsDebugMsgLevel( QStringLiteral( "proj extent = %1" ).arg( extent.toString() ), 3 );
545 
546  return extent;
547 }
548 
549 
551 {
552  try
553  {
554  const QgsCoordinateTransform ct = layerTransform( layer );
555  if ( ct.isValid() )
556  point = ct.transform( point, Qgis::TransformDirection::Forward );
557  }
558  catch ( QgsCsException &cse )
559  {
560  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
561  }
562 
563  return point;
564 }
565 
567 {
568  double x = point.x();
569  double y = point.y();
570  double z = point.z();
571  const double m = point.m();
572 
573  try
574  {
575  const QgsCoordinateTransform ct = layerTransform( layer );
576  if ( ct.isValid() )
577  ct.transformInPlace( x, y, z, Qgis::TransformDirection::Forward );
578  }
579  catch ( QgsCsException &cse )
580  {
581  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
582  }
583 
584  return QgsPoint( x, y, z, m );
585 }
586 
587 
589 {
590  try
591  {
592  const QgsCoordinateTransform ct = layerTransform( layer );
593  if ( ct.isValid() )
594  rect = ct.transform( rect, Qgis::TransformDirection::Forward );
595  }
596  catch ( QgsCsException &cse )
597  {
598  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
599  }
600 
601  return rect;
602 }
603 
604 
606 {
607  try
608  {
609  const QgsCoordinateTransform ct = layerTransform( layer );
610  if ( ct.isValid() )
611  point = ct.transform( point, Qgis::TransformDirection::Reverse );
612  }
613  catch ( QgsCsException &cse )
614  {
615  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
616  }
617 
618  return point;
619 }
620 
622 {
623  double x = point.x();
624  double y = point.y();
625  double z = point.z();
626  const double m = point.m();
627 
628  try
629  {
630  const QgsCoordinateTransform ct = layerTransform( layer );
631  if ( ct.isValid() )
632  ct.transformInPlace( x, y, z, Qgis::TransformDirection::Reverse );
633  }
634  catch ( QgsCsException &cse )
635  {
636  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
637  }
638 
639  return QgsPoint( x, y, z, m );
640 }
641 
642 
644 {
645  try
646  {
647  const QgsCoordinateTransform ct = layerTransform( layer );
648  if ( ct.isValid() )
649  rect = ct.transform( rect, Qgis::TransformDirection::Reverse );
650  }
651  catch ( QgsCsException &cse )
652  {
653  QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
654  }
655 
656  return rect;
657 }
658 
659 
660 
662 {
663  // reset the map canvas extent since the extent may now be smaller
664  // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
667 
668  // iterate through the map layers and test each layers extent
669  // against the current min and max values
670  QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( mLayers.count() ), 5 );
671  const auto constMLayers = mLayers;
672  for ( const QgsWeakMapLayerPointer &layerPtr : constMLayers )
673  {
674  if ( QgsMapLayer *lyr = layerPtr.data() )
675  {
676  QgsDebugMsgLevel( "Updating extent using " + lyr->name(), 5 );
677  QgsDebugMsgLevel( "Input extent: " + lyr->extent().toString(), 5 );
678 
679  if ( lyr->extent().isNull() )
680  continue;
681 
682  // Layer extents are stored in the coordinate system (CS) of the
683  // layer. The extent must be projected to the canvas CS
684  const QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() );
685 
686  QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
688  }
689  }
690 
691  if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
692  {
693  // If all of the features are at the one point, buffer the
694  // rectangle a bit. If they are all at zero, do something a bit
695  // more crude.
696 
697  if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
698  fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
699  {
700  fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
701  }
702  else
703  {
704  const double padFactor = 1e-8;
705  const double widthPad = fullExtent.xMinimum() * padFactor;
706  const double heightPad = fullExtent.yMinimum() * padFactor;
707  const double xmin = fullExtent.xMinimum() - widthPad;
708  const double xmax = fullExtent.xMaximum() + widthPad;
709  const double ymin = fullExtent.yMinimum() - heightPad;
710  const double ymax = fullExtent.yMaximum() + heightPad;
711  fullExtent.set( xmin, ymin, xmax, ymax );
712  }
713  }
714 
715  QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
716  return fullExtent;
717 }
718 
719 
720 void QgsMapSettings::readXml( QDomNode &node )
721 {
722  // set destination CRS
724  const QDomNode srsNode = node.namedItem( QStringLiteral( "destinationsrs" ) );
725  if ( !srsNode.isNull() )
726  {
727  srs.readXml( srsNode );
728  }
729  setDestinationCrs( srs );
730 
731  // set extent
732  const QDomNode extentNode = node.namedItem( QStringLiteral( "extent" ) );
733  const QgsRectangle aoi = QgsXmlUtils::readRectangle( extentNode.toElement() );
734  setExtent( aoi );
735 
736  // set rotation
737  const QDomNode rotationNode = node.namedItem( QStringLiteral( "rotation" ) );
738  const QString rotationVal = rotationNode.toElement().text();
739  if ( ! rotationVal.isEmpty() )
740  {
741  const double rot = rotationVal.toDouble();
742  setRotation( rot );
743  }
744 
745  //render map tile
746  const QDomElement renderMapTileElem = node.firstChildElement( QStringLiteral( "rendermaptile" ) );
747  if ( !renderMapTileElem.isNull() )
748  {
749  setFlag( Qgis::MapSettingsFlag::RenderMapTile, renderMapTileElem.text() == QLatin1String( "1" ) );
750  }
751 }
752 
753 
754 
755 void QgsMapSettings::writeXml( QDomNode &node, QDomDocument &doc )
756 {
757  // units
758  node.appendChild( QgsXmlUtils::writeMapUnits( mapUnits(), doc ) );
759 
760  // Write current view extents
761  node.appendChild( QgsXmlUtils::writeRectangle( extent(), doc ) );
762 
763  // Write current view rotation
764  QDomElement rotNode = doc.createElement( QStringLiteral( "rotation" ) );
765  rotNode.appendChild(
766  doc.createTextNode( qgsDoubleToString( rotation() ) )
767  );
768  node.appendChild( rotNode );
769 
770  // destination CRS
771  if ( mDestCRS.isValid() )
772  {
773  QDomElement srsNode = doc.createElement( QStringLiteral( "destinationsrs" ) );
774  node.appendChild( srsNode );
775  mDestCRS.writeXml( srsNode, doc );
776  }
777 
778  //render map tile
779  QDomElement renderMapTileElem = doc.createElement( QStringLiteral( "rendermaptile" ) );
780  const QDomText renderMapTileText = doc.createTextNode( testFlag( Qgis::MapSettingsFlag::RenderMapTile ) ? "1" : "0" );
781  renderMapTileElem.appendChild( renderMapTileText );
782  node.appendChild( renderMapTileElem );
783 }
784 
786 {
787  return mLabelBoundaryGeometry;
788 }
789 
791 {
792  mLabelBoundaryGeometry = boundary;
793 }
794 
796 {
797  mClippingRegions.append( region );
798 }
799 
800 void QgsMapSettings::setClippingRegions( const QList<QgsMapClippingRegion> &regions )
801 {
802  mClippingRegions = regions;
803 }
804 
805 QList<QgsMapClippingRegion> QgsMapSettings::clippingRegions() const
806 {
807  return mClippingRegions;
808 }
809 
811 {
812  mRenderedFeatureHandlers.append( handler );
813 }
814 
815 QList<QgsRenderedFeatureHandlerInterface *> QgsMapSettings::renderedFeatureHandlers() const
816 {
817  return mRenderedFeatureHandlers;
818 }
819 
821 {
822  return mZRange;
823 }
824 
826 {
827  mZRange = zRange;
828 }
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:63
MapSettingsFlag
Flags which adjust the way maps are rendered.
Definition: qgis.h:908
@ 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.
QString authid() const
Returns the authority identifier for the CRS.
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:124
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.
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
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 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.
QStringList layerIds() const
Returns the list of layer IDs which will be rendered in the map.
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.
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.
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.
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.
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
QList< QgsMapLayer * > layers() const
Returns the list of layers which will be rendered in the map.
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
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:1186
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:1234
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
Definition: qgsmaplayer.h:2129
Q_GUI_EXPORT int qt_defaultDpiX()
const QgsCoordinateReferenceSystem & crs
Contains parameters for an ellipsoid.
bool valid
Whether ellipsoid parameters are valid.