complex_grid.h

Go to the documentation of this file.
00001 #ifndef VVELIB_FACTORY_COMPLEX_GRID_H
00002 #define VVELIB_FACTORY_COMPLEX_GRID_H
00003 
00009 #include <config.h>
00010 #include <util/vector.h>
00011 #include <factory/grid.h>
00012 #include <algorithms/insert.h>
00013 #include <algorithms/complex.h>
00014 #include <cassert>
00015 #include <cmath>
00016 
00017 #define TF_CORNER(i,j) corners[(i)*(M+1)+(j)]
00018 #define TF_TOP_CORNER(i,j) top_corner[(((i)>N)?N:(i))*(M+1)+(j)]
00019 #define TF_BOTTOM_CORNER(i,j) bottom_corner[(i)*(M+1)+(j)]
00020 
00026 namespace complex_factory
00027 {
00028   using algorithms::insertAfter;
00029   typedef util::Vector<3,double> Point3d;
00030   typedef util::Vector<2,size_t> Point2u;
00031 
00037   template <typename Complex, class Model>
00038   struct SquareFiller
00039   {
00040     IMPORT_COMPLEX_VERTICES(Complex);
00041     typedef typename Complex::cell_graph cell_graph;
00042 
00043     SquareFiller(const Point3d& bl,
00044                  const Point3d& sr,
00045                  const Point3d& su,
00046                  Complex& T,
00047                  Model& model)
00048       : bottom_left(bl)
00049       , shift_right(sr)
00050       , shift_up(su)
00051       , delta_right(sr/2)
00052       , delta_up(su/2)
00053       , T(T)
00054       , model(model)
00055     { }
00056 
00057     void initGridVertex(size_t i, size_t j, const cell& v, cell_graph&)
00058     {
00059       Point3d pos = (delta_right + (1.0*j)*shift_right) + (delta_up + (1.0*i)*shift_up);
00060       model.setPosition(v, pos);
00061       model.saveGridCellPosition(v, Point2u(i,j), T);
00062     }
00063 
00064     Point3d bottom_left, shift_right, shift_up;
00065     Point3d delta_right, delta_up;
00066     Complex& T;
00067     Model& model;
00068   };
00069 
00073   template <typename Complex, class Model>
00074   SquareFiller<Complex,Model> squareFiller(const Point3d& bottom_left,
00075                                            const Point3d& shift_right,
00076                                            const Point3d& shift_up,
00077                                            Complex& T,
00078                                            Model& model)
00079   {
00080     return SquareFiller<Complex,Model>(bottom_left, shift_right, shift_up, T, model);
00081   }
00082 
00115   template <typename Complex, class Model>
00116   bool square_grid(size_t N, size_t M, Complex& T, Model& model,
00117                    const Point3d& bottom_left = Point3d(0,0,0),
00118                    const Point3d& shift_right = Point3d(1,0,0),
00119                    const Point3d& shift_up = Point3d(0,1,0))
00120   {
00121     IMPORT_COMPLEX_TYPES(Complex);
00122     SquareFiller<Complex,Model> sf(bottom_left, shift_right, shift_up, T, model);
00123     if(!factory::square_grid(N, M, T.C, sf))
00124       return false;
00125     // Store the bottom-left corner of each cell
00126     std::vector<junction> corners((N+1)*(M+1), junction(0));
00127 
00128     // Grid of cells
00129     std::vector<std::vector<cell> > cell_grid(N, std::vector<cell>(M, cell(0)));
00130     forall(const cell& c, T.C)
00131     {
00132       Point2u ij = model.gridCellPosition(c, T);
00133       cell_grid[ij.x()][ij.y()] = c;
00134     }
00135 
00136     // Create the corners and connect them to the cells
00137     size_t k = 0;
00138     for(size_t i = 0 ; i < N+1 ; ++i)
00139       for(size_t j = 0 ; j < M+1 ; ++j, ++k)
00140       {
00141         Point3d pos = bottom_left + (1.0*i)*shift_up + (1.0*j)*shift_right;
00142         junction v;
00143         T.S.insert(v);
00144         T.W.insert(v);
00145         model.setPosition(v, pos);
00146         corners[k] = v;
00147       }
00148     // Connect the corners to each other
00149     const size_t delta_right = 1;
00150     const size_t delta_up = M+1;
00151     k = 0;
00152     for(size_t i = 0 ; i < N+1 ; ++i)
00153       for(size_t j = 0 ; j < M+1 ; ++j, ++k)
00154       {
00155         const junction& v = corners[k];
00156         junction pv(0);
00157         // First, connect up
00158         if(i < N)
00159         {
00160           pv = corners[k+delta_up];
00161           T.W.insertEdge(v, pv);
00162         }
00163         // Second, connect left
00164         if(j > 0)
00165         {
00166           pv = corners[k-delta_right];
00167           T.W.insertEdge(v, pv);
00168         }
00169         // Third, connect down
00170         if(i > 0)
00171         {
00172           const junction& nv = corners[k-delta_up];
00173           insertAfter(v, pv, nv, T.W);
00174           pv = nv;
00175         }
00176         // At last, connect right
00177         if(j < M)
00178         {
00179           const junction& nv = corners[k+delta_right];
00180           insertAfter(v, pv, nv, T.W);
00181         }
00182       }
00183     // Next, connect the cells to the corners
00184     for(size_t i = 0 ; i < N ; ++i)
00185       for(size_t j = 0 ; j < M ; ++j, ++k)
00186       {
00187         const cell& c = cell_grid[i][j];
00188         T.S.insert(c);
00189         junction c1 = TF_CORNER(i,j);
00190         junction c2 = TF_CORNER(i,j+1);
00191         junction c3 = TF_CORNER(i+1,j+1);
00192         junction c4 = TF_CORNER(i+1,j);
00193         T.S.insertEdge(c, c1);
00194         T.S.insertEdge(c, c2);
00195         T.S.spliceAfter(c, c2, c3);
00196         T.S.spliceAfter(c, c3, c4);
00197 
00198         if(i == 0)
00199         {
00200           T.S.insertEdge(c1, c);
00201           T.S.insertEdge(c2, c);
00202         }
00203         else
00204         {
00205           forall(const cell& cc, T.S.neighbors(c1))
00206           {
00207             Point2u ij = model.gridCellPosition(cc, T);
00208             if(ij.x() == i-1 and ij.y() == j)
00209             {
00210               T.S.spliceAfter(c1, cc, c);
00211               T.S.spliceBefore(c2, cc, c);
00212               break;
00213             }
00214           }
00215         }
00216 
00217         T.S.insertEdge(c3, c);
00218         T.S.insertEdge(c4, c);
00219 
00220         /*
00221            T.S.spliceAfter(c1, c2, c);
00222            T.S.spliceAfter(c2, c3, c);
00223            T.S.spliceAfter(c3, c4, c);
00224            T.S.spliceAfter(c4, c1, c);
00225            */
00226       }
00227     return true;
00228   }
00229 
00235   template <typename Complex, class Model>
00236   struct HexFiller
00237   {
00238     IMPORT_COMPLEX_TYPES(Complex);
00239 
00240     HexFiller(const Point3d& bl,
00241               const Point3d& u,
00242               const Point3d& v,
00243               Complex& T,
00244               Model& model)
00245       : bottom_left(bl)
00246       , shift_right(sqrt(3)*u)
00247       , shift_up(1.5*v)
00248       , delta_odd(std::sqrt(3)/2*u)
00249       , T(T)
00250       , model(model)
00251     { }
00252 
00253     void initGridVertex(size_t i, size_t j, const cell& v, cell_graph&)
00254     {
00255       Point3d pos = (double)i*shift_up + (double)j*shift_right;
00256       if(i%2)
00257         pos += delta_odd;
00258       model.setPosition(v, pos);
00259       model.saveGridCellPosition(v, Point2u(i,j), T);
00260     }
00261 
00262     Point3d bottom_left, shift_right, shift_up;
00263     Point3d delta_odd;
00264     Complex& T;
00265     Model& model;
00266   };
00267 
00274   template <class Graph>
00275   void connectJunction(const typename Graph::vertex_t& j,
00276                        const typename Graph::vertex_t& nj,
00277                        const typename Graph::vertex_t& pj,
00278                        Graph& S,
00279                        bool direct = true)
00280   {
00281     typedef typename Graph::vertex_t vertex;
00282     if(S.empty(j))
00283     {
00284       S.insertEdge(j, nj);
00285       return;
00286     }
00287     if(S.edge(j, pj))
00288     {
00289       if(direct)
00290         S.spliceBefore(j, pj, nj);
00291       else
00292         S.spliceAfter(j, pj, nj);
00293       return;
00294     }
00295     const vertex& v = S.anyIn(j);
00296     S.spliceBefore(j, v, nj);
00297   }
00298 
00332   template <typename Complex, class Model>
00333   bool hex_grid(size_t N, size_t M, Complex& T, Model& model,
00334                 const Point3d& bottom_left = Point3d(0,0,0),
00335                 const Point3d& u = Point3d(1,0,0),
00336                 const Point3d& v = Point3d(0,1,0))
00337   {
00338     IMPORT_COMPLEX_TYPES(Complex);
00339     HexFiller<Complex,Model> sf(bottom_left, u, v, T, model);
00340     if(!factory::hex_grid(N, M, T.C, sf))
00341       return false;
00342     size_t nb_corners = (M+1)*(N+1)-1;
00343     // Bottom-left and top-left corners
00344     std::vector<junction> bottom_corner(nb_corners,junction(0)), top_corner(nb_corners, junction(0));
00345     size_t k = 0;
00346     Point3d shift_top_left = bottom_left + v*0.5 - u*std::sqrt(3)/2;
00347     Point3d shift_bottom_left = bottom_left - v*0.5 - u*std::sqrt(3)/2;
00348     Point3d delta_pos_j = std::sqrt(3)*u;
00349     Point3d delta_pos_i = 1.5*v;
00350     Point3d odd_shift_pos = std::sqrt(3)/2*u;
00351 
00352     // Grid of cells
00353     std::vector<std::vector<cell> > cell_grid(N, std::vector<cell>(M, cell(0)));
00354     forall(const cell& c, T.C)
00355     {
00356       Point2u ij = model.gridCellPosition(c, T);
00357       cell_grid[ij.x()][ij.y()] = c;
00358     }
00359 
00360     for(size_t i = 0 ; i < N+1 ; ++i)
00361       for(size_t j = 0 ; j < M+1 ; ++j, ++k)
00362       {
00363         if(i == N and j == M)
00364           continue;
00365         junction top;
00366         junction bottom;
00367         T.W.insert(top); T.W.insert(bottom);
00368         T.S.insert(top); T.S.insert(bottom);
00369         Point3d delta_pos;
00370         delta_pos = (double)j*delta_pos_j + (double)i*delta_pos_i;
00371         if(i%2)
00372           delta_pos += odd_shift_pos;
00373         else if(i == N)
00374           delta_pos += 2*odd_shift_pos;
00375         Point3d pos_top;
00376         if(i == N)
00377         {
00378           pos_top = (double)j*delta_pos_j - v;
00379         }
00380         else
00381           pos_top = shift_top_left + delta_pos;
00382         Point3d pos_bottom = shift_bottom_left + delta_pos;
00383         model.setPosition(top, pos_top);
00384         model.setPosition(bottom, pos_bottom);
00385         bottom_corner[k] = bottom;
00386         top_corner[k] = top;
00387       }
00388 
00389     // Connect everything
00390     for(size_t i = 0 ; i < N ; ++i)
00391       for(size_t j = 0 ; j < M ; ++j)
00392       {
00393         const cell& c = cell_grid[i][j];
00394         T.S.insert(c);
00395         const junction& c1 = TF_TOP_CORNER(i,j);
00396         const junction& c2 = TF_BOTTOM_CORNER(i,j);
00397         const junction& c3 = (i%2)?TF_TOP_CORNER(i-1,j+1):TF_TOP_CORNER(i-1,j);
00398         const junction& c4 = TF_BOTTOM_CORNER(i,j+1);
00399         const junction& c5 = TF_TOP_CORNER(i,j+1);
00400         const junction& c6 = (i%2)?TF_BOTTOM_CORNER(i+1,(i==N-1)?j:j+1):TF_BOTTOM_CORNER(i+1,j);
00401         // Connect the junctions to each other
00402         connectJunction(c1, c2, c6, T.W);
00403         connectJunction(c2, c3, c1, T.W);
00404         connectJunction(c3, c4, c2, T.W);
00405         connectJunction(c4, c5, c3, T.W);
00406         connectJunction(c5, c6, c4, T.W);
00407         connectJunction(c6, c1, c5, T.W);
00408 
00409         if(i == 0)
00410         {
00411           connectJunction(c3, c2, c4, T.W, false);
00412           connectJunction(c4, c3, c5, T.W, false);
00413         }
00414         if(j == 0)
00415         {
00416           if(i%2 == 0)
00417           {
00418             if(i != 0)
00419               connectJunction(c3, c2, c4, T.W, false);
00420             if(i != N-1)
00421               connectJunction(c1, c6, c2, T.W, false);
00422           }
00423           connectJunction(c2, c1, c3, T.W, false);
00424         }
00425         if(i == N-1)
00426         {
00427           connectJunction(c1, c6, c2, T.W, false);
00428           connectJunction(c6, c5, c1, T.W, false);
00429         }
00430         if(j == M-1)
00431         {
00432           if(i%2)
00433           {
00434             if(i != N-1)
00435               connectJunction(c6, c5, c1, T.W, false);
00436             if(i != 0)
00437               connectJunction(c4, c3, c5, T.W, false);
00438           }
00439           connectJunction(c5, c4, c6, T.W, false);
00440         }
00441 
00442         // Connect the center to the junctions
00443         T.S.insertEdge(c, c1);
00444         T.S.insertEdge(c, c2);
00445         T.S.spliceAfter(c, c2, c3);
00446         T.S.spliceAfter(c, c3, c4);
00447         T.S.spliceAfter(c, c4, c5);
00448         T.S.spliceAfter(c, c5, c6);
00449 
00450         // Connect the junctions to the center
00451         if(i == 0 or j == 0)
00452         {
00453           T.S.insertEdge(c1, c);
00454           T.S.insertEdge(c2, c);
00455         }
00456         else
00457         {
00458           const cell& nc = T.S.anyIn(c1);
00459           T.S.spliceAfter(c1, nc, c);
00460           T.S.spliceBefore(c2, nc, c);
00461         }
00462         {
00463           const cell& nc = T.S.anyIn(c4);
00464           if(nc)
00465             T.S.spliceAfter(c3, nc, c);
00466           else
00467             T.S.insertEdge(c3, c);
00468         }
00469         T.S.insertEdge(c4, c);
00470         T.S.insertEdge(c5, c);
00471         T.S.insertEdge(c6, c);
00472       }
00473     return true;
00474   }
00475 }
00476 
00477 #undef TF_CORNER
00478 #undef TF_TOP_CORNER
00479 #undef TF_BOTTOM_CORNER
00480 #endif // VVELIB_FACTORY_COMPLEX_GRID_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:37:50 2013 for VVE by  doxygen 1.6.3