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
00126 std::vector<junction> corners((N+1)*(M+1), junction(0));
00127
00128
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
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
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
00158 if(i < N)
00159 {
00160 pv = corners[k+delta_up];
00161 T.W.insertEdge(v, pv);
00162 }
00163
00164 if(j > 0)
00165 {
00166 pv = corners[k-delta_right];
00167 T.W.insertEdge(v, pv);
00168 }
00169
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
00177 if(j < M)
00178 {
00179 const junction& nv = corners[k+delta_right];
00180 insertAfter(v, pv, nv, T.W);
00181 }
00182 }
00183
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
00222
00223
00224
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
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
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
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
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
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
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