MC_triangle.cpp

Go to the documentation of this file.
00001 
00002 #include <MC_segment.hpp>
00003 #include <MC_double_vector.hpp>
00004 
00005 
00006 #include <MC_triangle.hpp>
00007 
00008 
00009 namespace mesh_conv
00010 {
00011 
00012     MC_v3d MC_triangle::normal() const
00013     {
00014 
00015         MC_v3d v0=v[1]-v[0];
00016         MC_v3d v1=v[2]-v[0];
00017 
00018         MC_v3d n=v0.cross(v1);
00019         double nn=n.norm();
00020         double epsilon=0.00000001;
00021         if(nn<epsilon)
00022         {std::cout<<"Warning in MC_triangle::normal(), from triangle "<<*this<<", normal is "<<n<<" of norm()="<<nn<<std::endl;return MC_v3d(0,0,1);}
00023         n/=nn;
00024         return n;
00025     }
00026 
00027     MC_v3d MC_triangle::barycenter() const
00028     {return 1.0/3.0*(v[0]+v[1]+v[2]);}
00029 
00030     MC_triangle::MC_triangle(){resize(3);}
00031     MC_triangle::MC_triangle(const MC_v3d& v0,const MC_v3d& v1,const MC_v3d& v2)
00032             :MC_v3d_vector(v0,v1,v2)
00033     {}
00034     MC_triangle::MC_triangle(const MC_v3d_vector& vec)
00035             :MC_v3d_vector()
00036     {
00037         if(vec.size()!=3)
00038         {std::cout<<"Error in MC_triangle::MC_triangle("<<vec<<"), size should be 3"<<std::endl;exit(-1);}
00039         resize(3);
00040         v[0]=vec[0];v[1]=vec[1];v[2]=vec[2];
00041     }
00042     MC_triangle::MC_triangle(const std::vector <MC_v3d>& vec)
00043             :MC_v3d_vector()
00044     {
00045         if(vec.size()!=3)
00046         {std::cout<<"Error in MC_triangle::MC_triangle(std::vector <MC_v3d>), size should be 3 and not "<<vec.size()<<std::endl;exit(-1);}
00047         resize(3);
00048         v[0]=vec[0];v[1]=vec[1];v[2]=vec[2];
00049     }
00050     MC_triangle::MC_triangle(const MC_triangle& p)
00051             :MC_v3d_vector(p)
00052     {v=p.v;}
00053 
00054     MC_v3d MC_triangle::closest_point(const MC_v3d& x,int *type) const
00055     {
00056 
00057         double epsilon=0.00001;
00058 
00059         // First project and look if the projection is inside the triangle (barycentric coordinates)
00060         MC_v3d n=normal();
00061         MC_v3d proj = x-((x-v[0]).dot(n))*n;
00062 
00063         // if the proj is inside the triangle, this is the closest point
00064         if(is_inside(proj)==1)
00065         {
00066             if(type!=0)
00067                 *type=0;
00068             return proj;
00069         }
00070 
00071 
00072         // if not, take the closest line
00073         if(type!=0)
00074             *type=1;
00075         MC_segment s0=segment(0),s1=segment(1),s2=segment(2);
00076         MC_v3d y0=s0.closest_point(x),y1=s1.closest_point(x),y2=s2.closest_point(x);
00077         double dist_1=(y0-x).norm(),dist_2=(y1-x).norm(),dist_3=(y2-x).norm();
00078         if(dist_1<=dist_2 && dist_1<=dist_3)
00079         {
00080             //check if its a vertex point
00081             for(int k=0;k<3;k++){if((y0-v[k]).norm()<epsilon) *type=2;}
00082             return y0;
00083         }
00084         else if(dist_2<=dist_1 && dist_2<=dist_3)
00085         {
00086             for(int k=0;k<3;k++){if((y1-v[k]).norm()<epsilon) *type=2;}
00087             return y1;
00088         }
00089         else
00090         {
00091             for(int k=0;k<3;k++){if((y2-v[k]).norm()<epsilon) *type=2;}
00092             return y2;
00093         }
00094 
00095     }
00096 
00097     bool MC_triangle::is_inside(const MC_v3d& _x) const
00098     {
00099         std::pair <MC_double_vector,bool> bar=barycentric_coordinates(_x);
00100         if(bar.second==false) //not in plane
00101             return false;
00102         double epsilon=0.0001;
00103         if(bar.first[0]>1.0 || bar.first[1]>1.0 || bar.first[2]>1.0 || (bar.first[0]+bar.first[1]+bar.first[2]-1.0)>epsilon) // outside the polygon
00104             return false;
00105 
00106         // in the polygon
00107         return true;
00108     }
00109 
00110     std::pair<MC_double_vector,bool> MC_triangle::barycentric_coordinates(const MC_v3d& x) const
00111     {
00112         // check if _x is in the plane
00113         double epsilon=0.0001;
00114         double L = (x-v[0]).dot(normal());
00115         if(L>epsilon)//not in the plane
00116             return std::pair <MC_double_vector,bool> (MC_double_vector(-1,-1,-1),false);
00117 
00118         // calculate the barycentric coordinates
00119         double area_1=MC_v3d::area(v[1]-v[0],x-v[0]);
00120         double area_2=MC_v3d::area(v[2]-v[1],x-v[1]);
00121         double area_3=MC_v3d::area(v[0]-v[2],x-v[2]);
00122         double area_tot = area();
00123 
00124         MC_double_vector b(area_1/area_tot,area_2/area_tot,area_3/area_tot);
00125         return std::pair <MC_double_vector,bool> (b,true);
00126     }
00127 
00128     MC_segment MC_triangle::segment(const int& edge_number) const
00129     {
00130         if(edge_number<0 || edge_number>2)
00131         {std::cout<<"MC_triangle::segment("<<edge_number<<"),_k_edge has to be between 0 and 2"<<std::endl;exit(-1);}
00132 
00133         return MC_segment(v[edge_number],v[(edge_number+1)%3]);
00134     }
00135 
00136     double MC_triangle::area() const
00137     {
00138         return MC_v3d::area(v[1]-v[0],v[2]-v[0]);
00139     }
00140 
00141     MC_triangle::MC_triangle(const MC_polygon& p)
00142     {
00143         if(p.size()!=3)
00144         {std::cout<<"Error in MC_triangle::MC_triangle("<<p<<"), size must be 3 and not "<<p.size()<<std::endl;exit(-1);}
00145         resize(3);
00146         v[0]=p[0];v[1]=p[1];v[2]=p[2];
00147     }
00148     std::vector<MC_triangle> MC_triangle::triangulate(const MC_polygon& p)
00149     {
00150         int N=p.size();
00151         std::vector <MC_triangle> vtri(N-2);
00152         for(int k_triangle=0;k_triangle<N-2;k_triangle++)
00153             vtri[k_triangle]=MC_triangle(p[0],p[k_triangle+1],p[k_triangle+2]);
00154         return vtri;
00155     }
00156 
00157     MC_v3d MC_triangle::segment_intersection(const MC_segment& s,int *type) const
00158     {
00159         int temp_type=0;
00160         MC_v3d i=s.plane_intersection(normal(),v[0],&temp_type);
00161 
00162         if(type!=0)
00163             *type=temp_type;
00164 
00165         if(temp_type==0 || temp_type==3)
00166             return i;
00167 
00168         if(is_inside(i)==false)
00169             if(type!=0)
00170                 *type=0;
00171 
00172         return i;
00173     }
00174 
00175     MC_v3d MC_triangle::pn_triangle(const MC_v3d_vector& X,const MC_v3d_vector& N,const MC_double_vector& x)
00176     {
00177         MC_double_vector w=MC_double_vector::zeros(9);
00178         for(int i=0;i<3;++i)
00179             for(int j=0;j<3;++j)
00180                 w[3*i+j]=(X[j]-X[i]).dot(N[i]);
00181 
00182         MC_v3d b300=X[0];
00183         MC_v3d b030=X[1];
00184         MC_v3d b003=X[2];
00185 
00186         MC_v3d b210=(2*X[0]+X[1]-w[0*3+1]*N[0])/3.0;
00187         MC_v3d b120=(2*X[1]+X[0]-w[1*3+0]*N[1])/3.0;
00188         MC_v3d b021=(2*X[1]+X[2]-w[1*3+2]*N[1])/3.0;
00189         MC_v3d b012=(2*X[2]+X[1]-w[2*3+1]*N[2])/3.0;
00190         MC_v3d b102=(2*X[2]+X[0]-w[2*3+0]*N[2])/3.0;
00191         MC_v3d b201=(2*X[0]+X[2]-w[0*3+2]*N[0])/3.0;
00192         MC_v3d E=(b210+b120+b021+b012+b102+b201)/6.0;
00193         MC_v3d V=(X[0]+X[1]+X[2])/3.0;
00194         MC_v3d b111=E+(E-V)/2.0;
00195 
00196         MC_v3d y=b300*x[0]*x[0]*x[0]+b030*x[1]*x[1]*x[1]+b003*x[2]*x[2]*x[2]+
00197                  b210*3.0*x[0]*x[0]*x[1]+b120*3.0*x[0]*x[1]*x[1]+b201*3.0*x[0]*x[0]*x[2]+
00198                  b021*3.0*x[1]*x[1]*x[2]+b102*3.0*x[0]*x[2]*x[2]+b012*3.0*x[1]*x[2]*x[2]+
00199                  b111*6.0*x[0]*x[1]*x[2];
00200 
00201         return y;
00202     }
00203 
00204     MC_matrix MC_triangle::inertia() const
00205     {
00206         MC_v3d x0=(*this)[0];
00207         MC_v3d x1=(*this)[1];
00208         MC_v3d x2=(*this)[2];
00209 
00210         double a=((x1-x0).cross(x2-x0)).norm();
00211 
00212         MC_matrix S(3,3);
00213         S(0,0)=2;S(0,1)=1;S(0,2)=1;
00214         S(1,0)=1;S(1,1)=2;S(1,2)=1;
00215         S(2,0)=1;S(2,1)=1;S(2,2)=2;
00216         S*=1.0/24.0;
00217 
00218         MC_matrix V(x0,x1,x2);
00219 
00220         MC_matrix C=a*V*S*V.transposed();
00221         MC_matrix J=C.trace()*MC_matrix(3)-C;
00222 
00223         return J;
00224     }
00225 
00226 }

Generated on Sun Apr 18 20:24:47 2010 by  doxygen 1.6.1