QGIS API Documentation 4.3.0-Master (e0370aa57ef)
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#include <QString>
30
31using namespace Qt::StringLiterals;
32
33class QString;
34class QRectF;
35class QgsBox3D;
36
37
46class CORE_EXPORT QgsRectangle
47{
48 Q_GADGET
49
50 Q_PROPERTY( double xMinimum READ xMinimum WRITE setXMinimum )
51 Q_PROPERTY( double xMaximum READ xMaximum WRITE setXMaximum )
52 Q_PROPERTY( double yMinimum READ yMinimum WRITE setYMinimum )
53 Q_PROPERTY( double yMaximum READ yMaximum WRITE setYMaximum )
54 Q_PROPERTY( double width READ width )
55 Q_PROPERTY( double height READ height )
56 Q_PROPERTY( double area READ area )
57 Q_PROPERTY( double perimeter READ perimeter )
58 Q_PROPERTY( QgsPointXY center READ center )
59 Q_PROPERTY( bool isEmpty READ isEmpty )
60 Q_PROPERTY( bool isNull READ isNull )
61 Q_PROPERTY( bool isValid READ isValid )
62
63 public:
65 QgsRectangle() = default; // optimised constructor for null rectangle - no need to call normalize here
66
67 // clang-format off
77 explicit QgsRectangle( double xMin, double yMin = 0, double xMax = 0, double yMax = 0, bool normalize = true ) SIP_HOLDGIL
78 // clang-format on
79 : mXmin( xMin )
80 , mYmin( yMin )
81 , mXmax( xMax )
82 , mYmax( yMax )
83 {
84 if ( normalize )
86 }
87
94 QgsRectangle( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true ) SIP_HOLDGIL
95 {
96 set( p1, p2, normalize );
97 }
98
104 QgsRectangle( const QRectF &qRectF ) SIP_HOLDGIL
105 {
106 mXmin = qRectF.topLeft().x();
107 mYmin = qRectF.topLeft().y();
108 mXmax = qRectF.bottomRight().x();
109 mYmax = qRectF.bottomRight().y();
110 }
111
113 {
114 mXmin = other.xMinimum();
115 mYmin = other.yMinimum();
116 mXmax = other.xMaximum();
117 mYmax = other.yMaximum();
118 }
119
120 // IMPORTANT - while QgsRectangle is inherited by QgsReferencedRectangle, we do NOT want a virtual destructor here
121 // because this class MUST be lightweight and we don't want the cost of the vtable here.
122 // see https://github.com/qgis/QGIS/pull/4720#issuecomment-308652392
123 ~QgsRectangle() = default;
124
129 static QgsRectangle fromWkt( const QString &wkt );
130
135 static QgsRectangle fromCenterAndSize( const QgsPointXY &center, double width, double height );
136
147 static QgsRectangle fromEdges( double left, double top, double right, double bottom );
148
155 void set( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true )
156 {
157 mXmin = p1.x();
158 mXmax = p2.x();
159 mYmin = p1.y();
160 mYmax = p2.y();
161 if ( normalize )
163 }
164
171 void set( double xMin, double yMin, double xMax, double yMax, bool normalize = true )
172 {
173 mXmin = xMin;
174 mYmin = yMin;
175 mXmax = xMax;
176 mYmax = yMax;
177 if ( normalize )
179 }
180
184 void setXMinimum( double x ) SIP_HOLDGIL { mXmin = x; }
185
189 void setXMaximum( double x ) SIP_HOLDGIL { mXmax = x; }
190
194 void setYMinimum( double y ) SIP_HOLDGIL { mYmin = y; }
195
199 void setYMaximum( double y ) SIP_HOLDGIL { mYmax = y; }
200
212 {
213 mXmin = mYmin = std::numeric_limits<double>::max();
214 mXmax = mYmax = -std::numeric_limits<double>::max();
215 }
216
223 Q_DECL_DEPRECATED void setMinimal() SIP_DEPRECATED
224 {
225 setNull();
226 }
227
238 double xMaximum() const SIP_HOLDGIL { return mXmax; }
239
250 double xMinimum() const SIP_HOLDGIL { return mXmin; }
251
260 double yMaximum() const SIP_HOLDGIL { return mYmax; }
261
270 double yMinimum() const SIP_HOLDGIL { return mYmin; }
271
282 double left() const SIP_HOLDGIL { return mXmin; }
283
294 double right() const SIP_HOLDGIL { return mXmax; }
295
305 double top() const SIP_HOLDGIL { return mYmax; }
306
316 double bottom() const SIP_HOLDGIL { return mYmin; }
317
322 {
323 if ( isNull() )
324 return;
325
326 if ( mXmin > mXmax )
327 {
328 std::swap( mXmin, mXmax );
329 }
330 if ( mYmin > mYmax )
331 {
332 std::swap( mYmin, mYmax );
333 }
334 }
335
341 double width() const SIP_HOLDGIL { return mXmax - mXmin; }
342
348 double height() const SIP_HOLDGIL { return mYmax - mYmin; }
349
356 double area() const SIP_HOLDGIL { return ( mXmax - mXmin ) * ( mYmax - mYmin ); }
357
362 double perimeter() const SIP_HOLDGIL { return 2 * ( mXmax - mXmin ) + 2 * ( mYmax - mYmin ); }
363
367 QgsPointXY center() const SIP_HOLDGIL { return QgsPointXY( mXmax * 0.5 + mXmin * 0.5, mYmin * 0.5 + mYmax * 0.5 ); }
368
372 void scale( double scaleFactor, const QgsPointXY *c = nullptr )
373 {
374 // scale from the center
375 double centerX, centerY;
376 if ( c )
377 {
378 centerX = c->x();
379 centerY = c->y();
380 }
381 else
382 {
383 centerX = mXmin + width() / 2;
384 centerY = mYmin + height() / 2;
385 }
386 scale( scaleFactor, centerX, centerY );
387 }
388
392 void scale( double scaleFactor, double centerX, double centerY )
393 {
394 const double newWidth = width() * scaleFactor;
395 const double newHeight = height() * scaleFactor;
396 mXmin = centerX - newWidth / 2.0;
397 mXmax = centerX + newWidth / 2.0;
398 mYmin = centerY - newHeight / 2.0;
399 mYmax = centerY + newHeight / 2.0;
400 }
401
406 QgsRectangle scaled( double scaleFactor, const QgsPointXY *center = nullptr ) const;
407
412 void grow( double delta )
413 {
414 if ( isNull() )
415 return;
416 mXmin -= delta;
417 mXmax += delta;
418 mYmin -= delta;
419 mYmax += delta;
420 }
421
425 void include( const QgsPointXY &p )
426 {
427 if ( isNull() )
428 {
429 setXMinimum( p.x() );
430 setXMaximum( p.x() );
431 setYMinimum( p.y() );
432 setYMaximum( p.y() );
433 return;
434 }
435 if ( p.x() < xMinimum() )
436 setXMinimum( p.x() );
437 if ( p.x() > xMaximum() )
438 setXMaximum( p.x() );
439 if ( p.y() < yMinimum() )
440 setYMinimum( p.y() );
441 if ( p.y() > yMaximum() )
442 setYMaximum( p.y() );
443 }
444
451 {
452 if ( isNull() )
453 return QgsRectangle();
454 return QgsRectangle( mXmin - width, mYmin - width, mXmax + width, mYmax + width );
455 }
456
461 {
462 QgsRectangle intersection = QgsRectangle();
463 if ( intersects( rect ) )
464 {
465 intersection.setXMinimum( mXmin > rect.xMinimum() ? mXmin : rect.xMinimum() );
466 intersection.setXMaximum( mXmax < rect.xMaximum() ? mXmax : rect.xMaximum() );
467 intersection.setYMinimum( mYmin > rect.yMinimum() ? mYmin : rect.yMinimum() );
468 intersection.setYMaximum( mYmax < rect.yMaximum() ? mYmax : rect.yMaximum() );
469 }
470 return intersection;
471 }
472
476 bool intersects( const QgsRectangle &rect ) const SIP_HOLDGIL
477 {
478 if ( isNull() || rect.isNull() )
479 {
480 return false;
481 }
482
483 const double x1 = ( mXmin > rect.mXmin ? mXmin : rect.mXmin );
484 const double x2 = ( mXmax < rect.mXmax ? mXmax : rect.mXmax );
485 if ( x1 > x2 )
486 return false;
487 const double y1 = ( mYmin > rect.mYmin ? mYmin : rect.mYmin );
488 const double y2 = ( mYmax < rect.mYmax ? mYmax : rect.mYmax );
489 return y1 <= y2;
490 }
491
495 bool contains( const QgsRectangle &rect ) const SIP_HOLDGIL
496 {
497 // simple case, both rectangles are normalized
498 if ( isNormalized() && rect.isNormalized() )
499 {
500 return qgsDoubleGreaterThanOrNear( rect.mXmin, mXmin ) && qgsDoubleLessThanOrNear( rect.mXmax, mXmax )
501 && qgsDoubleGreaterThanOrNear( rect.mYmin, mYmin ) && qgsDoubleLessThanOrNear( rect.mYmax, mYmax );
502 }
503 else
504 {
505 return containsRange(mXmin, mXmax, rect.mXmin, rect.mXmax) && containsRange(mYmin, mYmax, rect.mYmin, rect.mYmax);
506 }
507 }
508
512 bool contains( const QgsPointXY &p ) const SIP_HOLDGIL
513 {
514 return mXmin <= p.x() && p.x() <= mXmax &&
515 mYmin <= p.y() && p.y() <= mYmax;
516 }
517
523 bool contains( double x, double y ) const SIP_HOLDGIL
524 {
525 return mXmin <= x && x <= mXmax &&
526 mYmin <= y && y <= mYmax;
527 }
528
532 void combineExtentWith( const QgsRectangle &rect )
533 {
534 if ( isNull() )
535 *this = rect;
536 else if ( !rect.isNull() )
537 {
538 mXmin = std::min( mXmin, rect.xMinimum() );
539 mXmax = std::max( mXmax, rect.xMaximum() );
540 mYmin = std::min( mYmin, rect.yMinimum() );
541 mYmax = std::max( mYmax, rect.yMaximum() );
542 }
543 }
544
548 void combineExtentWith( double x, double y )
549 {
550 if ( isNull() )
551 *this = QgsRectangle( x, y, x, y );
552 else
553 {
554 mXmin = ( ( mXmin < x ) ? mXmin : x );
555 mXmax = ( ( mXmax > x ) ? mXmax : x );
556
557 mYmin = ( ( mYmin < y ) ? mYmin : y );
558 mYmax = ( ( mYmax > y ) ? mYmax : y );
559 }
560 }
561
566 void combineExtentWith( const QgsPointXY &point )
567 {
568 combineExtentWith( point.x(), point.y() );
569 }
570
575 double distance( const QgsPointXY &point ) const
576 {
577 const double dx = std::max( std::max( mXmin - point.x(), 0.0 ), point.x() - mXmax );
578 const double dy = std::max( std::max( mYmin - point.y(), 0.0 ), point.y() - mYmax );
579 return std::sqrt( dx * dx + dy * dy );
580 }
581
586
591
595 QgsRectangle &operator-=( QgsVector v );
596
600 QgsRectangle &operator+=( QgsVector v );
601
616 bool isEmpty() const
617 {
618 return isNull() || qgsDoubleNear( mXmax, mXmin ) || qgsDoubleNear( mYmax, mYmin );
619 }
620
630 bool isPoint() const
631 {
632 return qgsDoubleNear( mXmax, mXmin ) && qgsDoubleNear( mYmax, mYmin ) && !isNull();
633 }
634
642 bool isNormalized() const
643 {
644 return qgsDoubleLessThanOrNear( mXmin, mXmax ) && qgsDoubleLessThanOrNear( mYmin, mYmax );
645 }
646
657 bool isNull() const
658 {
659 // rectangle created QgsRectangle() or with rect.setNull() or
660 // otherwise having NaN ordinates
661 return ( std::isnan( mXmin ) && std::isnan( mXmax ) && std::isnan( mYmin ) && std::isnan( mYmax ) ) ||
662 ( qgsDoubleNear( mXmin, std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmin, std::numeric_limits<double>::max() ) &&
663 qgsDoubleNear( mXmax, -std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmax, -std::numeric_limits<double>::max() ) );
664 }
665
675 bool isValid() const
676 {
677 if ( ( !isFinite() ) || ( mXmax <= mXmin ) || ( mYmax <= mYmin ) )
678 {
679 return false;
680 }
681 return true;
682 }
683
696 bool isMaximal() const
697 {
698 return ( std::isinf( mXmin ) || mXmin == std::numeric_limits<double>::lowest() )
699 && ( std::isinf( mYmin ) || mYmin == std::numeric_limits<double>::lowest() )
700 && ( std::isinf( mXmax ) || mXmax == std::numeric_limits<double>::max() )
701 && ( std::isinf( mYmax ) || mYmax == std::numeric_limits<double>::max() );
702 }
703
707 Q_INVOKABLE QString asWktCoordinates() const;
708
712 Q_INVOKABLE QString asWktPolygon() const;
713
717 QRectF toRectF() const
718 {
719 return QRectF( static_cast< qreal >( mXmin ), static_cast< qreal >( mYmin ), static_cast< qreal >( mXmax - mXmin ), static_cast< qreal >( mYmax - mYmin ) );
720 }
721
727 Q_INVOKABLE QString toString( int precision = 16 ) const;
728
732 QString asPolygon() const;
733
734 bool operator==( const QgsRectangle &r1 ) const
735 {
736 if ( isNull() ) return r1.isNull();
737
738 return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
739 qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
740 qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
742 }
743
744 bool operator!=( const QgsRectangle &r1 ) const
745 {
746 return ( ! operator==( r1 ) );
747 }
748
750 {
751 if ( &r1 != this )
752 {
753 mXmax = r1.xMaximum();
754 mXmin = r1.xMinimum();
755 mYmax = r1.yMaximum();
756 mYmin = r1.yMinimum();
757 }
758
759 return *this;
760 }
761
770 bool isFinite() const
771 {
772 if ( std::isinf( mXmin ) || std::isinf( mYmin ) || std::isinf( mXmax ) || std::isinf( mYmax ) )
773 {
774 return false;
775 }
776 if ( std::isnan( mXmin ) || std::isnan( mYmin ) || std::isnan( mXmax ) || std::isnan( mYmax ) )
777 {
778 return false;
779 }
780 return true;
781 }
782
786 void invert()
787 {
788 std::swap( mXmin, mYmin );
789 std::swap( mXmax, mYmax );
790 }
791
796 QgsBox3D toBox3d( double zMin, double zMax ) const;
797
814 std::pair< QgsRectangle, QgsRectangle > splitAtAntimeridian() const;
815
817 operator QVariant() const
818 {
819 return QVariant::fromValue( *this );
820 }
821
828 QgsRectangle snappedToGrid( double spacing ) const;
829
830#ifdef SIP_RUN
831// clang-format off
832 SIP_PYOBJECT __repr__();
833 % MethodCode
834 QString str;
835 if ( sipCpp->isNull() )
836 str = u"<QgsRectangle()>"_s;
837 else
838 str = u"<QgsRectangle: %1>"_s.arg( sipCpp->asWktCoordinates() );
839 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
840 % End
841// clang-format on
842#endif
843
844 private:
845
846 double mXmin = std::numeric_limits<double>::max();
847 double mYmin = std::numeric_limits<double>::max();
848 double mXmax = -std::numeric_limits<double>::max();
849 double mYmax = -std::numeric_limits<double>::max();
850
855 static bool containsRange(double aMin, double aMax, double bMin, double bMax)
856 {
857 const bool aNormalized = (aMax >= aMin);
858 const bool bNormalized = (bMax >= bMin);
859
860 if (aNormalized && bNormalized)
861 {
862 // both ranges normal, nice and easy
863 return qgsDoubleGreaterThanOrNear( bMin, aMin ) && qgsDoubleLessThanOrNear( bMax, aMax );
864 }
865 else if (!aNormalized && bNormalized)
866 {
867 return qgsDoubleGreaterThanOrNear( bMin, aMin ) || qgsDoubleLessThanOrNear( bMax, aMax );
868 }
869 else if ( aNormalized && !bNormalized )
870 {
871 // a cannot possibly contain b
872 return false;
873 }
874 else {
875 // both non-normalized
876 return qgsDoubleLessThanOrNear( aMin, bMin ) && qgsDoubleGreaterThanOrNear( aMax, bMax );
877 }
878 }
879
880};
881
883
884#ifndef SIP_RUN
885
889CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsRectangle &rectangle );
890
894CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsRectangle &rectangle );
895
896inline std::ostream &operator << ( std::ostream &os, const QgsRectangle &r )
897{
898 return os << r.toString().toLocal8Bit().data();
899}
900
901#endif
902
903#endif // QGSRECTANGLE_H
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:45
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
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 rounded to the spec...
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.
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.
bool operator!=(const QgsRectangle &r1) const
void setXMinimum(double x)
Set the minimum x value.
static QgsRectangle fromEdges(double left, double top, double right, double bottom)
Creates a rectangle from the left, top, right and bottom edges.
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.
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.
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.
double left() const
Returns the left side of the rectangle.
void normalize()
Normalize the rectangle so it has non-negative width/height.
double right() const
Returns the right side of the rectangle.
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.
bool isNormalized() const
Returns true if the rectangle is normalized.
double height() const
Returns the height of the rectangle.
QgsPointXY center
void setNull()
Mark a rectangle as being null (holding no spatial information).
bool isPoint() const
Returns true if the rectangle represents a point.
double bottom() const
Returns the bottom side of the rectangle.
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.
double top() const
Returns the top side of the rectangle.
Represent a 2-dimensional vector.
Definition qgsvector.h:34
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:7795
bool qgsDoubleGreaterThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is greater than the other or very near to the other.
Definition qgis.h:7835
bool qgsDoubleLessThanOrNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles to see if one is less than the other or very near to the other.
Definition qgis.h:7808
#define SIP_DEPRECATED
Definition qgis_sip.h:113
#define SIP_HOLDGIL
Definition qgis_sip.h:183
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.