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