QGIS API Documentation  3.18.1-Zürich (202f1bf7e5)
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 
19 #include <QPoint>
20 #include <QTextStream>
21 #include <QVector>
22 #include <QTransform>
23 
24 #include "qgslogger.h"
25 #include "qgspointxy.h"
26 
27 
28 QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel,
29  double xc,
30  double yc,
31  int width,
32  int height,
33  double rotation )
34  : mMapUnitsPerPixel( mapUnitsPerPixel )
35  , mWidth( width )
36  , mHeight( height )
37  , mRotation( rotation )
38  , mXCenter( xc )
39  , mYCenter( yc )
40  , mXMin( xc - ( mWidth * mMapUnitsPerPixel / 2.0 ) )
41  , mYMin( yc - ( mHeight * mMapUnitsPerPixel / 2.0 ) )
42 {
43  Q_ASSERT( mapUnitsPerPixel > 0 );
44  updateMatrix();
45 }
46 
47 QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel )
48  : mMapUnitsPerPixel( mapUnitsPerPixel )
49  , mWidth( 0 )
50  , mHeight( 0 )
51  , mXCenter( 0 )
52  , mYCenter( 0 )
53 {
54  updateMatrix();
55 }
56 
58 {
59  double metersPerPixel = 25.4 / dpi / 1000.0;
61  return QgsMapToPixel( mapUnitsPerPixel * scale );
62 }
63 
65 {
66  updateMatrix();
67 }
68 
69 bool QgsMapToPixel::updateMatrix()
70 {
71  QTransform newMatrix = transform();
72 
73  // https://github.com/qgis/QGIS/issues/20856
74  if ( !newMatrix.isInvertible() )
75  return false;
76 
77  mMatrix = newMatrix;
78  return true;
79 }
80 
81 void QgsMapToPixel::setMapUnitsPerPixel( double mapUnitsPerPixel )
82 {
83  double oldUnits = mMapUnitsPerPixel;
84  mMapUnitsPerPixel = mapUnitsPerPixel;
85  if ( !updateMatrix() )
86  {
87  mMapUnitsPerPixel = oldUnits;
88  }
89 }
90 
91 void QgsMapToPixel::setMapRotation( double degrees, double cx, double cy )
92 {
93  double oldRotation = mRotation;
94  double oldXCenter = mXCenter;
95  double oldYCenter = mYCenter;
96  double oldWidth = mWidth;
97 
98  mRotation = degrees;
99  mXCenter = cx;
100  mYCenter = cy;
101  if ( mWidth < 0 )
102  {
103  // set width not that we can compute it
104  mWidth = ( ( mXCenter - mXMin ) * 2 ) / mMapUnitsPerPixel;
105  }
106 
107  if ( !updateMatrix() )
108  {
109  mRotation = oldRotation;
110  mXCenter = oldXCenter;
111  mYCenter = oldYCenter;
112  mWidth = oldWidth;
113  }
114 }
115 
116 void QgsMapToPixel::setParameters( double mapUnitsPerPixel,
117  double xc,
118  double yc,
119  int width,
120  int height,
121  double rotation )
122 {
123  double oldMUPP = mMapUnitsPerPixel;
124  double oldXCenter = mXCenter;
125  double oldYCenter = mYCenter;
126  double oldWidth = mWidth;
127  double oldHeight = mHeight;
128  double oldRotation = mRotation;
129  double oldXMin = mXMin;
130  double oldYMin = mYMin;
131 
132  mMapUnitsPerPixel = mapUnitsPerPixel;
133  mXCenter = xc;
134  mYCenter = yc;
135  mWidth = width;
136  mHeight = height;
137  mRotation = rotation;
138  mXMin = xc - ( mWidth * mMapUnitsPerPixel / 2.0 );
139  mYMin = yc - ( mHeight * mMapUnitsPerPixel / 2.0 );
140 
141  if ( !updateMatrix() )
142  {
143  mMapUnitsPerPixel = oldMUPP;
144  mXCenter = oldXCenter;
145  mYCenter = oldYCenter;
146  mWidth = oldWidth;
147  mHeight = oldHeight;
148  mRotation = oldRotation;
149  mXMin = oldXMin;
150  mYMin = oldYMin;
151  }
152 }
153 
155 {
156  QString rep;
157  QTextStream( &rep ) << "Map units/pixel: " << mMapUnitsPerPixel
158  << " center: " << mXCenter << ',' << mYCenter
159  << " rotation: " << mRotation
160  << " size: " << mWidth << 'x' << mHeight;
161  return rep;
162 }
163 
164 QTransform QgsMapToPixel::transform() const
165 {
166  // NOTE: operations are done in the reverse order in which
167  // they are configured, so translation to geographical
168  // center happens first, then scaling, then rotation
169  // and finally translation to output viewport center
170 
171  double rotation = mapRotation();
172  if ( qgsDoubleNear( rotation, 0.0 ) )
173  {
174  //no rotation, return a simplified matrix
175  return QTransform::fromScale( 1.0 / mMapUnitsPerPixel, -1.0 / mMapUnitsPerPixel )
176  .translate( -mXMin, - ( mYMin + mHeight * mMapUnitsPerPixel ) );
177  }
178  else
179  {
180  double cy = mapHeight() / 2.0;
181  double cx = mapWidth() / 2.0;
182  return QTransform::fromTranslate( cx, cy )
183  .rotate( rotation )
184  .scale( 1 / mMapUnitsPerPixel, -1 / mMapUnitsPerPixel )
185  .translate( -mXCenter, -mYCenter );
186  }
187 }
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)
Set map units per pixel.
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
QgsMapToPixel()
Constructor.
double mapUnitsPerPixel() const
Returns current map units per pixel.
QTransform transform() const
Returns a QTransform encapsulating the map to pixel conversion.
int mapWidth() const
Returns current map width in pixels The information is only known if setRotation was used.
double mapRotation() const
Returns current map rotation in degrees (clockwise)
static QgsMapToPixel fromScale(double scale, QgsUnitTypes::DistanceUnit mapUnits, double dpi=96)
Returns a new QgsMapToPixel created using a specified scale and distance unit.
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Set parameters for use in transforming coordinates.
QString showParameters() const
String representation of the parameters used in the transform.
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:68
@ DistanceMeters
Meters.
Definition: qgsunittypes.h:69
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::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:316