Changeset - 782330072e62
[Not reviewed]
default
0 91 0
Michael Guravage - 15 years ago 2010-06-17 18:13:46
michael.guravage@cwi.nl
Reformatted the source files and generally straighten up the code.

--
user: Michael Guravage <michael.guravage@cwi.nl>
branch 'default'

changed src/Neighbor.cpp
changed src/Neighbor.h
changed src/OptionFileDialog.cpp
changed src/OptionFileDialog.h
changed src/UniqueMessage.cpp
changed src/UniqueMessage.h
changed src/VirtualLeaf.cpp
changed src/apoplastitem.cpp
changed src/apoplastitem.h
changed src/build_models/auxingrowthplugin.cpp
changed src/build_models/auxingrowthplugin.h
changed src/build_models/meinhardtplugin.cpp
changed src/build_models/meinhardtplugin.h
changed src/build_models/testplugin.cpp
changed src/build_models/testplugin.h
changed src/build_models/translate_plugin.pl
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/cellitem.cpp
changed src/cellitem.h
changed src/curvecolors.h
changed src/data_plot.cpp
changed src/data_plot.h
changed src/far_mem_5.h
changed src/flux_function.h
changed src/forwardeuler.cpp
changed src/forwardeuler.h
changed src/infobar.h
changed src/mainbase.cpp
changed src/mainbase.h
changed src/matrix.cpp
changed src/matrix.h
changed src/maxmin.h
changed src/mesh.cpp
changed src/mesh.h
changed src/miscq.cpp
changed src/miscq.h
changed src/modelcatalogue.cpp
changed src/modelcatalogue.h
changed src/modelelement.h
changed src/node.cpp
changed src/node.h
changed src/nodeitem.cpp
changed src/nodeitem.h
changed src/nodeset.cpp
changed src/nodeset.h
changed src/output.cpp
changed src/output.h
changed src/parameter.cpp
changed src/parameter.h
changed src/pardialog.cpp
changed src/pardialog.h
changed src/parse.cpp
changed src/parse.h
changed src/perl/deployapp.pl
changed src/perl/histogram.pl
changed src/perl/make_parameter_source.pl
changed src/perl/make_pardialog_source.pl
changed src/perl/make_xmlwritecode.pl
changed src/pi.h
changed src/qcanvasarrow.h
changed src/random.cpp
changed src/random.h
changed src/rseed.cpp
changed src/rungekutta.cpp
changed src/rungekutta.h
changed src/simitembase.cpp
changed src/simitembase.h
changed src/simplugin.cpp
changed src/simplugin.h
changed src/sqr.h
changed src/tiny.h
changed src/transporterdialog.cpp
changed src/transporterdialog.h
changed src/vector.cpp
changed src/vector.h
changed src/vleafmodel.h
changed src/wall.cpp
changed src/wall.h
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
changed src/xmlwrite.h
87 files changed with 601 insertions and 792 deletions:
src/cell.cpp
62
118
src/node.h
19
32
0 comments (0 inline, 0 general)
src/Neighbor.cpp
Show inline comments
 
@@ -34,13 +34,14 @@ Neighbor::Neighbor(Cell *c, Node *n1, No
 
Neighbor::Neighbor(const Neighbor &src):
 
  cell(src.cell), nb1(src.nb1), nb2(src.nb2){} // copy constructor
 
  
 
bool Neighbor::CellEquals(int i) const { return cell->Index() == i; } 
 
bool Neighbor::Cmp(Neighbor &c) const { return cell->Index() < c.cell->Index(); } // Compare cell indices not pointers.
 
bool Neighbor::Eq(Neighbor &c) const { return cell->Index() == c.cell->Index(); }
 
Cell* Neighbor::getCell(void) const { return cell; } 
 

	
 
bool neighbor_cell_eq(const Neighbor &n1, const Neighbor &n2) {
 
  return (n1.getCell())->Index() == (n2.getCell())->Index(); // Compare cell indices not pointers.
 
}
 
  
 
// finis
 
/* finis */
 

	
src/Neighbor.h
Show inline comments
 
@@ -59,13 +59,14 @@ class Neighbor {
 

	
 
  ostream &print(ostream &os) const;
 
};
 

	
 
// Overload the << operator 
 
ostream &operator<<(ostream &os, const Neighbor &n);
 

	
 
// Realize that we're equating like pointers with object equivalence!
 
bool neighbor_cell_eq(const Neighbor &n1, const Neighbor &n2);
 

	
 
#endif
 

	
 
// finis
 
/* finis */
 

	
src/OptionFileDialog.cpp
Show inline comments
 
@@ -18,32 +18,33 @@
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include "OptionFileDialog.h"
 
#include <QCheckBox>
 
#include <iostream>
 
using namespace  std; 
 

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

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

	
 
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);
 
	
 
	addToolButton(geometrycheck);
 
	addToolButton(parcheck);
 

	
 
};
 

	
 
OptionFileDialog::OptionFileDialog ( const QString & dirName, const QString & filter , QWidget * parent, const char * name , bool modal  ) :
 
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";
 
};
 
					
 
	};
 
/* finis */
src/OptionFileDialog.h
Show inline comments
 
@@ -21,23 +21,26 @@
 
 */
 

	
 
#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 );
 
  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;
 
};
 

	
 
#endif
 

	
 
/* finis */
src/UniqueMessage.cpp
Show inline comments
 
@@ -59,27 +59,26 @@ QDialog(parent, f) {
 
	QVBoxLayout *layout = new QVBoxLayout;
 
	layout->addLayout(hlayout);
 
	layout->addWidget(show_again);
 
	setLayout(layout);
 
	setWindowTitle(title);
 
};
 
		
 
UniqueMessageBox::~UniqueMessageBox(void)  {
 
	
 
	if (show_again->checkState() == Qt::Checked ) {
 
		cerr << "Message won't be shown again\n";
 
		issued_messages << boxtext;
 

	
 
	}
 
}
 
int UniqueMessageBox::exec(void)  {
 
	
 
	if (display)
 
		return QDialog::exec();
 
	else {
 
		return 1;
 
	}
 

	
 
}
 
					   
 
QStringList UniqueMessageBox::issued_messages;
 
					   
 
/* finis */
src/UniqueMessage.h
Show inline comments
 
@@ -43,12 +43,14 @@ public:
 
	int exec(void);
 
	
 
private:
 
	static QStringList issued_messages;
 
	bool display;
 
	QCheckBox *show_again;
 
	QPushButton *okButton;
 
	QLabel *label;
 
	QString boxtext;
 
};
 

	
 
#endif
 

	
 
/* finis */
src/VirtualLeaf.cpp
Show inline comments
 
@@ -129,25 +129,26 @@ public:
 
	c.DrawCenter(&canvas);
 
      }
 
      if (m.ShowFluxesP()){
 
	c.DrawFluxes(&canvas, par.arrowsize);
 
      }
 
    }
 
  }
 
};
 

	
 
Mesh mesh;
 
bool batch=false;
 

	
 
void MainBase::Plot(int resize_stride) {
 
void MainBase::Plot(int resize_stride)
 
{
 
	
 
  clear();
 
	
 
  static int count=0;
 
  if (resize_stride) {
 
    if ( !((++count)%resize_stride) ) {
 
      FitLeafToCanvas();
 
    }
 
  }
 
  mesh.LoopCells(DrawCell(),canvas,*this);
 
	
 
  if (ShowNodeNumbersP()) 
 
@@ -252,48 +253,40 @@ TIMESTEP {
 
    // 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	
 
      mesh.ReactDiffuse(par.rd_dt);
 
				
 
      t++;
 
				
 
      Plot(par.resize_stride);
 
		
 
    }
 
		
 
  } else {
 
			
 
    mesh.ReactDiffuse(par.rd_dt);
 
		
 
    Plot(par.resize_stride);
 
			
 
  }
 
		
 
  i++;
 
  return mesh.getTime();
 
		
 
}
 
		
 
		
 
				
 
/* Called if a cell is clicked */
 
void Cell::OnClick(QMouseEvent *e) {
 
void Cell::OnClick(QMouseEvent *e)
 
{
 
  e = NULL; // use assignment merely to obviate compilation warning
 
}
 
				
 

	
 
/* 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;
 
@@ -309,29 +302,25 @@ void vlMessageOutput(QtMsgType type, con
 
    //fprintf(stderr, "Fatal: %s\n", msg);
 
    cerr << "Fatal: " << msg << flush;
 
    abort();
 
  }
 
}
 
				
 

	
 
Parameter par;
 
				
 
int main(int argc,char **argv) {
 
					
 
  try {
 
						
 

	
 
    int c;
 

	
 
						
 
    char *leaffile=0;
 
    char *modelfile=0;
 
						
 
    while (1) {
 
							
 
      //int this_option_optind = optind ? optind : 1;
 
      int option_index = 0;
 
      static struct option long_options[] = {
 
	{"batch", no_argument, NULL, 'b'},
 
	{"leaffile", required_argument, NULL, 'l'},
 
	{"model", required_argument, NULL, 'm'} 
 
      };
 
@@ -408,72 +397,68 @@ int main(int argc,char **argv) {
 
    if (useGUI) {
 
      main_window=new Main(canvas, mesh);
 
      if ( QApplication::desktop()->width() > ((Main *)main_window)->width() + 10
 
	   && QApplication::desktop()->height() > ((Main *)main_window)->height() +30 ) {
 

	
 
	((Main *)main_window)->show();
 
	((Main *)main_window)->resize( ((Main *)main_window)->sizeHint());
 
      } else {
 
        ((Main *)main_window)->showMaximized();
 
      }
 
    } else {
 
      main_window=new MainBase(canvas, mesh);
 

	
 
    }
 

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

	
 
    // 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);
 
						
 
    main_window->FitLeafToCanvas();
 
							
 
    main_window->Plot();
 

	
 
    if (batch) {
 
      double t=0.;
 
      do {
 
	t = main_window->TimeStep();
 
      } while (t < par.maxt);
 
							
 
    } else
 
      return app.exec();
 
	  
 
						
 
  } catch (const char *message) {
 
    if (batch) { 
 
      cerr << "Exception caught:" << endl;
 
      cerr << message << endl;
 
      abort();
 
    } else {
 
      QString qmess=QString("Exception caught: %1").arg(message);
 
      QMessageBox::critical(0, "Critical Error", qmess);
 
      abort();
 
    }
 
  } catch (ios_base::failure) {
 
    stringstream error_message;
 
    error_message << "I/O failure: " << strerror(errno);
 
    if (batch) {
 
      cerr << error_message.str() <<endl;
 
      abort();
 
    } else {
 
      QString qmess(error_message.str().c_str());
 
      QMessageBox::critical(0, "I/O Error", qmess );
 
      abort();
 
    }
 
  }
 
}
 

	
 
/* finis */
src/apoplastitem.cpp
Show inline comments
 
@@ -57,19 +57,19 @@ ApoplastItem::ApoplastItem( Wall *w, QGr
 

	
 
void ApoplastItem::setColor(void) {
 
	
 
	QColor diffcolor;
 
	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 compilation warnings
 
}
 

	
 
/* finis*/
src/apoplastitem.h
Show inline comments
 
@@ -14,35 +14,38 @@
 
 *  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 _APOPLASTITEM_H_
 
#define _APOPLASTITEM_H_
 

	
 
#include <QGraphicsScene>
 
#include <QGraphicsLineItem>
 
#include <QPainter>
 
#include <qpainter.h>
 
#include <QMouseEvent>
 
#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);  
 
	void setColor(void);
 
private:
 
	int wn;
 
};
 

	
 
#endif
 

	
 
/* finis*/
src/build_models/auxingrowthplugin.cpp
Show inline comments
 
@@ -28,90 +28,90 @@
 
#include "wallbase.h"
 
#include "cellbase.h"
 
#include "auxingrowthplugin.h"
 

	
 
#include "far_mem_5.h"
 

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

	
 
bool batch = false;
 

	
 

	
 
// To be executed after cell division
 
void AuxinGrowthPlugin::OnDivide(ParentInfo *parent_info, CellBase *daughter1, CellBase *daughter2) {
 
void AuxinGrowthPlugin::OnDivide(ParentInfo *parent_info, CellBase *daughter1, CellBase *daughter2)
 
{
 
  parent_info = NULL; // merely to obviate compile time error
 

	
 
	// Auxin distributes between parent and daughter according to area
 
	double area1 = daughter1->Area(), area2 = daughter2->Area();
 
	double tot_area = area1 + area2;
 
	
 
	daughter1->SetChemical(0,daughter1->Chemical(0)*(area1/tot_area));
 
	daughter2->SetChemical(0,daughter2->Chemical(0)*(area2/tot_area));
 
	
 
	// 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.);
 
	}
 
	
 
}
 

	
 
void AuxinGrowthPlugin::SetCellColor(CellBase *c, QColor *color) { 
 
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);
 
	
 
  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.), 0);
 
}
 

	
 

	
 

	
 
void AuxinGrowthPlugin::CellHouseKeeping(CellBase *c) {
 

	
 
void AuxinGrowthPlugin::CellHouseKeeping(CellBase *c)
 
{
 
	if (c->Boundary()==CellBase::None) {
 
		if (c->Area() > par->rel_cell_div_threshold * c->BaseArea() ) {
 
			c->SetChemical(0,0);
 
			c->Divide();
 
        }		
 
		if (c->Chemical(0)>0.6) {
 
			c->SetCellType(1);
 
		} 
 
		// expand according to auxin concentration
 
   		c->EnlargeTargetArea(par->auxin_dependent_growth?(c->Chemical(0)/(1.+c->Chemical(0)))*par->cell_expansion_rate:par->cell_expansion_rate);
 
	}  
 
	
 

	
 
}
 

	
 
void AuxinGrowthPlugin::CelltoCellTransport(Wall *w, double *dchem_c1, double *dchem_c2) {
 
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;
 
			return;
 
		} else {
 
			return;
 
		}
 
	}
 
	
 
	
 
	if (w->C1()->BoundaryPolP()) {
 
		
 
		if (w->AuxinSource()) {
 
			double aux_flux = par->leaf_tip_source * w->Length();
 
			dchem_c2[0] += aux_flux;
 
			return;
 
		} else {
 
			
 
			if (w->AuxinSink()) {
 
				
 
				// efflux into Shoot Apical meristem
 
				// we assume all PINs are directed towards shoot apical meristem
 
@@ -137,28 +137,26 @@ void AuxinGrowthPlugin::CelltoCellTransp
 
    // (Transporters measured in moles, here)
 
    // efflux from cell 1 to cell 2
 
    double trans12 = ( par->transport * w->Transporters1(1) * w->C1()->Chemical(0) / (par->ka + w->C1()->Chemical(0)) );
 
	
 
    // efflux from cell 2 to cell 1
 
    double trans21 = ( par->transport * w->Transporters2(1) * w->C2()->Chemical(0) / (par->ka + w->C2()->Chemical(0)) );
 
    
 
    dchem_c1[0] += trans21 - trans12;
 
    dchem_c2[0] += trans12 - trans21;
 
	
 
}
 

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

	
 
	
 
	
 
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.;
 
            
 
			// 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);
 
@@ -218,57 +216,56 @@ void AuxinGrowthPlugin::WallDynamics(Wal
 
    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[1] = dPijdt1;
 
    dw2[1] = dPijdt2;
 
}
 

	
 
double AuxinGrowthPlugin::complex_PijAj(CellBase *here, CellBase *nb, Wall *w) { 
 
	
 
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);
 
	
 
	return here->Chemical(1) * receptor_level / ( par->km + here->Chemical(1));
 
	
 
}
 

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

	
 
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;
 
	
 
	// 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;
 
		
 
		
 
		// source of auxin
 
		dchem[0] = par->aux_cons - par->aux_breakdown * c->Chemical(0);
 
		>
 
  }
 
	}
 
	
 
	
 
Q_EXPORT_PLUGIN2(auxingrowthplugin, AuxinGrowthPlugin)
 
	
 
}
 

	
 

	
 
Q_EXPORT_PLUGIN2(auxingrowthplugin, AuxinGrowthPlugin)
 
/* finis */
src/build_models/auxingrowthplugin.h
Show inline comments
 
@@ -52,12 +52,14 @@ public:
 
	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 2; }
 
	
 
private:
 
	double complex_PijAj(CellBase *here, CellBase *nb, Wall *w);
 
};
 

	
 
#endif
 

	
 
/* finis */
src/build_models/meinhardtplugin.cpp
Show inline comments
 
@@ -45,86 +45,82 @@ void MeinhardtPlugin::SetCellColor(CellB
 
		// somehow the function isnan doesn't work properly on my system... SuSE Linux
 
		// 10.0 64-bits (isnan seems not be implemented using fpclassify).
 
		MyWarning::warning("Whoops! Numerical instability!!");
 
		color->setNamedColor("red");
 
	} else {
 
		double range_min = 0.;//, range_max = 1.;
 
		if (c->Chemical(0)<range_min) {
 
			MyWarning::warning("Whoops! Numerical instability!!");
 
			color->setNamedColor("blue");
 
		} else {
 
			color->setRgb(c->Chemical(1)/(1+c->Chemical(1)) * 255.,(c->Chemical(0)/(1+c->Chemical(0)) * 255.),(c->Chemical(3)/(1+c->Chemical(3)) *255.) );
 
		}
 
		
 
	}
 
}
 

	
 

	
 

	
 
void MeinhardtPlugin::CellHouseKeeping(CellBase *c) {
 
	
 
	if (c->Area() > par->rel_cell_div_threshold * c->BaseArea() ) {
 
		c->Divide();
 
	}
 
	
 
    // cell expansion is inhibited by substrate (chem 3)
 
	if (!par->constituous_expansion_limit || c->NCells()<par->constituous_expansion_limit) {
 
		c->EnlargeTargetArea(par->cell_expansion_rate );
 
	} else {
 
		if (c->Chemical(0)<0.5) {
 
			double tmp;
 
			c->EnlargeTargetArea((tmp=(1.-par->vessel_inh_level*c->Chemical(3))*par->cell_expansion_rate /* + c->Chemical(4)*/)<0?0:tmp); 
 
		} else {
 
			c->EnlargeTargetArea(par->vessel_expansion_rate);
 
		}
 
	} 
 
    
 
}
 

	
 
void MeinhardtPlugin::CelltoCellTransport(Wall *w, double *dchem_c1, double *dchem_c2) {
 
	
 
	// No flux boundaries for all chemicals, except activator: boundary is sink
 
  if (w->C1()->BoundaryPolP() || w->C2()->BoundaryPolP()) {
 
		
 
		if (w->C1()->BoundaryPolP()) {
 
			dchem_c2[1] -=  w->Length() * ( par->D[1] ) * ( w->C2()->Chemical(1) );
 
			} else {
 
			dchem_c1[1] -=  w->Length() * ( par->D[1] ) * ( w->C1()->Chemical(1) );
 
			} 
 
		return;
 
		}
 
	
 

	
 
    // Passive fluxes (Fick's law)
 
    for (int c=0;c<NChem();c++) {
 
		double phi = w->Length() * ( par->D[c] ) * ( w->C2()->Chemical(c) - w->C1()->Chemical(c) );
 
		dchem_c1[c] += phi; 
 
		dchem_c2[c] -= phi;
 
	}
 
   
 

	
 
}
 

	
 
void MeinhardtPlugin::WallDynamics(Wall *w, double *dw1, double *dw2) {
 
  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);
 

	
 
	
 
	
 
    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 );
 
}
 

	
 

	
 
Q_EXPORT_PLUGIN2(meinhardtplugin, MeinhardtPlugin)
 

	
 
/* finis */
src/build_models/meinhardtplugin.h
Show inline comments
 
@@ -49,12 +49,14 @@ public:
 
	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 4; }
 
};
 

	
 
#endif
 

	
 
/* finis */
src/build_models/testplugin.cpp
Show inline comments
 
@@ -66,12 +66,14 @@ void TestPlugin::CelltoCellTransport(Wal
 

	
 
void TestPlugin::WallDynamics(Wall *w, double *dw1, double *dw2) {
 
  w = NULL;
 
  dw1 = dw2 = NULL;
 
}
 

	
 
void TestPlugin::CellDynamics(CellBase *c, double *dchem) {
 
  c = NULL;
 
  dchem=NULL;
 
}
 

	
 
Q_EXPORT_PLUGIN2(testplugin, TestPlugin)
 

	
 
/* finis */
src/build_models/testplugin.h
Show inline comments
 
@@ -49,12 +49,14 @@ public:
 
	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
 

	
 
/* finis */
src/build_models/translate_plugin.pl
Show inline comments
 
@@ -66,13 +66,15 @@ while (<hfile>) {
 
}
 

	
 
open pfile,"<$pfilename";
 
open opfile,">$opfname";
 

	
 
while (<pfile>) {
 
	
 
	s/\bplugin\b\.h/plugin_tl\.h/g;
 
	s/\bplugin\b\.cpp/plugin_tl\.cpp/g;
 
	
 
	print opfile;
 
	
 
}
 
\ No newline at end of file
 
}
 

	
 
#finis
src/canvas.cpp
Show inline comments
 
@@ -10,26 +10,24 @@
 
 *  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.
 
 *
 
 */
 

	
 
#include <QDebug>
 

	
 
#include <string>
 
#include <QGraphicsScene>
 
#include <QGraphicsView>
 
#include <qdatetime.h>
 
#include <q3mainwindow.h>
 
#include <qstatusbar.h>
 
#include <qmessagebox.h>
 
#include <qmenubar.h>
 
#include <qapplication.h>
 
#include <qpainter.h>
 
#include <qprinter.h>
 
#include <qlabel.h>
 
@@ -125,38 +123,38 @@ void FigureEditor::clear()
 
 {
 
   scaleView(pow((double)2, -event->delta() / 240.0));
 
 }
 

	
 

	
 
void FigureEditor::scaleView (qreal scaleFactor)
 
{
 
  qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)). width();
 
  if (factor < 0.07 || factor > 100) return;
 
  scale (scaleFactor, scaleFactor);
 
}
 

	
 
void FigureEditor::Save(const char *fname, const char *format, int sizex, int sizey) {
 
void FigureEditor::Save(const char *fname, const char *format, int sizex, int sizey)
 
{
 
  
 
    QImage *image = new QImage(sizex, sizey, QImage::Format_RGB32);
 
    image->fill(QColor(Qt::white).rgb());
 
    QPainter *painter=new QPainter(image);
 
    
 
    render(painter);
 
    
 
    image->save(QString(fname),format);
 
    delete painter;
 
    delete image;
 
}
 

	
 
//void FigureEditor::contentsMousePressEvent(QMouseEvent* e)
 
void FigureEditor::mousePressEvent(QMouseEvent* e)
 
{
 
  static QList<Node*> selected;
 
  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;
 
@@ -201,25 +199,24 @@ void FigureEditor::mousePressEvent(QMous
 
	  c.OnClick(e);
 
	} else {
 
	  if ( !strcmp(typeid(**it).name(),"8WallItem") ) {
 
	    (dynamic_cast<WallItem *>(*it))->OnClick(e);
 
	  } 
 
	}
 
    }
 

	
 
  FullRedraw();
 
  moving = 0;
 
}
 
  
 
//void FigureEditor::contentsMouseMoveEvent(QMouseEvent* e)
 
void FigureEditor::mouseMoveEvent(QMouseEvent* e)
 
{
 

	
 
  // User choose "rotation mode" and we can rotate the object around its center of mass
 
  if (dynamic_cast<Main *>(parent())->RotationModeP()) {
 

	
 
    QPointF p = mapToScene(e->pos());
 
    p.setX(p.x() / Cell::Magnification());
 
    p.setY(p.y() / Cell::Magnification());
 

	
 

	
 
    // get object's center of mass
 
@@ -383,52 +380,52 @@ void FigureEditor::mouseReleaseEvent(QMo
 
      if (intersection_line /* && !angle_line*/) {
 
	
 
	QPointF p = mapToScene(e->pos());
 
	QPointF sp = intersection_line->line().p1();
 
	
 
	viewport()->setMouseTracking( TRUE );
 
      } 
 
    }
 
}
 

	
 

	
 
// returns a vector of pointer to cells colliding with intersection line
 
vector <CellItem *> FigureEditor::getIntersectedCells(void) { 
 
  
 
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) {
 
void FigureEditor::FullRedraw(void)
 
{
 
	QList<QRectF> rl;
 
	rl << sceneRect();
 
	updateScene(rl);   
 
}
 

	
 

	
 
NodeItem *FigureEditor::selectedNodeItem(QList<QGraphicsItem *> graphicItems) const
 
{
 
  NodeItem *nodeItem = 0;
 
  // graphicItems is a list of the QgraphicItems under the mouse click event 
 
  QList<QGraphicsItem *>::Iterator it = graphicItems.begin();
 
  for (; it != graphicItems.end(); ++it) {
 
@@ -576,121 +573,119 @@ Main::Main(QGraphicsScene& c, Mesh &m, Q
 
  // 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;
 
	
 
	infobar = new InfoBar();
 
	addDockWindow(infobar);
 

	
 
}
 

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

	
 

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

	
 
void Main::UserMessage(QString message, int timeout)
 
{
 
  statusBar()->showMessage(message, timeout);
 

	
 
}
 

	
 

	
 
void Main::init()
 
{
 
  clear();
 
  
 
  static int r=24;
 
  srand(++r);
 
  
 
  mainCount++;
 
  
 
  
 
}
 

	
 
Main::~Main()
 
{
 
  delete printer;
 
  if ( !--mainCount ) {
 
  }
 
  //EndGifAnim();
 
}
 

	
 
void Main::newView()
 
{
 
  // Open a new view... have it delete when closed.
 
  Main *m = new Main(canvas, mesh, 0, 0, Qt::WDestructiveClose);
 
  qApp->setMainWidget(m);
 
  m->show();
 
  qApp->setMainWidget(0);
 
}
 

	
 

	
 
void Main::EditParameters() {
 
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() {
 
void Main::savePars()
 
{
 
  
 
  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);
 
  }
 

	
 
  startSimulation();
 

	
 
}
 

	
 
void Main::readPars() {
 
void Main::readPars()
 
{
 
  
 
  stopSimulation();
 
  
 
  Q3FileDialog *fd = new Q3FileDialog( this, "file dialog", TRUE );
 
  fd->setMode( Q3FileDialog::ExistingFile );
 
  fd->setFilter( "Parameter files (*.par)");
 

	
 
  QString fileName;
 
  if ( fd->exec() == QDialog::Accepted ) {
 
    fileName = fd->selectedFile();
 
    par.Read((const char *)fileName);
 
  }
 
  
 
  emit ParsChanged();
 
  /* if (timer_active)
 
     timer->start( 0 );*/
 
  
 
}
 

	
 

	
 
void Main::saveStateXML() {
 
void Main::saveStateXML()
 
{
 
  
 
  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,
 
@@ -699,30 +694,30 @@ void Main::saveStateXML() {
 
				  "Do you want to overwrite it?")
 
			       .arg( fileName ),
 
			       tr("&Yes"), tr("&No"),
 
			       QString::null, 1, 1 ) ) {
 
      return saveStateXML();
 
      
 
    } else {
 
      
 
      mesh.XMLSave((const char *)fileName, XMLSettingsTree());
 
    
 
    }
 
  }
 

	
 
}
 

	
 

	
 

	
 
void Main::snapshot() {
 
void Main::snapshot()
 
{
 
  
 
   
 
  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(
 
@@ -735,30 +730,30 @@ void Main::snapshot() {
 
			       QString::null, 1, 1 ) ) {
 
      return snapshot();
 
      
 
    } else {
 
      
 
      // extract extension from filename
 
		QString extension = getExtension(fileName);
 
		
 
		// Save bitmaps at 1024x768
 
		Save((const char *)fileName, extension, 1024, 768);
 
    }
 
  }
 

	
 
}
 

	
 
 
 

	
 
void Main::readPrevStateXML() {
 
void Main::readPrevStateXML()
 
{
 
  
 
  // if we have already read a file, read the next file
 
  if (!currentFile.isEmpty() && working_dir) {
 
    QString next_file;
 
    
 
    QStringList xml_files = working_dir->entryList("*.xml");
 
    QString currentFile_nopath = currentFile.section( '/', -1 );
 
    QString currentFile_path = currentFile.section( '/', 0, -2 );
 
    
 
    QList<QString>::iterator f = xml_files.find( currentFile_nopath );
 
   
 
    if (f == xml_files.end()) {
 
@@ -774,25 +769,26 @@ void Main::readPrevStateXML() {
 
		      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) {
 
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);
 
    
 
@@ -811,29 +807,29 @@ int Main::readStateXML(const char *filen
 
    #endif
 
    return 0;
 
  } catch (const char *error_message) {
 
    QMessageBox mb( "Read leaf from XML file",
 
		    QString(error_message),
 
		    QMessageBox::Critical,
 
		    QMessageBox::Ok | QMessageBox::Default,
 
		    Qt::NoButton,
 
		    Qt::NoButton);
 
    mb.exec();
 
    return 1;
 
  }
 
  
 
}
 

	
 

	
 
void Main::readNextStateXML() {
 
void Main::readNextStateXML()
 
{
 
  
 
  // if we have already read a file, read the next file
 
  if (!currentFile.isEmpty() && working_dir) {
 
    QString next_file;
 
    
 
    QStringList xml_files = working_dir->entryList("*.xml");
 
    QString currentFile_nopath = currentFile.section( '/', -1 );
 
    QString currentFile_path = currentFile.section( '/', 0, -2 );
 
    
 
    
 
    QList<QString>::iterator f = xml_files.find( currentFile_nopath );
 
   
 
@@ -848,72 +844,69 @@ void Main::readNextStateXML() {
 
		      QMessageBox::Information,
 
		      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);
 
  }
 
  
 
  
 
}
 

	
 
void Main::readLastStateXML() {
 
void Main::readLastStateXML()
 
{
 
  
 
  // if we have already read a file, read the next file
 
  if (!currentFile.isEmpty() && working_dir) {
 
    QString next_file;
 
    
 
    QStringList xml_files = working_dir->entryList("*.xml");
 
    QString currentFile_nopath = currentFile.section( '/', -1 );
 
    QString currentFile_path = currentFile.section( '/', 0, -2 );
 
    
 
    
 
    next_file = xml_files.back();
 
    
 
    next_file = currentFile_path+"/"+next_file;
 

	
 
    readStateXML((const char*)next_file);
 
  }
 
  
 
  
 
}
 

	
 

	
 
void Main::readFirstStateXML() {
 
void Main::readFirstStateXML()
 
{
 
  
 
  // if we have already read a file, read the next file
 
  if (!currentFile.isEmpty() && working_dir) {
 
    QString next_file;
 
    
 
    QStringList xml_files = working_dir->entryList("*.xml");
 
    QString currentFile_nopath = currentFile.section( '/', -1 );
 
    QString currentFile_path = currentFile.section( '/', 0, -2 );
 
    
 
    
 
    next_file = xml_files.front();
 
    
 
    next_file = currentFile_path+"/"+next_file;
 

	
 
    readStateXML((const char*)next_file);
 
  }
 
  
 
  
 
}
 

	
 
void Main::readStateXML() {
 
void Main::readStateXML()
 
{
 

	
 
  //  extern Mesh mesh;
 

	
 
  stopSimulation();
 
  #ifdef QDEBUG
 
  qDebug() << "Trying to open an OptionFileDialog" << endl;
 
  #endif
 
  OptionFileDialog *fd = new OptionFileDialog( this, "read dialog", TRUE );
 
  fd->setMode( OptionFileDialog::ExistingFile );
 
  fd->setFilter( "XML files (*.xml)");
 
  if (working_dir) {
 
    fd->setDir(*working_dir);
 
@@ -947,124 +940,136 @@ void Main::help()
 
      "Leaf growth computer model <br>"
 
      "(c) 2005-2007, Roeland Merks <br>"
 
      "VIB Department Plant Systems Biology <br>"
 
	 "Ghent, Belgium <br>"
 
      "(c) 2008-2009, Roeland Merks <br>"
 
      "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()
 
  {
 
void Main::aboutQt(){
 
    QMessageBox::aboutQt( this, "Virtual Leaf" );
 
  }
 

	
 
  void Main::toggleShowCellCenters()
 
  {
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowWalls()
 
  {
 
    Plot();
 
  }
 

	
 
void Main::toggleShowApoplasts()
 
{
 
    Plot();
 
}
 

	
 
  void Main::toggleShowNodes()
 
  {
 
    Plot();
 
  }
 

	
 
  void Main::toggleNodeNumbers(void) {
 
void Main::toggleNodeNumbers(void)
 
{
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellNumbers(void) {
 
void Main::toggleCellNumbers(void)
 
{
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellAxes(void) {
 
void Main::toggleCellAxes(void)
 
{
 
    Plot();
 
  }
 

	
 
  void Main::toggleCellStrain(void) {
 
void Main::toggleCellStrain(void)
 
{
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowFluxes(void) {
 
void Main::toggleShowFluxes(void)
 
{
 
    Plot();
 
  }
 

	
 
  void Main::toggleShowBorderCells(){
 
void Main::toggleShowBorderCells()
 
{
 
    Plot();
 
  }
 

	
 
void Main::toggleHideCells(void) {
 
void Main::toggleHideCells(void)
 
{
 
	Plot();
 
	editor->FullRedraw();
 
}
 

	
 
  void Main::toggleMovieFrames(){}
 

	
 
  void Main::toggleLeafBoundary(){}
 

	
 
  void Main::toggleDynCells() {}
 
  
 
  void Main::startSimulation(void) {
 
void Main::startSimulation(void)
 
{
 
    timer->start( 0 );
 
    statusBar()->message("Simulation started");
 
    running = true;
 
  }
 

	
 
  void Main::stopSimulation(void) {
 
void Main::stopSimulation(void)
 
{
 
    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();
 
    } else {
 
      cerr << "Calling stop simulation" << endl;
 
      stopSimulation();
 
    }
 
  }
 

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

	
 

	
 
  void Main::enlarge()
 
  {
 
    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::scale(double factor) {
 
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 );
 
  }
 

	
 
@@ -1101,201 +1106,211 @@ void Main::toggleHideCells(void) {
 
      // Note that Cell is also translated...
 
      pp.translate(-bbur.x,-bbur.y);
 
      if (cw>ch) {
 
	pp.scale(vp.width()/(2*cw*Cell::Magnification()), vp.width()/(2*cw*Cell::Magnification()));
 
      } else {
 
	pp.scale(vp.height()/(2*ch*Cell::Magnification()), vp.height()/(2*ch*Cell::Magnification()));
 
      }
 
      canvas.render(&pp, QRectF(), QRectF(0.,0.,canvas.width(),canvas.height()));
 
    }
 
  }
 

	
 

	
 
  void Main::TimeStepWrap(void) {
 
  
 
void Main::TimeStepWrap(void)
 
{
 
    static int t=0;
 
    TimeStep();
 
    t++;
 
    // check number of timesteps
 
    if (t==par.nit) {
 
      emit SimulationDone();
 
    }
 
  }
 

	
 

	
 
  void Main::RestartSim(void) {
 
void Main::RestartSim(void)
 
{
 

	
 
    stopSimulation();
 
    if ( QMessageBox::question(
 
			       this,
 
			       tr("Restart simulation?"),
 
			       tr("Restart simulation.\n"
 
				  "Are you sure?"),
 
							   QMessageBox::Yes | QMessageBox::No, QMessageBox::NoButton ) == QMessageBox::Yes ) {
 

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

	
 

	
 
void Main::FitCanvasToWindow(void) {
 
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;
 
  
 
  qDebug() << "scale_factor = " << scale_factor << endl;
 
  qDebug() << "scale_factor_x = " << scale_factor_x << endl;
 
  qDebug() << "scale_factor_y = " << scale_factor_y << endl;
 
  #endif
 
  m.scale( scale_factor, scale_factor );
 
  editor->setMatrix( m );
 
  editor->show();
 
}
 

	
 
  void Main::PauseIfRunning(void) {
 
void Main::PauseIfRunning(void)
 
{
 
    if (running) {
 
      timer->stop();
 
    }
 
  }
 

	
 
  void Main::ContIfRunning(void) {
 
void Main::ContIfRunning(void)
 
{
 
    if (running) {
 
      timer->start( 0 );
 
    }
 
  }
 

	
 
void Main::FitLeafToCanvas(void) {
 
void Main::FitLeafToCanvas(void) 
 
{
 

	
 
  Vector ll,ur;
 
  mesh.BoundingBox(ll, ur);
 
  
 
  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 );
 
  
 
  
 
  // cerr << ur << ", " << ll << endl;
 
  editor->fitInView(bb, Qt::KeepAspectRatio);
 
}
 

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

	
 
	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();
 
}
 

	
 
void Main::CleanMeshChemicals(void) {
 
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();
 
}
 

	
 
void Main::CleanMeshTransporters(void) {
 
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();
 
}
 

	
 
void Main::RandomizeMesh(void) {
 
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];
 
  }
 

	
 
  // Amount of PIN1 at walls
 
  max_transporters[1] = 0.01;
 
  
 
  mesh.RandomizeChemicals(max_chem, max_transporters);
 
  
 
  Plot();
 
}
 

	
 
void Main::XMLReadSettings(xmlNode *settings) {
 
void Main::XMLReadSettings(xmlNode *settings) 
 
{
 
  
 
  MainBase::XMLReadSettings(settings);
 

	
 
  view->setItemChecked(com_id, showcentersp);
 
  view->setItemChecked(mesh_id, showmeshp);
 
  view->setItemChecked(border_id, showbordercellp);
 
  view->setItemChecked(node_number_id, shownodenumbersp);
 
  view->setItemChecked(cell_number_id, showcellnumbersp);
 
  view->setItemChecked(cell_axes_id, showcellsaxesp);
 
  view->setItemChecked(cell_strain_id, showcellstrainp);
 
  view->setItemChecked(movie_frames_id, movieframesp);
 
  view->setItemChecked(only_boundary_id, showboundaryonlyp);
 
  view->setItemChecked(fluxes_id, showfluxesp);
 
  view->setItemChecked(hide_cells_id, hidecellsp);
 
  options->setItemChecked(dyn_cells_id, dynamicscellsp);
 
  view->setItemChecked( cell_walls_id, showwallsp);
 
	view->setItemChecked( apoplasts_id, showapoplastsp);
 
}
 

	
 
xmlNode *Main::XMLSettingsTree(void) {
 
xmlNode *Main::XMLSettingsTree(void) 
 
{
 

	
 
  showcentersp = view->isItemChecked(com_id);
 
  showmeshp = view->isItemChecked(mesh_id);
 
  showbordercellp =  view->isItemChecked(border_id);
 
  shownodenumbersp =  view->isItemChecked(node_number_id);
 
  showcellnumbersp =  view->isItemChecked(cell_number_id);
 
  showcellsaxesp = view->isItemChecked( cell_axes_id );
 
  showcellstrainp = view->isItemChecked( cell_strain_id );
 
  movieframesp = view->isItemChecked(movie_frames_id);;
 
  showboundaryonlyp =  view->isItemChecked(only_boundary_id);
 
  showfluxesp = view->isItemChecked(fluxes_id);
 
  dynamicscellsp = options->isItemChecked(dyn_cells_id);
 
  showwallsp = view->isItemChecked( cell_walls_id);
 
	showapoplastsp = view->isItemChecked( apoplasts_id);
 
  hidecellsp = view->isItemChecked( hide_cells_id);
 

	
 
  return MainBase::XMLSettingsTree();
 
}
 

	
 
/* finis */
 

	
src/canvas.h
Show inline comments
 
@@ -119,25 +119,26 @@ class Main : public Q3MainWindow, public
 
  virtual bool ShowCellStrainP(void) {return view->isItemChecked(cell_strain_id);}
 
  virtual bool MovieFramesP(void) {return view->isItemChecked(movie_frames_id);}
 
  virtual bool ShowBoundaryOnlyP(void) {return view->isItemChecked(only_boundary_id);}
 
  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) {
 
  virtual double getFluxArrowsize(void)
 
  {
 
    return flux_arrow_size;
 
  }
 
    
 
  void FitCanvasToWindow();
 
  void FitLeafToCanvas(void);
 

	
 

	
 
  public slots:
 

	
 
  void help();
 
  void TimeStepWrap();
 
  void togglePaused();
 
@@ -153,36 +154,38 @@ class Main : public Q3MainWindow, public
 
  void toggleCellStrain(void);
 
  void toggleShowWalls(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) {
 
  void EnterRotationMode(void)
 
  {
 

	
 
    UserMessage("Rotation mode. Click mouse to exit.");
 
    if (editor) {
 
      editor->rot_angle = 0. ; 
 

	
 
      // Exit rotation mode if mouse is clicked
 
      connect(editor, SIGNAL(MousePressed()), this, SLOT(ExitRotationMode()));
 
    }
 
  
 
  }
 
  void ExitRotationMode(void) { 
 
  void ExitRotationMode(void)
 
  { 
 
    UserMessage("Exited rotation mode.",2000);
 

	
 
    options->setItemChecked(rotation_mode_id, false); 
 
    if (editor)
 
      disconnect(editor, SIGNAL(MousePressed()), this, SLOT(ExitRotationMode()));
 
  }
 

	
 
  virtual void UserMessage(QString message, int timeout=0);
 
  void Refresh(void) { Plot(); }
 
  void PauseIfRunning(void);
 
  void ContIfRunning(void);
 
  virtual void XMLReadSettings(xmlNode *settings);
 
@@ -254,18 +257,17 @@ class Main : public Q3MainWindow, public
 
  int movie_frames_id;
 
  int fluxes_id;
 
  int dyn_cells_id;
 
  int rotation_mode_id;
 
  int insert_mode_id;
 
  QTimer *timer;
 
  QFile *gifanim;
 
  bool running;
 
  virtual xmlNode *XMLSettingsTree(void);
 
  static const QString caption;
 
  static const QString caption_with_file;
 
	InfoBar *infobar;
 

	
 
};
 

	
 

	
 
#endif
 

	
 
#endif
 
/* finis*/
src/cell.cpp
Show inline comments
 
@@ -31,53 +31,52 @@
 
#include "nodeitem.h"
 
#include "qcanvasarrow.h"
 
#include "parameter.h"
 

	
 

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

	
 
extern Parameter par;
 

	
 
double Cell::factor=1.;
 
double Cell::offset[3]={0,0,0};
 

	
 
Cell::Cell(void) : CellBase() {
 

	
 
Cell::Cell(void) : CellBase()
 
{
 
	m=0;
 

	
 
}
 

	
 
Cell::Cell(double x, double y, double z) : CellBase(x,y,z) {
 

	
 
Cell::Cell(double x, double y, double z) : CellBase(x,y,z)
 
{
 
	m=0;
 
	
 
}
 

	
 
Cell::Cell(const Cell &src) :  CellBase(src) {
 
	
 
Cell::Cell(const Cell &src) :  CellBase(src)
 
{
 
	m=src.m;
 
}
 

	
 
bool Cell::Cmp(Cell *c) const { return this->Index() < c->Index(); }
 
bool Cell::Eq(Cell *c) const { return this->Index() == c->Index(); }
 

	
 
Cell Cell::operator=(const Cell &src) {
 
Cell Cell::operator=(const Cell &src) 
 
{
 
	CellBase::operator=(src);
 
	m=src.m;
 
	return *this;
 
}
 
//Cell(void) : CellBase() {}
 

	
 
void Cell::DivideOverAxis(Vector axis) {
 
	
 
void Cell::DivideOverAxis(Vector axis) 
 
{
 
	// Build a wall
 
	// ->  find the position of the wall
 
	
 
	// better look for intersection with a simple line intersection algorithm as below?
 
	// this leads to some exceptions: e.g. dividing a horizontal rectangle.
 
	// leaving it like this for the time being
 
	
 
	if (dead) return;
 
	
 
	Vector centroid=Centroid();
 
	double prev_cross_z=(axis * (centroid - *(nodes.back()) ) ).z ;
 
		
 
@@ -90,33 +89,34 @@ void Cell::DivideOverAxis(Vector axis) {
 
		// 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);
 
			
 
		}		
 
		prev_cross_z=cross.z;
 
	}
 
	
 
	DivideWalls(new_node_locations, centroid, centroid+axis);
 
}
 
	
 
}
 
double Cell::MeanArea(void) {
 
double Cell::MeanArea(void)
 
{
 
	return m->MeanArea();
 
}
 

	
 

	
 
void Cell::Apoptose(void) {
 
	
 
void Cell::Apoptose(void)
 
{
 
	// First kill walls
 
        #ifdef QDEBUG
 
        qDebug() << "This is cell " << Index() << endl;
 
	qDebug() << "Number of walls: " << walls.size() << endl;
 
	#endif
 
	for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
             #ifdef QDEBUG
 
	     qDebug() << "Before apoptosis, wall " << (*w)->Index() << " says: c1 = "
 
		      << (*w)->c1->Index() << ", c2 = " << (*w)->c2->Index() << endl;
 
             #endif
 
	}
 
	for (list<Wall *>::iterator w=walls.begin();
 
@@ -159,25 +159,24 @@ void Cell::Apoptose(void) {
 
			  qDebug() << "Wall " << (*w)->Index() << " says: c1 = " 
 
				   << (*w)->c1->Index() << ", c2 = " << (*w)->c2->Index() << endl;
 
			}
 
			#endif
 
			(*w)=0;
 
		} else {
 
		        #ifdef QDEBUG
 
		        qDebug() << "Not killing wall." << endl;
 
			qDebug() << "Wall " << (*w)->Index() << " says: c1 = " 
 
				 << (*w)->c1->Index() << ", c2 = " << (*w)->c2->Index() << endl;
 
                        #endif
 
		}
 
		
 
	}
 
	walls.remove(0);
 
	
 
	// Unregister me from my nodes, and delete the node if it no longer belongs to any cells
 
	list<Node *> superfluous_nodes;
 
	for (list<Node *>::iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		
 
		Node &no(*(*n));
 
		// locate myself in the node's owner list
 
		list<Neighbor>::iterator cellpos;
 
@@ -206,32 +205,30 @@ void Cell::Apoptose(void) {
 
			no.MarkDead();
 
		} else {
 
			// 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);
 
			}
 
		}
 
	}
 
	
 
	
 
	
 
	// mark cell as dead
 
	MarkDead();
 
}
 

	
 
void Cell::ConstructConnections(void) {
 
	
 
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();
 
		 i++) {
 
		
 
		//cerr << "Connecting node " << *i << endl;
 
		//cerr << "Node " << *i << endl << " = " << *(*i) << endl;
 
		// 1. Tidy up existing connections (which are part of this cell)
 
		if ((*i)->owners.size()>0) {
 
@@ -252,52 +249,32 @@ void Cell::ConstructConnections(void) {
 
		} else {
 
			previous=nodes.back();
 
		}
 
		
 
		Node *next;
 
		list<Node *>::iterator next_iterator=i;
 
		next_iterator++;
 
		if (next_iterator==nodes.end()) {
 
			next=nodes.front();
 
		} else {
 
			next=*next_iterator;
 
		}
 
		
 
		//cerr << "[" << *i << "]";
 
		//if (*i==10 || *i==11) {
 
		//cerr << "previous = " << previous << ", next = " << next << endl;
 
		//}
 
		//if (*i!=10 && *i!=11)
 
		//cerr << "Node " << *i << endl << " = " << *(*i) << endl;
 
		(*i)->owners.push_back( Neighbor( this, previous, next ) );
 
		// if (*i==50 || *i==51) {
 
		//cerr << "Node " << *i << ".size() = " << (*i)->owners.size() << endl;
 
		// }
 
    }
 
}
 

	
 

	
 
/*! \brief Divide the cell over the line v1-v2.
 
 
 
 \param v1: First vertex of line.
 
 \param v2: Second vertex of line.
 
 \param fixed_wall: If true: wall will be set to "fixed" (i.e. not motile)
 
 \return: true if the cell divided, false if not (i.e. no intersection between v1 and v2, and the cell)
 
 */
 
bool Cell::DivideOverGivenLine(const Vector v1, const Vector v2, bool fix_cellwall, NodeSet *node_set ) {
 
	
 
bool Cell::DivideOverGivenLine(const Vector v1, const Vector v2, bool fix_cellwall, NodeSet *node_set )
 
{
 
	if (dead) return false;
 
	
 
	
 
	
 
	// check each edge for intersection with the line
 
	ItList new_node_locations;
 
	
 
	#ifdef QDEBUG
 
	qDebug() << "Cell " << Index() << " is doing DivideOverGivenLine" << endl;
 
	#endif
 
	for (list<Node *>::iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		
 
		Vector v3 = *(*i);
 
		list<Node *>::iterator nb=i;
 
@@ -344,29 +321,29 @@ bool Cell::DivideOverGivenLine(const Vec
 
	qDebug() << (*j)->Index() << endl;
 
	qDebug() << "-------------------------------" << endl;
 
    
 
	if ( **new_node_locations.begin() == *j ) {
 
	  qDebug() << "Rejecting proposed division (cutting off zero area)." << endl;
 
		return false;
 
	}
 
	#endif
 

	
 
	DivideWalls(new_node_locations, v1, v2, fix_cellwall, node_set);
 
	
 
	return true;
 
	
 
}
 

	
 
// Core division procedure
 
void Cell::DivideWalls(ItList new_node_locations, const Vector from, const Vector to, bool fix_cellwall, NodeSet *node_set) {
 
void Cell::DivideWalls(ItList new_node_locations, const Vector from, const Vector to, bool fix_cellwall, NodeSet *node_set)
 
{
 
	
 
	if (dead) return;
 
	
 
	bool boundary_touched_flag=false;
 
	
 
	// Step 0: keep some data about the parent before dividing
 
	
 
	ParentInfo parent_info;
 
	parent_info.polarization = ReduceCellAndWalls<Vector>( PINdir );
 
	parent_info.polarization.Normalise();
 
	parent_info.PINmembrane = SumTransporters(1);
 
	parent_info.PINendosome = Chemical(1);
 
@@ -378,34 +355,32 @@ void Cell::DivideWalls(ItList new_node_l
 
    
 
	// 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;
 
	
 
	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;
 
	
 
	
 
	// 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;
 
		
 
		// Reject the daughter cell and decrement the amount of cells
 
		// again. We can do this here because it is the last cell added.
 
@@ -417,25 +392,24 @@ void Cell::DivideWalls(ItList new_node_l
 
		#ifdef QDEBUG
 
		qDebug() << "new_node_locations.size() = " << new_node_locations.size() <<endl;
 
		qDebug() << "daughter->index = " << daughter->index << endl;
 
		qDebug() << "cells.size() = " << m->cells.size() << endl;
 
		#endif
 

	
 
		m->cells.pop_back();
 
		Cell::NCells()--;
 
		m->shuffled_cells.pop_back();
 
		return;
 
	}
 
	
 
	
 
	// We can be sure we only need two positions here because divisions
 
	// of non-convex cells are rejected above.
 
	Vector new_node[2];
 
	Node *new_node_ind[2];
 
	
 
	int new_node_flag[2];
 
	Edge div_edges[2];
 
	
 
	int nnc=0;
 
	
 
	Wall *div_wall[4];
 
	double orig_length[2];
 
@@ -620,25 +594,27 @@ void Cell::DivideWalls(ItList new_node_l
 
			
 
			
 
			// find first non-self duplicate in the owners: 
 
			// cells owning the same two nodes
 
			// share an edge with me
 
			owners.sort( mem_fun_ref( &Neighbor::Cmp ) );
 

	
 

	
 
                        #ifdef QDEBUG  
 
			list<Neighbor> unique_owners;
 
			copy(owners.begin(), owners.end(), back_inserter(unique_owners));
 
			unique_owners.unique( mem_fun_ref( &Neighbor::Eq ) );
 
			qDebug() << "The dividing edge nodes: " << div_edges[i].first->Index() << " and " << div_edges[i].second->Index() << " are owned by cells: ";
 
      qDebug() << "The dividing edge nodes: " << div_edges[i].first->Index() 
 
	       << " and " << div_edges[i].second->Index() << " are owned by cells: ";
 

	
 
			// spit out each owners' cell index
 
			foreach(Neighbor neighbor, unique_owners){
 
			  qDebug() << neighbor.cell->Index() << "  ";
 
			}
 
			qDebug() << endl;
 
                        #endif
 

	
 
			// Search through the sorted list of edge node owners looking for duplicate pairs. Each pair represents an actual edge owner.
 
			list<Neighbor> edge_owners;
 
			list<Neighbor>::iterator it;
 
			for (it=owners.begin(); it!=owners.end(); it++) {
 
			  it = adjacent_find(it, owners.end(), neighbor_cell_eq);
 
@@ -648,25 +624,26 @@ void Cell::DivideWalls(ItList new_node_l
 
                          #endif
 
			  if (it->cell->Index() != this->Index()) {
 
                            #ifdef QDEBUG
 
			    qDebug() << "Adding: " << it->cell->Index() << " to the list of edge owners." << endl;
 
                            #endif
 
			    edge_owners.push_back(*it);
 
			  }
 
			} 
 

	
 
			if (edge_owners.size() > 1){
 
			  // Remove the boundary polygon - if its there
 
			  list<Neighbor>::iterator it;
 
			  if ((it = find_if (edge_owners.begin(), edge_owners.end(), bind2nd(mem_fun_ref(&Neighbor::CellEquals), -1))) != edge_owners.end()) {
 
	if ((it = find_if (edge_owners.begin(), edge_owners.end(), bind2nd(mem_fun_ref(&Neighbor::CellEquals), -1)))
 
	    != edge_owners.end()) {
 
                            #ifdef QDEBUG
 
			    qDebug() << "deleating: " << it->cell->Index() << " from the list of edge owners." << endl;
 
                            #endif
 
			    edge_owners.erase(it);
 
			  }
 
			}
 

	
 
                        #ifdef QDEBUG
 
			qDebug() << "The edge owners list has: " << edge_owners.size() << " elements" << endl;
 
			#endif
 

	
 
			// Since the list should always contain exactly one element, pass it on as an iterator
 
@@ -836,24 +813,25 @@ void Cell::DivideWalls(ItList new_node_l
 
		}
 
		list<Node *>::iterator i=start;
 
		while ( i!=stop) {
 
			
 
			// give the node to the daughter
 
			// (find references to parent cell from this node,
 
			// and remove them)
 
			list<Neighbor>::iterator neighb_with_this_cell=
 
			find_if((*i)->owners.begin(),
 
					(*i)->owners.end(),
 
				bind2nd(mem_fun_ref( &Neighbor::CellEquals ),this->Index() )  );
 
			if (neighb_with_this_cell==(*i)->owners.end()) {
 

	
 
			        #ifdef QDEBUG
 
			  qDebug() << "not found" << endl;
 
                                #endif
 
				abort();
 
			}
 
			
 
			(*i)->owners.erase(neighb_with_this_cell);
 
			
 
			daughter->nodes.push_back( *i );
 
			
 
			
 
			i++;
 
@@ -972,100 +950,92 @@ void Cell::DivideWalls(ItList new_node_l
 
	// collecting neighbors of divided cell
 
	list<CellBase *> broken_neighbors;
 
	
 
	// this cell's old neighbors
 
	copy(neighbors.begin(), neighbors.end(), back_inserter(broken_neighbors) );
 
	
 
	// this cell
 
	broken_neighbors.push_back(this);
 
	
 
	// its daughter
 
	broken_neighbors.push_back(daughter);
 
	
 
	
 
	
 
	// Recalculate area of parent and daughter
 
	area = CalcArea();
 
	daughter->area = daughter->CalcArea();
 
	
 
	SetIntegrals();
 
	daughter->SetIntegrals();
 
	
 
    
 
	
 
	// Add a "Cell Wall" for diffusion algorithms
 
	Wall *wall = new Wall( new_node_ind[0], new_node_ind[1], this, daughter );
 
	
 
	AddWall( wall );
 
	
 
	daughter->AddWall( wall );
 
	
 
	//cerr << "Correct walls of cell " << Index() << " and daughter " << daughter->Index() << endl;
 
	
 
	// Move Walls to daughter cell
 
	list <Wall *> copy_walls = walls;
 
	for (list<Wall *>::iterator w = copy_walls.begin();
 
		 w!=copy_walls.end();
 
		 w++) {
 
		
 
		//cerr << "Doing wall, before:  " << **w << endl;
 
		
 
		//  checks the nodes of the wall and gives it away if appropriate
 
		(*w)->CorrectWall ( );
 
		
 
		//cerr << "and after: " << **w << endl;
 
		
 
	}
 
	
 
	
 
	
 
	// 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]);
 
		}
 
	}
 
	
 
	//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);
 
	
 
	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++) {
 
		*(*i)+=T;
 
    }
 
}
 

	
 
double Cell::Displace(double dx, double dy, double dh) {
 
double Cell::Displace(double dx, double dy, double dh)
 
{
 
	
 
	// Displace whole cell, add resulting energy to dh,
 
	// and accept displacement if energetically favorable
 
	// 
 
	// Method is called if a "fixed" node is displaced
 
	
 
	// Warning: length constraint not yet  CORRECTLY implemented for this function
 
	
 
	// Attempt to move this cell in a random direction
 
	//  Vector movement(par.mc_cell_stepsize*(RANDOM()-0.5),par.mc_cell_stepsize*(RANDOM()-0.5),0);
 
	
 
	
 
@@ -1149,31 +1119,32 @@ double Cell::Displace(double dx, double 
 
		//cerr << endl;
 
		
 
	} else {
 
		
 
		Move ( -1*movement);
 
		
 
	}
 
	
 
	return dh;
 
}
 

	
 

	
 
void Cell::Displace (void) {
 
void Cell::Displace (void)
 
{
 
	Displace(par.mc_cell_stepsize*(RANDOM()-0.5),par.mc_cell_stepsize*(RANDOM()-0.5),0);
 
}
 

	
 
// Get energy level of whole cell (excluding length constraint?)
 
double Cell::Energy(void) const {
 
	
 
double Cell::Energy(void) const
 
{
 
	double energy = 0.;
 
	double length_contribution = 0.;
 
	
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		
 
		for (list<Neighbor>::const_iterator n=(*i)->owners.begin();
 
			 n!=(*i)->owners.end();
 
			 n++) {
 
			
 
			if (n->getCell()==this) {
 
@@ -1184,38 +1155,35 @@ double Cell::Energy(void) const {
 
				
 
			}
 
		}
 
	}
 
	
 
	// wall elasticity constraint
 
	energy += par.lambda_length * length_contribution;
 
	
 
	// area constraint
 
	energy += DSQR(CalcArea() - target_area);
 
	
 
	// cell length constraint
 
	
 
	
 
	energy += lambda_celllength * DSQR(Length() - target_length);
 
	
 
	
 
	return energy;
 
}
 

	
 

	
 

	
 

	
 

	
 
bool Cell::SelfIntersect(void) {
 
	
 
bool Cell::SelfIntersect(void)
 
{
 
    // The (obvious) O(N*N) algorithm
 
	
 
    // Compare each edge against each other edge
 
	
 
    // An O(N log(N)) algorithm by Shamos & Hoey (1976) supposedly exists;
 
    // it was mentioned on comp.graphics.algorithms
 
	
 
    // But I haven't been able to lay my hand on the paper.
 
    // Let's try whether we need it....
 
	
 
    // method used: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
 
	
 
@@ -1256,25 +1224,26 @@ bool Cell::SelfIntersect(void) {
 
			
 
			if ( ( TINY < ua && ua < 1.-TINY ) && ( TINY < ub && ub < 1.-TINY ) ) {
 
				//cerr << "ua = " << ua << ", ub = " << ub << endl;
 
				return true;
 
			}
 
		}
 
    }
 
	
 
    return false;
 
}
 

	
 

	
 
bool Cell::MoveSelfIntersectsP(Node *moving_node_ind, Vector new_pos) {
 
bool Cell::MoveSelfIntersectsP(Node *moving_node_ind, Vector new_pos)
 
{
 
	
 
	// Check whether the polygon will self-intersect if moving_node_ind 
 
	// were displaced to new_pos
 
	
 
	// Compare the two new edges against each other edge
 
	
 
	// O(2*N)
 
	
 
	// method used for segment intersection:
 
	// http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
 
	
 
	Vector neighbor_of_moving_node[2];
 
@@ -1323,99 +1292,87 @@ bool Cell::MoveSelfIntersectsP(Node *mov
 
			
 
			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;
 
			
 
			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.
 
 
 
 */
 
bool Cell::IntersectsWithLineP(const Vector v1, const Vector v2) {
 
	
 
	
 
bool Cell::IntersectsWithLineP(const Vector v1, const Vector v2)
 
{
 
	// Compare the line against each edge
 
	
 
	// method used: http://astronomy.swin.edu.au/~pbourke/geometry/lineline2d/
 
	
 
	
 
	
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) 
 
  for (list<Node *>::const_iterator i=nodes.begin(); i!=nodes.end(); i++) 
 
    {
 
		
 
		Vector v3 = *(*i);
 
		list<Node *>::const_iterator nb=i;
 
		nb++;
 
		if (nb == nodes.end()) {
 
			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;
 
		
 
		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,
 
 making transport algorithms computationally more intensive than needed.
 
 
 
 We can remove this? Well, let's leave it in the code in case we need it for something else. E.g. for importing leaf architectures in different formats than our own... :-)
 
 
 
 */
 
void Cell::ConstructWalls(void) {
 
	
 
void Cell::ConstructWalls(void)
 
{
 
	return;
 
	if (dead) return;
 
	
 
	walls.clear();
 
	neighbors.clear();
 
	
 
	// Get "corner points; i.e. nodes where more than 2 cells are connected
 
	list<Node *> corner_points;
 
	
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();i++) {
 
		
 
		// look for nodes belonging to >2 cells
 
		if ((*i)->owners.size()>2) {
 
			
 
			// push onto list
 
			corner_points.push_back(*i);
 
		}
 
		
 
	}
 
	
 
	// Construct Walls between corner points
 
	
 
	// previous one in list
 
	list<Node *>::const_iterator nb = (--corner_points.end());
 
	
 
	// loop over list, 
 
	for (list<Node *>::const_iterator i=corner_points.begin();
 
		 i!=corner_points.end(); ( i++, nb++) ) {
 
		
 
		if (nb==corner_points.end()) nb=corner_points.begin();
 
@@ -1450,82 +1407,77 @@ void Cell::ConstructWalls(void) {
 
			if (*j==*prevj) duplicates.push_back(*j);
 
			
 
		}
 
		
 
		
 
		if (duplicates.size()==3) { // ignore cell boundary (this occurs only after the first division, I think)
 
			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) {
 
			AddWall(  new Wall(*nb,*i,duplicates[0],duplicates[1]) );
 
			if (!duplicates[1]->BoundaryPolP()) {
 
				
 
				neighbors.push_back(duplicates[1]);
 
			}
 
		} else {
 
			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) {
 
void BoundaryPolygon::Draw(QGraphicsScene *c, QString tooltip)
 
{
 
	
 
	// Draw the BoundaryPolygon on a QCanvas object
 
	
 
	
 
	CellItem* p = new CellItem(this, c);
 
	
 
	QPolygonF pa(nodes.size());
 
	int cc=0;
 
	
 
	for (list<Node *>::const_iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		Node *i=*n;
 
		
 
		pa[cc++] = QPoint((int)((Offset().x+i->x)*Factor()),
 
						  (int)((Offset().y+i->y)*Factor()) );
 
	}
 
	
 
	
 
	p->setPolygon(pa);
 
	p->setPen(par.outlinewidth>=0?QPen( QColor(par.cell_outline_color),par.outlinewidth):QPen(Qt::NoPen));
 
	p->setBrush( Qt::NoBrush );
 
	p->setZValue(1);
 
	
 
	if (!tooltip.isEmpty())
 
		p->setToolTip(tooltip);
 
	
 
	p->show();
 
	
 
}
 

	
 
void Cell::Flux(double *flux, double *D)  {
 
	
 
	
 
void Cell::Flux(double *flux, double *D)
 
{
 
	// loop over cell edges
 
	
 
	for (int c=0;c<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->BoundaryPolP()) continue;
 
		
 
@@ -1534,34 +1486,34 @@ void Cell::Flux(double *flux, double *D)
 
		for (int c=0;c<NChem();c++) {
 
			double phi = (*i)->length * ( D[c] ) * ( ((Cell *)(*i)->c2)->chem[c] - chem[c] );
 
			
 
			#ifdef QDEBUG
 
			if ((*i)->c1!=this) {
 
			  qDebug() << "Warning, bad cells boundary: " << (*i)->c1->Index() << ", " << index << endl;
 
			}
 
			#endif
 
			
 
			flux[c] += phi;
 
		}    
 
	}
 
	
 
}
 

	
 

	
 
// graphics stuff, not compiled for batch versions
 
#ifdef QTGRAPHICS
 

	
 
#include "canvas.h"
 

	
 
void Cell::Draw(QGraphicsScene *c, QString tooltip) {
 
void Cell::Draw(QGraphicsScene *c, QString tooltip)
 
{
 
	
 
	// Draw the cell on a QCanvas object
 
	
 
	if (DeadP()) { 
 
	        #ifdef QDEBUG
 
	  qDebug() << "Cell " << index << " not drawn, because dead." << endl;
 
		#endif
 
		return;
 
	}
 
	
 
	CellItem* p = new CellItem(this, c);
 
	
 
@@ -1582,25 +1534,24 @@ void Cell::Draw(QGraphicsScene *c, QStri
 
	
 
	m->plugin->SetCellColor(this,&cell_color);
 
	
 
	p->setPolygon(pa);
 
	p->setPen(par.outlinewidth>=0?QPen( QColor(par.cell_outline_color),par.outlinewidth):QPen(Qt::NoPen));
 
	p->setBrush( cell_color );
 
	p->setZValue(1);
 
	
 
	if (!tooltip.isEmpty())
 
		p->setToolTip(tooltip);
 
	
 
	p->show();
 
	
 
}
 

	
 

	
 
void Cell::DrawCenter(QGraphicsScene *c) const {
 
  // Maginfication derived similarly to that in nodeitem.cpp
 
  // Why not use Cell::Magnification()?
 
  const double mag = par.node_mag;
 
	
 
	// construct an ellipse
 
  QGraphicsEllipseItem *disk = new QGraphicsEllipseItem ( -1*mag, -1*mag, 2*mag, 2*mag, 0, c );
 
	disk->setBrush( QColor("forest green") );
 
	disk->setZValue(5);
 
@@ -1615,44 +1566,42 @@ void Cell::DrawNodes(QGraphicsScene *c) 
 
		 n!=nodes.end();
 
		 n++) {
 
		Node *i=*n;
 
		
 

	
 
		NodeItem *item = new NodeItem ( &(*i), c );
 
		item->setColor();
 
		item->setZValue(5);
 
		item->show();
 
		item ->setPos(((offset[0]+i->x)*factor),
 
					  ((offset[1]+i->y)*factor) );
 
	}
 
	
 
}
 

	
 
void Cell::DrawIndex(QGraphicsScene *c) const {
 
	
 
	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->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);
 
	
 
	//cerr << "Length is "  << length << endl;
 
	long_axis.Normalise();
 
	Vector short_axis=long_axis.Perp2D();
 
@@ -1664,85 +1613,84 @@ void Cell::DrawAxis(QGraphicsScene *c) c
 

	
 
	
 
	QGraphicsLineItem *line = new QGraphicsLineItem(0, c);
 
	line->setPen( QPen(QColor(par.arrowcolor),2) );
 
	line->setZValue(2);
 
    
 
	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.");
 
}
 

	
 

	
 
void Cell::DrawFluxes(QGraphicsScene *c, double arrowsize)  {
 
void Cell::DrawFluxes(QGraphicsScene *c, double arrowsize)
 
{
 
	
 
	// get the mean flux through this cell
 
	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.;
 
    
 
	
 
	arrow->setPen( QPen(QColor(par.arrowcolor),par.outlinewidth));
 
	arrow->setZValue(2);
 
	
 
	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();
 
	
 
}
 

	
 

	
 
void Cell::DrawWalls(QGraphicsScene *c) const {
 
	
 
	for_each(walls.begin(), walls.end(), bind2nd ( mem_fun ( &Wall::Draw ) , c ) );
 
	
 
	// to see the cells connected the each wall (for debugging), uncomment the following
 
	//for_each(walls.begin(), walls.end(), bind2nd ( mem_fun ( &Wall::ShowStructure ), c ) );
 
}
 

	
 

	
 
void Cell::DrawValence(QGraphicsScene *c) const {
 
	
 
	DrawText(c, QString("%1").arg(walls.size()) );
 
	
 
}
 

	
 
#endif
 
#endif // QTGRAPHICS !
 

	
 
/*! \brief Recalculate the lengths of the cell's Walls.
 
 
 
 Call this function after the Monte Carlo updates, and before doing the reaction-diffusion iterations.
 
 
 
 */
 
void Cell::SetWallLengths(void) {
 
void Cell::SetWallLengths(void)
 
{
 
	
 
	for (list<Wall *>::iterator de=walls.begin();
 
		 de!=walls.end();
 
		 de++) {
 
		
 
		// Step 1: find the path of nodes leading along the Wall.
 
		// A Wall often represents a curved cell wall: we want the total
 
		// length _along_ the wall here...
 
		
 
		
 
		// Locate first and second nodes of the edge in list of nodes
 
		list<Node *>::const_iterator first_node_edge = find(nodes.begin(), nodes.end(), (*de)->n1);
 
@@ -1770,63 +1718,59 @@ void Cell::SetWallLengths(void) {
 
		}
 
		
 
		// We got the total length of the Wall now, store it:
 
		(*de)->length = sum_length;
 
		
 
		//cerr << endl;
 
		// goto next de
 
	}
 
}
 

	
 

	
 
//! Add Wall w to the list of Walls
 
void Cell::AddWall( Wall *w ) {
 
void Cell::AddWall( Wall *w )
 
{
 
	
 
	// if necessary, we could try later inserting it at the correct position
 
        #ifdef QDEBUG
 
	if (w->c1 == w->c2 ){
 
	  qDebug() << "Wall between identical cells: " << w->c1->Index()<< endl;
 
	}
 
	#endif
 

	
 
	// Add Wall to Cell's list
 
	walls.push_back( w );
 
	
 
	// Add wall to Mesh's list if it isn't there yet
 
	
 
	if (find (
 
			  m->walls.begin(), m->walls.end(),
 
			  w )
 
		== m->walls.end() ) {
 
		m->walls.push_back(w);
 
	}
 
	
 
}
 

	
 
//! Remove Wall w from the list of Walls
 
list<Wall *>::iterator Cell::RemoveWall( Wall *w ) {
 
list<Wall *>::iterator Cell::RemoveWall( Wall *w )
 
{
 
	
 
	// remove wall from Mesh's list
 
	m->walls.erase(
 
				   find(
 
						m->walls.begin(), m->walls.end(),
 
						w )
 
				   );
 
	
 
	// remove wall from Cell's list
 
	return 
 
	walls.erase (
 
				 find( 
 
					  walls.begin(), walls.end(),
 
					  w )
 
				 );
 
	
 
  return walls.erase (find( walls.begin(), walls.end(), w ));
 
}
 

	
 

	
 

	
 
void Cell::EmitValues(double t) {
 
void Cell::EmitValues(double t)
 
{
 
	
 
	//  cerr << "Attempting to emit " << t << ", " << chem[0] << ", " << chem[1] << endl;
 
	emit ChemMonValue(t, chem);
 
}
 
	
 
}
 
/* finis */
src/cell.h
Show inline comments
 
@@ -83,59 +83,55 @@ public:
 
		offset[1]=oy;
 
    }
 
    static double Magnification(void) {
 
		return factor;
 
    }
 
	
 
    static double Scale(const double scale) {
 
		factor*=scale;
 
		return factor;
 
    }
 
    
 
    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)
 

	
 
  // divide over the line (if line and cell intersect)
 
  bool DivideOverGivenLine(const Vector v1, const Vector v2, bool wall_fixed = false, NodeSet *node_set = 0);
 
	
 
    void Divide(void) { // Divide cell over short axis
 
		
 
		Vector long_axis; 
 
		Length(&long_axis); 
 
		DivideOverAxis(long_axis.Perp2D()); 
 
		
 
    }
 
	
 
	//void CheckForGFDrivenDivision(void);
 
    inline int NNodes(void) const { return nodes.size(); }
 
  	
 
    void Move(Vector T);
 
    void Move(double dx, double dy, double dz=0) {
 
		Move( Vector (dx, dy, dz) );
 
    }
 
	
 
	double Displace(double dx, double dy, double dh);
 
    void Displace(void);
 
    double Energy(void) const;
 
    bool SelfIntersect(void);
 
    bool MoveSelfIntersectsP(Node *nid, Vector new_pos);
 
    bool IntersectsWithLineP(const Vector v1, const Vector v2);
 

	
 
	void XMLAdd(xmlNodePtr cells_node) const;
 
	
 
	void ConstructWalls(void);
 
	void Flux(double *flux, double *D);
 
	
 
	/*! \brief Method called if a cell is clicked. 
 
	 
 
	 Define this in the end-user code (e.g. meinhardt.cpp).
 
	 
 
	 */
 
    void OnClick(QMouseEvent *e);
 
    inline Mesh& getMesh(void) const { return *m; }
 
	double MeanArea(void);
 
	
 
	void Apoptose(void); // Cell kills itself
 
	list<Wall *>::iterator RemoveWall( Wall *w );
 
    void AddWall( Wall *w );
 

	
 
    void Draw(QGraphicsScene *c, QString tooltip = QString::Null());
 
    
 
	// Draw a text in the cell's center
 
    void DrawText(QGraphicsScene *c, const QString &text) const;
 
@@ -144,39 +140,37 @@ public:
 
    void DrawNodes(QGraphicsScene *c) const;
 
    
 
	void DrawAxis(QGraphicsScene *c) const;
 
    void DrawStrain(QGraphicsScene *c) const;
 
    void DrawFluxes(QGraphicsScene *c, double arrowsize = 1.);
 
    void DrawWalls(QGraphicsScene *c) const;
 
    void DrawValence(QGraphicsScene *c) const;
 
    void EmitValues(double t);
 
	
 
signals:
 
    void ChemMonValue(double t, double *x);
 
	
 
	
 
protected:
 
	void XMLAddCore(xmlNodePtr xmlcell) const;
 
    int XMLRead(xmlNode *cur);
 
	void DivideWalls(ItList new_node_locations, const Vector from, const Vector to, bool wall_fixed = false, NodeSet *node_set = 0);
 

	
 
private:
 

	
 
    static QPen *cell_outline_pen;
 
	static double offset[3];
 
    static double factor;
 
	Mesh *m;
 
	void ConstructConnections(void);
 
	void SetWallLengths(void);
 

	
 
};
 

	
 

	
 
// Boundarypolygon is a special cell; will not increase ncells
 
//  and will not be part of Mesh::cells
 
class BoundaryPolygon : public Cell {
 
	
 
public:
 
	BoundaryPolygon(void) : Cell() {
 
		NCells()--;
 
		index=-1;
 
	}
 
@@ -187,19 +181,17 @@ public:
 
    }
 
	
 
	BoundaryPolygon &operator=(Cell &src) {
 
		Cell::operator=(src);
 
		index=-1;
 
		return *this;
 
	}
 
	virtual void Draw(QGraphicsScene *c, QString tooltip = QString::Null());
 
	
 
	virtual void XMLAdd(xmlNodePtr parent_node) const;
 
	
 
	virtual bool BoundaryPolP(void) const { return true; } 
 

	
 

	
 
};
 

	
 

	
 
#endif
 

	
 
#endif
 
/* finis */
src/cellbase.cpp
Show inline comments
 
@@ -125,25 +125,24 @@ CellBase::CellBase(double x,double y,dou
 
	
 
	source = false;
 
	fixed = false;
 
	at_boundary=false;
 
	pin_fixed = false;
 
	stiffness = 0;
 
	marked=false;
 
	dead  = false;
 
	div_counter = 0;
 
	cell_type = 0;
 
	flag_for_divide = false;
 
	division_axis = 0;
 

	
 
}
 

	
 
CellBase::CellBase(const CellBase &src) :  Vector(src), QObject()
 
{
 
	
 
	chem=new double[NChem()];
 
	for (int i=0;i<NChem();i++) {
 
		chem[i]=src.chem[i];
 
	}
 
	new_chem=new double[NChem()];
 
	for (int i=0;i<NChem();i++) {
 
		new_chem[i]=src.new_chem[i];
 
@@ -169,25 +168,26 @@ CellBase::CellBase(const CellBase &src) 
 
	at_boundary=src.at_boundary;
 
	pin_fixed = src.pin_fixed;
 
	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) {
 
CellBase CellBase::operator=(const CellBase &src)
 
{
 
	Vector::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;
 
@@ -208,47 +208,50 @@ CellBase CellBase::operator=(const CellB
 
	at_boundary=src.at_boundary;
 
	pin_fixed = src.pin_fixed;
 
	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;
 
	return *this;
 
}
 

	
 
void CellBase::SetChemical(int c, double conc) {
 
void CellBase::SetChemical(int c, double conc)
 
{
 
	if (c>=NChem()) {
 
		stringstream error;
 
		error << "SetChemical: value c = " << c << " is out of range\n";
 
		throw error.str().c_str();
 
	}
 
	chem[c]=conc;
 
}
 

	
 
void CellBase::SetTransporters(int ch, double conc) {
 
void CellBase::SetTransporters(int ch, double conc)
 
{
 
	if (ch>=NChem()) {
 
		stringstream error;
 
		error << "SetChemical: value ch = " << ch << " is out of range\n";
 
		throw error.str().c_str();
 
	}
 
	for (list<Wall *>::iterator w=walls.begin();
 
		 w!=walls.end();
 
		 w++) {
 
		(*w)->setTransporter(this, ch, conc);
 
	}
 
}
 

	
 
ostream &CellBase::print(ostream &os) const {
 
ostream &CellBase::print(ostream &os) const
 
{
 
	
 
	
 
	os << "[ index = " << index << " {" << x << ", " << y << ", " << z << "}: {";
 
	
 
	for (int i=0;i<NChem()-1;i++) {
 
		os << chem[i] << ", ";
 
	}
 
	
 
	os << chem[NChem()-1] << " } ]";
 
	
 
	os << endl << "Nodelist = { " << endl;
 
	
 
@@ -267,55 +270,56 @@ ostream &CellBase::print(ostream &os) co
 
	os << " [ walls = ";
 
	
 
	for (list<Wall *>::const_iterator i= walls.begin();
 
		 i!=walls.end();
 
		 i++) {
 
		os << (*i)->n1->Index() << " -> " << (*i)->n2->Index() << ", " <<  (*i)->c1->Index() << " | " << (*i)->c2->Index() << ", ";
 
	}
 
	os << " ] ";
 
	os << "div_counter = " << div_counter << endl;
 
	os << "cell_type = " << cell_type << endl;
 
	os << endl;
 
	return os;
 
	
 
}
 

	
 
ostream &operator<<(ostream &os, const CellBase &c) {
 
ostream &operator<<(ostream &os, const CellBase &c)
 
{
 
	c.print(os);
 
	return os;
 
}
 

	
 

	
 
double CellBase::CalcArea(void) const {
 
double CellBase::CalcArea(void) const
 
{
 
	
 
	double loc_area=0.;
 
	
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=(nodes.end());
 
		 i++) {
 
		
 
		list<Node *>::const_iterator i_plus_1=i; i_plus_1++;
 
		if (i_plus_1==nodes.end())
 
			i_plus_1=nodes.begin();
 
		
 
		loc_area+= (*i)->x * (*i_plus_1)->y;
 
		loc_area-= (*i_plus_1)->x * (*i)->y;
 
	}
 

	
 
	// http://technology.niagarac.on.ca/courses/ctec1335/docs/arrays2.pdf	
 
	//return loc_area/2.0; 
 
	return fabs(loc_area)/2.0; 
 
} 
 

	
 
Vector CellBase::Centroid(void) const {
 
Vector CellBase::Centroid(void) const
 
{
 
	
 
	double area=0.;
 
	double integral_x_dxdy=0.,integral_y_dxdy=0.;
 
	
 
	for (list<Node *>::const_iterator i=nodes.begin();
 
		 i!=(nodes.end());
 
		 i++) {
 
		
 
		list<Node *>::const_iterator i_plus_1=i; i_plus_1++;
 
		if (i_plus_1==nodes.end())
 
			i_plus_1=nodes.begin();
 
		
 
@@ -323,38 +327,38 @@ Vector CellBase::Centroid(void) const {
 
		area-= (*i_plus_1)->x * (*i)->y;
 
		
 
		integral_x_dxdy+=
 
			((*i_plus_1)->x+(*i)->x)*
 
			((*i)->x*(*i_plus_1)->y-
 
			 (*i_plus_1)->x*(*i)->y);
 
		integral_y_dxdy+=
 
			((*i_plus_1)->y+(*i)->y)*
 
			((*i)->x*(*i_plus_1)->y-
 
			 (*i_plus_1)->x*(*i)->y);
 
	}
 
    
 
	//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;
 
}
 

	
 

	
 

	
 
void CellBase::SetIntegrals(void) const {
 
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.;
 
	list<Node *>::const_iterator nb;
 
	list<Node *>::const_iterator i=nodes.begin();
 
	
 
@@ -383,31 +387,29 @@ void CellBase::SetIntegrals(void) const 
 
			((*i)->y*(*i)->y+
 
			 (*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 = fabs(area)/2.0;
 
	
 
}
 

	
 
double CellBase::Length(Vector *long_axis, double *width)  const {
 
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.
 
		SetIntegrals();
 
	}
 
	
 
@@ -425,30 +427,28 @@ double CellBase::Length(Vector *long_axi
 
	//    cerr << "n = " << n << "\n";
 
	
 
	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);
 
    
 
	
 
	
 
}
 

	
 
double CellBase::CalcLength(Vector *long_axis, double *width)  const {
 
double CellBase::CalcLength(Vector *long_axis, double *width)  const
 
{
 
	
 
	// Calculate length and axes of CellBase, without touching cells raw moments
 
    
 
	// Calculate inertia tensor
 
	// see file inertiatensor.nb for explanation of this method
 
	
 
	double my_intgrl_xx=0., my_intgrl_xy=0., my_intgrl_yy=0.;
 
	double my_intgrl_x=0., my_intgrl_y=0., my_area=0.;
 
	my_area=0.;
 
	list<Node *>::const_iterator nb;
 
	list<Node *>::const_iterator i=nodes.begin();
 
	
 
@@ -506,32 +506,29 @@ double CellBase::CalcLength(Vector *long
 
	//    cerr << "n = " << n << "\n";
 
	
 
	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::ConstructNeighborList(void) {
 
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!=walls.end();
 
		 wit++) {
 
		
 
		if ((*wit)->C1() != this) {
 
			neighbors.push_back((*wit)->C1());
 
@@ -552,107 +549,102 @@ void CellBase::ConstructNeighborList(voi
 
		// 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);
 
	
 
}
 
	
 
	// Save the cell to a stream so we can reconstruct its state later
 
	void CellBase::Dump(ostream &os) const {
 
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 << " ";
 
		}
 
		os << endl;
 
		
 
		
 
		os << index << " " << neighbors.size() << endl;
 
		for (list<CellBase *>::const_iterator i=neighbors.begin();i!=neighbors.end();i++) {
 
			os << *i << " ";
 
		}
 
		os << endl;
 
		
 
		os << walls.size() << endl;
 
		/*for (list<Wall *>::const_iterator i=walls.begin();i!=walls.end(); i++) {
 
			(*i)->Dump(os);
 
		}*/
 
  os << endl << walls.size() << endl << endl;
 
  os << NChem() << " ";
 
		
 
		os << endl;
 
		
 
		os << NChem() << " ";
 
		for (int i=0;i<NChem();i++) {
 
			os << chem[i] << " ";
 
		}
 
		os << endl;
 
		
 
		os << NChem() << " ";
 
		for (int i=0;i<NChem();i++) {
 
			os << new_chem[i] << " ";
 
		}
 
		os << endl;
 
		
 
		os << boundary << " " << area << " " << target_area << " " << target_length << " " << fixed << " " << intgrl_xx << " " << intgrl_xy << " " << intgrl_yy << " " << intgrl_x << " " << intgrl_y << " " << source << " ";
 
  os << boundary << " " << area << " " << target_area << " " << target_length 
 
     << " " << fixed << " " << intgrl_xx << " " << intgrl_xy << " " << intgrl_yy 
 
     << " " << intgrl_x << " " << intgrl_y << " " << source << " ";
 
		
 
		cellvec.Dump(os);
 
		
 
		os << " " << source_conc << " " << source_chem;
 
		os << endl;
 
		
 
	}
 
	
 
	
 
	
 
	void CellBase::UnfixNodes(void) {
 
void CellBase::UnfixNodes(void)
 
{
 
		
 
		for (list<Node *>::const_iterator i=nodes.begin();
 
			 i!=nodes.end();
 
			 i++) {
 
			(*i)->Unfix();
 
		}
 
		
 
	}
 
	
 
	void CellBase::FixNodes(void) {
 

	
 
void CellBase::FixNodes(void)
 
{
 
		
 
		for (list<Node *>::const_iterator i=nodes.begin();
 
			 i!=nodes.end();
 
			 i++) {
 
			(*i)->Fix();
 
		}
 
		
 
	}
 
	
 
	// returns true if cell is at border
 
	bool CellBase::AtBoundaryP(void) const {
 
		
 
bool CellBase::AtBoundaryP(void) const
 
{
 
		return at_boundary;
 
	}
 
	
 

	
 

	
 

	
 

	
 

	
 

	
 
QString CellBase::printednodelist(void) {
 
QString CellBase::printednodelist(void)
 
{
 
	QString info_string = "Nodelist = { ";
 
	for (list<Node *>::const_iterator i =  nodes.begin(); i!=nodes.end(); i++) {
 
		info_string += QString("%1 ").arg((*i)->Index());
 
	}
 
	info_string += " } ";
 
	return info_string;
 
}
 

	
 
/* finis*/
src/cellbase.h
Show inline comments
 
@@ -42,25 +42,24 @@ extern Parameter par;
 
using namespace std;
 

	
 
class Mesh;
 
class Node;
 
class CellBase;
 
class NodeSet;
 

	
 
struct ParentInfo {
 
	
 
	Vector polarization;
 
	double PINmembrane;
 
	double PINendosome;
 
	
 
};
 

	
 
// We need a little trick here, to make sure the plugin and the main application will see the same static datamembers
 
// otherwise each have their own instantation.
 
// My solution is as follow. I collect all original statics in a class. The main application instantiates it and
 
// has a static pointer to it. After loading the plugin I set a static pointer to the same class 
 
class CellsStaticDatamembers {
 
	
 
public:
 
	CellsStaticDatamembers(void) {
 
		ncells = 0;
 
		nchem = 0;
 
@@ -68,34 +67,31 @@ public:
 
                #ifdef QDEBUG
 
		qDebug() << "Constructor of CellsStaticDatamembers" << endl;
 
		#endif
 
	}
 
	~CellsStaticDatamembers() {
 
                #ifdef QDEBUG
 
	        qDebug() << "Oops! Desctructor of CellsStaticDatamembers called" << endl;
 
                #endif
 
	}
 
	int ncells;
 
	int nchem;
 
	double base_area;
 

	
 

	
 
};
 

	
 
class CellBase :  public QObject, public Vector 
 
{
 

	
 
	Q_OBJECT
 

	
 

	
 
	friend class Mesh;
 
	friend class CellInfo;
 
	friend class Node;
 
	friend class WallBase;
 
	friend class SimPluginInterface;
 
	
 
 public:
 
	CellBase(QObject *parent=0);
 
	CellBase(double x,double y,double z=0); // constructor
 
	
 
  virtual ~CellBase() {
 
	  delete[] chem;
 
@@ -103,32 +99,36 @@ class CellBase :  public QObject, public
 
	  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 operator=(const CellBase &src); // assignment operator
 
    CellBase operator=(const Vector &src);
 
  
 
    void SetChemical(int chem, double conc);
 
    inline void SetNewChem(int chem, double conc) { 
 
  inline void SetNewChem(int chem, double conc)
 
  { 
 
      new_chem[chem] = conc;
 
    }
 
    void SetSource(int chem, double conc) {
 

	
 
  void SetSource(int chem, double conc)
 
  {
 
      source=true;
 
      source_chem = chem;
 
      source_conc = conc;
 
	}
 

	
 
	// set chem 1 to conc in all membranes of this cell
 
    void SetTransporters(int chem, double conc);
 
    void UnfixNodes(void);
 
    void FixNodes(void);
 
    void UnsetSource(void) {
 
      source = false;
 
    }
 
    
 
	inline bool Source(void) { return source; }
 
    enum boundary_type {None, Noflux, SourceSink, SAM};
 
    static const char * boundary_type_names[4];
 

	
 
@@ -145,96 +145,76 @@ class CellBase :  public QObject, public
 

	
 
      #ifdef _undefined_
 
      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) {
 
  boundary_type SetBoundary(boundary_type bound)
 
  {
 
      if (bound!=None) {
 
      }
 
      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;
 
    }
 
  boundary_type ResetBoundary(void) { return boundary=None; }
 

	
 
  boundary_type Boundary(void) const { return boundary; }
 

	
 
  static int &NChem(void) { return static_data_members->nchem; }
 
  
 
    double CalcArea(void) const;
 
    double RecalcArea(void) {
 
      return area = CalcArea();
 
    }
 

	
 
  double RecalcArea(void) { return area = CalcArea(); }
 
    
 
    Vector Centroid(void) const;
 
  
 
    void SetIntegrals(void) const;
 
    
 
    double Length(Vector *long_axis = 0, double *width = 0) const;
 
    double CalcLength(Vector *long_axis = 0, double *width = 0) const;
 
    
 

	
 
    inline int Index(void) const {
 
      return index;
 
    }
 
  inline int Index(void) const { return index; }
 
  
 

	
 
    void SetTargetArea(double tar_ar) {
 
      target_area=tar_ar;
 
    }
 
    inline void SetTargetLength(double tar_l) {
 
      target_length=tar_l;
 
    }
 
    inline void SetLambdaLength(double lambda_length) {
 
      lambda_celllength = lambda_length;
 
    }
 
    inline double TargetArea(void) {
 
      return target_area;
 
    }
 
  void SetTargetArea(double tar_ar) { target_area=tar_ar; }
 

	
 
  inline void SetTargetLength(double tar_l) { target_length=tar_l; }
 
  
 
    inline void SetStiffness(double stiff) {
 
      stiffness = stiff;
 
    }
 
  inline void SetLambdaLength(double lambda_length) { lambda_celllength = lambda_length; }
 

	
 
  inline double TargetArea(void) { return target_area; }
 

	
 
  inline void SetStiffness(double stiff) { stiffness = stiff; }
 

	
 
    inline double Stiffness(void) {
 
      return stiffness;
 
    }
 
    inline double EnlargeTargetArea(double da) {
 
      return target_area+=da;
 
    }
 
  inline double Stiffness(void) { return stiffness; }
 

	
 
  inline double EnlargeTargetArea(double da) { return target_area+=da; }
 
  
 
    inline double Area(void) const {
 
      return area;
 
    }
 
  inline double Area(void) const { return area; }
 
    
 
	inline void Divide(void) {
 
		flag_for_divide = true;
 
	}
 
  inline void Divide(void) { flag_for_divide = true; }
 
	
 
	inline void DivideOverAxis(const Vector &v) {
 
  inline void DivideOverAxis(const Vector &v)
 
  {
 
		division_axis = new Vector(v);
 
		flag_for_divide = true;
 
	}
 
	
 

	
 
    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) {
 
@@ -242,63 +222,65 @@ class CellBase :  public QObject, public
 
		for (list<Wall *>::iterator i=walls.begin();
 
			 i!=walls.end();
 
			 i++) {
 
			wall_list << *i;
 
		}
 
		return wall_list;
 
	}
 
    
 
    void Dump(ostream &os) const;
 
   	
 
	QString printednodelist(void);
 
 
 

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

	
 
	
 
    // write flux from neighboring cells into "flux"
 
    void Flux(double *flux, double *D); 
 
    inline bool FixedP(void) { return fixed; }
 
    inline bool Fix(void) {  FixNodes(); return (fixed=true); }
 
    inline bool Unfix(void) { UnfixNodes(); return (fixed=false);}
 
    inline void setCellVec(Vector cv) { cellvec = cv; }
 
    
 
	bool AtBoundaryP(void) const;
 
    
 
    static inline int &NCells(void) {
 
  static inline int &NCells(void)
 
  {
 
      return static_data_members->ncells;
 
    }
 

	
 
 
 
   
 
    inline void Mark(void) {
 
  inline void Mark(void)
 
  {
 
      marked=true;
 
    }
 
    inline void Unmark(void) {
 

	
 
  inline void Unmark(void)
 
  {
 
      marked=false;
 
    }
 

	
 
    inline bool Marked(void) const {
 
      return marked;
 
    }
 

	
 
	//! Returns the sum of chemical "chem" of this CellBase's neighbors
 
    double SumChemicalsOfNeighbors(int chem) {
 
  double SumChemicalsOfNeighbors(int chem)
 
  {
 
      double sum=0.;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum +=  (*w)->Length() * ( (*w)->c1!=this ? (*w)->c1->Chemical(chem) : (*w)->c2->Chemical(chem) );
 
      }
 
      return sum;
 
    }
 

	
 
    //! Generalization of the previous member function
 
    template<class P, class Op> P ReduceNeighbors(Op f) {
 
      P sum=0;
 
@@ -311,110 +293,111 @@ class CellBase :  public QObject, public
 
    }
 

	
 
    //! The same, but now for the walls
 
    template<class P, class Op> P ReduceWalls(Op f, P sum) {
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum += f( **w ); 
 
      }
 
      return sum;
 
    }
 
	
 
	
 
    
 
    
 
    //! The same, but now for the walls AND neighbors
 
    template<class P, class Op> P ReduceCellAndWalls(Op f) {
 
  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;
 
    }
 
    
 
	
 
    //! Sum transporters at this CellBase's side of the walls
 
    double SumTransporters(int ch) {
 
  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;
 
    }
 

	
 
    inline int NumberOfDivisions(void) { return div_counter; }
 
    
 
    //! Sum transporters at this CellBase's side of the walls
 
    double SumLengthTransporters(int ch) {
 
  double SumLengthTransporters(int ch)
 
  {
 
      double sum=0.;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum += (*w)->getTransporter(this, ch) * (*w)->Length();
 
      
 
      }
 
      
 
      return sum;
 
    }
 
    
 
	
 
    
 
    double SumLengthTransportersChemical(int trch, int ch) {
 
  double SumLengthTransportersChemical(int trch, int ch)
 
  {
 
      double sum=0.;
 
      for (list<Wall *>::const_iterator w=walls.begin();
 
	   w!=walls.end();
 
	   w++) {
 
	sum += (*w)->getTransporter(this, trch) * ( (*w)->c1!=this ? (*w)->c1->Chemical(ch) : (*w)->c2->Chemical(ch) );
 
	
 
      }
 
      
 
      return sum;
 
    }
 
	inline int CellType(void) const { return cell_type; } 
 
	inline void SetCellType(int ct) { cell_type = ct; }
 

	
 
    
 
	static void SetNChem(int new_nchem) {
 
  static void SetNChem(int new_nchem)
 
  {
 
		if (NCells()) {
 
			MyWarning::error("CellBase::SetNChem says: not permitted, call SetNChem after deleting all cells.");
 
		} else {
 
			NChem() = new_nchem;
 
		}
 
	}
 
	
 
	inline double TargetLength() const { return target_length; } 
 

	
 
	static inline CellsStaticDatamembers *GetStaticDataMemberPointer(void) { return static_data_members; }
 
	
 
protected:
 
	// (define a list of Node* iterators)
 
	typedef list < list<Node *>::iterator > ItList;
 

	
 
    int index;
 

	
 
	inline void SetChemToNewchem(void) {
 
  inline void SetChemToNewchem(void)
 
  {
 
		for (int c=0;c<CellBase::NChem();c++) {
 
			chem[c]=new_chem[c];
 
		}
 
    }
 
    inline void SetNewChemToChem(void) {
 
  inline void SetNewChemToChem(void)
 
  {
 
		for (int c=0;c<CellBase::NChem();c++) {
 
			new_chem[c]=chem[c];
 
		}
 
    }
 
	inline double NewChem(int c) const { return new_chem[c]; }
 
	
 
 protected:
 
    list<Node *> nodes;
 
    void ConstructNeighborList(void);
 
	long wall_list_index (Wall *elem) const;
 

	
 
    // DATA MEMBERS
 
@@ -437,50 +420,46 @@ protected:
 
    double target_length;
 
    double lambda_celllength;
 

	
 
    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;
 
	
 
    
 
    // 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;
 
	
 
    // PRIVATE MEMBER FUNCTIONS
 
    inline static void ClearNCells(void) {
 
  inline static void ClearNCells(void)
 
  {
 
      NCells()=0;
 
    }
 
    
 
    bool marked;
 
    int div_counter;
 
};
 

	
 
ostream &operator<<(ostream &os, const CellBase &v);
 

	
 
inline Vector PINdir(CellBase *here, CellBase *nb, Wall *w) {
 
inline Vector PINdir(CellBase *here, CellBase *nb, Wall *w)
 
{
 
	  nb = NULL; // assignment merely to obviate compilation warning
 
	  return w->getTransporter( here, 1)  *  w->getInfluxVector(here);
 
}
 

	
 

	
 
#endif
 

	
 

	
 

	
 

	
 

	
 
/* finis*/
src/cellitem.cpp
Show inline comments
 
@@ -20,26 +20,28 @@
 
 */
 

	
 
#include <string>
 
#include<QGraphicsScene>
 
#include "cellitem.h"
 

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

	
 
CellItem::CellItem( Cell *c, QGraphicsScene *canvas )
 
  : QGraphicsPolygonItem( 0, canvas ), SimItemBase( c, canvas){
 
}
 

	
 
void CellItem::userMove(double dx, double dy) {
 
void CellItem::userMove(double dx, double dy)
 
{
 
  QGraphicsPolygonItem::moveBy( dx, dy );
 

	
 
  // also move the cell itself
 
  class_cast<Cell *>(obj)->x += (dx/Cell::Magnification());
 
  class_cast<Cell *>(obj)->y += (dy/Cell::Magnification());
 
  
 
  class_cast<Cell*>(obj)->Move( (dx/Cell::Magnification()), (dy/Cell::Magnification()) );
 
}
 

	
 

	
 
QPainterPath CellItem::shape() const { return QGraphicsPolygonItem::shape(); }
 
QRectF CellItem::boundingRect() const { return QGraphicsPolygonItem::boundingRect(); }
 

	
 

	
 
/* finis */
src/cellitem.h
Show inline comments
 
@@ -34,16 +34,17 @@
 

	
 
class CellItem : public QGraphicsPolygonItem, public SimItemBase
 
{
 
public:
 
  CellItem( Cell *n, QGraphicsScene *canvas );
 
  virtual ~CellItem() {}
 
  Cell &getCell(void) const { return *class_cast<Cell*>(obj); }
 
  virtual void userMove(double dx, double dy);  
 
  QPainterPath shape() const;
 
  QRectF boundingRect() const;
 

	
 
 private:
 

	
 
};
 

	
 
#endif
 

	
 
/* finis */
src/curvecolors.h
Show inline comments
 
@@ -166,12 +166,14 @@ class CurveColors {
 
    colors += QString("thistle");
 
  }
 
  QString &operator[](int i) {
 
    if (i>=colors.size() || i<0) {
 
      throw("Color number out of range in curvecolors.h");
 
    } else
 
      return colors[i];
 
  }
 
 private:
 
  QStringList colors;
 
};
 
#endif
 

	
 
/* finis */
src/data_plot.cpp
Show inline comments
 
@@ -57,26 +57,24 @@ DataPlot::DataPlot(QWidget *parent, cons
 
  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);
 

	
 
  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.;
 
  }
 

	
 
  // Assign a title
 
  setTitle(title);
 
  insertLegend(new QwtLegend(), QwtPlot::BottomLegend);
 

	
 
@@ -89,105 +87,97 @@ DataPlot::DataPlot(QWidget *parent, cons
 
    curves[i].setPen(QPen(curvecolors[i]));
 
    QString col(curvecolors[i]);
 

	
 
    #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);
 

	
 
  data_pos = 0;
 

	
 
}
 

	
 
DataPlot::~DataPlot(void) {
 
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
 
//
 
void DataPlot::alignScales()
 
{
 
    // The code below shows how to align the scales to
 
    // the canvas frame, but is also a good example demonstrating
 
    // why the spreaded API needs polishing.
 

	
 
    canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
 
    canvas()->setLineWidth(1);
 
    
 
    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);
 
    }
 
}
 

	
 

	
 
//  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;
 

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

	
 
}
 

	
 

	
 
PlotDialog::PlotDialog(QWidget *parent, const QString title, const QStringList curvenames):
 
  QDialog(parent) 
 
{
 
  
 
  plot = new DataPlot(this,title,curvenames);
 
  
 
  plot->resize(400,300);
 
  
 
  show();
 

	
 
}
 

	
 
PlotDialog::~PlotDialog(void) {
 
  
 
PlotDialog::~PlotDialog(void)
 
{
 
  delete plot;
 
}
 

	
 
/* finis */
src/data_plot.h
Show inline comments
 
@@ -54,31 +54,32 @@ private:
 
    int d_timerId;
 
    
 
    QwtPlotCurve *curves;
 
    int data_pos;
 
    int ncurves;
 
    
 
    CurveColors curvecolors;
 

	
 
 protected:
 
    // to write contents of DataPlot to a file
 
    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 AddValue(double t, double *x) {
 
    //std::cerr << "AddValue receives: " << t << ", " << y << ", " << z << std::endl;
 
    plot->AddValue(t,x);
 
  }
 
 private:
 
  DataPlot *plot;
 
};
 

	
 
#endif
 

	
 
/* finis */
src/far_mem_5.h
Show inline comments
 
@@ -12,143 +12,156 @@
 
 *  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 _FAR_MEM_5_h_
 
#define _FAR_MEM_5_h_
 

	
 
template <class _Arg1,  class _Result>
 
	struct my_1_function
 
	{
 
typedef _Arg1 argument_type1;
 
typedef _Result result_type;  ///<  result_type is the return type
 
};
 
template <class Result, class Type,  class Param1>
 
class far_1_arg_mem_fun_t : public my_1_function<Param1, Result> {
 
public:
 
explicit far_1_arg_mem_fun_t(Type &ir_typ, Result (Type::*i_pmf)(Param1)) {
 
			m_ptyp = &ir_typ;
 
			m_pmf = i_pmf;
 
		};
 
Result operator()(Param1 i_prm1) { return (m_ptyp->*(m_pmf))(i_prm1); };
 

	
 
protected:
 
Type *m_ptyp;
 
Result (Type::*m_pmf)(Param1);
 
};
 

	
 
template <class Result, class Type, class Param1>far_1_arg_mem_fun_t<Result,Type,Param1> far_1_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1) ) {
 
template <class Result, class Type, 
 
  class Param1>far_1_arg_mem_fun_t<Result,Type,Param1> far_1_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1) )
 
{
 
	return far_1_arg_mem_fun_t<Result,Type,Param1>(ir_typ,i_pmf);
 
 }
 

	
 
template <class _Arg1, class _Arg2,  class _Result>
 
	struct my_2_function
 
	{
 
typedef _Arg1 argument_type1;
 
typedef _Arg2 argument_type2;
 
typedef _Result result_type;  ///<  result_type is the return type
 
};
 

	
 
template <class Result, class Type,  class Param1, class Param2>
 
class far_2_arg_mem_fun_t : public my_2_function<Param1, Param2, Result> {
 
public:
 
explicit far_2_arg_mem_fun_t(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2)) {
 
			m_ptyp = &ir_typ;
 
			m_pmf = i_pmf;
 
		};
 
Result operator()(Param1 i_prm1, Param2 i_prm2) { return (m_ptyp->*(m_pmf))(i_prm1, i_prm2); };
 

	
 
protected:
 
Type *m_ptyp;
 
Result (Type::*m_pmf)(Param1, Param2);
 
};
 

	
 
template <class Result, class Type, class Param1, class Param2>far_2_arg_mem_fun_t<Result,Type,Param1, Param2> far_2_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2) ) {
 
template <class Result, class Type, class Param1, 
 
  class Param2>far_2_arg_mem_fun_t<Result,Type,Param1, Param2> far_2_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2) ) {
 
	return far_2_arg_mem_fun_t<Result,Type,Param1, Param2>(ir_typ,i_pmf);
 
 }
 

	
 
template <class _Arg1, class _Arg2, class _Arg3,  class _Result>
 
	struct my_3_function
 
	{
 
typedef _Arg1 argument_type1;
 
typedef _Arg2 argument_type2;
 
typedef _Arg3 argument_type3;
 
typedef _Result result_type;  ///<  result_type is the return type
 
};
 

	
 
template <class Result, class Type,  class Param1, class Param2, class Param3>
 
class far_3_arg_mem_fun_t : public my_3_function<Param1, Param2, Param3, Result> {
 
public:
 
explicit far_3_arg_mem_fun_t(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3)) {
 
			m_ptyp = &ir_typ;
 
			m_pmf = i_pmf;
 
		};
 
Result operator()(Param1 i_prm1, Param2 i_prm2, Param3 i_prm3) { return (m_ptyp->*(m_pmf))(i_prm1, i_prm2, i_prm3); };
 

	
 
protected:
 
Type *m_ptyp;
 
Result (Type::*m_pmf)(Param1, Param2, Param3);
 
};
 

	
 
template <class Result, class Type, class Param1, class Param2, class Param3>far_3_arg_mem_fun_t<Result,Type,Param1, Param2, Param3> far_3_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3) ) {
 
template <class Result, class Type, class Param1, class Param2, 
 
class Param3>far_3_arg_mem_fun_t<Result,Type,Param1, Param2, Param3> far_3_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3) ) {
 
	return far_3_arg_mem_fun_t<Result,Type,Param1, Param2, Param3>(ir_typ,i_pmf);
 
 }
 

	
 
template <class _Arg1, class _Arg2, class _Arg3, class _Arg4,  class _Result>
 
	struct my_4_function
 
	{
 
typedef _Arg1 argument_type1;
 
typedef _Arg2 argument_type2;
 
typedef _Arg3 argument_type3;
 
typedef _Arg4 argument_type4;
 
typedef _Result result_type;  ///<  result_type is the return type
 
};
 

	
 
template <class Result, class Type,  class Param1, class Param2, class Param3, class Param4>
 
class far_4_arg_mem_fun_t : public my_4_function<Param1, Param2, Param3, Param4, Result> {
 
public:
 
explicit far_4_arg_mem_fun_t(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3, Param4)) {
 
			m_ptyp = &ir_typ;
 
			m_pmf = i_pmf;
 
		};
 
Result operator()(Param1 i_prm1, Param2 i_prm2, Param3 i_prm3, Param4 i_prm4) { return (m_ptyp->*(m_pmf))(i_prm1, i_prm2, i_prm3, i_prm4); };
 

	
 
protected:
 
Type *m_ptyp;
 
Result (Type::*m_pmf)(Param1, Param2, Param3, Param4);
 
};
 

	
 
template <class Result, class Type, class Param1, class Param2, class Param3, class Param4>far_4_arg_mem_fun_t<Result,Type,Param1, Param2, Param3, Param4> far_4_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3, Param4) ) {
 
	return far_4_arg_mem_fun_t<Result,Type,Param1, Param2, Param3, Param4>(ir_typ,i_pmf);
 
 }
 

	
 
template <class _Arg1, class _Arg2, class _Arg3, class _Arg4, class _Arg5,  class _Result>
 
	struct my_5_function
 
	{
 
typedef _Arg1 argument_type1;
 
typedef _Arg2 argument_type2;
 
typedef _Arg3 argument_type3;
 
typedef _Arg4 argument_type4;
 
typedef _Arg5 argument_type5;
 
typedef _Result result_type;  ///<  result_type is the return type
 
};
 

	
 
template <class Result, class Type,  class Param1, class Param2, class Param3, class Param4, class Param5>
 
class far_5_arg_mem_fun_t : public my_5_function<Param1, Param2, Param3, Param4, Param5, Result> {
 
public:
 
explicit far_5_arg_mem_fun_t(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3, Param4, Param5)) {
 
			m_ptyp = &ir_typ;
 
			m_pmf = i_pmf;
 
		};
 
Result operator()(Param1 i_prm1, Param2 i_prm2, Param3 i_prm3, Param4 i_prm4, Param5 i_prm5) { return (m_ptyp->*(m_pmf))(i_prm1, i_prm2, i_prm3, i_prm4, i_prm5); };
 

	
 
protected:
 
Type *m_ptyp;
 
Result (Type::*m_pmf)(Param1, Param2, Param3, Param4, Param5);
 
};
 

	
 
template <class Result, class Type, class Param1, class Param2, class Param3, class Param4, class Param5>far_5_arg_mem_fun_t<Result,Type,Param1, Param2, Param3, Param4, Param5> far_5_arg_mem_fun(Type &ir_typ, Result (Type::*i_pmf)(Param1, Param2, Param3, Param4, Param5) ) {
 
	return far_5_arg_mem_fun_t<Result,Type,Param1, Param2, Param3, Param4, Param5>(ir_typ,i_pmf);
 
 }
 

	
 
#endif
 

	
 
/* finis */
src/flux_function.h
Show inline comments
 
@@ -30,12 +30,14 @@
 

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

	
 
/* finis */
src/forwardeuler.cpp
Show inline comments
 
@@ -82,39 +82,37 @@ void ForwardEuler::odeint(double *ystart
 

	
 
  for (int nstp=0;nstp<Maxstp;nstp++) {
 
    
 
    derivs(x,y,dydx);
 
    
 
    if (kmax > 0 && kount < kmax-1) {
 
      xp[kount]=x; //Store intermediate results.
 
      for (int i=0;i<nvar;i++) yp[i][kount]=y[i];
 
      kount++;
 
      //xsav=x;
 
    }
 

	
 

	
 
    for (int i=0;i<nvar;i++) {
 
      y[i]=y[i] + h1 * dydx[i];
 
    }
 
      
 
    x = x + h1;
 

	
 
    if ((x-x2)*(x2-x1) >= 0.0) { //Are we done?
 
      goto done;
 
    }
 

	
 

	
 
  }
 

	
 
 done:
 
  for (int i=0;i<nvar;i++) ystart[i]=y[i];
 
  if (kmax) {
 
    xp[kount]=x; //Save final step.
 
    for (int i=0;i<nvar;i++) yp[i][kount]=y[i];
 
    
 
  }
 
  
 
  delete[] dydx;
 
  delete[] y;
 
  return; //Normal exit.
 
}
 

	
 
}
 
/* finis */
src/forwardeuler.h
Show inline comments
 
@@ -13,25 +13,24 @@
 
 *  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 _FORWARDEULER_H_
 
#define _FORWARDEULER_H_
 

	
 
class ForwardEuler  {
 

	
 
 public:
 
  ForwardEuler(void) {
 
    kmax=kount=0;
 
    dxsav=0.;
 
    xp=0;
 
    yp=0;
 
  }
 
@@ -46,16 +45,16 @@ class ForwardEuler  {
 
  virtual void derivs(double x, double *y, double *dxdy) = 0;
 
  int kmax,kount;
 
  double *xp,**yp,dxsav;
 
  
 
 private:
 

	
 
  static const double Safety;
 
  static const double PGrow;
 
  static const double Pshrnk;
 
  static const double Errcon;
 
  static const double Maxstp;
 
  static const double Tiny;
 
  
 

	
 
};
 
#endif
 

	
 
/* finis */
src/infobar.h
Show inline comments
 
@@ -45,13 +45,15 @@ public:
 
		boxLayout()->addWidget(virtleaf);//, Qt::AlignHCenter);
 
		boxLayout()->addStretch();
 
	}
 
	
 
	void SetText(QString text) {
 
		virtleaf->setText(QString("<h1>The Virtual Leaf</h1>\n<center><b>Model:</b> <i>%1</i></center>").arg(text));
 
	}
 
	
 
private:
 
	QLabel *virtleaf;
 
};
 

	
 
#endif
 
\ No newline at end of file
 
#endif
 

	
 
/* finis */
src/mainbase.cpp
Show inline comments
 
@@ -122,29 +122,29 @@ xmlNode *MainBase::XMLSettingsTree(void)
 
		xmlNewProp(xmloption, BAD_CAST "name", BAD_CAST "cell_growth");
 
		ostringstream text;
 
		text << bool_name(dynamicscellsp);
 
		xmlNewProp(xmloption, BAD_CAST "val", BAD_CAST text.str().c_str());
 
	}
 
	{
 
		xmlNode *xmloption = xmlNewChild(xmlsettings, NULL, BAD_CAST "setting", NULL);
 
		xmlNewProp(xmloption, BAD_CAST "name", BAD_CAST "hide_cells");
 
		ostringstream text;
 
		text << bool_name(hidecellsp);
 
		xmlNewProp(xmloption, BAD_CAST "val", BAD_CAST text.str().c_str());
 
	}
 
	
 
	return xmlsettings;
 
}
 

	
 
void MainBase::XMLReadSettings(xmlNode *settings) {
 
void MainBase::XMLReadSettings(xmlNode *settings)
 
{
 
	
 
	// Many files have no settings section, so don't complain about it.
 
	// Defaults will be used instead.
 
	if (settings == 0) {
 
		return;
 
	}
 
	
 
	xmlNode *cur = settings->xmlChildrenNode;
 
	
 
	while (cur!=NULL) {
 
		
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"setting"))){
 
@@ -187,43 +187,40 @@ void MainBase::XMLReadSettings(xmlNode *
 
			if (!xmlStrcmp(name, (const xmlChar *)"show_only_leaf_boundary")) {
 
				showboundaryonlyp = strtobool( (const char *)val );
 
			}
 
			if (!xmlStrcmp(name, (const xmlChar *)"cell_growth")) {
 
				dynamicscellsp = strtobool( (const char *)val );
 
			}
 
			if (!xmlStrcmp(name,(const xmlChar *)"hide_cells")) {
 
				hidecellsp = strtobool( (const char *)val ); 
 
			}
 
			
 
			xmlFree(name);
 
			xmlFree(val);
 
			
 
			
 
		}
 
		cur=cur->next;
 
	}
 
	
 
}
 

	
 
void MainBase::Save(const char *fname, const char *format, int sizex, int sizey) {
 
void MainBase::Save(const char *fname, const char *format, int sizex, int sizey)
 
{
 
	
 
	Vector ll,ur;
 
	mesh.BoundingBox(ll, ur);
 
	
 
	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.);
 
	
 
	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);
 
		if (!image->save(QString(fname))) {
 
@@ -233,17 +230,18 @@ void MainBase::Save(const char *fname, c
 
		delete image;
 
	} else {
 
		QPrinter pdf(QPrinter::HighResolution);
 
		pdf.setOutputFileName(fname);
 
		pdf.setOutputFormat(QPrinter::PdfFormat);
 
		QPainter painter(&pdf);
 
		canvas.render(&painter, QRectF(), QRectF(-5000,-5000, 10000, 10000));
 
		
 
		cerr << "Rendering to printer\n";
 
	}
 
}
 

	
 
void MainBase::CutSAM() {
 
	
 
void MainBase::CutSAM()
 
{
 
	mesh.CutAwaySAM();
 
}
 
	
 
}
 
/* finis */
src/mainbase.h
Show inline comments
 
@@ -123,12 +123,14 @@ class MainBase  {
 
    bool showapoplastsp;
 
    bool showfluxesp;
 
    bool dynamicscellsp;
 
    bool showtooltipsp;
 
    bool hidecellsp;
 
};
 

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

	
 
#endif
 

	
 
/* finis */
src/matrix.cpp
Show inline comments
 
@@ -26,149 +26,141 @@
 
#include "matrix.h"
 
#include "tiny.h"
 

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

	
 
Matrix::Matrix(const Vector &c1, const Vector &c2, const Vector &c3) {
 
  
 
  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) {
 

	
 
void Matrix::Alloc(void)
 
{
 
  // constructor
 
  mat = new double*[3];
 
  mat[0] = new double[9];
 
  for (int i=1;i<3;i++)
 
    mat[i]=mat[i-1]+3;
 
  
 
}
 

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

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

	
 
  // clear matrix
 
  for (int i=0;i<9;i++) {
 
    mat[0][i]=0.;
 
  }
 
 
 
}
 

	
 
Matrix::Matrix(const Matrix &source) {
 
 
 
Matrix::Matrix(const Matrix &source)
 
{
 
  // copy constructor
 
  Alloc();
 
  
 
  for (int i=0;i<9;i++) {
 
    mat[0][i]=source.mat[0][i];
 
  }
 
  
 
}
 

	
 

	
 
void Matrix::operator=(const Matrix &source) {
 
  
 
void Matrix::operator=(const Matrix &source)
 
{
 
  // assignment
 
  
 
  // don't assign to self
 
  if (this==&source) return;
 
  
 
  // copy 
 
  for (int i=0;i<9;i++)
 
    mat[0][i]=source.mat[0][i];
 
  
 
}
 

	
 

	
 
void Matrix::print(ostream *os) {
 
  
 
  *os << "{ { " << mat[0][0] << "," << mat[0][1] << "," << mat[0][2] << "},{" << mat[1][0] << "," << mat[1][1] << "," << mat[1][2] << "},{" << mat[2][0] << "," << mat[2][1] << "," << mat[2][2] << "} }";
 

	
 
void Matrix::print(ostream *os)
 
{
 
  *os << "{ { " << mat[0][0] << "," << mat[0][1] << "," << mat[0][2] 
 
      << "},{" << mat[1][0] << "," << mat[1][1] << "," << mat[1][2] 
 
      << "},{" << mat[2][0] << "," << mat[2][1] << "," << mat[2][2] << "} }";
 
}
 

	
 
ostream &operator<<(ostream &os, Matrix &v) {
 
  v.print(&os);
 
  return os;
 
}
 

	
 

	
 
Vector Matrix::operator*(const Vector &v) const {
 
  
 
Vector Matrix::operator*(const Vector &v) const
 
{
 
  // matrix * vector
 
  Vector result;
 
  
 
  result.x = mat[0][0]*v.x+mat[0][1]*v.y+mat[0][2]*v.z;
 
  result.y = mat[1][0]*v.x+mat[1][1]*v.y+mat[1][2]*v.z;
 
  result.z = mat[2][0]*v.x+mat[2][1]*v.y+mat[2][2]*v.z;
 
  
 
  return result;
 
  
 
  
 
}
 

	
 

	
 
bool Matrix::operator==(Matrix &m) const {
 
   
 
bool Matrix::operator==(Matrix &m) const
 
{
 
  for (int i=0;i<9;i++) {
 
    if ((mat[0][i]-m.mat[0][i])>TINY)
 
      return false;
 
  }
 
  return true;
 
  
 
}
 

	
 
double Matrix::Det(void) const {
 
  
 
double Matrix::Det(void) const
 
{
 
  return 
 
    - mat[0][2]*mat[0][4]*mat[0][6]
 
    + mat[0][1]*mat[0][5]*mat[0][6] 
 
    + mat[0][2]*mat[0][3]*mat[0][7]
 
    - mat[0][0]*mat[0][5]*mat[0][7]
 
    - mat[0][1]*mat[0][3]*mat[0][8]
 
    + mat[0][0]*mat[0][4]*mat[0][8];
 

	
 
}
 

	
 
Matrix Matrix::Inverse(void) const {
 
Matrix Matrix::Inverse(void) const
 
{
 
  
 
  // return the Inverse of this matrix
 
  double rd=1./Det(); // Reciproce Det;
 
  Matrix inverse;
 
  inverse.mat[0][0]=rd*(-mat[0][5]*mat[0][7]+mat[0][4]*mat[0][8]);
 
  inverse.mat[0][1]=rd*( mat[0][2]*mat[0][7]-mat[0][1]*mat[0][8]);
 
  inverse.mat[0][2]=rd*(-mat[0][2]*mat[0][4]+mat[0][1]*mat[0][5]);
 
  inverse.mat[0][3]=rd*( mat[0][5]*mat[0][6]-mat[0][3]*mat[0][8]);
 
  inverse.mat[0][4]=rd*(-mat[0][2]*mat[0][6]+mat[0][0]*mat[0][8]);
 
  inverse.mat[0][5]=rd*( mat[0][2]*mat[0][3]-mat[0][0]*mat[0][5]);
 
  inverse.mat[0][6]=rd*(-mat[0][4]*mat[0][6]+mat[0][3]*mat[0][7]);
 
  inverse.mat[0][7]=rd*( mat[0][1]*mat[0][6]-mat[0][0]*mat[0][7]);
 
  inverse.mat[0][8]=rd*(-mat[0][1]*mat[0][3]+mat[0][0]*mat[0][4]);
 
  
 

	
 
  return inverse;
 
}
 

	
 
void Matrix::Rot2D(double theta) { 
 
  
 
void Matrix::Rot2D(double theta)
 
{ 
 
  // make this matrix a rotation matrix over theta
 
  // see http://mathworld.wolfram.com/RotationMatrix.html
 
 
 
  mat[0][0] = cos(theta); mat[0][1]=sin(theta);
 
  mat[1][0] = -sin(theta); mat[1][1]=cos(theta);
 
  mat[0][2] = mat[1][2] = mat[2][0] = mat[2][1] = mat[2][2] = 0.;
 
}
 

	
 
}
 
/* finis */
src/matrix.h
Show inline comments
 
@@ -46,12 +46,14 @@ public:
 
  void Rot2D(double theta); // make a matrix doing a 2D rotation over theta
 
  // data members 
 
  double **mat;
 

	
 
private:
 

	
 
  void Alloc(void);
 
};
 

	
 
ostream &operator<<(ostream &os, Matrix &v);
 

	
 
#endif
 

	
 
/* finis */
src/maxmin.h
Show inline comments
 
@@ -24,12 +24,13 @@
 

	
 
#ifndef _MAXMIN_H_
 
#define _MAXMIN_H_
 

	
 
#include <cmath>
 

	
 
inline double FMAX(double a, double b) { return a>b ? a : b; }
 
inline double FMIN(double a, double b) { return a<b ? a : b; }
 
inline double SIGN(double a, double b) { return b>=0.0 ? fabs(a) : -fabs(a); }
 

	
 
#endif
 

	
 
/* finis */
src/mesh.cpp
Show inline comments
 
@@ -52,36 +52,34 @@ static const std::string _module_id("$Id
 
extern Parameter par;
 

	
 
void Mesh::AddNodeToCellAtIndex(Cell *c, Node *n, Node *nb1, Node *nb2, list<Node *>::iterator ins_pos) {
 
  c->nodes.insert(ins_pos, n);        
 
  n->owners.push_back( Neighbor(c, nb1, nb2 ) );
 
}
 

	
 

	
 
void Mesh::AddNodeToCell(Cell *c, Node *n, Node *nb1, Node *nb2) {
 
  
 
  c->nodes.push_back( n );
 
  n->owners.push_back( Neighbor(c, nb1, nb2 ) );
 
  
 
}
 

	
 
void Mesh::PerturbChem(int chemnum, double range) {
 
  
 
  for (vector<Cell *>::iterator i=cells.begin();
 
       i!=cells.end();
 
       i++) {
 
    (*i)->chem[chemnum] += range*(RANDOM()-0.5);
 
    if ((*i)->chem[chemnum]<0.) (*i)->chem[chemnum]=0.;
 
  }
 
  
 
}
 

	
 
void Mesh::CellFiles(const Vector ll, const Vector ur) {
 
  
 
  Cell *cell = RectangularCell(ll,ur,0.001); 
 
  
 
  for (int c=0;c<Cell::NChem();c++) {
 
    cell->SetChemical(c,par.initval[c]);
 
  }
 
  
 
  cell->SetTargetArea(cell->CalcArea());
 
  
 
@@ -123,25 +121,24 @@ void Mesh::CellFiles(const Vector ll, co
 
   
 
    sum_l += l;
 
    n_l++;
 
  
 
  }
 
  
 
  
 
  Node::target_length = sum_l/(double)n_l;
 
  // a bit more tension
 
  Node::target_length/=4.;
 
  
 
  SetBaseArea();
 

	
 
}
 

	
 
Cell *Mesh::RectangularCell(const Vector ll, const Vector ur, double rotation) {
 

	
 
  Cell *cell=AddCell(new Cell());
 
  cell->m=this;
 
  
 
  Matrix rotmat;
 
  rotmat.Rot2D(rotation); // rotation over 0,0
 
  
 
  Node *n1=AddNode(new Node(rotmat * ll));
 
  Node *n2=AddNode(new Node(rotmat * Vector(ll.x, ur.y,0)));
 
@@ -272,26 +269,24 @@ Cell &Mesh::EllipticCell(double xc, doub
 
  
 
  c->SetIntegrals(); 
 
  //c->ConstructNeighborList();
 
  
 
  //c->ConstructWalls();
 

	
 
  // initial cell has one wall with the outside world
 
  //c->walls.push_back( new Wall ( nodes.front(), nodes.front(), c, boundary_polygon )); 
 
  
 
  c->at_boundary=true;
 
  
 
  return *c;
 

	
 
  
 
}
 

	
 
Cell &Mesh::LeafPrimordium(int nnodes, double pet_length) {
 
  
 
  // first leaf cell
 

	
 
  int first_node=Node::nnodes;
 
  
 
  Cell *circle=AddCell(new Cell(0,0));
 
  circle->m=this;
 
  const double ra=10, rb=10;
 
  const double xc=0,yc=0;
 
@@ -442,52 +437,48 @@ Cell &Mesh::LeafPrimordium(int nnodes, d
 
  petiole->target_area=petiole->area;  
 
  petiole->ConstructNeighborList();
 
  circle->ConstructNeighborList();
 
  boundary_polygon->ConstructConnections();
 
  boundary_polygon->ConstructNeighborList();
 

	
 
  circle->setCellVec(Vector(0,1,0));
 
  
 
  return *circle;
 
}
 

	
 
/*Cell &Mesh::Box() {
 
  
 
  
 
  
 
}*/
 

	
 

	
 
// return bounding box of mesh
 
void Mesh::BoundingBox(Vector &LowerLeft, Vector &UpperRight) {
 
   
 
  LowerLeft = **nodes.begin();
 
  UpperRight = **nodes.begin();
 
  for (vector<Node *>::iterator c=nodes.begin();
 
       c!=nodes.end();
 
       c++) {
 
    if ((*c)->x < LowerLeft.x)
 
      LowerLeft.x = (*c)->x;
 
    if ((*c)->y < LowerLeft.y)
 
      LowerLeft.y = (*c)->y;
 
    if ((*c)->z < LowerLeft.z)
 
      LowerLeft.z = (*c)->z;
 
    if ((*c)->x > UpperRight.x) 
 
      UpperRight.x = (*c)->x;
 
    if ((*c)->y > UpperRight.y) 
 
      UpperRight.y = (*c)->y;
 
    if ((*c)->z > UpperRight.z)
 
      UpperRight.z = (*c)->z;
 
  }
 
  
 
}
 

	
 

	
 
double Mesh::Area(void) {
 
  
 
  double area=0;
 
  vector<Cell *>::iterator i=cells.begin();
 
  while (i != cells.end()) {
 
    area += (*(i++))->Area();
 
  }
 
  return area;
 
}
 
@@ -1020,25 +1011,24 @@ double Mesh::DisplaceNodes(void) {
 
	       }*/
 
	  }
 
	  sum_dh += dh;
 
	}  
 
      }
 
    } 
 
    next_node:
 
      delta_intgrl_list.clear();//dA_list.clear();
 
      
 
    }
 
    
 
    return sum_dh;
 
    
 
}
 
				   
 

	
 
void Mesh::InsertNode(Edge &e) {
 

	
 

	
 
  // Construct a new node in the middle of the edge
 
  Node *new_node = AddNode( new Node ( ( *e.first + *e.second )/2 ) );
 
  
 
  // if new node is inserted into the boundary
 
  // it will be part of the boundary, fixed, and source, too
 

	
 
@@ -1179,25 +1169,24 @@ void Mesh::InsertNode(Edge &e) {
 
  // `administration' is up to date
 
  while (c!=owners.end()) {
 
    c=adjacent_find(c,owners.end(),  neighbor_cell_eq);
 
    // repair neighborhood lists of cell and Wall lists
 
    //if (c->cell>=0) {
 
    if (!c->cell->BoundaryPolP()) {
 
      c->cell->ConstructNeighborList();
 
      //      debug_stream << "Repairing NeighborList of " << c->cell << endl;
 
    }
 
    c++;
 
  }
 
  //  debug_stream.flush();
 

	
 
}
 

	
 

	
 
/*
 
   Calculate circumcircle of triangle (x1,y1), (x2,y2), (x3,y3)
 
   The circumcircle centre is returned in (xc,yc) and the radius in r
 
   NOTE: A point on the edge is inside the circumcircle
 
*/
 
void Mesh::CircumCircle(double x1,double y1,double x2,double y2,double x3,double y3,
 
		 double *xc,double *yc,double *r)
 
{
 
  double m1,m2,mx1,mx2,my1,my2;
 
@@ -1229,41 +1218,39 @@ void Mesh::CircumCircle(double x1,double
 
    *xc = (m1 * mx1 - m2 * mx2 + my2 - my1) / (m1 - m2);
 
    *yc = m1 * (*xc - mx1) + my1;
 
  }
 

	
 
  dx = x2 - *xc;
 
  dy = y2 - *yc;
 
  rsqr = dx*dx + dy*dy;
 
  *r = sqrt(rsqr);
 

	
 
  return;
 
  // Suggested
 
  // return((drsqr <= rsqr + EPSILON) ? TRUE : FALSE);
 

	
 
}
 
  
 
//
 

	
 
// return the total amount of chemical "ch" in the leaf
 
double Mesh::SumChemical(int ch) {
 
  
 
  double sum=0.;
 
  for (vector<Cell *>::iterator i=cells.begin();
 
       i!=cells.end();
 
       i++) {
 
  
 
    sum+=(*i)->chem[ch];
 
  }
 
  return sum;
 

	
 
}
 

	
 

	
 

	
 
void Mesh::CleanUpCellNodeLists(void) {
 
  
 
  typedef vector <vector<Cell *>::iterator> CellItVect;
 
  
 
  CellItVect cellstoberemoved;
 
  vector<int> cellind;
 
  
 
  // Start of by removing all stale walls.
 
@@ -1430,25 +1417,24 @@ void Mesh::CleanUpCellNodeLists(void) {
 
       i++) {
 
    
 
    (*i)->ConstructWalls();
 
  }
 
  */
 
  
 
  // remake shuffled_nodes and shuffled cells
 
  shuffled_nodes.clear();
 
  shuffled_nodes = nodes;
 
  
 
  shuffled_cells.clear();
 
  shuffled_cells = cells;
 
 
 
}
 

	
 
void Mesh::CutAwayBelowLine( Vector startpoint, Vector endpoint) {
 
  
 
  // Kills all cells below the line startpoint -> endpoint
 
  
 
  Vector perp = (endpoint-startpoint).Perp2D().Normalised();
 
  
 
  #ifdef QDEBUG
 
  qDebug() << "Before Apoptose" << endl;
 
  #endif
 

	
 
@@ -1463,74 +1449,69 @@ void Mesh::CutAwayBelowLine( Vector star
 
    if ( InnerProduct(perp, cellvec) < 0 ) {
 
      // remove those cells
 
      (*i)->Apoptose();
 
    }
 
  }
 

	
 
  #ifdef QDEBUG
 
  qDebug() << "Before CleanUpCellNodeLists" << endl;
 
  #endif
 
  TestIllegalWalls();
 
  
 
  CleanUpCellNodeLists();
 

	
 
}
 

	
 
void Mesh::CutAwaySAM(void) {
 

	
 
  for (vector<Cell *>::iterator i=cells.begin();
 
       i!=cells.end();
 
       i++) {
 
    
 
    if( (*i)->Boundary() == Cell::SAM ) {
 

	
 
	(*i)->Apoptose();
 
    }
 
  }
 

	
 
  TestIllegalWalls();
 
  
 
  CleanUpCellNodeLists();
 

	
 

	
 
}
 
void Mesh::TestIllegalWalls(void) {
 

	
 
  for (list<Wall *>::iterator w = walls.begin();
 
       w!=walls.end();
 
       w++) {
 
    if ((*w)->IllegalP() ) {
 
      #ifdef QDEBUG
 
      qDebug() << "Wall " << **w << " is illegal." << endl;
 
      #endif
 
    }
 
  }
 

	
 
}
 

	
 

	
 

	
 
class node_owners_eq : public unary_function<Node, bool> {
 
  int no;
 
public:
 
  
 
  explicit node_owners_eq(int nn) { no=nn; }
 

	
 
  bool operator() (const Node &n) const {
 
    if (n.CellsSize()==1) 
 
      return true;
 
    else 
 
      return false;
 
  }
 
  
 
};
 

	
 

	
 
void Mesh::RepairBoundaryPolygon(void) {
 
  
 
  // After serious manipulations (e.g. after cutting part off the
 
  // leaf) repair the boundary polygon. It assumes the cut line has
 
  // already been marked "boundary" and the original boundary marks
 
  // were not removed. 
 
  //
 
  // So, this function just puts boundary nodes into the boundary
 
  // polygon in the right order; it cannot detect boundaries from
 
@@ -1643,25 +1624,24 @@ void Mesh::RepairBoundaryPolygon(void) {
 
  foreach(Wall* wall, walls) {
 
    qDebug() << *wall;
 
  }
 
  qDebug() << endl;
 

	
 
  qDebug() << "CELLS:" << endl;
 
  foreach(Cell* cell, cells) {
 
    qDebug() << *cell;
 
  }
 
  qDebug() << endl;
 
  #endif
 
#endif
 

	
 
}
 

	
 

	
 
Node* Mesh::findNextBoundaryNode(Node* boundary_node) {
 
  bool found_next_boundary_node = false;
 
  Node *next_boundary_node = NULL;
 
  set<int> boundary_node_owners; // This is a list of the current boundary node's owners' Ids
 
  vector<int> neighborIds; // A list of the current boundary node's owners' 2nd neighbor Ids
 
  vector<set<int> *>  nodeOwners; // A vector of set pointers where each set contains the owner Ids of the nodes in the neighborIds list.
 
  vector<int> intersection; // set intersection result
 

	
 
  // The next boundary node is that which has only one owner in common with the current boundary node
 
@@ -1746,25 +1726,24 @@ void Mesh::Rotate(double angle, Vector c
 
       n!=nodes.end();
 
       n++) {
 

	
 
    (*n)->setPos ( rotmat * ( *(*n) - center ) + center );  
 
    
 
  }
 
}
 

	
 

	
 
void Mesh::PrintWallList( void ) {
 
  
 
   transform ( walls.begin(), walls.end(), ostream_iterator<Wall>(cerr, "\n"), deref_ptr<Wall> );
 

	
 
}
 

	
 
#include <QString>
 
//#include "forwardeuler.h"
 
#include "rungekutta.h"
 

	
 
class SolveMesh : public RungeKutta {
 
    
 
private:
 
  SolveMesh(void);
 
    
 
public:
 
@@ -1819,25 +1798,24 @@ void Mesh::ReactDiffuse(double delta_t) 
 
	     mem_fun( &Wall::SetLength ) );
 
  
 
  static SolveMesh *solver = new SolveMesh(this);
 
  
 
  int nok, nbad, nvar;
 
  double *ystart = getValues(&nvar);
 
  
 
  solver->odeint(ystart, nvar, getTime(), getTime() + delta_t, 
 
		 par.ode_accuracy, par.dt, 1e-10, &nok, &nbad);
 
  
 
  setTime(getTime()+delta_t);
 
  setValues(getTime(),ystart);
 
  
 
}
 

	
 

	
 
Vector Mesh::FirstConcMoment(int chem) {
 
  
 
  Vector moment;
 
  for (vector<Cell *>::const_iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
    
 
    moment += (*c)->Chemical(chem) * (*c)->Centroid();
 
    
 
@@ -1865,25 +1843,24 @@ void Mesh::DeleteLooseWalls(void) {
 
      } else {
 
	if ((*w)->C1()->DeadP())
 
	  (*w)->c1 = boundary_polygon;
 
	else
 
	  (*w)->c2 = boundary_polygon;
 
	w++;
 
      }
 
    } else {
 
      w++;
 
    }
 
    
 
  }
 
  
 
}
 

	
 
/*void Mesh::FitLeafToCanvas(double width, double height) {
 

	
 
  Vector bbll,bbur;
 
  BoundingBox(bbll,bbur);
 
  
 
  double scale_x = width/(bbur.x-bbll.x);
 
  double scale_y = height/(bbur.y-bbll.y);
 
  
 
  double factor = scale_x<scale_y ? scale_x:scale_y;
 
  
 
@@ -1904,47 +1881,44 @@ void Mesh::CleanChemicals(const vector<d
 
		throw "Run time error in Mesh::CleanChemicals: size of clean_chem should be equal to Cell::NChem()";
 
	}
 
	for (vector<Cell *>::iterator c=cells.begin();
 
		 c!=cells.end();
 
		 c++) {
 
		
 
		for (int i=0;i<Cell::NChem();i++) {
 
			(*c)->SetChemical(i,clean_chem[i]);
 
		}
 
		(*c)->SetNewChemToChem();
 
		
 
	}
 
	
 

	
 
}
 

	
 

	
 
void Mesh::CleanTransporters(const vector<double> &clean_transporters) {
 
	
 
	if (clean_transporters.size()!=(unsigned)Cell::NChem()) {
 
		throw "Run time error in Mesh::CleanTransporters: size ofclean_transporters should be equal to Cell::NChem()";
 
	}
 

	
 
	
 
	// clean transporters
 
	for (list<Wall *>::iterator w=walls.begin();
 
		 w!=walls.end();
 
		 w++) {
 
		
 
		for (int i=0;i<Cell::NChem();i++) {
 
			(*w)->setTransporters1(i,clean_transporters[i]); (*w)->setNewTransporters1(i,clean_transporters[i]);
 
			(*w)->setTransporters2(i,clean_transporters[i]); (*w)->setNewTransporters2(i,clean_transporters[i]);
 
		}
 
	}
 
	
 
}
 

	
 

	
 
void Mesh::RandomizeChemicals(const vector<double> &max_chem, const vector<double> &max_transporters) {
 
  
 
  if (max_chem.size()!=(unsigned)Cell::NChem() || max_transporters.size()!=(unsigned)Cell::NChem()) {
 
    throw "Run time error in Mesh::CleanChemicals: size of max_chem and max_transporters should be equal to Cell::NChem()";
 
  }
 
  
 
  for (vector<Cell *>::iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
@@ -1957,25 +1931,24 @@ void Mesh::RandomizeChemicals(const vect
 
  }
 

	
 
  // randomize transporters
 
  for (list<Wall *>::iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 
    
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*w)->setTransporters1(i,max_transporters[i] * RANDOM()); (*w)->setNewTransporters1(i, (*w)->Transporters1(i) );
 
      (*w)->setTransporters2(i,max_transporters[i] * RANDOM()); (*w)->setNewTransporters2(i, (*w)->Transporters1(i) );
 
    }
 
  }
 
  
 
}
 

	
 
//!\brief Calculates a vector with derivatives of all variables, which
 
// we can pass to an ODESolver. 
 
void Mesh::Derivatives(double *derivs) {
 
  
 
  int nwalls = walls.size();
 
  int ncells = cells.size();
 
  int nchems = Cell::NChem();
 
  
 
  // two eqs per chemical for each walls, and one eq per chemical for each cell
 
  // This is for generality. For a specific model you may optimize
 
@@ -2015,26 +1988,24 @@ void Mesh::Derivatives(double *derivs) {
 
	  if ((*w)->c1->Index()<0) { // tests if c1 is the boundary pol
 
		  dchem_c1 = &dummy1;
 
	  }
 
	  if ((*w)->c2->Index()<0) {
 
		  dchem_c2 = &dummy2;
 
	  }
 
	  plugin->CelltoCellTransport(*w, dchem_c1, dchem_c2); 
 
								  
 
	  //(*tf)(*w, &(derivs[(*w)->c1->Index() * nchems]),
 
      //&(derivs[(*w)->c2->Index() * nchems] ) );
 
    i+=2*nchems;
 
  }
 
  
 
  
 
}
 

	
 
void Mesh::setValues(double x, double *y) {
 

	
 
  //int nwalls = walls.size();
 
  //int ncells = cells.size();
 
  int nchems = Cell::NChem();
 
  
 
  // two eqs per chemical for each walls, and one eq per chemical for each cell
 
  // This is for generality. For a specific model you may optimize
 
  // this by removing superfluous (empty) equations.
 
  //int neqs = 2 * nwalls * nchems + ncells * nchems;
 
@@ -2129,25 +2100,24 @@ void Mesh::DrawNodes(QGraphicsScene *c) 
 
       n++) {
 
    
 
    Node *i=*n;
 
    
 
    NodeItem *item = new NodeItem ( &(*i), c );
 
    item->setColor();
 
    
 
    item->setZValue(5);
 
    item->show();
 
    item ->setPos(((Cell::offset[0]+i->x)*Cell::factor),
 
		  ((Cell::offset[1]+i->y)*Cell::factor) );
 
  }
 

	
 
}
 

	
 
/*! Returns the sum of protein "ch" of a cycling protein in cells and walls */
 
double Mesh::CalcProtCellsWalls(int ch) const {
 

	
 

	
 
  double sum_prot=0.;
 

	
 
  // At membranes
 
  for (list<Wall *>::const_iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 
@@ -2155,43 +2125,41 @@ double Mesh::CalcProtCellsWalls(int ch) 
 
    sum_prot += (*w)->Transporters2(ch);
 
  }
 

	
 
  // At cells
 
  for (vector<Cell *>::const_iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
    
 
    sum_prot += (*c)->Chemical(ch);
 
  }
 
  
 
  return sum_prot;
 

	
 
}
 

	
 
void Mesh::SettoInitVals(void) {
 
  
 
  vector<double> clean_chem(Cell::NChem());
 
  vector<double> clean_transporters(Cell::NChem());
 
  
 
  for (int i=0;i<Cell::NChem();i++) {
 
    clean_transporters[i]=0.;
 
    clean_chem[i]=par.initval[i];
 
  }
 

	
 
  // Amount of PIN1
 
  //clean_chem[1] = 0.;
 
  
 
	CleanChemicals(clean_chem);
 
	CleanTransporters(clean_transporters);
 

	
 
}
 

	
 
string Mesh::getTimeHours(void) const {
 
	int hours = (int)(time / 3600);
 
	int mins = (int)((time - hours * 3600)/60);
 
	int secs = (int)((time - hours * 3600 - mins * 60));
 
	ostringstream tstr;
 
	tstr << hours << " h " << mins << " m " << secs << " s";
 
	return tstr.str();
 
}
 

	
 
QVector<qreal> Mesh::VertexAngles(void) {
src/mesh.h
Show inline comments
 
@@ -156,39 +156,36 @@ public:
 
	}
 
	
 
	template<class Op> void RandomlyLoopNodes(Op f) {
 
		
 
		MyUrand r(shuffled_nodes.size());
 
		random_shuffle(shuffled_nodes.begin(),shuffled_nodes.end(),r);
 
		
 
		for (vector<Node *>::const_iterator i=shuffled_nodes.begin();
 
			 i!=shuffled_nodes.end();
 
			 i++) {
 
			f(*shuffled_nodes[*i]);
 
		}
 
		
 
	}
 
	
 
	template<class Op> void RandomlyLoopCells(Op f) {
 
		
 
		MyUrand r(shuffled_cells.size());
 
		random_shuffle(shuffled_cells.begin(),shuffled_cells.end(),r);
 
		
 
		for (vector<Cell *>::const_iterator i=shuffled_cells.begin();
 
			 i!=shuffled_cells.end();
 
			 i++) {
 
			f(*shuffled_cells[*i]);
 
		}
 
		
 
		
 
	}
 
	
 
	template<class Op1, class Op2> void LoopCells(Op1 f, Op2 &g) {
 
		for (vector<Cell *>::iterator i=cells.begin();
 
			 i!=cells.end();
 
			 i++) {
 
			f(**i,g); 
 
		}
 
	}
 
	
 
	template<class Op1, class Op2, class Op3> void LoopCells(Op1 f, Op2 &g, Op3 &h) {
 
		for (vector<Cell *>::iterator i=cells.begin();
 
@@ -418,12 +415,14 @@ private:
 
		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;
 
	}
 
	
 
	void CircumCircle(double x1,double y1,double x2,double y2,double x3,double y3,
 
					  double *xc,double *yc,double *r);
 
};
 
#endif
 

	
 
/* finis */
src/miscq.cpp
Show inline comments
 
@@ -17,21 +17,22 @@
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include <QString>
 
#include <QStringList>
 

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

	
 
// Returns the extension of a filename
 
QString getExtension(const QString fn) {
 
  
 
QString getExtension(const QString fn)
 
{
 
  // split on dots
 
  QStringList parts = fn.split(".");
 
  
 
  // return last part, this should be the extension
 
  return QString(parts.last());
 
}
 
  
 
}
 
/* finis */
src/miscq.h
Show inline comments
 
@@ -24,12 +24,13 @@
 

	
 
#ifndef _MISCQ_h_
 
#define _MISCQ_h_
 

	
 
#include <QString>
 

	
 
// Miscellaneous helper functions, using Qt
 

	
 
QString getExtension(const QString fn);
 

	
 
#endif
 

	
 
/* finis */
src/modelcatalogue.h
Show inline comments
 
@@ -46,15 +46,14 @@ public:
 
	void LoadPlugin(const char *model);
 
	
 
	void InstallFirstModel();
 
	void PopulateModelMenu();	
 

	
 
public slots:
 
	void InstallModel(SimPluginInterface *model);	
 
	void InstallModel(QAction *modelaction);
 
private:
 
	QVector<SimPluginInterface *> models;
 
	Mesh *mesh;
 
	Main *mainwin;
 

	
 
};
 
#endif
src/node.cpp
Show inline comments
 
@@ -40,184 +40,179 @@ extern Parameter par;
 

	
 
int Node::nnodes=0;
 
double Node::target_length=1;
 

	
 
ostream &Edge::print(ostream &os) const {
 
  return os << "{ " << first->Index() << ", " << second->Index() << " }";
 
}
 

	
 
ostream &Neighbor::print(ostream &os) const {
 
  
 
  os << " {" << cell->Index() << " " << nb1->Index() << " " << nb2->Index() << "}";
 
  return os;
 

	
 
}
 

	
 
ostream &operator<<(ostream &os, const Neighbor &n) {
 
  n.print(os);
 
  return os;
 
}
 
 
 

	
 
Node::Node(void) : Vector() {
 

	
 
Node::Node(void) : Vector()
 
{
 
  index=(nnodes++);
 
  node_set =0;
 
  fixed=false;
 
  boundary=false;
 
  sam=false;
 
  dead=false;
 
}
 

	
 
Node::Node(int ind) : Vector() {
 
Node::Node(int ind) : Vector()
 
{
 
  node_set =0;
 
  index=ind;
 
  fixed=false;
 
  boundary=false;
 
  sam=false;
 
  dead=false;
 
}
 

	
 
Node::Node(const Vector &src) : Vector(src) {
 

	
 
Node::Node(const Vector &src) : Vector(src)
 
{
 
  node_set = 0;
 
  index=(nnodes++);
 
  fixed=false;
 
  boundary=false;
 
  sam=false;
 
  dead = false;
 
}
 

	
 
Node::Node(double x,double y, double z) : Vector (x,y,z) {
 
  
 
Node::Node(double x,double y, double z) : Vector (x,y,z)
 
{
 
  node_set = 0;
 
  index=(nnodes++);
 
  fixed=false;
 
  boundary=false;
 
  sam=false;
 
  dead = false;
 
}
 

	
 
Node::Node(const Node &src) : Vector(src) {
 
  
 
Node::Node(const Node &src) : Vector(src)
 
{
 
  node_set=0;
 
  owners=src.owners;
 
  m=src.m;
 
  index=src.index;
 
  fixed = src.fixed;
 
  boundary = src.boundary;
 
  sam=src.sam;
 
  dead = src.dead;
 
}
 

	
 

	
 
Cell &Node::getCell(const Neighbor &i) {
 
Cell &Node::getCell(const Neighbor &i)
 
{
 
  return *i.getCell(); // use accessor!
 
}
 

	
 

	
 
ostream &Node::print(ostream &os) const {
 
  
 
  if (!dead) 
 
    os << "Node ";
 
  else
 
    os << "DEAD NODE ";
 
  
 
  os  << index << "[ {" << x << ", " << y << ", " << z << "}: {";
 
  
 
  os << "Neighbors = { ";
 

	
 
  for (list<Neighbor>::const_iterator i =  owners.begin(); i!=owners.end(); i++) {
 
    os << " {" << i->cell->Index() << " " << i->nb1->Index() << " " << i->nb2->Index() << "} ";
 
  }
 
  os << " } " << endl;
 

	
 
  return os;
 

	
 
}
 

	
 

	
 
#ifdef QTGRAPHICS
 
void Node::DrawIndex(QGraphicsScene *c) const {
 

	
 
  //return DrawOwners(c);
 
  stringstream text;
 
  text << index;
 
  QGraphicsSimpleTextItem *number = new QGraphicsSimpleTextItem ( QString (text.str().c_str()), 0, c );
 
  number->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
  number->setPen( QPen (par.textcolor) );
 
  number->setZValue(20);
 
  number->show();
 
  Vector offs=Cell::Offset();
 
  number -> setPos(
 
		   ((offs.x+x)*Cell::Factor()),
 
		   ((offs.y+y)*Cell::Factor()) );
 
}
 

	
 
void Node::DrawOwners(QGraphicsScene *c) const {
 
  
 
  stringstream text;
 
  
 
  
 

	
 
  text << owners.size();
 
  
 
  
 
  QGraphicsSimpleTextItem *number = new QGraphicsSimpleTextItem ( QString (text.str().c_str()), 0, c );
 
  number->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
  number->setPen( QPen(par.textcolor) );
 
  number->setZValue(20);
 
  number->show();
 
  Vector offs=Cell::Offset();
 
  
 
  number ->setPos(((offs.x+x)*Cell::Factor()),
 
		  ((offs.y+y)*Cell::Factor()) );
 
}
 

	
 

	
 

	
 
QVector<qreal> Node::NeighbourAngles(void) {
 
	
 
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();	
 
	
 
		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;
 
    //cerr << "Cell " << i->cell->Index() << ": " <<  v1 << " and " << v2 
 
    //     << ": angle = " << angles.back() << ", " << v1.Angle(v2) << endl;
 
		
 
	}
 
	
 
	double sum=0.;
 
	for (QVector<qreal>::iterator i=angles.begin();
 
		 i!=angles.end();
 
		 i++) {
 
		sum+=*i;
 
	}
 
	//cerr << "Angle sum = " << sum << endl;
 
	// Check if the summed angle is different from 2 Pi 
 
	if (fabs(sum-(2*Pi))>0.0001) {
 
		
 
		MyWarning::warning("sum = %f",sum);
 
	}
 
		return angles;
 
}
 

	
 

	
 

	
 
#endif
 

	
 

	
 
ostream &operator<<(ostream &os, const Node &n) {
 
  n.print(os);
 
  return os;
 
}
 

	
 
/* finis */
src/node.h
Show inline comments
 
@@ -69,25 +69,24 @@ public:
 
  }
 

	
 
  // Ambidextrous equivalence 
 
  inline bool operator==(const Edge &e) {
 
    return ( (first==e.first && second==e.second) ||
 
	     (first==e.second && second==e.first) );
 
  }
 
  
 

	
 
  // Output the Edge
 
  ostream &print(ostream &os) const;
 
    
 
  
 
  Node *first, *second;
 
};
 

	
 

	
 
class NodeSet;
 

	
 
// this class is a node in a cell wall
 
class Node : public Vector {
 

	
 
  friend class Mesh;
 
  friend class CellBase;
 
  friend class Cell;
 
@@ -129,63 +128,50 @@ public:
 
  Cell &getCell(const Neighbor &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();
 
  }
 
  inline int CellsSize(void) const { return owners.size(); }
 

	
 
  inline int Value(void) const { return owners.size(); }
 

	
 
  inline int Value(void) const {
 
    return owners.size();
 
  }
 
  void Fix(void) { fixed=true; }
 

	
 
  inline bool Fixed(void) const { return fixed; }
 

	
 
  inline void Unfix(void) { fixed=false; }
 

	
 
  void Fix(void) {
 
    fixed=true;
 
  }
 
  inline bool Fixed(void) const {
 
    return fixed;
 
  }
 
  inline void Unfix(void) {
 
    fixed=false;
 
  }
 
  inline void MarkDead(void) {
 
    dead=true;
 
  }
 
  inline bool DeadP(void) {
 
    return dead;
 
  }
 
  inline void MarkDead(void) { dead=true; }
 

	
 
  inline bool DeadP(void) { return dead; }
 

	
 
  inline void Mark(void) {
 
    marked=true;
 
  }
 
  inline void Unmark(void) {
 
    marked=false;
 
  }
 
  inline bool Marked(void) const {
 
    return marked;
 
  }
 
  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; }
 

	
 
  //!\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;
 
@@ -201,14 +187,15 @@ private:
 
  bool sam; // true if node is connected to the shoot
 
  bool dead;
 
  bool marked;
 
};
 

	
 
ostream &operator<<(ostream &os, const Node &n);
 

	
 
inline ostream &operator<<(ostream &os, const Edge &e) {
 
  e.print(os);
 
  return os;
 
}
 

	
 
#endif
 

	
 
#endif
 
/* finis */
src/nodeitem.cpp
Show inline comments
 
@@ -30,86 +30,88 @@
 

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

	
 
extern Parameter par;
 

	
 
NodeItem::NodeItem( Node *n, QGraphicsScene *canvas )
 
  : QGraphicsItem( 0, canvas ), SimItemBase( n, canvas) {
 
  
 
  brush = Qt::darkGray;
 
  
 
  const double mag = par.node_mag;
 
  ellipsesize=QRectF(-1*mag, -1*mag, 2*mag, 2*mag);
 

	
 
}
 

	
 
void NodeItem::userMove(double dx, double dy) {
 
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 *)
 
{
 

	
 
  option = NULL; // use assignment merely to obviate compilation warning
 
  
 
  painter->setBrush(brush);
 
  painter->setPen(Qt::NoPen);
 
  painter->drawEllipse(ellipsesize);
 
}
 

	
 

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

	
 
QRectF NodeItem::boundingRect() const
 
{
 
  qreal penwidth = 0;// painter->pen()->widthF();
 
  return QRectF(ellipsesize.x()-penwidth/2.,ellipsesize.y()-penwidth/2.,
 
		ellipsesize.width()+penwidth, ellipsesize.height()+penwidth);
 
}
 

	
 
// polymorphic OnClick functions
 
void NodeItem::OnClick(void) {
 
void NodeItem::OnClick(void)
 
{
 
  Node *n = &getNode();
 
  n->toggleBoundary();
 
  setColor();
 
  update();
 
}
 

	
 
void NodeItem::OnClick(const Qt::MouseButton &mb) {
 
void NodeItem::OnClick(const Qt::MouseButton &mb)
 
{
 
  if (mb == Qt::LeftButton) {
 
    Node *n = &getNode();
 
    n->toggleBoundary();
 
    setColor();
 
    update();
 

	
 
  }
 
}
 

	
 
void NodeItem::setColor(void) {
 

	
 
void NodeItem::setColor(void)
 
{
 
  static QColor indian_red("IndianRed");
 
  static QColor deep_sky_blue("DeepSkyBlue");
 
  static QColor purple("Purple");
 
  
 
  Node &n=getNode();
 

	
 
  if (n.SamP()) {
 
    setBrush( purple );
 
  } else {
 
    if (n.BoundaryP()) {
 
      setBrush( deep_sky_blue );
 
    } 
 
    else {
 
      setBrush( indian_red );
 
    }
 
  }
 
}
 

	
 
/* finis */
src/nodeitem.h
Show inline comments
 
@@ -47,12 +47,14 @@ public:
 
  /*! We use this function internally, to (somewhat) interactively edit init configurations.
 
    Simply put the property to be change upon clicking a node in this function. */
 
  void OnClick( const Qt::MouseButton &mb );
 
  void OnClick(void);
 
protected:
 
  QBrush brush;
 
  QRectF ellipsesize;
 

	
 
private:
 
};
 

	
 
#endif
 

	
 
/* finis */
src/nodeset.cpp
Show inline comments
 
@@ -20,12 +20,14 @@
 
 */
 

	
 
#include <string>
 
#include <ostream>
 
#include "nodeset.h"
 

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

	
 
ostream &operator<<(ostream &os, const NodeSet &ns)  {
 
  ns.print(os);
 
  return os;
 
}
 

	
 
/* finis */
src/nodeset.h
Show inline comments
 
@@ -52,26 +52,25 @@ class NodeSet : public list<Node *> {
 
    
 
    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();
 
    
 
    // remove all non-unique elements
 
    // (unique moves all unique elements to the front and returns an iterator to the end of the unique elements;
 
    // so we simply erase all remaining elements.
 
    cellset.erase(::unique(cellset.begin(), cellset.end() ), 
 
		  cellset.end() );
 
    cellset.erase(::unique(cellset.begin(), cellset.end() ), cellset.end() );
 
    
 
    // remove boundary_polygon
 
    cellset.erase( find_if ( cellset.begin(), cellset.end(), mem_fun( &Cell::BoundaryPolP  ) ) );
 
    return cellset;
 
  }
 

	
 
  void CleanUp(void) {
 
    
 
    // remove double Nodes from the set
 
    sort();
 
    erase(::unique(begin(), end() ), 
 
	      end() );
 
@@ -102,25 +101,24 @@ class NodeSet : public list<Node *> {
 
      old_energy += (*i)->Energy();
 
      sum_stiff += (*i)->Stiffness();
 
    }
 
    
 
    // 3. (Temporarily) move the set's nodes.
 
    for ( list<Node *>::iterator n = begin();
 
	  n!=end();
 
	  ++n ) {
 
       
 
      (*n)->x+=rx;
 
      (*n)->y+=ry;
 
      // (*n)->z += rz;
 
       
 
    }
 
    
 
    // 4. Recalculate the energy
 
    double new_energy = 0.;
 
    for ( list<Cell *>::const_iterator i = celllist.begin(); 
 
	  i!=celllist.end();
 
	  ++i ) {
 
      
 
      new_energy += (*i)->Energy();
 
    }
 
    
 
    
 
@@ -142,25 +140,25 @@ 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;
 
	  }
 
      
 
      
 
    }
 
  }
 
  
 
  void XMLAdd(xmlNode *root) const;
 
  void XMLRead(xmlNode *root, Mesh *m);
 
 private:
 
  bool done;
 
};
 

	
 
ostream &operator<<(ostream &os, const NodeSet &ns);
 
#endif
 

	
 
/* finis */
src/output.cpp
Show inline comments
 
@@ -52,85 +52,80 @@ int OpenFileAndCheckExistance(FILE **fp,
 
  } else return TRUE;
 
}
 
 
int FileExistsP(const char *fname) {
 
  
 
  FILE *fp;
 
  fp=fopen(fname,"r");
 
  if (fp==NULL)
 
    return FALSE;
 
  
 
  fclose(fp);
 
  return TRUE;
 
 
}
 
		       
 
int YesNoP(const char *message) {
 
  
 
  char answer[100];
 
 
  fprintf(stderr,"%s (y/n) ",message);
 
  fflush(stderr);
 
  
 
  scanf("%s",answer);
 
  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(const char *filename) 
 
{
 
 
  char fname[FNAMESIZE];
 
 
  FILE *fp;
 
 
  fprintf(stderr,"Opening %s for writing\n",filename);
 
	
 
  if(FileExistsP(filename)==TRUE) {
 
  
 
    if (false/*par.interactive*/) {
 
      char *message=(char *)malloc(2000*sizeof(char));
 
      if (!YesNoP("File exists, overwrite?")) {
 
	sprintf(message," Could not open file %s for writing, exiting... \n"
 
		,filename);
 
	//exit(0);
 
	throw(message);
 
      }
 
    } else {
 
      /* Rename old file */
 
      sprintf(fname, "%s~",filename);
 
      rename(filename, fname);
 
      
 
    }
 
  }
 
  
 
  strncpy(fname, filename, FNAMESIZE-1);
 
  
 
  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 *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));
 
@@ -161,62 +156,54 @@ char *ReadLine(FILE *fp)
 
 
  CheckFile(fp);
 
    
 
  /* first allocate a string with a standard length */
 
  bufsize=INITIAL_BUFSIZE;
 
  MEMORYCHECK(tmpstring=(char *)malloc(bufsize*sizeof(char)));
 
 
  pos=0;
 
  
 
  while ((character=getc(fp))!=EOF && /* read a character and check */
 
		 character!='\n') {
 
 
	
 
	tmpstring[pos]=(char)character;
 
	(pos)++;
 
 
	if (pos >= bufsize) {
 
	  /* line is longer than initial_bufsize, reallocate space */
 
	  bufsize+=INITIAL_BUFSIZE;
 
	  MEMORYCHECK(tmpstring=(char *)realloc(tmpstring,bufsize*sizeof(char)));
 
	  
 
	}
 
		   
 
  }
 
 
 
  if (character==EOF) {
 
	
 
	if (pos==0) {
 
	  /* EOF was reached, while no characters were read */
 
	  free(tmpstring);
 
	  return NULL;
 
 
	}
 
	if (ferror(fp)) {
 
	  error("I/O error in ReadLine(%ld): %s\n",fp, strerror(errno));
 
	}
 
	
 
 
  }
 
  
 
  /* Allocate enough memory for the line */
 
  MEMORYCHECK(line=(char *)malloc((++(pos))*sizeof(char)));
 
 
  strncpy(line,tmpstring,(pos)-1);
 
  free(tmpstring);
 
  
 
  line[pos-1]='\0';
 
  return line;
 
    
 
}
 
 
 
void CheckFile(FILE *fp) 
 
{
 
  if (ftell(fp)<0) {
 
	/* file is probably not open, or another error occured */
 
	error("File error (fp=%ld): %d %s\n",fp,errno,strerror(errno));
 
  }
 
  /* File pointer is ok */
 
}
 
 
@@ -228,61 +215,57 @@ char *Chext(char *filename) {
 
  
 
  /* Remember to free the memory allocated by this function */
 
  /* ( free(result) ) */
 
  
 
  /* not yet tested */
 
 
  int i;
 
  char *result;
 
 
  for (i=strlen(filename)-1;i>=0;i--) {
 
    if (filename[i]=='.') 
 
      break;
 
    
 
  }
 
  
 
  /* No . found */
 
  if (i==0) {
 
    
 
    result=strdup(filename);
 
  } else {
 
   
 
    /* . found */
 
    result=(char *)malloc((i+1)*sizeof(char));
 
    strncpy(result, filename, i);
 
  }
 
  return result;
 
  
 
  
 
}
 
 
void MakeDir(const char *dirname) {
 
 
#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." << 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;
 
  if (!dir.mkdir(QString(dirname))) {
 
    char *message = new char[MESS_BUF_SIZE+1];
 
    snprintf(message,MESS_BUF_SIZE,"%s: Error in making directory %s",strerror(errno),dirname);
 
    warning(message);
 
    //strerror(message);
 
    //exit(1);
 
    return;
 
  }
 
@@ -320,22 +303,20 @@ void MakeDir(const char *dirname) {
 
	}
 
      } else {
 
	snprintf(message, MESS_BUF_SIZE, "%s is not a directory", dirname);
 
	perror(message);
 
	exit(1);
 
      }
 
    } else {
 
      // a different error occurred. Print error and quit 
 
      
 
      snprintf(message,MESS_BUF_SIZE,"Error in making directory %s",dirname);
 
      perror(message);
 
      exit(1);
 
      
 
    }
 
  
 
 
 
  }
 
 
#endif
 
}
 
 
 
/* finis */
src/output.h
Show inline comments
 
@@ -44,12 +44,14 @@ bool CanWeWriteP(char *filename);
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 

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

	
 
#endif
 

	
 
/* finis */
src/parameter.cpp
Show inline comments
 
@@ -180,25 +180,24 @@ Parameter::Parameter() {
 
  b4 = false;
 
  dir1 = strdup(".");
 
  dir2 = strdup(".");
 
}
 

	
 
Parameter::~Parameter() {
 
  
 
  // destruct parameter object
 

	
 
  // free string parameter
 

	
 
  CleanUp();
 

	
 
}
 

	
 
void Parameter::CleanUp(void) {
 
  if (arrowcolor) 
 
     free(arrowcolor);
 
  if (textcolor) 
 
     free(textcolor);
 
  if (cell_outline_color) 
 
     free(cell_outline_color);
 
  if (D) 
 
     free(D);
 
  if (initval) 
 
@@ -208,25 +207,24 @@ void Parameter::CleanUp(void) {
 
  if (k) 
 
     free(k);
 
  if (s1) 
 
     free(s1);
 
  if (s2) 
 
     free(s2);
 
  if (s3) 
 
     free(s3);
 
  if (dir1) 
 
     free(dir1);
 
  if (dir2) 
 
     free(dir2);
 

	
 
}
 

	
 
void Parameter::Read(const char *filename) {
 
  
 
  static bool ReadP=false;
 

	
 
  if (ReadP) {
 

	
 
    //throw "Run Time Error in parameter.cpp: Please Read parameter file only once!!";
 
    CleanUp();
 
    
 
  } else
 
@@ -330,25 +328,24 @@ void Parameter::Read(const char *filenam
 
  s2 = sgetpar(fp, "s2", "", true);
 
  s3 = sgetpar(fp, "s3", "", true);
 
  b1 = bgetpar(fp, "b1", false, true);
 
  b2 = bgetpar(fp, "b2", false, true);
 
  b3 = bgetpar(fp, "b3", false, true);
 
  b4 = bgetpar(fp, "b4", false, true);
 
  dir1 = sgetpar(fp, "dir1", ".", true);
 
  if (strcmp(dir1, "."))
 
    MakeDir(dir1);
 
  dir2 = sgetpar(fp, "dir2", ".", true);
 
  if (strcmp(dir2, "."))
 
    MakeDir(dir2);
 

	
 
}
 

	
 
const char *sbool(const bool &p) {
 

	
 
  const char *true_str="true";
 
  const char *false_str="false";
 
  if (p)
 
    return true_str;
 
  else
 
    return false_str;
 
}
 

	
 
@@ -1867,20 +1864,19 @@ if (!strcmp(namec, "k")) {
 
		sub_par_node = sub_par_node->next;
 
	      }
 
	      AssignValArrayToPar((const char*)namec, valarray);
 
	    }
 
	  }
 
	}	  
 
	par_node = par_node->next;
 
      }
 

	
 
    }
 
    cur=cur->next;
 
  }
 
    
 
}*/
 

	
 
ostream &operator<<(ostream &os, Parameter &p) {
 
  p.Write(os);
 
  return os;
 
}
 

	
src/pardialog.cpp
Show inline comments
 
@@ -685,25 +685,24 @@ void ParameterDialog::write(void) {
 
      else par.b3=false;
 
  }
 
  tmpval = b4_edit->text().stripWhiteSpace();
 
  if (tmpval == "true" || tmpval == "yes" ) par.b4 = true;
 
  else if (tmpval == "false" || tmpval == "no") par.b4 = false;
 
  else {
 
    if (QMessageBox::question(this, "Syntax error", tr("Value %1 of parameter %2 is not recognized as Boolean.\nDo you mean TRUE or FALSE?").arg(tmpval).arg("b4"),"True","False", QString::null, 0, 1)==0) par.b4=true;
 
      else par.b4=false;
 
  }
 
  par.dir1 = strdup((const char *)dir1_edit->text());
 
  par.dir2 = strdup((const char *)dir2_edit->text());
 
  Reset();
 

	
 
}
 
void ParameterDialog::Reset(void) {
 
  extern Parameter par;
 
  arrowcolor_edit->setText( QString("%1").arg(par.arrowcolor) );
 
  arrowsize_edit->setText( QString("%1").arg(par.arrowsize) );
 
  textcolor_edit->setText( QString("%1").arg(par.textcolor) );
 
  cellnumsize_edit->setText( QString("%1").arg(par.cellnumsize) );
 
  nodenumsize_edit->setText( QString("%1").arg(par.nodenumsize) );
 
  node_mag_edit->setText( QString("%1").arg(par.node_mag) );
 
  outlinewidth_edit->setText( QString("%1").arg(par.outlinewidth) );
 
  cell_outline_color_edit->setText( QString("%1").arg(par.cell_outline_color) );
 
  resize_stride_edit->setText( QString("%1").arg(par.resize_stride) );
src/parse.cpp
Show inline comments
 
@@ -55,25 +55,24 @@ char *ParsePar(FILE *fp, char *parameter
 
  // warning("Reading value for token %s...",token);
 
  fprintf(stderr, "[%s = ",token);
 
  
 
  token=strtok(NULL,"=");
 
  if (token==NULL)
 
	error("\nParse error: no value found after '=' sign, in line: \n %s",
 
		  line);
 
 
  value=strdup(token);
 
  free(line);
 
  
 
  return value;
 
      
 
}
 
 
 
int igetpar(FILE *fp,char *parameter, bool wrapflag) {
 
  
 
  // overloaded compatibility function. Doesn't need default parameter
 
 
  return igetpar(fp, parameter, 0, wrapflag);
 
}
 
 
int igetpar(FILE *fp,char *parameter, int default_val, bool wrapflag) 
 
{
 
@@ -86,56 +85,51 @@ int igetpar(FILE *fp,char *parameter, in
 
  if (token==0) {
 
    /* default value */
 
    warning("No token %s found. Using default value %d.\n", parameter, default_val);
 
    return default_val;
 
  }
 
  /* read it */
 
  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
 
  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 */
 
    warning("No token %s found. Using default value %f.\n", parameter, default_val);
 
    return default_val;
 
  }
 
 
  /* read it */
 
  sscanf(token,"%e",&value);
 
 
  fprintf(stderr,"%e]\n",value);
 
  
 
  free(token);
 
 
  return value;
 
  
 
}
 
 
 
double *dgetparlist(FILE *fp,char *parameter, int n, bool wrapflag) 
 
{
 
  /* Get a list of n comma separated doubles */
 
  char *token;
 
  double *value;
 
  char *number;
 
  int i;
 
 
  value=(double *)malloc(n*sizeof(double));
 
@@ -171,25 +165,24 @@ double *dgetparlist(FILE *fp,char *param
 
    warning("Padding with 0.");
 
    for (int j=i;j<n;j++) 
 
      value[j]=0.;
 
    
 
    fprintf(stderr, "Full array is ");
 
    for (int i=0;i<n;i++) {
 
      fprintf(stderr," %lf ",value[i]);
 
    }
 
    fprintf(stderr, "\n");
 
  }
 
  
 
  return value;
 
  
 
}
 
 
char *sgetpar(FILE *fp,char *parameter, bool wrapflag) 
 
{
 
  return sgetpar(fp, parameter, " ", wrapflag);
 
}
 
 
char *sgetpar(FILE *fp, char *parameter, const char *default_val, bool wrapflag) {
 
 
  char *token;
 
  char *value;
 
  int pos;
 
@@ -204,50 +197,47 @@ char *sgetpar(FILE *fp, char *parameter,
 
    return value;
 
  }
 
  
 
  /* strip leading spaces and duplicate string */
 
  pos=strspn(token," \t\n");
 
  value=(char *)malloc((strlen(&token[pos])+1)*sizeof(char));
 
  sprintf(value,"%s",&token[pos]);
 
  free(token);
 
 
  fprintf(stderr,"%s]\n",value);
 
 
  return value;
 
  
 
}
 
 
char *bool_str(bool bool_var) {
 
  
 
  /* Return string "true" if bool_var=true */
 
  /* Return string "false" if bool_var=false */
 
  
 
  static char t[5] = "true";
 
  static char f[6] = "false";
 
 
  if (bool_var) {
 
    return t;
 
  } else {
 
    return f;
 
  }
 
  
 
}
 
 
bool bgetpar(FILE *fp, char *parameter,  bool wrapflag) {
 
  
 
  // overloaded compatibility function. Doesn't need default parameter
 
  // default = false
 
 
  return bgetpar(fp, parameter, 0, wrapflag);
 
 
}
 
 
bool bgetpar(FILE *fp, char *parameter, int default_val, bool wrapflag) {
 
 
  /* Get boolean parameter. */
 
  /* if "true" or "yes", return 1 */
 
  /* if "false" or "no", return 0 */
 
  /* else complain */
 
 
  char *token;
 
  int value=0;
 
  int pos;
 
@@ -267,25 +257,24 @@ bool bgetpar(FILE *fp, char *parameter, 
 
  
 
  if (!strcmp(&token[pos],"yes") || !strcmp(&token[pos],"true") || !strcmp(&token[pos],"1"))
 
    value=1;
 
  else 
 
    if (!strcmp(&token[pos],"no") || !strcmp(&token[pos],"false") || !strcmp(&token[pos],"0"))
 
      value=0;
 
  else
 
    error("Keyword '%s' not recognized. Try yes/no or true/false.\n",&token[pos]);
 
 
  fprintf(stderr, "%s]\n",bool_str(value));
 
 
  return value;
 
 
}
 
 
 
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;
 
@@ -335,57 +324,54 @@ char *SearchToken(FILE *fp, char *token,
 
    len=strlen(line);
 
    if (strlen(tokenplusspace)<=len) {
 
 
      /* only if the line is longer than the token, it might be found */
 
      // if (strstr(line,tokenplusspace)!=NULL) /* FOUND */
 
      if (strstr(line,tokenplusspace)==(&line[pos])) /* FOUND */
 
	{
 
	  free(tokenplusspace);
 
	  return line;
 
	}
 
    }
 
    
 
 
    free(line);
 
    
 
  }
 
  free(tokenplusspace);
 
  return NULL; /* Token Not Found in the file */
 
}
 
 
int TokenInLineP(char *line,char *token) 
 
{
 
  if (strstr(token, line)!=NULL)
 
    return true;
 
  else
 
    return false;
 
}
 
 
 
void SkipLine(FILE *fp) {
 
  
 
  /* Just skips a line in FILE *fp */
 
  char *tmpstring;
 
  tmpstring=ReadLine(fp);
 
  free(tmpstring);
 
  
 
}
 
 
void SkipToken(FILE *fp,char *token, bool wrapflag)
 
{
 
  /* A very simple function:
 
	 call SearchToken() and get rid of the memory returned by
 
     it.
 
	 Also, return an error if the desired token was not found in the file.
 
  */
 
  char *tmppointer;
 
 
  tmppointer=SearchToken(fp,token, wrapflag);
 
 
  if (tmppointer==NULL) {
 
	error("Token `%s' not found by function SkipToken.\n",token);
 
  }
 
 
  free(tmppointer);
 
      
 
}
 
 
/* finis */
src/parse.h
Show inline comments
 
@@ -35,12 +35,14 @@ float fgetpar(FILE *fp,char *parameter, 
 
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
 

	
 
/* finis */
src/perl/deployapp.pl
Show inline comments
 
@@ -103,12 +103,14 @@ for $fw (@frameworks) {
 

	
 
# do the same for additional libs not in a framework depending on frameworks (e.g. libqwt...)
 
@additionallibs = ( "libqwt.dylib" );
 

	
 
for $lib (@additionallibs) {
 
  my @frameworks_of_lib = get_frameworks ( "$appdir/Contents/Frameworks/$lib" );
 
  for $fwfw (@frameworks_of_lib) {
 
    #    print "$fwfw\n";
 
    $liblib = $fwfw; $liblib =~ s/\.framework//g;    
 
    system "install_name_tool -change $fwfw/Versions/4/$liblib \@executable_path/../Frameworks/$fwfw/Versions/4.0/$liblib  $appdir/Contents/Frameworks/$lib";
 
  }
 
}
 

	
 
# finis
src/perl/histogram.pl
Show inline comments
 
@@ -36,12 +36,15 @@ while (<>) {
 
  @line=split;
 
  $num=$line[0];
 
  $bin = int($num / $binsize);
 
	# print "[$num, $bin] ";
 
  $bins[$bin]++;
 
}
 

	
 

	
 
for ($bin=0;$bin<=$#bins;$bin++) {
 
   $halfwaybin = $bin * $binsize + $binsize/2.;
 
   print $halfwaybin." ".$bins[$bin]."\n";
 
}
 

	
 
# finis
 

	
src/perl/make_parameter_source.pl
Show inline comments
 
@@ -431,12 +431,14 @@ const char *sbool(const bool &p);
 
END_TRAILER2
 

	
 
# finally, a parameter file with the default values, based on the template
 

	
 
open parfile,">default.par";
 

	
 
for ($i=0;$i<$lines;$i++) {
 
  if ($type[$i] ne "title" && $type[$i] ne "label") {
 
    $value[$i] =~ s/\"//g;
 
    print parfile "  $param[$i] = $value[$i]\n";
 
  }
 
}
 

	
 
# finis
src/perl/make_pardialog_source.pl
Show inline comments
 
@@ -292,12 +292,13 @@ END_HEADER2
 

	
 
for ($i=0;$i<$lines;$i++) {
 
  if ($convtype[$i] ne "label" && $convtype[$i] ne "title") {
 
    print hfile "  QLineEdit *$param[$i]_edit;\n";
 
  }
 
}
 

	
 
print hfile <<END_TRAILER2;
 
};
 
#endif
 
END_TRAILER2
 

	
 
# finis
src/perl/make_xmlwritecode.pl
Show inline comments
 
@@ -212,12 +212,13 @@ END_MARKER2
 
print xmlsrc "xmlChar *sourcecode = (xmlChar *)\"".construct_string_constant_from_file( "$reaction" );
 
   print xmlsrc <<END_MARKER3;
 
    xmlNodePtr xmlcode = xmlNewChild(parent, NULL, BAD_CAST \"code\", sourcecode);
 

	
 
     {
 
        xmlNewProp(xmlcode, BAD_CAST "name", BAD_CAST \"$reaction\");
 
     }
 
  
 
}
 

	
 
END_MARKER3
 

	
 
# finis
src/pi.h
Show inline comments
 
@@ -19,12 +19,14 @@
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _PI_H_
 
#define _PI_H_
 

	
 
const double Pi=3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170676;
 

	
 
#endif
 

	
 
/* finis */
src/qcanvasarrow.h
Show inline comments
 
@@ -21,26 +21,25 @@
 
 *
 
 */
 

	
 

	
 
#ifndef _QCANVASARROW_H_
 
#define _QCANVASARROW_H_
 

	
 
#include <QGraphicsScene>
 

	
 
class QGraphicsArrowItem : public QGraphicsLineItem {
 

	
 
 public:
 
  QGraphicsArrowItem(QGraphicsItem *parent, QGraphicsScene *c) : QGraphicsLineItem(parent, c) {
 
  };
 
 QGraphicsArrowItem(QGraphicsItem *parent, QGraphicsScene *c) : QGraphicsLineItem(parent, c) {};
 
    
 
    void paint ( QPainter *p, const QStyleOptionGraphicsItem *option,
 
		 QWidget *widget ) {
 

	
 
      widget = NULL; //use assignment merely to obviate compilation warning
 
      option = NULL;
 

	
 
      // construct arrow head
 
      QPointF start=line().p1();
 
      QPointF end=line().p2();
 
      QPointF mid=start + (3./4.)*(end-start);
 
      
 
@@ -65,12 +64,14 @@ class QGraphicsArrowItem : public QGraph
 
				   (int)( (length/4.)*py ) );
 
      
 
      p->setPen(pen());
 
      // Draw arrow head
 
      p->drawLine( end, arwp1 );
 
      p->drawLine( end, arwp2 );
 
      // Draw arrow line
 
      p->drawLine( start, end);
 
    }
 
};
 

	
 
#endif
 

	
 
/* finis */
src/random.cpp
Show inline comments
 
@@ -138,12 +138,13 @@ int Randomize(void) {
 
  int seed;
 
 
  ftime(&t);
 
  
 
  seed=abs((int)((t.time*t.millitm)%655337));
 
  Seed(seed);
 
#ifdef QDEBUG
 
  qdebug() << "Random seed is " << seed << endl;
 
#endif
 
  return seed;
 
}
 
 
/* finis */
src/random.h
Show inline comments
 
@@ -49,18 +49,15 @@ class MyUrand {
 
    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
 

	
 

	
 

	
 
#endif
 
/* finis */
src/rseed.cpp
Show inline comments
 
@@ -19,15 +19,16 @@
 
 *
 
 */
 

	
 
#include <string>
 
#include <iostream>
 
#include "random.h"
 

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

	
 
int main() {
 

	
 
   long rseed=Randomize();
 
   std::cout << rseed << "\n";
 
  std::cerr << rseed << std::endl;
 
}
 

	
 
}
 
/* finis */
src/rungekutta.cpp
Show inline comments
 
@@ -76,25 +76,24 @@ void RungeKutta::rkqs(double *y, double 
 
    xnew=(*x)+h;
 
    if (xnew == *x) MyWarning::error("stepsize underflow in rkqs, with h = %f and htry = %f",h, htry);
 
  }
 
  if (errmax > Errcon) {
 
    *hnext=Safety*h*pow(errmax,PGrow);
 
    //std::cerr << "hnext = " << *hnext << std::endl;
 
  }
 
  else *hnext=5.0*h; //No more than a factor of 5 increase.
 
  *x += (*hdid=h);
 
  for (i=0;i<n;i++) y[i]=ytemp[i];
 
  delete[] ytemp;
 
  delete[] yerr;
 

	
 
}
 

	
 

	
 
void RungeKutta::rkck(double *y, double *dydx, int n, double x, double h, double *yout, double *yerr)
 
/*Given values for n variables y[1..n] and their derivatives dydx[1..n] known at x, use
 
  the fifth-order Cash-Karp Runge-Kutta method to advance the solution over an interval h
 
  and return the incremented variables as yout[1..n]. Also return an estimate of the local
 
  truncation error in yout using the embedded fourth-order method. The user supplies the routine
 
  derivs(x,y,dydx), which returns derivatives dydx at x.*/
 
{
 
  int i;
 

	
 
@@ -194,12 +193,14 @@ void RungeKutta::odeint(double *ystart, 
 
	for (i=0;i<nvar;i++) yp[i][kount]=y[i];
 
      }
 
      delete[] dydx;
 
      delete[] y;
 
      delete[] yscal;
 
      return; //Normal exit.
 
    }
 
    if (fabs(hnext) <= hmin) MyWarning::error("Step size too small in odeint");
 
    h=hnext;
 
  }
 
  MyWarning::error("Too many steps in routine odeint");
 
}
 

	
 
/* finis */
src/rungekutta.h
Show inline comments
 
@@ -50,16 +50,16 @@ class RungeKutta  {
 
  void rkqs(double *y, double *dydx, int n, double *x, double htry, double eps,
 
       double *yscal, double *hdid, double *hnext);
 
  
 
  void rkck(double *y, double *dydx, int n, double x, double h, double yout[],
 
	    double *yerr);
 

	
 
  static const double Safety;
 
  static const double PGrow;
 
  static const double Pshrnk;
 
  static const double Errcon;
 
  static const double Maxstp;
 
  static const double Tiny;
 
  
 

	
 
};
 
#endif
 

	
 
/* finis */
src/simitembase.cpp
Show inline comments
 
@@ -16,23 +16,27 @@
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include <QBrush>
 
#include "simitembase.h"
 

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

	
 
SimItemBase::SimItemBase( void *v, QGraphicsScene *canvas ) {
 
SimItemBase::SimItemBase( void *v, QGraphicsScene *canvas )
 
{
 
  canvas = NULL; // use assignment merely to obviate compilation warning
 
    obj=v;
 
};
 

	
 
SimItemBase::~SimItemBase(void) {};
 

	
 

	
 
void SimItemBase::userMove(double dx, double dy) {
 
void SimItemBase::userMove(double dx, double dy)
 
{
 
  dx = dy = 0.0; // use assignment merely to obviate compilation warning
 
};
 

	
 
/* finis */
src/simitembase.h
Show inline comments
 
@@ -56,12 +56,14 @@ public:
 
 protected:
 

	
 
  // I know which simulation object I represent, so if I am moved around
 
  // the canvas, the real object can be moved as well
 
  
 
  // (both Cell and Node have Vector as base class...)
 
  // Not proper design... sorry.
 
 
 
  void *obj; 
 
  };
 

	
 
#endif
 

	
 
/* finis */
src/simplugin.cpp
Show inline comments
 
@@ -15,21 +15,23 @@
 
 *  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 "simplugin.h"
 

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

	
 
void SimPluginInterface::SetParameters(Parameter *pass_pars) {
 
void SimPluginInterface::SetParameters(Parameter *pass_pars)
 
{
 
	par = pass_pars; 
 
}
 

	
 
void SimPluginInterface::SetCellsStaticDatamembers( CellsStaticDatamembers *cells_static_data_members_of_main)
 
{
 
	CellBase::static_data_members = cells_static_data_members_of_main;
 
}
 

	
 
/* finis */
src/simplugin.h
Show inline comments
 
@@ -62,21 +62,20 @@ public:
 
	// to be executed for coloring a cell
 
	virtual void SetCellColor(CellBase *c, QColor *color) = 0;
 
	
 
	// Number of chemicals
 
	virtual int NChem(void) = 0;
 
	
 
	// For internal use; not to be redefined by end users
 
	virtual void SetParameters(Parameter *pass_pars);// { par = pass_pars; }
 
	virtual void SetCellsStaticDatamembers (CellsStaticDatamembers *cells_static_data_members_of_main);
 

	
 
protected:
 
	class Parameter *par;
 
	
 
};
 

	
 
Q_DECLARE_INTERFACE(SimPluginInterface, 
 
                    "nl.cwi.VirtualLeaf.SimPluginInterface/1.2") 
 
Q_DECLARE_INTERFACE(SimPluginInterface, "nl.cwi.VirtualLeaf.SimPluginInterface/1.2") 
 
Q_DECLARE_METATYPE(SimPluginInterface *)
 

	
 
#endif
 

	
 
#endif
 
\ No newline at end of file
 
/* finis */
src/sqr.h
Show inline comments
 
@@ -31,23 +31,25 @@
 
// 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 {
 
    return a*a;
 
  }
 

	
 
}
 

	
 
inline float SQR( float a ) {
 
   if (a == 0.0) {
 
    return 0.0;
 
  } else {
 
    return a*a;
 
  }
 
}
 

	
 
#endif
 

	
 
/* finis */
src/tiny.h
Show inline comments
 
@@ -19,12 +19,14 @@
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 
#ifndef _TINY_H_
 
#define _TINY_H_
 

	
 
#define TINY 1e-5
 

	
 
#endif
 

	
 
/* finis */
src/transporterdialog.cpp
Show inline comments
 
@@ -32,25 +32,26 @@ TransporterDialog::TransporterDialog(Wal
 
{
 
  int frameStyle = QFrame::Plain | QFrame::NoFrame;
 
  QPushButton *ok = new QPushButton(tr("Ok"));
 
  QPushButton *cancel = new QPushButton(tr("Cancel"));
 
  QGridLayout *t_grid = new QGridLayout; // transporter grid
 

	
 
  // connect the slots
 
  connect(ok, SIGNAL(clicked()), this, SLOT(setTransporterValues()));
 
  connect(cancel, SIGNAL(clicked()), this, SLOT(close()));
 

	
 
  // compose a label for the dialog box
 
  std::stringstream label_text; 
 
  label_text << "C("<< wall->C1()->Index() << "," << wall->C2()->Index() << "), N(" << wall->N1()->Index() << "," << wall->N2()->Index() << ")";
 
  label_text << "C("<< wall->C1()->Index() << "," << wall->C2()->Index() << "), N(" 
 
	     << wall->N1()->Index() << "," << wall->N2()->Index() << ")";
 
	
 
  // retrieve the current transporters
 
  QVector <double> transporters;  // transporter vector
 
  ntransporters = cell->NChem(); // size of transporter vector
 
  for (int i=0; i<ntransporters; ++i){
 
    transporters << ((wall_num == 1) ? wall->Transporters1(i) : wall->Transporters2(i)); // dependent on the wall number of course.
 
  }
 

	
 
  // iterate over the vector of transporter values making a label/edit line for each
 
  for (int i=0; i<transporters.size(); ++i) {
 

	
 
    // label
 
@@ -77,30 +78,31 @@ TransporterDialog::TransporterDialog(Wal
 
  b_grid->addWidget(ok, 0, 0);
 
  b_grid->addWidget(cancel, 0, 1);
 

	
 
  // add both transporter and button grids to the box layout widget
 
  QVBoxLayout *layout = new QVBoxLayout;
 
  layout->addLayout(t_grid);
 
  layout->addLayout(b_grid);
 
  setLayout(layout);
 

	
 
  setWindowTitle(tr(label_text.str().c_str()));
 
}
 

	
 
void TransporterDialog::setTransporterValues(){
 

	
 
void TransporterDialog::setTransporterValues()
 
{
 
  // iterate over the editor widgets soliciting their values and setting the wall's transporters accordingly.
 
  for (int i=0; i<ntransporters; ++i){
 
    #ifdef QDEBUG  
 
    qDebug() << "Transporter(" << i << "): " << editors[i]->text().toDouble() << endl;
 
    #endif
 
    if (wall_num == 1)
 
      wall->setTransporters1(i, editors[i]->text().toDouble());
 
    else 
 
      wall->setTransporters2(i, editors[i]->text().toDouble());
 
  }
 
  editors.resize(0);
 
  close();
 
}
 

	
 
// finis
 
/* finis */
 

	
 

	
src/transporterdialog.h
Show inline comments
 
@@ -46,12 +46,14 @@ class TransporterDialog : public QDialog
 
  void setTransporterValues();
 

	
 
 private:
 
  Wall *wall;
 
  CellBase *cell;
 
  int wall_num;
 
  QLabel *label;
 
  int ntransporters;
 
  QVector <QLineEdit*> editors;
 
};
 

	
 
#endif
 

	
 
/* finis */
src/vector.cpp
Show inline comments
 
@@ -34,264 +34,241 @@
 
static const std::string _module_id("$Id$");
 

	
 
void Vector::operator=(const Vector &source) {
 
  
 
  // assignment
 
  
 
  // don't assign to self
 
  if (this==&source) return;
 
  
 
  x=source.x;
 
  y=source.y;
 
  z=source.z;
 
  
 
}
 

	
 

	
 

	
 

	
 

	
 
ostream &Vector::print(ostream &os) const {
 
  os << "(" << x << ", " << y << ", " << z << ")";
 
  return os;
 
}
 

	
 

	
 
ostream &operator<<(ostream &os, const Vector &v) {
 
  v.print(os);
 
  return os;
 
}
 

	
 

	
 
Vector Vector::operator+(const Vector &v) const {
 
  
 
  Vector result;
 
  result.x=x+v.x;
 
  result.y=y+v.y;
 
  result.z=z+v.z;
 
  
 
  return result;
 

	
 
}
 

	
 

	
 
Vector& Vector::operator-=(const Vector &v) {
 
  
 
  x-=v.x;
 
  y-=v.y;
 
  z-=v.z;
 
  
 
  return *this;
 

	
 
}
 

	
 
Vector Vector::operator/(const double divisor) const {
 
  
 
  
 
  Vector result;
 
  
 
  result.x=x/divisor;
 
  result.y=y/divisor;
 
  result.z=z/divisor;
 

	
 
  return result;
 
  
 
  
 
}
 

	
 

	
 
Vector Vector::operator*(const double multiplier) const {
 

	
 
  Vector result;
 
  
 
  result.x=x*multiplier;
 
  result.y=y*multiplier;
 
  result.z=z*multiplier;
 

	
 
  return result;
 

	
 
  
 
}
 

	
 

	
 
Vector operator*(const double multiplier, const Vector &v) {
 

	
 
  Vector result;
 
  
 
  result.x=v.x*multiplier;
 
  result.y=v.y*multiplier;
 
  result.z=v.z*multiplier;
 

	
 
  return result;
 
  
 
}
 

	
 
Vector &Vector::operator/=(const double divisor) {
 
  x/=divisor;
 
  y/=divisor;
 
  z/=divisor;
 
  
 
  return *this;
 

	
 
}
 

	
 
Vector &Vector::operator*=(const double multiplier) {
 

	
 
  x*=multiplier;
 
  y*=multiplier;
 
  z*=multiplier;
 

	
 
  return *this;
 

	
 
}
 

	
 
Vector Vector::operator*(const Vector &v) const {
 
  
 
  // cross product ("uitproduct")
 
  Vector result;
 
  
 
  result.x=y*v.z-z*v.y;
 
  result.y=z*v.x-x*v.z;
 
  result.z=x*v.y-y*v.x;
 
  
 
  return result;
 
  
 
  
 
}
 

	
 

	
 
double InnerProduct(const Vector &v1, const Vector &v2) {
 

	
 
  // Inner product ("inproduct")
 
  double result;
 
  result=v1.x*v2.x+v1.y*v2.y+v1.z*v2.z;
 
  return result;
 

	
 
}
 

	
 
double Vector::Angle(const Vector &v) const {
 
  
 
  // angle between this vector and another vector
 
  
 
  // angle is within range of [0,pi] radians
 
  
 
  // angle is arccosine of the inner product over the product of the norms of the vectors
 
  
 
  double cos_angle=InnerProduct(*this,v)/(Norm()*v.Norm());
 
  
 
  // check for computational inaccuracies
 
  if (cos_angle<=-1)
 
    return Pi;
 
  
 
  if (cos_angle>=1)
 
    return 0.;
 
  
 
  double angle=acos(cos_angle);
 
  
 
  return angle;
 

	
 
}
 

	
 
double Vector::SignedAngle(const Vector &v) const {
 
  
 
  // angle between this vector and another vector
 
  
 
  // angle is within range of [-pi,pi] radians
 
  
 
  // angle is arccosine of the inner product over the product of the norms of the vectors
 
  
 
  double cos_angle=InnerProduct(*this,v)/(Norm()*v.Norm());
 
  
 
  // check for computational inaccuracies
 
  if (cos_angle<=-1)
 
    return Pi;
 
  
 
  if (cos_angle>=1)
 
    return 0.;
 
  
 
  double angle=acos(cos_angle);
 
  
 
  double sign = (InnerProduct ( Perp2D(), v ) )>0.?1.:-1.;
 
  return angle * sign;
 

	
 
}
 

	
 

	
 
bool Vector::operator==(const Vector &v) const {
 
   
 
  // "sloppy equal"
 
  if ((fabs(x-v.x)<TINY) && (fabs(y-v.y)<TINY) && (fabs(z-v.z)<TINY))
 
    return true;
 
  else
 
    return false;
 
  
 
}
 

	
 
bool Vector::operator< (const Vector &v) const {
 
  
 
  // Compare x coordinate
 
  if (x<v.x) 
 
    return true;
 
  else 
 
    return false;
 
  
 
}
 

	
 

	
 
double Vector::SqrNorm(void) const {
 
  
 
  // return the square of the norm
 
  // added this function to avoid taking the square root and 
 
  // the square again if this value is needed
 
  return DSQR(x)+DSQR(y)+DSQR(z);
 

	
 
}
 

	
 
void Vector::Normalise(void) {
 
  
 
  double norm;
 
  norm=Norm(); // Absolute value;
 
  
 
  if (norm>0.) { // if the norm is 0, don't normalise 
 
    // (otherwise division by zero occurs)
 
    
 
    (*this)/=norm;
 
  }
 
  
 
}
 

	
 
Vector Vector::Normalised(void) const {
 
  
 
  double norm;
 
  norm=Norm(); // Absolute value;
 
  
 
  if (norm>0.) { // if the norm is 0, don't normalise 
 
    // (otherwise division by zero occurs)
 
    return (*this)/norm;
 
  } else {
 
    return *this;
 
  }
 
    
 
}
 

	
 
bool Vector::SameDirP(const Vector &v) {
 
  
 
  // return true if the two (parallel) vectors point in the same direction
 
  //  if (x*v.x>=0 && y*v.y>=0 && z*v.z>=0)
 
  double angle=Angle(v);
 
  
 
  if (angle<(Pi/2))
 
    return true;
 
  else
 
    return false;
 
 
 
}
 

	
 
double Vector::Max(void) {
 
  
 
  // Find maximum value of vector
 
  double max;
 
  
 
  max=x > y ? x : y;
 
  max=max > z ? max : z;
 
  
 
  return max;
 
}
 
@@ -325,17 +302,17 @@ void main() {
 
  
 
//  cerr << d << "\n";
 
  
 
  d=v/5;
 
  
 
//  cerr << d << "\n";
 

	
 
//  cerr << d.Norm() << "\n";
 
  
 
  d.Normalise();
 
  
 
//  cerr << d << "  " << d.Norm() << "\n";
 
  
 
  
 
}
 

	
 
#endif 
 

	
 
/* finis */
src/vector.h
Show inline comments
 
@@ -88,74 +88,73 @@ public:
 
    z=s;
 
  }
 
  Vector operator+(const Vector &v) const; // addition
 
  inline Vector operator-(const Vector &v) const { 
 
    
 
    Vector result;
 
    
 
    result.x=x-v.x;
 
    result.y=y-v.y;
 
    result.z=z-v.z;
 
    
 
    return result;
 
    
 
  }
 
  Vector &operator-=(const Vector &v);
 
  
 
  inline Vector &operator+=(const Vector &v) {
 
  
 
    x+=v.x;
 
    y+=v.y;
 
    z+=v.z;
 
    
 
    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
 
  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;
 
  }
 
  
 
  double SqrNorm(void) const; // gives the square of |v|
 
  void Normalise(void); // normalise myself
 
  Vector Normalised(void) const; // return me normalised
 
  double Angle(const Vector &angle) const; // gives the angle between me and another vector
 
  double SignedAngle(const Vector &v) const;
 
  bool SameDirP(const Vector &v);
 
  double Max(void); // Find max, resp. min value of vector
 
  double Min(void);
 
  Vector Perp2D(void) const {
 
    return Vector(y,-x,0);
 
  }
 

	
 
  // data members
 
  double x,y,z;
 

	
 
  void Dump(ostream &os) const { 
 
    os << x << " " << y << " " << z << " ";
 
  }
 
  void ReadDump(istream &is) {
 
    is >> x >> y >> z;
 
  }
 
private:
 

	
 
};
 

	
 
ostream &operator<<(ostream &os, const Vector &v);
 
Vector operator*(const double multiplier, const Vector &v);
 
double InnerProduct(const Vector &v1, const Vector &v2);
 

	
 
#endif
 

	
 
/* finis */
src/vleafmodel.h
Show inline comments
 
@@ -28,12 +28,14 @@
 
#include <QtGui>
 
#include <fstream>
 
#include "simplugin.h"
 

	
 
#include "parameter.h"
 

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

	
 
#endif
 

	
 
/* finis */
src/wall.cpp
Show inline comments
 
@@ -55,63 +55,63 @@ bool Wall::CorrectWall( void ) {
 
	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 (
 
												   wall_owners.begin(), wall_owners.end(), 
 
												   mem_fun( &CellBase::BoundaryPolP )
 
												   );
 
		
 
		if (bpit!=wall_owners.end()) {
 
			
 
			// add a Wall with the boundary_polygon to each cell
 
			Wall *bp_wall1 = new Wall( n2, n1, c1, (*bpit) );
 
			bp_wall1->CopyWallContents(*this);
 
			((Cell *)c1)->AddWall( bp_wall1);
 
			((Cell *)(*bpit))->AddWall(bp_wall1);
 
			
 
			Wall *bp_wall2 = new Wall( n1, n2, c2, (*bpit) );
 
			bp_wall2->CopyWallContents(*this);
 
			((Cell *)c2)->AddWall( bp_wall2);
 
			((Cell *)(*bpit))->AddWall(bp_wall2);
 
			
 
			wall_owners.erase(bpit); 
 
			
 
		}else {
 

	
 
		  #ifdef QDEBUG
 
		  qDebug() << "Wall::CorrectWall says: Wall has three owners, but none of them is the BoundaryPolygon. I have no clue what to do with this case... Sorry!" << endl;
 
		  qDebug() << "Wall: " << *this << endl;
 
		  qDebug() << "Owners are: ";
 
		  transform(wall_owners.begin(), wall_owners.end(), ostream_iterator<int>(qDebug(), "  "), mem_fun (&CellBase::Index) );
 
		  qDebug() << endl;
 
		  qDebug() << "Owners node " << n1->Index() << ": ";
 

	
 
		  for (list<Neighbor>::iterator i = n1->owners.begin(); i!=n1->owners.end(); i++) {
 
		    qDebug() << i->getCell()->Index() << " ";
 
		  }
 

	
 
		  qDebug() << endl;
 
		  qDebug() << "Owners node " << n2->Index() << ": ";
 
			
 
		  for (list<Neighbor>::iterator i = n2->owners.begin(); i!=n2->owners.end(); i++) {
 
		    qDebug() << i->getCell()->Index() << " ";
 
		  }
 
		  qDebug() << endl;
 
                  #endif
 
		  std::exit(1);
 
		}
 
		
 
	}
 
	
 
	#ifdef QDEBUG
 
	if (wall_owners.size() == 1) {
 
	  qDebug() << "Corner point. Special case." << endl;
 
	}
 
	#endif
 
	
 
	CellBase *cell1 = wall_owners.front();
 
	CellBase *cell2 = wall_owners.back();
 
	
 
	if ( (c1 == cell1 && c2==cell2) || (c1 == cell2 && c2 == cell1) ) {
 
@@ -142,45 +142,38 @@ bool Wall::CorrectWall( void ) {
 
					c1 = cell1;
 
					((Cell *)c1)->AddWall(this);
 
					//	  cerr << "Block 3\n";
 
				} else {
 
				        #ifdef QDEBUG
 
				        qDebug() << "Warning, cell wall was not corrected." << endl;
 
					#endif
 
					return false;
 
				}
 
			}
 
		}
 
	}
 
	
 
	return true;
 
	
 
	
 
	
 
	
 
}
 

	
 
void Wall::Draw(QGraphicsScene *c) {
 
	
 
	WallItem *wi1 = new WallItem(this, 1, c);
 
	WallItem *wi2 = new WallItem(this, 2, c);
 
	wi1->show();
 
	wi2->show();
 
	
 
}
 

	
 
void Wall::DrawApoplast(QGraphicsScene *c) {
 
	ApoplastItem *apo = new ApoplastItem(this, c);
 
	apo->show();
 
	
 
}
 

	
 
void Wall::ShowStructure(QGraphicsScene *c) {
 
	
 
	Vector offset = Cell::Offset();
 
	double factor = Cell::Factor();
 
	
 
	Vector startpoint ( ((offset.x+n1->x)*factor),((offset.y+n1->y)*factor)),
 
    endpoint (((offset.x+n2->x)*factor),((offset.y+n2->y)*factor));
 
	
 
	Vector linevec = endpoint - startpoint;
 
	Vector midline = startpoint + linevec/2.;
 
@@ -199,33 +192,31 @@ void Wall::ShowStructure(QGraphicsScene 
 
	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->show(); text2->show();
 
	
 
}
 
string Wall::WallTypetoStr(const WallType &wt) const {
 
	
 
	if (wt == Normal) {
 
		return string("normal");
 
	}
 
	
 
	if (wt == AuxSource) {
 
		return string("aux_source");
 
	}
 
	
 
	if (wt == AuxSink) {
 
		return string("aux_sink");
 
	}
 
	
 
	return string("");
 
}
 

	
 

	
 

	
 
/* finis */
src/wall.h
Show inline comments
 
@@ -45,19 +45,17 @@ public:
 
	//! Visualize transport protein concentrations
 
	void Draw(QGraphicsScene *c);
 
	
 
	//! Visualize contents of the apoplast
 
	void DrawApoplast(QGraphicsScene *c); 
 
	/*! \brief Visualize the structure of the wall (Cell ID's etc.). 
 
	 Used for debugging purposes.
 
	 */
 
	void ShowStructure(QGraphicsScene *c);
 

	
 
private:
 
	string WallTypetoStr(const WallType &wt) const;
 
	    
 
	
 
	
 
	
 
};
 

	
 
#endif
 

	
 
/* finis */
src/wallbase.cpp
Show inline comments
 
@@ -44,25 +44,26 @@ int WallBase::nwalls=0;
 
ostream &WallBase::print(ostream &os) const {
 
	os << "{ " << n1->Index() << "->" << n2->Index() 
 
	<< ", " << c1->Index() << " | " << c2->Index() << "} ";
 
	return os;
 
}
 

	
 
ostream &operator<<(ostream &os, const WallBase &w) { 
 
	w.print(os); 
 
	return os;
 
}
 

	
 

	
 
WallBase::WallBase(Node *sn1, Node *sn2, CellBase *sc1, CellBase *sc2) {
 
WallBase::WallBase(Node *sn1, Node *sn2, CellBase *sc1, CellBase *sc2)
 
{
 
	
 
        #ifdef QDEBUG
 
	if (sc1==sc2) { 
 
	  qDebug() << "Attempting to build a wall between identical cells: " << sc1->Index() << endl; 
 
	}
 
	#endif
 
	
 
	c1 = sc1;
 
	c2 = sc2;
 
	
 
	n1 = sn1;
 
	n2 = sn2;
 
@@ -76,52 +77,53 @@ WallBase::WallBase(Node *sn1, Node *sn2,
 
		transporters1[i] = transporters2[i] = new_transporters1[i] = new_transporters2[i] = 0.;
 
	}
 
	
 
	apoplast = new double[CellBase::NChem()]; // not yet in use.
 
    
 
	SetLength();
 
	
 
	// to visualize flux through WallBase
 
	viz_flux=0;
 
	dead = false;
 
	wall_type = Normal;
 
	wall_index = nwalls++;
 
	
 
}
 

	
 
void WallBase::CopyWallContents(const WallBase &src) {
 
void WallBase::CopyWallContents(const WallBase &src)
 
{
 
	
 
	for (int i=0; i<CellBase::NChem(); i++) {
 
		if (transporters1) {
 
			transporters1[i]=src.transporters1[i];
 
		}
 
		if (transporters2) {
 
			transporters2[i]=src.transporters2[i];
 
		}
 
		if (new_transporters1) {
 
			new_transporters1[i]=src.new_transporters1[i];
 
		}
 
		if (new_transporters2) {
 
			new_transporters2[i]=src.new_transporters2[i];
 
		}
 
		
 
		if (apoplast) {
 
			apoplast[i]=src.apoplast[i];
 
		}
 
	}
 
	dead = src.dead;
 
	wall_type = src.wall_type;
 
}
 

	
 
void WallBase::SwapWallContents(WallBase *src) {
 
void WallBase::SwapWallContents(WallBase *src)
 
{
 
	
 
	for (int i=0; i<CellBase::NChem(); i++) {
 
		if (transporters1) {
 
			double tmp;
 
			
 
			tmp=src->transporters1[i];
 
			src->transporters1[i]=transporters1[i];
 
			transporters1[i]=tmp;
 
			
 
		}
 
		if (transporters2) {
 
			double tmp;
 
@@ -149,40 +151,36 @@ void WallBase::SwapWallContents(WallBase
 
			apoplast[i]=tmp;		
 
		}
 
	}
 
	bool tmp_bool;
 
	tmp_bool = src->dead;
 
	src->dead=dead;
 
	dead = tmp_bool;
 
	
 
	WallType tmp_wall_type;
 
	tmp_wall_type = src->wall_type;
 
	src->wall_type = wall_type;
 
	wall_type = tmp_wall_type;
 
	
 
}
 

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

	
 
#include <fstream>
 

	
 
void WallBase::SetLength(void) {
 
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);
 
	
 
	// wrap around
 
	if (second_node_edge_plus_1 == c1->nodes.end()) {
 
		second_node_edge_plus_1 = c1->nodes.begin();
 
	}
 
@@ -197,80 +195,80 @@ void WallBase::SetLength(void) {
 
		 (++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  ) {
 
		
 
		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(); 
 
		
 
	}
 
}
 

	
 
void WallBase::CorrectTransporters(double orig_length) {
 
void WallBase::CorrectTransporters(double orig_length)
 
{
 
	
 
	double length_factor = length / orig_length;
 

	
 
	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) {
 
Vector WallBase::VizFlux(void)
 
{
 
	return viz_flux * ( (*n2) - (*n1) ).Normalised().Perp2D();    
 
}
 

	
 

	
 
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) {
 
Vector WallBase::getWallVector(CellBase *c)
 
{
 
	if ( c == c1 ) {
 
		return ( Vector(*n2) - Vector(*n1) );
 
	} else {
 
		return ( Vector(*n1) - Vector(*n2) );
 
	}
 
	
 
}
 
Vector WallBase::getInfluxVector(CellBase *c) {
 
Vector WallBase::getInfluxVector(CellBase *c)
 
{
 
	if ( c == c1 ) {
 
		return ( Vector(*n2) - Vector(*n1) ).Normalised().Perp2D();
 
	} else {
 
		return ( Vector(*n1) - Vector(*n2) ).Normalised().Perp2D();
 
	}
 
}
 

	
 
//! \brief Test if this wall intersects with division plane p1 -> p2 
 
bool WallBase::IntersectsWithDivisionPlaneP(const Vector &p1, const Vector &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));
 
	
 
	// If ua is between 0 and 1, line p1 intersects the line segment
 
	if ( ua >=0. && ua <=1.) return true;
 
	else return false;
 
	
 
}
 

	
 
/* finis */
src/wallbase.h
Show inline comments
 
@@ -19,30 +19,26 @@
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 

	
 

	
 
#ifndef _WALLBASE_H_
 
#define _WALLBASE_H_
 

	
 
#include <list>
 
#include <iostream>
 

	
 

	
 

	
 
#include "vector.h"
 

	
 

	
 
class Node;
 
class CellBase;
 

	
 
using namespace std;
 

	
 
// warning, touches original sequence
 
template<class In, class Out> Out duplicates_copy(In first, In last, Out res) {
 
	
 
	In i = adjacent_find(first, last);
 
	
 
	while (i!=last) {
 
		res++ = *i;
 
@@ -147,25 +143,28 @@ public:
 
		
 
		if (wall_type == Normal)  
 
			wall_type = AuxSource;
 
		else
 
			if (wall_type == AuxSource) 
 
				wall_type = AuxSink;
 
			else
 
				if (wall_type == AuxSink) {
 
					wall_type = Normal;
 
				}
 
	}
 
	// checked version. Use during debugging stage.
 
	inline double getTransporter(CellBase *c, int ch) const { return c1 == c ? transporters1[ch] : ( c2 == c ? transporters2[ch] : throw "WallBase::getTransporter called with wrong cell") ; } 
 
  inline double getTransporter(CellBase *c, int ch) const
 
  { 
 
    return c1 == c ? transporters1[ch] : ( c2 == c ? transporters2[ch] : throw "WallBase::getTransporter called with wrong cell") ; } 
 

	
 
	inline void setTransporter(CellBase *c, int ch, double val) { 
 
		if ( c1 == c ) {
 
			transporters1[ch]=val;
 
		} else 
 
			
 
			if (c2 == c ) {
 
				transporters2[ch]=val;
 
			} else {
 
				throw "WallBase::setTransporter called with wrong cell"; 
 
			}
 
	}
 
	inline double getApoplast(int ch) const { return apoplast[ch]; }
 
@@ -185,17 +184,18 @@ public:
 
	
 
	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);
 
	void SetTransToNewTrans( void );
 
	
 
private:
 
	
 
};
 

	
 
ostream &operator<<(ostream &os, const WallBase &w);
 
#endif
 

	
 
/* finis */
src/wallitem.cpp
Show inline comments
 
@@ -119,12 +119,14 @@ void WallItem::OnClick(QMouseEvent *e) {
 
					
 
				} else {
 
					// set high amount of PIN1
 
					//cerr << "Setting PIN1\n";
 
					wn==1?w->setTransporters1(1,10):w->setTransporters2(1,10);
 
				}
 
			}
 
			setColor();
 
			update(boundingRect());
 
		} 
 
	}
 
}
 

	
 
/* finis */
src/wallitem.h
Show inline comments
 
@@ -39,12 +39,14 @@ class WallItem : public QGraphicsLineIte
 
{
 
public:
 
  WallItem( Wall *n, int wallnumber, QGraphicsScene *canvas );
 
  virtual ~WallItem() {}
 
  Wall &getWall(void) const { return *class_cast<Wall*>(obj); }
 
  void OnClick(QMouseEvent *e);  
 
  void setColor(void);
 
 private:
 
  int wn;
 
};
 

	
 
#endif
 

	
 
/* finis */
src/warning.cpp
Show inline comments
 
@@ -72,25 +72,24 @@ void MyWarning::error(const char *fmt, .
 
    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);
 
    std::exit(1);
 
  }
 
  delete[] message;
 
  
 
}
 
#endif
 

	
 

	
 
/*
 
 * EPRINTF: scream, but don't die yet.
 
 * Roeland changed this to "warning" (21/10/1998)
 
 * and added an automatic "\n"
 
 */
 

	
 
#ifndef QTGRAPHICS
 
void MyWarning::warning(const char * fmt, ...)
 
@@ -122,25 +121,24 @@ void MyWarning::warning(const char *fmt,
 
  QString qmess(message);
 
  
 
  //  bool batch = false;
 
  
 
  if (qApp->type()==QApplication::Tty) {
 
    // batch mode: print the message to stderr
 
    fprintf(stderr, "Warning: %s\n",qmess.toStdString().c_str());
 
  } else { // issue a dialog box
 
	  UniqueMessageBox msgBox( QString("Warning"), qmess );
 
	  msgBox.exec();
 
  }
 
  delete[] message;
 

	
 
}
 
#endif
 

	
 
/*! Issues a warning only once,
 
  by comparing it to a list of warnings issued previously. */
 
void MyWarning::unique_warning(const char *fmt, ...) {
 
  
 
  va_list ap;
 
  if (Quiet) return;
 
  char *message = new char[1000];
 
 
 
  va_start(ap, fmt);
 
@@ -168,12 +166,14 @@ void MyWarning::unique_warning(const cha
 
}
 

	
 

	
 
#ifdef TESTBED
 

	
 
main(int argc, char * argv[])
 
{
 
    eprintf("warning: foo=%f\tbar=%d\tfum=\"%s\"\n", 3.1415, 32768, "waldo");
 
    error("error: foo=%f\tbar=%d\tfum=\"%s\"\n", 3.1415, 32768, "waldo");
 
}
 

	
 
#endif
 

	
 
/* finis */
src/warning.h
Show inline comments
 
@@ -36,12 +36,14 @@ extern "C" {
 
    
 
  namespace MyWarning {
 
    void error(const char *, ...);
 
    void warning(const char *, ...);
 
    void unique_warning(const char *, ...);
 
  }
 
  
 
#ifdef __cplusplus
 
}
 
#endif
 

	
 
#endif
 

	
 
/* finis */
src/xmlwrite.cpp
Show inline comments
 
@@ -47,47 +47,44 @@ void ThrowStringStream(stringstream &s) 
 
	msg = (char *)malloc((1+s.str().length())*sizeof(char));
 
	strcpy(msg,s.str().c_str());
 
	throw(msg);
 
}
 

	
 

	
 
// Add this cell to the XML tree
 
void Cell::XMLAdd(xmlNodePtr cells_node) const {
 

	
 
  // Save the cell to a stream so we can reconstruct its state later
 
  xmlNodePtr xmlcell = xmlNewChild(cells_node, NULL, BAD_CAST "cell",NULL);
 
  XMLAddCore(xmlcell);
 

	
 
}
 

	
 
void BoundaryPolygon::XMLAdd(xmlNodePtr parent_node) const {
 
  
 
  xmlNodePtr xmlcell = xmlNewChild(parent_node, NULL, BAD_CAST "boundary_polygon",NULL);
 
  XMLAddCore(xmlcell);
 

	
 
}
 

	
 
void NodeSet::XMLAdd(xmlNode *root) const {
 
  
 
  xmlNode *xmlnodeset = xmlNewChild(root, NULL, BAD_CAST "nodeset", NULL);
 
  
 
  for (list<Node *>::const_iterator i=begin();i!=end();i++) {
 
    {
 
      ostringstream text;
 
      xmlNodePtr node_xml = xmlNewChild(xmlnodeset, NULL, BAD_CAST "node", NULL);
 
      text << (*i)->Index();
 
      xmlNewProp(node_xml, BAD_CAST "n", BAD_CAST text.str().c_str());
 
    }
 
  }
 
  
 
}
 

	
 

	
 

	
 

	
 
void Cell::XMLAddCore(xmlNodePtr xmlcell) const {
 
  
 
  // properties
 

	
 
  {
 
    ostringstream text;
 
    text << index;
 
@@ -199,41 +196,35 @@ void Cell::XMLAddCore(xmlNodePtr xmlcell
 
  {
 
    ostringstream text;
 
    text << NChem();
 
    xmlNewProp(chem_xml, BAD_CAST "n", BAD_CAST text.str().c_str());
 
  }
 
  
 
  for (int i=0;i<NChem();i++) {
 
    xmlNodePtr chem_val_xml = xmlNewChild(chem_xml, NULL, BAD_CAST "val", NULL);
 
    { 
 
      ostringstream text;
 
      text << chem[i];
 
      xmlNewProp(chem_val_xml, BAD_CAST "v", BAD_CAST text.str().c_str());
 

	
 
    }
 
  }
 
  
 
  
 

	
 
}
 

	
 

	
 

	
 
void Node::XMLAdd(xmlNodePtr nodes_node) const { 
 
  
 
  // Save the node to a stream so we can reconstruct its state later
 
  xmlNodePtr xmlnode = xmlNewChild(nodes_node, NULL, BAD_CAST "node",NULL);
 

	
 
  
 
  
 
  {
 
    ostringstream text;
 
    text << x;
 
    xmlNewProp(xmlnode, BAD_CAST "x", BAD_CAST text.str().c_str());
 
  }
 
  
 
  {
 
    ostringstream text;
 
    text << y;
 
    xmlNewProp(xmlnode, BAD_CAST "y", BAD_CAST text.str().c_str());
 
  }
 

	
 
@@ -251,49 +242,46 @@ void Node::XMLAdd(xmlNodePtr nodes_node)
 

	
 
  {
 
    ostringstream text;
 
    text << bool_name(sam);
 
    xmlNewProp(xmlnode, BAD_CAST "sam", BAD_CAST text.str().c_str());
 
  }
 

	
 
  if (node_set) {
 
    ostringstream text;
 
    text << XMLIO::list_index(m->node_sets.begin(),m->node_sets.end(),node_set);
 
    xmlNewProp(xmlnode, BAD_CAST "nodeset", BAD_CAST text.str().c_str());    
 
  }
 
  
 

	
 
}
 

	
 
void Neighbor::XMLAdd(xmlNodePtr neighbors_node) const {
 
  
 
  xmlNodePtr xmlnode = xmlNewChild(neighbors_node, NULL, BAD_CAST "neighbor",NULL);
 
  {
 
    ostringstream text;
 
    text << cell->Index();
 
    xmlNewProp(xmlnode, BAD_CAST "cell", BAD_CAST text.str().c_str());
 
  }
 

	
 
  {
 
    ostringstream text;
 
    text << nb1->Index();
 
    xmlNewProp(xmlnode, BAD_CAST "nb1", BAD_CAST text.str().c_str());
 
  }
 

	
 
  {
 
    ostringstream text;
 
    text << nb2->Index();
 
    xmlNewProp(xmlnode, BAD_CAST "nb2", BAD_CAST text.str().c_str());
 
  }
 

	
 
}
 

	
 

	
 
// from example code on www.libxml.org:
 
xmlXPathObjectPtr
 
getnodeset (xmlDocPtr doc, xmlChar *xpath){
 
	
 
  xmlXPathContextPtr context;
 
  xmlXPathObjectPtr result;
 

	
 
  context = xmlXPathNewContext(doc);
 
  if (context == NULL) {
 
@@ -307,25 +295,26 @@ getnodeset (xmlDocPtr doc, xmlChar *xpat
 
    return NULL;
 
  }
 
  if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
 
    xmlXPathFreeObject(result);
 
    // printf("No result\n");
 
    return NULL;
 
  }
 
  return result;
 
}
 

	
 

	
 

	
 
int Cell::XMLRead(xmlNode *cur)  {
 
int Cell::XMLRead(xmlNode *cur)
 
{
 
  
 
  xmlNode *n = cur->xmlChildrenNode;
 
  QLocale standardlocale(QLocale::C);
 
  bool ok;
 

	
 
  vector<int> tmp_nodes;
 

	
 
	while(n!=NULL) {
 
    if ((!xmlStrcmp(n->name, (const xmlChar *)"node"))) {
 
      xmlChar *nc = xmlGetProp(n, BAD_CAST "n");
 

	
 
      if (nc==0) {
 
@@ -545,50 +534,49 @@ int Cell::XMLRead(xmlNode *cur)  {
 
		if (v_str==0) {
 
			unique_warning("Token \"cell_type\" not found in xmlwrite.cpp at or around line no. 1237");
 
		}
 
		if (v_str != NULL) {
 
			cell_type = atoi( (char *)v_str);
 
			xmlFree(v_str);
 
		}
 
	}
 
  
 
  // Recalculate moments and area
 
  SetIntegrals();
 
  return 0;
 

	
 
}
 
  
 
void NodeSet::XMLRead(xmlNode *root, Mesh *m) {
 
void NodeSet::XMLRead(xmlNode *root, Mesh *m)
 
{
 
  
 
  xmlNode *n = root->xmlChildrenNode;
 
  
 
  vector<int> tmp_nodes;
 
  while(n!=NULL) {
 
    if ((!xmlStrcmp(n->name, (const xmlChar *)"node"))) {
 
      xmlChar *nc = xmlGetProp(n, BAD_CAST "n");
 

	
 
      if (nc==0) {
 
	unique_warning("Token \"n\" not found in xmlwrite.cpp at or around line no. 966");
 
      }
 
      tmp_nodes.push_back(atoi( (char *)nc));
 
      xmlFree(nc);
 
    }
 
    n = n->next;
 
  }
 
  
 
  int nnodes = tmp_nodes.size();
 
  for (int i=0;i<nnodes;i++) {
 
    AddNode( &(m->getNode(tmp_nodes[i])) );
 
  }
 
  
 
}
 

	
 

	
 

	
 

	
 
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;
 
@@ -654,46 +642,45 @@ void Wall::XMLAdd(xmlNode *parent) const
 
      }
 
    }
 
  }
 
  if (transporters2) {
 
    xmlNodePtr tr2_xml = xmlNewChild(xmlwall, NULL, BAD_CAST "transporters2", NULL); 
 
  
 
    for (int i=0;i<Cell::NChem();i++) {
 
      xmlNodePtr tr2_val_xml = xmlNewChild(tr2_xml, NULL, BAD_CAST "val", NULL);
 
      { 
 
	ostringstream text;
 
	text << transporters2[i];
 
	xmlNewProp(tr2_val_xml, BAD_CAST "v", BAD_CAST text.str().c_str());
 
      
 
      }
 
    }
 
  }
 
   
 
  if (apoplast) {
 
    xmlNodePtr apo_xml = xmlNewChild(xmlwall, NULL, BAD_CAST "apoplast", NULL); 
 
  
 
    for (int i=0;i<Cell::NChem();i++) {
 
      xmlNodePtr apo_val_xml = xmlNewChild(apo_xml, NULL, BAD_CAST "val", NULL);
 
      { 
 
	ostringstream text;
 
	text << transporters2[i];
 
	xmlNewProp(apo_val_xml, BAD_CAST "v", BAD_CAST text.str().c_str());
 
	
 
      }
 
    }
 
  } 
 
}
 

	
 

	
 
vector<double> XMLIO::XMLReadValArray(xmlNode *cur) {
 
vector<double> XMLIO::XMLReadValArray(xmlNode *cur)
 
{
 
  
 
  vector<double> result;
 
  QLocale standardlocale(QLocale::C);
 
  bool ok;
 

	
 
  xmlNode *valarray_node = cur->xmlChildrenNode;
 
  while (valarray_node!=NULL) {
 
    if (!xmlStrcmp(valarray_node->name, (const xmlChar *)"val")) {
 
      xmlChar *vc = xmlGetProp(valarray_node, BAD_CAST "v");
 
      if (vc) {
 
	//result.push_back(strtod( (const char *)vc, 0));
 
	result.push_back(standardlocale.toDouble((char *)vc, &ok));
 
@@ -754,26 +741,24 @@ void Mesh::XMLSave(const char *docname, 
 

	
 
	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());
 
	}
 
	
 
	
 
	
 
	for (vector<Node *>::const_iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		(*i)->XMLAdd(xmlnodes) ;
 
	}
 
	
 
	
 
	/* 
 
	 * xmlNewChild() creates a new node, which is "attached" as child node
 
	 * of root_node node. 
 
	 */
 
	xmlNodePtr xmlcells = xmlNewChild(root_node, NULL, BAD_CAST "cells",NULL);
 
@@ -833,63 +818,56 @@ void Mesh::XMLSave(const char *docname, 
 
		 i++) {
 
		(*i)->XMLAdd(xmlwalls) ;
 
	}
 
	
 
	
 
	xmlNodePtr xmlnodesets = xmlNewChild(root_node, NULL, BAD_CAST "nodesets",NULL);
 
	{ 
 
		ostringstream text;
 
		text << node_sets.size();
 
		xmlNewProp(xmlnodesets, BAD_CAST "n", BAD_CAST text.str().c_str());
 
	}
 
	
 
	
 
	for_each( node_sets.begin(), node_sets.end(), 
 
			 bind2nd ( 
 
					  mem_fun( &NodeSet::XMLAdd ),
 
					  xmlnodesets
 
					  ) );
 
	
 
  for_each( node_sets.begin(), node_sets.end(), bind2nd ( mem_fun( &NodeSet::XMLAdd ), xmlnodesets ) );
 
	
 
	// Add option tree for interactive application
 
	if (options) {
 
		xmlAddChild(root_node, options);
 
	}
 
	
 
	
 
	
 
	
 
	/* 
 
	 * Dumping document to stdio or file
 
	 */
 
	xmlSetDocCompressMode(doc,9);
 
	xmlSaveFormatFileEnc(docname, doc, "UTF-8", 1);
 
	
 
	/*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
 
	 */
 
}
 

	
 

	
 

	
 
void Mesh::XMLReadSimtime(const xmlNode *a_node) {
 
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) {
 

	
 
    QLocale standardlocale(QLocale::C);
 
    bool ok;
 
    
 
    double simtime=standardlocale.toDouble((char *)strsimtime, &ok);
 
@@ -897,25 +875,26 @@ void Mesh::XMLReadSimtime(const xmlNode 
 
      time = simtime;
 
#ifdef QDEBUG
 
                qDebug() << "Simtime = " << strsimtime << endl;
 
#endif
 
	} else {
 
#ifdef QDEBUG
 
    qDebug() << "No simtime found in file." << endl;
 
#endif
 
		time =0;
 
	}	
 
}
 

	
 
void Mesh::XMLReadPars(const xmlNode * a_node) {
 
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);
 
}
 

	
 
void Mesh::XMLReadGeometry(const xmlNode * a_node)
 
{
 
  
 
	xmlNode *root_node;
 
	root_node = (xmlNode *)a_node;
 
@@ -970,25 +949,24 @@ void Mesh::XMLReadGeometry(const xmlNode
 
			xmlChar *magnificationc = xmlGetProp(cur, BAD_CAST "magnification");
 

	
 
			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() = 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;
 
	cur = root_node->xmlChildrenNode;
 
	while (cur!=NULL) {
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"walls"))){
 
			XMLReadWalls(cur, &tmp_walls);
 
		}
 
@@ -1012,58 +990,56 @@ void Mesh::XMLReadGeometry(const xmlNode
 
		 c++) {
 
		
 
		(*c)->ConstructNeighborList();
 
		(*c)->ConstructConnections();
 
		
 
	}
 
	
 
	shuffled_cells.clear();
 
	shuffled_cells = cells;
 
	
 
	MyUrand r(shuffled_cells.size());
 
	random_shuffle(shuffled_cells.begin(),shuffled_cells.end(),r);
 
    
 
}
 

	
 
void Mesh::XMLParseTree(const xmlNode *root_node) {
 
	
 
void Mesh::XMLParseTree(const xmlNode *root_node)
 
{
 
	XMLReadSimtime(root_node);
 
	XMLReadPars(root_node);
 
	XMLReadGeometry(root_node);
 
	
 
}
 

	
 

	
 
void Mesh::XMLReadNodes(xmlNode *root) {
 
void Mesh::XMLReadNodes(xmlNode *root)
 
{
 
	
 
  QLocale standardlocale(QLocale::C);
 
  bool ok;
 

	
 
  xmlNode *cur = root;
 
  cur = cur->xmlChildrenNode;
 
	
 
  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 = 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"))){
 
			
 
@@ -1106,39 +1082,37 @@ void Mesh::XMLReadNodes(xmlNode *root) {
 
			
 
      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;
 
			
 
      xmlFree(xc);
 
      xmlFree(yc);
 
      xmlFree(boundaryc);
 
      xmlFree(fixedc);
 
      xmlFree(samc);
 
			
 
			
 
    }
 
    cur=cur->next;
 
  }
 
	
 
  shuffled_nodes.clear();
 
  shuffled_nodes = nodes;
 
	
 
  MyUrand r(shuffled_nodes.size());
 
  random_shuffle(shuffled_nodes.begin(),shuffled_nodes.end(),r);
 
	
 
}
 

	
 
void Mesh::XMLReadWalls(xmlNode *root, vector<Wall *> *tmp_walls) {
 
void Mesh::XMLReadWalls(xmlNode *root, vector<Wall *> *tmp_walls)
 
{
 
	
 
  xmlNode *cur = root;
 
  cur = cur->xmlChildrenNode;
 
	
 
  for (list<Wall *>::iterator i=walls.begin();
 
       i!=walls.end();
 
       i++) {
 
    delete *i;
 
  }
 
	
 
  walls.clear();
 
  Wall::nwalls = 0;
 
@@ -1231,25 +1205,24 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
				
 
	bool dead = false;
 
	{
 
	  // Note: property "delete" is used to manually clean up wall lists in XML files
 
	  // Simply add property 'delete="true"' to the wall and it will be removed from
 
	  // the mesh. (This saves us from manually reindexing the file). Otherwise do not use it.
 
	  xmlChar *v_str = xmlGetProp(cur, BAD_CAST "delete");
 
					
 
	  if (v_str != 0) {
 
	    dead = strtobool( (char *)v_str);
 
	    xmlFree(v_str);
 
	  }
 
					
 
	}
 
				
 
	Cell *cc1 = c1 != -1 ? cells[c1] : boundary_polygon;
 
	Cell *cc2 = c2 != -1 ? cells[c2] : boundary_polygon;
 
				
 
	Wall *w = new Wall( nodes[n1], nodes[n2], cc1, cc2);
 
	w->length = length;
 
	w->viz_flux = viz_flux;
 
	w->wall_type = wall_type;
 
	w->dead = dead;
 
	tmp_walls->push_back(w);
 
	walls.push_back(w);
 
@@ -1278,59 +1251,55 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
		  unique_warning("Token \"v\" not found in xmlwrite.cpp at or around line no. 835");
 
		}
 

	
 
		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; 
 
	    }
 
						
 
	  }
 
					
 
					
 
	  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;
 

	
 
		  }
 
		}
 
								
 
		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 = 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;
 
@@ -1355,25 +1324,26 @@ void Mesh::XMLReadWalls(xmlNode *root, v
 
	      v_node = v_node->next; 
 
	    }
 
	  }
 
	  w_node=w_node->next;
 
	}
 
      }
 
      cur = cur->next;
 
    }
 
  }
 
}
 

	
 

	
 
void Mesh::XMLReadWallsToCells(xmlNode *root, vector<Wall *> *tmp_walls) {
 
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) {
 
		
 
@@ -1400,37 +1370,34 @@ void Mesh::XMLReadWallsToCells(xmlNode *
 
			if (!xmlStrcmp(cur->name, (const xmlChar *)"boundary_polygon")) {
 
				
 
				int nwalls = tmp_walls_ind.size();
 
				for (int i=0;i<nwalls;i++) {
 
					boundary_polygon->walls.push_back((*tmp_walls)[tmp_walls_ind[i]]);
 
				}
 
			} else {
 
				
 
				int nwalls = tmp_walls_ind.size();
 
				for (int i=0;i<nwalls;i++) {
 
					cells[ci]->walls.push_back((*tmp_walls)[tmp_walls_ind[i]]);	
 
				}
 
				
 
				ci++;
 
			}
 
			
 
		} 
 
		cur=cur->next;
 
	}
 
	
 
	
 
}
 

	
 

	
 
void Mesh::XMLReadNodeSetsToNodes(xmlNode *root) {
 
void Mesh::XMLReadNodeSetsToNodes(xmlNode *root)
 
{
 
	
 
	xmlNode *cur = root->xmlChildrenNode;
 
	int ci=0; // cell index
 
	
 
	while (cur!=NULL) {
 
		
 
		
 
		
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"node"))) {
 
			
 
			xmlNode *n = cur->xmlChildrenNode;
 
			
 
@@ -1439,36 +1406,33 @@ void Mesh::XMLReadNodeSetsToNodes(xmlNod
 
				xmlChar *nc = xmlGetProp(n, BAD_CAST "nodeset");
 
				
 
				if (nc!=0) {
 
					int nodeset_n = atoi( (char *)nc);
 
					nodes[ci]->node_set = node_sets[nodeset_n];
 
					xmlFree(nc);
 
				} else {
 
					nodes[ci]->node_set = 0;
 
				}
 
				
 
				n = n->next;
 
			}
 
			
 
			ci++;
 
			
 
		} 
 
		cur=cur->next;
 
	}
 
	
 
	
 
}
 

	
 

	
 
void Mesh::XMLReadNodeSets(xmlNode *root) {
 
void Mesh::XMLReadNodeSets(xmlNode *root)
 
{
 
	
 
	for (vector<NodeSet *>::iterator i=node_sets.begin();
 
		 i!=node_sets.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	
 
	node_sets.clear();
 
	
 
	xmlNode *cur = root->xmlChildrenNode;
 
	
 
	while (cur!=NULL) {
 
@@ -1478,28 +1442,28 @@ void Mesh::XMLReadNodeSets(xmlNode *root
 
		if ((!xmlStrcmp(cur->name, (const xmlChar *)"nodeset"))){
 
			new_nodeset = new NodeSet();
 
			node_sets.push_back(new_nodeset);
 
		} 
 
		
 
		if (new_nodeset == 0) { 
 
			cur = cur->next;
 
			continue;
 
		}
 
		new_nodeset->XMLRead(cur, this);
 
		cur=cur->next;
 
	}
 
	
 
}
 

	
 
void Mesh::XMLReadCells(xmlNode *root) {
 
void Mesh::XMLReadCells(xmlNode *root)
 
{
 
	
 
	for (vector<Cell *>::iterator i=cells.begin();
 
		 i!=cells.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	
 
	cells.clear();
 
	Cell::NCells() = 0;
 
	
 
	delete boundary_polygon;
 
	
 
@@ -1521,28 +1485,28 @@ void Mesh::XMLReadCells(xmlNode *root) {
 
				boundary_polygon->m = this;
 
			}
 
		}
 
		
 
		if (new_cell == 0) { 
 
			cur = cur->next;
 
			continue;
 
		}
 
		
 
		new_cell->XMLRead(cur);
 
		cur=cur->next;
 
	}
 
	
 
}
 

	
 
void Mesh::XMLRead(const char *docname, xmlNode **settings, bool geometry, bool pars, bool simtime) {
 
void Mesh::XMLRead(const char *docname, xmlNode **settings, bool geometry, bool pars, bool simtime)
 
{
 
	
 
	xmlDocPtr doc = xmlParseFile(docname);
 
	if (doc == NULL ) {
 
		throw("Document not parsed successfully.");
 
		return;
 
	}
 
	
 
	xmlNodePtr cur = xmlDocGetRootElement(doc);
 
	
 
	if (cur == NULL) {
 
		throw("Document is empty");
 
		xmlFreeDoc(doc);
 
@@ -1575,29 +1539,29 @@ void Mesh::XMLRead(const char *docname, 
 
		}
 
	}
 
	xmlFreeDoc(doc);
 
	
 
	/*
 
	 *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();
 
	
 
}
 

	
 

	
 
void Parameter::XMLRead(xmlNode *root) {
 
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) {
 
							AssignValToPar((const char*)namec,(const char*)valc);
 
@@ -1608,19 +1572,18 @@ void Parameter::XMLRead(xmlNode *root) {
 
							while (sub_par_node != NULL) {
 
								if (!xmlStrcmp(sub_par_node->name, (const xmlChar *)"valarray")) {
 
									valarray = XMLIO::XMLReadValArray(sub_par_node);
 
								}
 
								sub_par_node = sub_par_node->next;
 
							}
 
							AssignValArrayToPar((const char*)namec, valarray);
 
						}
 
					}
 
				}	  
 
				par_node = par_node->next;
 
			}
 
			
 
		}
 
		cur=cur->next;
 
	}
 
    
 
}
 

	
 
/* finis */
src/xmlwrite.h
Show inline comments
 
@@ -36,33 +36,34 @@ namespace XMLIO {
 
    
 
    long n = 0;
 
    for (For i=beg;
 
	 i!=end;
 
	 i++) {
 
      if (*i == elem) {
 
	return n;
 
      }
 
      n++;
 
    }
 
    return -1;
 
  }
 
 	
 
}
 

	
 

	
 
static const char * bool_names[2] = {"true","false"};
 

	
 
inline const char *bool_name(bool q) { return q ? bool_names[0] : bool_names[1]; }
 

	
 
inline bool strtobool(const char *str) { 
 
  if (!strcmp(str, "true")) {
 
    return true;
 
  } else {
 
    if (!strcmp(str, "false")) {
 
      return false;
 
    } else {
 
      throw("Error in xmlwrite.cpp : strtobool(const char *str). Parameter passed other than \"true\" or \"false\".");
 
    }
 
  }
 
}
 

	
 
#endif
 

	
 
/* finis */
0 comments (0 inline, 0 general)