Branch data Line data Source code
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 <QString>
22 : : #include <QTextStream>
23 : : #include <QTransform>
24 : : #include <QRegExp>
25 : :
26 : : #include "qgsgeometry.h"
27 : : #include "qgspointxy.h"
28 : : #include "qgsrectangle.h"
29 : : #include "qgslogger.h"
30 : : #include "qgsbox3d.h"
31 : : #include "qgspolygon.h"
32 : : #include "qgslinestring.h"
33 : :
34 : 0 : QgsRectangle QgsRectangle::fromWkt( const QString &wkt )
35 : : {
36 : 0 : QgsGeometry geom = QgsGeometry::fromWkt( wkt );
37 : 0 : if ( geom.isMultipart() )
38 : 0 : return QgsRectangle();
39 : :
40 : 0 : QgsPolygonXY poly = geom.asPolygon();
41 : :
42 : 0 : if ( poly.size() != 1 )
43 : 0 : return QgsRectangle();
44 : :
45 : 0 : QgsPolylineXY polyline = geom.asPolygon().at( 0 );
46 : 0 : if ( polyline.size() == 5 && polyline.at( 0 ) == polyline.at( 4 ) && geom.isGeosValid() )
47 : 0 : return QgsRectangle( polyline.at( 0 ).x(), polyline.at( 0 ).y(), polyline.at( 2 ).x(), polyline.at( 2 ).y() );
48 : : else
49 : 0 : return QgsRectangle();
50 : 0 : }
51 : :
52 : 0 : QgsRectangle QgsRectangle::fromCenterAndSize( QgsPointXY center, double width, double height )
53 : : {
54 : 0 : double xMin = center.x() - width / 2.0;
55 : 0 : double xMax = xMin + width;
56 : 0 : double yMin = center.y() - height / 2.0;
57 : 0 : double yMax = yMin + height;
58 : 0 : return QgsRectangle( xMin, yMin, xMax, yMax );
59 : : }
60 : :
61 : 0 : QgsRectangle QgsRectangle::scaled( double scaleFactor, const QgsPointXY *center ) const
62 : : {
63 : 0 : QgsRectangle scaledRect = QgsRectangle( *this );
64 : 0 : scaledRect.scale( scaleFactor, center );
65 : 0 : return scaledRect;
66 : : }
67 : :
68 : 0 : QgsRectangle QgsRectangle::operator-( const QgsVector v ) const
69 : : {
70 : 0 : double xmin = mXmin - v.x();
71 : 0 : double xmax = mXmax - v.x();
72 : 0 : double ymin = mYmin - v.y();
73 : 0 : double ymax = mYmax - v.y();
74 : 0 : return QgsRectangle( xmin, ymin, xmax, ymax );
75 : : }
76 : :
77 : 0 : QgsRectangle QgsRectangle::operator+( const QgsVector v ) const
78 : : {
79 : 0 : double xmin = mXmin + v.x();
80 : 0 : double xmax = mXmax + v.x();
81 : 0 : double ymin = mYmin + v.y();
82 : 0 : double ymax = mYmax + v.y();
83 : 0 : return QgsRectangle( xmin, ymin, xmax, ymax );
84 : : }
85 : :
86 : 0 : QgsRectangle &QgsRectangle::operator-=( const QgsVector v )
87 : : {
88 : 0 : mXmin -= v.x();
89 : 0 : mXmax -= v.x();
90 : 0 : mYmin -= v.y();
91 : 0 : mYmax -= v.y();
92 : 0 : return *this;
93 : : }
94 : :
95 : 0 : QgsRectangle &QgsRectangle::operator+=( const QgsVector v )
96 : : {
97 : 0 : mXmin += v.x();
98 : 0 : mXmax += v.x();
99 : 0 : mYmin += v.y();
100 : 0 : mYmax += v.y();
101 : 0 : return *this;
102 : : }
103 : :
104 : 0 : QString QgsRectangle::asWktCoordinates() const
105 : : {
106 : 0 : QString rep =
107 : 0 : qgsDoubleToString( mXmin ) + ' ' + qgsDoubleToString( mYmin ) + QLatin1String( ", " ) +
108 : 0 : qgsDoubleToString( mXmax ) + ' ' + qgsDoubleToString( mYmax );
109 : :
110 : 0 : return rep;
111 : 0 : }
112 : :
113 : 0 : QString QgsRectangle::asWktPolygon() const
114 : : {
115 : 0 : QString rep =
116 : 0 : QLatin1String( "POLYGON((" ) +
117 : 0 : qgsDoubleToString( mXmin ) + ' ' + qgsDoubleToString( mYmin ) + QLatin1String( ", " ) +
118 : 0 : qgsDoubleToString( mXmax ) + ' ' + qgsDoubleToString( mYmin ) + QLatin1String( ", " ) +
119 : 0 : qgsDoubleToString( mXmax ) + ' ' + qgsDoubleToString( mYmax ) + QLatin1String( ", " ) +
120 : 0 : qgsDoubleToString( mXmin ) + ' ' + qgsDoubleToString( mYmax ) + QLatin1String( ", " ) +
121 : 0 : qgsDoubleToString( mXmin ) + ' ' + qgsDoubleToString( mYmin ) +
122 : 0 : QStringLiteral( "))" );
123 : :
124 : 0 : return rep;
125 : 0 : }
126 : :
127 : 10 : QString QgsRectangle::toString( int precision ) const
128 : : {
129 : 10 : QString rep;
130 : :
131 : 10 : if ( precision < 0 )
132 : : {
133 : 0 : precision = 0;
134 : 0 : if ( ( width() < 10 || height() < 10 ) && ( width() > 0 && height() > 0 ) )
135 : : {
136 : 0 : precision = static_cast<int>( std::ceil( -1.0 * std::log10( std::min( width(), height() ) ) ) ) + 1;
137 : : // sanity check
138 : 0 : if ( precision > 20 )
139 : 0 : precision = 20;
140 : 0 : }
141 : 0 : }
142 : :
143 : 10 : if ( isEmpty() )
144 : 0 : rep = QStringLiteral( "Empty" );
145 : : else
146 : 30 : rep = QStringLiteral( "%1,%2 : %3,%4" )
147 : 10 : .arg( mXmin, 0, 'f', precision )
148 : 10 : .arg( mYmin, 0, 'f', precision )
149 : 10 : .arg( mXmax, 0, 'f', precision )
150 : 10 : .arg( mYmax, 0, 'f', precision );
151 : :
152 : 10 : QgsDebugMsgLevel( QStringLiteral( "Extents : %1" ).arg( rep ), 4 );
153 : :
154 : 10 : return rep;
155 : 10 : }
156 : :
157 : 0 : QString QgsRectangle::asPolygon() const
158 : : {
159 : : // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
160 : : // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
161 : 0 : QString rep;
162 : :
163 : 0 : QTextStream foo( &rep );
164 : :
165 : 0 : foo.setRealNumberPrecision( 8 );
166 : 0 : foo.setRealNumberNotation( QTextStream::FixedNotation );
167 : : // NOTE: a polygon isn't a polygon unless its closed. In the case of
168 : : // a rectangle, that means 5 points (last == first)
169 : : foo
170 : 0 : << mXmin << ' ' << mYmin << ", "
171 : 0 : << mXmin << ' ' << mYmax << ", "
172 : 0 : << mXmax << ' ' << mYmax << ", "
173 : 0 : << mXmax << ' ' << mYmin << ", "
174 : 0 : << mXmin << ' ' << mYmin;
175 : :
176 : 0 : return rep;
177 : :
178 : 0 : }
179 : :
180 : 0 : QgsBox3d QgsRectangle::toBox3d( double zMin, double zMax ) const
181 : : {
182 : 0 : return QgsBox3d( mXmin, mYmin, zMin, mXmax, mYmax, zMax );
183 : : }
184 : :
185 : 64 : QgsRectangle QgsRectangle::snappedToGrid( double spacing ) const
186 : : {
187 : : // helper function
188 : 256 : auto gridifyValue = []( double value, double spacing ) -> double
189 : : {
190 : 256 : if ( spacing > 0 )
191 : 256 : return std::round( value / spacing ) * spacing;
192 : : else
193 : 0 : return value;
194 : 256 : };
195 : :
196 : 64 : return QgsRectangle(
197 : 64 : gridifyValue( mXmin, spacing ),
198 : 64 : gridifyValue( mYmin, spacing ),
199 : 64 : gridifyValue( mXmax, spacing ),
200 : 64 : gridifyValue( mYmax, spacing )
201 : : );
202 : : }
203 : :
204 : 0 : QDataStream &operator<<( QDataStream &out, const QgsRectangle &rectangle )
205 : : {
206 : 0 : out << rectangle.xMinimum() << rectangle.yMinimum() << rectangle.xMaximum() << rectangle.yMaximum();
207 : 0 : return out;
208 : : }
209 : :
210 : 0 : QDataStream &operator>>( QDataStream &in, QgsRectangle &rectangle )
211 : : {
212 : : double xmin, ymin, xmax, ymax;
213 : 0 : in >> xmin >> ymin >> xmax >> ymax;
214 : 0 : rectangle.setXMinimum( xmin );
215 : 0 : rectangle.setYMinimum( ymin );
216 : 0 : rectangle.setXMaximum( xmax );
217 : 0 : rectangle.setYMaximum( ymax );
218 : 0 : return in;
219 : : }
|