QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsmaptopixel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmaptopixel.cpp - description
3 -------------------
4 begin : Sat Jun 22 2002
5 copyright : (C) 2002 by Gary E.Sherman
6 email : sherman at mrcc.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#include "qgsmaptopixel.h"
18#include "qgsunittypes.h"
19
20#include <QPoint>
21#include <QTextStream>
22#include <QVector>
23#include <QTransform>
24
25QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel,
26 double xc,
27 double yc,
28 int width,
29 int height,
30 double rotation )
31 : mValid( true )
32 , mMapUnitsPerPixel( mapUnitsPerPixel )
33 , mWidth( width )
34 , mHeight( height )
35 , mRotation( rotation )
36 , mXCenter( xc )
37 , mYCenter( yc )
38 , mXMin( xc - ( mWidth * mMapUnitsPerPixel / 2.0 ) )
39 , mYMin( yc - ( mHeight * mMapUnitsPerPixel / 2.0 ) )
40{
41 Q_ASSERT( mapUnitsPerPixel > 0 );
42 updateMatrix();
43}
44
45QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel )
46 : mValid( true )
47 , mMapUnitsPerPixel( mapUnitsPerPixel )
48 , mWidth( 0 )
49 , mHeight( 0 )
50 , mXCenter( 0 )
51 , mYCenter( 0 )
52{
53 updateMatrix();
54}
55
56QgsMapToPixel QgsMapToPixel::fromScale( double scale, Qgis::DistanceUnit mapUnits, double dpi )
57{
58 const double metersPerPixel = 25.4 / dpi / 1000.0;
59 const double mapUnitsPerPixel = metersPerPixel * QgsUnitTypes::fromUnitToUnitFactor( Qgis::DistanceUnit::Meters, mapUnits );
60 return QgsMapToPixel( mapUnitsPerPixel * scale );
61}
62
64{
65 updateMatrix();
66}
67
68bool QgsMapToPixel::updateMatrix()
69{
70 const QTransform newMatrix = transform();
71
72 // https://github.com/qgis/QGIS/issues/20856
73 if ( !newMatrix.isInvertible() )
74 return false;
75
76 mMatrix = newMatrix;
77 return true;
78}
79
80void QgsMapToPixel::setMapUnitsPerPixel( double mapUnitsPerPixel )
81{
82 mValid = true;
83
84 const double oldUnits = mMapUnitsPerPixel;
85 mMapUnitsPerPixel = mapUnitsPerPixel;
86 if ( !updateMatrix() )
87 {
88 mMapUnitsPerPixel = oldUnits;
89 }
90}
91
92void QgsMapToPixel::setMapRotation( double degrees, double cx, double cy )
93{
94 mValid = true;
95
96 const double oldRotation = mRotation;
97 const double oldXCenter = mXCenter;
98 const double oldYCenter = mYCenter;
99 const double oldWidth = mWidth;
100
101 mRotation = degrees;
102 mXCenter = cx;
103 mYCenter = cy;
104 if ( mWidth < 0 )
105 {
106 // set width not that we can compute it
107 mWidth = ( ( mXCenter - mXMin ) * 2 ) / mMapUnitsPerPixel;
108 }
109
110 if ( !updateMatrix() )
111 {
112 mRotation = oldRotation;
113 mXCenter = oldXCenter;
114 mYCenter = oldYCenter;
115 mWidth = oldWidth;
116 }
117}
118
119void QgsMapToPixel::setParameters( double mapUnitsPerPixel,
120 double xc,
121 double yc,
122 int width,
123 int height,
124 double rotation,
125 bool *ok )
126{
127 mValid = true;
128
129 const double oldMUPP = mMapUnitsPerPixel;
130 const double oldXCenter = mXCenter;
131 const double oldYCenter = mYCenter;
132 const double oldWidth = mWidth;
133 const double oldHeight = mHeight;
134 const double oldRotation = mRotation;
135 const double oldXMin = mXMin;
136 const double oldYMin = mYMin;
137
138 mMapUnitsPerPixel = mapUnitsPerPixel;
139 mXCenter = xc;
140 mYCenter = yc;
141 mWidth = width;
142 mHeight = height;
143 mRotation = rotation;
144 mXMin = xc - ( mWidth * mMapUnitsPerPixel / 2.0 );
145 mYMin = yc - ( mHeight * mMapUnitsPerPixel / 2.0 );
146
147 if ( !updateMatrix() )
148 {
149 mMapUnitsPerPixel = oldMUPP;
150 mXCenter = oldXCenter;
151 mYCenter = oldYCenter;
152 mWidth = oldWidth;
153 mHeight = oldHeight;
154 mRotation = oldRotation;
155 mXMin = oldXMin;
156 mYMin = oldYMin;
157 *ok = false;
158 }
159 else
160 {
161 *ok = true;
162 }
163}
164
165void QgsMapToPixel::setParameters( double mapUnitsPerPixel,
166 double xc,
167 double yc,
168 int width,
169 int height,
170 double rotation )
171{
172 mValid = true;
173 bool ok;
174 setParameters( mapUnitsPerPixel, xc, yc, width, height, rotation, &ok );
175}
176
178{
179 QString rep;
180 QTextStream( &rep ) << "Map units/pixel: " << mMapUnitsPerPixel
181 << " center: " << mXCenter << ',' << mYCenter
182 << " rotation: " << mRotation
183 << " size: " << mWidth << 'x' << mHeight;
184 return rep;
185}
186
187QTransform QgsMapToPixel::transform() const
188{
189 // NOTE: operations are done in the reverse order in which
190 // they are configured, so translation to geographical
191 // center happens first, then scaling, then rotation
192 // and finally translation to output viewport center
193
194 const double rotation = mapRotation();
195 if ( qgsDoubleNear( rotation, 0.0 ) )
196 {
197 //no rotation, return a simplified matrix
198 return QTransform::fromScale( 1.0 / mMapUnitsPerPixel, -1.0 / mMapUnitsPerPixel )
199 .translate( -mXMin, - ( mYMin + mHeight * mMapUnitsPerPixel ) );
200 }
201 else
202 {
203 const double cy = mapHeight() / 2.0;
204 const double cx = mapWidth() / 2.0;
205 return QTransform::fromTranslate( cx, cy )
206 .rotate( rotation )
207 .scale( 1 / mMapUnitsPerPixel, -1 / mMapUnitsPerPixel )
208 .translate( -mXCenter, -mYCenter );
209 }
210}
211
DistanceUnit
Units of distance.
Definition: qgis.h:4124
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
int mapHeight() const
Returns current map height in pixels.
void setMapUnitsPerPixel(double mapUnitsPerPixel)
Sets the map units per pixel.
void setMapRotation(double degrees, double cx, double cy)
Sets map rotation in degrees (clockwise).
QgsMapToPixel()
Constructor for an invalid QgsMapToPixel.
double mapUnitsPerPixel() const
Returns the current map units per pixel.
static QgsMapToPixel fromScale(double scale, Qgis::DistanceUnit mapUnits, double dpi=96)
Returns a new QgsMapToPixel created using a specified scale and distance unit.
QTransform transform() const
Returns a QTransform encapsulating the map to pixel conversion.
int mapWidth() const
Returns the current map width in pixels.
double mapRotation() const
Returns the current map rotation in degrees (clockwise).
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Sets parameters for use in transforming coordinates.
QString showParameters() const
Returns a string representation of the parameters used in the transform.
static Q_INVOKABLE double fromUnitToUnitFactor(Qgis::DistanceUnit fromUnit, Qgis::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5207