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