QGIS API Documentation  master-59fd5e0
src/core/qgsrectangle.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines