QGIS API Documentation  2.0.1-Dufour
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsrectangle.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrectangle.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 
18 #include <algorithm>
19 #include <cmath>
20 #include <limits>
21 #include <QRectF>
22 #include <QString>
23 #include <QTextStream>
24 #include <QRegExp>
25 #include <qnumeric.h>
26 
27 #include "qgspoint.h"
28 #include "qgsrectangle.h"
29 #include "qgslogger.h"
30 
31 QgsRectangle::QgsRectangle( double newxmin, double newymin, double newxmax, double newymax )
32  : xmin( newxmin ), ymin( newymin ), xmax( newxmax ), ymax( newymax )
33 {
34  normalize();
35 }
36 
37 QgsRectangle::QgsRectangle( QgsPoint const & p1, QgsPoint const & p2 )
38 {
39  set( p1, p2 );
40 }
41 
42 QgsRectangle::QgsRectangle( QRectF const & qRectF )
43 {
44  xmin = qRectF.topLeft().x();
45  ymin = qRectF.topLeft().y();
46  xmax = qRectF.bottomRight().x();
47  ymax = qRectF.bottomRight().y();
48 }
49 
51 {
52  xmin = r.xMinimum();
53  ymin = r.yMinimum();
54  xmax = r.xMaximum();
55  ymax = r.yMaximum();
56 }
57 
58 
59 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
60 {
61  xmin = p1.x();
62  xmax = p2.x();
63  ymin = p1.y();
64  ymax = p2.y();
65  normalize();
66 }
67 
68 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ )
69 {
70  xmin = xmin_;
71  ymin = ymin_;
72  xmax = xmax_;
73  ymax = ymax_;
74  normalize();
75 }
76 
78 {
79  if ( xmin > xmax )
80  {
81  std::swap( xmin, xmax );
82  }
83  if ( ymin > ymax )
84  {
85  std::swap( ymin, ymax );
86  }
87 } // QgsRectangle::normalize()
88 
89 
91 {
96 }
97 
98 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
99 {
100  // scale from the center
101  double centerX, centerY;
102  if ( cp )
103  {
104  centerX = cp->x();
105  centerY = cp->y();
106  }
107  else
108  {
109  centerX = xmin + width() / 2;
110  centerY = ymin + height() / 2;
111  }
112  double newWidth = width() * scaleFactor;
113  double newHeight = height() * scaleFactor;
114  xmin = centerX - newWidth / 2.0;
115  xmax = centerX + newWidth / 2.0;
116  ymin = centerY - newHeight / 2.0;
117  ymax = centerY + newHeight / 2.0;
118 }
119 
121 {
122  QgsRectangle intersection = QgsRectangle();
123  //If they don't actually intersect an empty QgsRectangle should be returned
124  if ( !rect || !intersects( *rect ) )
125  {
126  return intersection;
127  }
128 
129  intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
130  intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
131  intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
132  intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
133  return intersection;
134 }
135 
136 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
137 {
138  double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
139  double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
140  if ( x1 > x2 )
141  return false;
142  double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
143  double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
144  if ( y1 > y2 )
145  return false;
146  return true;
147 }
148 
149 bool QgsRectangle::contains( const QgsRectangle& rect ) const
150 {
151  return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
152 }
153 
154 bool QgsRectangle::contains( const QgsPoint &p ) const
155 {
156  return xmin <= p.x() && p.x() <= xmax &&
157  ymin <= p.y() && p.y() <= ymax;
158 }
159 
161 {
162 
163  xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
164  xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
165 
166  ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
167  ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
168 
169 }
170 
171 void QgsRectangle::combineExtentWith( double x, double y )
172 {
173 
174  xmin = (( xmin < x ) ? xmin : x );
175  xmax = (( xmax > x ) ? xmax : x );
176 
177  ymin = (( ymin < y ) ? ymin : y );
178  ymax = (( ymax > y ) ? ymax : y );
179 
180 }
181 
183 {
184  return xmax <= xmin || ymax <= ymin;
185 }
186 
188 {
189  QString rep =
190  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
192 
193  return rep;
194 }
195 
197 {
198  QString rep =
199  QString( "POLYGON((" ) +
200  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
201  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymin ) + ", " +
202  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymax ) + ", " +
203  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymax ) + ", " +
205  QString( "))" );
206 
207  return rep;
208 }
209 
211 //@note added in 2.0
212 QRectF QgsRectangle::toRectF() const
213 {
214  return QRectF(( qreal )xmin, ( qreal )ymin, ( qreal )xmax - xmin, ( qreal )ymax - ymin );
215 }
216 
217 // Return a string representation of the rectangle with automatic or high precision
218 QString QgsRectangle::toString( bool automaticPrecision ) const
219 {
220  if ( automaticPrecision )
221  {
222  int precision = 0;
223  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
224  {
225  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
226  // sanity check
227  if ( precision > 20 )
228  precision = 20;
229  }
230  return toString( precision );
231  }
232  else
233  return toString( 16 );
234 }
235 
236 // overloaded version of above fn to allow precision to be set
237 // Return a string representation of the rectangle with high precision
238 QString QgsRectangle::toString( int thePrecision ) const
239 {
240  QString rep;
241  if ( isEmpty() )
242  rep = "Empty";
243  else
244  rep = QString( "%1,%2 : %3,%4" )
245  .arg( xmin, 0, 'f', thePrecision )
246  .arg( ymin, 0, 'f', thePrecision )
247  .arg( xmax, 0, 'f', thePrecision )
248  .arg( ymax, 0, 'f', thePrecision );
249 
250  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
251 
252  return rep;
253 }
254 
255 
256 // Return the rectangle as a set of polygon coordinates
257 QString QgsRectangle::asPolygon() const
258 {
259 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
260 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
261  QString rep;
262 
263  QTextStream foo( &rep );
264 
265  foo.setRealNumberPrecision( 8 );
266  foo.setRealNumberNotation( QTextStream::FixedNotation );
267  // NOTE: a polygon isn't a polygon unless its closed. In the case of
268  // a rectangle, that means 5 points (last == first)
269  foo
270  << xmin << " " << ymin << ", "
271  << xmin << " " << ymax << ", "
272  << xmax << " " << ymax << ", "
273  << xmax << " " << ymin << ", "
274  << xmin << " " << ymin;
275 
276  return rep;
277 
278 } // QgsRectangle::asPolygon() const
279 
280 
281 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
282 {
283  return r1.xMaximum() == xMaximum() &&
284  r1.xMinimum() == xMinimum() &&
285  r1.yMaximum() == yMaximum() &&
286  r1.yMinimum() == yMinimum();
287 }
288 
289 
290 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
291 {
292  return ( ! operator==( r1 ) );
293 }
294 
295 
297 {
298  if ( &r != this )
299  {
300  xmax = r.xMaximum();
301  xmin = r.xMinimum();
302  ymax = r.yMaximum();
303  ymin = r.yMinimum();
304  }
305 
306  return *this;
307 }
308 
309 
311 {
312  if ( r.xMinimum() < xMinimum() )
313  setXMinimum( r.xMinimum() );
314  if ( r.xMaximum() > xMaximum() )
315  setXMaximum( r.xMaximum() );
316  if ( r.yMinimum() < yMinimum() )
317  setYMinimum( r.yMinimum() );
318  if ( r.yMaximum() > yMaximum() )
319  setYMaximum( r.yMaximum() );
320 }
321 
323 {
324  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
325  {
326  return false;
327  }
328  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
329  {
330  return false;
331  }
332  return true;
333 }
334 
336 {
337  double tmp;
338  tmp = xmin; xmin = ymin; ymin = tmp;
339  tmp = xmax; xmax = ymax; ymax = tmp;
340 }