Quantum GIS API Documentation  1.8
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 <QString>
00022 #include <QTextStream>
00023 #include <qnumeric.h>
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 } // QgsRectangle::normalize()
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   // scale from the center
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   // scale from the center
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   //If they don't actually intersect an empty QgsRectangle should be returned
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 )
00153     return false;
00154   double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
00155   double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
00156   if ( y1 > y2 )
00157     return false;
00158   return true;
00159 }
00160 
00161 bool QgsRectangle::contains( const QgsRectangle& rect ) const
00162 {
00163   return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
00164 }
00165 
00166 bool QgsRectangle::contains( const QgsPoint &p ) const
00167 {
00168   return xmin <= p.x() && p.x() <= xmax &&
00169          ymin <= p.y() && p.y() <= ymax;
00170 }
00171 
00172 void QgsRectangle::combineExtentWith( QgsRectangle * rect )
00173 {
00174 
00175   xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
00176   xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
00177 
00178   ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
00179   ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
00180 
00181 }
00182 
00183 void QgsRectangle::combineExtentWith( double x, double y )
00184 {
00185 
00186   xmin = (( xmin < x ) ? xmin : x );
00187   xmax = (( xmax > x ) ? xmax : x );
00188 
00189   ymin = (( ymin < y ) ? ymin : y );
00190   ymax = (( ymax > y ) ? ymax : y );
00191 
00192 }
00193 
00194 bool QgsRectangle::isEmpty() const
00195 {
00196   return xmax <= xmin || ymax <= ymin;
00197 }
00198 
00199 QString QgsRectangle::asWktCoordinates() const
00200 {
00201   QString rep =
00202     QString::number( xmin, 'f', 16 ) + " " +
00203     QString::number( ymin, 'f', 16 ) + ", " +
00204     QString::number( xmax, 'f', 16 ) + " " +
00205     QString::number( ymax, 'f', 16 );
00206 
00207   return rep;
00208 }
00209 
00210 // Return a string representation of the rectangle with automatic or high precision
00211 QString QgsRectangle::toString( bool automaticPrecision ) const
00212 {
00213   if ( automaticPrecision )
00214   {
00215     int precision = 0;
00216     if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
00217     {
00218       precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
00219       // sanity check
00220       if ( precision > 20 )
00221         precision = 20;
00222     }
00223     return toString( precision );
00224   }
00225   else
00226     return toString( 16 );
00227 }
00228 
00229 // overloaded version of above fn to allow precision to be set
00230 // Return a string representation of the rectangle with high precision
00231 QString QgsRectangle::toString( int thePrecision ) const
00232 {
00233   QString rep;
00234   if ( isEmpty() )
00235     rep = "Empty";
00236   else
00237     rep = QString( "%1,%2 : %3,%4" )
00238           .arg( xmin, 0, 'f', thePrecision )
00239           .arg( ymin, 0, 'f', thePrecision )
00240           .arg( xmax, 0, 'f', thePrecision )
00241           .arg( ymax, 0, 'f', thePrecision );
00242 
00243   QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
00244 
00245   return rep;
00246 }
00247 
00248 
00249 // Return the rectangle as a set of polygon coordinates
00250 QString QgsRectangle::asPolygon() const
00251 {
00252 //   QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
00253 //     xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
00254   QString rep;
00255 
00256   QTextStream foo( &rep );
00257 
00258   foo.setRealNumberPrecision( 8 );
00259   foo.setRealNumberNotation( QTextStream::FixedNotation );
00260   // NOTE: a polygon isn't a polygon unless its closed. In the case of
00261   //       a rectangle, that means 5 points (last == first)
00262   foo <<  xmin << " " <<  ymin << ", "
00263   <<  xmin << " " <<  ymax << ", "
00264   <<  xmax << " " <<  ymax << ", "
00265   <<  xmax << " " <<  ymin << ", "
00266   <<  xmin << " " <<  ymin;
00267 
00268   return rep;
00269 
00270 } // QgsRectangle::asPolygon() const
00271 
00272 
00273 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
00274 {
00275   return ( r1.xMaximum() == xMaximum() &&
00276            r1.xMinimum() == xMinimum() &&
00277            r1.yMaximum() == yMaximum() &&
00278            r1.yMinimum() == yMinimum() );
00279 }
00280 
00281 
00282 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
00283 {
00284   return ( ! operator==( r1 ) );
00285 }
00286 
00287 
00288 QgsRectangle & QgsRectangle::operator=( const QgsRectangle & r )
00289 {
00290   if ( &r != this )
00291   {
00292     xmax = r.xMaximum();
00293     xmin = r.xMinimum();
00294     ymax = r.yMaximum();
00295     ymin = r.yMinimum();
00296   }
00297 
00298   return *this;
00299 }
00300 
00301 
00302 void QgsRectangle::unionRect( const QgsRectangle& r )
00303 {
00304   if ( r.xMinimum() < xMinimum() )
00305     setXMinimum( r.xMinimum() );
00306   if ( r.xMaximum() > xMaximum() )
00307     setXMaximum( r.xMaximum() );
00308   if ( r.yMinimum() < yMinimum() )
00309     setYMinimum( r.yMinimum() );
00310   if ( r.yMaximum() > yMaximum() )
00311     setYMaximum( r.yMaximum() );
00312 }
00313 
00314 bool QgsRectangle::isFinite() const
00315 {
00316   if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
00317   {
00318     return false;
00319   }
00320   if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
00321   {
00322     return false;
00323   }
00324   return true;
00325 }
00326 
00327 void QgsRectangle::invert()
00328 {
00329   double tmp;
00330   tmp = xmin; xmin = ymin; ymin = tmp;
00331   tmp = xmax; xmax = ymax; ymax = tmp;
00332 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines