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
00051
00052
00053
00054
00055
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
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
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
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
00097
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
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
00169 V_3D AB=x1-x0;
00170 if(fabs(AB.dot(n))<epsilon)
00171 {
00172
00173
00174 if(n.dot(_x0-x0)<epsilon)
00175 {
00176 *type=3;
00177 return V_3D(-1,-1,-1);
00178 }
00179 else
00180 {
00181 *type=0;
00182 return V_3D(-1,-1,-1);
00183 }
00184 }
00185
00186
00187 double t=n.dot(_x0-x0)/AB.dot(n);
00188
00189 V_3D intersection=x0+t*AB;
00190
00191
00192
00193
00194 if(t>=0 && t<=1)
00195 {
00196
00197 if( (intersection-x0).norm()<epsilon || (intersection-x1).norm()<epsilon)
00198 *type=2;
00199 else
00200 *type=1;
00201 return intersection;
00202 }
00203
00204
00205 *type=0;
00206 return intersection;
00207
00208 }