00001
00002 #include <MC_string_helper.hpp>
00003 #include <MC_v3d.hpp>
00004 #include <cmath>
00005
00006 #include <MC_v3d_vector.hpp>
00007 #include <MC_matrix.hpp>
00008 #include <MC_quaternion.hpp>
00009 #include <MC_segment.hpp>
00010
00011
00012 namespace mesh_conv
00013 {
00014
00015 MC_v3d::MC_v3d()
00016 {v[0]=0;v[1]=0;v[2]=0;}
00017
00018 MC_v3d::MC_v3d(const double& x,const double& y,const double& z)
00019 {v[0]=x;v[1]=y;v[2]=z;}
00020
00021 MC_v3d::~MC_v3d(){}
00022
00023 MC_v3d::MC_v3d(const MC_v3d_vector& vec)
00024 {
00025 if(vec.size()==1)
00026 *this=vec.first();
00027 else
00028 {std::cout<<"Error in MC_v3d::MC_v3d(const MC_v3d_vector& "<<vec<<"), size must be 1"<<std::endl;exit(-1);}
00029 }
00030
00031 const double& MC_v3d::operator()(const int& k_dim) const
00032 {
00033 if(k_dim<0 || k_dim>2)
00034 {std::cout<<"Error in const MC_v3d("<<k_dim<<"), size must be 0,1 or 2"<<std::endl;exit(-1);}
00035 return v[k_dim];
00036 }
00037 double& MC_v3d::operator()(const int& k_dim)
00038 {
00039 if(k_dim<0 || k_dim>2)
00040 {std::cout<<"Error in MC_v3d("<<k_dim<<"), size must be 0,1 or 2"<<std::endl;exit(-1);}
00041 return v[k_dim];
00042 }
00043 const double& MC_v3d::operator[](const int& k_dim) const
00044 {
00045 if(k_dim<0 || k_dim>2)
00046 {std::cout<<"Error in const MC_v3d["<<k_dim<<"], size must be 0,1 or 2"<<std::endl;exit(-1);}
00047 return v[k_dim];
00048 }
00049 double& MC_v3d::operator[](const int& k_dim)
00050 {
00051 if(k_dim<0 || k_dim>2)
00052 {std::cout<<"Error in MC_v3d["<<k_dim<<"], size must be 0,1 or 2"<<std::endl;exit(-1);}
00053 return v[k_dim];
00054 }
00055 MC_v3d::MC_v3d(const MC_v3d& _v)
00056 {v[0]=_v[0];v[1]=_v[1];v[2]=_v[2];}
00057
00058 MC_v3d::MC_v3d(const double* _v)
00059 {v[0]=_v[0];v[1]=_v[1];v[2]=_v[2];}
00060
00061 MC_v3d MC_v3d::operator-() const
00062 {return MC_v3d(-v[0],-v[1],-v[2]);}
00063
00064
00065 MC_v3d operator+(const MC_v3d& vec,const double& to_add)
00066 {return MC_v3d(vec[0]+to_add,vec[1]+to_add,vec[2]+to_add);}
00067 MC_v3d operator-(const MC_v3d& vec,const double& to_sub)
00068 {return MC_v3d(vec[0]-to_sub,vec[1]-to_sub,vec[2]-to_sub);}
00069 MC_v3d operator*(const MC_v3d& vec,const double& to_mult)
00070 {return MC_v3d(vec[0]*to_mult,vec[1]*to_mult,vec[2]*to_mult);}
00071 MC_v3d operator*(const double& to_mult,const MC_v3d& vec)
00072 {return vec*to_mult;}
00073
00074 MC_v3d operator/(const MC_v3d& vec,const double& to_subdiv)
00075 {
00076 double epsilon=0.000000001;
00077 if(fabs(to_subdiv)<epsilon)
00078 {std::cout<<"Error in MC_v3d("<<vec<<"/"<<to_subdiv<<", divide by zero"<<std::endl;exit(-1);}
00079
00080 return MC_v3d(vec[0]/to_subdiv,vec[1]/to_subdiv,vec[2]/to_subdiv);
00081 }
00082 MC_v3d operator+(const MC_v3d& vec,const MC_v3d& to_add)
00083 {return MC_v3d(vec[0]+to_add[0],vec[1]+to_add[1],vec[2]+to_add[2]);}
00084 MC_v3d operator-(const MC_v3d& vec,const MC_v3d& to_sub)
00085 {return MC_v3d(vec[0]-to_sub[0],vec[1]-to_sub[1],vec[2]-to_sub[2]);}
00086
00087 MC_v3d& MC_v3d::operator+=(const double& to_add)
00088 {
00089 v[0]+=to_add;v[1]+=to_add;v[2]+=to_add;
00090 return *this;
00091 }
00092
00093 MC_v3d& MC_v3d::operator-=(const double& to_sub)
00094 {
00095 v[0]-=to_sub;v[1]-=to_sub;v[2]-=to_sub;
00096 return *this;
00097 }
00098 MC_v3d& MC_v3d::operator*=(const double& to_mult)
00099 {
00100 v[0]*=to_mult;v[1]*=to_mult;v[2]*=to_mult;
00101 return *this;
00102 }
00103 MC_v3d& MC_v3d::operator/=(const double& to_subdiv)
00104 {
00105 double epsilon=0.000000001;
00106 if(fabs(to_subdiv)<epsilon)
00107 {std::cout<<"Error in MC_v3d("<<*this<<"/="<<to_subdiv<<", divide by zero"<<std::endl;exit(-1);}
00108
00109 v[0]/=to_subdiv;v[1]/=to_subdiv;v[2]/=to_subdiv;
00110 return *this;
00111 }
00112 MC_v3d& MC_v3d::operator+=(const MC_v3d& to_add){
00113 v[0]+=to_add[0];v[1]+=to_add[1];v[2]+=to_add[2];
00114 return *this;
00115 }
00116 MC_v3d& MC_v3d::operator-=(const MC_v3d& to_sub){
00117 v[0]-=to_sub[0];v[1]-=to_sub[1];v[2]-=to_sub[2];return *this;
00118 }
00119
00120
00121 std::ostream& operator<<(std::ostream& stream,const MC_v3d& v)
00122 {
00123 stream<<"("<<v[0]<<","<<v[1]<<","<<v[2]<<")";
00124 return stream;
00125 }
00126
00127 MC_v3d::MC_v3d(const std::string& s)
00128 {
00129 std::vector <std::string> v_s=mesh_conv::MC_string_tokenizer::tokenize(s," (),;");
00130
00131 int number_ok=0;
00132 for(unsigned int k=0;number_ok<3 && k<v_s.size();k++)
00133 {
00134 bool is_converted=false;
00135 double temp_value=MC_string_converter::value_of<double>(v_s[k],&is_converted);
00136 if(is_converted==true)
00137 v[number_ok++]=temp_value;
00138 }
00139
00140 }
00141
00142
00143 bool operator>>(std::istream& stream,MC_v3d& vec)
00144 {
00145 int current_position=0;
00146 std::string temp_string;
00147 while(current_position<3 && stream.good())
00148 {
00149 if(stream>>temp_string)
00150 {
00151 std::vector <std::string> v_token=MC_string_tokenizer::tokenize(temp_string,",;() ");
00152
00153 for(unsigned int k=0;current_position<3 && k<v_token.size();++k)
00154 {
00155 bool is_converted=false;
00156 double temp_value=MC_string_converter::value_of<double>(v_token[k],&is_converted);
00157 if(is_converted==true)
00158 vec[current_position++]=temp_value;
00159 }
00160 }
00161 }
00162 return 0;
00163 }
00164
00165 MC_v3d& MC_v3d::scale(const double& sx,const double& sy,const double& sz)
00166 {v[0]*=sx;v[1]*=sy;v[2]*=sz;return *this;}
00167 MC_v3d MC_v3d::mask(const double& sx,const double& sy,const double& sz) const
00168 {return MC_v3d(v[0]*sx,v[1]*sy,v[2]*sz);}
00169 MC_v3d& MC_v3d::scale(const MC_v3d& scaling){v[0]*=scaling[0];v[1]*=scaling[1];v[2]*=scaling[2];return *this;}
00170 MC_v3d MC_v3d::mask(const MC_v3d& scaling) const{return MC_v3d(v[0]*scaling[0],v[1]*scaling[1],v[2]*scaling[2]);}
00171 MC_v3d& MC_v3d::scale(const double& scaling){return (*this)*=scaling;}
00172 MC_v3d MC_v3d::scale(const double& scaling) const{return (*this)*scaling;}
00173
00174 MC_v3d MC_v3d::scaled(const MC_v3d& scaling) const
00175 {return MC_v3d(v[0]*scaling[0],v[1]*scaling[1],v[2]*scaling[2]);}
00176 MC_v3d MC_v3d::scaled(const double& scaling) const
00177 {return MC_v3d(v[0]*scaling,v[1]*scaling,v[2]*scaling);}
00178
00179
00180 double MC_v3d::dot(const MC_v3d& vec) const
00181 {return v[0]*vec[0]+v[1]*vec[1]+v[2]*vec[2];}
00182 MC_v3d MC_v3d::cross(const MC_v3d& vec) const
00183 {return MC_v3d(v[1]*vec[2]-v[2]*vec[1],v[2]*vec[0]-v[0]*vec[2],v[0]*vec[1]-v[1]*vec[0]);}
00184 double MC_v3d::norm() const
00185 {return sqrt(dot(*this));}
00186 MC_v3d MC_v3d::normalized() const
00187 {
00188 double epsilon=0.000000001;
00189 double n=norm();
00190 if(n<epsilon)
00191 {
00192 return MC_v3d(0,0,1);}
00193 return (*this)/n;
00194 }
00195
00196 std::pair <MC_v3d,MC_v3d_vector> MC_v3d::normalized_with_gradient() const
00197 {
00198 MC_v3d_vector nabla=MC_v3d_vector::zeros(3);
00199
00200 double norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
00201 double epsilon=0.00000001;
00202 if(norm<epsilon)
00203 return std::pair <MC_v3d,MC_v3d_vector> (MC_v3d(0,0,1),nabla);
00204
00205 MC_v3d n_normalized=MC_v3d(v[0]/norm,v[1]/norm,v[2]/norm);
00206 nabla[0]=1/norm*(MC_v3d(1,0,0)-n_normalized*v[0]/norm);
00207 nabla[1]=1/norm*(MC_v3d(0,1,0)-n_normalized*v[1]/norm);
00208 nabla[2]=1/norm*(MC_v3d(0,0,1)-n_normalized*v[2]/norm);
00209
00210 return std::pair<MC_v3d,MC_v3d_vector> (n_normalized,nabla);
00211 }
00212
00213
00214
00215 MC_v3d& MC_v3d::operator*=(const MC_matrix& M)
00216 {M.internal_product(this); return *this;}
00217
00218 MC_v3d::MC_v3d(const MC_matrix& M)
00219 {
00220 if( ( (M.size_1()==3 || M.size_1()==4) && M.size_2()==1) ||
00221 ( (M.size_2()==3 || M.size_2()==4) && M.size_1()==1) )
00222 {v[0]=M(0);v[1]=M(1);v[2]=M(2);}
00223 }
00224
00225 MC_v3d& MC_v3d::operator=(const MC_matrix& M)
00226 {*this=MC_v3d(M);return *this;}
00227
00228 MC_v3d operator*(const MC_quaternion& q,const MC_v3d& vec)
00229 {
00230 MC_quaternion q_b=q.conjugated();
00231 MC_quaternion v_quat;
00232 v_quat.set_v3d(vec);
00233
00234 MC_quaternion result = q*v_quat*q_b;
00235 return MC_v3d(result[0],result[1],result[2]);
00236 }
00237 MC_v3d& MC_v3d::operator*=(const MC_quaternion& q)
00238 {
00239 MC_quaternion q_b=q.conjugated();
00240 MC_quaternion v_quat(*this,0);
00241 v_quat = q*v_quat*q_b;
00242 v[0]=v_quat[0];v[1]=v_quat[1];v[2]=v_quat[2];
00243 return *this;
00244 }
00245 const double* MC_v3d::pointer() const{return v;}
00246
00247 bool operator==(const MC_v3d& a1,const MC_v3d& a2)
00248 {
00249 MC_v3d_less L;
00250 if(L(a1,a2)==false && L(a2,a1)==false)
00251 return true;
00252 return false;
00253 }
00254 bool operator!=(const MC_v3d& a1,const MC_v3d& a2)
00255 {return !(a1==a2);}
00256
00257 double MC_v3d::area(const MC_v3d& v0,const MC_v3d& v1)
00258 {
00259 return (v0.cross(v1)).norm()/2.0;
00260 }
00261
00262 double MC_v3d::cotan(const MC_v3d& u0,const MC_v3d& u1)
00263 {
00264 double div=(u0.cross(u1)).norm();
00265
00266 double epsilon=0.00000001;
00267 if(div<epsilon)
00268 {std::cout<<"Error in V_3D::cotan(), points are aligned"<<std::endl;return 0.0;}
00269
00270 return (u0.dot(u1))/(div);
00271 }
00272 double* MC_v3d::pointer_unprotected() {return &v[0];}
00273
00274 double MC_v3d::angle(const MC_v3d& u0,const MC_v3d& u1)
00275 {
00276 double epsilon=0.00001;
00277 double n0=u0.norm(),n1=u1.norm();
00278 if(n0>epsilon && n1>epsilon)
00279 {
00280 double dot=u0.dot(u1)/(n0*n1);
00281 if(dot>=1.0)
00282 return 0.0;
00283 if(dot<=-1.0)
00284 return M_PI;
00285 return acos(dot);
00286 }
00287 else
00288 return 0.0;
00289 }
00290
00291 MC_v3d MC_v3d::project_on_plane(const MC_v3d& normal) const
00292 {
00293 double epsilon=0.00001;
00294 if(normal.norm()<epsilon)
00295 return *this;
00296 MC_v3d n=normal.normalized();
00297 return (*this)-(*this).dot(n)*n;
00298 }
00299
00300 MC_v3d::MC_v3d(const MC_double_vector& vec)
00301 {
00302 if(vec.size()!=3)
00303 {std::cout<<"Error in MC_v3d::MC_v3d(MC_double_vector), size ="<<vec.size()<<"!=3"<<std::endl;exit(-1);}
00304
00305 for(int k_dim=0;k_dim<3;++k_dim)
00306 v[k_dim]=vec[k_dim];
00307 }
00308
00309 std::string MC_v3d::to_string() const
00310 {
00311 std::stringstream stream;
00312 stream<<*this;
00313 return stream.str();
00314 }
00315
00316 MC_v3d MC_v3d::project_on_line(const MC_v3d& dir) const
00317 {
00318 MC_v3d u=dir.normalized();
00319 return (*this).dot(u)*u;
00320 }
00321 MC_v3d MC_v3d::project_on_line(const MC_segment& seg) const
00322 {
00323 MC_v3d u=seg.unit_vector();
00324 return seg[0]+((*this)-seg[0]).dot(u)*u;
00325 }
00326 void MC_v3d::set_zero()
00327 {v[0]=0;v[1]=0;v[2]=0;}
00328 }