00001 #ifndef BSPLINE_TISSUE_MODEL_H
00002 #define BSPLINE_TISSUE_MODEL_H
00003
00174 #include <vve.h>
00175 #include <util/parms.h>
00176 #include <util/palette.h>
00177
00178 #include <util/vector.h>
00179 #include <util/watchdog.h>
00180
00181 #include <util/bsurface.h>
00182 #include <util/key_framer.h>
00183
00184 #include <algorithms/tissue.h>
00185 #include <iostream>
00186
00187 using util::Point3d;
00188 using util::Point2d;
00189
00193 typedef util::Palette::Color Color;
00194
00200 namespace bspline_tissue_model
00201 {
00205 const double epsilon=0.0001;
00206
00207 using std::cout;
00208 using std::endl;
00209
00215 template <typename RealModel, typename TissueClass>
00216 struct TissueModel : public Model
00217 {
00218 IMPORT_COMPLEX_TYPES(TissueClass);
00219
00223 struct CompareSize : public std::binary_function<cell, cell, bool>
00224 {
00225 bool operator()(const cell& c1, const cell& c2) const
00226 {
00227 return c1->area < c2->area;
00228 }
00229 };
00230
00236 typedef std::set<cell,CompareSize> ordered_cells_t;
00237
00238 util::WatchDog rex;
00239 util::Palette palette;
00240 TissueClass T;
00241
00242 util::KeyFramer leaf;
00243 util::BSplineSurface leafs;
00244
00245 int cellInitWalls;
00246 double dt;
00247 double growthStartTime;
00248 int backColor;
00249 bool drawNeighborhood;
00250
00251 double time;
00252
00258 TissueModel(QObject *parent)
00259 : Model(parent)
00260 , rex(this)
00261 , palette("pal.map")
00262 , T(palette, (RealModel*)this)
00263 {
00264 rex.addObject(&palette);
00265 rex.addObject(&leaf);
00266 }
00267
00272 void modifiedFiles( const std::set<std::string>& filenames )
00273 {
00274 if(filenames.count("view.v"))
00275 readTissueParam();
00276 rex.watch(filenames);
00277 }
00278
00282 virtual void readParam( util::Parms& ) { }
00283
00287 void SetPos( const cell& c )
00288 {
00289 c->pos = leafs.EvalN(c->uv[0], c->uv[1]);
00290 c->normal = leafs.NormalEvalN(c->uv[0], c->uv[1]);
00291 }
00292
00296 void SetPos( const junction& j )
00297 {
00298 j->pos = leafs.EvalN(j->uv[0], j->uv[1]);
00299 j->normal = leafs.NormalEvalN(j->uv[0], j->uv[1]);
00300 }
00301
00306 void initTissue()
00307 {
00308 time = growthStartTime;
00309 leaf.SetTime(time);
00310 leafs = leaf.GetSurfaceTime();
00311
00312
00313 cell c;
00314 c->uv[0] = c->uv[1] = .5;
00315 c->value = 0.5;
00316 SetPos(c);
00317
00318 std::vector<junction> junctions(cellInitWalls, junction(0));
00319 for(int i = 0 ; i < cellInitWalls ; i++)
00320 {
00321 double s = (double)(cellInitWalls-i)/(double)cellInitWalls;
00322 junction v;
00323 v->uv = leafs.ContourInverse(s);
00324 SetPos(v);
00325 junctions[i] = v;
00326 }
00327
00328 T.addCell(c, junctions);
00329
00330 updateCellsArea();
00331 }
00332
00337 void updatePositions()
00338 {
00339 leaf.SetTime(time);
00340 leafs = leaf.GetSurfaceTime();
00341 forall(const cell& c, T.C)
00342 {
00343 SetPos(c);
00344 }
00345 forall(const junction& j, T.W)
00346 {
00347 SetPos(j);
00348 }
00349 }
00350
00354 void updateCellsArea()
00355 {
00356 forall_named( const cell& c, T.S, cells )
00357 {
00358 c->area = 0.0;
00359 forall( const junction& n, T.S.neighbors(c) )
00360 {
00361
00362 const junction& m = T.S.nextTo(c, n);
00363 c->area += geometry::triangleArea(c->pos, m->pos, n->pos);
00364 }
00365 if(c->area <= epsilon )
00366 {
00367 cout << "Bad area " << c->area << endl;
00368 c->area = 0.1;
00369 }
00370 }
00371 }
00372
00376 void registerFiles()
00377 {
00378 registerFile("view.v");
00379 }
00380
00384 void readTissueParam()
00385 {
00386 util::Parms parms("view.v");
00387 std::string newKeyFrameFile;
00388
00389 parms("Main", "dt", dt);
00390 parms("Main", "KeyFrameFile", newKeyFrameFile);
00391 parms("Main", "GrowthStartTime", growthStartTime);
00392 parms("Main", "CellInitWalls", cellInitWalls);
00393
00394 rex.changeFilename(&leaf, newKeyFrameFile);
00395
00396 T.readViewParms(parms, "View");
00397 parms("View", "BackColor", backColor);
00398 parms("View", "DrawNeighborhood", drawNeighborhood);
00399
00400 T.readParms(parms, "Tissue");
00401
00402 readParam(parms);
00403 }
00404
00405 void initDraw()
00406 {
00407 glEnable(GL_NICEST);
00408 glDisable(GL_CULL_FACE);
00409 }
00410
00411 void preDraw()
00412 {
00413 Color bg = palette.getColor(backColor);
00414 glClearColor(bg.r(), bg.g(), bg.b(), 1.0);
00415 T.preDraw();
00416 glEnable(GL_BLEND);
00417 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00418 }
00419
00420 void postDraw()
00421 {
00422 glDisable(GL_BLEND);
00423 T.postDraw();
00424 }
00425
00426 void draw(Viewer *viewer)
00427 {
00428 forall_named(const cell& c, T.S, cells)
00429 {
00430 Color color = getCellColor(c);
00431 Color center_color = getCellCenterColor(c);
00432 T.drawCell(c, color, center_color);
00433 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00434 if(drawNeighborhood)
00435 {
00436 int cnt = 3;
00437 double ds = 0.1 / (3+T.C.valence(c));
00438 glColor3f(1.0, 0, 0);
00439 Vec from(c->pos);
00440 forall(const cell& n, T.C.neighbors(c))
00441 {
00442 glColor3f(1.0, 1.0, 1.0);
00443 Vec to(n->pos);
00444 Vec u = to-from;
00445 u.normalize();
00446 to = from + cnt*ds*u;
00447 cnt++;
00448 viewer->drawArrow(from, to, -1, 6);
00449 }
00450 }
00451 }
00452
00453 double vmin[3], vmax[3];
00454 leafs.BoundingBox(vmin[0], vmin[1], vmin[2], vmax[0], vmax[1], vmax[2]);
00455 Vec pmin(vmin), pmax(vmax);
00456 viewer->setSceneBoundingBox(pmin, pmax);
00457 }
00458
00462 void drawWithNames()
00463 {
00464 bool db = T.drawBorders;
00465 T.drawBorders = false;
00466 int i = 0;
00467 forall_named(const cell& c, T.S, cells)
00468 {
00469 glPushName(i++);
00470 T.drawCell(c, c->value);
00471 glPopName();
00472 }
00473 T.drawBorders = db;
00474 }
00475
00479 virtual Color getCellColor(const cell &c)
00480 {
00481 return T.valueColor(c->value);
00482 }
00483
00487 virtual Color getCellCenterColor(const cell &c)
00488 {
00489 return T.valueCenterColor(c->value);
00490 }
00491
00498 const cell& cellFromId(int i)
00499 {
00500 if(i == -1)
00501 return cell::null;
00502 return T.S.get_cell(i);
00503 }
00504
00506
00507 Point3d position( const cell& v) const
00508 {
00509 return v->pos;
00510 }
00511 Point3d position( const junction& v) const
00512 {
00513 return v->pos;
00514 }
00515
00516 void setPosition( const cell& v, const Point3d& pos)
00517 {
00518 leafs.PointInversionN(v->uv, v->uv, pos);
00519 SetPos(v);
00520 }
00521
00522 void setPosition( const junction& v, const Point3d& pos)
00523 {
00524 leafs.PointInversionN(v->uv, v->uv, pos);
00525 SetPos(v);
00526 }
00527
00528 void setPositionHint( const junction& v, const junction& n1, const junction& n2, double r)
00529 {
00530 v->uv = (1-r)*n1->uv + r*n2->uv;
00531 }
00532
00533 Point3d normal( const cell& v) const
00534 {
00535 return v->normal;
00536 }
00537
00538 Point3d normal( const junction& v) const
00539 {
00540 return v->normal;
00541 }
00542
00543 void updateFromOld( const cell& , const cell& , const cell& ,
00544 const typename TissueClass::division_data&, TissueClass& )
00545 {
00546 }
00548
00552 void step() { }
00553
00557 void initialize() {}
00558
00559 };
00560 }
00561
00562 #ifndef CellAttributes
00563 # define CellAttributes
00564 #endif
00565
00566 #ifndef JunctionAttributes
00567 # define JunctionAttributes
00568 #endif
00569
00570 #ifndef CellEdgeAttributes
00571 # define CellEdgeAttributes
00572 #endif
00573
00574 #ifndef WallAttributes
00575 # define WallAttributes
00576 #endif
00577
00578 #ifndef CellJunctionEdgeAttributes
00579 # define CellJunctionEdgeAttributes
00580 #endif
00581
00582 #ifndef JunctionCellEdgeAttributes
00583 # define JunctionCellEdgeAttributes
00584 #endif
00585
00586 #ifndef ModelInit
00587 # define ModelInit
00588 #endif
00589
00593 #define StartModel \
00594 struct CellType \
00595 { \
00596 double area; \
00597 Point3d pos; \
00598 Point3d normal; \
00599 Point2d uv; \
00600 double value; \
00601 CellAttributes\
00602 }; \
00603 \
00604 struct JunctionType \
00605 { \
00606 Point3d pos; \
00607 Point3d normal; \
00608 Point2d uv; \
00609 JunctionAttributes\
00610 }; \
00611 \
00612 struct CellEdgeType \
00613 { \
00614 CellEdgeAttributes\
00615 }; \
00616 \
00617 struct WallType \
00618 { \
00619 WallAttributes\
00620 }; \
00621 \
00622 struct CellJunctionEdgeType \
00623 { \
00624 CellJunctionEdgeAttributes\
00625 }; \
00626 \
00627 struct JunctionCellEdgeType \
00628 { \
00629 JunctionCellEdgeAttributes\
00630 }; \
00631 \
00632 class ModelClass; \
00633 typedef tissue::Tissue<ModelClass, CellType, JunctionType, WallType, CellEdgeType,CellJunctionEdgeType, JunctionCellEdgeType> Tissue; \
00634 \
00635 struct ModelClass : public bspline_tissue_model::TissueModel<ModelClass,Tissue> \
00636 { \
00637 typedef bspline_tissue_model::TissueModel<ModelClass,Tissue> ParentClass; \
00638 ModelClass(QObject *parent) \
00639 : ParentClass(parent)\
00640 ModelInit \
00641 { \
00642 readTissueParam(); \
00643 registerFiles(); \
00644 initialize(); \
00645 if(T.C.empty()) initTissue(); \
00646 }
00647
00651 #define EndModel }; DEFINE_MODEL(ModelClass);
00652
00653 #endif // BSPLINE_TISSUE_MODEL_H