QGIS API Documentation 4.3.0-Master (e0370aa57ef)
Loading...
Searching...
No Matches
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 "qgsrectangle.h"
19
20#include <algorithm>
21#include <cmath>
22#include <limits>
23
24#include "qgsbox3d.h"
25#include "qgsgeometry.h"
26#include "qgslinestring.h"
27#include "qgslogger.h"
28#include "qgspointxy.h"
29#include "qgspolygon.h"
30
31#include <QString>
32#include <QTextStream>
33#include <QTransform>
34
35#include "moc_qgsrectangle.cpp"
36
37using namespace Qt::StringLiterals;
38
40{
41 const QgsGeometry geom = QgsGeometry::fromWkt( wkt );
42 if ( geom.isEmpty() )
43 return QgsRectangle();
44
46 {
47 if ( polygon->numInteriorRings() > 0 )
48 return QgsRectangle();
49
50 if ( const QgsLineString *exterior = qgsgeometry_cast< const QgsLineString * >( polygon->exteriorRing() ) )
51 {
52 if ( exterior->numPoints() == 5 && qgsDoubleNear( exterior->xAt( 0 ), exterior->xAt( 4 ) ) && qgsDoubleNear( exterior->yAt( 0 ), exterior->yAt( 4 ) ) && geom.isGeosValid() )
53 return QgsRectangle( exterior->xAt( 0 ), exterior->yAt( 0 ), exterior->xAt( 2 ), exterior->yAt( 2 ) );
54 }
55 }
56 return QgsRectangle();
57}
58
60{
61 const double xMin = center.x() - width / 2.0;
62 const double xMax = xMin + width;
63 const double yMin = center.y() - height / 2.0;
64 const double yMax = yMin + height;
65 return QgsRectangle( xMin, yMin, xMax, yMax );
66}
67
68QgsRectangle QgsRectangle::fromEdges( double left, double top, double right, double bottom )
69{
70 return QgsRectangle( left, bottom, right, top, false );
71}
72
73QgsRectangle QgsRectangle::scaled( double scaleFactor, const QgsPointXY *center ) const
74{
75 QgsRectangle scaledRect = QgsRectangle( *this );
76 scaledRect.scale( scaleFactor, center );
77 return scaledRect;
78}
79
81{
82 const double xmin = mXmin - v.x();
83 const double xmax = mXmax - v.x();
84 const double ymin = mYmin - v.y();
85 const double ymax = mYmax - v.y();
86 return QgsRectangle( xmin, ymin, xmax, ymax );
87}
88
90{
91 const double xmin = mXmin + v.x();
92 const double xmax = mXmax + v.x();
93 const double ymin = mYmin + v.y();
94 const double ymax = mYmax + v.y();
95 return QgsRectangle( xmin, ymin, xmax, ymax );
96}
97
99{
100 mXmin -= v.x();
101 mXmax -= v.x();
102 mYmin -= v.y();
103 mYmax -= v.y();
104 return *this;
105}
106
108{
109 mXmin += v.x();
110 mXmax += v.x();
111 mYmin += v.y();
112 mYmax += v.y();
113 return *this;
114}
115
117{
118 QString rep = qgsDoubleToString( mXmin ) + ' ' + qgsDoubleToString( mYmin ) + ", "_L1 + qgsDoubleToString( mXmax ) + ' ' + qgsDoubleToString( mYmax );
119
120 return rep;
121}
122
124{
125 if ( isNull() )
126 {
127 return u"Polygon EMPTY"_s;
128 }
129
130 return u"Polygon ((%1 %2, %3 %2, %3 %4, %1 %4, %1 %2))"_s.arg( qgsDoubleToString( mXmin ), qgsDoubleToString( mYmin ), qgsDoubleToString( mXmax ), qgsDoubleToString( mYmax ) );
131}
132
133QString QgsRectangle::toString( int precision ) const
134{
135 QString rep;
136
137 if ( precision < 0 )
138 {
139 precision = 0;
140 if ( ( width() < 10 || height() < 10 ) && ( width() > 0 && height() > 0 ) )
141 {
142 precision = static_cast<int>( std::ceil( -1.0 * std::log10( std::min( width(), height() ) ) ) ) + 1;
143 // sanity check
144 if ( precision > 20 )
145 precision = 20;
146 }
147 }
148
149 if ( isNull() )
150 rep = u"Null"_s;
151 else
152 rep = u"%1,%2 : %3,%4"_s.arg( mXmin, 0, 'f', precision ).arg( mYmin, 0, 'f', precision ).arg( mXmax, 0, 'f', precision ).arg( mYmax, 0, 'f', precision );
153
154 QgsDebugMsgLevel( u"Extents : %1"_s.arg( rep ), 4 );
155
156 return rep;
157}
158
160{
161 if ( isNull() )
162 {
163 return u"EMPTY"_s;
164 }
165
166 QString rep;
167
168 QTextStream foo( &rep );
169
170 foo.setRealNumberPrecision( 8 );
171 foo.setRealNumberNotation( QTextStream::FixedNotation );
172 // NOTE: a polygon isn't a polygon unless its closed. In the case of
173 // a rectangle, that means 5 points (last == first)
174 foo << mXmin << ' ' << mYmin << ", " << mXmin << ' ' << mYmax << ", " << mXmax << ' ' << mYmax << ", " << mXmax << ' ' << mYmin << ", " << mXmin << ' ' << mYmin;
175
176 return rep;
177}
178
179QgsBox3D QgsRectangle::toBox3d( double zMin, double zMax ) const
180{
181 return QgsBox3D( mXmin, mYmin, zMin, mXmax, mYmax, zMax );
182}
183
184std::pair<QgsRectangle, QgsRectangle> QgsRectangle::splitAtAntimeridian() const
185{
186 if ( isNull() )
187 return { QgsRectangle(), QgsRectangle() };
188
189 auto normalizeLongitude = []( double x ) {
190 double res = std::fmod( x, 360 );
191 if ( res > 180 )
192 res -= 360;
193 else if ( res < -180 )
194 res += 360;
195 return res;
196 };
197
198 if ( qgsDoubleNear( xMinimum(), xMaximum() ) )
199 {
200 // vertical slice
201 const double x = normalizeLongitude( xMinimum() );
202 return { QgsRectangle( x, yMinimum(), x, yMaximum() ), QgsRectangle() };
203 }
204 else if ( xMinimum() < xMaximum() )
205 {
206 // normalized rect
207 const double x1 = normalizeLongitude( xMinimum() );
208 const double x2 = normalizeLongitude( xMaximum() );
209 if ( x1 < x2 )
210 {
211 return { QgsRectangle( x1, yMinimum(), x2, yMaximum() ), QgsRectangle() };
212 }
213 else
214 {
215 return { QgsRectangle( x1, yMinimum(), 180, yMaximum() ), QgsRectangle( -180, yMinimum(), x2, yMaximum() ) };
216 }
217 }
218 else
219 {
220 // non-normalized
221 const double x1 = normalizeLongitude( xMinimum() );
222 const double x2 = normalizeLongitude( xMaximum() );
223 return { QgsRectangle( x1, yMinimum(), 180, yMaximum() ), QgsRectangle( -180, yMinimum(), x2, yMaximum() ) };
224 }
225}
226
228{
229 if ( isNull() )
230 return *this;
231
232 // helper function
233 auto gridifyValue = []( double value, double spacing ) -> double {
234 if ( spacing > 0 )
235 return std::round( value / spacing ) * spacing;
236 else
237 return value;
238 };
239
240 return QgsRectangle( gridifyValue( mXmin, spacing ), gridifyValue( mYmin, spacing ), gridifyValue( mXmax, spacing ), gridifyValue( mYmax, spacing ) );
241}
242
243QDataStream &operator<<( QDataStream &out, const QgsRectangle &rectangle )
244{
245 out << rectangle.xMinimum() << rectangle.yMinimum() << rectangle.xMaximum() << rectangle.yMaximum();
246 return out;
247}
248
249QDataStream &operator>>( QDataStream &in, QgsRectangle &rectangle )
250{
251 double xmin, ymin, xmax, ymax;
252 in >> xmin >> ymin >> xmax >> ymax;
253 rectangle.setXMinimum( xmin );
254 rectangle.setYMinimum( ymin );
255 rectangle.setXMaximum( xmax );
256 rectangle.setYMaximum( ymax );
257 return in;
258}
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:45
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static Q_INVOKABLE QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
bool isGeosValid(Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const
Checks validity of the geometry using GEOS.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
Line string geometry type, with support for z-dimension and m-values.
Represents a 2D point.
Definition qgspointxy.h:62
Polygon geometry type.
Definition qgspolygon.h:37
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.
double xMinimum
QgsRectangle & operator+=(QgsVector v)
Moves this rectangle in the direction of the vector.
QgsRectangle()=default
Constructor for a null rectangle.
double yMinimum
double xMaximum
static QgsRectangle fromWkt(const QString &wkt)
Creates a new rectangle from a wkt string.
void setYMinimum(double y)
Set the minimum y value.
QgsRectangle & operator-=(QgsVector v)
Moves this rectangle in the direction of the reversed vector.
void setXMinimum(double x)
Set the minimum x value.
Q_INVOKABLE QString asWktPolygon() const
Returns a string representation of the rectangle as a WKT Polygon.
static QgsRectangle fromEdges(double left, double top, double right, double bottom)
Creates a rectangle from the left, top, right and bottom edges.
Q_INVOKABLE QString asWktCoordinates() const
Returns a string representation of the rectangle in WKT format.
QgsRectangle operator-(QgsVector v) const
Returns a rectangle offset from this one in the direction of the reversed vector.
QgsRectangle scaled(double scaleFactor, const QgsPointXY *center=nullptr) const
Scale the rectangle around its center point.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
std::pair< QgsRectangle, QgsRectangle > splitAtAntimeridian() const
Splits the rectangle at the antimeridian (longitude 180 degrees).
double yMaximum
double left() const
Returns the left side of the rectangle.
double right() const
Returns the right side of the rectangle.
static QgsRectangle fromCenterAndSize(const QgsPointXY &center, double width, double height)
Creates a new rectangle, given the specified center point and width and height.
QString asPolygon() const
Returns the rectangle as a polygon.
QgsPointXY center
double bottom() const
Returns the bottom side of the rectangle.
QgsRectangle snappedToGrid(double spacing) const
Returns a copy of this rectangle that is snapped to a grid with the specified spacing between the gri...
QgsRectangle operator+(QgsVector v) const
Returns a rectangle offset from this one in the direction of the vector.
QgsBox3D toBox3d(double zMin, double zMax) const
Converts the rectangle to a 3D box, with the specified zMin and zMax z values.
double top() const
Returns the top side of the rectangle.
Represent a 2-dimensional vector.
Definition qgsvector.h:34
double y() const
Returns the vector's y-component.
Definition qgsvector.h:155
double x() const
Returns the vector's x-component.
Definition qgsvector.h:146
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:7702
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
T qgsgeometry_cast(QgsAbstractGeometry *geom)
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:80
QDataStream & operator>>(QDataStream &in, QgsRectangle &rectangle)
Reads a rectangle from stream in into rectangle.
QDataStream & operator<<(QDataStream &out, const QgsRectangle &rectangle)
Writes the list rectangle to stream out.