cellsystem_model.h

00001 #ifndef CELLSYSTEM_MODEL_H
00002 #define CELLSYSTEM_MODEL_H
00003 
00004 #include <vve.h>
00005 #include <util/parms.h>
00006 #include <util/palette.h>
00007 #include <util/watchdog.h>
00008 #include <util/vector.h>
00009 
00010 #include <algorithms/tissue.h>
00011 #include <algorithms/cellsystem.h>
00012 
00013 #include <iostream>
00014 
00015 typedef util::Vector<3,double> Point3d;
00016 
00017 namespace cellsystem_model
00018 {
00019   using std::endl;
00020   using std::cout;
00021 
00022   template <typename TissueClass, typename RealModel>
00023   struct CellSystemModel : public cell_system::CellSystem<TissueClass,RealModel>
00024   {
00025     typedef cell_system::CellSystem<TissueClass,RealModel> ParentClass;
00026 
00027     IMPORT_COMPLEX_TYPES(TissueClass);
00028 
00029     typedef graph::VVBiGraph<typename cell::content_t, typename junction::content_t> ReferenceGraph;
00030 
00031     util::WatchDog rex;
00032     util::Palette palette;
00033 
00034     int backColor;
00035     int wallColor;
00036     bool division;
00037     bool showReference;
00038     bool torusWorld;
00039     double referenceVectorSize;
00040     bool stopAfterRules, stopBeforeRules, applyRule;
00041     std::vector<int> polygon_sizes;
00042     std::vector<int> symbol_color;
00043 
00044     ReferenceGraph reference;
00045     cell_system::label_t axiom;
00046     Point3d init_ref;
00047 
00048     TissueClass& T;
00049 
00050     virtual void readParms()
00051     {
00052       util::Parms parms("view.v");
00053       parms("Main", "ViewRulesApplication", this->viewRulesApplication);
00054       parms("Main", "ViewRulesDefinitions", this->viewRulesDefinitions);
00055       parms("Main", "ShowReference", this->showReference);
00056       parms("Main", "ReferenceVectorSize", this->referenceVectorSize);
00057       parms("Main", "StopAfterRules", stopAfterRules);
00058       parms("Main", "StopBeforeRules", stopBeforeRules);
00059       parms("Main", "TorusWorld", torusWorld);
00060 
00061       parms("View", "BackColor", backColor);
00062       T.readViewParms(parms, "View");
00063       this->readMechanicParam(parms, "Mechanic");
00064       this->readSymbols(parms, "Symbols");
00065       this->readRules(parms, "Rules");
00066 
00067       readSymbolsParams(parms, "Symbols");
00068 
00069       QString axiom_name;
00070       parms("Init", "Axiom", axiom_name);
00071       axiom = this->label_numbers[axiom_name];
00072       parms("Init", "Reference", init_ref);
00073       if(this->viewRulesDefinitions)
00074       {
00075         cout << "Axiom: " << this->label_names[axiom].toStdString() << endl;
00076         cout << "Reference vector: " << init_ref << endl;
00077       }
00078 
00079       readParam(parms);
00080     }
00081 
00082     virtual void readParam(util::Parms&) {}
00083 
00084     void readSymbolsParams(util::Parms& parms, QString section)
00085     {
00086       polygon_sizes.clear();
00087       symbol_color.clear();
00088       polygon_sizes.resize(this->label_names.size(), 0);
00089       symbol_color.resize(this->label_names.size(), 1);
00090       forall(const QString& symbol, this->label_names)
00091       {
00092         int lab = this->label_numbers[symbol];
00093         QString val;
00094         //cout << "Parameters of symbol " << this->label_names[lab] << ":";
00095         if(parms(section, symbol, val))
00096         {
00097           QStringList lst = val.split(" ");
00098           forall(const QString& field, lst)
00099           {
00100             QStringList s = field.split("=");
00101             if(s.size() != 2)
00102             {
00103               cout << "Error, field '" << field.toStdString() << ", is not valid" << endl;
00104               continue;
00105             }
00106             if(s[0] == "polygon")
00107             {
00108               bool ok;
00109               int n = s[1].toInt(&ok);
00110               if(!ok)
00111               {
00112                 cout << "Cannot read number of sides of polygon ('" << s[1].toStdString() << "')" << endl;
00113               }
00114               else
00115                 polygon_sizes[lab] = n;
00116             }
00117             else if(s[0] == "color")
00118             {
00119               bool ok;
00120               int n = s[1].toInt(&ok);
00121               if(!ok)
00122               {
00123                 cout << "Cannot read color number ('" << s[1].toStdString() << "')" << endl;
00124               }
00125               else
00126                 symbol_color[lab] = n;
00127             }
00128           }
00129         }
00130       }
00131     }
00132 
00133     void modifiedFiles( const std::set<std::string>& filenames )
00134     {
00135       if(filenames.count("view.v"))
00136         readParms();
00137       rex.watch(filenames);
00138     }
00139 
00140     CellSystemModel(QObject *parent)
00141       : cell_system::CellSystem<TissueClass, RealModel>(parent)
00142       , rex(this)
00143       , palette("pal.map")
00144       , T(ParentClass::T)
00145     {
00146       rex.addObject(&palette);
00147       T.palette = &palette;
00148       applyRule = false;
00149     }
00150 
00151     void initDraw()
00152     {
00153       glEnable(GL_NICEST);
00154       glDisable(GL_CULL_FACE);
00155     }
00156 
00157     void preDraw()
00158     {
00159       util::Palette::Color bg = palette.getColor(backColor);
00160       glClearColor(bg.r(), bg.g(), bg.b(), 1.0);
00161       T.preDraw();
00162       glEnable(GL_BLEND);
00163       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
00164     }
00165 
00166     void postDraw()
00167     {
00168       glDisable(GL_BLEND);
00169       T.postDraw();
00170     }
00171 
00172     void draw(Viewer *viewer)
00173     {
00174       qglviewer::Vec pmin(HUGE_VAL, HUGE_VAL, HUGE_VAL), pmax(-HUGE_VAL,-HUGE_VAL,-HUGE_VAL);
00175       palette.useColor(wallColor);
00176       forall_named(const cell& c, T.S, cells)
00177       {
00178         util::Palette::Color cell_color;
00179         if(c->label >= symbol_color.size())
00180         {
00181           cell_color = palette.getColor(backColor);
00182         }
00183         else
00184         {
00185           cell_color = palette.getColor(symbol_color[c->label]);
00186         }
00187         T.drawCell(c, cell_color, cell_color);
00188         forall(const junction& j, T.S.neighbors(c))
00189         {
00190           const Point3d& p = j->pos;
00191           if(p.x() < pmin.x)
00192             pmin.x = p.x();
00193           if(p.y() < pmin.y)
00194             pmin.y = p.y();
00195           if(p.z() < pmin.z)
00196             pmin.z = p.z();
00197           if(p.x() > pmax.x)
00198             pmax.x = p.x();
00199           if(p.y() > pmax.y)
00200             pmax.y = p.y();
00201           if(p.z() > pmax.z)
00202             pmax.z = p.z();
00203         }
00204         if(showReference)
00205         {
00206           glColor3f(1,1,1);
00207           Point3d s = c->pos;
00208           Point3d ref = referenceVector(c);
00209           ref.normalize();
00210           ref *= referenceVectorSize;
00211           s -= ref/2;
00212           Point3d e = s+ref;
00213           viewer->drawArrow(Vec(s), Vec(e));
00214         }
00215       }
00216 
00217       viewer->setSceneBoundingBox(pmin, pmax);
00218     }
00219 
00220     void updateFromOld( const cell& cl, const cell& cr, const cell& c,
00221                         const typename TissueClass::division_data& ddata, TissueClass& T)
00222     {
00223       ParentClass::updateFromOld(cl, cr, c, ddata, T);
00224 
00225       std::vector<junction> to_clean;
00226       forall(const junction& j, reference.neighbors(c))
00227       {
00228         if(reference.iValence(j) == 1)
00229           to_clean.push_back(j);
00230       }
00231       reference.erase(c);
00232       forall(const junction& j, to_clean)
00233       {
00234         reference.erase(j);
00235       }
00236       reference.insert(cl);
00237       reference.insert(cr);
00238       forall(const junction& j, T.S.neighbors(cl))
00239       {
00240         if(!T.OldS.edge(c, j))
00241         {
00242           reference.insert(j);
00243           reference.insertEdge(cl, j);
00244           reference.insertEdge(cr, j);
00245         }
00246       }
00247     }
00248 
00249     void insertMissingEdges(const cell& c)
00250     {
00251       int size_cell = polygon_sizes[c->label];
00252       int diff = size_cell - T.S.valence(c);
00253       if(diff > 0)
00254       {
00255         if(this->viewRulesApplication)
00256         {
00257           cout << "Cell of label " << this->label_names[c->label].toStdString() << " has only " << T.S.valence(c) << " edges" << endl;
00258         }
00259         // Then add the missing number of vertices to an external edge
00260         // If there are no external edge, then do nothing
00261         forall(const junction& j, T.S.neighbors(c))
00262         {
00263           const junction& jn = T.S.nextTo(c, j);
00264           if(T.border(j, jn))
00265           {
00266             Point3d u = jn->pos - j->pos;
00267             u /= diff+1;
00268             junction prev = j;
00269             for(int i = 0 ; i < diff ; ++i)
00270             {
00271               const junction& v = algorithms::insert(prev, jn, T.W);
00272               v->pos = prev->pos + u;
00273               T.S.insert(v);
00274               T.S.spliceBefore(c, jn, v);
00275               T.S.insertEdge(v, c);
00276               prev = v;
00277             }
00278             break;
00279           }
00280         }
00281       }
00282     }
00283 
00284     virtual Point3d referenceVector(const cell& c)
00285     {
00286       if(reference.valence(c) < 2)
00287       {
00288         return init_ref;
00289       }
00290       else
00291       {
00292         const junction& v = reference.anyIn(c);
00293         const junction& n = reference.nextTo(c, v);
00294         Point3d ref = v->pos - n->pos;
00295         ref = Point3d(ref.y(), -ref.x(), 0);
00296         if(ref * (v->pos - c->pos) > 0)
00297         {
00298           ref *= -1;
00299         }
00300         return ref;
00301       }
00302     }
00303 
00304     bool apply_division()
00305     {
00306       this->step_cellsystem_division();
00307       if(torusWorld)
00308       {
00309         forall_named(const cell& c, T.S, cells)
00310         {
00311           insertMissingEdges(c);
00312         }
00313       }
00314       if(stopAfterRules)
00315       {
00316         this->stop();
00317         return true;
00318       }
00319       return false;
00320     }
00321 
00322     void cellsystem_step()
00323     {
00324       if(stopBeforeRules and applyRule)
00325       {
00326         applyRule = false;
00327         if(apply_division())
00328           return;
00329       }
00330       if(this->step_cellsystem_meca())
00331       {
00332         if(stopBeforeRules)
00333         {
00334           cout << "Rule to be applied ..." << endl;
00335           applyRule = true;
00336           this->stop();
00337         }
00338         else
00339         {
00340           apply_division();
00341         }
00342       }
00343     }
00344 
00345     virtual void initialize() {}
00346 
00347     void defineReferenceWall(const cell& c, const junction& v1, const junction& v2)
00348     {
00349       reference.insert(c);
00350       reference.insert(v1);
00351       reference.insert(v2);
00352       reference.insertEdge(c, v1);
00353       reference.insertEdge(c, v2);
00354     }
00355 
00356     void initReference()
00357     {
00358       forall(const cell& c, T.C)
00359       {
00360         reference.insert(c);
00361       }
00362     }
00363 
00364     void initTissue()
00365     {
00366       if(T.C.empty())
00367       {
00368         int nb_sides = polygon_sizes[axiom];
00369         if(nb_sides == 0)
00370         {
00371           cout << "You have to specify a number of sides for the axiom" << endl;
00372           return;
00373         }
00374         std::vector<junction> junctions(nb_sides, junction(0));
00375         for(int i = 0 ; i < nb_sides ; i++)
00376         {
00377           junction v;
00378           v->pos = Point3d(cos(2*M_PI/nb_sides*i), sin(2*M_PI/nb_sides*i), 0);
00379           junctions[i] = v;
00380         }
00381 
00382         cell c;
00383         c->pos = Point3d(0,0,0);
00384 
00385         T.addCell(c, junctions);
00386         c->label = axiom;
00387 
00388         this->updateCellsArea();
00389       }
00390     }
00391 
00392     void step()
00393     {
00394       this->cellsystem_step();
00395     }
00396 
00397   };
00398 }
00399 
00400 #ifndef CellAttributes
00401 #  define CellAttributes
00402 #endif
00403 
00404 #ifndef JunctionAttributes
00405 #  define JunctionAttributes
00406 #endif
00407 
00408 #ifndef CellEdgeAttributes
00409 #  define CellEdgeAttributes
00410 #endif
00411 
00412 #ifndef WallAttributes
00413 #  define WallAttributes
00414 #endif
00415 
00416 #ifndef CellJunctionEdgeAttributes
00417 #  define CellJunctionEdgeAttributes
00418 #endif
00419 
00420 #ifndef JunctionCellEdgeAttributes
00421 #  define JunctionCellEdgeAttributes
00422 #endif
00423 
00424 #ifndef ModelInit
00425 #  define ModelInit
00426 #endif
00427 
00428 #define StartModel \
00429   struct CellType : public cell_system::CellSystemCell \
00430   { \
00431     CellAttributes\
00432   }; \
00433  \
00434   struct JunctionType : public cell_system::CellSystemJunction \
00435   { \
00436     JunctionAttributes\
00437   }; \
00438  \
00439   struct CellEdgeType \
00440   { \
00441     bool serialize(storage::VVEStorage&) { return true; } \
00442     CellEdgeAttributes\
00443   }; \
00444  \
00445   struct WallType \
00446   { \
00447     bool serialize(storage::VVEStorage&) { return true; } \
00448     WallAttributes\
00449   }; \
00450  \
00451   struct CellJunctionEdgeType \
00452   { \
00453     bool serialize(storage::VVEStorage&) { return true; } \
00454     CellJunctionEdgeAttributes\
00455   }; \
00456  \
00457   struct JunctionCellEdgeType \
00458   { \
00459     bool serialize(storage::VVEStorage&) { return true; } \
00460     JunctionCellEdgeAttributes\
00461   }; \
00462  \
00463   class ModelClass; \
00464   typedef tissue::Tissue<ModelClass, CellType, JunctionType, CellEdgeType, WallType, CellJunctionEdgeType, JunctionCellEdgeType> Tissue; \
00465  \
00466   struct ModelClass : public cellsystem_model::CellSystemModel<Tissue,ModelClass> \
00467   { \
00468     typedef cellsystem_model::CellSystemModel<Tissue,ModelClass> ParentClass;\
00469     ModelClass(QObject *parent) \
00470       : ParentClass(parent) \
00471       ModelInit \
00472     { \
00473       readParms(); \
00474       registerFile("view.v"); \
00475       initialize(); \
00476       initTissue(); \
00477       initReference(); \
00478       updateCellsArea(); \
00479     } \
00480 
00481 #define EndModel }; DEFINE_MODEL(ModelClass);
00482 
00483 #endif // CELLSYSTEM_MODEL_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:37:50 2013 for VVE by  doxygen 1.6.3