diff options
Diffstat (limited to 'kpovmodeler/pmvector.cpp')
-rw-r--r-- | kpovmodeler/pmvector.cpp | 593 |
1 files changed, 593 insertions, 0 deletions
diff --git a/kpovmodeler/pmvector.cpp b/kpovmodeler/pmvector.cpp new file mode 100644 index 00000000..035f0d2b --- /dev/null +++ b/kpovmodeler/pmvector.cpp @@ -0,0 +1,593 @@ +/* +************************************************************************** + description + -------------------- + copyright : (C) 2000-2001 by Andreas Zehender + email : zehender@kde.org +************************************************************************** + +************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +**************************************************************************/ + + +#include "pmvector.h" +#include "pmmath.h" +#include "pmmatrix.h" +#include "pmdebug.h" + +#include <qtextstream.h> +#include <stdio.h> +#include <stdlib.h> + +double PMVector::s_dummy = 0; + +double& PMVector::operator[] ( int index ) +{ + if( ( index >= 0 ) && ( index < ( signed ) m_size ) ) + return m_coord[index]; + kdError( PMArea ) << "Bad index in PMVector operator []\n"; + return s_dummy; +} + +const double& PMVector::operator[] ( int index ) const +{ + if( ( index >= 0 ) && ( index < ( signed ) m_size ) ) + return m_coord[index]; + kdError( PMArea ) << "Bad index in PMVector operator []\n"; + return s_dummy; +} + +void PMVector::allocateMemory( unsigned int size ) +{ + m_size = size; + + if( m_size == 0 ) + m_coord = 0; + else + m_coord = ( double* ) malloc( sizeof( double ) * m_size ); +} + +PMVector::PMVector( const PMVector& v ) +{ + unsigned int i; + allocateMemory( v.m_size ); + + for( i = 0; i < m_size; i++ ) + m_coord[i] = v.m_coord[i]; +} + +PMVector::PMVector( ) +{ + unsigned int i; + + allocateMemory( 3 ); + + for( i = 0; i < 3; i++ ) + m_coord[i] = 0.0; +} + +PMVector::PMVector( unsigned int s ) +{ + unsigned int i; + + allocateMemory( s ); + + for( i = 0; i < s; i++ ) + m_coord[i] = 0.0; +} + +PMVector::PMVector( const double x, const double y ) +{ + allocateMemory( 2 ); + + m_coord[0] = x; + m_coord[1] = y; +} + +PMVector::PMVector( const double x, const double y, const double z ) +{ + allocateMemory( 3 ); + + m_coord[0] = x; + m_coord[1] = y; + m_coord[2] = z; +} + +PMVector::PMVector( const double x, const double y, const double z, + const double t ) +{ + allocateMemory( 4 ); + + m_coord[0] = x; + m_coord[1] = y; + m_coord[2] = z; + m_coord[3] = t; +} + +PMVector::~PMVector( ) +{ + if( m_coord ) + free( m_coord ); +} + + +void PMVector::resize( unsigned int s ) +{ + unsigned int i; + + if( s != m_size ) + { + m_coord = ( double* ) realloc( m_coord, sizeof( double ) * s ); + + for( i = m_size; i < s; i++ ) + m_coord[i] = 0.0; + + if( m_coord ) + m_size = s; + else + m_size = 0; // possibly out of memory + } +} + +void PMVector::transform( const PMMatrix& m ) +{ + (*this) = m * (*this); +} + +PMVector& PMVector::operator= ( const PMVector& p ) +{ + unsigned int i; + + resize( p.m_size ); + for( i = 0; i < m_size; i++ ) + m_coord[i] = p[i]; + return *this; +} + +PMVector& PMVector::operator= ( const double d ) +{ + unsigned int i; + + for( i = 0; i < m_size; i++ ) + m_coord[i] = d; + return *this; +} + +PMVector& PMVector::operator*= ( const PMVector& p ) +{ + unsigned int i; + + if( m_size != p.m_size ) + resize( p.m_size ); + + for( i = 0; i < m_size; i++ ) + m_coord[i] *= p[i]; + + return *this; +} + +PMVector& PMVector::operator/= ( const PMVector& p ) +{ + unsigned int i; + + if( m_size > p.m_size ) + { + kdError( PMArea ) << "Vector p is too small in PMVector& PMVector::operator/= ( const PMVector& p )\n"; + } + else + { + for( i = 0; i < m_size; i++ ) + { + if( approxZero( p[i] ) ) + kdError( PMArea ) << "Division by zero in PMVector::operator/= " << "\n"; + else + m_coord[i] *= p[i]; + } + } + + return *this; +} + +PMVector& PMVector::operator*= ( double d ) +{ + unsigned int i; + + for( i = 0; i < m_size; i++ ) + m_coord[i] *= d; + + return *this; +} + +PMVector& PMVector::operator/= ( double d ) +{ + if( approxZero( d ) ) + { + kdError( PMArea ) << "Division by zero in PMVector::operator/= " << "\n"; + } + else + { + unsigned int i; + + for( i = 0; i < m_size; i++ ) + m_coord[i] /= d; + } + + return *this; +} + +PMVector& PMVector::operator+= ( double d ) +{ + unsigned int i; + + for( i = 0; i < m_size; i++ ) + m_coord[i] += d; + + return *this; +} + +PMVector& PMVector::operator-= ( double d ) +{ + unsigned int i; + + for( i = 0; i < m_size; i++ ) + m_coord[i] -= d; + + return *this; +} + +PMVector& PMVector::operator+= ( const PMVector& p ) +{ + unsigned int i; + + if( m_size < p.m_size ) + resize( p.m_size ); + + for( i = 0; i < p.m_size; i++ ) + m_coord[i] += p[i]; + + return *this; +} + +PMVector& PMVector::operator-= ( const PMVector& p ) +{ + unsigned int i; + + if( m_size < p.m_size ) + resize( p.m_size ); + + for( i = 0; i < m_size; i++ ) + m_coord[i] -= p[i]; + + return *this; +} + +PMVector operator- ( const PMVector& p ) +{ + PMVector result( p.m_size ); + unsigned int i; + + for( i = 0; i < p.m_size; i++ ) + result[i] = -p[i]; + + return result; +} + +PMVector operator+ ( const PMVector& p1, const PMVector& p2 ) +{ + PMVector result( p1 ); + result += p2; + + return result; +} + +PMVector operator- ( const PMVector& p1, const PMVector& p2 ) +{ + PMVector result( p1 ); + result -= p2; + + return result; +} + +PMVector operator* ( const PMVector& p, const double d ) +{ + PMVector result( p.m_size ); + unsigned int i; + + for( i = 0; i < p.m_size; i++ ) + result[i] = p[i] * d; + + return result; +} + +PMVector operator/ ( const PMVector& p, const double d ) +{ + PMVector result( p.m_size ); + unsigned int i; + + if( approxZero( d ) ) + kdError( PMArea ) << "Division by zero in PMVector::operator/ ( PMVector& p, double d ) " << "\n"; + else + for( i = 0; i < p.m_size; i++ ) + result[i] = p[i] / d; + + return result; +} + +PMVector operator+ ( const PMVector& p, const double d ) +{ + PMVector result( p.m_size ); + unsigned int i; + + for( i = 0; i < p.m_size; i++ ) + result[i] = p[i] + d; + + return result; +} + +PMVector operator- ( const PMVector& p, const double d ) +{ + PMVector result( p.m_size ); + unsigned int i; + + for( i = 0; i < p.m_size; i++ ) + result[i] = p[i] - d; + + return result; +} + +PMVector operator* ( const double d, const PMVector& p ) +{ + PMVector result( p.m_size ); + unsigned int i; + + for( i = 0; i < p.m_size; i++ ) + result[i] = p[i] * d; + + return result; +} + +PMVector operator* ( const PMMatrix& m, const PMVector& p ) +{ + PMVector result( 3 ); + int c, i; + // for homogenous coordinates + double u; + + if( p.m_size != 3 ) + kdError( PMArea ) << "Vector has not size 3 in PMVector operator* ( const PMVector& p, const PMMatrix& m ) \n"; + else + { + for( c=0; c<3; c++ ) + { + result[c] = 0.0; + for( i=0; i<4; i++ ) + result[c] += m[i][c] * ( i<3 ? p[i] : 1.0 ); + } + + u = 0.0; + for( i=0; i<4; i++ ) + u += m[i][3] * ( i<3 ? p[i] : 1.0 ); + if( !approxZero( u ) ) + for( i=0; i<3; i++ ) + result[i] /= u; + } + + return result; +} + +PMVector operator* ( const PMVector& p1, const PMVector& p2 ) +{ + PMVector result( p1 ); + result *= p2; + + return result; +} + +PMVector operator/ ( const PMVector& p1, const PMVector& p2 ) +{ + PMVector result( p1 ); + result /= p2; + + return result; +} + +bool PMVector::operator== ( const PMVector& p ) const +{ + unsigned int i; + if( m_size != p.m_size ) + return false; + if( m_size == 0 ) + return true; + + for( i = 0; i < m_size; i++ ) + if( p.m_coord[i] != m_coord[i] ) + return false; + return true; +} + +bool PMVector::approxEqual( const PMVector& p, double epsilon ) const +{ + unsigned int i; + if( m_size != p.m_size ) + return false; + if( m_size == 0 ) + return true; + + for( i = 0; i < m_size; i++ ) + if( ! approx( p.m_coord[i], m_coord[i], epsilon ) ) + return false; + return true; +} + +bool PMVector::operator!= ( const PMVector& p ) const +{ + return !( *this == p ); +} + + +PMVector PMVector::cross( const PMVector& v1, const PMVector& v2 ) +{ + PMVector result; + if( ( v1.size( ) == 3 ) && ( v2.size( ) == 3 ) ) + { + result[0] = v1[1]*v2[2] - v1[2]*v2[1]; + result[1] = v1[2]*v2[0] - v1[0]*v2[2]; + result[2] = v1[0]*v2[1] - v1[1]*v2[0]; + } + else + kdError( PMArea ) << "Wrong sizes in PMVector::cross( )\n"; + + return result; +} + +double PMVector::dot( const PMVector& v1, const PMVector& v2 ) +{ + double result = 0.0; + unsigned int i; + + if( v1.size( ) == v2.size( ) ) + { + for( i = 0; i < v1.size( ); i++ ) + result += v1[i] * v2[i]; + } + else + kdError( PMArea ) << "Wrong sizes in PMVector::dot( )\n"; + + return result; +} + +double PMVector::angle( const PMVector& v1, const PMVector& v2 ) +{ + PMVector cr; + double s, c, n; + double a = 0; + int i; + + if( ( v1.size( ) == 3 ) && ( v2.size( ) == 3 ) ) + { + n = v1.abs( ) * v2.abs( ); + + if( approxZero( n ) ) + a = 0; + else + { + cr = cross( v1, v2 ); + s = cr.abs( ) / n; + + c = 0; + for( i = 0; i < 3; i++ ) + c += v1[i] * v2[i]; + + c = c / n; + + a = pmatan( s, c ); + } + } + else + kdError( PMArea ) << "Wrong sizes in PMVector::angle( )\n"; + + return a; +} + +double PMVector::abs( ) const +{ + unsigned int i; + double a = 0.0; + + for( i = 0; i < m_size; i++ ) + a += m_coord[i] * m_coord[i]; + + return sqrt( a ); +} + +PMVector PMVector::orthogonal( ) const +{ + PMVector result; + double l, rl; + + l = abs( ); + if( approxZero( l ) ) + { + kdError( PMArea ) << "Can't calculate an orthogonal vector from a null vector\n"; + return PMVector( 1, 0, 0 ); + } + + result = cross( (*this) / l, PMVector( 0, 0, 1 ) ); + rl = result.abs( ); + if( rl < 0.001 ) + { + result = cross( (*this) / l, PMVector( 1, 0, 0 ) ); + rl = result.abs( ); + } + return result / rl; +} + +QString PMVector::serialize( ) const +{ + QString result; + QTextStream str( &result, IO_WriteOnly ); + unsigned int i; + + if( m_size > 0 ) + { + str << '<'; + for( i = 0; i < m_size; i++ ) + { + if( i > 0 ) + str << ", "; + str << m_coord[i]; + } + str << '>'; + } + else + kdError( PMArea ) << "Can't serialize a vector with size 0\n"; + + return result; +} + +QString PMVector::serializeXML( ) const +{ + QString result; + QTextStream str( &result, IO_WriteOnly ); + unsigned int i; + + if( m_size > 0 ) + { + for( i = 0; i < m_size; i++ ) + { + if( i > 0 ) + str << ' '; + str << m_coord[i]; + } + } + else + kdError( PMArea ) << "Can't serialize a vector with size 0\n"; + + return result; +} + +bool PMVector::loadXML( const QString& str ) +{ + int i; + int size = str.contains( ' ' ) + 1; + QString tmp( str ); + QTextStream s( &tmp, IO_ReadOnly ); + QString val; + bool ok; + + resize( size ); + for( i = 0; i < size; i++ ) + { + s >> val; + m_coord[i] = val.toDouble( &ok ); + if( !ok ) + return false; + } + return true; +} |