QGIS API Documentation  2.14.0-Essen
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 
39 {
40  set( p1, p2 );
41 }
42 
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 ( isNull() )
81  return;
82 
83  if ( xmin > xmax )
84  {
85  std::swap( xmin, xmax );
86  }
87  if ( ymin > ymax )
88  {
89  std::swap( ymin, ymax );
90  }
91 } // QgsRectangle::normalize()
92 
93 
95 {
100 }
101 
102 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
103 {
104  // scale from the center
105  double centerX, centerY;
106  if ( cp )
107  {
108  centerX = cp->x();
109  centerY = cp->y();
110  }
111  else
112  {
113  centerX = xmin + width() / 2;
114  centerY = ymin + height() / 2;
115  }
116  scale( scaleFactor, centerX, centerY );
117 }
118 
119 void QgsRectangle::scale( double scaleFactor, double centerX, double centerY )
120 {
121  double newWidth = width() * scaleFactor;
122  double newHeight = height() * scaleFactor;
123  xmin = centerX - newWidth / 2.0;
124  xmax = centerX + newWidth / 2.0;
125  ymin = centerY - newHeight / 2.0;
126  ymax = centerY + newHeight / 2.0;
127 }
128 
129 void QgsRectangle::grow( double delta )
130 {
131  xmin -= delta;
132  xmax += delta;
133  ymin -= delta;
134  ymax += delta;
135 }
136 
138 {
139  if ( p.x() < xMinimum() )
140  setXMinimum( p.x() );
141  else if ( p.x() > xMaximum() )
142  setXMaximum( p.x() );
143  if ( p.y() < yMinimum() )
144  setYMinimum( p.y() );
145  if ( p.y() > yMaximum() )
146  setYMaximum( p.y() );
147 }
148 
150 {
151  return QgsRectangle( xmin - width, ymin - width, xmax + width, ymax + width );
152 }
153 
155 {
156  QgsRectangle intersection = QgsRectangle();
157  //If they don't actually intersect an empty QgsRectangle should be returned
158  if ( !rect || !intersects( *rect ) )
159  {
160  return intersection;
161  }
162 
163  intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
164  intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
165  intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
166  intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
167  return intersection;
168 }
169 
170 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
171 {
172  double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
173  double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
174  if ( x1 > x2 )
175  return false;
176  double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
177  double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
178  if ( y1 > y2 )
179  return false;
180  return true;
181 }
182 
183 bool QgsRectangle::contains( const QgsRectangle& rect ) const
184 {
185  return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
186 }
187 
188 bool QgsRectangle::contains( const QgsPoint &p ) const
189 {
190  return xmin <= p.x() && p.x() <= xmax &&
191  ymin <= p.y() && p.y() <= ymax;
192 }
193 
195 {
196 
197  xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
198  xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
199 
200  ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
201  ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
202 
203 }
204 
205 void QgsRectangle::combineExtentWith( double x, double y )
206 {
207 
208  xmin = (( xmin < x ) ? xmin : x );
209  xmax = (( xmax > x ) ? xmax : x );
210 
211  ymin = (( ymin < y ) ? ymin : y );
212  ymax = (( ymax > y ) ? ymax : y );
213 
214 }
215 
217 {
218  return xmax <= xmin || ymax <= ymin;
219 }
220 
222 {
223  // rectangle created QgsRectangle() or with rect.setMinimal() ?
224  return ( qgsDoubleNear( xmin, 0.0 ) && qgsDoubleNear( xmax, 0.0 ) && qgsDoubleNear( ymin, 0.0 ) && qgsDoubleNear( ymax, 0.0 ) ) ||
227 }
228 
230 {
231  QString rep =
232  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
234 
235  return rep;
236 }
237 
239 {
240  QString rep =
241  QString( "POLYGON((" ) +
242  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymin ) + ", " +
243  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymin ) + ", " +
244  qgsDoubleToString( xmax ) + ' ' + qgsDoubleToString( ymax ) + ", " +
245  qgsDoubleToString( xmin ) + ' ' + qgsDoubleToString( ymax ) + ", " +
247  QString( "))" );
248 
249  return rep;
250 }
251 
254 {
255  return QRectF( static_cast< qreal >( xmin ), static_cast< qreal >( ymin ), static_cast< qreal >( xmax - xmin ), static_cast< qreal >( ymax - ymin ) );
256 }
257 
258 // Return a string representation of the rectangle with automatic or high precision
259 QString QgsRectangle::toString( bool automaticPrecision ) const
260 {
261  if ( automaticPrecision )
262  {
263  int precision = 0;
264  if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
265  {
266  precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
267  // sanity check
268  if ( precision > 20 )
269  precision = 20;
270  }
271  return toString( precision );
272  }
273  else
274  return toString( 16 );
275 }
276 
277 // overloaded version of above fn to allow precision to be set
278 // Return a string representation of the rectangle with high precision
279 QString QgsRectangle::toString( int thePrecision ) const
280 {
281  QString rep;
282  if ( isEmpty() )
283  rep = "Empty";
284  else
285  rep = QString( "%1,%2 : %3,%4" )
286  .arg( xmin, 0, 'f', thePrecision )
287  .arg( ymin, 0, 'f', thePrecision )
288  .arg( xmax, 0, 'f', thePrecision )
289  .arg( ymax, 0, 'f', thePrecision );
290 
291  QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
292 
293  return rep;
294 }
295 
296 
297 // Return the rectangle as a set of polygon coordinates
299 {
300 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
301 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
302  QString rep;
303 
304  QTextStream foo( &rep );
305 
306  foo.setRealNumberPrecision( 8 );
307  foo.setRealNumberNotation( QTextStream::FixedNotation );
308  // NOTE: a polygon isn't a polygon unless its closed. In the case of
309  // a rectangle, that means 5 points (last == first)
310  foo
311  << xmin << ' ' << ymin << ", "
312  << xmin << ' ' << ymax << ", "
313  << xmax << ' ' << ymax << ", "
314  << xmax << ' ' << ymin << ", "
315  << xmin << ' ' << ymin;
316 
317  return rep;
318 
319 } // QgsRectangle::asPolygon() const
320 
321 
322 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
323 {
324  return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
325  qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
326  qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
327  qgsDoubleNear( r1.yMinimum(), yMinimum() );
328 }
329 
330 
331 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
332 {
333  return ( ! operator==( r1 ) );
334 }
335 
336 
338 {
339  if ( &r != this )
340  {
341  xmax = r.xMaximum();
342  xmin = r.xMinimum();
343  ymax = r.yMaximum();
344  ymin = r.yMinimum();
345  }
346 
347  return *this;
348 }
349 
350 
352 {
353  if ( r.xMinimum() < xMinimum() )
354  setXMinimum( r.xMinimum() );
355  if ( r.xMaximum() > xMaximum() )
356  setXMaximum( r.xMaximum() );
357  if ( r.yMinimum() < yMinimum() )
358  setYMinimum( r.yMinimum() );
359  if ( r.yMaximum() > yMaximum() )
360  setYMaximum( r.yMaximum() );
361 }
362 
364 {
365  if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
366  {
367  return false;
368  }
369  if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
370  {
371  return false;
372  }
373  return true;
374 }
375 
377 {
378  double tmp;
379  tmp = xmin;
380  xmin = ymin;
381  ymin = tmp;
382  tmp = xmax;
383  xmax = ymax;
384  ymax = tmp;
385 }
386 
387 QDataStream& operator<<( QDataStream& out, const QgsRectangle& rectangle )
388 {
389  out << rectangle.xMinimum() << rectangle.yMinimum() << rectangle.xMaximum() << rectangle.yMaximum();
390  return out;
391 }
392 
394 {
395  double xmin, ymin, xmax, ymax;
396  in >> xmin >> ymin >> xmax >> ymax;
397  rectangle.setXMinimum( xmin );
398  rectangle.setYMinimum( ymin );
399  rectangle.setXMaximum( xmax );
400  rectangle.setYMaximum( ymax );
401  return in;
402 }
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)
Definition: qgis.h:285
double x() const
Get the x value of the point.
Definition: qgspoint.h:128
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.
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
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)
Definition: qgis.h:274
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:65
bool operator!=(const QgsRectangle &r1) const
Comparison operator.
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:136
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.