QGIS API Documentation  2.12.0-Lyon
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 
45 QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel )
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
72 QgsMapToPixel::QgsMapToPixel( double mapUnitsPerPixel,
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 }
91 
93 {
94  return mHeight;
95 }
96 
98 {
99  return mWidth;
100 }
101 
102 bool QgsMapToPixel::updateMatrix()
103 {
104  QTransform newMatrix = transform();
105 
106  // http://hub.qgis.org/issues/12757
107  if ( !newMatrix.isInvertible() )
108  return false;
109 
110  mMatrix = newMatrix;
111  return true;
112 }
113 
114 QgsPoint QgsMapToPixel::toMapPoint( double x, double y ) const
115 {
116  bool invertible;
117  QTransform matrix = mMatrix.inverted( &invertible );
118  assert( invertible );
119  qreal mx, my;
120  qreal x_qreal = x, y_qreal = y;
121  matrix.map( x_qreal, y_qreal, &mx, &my );
122  //QgsDebugMsg(QString("XXX toMapPoint x:%1 y:%2 -> x:%3 y:%4").arg(x).arg(y).arg(mx).arg(my));
123  return QgsPoint( mx, my );
124 }
125 
127 {
128  QgsPoint mapPt = toMapPoint( p.x(), p.y() );
129  return QgsPoint( mapPt );
130 }
131 
133 {
134  return toMapPoint( x, y );
135 }
136 
137 QgsPoint QgsMapToPixel::toMapCoordinatesF( double x, double y ) const
138 {
139  return toMapPoint( x, y );
140 }
141 
142 void QgsMapToPixel::setMapUnitsPerPixel( double mapUnitsPerPixel )
143 {
144  double oldUnits = mMapUnitsPerPixel;
145  mMapUnitsPerPixel = mapUnitsPerPixel;
146  if ( !updateMatrix() )
147  {
148  mMapUnitsPerPixel = oldUnits;
149  }
150 }
151 
153 {
154  return mMapUnitsPerPixel;
155 }
156 
157 void QgsMapToPixel::setMapRotation( double degrees, double cx, double cy )
158 {
159  double oldRotation = mRotation;
160  double oldXCenter = xCenter;
161  double oldYCenter = yCenter;
162  double oldWidth = mWidth;
163 
164  mRotation = degrees;
165  xCenter = cx;
166  yCenter = cy;
167  if ( mWidth < 0 )
168  {
169  // set width not that we can compute it
170  mWidth = (( xCenter - xMin ) * 2 ) / mMapUnitsPerPixel;
171  }
172 
173  if ( !updateMatrix() )
174  {
175  mRotation = oldRotation;
176  xCenter = oldXCenter;
177  yCenter = oldYCenter;
178  mWidth = oldWidth;
179  }
180 }
181 
183 {
184  return mRotation;
185 }
186 
187 // @deprecated in 2.8
188 void QgsMapToPixel::setYMinimum( double ymin )
189 {
190  double oldRotation = mRotation;
191  double oldYCenter = yCenter;
192 
193  yCenter = ymin + mHeight * mMapUnitsPerPixel / 2.0;
194  mRotation = 0.0;
195  if ( !updateMatrix() )
196  {
197  mRotation = oldRotation;
198  yCenter = oldYCenter;
199  }
200 }
201 
202 // @deprecated in 2.8
203 void QgsMapToPixel::setXMinimum( double xmin )
204 {
205  double oldRotation = mRotation;
206  double oldXCenter = xCenter;
207 
208  xCenter = xmin + mWidth * mMapUnitsPerPixel / 2.0;
209  mRotation = 0.0;
210 
211  if ( !updateMatrix() )
212  {
213  mRotation = oldRotation;
214  xCenter = oldXCenter;
215  }
216 }
217 
218 // @deprecated in 2.8
219 void QgsMapToPixel::setParameters( double mapUnitsPerPixel, double xmin, double ymin, double ymax )
220 {
221  double oldMUPP = mMapUnitsPerPixel;
222  double oldXMin = xMin;
223  double oldYMin = yMin;
224  double oldHeight = mHeight;
225  double oldXCenter = xCenter;
226  double oldYCenter = yCenter;
227  double oldRotation = mRotation;
228 
229  mMapUnitsPerPixel = mapUnitsPerPixel;
230  xMin = xmin;
231  yMin = ymin;
232  mHeight = ymax;
233  xCenter = xmin + mWidth * mMapUnitsPerPixel / 2.0;
234  yCenter = ymin + mHeight * mMapUnitsPerPixel / 2.0;
235  mRotation = 0.0;
236 
237  if ( !updateMatrix() )
238  {
239  mMapUnitsPerPixel = oldMUPP;
240  xMin = oldXMin;
241  yMin = oldYMin;
242  mHeight = oldHeight;
243  xCenter = oldXCenter;
244  yCenter = oldYCenter;
245  mRotation = oldRotation;
246  }
247 }
248 
249 void QgsMapToPixel::setParameters( double mapUnitsPerPixel,
250  double xc,
251  double yc,
252  int width,
253  int height,
254  double rotation )
255 {
256  double oldMUPP = mMapUnitsPerPixel;
257  double oldXCenter = xCenter;
258  double oldYCenter = yCenter;
259  double oldWidth = mWidth;
260  double oldHeight = mHeight;
261  double oldRotation = mRotation;
262  double oldXMin = xMin;
263  double oldYMin = yMin;
264 
265  mMapUnitsPerPixel = mapUnitsPerPixel;
266  xCenter = xc;
267  yCenter = yc;
268  mWidth = width;
269  mHeight = height;
270  mRotation = rotation;
271  xMin = xc - ( mWidth * mMapUnitsPerPixel / 2.0 );
272  yMin = yc - ( mHeight * mMapUnitsPerPixel / 2.0 );
273 
274  if ( !updateMatrix() )
275  {
276  mMapUnitsPerPixel = oldMUPP;
277  xCenter = oldXCenter;
278  yCenter = oldYCenter;
279  mWidth = oldWidth;
280  mHeight = oldHeight;
281  mRotation = oldRotation;
282  xMin = oldXMin;
283  yMin = oldYMin;
284  }
285 }
286 
288 {
289  QString rep;
290  QTextStream( &rep ) << "Map units/pixel: " << mMapUnitsPerPixel
291  << " center: " << xCenter << "," << yCenter
292  << " rotation: " << mRotation
293  << " size: " << mWidth << "x" << mHeight;
294  return rep;
295 }
296 
297 QgsPoint QgsMapToPixel::transform( qreal x, qreal y ) const
298 {
299  transformInPlace( x, y );
300  return QgsPoint( x, y );
301 }
302 
304 {
305  qreal x = p.x(), y = p.y();
306  transformInPlace( x, y );
307 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p.x()).arg(dx).arg(p.y()).arg(dy));
308  return QgsPoint( x, y );
309 }
310 
312 {
313  qreal x = p->x(), y = p->y();
314  transformInPlace( x, y );
315 // QgsDebugMsg(QString("Point to pixel...X : %1-->%2, Y: %3 -->%4").arg(p->x()).arg(x).arg(p->y()).arg(y));
316  p->set( x, y );
317 }
318 
319 void QgsMapToPixel::transformInPlace( double& x, double& y ) const
320 {
321  // Map 2 Pixel
322  qreal mx, my;
323  qreal x_qreal = x, y_qreal = y;
324  mMatrix.map( x_qreal, y_qreal, &mx, &my );
325  //QgsDebugMsg(QString("XXX transformInPlace X : %1-->%2, Y: %3 -->%4").arg(x).arg(mx).arg(y).arg(my));
326  x = mx; y = my;
327 }
328 
329 void QgsMapToPixel::transformInPlace( float& x, float& y ) const
330 {
331  double mx = x, my = y;
332  transformInPlace( mx, my );
333  x = mx; y = my;
334 }
335 
337 {
338  // NOTE: operations are done in the reverse order in which
339  // they are configured, so translation to geographical
340  // center happens first, then scaling, then rotation
341  // and finally translation to output viewport center
342 
343  double rotation = mapRotation();
344  if ( qgsDoubleNear( rotation, 0.0 ) )
345  {
346  //no rotation, return a simplified matrix
347  return QTransform::fromScale( 1.0 / mMapUnitsPerPixel, -1.0 / mMapUnitsPerPixel )
348  .translate( -xMin, - ( yMin + mHeight * mMapUnitsPerPixel ) );
349  }
350  else
351  {
352  double cy = mapHeight() / 2.0;
353  double cx = mapWidth() / 2.0;
354  return QTransform::fromTranslate( cx, cy )
355  .rotate( rotation )
356  .scale( 1 / mMapUnitsPerPixel, -1 / mMapUnitsPerPixel )
357  .translate( -xCenter, -yCenter );
358  }
359 }
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)
Definition: qgis.h:268
double x() const
Get the x value of the point.
Definition: qgspoint.h:126
QTransform inverted(bool *invertible) const
int x() const
int y() const
void transformInPlace(double &x, double &y) const
Transform device coordinates to map (world) 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:117
A class to represent a point.
Definition: qgspoint.h:63
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:134
QTransform transform() const
void setMapUnitsPerPixel(double mapUnitsPerPixel)
Set map units per pixel.
~QgsMapToPixel()
destructor
QgsPoint toMapPoint(double x, double y) const
Q_DECL_DEPRECATED void setYMinimum(double ymin)
Set minimum y value.