QGIS API Documentation  2.99.0-Master (e077efd)
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 
46 QgsRectangle::QgsRectangle( QRectF const & qRectF )
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  if ( isNull() )
200  *this = rect;
201  else
202  {
203  xmin = (( xmin < rect.xMinimum() ) ? xmin : rect.xMinimum() );
204  xmax = (( xmax > rect.xMaximum() ) ? xmax : rect.xMaximum() );
205 
206  ymin = (( ymin < rect.yMinimum() ) ? ymin : rect.yMinimum() );
207  ymax = (( ymax > rect.yMaximum() ) ? ymax : rect.yMaximum() );
208  }
209 
210 }
211 
212 void QgsRectangle::combineExtentWith( double x, double y )
213 {
214  if ( isNull() )
215  *this = QgsRectangle( x, y, x, y );
216  else
217  {
218  xmin = (( xmin < x ) ? xmin : x );
219  xmax = (( xmax > x ) ? xmax : x );
220 
221  ymin = (( ymin < y ) ? ymin : y );
222  ymax = (( ymax > y ) ? ymax : y );
223  }
224 }
225 
227 {
228  return xmax <= xmin || ymax <= ymin;
229 }
230 
232 {
233  // rectangle created QgsRectangle() or with rect.setMinimal() ?
234  return ( qgsDoubleNear( xmin, 0.0 ) && qgsDoubleNear( xmax, 0.0 ) && qgsDoubleNear( ymin, 0.0 ) && qgsDoubleNear( ymax, 0.0 ) ) ||
237 }
238 
240 {
241  QString rep =
242  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
244 
245  return rep;
246 }
247 
249 {
250  QString rep =
251  QStringLiteral( "POLYGON((" ) +
252  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
253  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymin ) + ", " +
254  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymax ) + ", " +
255  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymax ) + ", " +
257  QStringLiteral( "))" );
258 
259  return rep;
260 }
261 
263 QRectF QgsRectangle::toRectF() const
264 {
265  return QRectF( static_cast< qreal >( xmin ), static_cast< qreal >( ymin ), static_cast< qreal >( xmax - xmin ), static_cast< qreal >( ymax - ymin ) );
266 }
267 
268 // Return a string representation of the rectangle with automatic or high precision
269 QString QgsRectangle::toString( bool automaticPrecision ) const
270 {
271  if ( automaticPrecision )
272  {
273  int precision = 0;
274  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
275  {
276  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
277  // sanity check
278  if ( precision > 20 )
279  precision = 20;
280  }
281  return toString( precision );
282  }
283  else
284  return toString( 16 );
285 }
286 
287 // overloaded version of above fn to allow precision to be set
288 // Return a string representation of the rectangle with high precision
289 QString QgsRectangle::toString( int thePrecision ) const
290 {
291  QString rep;
292  if ( isEmpty() )
293  rep = QStringLiteral( "Empty" );
294  else
295  rep = QStringLiteral( "%1,%2 : %3,%4" )
296  .arg( xmin, 0, 'f', thePrecision )
297  .arg( ymin, 0, 'f', thePrecision )
298  .arg( xmax, 0, 'f', thePrecision )
299  .arg( ymax, 0, 'f', thePrecision );
300 
301  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
302 
303  return rep;
304 }
305 
306 
307 // Return the rectangle as a set of polygon coordinates
308 QString QgsRectangle::asPolygon() const
309 {
310 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
311 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
312  QString rep;
313 
314  QTextStream foo( &rep );
315 
316  foo.setRealNumberPrecision( 8 );
317  foo.setRealNumberNotation( QTextStream::FixedNotation );
318  // NOTE: a polygon isn't a polygon unless its closed. In the case of
319  // a rectangle, that means 5 points (last == first)
320  foo
321  << xmin << ' ' << ymin << ", "
322  << xmin << ' ' << ymax << ", "
323  << xmax << ' ' << ymax << ", "
324  << xmax << ' ' << ymin << ", "
325  << xmin << ' ' << ymin;
326 
327  return rep;
328 
329 } // QgsRectangle::asPolygon() const
330 
331 
332 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
333 {
334  return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
335  qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
336  qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
337  qgsDoubleNear( r1.yMinimum(), yMinimum() );
338 }
339 
340 
341 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
342 {
343  return ( ! operator==( r1 ) );
344 }
345 
346 
348 {
349  if ( &r != this )
350  {
351  xmax = r.xMaximum();
352  xmin = r.xMinimum();
353  ymax = r.yMaximum();
354  ymin = r.yMinimum();
355  }
356 
357  return *this;
358 }
359 
360 
362 {
363  if ( r.xMinimum() < xMinimum() )
364  setXMinimum( r.xMinimum() );
365  if ( r.xMaximum() > xMaximum() )
366  setXMaximum( r.xMaximum() );
367  if ( r.yMinimum() < yMinimum() )
368  setYMinimum( r.yMinimum() );
369  if ( r.yMaximum() > yMaximum() )
370  setYMaximum( r.yMaximum() );
371 }
372 
374 {
375  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
376  {
377  return false;
378  }
379  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
380  {
381  return false;
382  }
383  return true;
384 }
385 
387 {
388  double tmp;
389  tmp = xmin;
390  xmin = ymin;
391  ymin = tmp;
392  tmp = xmax;
393  xmax = ymax;
394  ymax = tmp;
395 }
396 
397 QDataStream& operator<<( QDataStream& out, const QgsRectangle& rectangle )
398 {
399  out << rectangle.xMinimum() << rectangle.yMinimum() << rectangle.xMaximum() << rectangle.yMaximum();
400  return out;
401 }
402 
403 QDataStream& operator>>( QDataStream& in, QgsRectangle& rectangle )
404 {
405  double xmin, ymin, xmax, ymax;
406  in >> xmin >> ymin >> xmax >> ymax;
407  rectangle.setXMinimum( xmin );
408  rectangle.setYMinimum( ymin );
409  rectangle.setXMaximum( xmax );
410  rectangle.setYMaximum( ymax );
411  return in;
412 }
void unionRect(const QgsRectangle &rect)
Updates rectangle to include passed argument.
bool contains(const QgsRectangle &rect) const
return true when rectangle contains other rectangle
QgsRectangle & operator=(const QgsRectangle &r1)
Assignment operator.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
double y
Definition: qgspoint.h:116
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:176
QgsRectangle buffer(double width)
Get rectangle enlarged by buffer.
QDataStream & operator>>(QDataStream &in, QgsRectangle &rectangle)
Reads a rectangle from stream in into rectangle. QGIS version compatibility is not guaranteed...
void scale(double scaleFactor, const QgsPoint *c=nullptr)
Scale the rectangle around its center point.
QgsRectangle intersect(const QgsRectangle *rect) const
return the intersection with the given rectangle
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:196
void set(const QgsPoint &p1, const QgsPoint &p2)
Set the rectangle from two QgsPoints.
QString asWktPolygon() const
returns string representation as WKT Polygon
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
QgsRectangle(double xmin=0, double ymin=0, double xmax=0, double ymax=0)
Constructor.
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
void grow(double delta)
Grow the rectangle by the specified amount.
bool isEmpty() const
test if rectangle is empty.
void include(const QgsPoint &p)
Updates the rectangle to include the specified point.
double width() const
Width of the rectangle.
Definition: qgsrectangle.h:211
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:184
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:181
QString asPolygon() const
returns rectangle as a polygon
A class to represent a point.
Definition: qgspoint.h:111
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
Definition: MathUtils.cc:437
QString asWktCoordinates() const
returns string representation in Wkt form
bool isFinite() const
Returns true if the rectangle has finite boundaries.
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:206
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:191
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
bool operator==(const QgsRectangle &r1) const
Comparison operator.
QRectF toRectF() const
returns a QRectF with same coordinates.
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:186
bool isNull() const
test if the rectangle is null (all coordinates zero or after call to setMinimal()).
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:196
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:201
void normalize()
Normalize the rectangle so it has non-negative width/height.
bool operator!=(const QgsRectangle &r1) const
Comparison operator.
bool intersects(const QgsRectangle &rect) const
returns true when rectangle intersects with other rectangle
QDataStream & operator<<(QDataStream &out, const QgsRectangle &rectangle)
Writes the list rectangle to stream out. QGIS version compatibility is not guaranteed.
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:171
void invert()
swap x/y
double height() const
Height of the rectangle.
Definition: qgsrectangle.h:216
double x
Definition: qgspoint.h:115