Segment.cpp

Go to the documentation of this file.
00001 
00002 #include <Segment.h>
00003 
00004 
00005 Segment::Segment(){}
00006 Segment::Segment(const V_3D& start_point,const V_3D& end_point)
00007 {x0=start_point;x1=end_point;}
00008 Segment::Segment(const Segment& s){x0=s.x0;x1=s.x1;}
00009 
00010 Segment::~Segment(){destroy();}
00011 
00012 int Segment::set(const V_3D _x0,const V_3D _x1){x0=_x0;x1=_x1;return 0;}
00013 const V_3D& Segment::get_start() const{return x0;}
00014 const V_3D& Segment::get_last() const{return x1;}
00015 
00016 int Segment::flip(){V_3D temp=x0;x0=x1;x1=temp;return 0;}
00017 int Segment::destroy(){x0.set(0.0,0.0,0.0);x1.set(0.0,0.0,0.0);return 0;}
00018 
00019 V_3D Segment::unit_vector() const
00020 {
00021   V_3D u=x1-x0;
00022   u = u.normalized();
00023   return u;
00024 }
00025 
00026 double Segment::length() const
00027 {return (x1-x0).norm();}
00028 
00029 V_3D Segment::closest_point(const V_3D& x) const
00030 {
00031   V_3D u=unit_vector();
00032   double proj=0.0;
00033   proj = (x-x0).dot(u);
00034   if(proj<0)
00035     return x0;
00036   else if(proj>length())
00037     return x1;
00038   else
00039     return x0+proj*u;
00040 }
00041 
00042 double Segment::distance_to_point(const V_3D& x) const
00043 {return (x-closest_point(x)).norm();}
00044 
00045 
00046 
00047 Segment Segment::closest_to_segment(const Segment& s) const
00048 {
00049 
00050   // 1. Search the closest position between the two lines
00051   //    = line perpendicular to both segments
00052   //****************************************************//
00053 
00054 
00055   // useful vectors
00056   V_3D u1,u2;
00057   V_3D A12;
00058 
00059   u1 = get_last()-get_start();
00060   u2 = s.get_last()-s.get_start();
00061   A12 = s.get_start()-get_start();
00062   
00063   double det=0.0;
00064   det = powf(u1.dot(u2),2.0) - u1.dot(u1)*u2.dot(u2);
00065 
00066   // check if the lines are parallel
00067   double epsilon=0.00001;
00068   if(fabs(det)<epsilon)
00069     {printf("Error in closest_point_in_segment, lines are almost parallel\n");exit(-1);}
00070 
00071   // distance of the intersection
00072   double s1=0.0,s2=0.0;
00073   s1 = 1/det*(-(A12.dot(u1))*(u2.dot(u2)) + (A12.dot(u2))*(u1.dot(u2)) );
00074   s2 = 1/det*(-(A12.dot(u1))*(u2.dot(u1)) + (A12.dot(u2))*(u1.dot(u1)) );
00075 
00076   V_3D A1=get_start(),A2=s.get_start();
00077   V_3D P1;P1 = A1 + s1*u1;
00078   V_3D P2;P2 = A2 + s2*u2;
00079 
00080   // check if the points (P1,P2) are inside the two segments
00081   double dot_p1=0.0,dot_p2=0.0;
00082   dot_p1 = (P1-A1).dot(u1);
00083   dot_p2 = (P2-A2).dot(u2);
00084 
00085   Segment seg;
00086   int is_valid_p1=0,is_valid_p2=0;
00087   if(dot_p1>=0 && dot_p1<=u1.dot(u1))
00088     is_valid_p1=1;
00089   if(dot_p2>=0 && dot_p2<=u2.dot(u2))
00090     is_valid_p2=1;
00091 
00092   if(is_valid_p1==1 && is_valid_p2==1)
00093     seg.set(P1,P2);
00094   else
00095     {
00096       // else the closest points are at the extremities
00097       // 9 possibilities in this cases:
00098       V_3D y0[3]={A1,A1+u1,P1};
00099       V_3D y1[3]={A2,A2+u2,P2};
00100       double min_dist=99999.99;
00101       double current_dist=0.0;
00102       int min_k1=-1,min_k2=-1;
00103       for(int k1=0;k1<3;k1++)
00104         for(int k2=0;k2<3;k2++)
00105           {
00106             current_dist=(y0[k1]-y1[k2]).norm();
00107             if(current_dist<min_dist)
00108               if(k1!=2 || (k1==2 && is_valid_p1==1))
00109                 if(k2!=2 || (k2==2 && is_valid_p2==1))
00110                   {min_dist=current_dist;min_k1=k1;min_k2=k2;}
00111           }
00112 
00113       // 9 cases
00114            if(min_k1==0 && min_k2==0) {seg.set(A1,A2);}
00115       else if(min_k1==0 && min_k2==1) {seg.set(A1,A2+u2);}
00116       else if(min_k1==0 && min_k2==2) {seg.set(A1,P2);}
00117 
00118       else if(min_k1==1 && min_k2==0) {seg.set(A1+u1,A2);}
00119       else if(min_k1==1 && min_k2==1) {seg.set(A1+u1,A2+u2);}
00120       else if(min_k1==1 && min_k2==2) {seg.set(A1+u1,P2);}
00121 
00122       else if(min_k1==2 && min_k2==0) {seg.set(P1,A2);}
00123       else if(min_k1==2 && min_k2==1) {seg.set(P1,A2+u2);}
00124       else if(min_k1==2 && min_k2==2) {seg.set(P1,P2);}
00125 
00126     }
00127   
00128   return seg;
00129 
00130 
00131 }
00132 
00133 V_3D Segment::operator()(int index) const
00134 {
00135   if(index!=0 && index!=1){printf("Error in Segment(%d), index must be 0 or 1\n",index);}
00136   if(index==0) return x0;
00137   return x1;
00138 }
00139 V_3D& Segment::operator()(int index)
00140 {
00141   if(index!=0 && index!=1){printf("Error in Segment(%d), index must be 0 or 1\n",index);}
00142   if(index==0) return x0;
00143   return x1;
00144 }
00145 V_3D Segment::operator[](int index) const
00146 {
00147   if(index!=0 && index!=1){printf("Error in Segment[%d], index must be 0 or 1\n",index);}
00148   if(index==0) return x0;
00149   return x1;
00150 }
00151 V_3D Segment::operator[](int index)
00152 {
00153   if(index!=0 && index!=1){printf("Error in Segment[%d], index must be 0 or 1\n",index);}
00154   if(index==0) return x0;
00155   return x1;
00156 }
00157 
00158 double Segment::distance_to_segment(const Segment& s) const
00159 {Segment closest = closest_to_segment(s);return closest.length();}
00160 
00161 ostream& operator << (ostream& flux, const Segment& s)
00162 {flux<<"["<<s.get_start()<<" ; "<<s.get_last()<<"]";return flux;}
00163 
00164 V_3D Segment::plane_intersection(const V_3D& n,const V_3D& _x0,int *type) const
00165 {
00166 
00167   double epsilon=0.0001;
00168   //first check if the segment is parallel to the plane
00169   V_3D AB=x1-x0;
00170   if(fabs(AB.dot(n))<epsilon)
00171     {
00172       //plane is \\ to the segment
00173       //now test if the plane pass through the line
00174       if(n.dot(_x0-x0)<epsilon)//pass through
00175         {
00176           *type=3;
00177           return V_3D(-1,-1,-1);
00178         }
00179       else//no intersection
00180         {
00181           *type=0;
00182           return V_3D(-1,-1,-1);
00183         }
00184     }
00185   
00186   //We are sure that the plane is not \\ to the segment
00187   double t=n.dot(_x0-x0)/AB.dot(n);
00188 
00189   V_3D intersection=x0+t*AB;
00190 
00191 
00192 
00193   //check if the intersection is inside the segment
00194   if(t>=0 && t<=1)
00195     {
00196       //check if its close to a vertex or not
00197       if( (intersection-x0).norm()<epsilon || (intersection-x1).norm()<epsilon)
00198         *type=2;
00199       else
00200         *type=1;
00201       return intersection;
00202     }
00203   
00204   //else outside the segment => no intersection
00205   *type=0;
00206   return intersection;
00207     
00208 }

Generated on Mon Mar 30 16:55:54 2009 by  doxygen 1.5.6