00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <algorithm>
00020 #include <cmath>
00021 #include <limits>
00022 #include <QString>
00023 #include <QTextStream>
00024
00025 #include "qgspoint.h"
00026 #include "qgsrectangle.h"
00027 #include "qgslogger.h"
00028
00029 QgsRectangle::QgsRectangle( double newxmin, double newymin, double newxmax, double newymax )
00030 : xmin( newxmin ), ymin( newymin ), xmax( newxmax ), ymax( newymax )
00031 {
00032 normalize();
00033 }
00034
00035 QgsRectangle::QgsRectangle( QgsPoint const & p1, QgsPoint const & p2 )
00036 {
00037 set( p1, p2 );
00038 }
00039
00040 QgsRectangle::QgsRectangle( const QgsRectangle &r )
00041 {
00042 xmin = r.xMinimum();
00043 ymin = r.yMinimum();
00044 xmax = r.xMaximum();
00045 ymax = r.yMaximum();
00046 }
00047
00048 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
00049 {
00050 xmin = p1.x();
00051 xmax = p2.x();
00052 ymin = p1.y();
00053 ymax = p2.y();
00054 normalize();
00055 }
00056
00057 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ )
00058 {
00059 xmin = xmin_;
00060 ymin = ymin_;
00061 xmax = xmax_;
00062 ymax = ymax_;
00063 normalize();
00064 }
00065
00066 void QgsRectangle::normalize()
00067 {
00068 if ( xmin > xmax )
00069 {
00070 std::swap( xmin, xmax );
00071 }
00072 if ( ymin > ymax )
00073 {
00074 std::swap( ymin, ymax );
00075 }
00076 }
00077
00078
00079 void QgsRectangle::setMinimal()
00080 {
00081 xmin = std::numeric_limits<double>::max();
00082 ymin = std::numeric_limits<double>::max();
00083 xmax = -std::numeric_limits<double>::max();
00084 ymax = -std::numeric_limits<double>::max();
00085 }
00086
00087 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
00088 {
00089
00090 double centerX, centerY;
00091 if ( cp )
00092 {
00093 centerX = cp->x();
00094 centerY = cp->y();
00095 }
00096 else
00097 {
00098 centerX = xmin + width() / 2;
00099 centerY = ymin + height() / 2;
00100 }
00101 double newWidth = width() * scaleFactor;
00102 double newHeight = height() * scaleFactor;
00103 xmin = centerX - newWidth / 2.0;
00104 xmax = centerX + newWidth / 2.0;
00105 ymin = centerY - newHeight / 2.0;
00106 ymax = centerY + newHeight / 2.0;
00107 }
00108
00109 void QgsRectangle::expand( double scaleFactor, const QgsPoint * cp )
00110 {
00111
00112 double centerX, centerY;
00113 if ( cp )
00114 {
00115 centerX = cp->x();
00116 centerY = cp->y();
00117 }
00118 else
00119 {
00120 centerX = xmin + width() / 2;
00121 centerY = ymin + height() / 2;
00122 }
00123
00124 double newWidth = width() * scaleFactor;
00125 double newHeight = height() * scaleFactor;
00126 xmin = centerX - newWidth;
00127 xmax = centerX + newWidth;
00128 ymin = centerY - newHeight;
00129 ymax = centerY + newHeight;
00130 }
00131
00132 QgsRectangle QgsRectangle::intersect( const QgsRectangle * rect ) const
00133 {
00134 QgsRectangle intersection = QgsRectangle();
00135
00136 if ( !rect || !intersects( *rect ) )
00137 {
00138 return intersection;
00139 }
00140
00141 intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
00142 intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
00143 intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
00144 intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
00145 return intersection;
00146 }
00147
00148 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
00149 {
00150 double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
00151 double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
00152 if ( x1 > x2 ) return false;
00153 double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
00154 double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
00155 if ( y1 > y2 ) return false;
00156 return true;
00157 }
00158
00159 bool QgsRectangle::contains( const QgsRectangle& rect ) const
00160 {
00161 return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
00162 }
00163
00164 bool QgsRectangle::contains( const QgsPoint &p ) const
00165 {
00166 return xmin <= p.x() && p.x() <= xmax &&
00167 ymin <= p.y() && p.y() <= ymax;
00168 }
00169
00170 void QgsRectangle::combineExtentWith( QgsRectangle * rect )
00171 {
00172
00173 xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
00174 xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
00175
00176 ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
00177 ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
00178
00179 }
00180
00181 void QgsRectangle::combineExtentWith( double x, double y )
00182 {
00183
00184 xmin = (( xmin < x ) ? xmin : x );
00185 xmax = (( xmax > x ) ? xmax : x );
00186
00187 ymin = (( ymin < y ) ? ymin : y );
00188 ymax = (( ymax > y ) ? ymax : y );
00189
00190 }
00191
00192 bool QgsRectangle::isEmpty() const
00193 {
00194 return xmax <= xmin || ymax <= ymin;
00195 }
00196
00197 QString QgsRectangle::asWktCoordinates() const
00198 {
00199 QString rep =
00200 QString::number( xmin, 'f', 16 ) + " " +
00201 QString::number( ymin, 'f', 16 ) + ", " +
00202 QString::number( xmax, 'f', 16 ) + " " +
00203 QString::number( ymax, 'f', 16 );
00204
00205 return rep;
00206 }
00207
00208
00209 QString QgsRectangle::toString( bool automaticPrecision ) const
00210 {
00211 if ( automaticPrecision )
00212 {
00213 int precision = 0;
00214 if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
00215 {
00216 precision = static_cast<int>( ceil( -1.0 * log10( std::min( width(), height() ) ) ) ) + 1;
00217
00218 if ( precision > 20 )
00219 precision = 20;
00220 }
00221 return toString( precision );
00222 }
00223 else
00224 return toString( 16 );
00225 }
00226
00227
00228
00229 QString QgsRectangle::toString( int thePrecision ) const
00230 {
00231
00232 QString rep = QString::number( xmin, 'f', thePrecision ) +
00233 QString( "," ) +
00234 QString::number( ymin, 'f', thePrecision ) +
00235 QString( " : " ) +
00236 QString::number( xmax, 'f', thePrecision ) +
00237 QString( "," ) +
00238 QString::number( ymax, 'f', thePrecision ) ;
00239 #ifdef QGISDEBUG
00240
00241 #endif
00242 return rep;
00243 }
00244
00245
00246
00247 QString QgsRectangle::asPolygon() const
00248 {
00249
00250
00251 QString rep;
00252
00253 QTextStream foo( &rep );
00254
00255 foo.setRealNumberPrecision( 8 );
00256 foo.setRealNumberNotation( QTextStream::FixedNotation );
00257
00258
00259 foo << xmin << " " << ymin << ", "
00260 << xmin << " " << ymax << ", "
00261 << xmax << " " << ymax << ", "
00262 << xmax << " " << ymin << ", "
00263 << xmin << " " << ymin;
00264
00265 return rep;
00266
00267 }
00268
00269
00270 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
00271 {
00272 return ( r1.xMaximum() == xMaximum() &&
00273 r1.xMinimum() == xMinimum() &&
00274 r1.yMaximum() == yMaximum() &&
00275 r1.yMinimum() == yMinimum() );
00276 }
00277
00278
00279 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
00280 {
00281 return ( ! operator==( r1 ) );
00282 }
00283
00284
00285 QgsRectangle & QgsRectangle::operator=( const QgsRectangle & r )
00286 {
00287 if ( &r != this )
00288 {
00289 xmax = r.xMaximum();
00290 xmin = r.xMinimum();
00291 ymax = r.yMaximum();
00292 ymin = r.yMinimum();
00293 }
00294
00295 return *this;
00296 }
00297
00298
00299 void QgsRectangle::unionRect( const QgsRectangle& r )
00300 {
00301 if ( r.xMinimum() < xMinimum() ) setXMinimum( r.xMinimum() );
00302 if ( r.xMaximum() > xMaximum() ) setXMaximum( r.xMaximum() );
00303 if ( r.yMinimum() < yMinimum() ) setYMinimum( r.yMinimum() );
00304 if ( r.yMaximum() > yMaximum() ) setYMaximum( r.yMaximum() );
00305 }
00306
00307 bool QgsRectangle::isFinite() const
00308 {
00309 if ( std::numeric_limits<double>::has_infinity )
00310 {
00311 if ( xmin == std::numeric_limits<double>::infinity() ||
00312 xmax == std::numeric_limits<double>::infinity() ||
00313 ymin == std::numeric_limits<double>::infinity() ||
00314 ymax == std::numeric_limits<double>::infinity() )
00315 return false;
00316 }
00317
00318
00319 if ( xmin != xmin || xmax != xmax || ymin != ymin || ymax != ymax )
00320 return false;
00321
00322 return true;
00323 }