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