/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/Vector.h" #include "mg/Position.h" #include "mg/Unit_vector.h" #include "mg/Tolerance.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif //Implemetation of class Vector. // <<< 1. Constructor >>> //void Constructor MGVector::MGVector(int dim) :m_sdim(dim),m_element(m_data),m_length(-1.) { if(dim>3) m_element=new double[dim]; if(!dim) m_length=0.; } //Construct 2D vector by providing each element data. MGVector::MGVector ( double x, double y) :m_sdim(2),m_element(m_data),m_length(-1.) { m_element[0]=x; m_element[1]=y; } // x,y,zを指定して3Dベクトルを生成する MGVector::MGVector(double x, double y, double z) :m_sdim(3),m_element(m_data),m_length(-1.) { m_element[0]=x; m_element[1]=y; m_element[2]=z; } // x,y,z, wを指定して4Dベクトルを生成する MGVector::MGVector(double x, double y, double z, double w) :m_sdim(4),m_element(new double[4]),m_length(-1.) { m_element[0]=x; m_element[1]=y; m_element[2]=z; m_element[3]=w; } // 初期値 v ですべてのエレメントを初期化してベクトルを生成する。 MGVector::MGVector(int dim, double v) :m_sdim(dim),m_element(m_data),m_length(-1.) { if(dim>3) m_element=new double[dim]; for(int i=0; i3) m_element=new double[dim]; for(int i=0; i3) m_element=new double[dimd]; for(i=0; i3) m_element=new double[dim]; assert (dim>0 && start1=dim) i=0; if(j>=dim2) j=0; } while(k++=dim) i=0; } if(dim MGVector::MGVector(const std::vector& darrays) :m_sdim((int)darrays.size()),m_element(m_data),m_length(-1.){ if(m_sdim>3) m_element=new double[m_sdim]; for(int i=0; i MGVector::MGVector(const std::valarray& darrays) :m_sdim(darrays.size()),m_element(m_data),m_length(-1.){ if(m_sdim>3) m_element=new double[m_sdim]; for(int i=0; i3) m_element=new double[m_sdim]; else m_element=m_data; for(int i=0; i3){ delete[] m_element; m_element=m_data; } for(i=0; i3){ if(m_sdim>3) delete[] m_element; m_element=new double[dim]; } for(i=0; i=dim2){ for(i=0; i=dim2){ for(i=0; i=0.) m_length*=fabs(scale); return *this; } //ベクタの外積 //vector product of two vectors. MGVector operator*(const MGVector& vec1,const MGVector& vec2){ MGVector v(vec1); return v*=vec2; } // ベクトルの外積を行い自身のベクトルとする MGVector& MGVector::operator*= (const MGVector &vec2){ double d0,d1,d2; int dim=sdim(), dim2=vec2.sdim(); if(dim3, find three id of this and vec2 that construct //3D vectors whose inner products are zero, //and whose vector products has maximum vector length. int i,j,k, i1,j1,k1; double v10,v11,v12, v20,v21,v22; double d0s,d1s,d2s; double dmaxt,dmaxs=-1.; for(i=0; idmaxs){ dmaxs=dmaxt; i1=i; j1=j; k1=k; d0s=d0; d1s=d1; d2s=d2; } } } } double sa=sangle(vec2); double v1v2stheta=len()*vec2.len()*sa; double vlen=sqrt(dmaxs); if(m_sdim>3) delete[] m_element; m_sdim=k1+1; m_length=-1.; if(m_sdim<=3) m_element=m_data; else m_element=new double[m_sdim]; for(i=0; idim2) dim=dim2; double product=0.; for(int i=0; i0.) new_vec.m_length=vec1.m_length/fabs(scale); return new_vec; } // スカラーの除算を行い自身のベクトルとする MGVector& MGVector::operator/= (double scalar){ for(int i=0; i0.) m_length/=fabs(scalar); return *this; } // 与えられたベクトルの成分の値を比較し、同じであれば TRUE を返却 //Test if two vectors are equal. bool operator==(const MGVector& v1,const MGVector& v2){ // ベクトルの差分を取得し、そのベクトルが0ベクトルの時等しい double len1=v1.len(), len2=v2.len(); double dif=(v1 - v2 ).len(); if(len1>=len2){ if(len1<=MGTolerance::mach_zero()) return 1; else return MGRZero2(dif,len1); }else{ if(len2<=MGTolerance::mach_zero()) return 1; else return MGRZero2(dif,len2); } } //Member Function // // 自身のベクトルと与えられたベクトルのなす角度を Radian で返却 //Compute angle in radian of two vectors. // 0<= angle 3 || vec2.sdim()>3) return acos(ca); double sa=sangle(vec2); // Note that sa >=0 always holds. if(ca>=sa) angle=asin(sa); // 0<= <=pai/4. else if(ca>=0. && sa>=ca) angle=acos(ca); // pai/4 <= <=pai/2. else if(sa>=-ca) angle=acos(ca); // pai/2<= <=3*pai/4. else angle=mgPAI-asin(sa); // 3*pai/4<= <=pai. return angle; } //Compute angle in radian measured from this to v2 around the normal N. //The angle's range is 0<= angle <2*pai. //Although N is assumed to be parallel to N2=(*this)*v2, N may not perpendicular //to v1 and v2, in which case, the projected N to N2 is used to measure the angle. //v1.angle2pai(v2,N)+v2.angle2pai(v1,N)=2*pai always holds. double MGVector::angle2pai(const MGVector& v2, const MGVector& N)const{ double ca=cangle(v2); double sa=sangle(v2); // Note that sa >=0 always holds. MGVector v1v2=(*this)*v2; if(v1v2%N<0.) sa*=-1.; return MGAngle(ca,sa); } // 自身のベクトルと与えられたベクトルのなす角度を cosΘ で返却する // 自身か与えられたベクトルが零ベクトルの時は、cosΘは 1.0 とする double MGVector::cangle ( const MGVector & vec2 ) const { double cos_theta; double ll=len()*vec2.len(); if(MGMZero(ll)) cos_theta=1.0; else{ cos_theta = (*this)%vec2; cos_theta/=ll; } return cos_theta; } //Clear all the elements by the value init. MGVector& MGVector::clear(double init){ for(int i=0; isd) sd=sd2; MGVector vec(sd); for(int i=0; i3){ for(int i=0; i3) delete[] m_element; m_element=data; } } m_sdim=new_sdim; m_length=-1.; } // 自身のベクトルと与えられたベクトルのなす角度の sinΘ の絶対値を返却する double MGVector::sangle(const MGVector &vec2) const{ double sin_theta; // 自身か与えられたベクトルが零ベクトルの場合 sinΘを0.0 にする double len12=len()*vec2.len(); if(MGMZero(len12)) sin_theta = 0.0; else{ if(sdim()<=3 && vec2.sdim()<=3){ sin_theta = ((*this)*vec2).len()/len12; } else { sin_theta=sin(angle(vec2)); } } return sin_theta; } //Set this as a null vector. void MGVector::set_null(){ if(m_sdim>3) delete[] m_element; m_element=m_data; m_sdim=0; m_length=-1; } //Change this to a unit vector. void MGVector::set_unit(){ int dim=sdim(); if(!dim){(*this)=MGUnit_vector(); return;} double length=len(); // 自身のベクトルが零ベクトルの時はデフォルトベクトルを生成 int i; if(MGMZero(length)){ for(i=0; in1) len=n1; for(int n=0; n=n1) i=0; if(j>=n2) j=0; m_element[i++]=vec2.ref(j++); } m_length=-1.; } //swap the coordinates. //swap coordinates (i) and (j). void MGVector::swap(int i, int j){ assert(i