QGIS API Documentation  2.15.0-Master (972fc9f)
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 
26 QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel,
27  double xc,
28  double yc,
29  int width,
30  int height,
31  double rotation )
32  : mMapUnitsPerPixel( mapUnitsPerPixel )
33  , mWidth( width )
34  , mHeight( height )
35  , mRotation( rotation )
36  , xCenter( xc )
37  , yCenter( yc )
38  , xMin( xc - ( mWidth * mMapUnitsPerPixel / 2.0 ) )
39  , yMin( yc - ( mHeight * mMapUnitsPerPixel / 2.0 ) )
40 {
41  Q_ASSERT( mapUnitsPerPixel > 0 );
42  updateMatrix();
43 }
44 
46  : mMapUnitsPerPixel( mapUnitsPerPixel )
47  , mWidth( 0 )
48  , mHeight( 0 )
49  , mRotation( 0 )
50  , xCenter( 0 )
51  , yCenter( 0 )
52  , xMin( 0 )
53  , yMin( 0 )
54 {
55  updateMatrix();
56 }
57 
59  : mMapUnitsPerPixel( 1 )
60  , mWidth( 1 )
61  , mHeight( 1 )
62  , mRotation( 0.0 )
63  , xCenter( 0.5 )
64  , yCenter( 0.5 )
65  , xMin( 0 )
66  , yMin( 0 )
67 {
68  updateMatrix();
69 }
70 
71 // @deprecated in 2.8
73  double height,
74  double ymin,
75  double xmin )
76  : mMapUnitsPerPixel( mapUnitsPerPixel )
77  , mWidth( -1 )
78  , mHeight( height )
79  , mRotation( 0.0 )
80  , xCenter( 0.0 )
81  , yCenter( 0.0 )
82  , xMin( xmin )
83  , yMin( ymin )
84 {
85  updateMatrix();
86 }
87 
89 {
90  return mHeight;
91 }
92 
94 {
95  return mWidth;
96 }
97 
98 bool QgsMapToPixel::updateMatrix()
99 {
100  QTransform newMatrix = transform();
101 
102  // http://hub.qgis.org/issues/12757
103  if ( !newMatrix.isInvertible() )
104  return false;
105 
106  mMatrix = newMatrix;
107  return true;
108 }
109 
110 QgsPoint QgsMapToPixel::toMapPoint( double x, double y ) const
111 {
112  bool invertible;
113  QTransform matrix = mMatrix.inverted( &invertible );
114  assert( invertible );
115  qreal mx, my;
116  qreal x_qreal = x, y_qreal = y;
117  matrix.map( x_qreal, y_qreal, &mx, &my );
118  //QgsDebugMsg(QString("XXX toMapPoint x:%1 y:%2 -> x:%3 y:%4").arg(x).arg(y).arg(mx).arg(my));
119  return QgsPoint( mx, my );
120 }
121 
123 {
124  QgsPoint mapPt = toMapPoint( p.x(), p.y() );
125  return QgsPoint( mapPt );
126 }
127 
129 {
130  return toMapPoint( x, y );
131 }
132 
133 QgsPoint QgsMapToPixel::toMapCoordinatesF( double x, double y ) const
134 {
135  return toMapPoint( x, y );
136 }
137 
139 {
140  double oldUnits = mMapUnitsPerPixel;
141  mMapUnitsPerPixel = mapUnitsPerPixel;
142  if ( !updateMatrix() )
143  {
144  mMapUnitsPerPixel = oldUnits;
145  }
146 }
147 
149 {
150  return mMapUnitsPerPixel;
151 }
152 
153 void QgsMapToPixel::setMapRotation( double degrees, double cx, double cy )
154 {
155  double oldRotation = mRotation;
156  double oldXCenter = xCenter;
157  double oldYCenter = yCenter;
158  double oldWidth = mWidth;
159 
160  mRotation = degrees;
161  xCenter = cx;
162  yCenter = cy;
163  if ( mWidth < 0 )
164  {
165  // set width not that we can compute it
166  mWidth = (( xCenter - xMin ) * 2 ) / mMapUnitsPerPixel;
167  }
168 
169  if ( !updateMatrix() )
170  {
171  mRotation = oldRotation;
172  xCenter = oldXCenter;
173  yCenter = oldYCenter;
174  mWidth = oldWidth;
175  }
176 }
177 
179 {
180  return mRotation;
181 }
182 
183 // @deprecated in 2.8
184 void QgsMapToPixel::setYMinimum( double ymin )
185 {
186  double oldRotation = mRotation;
187  double oldYCenter = yCenter;
188 
189  yCenter = ymin + mHeight * mMapUnitsPerPixel / 2.0;
190  mRotation = 0.0;
191  if ( !updateMatrix() )
192  {
193  mRotation = oldRotation;
194  yCenter = oldYCenter;
195  }
196 }
197 
198 // @deprecated in 2.8
199 void QgsMapToPixel::setXMinimum( double xmin )
200 {
201  double oldRotation = mRotation;
202  double oldXCenter = xCenter;
203 
204  xCenter = xmin + mWidth * mMapUnitsPerPixel / 2.0;
205  mRotation = 0.0;
206 
207  if ( !updateMatrix() )
208  {
209  mRotation = oldRotation;
210  xCenter = oldXCenter;
211  }
212 }
213 
214 // @deprecated in 2.8
215 void QgsMapToPixel::setParameters( double mapUnitsPerPixel, double xmin, double ymin, double ymax )
216 {
217  double oldMUPP = mMapUnitsPerPixel;
218  double oldXMin = xMin;
219  double oldYMin = yMin;
220  double oldHeight = mHeight;
221  double oldXCenter = xCenter;
222  double oldYCenter = yCenter;
223  double oldRotation = mRotation;
224 
225  mMapUnitsPerPixel = mapUnitsPerPixel;
226  xMin = xmin;
227  yMin = ymin;
228  mHeight = ymax;
229  xCenter = xmin + mWidth * mMapUnitsPerPixel / 2.0;
230  yCenter = ymin + mHeight * mMapUnitsPerPixel / 2.0;
231  mRotation = 0.0;
232 
233  if ( !updateMatrix() )
234  {
235  mMapUnitsPerPixel = oldMUPP;
236  xMin = oldXMin;
237  yMin = oldYMin;
238  mHeight = oldHeight;
239  xCenter = oldXCenter;
240  yCenter = oldYCenter;
241  mRotation = oldRotation;
242  }
243 }
244 
246  double xc,
247  double yc,
248  int width,
249  int height,
250  double rotation )
251 {
252  double oldMUPP = mMapUnitsPerPixel;
253  double oldXCenter = xCenter;
254  double oldYCenter = yCenter;
255  double oldWidth = mWidth;
256  double oldHeight = mHeight;
257  double oldRotation = mRotation;
258  double oldXMin = xMin;
259  double oldYMin = yMin;
260 
261  mMapUnitsPerPixel = mapUnitsPerPixel;
262  xCenter = xc;
263  yCenter = yc;
264  mWidth = width;
265  mHeight = height;
266  mRotation = rotation;
267  xMin = xc - ( mWidth * mMapUnitsPerPixel / 2.0 );
268  yMin = yc - ( mHeight * mMapUnitsPerPixel / 2.0 );
269 
270  if ( !updateMatrix() )
271  {
272  mMapUnitsPerPixel = oldMUPP;
273  xCenter = oldXCenter;
274  yCenter = oldYCenter;
275  mWidth = oldWidth;
276  mHeight = oldHeight;
277  mRotation = oldRotation;
278  xMin = oldXMin;
279  yMin = oldYMin;
280  }
281 }
282 
284 {
285  QString rep;
286  QTextStream( &rep ) << "Map units/pixel: " << mMapUnitsPerPixel
287  << " center: " << xCenter << ',' << yCenter
288  << " rotation: " << mRotation
289  << " size: " << mWidth << 'x' << mHeight;
290  return rep;
291 }
292 
293 QgsPoint QgsMapToPixel::transform( qreal x, qreal y ) const
294 {
295  transformInPlace( x, y );
296  return QgsPoint( x, y );
297 }
298 
300 {
301  qreal x = p.x(), y = p.y();
302  transformInPlace( x, y );
303 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p.x()).arg(dx).arg(p.y()).arg(dy));
304  return QgsPoint( x, y );
305 }
306 
308 {
309  qreal x = p->x(), y = p->y();
310  transformInPlace( x, y );
311 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p->x()).arg(x).arg(p->y()).arg(y));
312  p->set( x, y );
313 }
314 
315 void QgsMapToPixel::transformInPlace( double& x, double& y ) const
316 {
317  // Map 2 Pixel
318  qreal mx, my;
319  qreal x_qreal = x, y_qreal = y;
320  mMatrix.map( x_qreal, y_qreal, &mx, &my );
321  //QgsDebugMsg(QString("XXX transformInPlace X : %1-->%2, Y: %3 -->%4").arg(x).arg(mx).arg(y).arg(my));
322  x = mx;
323  y = my;
324 }
325 
326 void QgsMapToPixel::transformInPlace( float& x, float& y ) const
327 {
328  double mx = x, my = y;
329  transformInPlace( mx, my );
330  x = mx;
331  y = my;
332 }
333 
335 {
336  // NOTE: operations are done in the reverse order in which
337  // they are configured, so translation to geographical
338  // center happens first, then scaling, then rotation
339  // and finally translation to output viewport center
340 
341  double rotation = mapRotation();
342  if ( qgsDoubleNear( rotation, 0.0 ) )
343  {
344  //no rotation, return a simplified matrix
345  return QTransform::fromScale( 1.0 / mMapUnitsPerPixel, -1.0 / mMapUnitsPerPixel )
346  .translate( -xMin, - ( yMin + mHeight * mMapUnitsPerPixel ) );
347  }
348  else
349  {
350  double cy = mapHeight() / 2.0;
351  double cx = mapWidth() / 2.0;
352  return QTransform::fromTranslate( cx, cy )
353  .rotate( rotation )
354  .scale( 1 / mMapUnitsPerPixel, -1 / mMapUnitsPerPixel )
355  .translate( -xCenter, -yCenter );
356  }
357 }
int mapWidth() const
Return current map width in pixels The information is only known if setRotation was used...
QTransform fromTranslate(qreal dx, qreal dy)
QTransform fromScale(qreal sx, qreal sy)
void setMapRotation(double degrees, double cx, double cy)
Set map rotation in degrees (clockwise)
QPoint map(const QPoint &point) const
Q_DECL_DEPRECATED void setParameters(double mapUnitsPerPixel, double xmin, double ymin, double height)
Set parameters for use in transforming coordinates.
double mapRotation() const
Return current map rotation in degrees.
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:352
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
QTransform inverted(bool *invertible) const
int x() const
int y() const
void transformInPlace(double &x, double &y) const
Transform device coordinates to map coordinates.
QTransform & translate(qreal dx, qreal dy)
QTransform & scale(qreal sx, qreal sy)
QgsMapToPixel()
Constructor.
Q_DECL_DEPRECATED void setXMinimum(double xmin)
set minimum x value
QString showParameters() const
String representation of the parameters used in the transform.
bool isInvertible() const
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:176
A class to represent a point.
Definition: qgspoint.h:117
QgsPoint toMapCoordinatesF(double x, double y) const
Transform device coordinates to map (world) coordinates.
QgsPoint toMapCoordinates(int x, int y) const
QTransform & rotate(qreal angle, Qt::Axis axis)
int mapHeight() const
Return current map height in pixels.
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
QTransform transform() const
void setMapUnitsPerPixel(double mapUnitsPerPixel)
Set map units per pixel.
QgsPoint toMapPoint(double x, double y) const
Q_DECL_DEPRECATED void setYMinimum(double ymin)
Set minimum y value.