00001 #ifndef VVELIB_ALGORITHMS_TRIANGLE_GROWTH_H
00002 #define VVELIB_ALGORITHMS_TRIANGLE_GROWTH_H
00003
00011 #include <config.h>
00012 #include <geometry/geometry.h>
00013 #include <vector>
00014 #include <algorithms/complex.h>
00015 #include <QString>
00016 #include <storage/storage.h>
00017 #include <util/unorderedset.h>
00018 #include <util/unorderedmap.h>
00019 #include <util/assert.h>
00020 #include <QTextStream>
00021
00022 namespace algorithms
00023 {
00024 using geometry::Point3d;
00025
00031 class TriangleSurface
00032 {
00033 public:
00037 struct Cell
00038 {
00040 Point3d normal;
00042 int id;
00043 };
00044
00048 struct Vertex
00049 {
00051 Point3d pos;
00053 Point3d normal;
00055 int id;
00056 };
00057
00059 typedef vvcomplex::VVComplexGraph<Cell, Vertex> CellComplex;
00060 EXPORT_COMPLEX_VERTICES(CellComplex);
00061
00063 CellComplex S;
00064
00069 struct Position
00070 {
00071 Point3d barycentric;
00072 int v1, v2, v3;
00073 int face;
00074
00075 Position() : v1(0), v2(0), v3(0), face(0) {}
00076 Position(const Point3d& bar, int vv1, int vv2, int vv3, int f)
00077 : barycentric(bar)
00078 , v1(vv1) , v2(vv2) , v3(vv3) , face(f)
00079 {}
00080 Position(const Position& copy)
00081 : barycentric(copy.barycentric)
00082 , v1(copy.v1), v2(copy.v2), v3(copy.v3), face(copy.face)
00083 {}
00084 #ifdef USE_CXX0X
00085 Position(Position&& copy) = default;
00086 #endif
00087
00088 bool serialize(storage::VVEStorage&);
00089
00090 operator bool() const { return face != 0; }
00091 };
00092
00093 TriangleSurface();
00094 #ifdef USE_CXX0X
00095 TriangleSurface(TriangleSurface&& ) = default;
00096 TriangleSurface(const TriangleSurface& ) = default;
00097 #endif
00098
00103 Point3d point3d(const Position& pos) const;
00107 Point3d normal(const Position& pos) const;
00115 Point3d smoothNormal(const Position& pos) const;
00116
00121 Position position(const Point3d& pos) const;
00132 Position position(const Position& start, const Point3d& pos) const;
00133
00140 Position centerPosition(int face) const;
00141
00148 Point3d center3d(int face) const;
00149
00157 Point3d vector3d(const Position& pos) const;
00158
00162 Position vector(const Point3d& ref, const Point3d& pos) const;
00166 Position vector(const Position& ref, const Point3d& pos) const;
00167
00171 void clear();
00172
00177 std::vector<Position> contour() const;
00178
00180 double time;
00181 int time_index;
00182
00184 std::vector<junction> vertices;
00186 std::vector<cell> faces;
00187
00189 Point3d pmin, pmax;
00190 protected:
00191 typedef std::unordered_set<cell> cell_set_t;
00192 Position find_position(const cell& c, const Point3d& pos, cell_set_t& visited) const;
00193 Position vertexPosition(const junction& j) const;
00194 std::vector<Position> nextContourVertex(const junction& first, const cell& c, const junction& j, std::vector<Position> acc) const;
00195 };
00196
00205 class TriangleGrowth
00206 {
00207 public:
00208 typedef TriangleSurface::Position Position;
00209
00210 struct Cell
00211 {
00212 int id;
00213 };
00214
00215 struct Vertex
00216 {
00217 std::vector<Point3d> pos;
00218 std::vector<Point3d> normal;
00219 int id;
00220 };
00221
00222 TriangleGrowth();
00223
00230 bool readOBJs(QString desc_filepath);
00231
00238 bool readOBJs(const std::string& desc_filepath) { return readOBJs(QString::fromStdString(desc_filepath)); }
00239
00260 template <typename Model, typename ComplexGraph>
00261 bool init(const ComplexGraph& cplx, std::vector<double> times, Model *model);
00262
00266 bool valid() const { return _valid; }
00267
00271 const QString& errorMsg() const { return _errorMsg; }
00272
00276 size_t size() const;
00277
00281 double startTime() const { return times.front(); }
00282
00286 double endTime() const { return times.back(); }
00287
00294 void setTime(double t);
00295
00299 double time() const { return _time; }
00300
00304 int timePos() const { return _time_pos; }
00305
00309 const TriangleSurface& surface() const;
00310
00314 TriangleSurface surface(double time);
00315
00320 std::vector<Position> contour() const;
00321
00322 protected:
00323 void setSurface(TriangleSurface& s) const;
00324
00325 typedef vvcomplex::VVComplexGraph<Cell,Vertex> CellComplex;
00326 EXPORT_COMPLEX_VERTICES(CellComplex);
00327
00328 Position vertexPosition(const junction& j) const;
00329
00330 mutable TriangleSurface TS;
00331
00332 CellComplex S;
00333 std::vector<double> times;
00334 double _time;
00335 int _time_pos;
00336 bool _valid;
00337 QString _errorMsg;
00338 std::vector<cell> faces;
00339 std::vector<junction> vertices;
00340 };
00341
00342 template <typename Model, typename ComplexGraph>
00343 bool TriangleGrowth::init(const ComplexGraph& cplx, std::vector<double> _times, Model *model)
00344 {
00345 typedef typename ComplexGraph::cell ext_cell;
00346 typedef typename ComplexGraph::junction ext_junction;
00347
00348
00349
00350 _valid = false;
00351
00352 std::unordered_map<ext_cell, cell> cell_convert;
00353 std::unordered_map<ext_junction, junction> junction_convert;
00354
00355 faces.clear();
00356 vertices.clear();
00357 S.clear();
00358
00359
00360
00361 if(_times.empty())
00362 return false;
00363 size_t nb_times = _times.size();
00364 times = _times;
00365 _time = times.front();
00366 _time_pos = 0;
00367 faces.resize(cplx.nb_cells(), cell(0));
00368 vertices.resize(cplx.nb_junctions(), junction(0));
00369
00370
00371
00372
00373
00374
00375 int i = 0;
00376 forall(const ext_cell& ec, cplx.cells())
00377 {
00378
00379 cell c;
00380 c->id = i;
00381 faces[i] = c;
00382 S.insert(c);
00383 cell_convert[ec] = c;
00384 i++;
00385 }
00386
00387
00388
00389
00390
00391 i = 0;
00392 forall(const ext_junction& ej, cplx.junctions())
00393 {
00394
00395 junction j;
00396 j->id = i;
00397 j->pos.resize(nb_times);
00398 j->normal.resize(nb_times);
00399 for(size_t t = 0 ; t < nb_times ; ++t)
00400 {
00401 j->pos[t] = model->position(ej, t);
00402 j->normal[t] = model->normal(ej, t);
00403 }
00404 vertices[i] = j;
00405 S.insert(j);
00406 junction_convert[ej] = j;
00407 i++;
00408 }
00409
00410
00411
00412
00413
00414 forall(const ext_cell& ec, cplx.cells())
00415 {
00416
00417 const cell& c = S.reference(cell_convert[ec]);
00418 forall(const ext_junction& ej, cplx.neighbors(ec))
00419 {
00420 junction j = junction_convert[ej];
00421 if(S.valence(c) < 2)
00422 {
00423 S.insertEdge(c, j);
00424 }
00425 else
00426 {
00427 junction pj = junction_convert[cplx.prevTo(ec, ej)];
00428 S.spliceAfter(c, pj, j);
00429 }
00430 }
00431 vvassert_msg(S.valence(c) == 3, QString("Face %1 has %2 junctions instead of 3").arg(c->id).arg(S.valence(c)));
00432 }
00433
00434
00435
00436
00437 forall(const ext_junction& ej, cplx.junctions())
00438 {
00439
00440 const junction& j = S.reference(junction_convert[ej]);
00441 forall(const ext_cell& ec, cplx.neighbors(ej))
00442 {
00443 cell c = cell_convert[ec];
00444 if(S.valence(j) < 2)
00445 {
00446 S.insertEdge(j, c);
00447 }
00448 else
00449 {
00450 cell pc = cell_convert[cplx.prevTo(ej, ec)];
00451 S.spliceAfter(j, pc, c);
00452 }
00453 }
00454 }
00455
00456
00457 _valid = true;
00458 return true;
00459 }
00460 }
00461
00462 #endif // VVELIB_ALGORITHMS_TRIANGLE_GROWTH_H
00463