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
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
00260
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