Polygon.cpp

Go to the documentation of this file.
00001 
00002 #include <Polygon.h>
00003 
00004 Polygon::Polygon() {x.resize(0);}
00005 Polygon::Polygon(const Polygon& poly) {x=poly.x;}
00006 Polygon::~Polygon() {destroy();}
00007 
00008 
00009 Polygon::Polygon(const V_3D& x0,const V_3D& x1,const V_3D& x2)
00010 {destroy();x.push_back(x0);x.push_back(x1);x.push_back(x2);}
00011 Polygon::Polygon(const V_3D& x0,const V_3D& x1,const V_3D& x2,const V_3D& x3)
00012 {destroy();x.push_back(x0);x.push_back(x1);x.push_back(x2);x.push_back(x3);}
00013 Polygon::Polygon(const std::vector <V_3D>& v)
00014 {set_polygon(v);}
00015 
00016 int Polygon::destroy() {x.resize(0);return 0;}
00017 int Polygon::size() const {return x.size();}
00018 
00019 
00020 V_3D Polygon::operator()(int index) const
00021 {
00022   if(index<0 || index>size()){printf("Error in Polygon(%d) size of polygon=%d\n",index,size());exit(-1);}
00023   return x[index];
00024 }
00025 V_3D& Polygon::operator()(int index)
00026 {
00027   if(index<0 || index>size()){printf("Error in Polygon(%d) size of polygon=%d\n",index,size());exit(-1);}
00028   return x[index];
00029 }
00030 V_3D Polygon::operator[](int index) const
00031 {
00032   if(index<0 || index>size()){printf("Error in Polygon[%d] size of polygon=%d\n",index,size());exit(-1);}
00033   return x[index];
00034 }
00035 V_3D& Polygon::operator[](int index)
00036 {
00037   if(index<0 || index>size()){printf("Error in Polygon[%d] size of polygon=%d\n",index,size());exit(-1);}
00038   return x[index];
00039 }
00040 
00041 int Polygon::set_polygon(const std::vector <V_3D>& v)
00042 {
00043   if(v.size()<=2)
00044     {printf("Error in set_polygon in Polygon, size of given polygon=%d < 3\n",v.size());exit(-1);}
00045 
00046   //copy the vector
00047   x=v;
00048 
00049   return 0;
00050 }
00051 int Polygon::set_polygon(const V_3D& x0,const V_3D& x1,const V_3D& x2)
00052 {
00053   destroy();
00054   x.push_back(x0);
00055   x.push_back(x1);
00056   x.push_back(x2);
00057   return 0;
00058 }
00059 
00060 int Polygon::add_vertex(const V_3D& v)
00061 {x.push_back(v);return 0;}
00062 int Polygon::add_vertex(double x0,double x1,double x2)
00063 {V_3D temp(x0,x1,x2);x.push_back(temp);return 0;}
00064 int Polygon::add_vertex(const std::vector <V_3D>& v)
00065 {
00066   for(unsigned int k=0;k<v.size();k++)
00067     x.push_back(v[k]);
00068   return 0;
00069 }
00070 
00071 std::vector <Polygon> Polygon::triangulate() const
00072 {
00073   int N_triangle=size()-2;
00074   std::vector <Polygon> vector_triangle(N_triangle);
00075 
00076   if(N_triangle<=0)
00077     {printf("Error in triangulate in Polygon, size of current polygon (%d) is not enough\n",size());exit(-1);}
00078 
00079   for(int k_tri=0;k_tri<N_triangle;k_tri++)
00080     {
00081       vector_triangle[k_tri].add_vertex(x[0]);
00082       vector_triangle[k_tri].add_vertex(x[k_tri+1]);
00083       vector_triangle[k_tri].add_vertex(x[k_tri+2]);
00084     }
00085   return vector_triangle;
00086 }
00087 std::vector <Triangle> Polygon::get_triangulation() const
00088 {
00089   std::vector <Polygon> polygon_set=triangulate();
00090 
00091   // convert polygon to triangles
00092   std::vector <Triangle> triangle_set;
00093   for(unsigned int k=0;k<polygon_set.size();k++)
00094     triangle_set.push_back(polygon_set[k].to_triangle());
00095   return triangle_set;
00096 }
00097 
00098 ostream& operator<<(ostream& stream,const Polygon& poly)
00099 {
00100   int N_vertex=poly.size();
00101   for(int k_vertex=0;k_vertex<N_vertex;k_vertex++)
00102     stream<<poly[k_vertex]<<endl;
00103   return stream;
00104 }
00105 
00106 Polygon& Polygon::operator=(const Polygon& poly)
00107 {
00108   x = poly.x;
00109   return *this;
00110 }
00111 
00112 V_3D Polygon::normal() const
00113 {
00114   if(size()<=2){printf("Error in normal() in Polygon, Polygon size is not ok [%d]\n",size());exit(-1);}
00115   V_3D n = ((x[1]-x[0]).vector_prod(x[2]-x[0])).normalized();
00116   return n;
00117 }
00118 
00119 
00120 Triangle Polygon::to_triangle() const
00121 {
00122   if(size()!=3){printf("Error in to_triangle, in Polygon, size is != 3 (%d)\n",size());exit(-1);}
00123   Triangle t(x[0],x[1],x[2]);
00124   return t;
00125 }
00126 
00127 
00128 double Polygon::shortest_distance_to_point(const V_3D& _x) const
00129 {V_3D y=closest_point(_x);return (y-_x).norm();}
00130 
00131 V_3D Polygon::closest_point(const V_3D& _x) const
00132 {int type=0;return closest_point(_x,&type);}
00133 
00134 V_3D Polygon::closest_point(const V_3D& _x,int *type) const
00135 {
00136   if(size()<=2){printf("Error in closest_polygon_point in Polygon, Polygon size is not ok [%d]\n",size());exit(-1);}
00137 
00138   double epsilon=0.00001;
00139   V_3D n = normal();
00140 
00141   // get the projection on the plane
00142   V_3D projection;
00143   projection = _x-((_x-x[0]).dot(n))*n;
00144   
00145   std::vector <Triangle> triangles=get_triangulation();
00146   
00147   // first, try to find if the projection is inside the polygon (in one of the triangle)
00148   for(unsigned int k=0;k<triangles.size();k++)
00149     {
00150       if(triangles[k].is_vertex_inside(projection)==1)
00151         {
00152           *type=0;
00153           return projection;
00154         }
00155     }
00156   
00157   // then, the projection is outside the polygon
00158   // find the closest edge
00159   V_3D x0,x1,closest;Segment s;double L=0.0,L_min=9999.9;
00160   int closest_edge=-1;
00161   for(int k=0;k<size();k++)
00162     {
00163       x0 = x[k];
00164       x1 = x[(k+1)%size()];
00165       s.set(x0,x1);
00166       
00167       L = s.distance_to_point(projection);
00168       if(L<L_min)
00169         {
00170           closest = s.closest_point(projection);
00171           closest_edge = k;
00172           L_min=L;
00173         }
00174     }
00175 
00176 
00177   *type = 1;
00178   //look if the closest point is inside an edge, or a vertex
00179   for(int k=0;k<size();k++)
00180     if( (closest-x[k]).norm() < epsilon) //then it is close to a vertex
00181       *type=2;
00182   return closest;
00183 }
00184 
00185 Segment Polygon::get_segment(int index) const
00186 {
00187   if(index<0 || index>=size())
00188     {printf("Error in get_segment(%d) in Polygon, size=%d\n",index,size());exit(-1);}
00189 
00190   Segment s(x[index],x[(index+1)%size()]);
00191   return s;
00192 }
00193 
00194 
00195 
00196 std::vector <V_3D> Polygon::plane_intersection(const V_3D& n,const V_3D& x0,int *type) const
00197 {std::vector <int> type_edge;return plane_intersection(n,x0,type,&type_edge);}
00198 
00199 std::vector <V_3D> Polygon::plane_intersection(const V_3D& n,const V_3D& x0,int *type,std::vector <int> *type_edge) const
00200 {
00201 
00202   std::vector <V_3D> intersections;
00203 
00204   // First, take every intersection with every segment
00205 
00206   std::vector <Segment> s;
00207   std::vector <V_3D> inter;
00208   type_edge->resize(size());
00209   for(int k=0;k<size();k++)
00210     {
00211       s.push_back(get_segment(k));
00212       inter.push_back(s[k].plane_intersection(n,x0,&((*type_edge)[k])));
00213     }
00214 
00215   
00216   // look if there is no intersection that all
00217   int is_intersection=0;
00218   for(int k=0;is_intersection==0 && k<size();k++)
00219     if((*type_edge)[k]!=0)
00220       is_intersection=1;
00221   if(is_intersection==0)//no intersection
00222     {*type=0;return intersections;}
00223 
00224   // look if there is a parralel edge
00225   for(int k=0;k<size();k++)
00226     if((*type_edge)[k]==3)
00227       {*type=3;intersections.push_back(s[k][0]);intersections.push_back(s[k][1]);return intersections;}
00228 
00229   // look if there is only one vertex in common
00230   int is_two_intersection=0;
00231   int k_vertex=-1;
00232   for(int k=0;is_two_intersection==0 && k<size();k++)
00233     {
00234       if( (*type_edge)[k]==1) is_two_intersection=1;
00235       if( (*type_edge)[k]==2) k_vertex=k;
00236     }
00237   if(is_two_intersection==0)
00238     {
00239       if(k_vertex==-1)
00240         {printf("Error in Polygon in plane_intersection, types are not corrects\n");exit(-1);}
00241       *type=2; intersections.push_back(x[k_vertex]); return intersections;
00242     }
00243   
00244 
00245   // there is two intersections
00246   int k_1=0,k_2=0;
00247   for(k_1=0;k_1<size();k_1++)
00248     for(k_2=k_1+1;k_2<size();k_2++)
00249       if( ((*type_edge)[k_1]==1||(*type_edge)[k_1]==2) && ((*type_edge)[k_2]==1||(*type_edge)[k_2]==2) )
00250         {*type=1;intersections.push_back(inter[k_1]);intersections.push_back(inter[k_2]);return intersections;}
00251 
00252 
00253   //else probleme
00254   cout<<"Error in plane_intersection("<<n<<","<<x0<<") ";
00255   printf("in Polygon, types are not correct: (");
00256   for(int k=0;k<size()-1;k++)
00257     printf("%d,",(*type_edge)[k]);
00258   printf("%d)\n",(*type_edge)[size()-1]);
00259   exit(-1);
00260 }
00261 
00262 Polygon Polygon::half_space_intersection(const V_3D& n,const V_3D& x0,int *type)
00263 {
00264   //first take the intersection of the polygon and the plane
00265   std::vector <V_3D> intersection;
00266   int type_edges;
00267   
00268   intersection = plane_intersection(n,x0,&type_edges);
00269 
00270   //check if we need to cut or not the polygon
00271   Polygon new_polygon;
00272   if(type_edges!=1) // no change or just destroy the polygon
00273     {
00274       if(((*this)[0]-x0).dot(n)<0)//check the orientation of the polygon to the plane
00275         {
00276           //negativ so there is no more polygons
00277           *type=2;
00278           new_polygon.add_vertex(V_3D(-1.0,-1.0,-1.0));
00279           return new_polygon;
00280         }
00281       else
00282         {
00283           // the polygon is unchanged
00284           *type=0;
00285           return *this;
00286         }
00287     }
00288 
00289   //else there is a modification to bring to the polygon
00290 
00291   *type=1;
00292   Segment s(intersection[0],intersection[1]);
00293   V_3D old_normal=normal();
00294 
00295   //first add every points in the correct half space
00296   //(just to be sure that we know the vertex before the line)
00297 
00298   //find the first vertex in half space
00299   int k=0;
00300   while(((*this)[k]-x0).dot(n)<0)
00301     k++;
00302   int k_2=k;
00303 
00304   int added_line=0;
00305   do
00306     {
00307       if( ((*this)[k_2]-x0).dot(n)>0 )
00308         new_polygon.add_vertex((*this)[k_2]);
00309       else if(added_line==0)
00310         {
00311           // check if the line is in the right sense (we are sure that (*this[k2-1] already exists))
00312           if( ((s[1]-s[0]).vector_prod(s[0]-(*this)[(k_2-1)<0?size()-1:k_2-1])).dot(old_normal)<0)
00313             {new_polygon.add_vertex(s[0]);new_polygon.add_vertex(s[1]);}     
00314           else{new_polygon.add_vertex(s[1]);new_polygon.add_vertex(s[0]);}
00315           added_line=1;
00316         }
00317       k_2=(k_2+1)%size();
00318     }while(k_2!=k);
00319   
00320   return new_polygon;
00321   
00322 }
00323 
00324 std::vector <Polygon> Polygon::subdivide_mid_edge() const
00325 {
00326   // the new midpoints
00327   std::vector <V_3D> mid_points;
00328   // as much mid point as there is vertices in the polygon
00329   mid_points.resize(size());
00330 
00331   int k=0,N_mid_points=size();
00332   for(k=0;k<N_mid_points;k++)
00333     mid_points[k]=0.5*(x[k]+x[(k+1)%N_mid_points]);
00334 
00335   // the new polygons
00336   std::vector <Polygon> new_polygon;
00337   // size of new_polygon = (old)N_vertex + 1
00338   new_polygon.resize(N_mid_points+1);
00339 
00340   // all triangles excepted the last on linking the mid_points
00341   for(k=0;k<N_mid_points;k++)
00342     {
00343       new_polygon[k].add_vertex(x[k]);
00344       new_polygon[k].add_vertex(mid_points[k]);
00345       new_polygon[k].add_vertex(mid_points[k-1>=0?k-1:N_mid_points-1]);
00346     }
00347   //last one linking every mid_points
00348   for(k=0;k<N_mid_points;k++)
00349     new_polygon[N_mid_points].add_vertex(mid_points[k]);
00350 
00351   
00352   return new_polygon;
00353 }
00354 
00355 
00356 std::vector <Polygon> Polygon::subdivide_barycenter_mid_edge() const
00357 {
00358 
00359   V_3D barycenter;
00360 
00361   // the new midpoints
00362   std::vector <V_3D> mid_points;
00363 
00364   // as much mid point as there is vertices in the polygon
00365   mid_points.resize(size());
00366 
00367   int k=0,N_mid_points=size();
00368   for(k=0;k<N_mid_points;k++)
00369     {
00370       mid_points[k]=0.5*(x[k]+x[(k+1)%N_mid_points]);
00371       barycenter+=x[k];
00372     }
00373   barycenter/=double(N_mid_points);
00374 
00375   std::vector <Polygon> new_polygon(N_mid_points);
00376   
00377     for(k=0;k<N_mid_points;k++)
00378     {
00379       new_polygon[k].add_vertex(x[k]);
00380       new_polygon[k].add_vertex(mid_points[k]);
00381       new_polygon[k].add_vertex(barycenter);
00382       new_polygon[k].add_vertex(mid_points[k-1>=0?k-1:N_mid_points-1]);
00383     }
00384 
00385     return new_polygon;
00386 }
00387 
00388 // V_3D Polygon::closest_segment_point(const Segment& s) const;
00389 // {
00390 
00391 //   V_3D n=normal();
00392 
00393 //   // calculate the signed distance of the two extremities
00394 //   double sign_d0=0.0;
00395 //   double sign_d1=0.0;
00396 
00397 //   double sign_0=0.0,sign_1=0.0;
00398 //   if(s[0].dot(n)<0) sign_0=-1;
00399 //   if(s[1].dot(n)<0) sign_1=-1;
00400 
00401 //   sign_d0 = shortest_distance_to_point(s[0]) * sign_0;
00402 //   sign_d1 = shortest_distance_to_point(s[1]) * sign_1;
00403 
00404   
00405   
00406 
00407 // }
00408 
00409 
00410 
00411 
00412 

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