QGIS API Documentation 4.1.0-Master (60fea48833c)
Loading...
Searching...
No Matches
qgsmapsettingsutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmapsettingsutils.cpp
3 -------------------
4 begin : May 2017
5 copyright : (C) 2017 by Mathieu Pellerin
6 email : nirvn dot asia at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsmapsettingsutils.h"
19
21#include "qgsmapsettings.h"
22#include "qgspallabeling.h"
23#include "qgstextformat.h"
24#include "qgsvectorlayer.h"
26
27#include <QString>
28
30{
31 QSet< QString > layers;
32
33 QgsTextFormat layerFormat;
34 const auto constLayers = mapSettings.layers();
35 for ( QgsMapLayer *layer : constLayers )
36 {
37 if ( layer && layer->isInScaleRange( mapSettings.scale() ) )
38 {
39 bool layerHasAdvancedBlendMode = false;
40 if ( layer->blendMode() != QPainter::CompositionMode_SourceOver )
41 {
43 {
44 layerHasAdvancedBlendMode = !QgsAbstractGeospatialPdfExporter::compositionModeSupported( layer->blendMode() );
45 }
46 else
47 {
48 layerHasAdvancedBlendMode = true;
49 }
50 }
51
52 if ( layerHasAdvancedBlendMode )
53 {
54 layers << layer->name();
55 }
56 // if vector layer, check labels and feature blend mode
57 if ( QgsVectorLayer *currentVectorLayer = qobject_cast<QgsVectorLayer *>( layer ) )
58 {
59 if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
60 {
61 layers << layer->name();
62 }
63 // check label blend modes
64 if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
65 {
66 if ( currentVectorLayer->labeling() && currentVectorLayer->labeling()->requiresAdvancedEffects() )
67 {
68 layers << layer->name();
69 }
70 }
71 }
72 }
73 }
74
75 return QStringList( layers.constBegin(), layers.constEnd() );
76}
77
78void QgsMapSettingsUtils::worldFileParameters( const QgsMapSettings &mapSettings, double &a, double &b, double &c, double &d, double &e, double &f )
79{
80 QgsMapSettings ms = mapSettings;
81
82 const double rotation = ms.rotation();
83 const double alpha = rotation / 180 * M_PI;
84
85 // reset rotation to 0 to calculate world file parameters
86 ms.setRotation( 0 );
87
88 const double xOrigin = ms.visibleExtent().xMinimum() + ( ms.mapUnitsPerPixel() / 2 );
89 const double yOrigin = ms.visibleExtent().yMaximum() - ( ms.mapUnitsPerPixel() / 2 );
90
91 const double xCenter = ms.visibleExtent().center().x();
92 const double yCenter = ms.visibleExtent().center().y();
93
94 // scaling matrix
95 double s[6];
96 s[0] = ms.mapUnitsPerPixel() / ms.devicePixelRatio();
97 s[1] = 0;
98 s[2] = xOrigin;
99 s[3] = 0;
100 s[4] = -ms.mapUnitsPerPixel() / ms.devicePixelRatio();
101 s[5] = yOrigin;
102
103 // rotation matrix
104 double r[6];
105 r[0] = std::cos( alpha );
106 r[1] = -std::sin( alpha );
107 r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
108 r[3] = std::sin( alpha );
109 r[4] = std::cos( alpha );
110 r[5] = -xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
111
112 // result = rotation x scaling = rotation(scaling(X))
113 a = r[0] * s[0] + r[1] * s[3];
114 b = r[0] * s[1] + r[1] * s[4];
115 c = r[0] * s[2] + r[1] * s[5] + r[2];
116 d = r[3] * s[0] + r[4] * s[3];
117 // Pixel YDim - almost always negative
118 // See https://en.wikipedia.org/wiki/World_file#cite_ref-3, https://github.com/qgis/QGIS/issues/26379
119 e = r[3] * s[1] + r[4] * s[4];
120 f = r[3] * s[2] + r[4] * s[5] + r[5];
121}
122
124{
125 double a, b, c, d, e, f;
126 worldFileParameters( mapSettings, a, b, c, d, e, f );
127
128 QString content;
129 // Pixel XDim
130 content += qgsDoubleToString( a ) + "\r\n";
131 // Rotation on y axis
132 content += qgsDoubleToString( d ) + "\r\n";
133 // Rotation on x axis
134 content += qgsDoubleToString( b ) + "\r\n";
135 // Pixel YDim
136 content += qgsDoubleToString( e ) + "\r\n";
137 // Origin X (top left cell)
138 content += qgsDoubleToString( c ) + "\r\n";
139 // Origin Y (top left cell)
140 content += qgsDoubleToString( f ) + "\r\n";
141
142 return content;
143}
144
146{
147 if ( extent.isEmpty() || !extent.isFinite() )
148 {
149 return false;
150 }
151
152 // Don't allow extents that are so small that they
153 // can't be accurately represented using a double. Excluding 0 avoids
154 // a divide by zero and an infinite loop when rendering to a new canvas.
155 // Excluding extents greater than 1 avoids doing unnecessary calculations.
156
157 // The scheme is to compare the width against the mean x coordinate
158 // (and height against mean y coordinate) and only allow zooms where
159 // the ratio indicates that there is more than about 12 significant
160 // figures (there are about 16 significant figures in a double).
161
162 if ( extent.width() > 0 && extent.height() > 0 && extent.width() < 1 && extent.height() < 1 )
163 {
164 // Use abs() on the extent to avoid the case where the extent is
165 // symmetrical about 0.
166 const double xMean = ( std::fabs( extent.xMinimum() ) + std::fabs( extent.xMaximum() ) ) * 0.5;
167 const double yMean = ( std::fabs( extent.yMinimum() ) + std::fabs( extent.yMaximum() ) ) * 0.5;
168
169 const double xRange = extent.width() / xMean;
170 const double yRange = extent.height() / yMean;
171
172 static const double MIN_PROPORTION = 1e-12;
173 if ( xRange < MIN_PROPORTION || yRange < MIN_PROPORTION )
174 {
175 return false;
176 }
177 }
178 return true;
179}
static bool compositionModeSupported(QPainter::CompositionMode mode)
Returns true if the specified composition mode is supported for layers during Geospatial PDF exports.
Base class for all map layer types.
Definition qgsmaplayer.h:83
@ IgnoreGeoPdfSupportedEffects
Ignore advanced effects which are supported in geospatial PDF exports.
static bool isValidExtent(const QgsRectangle &extent)
Returns true if an extent is a valid extent which can be used by QgsMapSettings.
QFlags< EffectsCheckFlag > EffectsCheckFlags
static void worldFileParameters(const QgsMapSettings &mapSettings, double &a, double &b, double &c, double &d, double &e, double &f)
Computes the six parameters of a world file.
static QStringList containsAdvancedEffects(const QgsMapSettings &mapSettings, EffectsCheckFlags flags=QgsMapSettingsUtils::EffectsCheckFlags())
Checks whether any of the layers attached to a map settings object contain advanced effects.
static QString worldFileContent(const QgsMapSettings &mapSettings)
Creates the content of a world file.
Contains configuration for rendering maps.
QList< QgsMapLayer * > layers(bool expandGroupLayers=false) const
Returns the list of layers which will be rendered in the map.
double scale() const
Returns the calculated map scale.
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 visibleExtent() const
Returns the actual extent derived from requested extent that takes output image size into account.
void setRotation(double rotation)
Sets the rotation of the resulting map image, in degrees clockwise.
double rotation() const
Returns the rotation of the resulting map image, in degrees clockwise.
static bool staticWillUseLayer(const QgsMapLayer *layer)
Called to find out whether a specified layer is used for labeling.
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
A rectangle specified with double values.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
QgsPointXY center
bool isFinite() const
Returns true if the rectangle has finite boundaries.
Container for all settings relating to text rendering.
Represents a vector layer which manages a vector based dataset.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6893