Contains functions to initialise a complex. More...
Classes | |
struct | HexFiller |
For internal use only! More... | |
class | ObjReaderError |
Error object returned by the complex_factory::objreader functions. More... | |
struct | SquareFiller |
For internal use only! More... | |
Typedefs | |
typedef util::Vector< 2, size_t > | Point2u |
typedef util::Vector< 3, double > | Point3d |
Functions | |
template<class Graph > | |
void | connectJunction (const typename Graph::vertex_t &j, const typename Graph::vertex_t &nj, const typename Graph::vertex_t &pj, Graph &S, bool direct=true) |
Connect j to nj knowing than pj is the junction before j in the current cell. | |
template<typename Complex , class Model > | |
bool | hex_grid (size_t N, size_t M, Complex &T, Model &model, const Point3d &bottom_left=Point3d(0, 0, 0), const Point3d &u=Point3d(1, 0, 0), const Point3d &v=Point3d(0, 1, 0)) |
Create a hexagonal grid with N lines and M columns. | |
template<class CellComplex , class Model > | |
ObjReaderError | objreader (std::string filename, CellComplex &T, Model &model) |
Convenience methods that read a Wavefront OBJ file. | |
template<class CellComplex , class Model > | |
ObjReaderError | objreader (const QString &filename, CellComplex &T, Model &model) |
Convenience methods that read a Wavefront OBJ file. | |
template<class CellComplex , class Model > | |
ObjReaderError | objreader (QTextStream &content, CellComplex &T, Model &model) |
Read a Wavefront OBJ file describing a surface and return the complex representing it. | |
template<typename Complex , class Model > | |
bool | square_grid (size_t N, size_t M, Complex &T, Model &model, const Point3d &bottom_left=Point3d(0, 0, 0), const Point3d &shift_right=Point3d(1, 0, 0), const Point3d &shift_up=Point3d(0, 1, 0)) |
Create a square grid with N lines and M columns. | |
template<typename Complex , class Model > | |
SquareFiller< Complex, Model > | squareFiller (const Point3d &bottom_left, const Point3d &shift_right, const Point3d &shift_up, Complex &T, Model &model) |
Create a square filler. |
Contains functions to initialise a complex.
void complex_factory::connectJunction | ( | const typename Graph::vertex_t & | j, | |
const typename Graph::vertex_t & | nj, | |||
const typename Graph::vertex_t & | pj, | |||
Graph & | S, | |||
bool | direct = true | |||
) | [inline] |
Connect j
to nj
knowing than pj
is the junction before j
in the current cell.
Definition at line 275 of file complex_grid.h.
Referenced by hex_grid().
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 }
bool complex_factory::hex_grid | ( | size_t | N, | |
size_t | M, | |||
Complex & | T, | |||
Model & | model, | |||
const Point3d & | bottom_left = Point3d(0,0,0) , |
|||
const Point3d & | u = Point3d(1,0,0) , |
|||
const Point3d & | v = Point3d(0,1,0) | |||
) | [inline] |
Create a hexagonal grid with N lines and M columns.
N | Number of lines | |
M | Number of columns | |
G | Graph to initialize as a grid | |
m | Model containing the initialization functions | |
bottom_left | Position of the center of the bottom-left cell | |
u | Vector describing the reference system. if u=(1,0,0) and v=(0,1,0), then the hexagon drawn would be of radius 1 and placed vertically. | |
v | Vector describing the reference system. |
The model should contain this method:
void saveGridCellPosition(const cell& c, Point2u pos, Complex&)
Point2u gridCellPosition(const cell& c, Complex&)
The neighbors are oriented in that order: bottom -> right -> top -> left
With the bottom-left corner being the one of coordinate (0,0).
The graph is cleared at the beginning of the process
Definition at line 333 of file complex_grid.h.
References connectJunction(), forall, factory::hex_grid(), IMPORT_COMPLEX_TYPES, util::Vector< dim, T >::x(), and util::Vector< dim, T >::y().
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 }
ObjReaderError complex_factory::objreader | ( | std::string | filename, | |
CellComplex & | T, | |||
Model & | model | |||
) | [inline] |
Convenience methods that read a Wavefront OBJ file.
Definition at line 461 of file objreader.h.
References QString::fromLocal8Bit(), and objreader().
00462 { 00463 QString fn = QString::fromLocal8Bit(filename.c_str()); 00464 return objreader(fn, T, model); 00465 }
ObjReaderError complex_factory::objreader | ( | const QString & | filename, | |
CellComplex & | T, | |||
Model & | model | |||
) | [inline] |
Convenience methods that read a Wavefront OBJ file.
Definition at line 444 of file objreader.h.
References objreader(), and QFile::open().
00445 { 00446 QFile f(filename); 00447 if(!f.open(QIODevice::ReadOnly)) 00448 { 00449 return ObjReaderError(ObjReaderError::CANNOT_OPEN_FILE, f.errorString()); 00450 } 00451 QTextStream ts(&f); 00452 return objreader(ts, T, model); 00453 }
ObjReaderError complex_factory::objreader | ( | QTextStream & | content, | |
CellComplex & | T, | |||
Model & | model | |||
) | [inline] |
Read a Wavefront OBJ file describing a surface and return the complex representing it.
content | Stream containing the OBJ file | |
T | Complex to fill with the OBJ file mesh | |
model | Object containing needed methods |
This version interpret vertices, faces and normals on vertices.
The model
object should include, in addition to the methods required by the complex object, the following methods:
void setVertexId(const junction& v, int id);
Associate the identifier id
with the vertex v
. The identifiers for faces and junctions are independant. Typically, the id will be store in the vertex itself.
void setFaceId(const cell& f, int id);
Associate the identifier id
with the face f
. The identifiers for faces and junctions are independant. Typically, the id will be store in the face itself.
int vertexId(const junction& v);
Returns the identifier that was previously associated with the vertex v
.
int faceId(const cell& f);
Returns the identifier that was previously associated with the face f
.
Set the normal of the face v
to normal
. The normal is just for information, and do not have to be used.
Set the normal of the vertex v
to normal
. The normal is just for information, and do not have to be used.
Definition at line 126 of file objreader.h.
References QTextStream::atEnd(), forall, forall_named, IMPORT_COMPLEX_TYPES, util::Vector< dim, T >::normalize(), QString::number(), QTextStream::readLine(), util::Vector< dim, T >::size(), QList::size(), QString::split(), QString::toInt(), util::Vector< dim, T >::x(), util::Vector< dim, T >::y(), and util::Vector< dim, T >::z().
Referenced by objreader().
00127 { 00128 IMPORT_COMPLEX_TYPES(CellComplex); 00129 00130 std::vector<Point3d> vertices_pos; 00131 std::vector<Point3d> normals; 00132 std::vector<std::vector<int> > faces_idx; 00133 00134 QString token; 00135 00136 while(!content.atEnd()) 00137 { 00138 content >> token; 00139 QString buffer = content.readLine(); 00140 // cerr << "Reading token '" << token.toStdString() << "'" << endl; 00141 // cerr << "Buffer: '" << buffer.toStdString() << "'" << endl; 00142 if(token == QString("v")) 00143 { 00144 QList<QString> pos = buffer.split(' ', QString::SkipEmptyParts); 00145 if(pos.size() != 3) 00146 { 00147 QString msg = "Error, vertex " + QString::number(vertices_pos.size()) + 00148 " has " + QString::number(pos.size()) + " dimensions instead of 3"; 00149 return ObjReaderError(ObjReaderError::BAD_NUMBER_OF_DIMENSIONS, msg); 00150 } 00151 Point3d p; 00152 bool ok, ok_tmp; 00153 p.x() = pos[0].toDouble(&ok); 00154 p.y() = pos[1].toDouble(&ok_tmp); 00155 ok &= ok_tmp; 00156 p.z() = pos[2].toDouble(&ok_tmp); 00157 ok &= ok_tmp; 00158 if(!ok) 00159 { 00160 QString msg = "Error on vertex " + QString::number(vertices_pos.size()) + 00161 ": double value expected"; 00162 return ObjReaderError(ObjReaderError::DOUBLE_EXPECTED, msg); 00163 } 00164 vertices_pos.push_back(p); 00165 } 00166 else if(token == QString("vn")) 00167 { 00168 QList<QString> pos = buffer.split(' '); 00169 if(pos.size() != 3) 00170 { 00171 QString msg = "Error, normal " + QString::number(normals.size()) + " has " + 00172 QString::number(pos.size()) + " dimensions instead of 3"; 00173 return ObjReaderError(ObjReaderError::BAD_NUMBER_OF_DIMENSIONS, msg); 00174 } 00175 Point3d p; 00176 bool ok, ok_tmp; 00177 p.x() = pos[0].toDouble(&ok); 00178 p.y() = pos[1].toDouble(&ok_tmp); 00179 ok &= ok_tmp; 00180 p.z() = pos[2].toDouble(&ok_tmp); 00181 ok &= ok_tmp; 00182 if(!ok) 00183 { 00184 QString msg = "Error on normal " + QString::number(vertices_pos.size()) + ": double value expected"; 00185 return ObjReaderError(ObjReaderError::DOUBLE_EXPECTED, msg); 00186 } 00187 normals.push_back(p); 00188 } 00189 else if(token == QString("f")) 00190 { 00191 std::vector<int> f; 00192 QList<QString> face = buffer.split(' ', QString::SkipEmptyParts); 00193 if(face.size() < 3) 00194 { 00195 QString msg = "Error, face " + QString::number(faces_idx.size()) + " has less than 3 vertices."; 00196 return ObjReaderError(ObjReaderError::INVALID_FACE, msg); 00197 } 00198 bool ok = true; 00199 forall(QString& value, face) 00200 { 00201 int vn = value.toInt(&ok); 00202 if(!ok) 00203 { 00204 QString msg = "Error on face " + QString::number(faces_idx.size()) + ": integer values expected"; 00205 return ObjReaderError(ObjReaderError::INTEGER_EXPECTED, msg); 00206 } 00207 f.push_back(vn); 00208 } 00209 faces_idx.push_back(f); 00210 } 00211 } 00212 if(normals.size() > vertices_pos.size()) 00213 { 00214 cerr << "Warning: more normals than vertices" << endl; 00215 } 00216 if(!normals.empty() and normals.size() < vertices_pos.size()) 00217 { 00218 cerr << "Warning: not all vertices have a normal, ignoring the specified normals." << endl; 00219 normals.clear(); 00220 } 00221 // First, add the vertices 00222 std::vector<junction> vertices; 00223 std::vector<cell> faces; 00224 int id = 0; 00225 forall(const Point3d& pos, vertices_pos) 00226 { 00227 junction v; 00228 T.S.insert(v); 00229 T.W.insert(v); 00230 model.setPosition(v, pos); 00231 vertices.push_back(v); 00232 model.setVertexId(v, ++id); 00233 } 00234 // Then add the faces and connect the center to the junctions (in the 00235 // correct order) 00236 id = 0; 00237 forall(const std::vector<int>& face_idx, faces_idx) 00238 { 00239 cell face; 00240 junction pf(0); 00241 T.S.insert(face); 00242 T.C.insert(face); 00243 Point3d center; 00244 forall(int i, face_idx) 00245 { 00246 center += vertices_pos[i-1]; 00247 junction current = vertices[i-1]; 00248 if(pf) 00249 { 00250 T.S.spliceAfter(face, pf, current); 00251 } 00252 else 00253 T.S.insertEdge(face, current); 00254 pf = current; 00255 } 00256 center /= face_idx.size(); 00257 model.setPosition(face, center); 00258 model.setFaceId(face, ++id); 00259 } 00260 // Connect the vertices to the faces 00261 forall_named(const junction& j, T.S, junctions) 00262 { 00263 if(T.S.iValence(j) < 3) 00264 { 00265 // There is nothing to sort ... 00266 forall(const cell& f, T.S.iNeighbors(j)) 00267 { 00268 T.S.insertEdge(j, f); 00269 } 00270 } 00271 else 00272 { 00273 const cell& f_init = T.S.iAnyIn(j); 00274 cell pf = f_init; 00275 T.S.insertEdge(j, f_init); 00276 do 00277 { 00278 cell f(0); 00279 const junction& m = T.S.prevTo(pf, j); 00280 // Now, find the face that contains also m 00281 forall(const cell& of, T.S.iNeighbors(j)) 00282 { 00283 if(of == pf) 00284 continue; 00285 if(T.S.edge(of, m)) 00286 { 00287 f = of; 00288 break; 00289 } 00290 } 00291 if(!f or f == f_init) 00292 { 00293 break; 00294 } 00295 // Insert f after pf in j 00296 T.S.spliceAfter(j, pf, f); 00297 pf = f; 00298 } while( T.S.iValence(j) != T.S.valence(j)); 00299 pf = f_init; 00300 // If we didn't find all the neighbors, it means we have to go the 00301 // other way around 00302 while(T.S.iValence(j) != T.S.valence(j)) 00303 { 00304 cell f(0); 00305 const junction& m = T.S.nextTo(pf, j); 00306 forall(const cell& of, T.S.iNeighbors(j)) 00307 { 00308 if(of == pf) 00309 continue; 00310 if(T.S.edge(of, m)) 00311 { 00312 f = of; 00313 break; 00314 } 00315 } 00316 if(!f) 00317 break; 00318 T.S.spliceBefore(j, pf, f); 00319 pf = f; 00320 } 00321 if(T.S.valence(j) != T.S.iValence(j)) 00322 { 00323 cerr << "Error, vertex " << model.vertexId(j) << " was not properly connected to the faces" << endl; 00324 } 00325 } 00326 } 00327 // Connect the junctions 00328 forall_named(const junction& j, T.S, junctions) 00329 { 00330 junction prev(0); 00331 forall(const cell& c, T.S.neighbors(j)) 00332 { 00333 const junction& jn = T.S.nextTo(c, j); 00334 const junction& jp = T.S.prevTo(c, j); 00335 if(prev.isNull()) 00336 { 00337 T.W.insertEdge(j, jn); 00338 prev = jn; 00339 } 00340 else if(prev != jn) 00341 { 00342 T.W.spliceAfter(j, prev, jn); 00343 } 00344 T.W.spliceAfter(j, jn, jp); 00345 prev = jp; 00346 } 00347 } 00348 // if the normals aren't specified, then compute them 00349 if(normals.empty()) 00350 { 00351 forall_named(const junction& v, T.S, junctions) 00352 { 00353 Point3d pos = model.position(v); 00354 Point3d normal; 00355 if(T.border(v)) 00356 { 00357 // If this is a border index, first find the border 00358 forall(const junction& n, T.W.neighbors(v)) 00359 { 00360 const junction& m = T.W.nextTo(v,n); 00361 if(T.border(v, m) and T.border(v, n)) 00362 { 00363 junction n1 = m; 00364 do 00365 { 00366 const junction& n2 = T.W.nextTo(v, n1); 00367 Point3d p1 = model.position(n1) - pos; 00368 Point3d p2 = model.position(n2) - pos; 00369 normal += p1^p2; 00370 n1 = n2; 00371 } while(n1 != n); 00372 break; 00373 } 00374 } 00375 } 00376 else 00377 { 00378 // If this is an inside vertex 00379 forall(const junction& n, T.W.neighbors(v)) 00380 { 00381 Point3d p1 = model.position(n) - pos; 00382 Point3d p2 = model.position(T.W.nextTo(v, n)) - pos; 00383 normal += p1^p2; 00384 } 00385 } 00386 normal.normalize(); 00387 model.setNormal(v, normal); 00388 } 00389 } 00390 else 00391 { 00392 int k = 0; 00393 forall(const Point3d& n, normals) 00394 { 00395 junction v = vertices[k++]; 00396 model.setNormal(v, n); 00397 } 00398 } 00399 // Compute normals for the faces 00400 forall_named(const cell& f, T.S, cells) 00401 { 00402 Point3d pos = model.position(f); 00403 Point3d normal; 00404 forall(const junction& v, T.S.neighbors(f)) 00405 { 00406 const junction& v1 = T.S.nextTo(f, v); 00407 Point3d p1 = model.position(v) - pos; 00408 Point3d p2 = model.position(v1) - pos; 00409 normal += p1^p2; 00410 } 00411 normal.normalize(); 00412 model.setNormal(f, normal); 00413 } 00414 // At last, connect the cell graph 00415 forall_named(const cell& f, T.S, cells) 00416 { 00417 cell pf(0); 00418 forall(const junction& j, T.S.neighbors(f)) 00419 { 00420 const cell& f2 = T.adjacentCell(f, j); 00421 if(f2) 00422 { 00423 if(pf) 00424 { 00425 T.C.spliceAfter(f, pf, f2); 00426 } 00427 else 00428 { 00429 T.C.insertEdge(f, f2); 00430 } 00431 pf = f2; 00432 } 00433 } 00434 } 00435 return ObjReaderError(ObjReaderError::NO_ERRORS); 00436 }
bool complex_factory::square_grid | ( | size_t | N, | |
size_t | M, | |||
Complex & | T, | |||
Model & | model, | |||
const Point3d & | bottom_left = Point3d(0,0,0) , |
|||
const Point3d & | shift_right = Point3d(1,0,0) , |
|||
const Point3d & | shift_up = Point3d(0,1,0) | |||
) | [inline] |
Create a square grid with N lines and M columns.
N | Number of lines | |
M | Number of columns | |
G | Graph to initialize as a grid | |
m | Model containing the initialization functions | |
bottom_left | Position of the bottom-left corner of the bottom_left cell | |
shift_right | Vector describing the width of a cell | |
shift_up | Vector describing the height of a cell |
The model should contain this method:
void saveGridCellPosition(const cell&, Point2u pos, Complex&)
Point2u gridCellPosition(const cell&, Complex&)
The neighbors are oriented in that order: bottom -> right -> top -> left
With the bottom-left corner being the one of coordinate (0,0).
The graph is cleared at the beginning of the process
Definition at line 116 of file complex_grid.h.
References forall, IMPORT_COMPLEX_TYPES, algorithms::insertAfter(), factory::square_grid(), util::Vector< dim, T >::x(), and util::Vector< dim, T >::y().
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 }
SquareFiller<Complex,Model> complex_factory::squareFiller | ( | const Point3d & | bottom_left, | |
const Point3d & | shift_right, | |||
const Point3d & | shift_up, | |||
Complex & | T, | |||
Model & | model | |||
) | [inline] |
Create a square filler.
Definition at line 74 of file complex_grid.h.