QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 "qgsmapsettings.h"
19 #include "qgsmapsettingsutils.h"
20 #include "qgspallabeling.h"
21 #include "qgstextformat.h"
22 #include "qgsvectorlayer.h"
24 
25 #include <QString>
26 
27 QStringList QgsMapSettingsUtils::containsAdvancedEffects( const QgsMapSettings &mapSettings, EffectsCheckFlags flags )
28 {
29  QSet< QString > layers;
30 
31  QgsTextFormat layerFormat;
32  const auto constLayers = mapSettings.layers();
33  for ( QgsMapLayer *layer : constLayers )
34  {
35  if ( layer && layer->isInScaleRange( mapSettings.scale() ) )
36  {
37  bool layerHasAdvancedBlendMode = false;
38  if ( layer->blendMode() != QPainter::CompositionMode_SourceOver )
39  {
41  {
42  layerHasAdvancedBlendMode = !QgsAbstractGeoPdfExporter::compositionModeSupported( layer->blendMode() );
43  }
44  else
45  {
46  layerHasAdvancedBlendMode = true;
47  }
48  }
49 
50  if ( layerHasAdvancedBlendMode )
51  {
52  layers << layer->name();
53  }
54  // if vector layer, check labels and feature blend mode
55  if ( QgsVectorLayer *currentVectorLayer = qobject_cast<QgsVectorLayer *>( layer ) )
56  {
57 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
58  // Qt < 5.15 does not correctly support layer level opacity in PDF exports -- see https://github.com/qgis/QGIS/issues/42698
59  if ( !qgsDoubleNear( currentVectorLayer->opacity(), 1.0 ) && !( flags & EffectsCheckFlag::IgnoreGeoPdfSupportedEffects ) )
60  {
61  layers << layer->name();
62  }
63 #endif
64  if ( currentVectorLayer->featureBlendMode() != QPainter::CompositionMode_SourceOver )
65  {
66  layers << layer->name();
67  }
68  // check label blend modes
69  if ( QgsPalLabeling::staticWillUseLayer( currentVectorLayer ) )
70  {
71  // Check all label blending properties
72  layerFormat.readFromLayer( currentVectorLayer );
73  if ( layerFormat.containsAdvancedEffects() )
74  {
75  layers << layer->name();
76  }
77  }
78  }
79  }
80  }
81 
82  return qgis::setToList( layers );
83 }
84 
85 void QgsMapSettingsUtils::worldFileParameters( const QgsMapSettings &mapSettings, double &a, double &b, double &c, double &d, double &e, double &f )
86 {
87  QgsMapSettings ms = mapSettings;
88 
89  const double rotation = ms.rotation();
90  const double alpha = rotation / 180 * M_PI;
91 
92  // reset rotation to 0 to calculate world file parameters
93  ms.setRotation( 0 );
94 
95  const double xOrigin = ms.visibleExtent().xMinimum() + ( ms.mapUnitsPerPixel() / 2 );
96  const double yOrigin = ms.visibleExtent().yMaximum() - ( ms.mapUnitsPerPixel() / 2 );
97 
98  const double xCenter = ms.visibleExtent().center().x();
99  const double yCenter = ms.visibleExtent().center().y();
100 
101  // scaling matrix
102  double s[6];
103  s[0] = ms.mapUnitsPerPixel();
104  s[1] = 0;
105  s[2] = xOrigin;
106  s[3] = 0;
107  s[4] = -ms.mapUnitsPerPixel();
108  s[5] = yOrigin;
109 
110  // rotation matrix
111  double r[6];
112  r[0] = std::cos( alpha );
113  r[1] = -std::sin( alpha );
114  r[2] = xCenter * ( 1 - std::cos( alpha ) ) + yCenter * std::sin( alpha );
115  r[3] = std::sin( alpha );
116  r[4] = std::cos( alpha );
117  r[5] = - xCenter * std::sin( alpha ) + yCenter * ( 1 - std::cos( alpha ) );
118 
119  // result = rotation x scaling = rotation(scaling(X))
120  a = r[0] * s[0] + r[1] * s[3];
121  b = r[0] * s[1] + r[1] * s[4];
122  c = r[0] * s[2] + r[1] * s[5] + r[2];
123  d = r[3] * s[0] + r[4] * s[3];
124  // Pixel YDim - almost always negative
125  // See https://en.wikipedia.org/wiki/World_file#cite_ref-3, https://github.com/qgis/QGIS/issues/26379
126  e = r[3] * s[1] + r[4] * s[4];
127  f = r[3] * s[2] + r[4] * s[5] + r[5];
128 }
129 
131 {
132  double a, b, c, d, e, f;
133  worldFileParameters( mapSettings, a, b, c, d, e, f );
134 
135  QString content;
136  // Pixel XDim
137  content += qgsDoubleToString( a ) + "\r\n";
138  // Rotation on y axis
139  content += qgsDoubleToString( d ) + "\r\n";
140  // Rotation on x axis
141  content += qgsDoubleToString( b ) + "\r\n";
142  // Pixel YDim
143  content += qgsDoubleToString( e ) + "\r\n";
144  // Origin X (top left cell)
145  content += qgsDoubleToString( c ) + "\r\n";
146  // Origin Y (top left cell)
147  content += qgsDoubleToString( f ) + "\r\n";
148 
149  return content;
150 }
static bool compositionModeSupported(QPainter::CompositionMode mode)
Returns true if the specified composition mode is supported for layers during GeoPDF exports.
Base class for all map layer types.
Definition: qgsmaplayer.h:73
@ IgnoreGeoPdfSupportedEffects
Ignore advanced effects which are supported in GeoPDF exports.
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.
The QgsMapSettings class contains configuration for rendering of the map.
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.
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:63
Q_GADGET double x
Definition: qgspointxy.h:62
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
QgsPointXY center() const SIP_HOLDGIL
Returns the center point of the rectangle.
Definition: qgsrectangle.h:251
Container for all settings relating to text rendering.
Definition: qgstextformat.h:41
void readFromLayer(QgsVectorLayer *layer)
Reads settings from a layer's custom properties (for QGIS 2.x projects).
bool containsAdvancedEffects() const
Returns true if any component of the font format requires advanced effects such as blend modes,...
Represents a vector layer which manages a vector based data sets.
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:1530
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:1578