QGIS API Documentation  2.8.2-Wien
 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 <QTransform>
25 #include <QRegExp>
26 #include <qnumeric.h>
27 
28 #include "qgspoint.h"
29 #include "qgsrectangle.h"
30 #include "qgslogger.h"
31 
32 QgsRectangle::QgsRectangle( double newxmin, double newymin, double newxmax, double newymax )
33  : xmin( newxmin ), ymin( newymin ), xmax( newxmax ), ymax( newymax )
34 {
35  normalize();
36 }
37 
38 QgsRectangle::QgsRectangle( QgsPoint const & p1, QgsPoint const & p2 )
39 {
40  set( p1, p2 );
41 }
42 
43 QgsRectangle::QgsRectangle( QRectF const & qRectF )
44 {
45  xmin = qRectF.topLeft().x();
46  ymin = qRectF.topLeft().y();
47  xmax = qRectF.bottomRight().x();
48  ymax = qRectF.bottomRight().y();
49 }
50 
52 {
53  xmin = r.xMinimum();
54  ymin = r.yMinimum();
55  xmax = r.xMaximum();
56  ymax = r.yMaximum();
57 }
58 
59 
60 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
61 {
62  xmin = p1.x();
63  xmax = p2.x();
64  ymin = p1.y();
65  ymax = p2.y();
66  normalize();
67 }
68 
69 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ )
70 {
71  xmin = xmin_;
72  ymin = ymin_;
73  xmax = xmax_;
74  ymax = ymax_;
75  normalize();
76 }
77 
79 {
80  if ( xmin > xmax )
81  {
82  std::swap( xmin, xmax );
83  }
84  if ( ymin > ymax )
85  {
86  std::swap( ymin, ymax );
87  }
88 } // QgsRectangle::normalize()
89 
90 
92 {
97 }
98 
99 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
100 {
101  // scale from the center
102  double centerX, centerY;
103  if ( cp )
104  {
105  centerX = cp->x();
106  centerY = cp->y();
107  }
108  else
109  {
110  centerX = xmin + width() / 2;
111  centerY = ymin + height() / 2;
112  }
113  scale( scaleFactor, centerX, centerY );
114 }
115 
116 void QgsRectangle::scale( double scaleFactor, double centerX, double centerY )
117 {
118  double newWidth = width() * scaleFactor;
119  double newHeight = height() * scaleFactor;
120  xmin = centerX - newWidth / 2.0;
121  xmax = centerX + newWidth / 2.0;
122  ymin = centerY - newHeight / 2.0;
123  ymax = centerY + newHeight / 2.0;
124 }
125 
127 {
128  return QgsRectangle( xmin - width, ymin - width, xmax + width, ymax + width );
129 }
130 
132 {
133  QgsRectangle intersection = QgsRectangle();
134  //If they don't actually intersect an empty QgsRectangle should be returned
135  if ( !rect || !intersects( *rect ) )
136  {
137  return intersection;
138  }
139 
140  intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
141  intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
142  intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
143  intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
144  return intersection;
145 }
146 
147 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
148 {
149  double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
150  double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
151  if ( x1 > x2 )
152  return false;
153  double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
154  double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
155  if ( y1 > y2 )
156  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  // rectangle created QgsRectangle() or with rect.setMinimal() ?
201  return ( xmin == 0 && xmax == 0 && ymin == 0 && ymax == 0 ) ||
204 }
205 
207 {
208  QString rep =
209  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
211 
212  return rep;
213 }
214 
216 {
217  QString rep =
218  QString( "POLYGON((" ) +
219  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymin ) + ", " +
220  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymin ) + ", " +
221  qgsDoubleToString( xmax ) + " " + qgsDoubleToString( ymax ) + ", " +
222  qgsDoubleToString( xmin ) + " " + qgsDoubleToString( ymax ) + ", " +
224  QString( "))" );
225 
226  return rep;
227 }
228 
230 QRectF QgsRectangle::toRectF() const
231 {
232  return QRectF(( qreal )xmin, ( qreal )ymin, ( qreal )xmax - xmin, ( qreal )ymax - ymin );
233 }
234 
235 // Return a string representation of the rectangle with automatic or high precision
236 QString QgsRectangle::toString( bool automaticPrecision ) const
237 {
238  if ( automaticPrecision )
239  {
240  int precision = 0;
241  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
242  {
243  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
244  // sanity check
245  if ( precision > 20 )
246  precision = 20;
247  }
248  return toString( precision );
249  }
250  else
251  return toString( 16 );
252 }
253 
254 // overloaded version of above fn to allow precision to be set
255 // Return a string representation of the rectangle with high precision
256 QString QgsRectangle::toString( int thePrecision ) const
257 {
258  QString rep;
259  if ( isEmpty() )
260  rep = "Empty";
261  else
262  rep = QString( "%1,%2 : %3,%4" )
263  .arg( xmin, 0, 'f', thePrecision )
264  .arg( ymin, 0, 'f', thePrecision )
265  .arg( xmax, 0, 'f', thePrecision )
266  .arg( ymax, 0, 'f', thePrecision );
267 
268  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
269 
270  return rep;
271 }
272 
273 
274 // Return the rectangle as a set of polygon coordinates
275 QString QgsRectangle::asPolygon() const
276 {
277 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
278 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
279  QString rep;
280 
281  QTextStream foo( &rep );
282 
283  foo.setRealNumberPrecision( 8 );
284  foo.setRealNumberNotation( QTextStream::FixedNotation );
285  // NOTE: a polygon isn't a polygon unless its closed. In the case of
286  // a rectangle, that means 5 points (last == first)
287  foo
288  << xmin << " " << ymin << ", "
289  << xmin << " " << ymax << ", "
290  << xmax << " " << ymax << ", "
291  << xmax << " " << ymin << ", "
292  << xmin << " " << ymin;
293 
294  return rep;
295 
296 } // QgsRectangle::asPolygon() const
297 
298 
299 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
300 {
301  return r1.xMaximum() == xMaximum() &&
302  r1.xMinimum() == xMinimum() &&
303  r1.yMaximum() == yMaximum() &&
304  r1.yMinimum() == yMinimum();
305 }
306 
307 
308 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
309 {
310  return ( ! operator==( r1 ) );
311 }
312 
313 
315 {
316  if ( &r != this )
317  {
318  xmax = r.xMaximum();
319  xmin = r.xMinimum();
320  ymax = r.yMaximum();
321  ymin = r.yMinimum();
322  }
323 
324  return *this;
325 }
326 
327 
329 {
330  if ( r.xMinimum() < xMinimum() )
331  setXMinimum( r.xMinimum() );
332  if ( r.xMaximum() > xMaximum() )
333  setXMaximum( r.xMaximum() );
334  if ( r.yMinimum() < yMinimum() )
335  setYMinimum( r.yMinimum() );
336  if ( r.yMaximum() > yMaximum() )
337  setYMaximum( r.yMaximum() );
338 }
339 
341 {
342  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
343  {
344  return false;
345  }
346  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
347  {
348  return false;
349  }
350  return true;
351 }
352 
354 {
355  double tmp;
356  tmp = xmin; xmin = ymin; ymin = tmp;
357  tmp = xmax; xmax = ymax; ymax = tmp;
358 }