QGIS API Documentation 3.99.0-Master (d270888f95f)
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:
64
66 QgsRectangle() = default; // optimised constructor for null rectangle - no need to call normalize here
67
74 explicit QgsRectangle( double xMin, double yMin = 0, double xMax = 0, double yMax = 0, bool normalize = true ) SIP_HOLDGIL
75 : mXmin( xMin )
76 , mYmin( yMin )
77 , mXmax( xMax )
78 , mYmax( yMax )
79 {
80 if ( normalize )
82 }
83
90 QgsRectangle( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true ) SIP_HOLDGIL
91 {
92 set( p1, p2, normalize );
93 }
94
100 QgsRectangle( const QRectF &qRectF ) SIP_HOLDGIL
101 {
102 mXmin = qRectF.topLeft().x();
103 mYmin = qRectF.topLeft().y();
104 mXmax = qRectF.bottomRight().x();
105 mYmax = qRectF.bottomRight().y();
106 }
107
109 {
110 mXmin = other.xMinimum();
111 mYmin = other.yMinimum();
112 mXmax = other.xMaximum();
113 mYmax = other.yMaximum();
114 }
115
116 // IMPORTANT - while QgsRectangle is inherited by QgsReferencedRectangle, we do NOT want a virtual destructor here
117 // because this class MUST be lightweight and we don't want the cost of the vtable here.
118 // see https://github.com/qgis/QGIS/pull/4720#issuecomment-308652392
119 ~QgsRectangle() = default;
120
125 static QgsRectangle fromWkt( const QString &wkt );
126
131 static QgsRectangle fromCenterAndSize( const QgsPointXY &center, double width, double height );
132
139 void set( const QgsPointXY &p1, const QgsPointXY &p2, bool normalize = true )
140 {
141 mXmin = p1.x();
142 mXmax = p2.x();
143 mYmin = p1.y();
144 mYmax = p2.y();
145 if ( normalize )
147 }
148
155 void set( double xMin, double yMin, double xMax, double yMax, bool normalize = true )
156 {
157 mXmin = xMin;
158 mYmin = yMin;
159 mXmax = xMax;
160 mYmax = yMax;
161 if ( normalize )
163 }
164
168 void setXMinimum( double x ) SIP_HOLDGIL { mXmin = x; }
169
173 void setXMaximum( double x ) SIP_HOLDGIL { mXmax = x; }
174
178 void setYMinimum( double y ) SIP_HOLDGIL { mYmin = y; }
179
183 void setYMaximum( double y ) SIP_HOLDGIL { mYmax = y; }
184
196 {
197 mXmin = mYmin = std::numeric_limits<double>::max();
198 mXmax = mYmax = -std::numeric_limits<double>::max();
199 }
200
207 Q_DECL_DEPRECATED void setMinimal() SIP_DEPRECATED
208 {
209 setNull();
210 }
211
215 double xMaximum() const SIP_HOLDGIL { return mXmax; }
216
220 double xMinimum() const SIP_HOLDGIL { return mXmin; }
221
225 double yMaximum() const SIP_HOLDGIL { return mYmax; }
226
230 double yMinimum() const SIP_HOLDGIL { return mYmin; }
231
236 {
237 if ( isNull() )
238 return;
239
240 if ( mXmin > mXmax )
241 {
242 std::swap( mXmin, mXmax );
243 }
244 if ( mYmin > mYmax )
245 {
246 std::swap( mYmin, mYmax );
247 }
248 }
249
255 double width() const SIP_HOLDGIL { return mXmax - mXmin; }
256
262 double height() const SIP_HOLDGIL { return mYmax - mYmin; }
263
270 double area() const SIP_HOLDGIL { return ( mXmax - mXmin ) * ( mYmax - mYmin ); }
271
276 double perimeter() const SIP_HOLDGIL { return 2 * ( mXmax - mXmin ) + 2 * ( mYmax - mYmin ); }
277
281 QgsPointXY center() const SIP_HOLDGIL { return QgsPointXY( mXmax * 0.5 + mXmin * 0.5, mYmin * 0.5 + mYmax * 0.5 ); }
282
286 void scale( double scaleFactor, const QgsPointXY *c = nullptr )
287 {
288 // scale from the center
289 double centerX, centerY;
290 if ( c )
291 {
292 centerX = c->x();
293 centerY = c->y();
294 }
295 else
296 {
297 centerX = mXmin + width() / 2;
298 centerY = mYmin + height() / 2;
299 }
300 scale( scaleFactor, centerX, centerY );
301 }
302
306 void scale( double scaleFactor, double centerX, double centerY )
307 {
308 const double newWidth = width() * scaleFactor;
309 const double newHeight = height() * scaleFactor;
310 mXmin = centerX - newWidth / 2.0;
311 mXmax = centerX + newWidth / 2.0;
312 mYmin = centerY - newHeight / 2.0;
313 mYmax = centerY + newHeight / 2.0;
314 }
315
320 QgsRectangle scaled( double scaleFactor, const QgsPointXY *center = nullptr ) const;
321
326 void grow( double delta )
327 {
328 if ( isNull() )
329 return;
330 mXmin -= delta;
331 mXmax += delta;
332 mYmin -= delta;
333 mYmax += delta;
334 }
335
339 void include( const QgsPointXY &p )
340 {
341 if ( isNull() )
342 {
343 setXMinimum( p.x() );
344 setXMaximum( p.x() );
345 setYMinimum( p.y() );
346 setYMaximum( p.y() );
347 return;
348 }
349 if ( p.x() < xMinimum() )
350 setXMinimum( p.x() );
351 if ( p.x() > xMaximum() )
352 setXMaximum( p.x() );
353 if ( p.y() < yMinimum() )
354 setYMinimum( p.y() );
355 if ( p.y() > yMaximum() )
356 setYMaximum( p.y() );
357 }
358
365 {
366 if ( isNull() )
367 return QgsRectangle();
368 return QgsRectangle( mXmin - width, mYmin - width, mXmax + width, mYmax + width );
369 }
370
375 {
376 QgsRectangle intersection = QgsRectangle();
377 if ( intersects( rect ) )
378 {
379 intersection.setXMinimum( mXmin > rect.xMinimum() ? mXmin : rect.xMinimum() );
380 intersection.setXMaximum( mXmax < rect.xMaximum() ? mXmax : rect.xMaximum() );
381 intersection.setYMinimum( mYmin > rect.yMinimum() ? mYmin : rect.yMinimum() );
382 intersection.setYMaximum( mYmax < rect.yMaximum() ? mYmax : rect.yMaximum() );
383 }
384 return intersection;
385 }
386
390 bool intersects( const QgsRectangle &rect ) const SIP_HOLDGIL
391 {
392 if ( isNull() || rect.isNull() )
393 {
394 return false;
395 }
396
397 const double x1 = ( mXmin > rect.mXmin ? mXmin : rect.mXmin );
398 const double x2 = ( mXmax < rect.mXmax ? mXmax : rect.mXmax );
399 if ( x1 > x2 )
400 return false;
401 const double y1 = ( mYmin > rect.mYmin ? mYmin : rect.mYmin );
402 const double y2 = ( mYmax < rect.mYmax ? mYmax : rect.mYmax );
403 return y1 <= y2;
404 }
405
409 bool contains( const QgsRectangle &rect ) const SIP_HOLDGIL
410 {
411 return ( rect.mXmin >= mXmin && rect.mXmax <= mXmax && rect.mYmin >= mYmin && rect.mYmax <= mYmax );
412 }
413
417 bool contains( const QgsPointXY &p ) const SIP_HOLDGIL
418 {
419 return mXmin <= p.x() && p.x() <= mXmax &&
420 mYmin <= p.y() && p.y() <= mYmax;
421 }
422
428 bool contains( double x, double y ) const SIP_HOLDGIL
429 {
430 return mXmin <= x && x <= mXmax &&
431 mYmin <= y && y <= mYmax;
432 }
433
437 void combineExtentWith( const QgsRectangle &rect )
438 {
439 if ( isNull() )
440 *this = rect;
441 else if ( !rect.isNull() )
442 {
443 mXmin = std::min( mXmin, rect.xMinimum() );
444 mXmax = std::max( mXmax, rect.xMaximum() );
445 mYmin = std::min( mYmin, rect.yMinimum() );
446 mYmax = std::max( mYmax, rect.yMaximum() );
447 }
448 }
449
453 void combineExtentWith( double x, double y )
454 {
455 if ( isNull() )
456 *this = QgsRectangle( x, y, x, y );
457 else
458 {
459 mXmin = ( ( mXmin < x ) ? mXmin : x );
460 mXmax = ( ( mXmax > x ) ? mXmax : x );
461
462 mYmin = ( ( mYmin < y ) ? mYmin : y );
463 mYmax = ( ( mYmax > y ) ? mYmax : y );
464 }
465 }
466
471 void combineExtentWith( const QgsPointXY &point )
472 {
473 combineExtentWith( point.x(), point.y() );
474 }
475
480 double distance( const QgsPointXY &point ) const
481 {
482 const double dx = std::max( std::max( mXmin - point.x(), 0.0 ), point.x() - mXmax );
483 const double dy = std::max( std::max( mYmin - point.y(), 0.0 ), point.y() - mYmax );
484 return std::sqrt( dx * dx + dy * dy );
485 }
486
491
496
500 QgsRectangle &operator-=( QgsVector v );
501
505 QgsRectangle &operator+=( QgsVector v );
506
516 bool isEmpty() const
517 {
518 return isNull() || mXmax <= mXmin || mYmax <= mYmin || qgsDoubleNear( mXmax, mXmin ) || qgsDoubleNear( mYmax, mYmin );
519 }
520
531 bool isNull() const
532 {
533 // rectangle created QgsRectangle() or with rect.setNull() or
534 // otherwise having NaN ordinates
535 return ( std::isnan( mXmin ) && std::isnan( mXmax ) && std::isnan( mYmin ) && std::isnan( mYmax ) ) ||
536 ( qgsDoubleNear( mXmin, std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmin, std::numeric_limits<double>::max() ) &&
537 qgsDoubleNear( mXmax, -std::numeric_limits<double>::max() ) && qgsDoubleNear( mYmax, -std::numeric_limits<double>::max() ) );
538 }
539
549 bool isValid() const
550 {
551 if ( ( !isFinite() ) || ( mXmax <= mXmin ) || ( mYmax <= mYmin ) )
552 {
553 return false;
554 }
555 return true;
556 }
557
570 bool isMaximal() const
571 {
572 return ( std::isinf( mXmin ) || mXmin == std::numeric_limits<double>::lowest() )
573 && ( std::isinf( mYmin ) || mYmin == std::numeric_limits<double>::lowest() )
574 && ( std::isinf( mXmax ) || mXmax == std::numeric_limits<double>::max() )
575 && ( std::isinf( mYmax ) || mYmax == std::numeric_limits<double>::max() );
576 }
577
581 Q_INVOKABLE QString asWktCoordinates() const;
582
586 Q_INVOKABLE QString asWktPolygon() const;
587
591 QRectF toRectF() const
592 {
593 return QRectF( static_cast< qreal >( mXmin ), static_cast< qreal >( mYmin ), static_cast< qreal >( mXmax - mXmin ), static_cast< qreal >( mYmax - mYmin ) );
594 }
595
601 Q_INVOKABLE QString toString( int precision = 16 ) const;
602
606 QString asPolygon() const;
607
608 bool operator==( const QgsRectangle &r1 ) const
609 {
610 if ( isNull() ) return r1.isNull();
611
612 return qgsDoubleNear( r1.xMaximum(), xMaximum() ) &&
613 qgsDoubleNear( r1.xMinimum(), xMinimum() ) &&
614 qgsDoubleNear( r1.yMaximum(), yMaximum() ) &&
616 }
617
618 bool operator!=( const QgsRectangle &r1 ) const
619 {
620 return ( ! operator==( r1 ) );
621 }
622
624 {
625 if ( &r1 != this )
626 {
627 mXmax = r1.xMaximum();
628 mXmin = r1.xMinimum();
629 mYmax = r1.yMaximum();
630 mYmin = r1.yMinimum();
631 }
632
633 return *this;
634 }
635
644 bool isFinite() const
645 {
646 if ( std::isinf( mXmin ) || std::isinf( mYmin ) || std::isinf( mXmax ) || std::isinf( mYmax ) )
647 {
648 return false;
649 }
650 if ( std::isnan( mXmin ) || std::isnan( mYmin ) || std::isnan( mXmax ) || std::isnan( mYmax ) )
651 {
652 return false;
653 }
654 return true;
655 }
656
660 void invert()
661 {
662 std::swap( mXmin, mYmin );
663 std::swap( mXmax, mYmax );
664 }
665
670 QgsBox3D toBox3d( double zMin, double zMax ) const;
671
673 operator QVariant() const
674 {
675 return QVariant::fromValue( *this );
676 }
677
684 QgsRectangle snappedToGrid( double spacing ) const;
685
686#ifdef SIP_RUN
687 SIP_PYOBJECT __repr__();
688 % MethodCode
689 QString str;
690 if ( sipCpp->isNull() )
691 str = u"<QgsRectangle()>"_s;
692 else
693 str = u"<QgsRectangle: %1>"_s.arg( sipCpp->asWktCoordinates() );
694 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
695 % End
696#endif
697
698 private:
699
700 double mXmin = std::numeric_limits<double>::max();
701 double mYmin = std::numeric_limits<double>::max();
702 double mXmax = -std::numeric_limits<double>::max();
703 double mYmax = -std::numeric_limits<double>::max();
704
705};
706
708
709#ifndef SIP_RUN
710
714CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsRectangle &rectangle );
715
719CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsRectangle &rectangle );
720
721inline std::ostream &operator << ( std::ostream &os, const QgsRectangle &r )
722{
723 return os << r.toString().toLocal8Bit().data();
724}
725
726#endif
727
728#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 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: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:6900
#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.