Quantum GIS API Documentation  1.7.4
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 /* $Id$ */
00018 
00019 #include <algorithm>
00020 #include <cmath>
00021 #include <limits>
00022 #include <QString>
00023 #include <QTextStream>
00024 #include <qnumeric.h>
00025 
00026 #include "qgspoint.h"
00027 #include "qgsrectangle.h"
00028 #include "qgslogger.h"
00029 
00030 QgsRectangle::QgsRectangle( double newxmin, double newymin, double newxmax, double newymax )
00031     : xmin( newxmin ), ymin( newymin ), xmax( newxmax ), ymax( newymax )
00032 {
00033   normalize();
00034 }
00035 
00036 QgsRectangle::QgsRectangle( QgsPoint const & p1, QgsPoint const & p2 )
00037 {
00038   set( p1, p2 );
00039 }
00040 
00041 QgsRectangle::QgsRectangle( const QgsRectangle &r )
00042 {
00043   xmin = r.xMinimum();
00044   ymin = r.yMinimum();
00045   xmax = r.xMaximum();
00046   ymax = r.yMaximum();
00047 }
00048 
00049 void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
00050 {
00051   xmin = p1.x();
00052   xmax = p2.x();
00053   ymin = p1.y();
00054   ymax = p2.y();
00055   normalize();
00056 }
00057 
00058 void QgsRectangle::set( double xmin_, double ymin_, double xmax_, double ymax_ )
00059 {
00060   xmin = xmin_;
00061   ymin = ymin_;
00062   xmax = xmax_;
00063   ymax = ymax_;
00064   normalize();
00065 }
00066 
00067 void QgsRectangle::normalize()
00068 {
00069   if ( xmin > xmax )
00070   {
00071     std::swap( xmin, xmax );
00072   }
00073   if ( ymin > ymax )
00074   {
00075     std::swap( ymin, ymax );
00076   }
00077 } // QgsRectangle::normalize()
00078 
00079 
00080 void QgsRectangle::setMinimal()
00081 {
00082   xmin = std::numeric_limits<double>::max();
00083   ymin = std::numeric_limits<double>::max();
00084   xmax = -std::numeric_limits<double>::max();
00085   ymax = -std::numeric_limits<double>::max();
00086 }
00087 
00088 void QgsRectangle::scale( double scaleFactor, const QgsPoint * cp )
00089 {
00090   // scale from the center
00091   double centerX, centerY;
00092   if ( cp )
00093   {
00094     centerX = cp->x();
00095     centerY = cp->y();
00096   }
00097   else
00098   {
00099     centerX = xmin + width() / 2;
00100     centerY = ymin + height() / 2;
00101   }
00102   double newWidth = width() * scaleFactor;
00103   double newHeight = height() * scaleFactor;
00104   xmin = centerX - newWidth / 2.0;
00105   xmax = centerX + newWidth / 2.0;
00106   ymin = centerY - newHeight / 2.0;
00107   ymax = centerY + newHeight / 2.0;
00108 }
00109 
00110 void QgsRectangle::expand( double scaleFactor, const QgsPoint * cp )
00111 {
00112   // scale from the center
00113   double centerX, centerY;
00114   if ( cp )
00115   {
00116     centerX = cp->x();
00117     centerY = cp->y();
00118   }
00119   else
00120   {
00121     centerX = xmin + width() / 2;
00122     centerY = ymin + height() / 2;
00123   }
00124 
00125   double newWidth = width() * scaleFactor;
00126   double newHeight = height() * scaleFactor;
00127   xmin = centerX - newWidth;
00128   xmax = centerX + newWidth;
00129   ymin = centerY - newHeight;
00130   ymax = centerY + newHeight;
00131 }
00132 
00133 QgsRectangle QgsRectangle::intersect( const QgsRectangle * rect ) const
00134 {
00135   QgsRectangle intersection = QgsRectangle();
00136   //If they don't actually intersect an empty QgsRectangle should be returned
00137   if ( !rect || !intersects( *rect ) )
00138   {
00139     return intersection;
00140   }
00141 
00142   intersection.setXMinimum( xmin > rect->xMinimum() ? xmin : rect->xMinimum() );
00143   intersection.setXMaximum( xmax < rect->xMaximum() ? xmax : rect->xMaximum() );
00144   intersection.setYMinimum( ymin > rect->yMinimum() ? ymin : rect->yMinimum() );
00145   intersection.setYMaximum( ymax < rect->yMaximum() ? ymax : rect->yMaximum() );
00146   return intersection;
00147 }
00148 
00149 bool QgsRectangle::intersects( const QgsRectangle& rect ) const
00150 {
00151   double x1 = ( xmin > rect.xmin ? xmin : rect.xmin );
00152   double x2 = ( xmax < rect.xmax ? xmax : rect.xmax );
00153   if ( x1 > x2 ) return false;
00154   double y1 = ( ymin > rect.ymin ? ymin : rect.ymin );
00155   double y2 = ( ymax < rect.ymax ? ymax : rect.ymax );
00156   if ( y1 > y2 ) return false;
00157   return true;
00158 }
00159 
00160 bool QgsRectangle::contains( const QgsRectangle& rect ) const
00161 {
00162   return ( rect.xmin >= xmin && rect.xmax <= xmax && rect.ymin >= ymin && rect.ymax <= ymax );
00163 }
00164 
00165 bool QgsRectangle::contains( const QgsPoint &p ) const
00166 {
00167   return xmin <= p.x() && p.x() <= xmax &&
00168          ymin <= p.y() && p.y() <= ymax;
00169 }
00170 
00171 void QgsRectangle::combineExtentWith( QgsRectangle * rect )
00172 {
00173 
00174   xmin = (( xmin < rect->xMinimum() ) ? xmin : rect->xMinimum() );
00175   xmax = (( xmax > rect->xMaximum() ) ? xmax : rect->xMaximum() );
00176 
00177   ymin = (( ymin < rect->yMinimum() ) ? ymin : rect->yMinimum() );
00178   ymax = (( ymax > rect->yMaximum() ) ? ymax : rect->yMaximum() );
00179 
00180 }
00181 
00182 void QgsRectangle::combineExtentWith( double x, double y )
00183 {
00184 
00185   xmin = (( xmin < x ) ? xmin : x );
00186   xmax = (( xmax > x ) ? xmax : x );
00187 
00188   ymin = (( ymin < y ) ? ymin : y );
00189   ymax = (( ymax > y ) ? ymax : y );
00190 
00191 }
00192 
00193 bool QgsRectangle::isEmpty() const
00194 {
00195   return xmax <= xmin || ymax <= ymin;
00196 }
00197 
00198 QString QgsRectangle::asWktCoordinates() const
00199 {
00200   QString rep =
00201     QString::number( xmin, 'f', 16 ) + " " +
00202     QString::number( ymin, 'f', 16 ) + ", " +
00203     QString::number( xmax, 'f', 16 ) + " " +
00204     QString::number( ymax, 'f', 16 );
00205 
00206   return rep;
00207 }
00208 
00209 // Return a string representation of the rectangle with automatic or high precision
00210 QString QgsRectangle::toString( bool automaticPrecision ) const
00211 {
00212   if ( automaticPrecision )
00213   {
00214     int precision = 0;
00215     if (( width() < 1 || height() < 1 ) && ( width() > 0 && height() > 0 ) )
00216     {
00217       precision = static_cast<int>( ceil( -1.0 * log10( qMin( width(), height() ) ) ) ) + 1;
00218       // sanity check
00219       if ( precision > 20 )
00220         precision = 20;
00221     }
00222     return toString( precision );
00223   }
00224   else
00225     return toString( 16 );
00226 }
00227 
00228 // overloaded version of above fn to allow precision to be set
00229 // Return a string representation of the rectangle with high precision
00230 QString QgsRectangle::toString( int thePrecision ) const
00231 {
00232   QString rep;
00233   if ( isEmpty() )
00234     rep = "Empty";
00235   else
00236     rep = QString( "%1,%2 : %3,%4" )
00237           .arg( xmin, 0, 'f', thePrecision )
00238           .arg( ymin, 0, 'f', thePrecision )
00239           .arg( xmax, 0, 'f', thePrecision )
00240           .arg( ymax, 0, 'f', thePrecision );
00241 
00242   QgsDebugMsgLevel( QString( "Extents : %1" ).arg( rep ), 4 );
00243 
00244   return rep;
00245 }
00246 
00247 
00248 // Return the rectangle as a set of polygon coordinates
00249 QString QgsRectangle::asPolygon() const
00250 {
00251 //   QString rep = tmp.sprintf("%16f %16f,%16f %16f,%16f %16f,%16f %16f,%16f %16f",
00252 //     xmin, ymin, xmin, ymax, xmax, ymax, xmax, ymin, xmin, ymin);
00253   QString rep;
00254 
00255   QTextStream foo( &rep );
00256 
00257   foo.setRealNumberPrecision( 8 );
00258   foo.setRealNumberNotation( QTextStream::FixedNotation );
00259   // NOTE: a polygon isn't a polygon unless its closed. In the case of
00260   //       a rectangle, that means 5 points (last == first)
00261   foo <<  xmin << " " <<  ymin << ", "
00262   <<  xmin << " " <<  ymax << ", "
00263   <<  xmax << " " <<  ymax << ", "
00264   <<  xmax << " " <<  ymin << ", "
00265   <<  xmin << " " <<  ymin;
00266 
00267   return rep;
00268 
00269 } // QgsRectangle::asPolygon() const
00270 
00271 
00272 bool QgsRectangle::operator==( const QgsRectangle & r1 ) const
00273 {
00274   return ( r1.xMaximum() == xMaximum() &&
00275            r1.xMinimum() == xMinimum() &&
00276            r1.yMaximum() == yMaximum() &&
00277            r1.yMinimum() == yMinimum() );
00278 }
00279 
00280 
00281 bool QgsRectangle::operator!=( const QgsRectangle & r1 ) const
00282 {
00283   return ( ! operator==( r1 ) );
00284 }
00285 
00286 
00287 QgsRectangle & QgsRectangle::operator=( const QgsRectangle & r )
00288 {
00289   if ( &r != this )
00290   {
00291     xmax = r.xMaximum();
00292     xmin = r.xMinimum();
00293     ymax = r.yMaximum();
00294     ymin = r.yMinimum();
00295   }
00296 
00297   return *this;
00298 }
00299 
00300 
00301 void QgsRectangle::unionRect( const QgsRectangle& r )
00302 {
00303   if ( r.xMinimum() < xMinimum() ) setXMinimum( r.xMinimum() );
00304   if ( r.xMaximum() > xMaximum() ) setXMaximum( r.xMaximum() );
00305   if ( r.yMinimum() < yMinimum() ) setYMinimum( r.yMinimum() );
00306   if ( r.yMaximum() > yMaximum() ) setYMaximum( r.yMaximum() );
00307 }
00308 
00309 bool QgsRectangle::isFinite() const
00310 {
00311   if ( qIsInf( xmin ) || qIsInf( ymin ) || qIsInf( xmax ) || qIsInf( ymax ) )
00312   {
00313     return false;
00314   }
00315   if ( qIsNaN( xmin ) || qIsNaN( ymin ) || qIsNaN( xmax ) || qIsNaN( ymax ) )
00316   {
00317     return false;
00318   }
00319   return true;
00320 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines