|
QGIS API Documentation
master-6164ace
|
00001 /*************************************************************************** 00002 qgsrectangle.cpp - description 00003 ------------------- 00004 begin : Sat Jun 22 2002 00005 copyright : (C) 2002 by Gary E.Sherman 00006 email : sherman at mrcc.com 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 00018 #include <algorithm> 00019 #include <cmath> 00020 #include <limits> 00021 #include <QRectF> 00022 #include <QString> 00023 #include <QTextStream> 00024 #include <QRegExp> 00025 #include <qnumeric.h> 00026 00027 #include "qgspoint.h" 00028 #include "qgsrectangle.h" 00029 #include "qgslogger.h" 00030 00031 QgsRectangle::QgsRectangle( double newxmin, double newymin, double newxmax, double newymax ) 00032 : xmin( newxmin ), ymin( newymin ), xmax( newxmax ), ymax( newymax ) 00033 { 00034 normalize(); 00035 } 00036 00037 QgsRectangle::QgsRectangle( QgsPoint const & p1, QgsPoint const & p2 ) 00038 { 00039 set( p1, p2 ); 00040 } 00041 00042 QgsRectangle::QgsRectangle( QRectF const & qRectF ) 00043 { 00044 xmin = qRectF.topLeft().x(); 00045 ymin = qRectF.topLeft().y(); 00046 xmax = qRectF.bottomRight().x(); 00047 ymax = qRectF.bottomRight().y(); 00048 } 00049 00050 QgsRectangle::QgsRectangle( const QgsRectangle &r ) 00051 { 00052 xmin = r.xMinimum(); 00053 ymin = r.yMinimum(); 00054 xmax = r.xMaximum(); 00055 ymax = r.yMaximum(); 00056 } 00057 00058 00059 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 ) 00060 { 00061 xmin = p1.x(); 00062 xmax = p2.x(); 00063 ymin = p1.y(); 00064 ymax = p2.y(); 00065 normalize(); 00066 } 00067 00068 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ ) 00069 { 00070 xmin = xmin_; 00071 ymin = ymin_; 00072 xmax = xmax_; 00073 ymax = ymax_; 00074 normalize(); 00075 } 00076 00077 void QgsRectangle::normalize() 00078 { 00079 if ( xmin > xmax ) 00080 { 00081 std::swap( xmin, xmax ); 00082 } 00083 if ( ymin > ymax ) 00084 { 00085 std::swap( ymin, ymax ); 00086 } 00087 } // QgsRectangle::normalize() 00088 00089 00090 void QgsRectangle::setMinimal() 00091 { 00092 xmin = std::numeric_limits<double>::max(); 00093 ymin = std::numeric_limits<double>::max(); 00094 xmax = -std::numeric_limits<double>::max(); 00095 ymax = -std::numeric_limits<double>::max(); 00096 } 00097 00098 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp ) 00099 { 00100 // scale from the center 00101 double centerX, centerY; 00102 if ( cp ) 00103 { 00104 centerX = cp->x(); 00105 centerY = cp->y(); 00106 } 00107 else 00108 { 00109 centerX = xmin + width() / 2; 00110 centerY = ymin + height() / 2; 00111 } 00112 double newWidth = width() * scaleFactor; 00113 double newHeight = height() * scaleFactor; 00114 xmin = centerX - newWidth / 2.0; 00115 xmax = centerX + newWidth / 2.0; 00116 ymin = centerY - newHeight / 2.0; 00117 ymax = centerY + newHeight / 2.0; 00118 } 00119 00120 QgsRectangle QgsRectangle::intersect( const QgsRectangle * rect ) const 00121 { 00122 QgsRectangle intersection = QgsRectangle(); 00123 //If they don't actually intersect an empty QgsRectangle should be returned 00124 if ( !rect || !intersects( *rect ) ) 00125 { 00126 return intersection; 00127 } 00128 00129 intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() ); 00130 intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() ); 00131 intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() ); 00132 intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() ); 00133 return intersection; 00134 } 00135 00136 bool QgsRectangle::intersects( const QgsRectangle& rect ) const 00137 { 00138 double x1 = ( xmin > rect.xmin ? xmin : rect.xmin ); 00139 double x2 = ( xmax < rect.xmax ? xmax : rect.xmax ); 00140 if ( x1 > x2 ) 00141 return false; 00142 double y1 = ( ymin > rect.ymin ? ymin : rect.ymin ); 00143 double y2 = ( ymax < rect.ymax ? ymax : rect.ymax ); 00144 if ( y1 > y2 ) 00145 return false; 00146 return true; 00147 } 00148 00149 bool QgsRectangle::contains( const QgsRectangle& rect ) const 00150 { 00151 return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax ); 00152 } 00153 00154 bool QgsRectangle::contains( const QgsPoint &p ) const 00155 { 00156 return xmin <= p.x() && p.x() <= xmax && 00157 ymin <= p.y() && p.y() <= ymax; 00158 } 00159 00160 void QgsRectangle::combineExtentWith( QgsRectangle * rect ) 00161 { 00162 00163 xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() ); 00164 xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() ); 00165 00166 ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() ); 00167 ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() ); 00168 00169 } 00170 00171 void QgsRectangle::combineExtentWith( double x, double y ) 00172 { 00173 00174 xmin = (( xmin < x ) ? xmin : x ); 00175 xmax = (( xmax > x ) ? xmax : x ); 00176 00177 ymin = (( ymin < y ) ? ymin : y ); 00178 ymax = (( ymax > y ) ? ymax : y ); 00179 00180 } 00181 00182 bool QgsRectangle::isEmpty() const 00183 { 00184 return xmax <= xmin || ymax <= ymin; 00185 } 00186 00187 QString QgsRectangle::asWktCoordinates() const 00188 { 00189 QString rep = 00190 QString::number( xmin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00191 QString::number( ymin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + ", " + 00192 QString::number( xmax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00193 QString::number( ymax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ); 00194 00195 return rep; 00196 } 00197 00198 QString QgsRectangle::asWktPolygon() const 00199 { 00200 QString rep = 00201 QString( "POLYGON((" ) + 00202 QString::number( xmin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00203 QString::number( ymin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + ", " + 00204 QString::number( xmax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00205 QString::number( ymin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + ", " + 00206 QString::number( xmax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00207 QString::number( ymax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + ", " + 00208 QString::number( xmin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00209 QString::number( ymax, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + ", " + 00210 QString::number( xmin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + " " + 00211 QString::number( ymin, 'f', 16 ).remove( QRegExp( "[0]{1,15}$" ) ) + 00212 QString( "))" ); 00213 00214 return rep; 00215 } 00216 00218 //@note added in 2.0 00219 QRectF QgsRectangle::toRectF() const 00220 { 00221 return QRectF(( qreal )xmin, ( qreal )ymin, ( qreal )xmax - xmin, ( qreal )ymax - ymin ); 00222 } 00223 00224 // Return a string representation of the rectangle with automatic or high precision 00225 QString QgsRectangle::toString( bool automaticPrecision ) const 00226 { 00227 if ( automaticPrecision ) 00228 { 00229 int precision = 0; 00230 if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) ) 00231 { 00232 precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1; 00233 // sanity check 00234 if ( precision > 20 ) 00235 precision = 20; 00236 } 00237 return toString( precision ); 00238 } 00239 else 00240 return toString( 16 ); 00241 } 00242 00243 // overloaded version of above fn to allow precision to be set 00244 // Return a string representation of the rectangle with high precision 00245 QString QgsRectangle::toString( int thePrecision ) const 00246 { 00247 QString rep; 00248 if ( isEmpty() ) 00249 rep = "Empty"; 00250 else 00251 rep = QString( "%1,%2 : %3,%4" ) 00252 .arg( xmin, 0, 'f', thePrecision ) 00253 .arg( ymin, 0, 'f', thePrecision ) 00254 .arg( xmax, 0, 'f', thePrecision ) 00255 .arg( ymax, 0, 'f', thePrecision ); 00256 00257 QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 ); 00258 00259 return rep; 00260 } 00261 00262 00263 // Return the rectangle as a set of polygon coordinates 00264 QString QgsRectangle::asPolygon() const 00265 { 00266 // QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f", 00267 // xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin); 00268 QString rep; 00269 00270 QTextStream foo( &rep ); 00271 00272 foo.setRealNumberPrecision( 8 ); 00273 foo.setRealNumberNotation( QTextStream::FixedNotation ); 00274 // NOTE: a polygon isn't a polygon unless its closed. In the case of 00275 // a rectangle, that means 5 points (last == first) 00276 foo << xmin << " " << ymin << ", " 00277 << xmin << " " << ymax << ", " 00278 << xmax << " " << ymax << ", " 00279 << xmax << " " << ymin << ", " 00280 << xmin << " " << ymin; 00281 00282 return rep; 00283 00284 } // QgsRectangle::asPolygon() const 00285 00286 00287 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const 00288 { 00289 return ( r1.xMaximum() == xMaximum() && 00290 r1.xMinimum() == xMinimum() && 00291 r1.yMaximum() == yMaximum() && 00292 r1.yMinimum() == yMinimum() ); 00293 } 00294 00295 00296 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const 00297 { 00298 return ( ! operator==( r1 ) ); 00299 } 00300 00301 00302 QgsRectangle & QgsRectangle::operator=( const QgsRectangle & r ) 00303 { 00304 if ( &r != this ) 00305 { 00306 xmax = r.xMaximum(); 00307 xmin = r.xMinimum(); 00308 ymax = r.yMaximum(); 00309 ymin = r.yMinimum(); 00310 } 00311 00312 return *this; 00313 } 00314 00315 00316 void QgsRectangle::unionRect( const QgsRectangle& r ) 00317 { 00318 if ( r.xMinimum() < xMinimum() ) 00319 setXMinimum( r.xMinimum() ); 00320 if ( r.xMaximum() > xMaximum() ) 00321 setXMaximum( r.xMaximum() ); 00322 if ( r.yMinimum() < yMinimum() ) 00323 setYMinimum( r.yMinimum() ); 00324 if ( r.yMaximum() > yMaximum() ) 00325 setYMaximum( r.yMaximum() ); 00326 } 00327 00328 bool QgsRectangle::isFinite() const 00329 { 00330 if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) ) 00331 { 00332 return false; 00333 } 00334 if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) ) 00335 { 00336 return false; 00337 } 00338 return true; 00339 } 00340 00341 void QgsRectangle::invert() 00342 { 00343 double tmp; 00344 tmp = xmin; xmin = ymin; ymin = tmp; 00345 tmp = xmax; xmax = ymax; ymax = tmp; 00346 }