Quantum GIS API Documentation  1.7.4
src/core/qgspoint.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           qgspoint.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 
00020 #include "qgspoint.h"
00021 #include "qgis.h"
00022 #include <cmath>
00023 #include <QTextStream>
00024 #include <QObject> // for tr()
00025 
00026 #include "qgsexception.h"
00027 
00028 //
00029 // QgsVector
00030 //
00031 
00032 QgsVector::QgsVector() : m_x( 0.0 ), m_y( 0.0 )
00033 {
00034 }
00035 
00036 QgsVector::QgsVector( double x, double y ) : m_x( x ), m_y( y )
00037 {
00038 }
00039 
00040 QgsVector QgsVector::operator-( void ) const
00041 {
00042   return QgsVector( -m_x, -m_y );
00043 }
00044 
00045 QgsVector QgsVector::operator*( double scalar ) const
00046 {
00047   return QgsVector( m_x * scalar, m_y * scalar );
00048 }
00049 
00050 QgsVector QgsVector::operator/( double scalar ) const
00051 {
00052   return *this * ( 1.0 / scalar );
00053 }
00054 
00055 double QgsVector::operator*( QgsVector v ) const
00056 {
00057   return m_x * v.m_x + m_y * v.m_y;
00058 }
00059 
00060 double QgsVector::length() const
00061 {
00062   return sqrt( m_x * m_x + m_y * m_y );
00063 }
00064 
00065 double QgsVector::x() const
00066 {
00067   return m_x;
00068 }
00069 
00070 double QgsVector::y() const
00071 {
00072   return m_y;
00073 }
00074 
00075 // perpendicular vector (rotated 90 counter-clockwise)
00076 QgsVector QgsVector::perpVector() const
00077 {
00078   return QgsVector( -m_y, m_x );
00079 }
00080 
00081 double QgsVector::angle( void ) const
00082 {
00083   double ang = atan2( m_y, m_x );
00084   return ang < 0.0 ? ang + 2.0 * M_PI : ang;
00085 }
00086 
00087 double QgsVector::angle( QgsVector v ) const
00088 {
00089   return v.angle() - angle();
00090 }
00091 
00092 QgsVector QgsVector::rotateBy( double rot ) const
00093 {
00094   double ang = atan2( m_y, m_x ) + rot;
00095   double len = length();
00096   return QgsVector( len * cos( ang ), len * sin( ang ) );
00097 }
00098 
00099 QgsVector QgsVector::normal() const
00100 {
00101   double len = length();
00102 
00103   if ( len == 0.0 )
00104   {
00105     throw QgsException( "normal vector of null vector undefined" );
00106   }
00107 
00108   return *this / len;
00109 }
00110 
00111 
00112 //
00113 // QgsPoint
00114 //
00115 
00116 QgsPoint::QgsPoint( const QgsPoint& p )
00117 {
00118   m_x = p.x();
00119   m_y = p.y();
00120 }
00121 
00122 QString QgsPoint::toString() const
00123 {
00124   QString rep;
00125   QTextStream ot( &rep );
00126   ot.setRealNumberPrecision( 12 );
00127   ot << m_x << ", " << m_y;
00128   return rep;
00129 }
00130 
00131 QString QgsPoint::toString( int thePrecision ) const
00132 {
00133   QString rep = QString::number( m_x, 'f', thePrecision ) + QString( "," ) +
00134                 QString::number( m_y, 'f', thePrecision );
00135   return rep;
00136 }
00137 
00138 QString QgsPoint::toDegreesMinutesSeconds( int thePrecision ) const
00139 {
00140   int myDegreesX = int( qAbs( m_x ) );
00141   float myFloatMinutesX = float(( qAbs( m_x ) - myDegreesX ) * 60 );
00142   int myIntMinutesX = int( myFloatMinutesX );
00143   float mySecondsX = float( myFloatMinutesX - myIntMinutesX ) * 60;
00144 
00145   int myDegreesY = int( qAbs( m_y ) );
00146   float myFloatMinutesY = float(( qAbs( m_y ) - myDegreesY ) * 60 );
00147   int myIntMinutesY = int( myFloatMinutesY );
00148   float mySecondsY = float( myFloatMinutesY - myIntMinutesY ) * 60;
00149 
00150   QString myXHemisphere = m_x < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
00151   QString myYHemisphere = m_y < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
00152   QString rep = QString::number( myDegreesX ) + QChar( 176 ) +
00153                 QString::number( myIntMinutesX ) + QString( "'" ) +
00154                 QString::number( mySecondsX, 'f', thePrecision ) + QString( "\"" ) +
00155                 myXHemisphere + QString( "," ) +
00156                 QString::number( myDegreesY ) + QChar( 176 ) +
00157                 QString::number( myIntMinutesY ) + QString( "'" ) +
00158                 QString::number( mySecondsY, 'f', thePrecision ) + QString( "\"" ) +
00159                 myYHemisphere;
00160   return rep;
00161 }
00162 
00163 
00164 QString QgsPoint::wellKnownText() const
00165 {
00166   return QString( "POINT(%1 %2)" ).arg( QString::number( m_x, 'f', 18 ) ).arg( QString::number( m_y, 'f', 18 ) );
00167 }
00168 
00169 double QgsPoint::sqrDist( double x, double y ) const
00170 {
00171   return ( m_x - x ) * ( m_x - x ) + ( m_y - y ) * ( m_y - y );
00172 }
00173 
00174 double QgsPoint::sqrDist( const QgsPoint& other ) const
00175 {
00176   return sqrDist( other.x(), other.y() );
00177 }
00178 
00179 double QgsPoint::azimuth( const QgsPoint& other )
00180 {
00181   double dx = other.x() - m_x;
00182   double dy = other.y() - m_y;
00183   return ( atan2( dx, dy ) * 180.0 / M_PI );
00184 }
00185 
00186 // operators
00187 bool QgsPoint::operator==( const QgsPoint & other )
00188 {
00189   if (( m_x == other.x() ) && ( m_y == other.y() ) )
00190     return true;
00191   else
00192     return false;
00193 }
00194 
00195 bool QgsPoint::operator!=( const QgsPoint & other ) const
00196 {
00197   if (( m_x == other.x() ) && ( m_y == other.y() ) )
00198     return false;
00199   else
00200     return true;
00201 }
00202 
00203 QgsPoint & QgsPoint::operator=( const QgsPoint & other )
00204 {
00205   if ( &other != this )
00206   {
00207     m_x = other.x();
00208     m_y = other.y();
00209   }
00210 
00211   return *this;
00212 }
00213 
00214 void QgsPoint::multiply( const double& scalar )
00215 {
00216   m_x *= scalar;
00217   m_y *= scalar;
00218 }
00219 
00220 int QgsPoint::onSegment( const QgsPoint& a, const QgsPoint& b ) const
00221 {
00222   //algorithm from 'graphics GEMS', A. Paeth: 'A Fast 2D Point-on-line test'
00223   if (
00224     qAbs(( b.y() - a.y() ) *( m_x - a.x() ) - ( m_y - a.y() ) *( b.x() - a.x() ) )
00225     >= qMax( qAbs( b.x() - a.x() ), qAbs( b.y() - a.y() ) )
00226   )
00227   {
00228     return 0;
00229   }
00230   if (( b.x() < a.x() && a.x() < m_x ) || ( b.y() < a.y() && a.y() < m_y ) )
00231   {
00232     return 1;
00233   }
00234   if (( m_x < a.x() && a.x() < b.x() ) || ( m_y < a.y() && a.y() < b.y() ) )
00235   {
00236     return 1;
00237   }
00238   if (( a.x() < b.x() && b.x() < m_x ) || ( a.y() < b.y() && b.y() < m_y ) )
00239   {
00240     return 3;
00241   }
00242   if (( m_x < b.x() && b.x() < a.x() ) || ( m_y < b.y() && b.y() < a.y() ) )
00243   {
00244     return 3;
00245   }
00246 
00247   return 2;
00248 }
00249 
00250 double QgsPoint::sqrDistToSegment( double x1, double y1, double x2, double y2, QgsPoint& minDistPoint ) const
00251 {
00252   double nx, ny; //normal vector
00253 
00254   nx = y2 - y1;
00255   ny = -( x2 - x1 );
00256 
00257   double t;
00258   t = ( m_x * ny - m_y * nx - x1 * ny + y1 * nx ) / (( x2 - x1 ) * ny - ( y2 - y1 ) * nx );
00259 
00260   if ( t < 0.0 )
00261   {
00262     minDistPoint.setX( x1 );
00263     minDistPoint.setY( y1 );
00264   }
00265   else if ( t > 1.0 )
00266   {
00267     minDistPoint.setX( x2 );
00268     minDistPoint.setY( y2 );
00269   }
00270   else
00271   {
00272     minDistPoint.setX( x1 + t *( x2 - x1 ) );
00273     minDistPoint.setY( y1 + t *( y2 - y1 ) );
00274   }
00275 
00276   double dist = sqrDist( minDistPoint );
00277   //prevent rounding errors if the point is directly on the segment
00278   if ( doubleNear( dist, 0.0, 0.00000001 ) )
00279   {
00280     minDistPoint.setX( m_x );
00281     minDistPoint.setY( m_y );
00282     return 0.0;
00283   }
00284   return dist;
00285 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines