Triangle.cpp

Go to the documentation of this file.
00001 
00002 #include <Triangle.h>
00003 
00004 
00005 Triangle::Triangle(){}
00006 Triangle::Triangle(const V_3D& x0,const V_3D& x1,const V_3D& x2)
00007 {x[0]=x0;x[1]=x1;x[2]=x2;}
00008 Triangle::Triangle(const Triangle& t)
00009 {for(int k_dim=0;k_dim<3;k_dim++){x[k_dim]=t.x[k_dim];}}
00010 Triangle::~Triangle(){destroy();}
00011 
00012 int Triangle::destroy(){for(int k_dim=0;k_dim<3;k_dim++)x[k_dim].set(0.0,0.0,0.0);return 0;}
00013 
00014 V_3D  Triangle::operator()(int index) const
00015 {
00016   if(index<0 || index>2){printf("Error in operator(%d) in Triangle, index must be in [0,3]\n",index);exit(-1);}
00017   return x[index];
00018 }
00019 V_3D& Triangle::operator()(int index)
00020 {
00021   if(index<0 || index>2){printf("Error in operator(%d) in Triangle, index must be in [0,3]\n",index);exit(-1);}
00022   return x[index];
00023 }
00024 V_3D  Triangle::operator[](int index) const
00025 {
00026   if(index<0 || index>2){printf("Error in operator[%d] in Triangle, index must be in [0,3]\n",index);exit(-1);}
00027   return x[index];
00028 }
00029 V_3D  Triangle::operator[](int index)
00030 {
00031   if(index<0 || index>2){printf("Error in operator[%d] in Triangle, index must be in [0,3]\n",index);exit(-1);}
00032   return x[index];
00033 }
00034 Triangle& Triangle::operator=(const Triangle& t)
00035 {for(int k_dim=0;k_dim<3;k_dim++){x[k_dim]=t.x[k_dim];} return *this;}
00036 
00037 
00038 int Triangle::barycentric_coordinates(const V_3D& _x,double *alpha,double *beta,double *gamma) const
00039 {
00040   // check if _x is in the plane
00041   double epsilon=0.0001;
00042   double L = (_x-x[0]).dot(normal());
00043   if(L>epsilon)//not in the plane
00044     return -1;
00045 
00046 
00047   
00048   // calculate the barycentric coordinates
00049   double area_1=0.0,area_2=0.0,area_3=0.0,area_tot=0.0;
00050   area_1 = (x[1]-x[0]).area(_x-x[0]);
00051   area_2 = (x[2]-x[1]).area(_x-x[1]);
00052   area_3 = (x[0]-x[2]).area(_x-x[2]);
00053   area_tot = area();
00054 
00055   *alpha = area_1/area_tot;
00056   *beta  = area_2/area_tot;
00057   *gamma = area_3/area_tot;
00058 
00059   return 0;
00060 }
00061 
00062 int Triangle::is_vertex_inside(const V_3D _x) const
00063 {
00064   double alpha=-1.0,beta=-1.0,gamma=-1.0;
00065   if(barycentric_coordinates(_x,&alpha,&beta,&gamma)==-1) //not in plane
00066     return 0;
00067 
00068   double epsilon=0.0001;
00069   if(alpha>1.0 || beta>1.0 || gamma>1.0 || (alpha+beta+gamma-1.0)>epsilon) // outside the polygon
00070     return 0;
00071 
00072   // in the polygon
00073   return 1;
00074 }
00075 
00076 V_3D Triangle::normal() const
00077 {return (x[2]-x[0]).vector_prod(x[1]-x[0]).normalized();}
00078 
00079 double Triangle::area() const
00080 {return (x[2]-x[0]).area(x[1]-x[0]);}
00081 
00082 V_3D Triangle::closest_point(const V_3D& _x,int *type) const
00083 {
00084   double epsilon=0.00001;
00085 
00086   // First project and look if the projection is inside the triangle (barycentric coordinates)
00087   V_3D n=normal();
00088   V_3D proj = _x-((_x-x[0]).dot(n))*n;
00089 
00090   // if the proj is inside the triangle, this is the closest point
00091   if(is_vertex_inside(proj)==1)
00092     {*type=0;return proj;}
00093 
00094       
00095   // if not, take the closest line
00096   *type=1;
00097   Segment s0=get_segment(0),s1=get_segment(1),s2=get_segment(2);
00098   V_3D y0=s0.closest_point(_x),y1=s1.closest_point(_x),y2=s2.closest_point(_x);
00099   double dist_1=(y0-_x).norm(),dist_2=(y1-_x).norm(),dist_3=(y2-_x).norm();
00100   if(dist_1<=dist_2 && dist_1<=dist_3)
00101     {
00102       //check if its a vertex point
00103       for(int k=0;k<3;k++){if((y0-x[k]).norm()<epsilon) *type=2;}
00104       return y0;
00105     }
00106   else if(dist_2<=dist_1 && dist_2<=dist_3)
00107     {
00108       for(int k=0;k<3;k++){if((y1-x[k]).norm()<epsilon) *type=2;}
00109       return y1;
00110     }
00111   else 
00112     {
00113       for(int k=0;k<3;k++){if((y2-x[k]).norm()<epsilon) *type=2;}
00114       return y2;
00115     }
00116 
00117 }
00118 
00119 Segment Triangle::get_segment(int k_edge) const
00120 {
00121   if(k_edge<0 || k_edge>2)
00122     {printf("Error in get_segment(%d) in Triangle, k_edge has to be between 0 and 2\n",k_edge);exit(-1);}
00123 
00124   Segment s(x[k_edge],x[(k_edge+1)%3]);
00125   return s;
00126 }
00127 
00128 std::vector <V_3D> Triangle::plane_intersection(const V_3D& n,const V_3D& x0,int *type) const
00129 {int type_0=1,type_1=-1,type_2=1;return plane_intersection(n,x0,type,&type_0,&type_1,&type_2);}
00130 std::vector <V_3D> Triangle::plane_intersection(const V_3D& n,const V_3D& x0,int *type,int *type_0,int *type_1,int *type_2) const
00131 {
00132   Segment s0=get_segment(0),s1=get_segment(1),s2=get_segment(2);
00133   *type_0=-1,*type_1=-1,*type_2=-1;
00134   V_3D inter_0(-1.0,-1.0,-1.0),inter_1(-1.0,-1.0,-1.0),inter_2(-1.0,-1.0,-1.0);
00135 
00136   // take the intersection with the three segments of the polygon
00137   inter_0=s0.plane_intersection(n,x0,type_0);
00138   inter_1=s1.plane_intersection(n,x0,type_1);
00139   inter_2=s2.plane_intersection(n,x0,type_2);
00140 
00141   std::vector <V_3D> intersections;
00142 
00143   //1 - no intersection
00144   if(*type_0==0 && *type_1==0 && *type_2==0)
00145     {*type=0;return intersections;}
00146 
00147 
00148   //2 - parrallel
00149   if(*type_0==3){*type=3;intersections.push_back(x[0]),intersections.push_back(x[1]);return intersections;}
00150   if(*type_1==3){*type=3;intersections.push_back(x[1]),intersections.push_back(x[2]);return intersections;}
00151   if(*type_2==3){*type=3;intersections.push_back(x[2]),intersections.push_back(x[0]);return intersections;}
00152 
00153   //3 - vertex intersection (and only with a vertex)
00154   if(*type_0==2 && *type_1!=1 && *type_2!=1){*type=2;intersections.push_back(x[0]);return intersections;}
00155   if(*type_1==2 && *type_0!=1 && *type_2!=1){*type=2;intersections.push_back(x[1]);return intersections;}
00156   if(*type_2==2 && *type_0!=1 && *type_1!=1){*type=2;intersections.push_back(x[2]);return intersections;}
00157 
00158   //4 - two distinct points
00159   if( (*type_0==1 || *type_0==2) && (*type_1==1 || *type_1==2) )
00160     {*type=1;intersections.push_back(inter_0);intersections.push_back(inter_1);return intersections;}
00161   if( (*type_0==1 || *type_0==2) && (*type_2==1 || *type_2==2) )
00162     {*type=1;intersections.push_back(inter_0);intersections.push_back(inter_2);return intersections;}
00163   if( (*type_1==1 || *type_1==2) && (*type_2==1 || *type_2==2) )
00164     {*type=1;intersections.push_back(inter_1);intersections.push_back(inter_2);return intersections;}
00165 
00166   
00167   // else unknown configuration
00168   cout<<"Error in plane_intersection("<<n<<","<<x0<<") ";
00169   printf("Unknown configuration type=(%d,%d,%d)\n",*type_0,*type_1,*type_2);
00170   exit(-1);
00171 }

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