00001 #ifndef TISSUE_MODEL_H
00002 #define TISSUE_MODEL_H
00003
00152 #include <vve.h>
00153 #include <util/parms.h>
00154 #include <util/palette.h>
00155 #include <iostream>
00156
00157 #include <util/watchdog.h>
00158 #include <algorithms/tissue.h>
00159
00160 #include <geometry/geometry.h>
00161
00162 using geometry::Point3d;
00163
00164 typedef util::Palette::Color Color;
00165
00169 namespace tissue_model
00170 {
00174 const double epsilon=0.0001;
00175
00179 template <typename RealModel, typename TissueClass>
00180 struct TissueModel : public Model
00181 {
00213 IMPORT_COMPLEX_TYPES(TissueClass);
00214
00218 struct CompareSize : public std::binary_function<cell, cell, bool>
00219 {
00220 bool operator()(const cell& c1, const cell& c2) const
00221 {
00222 return c1->area < c2->area;
00223 }
00224 };
00225
00231 typedef std::set<cell,CompareSize> ordered_cells_t;
00232
00234 util::WatchDog rex;
00236 util::Palette palette;
00238 TissueClass T;
00239
00241 int backColor;
00243 bool drawNeighborhood;
00244
00250 TissueModel(QObject *parent)
00251 : Model(parent)
00252 , rex(this)
00253 , palette("pal.map")
00254 , T(palette, (RealModel*)this)
00255 {
00256 rex.addObject(&palette);
00257 }
00258
00259 void modifiedFiles( const std::set<std::string>& filenames )
00260 {
00261 if(filenames.find("view.v") != filenames.end())
00262 readTissueParam();
00263 rex.watch(filenames);
00264 }
00265
00269 virtual void readParam( util::Parms& ) {}
00270
00274 void updateCellsArea()
00275 {
00276 forall_named(const cell& c, T.S, cells)
00277 {
00278 c->area = 0.0;
00279 forall( const junction& n, T.S.neighbors(c) )
00280 {
00281
00282 const junction& m = T.S.nextTo(c, n);
00283 c->area += geometry::triangleArea(c->pos, m->pos, n->pos);
00284 }
00285 if(c->area <= epsilon )
00286 {
00287 std::cout << "Bad area " << c->area << std::endl;
00288 c->area = 0.1;
00289 }
00290 }
00291 }
00292
00293 void registerFiles()
00294 {
00295 registerFile("view.v");
00296 }
00297
00302 void readTissueParam()
00303 {
00304 util::Parms parms("view.v");
00305 T.readViewParms(parms, "View");
00306 T.readParms(parms, "Tissue");
00307 parms("View", "BackColor", backColor);
00308 parms("View", "DrawNeighborhood", drawNeighborhood);
00309 readParam(parms);
00310 }
00311
00313
00314
00315 void initDraw()
00316 {
00317 glEnable(GL_NICEST);
00318 glDisable(GL_CULL_FACE);
00319 }
00320
00321 void preDraw()
00322 {
00323 Color bg = palette.getColor(backColor);
00324 glClearColor(bg.r(), bg.g(), bg.b(), 1.0);
00325 T.preDraw();
00326 glEnable(GL_BLEND);
00327 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00328 }
00329
00330 void postDraw()
00331 {
00332 glDisable(GL_BLEND);
00333 T.postDraw();
00334 }
00335
00340 void draw(Viewer *viewer)
00341 {
00342 Vec vmin(HUGE_VAL,HUGE_VAL,HUGE_VAL), vmax(-HUGE_VAL,-HUGE_VAL,-HUGE_VAL);
00343 forall(const junction& v, T.W)
00344 {
00345 const Point3d& pos = v->pos;
00346 if(pos.x() < vmin.x)
00347 vmin.x = pos.x();
00348 if(pos.y() < vmin.y)
00349 vmin.y = pos.y();
00350 if(pos.z() < vmin.z)
00351 vmin.z = pos.z();
00352 if(pos.x() > vmax.x)
00353 vmax.x = pos.x();
00354 if(pos.y() > vmax.y)
00355 vmax.y = pos.y();
00356 if(pos.z() > vmax.z)
00357 vmax.z = pos.z();
00358 }
00359 viewer->setSceneBoundingBox(vmin, vmax);
00360
00361 forall_named(const cell& c, T.S, cells)
00362 {
00363 Color color = getCellColor(c);
00364 Color center_color = getCellCenterColor(c);
00365 T.drawCell(c, color, center_color);
00366 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00367 if(drawNeighborhood)
00368 {
00369 int cnt = 3;
00370 double ds = 0.1 / (3+T.C.valence(c));
00371 glColor3f(1.0, 0, 0);
00372 Vec from(c->pos);
00373 forall(const cell& n, T.C.neighbors(c))
00374 {
00375 glColor3f(1.0, 1.0, 1.0);
00376 Vec to(n->pos);
00377 Vec u = to-from;
00378 u.normalize();
00379 to = from + cnt*ds*u;
00380 cnt++;
00381 viewer->drawArrow(from, to, -1, 6);
00382 }
00383 }
00384 }
00385 }
00386
00390 virtual Color getCellColor(const cell &c)
00391 {
00392 return T.valueColor(c->value);
00393 }
00394
00398 virtual Color getCellCenterColor(const cell &c)
00399 {
00400 return T.valueCenterColor(c->value);
00401 }
00402
00404
00406
00407
00411 void drawWithNames()
00412 {
00413 bool db = T.drawBorders;
00414 T.drawBorders = false;
00415 int i = 0;
00416 forall_named(const cell& c, T.S, cells)
00417 {
00418 glPushName(i++);
00419 T.drawCell(c, c->value);
00420 glPopName();
00421 }
00422 T.drawBorders = db;
00423 }
00424
00430 const cell& cellFromId(int i)
00431 {
00432 if(i == -1)
00433 return cell::null;
00434 return T.S.get_cell(i);
00435 }
00437
00439
00440 Point3d position( const cell& v) const
00441 {
00442 return v->pos;
00443 }
00444
00445 Point3d position( const junction& v) const
00446 {
00447 return v->pos;
00448 }
00449
00450 void setPosition( const cell& v, const Point3d& pos)
00451 {
00452 v->pos = pos;
00453 }
00454
00455 void setPosition( const junction& v, const Point3d& pos)
00456 {
00457 v->pos = pos;
00458 }
00459
00460 void setVertexPositionHint( const junction& , const junction& , const junction& , double )
00461 {
00462 }
00463
00464 Point3d normal( const cell& v) const
00465 {
00466 return v->normal;
00467 }
00468
00469 Point3d normal( const junction& v) const
00470 {
00471 return v->normal;
00472 }
00473
00474 void updateFromOld( const cell& , const cell& , const cell& ,
00475 const typename TissueClass::division_data&, TissueClass& )
00476 {
00477 }
00479
00483 void step() { }
00484
00488 void initialize() {}
00489 };
00490 }
00491
00492 #ifndef CellAttributes
00493 # define CellAttributes
00494 #endif
00495
00496 #ifndef JunctionAttributes
00497 # define JunctionAttributes
00498 #endif
00499
00500 #ifndef CellEdgeAttributes
00501 # define CellEdgeAttributes
00502 #endif
00503
00504 #ifndef WallAttributes
00505 # define WallAttributes
00506 #endif
00507
00508 #ifndef CellJunctionEdgeAttributes
00509 # define CellJunctionEdgeAttributes
00510 #endif
00511
00512 #ifndef JunctionCellEdgeAttributes
00513 # define JunctionCellEdgeAttributes
00514 #endif
00515
00516 #ifndef ModelInit
00517 # define ModelInit
00518 #endif
00519
00523 #define StartModel \
00524 struct CellType \
00525 { \
00526 double area; \
00527 Point3d pos; \
00528 Point3d normal; \
00529 double value; \
00530 CellAttributes\
00531 }; \
00532 \
00533 struct JunctionType \
00534 { \
00535 Point3d pos; \
00536 Point3d normal; \
00537 JunctionAttributes\
00538 }; \
00539 \
00540 struct CellEdgeType \
00541 { \
00542 CellEdgeAttributes\
00543 }; \
00544 \
00545 struct WallType \
00546 { \
00547 WallAttributes\
00548 }; \
00549 \
00550 struct CellJunctionEdgeType \
00551 { \
00552 CellJunctionEdgeAttributes\
00553 }; \
00554 \
00555 struct JunctionCellEdgeType \
00556 { \
00557 JunctionCellEdgeAttributes\
00558 }; \
00559 \
00560 class ModelClass; \
00561 typedef tissue::Tissue<ModelClass, CellType, JunctionType, WallType, CellEdgeType, CellJunctionEdgeType, JunctionCellEdgeType> Tissue; \
00562 \
00563 EXPORT_COMPLEX_TYPES(Tissue); \
00564 \
00565 struct ModelClass : public tissue_model::TissueModel<ModelClass,Tissue> \
00566 { \
00567 typedef tissue_model::TissueModel<ModelClass,Tissue> ParentClass; \
00568 ModelClass(QObject *parent) \
00569 : ParentClass(parent)\
00570 ModelInit \
00571 { \
00572 readTissueParam(); \
00573 registerFiles(); \
00574 initialize(); \
00575 }
00576
00580 #define EndModel \
00581 }; DEFINE_MODEL(ModelClass)
00582
00583 #endif // TISSUE_MODEL_H