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