QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
qgsrectangle.h
Go to the documentation of this file.
1/***************************************************************************
2 qgsrectangle.h - 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#ifndef QGSRECTANGLE_H
19#define QGSRECTANGLE_H
20
21#include <iosfwd>
22
23#include "qgis.h"
24#include "qgis_core.h"
25#include "qgspointxy.h"
26
27#include <QDomDocument>
28#include <QRectF>
29
30class QString;
31class QRectF;
32class QgsBox3D;
33
34
43class CORE_EXPORT QgsRectangle
44{
45 Q_GADGET
46
47 Q_PROPERTY( double xMinimum READ xMinimum WRITE setXMinimum )
48 Q_PROPERTY( double xMaximum READ xMaximum WRITE setXMaximum )
49 Q_PROPERTY( double yMinimum READ yMinimum WRITE setYMinimum )
50 Q_PROPERTY( double yMaximum READ yMaximum WRITE setYMaximum )
51 Q_PROPERTY( double width READ width )
52 Q_PROPERTY( double height READ height )
53 Q_PROPERTY( double area READ area )
54 Q_PROPERTY( double perimeter READ perimeter )
55 Q_PROPERTY( QgsPointXY center READ center )
56 Q_PROPERTY( bool isEmpty READ isEmpty )
57 Q_PROPERTY( bool isNull READ isNull )
58 Q_PROPERTY( bool isValid READ isValid )
59
60 public:
61
63 QgsRectangle() = default; // optimised constructor for null rectangle - no need to call normalize here
64
71 explicit QgsRectangle( double xMin, double yMin = 0, double xMax = 0, double yMax = 0, bool normalize = true ) SIP_HOLDGIL
72 : mXmin( xMin )
73 , mYmin( yMin )
74 , mXmax( xMax )
75 , mYmax( yMax )
76 {
77 if ( normalize )
79 }
80
87 QgsRectangle( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true ) SIP_HOLDGIL
88 {
89 set( p1, p2, normalize );
90 }
91
97 QgsRectangle( const QRectF &qRectF ) SIP_HOLDGIL
98 {
99 mXmin = qRectF.topLeft().x();
100 mYmin = qRectF.topLeft().y();
101 mXmax = qRectF.bottomRight().x();
102 mYmax = qRectF.bottomRight().y();
103 }
104
106 {
107 mXmin = other.xMinimum();
108 mYmin = other.yMinimum();
109 mXmax = other.xMaximum();
110 mYmax = other.yMaximum();
111 }
112
113 // IMPORTANT - while QgsRectangle is inherited by QgsReferencedRectangle, we do NOT want a virtual destructor here
114 // because this class MUST be lightweight and we don't want the cost of the vtable here.
115 // see https://github.com/qgis/QGIS/pull/4720#issuecomment-308652392
116 ~QgsRectangle() = default;
117
122 static QgsRectangle fromWkt( const QString &wkt );
123
128 static QgsRectangle fromCenterAndSize( const QgsPointXY &center, double width, double height );
129
136 void set( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true )
137 {
138 mXmin = p1.x();
139 mXmax = p2.x();
140 mYmin = p1.y();
141 mYmax = p2.y();
142 if ( normalize )
144 }
145
152 void set( double xMin, double yMin, double xMax, double yMax, bool normalize = true )
153 {
154 mXmin = xMin;
155 mYmin = yMin;
156 mXmax = xMax;
157 mYmax = yMax;
158 if ( normalize )
160 }
161
165 void setXMinimum( double x ) SIP_HOLDGIL { mXmin = x; }
166
170 void setXMaximum( double x ) SIP_HOLDGIL { mXmax = x; }
171
175 void setYMinimum( double y ) SIP_HOLDGIL { mYmin = y; }
176
180 void setYMaximum( double y ) SIP_HOLDGIL { mYmax = y; }
181
193 {
194 mXmin = mYmin = std::numeric_limits<double>::max();
195 mXmax = mYmax = -std::numeric_limits<double>::max();
196 }
197
204 Q_DECL_DEPRECATED void setMinimal() SIP_DEPRECATED
205 {
206 setNull();
207 }
208
212 double xMaximum() const SIP_HOLDGIL { return mXmax; }
213
217 double xMinimum() const SIP_HOLDGIL { return mXmin; }
218
222 double yMaximum() const SIP_HOLDGIL { return mYmax; }
223
227 double yMinimum() const SIP_HOLDGIL { return mYmin; }
228
233 {
234 if ( isNull() )
235 return;
236
237 if ( mXmin > mXmax )
238 {
239 std::swap( mXmin, mXmax );
240 }
241 if ( mYmin > mYmax )
242 {
243 std::swap( mYmin, mYmax );
244 }
245 }
246
252 double width() const SIP_HOLDGIL { return mXmax - mXmin; }
253
259 double height() const SIP_HOLDGIL { return mYmax - mYmin; }
260
267 double area() const SIP_HOLDGIL { return ( mXmax - mXmin ) * ( mYmax - mYmin ); }
268
273 double perimeter() const SIP_HOLDGIL { return 2 * ( mXmax - mXmin ) + 2 * ( mYmax - mYmin ); }
274
278 QgsPointXY center() const SIP_HOLDGIL { return QgsPointXY( mXmax * 0.5 + mXmin * 0.5, mYmin * 0.5 + mYmax * 0.5 ); }
279
283 void scale( double scaleFactor, const QgsPointXY *c = nullptr )
284 {
285 // scale from the center
286 double centerX, centerY;
287 if ( c )
288 {
289 centerX = c->x();
290 centerY = c->y();
291 }
292 else
293 {
294 centerX = mXmin + width() / 2;
295 centerY = mYmin + height() / 2;
296 }
297 scale( scaleFactor, centerX, centerY );
298 }
299
303 void scale( double scaleFactor, double centerX, double centerY )
304 {
305 const double newWidth = width() * scaleFactor;
306 const double newHeight = height() * scaleFactor;
307 mXmin = centerX - newWidth / 2.0;
308 mXmax = centerX + newWidth / 2.0;
309 mYmin = centerY - newHeight / 2.0;
310 mYmax = centerY + newHeight / 2.0;
311 }
312
317 QgsRectangle scaled( double scaleFactor, const QgsPointXY *center = nullptr ) const;
318
323 void grow( double delta )
324 {
325 if ( isNull() )
326 return;
327 mXmin -= delta;
328 mXmax += delta;
329 mYmin -= delta;
330 mYmax += delta;
331 }
332
336 void include( const QgsPointXY &p )
337 {
338 if ( isNull() )
339 {
340 setXMinimum( p.x() );
341 setXMaximum( p.x() );
342 setYMinimum( p.y() );
343 setYMaximum( p.y() );
344 return;
345 }
346 if ( p.x() < xMinimum() )
347 setXMinimum( p.x() );
348 if ( p.x() > xMaximum() )
349 setXMaximum( p.x() );
350 if ( p.y() < yMinimum() )
351 setYMinimum( p.y() );
352 if ( p.y() > yMaximum() )
353 setYMaximum( p.y() );
354 }
355
362 {
363 if ( isNull() )
364 return QgsRectangle();
365 return QgsRectangle( mXmin - width, mYmin - width, mXmax + width, mYmax + width );
366 }
367
372 {
373 QgsRectangle intersection = QgsRectangle();
374 if ( intersects( rect ) )
375 {
376 intersection.setXMinimum( mXmin > rect.xMinimum() ? mXmin : rect.xMinimum() );
377 intersection.setXMaximum( mXmax < rect.xMaximum() ? mXmax : rect.xMaximum() );
378 intersection.setYMinimum( mYmin > rect.yMinimum() ? mYmin : rect.yMinimum() );
379 intersection.setYMaximum( mYmax < rect.yMaximum() ? mYmax : rect.yMaximum() );
380 }
381 return intersection;
382 }
383
387 bool intersects( const QgsRectangle &rect ) const SIP_HOLDGIL
388 {
389 if ( isNull() || rect.isNull() )
390 {
391 return false;
392 }
393
394 const double x1 = ( mXmin > rect.mXmin ? mXmin : rect.mXmin );
395 const double x2 = ( mXmax < rect.mXmax ? mXmax : rect.mXmax );
396 if ( x1 > x2 )
397 return false;
398 const double y1 = ( mYmin > rect.mYmin ? mYmin : rect.mYmin );
399 const double y2 = ( mYmax < rect.mYmax ? mYmax : rect.mYmax );
400 return y1 <= y2;
401 }
402
406 bool contains( const QgsRectangle &rect ) const SIP_HOLDGIL
407 {
408 return ( rect.mXmin >= mXmin && rect.mXmax <= mXmax && rect.mYmin >= mYmin && rect.mYmax <= mYmax );
409 }
410
414 bool contains( const QgsPointXY &p ) const SIP_HOLDGIL
415 {
416 return mXmin <= p.x() && p.x() <= mXmax &&
417 mYmin <= p.y() && p.y() <= mYmax;
418 }
419
425 bool contains( double x, double y ) const SIP_HOLDGIL
426 {
427 return mXmin <= x && x <= mXmax &&
428 mYmin <= y && y <= mYmax;
429 }
430
434 void combineExtentWith( const QgsRectangle &rect )
435 {
436 if ( isNull() )
437 *this = rect;
438 else if ( !rect.isNull() )
439 {
440 mXmin = std::min( mXmin, rect.xMinimum() );
441 mXmax = std::max( mXmax, rect.xMaximum() );
442 mYmin = std::min( mYmin, rect.yMinimum() );
443 mYmax = std::max( mYmax, rect.yMaximum() );
444 }
445 }
446
450 void combineExtentWith( double x, double y )
451 {
452 if ( isNull() )
453 *this = QgsRectangle( x, y, x, y );
454 else
455 {
456 mXmin = ( ( mXmin < x ) ? mXmin : x );
457 mXmax = ( ( mXmax > x ) ? mXmax : x );
458
459 mYmin = ( ( mYmin < y ) ? mYmin : y );
460 mYmax = ( ( mYmax > y ) ? mYmax : y );
461 }
462 }
463
468 void combineExtentWith( const QgsPointXY &point )
469 {
470 combineExtentWith( point.x(), point.y() );
471 }
472
477 double distance( const QgsPointXY &point ) const
478 {
479 const double dx = std::max( std::max( mXmin - point.x(), 0.0 ), point.x() - mXmax );
480 const double dy = std::max( std::max( mYmin - point.y(), 0.0 ), point.y() - mYmax );
481 return std::sqrt( dx * dx + dy * dy );
482 }
483
488
493
497 QgsRectangle &operator-=( QgsVector v );
498
502 QgsRectangle &operator+=( QgsVector v );
503
513 bool isEmpty() const
514 {
515 return isNull() || mXmax <= mXmin || mYmax <= mYmin || qgsDoubleNear( mXmax, mXmin ) || qgsDoubleNear( mYmax, mYmin );
516 }
517
528 bool isNull() const
529 {
530 // rectangle created QgsRectangle() or with rect.setNull() or
531 // otherwise having NaN ordinates
532 return ( std::isnan( mXmin ) && std::isnan( mXmax ) && std::isnan( mYmin ) && std::isnan( mYmax ) ) ||
533 ( qgsDoubleNear( mXmin, std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmin, std::numeric_limits<double>::max() ) &&
534 qgsDoubleNear( mXmax, -std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmax, -std::numeric_limits<double>::max() ) );
535 }
536
546 bool isValid() const
547 {
548 if ( ( !isFinite() ) || ( mXmax <= mXmin ) || ( mYmax <= mYmin ) )
549 {
550 return false;
551 }
552 return true;
553 }
554
567 bool isMaximal() const
568 {
569 return ( std::isinf( mXmin ) || mXmin == std::numeric_limits<double>::lowest() )
570 && ( std::isinf( mYmin ) || mYmin == std::numeric_limits<double>::lowest() )
571 && ( std::isinf( mXmax ) || mXmax == std::numeric_limits<double>::max() )
572 && ( std::isinf( mYmax ) || mYmax == std::numeric_limits<double>::max() );
573 }
574
578 Q_INVOKABLE QString asWktCoordinates() const;
579
583 Q_INVOKABLE QString asWktPolygon() const;
584
588 QRectF toRectF() const
589 {
590 return QRectF( static_cast< qreal >( mXmin ), static_cast< qreal >( mYmin ), static_cast< qreal >( mXmax - mXmin ), static_cast< qreal >( mYmax - mYmin ) );
591 }
592
598 Q_INVOKABLE QString toString( int precision = 16 ) const;
599
603 QString asPolygon() const;
604
605 bool operator==( const QgsRectangle &r1 ) const
606 {
607 if ( isNull() ) return r1.isNull();
608
609 return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
610 qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
611 qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
613 }
614
615 bool operator!=( const QgsRectangle &r1 ) const
616 {
617 return ( ! operator==( r1 ) );
618 }
619
621 {
622 if ( &r1 != this )
623 {
624 mXmax = r1.xMaximum();
625 mXmin = r1.xMinimum();
626 mYmax = r1.yMaximum();
627 mYmin = r1.yMinimum();
628 }
629
630 return *this;
631 }
632
641 bool isFinite() const
642 {
643 if ( std::isinf( mXmin ) || std::isinf( mYmin ) || std::isinf( mXmax ) || std::isinf( mYmax ) )
644 {
645 return false;
646 }
647 if ( std::isnan( mXmin ) || std::isnan( mYmin ) || std::isnan( mXmax ) || std::isnan( mYmax ) )
648 {
649 return false;
650 }
651 return true;
652 }
653
657 void invert()
658 {
659 std::swap( mXmin, mYmin );
660 std::swap( mXmax, mYmax );
661 }
662
667 QgsBox3D toBox3d( double zMin, double zMax ) const;
668
670 operator QVariant() const
671 {
672 return QVariant::fromValue( *this );
673 }
674
681 QgsRectangle snappedToGrid( double spacing ) const;
682
683#ifdef SIP_RUN
684 SIP_PYOBJECT __repr__();
685 % MethodCode
686 QString str;
687 if ( sipCpp->isNull() )
688 str = QStringLiteral( "<QgsRectangle()>" );
689 else
690 str = QStringLiteral( "<QgsRectangle: %1>" ).arg( sipCpp->asWktCoordinates() );
691 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
692 % End
693#endif
694
695 private:
696
697 double mXmin = std::numeric_limits<double>::max();
698 double mYmin = std::numeric_limits<double>::max();
699 double mXmax = -std::numeric_limits<double>::max();
700 double mYmax = -std::numeric_limits<double>::max();
701
702};
703
705
706#ifndef SIP_RUN
707
711CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsRectangle &rectangle );
712
716CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsRectangle &rectangle );
717
718inline std::ostream &operator << ( std::ostream &os, const QgsRectangle &r )
719{
720 return os << r.toString().toLocal8Bit().data();
721}
722
723#endif
724
725#endif // QGSRECTANGLE_H
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:42
Represents a 2D point.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
A rectangle specified with double values.
Q_INVOKABLE QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
void scale(double scaleFactor, const QgsPointXY *c=nullptr)
Scale the rectangle around its center point.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
double xMinimum
Q_DECL_DEPRECATED void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void combineExtentWith(const QgsPointXY &point)
Expands the rectangle so that it covers both the original rectangle and the given point.
QgsRectangle()=default
Constructor for a null rectangle.
double area() const
Returns the area of the rectangle.
void include(const QgsPointXY &p)
Updates the rectangle to include the specified point.
bool isMaximal() const
Test if the rectangle is the maximal possible rectangle.
double yMinimum
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double xMaximum
void combineExtentWith(double x, double y)
Expands the rectangle so that it covers both the original rectangle and the given point.
QgsRectangle(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Construct a rectangle from two points.
bool contains(double x, double y) const
Returns true when rectangle contains the point at (x, y).
static QgsRectangle fromWkt(const QString &wkt)
Creates a new rectangle from a wkt string.
void setYMinimum(double y)
Set the minimum y value.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
bool operator!=(const QgsRectangle &r1) const
void setXMinimum(double x)
Set the minimum x value.
double width() const
Returns the width of the rectangle.
QRectF toRectF() const
Returns a QRectF with same coordinates as the rectangle.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
bool isNull() const
Test if the rectangle is null (holding no spatial information).
QgsRectangle(const QgsRectangle &other)
double yMaximum() const
Returns the y maximum value (top side of rectangle).
QgsRectangle & operator=(const QgsRectangle &r1)
void set(const QgsPointXY &p1, const QgsPointXY &p2, bool normalize=true)
Sets the rectangle from two QgsPoints.
void setYMaximum(double y)
Set the maximum y value.
QgsPointXY center() const
Returns the center point of the rectangle.
void setXMaximum(double x)
Set the maximum x value.
void grow(double delta)
Grows the rectangle in place by the specified amount.
bool operator==(const QgsRectangle &r1) const
~QgsRectangle()=default
bool isValid() const
Test if the rectangle is valid.
double perimeter
double yMaximum
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle.
double perimeter() const
Returns the perimeter of the rectangle.
void set(double xMin, double yMin, double xMax, double yMax, bool normalize=true)
Sets the rectangle from four points.
void normalize()
Normalize the rectangle so it has non-negative width/height.
bool isEmpty() const
Returns true if the rectangle has no area.
QgsRectangle(const QRectF &qRectF)
Construct a rectangle from a QRectF.
static QgsRectangle fromCenterAndSize(const QgsPointXY &center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
double height() const
Returns the height of the rectangle.
QgsPointXY center
void setNull()
Mark a rectangle as being null (holding no spatial information).
bool contains(const QgsPointXY &p) const
Returns true when rectangle contains a point.
QgsRectangle buffered(double width) const
Gets rectangle enlarged by buffer.
void scale(double scaleFactor, double centerX, double centerY)
Scale the rectangle around its center point.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
void invert()
Swap x/y coordinates in the rectangle.
bool isFinite() const
Returns true if the rectangle has finite boundaries.
double distance(const QgsPointXY &point) const
Returns the distance from point to the nearest point on the boundary of the rectangle.
Represent a 2-dimensional vector.
Definition qgsvector.h:31
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
#define SIP_DEPRECATED
Definition qgis_sip.h:114
#define SIP_HOLDGIL
Definition qgis_sip.h:179
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
QgsInterval operator-(QDate date1, QDate date2)
Returns the interval between two dates.
QDateTime operator+(const QDateTime &start, const QgsInterval &interval)
Adds an interval to a datetime.
CORE_EXPORT QDataStream & operator<<(QDataStream &out, const QgsRectangle &rectangle)
Writes the list rectangle to stream out.
CORE_EXPORT QDataStream & operator>>(QDataStream &in, QgsRectangle &rectangle)
Reads a rectangle from stream in into rectangle.