QGIS API Documentation  2.99.0-Master (37c43df)
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 "qgspoint.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  , xMin( xc - ( mWidth * mMapUnitsPerPixel / 2.0 ) )
41  , yMin( yc - ( mHeight * mMapUnitsPerPixel / 2.0 ) )
42 {
43  Q_ASSERT( mapUnitsPerPixel > 0 );
44  updateMatrix();
45 }
46 
48  : mMapUnitsPerPixel( mapUnitsPerPixel )
49  , mWidth( 0 )
50  , mHeight( 0 )
51  , mRotation( 0 )
52  , mXCenter( 0 )
53  , mYCenter( 0 )
54  , xMin( 0 )
55  , yMin( 0 )
56 {
57  updateMatrix();
58 }
59 
61 {
62  double metresPerPixel = 25.4 / dpi / 1000.0;
64  return QgsMapToPixel( mapUnitsPerPixel / scale );
65 }
66 
68  : mMapUnitsPerPixel( 1 )
69  , mWidth( 1 )
70  , mHeight( 1 )
71  , mRotation( 0.0 )
72  , mXCenter( 0.5 )
73  , mYCenter( 0.5 )
74  , xMin( 0 )
75  , yMin( 0 )
76 {
77  updateMatrix();
78 }
79 
81 {
82  return mHeight;
83 }
84 
86 {
87  return mWidth;
88 }
89 
90 bool QgsMapToPixel::updateMatrix()
91 {
92  QTransform newMatrix = transform();
93 
94  // http://hub.qgis.org/issues/12757
95  if ( !newMatrix.isInvertible() )
96  return false;
97 
98  mMatrix = newMatrix;
99  return true;
100 }
101 
102 QgsPoint QgsMapToPixel::toMapPoint( double x, double y ) const
103 {
104  bool invertible;
105  QTransform matrix = mMatrix.inverted( &invertible );
106  assert( invertible );
107  qreal mx, my;
108  qreal x_qreal = x, y_qreal = y;
109  matrix.map( x_qreal, y_qreal, &mx, &my );
110  //QgsDebugMsg(QString("XXX toMapPoint x:%1 y:%2 -> x:%3 y:%4").arg(x).arg(y).arg(mx).arg(my));
111  return QgsPoint( mx, my );
112 }
113 
115 {
116  QgsPoint mapPt = toMapPoint( p.x(), p.y() );
117  return QgsPoint( mapPt );
118 }
119 
121 {
122  return toMapPoint( x, y );
123 }
124 
125 QgsPoint QgsMapToPixel::toMapCoordinatesF( double x, double y ) const
126 {
127  return toMapPoint( x, y );
128 }
129 
131 {
132  double oldUnits = mMapUnitsPerPixel;
133  mMapUnitsPerPixel = mapUnitsPerPixel;
134  if ( !updateMatrix() )
135  {
136  mMapUnitsPerPixel = oldUnits;
137  }
138 }
139 
141 {
142  return mMapUnitsPerPixel;
143 }
144 
145 void QgsMapToPixel::setMapRotation( double degrees, double cx, double cy )
146 {
147  double oldRotation = mRotation;
148  double oldXCenter = mXCenter;
149  double oldYCenter = mYCenter;
150  double oldWidth = mWidth;
151 
152  mRotation = degrees;
153  mXCenter = cx;
154  mYCenter = cy;
155  if ( mWidth < 0 )
156  {
157  // set width not that we can compute it
158  mWidth = (( mXCenter - xMin ) * 2 ) / mMapUnitsPerPixel;
159  }
160 
161  if ( !updateMatrix() )
162  {
163  mRotation = oldRotation;
164  mXCenter = oldXCenter;
165  mYCenter = oldYCenter;
166  mWidth = oldWidth;
167  }
168 }
169 
171 {
172  return mRotation;
173 }
174 
176  double xc,
177  double yc,
178  int width,
179  int height,
180  double rotation )
181 {
182  double oldMUPP = mMapUnitsPerPixel;
183  double oldXCenter = mXCenter;
184  double oldYCenter = mYCenter;
185  double oldWidth = mWidth;
186  double oldHeight = mHeight;
187  double oldRotation = mRotation;
188  double oldXMin = xMin;
189  double oldYMin = yMin;
190 
191  mMapUnitsPerPixel = mapUnitsPerPixel;
192  mXCenter = xc;
193  mYCenter = yc;
194  mWidth = width;
195  mHeight = height;
196  mRotation = rotation;
197  xMin = xc - ( mWidth * mMapUnitsPerPixel / 2.0 );
198  yMin = yc - ( mHeight * mMapUnitsPerPixel / 2.0 );
199 
200  if ( !updateMatrix() )
201  {
202  mMapUnitsPerPixel = oldMUPP;
203  mXCenter = oldXCenter;
204  mYCenter = oldYCenter;
205  mWidth = oldWidth;
206  mHeight = oldHeight;
207  mRotation = oldRotation;
208  xMin = oldXMin;
209  yMin = oldYMin;
210  }
211 }
212 
214 {
215  QString rep;
216  QTextStream( &rep ) << "Map units/pixel: " << mMapUnitsPerPixel
217  << " center: " << mXCenter << ',' << mYCenter
218  << " rotation: " << mRotation
219  << " size: " << mWidth << 'x' << mHeight;
220  return rep;
221 }
222 
223 QgsPoint QgsMapToPixel::transform( qreal x, qreal y ) const
224 {
225  transformInPlace( x, y );
226  return QgsPoint( x, y );
227 }
228 
230 {
231  qreal x = p.x(), y = p.y();
232  transformInPlace( x, y );
233 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p.x()).arg(dx).arg(p.y()).arg(dy));
234  return QgsPoint( x, y );
235 }
236 
238 {
239  qreal x = p->x(), y = p->y();
240  transformInPlace( x, y );
241 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p->x()).arg(x).arg(p->y()).arg(y));
242  p->set( x, y );
243 }
244 
245 void QgsMapToPixel::transformInPlace( double& x, double& y ) const
246 {
247  // Map 2 Pixel
248  qreal mx, my;
249  qreal x_qreal = x, y_qreal = y;
250  mMatrix.map( x_qreal, y_qreal, &mx, &my );
251  //QgsDebugMsg(QString("XXX transformInPlace X : %1-->%2, Y: %3 -->%4").arg(x).arg(mx).arg(y).arg(my));
252  x = mx;
253  y = my;
254 }
255 
256 void QgsMapToPixel::transformInPlace( float& x, float& y ) const
257 {
258  double mx = x, my = y;
259  transformInPlace( mx, my );
260  x = mx;
261  y = my;
262 }
263 
264 QTransform QgsMapToPixel::transform() const
265 {
266  // NOTE: operations are done in the reverse order in which
267  // they are configured, so translation to geographical
268  // center happens first, then scaling, then rotation
269  // and finally translation to output viewport center
270 
271  double rotation = mapRotation();
272  if ( qgsDoubleNear( rotation, 0.0 ) )
273  {
274  //no rotation, return a simplified matrix
275  return QTransform::fromScale( 1.0 / mMapUnitsPerPixel, -1.0 / mMapUnitsPerPixel )
276  .translate( -xMin, - ( yMin + mHeight * mMapUnitsPerPixel ) );
277  }
278  else
279  {
280  double cy = mapHeight() / 2.0;
281  double cx = mapWidth() / 2.0;
282  return QTransform::fromTranslate( cx, cy )
283  .rotate( rotation )
284  .scale( 1 / mMapUnitsPerPixel, -1 / mMapUnitsPerPixel )
285  .translate( -mXCenter, -mYCenter );
286  }
287 }
double y
Definition: qgspoint.h:116
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
QgsPoint toMapPoint(double x, double y) const
QgsPoint toMapCoordinates(int x, int y) const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:196
double mapRotation() const
Return current map rotation in degrees.
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:33
int mapWidth() const
Return current map width in pixels The information is only known if setRotation was used...
int mapHeight() const
Return current map height in pixels.
static QgsMapToPixel fromScale(double scale, QgsUnitTypes::DistanceUnit mapUnits, double dpi=96)
Returns a new QgsMapToPixel created using a specified scale and distance unit.
QgsMapToPixel()
Constructor.
QString showParameters() const
String representation of the parameters used in the transform.
double mapUnitsPerPixel() const
Return current map units per pixel.
void set(double x, double y)
Sets the x and y value of the point.
Definition: qgspoint.h:175
A class to represent a point.
Definition: qgspoint.h:111
DistanceUnit
Units of distance.
Definition: qgsunittypes.h:42
void setParameters(double mapUnitsPerPixel, double centerX, double centerY, int widthPixels, int heightPixels, double rotation)
Set parameters for use in transforming coordinates.
QgsPoint toMapCoordinatesF(double x, double y) const
Transform device coordinates to map (world) coordinates.
QTransform transform() const
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
void setMapUnitsPerPixel(double mapUnitsPerPixel)
Set map units per pixel.
double x
Definition: qgspoint.h:115