mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-17 00:04:02 -04:00
657 lines
19 KiB
C++
657 lines
19 KiB
C++
/***************************************************************************
|
|
qgsmapsettings.cpp
|
|
--------------------------------------
|
|
Date : December 2013
|
|
Copyright : (C) 2013 by Martin Dobias
|
|
Email : wonder dot sk at gmail dot com
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsmapsettings.h"
|
|
|
|
#include "qgsscalecalculator.h"
|
|
#include "qgsmaprendererjob.h"
|
|
#include "qgsmaptopixel.h"
|
|
#include "qgslogger.h"
|
|
|
|
#include "qgsmessagelog.h"
|
|
#include "qgsmaplayer.h"
|
|
#include "qgsmaplayerlistutils.h"
|
|
#include "qgsproject.h"
|
|
#include "qgsxmlutils.h"
|
|
#include "qgsexception.h"
|
|
#include "qgsgeometry.h"
|
|
|
|
Q_GUI_EXPORT extern int qt_defaultDpiX();
|
|
|
|
|
|
QgsMapSettings::QgsMapSettings()
|
|
: mDpi( qt_defaultDpiX() ) // DPI that will be used by default for QImage instances
|
|
, mSize( QSize( 0, 0 ) )
|
|
, mBackgroundColor( Qt::white )
|
|
, mSelectionColor( Qt::yellow )
|
|
, mFlags( Antialiasing | UseAdvancedEffects | DrawLabeling | DrawSelection )
|
|
, mSegmentationTolerance( M_PI_2 / 90 )
|
|
{
|
|
mScaleCalculator.setMapUnits( QgsUnitTypes::DistanceUnknownUnit );
|
|
|
|
updateDerived();
|
|
}
|
|
|
|
void QgsMapSettings::setMagnificationFactor( double factor )
|
|
{
|
|
double ratio = mMagnificationFactor / factor;
|
|
|
|
mMagnificationFactor = factor;
|
|
|
|
double rot = rotation();
|
|
setRotation( 0.0 );
|
|
|
|
QgsRectangle ext = visibleExtent();
|
|
ext.scale( ratio );
|
|
|
|
mRotation = rot;
|
|
mExtent = ext;
|
|
mDpi = mDpi / ratio;
|
|
|
|
QgsDebugMsg( QStringLiteral( "Magnification factor: %1 dpi: %2 ratio: %3" ).arg( factor ).arg( mDpi ).arg( ratio ) );
|
|
|
|
updateDerived();
|
|
}
|
|
|
|
double QgsMapSettings::magnificationFactor() const
|
|
{
|
|
return mMagnificationFactor;
|
|
}
|
|
|
|
QgsRectangle QgsMapSettings::extent() const
|
|
{
|
|
return mExtent;
|
|
}
|
|
|
|
void QgsMapSettings::setExtent( const QgsRectangle &extent, bool magnified )
|
|
{
|
|
QgsRectangle magnifiedExtent = extent;
|
|
|
|
if ( !magnified )
|
|
magnifiedExtent.scale( 1 / mMagnificationFactor );
|
|
|
|
mExtent = magnifiedExtent;
|
|
|
|
updateDerived();
|
|
}
|
|
|
|
double QgsMapSettings::rotation() const
|
|
{
|
|
return mRotation;
|
|
}
|
|
|
|
void QgsMapSettings::setRotation( double degrees )
|
|
{
|
|
if ( qgsDoubleNear( mRotation, degrees ) )
|
|
return;
|
|
|
|
mRotation = degrees;
|
|
|
|
// TODO: update extent while keeping scale ?
|
|
updateDerived();
|
|
}
|
|
|
|
|
|
void QgsMapSettings::updateDerived()
|
|
{
|
|
QgsRectangle extent = mExtent;
|
|
|
|
if ( extent.isEmpty() || !extent.isFinite() )
|
|
{
|
|
mValid = false;
|
|
return;
|
|
}
|
|
|
|
// Don't allow zooms where the current extent is so small that it
|
|
// can't be accurately represented using a double (which is what
|
|
// currentExtent uses). Excluding 0 avoids a divide by zero and an
|
|
// infinite loop when rendering to a new canvas. Excluding extents
|
|
// greater than 1 avoids doing unnecessary calculations.
|
|
|
|
// The scheme is to compare the width against the mean x coordinate
|
|
// (and height against mean y coordinate) and only allow zooms where
|
|
// the ratio indicates that there is more than about 12 significant
|
|
// figures (there are about 16 significant figures in a double).
|
|
|
|
if ( extent.width() > 0 &&
|
|
extent.height() > 0 &&
|
|
extent.width() < 1 &&
|
|
extent.height() < 1 )
|
|
{
|
|
// Use abs() on the extent to avoid the case where the extent is
|
|
// symmetrical about 0.
|
|
double xMean = ( std::fabs( extent.xMinimum() ) + std::fabs( extent.xMaximum() ) ) * 0.5;
|
|
double yMean = ( std::fabs( extent.yMinimum() ) + std::fabs( extent.yMaximum() ) ) * 0.5;
|
|
|
|
double xRange = extent.width() / xMean;
|
|
double yRange = extent.height() / yMean;
|
|
|
|
static const double MIN_PROPORTION = 1e-12;
|
|
if ( xRange < MIN_PROPORTION || yRange < MIN_PROPORTION )
|
|
{
|
|
mValid = false;
|
|
return;
|
|
}
|
|
}
|
|
|
|
double myHeight = mSize.height() * mDevicePixelRatio;
|
|
double myWidth = mSize.width() * mDevicePixelRatio;
|
|
|
|
if ( !myWidth || !myHeight )
|
|
{
|
|
mValid = false;
|
|
return;
|
|
}
|
|
|
|
// calculate the translation and scaling parameters
|
|
double mapUnitsPerPixelY = mExtent.height() / myHeight;
|
|
double mapUnitsPerPixelX = mExtent.width() / myWidth;
|
|
mMapUnitsPerPixel = mapUnitsPerPixelY > mapUnitsPerPixelX ? mapUnitsPerPixelY : mapUnitsPerPixelX;
|
|
|
|
// calculate the actual extent of the mapCanvas
|
|
double dxmin = mExtent.xMinimum(), dxmax = mExtent.xMaximum(),
|
|
dymin = mExtent.yMinimum(), dymax = mExtent.yMaximum(), whitespace;
|
|
|
|
if ( mapUnitsPerPixelY > mapUnitsPerPixelX )
|
|
{
|
|
whitespace = ( ( myWidth * mMapUnitsPerPixel ) - mExtent.width() ) * 0.5;
|
|
dxmin -= whitespace;
|
|
dxmax += whitespace;
|
|
}
|
|
else
|
|
{
|
|
whitespace = ( ( myHeight * mMapUnitsPerPixel ) - mExtent.height() ) * 0.5;
|
|
dymin -= whitespace;
|
|
dymax += whitespace;
|
|
}
|
|
|
|
mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
|
|
|
|
// update the scale
|
|
mScaleCalculator.setDpi( mDpi );
|
|
mScale = mScaleCalculator.calculate( mVisibleExtent, mSize.width() );
|
|
|
|
mMapToPixel.setParameters( mapUnitsPerPixel(),
|
|
visibleExtent().center().x(),
|
|
visibleExtent().center().y(),
|
|
outputSize().width(),
|
|
outputSize().height(),
|
|
mRotation );
|
|
|
|
#if 1 // set visible extent taking rotation in consideration
|
|
if ( mRotation )
|
|
{
|
|
QgsPointXY p1 = mMapToPixel.toMapCoordinates( QPoint( 0, 0 ) );
|
|
QgsPointXY p2 = mMapToPixel.toMapCoordinates( QPoint( 0, myHeight ) );
|
|
QgsPointXY p3 = mMapToPixel.toMapCoordinates( QPoint( myWidth, 0 ) );
|
|
QgsPointXY p4 = mMapToPixel.toMapCoordinates( QPoint( myWidth, myHeight ) );
|
|
dxmin = std::min( p1.x(), std::min( p2.x(), std::min( p3.x(), p4.x() ) ) );
|
|
dymin = std::min( p1.y(), std::min( p2.y(), std::min( p3.y(), p4.y() ) ) );
|
|
dxmax = std::max( p1.x(), std::max( p2.x(), std::max( p3.x(), p4.x() ) ) );
|
|
dymax = std::max( p1.y(), std::max( p2.y(), std::max( p3.y(), p4.y() ) ) );
|
|
mVisibleExtent.set( dxmin, dymin, dxmax, dymax );
|
|
}
|
|
#endif
|
|
|
|
QgsDebugMsgLevel( QStringLiteral( "Map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mapUnitsPerPixelX ), qgsDoubleToString( mapUnitsPerPixelY ) ), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mSize.width() ), qgsDoubleToString( mSize.height() ) ), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Extent dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mExtent.width() ), qgsDoubleToString( mExtent.height() ) ), 5 );
|
|
QgsDebugMsgLevel( mExtent.toString(), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Adjusted map units per pixel (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / myWidth ), qgsDoubleToString( mVisibleExtent.height() / myHeight ) ), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Recalced pixmap dimensions (x,y) : %1, %2" ).arg( qgsDoubleToString( mVisibleExtent.width() / mMapUnitsPerPixel ), qgsDoubleToString( mVisibleExtent.height() / mMapUnitsPerPixel ) ), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Scale (assuming meters as map units) = 1:%1" ).arg( qgsDoubleToString( mScale ) ), 5 );
|
|
QgsDebugMsgLevel( QStringLiteral( "Rotation: %1 degrees" ).arg( mRotation ), 5 );
|
|
|
|
mValid = true;
|
|
}
|
|
|
|
|
|
QSize QgsMapSettings::outputSize() const
|
|
{
|
|
return mSize;
|
|
}
|
|
|
|
void QgsMapSettings::setOutputSize( QSize size )
|
|
{
|
|
mSize = size;
|
|
|
|
updateDerived();
|
|
}
|
|
|
|
float QgsMapSettings::devicePixelRatio() const
|
|
{
|
|
return mDevicePixelRatio;
|
|
}
|
|
|
|
void QgsMapSettings::setDevicePixelRatio( float dpr )
|
|
{
|
|
mDevicePixelRatio = dpr;
|
|
}
|
|
|
|
QSize QgsMapSettings::deviceOutputSize() const
|
|
{
|
|
return outputSize() * mDevicePixelRatio;
|
|
}
|
|
|
|
double QgsMapSettings::outputDpi() const
|
|
{
|
|
return mDpi;
|
|
}
|
|
|
|
void QgsMapSettings::setOutputDpi( double dpi )
|
|
{
|
|
mDpi = dpi;
|
|
|
|
updateDerived();
|
|
}
|
|
|
|
|
|
QStringList QgsMapSettings::layerIds() const
|
|
{
|
|
return _qgis_listQPointerToIDs( mLayers );
|
|
}
|
|
|
|
|
|
QList<QgsMapLayer *> QgsMapSettings::layers() const
|
|
{
|
|
return _qgis_listQPointerToRaw( mLayers );
|
|
}
|
|
|
|
void QgsMapSettings::setLayers( const QList<QgsMapLayer *> &layers )
|
|
{
|
|
// filter list, removing null layers and non-spatial layers
|
|
auto filteredList = layers;
|
|
filteredList.erase( std::remove_if( filteredList.begin(), filteredList.end(),
|
|
[]( QgsMapLayer * layer )
|
|
{
|
|
return !layer || !layer->isSpatial();
|
|
} ), filteredList.end() );
|
|
|
|
mLayers = _qgis_listRawToQPointer( filteredList );
|
|
}
|
|
|
|
QMap<QString, QString> QgsMapSettings::layerStyleOverrides() const
|
|
{
|
|
return mLayerStyleOverrides;
|
|
}
|
|
|
|
void QgsMapSettings::setLayerStyleOverrides( const QMap<QString, QString> &overrides )
|
|
{
|
|
mLayerStyleOverrides = overrides;
|
|
}
|
|
|
|
void QgsMapSettings::setDestinationCrs( const QgsCoordinateReferenceSystem &crs )
|
|
{
|
|
mDestCRS = crs;
|
|
mScaleCalculator.setMapUnits( crs.mapUnits() );
|
|
// Since the map units have changed, force a recalculation of the scale.
|
|
updateDerived();
|
|
}
|
|
|
|
QgsCoordinateReferenceSystem QgsMapSettings::destinationCrs() const
|
|
{
|
|
return mDestCRS;
|
|
}
|
|
|
|
bool QgsMapSettings::setEllipsoid( const QString &ellipsoid )
|
|
{
|
|
QgsEllipsoidUtils::EllipsoidParameters params = QgsEllipsoidUtils::ellipsoidParameters( ellipsoid );
|
|
if ( !params.valid )
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
mEllipsoid = ellipsoid;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void QgsMapSettings::setFlags( QgsMapSettings::Flags flags )
|
|
{
|
|
mFlags = flags;
|
|
}
|
|
|
|
void QgsMapSettings::setFlag( QgsMapSettings::Flag flag, bool on )
|
|
{
|
|
if ( on )
|
|
mFlags |= flag;
|
|
else
|
|
mFlags &= ~flag;
|
|
}
|
|
|
|
QgsMapSettings::Flags QgsMapSettings::flags() const
|
|
{
|
|
return mFlags;
|
|
}
|
|
|
|
bool QgsMapSettings::testFlag( QgsMapSettings::Flag flag ) const
|
|
{
|
|
return mFlags.testFlag( flag );
|
|
}
|
|
|
|
QgsUnitTypes::DistanceUnit QgsMapSettings::mapUnits() const
|
|
{
|
|
return mScaleCalculator.mapUnits();
|
|
}
|
|
|
|
|
|
bool QgsMapSettings::hasValidSettings() const
|
|
{
|
|
return mValid;
|
|
}
|
|
|
|
QgsRectangle QgsMapSettings::visibleExtent() const
|
|
{
|
|
return mVisibleExtent;
|
|
}
|
|
|
|
QPolygonF QgsMapSettings::visiblePolygon() const
|
|
{
|
|
QPolygonF poly;
|
|
|
|
const QSize &sz = outputSize();
|
|
const QgsMapToPixel &m2p = mapToPixel();
|
|
|
|
poly << m2p.toMapCoordinates( 0.0, 0.0 ).toQPointF();
|
|
poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), 0.0 ).toQPointF();
|
|
poly << m2p.toMapCoordinates( static_cast<double>( sz.width() ), static_cast<double>( sz.height() ) ).toQPointF();
|
|
poly << m2p.toMapCoordinates( 0.0, static_cast<double>( sz.height() ) ).toQPointF();
|
|
|
|
return poly;
|
|
}
|
|
|
|
double QgsMapSettings::mapUnitsPerPixel() const
|
|
{
|
|
return mMapUnitsPerPixel;
|
|
}
|
|
|
|
double QgsMapSettings::scale() const
|
|
{
|
|
return mScale;
|
|
}
|
|
|
|
QgsCoordinateTransformContext QgsMapSettings::transformContext() const
|
|
{
|
|
#ifdef QGISDEBUG
|
|
if ( !mHasTransformContext )
|
|
QgsDebugMsgLevel( QStringLiteral( "No QgsCoordinateTransformContext context set for transform" ), 4 );
|
|
#endif
|
|
|
|
return mTransformContext;
|
|
}
|
|
|
|
void QgsMapSettings::setTransformContext( const QgsCoordinateTransformContext &context )
|
|
{
|
|
mTransformContext = context;
|
|
#ifdef QGISDEBUG
|
|
mHasTransformContext = true;
|
|
#endif
|
|
}
|
|
|
|
QgsCoordinateTransform QgsMapSettings::layerTransform( const QgsMapLayer *layer ) const
|
|
{
|
|
if ( !layer )
|
|
return QgsCoordinateTransform();
|
|
|
|
return QgsCoordinateTransform( layer->crs(), mDestCRS, mTransformContext );
|
|
}
|
|
|
|
double QgsMapSettings::layerToMapUnits( const QgsMapLayer *layer, const QgsRectangle &referenceExtent ) const
|
|
{
|
|
return layerTransform( layer ).scaleFactor( referenceExtent );
|
|
}
|
|
|
|
|
|
QgsRectangle QgsMapSettings::layerExtentToOutputExtent( const QgsMapLayer *layer, QgsRectangle extent ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
{
|
|
QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
|
|
QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
|
|
QgsDebugMsgLevel( QStringLiteral( "extent %1" ).arg( extent.toString() ), 3 );
|
|
extent = ct.transformBoundingBox( extent );
|
|
}
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
QgsDebugMsgLevel( QStringLiteral( "proj extent = %1 " ).arg( extent.toString() ), 3 );
|
|
|
|
return extent;
|
|
}
|
|
|
|
|
|
QgsRectangle QgsMapSettings::outputExtentToLayerExtent( const QgsMapLayer *layer, QgsRectangle extent ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
{
|
|
QgsDebugMsgLevel( QStringLiteral( "sourceCrs = %1" ).arg( ct.sourceCrs().authid() ), 3 );
|
|
QgsDebugMsgLevel( QStringLiteral( "destCRS = %1" ).arg( ct.destinationCrs().authid() ), 3 );
|
|
QgsDebugMsgLevel( QStringLiteral( "extent = %1" ).arg( extent.toString() ), 3 );
|
|
extent = ct.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
|
|
}
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
QgsDebugMsgLevel( QStringLiteral( "proj extent = %1" ).arg( extent.toString() ), 3 );
|
|
|
|
return extent;
|
|
}
|
|
|
|
|
|
QgsPointXY QgsMapSettings::layerToMapCoordinates( const QgsMapLayer *layer, QgsPointXY point ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
point = ct.transform( point, QgsCoordinateTransform::ForwardTransform );
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
return point;
|
|
}
|
|
|
|
|
|
QgsRectangle QgsMapSettings::layerToMapCoordinates( const QgsMapLayer *layer, QgsRectangle rect ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
rect = ct.transform( rect, QgsCoordinateTransform::ForwardTransform );
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
return rect;
|
|
}
|
|
|
|
|
|
QgsPointXY QgsMapSettings::mapToLayerCoordinates( const QgsMapLayer *layer, QgsPointXY point ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
point = ct.transform( point, QgsCoordinateTransform::ReverseTransform );
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
return point;
|
|
}
|
|
|
|
|
|
QgsRectangle QgsMapSettings::mapToLayerCoordinates( const QgsMapLayer *layer, QgsRectangle rect ) const
|
|
{
|
|
try
|
|
{
|
|
QgsCoordinateTransform ct = layerTransform( layer );
|
|
if ( ct.isValid() )
|
|
rect = ct.transform( rect, QgsCoordinateTransform::ReverseTransform );
|
|
}
|
|
catch ( QgsCsException &cse )
|
|
{
|
|
QgsMessageLog::logMessage( QObject::tr( "Transform error caught: %1" ).arg( cse.what() ), QObject::tr( "CRS" ) );
|
|
}
|
|
|
|
return rect;
|
|
}
|
|
|
|
|
|
|
|
QgsRectangle QgsMapSettings::fullExtent() const
|
|
{
|
|
// reset the map canvas extent since the extent may now be smaller
|
|
// We can't use a constructor since QgsRectangle normalizes the rectangle upon construction
|
|
QgsRectangle fullExtent;
|
|
fullExtent.setMinimal();
|
|
|
|
// iterate through the map layers and test each layers extent
|
|
// against the current min and max values
|
|
QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( mLayers.count() ), 5 );
|
|
Q_FOREACH ( const QgsWeakMapLayerPointer &layerPtr, mLayers )
|
|
{
|
|
if ( QgsMapLayer *lyr = layerPtr.data() )
|
|
{
|
|
QgsDebugMsgLevel( "Updating extent using " + lyr->name(), 5 );
|
|
QgsDebugMsgLevel( "Input extent: " + lyr->extent().toString(), 5 );
|
|
|
|
if ( lyr->extent().isNull() )
|
|
continue;
|
|
|
|
// Layer extents are stored in the coordinate system (CS) of the
|
|
// layer. The extent must be projected to the canvas CS
|
|
QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() );
|
|
|
|
QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 );
|
|
fullExtent.combineExtentWith( extent );
|
|
}
|
|
}
|
|
|
|
if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 )
|
|
{
|
|
// If all of the features are at the one point, buffer the
|
|
// rectangle a bit. If they are all at zero, do something a bit
|
|
// more crude.
|
|
|
|
if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 &&
|
|
fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 )
|
|
{
|
|
fullExtent.set( -1.0, -1.0, 1.0, 1.0 );
|
|
}
|
|
else
|
|
{
|
|
const double padFactor = 1e-8;
|
|
double widthPad = fullExtent.xMinimum() * padFactor;
|
|
double heightPad = fullExtent.yMinimum() * padFactor;
|
|
double xmin = fullExtent.xMinimum() - widthPad;
|
|
double xmax = fullExtent.xMaximum() + widthPad;
|
|
double ymin = fullExtent.yMinimum() - heightPad;
|
|
double ymax = fullExtent.yMaximum() + heightPad;
|
|
fullExtent.set( xmin, ymin, xmax, ymax );
|
|
}
|
|
}
|
|
|
|
QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 );
|
|
return fullExtent;
|
|
}
|
|
|
|
|
|
void QgsMapSettings::readXml( QDomNode &node )
|
|
{
|
|
// set destination CRS
|
|
QgsCoordinateReferenceSystem srs;
|
|
QDomNode srsNode = node.namedItem( QStringLiteral( "destinationsrs" ) );
|
|
if ( !srsNode.isNull() )
|
|
{
|
|
srs.readXml( srsNode );
|
|
}
|
|
setDestinationCrs( srs );
|
|
|
|
// set extent
|
|
QDomNode extentNode = node.namedItem( QStringLiteral( "extent" ) );
|
|
QgsRectangle aoi = QgsXmlUtils::readRectangle( extentNode.toElement() );
|
|
setExtent( aoi );
|
|
|
|
// set rotation
|
|
QDomNode rotationNode = node.namedItem( QStringLiteral( "rotation" ) );
|
|
QString rotationVal = rotationNode.toElement().text();
|
|
if ( ! rotationVal.isEmpty() )
|
|
{
|
|
double rot = rotationVal.toDouble();
|
|
setRotation( rot );
|
|
}
|
|
|
|
//render map tile
|
|
QDomElement renderMapTileElem = node.firstChildElement( QStringLiteral( "rendermaptile" ) );
|
|
if ( !renderMapTileElem.isNull() )
|
|
{
|
|
setFlag( QgsMapSettings::RenderMapTile, renderMapTileElem.text() == QLatin1String( "1" ) );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void QgsMapSettings::writeXml( QDomNode &node, QDomDocument &doc )
|
|
{
|
|
// units
|
|
node.appendChild( QgsXmlUtils::writeMapUnits( mapUnits(), doc ) );
|
|
|
|
// Write current view extents
|
|
node.appendChild( QgsXmlUtils::writeRectangle( extent(), doc ) );
|
|
|
|
// Write current view rotation
|
|
QDomElement rotNode = doc.createElement( QStringLiteral( "rotation" ) );
|
|
rotNode.appendChild(
|
|
doc.createTextNode( qgsDoubleToString( rotation() ) )
|
|
);
|
|
node.appendChild( rotNode );
|
|
|
|
// destination CRS
|
|
if ( mDestCRS.isValid() )
|
|
{
|
|
QDomElement srsNode = doc.createElement( QStringLiteral( "destinationsrs" ) );
|
|
node.appendChild( srsNode );
|
|
mDestCRS.writeXml( srsNode, doc );
|
|
}
|
|
|
|
//render map tile
|
|
QDomElement renderMapTileElem = doc.createElement( QStringLiteral( "rendermaptile" ) );
|
|
QDomText renderMapTileText = doc.createTextNode( testFlag( QgsMapSettings::RenderMapTile ) ? "1" : "0" );
|
|
renderMapTileElem.appendChild( renderMapTileText );
|
|
node.appendChild( renderMapTileElem );
|
|
}
|