MC_segment.cpp

Go to the documentation of this file.
00001 
00002 #include <MC_segment.hpp>
00003 
00004 #include <MC_v3d_vector.hpp>
00005 #include <MC_double_vector.hpp>
00006 #include <MC_int_pair.hpp>
00007 
00008 namespace mesh_conv
00009 {
00010 
00011     MC_segment::MC_segment(){}
00012     MC_segment::MC_segment(const MC_v3d& start_point,const MC_v3d& end_point)
00013     {x0=start_point;x1=end_point;}
00014     MC_segment::MC_segment(const MC_segment& s){x0=s.x0;x1=s.x1;}
00015 
00016     MC_segment::~MC_segment(){}
00017 
00018 
00019     MC_v3d MC_segment::unit_vector() const {return vector().normalized();}
00020     MC_v3d MC_segment::vector() const {return x1-x0;}
00021     MC_segment MC_segment::fliped() const {return MC_segment(x1,x0);}
00022 
00023 
00024     double MC_segment::length() const {return vector().norm();}
00025     MC_v3d MC_segment::closest_point(const MC_v3d& x) const
00026     {
00027         MC_v3d u=unit_vector();
00028         double proj=0.0;
00029         proj = (x-x0).dot(u);
00030         if(proj<0)
00031             return x0;
00032         else if(proj>length())
00033             return x1;
00034         else
00035             return x0+proj*u;
00036     }
00037 
00038     double MC_segment::distance_to_point(const MC_v3d& x) const {return (x-closest_point(x)).norm();}
00039     MC_segment MC_segment::closest_to_segment(const MC_segment& s) const
00040     {
00041         //****************************************************//
00042         // 1. Search the closest position between the two lines
00043         //    = line perpendicular to both segments
00044         //****************************************************//
00045 
00046 
00047         // useful vectors
00048         MC_v3d u1,u2;
00049         MC_v3d A12;
00050 
00051         u1 = vector();
00052         u2 = s.vector();
00053         A12 = s[0]-x0;
00054 
00055         double det=0.0;
00056         det = powf(float(u1.dot(u2)),2.0) - u1.dot(u1)*u2.dot(u2);
00057 
00058         // check if the lines are parallel
00059         double epsilon=0.00001;
00060         if(fabs(det)<epsilon)
00061         {std::cout<<"Error in MC_segment::closest_to_segment(), lines are almost parallel"<<std::endl;exit(-1);}
00062 
00063         // distance of the intersection
00064         double s1=0.0,s2=0.0;
00065         s1 = 1/det*(-(A12.dot(u1))*(u2.dot(u2)) + (A12.dot(u2))*(u1.dot(u2)) );
00066         s2 = 1/det*(-(A12.dot(u1))*(u2.dot(u1)) + (A12.dot(u2))*(u1.dot(u1)) );
00067 
00068         MC_v3d A1=x0,A2=s[0];
00069         MC_v3d P1;P1 = A1 + s1*u1;
00070         MC_v3d P2;P2 = A2 + s2*u2;
00071 
00072         // check if the points (P1,P2) are inside the two segments
00073         double dot_p1=0.0,dot_p2=0.0;
00074         dot_p1 = (P1-A1).dot(u1);
00075         dot_p2 = (P2-A2).dot(u2);
00076 
00077         MC_segment seg;
00078         int is_valid_p1=0,is_valid_p2=0;
00079         if(dot_p1>=0 && dot_p1<=u1.dot(u1))
00080             is_valid_p1=1;
00081         if(dot_p2>=0 && dot_p2<=u2.dot(u2))
00082             is_valid_p2=1;
00083 
00084         if(is_valid_p1==1 && is_valid_p2==1)
00085             seg=MC_segment(P1,P2);
00086         else
00087         {
00088             // else the closest points are at the extremities
00089             // 9 possibilities in this cases: check all of these
00090             MC_v3d y0[3]={A1,A1+u1,P1};
00091             MC_v3d y1[3]={A2,A2+u2,P2};
00092             double min_dist=99999.99;
00093             double current_dist=0.0;
00094             int min_k1=-1,min_k2=-1;
00095             for(int k1=0;k1<3;k1++)
00096                 for(int k2=0;k2<3;k2++)
00097                 {
00098                 current_dist=(y0[k1]-y1[k2]).norm();
00099                 if(current_dist<min_dist)
00100                     if(k1!=2 || (k1==2 && is_valid_p1==1))
00101                         if(k2!=2 || (k2==2 && is_valid_p2==1))
00102                         {min_dist=current_dist;min_k1=k1;min_k2=k2;}
00103             }
00104 
00105             // 9 cases
00106             if(min_k1==0 && min_k2==0) {seg=MC_segment(A1,A2);}
00107             else if(min_k1==0 && min_k2==1) {seg=MC_segment(A1,A2+u2);}
00108             else if(min_k1==0 && min_k2==2) {seg=MC_segment(A1,P2);}
00109 
00110             else if(min_k1==1 && min_k2==0) {seg=MC_segment(A1+u1,A2);}
00111             else if(min_k1==1 && min_k2==1) {seg=MC_segment(A1+u1,A2+u2);}
00112             else if(min_k1==1 && min_k2==2) {seg=MC_segment(A1+u1,P2);}
00113 
00114             else if(min_k1==2 && min_k2==0) {seg=MC_segment(P1,A2);}
00115             else if(min_k1==2 && min_k2==1) {seg=MC_segment(P1,A2+u2);}
00116             else if(min_k1==2 && min_k2==2) {seg=MC_segment(P1,P2);}
00117 
00118         }
00119 
00120         return seg;
00121 
00122     }
00123 
00124 
00125     double MC_segment::distance_to_segment(const MC_segment& s) const
00126     {return closest_to_segment(s).length();}
00127 
00128     MC_v3d MC_segment::plane_intersection(const MC_v3d& n,const MC_v3d& _x0,int *type) const
00129     {
00130         double epsilon=0.00001;
00131         //first check if the segment is parallel to the plane
00132         MC_v3d AB=x1-x0;
00133         if(fabs(AB.dot(n))<epsilon)
00134         {
00135             //plane is \\ to the segment
00136             //now test if the plane pass through the line
00137             if(fabs(n.dot(_x0-x0))<epsilon)//pass through
00138             {
00139                 if(type!=0)
00140                     *type=3;
00141                 return MC_v3d(-1,-1,-1);
00142             }
00143             else//no intersection
00144             {
00145                 if(type!=0)
00146                     *type=0;
00147                 return MC_v3d(-1,-1,-1);
00148             }
00149         }
00150 
00151         //We are sure that the plane is not \\ to the segment
00152         double t=n.dot(_x0-x0)/AB.dot(n);
00153 
00154         MC_v3d intersection=x0+t*AB;
00155 
00156 
00157 
00158         //check if the intersection is inside the segment
00159         if(t>=0 && t<=1)
00160         {
00161             //check if its close to a vertex or not
00162             if( ((intersection-x0).norm()<epsilon) || ((intersection-x1).norm()<epsilon) )
00163             {if(type!=0) *type=2;}
00164             else
00165             {if(type!=0) *type=1;}
00166             return intersection;
00167         }
00168 
00169         //else outside the segment => no intersection
00170         if(type!=0) *type=0;
00171         return intersection;
00172     }
00173 
00174     bool MC_segment::is_belonging(const MC_v3d& x,int *type) const
00175     {
00176         bool belongs=0;
00177         double t = relative_position(x,&belongs);
00178         if(belongs!=1)
00179         {
00180             if(type!=0) *type=-2;
00181             return false;
00182         }
00183         else if(t<0 || t>1)
00184         {
00185             if(type!=0) *type=-1;
00186             return false;
00187         }
00188         if(type!=0) *type=1;
00189         return true;
00190     }
00191     bool MC_segment::is_aligned(const MC_v3d& x) const
00192     {
00193         double epsilon=0.0001;
00194         return ((x-x0)-(x-x0).dot(unit_vector())*unit_vector()).norm()<epsilon;
00195     }
00196     double MC_segment::relative_position(const MC_v3d& x,bool *_is_aligned) const
00197     {
00198         // check if it is aligned
00199         if(is_aligned(x)==false)
00200         {
00201             if(_is_aligned!=0)
00202                 *_is_aligned=false;
00203             return 0.0;}
00204 
00205         if(_is_aligned!=0)
00206             *_is_aligned=true;
00207         return (x-x0).dot(unit_vector())/length();
00208     }
00209     void MC_segment::assert_bounds(const int& u) const
00210     {
00211         if(u!=0 && u!=1)
00212         {std::cout<<"Error in MC_segment::assert_bounds("<<u<<"), value should be 0 or 1"<<std::endl;exit(-1);}
00213     }
00214     MC_v3d  MC_segment::operator()(const int& index) const
00215     {assert_bounds(index); if(index==0)return x0;if(index==1) return x1;exit(-1);}
00216     MC_v3d& MC_segment::operator()(const int& index)
00217     {assert_bounds(index); if(index==0)return x0;if(index==1) return x1;exit(-1);}
00218     MC_v3d  MC_segment::operator[](const int& index) const
00219     {assert_bounds(index); if(index==0)return x0;if(index==1) return x1;exit(-1);}
00220     MC_v3d& MC_segment::operator[](const int& index)
00221     {assert_bounds(index); if(index==0)return x0;if(index==1) return x1;exit(-1);}
00222 
00223     MC_v3d MC_segment::value(const double& t) const
00224     {return (1-t)*x0+t*x1;}
00225     MC_v3d_vector MC_segment::value(const MC_double_vector& t) const
00226     {return (1-t)*x0+t*x1;}
00227 
00228 
00229 
00230     std::pair<MC_v3d_vector,MC_double_vector> MC_segment::linear_sampling_intervals(const double& d_L) const
00231     {
00232         double epsilon=0.00001;
00233         if(d_L<=epsilon)
00234         {std::cout<<"Error in MC_segment::linear_sampling_intervals("<<d_L<<"), interval is too low"<<std::endl;exit(-1);}
00235 
00236         double total_length=length();
00237         int N_subdiv=int(total_length/d_L+1);
00238 
00239         return linear_sampling(N_subdiv);
00240     }
00241     std::pair<MC_v3d_vector,MC_double_vector> MC_segment::linear_sampling(const int& N) const
00242     {
00243         MC_double_vector t_value=MC_double_vector::zeros(N);
00244         MC_v3d_vector sampling=MC_v3d_vector::zeros(N);
00245         for(int k=0;k<N;k++)
00246         {
00247             double u=double(k)/double(N-1);
00248             sampling(k) = (1-u)*x0 + u*x1;
00249             t_value(k)=u;
00250         }
00251         return std::pair<MC_v3d_vector,MC_double_vector> (sampling,t_value);
00252     }
00253     MC_segment operator+(const MC_segment& s,const MC_v3d& x)
00254     {return MC_segment(s[0]+x,s[1]+x);}
00255     MC_segment operator+(const MC_v3d& x,const MC_segment& s)
00256     {return s+x;}
00257     MC_segment operator*(const MC_segment& s,const double& a)
00258     {return MC_segment(s[0]*a,s[1]*a);}
00259     MC_segment operator*(const double& a,const MC_segment& s)
00260     {return s*a;}
00261 
00262     std::ostream& operator << (std::ostream& stream, const MC_segment& s)
00263     {stream<<"["<<s[0]<<" ; "<<s[1]<<"]";return stream;}
00264 
00265     std::vector<MC_segment> MC_segment::build_segment_vector(const MC_v3d_vector& vertices,const std::vector<MC_int_pair>& constraints)
00266     {
00267         unsigned int N_vertices=vertices.size();
00268         std::vector<MC_segment> v_seg;
00269         for(int k=0,N=constraints.size();k<N;++k)
00270         {
00271             const MC_int_pair& index=constraints[k];
00272             if(index[0]>=N_vertices || index[1]>=N_vertices)
00273             {std::cout<<"Error in MC_segment::build_segment_vector(), index "<<index<<" is too large compared to N_vertex="<<N_vertices<<" at k="<<k<<std::endl;exit(-1);}
00274             v_seg.push_back(MC_segment(vertices[index[0]],vertices[index[1]]));
00275         }
00276         return v_seg;
00277     }
00278 
00279 
00280 }

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