Changeset - a58b80c85b6f
[Not reviewed]
default
0 46 0
Michael Guravage - 15 years ago 2010-06-17 12:25:40
michael.guravage@cwi.nl
Cleanup: e.g. removed commented out and otherwise disabled code.
--
user: Michael Guravage <michael.guravage@cwi.nl>
branch 'default'

changed src/OptionFileDialog.cpp
changed src/OptionFileDialog.h
changed src/UniqueMessage.cpp
changed src/VirtualLeaf.cpp
changed src/apoplastitem.cpp
changed src/apoplastitem.h
changed src/build_models/auxingrowthplugin.cpp
changed src/build_models/meinhardtplugin.cpp
changed src/build_models/testplugin.h
changed src/canvas.cpp
changed src/canvas.h
changed src/cell.cpp
changed src/cell.h
changed src/cellbase.cpp
changed src/cellbase.h
changed src/data_plot.cpp
changed src/data_plot.h
changed src/flux_function.h
changed src/forwardeuler.cpp
changed src/infobar.h
changed src/mainbase.cpp
changed src/mainbase.h
changed src/matrix.cpp
changed src/mesh.h
changed src/modelcatalogue.cpp
changed src/node.cpp
changed src/node.h
changed src/nodeitem.cpp
changed src/nodeset.h
changed src/output.cpp
changed src/output.h
changed src/parse.cpp
changed src/parse.h
changed src/random.cpp
changed src/random.h
changed src/sqr.h
changed src/vector.h
changed src/vleafmodel.h
changed src/wall.cpp
changed src/wallbase.cpp
changed src/wallbase.h
changed src/wallitem.cpp
changed src/wallitem.h
changed src/warning.cpp
changed src/warning.h
changed src/xmlwrite.cpp
46 files changed with 332 insertions and 1831 deletions:
0 comments (0 inline, 0 general)
src/OptionFileDialog.cpp
Show inline comments
 
@@ -27,27 +27,23 @@ using namespace  std;
 

	
 
static const std::string _module_id("$Id$");
 

	
 
OptionFileDialog::OptionFileDialog(QWidget *parent, const char *name, bool modal) : Q3FileDialog(parent, name, modal) {
 

	
 
	//cerr << "This is an OptionFileDialog\n";
 
	geometrycheck = new QCheckBox("geometry",this);
 
	geometrycheck -> setCheckState(Qt::Checked);
 
	
 
	parcheck = new QCheckBox("parameters", this);
 
	parcheck -> setCheckState(Qt::Checked);
 
	
 
	//timecheck = new QCheckBox("time",this);
 
	//timecheck -> setCheckState(Qt::Checked);
 
	
 
	addToolButton(geometrycheck);
 
	//addToolButton(timecheck);
 
	addToolButton(parcheck);
 

	
 
};
 

	
 
OptionFileDialog::OptionFileDialog ( const QString & dirName, const QString & filter , QWidget * parent, const char * name , bool modal  ) :
 
		Q3FileDialog(dirName, filter, parent, name, modal) {
 
		
 
			cerr << "This is an OptionFileDialog\n";
 
					
 
	};
src/OptionFileDialog.h
Show inline comments
 
@@ -11,31 +11,33 @@
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#ifndef _OPTIONFILEDIALOG_H_
 
#define _OPTIONFILEDIALOG_H_
 

	
 
#include <Q3FileDialog>
 
#include <QCheckBox>
 

	
 
class OptionFileDialog : public Q3FileDialog {
 
	Q_OBJECT
 
public:
 
	OptionFileDialog(QWidget *parent = 0, const char *name = 0, bool modal = false);
 
	OptionFileDialog ( const QString & dirName, const QString & filter = QString(), QWidget * parent = 0, const char * name = 0, bool modal = false );
 
	
 
	bool readGeometryP(void) const { return geometrycheck->checkState()==Qt::Checked; }
 
	bool readParametersP(void) const { return parcheck->checkState()==Qt::Checked; }
 

	
 
private:
 
	QCheckBox *geometrycheck;	
 
	QCheckBox *parcheck;
 
	//QCheckBox *timecheck;
 
	
 
};
 

	
 
};
 
#endif
src/UniqueMessage.cpp
Show inline comments
 
@@ -33,35 +33,31 @@ static const std::string _module_id("$Id
 
using namespace std;
 
UniqueMessageBox::UniqueMessageBox ( /* Icon icon,*/ 
 
									 const QString & title, 
 
									 const QString & text, 
 
									 QWidget * parent ,
 
									 Qt::WindowFlags f ) : 
 
QDialog(parent, f) {
 
	
 
	label = new QLabel(text);
 
	boxtext = text;
 
	
 
	show_again = new QCheckBox(tr("Do not show this message again"));
 
	//addButton(show_again, QMessageBox::ActionRole);
 
	//addButton(QMessageBox::Ok);
 
	okButton = new QPushButton(tr("Ok"));
 
		
 
	if (issued_messages.contains(boxtext) ) {
 
		
 
		cerr << "Saw message before\n";
 
		display = false;
 
	} else {
 
		//cerr << "First time message\n";
 
		//issued_messages << text;
 
		display=true;
 
	}
 
	
 
	connect(okButton, SIGNAL(clicked()), this, SLOT(close()) );
 
	QHBoxLayout *hlayout = new QHBoxLayout;
 
	hlayout->addWidget(label);
 
	hlayout->addWidget(okButton);
 
	QVBoxLayout *layout = new QVBoxLayout;
 
	layout->addLayout(hlayout);
 
	layout->addWidget(show_again);
 
	setLayout(layout);
 
	setWindowTitle(title);
src/VirtualLeaf.cpp
Show inline comments
 
@@ -48,36 +48,29 @@
 

	
 
#ifdef HAVE_QWT
 
#include "data_plot.h"
 
#endif
 
#include <QPalette>
 
#include <QBrush>
 
#include <QToolTip>
 
#include "simplugin.h"
 
#include <QPluginLoader>
 
#include <QDir>
 
#include "modelcatalogue.h"
 

	
 
/* #define _xstr_(s) _str_(s)
 
   #define _str_(s) #s
 
   #include _xstr_(REACTIONS_HEADER)
 
*/
 

	
 
static const std::string _module_id("$Id$");
 

	
 
extern Parameter par;
 

	
 
MainBase *main_window = 0;
 
//double auxin_account = 0.;
 

	
 

	
 
#ifdef XFIGGRAPHICS
 
#define TIMESTEP double Graphics::TimeStep(void)
 
#endif
 

	
 
class PrintNode {
 
public:
 
  void operator() (const Node &n) const 
 
  {
 
    cerr << n.Index() << ": " << n <<  endl;
 
  }
 
};
 
@@ -183,34 +176,24 @@ void MainBase::Plot(int resize_stride) {
 
  if ( ( batch || MovieFramesP() )) {
 
		
 
    static int frame = 0;
 
    // frame numbers are sequential for the most frequently written file type.
 
    // for the less frequently written file type they match the other type
 
    if (!(count%par.storage_stride) )  {
 
		
 
      stringstream fname;
 
      fname << par.datadir << "/leaf.";
 
      fname.fill('0');
 
      fname.width(6);
 
	
 
      /* 
 
	 fname << frame << ".pdf";
 
	 if (par.storage_stride <= par.xml_storage_stride) {
 
	 frame++;
 
	 }
 
			
 
	 // Write high-res JPG snapshot every plot step
 
	 Save(fname.str().c_str(), "PDF");
 
      */
 
			
 
      fname << frame << ".jpg";
 
      if (par.storage_stride <= par.xml_storage_stride) {
 
	frame++;
 
      }
 
			
 
      // Write high-res JPG snapshot every plot step
 
      Save(fname.str().c_str(), "JPEG",1024,768);
 
    }
 
	
 
    if (!(count%par.xml_storage_stride)) {
 
      stringstream fname;
 
      fname << par.datadir << "/leaf.";
 
@@ -268,84 +251,50 @@ TIMESTEP {
 
    // i.e. cell wall tension equillibrization is much faster
 
    // than biological processes, including division, cell wall yielding
 
    // and cell expansion
 
    mesh.InsertNodes(); // (this amounts to cell wall yielding)
 
			
 
    if ( (-dh) < par.energy_threshold) {
 
				
 
      mesh.IncreaseCellCapacityIfNecessary();
 
      mesh.DoCellHouseKeeping();
 
      //mesh.LoopCurrentCells(mem_fun(&plugin->CellHouseKeeping)); // this includes cell division
 
				
 
      // Reaction diffusion	
 
      /*CelltoCellTransport *transport_f = &TestPlugin::CelltoCellTransport;
 
	CellReaction *cellreaction_f = new plugin->CellDynamics();
 
	WallReaction *wall_f = new WallDynamics();*/
 
				
 
      mesh.ReactDiffuse(par.rd_dt);
 
				
 
      t++;
 
				
 
      Plot(par.resize_stride);
 
		
 
      /*QVector< QPair<double, int> > angles=mesh.VertexAnglesValues();
 
	QString afname=QString("Angles/anglesvalues%1.dat").arg(t,6,10,QChar('0'));
 
	ofstream af(afname.toStdString().c_str());
 
      */
 
		
 
      /*for (QVector< QPair<qreal, int> >::const_iterator v=angles.begin();
 
	v!=angles.end();
 
	v++) {
 
	af << v->first << " " << v->second << endl;
 
	}
 
      */
 
    }
 
		
 
  } else {
 
			
 
    /*  TransportFunction *transport_f = new CelltoCellTransport();
 
	CellReaction *cellreaction_f = new CellDynamics();
 
	WallReaction *wall_f = new WallDynamics();
 
			
 
	mesh.ReactDiffuse_New(transport_f, cellreaction_f, wall_f, par.rd_dt);*/
 
    mesh.ReactDiffuse(par.rd_dt);
 
		
 
    Plot(par.resize_stride);
 
			
 
  }
 
		
 
  i++;
 
  return mesh.getTime();
 
		
 
}
 
		
 
		
 
				
 
/* Called if a cell is clicked */
 
void Cell::OnClick(QMouseEvent *e) {
 

	
 
  e = NULL; // use assignment merely to obviate compilation warning
 

	
 
  /* #ifdef HAVE_QWT
 
  // Launch DataPlot window
 
  QStringList curvenames;
 
  for (int i=0;i<NChem();i++) {
 
  curvenames += QString("Chem #%1").arg(i);
 
  }
 
  PlotDialog *plot = new PlotDialog((Main *)main_window, QString("Monitor for Cell %1").arg(Index()), curvenames);
 
  QObject::connect(this, SIGNAL(ChemMonValue(double, double *)),
 
  plot, SLOT(AddValue(double,double *)));
 
  #endif
 
  */
 
  //getMesh().plugin->OnClick(*this);
 
}
 
				
 

	
 
/* Custom message handler - Default appends a newline character to the end of each line. */ 
 
void vlMessageOutput(QtMsgType type, const char *msg)
 
{
 
  switch (type) {
 
  case QtDebugMsg:
 
    //fprintf(stderr, "Debug: %s\n", msg);
 
    cerr << msg << flush;
 
    break;
 
  case QtWarningMsg:
 
@@ -469,35 +418,24 @@ int main(int argc,char **argv) {
 
    } else {
 
      main_window=new MainBase(canvas, mesh);
 

	
 
    }
 

	
 
    
 
	  
 
    canvas.setSceneRect(QRectF());
 
    if (!batch) {
 
      QObject::connect( qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()) );
 
    }
 

	
 
    // Load plugins
 
    /*QVector<SimPluginInterface *> plugins = LoadPlugins();
 
      InstallPlugin(plugins[0], main_window);
 
	  
 
      cerr << "List of models:" << endl;
 
      foreach (SimPluginInterface *p, plugins) {
 
      cerr << p->ModelID().toStdString() << endl;
 
      }
 
    */
 

	
 
	 	  
 
    // Install model or read catalogue of models
 
    ModelCatalogue model_catalogue(&mesh, useGUI?(Main *)main_window:0,modelfile);
 
    if (useGUI)
 
      model_catalogue.PopulateModelMenu();
 
    model_catalogue.InstallFirstModel();
 
    
 

	
 
    if (leaffile) 
 
      main_window->Init(leaffile);
 
	  
 
    Cell::SetMagnification(1);
 
    Cell::setOffset(0,0);
src/apoplastitem.cpp
Show inline comments
 
@@ -34,26 +34,26 @@ static const std::string _module_id("$Id
 
ApoplastItem::ApoplastItem( Wall *w, QGraphicsScene *canvas )
 
: QGraphicsLineItem( 0, canvas ), SimItemBase( w, canvas){
 
		
 
	setColor();
 
	
 
	// line with "PIN1"is a bit inside the cell wall
 
	Vector edgevec = (*(w->N2())) - (*(w->N1()));
 
	Vector perp = edgevec.Normalised().Perp2D();
 
	
 
	Vector offs = Cell::Offset();
 
	double factor = Cell::Factor();
 
	
 
	Vector from = ( offs + *(w->N1()) ) * factor;// + (wn==1?-1:1) * par.outlinewidth;// * 0.2 * factor * perp;
 
	Vector to = ( offs + *(w->N2()) ) *factor;// + (wn==1?-1:1) * par.outlinewidth;// * 0.2 * factor * perp;
 
	Vector from = ( offs + *(w->N1()) ) * factor;
 
	Vector to = ( offs + *(w->N2()) ) *factor;
 
	
 
	
 
	setLine(( from.x ),
 
			( from.y ),
 
			( to.x ),
 
			( to.y ) );
 
	setZValue(12);
 
}
 

	
 

	
 
void ApoplastItem::setColor(void) {
 
	
 
@@ -61,15 +61,15 @@ void ApoplastItem::setColor(void) {
 
	static const QColor purple("Purple");
 
	static const QColor blue("blue");
 
	
 
	Wall *w=&getWall();
 
	double val = w->getApoplast(2);
 

	
 
	diffcolor.setRgb( 0,0,(int)( ( val / (1 + val) )*255.));
 
	setPen (QPen(diffcolor, 20) );
 

	
 
}
 

	
 
void ApoplastItem::OnClick(QMouseEvent *e) {
 
  e = NULL; // merely to obviate compile time warning
 
  e = NULL; // merely to obviate compilation warnings
 
}
 

	
src/apoplastitem.h
Show inline comments
 
@@ -31,20 +31,18 @@
 
#include "simitembase.h"
 
#include "wall.h"
 

	
 
//! Shows transporter concentrations at one side of the wall
 

	
 
class ApoplastItem : public QGraphicsLineItem, public SimItemBase
 
{
 
public:
 
	ApoplastItem( Wall *n, QGraphicsScene *canvas );
 
	virtual ~ApoplastItem() {}
 
	Wall &getWall(void) const { return *class_cast<Wall*>(obj); }
 
	void OnClick(QMouseEvent *e);  
 
	//virtual void userMove(double dx, double dy);  
 
	//virtual void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
 
	void setColor(void);
 
private:
 
	int wn;
 
};
 

	
 
#endif
src/build_models/auxingrowthplugin.cpp
Show inline comments
 
@@ -49,34 +49,24 @@ void AuxinGrowthPlugin::OnDivide(ParentI
 
	
 
	// After divisions, parent and daughter cells get a standard stock of PINs.
 
	daughter1->SetChemical(1, par->initval[1]);
 
	daughter2->SetChemical(1, par->initval[1]);
 
	
 
	
 
	// Reset transporter values of parent and daughter
 
	QList<WallBase *> walls;
 
	foreach(WallBase *w, walls) { 
 
		w->setTransporter(daughter1, 1, 0.);
 
	}
 
	
 
	//daughter1.LoopWalls(Wall::setTransporter(&daughter1, 1, 0.));
 
	
 
	
 
	/* for (list<Wall *>::const_iterator w=daughter2.walls.begin();
 
		 w!=daughter2.walls.end();
 
		 w++) {
 
		// reset transporter value
 
		(*w)->setTransporter(&daughter2, 1, 0.);
 
	}
 
	*/
 
}
 

	
 
void AuxinGrowthPlugin::SetCellColor(CellBase *c, QColor *color) { 
 

	
 
	// Red: PIN1
 
	// Green: Auxin
 
	if (c->CellType()==1) color->setNamedColor("Blue"); 
 
	else color->setRgb(c->Chemical(1)/(1+c->Chemical(1)) * 255.,(c->Chemical(0)/(1+c->Chemical(0)) * 255.),/* (chem[2]/(1+chem[2]) *255.) */ 0);
 
	
 
}
 

	
 

	
 
@@ -97,38 +87,36 @@ void AuxinGrowthPlugin::CellHouseKeeping
 
	
 

	
 
}
 

	
 
void AuxinGrowthPlugin::CelltoCellTransport(Wall *w, double *dchem_c1, double *dchem_c2) {
 

	
 
	// leaf edge is const source of auxin
 
    // (Neumann boundary condition: we specify the influx)
 
    if (w->C2()->BoundaryPolP()) {
 
		if (w->AuxinSource()) {
 
			double aux_flux = par->leaf_tip_source * w->Length();
 
			dchem_c1[0]+= aux_flux;
 
			// dchem_c2 is undefined..!
 
			return;
 
		} else {
 
			return;
 
		}
 
	}
 
	
 
	
 
	if (w->C1()->BoundaryPolP()) {
 
		
 
		if (w->AuxinSource()) {
 
			double aux_flux = par->leaf_tip_source * w->Length();
 
			dchem_c2[0] += aux_flux;
 
			// dchem_c1 is undefined...!
 
			return;
 
		} else {
 
			
 
			if (w->AuxinSink()) {
 
				
 
				// efflux into Shoot Apical meristem
 
				// we assume all PINs are directed towards shoot apical meristem
 
				dchem_c2[0] -= par->sam_efflux * w->C2()->Chemical(0) / (par->ka + w->C2()->Chemical(0));
 
				
 
				return;
 
			} else 
 
				return;
 
@@ -158,59 +146,57 @@ void AuxinGrowthPlugin::CelltoCellTransp
 
	
 
}
 

	
 
void AuxinGrowthPlugin::WallDynamics(Wall *w, double *dw1, double *dw2) {
 

	
 
	
 
	
 
    // Cells polarize available PIN1 to Shoot Apical Meristem
 
    if (w->C2()->BoundaryPolP()) {
 
		if (w->AuxinSink()) {
 
			
 
			dw1[0] = 0.; dw2[0] = 0.;
 
			//dw1[2] = 0.; dw2[2] = 0.;
 
            
 
			// assume high auxin concentration in SAM, to convince PIN1 to polarize to it
 
			// exocytosis regulated0
 
			double nb_auxin = par->sam_auxin;
 
			double receptor_level = nb_auxin * par->r / (par->kr + nb_auxin);
 
			
 
			dw1[1] = par->k1 * w->C1()->Chemical(1) * receptor_level /( par->km + w->C1()->Chemical(1) ) - par->k2 * w->Transporters1(1);
 
			
 
			dw2[1] = 0.;
 
			return;
 
			
 
		} else {
 
			dw1[0]=dw2[0]=dw1[1]=dw2[1];//=dw1[2]=dw2[2];
 
			dw1[0]=dw2[0]=dw1[1]=dw2[1];
 
			return;
 
		}
 
    }
 
    
 
    if (w->C1()->BoundaryPolP()) {
 
		if (w->AuxinSink())  {
 
			
 
			dw1[0] = 0.; dw2[0] = 0.;
 
			//dw1[2] = 0.; dw2[2] = 0.;
 
			
 
			// assume high auxin concentration in SAM, to convince PIN1 to polarize to it
 
			// exocytosis regulated
 
			double nb_auxin = par->sam_auxin;
 
			double receptor_level = nb_auxin * par->r / (par->kr + nb_auxin);
 
			dw2[1] = par->k1 * w->C2()->Chemical(1) * receptor_level /( par->km + w->C2()->Chemical(1) ) - par->k2 * w->Transporters2(1);
 
			
 
			dw1[1] = 0.;
 
			return;
 
			
 
		}  else {
 
			dw1[0]=dw2[0]=dw1[1]=dw2[1];//=dw1[2]=dw2[2];
 
			dw1[0]=dw2[0]=dw1[1]=dw2[1];
 
			return;
 
		}
 
    }
 
    
 
    
 
    
 
    // PIN1 localization at wall 1
 
    // Note: chemical 0 is Auxin (intracellular storage only)
 
    // Chemical 1 is PIN1 (walls and intracellular storage)
 
    //! \f$ \frac{d Pij/dt}{dt} = k_1 A_j \frac{P_i}{L_ij} - k_2 P_{ij} \f$
 
    // Note that Pij is measured in term of concentration (mol/L)
 
    // Pi in terms of quantity (mol)
 
@@ -228,26 +214,24 @@ void AuxinGrowthPlugin::WallDynamics(Wal
 
    double  auxin1 = w->C1()->Chemical(0);
 
    double receptor_level2 = auxin1 * par->r / (par->kr + auxin1);
 
    
 
    // normal cell
 
    dPijdt2 = 
 
	
 
	// exocytosis regulated
 
	par->k1 * w->C2()->Chemical(1) * receptor_level2 / ( par->km + w->C2()->Chemical(1) ) - par->k2 * w->Transporters2(1);
 
    
 
    /* PIN1 of neighboring vascular cell inhibits PIN1 endocytosis */
 
    
 
    dw1[0] = 0.; dw2[0] = 0.;
 
    //dw1[2] = 0.; dw2[2] = 0.;
 
    
 
    dw1[1] = dPijdt1;
 
    dw2[1] = dPijdt2;
 
}
 

	
 
double AuxinGrowthPlugin::complex_PijAj(CellBase *here, CellBase *nb, Wall *w) { 
 
	
 
	// gives the amount of complex "auxinreceptor-Pin1"  at the wall (at QSS) 
 
	//return here.Chemical(1) * nb.Chemical(0) / ( par->km + here.Chemical(1));
 
	
 
	double nb_aux = (nb->BoundaryPolP() && w->AuxinSink()) ? par->sam_auxin : nb->Chemical(0);
 
	double receptor_level = nb_aux * par->r / (par->kr + nb_aux);
 
	
 
@@ -255,32 +239,24 @@ double AuxinGrowthPlugin::complex_PijAj(
 
	
 
}
 

	
 
void AuxinGrowthPlugin::CellDynamics(CellBase *c, double *dchem) {
 
	// Note: Pi and Pij measured in numbers of molecules, not concentrations		
 
		double dPidt = 0.;
 
		
 
		double sum_Pij = c->SumTransporters( 1 );
 
		
 
		// exocytosis regulated:
 
	
 
	dPidt = -par->k1 * c->ReduceCellAndWalls<double>( far_3_arg_mem_fun( *this, &AuxinGrowthPlugin::complex_PijAj ) ) + par->k2 * sum_Pij;
 
	/*for ( list<Wall *>::const_iterator w = c->walls.begin();
 
		 w!=walls.end();
 
		 w++) {
 
		if ((*w)->C1() == c)
 
			dPidt +=  complex_PijAj( (*w)->C1(), (*w)->C2(), *w );
 
		else
 
			dPidt +=  complex_PijAj( (*w)->C2(), (*w)->C1(), *w );
 
	}*/
 
	
 
	// production of PIN depends on auxin concentration
 
	dPidt +=  (c->AtBoundaryP()?par->pin_prod_in_epidermis:par->pin_prod) * c->Chemical(0) - c->Chemical(1) * par->pin_breakdown;
 
	
 
	// no PIN production in SAM
 
	if (c->Boundary() == CellBase::SAM) {
 
			dchem[1]=0.;
 
		dchem[0]= - par->sam_auxin_breakdown * c->Chemical(0);
 
	} else {
 
		
 
		dchem[1] = dPidt;
 
		
src/build_models/meinhardtplugin.cpp
Show inline comments
 
@@ -108,29 +108,23 @@ void MeinhardtPlugin::WallDynamics(Wall 
 
  w = NULL;
 
	for (int c = 0;c<NChem();c++) {
 
		dw1[c] = 0.; dw2[c] = 0.;
 
    }
 
}
 

	
 
void MeinhardtPlugin::CellDynamics(CellBase *c, double *dchem) {
 

	
 
	double Y = c->Chemical(0);
 
	double A = c->Chemical(1);
 
	double H = c->Chemical(2);
 
	double S = c->Chemical(3);
 
	//double expansin = c->Chemical(4);
 

	
 
	
 
	
 
    dchem[0] = ( par->d * A - par->e * Y + Y*Y/(1 + par->f * Y*Y ) );
 
	dchem[1] = ( par->c * A*A*S/H - par->mu * A + par->rho0*Y );
 
	dchem[2] = ( par->c * A*A*S - par->nu*H + par->rho1*Y );
 
	dchem[3] = ( par->c0 - par->gamma*S - par->eps * Y * S );
 
	//dchem[4] = ( -par->expansindecay * expansin );
 
	//for (int i=0;i<4;i++) { cerr << "[ " << dchem[i] << " ]"; } cerr << endl;
 
	 
 
//	cerr << "Chemicals: "; for (int i=0;i<NChem();i++) { cerr << c->Chemical(i) << " "; } cerr << endl; 
 
	
 
// test:	dchem[0] = 0.01 * c->Chemical(0) * ( 1. - c->Chemical(0));
 
}
 

	
 

	
 
Q_EXPORT_PLUGIN2(meinhardtplugin, MeinhardtPlugin)
src/build_models/testplugin.h
Show inline comments
 
@@ -11,24 +11,26 @@
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#ifndef _TESTPLUGIN_H_
 
#define _TESTPLUGIN_H_
 

	
 
#include <QObject>
 
#include <QtGui>
 
#include <QString>
 
#include "../simplugin.h"
 

	
 

	
 
class TestPlugin : public QObject, SimPluginInterface {
 
	Q_OBJECT
 
	Q_INTERFACES(SimPluginInterface);
 

	
 
public:
 
@@ -46,15 +48,13 @@ public:
 
	// Differential equations describing chemical reactions inside the cells
 
	virtual void CellDynamics(CellBase *c, double *dchem);
 
	
 
	// to be executed after a cell division
 
	virtual void OnDivide(ParentInfo *parent_info, CellBase *daughter1, CellBase *daughter2);
 
	
 
	// to be executed for coloring a cell
 
	virtual void SetCellColor(CellBase *c, QColor *color);	
 
	// return number of chemicals
 
	virtual int NChem(void) { return 0; }
 
};
 

	
 

	
 

	
 

	
 
#endif
src/canvas.cpp
Show inline comments
 
@@ -154,123 +154,58 @@ void FigureEditor::mousePressEvent(QMous
 
  emit MousePressed();
 

	
 
  //QPointF p = matrix().inverted().map(e->pos());
 
  QPointF p = mapToScene(e->pos());
 

	
 
#ifdef QDEBUG  
 
  qDebug() << endl << "MousePressEvent location: (" << p.x() << "," << p.y() << ")." << endl;
 
  qDebug() << "Magnification:  " << Cell::Magnification() << endl;
 
  qDebug() << "Offsets:  " << Cell::Offset() << endl;
 
#endif
 
  
 

	
 
  /*  if (dynamic_cast<Main *>(parent())->RotationModeP()) {
 
  // if in rotation mode, exit it upon a mouse click
 
  dynamic_cast<Main *>(parent())->ExitRotationMode();
 
  }*/
 
  
 
  QList<QGraphicsItem *> l=scene()->items(p);
 

	
 
#ifdef QDEBUG  
 
  qDebug() << "MousePressEvents, items: " << l.size() << endl;
 
  qDebug() << "Mouse button modifier: " << e->modifiers() << endl;
 
#endif
 

	
 

	
 
    /*  if (rotation_mid_point) {
 
    
 
    // calculate rotation angle alpha
 
    QPointF q_v1 = intersection_line->line().p2();
 
    - intersection_line->line().p1();
 
    QPointF q_v2 = angle_line->line().p2();
 
    - angle_line->line().p1();
 
    
 
    Vector v1(q_v1.x(),q_v1.y());
 
    Vector v2(q_v2.x(),q_v2.y());
 
    
 
    cerr << "v1 = " << v1 << endl;
 
    cerr << "v2 = " << v2 << endl;
 
    
 
    
 
    rot_angle = v1.SignedAngle(v2);
 
    cerr << "Angle is " << rot_angle << endl;
 
    
 
    const QPointF &q_c(angle_line->line().p1());
 
    Vector center = Vector(q_c.x(), q_c.y()) / Cell::Factor() - Cell::Offset();
 
    
 
    cerr << "Center is " << center << endl;
 
    
 
    mesh.Rotate(rot_angle, center);
 
    delete angle_line;
 
    angle_line=0;
 
    delete intersection_line;
 
    intersection_line=0;
 
    
 
    viewport()->setMouseTracking( FALSE );
 
    dynamic_cast<Main *>(parent())->Plot();
 
    
 
    
 
    return;
 
    
 
    }*/
 
  
 
   
 
    if (e->button()==Qt::RightButton || l.size()==0) {
 
    
 
      //cerr << "Drawing an intersection line from " << p.x() << ", " << p.y() << endl;
 
      intersection_line = new QGraphicsLineItem( 0, scene() );
 
      intersection_line->setPen( QPen( QColor("red"), 3, Qt::DashLine ) );
 
      intersection_line->setLine( QLineF(p,p) );
 
      intersection_line->setZValue( 100 );
 
      intersection_line->show();
 
    }
 
  
 
    for (QList<QGraphicsItem *>::Iterator it=l.begin(); it!=l.end(); ++it) {
 
      /*if ( (*it)->rtti() == imageRTTI ) {
 
	ImageItem *item= (ImageItem*)(*it);
 
	if ( !item->hit( p ) )
 
	continue;
 
	}*/
 
      #ifdef QDEBUG
 
      qDebug() << typeid(**it).name() << endl;
 
      #endif
 

	
 
      if ( !strcmp(typeid(**it).name(),"8NodeItem")) {
 
	//moving = dynamic_cast<NodeItem*>(*it);
 
	//moving = *it;
 
	//moving_start = p;
 
      
 
	stringstream data_strstream;
 
	data_strstream << (dynamic_cast<NodeItem*>(*it))->getNode();
 
	dynamic_cast<Main *>(parent())->UserMessage(QString(data_strstream.str().c_str()));
 
      
 
	(dynamic_cast<NodeItem*>(*it))->OnClick(e->button());
 
      }
 
      else 
 
	if ( !strcmp(typeid(**it).name(),"8CellItem") ) {
 
      
 
	  Cell &c=((dynamic_cast<CellItem *>(*it))->getCell());      
 
	  //static int old_stride=100;
 
	  //if (!c.Source()) {
 
	  /* if (!c.Source()) {
 
	     c.SetChemical(0,par.cellsource);
 
	     //flag=true;
 
	     //c.SetSource(0,par.cellsource);
 
	     //c.Fix();
 
	     //cerr << "Setting source\n";
 
			
 
	     } else { 
 
	     //c.UnsetSource();
 
	     cerr << "Unsetting source\n";
 
	     } */
 
	  // OnClick to be defined in end-user code
 
	  c.OnClick(e);
 
	} else {
 
	  if ( !strcmp(typeid(**it).name(),"8WallItem") ) {
 
	    (dynamic_cast<WallItem *>(*it))->OnClick(e);
 
	  } 
 
	}
 
    }
 

	
 
  FullRedraw();
 
  moving = 0;
 
}
 
@@ -291,108 +226,91 @@ void FigureEditor::mouseMoveEvent(QMouse
 
    QPointF rotation_midpoint = mesh.Centroid()*Cell::Factor() - Cell::Offset();
 
    
 
        
 
    // calculate rotation angle
 
    double dy = (rotation_midpoint.y() - p.y());
 
    double dx = (rotation_midpoint.x() - p.x());
 
    double new_rot_angle = atan2(dx, dy);
 
    double d_alpha = new_rot_angle - rot_angle;
 
    rot_angle = new_rot_angle;
 
    
 
    mesh.Rotate(d_alpha, ( Vector(rotation_midpoint) + Cell::Offset() ) / Cell::Factor() );
 
    
 
    //viewport()->setMouseTracking( FALSE );
 
    dynamic_cast<Main *>(parent())->Plot(0);
 
	  FullRedraw();
 
    return;
 
  }
 
  if ( moving ) {
 
    //QPoint p = matrix().inverted().map(e->pos());
 

	
 
    QPointF p = mapToScene(e->pos());
 
    
 
    moving->userMove(p.x() - moving_start.x(),
 
		     p.y() - moving_start.y());
 
    moving_start = p;
 
    scene()->update();
 
    
 
  }
 
  
 
  //cerr << "event";
 
  
 
  // keep track of intersection line to interactively cut a growing leaf
 
  /* if (angle_line) {
 

	
 
    QPointF sp = angle_line -> line().p1(); // startpoint
 
    //QPointF ep = matrix().inverted().map(e->pos()); // endpoint
 
    QPointF ep = mapToScene(e->pos()); // endpoint
 
    angle_line -> setLine( QLineF(sp, ep) ); 
 
    scene()->update();
 
  
 
    } else { */
 
    
 
  if ( intersection_line ) {
 
    
 
    QPointF sp = intersection_line -> line().p1(); // startpoint
 
    //QPointF ep = matrix().inverted().map(e->pos()); // endpoint
 
    QPointF ep = mapToScene(e->pos()); // endpoint
 
    intersection_line -> setLine( QLineF(sp, ep) ); 
 
    scene()->update();
 
    // Need this for Mac
 
    FullRedraw();
 
    }
 
  /* } */
 
  
 
}
 

	
 
//void FigureEditor::contentsMouseReleaseEvent(QMouseEvent* e)
 
void FigureEditor::mouseReleaseEvent(QMouseEvent* e)
 
{
 
  
 
  emit MouseReleased();
 
  // intersection line for leaf was finished now.
 
  
 
  if (e->button()==Qt::LeftButton) { 
 
    if (intersection_line ) {
 
      #ifdef QDEBUG
 
      qDebug() << "Trying to cut leaf" << endl;
 
      #endif
 
      QPointF sp = intersection_line -> line().p1(); // startpoint
 
      //QPointF ep = matrix().inverted().map(e->pos()); // endpoint
 
      QPointF ep = mapToScene(e->pos());
 

	
 
      intersection_line -> setLine( QLineF(sp, ep) ); 
 
      intersection_line -> show();
 

	
 
      vector <CellItem *> intersected_cells = getIntersectedCells();
 
    
 
      // no cells selected, do nothing
 
      if (intersected_cells.size()==0) {
 
        #ifdef QDEBUG
 
	qDebug() << "No cells detected :-(" << endl;
 
	#endif
 
	return;
 
      }
 
      
 
    
 
      Vector startpoint = Vector(sp.x(), sp.y()) / Cell::Factor() - Cell::Offset();
 
      Vector endpoint = Vector(ep.x(), ep.y()) / Cell::Factor() - Cell::Offset();
 
    
 
      // Mesh &m(intersected_cells.front()->getCell().getMesh());
 
      NodeSet *node_set = new NodeSet;
 
      
 
      for (vector<CellItem *>::iterator it = intersected_cells.begin();
 
	   it != intersected_cells.end();
 
	   it++) {
 
      
 
	//(*it)->Mark();
 
	(*it)->setBrush(QBrush("purple"));
 
       
 
	Cell &c=(*it)->getCell();
 
      
 
	// sometimes the cell hasn't properly divided yet before the
 
	// next division is called?  so check for it?  let's find a way
 
	// to do this later. Note that this functionality currently
 
	// might result in a segmentation fault for users who are
 
	// quickly dragging and releasing division lines...
 
	scene()->update();
 
	
 
	#ifdef QDEBUG
 
@@ -403,25 +321,24 @@ void FigureEditor::mouseReleaseEvent(QMo
 
      }
 
      
 
      node_set->CleanUp();
 
      mesh.AddNodeSet(node_set);
 
      
 
      #ifdef QDEBUG
 
      qDebug() << "Done DivideOverGivenLine" << endl;
 
      #endif
 

	
 
      mesh.TestIllegalWalls();
 
      // Do the actual cutting and removing
 
      if (intersected_cells.size()) {
 
	//      Mesh &m(intersected_cells.front()->getCell().getMesh());
 
	mesh.CutAwayBelowLine( startpoint, endpoint ); 
 
	
 
	// Correct flags of nodeset
 
	for (
 
	     NodeSet::iterator i = node_set->begin(); 
 
	     i != node_set->end();
 
	     i++) {
 
	  (*i)->SetSAM();
 
	  (*i)->SetBoundary();
 
	}
 

	
 
	// Make cells attached to nodeset part of the boundary
 
@@ -456,62 +373,52 @@ void FigureEditor::mouseReleaseEvent(QMo
 
      
 
      dynamic_cast<Main *>(parent())->Plot();
 
      
 
        #ifdef QDEBUG
 
	qDebug() << "NodeSet of cutting line: " << *node_set << endl;
 
	#endif
 
    }
 
  } else 
 
    if (e->button()==Qt::RightButton) {
 
      
 
      if (intersection_line /* && !angle_line*/) {
 
	
 
	//QPointF p = matrix().inverted().map(e->pos());
 
	QPointF p = mapToScene(e->pos());
 
	QPointF sp = intersection_line->line().p1();
 
	
 
	viewport()->setMouseTracking( TRUE );
 
	/* angle_line = new QGraphicsLineItem( 0, scene() );
 
	angle_line->setPen( QPen( QColor("Blue"), 3, Qt::DashLine ) );
 
	angle_line->setLine( QLineF(sp, p) );
 
	angle_line->setZValue( 100 );
 
	angle_line->show();
 
	*/
 
      } 
 
            
 
    }
 
}
 

	
 

	
 
// returns a vector of pointer to cells colliding with intersection line
 
vector <CellItem *> FigureEditor::getIntersectedCells(void) { 
 
  
 
  vector <CellItem *> colliding_cells;
 
  
 
  QList<QGraphicsItem *> l = intersection_line->collidingItems( );
 
  
 
  #ifdef QDEBUG
 
  qDebug() <<  "l.size() = " << l.size() << endl;
 
  #endif
 

	
 
  for (QList<QGraphicsItem *>::Iterator it=l.begin(); it!=l.end(); ++it) {
 
    
 
    #ifdef QDEBUG
 
    qDebug() << typeid(**it).name() << endl;
 
    #endif
 
    
 
    if ( !strcmp(typeid(**it).name(),"8CellItem") ) {
 
      
 
      colliding_cells.push_back(dynamic_cast<CellItem *>(*it));
 
      
 
    }
 
  }
 
  
 
  delete intersection_line;
 
  intersection_line = 0;
 
  return colliding_cells;
 
    
 
}
 

	
 
void FigureEditor::FullRedraw(void) {
 
	QList<QRectF> rl;
 
	rl << sceneRect();
 
@@ -546,192 +453,145 @@ void FigureEditor::insertNode(QPointF p)
 
  FullRedraw();
 
#ifdef QDEBUG  
 
  qDebug() << "Node: " << p << endl;
 
#endif
 
}
 

	
 
static uint mainCount = 0;
 

	
 
Main::Main(QGraphicsScene& c, Mesh &m, QWidget* parent, const char* name, Qt::WindowFlags f) :
 
  Q3MainWindow(parent,name,f),
 
  MainBase(c,m),
 
  mesh(m)
 
	   
 
	  //canvas(c)
 
{
 
  editor = new FigureEditor(canvas,mesh, this);
 

	
 
  #ifdef QDEBUG
 
  qDebug() << "Interactive = " << editor->isEnabled();
 
  #endif
 

	
 
  working_dir = 0;
 
  QObject::connect( editor, SIGNAL(MousePressed()), this, SLOT(PauseIfRunning()));
 
  QObject::connect( editor, SIGNAL(MouseReleased()), this, SLOT(ContIfRunning()));
 
  QMenuBar* menu = menuBar();
 
  
 
  Q3PopupMenu* file = new Q3PopupMenu( menu );
 
 // file->insertItem("&Fill canvas", this, SLOT(init()), Qt::CTRL+Qt::Key_F);
 

	
 
	file->insertItem("&Read leaf", this, SLOT(readStateXML()));
 
	file->insertItem("&Save leaf", this, SLOT(saveStateXML()));
 
	file->insertItem("Snapshot", this, SLOT(snapshot()), Qt::CTRL+Qt::SHIFT+Qt::Key_S);
 
 // file->insertItem("&New view", this, SLOT(newView()), Qt::CTRL+Qt::Key_N);
 

	
 
   file->insertSeparator();
 
	file->insertItem("Read next leaf", this, SLOT(readNextStateXML()), Qt::Key_PageDown);
 
	file->insertItem("Read previous leaf", this, SLOT(readPrevStateXML()), Qt::Key_PageUp);
 
	file->insertItem("Read last leaf", this, SLOT(readLastStateXML()), Qt::Key_End);
 
	file->insertItem("Read first leaf", this, SLOT(readFirstStateXML()), Qt::Key_Home);
 
	//file->insertItem("Read &parameters", this, SLOT(readPars()));
 
  //file->insertItem("&Write parameters", this, SLOT(savePars()));
 
	
 
	file->insertSeparator();
 
	file->insertItem("&Print...", this, SLOT(print()), Qt::CTRL+Qt::Key_P);
 
	file->insertSeparator();
 
	file->insertItem("E&xit", qApp, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
 
	menu->insertItem("&File", file);
 
	
 
	Q3PopupMenu* edit = new Q3PopupMenu( menu );
 
  edit->insertItem("Reset Chemicals and Transporters", this, SLOT( CleanMesh()), Qt::CTRL+Qt::Key_R );
 
	edit->insertItem("Reset Chemicals", this, SLOT( CleanMeshChemicals()) );
 
	edit->insertItem("Reset Transporters", this, SLOT( CleanMeshTransporters()) );
 
  edit->insertItem("Randomize PIN1 Transporters", this, SLOT( RandomizeMesh()) );
 
  edit->insertItem("Cut away SAM", this, SLOT( CutSAM() ));
 
  menu->insertItem("&Edit", edit);
 

	
 
  run = new Q3PopupMenu( menu );
 
  //  edit->insertItem("Add &Polygon", this, SLOT(addPolygon()), ALT+Key_P);
 
  //edit->insertItem("Add &Line", this, SLOT(addLine()), ALT+Key_L);
 
  running = false;
 
	paused_id = run->insertItem("&Simulation paused", this, SLOT(togglePaused()), Qt::Key_S);
 
  run->setItemChecked(paused_id, FALSE);
 

	
 
  //run->insertItem("&Divide Cell", this, SLOT(Divide()), Qt::CTRL+Qt::Key_D);
 
 // run->insertItem("&Restart Simulation", this, SLOT(RestartSim())); 
 
  menu->insertItem("&Run", run);
 
  
 
  view = new Q3PopupMenu( menu );
 
  //view->insertItem("&Enlarge", this, SLOT(enlarge()), SHIFT+CTRL+Key_Plus);
 
  //view->insertItem("Shr&ink", this, SLOT(shrink()), SHIFT+CTRL+Key_Minus);
 
	view->insertItem("&Zoom in", this, SLOT(zoomIn()), Qt::CTRL+Qt::Key_Equal);
 
  view->insertItem("Zoom &out", this, SLOT(zoomOut()), Qt::CTRL+Qt::Key_Minus);
 
	view->insertSeparator();
 
	com_id = view->insertItem("Show cell &centers", this, SLOT(toggleShowCellCenters()));
 
  view->setItemChecked(com_id, FALSE);
 
  //view->insertItem("Cell monitor", this, SLOT(cellmonitor()));
 

	
 
  mesh_id = view->insertItem("Show &nodes", this, SLOT(toggleShowNodes()), Qt::CTRL+Qt::SHIFT+Qt::Key_N);
 
  view->setItemChecked(mesh_id, TRUE);
 
  node_number_id = view->insertItem("Show node numbers", this, SLOT(toggleNodeNumbers()), Qt::CTRL+Qt::SHIFT+Qt::Key_M);
 
  view->setItemChecked(node_number_id, FALSE);
 
  cell_number_id = view->insertItem("Show cell numbers", this, SLOT(toggleCellNumbers()));
 
  view->setItemChecked(cell_number_id, FALSE);
 
  hide_cells_id = view->insertItem("Hide cells", this, SLOT(toggleHideCells()));
 
  view->setItemChecked(hide_cells_id, FALSE);
 
  border_id = view->insertItem("Show &border cells", this, SLOT(toggleShowBorderCells()));
 
  view->setItemChecked(border_id, FALSE);
 
  cell_axes_id = view->insertItem("Show cell &axes", this, SLOT(toggleCellAxes()));
 
  cell_strain_id = view->insertItem("Show cell &strain", this, SLOT(toggleCellStrain()));
 
  view->setItemChecked(cell_axes_id, FALSE);
 
  fluxes_id = view->insertItem("Show &fluxes", this, SLOT(toggleShowFluxes()));
 
  view->setItemChecked(fluxes_id, FALSE);
 
  cell_walls_id = view->insertItem("Show transporters", this, SLOT(toggleShowWalls()));
 
	view->setItemChecked(cell_walls_id, FALSE);
 
	apoplasts_id = view->insertItem("Show apoplasts", this, SLOT(toggleShowApoplasts()));
 
  view->setItemChecked(apoplasts_id, FALSE);
 
 	view->insertSeparator();
 
	  only_boundary_id = view->insertItem("Show only leaf &boundary", this, SLOT(toggleLeafBoundary()));
 
  //only_boundary_id = view->insertItem("Show only leaf &boundary", 0,0);
 
	view->insertSeparator();
 
	movie_frames_id = view->insertItem("Start saving movie &frames", this, SLOT(toggleMovieFrames()));
 
  view->setItemChecked(movie_frames_id, par.movie);
 
	
 
	view->setItemChecked(only_boundary_id, FALSE);
 
  menu->insertItem("&View", view);
 
  
 
  
 
  options = new Q3PopupMenu( menu );
 
  /* dbf_id = options->insertItem("Double buffer", this, SLOT(toggleDoubleBuffer()));
 
     options->setItemChecked(dbf_id, TRUE);*/
 
  dyn_cells_id = options->insertItem("Cell growth", this, SLOT(toggleDynCells()));
 
  options->setItemChecked(dyn_cells_id, true);
 

	
 
  options->insertItem("Edit &parameters", this, SLOT(EditParameters()), Qt::CTRL+Qt::Key_E);
 
  
 
  rotation_mode_id = options->insertItem("Rotate leaf", this, SLOT(EnterRotationMode()), Qt::CTRL + Qt::SHIFT + Qt::Key_R);
 
  options->setItemChecked(rotation_mode_id, false);
 

	
 
  menu->insertItem("&Options",options);
 
	
 
	// Menu of models
 
	modelmenu = new QMenu( menu );
 
	menu->insertItem("&Models", modelmenu);
 
	
 
	
 
  menu->insertSeparator();
 
  
 
  helpmenu = new Q3PopupMenu( menu );
 
  tooltips_id = helpmenu->insertItem("Show Cell&Info", this, SLOT(Refresh()));
 
  helpmenu->setItemChecked(tooltips_id, true);
 
  helpmenu->insertSeparator();
 

	
 
  helpmenu->insertItem("&About", this, SLOT(help()) ); //, Key_F1);
 
  //help->insertItem( "What's &This", this , SLOT(whatsThis()), SHIFT+Key_F1);
 
  menu->insertItem("&Help",helpmenu);
 
  //QSlider *flux_arrow_slider = new QSlider( 0, 10000, 1, 100, Qt::Horizontal, this, "flux arrow size");
 
  //QSpinBox *stride  = new QSpinBox( 1, 1000, 1, this, "stride");
 
  
 
	    
 
  //QGridLayout *controlgrid = new QGridLayout( this, 1, 2, 10);
 
  // 2x1, 10 pixel border
 
  
 
  //controlgrid->addWidget( stride, 0, 0);
 
  //controlgrid->addWidget( flux_arrow_slider, 0, 1);
 
  //controlgrid->setColStretch( 1, 10 );
 
  
 
  
 
  //flux_arrow_size = 1.;
 
  //flux_arrow_slider -> setMinimumSize( 200,50);
 
  //connect( flux_arrow_slider, SIGNAL( valueChanged( int ) ), this, SLOT( setFluxArrowSize(int) ) );
 
  
 
  statusBar();
 
  
 
  setCentralWidget(editor);
 

	
 
  printer = 0;
 

	
 
  init();
 
    
 
  // Start timer which repetitively invokes
 
  // a simulation time step
 
  timer = new QTimer( this );
 
  connect( timer, SIGNAL(timeout()), SLOT(TimeStepWrap()) );
 
  
 
  stopSimulation();
 
  statusBar()->addWidget(new QLabel("Ready."));
 
  setCaption(caption);
 
  gifanim = 0;
 
	
 
	// A little bit of PSB/CWI decoration ;-)
 
	/*dockwindow = new Q3DockWindow();
 
	addDockWindow(dockwindow);
 
	QLabel *viblab = new QLabel; viblab->setPixmap(QPixmap(cwi_xpm));
 
	QString virtleafstring("<h1>The Virtual Leaf</h1>\n<center><b>Model:</b> <i>%1</i></center>");
 
	QLabel *virtleaf = new QLabel(virtleafstring.arg(mesh.ModelID()));
 
	QLabel *psblab = new QLabel; psblab->setPixmap(QPixmap(PSB_xpm));
 
	dockwindow->setHorizontalStretchable(true);
 
	dockwindow->boxLayout()->addWidget(viblab);//,Qt::AlignLeft);
 
	dockwindow->boxLayout()->addStretch();
 
	dockwindow->boxLayout()->addWidget(virtleaf);//, Qt::AlignHCenter);
 
	dockwindow->boxLayout()->addStretch();
 
	dockwindow->boxLayout()->addWidget(psblab);//, Qt::AlignRight);*/
 
	//QString virtleafstring("<h1>The Virtual Leaf</h1>\n<center><b>Model:</b> <i>%1</i></center>");
 
	infobar = new InfoBar();
 
	addDockWindow(infobar);
 

	
 
}
 

	
 
void Main::RefreshInfoBar(void) {
 
	infobar->SetText(mesh.ModelID());
 
}
 

	
 

	
 
void Main::UserMessage(QString message, int timeout) {
 

	
 
@@ -774,27 +634,24 @@ void Main::EditParameters() {
 
  
 
  ParameterDialog *pardial = new ParameterDialog(this, "stridediag");
 

	
 
  // Make sure the values in the parameter dialog are updated after a file is read 
 
  // each method changing the parameters (reading XML or PAR files) should
 
  // emit this signal
 
  QObject::connect(   this, SIGNAL( ParsChanged() ), pardial, SLOT( Reset() ) );
 

	
 
}
 

	
 
void Main::savePars() {
 
  
 
  // bool timer_active;
 
  /* if (timer_active=timer->isActive())
 
     imer->stop();*/
 
  stopSimulation();
 
  
 
  Q3FileDialog *fd = new Q3FileDialog( this, "file dialog", TRUE );
 
  fd->setMode( Q3FileDialog::AnyFile );
 
  fd->setFilter( "Parameter files (*.par)");
 

	
 
  QString fileName;
 
  if ( fd->exec() == QDialog::Accepted ) {
 
    fileName = fd->selectedFile();
 
    ofstream parfile((const char *)fileName);
 
    par.Write(parfile);
 
  }
 
@@ -817,28 +674,24 @@ void Main::readPars() {
 
    par.Read((const char *)fileName);
 
  }
 
  
 
  emit ParsChanged();
 
  /* if (timer_active)
 
     timer->start( 0 );*/
 
  
 
}
 

	
 

	
 
void Main::saveStateXML() {
 
  
 
   
 
  //   bool timer_active;
 
  //   if (timer_active=timer->isActive())
 
  //     timer->stop();
 
  stopSimulation();
 
  Q3FileDialog *fd = new Q3FileDialog( this, "file dialog", TRUE );
 
  fd->setMode( Q3FileDialog::AnyFile );
 
  fd->setFilter( "XML (*.xml)");
 
  QString fileName;
 
  
 
  if ( fd->exec() == QDialog::Accepted ) {
 
    fileName = fd->selectedFile();
 
    if ( QFile::exists( fileName ) &&
 
	 QMessageBox::question(
 
			       this,
 
			       tr("Overwrite File? -- Leaf Growth"),
 
@@ -854,27 +707,24 @@ void Main::saveStateXML() {
 
      mesh.XMLSave((const char *)fileName, XMLSettingsTree());
 
    
 
    }
 
  }
 

	
 
}
 

	
 

	
 

	
 
void Main::snapshot() {
 
  
 
   
 
  //   bool timer_active;
 
  //   if (timer_active=timer->isActive())
 
  //     timer->stop();
 
  stopSimulation();
 
  Q3FileDialog *fd = new Q3FileDialog( this, "Save snapshot", TRUE );
 
  fd->setMode( Q3FileDialog::AnyFile );
 
  
 
  QString fileName;
 
  
 
  if ( fd->exec() == QDialog::Accepted ) {
 
    fileName = fd->selectedFile();
 
    if ( QFile::exists( fileName ) &&
 
	 QMessageBox::question(
 
			       this,
 
			       tr("Overwrite File? -- Leaf Growth"),
 
@@ -922,47 +772,45 @@ void Main::readPrevStateXML() {
 
		      QMessageBox::Ok | QMessageBox::Default,
 
		      QMessageBox::NoButton,
 
		      QMessageBox::NoButton);
 
      mb.exec();
 
      return;
 
    }
 
    next_file = *(--f);
 
    next_file = currentFile_path+"/"+next_file;
 
    
 
    readStateXML((const char *)next_file);
 
    
 
  }
 
  
 
  
 
}
 

	
 
int Main::readStateXML(const char *filename, bool geometry, bool pars, bool simtime) {
 
 
 
  try {
 
    xmlNode *settings;
 
    mesh.XMLRead((const char *)filename, &settings, geometry, pars, simtime);
 
    #ifdef QDEBUG
 
    qDebug() << "Reading done."<< endl;
 
    #endif
 
    XMLReadSettings(settings);
 
    xmlFree(settings);
 
    Cell::SetMagnification(1);
 
    Cell::setOffset(0,0);
 
    
 
    FitLeafToCanvas();
 
    
 
    currentFile =  QString(filename);
 
	
 
    Plot();
 
    QString status_message = QString("Succesfully read leaf from file %1. Time is %2 h.\n").arg(currentFile).arg(mesh.getTimeHours().c_str());
 
    QString status_message = QString("Successfully read leaf from file %1. Time is %2 h.").arg(currentFile).arg(mesh.getTimeHours().c_str());
 
    cerr << status_message.toStdString() << endl;
 
	setCaption(caption_with_file.arg(filename));
 
    statusBar()->message(status_message);
 
    emit ParsChanged();
 
    #ifdef QDEBUG
 
    qDebug() << "Done. Returning 0." << endl;
 
    #endif
 
    return 0;
 
  } catch (const char *error_message) {
 
    QMessageBox mb( "Read leaf from XML file",
 
		    QString(error_message),
 
		    QMessageBox::Critical,
 
@@ -1072,44 +920,24 @@ void Main::readStateXML() {
 
  }
 
  QString fileName;
 
  if ( fd->exec() == QDialog::Accepted ) {
 
    
 
    fileName = fd->selectedFile();
 
    if (working_dir) {
 
      delete working_dir;
 
    }
 
    working_dir = fd->dir();
 
	
 
    if (readStateXML((const char *)fileName,fd->readGeometryP(), fd->readParametersP()) )
 
      return readStateXML(); // user can try again
 
    
 
//     try {
 
//       mesh.XMLRead((const char *)fileName);
 
//       currentFile =  fileName;
 
//     } catch (const char *error_message) {
 
//       QMessageBox mb( "Read leaf from XML file",
 
// 		      QString(error_message),
 
// 		      QMessageBox::Critical,
 
// 		      QMessageBox::Ok | QMessageBox::Default,
 
// 		      QMessageBox::NoButton,
 
// 		      QMessageBox::NoButton);
 
//       mb.exec();
 
//       return readStateXML(); // user can try again
 
//     }
 
    
 
//     Vector bbll,bbur;
 
//     mesh.BoundingBox(bbll,bbur);
 
    
 
//     //FitLeafToCanvas();
 
//     Plot();
 
  }
 
}
 

	
 

	
 
void Main::clear()
 
{
 
  editor->clear();
 
}
 

	
 
void Main::help()
 
{
 
  static QMessageBox* about = new QMessageBox
 
@@ -1124,129 +952,83 @@ void Main::help()
 
      "CWI/NCSB, Amsterdam, Netherlands <br>"
 
      "Pilot release for WUR/Biometris, 21-10-2009 <br>", 
 
      QMessageBox::Information, 1, 0, 0, this, 0, FALSE );
 
  about->setButtonText( 1, "Dismiss" );
 
  about->show();
 
}
 

	
 
  void Main::aboutQt()
 
  {
 
    QMessageBox::aboutQt( this, "Virtual Leaf" );
 
  }
 

	
 
/* void Main::toggleDoubleBuffer()
 
{
 
  bool s = !options->isItemChecked(dbf_id);
 
  options->setItemChecked(dbf_id,s);
 
  canvas.setDoubleBuffering(s);
 
}
 
*/
 
  void Main::toggleShowCellCenters()
 
  {
 
    //bool s = !view->isItemChecked(com_id);
 
    //view->setItemChecked(com_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowWalls()
 
  {
 
    //bool s = !view->isItemChecked(cell_walls_id);
 
    //view->setItemChecked(cell_walls_id,s);
 
    Plot();
 
  }
 
void Main::toggleShowApoplasts()
 
{
 
    Plot();
 
}
 
  void Main::toggleShowNodes()
 
  {
 
    //bool s = !view->isItemChecked(mesh_id);
 
    //view->setItemChecked(mesh_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleNodeNumbers(void) {
 
  
 
    //bool s = !view->isItemChecked(node_number_id);
 
    //view->setItemChecked(node_number_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellNumbers(void) {
 
  
 
    //bool s = !view->isItemChecked(cell_number_id);
 
    //view->setItemChecked(cell_number_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellAxes(void) {
 
  
 
    //bool s = !view->isItemChecked(cell_axes_id);
 
    //view->setItemChecked(cell_axes_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellStrain(void) {
 
  
 
    //bool s = !view->isItemChecked(cell_strain_id);
 
    //view->setItemChecked(cell_strain_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowFluxes(void) {
 
  
 
    //bool s = !view->isItemChecked(fluxes_id);
 
    //view->setItemChecked(fluxes_id,s);
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowBorderCells()
 
  {
 
    //bool s = !view->isItemChecked(border_id);
 
    //view->setItemChecked(border_id,s);
 
  void Main::toggleShowBorderCells(){
 
    Plot();
 
  }
 

	
 
void Main::toggleHideCells(void) {
 
	Plot();
 
	editor->FullRedraw();
 
}
 
  void Main::toggleMovieFrames()
 
  {
 
    //bool s = !view->isItemChecked(movie_frames_id);
 
    //view->setItemChecked(movie_frames_id,s);
 
  }
 
  void Main::toggleMovieFrames(){}
 

	
 
  void Main::toggleLeafBoundary(){}
 

	
 
  void Main::toggleLeafBoundary()
 
  {
 
    //bool s = !view->isItemChecked(only_boundary_id);
 
    //view->setItemChecked(only_boundary_id,s);
 
  }
 

	
 
  void Main::toggleDynCells()
 
  {
 
    //bool s = !options->isItemChecked(dyn_cells_id);
 
    //options->setItemChecked(dyn_cells_id,s);
 
  }
 

	
 

	
 
  void Main::toggleDynCells() {}
 
  
 
  void Main::startSimulation(void) {
 
    //run->setItemChecked(paused_id, false);
 
    timer->start( 0 );
 
    statusBar()->message("Simulation started");
 
    running = true;
 
  }
 

	
 
  void Main::stopSimulation(void) {
 
    //run->setItemChecked(paused_id, true);
 
    timer->stop();
 
    cerr << "Stopping simulation" << endl;
 
    statusBar()->message("Simulation paused");
 
    running = false;
 
  }
 

	
 
  void Main::togglePaused()
 
  {
 
    bool s = run->isItemChecked(paused_id);
 
    if (s) {
 
      cerr << "Calling start simulation" << endl;
 
      startSimulation();
 
@@ -1255,37 +1037,32 @@ void Main::toggleHideCells(void) {
 
      stopSimulation();
 
    }
 
  }
 

	
 
  void Main::setFluxArrowSize(int size) {
 
  
 
    flux_arrow_size = size/100.;
 
  }
 

	
 

	
 
  void Main::enlarge()
 
  {
 
    //canvas.resize(canvas.width()*4/3, canvas.height()*4/3);
 
    canvas.setSceneRect( QRectF( 0,0, canvas.width()*4./3., canvas.height()*4./3.) );
 
  }
 

	
 
  void Main::shrink()
 
  {
 
    canvas.setSceneRect( QRectF( 0,0, canvas.width()*3/4, canvas.height()*3/4) );
 
    
 
  }
 

	
 
/* void Main::scrollBy(int dx, int dy) {
 
    editor->scrollBy(dx,dy);
 
    }*/
 

	
 
  void Main::scale(double factor) {
 
    QMatrix m = editor->matrix();
 
    m.scale(factor, factor);
 
    editor->setMatrix( m );
 
  }
 

	
 
  void Main::zoomIn()
 
  {
 
    QMatrix m = editor->matrix();
 
    m.scale( 1.1, 1.1 );
 
    editor->setMatrix( m );
 
@@ -1356,88 +1133,24 @@ void Main::toggleHideCells(void) {
 
							   QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton ) == QMessageBox::Yes ) {
 

	
 
      cerr << "Restarting simulation" << endl;
 
      //    extern Mesh mesh;
 
      mesh.Clear();
 
      Init();
 
		Plot();
 
		editor->FullRedraw();
 
    } 
 
    //startSimulation();
 
  }
 

	
 
  /*
 
    void Main::SaveToGifAnim(void) {
 
  
 
    if (gifanim) {
 
    
 
    QPixmap image(canvas.width(), canvas.height());
 
    QPainter im(&image);
 
    
 
    
 
    canvas.drawArea(QRect(0,0,canvas.width(),canvas.height()),&im,FALSE);
 
    QFile conversionpipe;
 
    conversionpipe.open ( IO_WriteOnly, popen("pngtopnm | ppmtogif > tmp.gif", "w") );
 
    image.save( &conversionpipe, "PNG");
 
    conversionpipe.close();
 
    
 
    QFile readconvertedimage("tmp.gif");
 
    readconvertedimage.open(IO_ReadOnly);
 
    int c;
 
    while ( (c=readconvertedimage.getch())!=-1) {
 
    gifanim->putch(c);
 
    }
 
    }
 
    }*/
 

	
 
  /* void Main::StartGifAnim(QString fname) {
 
  
 
  if (gifanim) {
 
  QMessageBox::information( this, "Animation",
 
  "Already making another animation."
 
  "Please end it and try again.",
 
  QMessageBox::Ok );
 
  } else {
 
    
 
  QString cmdline("gifsicle --multifile - > ");
 
  cmdline += fname;
 
    
 
  gifanim = new QFile;
 
  gifanim->open( IO_WriteOnly, 
 
  popen((const char *)cmdline, "w") );
 
    
 
  */   /* QStringList cmdline;
 
	  cmdline << "gifsicle" << "--multifile" << "-";
 
	  gifanim = new QProcess( cmdline );
 
       
 
	  cmdline.clear();
 
	  cmdline << "pngtopnm";
 
	  pngtopnm = new QProcess( cmdline );
 
	  pngtopnm->start();
 
       
 
	  cmdline.clear();
 
	  cmdline << "ppmtogif";
 
	  ppmtogif = new QProcess( cmdline );
 
	  ppmtogif->start();*/
 
       /*  }
 

	
 
       }*/
 

	
 
       /*void Main::EndGifAnim(void) {
 
  
 
       if (gifanim)
 
       gifanim->close();
 

	
 
       }*/
 

	
 

	
 
void Main::FitCanvasToWindow(void) {
 
  
 
  double scale_factor_x = (double)editor->width()/(double)canvas.width();
 
  double scale_factor_y = (double)editor->height()/(double)canvas.height();
 
  double scale_factor = scale_factor_x > scale_factor_y ? scale_factor_x : scale_factor_y;
 
  QMatrix m = editor->matrix();
 

	
 
  #ifdef QDEBUG  
 
  qDebug() << "editor->width() = " << editor->width() << endl;
 
  qDebug() << "editor->height() = " << editor->height() << endl;
 
  
 
@@ -1486,59 +1199,53 @@ void Main::CleanMesh(void) {
 
	for (int i=0;i<Cell::NChem();i++) {
 
		clean_chem[i]=par.initval[i];
 
		clean_transporters[i]=0.;		
 
	}
 
	
 
	mesh.CleanChemicals(clean_chem);
 
	mesh.CleanTransporters(clean_transporters);
 
	
 
	mesh.setTime(0);
 
	Plot();
 
	
 
	editor->FullRedraw();
 
	
 
  //  repaint();
 
}
 

	
 
void Main::CleanMeshChemicals(void) {
 
	
 
	vector<double> clean_chem(Cell::NChem());
 

	
 
	for (int i=0;i<Cell::NChem();i++) {
 
		clean_chem[i]=par.initval[i];
 
	}
 
	
 
	mesh.CleanChemicals(clean_chem);
 
	mesh.setTime(0);
 
	Plot();
 
	
 
	editor->FullRedraw();
 
	
 
	//  repaint();
 
}
 

	
 
void Main::CleanMeshTransporters(void) {
 
	vector<double> clean_transporters(Cell::NChem());
 
	for (int i=0;i<Cell::NChem();i++) {
 
		clean_transporters[i]=0.;
 
	}
 
	
 
	mesh.CleanTransporters(clean_transporters);
 
	
 
	mesh.setTime(0);
 
	Plot();
 
	
 
	editor->FullRedraw();
 
	
 
	//  repaint();
 
}
 

	
 
void Main::RandomizeMesh(void) {
 
  
 
  vector<double> max_chem(Cell::NChem());
 
  vector<double> max_transporters(Cell::NChem());
 
  
 
  for (int i=0;i<Cell::NChem();i++) {
 
    max_transporters[i]=0.;
 
    max_chem[i]=par.initval[i];
 
  }
 

	
src/canvas.h
Show inline comments
 
@@ -66,27 +66,24 @@ class InfoBar;
 

	
 
class FigureEditor : public QGraphicsView {
 
  Q_OBJECT
 

	
 
    friend class Main;
 
    public:
 
  FigureEditor(QGraphicsScene&, Mesh&, QWidget* parent=0, const char* name=0, Qt::WFlags f=0);
 
  void clear();
 
  void Save(const char *fname, const char *format, int sizex=640, int sizey=480);
 
  void FullRedraw(void);
 

	
 
protected:
 
  /* void contentsMousePressEvent(QMouseEvent*);
 
  void contentsMouseMoveEvent(QMouseEvent*);
 
  void contentsMouseReleaseEvent(QMouseEvent*);*/
 
  void mousePressEvent(QMouseEvent*);
 
  void mouseMoveEvent(QMouseEvent*);
 
  void mouseReleaseEvent(QMouseEvent*);
 
  void wheelEvent(QWheelEvent *event);
 
  void scaleView(qreal scaleFactor);
 

	
 
  vector <CellItem *> getIntersectedCells(void);
 
  void insertNode(QPointF p);
 
  NodeItem *selectedNodeItem(QList<QGraphicsItem *> l) const;  
 

	
 
 signals:
 
  void status(const QString&);
 
@@ -125,53 +122,46 @@ class Main : public Q3MainWindow, public
 
  virtual bool ShowWallsP(void) {return view->isItemChecked(cell_walls_id);}
 
	virtual bool ShowApoplastsP(void) { return view->isItemChecked(apoplasts_id);}
 
  virtual bool ShowFluxesP(void) { return view->isItemChecked(fluxes_id); }
 
  virtual bool DynamicCellsP(void) { return options->isItemChecked(dyn_cells_id); }
 
  virtual bool RotationModeP(void) { return options->isItemChecked(rotation_mode_id); }
 
  virtual bool InsertModeP(void) { return options->isItemChecked(insert_mode_id); }
 
  virtual bool ShowToolTipsP(void) { return helpmenu->isItemChecked(tooltips_id); }
 
  virtual bool HideCellsP(void) { return view->isItemChecked(hide_cells_id); }
 
  void scale(double factor); 
 
  virtual double getFluxArrowsize(void) {
 
    return flux_arrow_size;
 
  }
 
  //void Save(const char *fname, const char *format);
 
  /*void StartGifAnim(QString fname);
 
    void SaveToGifAnim(void);
 
    void EndGifAnim(void);*/
 
    
 
  void FitCanvasToWindow();
 
  void FitLeafToCanvas(void);
 

	
 

	
 
  public slots:
 

	
 
  void help();
 
  void TimeStepWrap();
 
  //void scrollBy(int dx, int dy);
 
  void togglePaused();
 
  void setFluxArrowSize(int size);
 
  //void Divide(void);
 
  void RestartSim(void);
 
  //void toggleDoubleBuffer(void);
 
  void toggleShowCellCenters(void);
 
  void toggleShowNodes(void);
 
  void toggleShowBorderCells(void);
 
  void toggleShowFluxes(void);
 
  void toggleNodeNumbers(void);
 
  void toggleCellNumbers(void);
 
  void toggleCellAxes(void);
 
  void toggleCellStrain(void);
 
  void toggleShowWalls(void);
 
	void toggleShowApoplasts(void);
 
  void toggleShowApoplasts(void);
 
  void toggleDynCells(void);
 
  void toggleMovieFrames(void);
 
  void toggleLeafBoundary(void);
 
  void toggleHideCells(void);
 
  void print();
 
  void startSimulation(void);
 
  void stopSimulation(void);
 
  void RefreshInfoBar(void);
 

	
 
  void EnterRotationMode(void) {
 

	
 
    UserMessage("Rotation mode. Click mouse to exit.");
 
@@ -205,54 +195,46 @@ class Main : public Q3MainWindow, public
 
  int readStateXML(const char *filename, bool geometry = true, bool pars=true, bool simtime = true);
 
  void readNextStateXML();
 
  void readPrevStateXML();
 
  void readFirstStateXML();
 
  void readLastStateXML();
 
  void saveStateXML();
 
  void snapshot();
 
  void savePars();
 
  void readPars();
 
  void clear();
 
  void init();
 
  virtual void CutSAM() { MainBase::CutSAM(); Refresh();}
 
/*   void cellmonitor() { */
 
/*     PlotDialog *plot = new PlotDialog(this); */
 
/*     cerr << "Attempting to launch a cell monitor\n"; */
 
/*   } */
 
  
 
  //void addPolygon();
 
  //void addLine();
 

	
 
  void enlarge();
 
  void shrink();
 
  void zoomIn();
 
  void zoomOut();
 
	
 
  void CleanMesh();
 
	void CleanMeshChemicals(void);
 
	void CleanMeshTransporters(void);
 
	
 
  void RandomizeMesh();
 

	
 
 signals:
 
  void SimulationDone(void);
 
  void ParsChanged(void);
 
  
 
 protected:
 
  Mesh &mesh;
 
  
 
 private:
 
  NodeSet *node_set;
 
  FigureEditor *editor;
 
  //QCanvas& canvas;
 
  Q3PopupMenu* options;
 
  Q3PopupMenu *view;
 
  Q3PopupMenu *run;
 
	QMenu *modelmenu;
 
  Q3PopupMenu *helpmenu;
 

	
 
  QPrinter* printer;
 
  const QDir *working_dir;
 
  QString currentFile;
 
  //  toggle item states 
 
  int dbf_id; // options->Double Buffer
 
  int com_id; // view->Show centers
src/cell.cpp
Show inline comments
 
@@ -85,28 +85,25 @@ void Cell::DivideOverAxis(Vector axis) {
 
	
 
	for (list<Node *>::iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		
 
		// cross product to detect position of division
 
		Vector cross = axis * (centroid - *(*i));
 
		
 
		if (cross.z * prev_cross_z < 0 ) {
 
			
 
			new_node_locations.push_back(i);
 
			
 
		} // else {
 
		//       //cerr << "cross.z * prev_cross_z = " << cross.z * prev_cross_z << endl;
 
		//     }
 
		
 
		}		
 
		prev_cross_z=cross.z;
 
	}
 
	
 
	DivideWalls(new_node_locations, centroid, centroid+axis);
 
	
 
}
 
double Cell::MeanArea(void) {
 
	return m->MeanArea();
 
}
 

	
 

	
 
void Cell::Apoptose(void) {
 
@@ -211,70 +208,24 @@ void Cell::Apoptose(void) {
 
			// register node with outside world
 
			if (find_if( no.owners.begin(), no.owners.end(), 
 
				     bind2nd ( mem_fun_ref(&Neighbor::CellEquals), m->boundary_polygon->Index() ) ) == no.owners.end() ) {
 
				
 
				tmp.cell = m->boundary_polygon;
 
				no.owners.push_back(tmp);
 
			}
 
		}
 
	}
 
	
 
	
 
	
 
	/*
 
	 // correct boundary polygon if this cell touches the boundary
 
	 
 
	 // find the first living boundary node after a dead node
 
	 bool node_found = false;
 
	 for (list<Node *>::iterator n=nodes.begin();
 
	 n!=nodes.end();
 
	 n++) {
 
	 
 
	 Node &no(*(*n));
 
	 
 
	 if (no.DeadP()) {
 
	 
 
	 list<Node *>::iterator first_node = n; 
 
	 if (++next_node == nodes.end()) first_node=nodes.begin();
 
	 
 
	 if (!(*(*first_node)).DeadP() && ((*first_node)->boundary)) {
 
	 node_found=true;
 
	 break;
 
	 }
 
	 
 
	 }
 
	 }
 
	 
 
	 // locate it in the boundary_polygon
 
	 if (node_found) {
 
	 list<Node *>::iterator insert_it = find(mesh->boundary_polygon->nodes.begin(),
 
	 mesh->boundary_polygon->nodes.end(),
 
	 ++first_node);
 
	 if (insert_it!=owners.end()) {
 
	 
 
	 if (insert_it==owners.end()) insert_it=owners.begin();
 
	 
 
	 for (list<Node *>::iterator n=insert_it;
 
	 n!=nodes.end();
 
	 n++) {
 
	 
 
	 Node &no(*(*n));
 
	 
 
	 mesh->boundary_polygon->nodes.insert(
 
	 
 
	 }
 
	 
 
	 
 
	 }
 
	 } */
 
	// mark cell as dead
 
	MarkDead();
 
}
 

	
 
void Cell::ConstructConnections(void) {
 
	
 
    // Tie up the nodes of this cell, assuming they are correctly ordered
 
	
 
    //cerr << "Constructing connections of cell " << index << endl;
 
	
 
    for (list<Node *>::iterator i=nodes.begin();
 
		 i!=nodes.end();
 
@@ -355,26 +306,24 @@ bool Cell::DivideOverGivenLine(const Vec
 
			nb = nodes.begin();
 
		}
 
		Vector v4 = *(*nb);
 
		
 
		double denominator = 
 
		(v4.y - v3.y)*(v2.x - v1.x) - (v4.x - v3.x)*(v2.y - v1.y);
 
		
 
		double ua = 
 
		((v4.x - v3.x)*(v1.y - v3.y) - (v4.y - v3.y)*(v1.x -v3.x))/denominator;
 
		double ub = 
 
		((v2.x - v1.x)*(v1.y-v3.y) - (v2.y- v1.y)*(v1.x - v3.x))/denominator;
 
		
 
		/* double intersec_x = v1.x + ua*(v2.x-v1.x);
 
		 double intersec_y = v1.y + ua*(v2.y-v1.y);*/
 
		
 
		//cerr << "Edge " << *i << " to " << *nb << ": ua = " << ua << ", ub = " << ub << ":  ";
 
		// this construction with "TINY" should simulate open/closed interval <0,1]
 
		if ( ( TINY < ua && ua < 1.+TINY ) && ( TINY < ub && ub < 1.+TINY ) ) {
 
			// yes, intersection detected. Push the location to the list of iterators
 
			new_node_locations.push_back(nb);
 
			
 
		} 
 
	}
 
	
 
        #ifdef QDEBUG
 
	if (new_node_locations.size()<2) { 
 
@@ -424,40 +373,37 @@ void Cell::DivideWalls(ItList new_node_l
 
	
 
	//cerr << "Parent polarization before division: " << parent_info.polarization << endl;
 
	
 
	// Step 1: create a daughter cell
 
	Cell *daughter=m->AddCell(new Cell());
 
    
 
	// Step 2: Copy the basics of parent cell to daughter
 
	for (int i=0;i<NChem();i++) {
 
		daughter->chem[i]=chem[i];
 
	}
 
	
 
	daughter->cell_type = cell_type;
 
	//extern double auxin_account;
 
	//auxin_account += daughter->chem[0];
 
	
 
	for (int i=0;i<NChem();i++) {
 
		daughter->new_chem[i]=new_chem[i];
 
	}
 
	
 
	
 
	daughter->boundary=boundary;
 
	daughter->m=m;
 
	
 
	daughter->target_area=target_area/2.;
 
	
 
	target_area/=2;
 
	daughter->cellvec=cellvec;
 
//	daughter->BaseArea()  = base_area;
 
	
 
	
 
	// Division currently only works for convex cells: i.e. if the division line
 
	// intersects the cells at two points only.
 
	if (new_node_locations.size()!=2) {
 
		
 
		// Note: if you would add the possibility of dividing non-convex
 
		// cells, remember to update the code below. There are some
 
		// fixed-size arrays over there!
 
		
 
		cerr << "Warning in Cell::Division: division of non-convex cells not fully implemented" << endl;
 
		
 
@@ -608,29 +554,24 @@ void Cell::DivideWalls(ItList new_node_l
 
				div_edges[i].first->node_set->AddNode( new_node_ind[i] );
 
			}
 
			
 
			// if the new wall should be fixed (i.e. immobile, or moving as
 
			// solid body), make it so, and make it part of the boundary. Using
 
			// this to make a nice initial condition by cutting off part of a
 
			// growing leaf.
 
			
 
			if (fix_cellwall) {
 
				(new_node_ind[i])->fixed = true;
 
				
 
				// All this we'll do later for the node set only
 
				/* (new_node_ind[i])->boundary = true;
 
				 (new_node_ind[i])->sam = true;
 
				 boundary_touched_flag = true;
 
				 boundary = SAM;
 
				 daughter->boundary = SAM;*/
 
			}
 
			
 
			// if new node is inserted into the boundary
 
			// it will be part of the boundary, too
 

	
 
			new_node_ind[i]->UnsetBoundary();
 
			if ((div_edges[i].first->BoundaryP() && div_edges[i].second->BoundaryP()) && // Both edge nodes are boundary nodes AND
 
			     ((m->findNextBoundaryNode(div_edges[i].first))->Index() == div_edges[i].second->Index())){ // The boundary proceeds from first to second.
 

	
 
                                #ifdef QDEBUG
 
			        qDebug() << "Index of the first node: " << div_edges[i].first->Index() << endl;
 
			        qDebug() << "Index of the second node: " << div_edges[i].second->Index() << endl;
 
@@ -797,25 +738,25 @@ void Cell::DivideWalls(ItList new_node_l
 
			/*************** 1. Find the correct wall element  ********************/
 
			
 
			list<Wall *>::iterator w, start_search;
 
			w = start_search = walls.begin();
 
			do {
 
				// Find wall between this cell and neighbor cell
 
				w = find_if( start_search, walls.end(), bind2nd (mem_fun( &Wall::is_wall_of_cell_p ), neighbor_cell ) );
 
				start_search = w; start_search++; // continue searching at next element
 
			} while ( w!=walls.end() && !(*w)->IntersectsWithDivisionPlaneP( from, to ) ); // go on until we find the right one.
 
			
 
			if (w == walls.end()) {
 
			        #ifdef QDEBUG
 
			  qDebug() << "Whoops, wall element not found...!" << endl;
 
			        qDebug() << "Whoops, wall element not found...!" << endl;
 
			        qDebug() << "Cell ID: " << neighbor_cell->Index() << endl;
 
				qDebug() << "My cell ID: " << Index() << endl;
 
                                #endif
 
			} else {
 
				
 
				// 2. Split it up, if we should (sometimes, the new node coincides with an existing node so
 
				// we should not split up the Wall)
 
				
 
				if (new_node_ind[i]!=(*w)->n1 && new_node_ind[i]!=(*w)->n2) {
 
					
 
					Wall *new_wall;
 
					
 
@@ -830,36 +771,24 @@ void Cell::DivideWalls(ItList new_node_l
 
						new_wall = new Wall( (*w)->n1, new_node_ind[i], this, neighbor_cell);
 
						(*w)->n1 = new_node_ind[i];
 
						
 
						//  cerr << "wall " << *(*w) << ", and new wall " << *new_wall << endl;
 
						
 
					} else {
 
						new_wall = new Wall( (*w)->n1, new_node_ind[i], neighbor_cell, this);
 
						
 
						(*w)->n1 = new_node_ind[i];
 
					}
 
					
 
					
 
					//new_wall->ResetTransporterConcentrations(orig_length);
 
					//(*w)->ResetTransporterConcentrations(orig_length);
 
					
 
					// reset the transporter concentrations
 
					
 
					
 
					/*	  new_wall->SetLength();
 
					 new_wall->CorrectLength(orig_length);
 
					 
 
					 (*w)->SetLength();
 
					 (*w)->CorrectLength(orig_length);*/
 
					
 
					// 3. Give wall elements to appropriate cells
 
					if (new_wall->n1 != new_wall->n2) {
 
						
 
						if (par.copy_wall)
 
							new_wall->CopyWallContents(**w);
 
						else {
 
							// If wall contents are not copied, decide randomly which wall will be the "parent"
 
							// otherwise we will get biases (to the left), for example in the meristem growth model
 
							if (RANDOM()<0.5) {
 
								new_wall->SwapWallContents(*w);
 
							}
 
						}
 
@@ -992,29 +921,26 @@ void Cell::DivideWalls(ItList new_node_l
 
	double element_length = dist/(double)(n+1);
 
	
 
	// note that wall nodes need to run in inverse order in parent
 
	list<Node *>::iterator ins_pos = daughter->nodes.end();
 
	for (int i=1;i<=n;i++) {
 
		Node *node=
 
		m->AddNode( new Node( new_node[0] + i*element_length*nodevec ) );
 
		
 
		node->fixed=fixed_wall;
 
		
 
		if (!fix_cellwall)
 
			node->boundary = false;
 
		else { // if fix_cellwall is true, that is if we are cutting off
 
			// part of a leaf to make a nice initial condition, we also want to make it part of the boundary
 
			//node->boundary = true;
 
		else {
 
			node->fixed = true;
 
			//node->sam = true;
 
		}
 
		
 
		ins_pos=daughter->nodes.insert(ins_pos, node );
 
		new_nodes_parent.push_back( node );
 
		
 
		// optionally add the new node to the nodeset (passed by pointer)
 
		// (in this way we can move the NodeSet as a whole; useful for a fixed cutting line)
 
		if (node_set) {
 
			node_set->AddNode( node );
 
		}
 
		
 
	}
 
@@ -1091,44 +1017,38 @@ void Cell::DivideWalls(ItList new_node_l
 
	}
 
	
 
	
 
	
 
	// Correct tranporterconcentrations of divided walls
 
	for (int i=0;i<4;i++) {
 
		if (div_wall[i]) {
 
			div_wall[i]->SetLength();
 
			div_wall[i]->CorrectTransporters(orig_length[i/2]);
 
		}
 
	}
 
	
 
	//neighbors.push_back( daughter );
 
	//daughter->neighbors.push_back( this );
 
	
 
	
 
	//cerr << "Cell " << index << " has been dividing, and gave birth to Cell " << daughter->index << endl;
 
	
 
	// now reconstruct neighbor list for all "broken" neighbors
 
	
 
	for (list<CellBase *>::iterator i=broken_neighbors.begin();
 
		 i!=broken_neighbors.end();i++) {
 
		((Cell *)(*i))->ConstructNeighborList();
 
	}
 
	
 
	
 
	ConstructNeighborList();
 
	daughter->ConstructNeighborList();
 
	
 
	m->plugin->OnDivide(&parent_info, daughter, this);
 
	// wall->OnWallInsert();
 
	//daughter->OnDivide();
 
	
 
	daughter->div_counter=(++div_counter);
 
	
 
	
 
}
 

	
 
// Move the whole cell
 
void Cell::Move(const Vector T) {
 
	
 
    for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
@@ -1157,37 +1077,35 @@ double Cell::Displace(double dx, double 
 
	vector<double> cellareas;
 
	cellareas.reserve(neighbors.size());
 
	
 
	// for the length constraint, collect all edges to this cell's nodes,
 
	// which are not part of the cell
 
	// the length of these edges will change
 
	
 
	double old_length=0.;
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		
 
		//if ((*i)->Fixed()) return; // commented out 01/12/05
 

	
 
		for (list<Neighbor>::const_iterator n=(*i)->owners.begin();
 
			 n!=(*i)->owners.end();
 
			 n++) {
 
			
 
			if (n->getCell()!=this) {
 
				//if (!(m->getNode(n->nb1).Fixed() && m->getNode(n->nb2).Fixed())) {
 
				length_edges.push_back( pair <Node *,Node *> (*i, n->nb1) );
 
				length_edges.push_back( pair <Node *,Node *> (*i, n->nb2) );
 
				old_length += 
 
				DSQR(Node::target_length-(*(*i)-*(n->nb1)).Norm())+
 
				DSQR(Node::target_length-(*(*i)-*(n->nb2)).Norm());
 
				//}
 
			}
 
		}
 
	}
 
	
 
	// calculate area energy difference of neighboring cells
 
	// (this cells' shape remains unchanged)
 
	double old_area_energy=0., old_length_energy=0.;
 
	for (list<CellBase *>::const_iterator i=neighbors.begin();
 
		 i!=neighbors.end();
 
		 i++) {
 
		old_area_energy += DSQR((*i)->Area()-(*i)->TargetArea());
 
		old_length_energy += DSQR((*i)->Length()-(*i)->TargetLength());
 
@@ -1221,40 +1139,24 @@ double Cell::Displace(double dx, double 
 
		// update areas of cells
 
		//cerr << "neighbors: ";
 
		list<CellBase *>::const_iterator nb_it = neighbors.begin();
 
		for (vector<double>::const_iterator ar_it = cellareas.begin();
 
			 ar_it!=cellareas.end();
 
			 ( ar_it++, nb_it++) ) {
 
			((Cell *)(*nb_it))->area = *ar_it;
 
			(*nb_it)->SetIntegrals(); 
 
		}
 
		
 
		//cerr << endl;
 
		
 
		/*vector<double> area1;
 
		 vector<double> area2;
 
		 m->ExtractFromCells( mem_fun_ref(&Cell::Area), back_inserter(area1) );
 
		 m->ExtractFromCells( mem_fun_ref(&Cell::CalcArea), back_inserter(area2));
 
		 vector<double>::iterator i=area1.begin();
 
		 vector<double>::iterator j=area2.begin();
 
		 int c=0;
 
		 for (;
 
		 i!=area1.end();
 
		 (i++, j++)) {
 
		 if ( (*i-*j) > 1e-10) {
 
		 cerr << c++ << " " << *i << " " << *j << endl;
 
		 abort();
 
		 }
 
		 }*/
 
		
 
	} else {
 
		
 
		Move ( -1*movement);
 
		
 
	}
 
	
 
	return dh;
 
}
 

	
 

	
 
void Cell::Displace (void) {
 
	Displace(par.mc_cell_stepsize*(RANDOM()-0.5),par.mc_cell_stepsize*(RANDOM()-0.5),0);
 
@@ -1342,26 +1244,24 @@ bool Cell::SelfIntersect(void) {
 
				nb = nodes.begin();
 
			} 
 
			Vector v4=*( *nb ); 
 
			
 
			double denominator = 
 
			(v4.y - v3.y)*(v2.x - v1.x) - (v4.x - v3.x)*(v2.y - v1.y);
 
			
 
			double ua = 
 
			((v4.x - v3.x)*(v1.y - v3.y) - (v4.y - v3.y)*(v1.x -v3.x))/denominator;
 
			double ub = 
 
			((v2.x - v1.x)*(v1.y-v3.y) - (v2.y- v1.y)*(v1.x - v3.x))/denominator;
 
			
 
			/* double intersec_x = v1.x + ua*(v2.x-v1.x);
 
			 double intersec_y = v1.y + ua*(v2.y-v1.y);*/
 
			
 
			if ( ( TINY < ua && ua < 1.-TINY ) && ( TINY < ub && ub < 1.-TINY ) ) {
 
				//cerr << "ua = " << ua << ", ub = " << ub << endl;
 
				return true;
 
			}
 
		}
 
    }
 
	
 
    return false;
 
}
 

	
 

	
 
@@ -1417,27 +1317,24 @@ bool Cell::MoveSelfIntersectsP(Node *mov
 
			
 
			Vector v3 = *(*i);
 
			Vector v4 = *(*nb);
 
			
 
			double denominator = 
 
			(v4.y - v3.y)*(neighbor_of_moving_node[j].x - new_pos.x) - (v4.x - v3.x)*(neighbor_of_moving_node[j].y - new_pos.y);
 
			
 
			double ua = 
 
			((v4.x - v3.x)*(new_pos.y - v3.y) - (v4.y - v3.y)*(new_pos.x -v3.x))/denominator;
 
			double ub = 
 
			((neighbor_of_moving_node[j].x - new_pos.x)*(new_pos.y-v3.y) - (neighbor_of_moving_node[j].y- new_pos.y)*(new_pos.x - v3.x))/denominator;
 
			
 
			/* double intersec_x = new_pos.x + ua*(neighbor_of_moving_node[j].x-new_pos.x);
 
			 double intersec_y = new_pos.y + ua*(neighbor_of_moving_node[j].y-new_pos.y);*/
 
			
 
			if ( ( TINY < ua && ua < 1.-TINY ) && ( TINY < ub && ub < 1.-TINY ) ) {
 
				//cerr << "ua = " << ua << ", ub = " << ub << endl;
 
				return true;
 
			}
 
		}
 
	}
 
	
 
	return false;
 
}
 

	
 
/*! \brief Test if this cell intersects with the given line.
 
 
 
@@ -1463,27 +1360,24 @@ bool Cell::IntersectsWithLineP(const Vec
 
			nb = nodes.begin();
 
		}
 
		Vector v4 = *(*nb);
 
		
 
		double denominator = 
 
		(v4.y - v3.y)*(v2.x - v1.x) - (v4.x - v3.x)*(v2.y - v1.y);
 
		
 
		double ua = 
 
		((v4.x - v3.x)*(v1.y - v3.y) - (v4.y - v3.y)*(v1.x -v3.x))/denominator;
 
		double ub = 
 
		((v2.x - v1.x)*(v1.y-v3.y) - (v2.y- v1.y)*(v1.x - v3.x))/denominator;
 
		
 
		/* double intersec_x = v1.x + ua*(v2.x-v1.x);
 
		 double intersec_y = v1.y + ua*(v2.y-v1.y);*/
 
		
 
		if ( ( TINY < ua && ua < 1.-TINY ) && ( TINY < ub && ub < 1.-TINY ) ) {
 
			return true;
 
		}
 
    }
 
	
 
	return false;
 
	
 
	
 
}
 
/*! \brief Constructs Walls, but only one per cell boundary.
 
 
 
 Standard method constructs a Wall for each cell wall element,
 
@@ -1562,32 +1456,30 @@ void Cell::ConstructWalls(void) {
 
			vector<Cell *>::iterator dup_it = find_if(duplicates.begin(),duplicates.end(),mem_fun(&Cell::BoundaryPolP) );
 
			if (dup_it!=duplicates.end()) 
 
				duplicates.erase(dup_it);
 
			else {
 
				return;
 
			}
 
			
 
		}
 
		
 
		
 
		// One Wall for each neighbor, so we should be able to correctly construct neighbor lists here.
 
		if (duplicates[0]==this) {
 
			//walls. new Wall(*nb,*i,duplicates[0],duplicates[1]) );
 
			AddWall(  new Wall(*nb,*i,duplicates[0],duplicates[1]) );
 
			if (!duplicates[1]->BoundaryPolP()) {
 
				
 
				neighbors.push_back(duplicates[1]);
 
			}
 
		} else {
 
			//walls.push_back( new Wall(*nb,*i,duplicates[1],duplicates[0]) ); 
 
			AddWall ( new Wall(*nb,*i,duplicates[1],duplicates[0]) );
 
			if (!duplicates[0]->BoundaryPolP()) {
 
				neighbors.push_back(duplicates[0]);
 
				
 
			}
 
		}
 
	}
 
	
 
}
 

	
 

	
 
void BoundaryPolygon::Draw(QGraphicsScene *c, QString tooltip) {
 
@@ -1715,76 +1607,48 @@ void Cell::DrawCenter(QGraphicsScene *c)
 
	disk->show();
 
	Vector centroid=Centroid();
 
	disk -> setPos((offset[0]+centroid.x)*factor,(offset[1]+centroid.y)*factor);
 
}
 

	
 
void Cell::DrawNodes(QGraphicsScene *c) const {
 
	
 
	for (list<Node *>::const_iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		Node *i=*n;
 
		
 
		//QCanvasEllipse *item = new QCanvasEllipse( 10, 10, c);
 

	
 
		NodeItem *item = new NodeItem ( &(*i), c );
 
		//QGraphicsRectItem *item = new QGraphicsRectItem(-50, -50, 50, 50, 0, c);
 
		//disk->setBrush( QColor("IndianRed") );
 
		
 
		/*if (i->sam) {
 
		 item->setBrush( purple );
 
		 } else {
 
		 if (i->boundary) {
 
		 item->setBrush( deep_sky_blue );
 
		 } 
 
		 else {
 
		 item->setBrush( indian_red );
 
		 }
 
		 }*/
 
		item->setColor();
 
		
 
		/*(if (item->getNode().DeadP()) {
 
		 item->setBrush( QBrush (Qt::Dense6Pattern) );
 
		 }*/
 
		item->setZValue(5);
 
		item->show();
 
		item ->setPos(((offset[0]+i->x)*factor),
 
					  ((offset[1]+i->y)*factor) );
 
	}
 
	
 
}
 

	
 
void Cell::DrawIndex(QGraphicsScene *c) const {
 
	
 
	//  stringstream text;
 
	//     text << index;
 
	//     Vector centroid = Centroid();
 
	//     QCanvasText *number = new QCanvasText ( QString (text.str()), c );
 
	//     number->setColor( QColor(par.textcolor) );
 
	//     number->setZ(20);
 
	//     number->setFont( QFont( "Helvetica", par.cellnumsize, QFont::Bold) );
 
	//     number->show();
 
	//     number -> move((int)((offset[0]+centroid.x)*factor),
 
	// 		   (int)((offset[1]+centroid.y)*factor) );
 
	DrawText( c, QString("%1").arg(index));
 
}
 

	
 
// Draw any text in the cell's center
 
void Cell::DrawText(QGraphicsScene *c, const QString &text) const {
 
    
 
	Vector centroid = Centroid();
 
	QGraphicsSimpleTextItem *ctext = new QGraphicsSimpleTextItem ( text, 0, c );
 
	ctext->setPen( QPen(QColor(par.textcolor)) );
 
	ctext->setZValue(20);
 
	ctext->setFont( QFont( "Helvetica", par.cellnumsize, QFont::Bold) );
 
	//ctext->setTextFlags(Qt::AlignCenter);
 
	ctext->show();
 
	ctext ->setPos(((offset[0]+centroid.x)*factor),
 
				   ((offset[1]+centroid.y)*factor) );
 
	
 
}
 

	
 

	
 
void Cell::DrawAxis(QGraphicsScene *c) const {
 
	
 
	Vector long_axis;
 
	double width;
 
	Length(&long_axis, &width);
 
@@ -1806,79 +1670,30 @@ void Cell::DrawAxis(QGraphicsScene *c) c
 
	line->setLine( ( (offset[0]+from.x)*factor ),
 
				  ( (offset[1]+from.y)*factor ), 
 
				  ( (offset[0]+to.x)*factor ),
 
				  ( (offset[1]+to.y)*factor ) );
 
	line->setZValue(10);
 
	line->show();
 
	
 
}
 

	
 
void Cell::DrawStrain(QGraphicsScene *c) const {
 
  c = NULL; // assignment merely to obviate compilation warning
 
	MyWarning::warning("Sorry, Cell::DrawStrain temporarily not implemented.");
 
	/* Vector long_axis;
 
	double width;
 
	Length(&long_axis, &width);
 
	
 
	//cerr << "Length is "  << length << endl;
 
	long_axis.Normalise();
 
	Vector short_axis=long_axis.Perp2D();
 
    
 
	//  To test method "Strain" temporarily substitute "short_axis" for "strain" 
 
	Vector strain = Strain();
 
	//strain.Normalise();
 
	//static ofstream strainf("strain.dat");
 
	//strainf << strain.Norm() << endl;
 
	Vector centroid = Centroid();
 
	// Vector from = centroid - 0.5 * width * short_axis;
 
    // Vector to = centroid + 0.5 * width *short_axis;
 
	Vector from = centroid - 0.5 * strain;
 
	Vector to = centroid + 0.5 * strain;
 
	
 
	QGraphicsArrowItem *arrow = new QGraphicsArrowItem(0, c);
 
	arrow->setPen( QPen(QColor(par.arrowcolor),100) );
 
    
 
	arrow->setLine( ( (offset[0]+from.x)*factor ),
 
				   ( (offset[1]+from.y)*factor ), 
 
				   ( (offset[0]+to.x)*factor ),
 
				   ( (offset[1]+to.y)*factor ) );
 
	arrow->setZValue(10.);
 
	arrow->show();
 
	*/
 
}
 

	
 
// Draw connecting lines to neighbors
 
/*void Cell::DrawTriangles(QCanvas &c) {
 
 
 
 for (list<Neighbor>::const_iterator nb=nb_list.begin();
 
 nb!=nb_list.end();
 
 nb++) {
 
 QCanvasLine *line = new QCanvasLine(&c);
 
 line->setPen( QPen(QColor("black"),2) );
 
 line->setZ(2);
 
 
 
 line->setPoints((offset[0]+x)*factor,(offset[1]+y)*factor, 
 
 (offset[0]+nb->c->x)*factor,(offset[1]+nb->c->y)*factor);
 
 line->setZ(10);
 
 line->show();
 
 }
 
 
 
 }*/
 

	
 

	
 

	
 
void Cell::DrawFluxes(QGraphicsScene *c, double arrowsize)  {
 
	
 
	// get the mean flux through this cell
 
	//Vector vec_flux = ReduceWalls( mem_fun_ref( &Wall::VizFlux ), Vector() );
 
	Vector vec_flux = ReduceCellAndWalls<Vector>( PINdir );
 
	
 
	vec_flux.Normalise();
 
	
 
	vec_flux *= arrowsize;
 
	
 
	QGraphicsArrowItem *arrow = new QGraphicsArrowItem(0,c);
 
	
 
	Vector centroid = Centroid();
 
	Vector from = centroid - vec_flux/2.;
 
	Vector to = centroid + vec_flux/2.;
 
    
 
@@ -2003,16 +1818,15 @@ list<Wall *>::iterator Cell::RemoveWall(
 
				 find( 
 
					  walls.begin(), walls.end(),
 
					  w )
 
				 );
 
	
 
}
 

	
 

	
 

	
 
void Cell::EmitValues(double t) {
 
	
 
	//  cerr << "Attempting to emit " << t << ", " << chem[0] << ", " << chem[1] << endl;
 
	//chem[3] = SumTransporters( 1 );
 
	emit ChemMonValue(t, chem);
 
	
 
}
src/cell.h
Show inline comments
 
@@ -82,28 +82,24 @@ public:
 
		offset[0]=ox;
 
		offset[1]=oy;
 
    }
 
    static double Magnification(void) {
 
		return factor;
 
    }
 
	
 
    static double Scale(const double scale) {
 
		factor*=scale;
 
		return factor;
 
    }
 
    
 
    // return node "i"
 
    // wrapped around, i.e. node n==node 0
 
    // will not work if i < -nodes.size()
 
    //Node &getNode(int i) const;
 
    void DivideOverAxis(Vector axis); // divide cell over axis
 
    bool DivideOverGivenLine(const Vector v1, const Vector v2, bool wall_fixed = false, NodeSet *node_set = 0); // divide over the line (if line and cell intersect)
 
	
 
    void Divide(void) { // Divide cell over short axis
 
		
 
		Vector long_axis; 
 
		Length(&long_axis); 
 
		DivideOverAxis(long_axis.Perp2D()); 
 
		
 
    }
 
	
 
	//void CheckForGFDrivenDivision(void);
src/cellbase.cpp
Show inline comments
 
@@ -31,46 +31,38 @@
 
#include <qcolor.h>
 
#include <qfont.h>
 
#include <qwidget.h>
 
//Added by qt3to4:
 
#include <Q3PointArray>
 
#include <fstream>
 
#include "nodeitem.h"
 
#include "cellitem.h"
 
#include "qcanvasarrow.h"
 
#endif
 
#include "nodeset.h"
 

	
 
//#include "cond_operator.h"
 
#include "cellbase.h"
 
//#include "node.h"
 
#include "wall.h"
 
#include "random.h"
 
#include "parameter.h" 
 
#include "mesh.h"
 
#include "sqr.h"
 
#include "tiny.h"
 

	
 
static const std::string _module_id("$Id$");
 

	
 
extern Parameter par;
 

	
 
const char* CellBase::boundary_type_names[4] = {"None", "NoFlux", "SourceSink", "SAM"};
 

	
 
// These statics have moved to class "CellsStaticDatamembers"
 

	
 
//double CellBase::static_base_area = 0.;
 
//int CellBase::ncells=0;
 
//int CellBase::NChem()=0;
 

	
 
#ifndef VLEAFPLUGIN
 
CellsStaticDatamembers *CellBase::static_data_members = new CellsStaticDatamembers();
 
#else
 
CellsStaticDatamembers *CellBase::static_data_members = 0;
 
#endif
 

	
 
CellBase::CellBase(QObject *parent) : 
 
QObject(parent),
 
Vector()
 
{
 

	
 
	chem=new double[NChem()];
 
@@ -179,25 +171,25 @@ CellBase::CellBase(const CellBase &src) 
 
	stiffness = src.stiffness;
 
	marked = src.marked;
 
	dead = src.dead;
 
	cell_type = src.cell_type;
 
	div_counter = src.div_counter;
 
	flag_for_divide = src.flag_for_divide;
 
	division_axis = src.division_axis;
 
}
 

	
 

	
 
CellBase CellBase::operator=(const CellBase &src) {
 
	Vector::operator=(src);
 
	//  QObject::operator=(src);
 

	
 
	for (int i=0;i<NChem();i++) {
 
		chem[i]=src.chem[i];
 
	}
 
	for (int i=0;i<NChem();i++) {
 
		new_chem[i]=src.chem[i];
 
	}
 
	boundary=src.boundary;
 
	area=src.area;
 
	intgrl_xx=src.intgrl_xx; intgrl_xy=src.intgrl_xy; intgrl_yy=src.intgrl_yy;
 
	intgrl_x=src.intgrl_x; intgrl_y=src.intgrl_y;
 
	target_area=src.target_area;
 
	target_length=src.target_length;
 
@@ -342,31 +334,24 @@ Vector CellBase::Centroid(void) const {
 
    
 
	//area/=2.0;
 
	area = fabs(area)/2.0;
 
	
 
	integral_x_dxdy/=6.;
 
	integral_y_dxdy/=6.;
 
	
 
	Vector centroid(integral_x_dxdy,integral_y_dxdy,0);
 
	centroid/=area;
 
	return centroid;
 
}
 

	
 
/*Node &CellBase::getNode(list<Node *>::const_iterator i) const {
 

	
 
if (i==
 
	return m->getNode(i);
 
  }*/
 

	
 

	
 

	
 

	
 
void CellBase::SetIntegrals(void) const {
 
	
 
	// Set the initial values for the integrals over x^2,
 
	// xy, yy, x, and y
 
	
 
	// these values will be updated after each move of the CellBase wall
 
	
 
	intgrl_xx=0.; intgrl_xy=0.; intgrl_yy=0.;
 
	intgrl_x=0.; intgrl_y=0.;
 
	area=0.;
 
@@ -399,35 +384,27 @@ void CellBase::SetIntegrals(void) const 
 
			 (*nb)->y*(*i)->y+
 
			 (*nb)->y*(*nb)->y );
 
		intgrl_x+=
 
			((*nb)->x+(*i)->x)*
 
			((*i)->x*(*nb)->y-
 
			 (*nb)->x*(*i)->y);
 
		intgrl_y+=
 
			((*nb)->y+(*i)->y)*
 
			((*i)->x*(*nb)->y-
 
			 (*nb)->x*(*i)->y);
 
	}
 
	
 
	//area/=2.0;
 

	
 
	area = fabs(area)/2.0;
 
	
 
	/* intgrl_x/=6.;
 
	intgrl_y/=6.;
 
	
 
	intgrl_xx/=12.;
 
	intgrl_xy/=24.;
 
	intgrl_yy/=12.;*/
 
	
 
	
 
}
 

	
 
double CellBase::Length(Vector *long_axis, double *width)  const {
 
	
 
	// Calculate length and axes of CellBase
 
    
 
	// Calculate inertia tensor
 
	// see file inertiatensor.nb for explanation of this method
 
	if (!lambda_celllength) {
 
		
 
		// Without length constraint we do not keep track of the cells'
 
		// moments of inertia. So we must calculate them here.
 
@@ -438,27 +415,24 @@ double CellBase::Length(Vector *long_axi
 
	double intry=intgrl_y/6.;
 
	double ixx=(intgrl_xx/12.)-(intrx*intrx)/area;
 
	double ixy=(intgrl_xy/24.)+(intrx*intry)/area;
 
	double iyy=(intgrl_yy/12.)-(intry*intry)/area;
 
	
 
	double rhs1=(ixx+iyy)/2., rhs2=sqrt( (ixx-iyy)*(ixx-iyy)+4*ixy*ixy )/2.;
 
    
 
	double lambda_b=rhs1+rhs2;
 
	
 
	// see: http://scienceworld.wolfram.com/physics/MomentofInertiaEllipse.html
 
	//    cerr << "n = " << n << "\n";
 
	
 
	// Vector eigenvectors[2];
 
	// eigenvectors[0] = Vector(-(-ixx + iyy ) + rhs2, ixy, 0);
 
	// eigenvectors[1] = Vector(-(-ixx + iyy ) - rhs2, ixy, 0);
 
	if (long_axis) {
 
		*long_axis = Vector(-ixy, lambda_b - ixx, 0);
 
		//   cerr << "ixx = " << ixx << ", ixy = " << ixy << ", iyy = " << iyy << ", area = " << area << endl;
 
	}
 
	
 
	if (width) {
 
		*width = 4*sqrt((rhs1-rhs2)/area);
 
	}
 
	
 
	return 4*sqrt(lambda_b/area);
 
    
 
	
 
@@ -522,435 +496,82 @@ double CellBase::CalcLength(Vector *long
 
	double intry=my_intgrl_y/6.;
 
	double ixx=(my_intgrl_xx/12.)-(intrx*intrx)/my_area;
 
	double ixy=(my_intgrl_xy/24.)+(intrx*intry)/my_area;
 
	double iyy=(my_intgrl_yy/12.)-(intry*intry)/my_area;
 
	
 
	double rhs1=(ixx+iyy)/2., rhs2=sqrt( (ixx-iyy)*(ixx-iyy)+4*ixy*ixy )/2.;
 
    
 
	double lambda_b=rhs1+rhs2;
 
	
 
	// see: http://scienceworld.wolfram.com/physics/MomentofInertiaEllipse.html
 
	//    cerr << "n = " << n << "\n";
 
	
 
	// Vector eigenvectors[2];
 
	// eigenvectors[0] = Vector(-(-ixx + iyy ) + rhs2, ixy, 0);
 
	// eigenvectors[1] = Vector(-(-ixx + iyy ) - rhs2, ixy, 0);
 
	if (long_axis) {
 
		*long_axis = Vector(-ixy, lambda_b - ixx, 0);
 
		//   cerr << "ixx = " << ixx << ", ixy = " << ixy << ", iyy = " << iyy << ", my_area = " << my_area << endl;
 
	}
 
	
 
	if (width) {
 
		*width = 4*sqrt((rhs1-rhs2)/my_area);
 
	}
 
	
 
	return 4*sqrt(lambda_b/my_area);
 
    
 
	
 
	
 
}
 

	
 

	
 
// void CellBase::NodeRemoved(int n) {
 
//   for (list<Node *>::iterator i=nodes.begin();
 
//        i!=nodes.end();
 
//        i++) {
 
//     if ((*i)->Index()>n) {
 
//       (*i)->index--;
 
//     }
 
//   }
 
// }
 

	
 
void CellBase::ConstructNeighborList(void) {
 
	
 
	neighbors.clear();
 
	for (//list<Wall *>::const_reverse_iterator wit=walls.rbegin();
 
		 list<Wall *>::const_iterator wit=walls.begin();
 
		 // somehow the reverse_iterator returns by walls needs to be casted to const to let this work.
 
		 // it seems to me it is a bug in the STL implementation...
 
		 //wit!=(list<Wall *>::const_reverse_iterator)walls.rend();
 

	
 
		 wit!=walls.end();
 
		 wit++) {
 
		
 
		if ((*wit)->C1() != this) {
 
			neighbors.push_back((*wit)->C1());
 
		} else {
 
			neighbors.push_back((*wit)->C2());
 
		}
 
		
 
	}
 
	
 
	
 
	/*
 
	 for (list<CellBase *>::iterator e=neighbors.begin();
 
		  e!=neighbors.end();
 
		  e++) {
 
		 cerr << (*e)->Index() << " ";
 
		 if ((*e)->CellBase::BoundaryPolP()) {
 
			 cerr << " b ";
 
		 }
 
	 }
 
	 */
 
	// remove all boundary_polygons from the list
 
	
 
	
 
    
 
	list <CellBase *>::iterator e=neighbors.begin();
 
	at_boundary=false;
 
	
 
	do { 
 
		// Code crashes here after cutting off part of the leaf. I can't find the problem.
 
		// Leaving the "Illegal" walls in the simulation helps. (c1=-1 && c2=-1)
 
		// Work-around: define leaf primordium. Save to XML. Restart. Read XML file.
 
		// Sorry about this; I hope to solve this annoying issue later. RM :-).
 
		// All cells in neighbors seem to be okay (I might be messing some part of the memory elsewhere
 
		// during the cutting operation?).
 
		e = find_if(neighbors.begin(),neighbors.end(),mem_fun(&CellBase::BoundaryPolP));
 
		if (e!=neighbors.end()) {
 
			e=neighbors.erase(e);
 
			at_boundary=true;
 
		} else {
 
			break;
 
		}
 
  } while(1);
 
	
 
}
 

	
 
// CellBase constructs its neighbor list from its node lists
 
// Assumes, obviously, that the node lists are up to date
 
// (i.e. call ConstructConnections before calling this method)
 
// We'll keep this one private, anyway.
 
/* void CellBase::ConstructNeighborList(void) {
 

	
 
//  extern ofstream debug_stream;
 

	
 
neighbors.clear();
 

	
 
//  debug_stream << "Nodes: ";
 
//  copy(nodes.begin(),nodes.end(),ostream_iterator<Node>(debug_stream, " "));
 
//debug_stream << endl;
 

	
 
for (list<Node *>::const_iterator i=nodes.begin();
 
	 i!=nodes.end();
 
	 i++) {
 
    
 
    // collect all cells to which my nodes are connected on one list
 
    //transform((*i)->cells.begin(),(*i)->cells.end(), back_inserter(neighbors), mem_fun_ref(&Neighbor::CellBase));
 
	
 
    // index of next node 
 
    list<Node *>::const_iterator nn=i;
 
    ++nn;
 
    if (nn==nodes.end()) 
 
		nn=nodes.begin();
 
	
 
    //    debug_stream << "Node " << *i << ", Neighbor " << *nn << endl;
 
    // debug_stream << "Owners: ";
 
    //    copy((*i)->cells.begin(),(*i)->cells.end(),ostream_iterator<Neighbor>(debug_stream, " "));
 
    // debug_stream << endl;
 
    
 
    for (list<Neighbor>::const_iterator nb=(*i)->owners.begin();
 
		 nb!=(*i)->owners.end();
 
		 nb++) {
 
		
 
		// collect info about neighboring cells, not about myself
 
		if (nb->CellBase!=this) {
 
			
 
			// make sure the whole edge touches this putative neighbor
 
			// if (*nn == nb->nb1 || *nn == nb->nb2) {
 
			//walls.push_back( new Wall(*i,*nn,this,nb->CellBase) );
 
			//debug_stream << "Adding edge " << walls.back() << " to CellBase " << index << endl;
 
			//}
 
			
 
			neighbors.push_back( nb->CellBase );
 
		} 
 
    }
 

	
 

	
 
}
 

	
 
neighbors.sort();
 

	
 
list<CellBase *>::iterator e=unique(neighbors.begin(),neighbors.end());
 

	
 
// iterator e point to the end of the subsequence of unique elements
 
// remove every thing that comes after it
 

	
 
neighbors.erase(e, neighbors.end());
 

	
 
// okay, now neighbors contains all neighbors of this CellBase, including itself
 

	
 
// A future optimization for the diffusion algorithm: now we list
 
// each of the edges of a (curved) CellBase boundary separately.  We
 
// could keep track just of the total length per CellBase boundary
 

	
 
// the following is not necessary anymore. Is
 
// checked at earlier stage
 
// // remove myself from the list
 
//   e = find(neighbors.begin(),neighbors.end(),index);
 
//   if (e!=neighbors.end())
 
//   neighbors.erase(e);
 
//    
 

	
 
// remove boundary_polygon from the list (CellBase identity <0 )
 
e=neighbors.begin();
 
at_boundary=false;
 
do { 
 
    e = find_if(neighbors.begin(),neighbors.end(),mem_fun(&CellBase::BoundaryPolP));
 
    if (e!=neighbors.end()) {
 
		e=neighbors.erase(e);
 
		at_boundary=true;
 
    } else {
 
		break;
 
    }
 
} while(1);
 

	
 

	
 
}*/
 

	
 

	
 
/*void Cell::print_nblist(void) const {
 
//  cerr << "{ ";
 

	
 
for (list<Neighbor>::const_iterator i=nb_list.begin();
 
	 i!=nb_list.end();
 
	 i++) {
 
	//    cerr << "(" << i->c->index << " " << i->Dij << ")";
 
	
 
}
 
//  cerr << "}" << endl;
 
}
 
*/
 

	
 

	
 
// Tests whether Cell p (given as Vector, remember that Cell is a
 
// Vector) is within polygon formed by nearest neighbor cells
 
// 
 
// Based on algorithm and code by Paul Bourke, see
 
// http://astronomy.swin.edu.au/~pbourke/geometry/insidepoly/
 
//
 
// Note: works for 2D only; projects everything on z=0;
 
/*
 
#define MIN(x,y) (x < y ? x : y)
 
#define MAX(x,y) (x > y ? x : y)
 
 */
 
/*bool Cell::CellInsidePolygonP(Vector &p)
 
{
 
    int counter = 0;
 
    double xinters;
 
    Vector p1,p2;
 
	
 
    //p1 = polygon[0];
 
    p1 = *(nb_list.begin()->c);
 
	
 
    int N=nb_list.size();
 
    list<Neighbor>::const_iterator nb=nb_list.begin();
 
	
 
    for (int i=1;i<=N;i++) {
 
		
 
		nb++;
 
		
 
		if (nb!=nb_list.end()) {
 
			p2 = *(nb->c);
 
		} else {
 
			p2 = *(nb_list.begin()->c);
 
		}
 
		
 
		if (p.y > MIN(p1.y,p2.y)) {
 
			if (p.y <= MAX(p1.y,p2.y)) {
 
				if (p.x <= MAX(p1.x,p2.x)) {
 
					if (p1.y != p2.y) {
 
						xinters = (p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
 
						if (p1.x == p2.x || p.x <= xinters)
 
							counter++;
 
					}
 
				}
 
			}
 
		}
 
		p1 = p2;
 
    }
 
	
 
    if (counter % 2 == 0)
 
		return false;
 
    else
 
		return true;
 
	
 
}*/
 

	
 

	
 
/* // at new position cell should be able to "see" all polygon sides
 
bool Cell::NewPointValidP(Vector &p) {
 
	
 
	//int ninvtri=0;
 
	for (list<Neighbor>::const_iterator nb=nb_list.begin();
 
		 nb!=nb_list.end();
 
		 nb++) {
 
		
 
		Vector p1=*(nb->c); // first neighbor
 
		list<Neighbor>::const_iterator nextv=nb; nextv++;
 
		
 
		
 
		if (nextv==nb_list.end()) {
 
			if (Boundary()==None) {
 
				nextv=nb_list.begin();
 
			} else continue;
 
		}
 
		
 
		Vector p2=*(nextv->c);
 
		
 
		Vector v1=(p1-p);
 
		Vector v2=(p2-p1);
 
		
 
		Vector cross=v1*v2;
 
		//    //cerr << "[" << cross << "]" << endl;
 
		
 
		if (cross.z<0) {
 
			// One of the triangles has "inverted".
 
			//if (Boundary()==None || ninvtri) 
 
			return false;
 
			//else 
 
			// accept one "inverted" triangle
 
			//ninvtri++;
 
		}
 
	}
 
	return true;
 
    
 
}*/
 

	
 

	
 

	
 

	
 
// void Cell::CheckForDivision(void) {
 
//  //  if (/* Chemical(0)<0.4 && */ /* differentiated cells do not divide */ area > 2*base_area /* || Length()>50 */) {
 

	
 
//  if (area > par.rel_cell_div_threshold * base_area ) {
 
//    /* remark no longer valid? //m->IncreaseCellCapacityIfNecessary();
 
//      // Note that calling Divide as follows prevents trouble if cell
 
//      // vector is relocated */
 
//      Divide();
 
//  }
 
//}
 

	
 
/* void Cell::CheckForGFDrivenDivision(void) {
 
if (area > base_area && chem[0]>par.gf_div_threshold) {
 
    //int ind=index;
 
    if (index==1) return; // petiole does not divide
 
	
 
    // remark no longer valid?
 
    //m->IncreaseCellCapacityIfNecessary();
 
    // Note that calling Divide as follows prevents trouble if cell
 
    // vector is relocated
 
    Vector horizontal(1,0,0);
 
    Vector vertical(0,1,0);
 
    double r; 
 
    if ((r=RANDOM())>par.vertdivprob) {
 
		DivideOverAxis(horizontal);
 
    } else {
 
		cerr << "[" << r << "]";
 
		DivideOverAxis(vertical);
 
    }
 
}
 
}
 
*/
 

	
 

	
 

	
 
// return (a measure of) the strain of this cell
 
/*Vector CellBase::Strain(void) const {
 
	
 
	cerr << "Sorry, CellBase::strain currently not implemented" << endl;
 
	std::exit(1);
 
	
 
	// Reason: we do not want to include "Node" in the plugins (Node::target_length below), and we do need Strain anyway...
 
	
 
	
 
	// go over all wall elements of the cell
 
	 Vector Fvec;
 
	
 
	for (list<Node *>::const_iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		
 
		list<Node *>::const_iterator nn=n; nn++;
 
		if (nn==nodes.end()) nn=nodes.begin();
 
		
 
		Vector wall_element = *(*n) - *(*nn);
 
		
 
		// assume k=1 (Hooke's constant), for now
 
		double Fscal  = (Node::target_length - wall_element.Norm())/Node::target_length;
 
		
 
		
 
		Fvec += Fscal * wall_element.Normalised();
 
		
 
	}
 
	
 
	return Fvec; 
 
} */
 

	
 

	
 

	
 
/* void Cell::Flux(double *flux, double D)  {
 

	
 
// Algorithm according to Rudge & Haseloff 2005
 
// (will we need to take cell area into account?)
 
// For the time being, we don't: assume cell area is 
 
// mainly determined by vacuole.
 

	
 
// Currently implements Rolland-Lagan-Mitchison algorithm
 
// Rolland-Lagan and Prusinkiewicz, The Plant Journal (2005), 44, 854-865
 

	
 
// currently I only implemented passive, diffusive transport 
 
// active transport will be added later
 

	
 
// loop over cell edges
 

	
 
for (int c=0;c<Cell::NChem();c++) flux[c]=0.;
 

	
 
for (list<Wall>::iterator i=walls.begin();
 
	 i!=walls.end();
 
	 i++) {
 
    
 
    
 
	// leaf cannot take up chemicals from environment ("no flux boundary")
 
	if (i->c2 < 0) continue;
 
    
 
	// calculate edge length 
 
	// (will later be updated during node displacement for efficiency)
 
	double edge_length = (m->nodes[i->n1]-m->nodes[i->n2]).Norm();
 
    
 
	// D is "background diffusion coefficient" (Rolland-Lagan)
 
	
 
	
 
	// flux depends on edge length and concentration difference */
 
	// i->phi = edge_length * ( /* i->D +*/ D ) * ( m->cells[i->c2].chem[0] - chem[0] );
 
	/*
 
	 if (m->cells[i->c1].index!=index) {
 
		 cerr << "Warning, bad cells boundary: " << m->cells[i->c1].index << ", " << index << endl;
 
	 }
 
	 
 
	 flux[0] += i->phi;
 
	 //double deltaD = par.alpha * (i->phi*i->phi) - par.gamma * i->D; // Note beta=0
 
	 //i->D += par.dt*deltaD; 
 
	 
 
	 //cerr << "[ i->D = " << i->D << ", deltaD = " << deltaD << "]";
 
	 //if (i->D > par.Dmax) i->D=par.Dmax;
 
	 
 
	 // first calculate all fluxes, we update diffusion coefficient afterwards.
 
	 
 
	 // cerr << "[ " << edge_length << ", " << m->cells[i->c2].chem[0] << " - " << chem[0] << "]";
 
	 
 
}
 

	
 

	
 
}
 
*/
 
	
 
	// Save the cell to a stream so we can reconstruct its state later
 
	void CellBase::Dump(ostream &os) const {
 
		
 
		
 
		os << index << " " << nodes.size() << endl;
 
		
 
		Vector::Dump(os);
 
		os << endl;
 
		
 
		for (list<Node *>::const_iterator i=nodes.begin();i!=nodes.end();i++) {
 
			os << *i << " ";
src/cellbase.h
Show inline comments
 
@@ -99,26 +99,24 @@ class CellBase :  public QObject, public
 
	
 
  virtual ~CellBase() {
 
	  delete[] chem;
 
	  delete[] new_chem;
 
	  if (division_axis) delete division_axis;
 
	  //cerr << "CellBase " << index << " is dying. " << endl;
 
  }
 
	
 
	CellBase(const CellBase &src); // copy constructor
 
	virtual bool BoundaryPolP(void) const { return false; } 
 
	
 
	
 
	//  CellBase(const Vector &src); // not allowed (we cannot know to which mesh 
 
	/// the CellBase will belong...)
 
    CellBase operator=(const CellBase &src); // assignment operator
 
    CellBase operator=(const Vector &src);
 
  
 
    void SetChemical(int chem, double conc);
 
    inline void SetNewChem(int chem, double conc) { 
 
      new_chem[chem] = conc;
 
    }
 
    void SetSource(int chem, double conc) {
 
      source=true;
 
      source_chem = chem;
 
      source_conc = conc;
 
	}
 
@@ -149,26 +147,24 @@ class CellBase :  public QObject, public
 
      if ((c<0) || (c>=nchem))
 
	MyWarning::warning("CellBase::Chemical says: index c is: %d, but nchem is: %d. Merely return zero", c, nchem);
 
      #endif
 

	
 
      return ((c<0) || (c>=nchem)) ? 0 : chem[c];
 
    }
 

	
 
    
 
    //void print_nblist(void) const;
 

	
 
    boundary_type SetBoundary(boundary_type bound) {
 
      if (bound!=None) {
 
	//area=0.;
 
	//length=0.;
 
      }
 
      return boundary=bound;
 
    }
 
  
 
    boundary_type ResetBoundary(void) {
 
      return boundary=None;
 
    }
 
    boundary_type Boundary(void) const {
 
      return boundary;
 
    }
 
    static int &NChem(void) {
 
      return static_data_members->nchem;
 
@@ -220,53 +216,50 @@ class CellBase :  public QObject, public
 
      return area;
 
    }
 
    
 
	inline void Divide(void) {
 
		flag_for_divide = true;
 
	}
 
	
 
	inline void DivideOverAxis(const Vector &v) {
 
		division_axis = new Vector(v);
 
		flag_for_divide = true;
 
	}
 
	
 
	//Vector Strain(void) const;
 

	
 
    inline double Circumference(void) const {
 
      double sum=0.;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum +=  (*w)->Length();
 
      }
 
      
 
      return sum;
 
    }
 

	
 
	QList<WallBase *> getWalls(void) {
 
		QList<WallBase *> wall_list;
 
		for (list<Wall *>::iterator i=walls.begin();
 
			 i!=walls.end();
 
			 i++) {
 
			wall_list << *i;
 
		}
 
		return wall_list;
 
	}
 
  //  void XFigPrint(std::ostream &os) const;
 
    
 
    void Dump(ostream &os) const;
 
   	
 
	QString printednodelist(void);
 
 
 
   // void OnDivide(ParentInfo &parent_info, CellBase &daughter);
 

	
 
    
 
    inline bool DeadP(void) { return dead; }
 
    inline void MarkDead(void) { dead  = true; }
 
    
 
	static double &BaseArea(void) { 
 
		return static_data_members->base_area;
 
	}
 
  
 
    void CheckForDivision(void);
 

	
 
	
 
@@ -334,31 +327,24 @@ class CellBase :  public QObject, public
 
    template<class P, class Op> P ReduceCellAndWalls(Op f) {
 
      P sum = 0;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum += ((*w)->c1 == this) ? 
 
	  f( ((*w)->c1), ((*w)->c2), *w ) :  
 
	  f( ((*w)->c2), ((*w)->c1), *w );
 
      }
 
      return sum;
 
    }
 
    
 
	/* template<class Op> void LoopWalls(Op f) {
 
		for (list<Wall *>::const_iterator w=walls.begin();
 
			 w!=walls.end();
 
			 w++) {
 
			( **w)->f;
 
		}
 
	}*/
 
	
 
    //! Sum transporters at this CellBase's side of the walls
 
    double SumTransporters(int ch) {
 
      double sum=0.;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum += (*w)->getTransporter(this, ch);
 
      
 
      }
 
      
 
      return sum;
 
@@ -454,27 +440,24 @@ protected:
 
    double stiffness; // stiffness like in Hogeweg (2000)
 

	
 
    bool fixed;
 
    bool pin_fixed;
 
    bool at_boundary; 
 
    bool dead; 
 
	bool flag_for_divide;
 
	
 
	Vector *division_axis;
 
	
 
	int cell_type;
 
	
 
    //double length;
 
    //Vector meanflux;
 
    //int valence;
 
    
 
    // for length constraint
 
    mutable double intgrl_xx, intgrl_xy, intgrl_yy, intgrl_x, intgrl_y;
 
    
 
    bool source;
 
    Vector cellvec;
 
	
 
	// STATIC DATAMEMBERS MOVED TO CLASS
 
	static CellsStaticDatamembers *static_data_members;
 
	double source_conc;
 
    int source_chem;
 
	
src/data_plot.cpp
Show inline comments
 
@@ -54,28 +54,24 @@ DataPlot::DataPlot(QWidget *parent, cons
 
  
 
  // allocate data and curves
 
  d_t = new double[PLOT_SIZE];
 
  d_x = new double *[ncurves];
 
  d_x[0] = new double[ncurves*PLOT_SIZE];
 
  for (int i=1;i<ncurves;i++) {
 
    d_x[i]=d_x[i-1]+PLOT_SIZE;
 
  }
 
  
 
  // Disable polygon clipping
 
  QwtPainter::setDeviceClipping(false);
 

	
 
  // We don't need the cache here
 
  //canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
 
  //canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);
 

	
 
  alignScales();
 
    
 
  //  Initialize data
 
  
 
  
 
  for (int i = 0; i< PLOT_SIZE; i++) {
 
    d_t[i] = 0.;     // time axis
 
  }
 

	
 
  for (int i=0;i<ncurves * PLOT_SIZE;i++) {
 
    d_x[0][i]=0.;
 
  }
 
@@ -96,42 +92,26 @@ DataPlot::DataPlot(QWidget *parent, cons
 
    #ifdef QDEBUG
 
    qDebug() << "Curvecolor " << col.toStdString() << endl;
 
    #endif
 

	
 
    curves[i].setRawData(d_t, d_x[i], PLOT_SIZE);
 
  }
 
    
 
  // Axis 
 
  setAxisTitle(QwtPlot::xBottom, "Time");
 

	
 
  setAxisTitle(QwtPlot::yLeft, "Level");
 
  setAxisScale(QwtPlot::yLeft, 0, 10);
 
    
 
  //    setTimerInterval(0.0); 
 

	
 
  data_pos = 0;
 
  
 

	
 
  // open file for writing
 
  /* QString fname(title);
 
  fname.replace(QString(" "),QString());
 
  fname.append(".dat");
 
  std::cerr << "Writing to file " << fname.toStdString() << std::endl;
 
  
 
  datfile = new QFile(fname);
 
  if (!datfile->open(QIODevice::WriteOnly | QIODevice::Text))
 
    return;
 
  
 
  datstream.setDevice(datfile);
 
  */
 

	
 
}
 

	
 
DataPlot::~DataPlot(void) {
 
  delete[] d_t ;
 
  delete[] d_x[0];
 
  delete[] d_x;
 
  delete[] curves;
 
}
 
//
 
//  Set a plain canvas frame and align the scales to it
 
//
 
@@ -147,70 +127,52 @@ void DataPlot::alignScales()
 
    for ( int i = 0; i < QwtPlot::axisCnt; i++ )
 
    {
 
        QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i);
 
        if ( scaleWidget )
 
            scaleWidget->setMargin(0);
 

	
 
        QwtScaleDraw *scaleDraw = (QwtScaleDraw *)axisScaleDraw(i);
 
        if ( scaleDraw )
 
            scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
 
    }
 
}
 

	
 
/* void DataPlot::setTimerInterval(double ms)
 
{
 
    d_interval = qRound(ms);
 

	
 
    if ( d_timerId >= 0 )
 
    {
 
        killTimer(d_timerId);
 
        d_timerId = -1;
 
    }
 
    if (d_interval >= 0 )
 
        d_timerId = startTimer(d_interval);
 
}
 
*/
 

	
 
//  Generate new values 
 
void DataPlot::AddValue(double t,double *x)
 
{
 

	
 
  //  std::cerr << "AddValue receives: " << t << ", " << y << ", " << z << std::endl;
 
  
 
  // Plot slowly fills up, then shifts to the left
 
  if ( data_pos >= PLOT_SIZE ) {
 
    
 
    for ( int j = 0; j < PLOT_SIZE - 1; j++ )
 
      d_t[j] = d_t[j+1];
 

	
 
    for ( int i=0;i<ncurves;i++) {
 
      for ( int j = 0; j < PLOT_SIZE - 1; j++ )
 
	d_x[i][j] = d_x[i][j+1];
 
    }
 
    data_pos = PLOT_SIZE - 1;
 
    
 
  } 
 

	
 
  d_t[data_pos] = t;
 

	
 
  // datstream << t;
 

	
 
  for ( int i=0;i<ncurves;i++) {
 
    curves[i].setRawData(d_t, d_x[i], data_pos);
 
    d_x[i][data_pos] = x[i];
 
    //datstream << " " << x[i];
 
  }
 
					       
 
  //datstream << "\n";
 
  
 
  setAxisScale(QwtPlot::xBottom, d_t[0], t);
 
  
 
  data_pos++;
 
  // update the display
 
  replot();
 
  
 

	
 
}
 

	
 

	
 
PlotDialog::PlotDialog(QWidget *parent, const QString title, const QStringList curvenames):
 
  QDialog(parent) 
src/data_plot.h
Show inline comments
 
@@ -33,25 +33,24 @@
 
#include "curvecolors.h"
 

	
 
const int PLOT_SIZE = 1000; 
 

	
 
class DataPlot : public QwtPlot
 
{
 
    Q_OBJECT
 

	
 
public:
 
  DataPlot(QWidget *parent, const QString title, const QStringList curvenames);
 
  virtual ~DataPlot(void);
 
public slots:
 
    //    void setTimerInterval(double interval);
 
    void AddValue(double t, double *x);
 

	
 
private:
 
    void alignScales();
 

	
 
    double *d_t; 
 
    double **d_x; 
 

	
 
    int d_interval; // timer in ms
 
    int d_timerId;
 
    
 
    QwtPlotCurve *curves;
 
@@ -65,22 +64,21 @@ private:
 
    QFile *datfile;
 
    QTextStream datstream;
 

	
 
};
 

	
 
class PlotDialog : public QDialog {
 

	
 
Q_OBJECT
 
 public:
 
  PlotDialog(QWidget *parent, const QString title, const QStringList curvenames);
 
  ~PlotDialog(void);
 
  public slots:
 
    //    void setTimerInterval(double interval);
 
  void AddValue(double t, double *x) {
 
    //std::cerr << "AddValue receives: " << t << ", " << y << ", " << z << std::endl;
 
    plot->AddValue(t,x);
 
  }
 
 private:
 
  DataPlot *plot;
 
};
 

	
 
#endif
src/flux_function.h
Show inline comments
 
/*
 
 *  flux_function.h
 
 *  VirtualLeaf
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  Created by Roeland Merks on 07-06-10.
 
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _FLUX_FUNCTION_h_
 
#define _FLUX_FUNCTION_h_
 

	
 
// This header file defines a macro "SumFluxFromWalls" that attempts to hide this 
 
// horrendously confusing member function wrapper construct from VirtualLeaf's end users
 

	
 
// required format of flux_function is:
 
// double [model class name]::[function name](CellBase *this_cell, CellBase *adjacent_cell, Wall *w)
 
// e.g.:
 
// double MyModel::PINflux(CellBase *this_cell, CellBase *adjacent_cell, Wall *w)
 

	
 
#include "far_mem_5.h"
 

	
 
#define SumFluxFromWalls( _vleafcellp_, _flux_function_ ) \
 
(( _vleafcellp_->ReduceCellAndWalls<double>( far_3_arg_mem_fun( *this, &_flux_function_ ) ) ))
 

	
 
#endif
src/forwardeuler.cpp
Show inline comments
 
@@ -23,34 +23,24 @@
 
#include <iostream> 
 
#include "forwardeuler.h"
 
#include "warning.h"
 
#include "maxmin.h"
 
#include <string>
 

	
 
using namespace std;
 

	
 
static const string _module_id("$Id$");
 

	
 
// The value Errcon equals (5/Safety) raised to the power (1/PGrow), see use below.
 

	
 
/* static float maxarg1,maxarg2;
 
   #define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?	\
 
   (maxarg1) : (maxarg2))
 
   static float minarg1,minarg2;
 
   #define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?	\
 
   (minarg1) : (minarg2))
 
   #define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
 
*/
 

	
 

	
 
const double ForwardEuler::Safety  = 0.9;
 
const double ForwardEuler::PGrow = -0.2;
 
const double ForwardEuler::Pshrnk = -0.25;
 
const double ForwardEuler::Errcon = 1.89e-4;
 
const double ForwardEuler::Maxstp = 10000000;
 
const double ForwardEuler::Tiny = 1.0e-30;
 
  
 

	
 

	
 
/* User storage for intermediate results. Preset kmax and dxsav in the calling program. If kmax =
 
   0 results are stored at approximate intervals dxsav in the arrays xp[1..kount], yp[1..nvar]
 
   [1..kount], where kount is output by odeint. Defining declarations for these variables, with
src/infobar.h
Show inline comments
 
@@ -32,30 +32,26 @@
 

	
 
class InfoBar : public Q3DockWindow {
 

	
 
	Q_OBJECT
 
public:
 

	
 
	InfoBar(void) : Q3DockWindow() { 
 
		
 
		virtleaf = new QLabel();
 
		SetText("undefined");
 
		
 
		setHorizontalStretchable(true);
 
		//dockwindow->boxLayout()->addWidget(viblab);//,Qt::AlignLeft);
 
		boxLayout()->addStretch();
 
		boxLayout()->addWidget(virtleaf);//, Qt::AlignHCenter);
 
		boxLayout()->addStretch();
 
	
 
		//dockwindow->boxLayout()->addWidget(psblab);//, Qt::AlignRight);
 
	}
 
	
 
	void SetText(QString text) {
 
		virtleaf->setText(QString("<h1>The Virtual Leaf</h1>\n<center><b>Model:</b> <i>%1</i></center>").arg(text));
 
	}
 
	
 
private:
 
	//Q3DockWindow *dockwindow;
 
	QLabel *virtleaf;
 
};
 

	
 
#endif
 
\ No newline at end of file
src/mainbase.cpp
Show inline comments
 
@@ -211,50 +211,39 @@ void MainBase::Save(const char *fname, c
 
	
 
	if (QString(fname).isEmpty()) {
 
		MyWarning::warning("No output filename given. Saving nothing.\n");
 
		return;
 
	}
 
	
 
	
 
	ll*=Cell::Magnification(); ur*=Cell::Magnification();
 
	
 
	// give the leaf some space
 
	Vector border = ((ur-ll)/5.);
 
	
 
	//QRectF bb( ll.x - border.x, ll.y - border.y, ur.x-ll.x + 2*border.x, ur.y-ll.y + 2*border.y );
 
	
 
	if (!QString(format).contains("pdf", Qt::CaseInsensitive)) {
 
	
 
		QImage *image = new QImage(QSize(sizex, sizey), QImage::Format_RGB32);
 
		image->fill(QColor(Qt::white).rgb());
 
		QPainter *painter=new QPainter(image);
 
		//canvas.render(painter,QRectF(),QRectF(-5000,-5000, 10000, 10000));
 
		canvas.render(painter);
 
		if (!image->save(QString(fname))) {
 
			MyWarning::warning("Image not saved successfully. Is the disk full or the extension not recognized?");
 
		};
 
		delete painter;
 
		delete image;
 
	} else {
 
		QPrinter pdf(QPrinter::HighResolution);
 
		pdf.setOutputFileName(fname);
 
		pdf.setOutputFormat(QPrinter::PdfFormat);
 
		//pdf.setPageSize(QPrinter::Custom);
 
		QPainter painter(&pdf);
 
		//	cerr << "Cell::Magnification() = " << Cell::Magnification() << endl;
 
		//if (sizex==0 || sizey==0) {
 
			// always fit to page
 
		//	canvas.render(&painter);
 
		//} else {
 
		//	canvas.render(&painter,QRectF(),QRectF(-5000,-5000, 10000, 10000));
 
		//}
 
		canvas.render(&painter, QRectF(), QRectF(-5000,-5000, 10000, 10000));
 
		
 
		cerr << "Rendering to printer\n";
 
	}
 
}
 

	
 
void MainBase::CutSAM() {
 
	
 
	mesh.CutAwaySAM();
 
	
 
}
src/mainbase.h
Show inline comments
 
@@ -49,80 +49,60 @@ class MainBase  {
 
    showmeshp =  false;
 
    showbordercellp =  false;
 
    shownodenumbersp =  false;
 
    showcellnumbersp =  false;
 
    showcellsaxesp = false;
 
    showcellstrainp =  false;
 
    movieframesp = true;
 
    showboundaryonlyp =  false;
 
    showwallsp =  false;
 
    showfluxesp = false;
 
    dynamicscellsp = true;
 
    showtooltipsp = false;
 
	hidecellsp = false;
 
    hidecellsp = false;
 
  }
 
    virtual ~MainBase() {};
 
    
 
    virtual double TimeStep();
 
    virtual void Init(char *leaffile=0);
 
    
 
    virtual bool ShowCentersP(void) {return showcentersp;}
 
    virtual bool ShowMeshP(void) {return showmeshp; }
 
    virtual bool ShowBorderCellsP(void) {return showbordercellp; }
 
    virtual bool PausedP(void) {return false; }
 
    virtual bool ShowNodeNumbersP(void) {return shownodenumbersp; }
 
    virtual bool ShowCellNumbersP(void) {return showcellnumbersp;}
 
    virtual bool ShowCellAxesP(void) {return showcellsaxesp;}
 
    virtual bool ShowCellStrainP(void) {return showcellstrainp;}
 
    virtual bool MovieFramesP(void) {return movieframesp;}
 
    virtual bool ShowBoundaryOnlyP(void) {return showboundaryonlyp;}
 
    virtual bool ShowToolTipsP(void) {return showtooltipsp;}
 
    virtual bool ShowWallsP(void) {return showwallsp;}
 
	virtual bool ShowApoplastsP(void) { return showapoplastsp;}
 
    virtual bool ShowApoplastsP(void) { return showapoplastsp;}
 
    virtual bool ShowFluxesP(void) { return showfluxesp; }
 
    virtual bool DynamicCellsP(void) { return dynamicscellsp; }
 
    virtual void FitCanvasToWindow() {};
 
    virtual void FitLeafToCanvas() {};
 
	virtual bool HideCellsP(void) { return hidecellsp; }
 
    virtual bool HideCellsP(void) { return hidecellsp; }
 
    virtual void clear(void) {
 
      QList<QGraphicsItem *> list = canvas.items();
 
      QList<QGraphicsItem *>::Iterator it = list.begin();
 
      for (; it != list.end(); ++it) {
 
	if ( *it )
 
	  delete *it;
 
      }
 
    };
 
    virtual void XMLReadSettings(xmlNode *settings);
 
    virtual double getFluxArrowsize(void) { return 10.;}
 
    
 
    /* void Save(const char *fname, const char *format, int width=640) {
 
      
 
    //cerr << "Initializing Pixmap\n";
 
      
 
    cerr << "Saving to file " << fname << endl;
 
    QPixmap *image=new QPixmap(width, (int) (((double)canvas.height()/
 
    (double)canvas.width())*((double)width)));
 

	
 
    //QPicture *image = new QPicture();
 
      
 
    //cerr << "Done initializing QPixmap image(640, " << (((double)canvas.height()/(double)canvas.width())*640.) << ")\n";
 
    QPainter im(image);
 
    //cerr << "Done initializing image\n";
 
    im.scale((double)width/canvas.width(),(double)width/canvas.width());
 
    canvas.render(&im, QRectF(0,0,canvas.width(),canvas.height()) );
 
    //im.end();      
 
    image->save(QString(fname), format);
 
    }*/
 
    
 

	
 
    void Save(const char *fname, const char *format, int sizex=640, int sizey=480);
 
    void CutSAM(void);
 
	
 
    void Plot(int resize_stride=10);
 

	
 
    virtual void UserMessage(QString message, int timeout = 0) {
 
      timeout = 0; // merely to obviate 'warning unused parameter' message
 
      cerr << message.toAscii().constData() << endl;
 
    }
 
    Mesh &mesh;
 
	
 
 protected:
 
@@ -131,24 +111,24 @@ class MainBase  {
 

	
 
 protected:
 
    bool showcentersp;
 
    bool showmeshp;
 
    bool showbordercellp;
 
    bool shownodenumbersp;
 
    bool showcellnumbersp;
 
    bool showcellsaxesp;
 
    bool showcellstrainp;
 
    bool movieframesp;
 
    bool showboundaryonlyp;
 
    bool showwallsp;
 
	bool showapoplastsp;
 
    bool showapoplastsp;
 
    bool showfluxesp;
 
    bool dynamicscellsp;
 
    bool showtooltipsp;
 
	bool hidecellsp;
 
    bool hidecellsp;
 
};
 

	
 
//#include <qapplication.h>
 
#define TIMESTEP double MainBase::TimeStep(void)
 
#define INIT void MainBase::Init(char *leaffile)
 

	
 
#endif
src/matrix.cpp
Show inline comments
 
@@ -33,38 +33,34 @@ Matrix::Matrix(const Vector &c1, const V
 
  Alloc();
 

	
 
  mat[0][0]=c1.x; mat[0][1]=c2.x; mat[0][2]=c3.x;
 
  mat[1][0]=c1.y; mat[1][1]=c2.y; mat[1][2]=c3.y;
 
  mat[2][0]=c1.z; mat[2][1]=c2.z; mat[2][2]=c3.z;
 

	
 
    
 
}
 

	
 
void Matrix::Alloc(void) {
 

	
 
  // constructor
 
//  mat=(double **)malloc(3*sizeof(double *));
 
//  mat[0]=(double *)malloc(9*sizeof(double));
 
  mat = new double*[3];
 
  mat[0] = new double[9];
 
  for (int i=1;i<3;i++)
 
    mat[i]=mat[i-1]+3;
 
  
 
}
 

	
 
Matrix::~Matrix() {
 
 
 
  // destructor
 
  //free(mat[0]);
 
  //free(mat);
 
  delete[] mat[0];
 
  delete[] mat;
 
}
 

	
 
Matrix::Matrix(void) {
 
  
 
  // constructor
 
  Alloc();
 

	
 
  // clear matrix
 
  for (int i=0;i<9;i++) {
 
    mat[0][i]=0.;
src/mesh.h
Show inline comments
 
@@ -50,148 +50,110 @@ public:
 
	typedef typename C::value_type value_type;
 
	// reimplements push: reject element if it exists already
 
	void push(const value_type &x) {
 
		if (find (queue<T,C>::c.begin(),queue<T,C>::c.end(),x)==queue<T,C>::c.end()) {
 
			queue<T,C>::c.push_back(x);
 
		}
 
	}
 
	void clear(void) {
 
		queue<T,C>::c.clear();
 
	}
 
};
 

	
 
//template<class P> P& deref_ptr<P>( P *obj) { return *obj; }
 
template<class P> P& deref_ptr ( P *obj) { return *obj; }
 

	
 

	
 
class Mesh {
 
	
 
	friend class Cell;
 
	friend class Node;
 
	friend class FigureEditor;
 
	
 
public: 
 
	Mesh(void) {
 
		// Make sure the reserved value is large enough if a cell is added
 
		// in "Divide" when the capacity is insufficient, "cells" might be
 
		// relocated including the current Cell (i.e. the value of *this)
 
		// calling "Mesh::IncreaseCapacityIfNecessary" (from another
 
		// object than Cell, e.g. Mesh) before entering Divide will solve
 
		// this issue (solved now).
 
		cells.reserve(2);
 
		nodes.reserve(500);
 
		
 
		//boundary_polygon = new BoundaryPolygon();
 
		
 
		time = 0.;
 
		plugin = 0;
 
	};
 
	~Mesh(void) {
 
		delete boundary_polygon;
 
		/* if (plugin)
 
			delete plugin;*/
 
	};
 
	
 
	void Clean(void);
 
	//void Plane(int xwidth, int ywidth, int nx, int ny, bool randomP=false);
 
	Cell &EllipticCell(double xc, double yc, double ra, double rb, int nnodes=10, double rotation=0);
 
	Cell &CircularCell(double xc, double yc, double r, int nnodes=10) {
 
		return EllipticCell(xc, yc, r, r, nnodes, 0);
 
	}
 
	Cell &LeafPrimordium(int n, double pet_length);
 
	Cell &LeafPrimordium2(int n);
 
	Cell *RectangularCell(const Vector ll, const Vector ur, double rotation = 0);
 
	void CellFiles(const Vector ll, const Vector ur);
 
	
 
	/*  void GMVoutput(ostream &os, 
 
	 const char *codename=0, const char *codever=0,
 
	 const char *comments=0);*/
 
	//void RandPoints(int npoints);
 
	
 
	inline Cell &getCell(int i) {
 
		if ((unsigned)i<cells.size())
 
			return *cells[i];
 
		else {
 
                        #ifdef QDEBUG
 
                        qDebug() << i << endl;
 
                        qDebug() << "size is " << cells.size() << endl;
 
                        #endif
 
			abort();
 
			//	throw("Index out of range in Mesh::getCell");
 
		}
 
	}
 
	
 
	inline Node &getNode(int i) {
 
		//if (i >= nodes.size() || i < 0) {
 
		//  cerr << "Mesh::getNode: Warning. Index " << i << " out of range.\n";
 
		// }
 
		return *nodes[i];    
 
	}
 
	
 
	//double Diffusion(void);
 
	inline int size(void) {
 
		return cells.size();
 
	}
 
	inline int nnodes(void) {
 
		return nodes.size();
 
	}
 
	//void SortNBLists(void);
 
	
 
	/*template<class Op> void LoopCells(Op f) {
 
	 for (vector<Cell>::iterator i=cells.begin();
 
	 i!=cells.end();
 
	 i++) {
 
	 f(*i); 
 
	 }
 
	 }*/
 
	
 
	/*! \brief Calls function f for all Cells f.
 
	 
 
	 Using this template requires some fiddling with function adaptors bind2nd and mem_fun_ref.
 
	 
 
	 Example usage for calling a member function on each cell:
 
	 
 
	 mesh.LoopCells( bind2nd (mem_fun_ref( &Cell::DrawDiffEdges), &canvas ) );
 
	 
 
	 This calls Cell's member function DrawDiffEdges, taking one
 
	 argument canvas, on all Cell objects in the current Mesh.
 
	 
 
	 */
 

	
 
	template<class Op> void LoopCells(Op f) {
 
		for (vector <Cell *>::iterator i=cells.begin();
 
			 i!=cells.end();
 
			 i++) {
 
			f(**i);
 
		}
 
		//for_each(cells.begin(),cells.end(),f);
 
	}
 
	
 
	template<class Op> void LoopWalls(Op f) {
 
		for (list <Wall *>::iterator i=walls.begin();
 
			 i!=walls.end();
 
			 i++) {
 
			f(**i);
 
		}
 
	}
 
	
 
	// if the amount of cells might increase, during looping, use this template
 
	template<class Op> void LoopCurrentCells(Op f) {
 
		vector<Cell *> current_cells = cells;
 
		for (vector <Cell *>::iterator i=current_cells.begin();
 
			 i!=current_cells.end();
 
			 i++) {
 
			f(**i);
 
			
 
		}
 
		//for_each(cells.begin(),cells.end(),f);
 
	}
 
	
 
	template<class Op> void LoopNodes(Op f) {
 
		for (vector<Node *>::iterator i=nodes.begin();
 
			 i!=nodes.end();
 
			 i++) {
 
			f(**i); 
 
		}
 
	}
 
	
 
	template<class Op> void RandomlyLoopNodes(Op f) {
 
		
 
@@ -247,31 +209,24 @@ public:
 
			if ((*i)->flag_for_divide) {
 
				if ((*i)->division_axis) {
 
					(*i)->DivideOverAxis(*(*i)->division_axis);
 
					delete (*i)->division_axis;
 
					(*i)->division_axis = 0;
 
				} else {
 
					(*i)->Divide();
 
				}
 
				(*i)->flag_for_divide=false;
 
			}
 
		}
 
	}
 
/*	template<class Op1, class Cont> void ExtractFromCells(Op1 f, Cont res) {
 
		for (vector<Cell>::iterator i=cells.begin();
 
			 i!=cells.end();
 
			 i++) {
 
			*(res++) = ( f(*i) );
 
		}
 
	}*/
 
	
 
	// Apply "f" to cell i
 
	// i.e. this is an adapter which allows you to call a function
 
	// operating on Cell on its numeric index index
 
	template<class Op> void cell_index_adapter(Op f,int i) {
 
		f(cells[i]);
 
	}
 
	
 
	double DisplaceNodes(void);
 
	
 
	void BoundingBox(Vector &LowerLeft, Vector &UpperRight);
 
	int NEqs(void) {     int nwalls = walls.size();
 
@@ -326,43 +281,40 @@ public:
 
	void SetBaseArea(void);
 
	int NCells(void) const {
 
		return cells.size();
 
	}
 
	inline int NNodes(void) const {
 
		return nodes.size();
 
	}
 
	void PrintQueue(ostream &os) {
 
		while (!node_insertion_queue.empty()) {
 
			os << node_insertion_queue.front() << endl;
 
			node_insertion_queue.pop();
 
		}
 
		//copy (node_insertion_queue.begin(),node_insertion_queue.end(),ostream_iterator<Edge>(cerr, " "));
 
	}
 
	
 
	void InsertNodes(void) {
 
		// insert the nodes in the insertion queue
 
		while (!node_insertion_queue.empty()) {
 
			
 
			//cerr << node_insertion_queue.front() << endl;
 
			InsertNode(node_insertion_queue.front());
 
			node_insertion_queue.pop();
 
		}
 
		
 
	}
 
	
 
	void Clear(); 
 
	
 
	//  template<class ReactFunction> ReactDiffuse(const double D, ReactFunction& react) {
 
	void ReactDiffuse( double delta_t = 1 );
 
	//void Diffuse(const double D);
 
	double SumChemical(int ch);
 
	void SetChemical(int ch, double value) {
 
		for (vector<Cell *>::iterator c=cells.begin();
 
			 c!=cells.end();
 
			 c++) {
 
			(*c)->chem[ch]=value;
 
		}
 
	}
 
	
 
	// used for interacing with ODE-solvers (e.g. NRCRungeKutta)
 
	void setValues(double x, double *y);
 
	double *getValues(int *neqs);
 
@@ -418,26 +370,24 @@ public:
 
	
 
	void CleanChemicals(const vector<double> &clean_chem);
 
	void CleanTransporters(const vector<double> &clean_transporters);
 
	void RandomizeChemicals(const vector<double> &max_chem, const vector<double> &max_transporters);
 
	inline double getTime(void) const { return time; }
 
	string getTimeHours(void) const; 
 
	inline void setTime(double t) { time = t; }
 
	double CalcProtCellsWalls(int ch) const;  
 
	void SettoInitVals(void);
 
	QVector<qreal> VertexAngles(void);
 
	QVector< QPair<qreal,int> > VertexAnglesValues(void);
 
	void SetSimPlugin(SimPluginInterface *new_plugin) {
 
		/* if (plugin) 
 
			delete plugin;*/
 
		plugin=new_plugin;
 
	}
 
	QString ModelID(void) { return plugin?plugin->ModelID():QString("undefined"); }
 
	void StandardInit(void);	
 

	
 
	Node* findNextBoundaryNode(Node*);
 

	
 
private:
 
	
 
	// Data members
 
	vector<Cell *> cells;
 
	vector<Node *> nodes;
 
@@ -464,21 +414,16 @@ private:
 
	}
 
	
 
	inline Cell *AddCell(Cell *c) {
 
		cells.push_back(c);
 
		shuffled_cells.push_back(c);
 
		//cerr << "Shuffled cell indices:  ";
 
		/*copy(shuffled_cells.begin(),shuffled_cells.end(),ostream_iterator<int>(cerr," "));
 
		 cerr << endl;*/
 
		c->m=this;
 
		return c;
 
	}
 
	
 
	//int Delaunay(void);
 
	void CircumCircle(double x1,double y1,double x2,double y2,double x3,double y3,
 
					  double *xc,double *yc,double *r);
 
	
 
	
 
	// void RenumberCells(void);
 
	
 
};
 
#endif
src/modelcatalogue.cpp
Show inline comments
 
@@ -95,27 +95,24 @@ void ModelCatalogue::LoadPlugin(const ch
 
    pluginDir.cdUp(); 
 
    pluginDir.cdUp(); 
 
  } 
 
  //plugin_filters << "*.dylib";
 
#endif
 
  plugin_filters << model;
 
  pluginDir.setNameFilters(plugin_filters);
 
	
 
  if (!pluginDir.cd("models")) {
 
    MyWarning::error("Directory 'models' not found!");
 
  }
 
	
 
	
 
  //QVector<SimPluginInterface *> plugins;
 
	
 
  QStringList modelnames=pluginDir.entryList(QDir::Files);
 
  if (modelnames.empty()) {
 
    MyWarning::error("Model %s not found - hint: do not include path in filename.",model);
 
  }
 
  foreach (QString fileName, modelnames){ 
 
    QPluginLoader loader(pluginDir.absoluteFilePath(fileName)); 
 
		
 
    if (SimPluginInterface *plugin = 
 
	qobject_cast<SimPluginInterface *>(loader.instance())) {
 
      models.append(plugin); 
 
      //MyWarning::warning("Successfully loaded model %s",fileName.toStdString().c_str());
 
    } else {
 
@@ -151,15 +148,13 @@ void ModelCatalogue::InstallModel(SimPlu
 
	
 
  // make sure both main and plugin use the same static datamembers (ncells, nchems...)
 
  plugin->SetCellsStaticDatamembers(CellBase::GetStaticDataMemberPointer());
 
	
 
  mesh->SetSimPlugin(plugin);
 
  Cell::SetNChem(plugin->NChem());
 
  plugin->SetParameters(&par);
 

	
 
  if (mainwin) {
 
    mainwin->RefreshInfoBar();
 
    mainwin->Init(0);
 
  }
 
  //	mesh->StandardInit();
 
	
 
}
src/node.cpp
Show inline comments
 
@@ -176,26 +176,24 @@ void Node::DrawOwners(QGraphicsScene *c)
 

	
 

	
 
QVector<qreal> Node::NeighbourAngles(void) {
 
	
 
	QVector<qreal> angles;
 
	for (list<Neighbor>::iterator i=owners.begin();
 
		 i!=owners.end();
 
		 i++) {
 
		
 
		Vector v1 = (*this - *i->nb1).Normalised();
 
		Vector v2 = (*this - *i->nb2).Normalised();	
 
	
 
		//angles.push_back(atan2(v2.y,v2.x)-atan2(v1.y,v1.x));
 
		//angles.push_back(atan2(v2.y,v2.x)-atan2(v1.y,v1.x));
 
		double angle = v1.SignedAngle(v2);
 
		if (angle<0) {
 
			//cerr << "Changing sign of angle " << angle << endl;
 
			angle = angle + 2*Pi;
 
		}
 
		angles.push_back(angle);
 
		
 
		//cerr << "Cell " << i->cell->Index() << ": " <<  v1 << " and " << v2 << ": angle = " << angles.back() << ", " << v1.Angle(v2) << endl;
 
		
 
	}
 
	
 
	double sum=0.;
src/node.h
Show inline comments
 
@@ -116,29 +116,27 @@ public:
 
  inline bool BoundaryP(void) const { return boundary; }
 

	
 
  inline void SetBoundary(void) { boundary = true; }
 

	
 
  inline void UnsetBoundary(void) { boundary = false; }
 

	
 
  inline void SetSAM(void) { sam = true; }
 

	
 
  inline void toggleBoundary(void) {
 
    boundary = !boundary;
 
  }
 
  
 
  //void Displace(void);
 

	
 
  Cell &getCell(const Neighbor &i);
 
  
 
  //Node &getNode(int i);
 
  ostream &print(ostream &os) const;
 
  void XMLAdd(xmlNodePtr nodes_node) const;
 
  
 
#ifdef QTGRAPHICS
 
  void Draw(QGraphicsScene &c, QColor color=QColor("black"), int size = 10) const;
 
  void DrawIndex(QGraphicsScene *c) const;
 
  void DrawOwners(QGraphicsScene *c) const;
 
#endif
 
  
 
  // temporary function for easier debugging
 
  inline int CellsSize(void) const {
 
    return owners.size();
 
@@ -155,59 +153,40 @@ public:
 
    return fixed;
 
  }
 
  inline void Unfix(void) {
 
    fixed=false;
 
  }
 
  inline void MarkDead(void) {
 
    dead=true;
 
  }
 
  inline bool DeadP(void) {
 
    return dead;
 
  }
 

	
 
  /*void UpdateAfterNodeRemoved(int n) {
 
    for (list<Neighbor>::iterator i=owners.begin();
 
    i!=owners.end();
 
    i++) {
 
    if (i->nb1>=n) i->nb1--;
 
    if (i->nb2>=n) i->nb2--;
 
    }
 
    }
 
 
 
    void UpdateAfterCellRemoved(int n) {
 
    for (list<Neighbor>::iterator i=owners.begin();
 
    i!=owners.end();
 
    i++) {
 
    if (i->cell>=n) i->cell--;
 
    }
 
    }
 
  */
 
  
 
  inline void Mark(void) {
 
    marked=true;
 
  }
 
  inline void Unmark(void) {
 
    marked=false;
 
  }
 
  inline bool Marked(void) const {
 
    return marked;
 
  }
 
  
 
  inline void setPos( Vector p ) { 
 
    x = p.x;
 
    y = p.y;
 
    z = p.z;
 
  }
 
  inline bool SamP(void) const { return sam; }
 
  //enum boundary_type {NoBoundary, Noflux, SourceSink, SAM};
 

	
 
  //!\brief Calculate angles with neighboring vertices
 
  //! Sum of angles should be 2*Pi
 
  QVector<qreal> NeighbourAngles(void);
 
private:
 
  
 
  // "owners" lists the cells to which this cell belong
 
  // and the two neighboring nodes relative to each cell
 
  list< Neighbor > owners;
 
  
 
  Mesh *m;
 
  int index;
src/nodeitem.cpp
Show inline comments
 
@@ -45,47 +45,28 @@ NodeItem::NodeItem( Node *n, QGraphicsSc
 
void NodeItem::userMove(double dx, double dy) {
 
  QGraphicsItem::moveBy( dx, dy );
 
  
 
  class_cast<Node *>(obj)->x += (dx/Cell::Magnification());
 
  class_cast<Node *>(obj)->y += (dy/Cell::Magnification());
 
}
 

	
 

	
 

	
 
void NodeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
 
{
 

	
 
  // from Qt4.2 example: "elastic nodes"
 
  //painter->setPen(Qt::NoPen);
 
  //painter->setBrush(Qt::darkGray);
 
  //painter->drawEllipse(-70, -70, 200, 200);
 
  
 
  /* QRadialGradient gradient(-30, -30, 100);
 
     
 
  if (option->state & QStyle::State_Sunken) {
 
  gradient.setCenter(30, 30);
 
  gradient.setFocalPoint(30, 30);
 
  gradient.setColorAt(1, QColor(Qt::yellow).light(120));
 
  gradient.setColorAt(0, QColor(Qt::darkYellow).light(120));
 
  } else {
 
  gradient.setColorAt(0, Qt::yellow);
 
  gradient.setColorAt(1, Qt::darkYellow);
 
  }
 
  
 
  painter->setBrush(gradient); */
 
  option = NULL; // use assignment merely to obviate compilation warning
 
  
 
  painter->setBrush(brush);
 
  painter->setPen(Qt::NoPen);
 
  // const static double mag=20.;
 
  painter->drawEllipse(ellipsesize);
 
}
 

	
 

	
 
QPainterPath NodeItem::shape() const
 
{
 
    QPainterPath path;
 
    path.addEllipse(ellipsesize);
 
    return path;
 
}
 

	
 
QRectF NodeItem::boundingRect() const
src/nodeset.h
Show inline comments
 
@@ -22,45 +22,39 @@
 
 */
 

	
 

	
 
#ifndef _NODESET_H_
 
#define _NODESET_H_
 

	
 
#include <algorithm>
 
#include <numeric>
 
#include <list>
 
#include <iterator>
 
#include "node.h"
 

	
 
//class xmlNode;
 

	
 
class NodeSet : public list<Node *> {
 
  
 
 public:
 
  NodeSet(void) {
 
    done = false;
 
  }
 
  
 
  inline bool DoneP(void) { return done; }
 
  inline void ResetDone(void) { done = false; }
 
  
 
  void AddNode(Node * n) {
 
    push_back(n);
 
    n->node_set = this;
 
  }
 

	
 
  //  list <Node *? getNodes(void) {
 
  //  return set;
 
  //}
 

	
 
  list <Cell *> getCells(void) {
 
    
 
    list<Cell *> cellset;
 
    
 
    for (list<Node *>::const_iterator i=begin();
 
	 i!=end();
 
	 i++) {
 
      transform ( (*i)->owners.begin(), (*i)->owners.end(), back_inserter( cellset ) , mem_fun_ref ( &Neighbor::getCell ));
 
    }
 
    
 
    cellset.sort();
 
    
 
@@ -147,28 +141,26 @@ class NodeSet : public list<Node *> {
 
      
 
		
 
    } else {
 
      // REJECT
 
      
 
      // Move the set's nodes back to their original position
 
      for ( list<Node *>::iterator n = begin();
 
	    n!= end();
 
	    ++n ) {
 
	
 
	(*n)->x-=rx;
 
	(*n)->y-=ry;
 
	// (*n)->z -= rz;
 
	  }
 
      
 
      
 
    }
 
  }
 
  
 
  void XMLAdd(xmlNode *root) const;
 
  void XMLRead(xmlNode *root, Mesh *m);
 
 private:
 
  // list<Node *> set;
 
  bool done;
 
};
 

	
 
ostream &operator<<(ostream &os, const NodeSet &ns);
 
#endif
src/output.cpp
Show inline comments
 
@@ -15,25 +15,24 @@
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
#include <string>
 
#include <stdio.h>
 
#include <string.h>
 
#include <stdlib.h>
 
#include <errno.h>
 
//#include <unistd.h>
 
#include <sys/types.h>
 
#include <sys/stat.h>
 
#include "warning.h"
 
#include "parameter.h"
 
#include "output.h"
 
 
 
#include <QDir>
 
#include <QFileInfo>
 
 
static const std::string _module_id("$Id$");
 
 
@@ -76,49 +75,24 @@ int YesNoP(const char *message) {
 
  while (strcmp(answer,"y") && strcmp(answer,"n")) {
 
    fprintf(stderr,"\n\bPlease answer 'y' or 'n'. ");
 
    fflush(stderr);
 
    scanf("%s",answer);
 
  }
 
  
 
  if (!strcmp(answer,"y")) return TRUE;
 
  
 
  return FALSE;
 
    
 
}
 
 
/* //FILE *OpenWriteFile(char *filename) 
 
// {
 
//   FILE *fp;
 
//   fprintf(stderr,"Opening %s for writing\n",filename);
 
	
 
//   if((OpenFileAndCheckExistance(&fp,filename,"r"))==TRUE) {
 
// 	if (!YesNoP("File exists, overwrite?")) {
 
// 	  fprintf(stderr," Could not open file %s for writing, exiting... \n"
 
// 			  ,filename);
 
// 	  exit(0);
 
// 	}
 
//   }
 
  
 
//   if (fp!=NULL) // file existed, but user wants to overwrite
 
// 	fclose(fp);
 
  
 
//   if ((fp=fopen(filename,"w"))==NULL) {
 
// 	fprintf(stderr," Could not open file %s for writing, exiting... \n"
 
// 			,filename);
 
// 	exit(0);
 
//   }
 
	
 
//   return fp;
 
// }
 
*/
 
 
FILE *OpenWriteFile(const char *filename) 
 
{
 
 
  char fname[FNAMESIZE];
 
 
  FILE *fp;
 
 
  fprintf(stderr,"Opening %s for writing\n",filename);
 
	
 
  if(FileExistsP(filename)==TRUE) {
 
  
 
@@ -142,73 +116,24 @@ FILE *OpenWriteFile(const char *filename
 
  
 
  if ((fp=fopen(fname,"w"))==NULL) {
 
    char *message=(char *)malloc(2000*sizeof(char));
 
    sprintf(message," Could not open file %s for writing: "
 
	    ,fname);
 
    perror("");
 
    throw(message);
 
  }
 
	
 
  return fp;
 
}
 
 
/*FILE *OpenGZippedWriteFile(const char *filename) 
 
{
 
 
  // Open file that is zipped while it is written
 
  // uses a pipe
 
    
 
  char fname[FNAMESIZE];
 
  char gzname[FNAMESIZE];
 
 
  FILE *fp;
 
  extern Parameter par;
 
 
  // step 1, add ".gz" to the filename
 
  sprintf(gzname, "%s.gz", filename);
 
  
 
  // and check whether it already exists
 
  fprintf(stderr,"Opening %s for writing\n",gzname);
 
	
 
  if(FileExistsP(gzname)==TRUE) {
 
  
 
    if (par.interactive) {
 
      if (!YesNoP("File exists, overwrite?")) {
 
	fprintf(stderr," Could not open file %s for writing, exiting... \n"
 
		,gzname);
 
	exit(0);
 
      }
 
    } else {
 
      // Rename old file 
 
      snprintf(fname, FNAMESIZE-1, "%s~",gzname);
 
      rename(gzname, fname);
 
      
 
    }
 
  }
 
  
 
  //  strncpy(fname, gzname, FNAMESIZE-1);
 
  char *command=new char[20+sizeof(gzname)];
 
  sprintf(command, "gzip -c > %s", gzname);
 
  
 
  if ((fp=popen(command,"w"))==NULL) {
 
    fprintf(stderr," Could not open file %s for writing: "
 
	    ,fname);
 
    perror("");
 
    exit(-1);
 
  }
 
	
 
  delete[] command;
 
  return fp;
 
}
 
*/
 
 
FILE *OpenReadFile(const char *filename) 
 
{
 
  FILE *fp;
 
 
  fprintf(stderr,"Opening %s for reading\n",filename);
 
  
 
  if((OpenFileAndCheckExistance(&fp,filename,"r"))==FALSE) {	
 
    char *message=(char *)malloc(2000*sizeof(char));
 
    sprintf(message," File %s not found or empty, exiting... \n" ,filename);
 
    throw(message);
 
  }
 
@@ -322,35 +247,34 @@ char *Chext(char *filename) {
 
  } else {
 
   
 
    /* . found */
 
    result=(char *)malloc((i+1)*sizeof(char));
 
    strncpy(result, filename, i);
 
  }
 
  return result;
 
  
 
  
 
}
 
 
void MakeDir(const char *dirname) {
 
  
 
  cerr << "Entering MakeDir for name " << dirname << "\n";
 
 
#ifdef QTGRAPHICS
 
  QFileInfo file_info(dirname);
 
  
 
  //check for existance
 
  if (file_info.exists()) {
 
    
 
    if (file_info.isDir()) {
 
      // OK 
 
      cerr << "Using existing directory " << dirname << " for data storage.\n";
 
      cerr << "Using existing directory " << dirname << " for data storage." << endl;
 
      return;
 
    } else {
 
      char *message = new char[MESS_BUF_SIZE+1];
 
      snprintf(message, MESS_BUF_SIZE, "%s is not a directory", dirname);
 
      cerr << message << endl;
 
      throw(message);
 
    }
 
    
 
  }
 
 
  // make directory
 
  QDir dir;
 
@@ -406,58 +330,12 @@ void MakeDir(const char *dirname) {
 
      perror(message);
 
      exit(1);
 
      
 
    }
 
  
 
 
 
  }
 
 
#endif
 
}
 
 
/*bool CanWeWriteP(char *filename) {
 
 
  // check for the existance of file "filename"
 
   // if it exists, ask the user whether we may overwrite it
 
   //false: do not overwrite. true: do overwrite 
 
   
 
  
 
  char message[MESS_BUF_SIZE];
 
  char fname[FNAMESIZE];
 
 
  extern const Parameter par;
 
 
  int status;
 
  status=access(filename, F_OK);
 
  if (status < 0) {// file does not exist, or something else is wrong      
 
    // check error code
 
    if (errno!=ENOENT) {
 
	
 
      // another error occured 
 
      snprintf(message, MESS_BUF_SIZE, "Error checking for existance of %s",filename);
 
      perror(message);	      
 
      exit(1);
 
    }
 
      
 
  } else {
 
      
 
    // file exists, ask for permission to overwrite if interactive
 
    if (par.interactive) {
 
      snprintf(message, MESS_BUF_SIZE, "File %s exists. Overwrite? ",filename);
 
      if (!YesNoP(message))
 
	return false;
 
      else 
 
	return true;
 
    } else {
 
      // Rename old file 
 
      snprintf(fname, FNAMESIZE-1, "%s~",filename);
 
      rename(filename, fname);
 
    }
 
    
 
    return true;
 
  }
 
    
 
  // file does not exist, or user permits overwriting
 
  return true;
 
    
 
}*/
src/output.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
 
#ifndef _OUTPUT_H_
 
#define _OUTPUT_H_
 
 
#ifdef __cplusplus
 
extern "C" {
 
#endif
 
 
int OpenFileAndCheckExistance(FILE **fp,const char *fname,char *ftype);
 
int YesNoP(const char *message);
 
FILE *OpenWriteFile(const char *filename);
 
FILE *OpenGZippedWriteFile(const char *filename);
 
FILE *OpenReadFile(const char *filename);
 
char *ReadLine(FILE *fp);
 
void CheckFile(FILE *fp);
 
int FileExistsP(const char *fname);
 
char *Chext(char *filename);
 
void MakeDir(const char *dirname);
 
bool CanWeWriteP(char *filename);
 
 
#ifdef __cplusplus
 
}
 
#endif
 
 
 
#define MESS_BUF_SIZE 160
 
#ifndef FALSE
 
#define FALSE 0
 
#define TRUE 1
 
#endif
 
 
#endif
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _OUTPUT_H_
 
#define _OUTPUT_H_
 

	
 
#ifdef __cplusplus
 
extern "C" {
 
#endif
 

	
 
int OpenFileAndCheckExistance(FILE **fp,const char *fname,char *ftype);
 
int YesNoP(const char *message);
 
FILE *OpenWriteFile(const char *filename);
 
FILE *OpenGZippedWriteFile(const char *filename);
 
FILE *OpenReadFile(const char *filename);
 
char *ReadLine(FILE *fp);
 
void CheckFile(FILE *fp);
 
int FileExistsP(const char *fname);
 
char *Chext(char *filename);
 
void MakeDir(const char *dirname);
 
bool CanWeWriteP(char *filename);
 

	
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 

	
 
#define MESS_BUF_SIZE 160
 
#ifndef FALSE
 
#define FALSE 0
 
#define TRUE 1
 
#endif
 

	
 
#endif
src/parse.cpp
Show inline comments
 
@@ -62,26 +62,25 @@ char *ParsePar(FILE *fp, char *parameter
 
 
  value=strdup(token);
 
  free(line);
 
  
 
  return value;
 
      
 
}
 
 
 
int igetpar(FILE *fp,char *parameter, bool wrapflag) {
 
  
 
  // overloaded compatibility function. Doesn't need default parameter
 
  // default = 0
 
  
 
 
  return igetpar(fp, parameter, 0, wrapflag);
 
}
 
 
int igetpar(FILE *fp,char *parameter, int default_val, bool wrapflag) 
 
{
 
  char *token;
 
  int value;
 
  
 
  /* Get token representing the value */
 
  token=ParsePar(fp,parameter, wrapflag);
 
 
  if (token==0) {
 
@@ -93,28 +92,25 @@ int igetpar(FILE *fp,char *parameter, in
 
  sscanf(token,"%d",&value);
 
  fprintf(stderr, "%d]\n",value);
 
  
 
  free(token);
 
 
  return value;
 
  
 
}
 
 
float fgetpar(FILE *fp,char *parameter, bool wrapflag) {
 
   
 
  // overloaded compatibility function. Doesn't need default parameter
 
  // default = 0
 
  
 
  return fgetpar(fp, parameter, 0., wrapflag);
 
 
}
 
 
float fgetpar(FILE *fp, char *parameter, double default_val, bool wrapflag) 
 
{
 
  char *token;
 
  float value;
 
 
  /* Get token representing the value */
 
  token=ParsePar(fp,parameter, wrapflag);
 
 
  if (token==0) {
 
    /* default value */
 
@@ -287,26 +283,24 @@ bool bgetpar(FILE *fp, char *parameter, 
 
char *SearchToken(FILE *fp, char *token,bool wrapflag) 
 
{
 
  /* This function returns the next line of FILE *fp that contains
 
     the string stored in the null terminated string token */
 
 
  /* remember to free the memory allocated for line */
 
  
 
  unsigned int len;
 
  char *line;
 
  int wrapped=false;
 
  long initial_position;
 
  
 
  /*  rewind(fp); */
 
 
  char *tokenplusspace = (char *)malloc( (strlen(token)+3)*sizeof(char));
 
  strcpy(tokenplusspace, token);
 
  strcat(tokenplusspace," ");
 
  
 
  initial_position=ftell(fp);
 
  if (ferror(fp)) /* error occured */
 
    {
 
      error("%s",strerror(errno));
 
    }
 
 
 
 
  if (feof(fp)) {
src/parse.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
 
#ifndef _PARSE_H_
 
#define _PARSE_H_
 
 
char *ParsePar(FILE *fp, char *parameter, bool wrapflag);
 
int igetpar(FILE *fp,char *parameter, bool wrapflag);
 
int igetpar(FILE *fp,char *parameter, int default_val, bool wrapflag);
 
float fgetpar(FILE *fp,char *parameter, bool wrapflag);
 
float fgetpar(FILE *fp,char *parameter, double default_val, bool wrapflag);
 
 
/* Get a list of n comma separated doubles */
 
double *dgetparlist(FILE *fp,char *parameter, int n, bool wrapflag);
 
char *sgetpar(FILE *fp,char *parameter, bool wrapflag);
 
char *sgetpar(FILE *fp,char *parameter,const char *default_val, bool wrapflag);
 
bool bgetpar(FILE *fp, char *parameter, bool wrapflag);
 
bool bgetpar(FILE *fp, char *parameter, int default_val, bool wrapflag);
 
char *SearchToken(FILE *fp, char *token, bool wrapflag);
 
int TokenInLineP(char *line,char *token);
 
void SkipToken(FILE *fp,char *token, bool wrapflag);
 
void SkipLine(FILE *fp);
 
char *bool_str(bool bool_var);
 
 
#endif
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _PARSE_H_
 
#define _PARSE_H_
 

	
 
char *ParsePar(FILE *fp, char *parameter, bool wrapflag);
 
int igetpar(FILE *fp,char *parameter, bool wrapflag);
 
int igetpar(FILE *fp,char *parameter, int default_val, bool wrapflag);
 
float fgetpar(FILE *fp,char *parameter, bool wrapflag);
 
float fgetpar(FILE *fp,char *parameter, double default_val, bool wrapflag);
 

	
 
/* Get a list of n comma separated doubles */
 
double *dgetparlist(FILE *fp,char *parameter, int n, bool wrapflag);
 
char *sgetpar(FILE *fp,char *parameter, bool wrapflag);
 
char *sgetpar(FILE *fp,char *parameter,const char *default_val, bool wrapflag);
 
bool bgetpar(FILE *fp, char *parameter, bool wrapflag);
 
bool bgetpar(FILE *fp, char *parameter, int default_val, bool wrapflag);
 
char *SearchToken(FILE *fp, char *token, bool wrapflag);
 
int TokenInLineP(char *line,char *token);
 
void SkipToken(FILE *fp,char *token, bool wrapflag);
 
void SkipLine(FILE *fp);
 
char *bool_str(bool bool_var);
 

	
 
#endif
src/random.cpp
Show inline comments
 
@@ -132,33 +132,18 @@ int RandomCounter(void) {
 
**/
 
 
int Randomize(void) {
 
  
 
  // Set the seed according to the local time
 
  struct timeb t;
 
  int seed;
 
 
  ftime(&t);
 
  
 
  seed=abs((int)((t.time*t.millitm)%655337));
 
  Seed(seed);
 
  fprintf(stderr,"Random seed is %d\n",seed);
 
#ifdef QDEBUG
 
  qdebug() << "Random seed is " << seed << endl;
 
#endif
 
  return seed;
 
}
 
 
/** TESTING random generator 
 
#include <vector>
 
#include <fstream>
 
int main(void) {
 
  
 
  MyUrand r(-1);
 
  
 
  vector<int> bucket(100);
 
  for (int i = 0; i<1000000 ; i++) {
 
    bucket[r(100)]++;
 
  }
 
  ofstream out("randomtest.dat");
 
  for (int i = 0; i<=100; i++) {
 
    out << i << " " << bucket[i] << endl;
 
  }
 
}
 
***/
src/random.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
 
#ifndef _RANDOM_H_
 
#define _RANDOM_H_
 
 
#define MBIG 1000000000
 
#define MSEED 161803398
 
#define MZ 0
 
#define FAC (1.0/MBIG)
 
 
double RANDOM();
 
int Seed(int seed);
 
long RandomNumber(long max);
 
void AskSeed();
 
int Randomize(void);
 
int RandomCounter(void);
 
 
 
 
// Class MyUrand, so we can pass the random generator to STL's random_shuffle,
 
// and get identical simulations for a given random seed.
 
class MyUrand {
 
 
 
  long n;
 
 public:
 
  MyUrand(long nn) {
 
    n=nn;
 
  }
 
  MyUrand(void){};
 
 
 
  void seed(long s) {
 
    Seed(s);
 
  }
 
  
 
  long operator()(long nn) { return RandomNumber(nn)-1; }
 
  long operator()(void) { return RandomNumber(n); }
 
};
 
 
 
 
 
 
 
#endif
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _RANDOM_H_
 
#define _RANDOM_H_
 

	
 
#define MBIG 1000000000
 
#define MSEED 161803398
 
#define MZ 0
 
#define FAC (1.0/MBIG)
 

	
 
double RANDOM();
 
int Seed(int seed);
 
long RandomNumber(long max);
 
void AskSeed();
 
int Randomize(void);
 
int RandomCounter(void);
 

	
 

	
 

	
 
// Class MyUrand, so we can pass the random generator to STL's random_shuffle,
 
// and get identical simulations for a given random seed.
 
class MyUrand {
 
 
 
  long n;
 
 public:
 
  MyUrand(long nn) {
 
    n=nn;
 
  }
 
  MyUrand(void){};
 
 
 
  void seed(long s) {
 
    Seed(s);
 
  }
 
  
 
  long operator()(long nn) { return RandomNumber(nn)-1; }
 
  long operator()(void) { return RandomNumber(n); }
 
};
 

	
 

	
 

	
 

	
 

	
 

	
 
#endif
src/sqr.h
Show inline comments
 
@@ -17,31 +17,24 @@
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  From "Numerical recipes in C"
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#ifndef _SQR_H_
 
#define _SQR_H_
 

	
 
/* static float sqrarg;
 
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
 

	
 
static double dsqrarg;
 
#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)
 
*/
 

	
 

	
 
// redefine these macros as inline functions, to prevent scary
 
// behavior.  (According to compiler warnings, the above macros from
 
// Numerical Recipes in C are officially undefined...)
 
//
 
// However, they seem to work, but it seems safer to redefine them.
 
// Inline functions will behave like macros anyhow.
 
inline double DSQR( double a ) {
 
  
 
  if (a == 0.0) {
 
    return 0.0;
 
  } else {
src/vector.h
Show inline comments
 
@@ -109,25 +109,24 @@ public:
 
    
 
    return *this;
 
    
 
  }
 
  
 
  Vector operator/(const double divisor) const; // division by a double
 
  Vector operator*(const double multiplier) const; // multiply by a scalar (double)
 
  Vector &operator/=(const double divisor);
 
  Vector &operator*=(const double multiplier);
 
  Vector operator*(const Vector &v) const; // cross product
 
  bool operator==(const Vector &v) const; // comparison
 
  bool operator< (const Vector &v) const; // order x,y,z
 
  //double Norm(void) const; // gives the "norm" (| v |) of v
 
  inline double Norm(void) const {
 
  
 
    return sqrt(DSQR(x)+DSQR(y)+DSQR(z));
 
    
 
  }
 

	
 
  // Quick and dirty Norm (i.e. Manhattan distance)
 
  // (e.g. useful if we want to see if the vec is (0,0,0);
 
  inline double ManhattanNorm(void) const {
 
    return x+y+z;
 
  }
 
  
src/vleafmodel.h
Show inline comments
 
/*
 
 *  vleafmodel.h
 
 *  mymodel
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  Created by Roeland Merks on 08-06-10.
 
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#ifndef _VLEAFMODEL_H_
 
#define _VLEAFMODEL_H_
 

	
 
#include <QObject>
 
#include <QtGui>
 
#include <fstream>
 
#include "simplugin.h"
 

	
 
#include "parameter.h"
 

	
 
#include "wallbase.h"
 
#include "cellbase.h"
 
#include "mymodel.h"
 
#include "flux_function.h"
 

	
 
#endif
src/wall.cpp
Show inline comments
 
@@ -40,31 +40,24 @@ bool Wall::CorrectWall( void ) {
 
	// collect all cells to which my nodes are connected on one list
 
	list<CellBase *> owners;
 
	transform(n1->owners.begin(),n1->owners.end(), back_inserter(owners), mem_fun_ref(&Neighbor::getCell));
 
	transform(n2->owners.begin(),n2->owners.end(), back_inserter(owners), mem_fun_ref(&Neighbor::getCell));
 
	
 
	// get the list of duplicates
 
	list<CellBase *> wall_owners;
 
	owners.sort();
 
	//transform(owners.begin(), owners.end(), ostream_iterator<int>(cerr, ", "), mem_fun(&Cell::Index));
 
	duplicates_copy( owners.begin(), owners.end(), back_inserter(wall_owners) );
 
	
 
	// duplicates are the cells to which the Wall belongs
 
	/* cerr << "Wall belongs to Cells: ";
 
     transform(wall_owners.begin(), wall_owners.end(), ostream_iterator<int>(cerr, ", "), mem_fun(&Cell::Index));
 
	 cerr << endl;
 
	 */
 
	
 
	//list<Cell *>::iterator f = adjacent_find (++e,owners.end());
 
	
 
	// For the first division, wall finds three "owners", including the boundary_polygon.
 
	// Remove that one from the list.
 
	//cerr << "wall_owners.size() = " << wall_owners.size() << endl;
 
	if (wall_owners.size() == 3 && nwalls==1 /* bug-fix 22/10/2007; confine this condition to first division only */) {
 
		
 
	        #ifdef QDEBUG
 
	        qDebug() << "nwalls = " << nwalls << endl;
 
		#endif
 
		// special case for first cleavage
 
		
 
		// find boundary polygon in the wall owners list
 
		list<CellBase *>::iterator bpit = find_if (
 
@@ -205,27 +198,24 @@ void Wall::ShowStructure(QGraphicsScene 
 
	QGraphicsSimpleTextItem *text1 = new QGraphicsSimpleTextItem( QString("%1").arg(c2->Index()),0,c);
 
	QGraphicsSimpleTextItem *text2 = new QGraphicsSimpleTextItem( QString("%1").arg(c1->Index()),0,c);
 
    
 
	text1 -> setPos( textpos1.x, textpos1.y );
 
	text2 -> setPos( textpos2.x, textpos2.y );
 
	text1->setZValue(20); text2->setZValue(20);
 
	
 
	text1->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
	text2->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
    
 
	text1->setPen ( QColor(par.textcolor) );
 
	text2->setPen ( text1->pen() );
 
    
 
	//text1->setTextFlags(Qt::AlignCenter);
 
	//text2->setTextFlags(Qt::AlignCenter);
 
	text1->show(); text2->show();
 
	
 
}
 
string Wall::WallTypetoStr(const WallType &wt) const {
 
	
 
	if (wt == Normal) {
 
		return string("normal");
 
	}
 
	
 
	if (wt == AuxSource) {
 
		return string("aux_source");
 
	}
src/wallbase.cpp
Show inline comments
 
@@ -69,25 +69,24 @@ WallBase::WallBase(Node *sn1, Node *sn2,
 
	
 
	transporters1 = new double[CellBase::NChem()];
 
	transporters2 = new double[CellBase::NChem()];
 
	new_transporters1 = new double[CellBase::NChem()];
 
	new_transporters2 = new double[CellBase::NChem()];
 
	
 
	for (int i=0;i<CellBase::NChem();i++) {
 
		transporters1[i] = transporters2[i] = new_transporters1[i] = new_transporters2[i] = 0.;
 
	}
 
	
 
	apoplast = new double[CellBase::NChem()]; // not yet in use.
 
    
 
	//length = 0;
 
	SetLength();
 
	
 
	// to visualize flux through WallBase
 
	viz_flux=0;
 
	dead = false;
 
	wall_type = Normal;
 
	wall_index = nwalls++;
 
	
 
}
 

	
 
void WallBase::CopyWallContents(const WallBase &src) {
 
	
 
@@ -161,28 +160,24 @@ void WallBase::SwapWallContents(WallBase
 
	wall_type = tmp_wall_type;
 
	
 
}
 

	
 
bool WallBase::SAM_P(void) { 
 
	
 
	return N1()->sam || N2()->sam; 
 
	
 
}  
 

	
 
#include <fstream>
 

	
 
/* double WallBase::Length(void){ 
 
 return (*n2 - *n1).Norm();
 
 }*/
 

	
 
void WallBase::SetLength(void) {
 
	
 
	//static bool show_nodes = true;
 
	
 
	//double old_length = length;
 
	// Step 1: find the path of nodes leading along the WallBase.
 
	// A WallBase often represents a curved cell wall: we want the total
 
	// length _along_ the wall here...
 
	
 
	// Locate first and second nodes of the edge in Cell's list of nodes
 
	list<Node *>::const_iterator first_node_edge = find(c1->nodes.begin(), c1->nodes.end(), n1);
 
	list<Node *>::const_iterator second_node_edge_plus_1 = ++find(c1->nodes.begin(), c1->nodes.end(), n2);
 
@@ -194,87 +189,58 @@ void WallBase::SetLength(void) {
 
	
 
	
 
	length = 0.;
 
    
 
	// Now, walk to the second node of the edge in the list of nodes
 
	stringstream deb_str;
 
	
 
	for (list<Node *>::const_iterator n=
 
		 (++first_node_edge==c1->nodes.end()?c1->nodes.begin():first_node_edge);
 
		 n!=second_node_edge_plus_1;
 
		 (++n == c1->nodes.end()) ? (n=c1->nodes.begin()):n  ) {
 
		
 
		/* if (n==c1->nodes.end()) { 
 
		 
 
		 n=c1->nodes.begin(); // wrap around
 
		 }*/
 
		
 
		list<Node *>::const_iterator prev_n = n; 
 
		if (prev_n==c1->nodes.begin()) prev_n=c1->nodes.end();
 
		--prev_n;
 
		
 
		//cerr << "Node: " << (Vector)(**n) << endl;
 
		
 
		// Note that Node derives from a Vector, so we can do vector calculus as defined in vector.h 
 
		
 
		
 
		deb_str << "[ " << (*prev_n)->index << " to " << (*n)->index << "]";
 
		
 
		length += (*(*prev_n) - *(*n)).Norm(); 
 
		
 
	}
 
	
 
	/*  if (length > 100) {
 
	 ostringstream warn;
 
	 warn << "Strange, length is " << length << "...: " << deb_str.str() << endl;
 
	 warn << "Strangeness in WallBase: " << *this << endl << endl << deb_str.str() << endl;
 
	 MyWarning::warning (warn.str().c_str());
 
	 }*/
 
	
 
	//cerr << deb_str .str() << ", length is " << length << endl;
 
	//of << length << " " << ((*n2)-(*n1)).Norm() << endl;
 
	
 
	
 
}
 

	
 
void WallBase::CorrectTransporters(double orig_length) {
 
	
 
	double length_factor = length / orig_length;
 
	// cerr << "[ lf = " << length_factor << "]";
 
	//cerr << "Correcting amount of transporters on WallBase "  << *this << ", length factor is "  << orig_length << " / " << length << endl;
 

	
 
	for (int ch=0;ch<CellBase::NChem();ch++) {
 
		transporters1[ch] *= length_factor;
 
		transporters2[ch] *= length_factor;
 
		new_transporters1[ch] *= length_factor;
 
		new_transporters2[ch] *= length_factor;
 
	}
 
	
 
}
 

	
 

	
 
Vector WallBase::VizFlux(void) {
 
	return viz_flux * ( (*n2) - (*n1) ).Normalised().Perp2D();    
 
	//return transporters1[1] * ( (*n2) - (*n1) ).Normalised().Perp2D();    
 
}
 

	
 
/* TransportFunction::TransportFunction( void ) {  
 
	
 
	//chem_change_c1 = new double[Cell::NChem()];
 
	//chem_change_c2 = new double[Cell::NChem()];
 
	
 
	//for (int i=0;i<Cell::NChem();i++) {
 
	// chem_change_c1[i] = chem_change_c2[i] = 0.;
 
	//}
 
}*/
 

	
 

	
 
void WallBase::SetTransToNewTrans( void ){ 
 
	for (int i=0;i<CellBase::NChem();i++) { 
 
		transporters1[i] = new_transporters1[i]; 
 
		transporters2[i] = new_transporters2[i]; 
 
	} 
 
}
 

	
 

	
 
Vector WallBase::getWallVector(CellBase *c) {
 
	if ( c == c1 ) {
 
		return ( Vector(*n2) - Vector(*n1) );
 
@@ -292,22 +258,19 @@ Vector WallBase::getInfluxVector(CellBas
 
}
 

	
 
//! \brief Test if this wall intersects with division plane p1 -> p2 
 
bool WallBase::IntersectsWithDivisionPlaneP(const Vector &p1, const Vector &p2) {
 
	
 
	// Algorithm of http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
 
	double x1 = n1->x, y1 = n1->y;
 
	double x2 = n2->x, y2 = n2->y;
 
	double x3 = p1.x, y3 = p1.y;
 
	double x4 = p2.x, y4 = p2.y;
 
	
 
	double ua = ( (x4 - x3) * (y1-y3) - (y4 - y3)*(x1-x3) ) / ( (y4 -y3) * (x2 -x1) - (x4-x3)*(y2-y1));
 
	//	double ub = ( (x2 - x1) * (y1 - y3)  - (y2 - y1) * (x1 -x3) ) / ( ( y4-y3) * (x2-x1) - (x4-x3)*(y2-y1)) ;
 
	
 
	// If ua is between 0 and 1, line p1 intersects the line segment
 
	if ( ua >=0. && ua <=1.) return true;
 
	else return false;
 
	
 
}
 

	
 

	
 

	
src/wallbase.h
Show inline comments
 
@@ -182,66 +182,20 @@ public:
 
		
 
	void SetLength(void);
 
	void Transport(void);
 
	
 
	inline void setVizFlux( double value ) { viz_flux = value; } 
 
	
 
	/*! Return vector containing the directional flux through the wall.
 
	 as defined by the value "viz_flux" which is supplied by the end-user
 
	 in the TransportFunction.
 
	 */
 
	Vector VizFlux(void);
 
	bool IntersectsWithDivisionPlaneP(const Vector &p1, const Vector &p2);
 
	
 
	/*! Function to be defined in leaf.cpp */
 
	//void OnWallInsert(void);
 
	
 
	
 

	
 
	void SetTransToNewTrans( void );
 
	
 
	// implemented in xmlwrite.cpp
 
	//void XMLAdd(xmlNode *parent) const;
 
private:
 
	
 
};
 

	
 
/* class TransportFunction {
 
	
 
	friend class Mesh;
 
public:
 
	TransportFunction( void );
 
	virtual ~TransportFunction() {
 
		//delete[] chem_change_c1;
 
		//delete[] chem_change_c2;
 
	}
 
	virtual void operator()(WallBase *w, double *dchem_c1, double *dchem_c2) = 0;// { cerr << "This is base class TransportFunction.\n"; }
 
	//virtual void operator()(WallBase *w, double *dchem_c1, double *dchem_c2, double *dapo) =0;
 
protected:
 
	int wall_index; //double *chem_change_c1;
 
	//double *chem_change_c2;
 
};
 

	
 
class CellReaction {
 
	
 
public:
 
	CellReaction(void) {};
 
	virtual ~CellReaction() {};
 
	
 
	//! Implements the actual, intracellular chemical reactions.
 
	virtual void operator()(CellBase * c, double *dchem ) = 0;
 
	
 
};
 

	
 
class WallReaction {
 
	
 
public:
 
	WallReaction(void) {};
 
	virtual ~WallReaction() {};
 
	
 
	//! Implements the actual, biochemical reactions occuring at the wall.
 
	virtual void operator()(WallBase *, double *dw1, double *dw2) = 0;
 
	
 
};*/
 

	
 
ostream &operator<<(ostream &os, const WallBase &w);
 
#endif
src/wallitem.cpp
Show inline comments
 
@@ -28,149 +28,103 @@
 
#include "parameter.h"
 
#include "node.h"
 
#include "transporterdialog.h"
 

	
 
static const std::string _module_id("$Id$");
 

	
 
WallItem::WallItem( Wall *w, int wallnumber, QGraphicsScene *canvas )
 
  : QGraphicsLineItem( 0, canvas ), SimItemBase( w, canvas){
 

	
 
  wn = wallnumber;
 

	
 
  extern Parameter par;
 
  //Wall *w=&getWall();
 
  
 
  // Draw amount of "PIN1"
 
  //double val = wn==1?(w->Transporters1(1)/par.Pi_tot)*255.:(w->Transporters2(1)/par.Pi_tot)*255.;
 
  
 
  /* if (val > 255 || val < 0 ) { 
 
     std::cerr << "val = " << val << endl;
 
     if (wn == 1) {
 
     std::cerr << "Transporters1(1) = " << w->Transporters1(1) << endl;
 
     } else {
 
     std::cerr << "Transporters2(1) = " << w->Transporters2(1) << endl;
 
     }
 
    
 
     }*/
 
  
 
  
 

	
 
	  setColor();
 
  
 
	  // line with "PIN1"is a bit inside the cell wall
 
	  Vector edgevec = (*(w->N2())) - (*(w->N1()));
 
	  Vector perp = edgevec.Normalised().Perp2D();
 
	  
 
	  Vector offs = Cell::Offset();
 
	  double factor = Cell::Factor();
 
	  
 
	  Vector from = ( offs + *(w->N1()) ) * factor + (wn==1?-1:1) * par.outlinewidth * 0.5 * factor * perp;
 
	  Vector to = ( offs + *(w->N2()) ) *factor + (wn==1?-1:1) * par.outlinewidth * 0.5 * factor * perp;
 
	  
 
	  
 
	  Vector tmp_centroid = ( *(w->N2()) + *(w->N1()) )/2.;
 
	  Vector centroid = ( offs + tmp_centroid ) * factor;
 
	  
 
	  QString text=QString("%1").arg(w->Index());
 

	
 
	  /*  if (0) {
 
		  QGraphicsSimpleTextItem *ctext = new QGraphicsSimpleTextItem ( text, 0, canvas );
 
		  ctext->setPen( QPen(QColor("orange")) );
 
		  ctext->setZValue(20);
 
		  ctext->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
		  //ctext->setTextFlags(Qt::AlignCenter);
 
		  ctext->show();
 
		  ctext ->setPos(centroid.x,
 
						 centroid.y );
 
	  }*/
 
	  
 
	  setLine(( from.x ),
 
			  ( from.y ),
 
			  ( to.x ),
 
			  ( to.y ) );
 
	  setZValue(12);
 
  }
 

	
 

	
 
void WallItem::setColor(void) {
 

	
 
  QColor diffcolor;
 
  static const QColor purple("Purple");
 
  static const QColor blue("blue");
 
  
 
  Wall *w=&getWall();
 
  double tr = wn==1?w->Transporters1(1):w->Transporters2(1);
 
  CellBase *c = wn==1?w->C1():w->C2();
 
  diffcolor.setRgb( (int)( ( tr / (1 + tr) )*255.), 0, 0);
 
  //diffcolor.setRgb( (int)( ((wn==1?w->Transporters1(1):w->Transporters2(1)))*255.), 0, 0);
 
  /* if (wn==1) {
 
     cerr << "Transporter: " << w->Transporters1(1) << endl;
 
     } else {
 
     cerr << "Transporter: " << w->Transporters2(1) << endl;
 
     }*/
 
  
 
  if (w->AuxinSource() && c->BoundaryPolP()) {
 
    setPen( QPen(purple , par.outlinewidth) );
 
  } else {
 
    if (w->AuxinSink() && c->BoundaryPolP()) {
 
      setPen( QPen(blue, par.outlinewidth));
 
    } else {
 
      setPen (QPen(diffcolor, par.outlinewidth) );
 
    }
 
  }
 
  
 
//   if (c->BoundaryPolP()) {
 
//     setPen(QPen(QColor("red"), 20));
 
//   }
 
}
 

	
 
void WallItem::OnClick(QMouseEvent *e) {
 
  
 

	
 
	Wall *w=&getWall();
 
	#ifdef QDEBUG
 
	qDebug() << "Wall ID = " << w->Index() << ", this = " << w << endl;
 
	qDebug() << "Wall item = " << this << endl;
 
	qDebug() << "C1 = " << w->C1()->Index() << ", C2 = " << w->C2()->Index() << endl;
 
	qDebug() << "N1 = " << w->N1()->Index() << ", N2 = " << w->N2()->Index() << endl;
 
	#endif
 
	//double tr = wn==1?w->Transporters1(1):w->Transporters2(1);
 
	CellBase *c = wn==1?w->C1():w->C2();
 

	
 
	TransporterDialog dialog(w, c, wn);
 
	dialog.exec();
 

	
 
	if (e->button() == Qt::RightButton) {
 
		QString message;
 
		if (wn==1) {
 
			message=QString("Transporter 1 = %1, color = %2, length = %3\n").arg(w->Transporters1(1)).arg(pen().color().red()).arg(getWall().Length());
 
		} else {
 
			message=QString("Transporter 2 = %1, color = %2, length = %3\n").arg(w->Transporters2(1)).arg(pen().color().red()).arg(getWall().Length());
 
		}
 
		
 
		//extern MainBase *main_window;
 
		//((Main *)main_window)->UserMessage(message);
 
		
 
	} else {
 
		if (e->button() == Qt::LeftButton) {
 
			if (c->BoundaryPolP()) {
 
				w->cycleWallType();
 
			} else {
 
				if (e->modifiers() == Qt::ShiftModifier) {
 
					wn==1?w->setTransporters1(1,0):w->setTransporters2(1,0);					
 
					
 
				} else {
 
					// set high amount of PIN1
 
					//cerr << "Setting PIN1\n";
 
					wn==1?w->setTransporters1(1,10):w->setTransporters2(1,10);
 
				}
 
			}
 
			setColor();
 
			update(boundingRect());
 
		} 
 
		/* else {
 
			if (e->button() == Qt::MidButton && (e->modifiers == Qt::ShiftModifier & Qt::ControlModifier)) {
 
				// hidden feature for correcting 
 
			}*/
 
		
 
	
 
	}
 
}
src/wallitem.h
Show inline comments
 
@@ -33,20 +33,18 @@
 
#include "simitembase.h"
 
#include "wall.h"
 

	
 
//! Shows transporter concentrations at one side of the wall
 

	
 
class WallItem : public QGraphicsLineItem, public SimItemBase
 
{
 
public:
 
  WallItem( Wall *n, int wallnumber, QGraphicsScene *canvas );
 
  virtual ~WallItem() {}
 
  Wall &getWall(void) const { return *class_cast<Wall*>(obj); }
 
  void OnClick(QMouseEvent *e);  
 
  //virtual void userMove(double dx, double dy);  
 
  //virtual void paint( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0);
 
  void setColor(void);
 
 private:
 
  int wn;
 
};
 

	
 
#endif
src/warning.cpp
Show inline comments
 
@@ -57,26 +57,24 @@ void MyWarning::error(char * fmt, ...)
 
void MyWarning::error(const char *fmt, ...)
 
{
 
  va_list ap;
 
  if (Quiet) return;
 
  char *message = new char[1000];
 
 
 
  va_start(ap, fmt);
 
  vsnprintf(message, 999, fmt, ap);		/* invoke interface to printf       */
 
  va_end(ap);
 
  
 
  QString qmess(message);
 
  
 
  //  bool batch = false;
 
  
 
  if (qApp->type()==QApplication::Tty) {
 
    // batch mode: print the message to stderr
 
    fprintf(stderr, "Fatal error: %s\n",qmess.toStdString().c_str());
 
    exit(1);
 
  } else { // issue a dialog box
 
    /* Solve this with signal and slot...! */
 
	  //extern MainBase *main_window;
 
    //((Main *)main_window)->stopSimulation();
 
    
 
	QMessageBox::critical( 0 , "Fatal error", qmess, QMessageBox::Abort, QMessageBox::NoButton, QMessageBox::NoButton );
 
    fprintf(stderr, "Error: %s\n",qmess.toStdString().c_str());
 
    QCoreApplication::exit(1);
src/warning.h
Show inline comments
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
 
#ifndef _WARNING_H_
 
#define _WARNING_H_
 
 
#define MEMORYCHECK(x) if ((x)==NULL) {   fprintf(stderr, "Out of Memory error in "#x" \n");  exit(0); }
 
 
#define UNIDENTIFIED 2353996
 
//static int last_value=UNIDENTIFIED;
 
/*#define WATCH(x) if (last_value==UNIDENTIFIED) {   last_value=x; 
 
} else { if (x!=last_value) { fprintf(stderr,"WATCH value changed. Suspending execution. \n Interrupt within debugger to examine position in program.\n"); 
 
				 last_value=x; 
 
				 while(1);
 
	   } else { 
 
		      last_value=x;
 
	   } 
 
	   }*/
 
 
 
/* These functions were a gift from Josh Barnes */
 
/* I changed the name "eprintf" to "warning" */
 
 
#ifdef __cplusplus 
 
extern "C" { 
 
#endif
 
  // namespace MyWarning needed because libxml2 also defines a warning token.
 
    
 
  namespace MyWarning {
 
    void error(const char *, ...);
 
    void warning(const char *, ...);
 
    void unique_warning(const char *, ...);
 
  }
 
  
 
#ifdef __cplusplus
 
}
 
#endif
 
 
#endif
 
/*
 
 *
 
 *  $Id$
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _WARNING_H_
 
#define _WARNING_H_
 

	
 
#define MEMORYCHECK(x) if ((x)==NULL) {   fprintf(stderr, "Out of Memory error in "#x" \n");  exit(0); }
 

	
 
#define UNIDENTIFIED 2353996
 

	
 
#ifdef __cplusplus 
 
extern "C" { 
 
#endif
 
  // namespace MyWarning needed because libxml2 also defines a warning token.
 
    
 
  namespace MyWarning {
 
    void error(const char *, ...);
 
    void warning(const char *, ...);
 
    void unique_warning(const char *, ...);
 
  }
 
  
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 
#endif
src/xmlwrite.cpp
Show inline comments
 
@@ -178,25 +178,24 @@ void Cell::XMLAddCore(xmlNodePtr xmlcell
 
    {
 
      ostringstream text;
 
      xmlNodePtr node_xml = xmlNewChild(xmlcell, NULL, BAD_CAST "node", NULL);
 
      text << (*i)->Index();
 
      xmlNewProp(node_xml, BAD_CAST "n", BAD_CAST text.str().c_str());
 
    }
 
  }
 

	
 
  for (list<Wall *>::const_iterator i=walls.begin();i!=walls.end();i++) {
 
    {
 
      ostringstream text;
 
      xmlNodePtr wall_xml = xmlNewChild(xmlcell, NULL, BAD_CAST "wall", NULL);
 
      //text <<wall_list_index( *i );
 
      text << XMLIO::list_index( m->walls.begin(), m->walls.end(), *i );
 
      xmlNewProp(wall_xml, BAD_CAST "w", BAD_CAST text.str().c_str());
 
    }
 
  }
 

	
 
  
 
  
 
  
 
  xmlNodePtr chem_xml = xmlNewChild(xmlcell, NULL, BAD_CAST "chem", NULL); 
 
  {
 
    ostringstream text;
 
    text << NChem();
 
@@ -353,113 +352,106 @@ int Cell::XMLRead(xmlNode *cur)  {
 
	  if ((!xmlStrcmp(n->name, (const xmlChar *)"chem"))) {
 

	
 
	    xmlNode *v_node = n->xmlChildrenNode;
 
	    int nv=0;
 
	    while (v_node!=NULL) {
 
	      if ((!xmlStrcmp(v_node->name, (const xmlChar *)"val"))) {
 
		
 
		
 
		if (nv>=Cell::NChem()) {
 
		  {
 
		    stringstream text;
 
		    text << "Exception in Mesh::XMLRead: Too many chemical values given for cell(s). Ignoring remaining values.";
 
		    //ThrowStringStream(text);
 
		    unique_warning(text.str().c_str());
 
		    break;
 
		  }
 
		}
 
		
 
		xmlChar *nc = xmlGetProp(v_node, (const xmlChar *) "v");
 
		
 
		if (nc==0) {
 
		  unique_warning("Token \"v\" not found in xmlwrite.cpp at or around line no. 1002");
 
		}
 
		//double v = strtod( (char *)nc, 0 );
 
		double v=standardlocale.toDouble((char *)nc, &ok);
 
		if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)nc);
 
		chem[nv++]=v;
 
		xmlFree(nc);
 
	      }
 
	      v_node = v_node->next; 
 
	    }
 
	  }
 
	  n = n->next;
 
  }
 
	
 
	// read cell properties
 
	{
 
		xmlChar *v_str = xmlGetProp(cur, BAD_CAST "area");
 
		
 
		if (v_str==0) {
 
			unique_warning("Token \"area\" not found in xmlwrite.cpp at or around line no. 1018");
 
		}
 
		if (v_str != NULL) {
 
		  //area = strtod( (char *)v_str, 0);
 
			area=standardlocale.toDouble((char *)v_str, &ok);
 
			if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)v_str);
 
			xmlFree(v_str);
 
		}
 
	}
 
	
 
	{
 
		xmlChar *v_str = xmlGetProp(cur, BAD_CAST "target_area");
 
		
 
		if (v_str==0) {
 
			unique_warning("Token \"target_area\" not found in xmlwrite.cpp at or around line no. 1029");
 
		}
 
    if (v_str != NULL) {
 
      //target_area = strtod( (char *)v_str, 0);
 
      	target_area=standardlocale.toDouble((char *)v_str, &ok);
 
	if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)v_str);
 
      xmlFree(v_str);
 
    }
 
  }
 
      
 
      
 
  {
 
    xmlChar *v_str = xmlGetProp(cur, BAD_CAST "target_length");
 

	
 
    if (v_str==0) {
 
      unique_warning("Token \"target_length\" not found in xmlwrite.cpp at or around line no. 1041");
 
    }
 
    if (v_str != NULL) {
 
      //target_length = strtod( (char *)v_str, 0);
 
      target_length=standardlocale.toDouble((char *)v_str, &ok);
 
      if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)v_str);
 
      xmlFree(v_str);
 
    }
 
  }
 

	
 
  {
 
    xmlChar *v_str = xmlGetProp(cur, BAD_CAST "lambda_celllength");
 

	
 
    if (v_str==0) {
 
      unique_warning("Token \"lambda_celllength\" not found in xmlwrite.cpp at or around line no. 1052");
 
    }
 
    if (v_str != NULL) {
 
      //lambda_celllength = strtod( (char *)v_str, 0);
 
      lambda_celllength=standardlocale.toDouble((char *)v_str, &ok);
 
      if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)v_str);
 
      xmlFree(v_str);
 
    }
 
  }
 

	
 
  {
 
    xmlChar *v_str = xmlGetProp(cur, BAD_CAST "stiffness");
 

	
 
    if (v_str==0) {
 
      unique_warning("Token \"stiffness\" not found in xmlwrite.cpp at or around line no. 1063");
 
    }
 
    if (v_str != NULL) {
 
      //stiffness = strtod( (char *)v_str, 0);
 
      stiffness=standardlocale.toDouble((char *)v_str, &ok);
 
      if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)v_str);
 
      xmlFree(v_str);
 
    }
 
  }
 

	
 
      
 
  {
 
    xmlChar *v_str = xmlGetProp(cur, BAD_CAST "fixed");
 

	
 
    if (v_str==0) {
 
      unique_warning("Token \"fixed\" not found in xmlwrite.cpp at or around line no. 1075");
 
@@ -589,30 +581,24 @@ void NodeSet::XMLRead(xmlNode *root, Mes
 
  }
 
  
 
}
 

	
 

	
 

	
 

	
 
void Wall::XMLAdd(xmlNode *parent) const { 
 
  
 
  // Save the node to a stream so we can reconstruct its state later
 
  xmlNodePtr xmlwall = xmlNewChild(parent, NULL, BAD_CAST "wall",NULL);
 
  
 
  /* {
 
     ostringstream text;
 
     text << index;
 
     xmlNewProp(xmlnode, BAD_CAST "index", BAD_CAST text.str().c_str());
 
     }*/
 
  
 
  {
 
    ostringstream text;
 
    text << Index();
 
    xmlNewProp(xmlwall, BAD_CAST "index" , BAD_CAST text.str().c_str() );
 
  }
 

	
 
  {
 
    ostringstream text;
 
    text << c1->Index();
 
    xmlNewProp(xmlwall, BAD_CAST "c1", BAD_CAST text.str().c_str());
 
  }
 
  
 
@@ -648,30 +634,24 @@ void Wall::XMLAdd(xmlNode *parent) const
 
    text << viz_flux;
 
    xmlNewProp(xmlwall, BAD_CAST "viz_flux", BAD_CAST text.str().c_str());
 
  }
 

	
 
  {
 
    ostringstream text;
 
    text << WallTypetoStr(wall_type);
 
    xmlNewProp(xmlwall, BAD_CAST "wall_type", BAD_CAST text.str().c_str());
 
  }
 
      
 
    
 
  xmlNodePtr tr1_xml = xmlNewChild(xmlwall, NULL, BAD_CAST "transporters1", NULL); 
 
  //   {
 
  //     ostringstream text;
 
  //     text << Cell::nchem;
 
  //     xmlNewProp(tr1_xml, BAD_CAST "n", BAD_CAST text.str().c_str());
 
  //   }
 
  
 
  if (transporters1) {
 
    for (int i=0;i<Cell::NChem();i++) {
 
      xmlNodePtr tr1_val_xml = xmlNewChild(tr1_xml, NULL, BAD_CAST "val", NULL);
 
      { 
 
	ostringstream text;
 
	text << transporters1[i];
 
	xmlNewProp(tr1_val_xml, BAD_CAST "v", BAD_CAST text.str().c_str());
 
      
 
      }
 
    }
 
  }
 
  if (transporters2) {
 
@@ -744,41 +724,41 @@ void Mesh::XMLSave(const char *docname, 
 
	doc = xmlNewDoc(BAD_CAST "1.0");
 
	root_node = xmlNewNode(NULL, BAD_CAST "leaf");
 
	xmlDocSetRootElement(doc, root_node);
 
	
 
	/* 
 
	 * xmlNewProp() creates attributes, which is "attached" to an node.
 
	 * It returns xmlAttrPtr, which isn't used here.
 
	 */
 
	xmlNewProp(root_node, BAD_CAST "name", BAD_CAST docname);
 
	
 
	time_t t;
 
	std::time(&t);
 
	// asctime_r(localtime(&t),tstring); //Doesn't work for MinGW
 

	
 
	char *tstring = strdup(asctime(localtime(&t))); // but this does
 
	// replace "end of line character by '\0'
 
	char *eol=strchr(tstring,'\n');
 
	if (eol!=NULL)
 
		*eol='\0';
 
	
 
	xmlNewProp(root_node, BAD_CAST "date", BAD_CAST tstring);
 
	free(tstring);
 
	
 
	
 
	QString simtime = QString("%1").arg(time);
 
	xmlNewProp(root_node, BAD_CAST "simtime", BAD_CAST simtime.toStdString().c_str()); 
 
	/*
 
	 * Creates a DTD declaration. Isn't mandatory. 
 
	 */
 
	//dtd = xmlCreateIntSubset(doc, BAD_CAST "root", NULL, BAD_CAST "tree2.dtd");
 

	
 
	par.XMLAdd(root_node);
 

	
 
	xmlNodePtr xmlnodes = xmlNewChild(root_node, NULL, BAD_CAST "nodes",NULL);
 
	{ ostringstream text;
 
		text << NNodes();
 
		xmlNewProp(xmlnodes, BAD_CAST "n", BAD_CAST text.str().c_str());
 
	}
 
	
 
	{ ostringstream text;
 
		text << Node::target_length;
 
		xmlNewProp(xmlnodes, BAD_CAST "target_length", BAD_CAST text.str().c_str());
 
	}
 
@@ -887,47 +867,50 @@ void Mesh::XMLSave(const char *docname, 
 
	/*free the document */
 
	xmlFreeDoc(doc);
 
	
 
	/*
 
	 *Free the global variables that may
 
	 *have been allocated by the parser.
 
	 */
 
	xmlCleanupParser();
 
	
 
	/*
 
	 * this is to debug memory for regression tests
 
	 */
 
	//xmlMemoryDump();
 
}
 

	
 

	
 

	
 
void Mesh::XMLReadSimtime(const xmlNode *a_node) {
 
	
 
  xmlNode *root_node;
 
  root_node = (xmlNode *)a_node;
 
  xmlChar *strsimtime = xmlGetProp(root_node, BAD_CAST "simtime");
 
  
 
  
 
  if (strsimtime) {
 
    //double simtime = strtod((const char *)strsimtime, 0);
 

	
 
    QLocale standardlocale(QLocale::C);
 
    bool ok;
 
    
 
    double simtime=standardlocale.toDouble((char *)strsimtime, &ok);
 
    if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(char *)strsimtime);
 
      time = simtime;
 
		cerr << "Simtime = " << strsimtime << endl;
 
#ifdef QDEBUG
 
                qDebug() << "Simtime = " << strsimtime << endl;
 
#endif
 
	} else {
 
		cerr << "No simtime found in file \n";
 
#ifdef QDEBUG
 
    qDebug() << "No simtime found in file." << endl;
 
#endif
 
		time =0;
 
	}	
 
}
 

	
 
void Mesh::XMLReadPars(const xmlNode * a_node) {
 
	xmlNode *root_node;
 
	root_node = (xmlNode *)a_node;
 
	par.XMLRead(root_node);
 
	Seed(par.rseed);
 
	MakeDir(par.datadir);
 
}
 

	
 
@@ -955,53 +938,52 @@ void Mesh::XMLReadGeometry(const xmlNode
 
		}
 
		cur=cur->next;
 
	}
 
	
 
	cur=root_node->xmlChildrenNode;
 
	while (cur!=NULL) {
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"nodes"))) {
 
			XMLReadNodeSetsToNodes(cur);
 
		}
 
		cur = cur->next;
 
	}
 
    
 
	//cur = root_node;
 
    
 
	// allocate Cells
 
	cur = root_node;
 
	
 
	// allocate Cells
 
	cur = cur->xmlChildrenNode;
 
	while (cur!=NULL) {
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"cells"))){
 
			xmlChar *offsetxc = xmlGetProp(cur, BAD_CAST "offsetx");
 
			xmlChar *offsetyc = xmlGetProp(cur, BAD_CAST "offsety");
 
			//double ox = strtod((const char*)offsetxc, 0);
 

	
 
			double ox=standardlocale.toDouble((const char *)offsetxc, &ok);
 
			if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)offsetxc);
 
			//double oy = strtod((const char*)offsetyc, 0);
 

	
 
			double oy=standardlocale.toDouble((const char *)offsetyc, &ok);
 
			if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)offsetyc);
 
			Cell::setOffset(ox, oy);
 
			xmlFree(offsetxc);
 
			xmlFree(offsetyc);
 
			
 
			xmlChar *magnificationc = xmlGetProp(cur, BAD_CAST "magnification");
 
			//Cell::SetMagnification(strtod((const char*)magnificationc, 0 ));
 

	
 
			Cell::SetMagnification(standardlocale.toDouble((const char *)magnificationc, &ok));
 
			if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)magnificationc);
 
			xmlFree(magnificationc);
 
			
 
			xmlChar *baseareac = xmlGetProp(cur, BAD_CAST "base_area");
 
			//Cell::BaseArea()= strtod((const char *)baseareac, 0 );
 

	
 
			Cell::BaseArea() = standardlocale.toDouble((const char *)baseareac, &ok);
 
			if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)baseareac);
 
			xmlFree(baseareac);
 
			
 
			
 
			XMLReadCells(cur);
 
		}
 
		cur=cur->next;
 
	}
 
    
 
	// allocate Walls (we need to have read the cells before constructing walls)
 
	vector <Wall *> tmp_walls;
 
@@ -1062,25 +1044,25 @@ void Mesh::XMLReadNodes(xmlNode *root) {
 
  for (vector<Node *>::iterator i=nodes.begin();
 
       i!=nodes.end();
 
       i++) {
 
    delete *i;
 
  }
 
	
 
  nodes.clear();
 
  Node::nnodes=0;
 
	
 
  xmlChar *tlc = xmlGetProp(root, BAD_CAST "target_length");
 
	
 
  if (tlc != 0) {
 
    //Node::target_length = strtod( (const char *)tlc, 0 );
 

	
 
	  
 
    Node::target_length = standardlocale.toDouble((const char *)tlc, &ok);
 
    if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)tlc);
 
		
 
    xmlFree(tlc);
 
  } else {
 
    // note that libxml2 also defines a token "warning"
 
    MyWarning::unique_warning("Warning: value found in XML file for Node::target_length.");
 
  }
 
    
 
  while (cur!=NULL) {
 
    if ((!xmlStrcmp(cur->name, (const xmlChar *)"node"))){
 
@@ -1103,29 +1085,28 @@ void Mesh::XMLReadNodes(xmlNode *root) {
 
      }
 
			
 
      xmlChar *boundaryc = xmlGetProp(cur, BAD_CAST "boundary");
 
      if (boundaryc==0) {
 
	unique_warning("Token \"boundary\" not found in xmlwrite.cpp at or around line.");
 
      }
 
			
 
      xmlChar *samc = xmlGetProp(cur, BAD_CAST "sam");
 
      if (samc==0) {
 
	unique_warning("Token \"sam\" not found in xmlwrite.cpp at or around line.");
 
      }
 
			
 
      //double x = strtod( (char *)xc , 0);
 

	
 
      double x = standardlocale.toDouble((const char *)xc, &ok);
 
      if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)xc);
 
		
 
      //double y = strtod( (char *)yc , 0 );
 
      double y = standardlocale.toDouble((const char *)yc, &ok);
 
      if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)yc);
 
			
 
      Node *new_node = new Node(x,y);
 
      nodes.push_back(new_node);
 
			
 
      new_node->m = this;
 
      new_node->fixed = strtobool( (char *)fixedc);
 
      new_node->boundary = strtobool( (char *)boundaryc );
 
      new_node->sam = strtobool ( (char *)samc);
 
      new_node->node_set = 0;
 
			
 
@@ -1153,26 +1134,24 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
  xmlNode *cur = root;
 
  cur = cur->xmlChildrenNode;
 
	
 
  for (list<Wall *>::iterator i=walls.begin();
 
       i!=walls.end();
 
       i++) {
 
    delete *i;
 
  }
 
	
 
  walls.clear();
 
  Wall::nwalls = 0;
 
  tmp_walls->clear();
 
  //Node::nnodes=0;
 
	
 
	
 
  QLocale standardlocale(QLocale::C);
 
  bool ok;
 

	
 
  while (cur!=NULL) {
 
		
 
    vector<int> tmp_nodes;
 
    while(cur!=NULL) {
 
      if ((!xmlStrcmp(cur->name, (const xmlChar *)"wall"))) {
 
				
 
	xmlChar *nc = xmlGetProp(cur, BAD_CAST "c1");
 
				
 
@@ -1202,36 +1181,36 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
				
 
	if (	nc==0) {
 
	  unique_warning("Token \"n2\" not found in xmlwrite.cpp at or around line no. 801");
 
	}
 
	int n2 = atoi( (char *)nc);
 
	xmlFree(nc);
 
				
 
	nc = xmlGetProp(cur, BAD_CAST "length");
 
				
 
	if (	nc==0) {
 
	  unique_warning("Token \"length\" not found in xmlwrite.cpp at or around line no. 809");
 
	}
 
	//double length = strtod( (char *)nc, 0);
 

	
 
	double length = standardlocale.toDouble((const char *)nc, &ok);
 
	if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)nc);
 

	
 
	xmlFree(nc);
 
				
 
				
 
	nc = xmlGetProp(cur, BAD_CAST "viz_flux");
 
				
 
	double viz_flux = 0.0;
 
	if (nc!=0) {
 
	  //viz_flux = strtod( (char *)nc, 0);
 

	
 
	  viz_flux = standardlocale.toDouble((const char *)nc, &ok);
 
	  if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)nc);
 
	}
 
	xmlFree(nc);
 
				
 
	Wall::WallType wall_type;
 
	{
 
	  xmlChar *v_str = xmlGetProp(cur, BAD_CAST "wall_type");
 
					
 
	  if (v_str != 0) {
 
						
 
	    if (!xmlStrcmp(v_str, (const xmlChar *)"aux_source")) {
 
@@ -1279,35 +1258,35 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
	while (w_node!=NULL) {
 
	  if ((!xmlStrcmp(w_node->name, (const xmlChar *)"transporters1"))) {
 
						
 
	    xmlNode *v_node = w_node->xmlChildrenNode;
 
	    int nv=0;
 
	    while (v_node!=NULL) {
 
							
 
	      if ((!xmlStrcmp(v_node->name, (const xmlChar *)"val"))) {
 
		if (nv>=Cell::NChem()) {
 
		  {
 
		    stringstream text;
 
		    text << "Exception in Mesh::XMLRead: Too many transporter values given for wall(s). Ignoring remaining values.";
 
		    //ThrowStringStream(text);
 

	
 
		    unique_warning(text.str().c_str());
 
		    break;
 
		  }
 
		}
 
		xmlChar *nc = xmlGetProp(v_node, (const xmlChar *) "v");
 
								
 
		if (nc==0) {
 
		  unique_warning("Token \"v\" not found in xmlwrite.cpp at or around line no. 835");
 
		}
 
		//double v = strtod( (char *)nc, 0 );
 

	
 
		double v = standardlocale.toDouble((const char *)nc, &ok);
 
		if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)nc);
 

	
 
		w->transporters1[nv++]=v;
 
		xmlFree(nc);
 
								
 
	      }
 
	      v_node = v_node->next; 
 
	    }
 
						
 
	  }
 
					
 
@@ -1315,104 +1294,98 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
	  if ((!xmlStrcmp(w_node->name, (const xmlChar *)"transporters2"))) {
 
						
 
	    xmlNode *v_node = w_node->xmlChildrenNode;
 
	    int nv=0;
 
	    while (v_node!=NULL) {
 
	      if ((!xmlStrcmp(v_node->name, (const xmlChar *)"val"))) {
 
		if (nv>=Cell::NChem()) {
 
		  {
 
		    stringstream text;
 
		    text << "Exception in Mesh::XMLRead: Too many transporter values given for wall(s). Ignoring remaining values.";
 
		    unique_warning(text.str().c_str());
 
		    break;
 
		    // ThrowStringStream(text);
 

	
 
		  }
 
		}
 
								
 
		xmlChar *nc = xmlGetProp(v_node, (const xmlChar *) "v");
 
								
 
		if (nc==0) {
 
		  unique_warning("Token \"v\" not found in xmlwrite.cpp at or around line no. 861");
 
		}
 
		//double v = strtod( (char *)nc, 0 );
 

	
 
		double v = standardlocale.toDouble((const char *)nc, &ok);
 
		if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)nc);
 

	
 
		w->transporters2[nv++]=v;
 
		xmlFree(nc);
 
	      }
 
	      v_node = v_node->next; 
 
	    }
 
						
 
	  } 
 
					
 
	  if ((!xmlStrcmp(w_node->name, (const xmlChar *)"apoplast"))) {
 
						
 
	    xmlNode *v_node = w_node->xmlChildrenNode;
 
	    int nv=0;
 
	    while (v_node!=NULL) {
 
							
 
	      if ((!xmlStrcmp(v_node->name, (const xmlChar *)"val"))) {
 
		if (nv>=Cell::NChem()) {
 
		  {
 
		    stringstream text;
 
		    text << "Exception in Mesh::XMLRead: Too many transporter values given for wall(s). Ignoring remaining values.";
 
		    //ThrowStringStream(text);
 

	
 
		    unique_warning(text.str().c_str());
 
		    break;
 
		  }
 
		}
 
		xmlChar *nc = xmlGetProp(v_node, (const xmlChar *) "v");
 
								
 
		if (nc==0) {
 
		  unique_warning("Token \"v\" not found in xmlwrite.cpp at or around line no. 887");
 
		}
 
		//double v = strtod( (char *)nc, 0 );
 

	
 
		double v = standardlocale.toDouble((const char *)nc, &ok);
 
		if (!ok) MyWarning::error("Could not convert \"%s\" to double in XMLRead.",(const char *)nc);
 

	
 
		w->apoplast[nv++]=v;
 
		xmlFree(nc);
 
	      }
 
	      v_node = v_node->next; 
 
	    }
 
						
 
	  }
 
	  w_node=w_node->next;
 
	}
 
				
 
      }
 
      cur = cur->next;
 
    }
 
		
 
  }
 
  //  CleanUpWalls();
 
}
 

	
 

	
 
void Mesh::XMLReadWallsToCells(xmlNode *root, vector<Wall *> *tmp_walls) {
 
	
 
	// Add the walls to the cells (do this after reading the walls; read walls after reading cells...)
 
	// 1. Read Nodes
 
	// 2. Read Cells
 
	// 3. Read Walls
 
	// 4. Read Walls into Cells
 
	
 
	xmlNode *cur = root->xmlChildrenNode;
 
	int ci=0; // cell index
 
	
 
	while (cur!=NULL) {
 
		
 
		//Cell *new_cell=0;
 
		
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"cell")) ||
 
			(!xmlStrcmp(cur->name, (const xmlChar *)"boundary_polygon" ))) {
 
			
 
			vector<int> tmp_walls_ind;
 
			xmlNode *n = cur->xmlChildrenNode;
 
			
 
			while(n!=NULL) {
 
				
 
				if ((!xmlStrcmp(n->name, (const xmlChar *)"wall"))) {
 
					xmlChar *nc = xmlGetProp(n, BAD_CAST "w");
 
					
 
					if (nc==0) {
 
@@ -1575,30 +1548,28 @@ void Mesh::XMLRead(const char *docname, 
 
		xmlFreeDoc(doc);
 
		return;
 
	}
 
	
 
	if (xmlStrcmp(cur->name, (const xmlChar *) "leaf")) {
 
		throw("XML file of the wrong type, it is not a leaf.");
 
		xmlFreeDoc(doc);
 
		return;
 
	}
 
	
 
	/*Get the root element node */
 
	xmlNode *root_element = xmlDocGetRootElement(doc);
 
	
 
	//XMLParseTree(root_element);
 

	
 
	if (geometry) XMLReadGeometry(root_element);
 
	if (pars) XMLReadPars(root_element);
 
	if (simtime) XMLReadSimtime(root_element);
 
	//print_element_names(root_element);
 
	
 
	// If pointer settings defined, return a copy of the settings tree
 
	if (settings) {
 
		xmlNode *cur = root_element->xmlChildrenNode;
 
		// if settings field is not found, *settings will be returned 0.
 
		*settings = 0;
 
		while (cur!=NULL) {
 
			if ((!xmlStrcmp(cur->name, (const xmlChar *)"settings"))){
 
				*settings = xmlCopyNode(cur,1);
 
			}
 
			cur=cur->next;
 
		}
 
@@ -1608,29 +1579,24 @@ void Mesh::XMLRead(const char *docname, 
 
	/*
 
	 *Free the global variables that may
 
	 *have been allocated by the parser.
 
	 */
 
	xmlCleanupParser();
 
	
 
	// We're doing this so we can manually delete walls with by adding the 'delete="true"' property
 
	CleanUpCellNodeLists();
 
	
 
}
 

	
 

	
 
/*  int Mesh::XMLReadWall(xmlNode *cur)  {
 
  
 

	
 
    return w;
 
    }*/
 
void Parameter::XMLRead(xmlNode *root) {
 
	
 
	xmlNode *cur = root->xmlChildrenNode;
 
	while (cur!=NULL) {
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"parameter"))){
 
			xmlNode *par_node = cur->xmlChildrenNode;
 
			while (par_node!=NULL) {
 
				{
 
					if (!xmlStrcmp(par_node->name, (const xmlChar *)"par")) {
 
						xmlChar *namec = xmlGetProp(par_node, BAD_CAST "name");
 
						xmlChar *valc = xmlGetProp(par_node, BAD_CAST "val");
 
						if (valc) {
0 comments (0 inline, 0 general)