LCOV - code coverage report
Current view: top level - core - qgsmapsettings.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 28 405 6.9 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       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                 :            : 
      34                 :          6 : QgsMapSettings::QgsMapSettings()
      35                 :          6 :   : mDpi( qt_defaultDpiX() ) // DPI that will be used by default for QImage instances
      36                 :          6 :   , mSize( QSize( 0, 0 ) )
      37                 :          6 :   , mBackgroundColor( Qt::white )
      38                 :          6 :   , mSelectionColor( Qt::yellow )
      39                 :          6 :   , mFlags( Antialiasing | UseAdvancedEffects | DrawLabeling | DrawSelection )
      40                 :          6 :   , mSegmentationTolerance( M_PI_2 / 90 )
      41                 :         12 : {
      42                 :          6 :   mScaleCalculator.setMapUnits( QgsUnitTypes::DistanceUnknownUnit );
      43                 :          6 :   mSimplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
      44                 :            : 
      45                 :          6 :   updateDerived();
      46                 :          6 : }
      47                 :            : 
      48                 :          0 : void QgsMapSettings::setMagnificationFactor( double factor, const QgsPointXY *center )
      49                 :            : {
      50                 :          0 :   double ratio = mMagnificationFactor / factor;
      51                 :            : 
      52                 :          0 :   mMagnificationFactor = factor;
      53                 :            : 
      54                 :          0 :   double rot = rotation();
      55                 :          0 :   setRotation( 0.0 );
      56                 :            : 
      57                 :          0 :   QgsRectangle ext = visibleExtent();
      58                 :          0 :   ext.scale( ratio, center );
      59                 :            : 
      60                 :          0 :   mRotation = rot;
      61                 :          0 :   mExtent = ext;
      62                 :          0 :   mDpi = mDpi / ratio;
      63                 :            : 
      64                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1  dpi: %2  ratio: %3" ).arg( factor ).arg( mDpi ).arg( ratio ), 3 );
      65                 :            : 
      66                 :          0 :   updateDerived();
      67                 :          0 : }
      68                 :            : 
      69                 :          0 : double QgsMapSettings::magnificationFactor() const
      70                 :            : {
      71                 :          0 :   return mMagnificationFactor;
      72                 :            : }
      73                 :            : 
      74                 :          0 : QgsRectangle QgsMapSettings::extent() const
      75                 :            : {
      76                 :          0 :   return mExtent;
      77                 :            : }
      78                 :            : 
      79                 :          0 : void QgsMapSettings::setExtent( const QgsRectangle &extent, bool magnified )
      80                 :            : {
      81                 :          0 :   QgsRectangle magnifiedExtent = extent;
      82                 :            : 
      83                 :          0 :   if ( !magnified )
      84                 :          0 :     magnifiedExtent.scale( 1 / mMagnificationFactor );
      85                 :            : 
      86                 :          0 :   mExtent = magnifiedExtent;
      87                 :            : 
      88                 :          0 :   updateDerived();
      89                 :          0 : }
      90                 :            : 
      91                 :          0 : double QgsMapSettings::extentBuffer() const
      92                 :            : {
      93                 :          0 :   return mExtentBuffer;
      94                 :            : }
      95                 :            : 
      96                 :          0 : void QgsMapSettings::setExtentBuffer( const double buffer )
      97                 :            : {
      98                 :          0 :   mExtentBuffer = buffer;
      99                 :          0 : }
     100                 :            : 
     101                 :          0 : double QgsMapSettings::rotation() const
     102                 :            : {
     103                 :          0 :   return mRotation;
     104                 :            : }
     105                 :            : 
     106                 :          0 : void QgsMapSettings::setRotation( double degrees )
     107                 :            : {
     108                 :          0 :   if ( qgsDoubleNear( mRotation, degrees ) )
     109                 :          0 :     return;
     110                 :            : 
     111                 :          0 :   mRotation = degrees;
     112                 :            : 
     113                 :            :   // TODO: update extent while keeping scale ?
     114                 :          0 :   updateDerived();
     115                 :          0 : }
     116                 :            : 
     117                 :            : 
     118                 :          6 : void QgsMapSettings::updateDerived()
     119                 :            : {
     120                 :          6 :   QgsRectangle extent = mExtent;
     121                 :            : 
     122                 :          6 :   if ( extent.isEmpty() || !extent.isFinite() )
     123                 :            :   {
     124                 :          6 :     mValid = false;
     125                 :          6 :     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                 :          0 :   if ( extent.width()  > 0 &&
     140                 :          0 :        extent.height() > 0 &&
     141                 :          0 :        extent.width()  < 1 &&
     142                 :          0 :        extent.height() < 1 )
     143                 :            :   {
     144                 :            :     // Use abs() on the extent to avoid the case where the extent is
     145                 :            :     // symmetrical about 0.
     146                 :          0 :     double xMean = ( std::fabs( extent.xMinimum() ) + std::fabs( extent.xMaximum() ) ) * 0.5;
     147                 :          0 :     double yMean = ( std::fabs( extent.yMinimum() ) + std::fabs( extent.yMaximum() ) ) * 0.5;
     148                 :            : 
     149                 :          0 :     double xRange = extent.width() / xMean;
     150                 :          0 :     double yRange = extent.height() / yMean;
     151                 :            : 
     152                 :            :     static const double MIN_PROPORTION = 1e-12;
     153                 :          0 :     if ( xRange < MIN_PROPORTION || yRange < MIN_PROPORTION )
     154                 :            :     {
     155                 :          0 :       mValid = false;
     156                 :          0 :       return;
     157                 :            :     }
     158                 :          0 :   }
     159                 :            : 
     160                 :          0 :   double myHeight = mSize.height();
     161                 :          0 :   double myWidth = mSize.width();
     162                 :            : 
     163                 :          0 :   if ( !myWidth || !myHeight )
     164                 :            :   {
     165                 :          0 :     mValid = false;
     166                 :          0 :     return;
     167                 :            :   }
     168                 :            : 
     169                 :            :   // calculate the translation and scaling parameters
     170                 :          0 :   double mapUnitsPerPixelY = mExtent.height() / myHeight;
     171                 :          0 :   double mapUnitsPerPixelX = mExtent.width() / myWidth;
     172                 :          0 :   mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
     173                 :            : 
     174                 :            :   // calculate the actual extent of the mapCanvas
     175                 :          0 :   double dxmin = mExtent.xMinimum(), dxmax = mExtent.xMaximum(),
     176                 :          0 :          dymin = mExtent.yMinimum(), dymax = mExtent.yMaximum(), whitespace;
     177                 :            : 
     178                 :          0 :   if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
     179                 :            :   {
     180                 :          0 :     whitespace = ( ( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
     181                 :          0 :     dxmin -= whitespace;
     182                 :          0 :     dxmax += whitespace;
     183                 :          0 :   }
     184                 :            :   else
     185                 :            :   {
     186                 :          0 :     whitespace = ( ( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
     187                 :          0 :     dymin -= whitespace;
     188                 :          0 :     dymax += whitespace;
     189                 :            :   }
     190                 :            : 
     191                 :          0 :   mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
     192                 :            : 
     193                 :            :   // update the scale
     194                 :          0 :   mScaleCalculator.setDpi( mDpi * mDevicePixelRatio );
     195                 :          0 :   mScale = mScaleCalculator.calculate( mVisibleExtent, mSize.width() );
     196                 :            : 
     197                 :          0 :   mMapToPixel.setParameters( mapUnitsPerPixel(),
     198                 :          0 :                              visibleExtent().center().x(),
     199                 :          0 :                              visibleExtent().center().y(),
     200                 :          0 :                              outputSize().width(),
     201                 :          0 :                              outputSize().height(),
     202                 :          0 :                              mRotation );
     203                 :            : 
     204                 :            : #if 1 // set visible extent taking rotation in consideration
     205                 :          0 :   if ( mRotation )
     206                 :            :   {
     207                 :          0 :     QgsPointXY p1 = mMapToPixel.toMapCoordinates( QPoint( 0, 0 ) );
     208                 :          0 :     QgsPointXY p2 = mMapToPixel.toMapCoordinates( QPoint( 0, myHeight ) );
     209                 :          0 :     QgsPointXY p3 = mMapToPixel.toMapCoordinates( QPoint( myWidth, 0 ) );
     210                 :          0 :     QgsPointXY p4 = mMapToPixel.toMapCoordinates( QPoint( myWidth, myHeight ) );
     211                 :          0 :     dxmin = std::min( p1.x(), std::min( p2.x(), std::min( p3.x(), p4.x() ) ) );
     212                 :          0 :     dymin = std::min( p1.y(), std::min( p2.y(), std::min( p3.y(), p4.y() ) ) );
     213                 :          0 :     dxmax = std::max( p1.x(), std::max( p2.x(), std::max( p3.x(), p4.x() ) ) );
     214                 :          0 :     dymax = std::max( p1.y(), std::max( p2.y(), std::max( p3.y(), p4.y() ) ) );
     215                 :          0 :     mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
     216                 :          0 :   }
     217                 :            : #endif
     218                 :            : 
     219                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ), 5 );
     220                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mSize.width() ), qgsDoubleToString( mSize.height() ) ), 5 );
     221                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ), 5 );
     222                 :          0 :   QgsDebugMsgLevel( mExtent.toString(), 5 );
     223                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / myWidth ), qgsDoubleToString( mVisibleExtent.height() / myHeight ) ), 5 );
     224                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ), 5 );
     225                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ), 5 );
     226                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Rotation: %1 degrees" ).arg( mRotation ), 5 );
     227                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Extent: %1" ).arg( mExtent.asWktCoordinates() ), 5 );
     228                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Visible Extent: %1" ).arg( mVisibleExtent.asWktCoordinates() ), 5 );
     229                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Magnification factor: %1" ).arg( mMagnificationFactor ), 5 );
     230                 :            : 
     231                 :          0 :   mValid = true;
     232                 :          6 : }
     233                 :            : 
     234                 :            : 
     235                 :          0 : QSize QgsMapSettings::outputSize() const
     236                 :            : {
     237                 :          0 :   return mSize;
     238                 :            : }
     239                 :            : 
     240                 :          0 : void QgsMapSettings::setOutputSize( QSize size )
     241                 :            : {
     242                 :          0 :   mSize = size;
     243                 :            : 
     244                 :          0 :   updateDerived();
     245                 :          0 : }
     246                 :            : 
     247                 :          0 : float QgsMapSettings::devicePixelRatio() const
     248                 :            : {
     249                 :          0 :   return mDevicePixelRatio;
     250                 :            : }
     251                 :            : 
     252                 :          0 : void QgsMapSettings::setDevicePixelRatio( float dpr )
     253                 :            : {
     254                 :          0 :   mDevicePixelRatio = dpr;
     255                 :          0 :   updateDerived();
     256                 :          0 : }
     257                 :            : 
     258                 :          0 : QSize QgsMapSettings::deviceOutputSize() const
     259                 :            : {
     260                 :          0 :   return outputSize() * mDevicePixelRatio;
     261                 :            : }
     262                 :            : 
     263                 :          0 : double QgsMapSettings::outputDpi() const
     264                 :            : {
     265                 :          0 :   return mDpi;
     266                 :            : }
     267                 :            : 
     268                 :          0 : void QgsMapSettings::setOutputDpi( double dpi )
     269                 :            : {
     270                 :          0 :   mDpi = dpi;
     271                 :            : 
     272                 :          0 :   updateDerived();
     273                 :          0 : }
     274                 :            : 
     275                 :            : 
     276                 :          0 : QStringList QgsMapSettings::layerIds() const
     277                 :            : {
     278                 :          0 :   return _qgis_listQPointerToIDs( mLayers );
     279                 :            : }
     280                 :            : 
     281                 :            : 
     282                 :          0 : QList<QgsMapLayer *> QgsMapSettings::layers() const
     283                 :            : {
     284                 :          0 :   return _qgis_listQPointerToRaw( mLayers );
     285                 :            : }
     286                 :            : 
     287                 :          0 : void QgsMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
     288                 :            : {
     289                 :            :   // filter list, removing null layers and non-spatial layers
     290                 :          0 :   auto filteredList = layers;
     291                 :          0 :   filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(),
     292                 :          0 :                                       []( QgsMapLayer * layer )
     293                 :            :   {
     294                 :          0 :     return !layer || !layer->isSpatial();
     295                 :          0 :   } ), filteredList.end() );
     296                 :            : 
     297                 :          0 :   mLayers = _qgis_listRawToQPointer( filteredList );
     298                 :          0 : }
     299                 :            : 
     300                 :          0 : QMap<QString, QString> QgsMapSettings::layerStyleOverrides() const
     301                 :            : {
     302                 :          0 :   return mLayerStyleOverrides;
     303                 :            : }
     304                 :            : 
     305                 :          0 : void QgsMapSettings::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
     306                 :            : {
     307                 :          0 :   mLayerStyleOverrides = overrides;
     308                 :          0 : }
     309                 :            : 
     310                 :          0 : void QgsMapSettings::setDestinationCrs( const QgsCoordinateReferenceSystem &crs )
     311                 :            : {
     312                 :          0 :   mDestCRS = crs;
     313                 :          0 :   mScaleCalculator.setMapUnits( crs.mapUnits() );
     314                 :            :   // Since the map units have changed, force a recalculation of the scale.
     315                 :          0 :   updateDerived();
     316                 :          0 : }
     317                 :            : 
     318                 :          0 : QgsCoordinateReferenceSystem QgsMapSettings::destinationCrs() const
     319                 :            : {
     320                 :          0 :   return mDestCRS;
     321                 :            : }
     322                 :            : 
     323                 :          0 : bool QgsMapSettings::setEllipsoid( const QString &ellipsoid )
     324                 :            : {
     325                 :          0 :   QgsEllipsoidUtils::EllipsoidParameters params = QgsEllipsoidUtils::ellipsoidParameters( ellipsoid );
     326                 :          0 :   if ( !params.valid )
     327                 :            :   {
     328                 :          0 :     return false;
     329                 :            :   }
     330                 :            :   else
     331                 :            :   {
     332                 :          0 :     mEllipsoid = ellipsoid;
     333                 :          0 :     return true;
     334                 :            :   }
     335                 :          0 : }
     336                 :            : 
     337                 :          0 : void QgsMapSettings::setFlags( QgsMapSettings::Flags flags )
     338                 :            : {
     339                 :          0 :   mFlags = flags;
     340                 :          0 : }
     341                 :            : 
     342                 :          0 : void QgsMapSettings::setFlag( QgsMapSettings::Flag flag, bool on )
     343                 :            : {
     344                 :          0 :   if ( on )
     345                 :          0 :     mFlags |= flag;
     346                 :            :   else
     347                 :          0 :     mFlags &= ~flag;
     348                 :          0 : }
     349                 :            : 
     350                 :          0 : QgsMapSettings::Flags QgsMapSettings::flags() const
     351                 :            : {
     352                 :          0 :   return mFlags;
     353                 :            : }
     354                 :            : 
     355                 :          0 : bool QgsMapSettings::testFlag( QgsMapSettings::Flag flag ) const
     356                 :            : {
     357                 :          0 :   return mFlags.testFlag( flag );
     358                 :            : }
     359                 :            : 
     360                 :          0 : QgsUnitTypes::DistanceUnit QgsMapSettings::mapUnits() const
     361                 :            : {
     362                 :          0 :   return mScaleCalculator.mapUnits();
     363                 :            : }
     364                 :            : 
     365                 :            : 
     366                 :          0 : bool QgsMapSettings::hasValidSettings() const
     367                 :            : {
     368                 :          0 :   return mValid;
     369                 :            : }
     370                 :            : 
     371                 :          0 : QgsRectangle QgsMapSettings::visibleExtent() const
     372                 :            : {
     373                 :          0 :   return mVisibleExtent;
     374                 :            : }
     375                 :            : 
     376                 :          0 : QPolygonF QgsMapSettings::visiblePolygon() const
     377                 :            : {
     378                 :          0 :   QPolygonF poly;
     379                 :            : 
     380                 :          0 :   const QSize &sz = outputSize();
     381                 :          0 :   const QgsMapToPixel &m2p = mapToPixel();
     382                 :            : 
     383                 :          0 :   poly << m2p.toMapCoordinates( 0.0,                             0.0 ).toQPointF();
     384                 :          0 :   poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), 0.0 ).toQPointF();
     385                 :          0 :   poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), static_cast<double>( sz.height() ) ).toQPointF();
     386                 :          0 :   poly << m2p.toMapCoordinates( 0.0,                             static_cast<double>( sz.height() ) ).toQPointF();
     387                 :            : 
     388                 :          0 :   return poly;
     389                 :          0 : }
     390                 :            : 
     391                 :          0 : double QgsMapSettings::mapUnitsPerPixel() const
     392                 :            : {
     393                 :          0 :   return mMapUnitsPerPixel;
     394                 :            : }
     395                 :            : 
     396                 :          0 : double QgsMapSettings::scale() const
     397                 :            : {
     398                 :          0 :   return mScale;
     399                 :            : }
     400                 :            : 
     401                 :          0 : QgsCoordinateTransformContext QgsMapSettings::transformContext() const
     402                 :            : {
     403                 :            : #ifdef QGISDEBUG
     404                 :            :   if ( !mHasTransformContext )
     405                 :            :     QgsDebugMsgLevel( QStringLiteral( "No QgsCoordinateTransformContext context set for transform" ), 4 );
     406                 :            : #endif
     407                 :            : 
     408                 :          0 :   return mTransformContext;
     409                 :            : }
     410                 :            : 
     411                 :          0 : void QgsMapSettings::setTransformContext( const QgsCoordinateTransformContext &context )
     412                 :            : {
     413                 :          0 :   mTransformContext = context;
     414                 :            : #ifdef QGISDEBUG
     415                 :            :   mHasTransformContext = true;
     416                 :            : #endif
     417                 :          0 : }
     418                 :            : 
     419                 :          0 : QgsCoordinateTransform QgsMapSettings::layerTransform( const QgsMapLayer *layer ) const
     420                 :            : {
     421                 :          0 :   if ( !layer )
     422                 :          0 :     return QgsCoordinateTransform();
     423                 :            : 
     424                 :          0 :   return QgsCoordinateTransform( layer->crs(), mDestCRS, mTransformContext );
     425                 :          0 : }
     426                 :            : 
     427                 :          0 : double QgsMapSettings::layerToMapUnits( const QgsMapLayer *layer, const QgsRectangle &referenceExtent ) const
     428                 :            : {
     429                 :          0 :   return layerTransform( layer ).scaleFactor( referenceExtent );
     430                 :          0 : }
     431                 :            : 
     432                 :            : 
     433                 :          0 : QgsRectangle QgsMapSettings::layerExtentToOutputExtent( const QgsMapLayer *layer, QgsRectangle extent ) const
     434                 :            : {
     435                 :            :   try
     436                 :            :   {
     437                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     438                 :          0 :     if ( ct.isValid() )
     439                 :            :     {
     440                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
     441                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
     442                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "extent %1" ).arg( extent.toString() ), 3 );
     443                 :          0 :       ct.setBallparkTransformsAreAppropriate( true );
     444                 :          0 :       extent = ct.transformBoundingBox( extent );
     445                 :          0 :     }
     446                 :          0 :   }
     447                 :            :   catch ( QgsCsException &cse )
     448                 :            :   {
     449                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     450                 :          0 :   }
     451                 :            : 
     452                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "proj extent = %1 " ).arg( extent.toString() ), 3 );
     453                 :            : 
     454                 :          0 :   return extent;
     455                 :          0 : }
     456                 :            : 
     457                 :            : 
     458                 :          0 : QgsRectangle QgsMapSettings::outputExtentToLayerExtent( const QgsMapLayer *layer, QgsRectangle extent ) const
     459                 :            : {
     460                 :            :   try
     461                 :            :   {
     462                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     463                 :          0 :     ct.setBallparkTransformsAreAppropriate( true );
     464                 :          0 :     if ( ct.isValid() )
     465                 :            :     {
     466                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
     467                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
     468                 :          0 :       QgsDebugMsgLevel( QStringLiteral( "extent = %1" ).arg( extent.toString() ), 3 );
     469                 :          0 :       extent = ct.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
     470                 :          0 :     }
     471                 :          0 :   }
     472                 :            :   catch ( QgsCsException &cse )
     473                 :            :   {
     474                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     475                 :          0 :   }
     476                 :            : 
     477                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "proj extent =  %1" ).arg( extent.toString() ), 3 );
     478                 :            : 
     479                 :          0 :   return extent;
     480                 :          0 : }
     481                 :            : 
     482                 :            : 
     483                 :          0 : QgsPointXY QgsMapSettings::layerToMapCoordinates( const QgsMapLayer *layer, QgsPointXY point ) const
     484                 :            : {
     485                 :            :   try
     486                 :            :   {
     487                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     488                 :          0 :     if ( ct.isValid() )
     489                 :          0 :       point = ct.transform( point, QgsCoordinateTransform::ForwardTransform );
     490                 :          0 :   }
     491                 :            :   catch ( QgsCsException &cse )
     492                 :            :   {
     493                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     494                 :          0 :   }
     495                 :            : 
     496                 :          0 :   return point;
     497                 :          0 : }
     498                 :            : 
     499                 :          0 : QgsPoint QgsMapSettings::layerToMapCoordinates( const QgsMapLayer *layer, const QgsPoint &point ) const
     500                 :            : {
     501                 :          0 :   double x = point.x();
     502                 :          0 :   double y = point.y();
     503                 :          0 :   double z = point.z();
     504                 :            : 
     505                 :            :   try
     506                 :            :   {
     507                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     508                 :          0 :     if ( ct.isValid() )
     509                 :          0 :       ct.transformInPlace( x, y, z, QgsCoordinateTransform::ForwardTransform );
     510                 :          0 :   }
     511                 :            :   catch ( QgsCsException &cse )
     512                 :            :   {
     513                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     514                 :          0 :   }
     515                 :            : 
     516                 :          0 :   return QgsPoint( x, y, z );
     517                 :          0 : }
     518                 :            : 
     519                 :            : 
     520                 :          0 : QgsRectangle QgsMapSettings::layerToMapCoordinates( const QgsMapLayer *layer, QgsRectangle rect ) const
     521                 :            : {
     522                 :            :   try
     523                 :            :   {
     524                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     525                 :          0 :     if ( ct.isValid() )
     526                 :          0 :       rect = ct.transform( rect, QgsCoordinateTransform::ForwardTransform );
     527                 :          0 :   }
     528                 :            :   catch ( QgsCsException &cse )
     529                 :            :   {
     530                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     531                 :          0 :   }
     532                 :            : 
     533                 :          0 :   return rect;
     534                 :          0 : }
     535                 :            : 
     536                 :            : 
     537                 :          0 : QgsPointXY QgsMapSettings::mapToLayerCoordinates( const QgsMapLayer *layer, QgsPointXY point ) const
     538                 :            : {
     539                 :            :   try
     540                 :            :   {
     541                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     542                 :          0 :     if ( ct.isValid() )
     543                 :          0 :       point = ct.transform( point, QgsCoordinateTransform::ReverseTransform );
     544                 :          0 :   }
     545                 :            :   catch ( QgsCsException &cse )
     546                 :            :   {
     547                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     548                 :          0 :   }
     549                 :            : 
     550                 :          0 :   return point;
     551                 :          0 : }
     552                 :            : 
     553                 :          0 : QgsPoint QgsMapSettings::mapToLayerCoordinates( const QgsMapLayer *layer, const QgsPoint &point ) const
     554                 :            : {
     555                 :          0 :   double x = point.x();
     556                 :          0 :   double y = point.y();
     557                 :          0 :   double z = point.z();
     558                 :            : 
     559                 :            :   try
     560                 :            :   {
     561                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     562                 :          0 :     if ( ct.isValid() )
     563                 :          0 :       ct.transformInPlace( x, y, z, QgsCoordinateTransform::ReverseTransform );
     564                 :          0 :   }
     565                 :            :   catch ( QgsCsException &cse )
     566                 :            :   {
     567                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     568                 :          0 :   }
     569                 :            : 
     570                 :          0 :   return QgsPoint( x, y, z );
     571                 :          0 : }
     572                 :            : 
     573                 :            : 
     574                 :          0 : QgsRectangle QgsMapSettings::mapToLayerCoordinates( const QgsMapLayer *layer, QgsRectangle rect ) const
     575                 :            : {
     576                 :            :   try
     577                 :            :   {
     578                 :          0 :     QgsCoordinateTransform ct = layerTransform( layer );
     579                 :          0 :     if ( ct.isValid() )
     580                 :          0 :       rect = ct.transform( rect, QgsCoordinateTransform::ReverseTransform );
     581                 :          0 :   }
     582                 :            :   catch ( QgsCsException &cse )
     583                 :            :   {
     584                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
     585                 :          0 :   }
     586                 :            : 
     587                 :          0 :   return rect;
     588                 :          0 : }
     589                 :            : 
     590                 :            : 
     591                 :            : 
     592                 :          0 : QgsRectangle QgsMapSettings::fullExtent() const
     593                 :            : {
     594                 :            :   // reset the map canvas extent since the extent may now be smaller
     595                 :            :   // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
     596                 :          0 :   QgsRectangle fullExtent;
     597                 :          0 :   fullExtent.setMinimal();
     598                 :            : 
     599                 :            :   // iterate through the map layers and test each layers extent
     600                 :            :   // against the current min and max values
     601                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( mLayers.count() ), 5 );
     602                 :          0 :   const auto constMLayers = mLayers;
     603                 :          0 :   for ( const QgsWeakMapLayerPointer &layerPtr : constMLayers )
     604                 :            :   {
     605                 :          0 :     if ( QgsMapLayer *lyr = layerPtr.data() )
     606                 :            :     {
     607                 :          0 :       QgsDebugMsgLevel( "Updating extent using " + lyr->name(), 5 );
     608                 :          0 :       QgsDebugMsgLevel( "Input extent: " + lyr->extent().toString(), 5 );
     609                 :            : 
     610                 :          0 :       if ( lyr->extent().isNull() )
     611                 :          0 :         continue;
     612                 :            : 
     613                 :            :       // Layer extents are stored in the coordinate system (CS) of the
     614                 :            :       // layer. The extent must be projected to the canvas CS
     615                 :          0 :       QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() );
     616                 :            : 
     617                 :          0 :       QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
     618                 :          0 :       fullExtent.combineExtentWith( extent );
     619                 :          0 :     }
     620                 :            :   }
     621                 :            : 
     622                 :          0 :   if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
     623                 :            :   {
     624                 :            :     // If all of the features are at the one point, buffer the
     625                 :            :     // rectangle a bit. If they are all at zero, do something a bit
     626                 :            :     // more crude.
     627                 :            : 
     628                 :          0 :     if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
     629                 :          0 :          fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
     630                 :            :     {
     631                 :          0 :       fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
     632                 :          0 :     }
     633                 :            :     else
     634                 :            :     {
     635                 :          0 :       const double padFactor = 1e-8;
     636                 :          0 :       double widthPad = fullExtent.xMinimum() * padFactor;
     637                 :          0 :       double heightPad = fullExtent.yMinimum() * padFactor;
     638                 :          0 :       double xmin = fullExtent.xMinimum() - widthPad;
     639                 :          0 :       double xmax = fullExtent.xMaximum() + widthPad;
     640                 :          0 :       double ymin = fullExtent.yMinimum() - heightPad;
     641                 :          0 :       double ymax = fullExtent.yMaximum() + heightPad;
     642                 :          0 :       fullExtent.set( xmin, ymin, xmax, ymax );
     643                 :            :     }
     644                 :          0 :   }
     645                 :            : 
     646                 :          0 :   QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
     647                 :            :   return fullExtent;
     648                 :          0 : }
     649                 :            : 
     650                 :            : 
     651                 :          0 : void QgsMapSettings::readXml( QDomNode &node )
     652                 :            : {
     653                 :            :   // set destination CRS
     654                 :          0 :   QgsCoordinateReferenceSystem srs;
     655                 :          0 :   QDomNode srsNode = node.namedItem( QStringLiteral( "destinationsrs" ) );
     656                 :          0 :   if ( !srsNode.isNull() )
     657                 :            :   {
     658                 :          0 :     srs.readXml( srsNode );
     659                 :          0 :   }
     660                 :          0 :   setDestinationCrs( srs );
     661                 :            : 
     662                 :            :   // set extent
     663                 :          0 :   QDomNode extentNode = node.namedItem( QStringLiteral( "extent" ) );
     664                 :          0 :   QgsRectangle aoi = QgsXmlUtils::readRectangle( extentNode.toElement() );
     665                 :          0 :   setExtent( aoi );
     666                 :            : 
     667                 :            :   // set rotation
     668                 :          0 :   QDomNode rotationNode = node.namedItem( QStringLiteral( "rotation" ) );
     669                 :          0 :   QString rotationVal = rotationNode.toElement().text();
     670                 :          0 :   if ( ! rotationVal.isEmpty() )
     671                 :            :   {
     672                 :          0 :     double rot = rotationVal.toDouble();
     673                 :          0 :     setRotation( rot );
     674                 :          0 :   }
     675                 :            : 
     676                 :            :   //render map tile
     677                 :          0 :   QDomElement renderMapTileElem = node.firstChildElement( QStringLiteral( "rendermaptile" ) );
     678                 :          0 :   if ( !renderMapTileElem.isNull() )
     679                 :            :   {
     680                 :          0 :     setFlag( QgsMapSettings::RenderMapTile, renderMapTileElem.text() == QLatin1String( "1" ) );
     681                 :          0 :   }
     682                 :          0 : }
     683                 :            : 
     684                 :            : 
     685                 :            : 
     686                 :          0 : void QgsMapSettings::writeXml( QDomNode &node, QDomDocument &doc )
     687                 :            : {
     688                 :            :   // units
     689                 :          0 :   node.appendChild( QgsXmlUtils::writeMapUnits( mapUnits(), doc ) );
     690                 :            : 
     691                 :            :   // Write current view extents
     692                 :          0 :   node.appendChild( QgsXmlUtils::writeRectangle( extent(), doc ) );
     693                 :            : 
     694                 :            :   // Write current view rotation
     695                 :          0 :   QDomElement rotNode = doc.createElement( QStringLiteral( "rotation" ) );
     696                 :          0 :   rotNode.appendChild(
     697                 :          0 :     doc.createTextNode( qgsDoubleToString( rotation() ) )
     698                 :            :   );
     699                 :          0 :   node.appendChild( rotNode );
     700                 :            : 
     701                 :            :   // destination CRS
     702                 :          0 :   if ( mDestCRS.isValid() )
     703                 :            :   {
     704                 :          0 :     QDomElement srsNode = doc.createElement( QStringLiteral( "destinationsrs" ) );
     705                 :          0 :     node.appendChild( srsNode );
     706                 :          0 :     mDestCRS.writeXml( srsNode, doc );
     707                 :          0 :   }
     708                 :            : 
     709                 :            :   //render map tile
     710                 :          0 :   QDomElement renderMapTileElem = doc.createElement( QStringLiteral( "rendermaptile" ) );
     711                 :          0 :   QDomText renderMapTileText = doc.createTextNode( testFlag( QgsMapSettings::RenderMapTile ) ? "1" : "0" );
     712                 :          0 :   renderMapTileElem.appendChild( renderMapTileText );
     713                 :          0 :   node.appendChild( renderMapTileElem );
     714                 :          0 : }
     715                 :            : 
     716                 :          0 : QgsGeometry QgsMapSettings::labelBoundaryGeometry() const
     717                 :            : {
     718                 :          0 :   return mLabelBoundaryGeometry;
     719                 :            : }
     720                 :            : 
     721                 :          0 : void QgsMapSettings::setLabelBoundaryGeometry( const QgsGeometry &boundary )
     722                 :            : {
     723                 :          0 :   mLabelBoundaryGeometry = boundary;
     724                 :          0 : }
     725                 :            : 
     726                 :          0 : void QgsMapSettings::addClippingRegion( const QgsMapClippingRegion &region )
     727                 :            : {
     728                 :          0 :   mClippingRegions.append( region );
     729                 :          0 : }
     730                 :            : 
     731                 :          0 : void QgsMapSettings::setClippingRegions( const QList<QgsMapClippingRegion> &regions )
     732                 :            : {
     733                 :          0 :   mClippingRegions = regions;
     734                 :          0 : }
     735                 :            : 
     736                 :          0 : QList<QgsMapClippingRegion> QgsMapSettings::clippingRegions() const
     737                 :            : {
     738                 :          0 :   return mClippingRegions;
     739                 :            : }
     740                 :            : 
     741                 :          0 : void QgsMapSettings::addRenderedFeatureHandler( QgsRenderedFeatureHandlerInterface *handler )
     742                 :            : {
     743                 :          0 :   mRenderedFeatureHandlers.append( handler );
     744                 :          0 : }
     745                 :            : 
     746                 :          0 : QList<QgsRenderedFeatureHandlerInterface *> QgsMapSettings::renderedFeatureHandlers() const
     747                 :            : {
     748                 :          0 :   return mRenderedFeatureHandlers;
     749                 :            : }
     750                 :            : 
     751                 :          0 : QgsDoubleRange QgsMapSettings::zRange() const
     752                 :            : {
     753                 :          0 :   return mZRange;
     754                 :            : }
     755                 :            : 
     756                 :          0 : void QgsMapSettings::setZRange( const QgsDoubleRange &zRange )
     757                 :            : {
     758                 :          0 :   mZRange = zRange;
     759                 :          0 : }

Generated by: LCOV version 1.14