QGIS API Documentation  2.15.0-Master (02a0ebe)
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 )
34  , ymin( newymin )
35  , xmax( newxmax )
36  , ymax( newymax )
37 {
38  normalize();
39 }
40 
42 {
43  set( p1, p2 );
44 }
45 
47 {
48  xmin = qRectF.topLeft().x();
49  ymin = qRectF.topLeft().y();
50  xmax = qRectF.bottomRight().x();
51  ymax = qRectF.bottomRight().y();
52 }
53 
55 {
56  xmin = r.xMinimum();
57  ymin = r.yMinimum();
58  xmax = r.xMaximum();
59  ymax = r.yMaximum();
60 }
61 
62 
63 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
64 {
65  xmin = p1.x();
66  xmax = p2.x();
67  ymin = p1.y();
68  ymax = p2.y();
69  normalize();
70 }
71 
72 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ )
73 {
74  xmin = xmin_;
75  ymin = ymin_;
76  xmax = xmax_;
77  ymax = ymax_;
78  normalize();
79 }
80 
82 {
83  if ( isNull() )
84  return;
85 
86  if ( xmin > xmax )
87  {
88  std::swap( xmin, xmax );
89  }
90  if ( ymin > ymax )
91  {
92  std::swap( ymin, ymax );
93  }
94 } // QgsRectangle::normalize()
95 
96 
98 {
103 }
104 
105 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
106 {
107  // scale from the center
108  double centerX, centerY;
109  if ( cp )
110  {
111  centerX = cp->x();
112  centerY = cp->y();
113  }
114  else
115  {
116  centerX = xmin + width() / 2;
117  centerY = ymin + height() / 2;
118  }
119  scale( scaleFactor, centerX, centerY );
120 }
121 
122 void QgsRectangle::scale( double scaleFactor, double centerX, double centerY )
123 {
124  double newWidth = width() * scaleFactor;
125  double newHeight = height() * scaleFactor;
126  xmin = centerX - newWidth / 2.0;
127  xmax = centerX + newWidth / 2.0;
128  ymin = centerY - newHeight / 2.0;
129  ymax = centerY + newHeight / 2.0;
130 }
131 
132 void QgsRectangle::grow( double delta )
133 {
134  xmin -= delta;
135  xmax += delta;
136  ymin -= delta;
137  ymax += delta;
138 }
139 
141 {
142  if ( p.x() < xMinimum() )
143  setXMinimum( p.x() );
144  else if ( p.x() > xMaximum() )
145  setXMaximum( p.x() );
146  if ( p.y() < yMinimum() )
147  setYMinimum( p.y() );
148  if ( p.y() > yMaximum() )
149  setYMaximum( p.y() );
150 }
151 
153 {
154  return QgsRectangle( xmin - width, ymin - width, xmax + width, ymax + width );
155 }
156 
158 {
159  QgsRectangle intersection = QgsRectangle();
160  //If they don't actually intersect an empty QgsRectangle should be returned
161  if ( !rect || !intersects( *rect ) )
162  {
163  return intersection;
164  }
165 
166  intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
167  intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
168  intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
169  intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
170  return intersection;
171 }
172 
173 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
174 {
175  double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
176  double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
177  if ( x1 > x2 )
178  return false;
179  double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
180  double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
181  if ( y1 > y2 )
182  return false;
183  return true;
184 }
185 
186 bool QgsRectangle::contains( const QgsRectangle& rect ) const
187 {
188  return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
189 }
190 
191 bool QgsRectangle::contains( const QgsPoint &p ) const
192 {
193  return xmin <= p.x() && p.x() <= xmax &&
194  ymin <= p.y() && p.y() <= ymax;
195 }
196 
198 {
199 
200  xmin = (( xmin < rect.xMinimum() ) ? xmin : rect.xMinimum() );
201  xmax = (( xmax > rect.xMaximum() ) ? xmax : rect.xMaximum() );
202 
203  ymin = (( ymin < rect.yMinimum() ) ? ymin : rect.yMinimum() );
204  ymax = (( ymax > rect.yMaximum() ) ? ymax : rect.yMaximum() );
205 
206 }
207 
208 void QgsRectangle::combineExtentWith( double x, double y )
209 {
210 
211  xmin = (( xmin < x ) ? xmin : x );
212  xmax = (( xmax > x ) ? xmax : x );
213 
214  ymin = (( ymin < y ) ? ymin : y );
215  ymax = (( ymax > y ) ? ymax : y );
216 
217 }
218 
220 {
221  return xmax <= xmin || ymax <= ymin;
222 }
223 
225 {
226  // rectangle created QgsRectangle() or with rect.setMinimal() ?
227  return ( qgsDoubleNear( xmin, 0.0 ) && qgsDoubleNear( xmax, 0.0 ) && qgsDoubleNear( ymin, 0.0 ) && qgsDoubleNear( ymax, 0.0 ) ) ||
230 }
231 
233 {
234  QString rep =
235  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
237 
238  return rep;
239 }
240 
242 {
243  QString rep =
244  QString( "POLYGON((" ) +
245  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
246  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymin ) + ", " +
247  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymax ) + ", " +
248  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymax ) + ", " +
250  QString( "))" );
251 
252  return rep;
253 }
254 
257 {
258  return QRectF( static_cast< qreal >( xmin ), static_cast< qreal >( ymin ), static_cast< qreal >( xmax - xmin ), static_cast< qreal >( ymax - ymin ) );
259 }
260 
261 // Return a string representation of the rectangle with automatic or high precision
262 QString QgsRectangle::toString( bool automaticPrecision ) const
263 {
264  if ( automaticPrecision )
265  {
266  int precision = 0;
267  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
268  {
269  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
270  // sanity check
271  if ( precision > 20 )
272  precision = 20;
273  }
274  return toString( precision );
275  }
276  else
277  return toString( 16 );
278 }
279 
280 // overloaded version of above fn to allow precision to be set
281 // Return a string representation of the rectangle with high precision
282 QString QgsRectangle::toString( int thePrecision ) const
283 {
284  QString rep;
285  if ( isEmpty() )
286  rep = "Empty";
287  else
288  rep = QString( "%1,%2 : %3,%4" )
289  .arg( xmin, 0, 'f', thePrecision )
290  .arg( ymin, 0, 'f', thePrecision )
291  .arg( xmax, 0, 'f', thePrecision )
292  .arg( ymax, 0, 'f', thePrecision );
293 
294  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
295 
296  return rep;
297 }
298 
299 
300 // Return the rectangle as a set of polygon coordinates
302 {
303 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
304 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
305  QString rep;
306 
307  QTextStream foo( &rep );
308 
309  foo.setRealNumberPrecision( 8 );
310  foo.setRealNumberNotation( QTextStream::FixedNotation );
311  // NOTE: a polygon isn't a polygon unless its closed. In the case of
312  // a rectangle, that means 5 points (last == first)
313  foo
314  << xmin << ' ' << ymin << ", "
315  << xmin << ' ' << ymax << ", "
316  << xmax << ' ' << ymax << ", "
317  << xmax << ' ' << ymin << ", "
318  << xmin << ' ' << ymin;
319 
320  return rep;
321 
322 } // QgsRectangle::asPolygon() const
323 
324 
325 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
326 {
327  return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
328  qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
329  qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
330  qgsDoubleNear( r1.yMinimum(), yMinimum() );
331 }
332 
333 
334 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
335 {
336  return ( ! operator==( r1 ) );
337 }
338 
339 
341 {
342  if ( &r != this )
343  {
344  xmax = r.xMaximum();
345  xmin = r.xMinimum();
346  ymax = r.yMaximum();
347  ymin = r.yMinimum();
348  }
349 
350  return *this;
351 }
352 
353 
355 {
356  if ( r.xMinimum() < xMinimum() )
357  setXMinimum( r.xMinimum() );
358  if ( r.xMaximum() > xMaximum() )
359  setXMaximum( r.xMaximum() );
360  if ( r.yMinimum() < yMinimum() )
361  setYMinimum( r.yMinimum() );
362  if ( r.yMaximum() > yMaximum() )
363  setYMaximum( r.yMaximum() );
364 }
365 
367 {
368  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
369  {
370  return false;
371  }
372  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
373  {
374  return false;
375  }
376  return true;
377 }
378 
380 {
381  double tmp;
382  tmp = xmin;
383  xmin = ymin;
384  ymin = tmp;
385  tmp = xmax;
386  xmax = ymax;
387  ymax = tmp;
388 }
389 
390 QDataStream& operator<<( QDataStream& out, const QgsRectangle& rectangle )
391 {
392  out << rectangle.xMinimum() << rectangle.yMinimum() << rectangle.xMaximum() << rectangle.yMaximum();
393  return out;
394 }
395 
397 {
398  double xmin, ymin, xmax, ymax;
399  in >> xmin >> ymin >> xmax >> ymax;
400  rectangle.setXMinimum( xmin );
401  rectangle.setYMinimum( ymin );
402  rectangle.setXMaximum( xmax );
403  rectangle.setYMaximum( ymax );
404  return in;
405 }
void unionRect(const QgsRectangle &rect)
Updates rectangle to include passed argument.
QgsRectangle & operator=(const QgsRectangle &r1)
Assignment operator.
bool intersects(const QgsRectangle &rect) const
returns true when rectangle intersects with other rectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:35
bool isEmpty() const
test if rectangle is empty.
QRectF toRectF() const
returns a QRectF with same coordinates.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void setRealNumberNotation(RealNumberNotation notation)
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:172
QgsRectangle buffer(double width)
Get rectangle enlarged by buffer.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
void setRealNumberPrecision(int precision)
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
QDataStream & operator>>(QDataStream &in, QgsRectangle &rectangle)
Reads a rectangle from stream in into rectangle.
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:352
double x() const
Get the x value of the point.
Definition: qgspoint.h:185
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
qreal x() const
qreal y() const
QgsRectangle(double xmin=0, double ymin=0, double xmax=0, double ymax=0)
Constructor.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
void grow(double delta)
Grow the rectangle by the specified amount.
void include(const QgsPoint &p)
Updates the rectangle to include the specified point.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:340
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:177
QPointF topLeft() const
QString asWktCoordinates() const
returns string representation in Wkt form
A class to represent a point.
Definition: qgspoint.h:117
bool operator!=(const QgsRectangle &r1) const
Comparison operator.
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
QString asWktPolygon() const
returns string representation as WKT Polygon
QString asPolygon() const
returns rectangle as a polygon
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:182
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
double y() const
Get the y value of the point.
Definition: qgspoint.h:193
QPointF bottomRight() const
void normalize()
Normalize the rectangle so it has non-negative width/height.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:207
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
QDataStream & operator<<(QDataStream &out, const QgsRectangle &rectangle)
Writes the list rectangle to stream out.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:167
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:212
void invert()
swap x/y
bool operator==(const QgsRectangle &r1) const
Comparison operator.