QGIS API Documentation  2.2.0-Valmiera
 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  scale( scaleFactor, centerX, centerY );
113 }
114 
115 void QgsRectangle::scale( double scaleFactor, double centerX, double centerY )
116 {
117  double newWidth = width() * scaleFactor;
118  double newHeight = height() * scaleFactor;
119  xmin = centerX - newWidth / 2.0;
120  xmax = centerX + newWidth / 2.0;
121  ymin = centerY - newHeight / 2.0;
122  ymax = centerY + newHeight / 2.0;
123 }
124 
126 {
127  return QgsRectangle( xmin - width, ymin - width, xmax + width, ymax + width );
128 }
129 
131 {
132  QgsRectangle intersection = QgsRectangle();
133  //If they don't actually intersect an empty QgsRectangle should be returned
134  if ( !rect || !intersects( *rect ) )
135  {
136  return intersection;
137  }
138 
139  intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
140  intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
141  intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
142  intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
143  return intersection;
144 }
145 
146 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
147 {
148  double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
149  double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
150  if ( x1 > x2 )
151  return false;
152  double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
153  double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
154  if ( y1 > y2 )
155  return false;
156  return true;
157 }
158 
159 bool QgsRectangle::contains( const QgsRectangle& rect ) const
160 {
161  return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
162 }
163 
164 bool QgsRectangle::contains( const QgsPoint &p ) const
165 {
166  return xmin <= p.x() && p.x() <= xmax &&
167  ymin <= p.y() && p.y() <= ymax;
168 }
169 
171 {
172 
173  xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
174  xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
175 
176  ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
177  ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
178 
179 }
180 
181 void QgsRectangle::combineExtentWith( double x, double y )
182 {
183 
184  xmin = (( xmin < x ) ? xmin : x );
185  xmax = (( xmax > x ) ? xmax : x );
186 
187  ymin = (( ymin < y ) ? ymin : y );
188  ymax = (( ymax > y ) ? ymax : y );
189 
190 }
191 
193 {
194  return xmax <= xmin || ymax <= ymin;
195 }
196 
198 {
199  QString rep =
200  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
202 
203  return rep;
204 }
205 
207 {
208  QString rep =
209  QString( "POLYGON((" ) +
210  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
211  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymin ) + ", " +
212  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymax ) + ", " +
213  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymax ) + ", " +
215  QString( "))" );
216 
217  return rep;
218 }
219 
221 //@note added in 2.0
222 QRectF QgsRectangle::toRectF() const
223 {
224  return QRectF(( qreal )xmin, ( qreal )ymin, ( qreal )xmax - xmin, ( qreal )ymax - ymin );
225 }
226 
227 // Return a string representation of the rectangle with automatic or high precision
228 QString QgsRectangle::toString( bool automaticPrecision ) const
229 {
230  if ( automaticPrecision )
231  {
232  int precision = 0;
233  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
234  {
235  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
236  // sanity check
237  if ( precision > 20 )
238  precision = 20;
239  }
240  return toString( precision );
241  }
242  else
243  return toString( 16 );
244 }
245 
246 // overloaded version of above fn to allow precision to be set
247 // Return a string representation of the rectangle with high precision
248 QString QgsRectangle::toString( int thePrecision ) const
249 {
250  QString rep;
251  if ( isEmpty() )
252  rep = "Empty";
253  else
254  rep = QString( "%1,%2 : %3,%4" )
255  .arg( xmin, 0, 'f', thePrecision )
256  .arg( ymin, 0, 'f', thePrecision )
257  .arg( xmax, 0, 'f', thePrecision )
258  .arg( ymax, 0, 'f', thePrecision );
259 
260  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
261 
262  return rep;
263 }
264 
265 
266 // Return the rectangle as a set of polygon coordinates
267 QString QgsRectangle::asPolygon() const
268 {
269 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
270 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
271  QString rep;
272 
273  QTextStream foo( &rep );
274 
275  foo.setRealNumberPrecision( 8 );
276  foo.setRealNumberNotation( QTextStream::FixedNotation );
277  // NOTE: a polygon isn't a polygon unless its closed. In the case of
278  // a rectangle, that means 5 points (last == first)
279  foo
280  << xmin << " " << ymin << ", "
281  << xmin << " " << ymax << ", "
282  << xmax << " " << ymax << ", "
283  << xmax << " " << ymin << ", "
284  << xmin << " " << ymin;
285 
286  return rep;
287 
288 } // QgsRectangle::asPolygon() const
289 
290 
291 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
292 {
293  return r1.xMaximum() == xMaximum() &&
294  r1.xMinimum() == xMinimum() &&
295  r1.yMaximum() == yMaximum() &&
296  r1.yMinimum() == yMinimum();
297 }
298 
299 
300 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
301 {
302  return ( ! operator==( r1 ) );
303 }
304 
305 
307 {
308  if ( &r != this )
309  {
310  xmax = r.xMaximum();
311  xmin = r.xMinimum();
312  ymax = r.yMaximum();
313  ymin = r.yMinimum();
314  }
315 
316  return *this;
317 }
318 
319 
321 {
322  if ( r.xMinimum() < xMinimum() )
323  setXMinimum( r.xMinimum() );
324  if ( r.xMaximum() > xMaximum() )
325  setXMaximum( r.xMaximum() );
326  if ( r.yMinimum() < yMinimum() )
327  setYMinimum( r.yMinimum() );
328  if ( r.yMaximum() > yMaximum() )
329  setYMaximum( r.yMaximum() );
330 }
331 
333 {
334  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
335  {
336  return false;
337  }
338  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
339  {
340  return false;
341  }
342  return true;
343 }
344 
346 {
347  double tmp;
348  tmp = xmin; xmin = ymin; ymin = tmp;
349  tmp = xmax; xmax = ymax; ymax = tmp;
350 }