Changeset - aaba9e8828d6
[Not reviewed]
default
0 5 0
Roeland Merks - 15 years ago 2010-06-07 15:50:24
roeland.merks@cwi.nl
Added to new menu options: edit->ResetChemicals and edit->ResetTransporters, which allows you to set only the chemicals or only the transporters to the initial values. I needed this for preparing a suitable initial condition for Tutorial 6 and thought it would be useful for the main distribution.

--
user: Roeland Merks <roeland.merks@cwi.nl>
branch 'default'
changed src/build_models/Makefile
changed src/canvas.cpp
changed src/canvas.h
changed src/mesh.cpp
changed src/mesh.h
5 files changed with 315 insertions and 59 deletions:
0 comments (0 inline, 0 general)
src/build_models/Makefile
Show inline comments
 
# $Id: Makefile,v 3f0977faba37 2010/06/03 15:54:37 michael $
 
#############################################################################
 
# Makefile for building: libauxinsimon.so
 
# Generated by qmake (2.01a) (Qt 4.4.1) on: Mon Jun 7 13:36:27 2010
 
# Project:  auxinsimon.pro
 
# Template: lib
 
# Command: /ufs/merks/Trolltech/Qt-4.4.1/bin/qmake -unix -o Makefile auxinsimon.pro
 
#############################################################################
 

	
 
QMAKE = qmake
 
####### Compiler, tools and options
 

	
 
all: plugin_auxingrowth plugin_leaf plugin_meinhardt plugin_test
 
CC            = gcc
 
CXX           = g++
 
DEFINES       = -DQTGRAPHICS -DQT_NO_DEBUG -DQT_PLUGIN -DQT_QT3SUPPORT_LIB -DQT3_SUPPORT -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
 
CFLAGS        = -m64 -pipe -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES)
 
CXXFLAGS      = -m64 -pipe -fexceptions -I.. -fPIC -I/usr/include/libxml2 -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES)
 
INCPATH       = -I../../../../Trolltech/Qt-4.4.1/mkspecs/linux-g++-64 -I. -I../../../../Trolltech/Qt-4.4.1/include/QtCore -I../../../../Trolltech/Qt-4.4.1/include/QtCore -I../../../../Trolltech/Qt-4.4.1/include/QtGui -I../../../../Trolltech/Qt-4.4.1/include/QtGui -I../../../../Trolltech/Qt-4.4.1/include/Qt3Support -I../../../../Trolltech/Qt-4.4.1/include/Qt3Support -I../../../../Trolltech/Qt-4.4.1/include -I. -I.
 
LINK          = g++
 
LFLAGS        = -m64 -fPIC -Wl,-rpath,/ufs/merks/Trolltech/Qt-4.4.1/lib -shared
 
LIBS          = $(SUBLIBS)  -L/ufs/merks/Trolltech/Qt-4.4.1/lib -L../../lib -lvleaf -lQt3Support -L/ufs/merks/Trolltech/Qt-4.4.1/lib -lQtSql -pthread -pthread -pthread -pthread -lQtXml -pthread -pthread -pthread -pthread -L/usr/X11R6/lib64 -pthread -pthread -pthread -pthread -pthread -pthread -lQtNetwork -pthread -pthread -pthread -pthread -pthread -pthread -lQtGui -pthread -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread
 
AR            = ar cqs
 
RANLIB        = 
 
QMAKE         = /ufs/merks/Trolltech/Qt-4.4.1/bin/qmake
 
TAR           = tar -cf
 
COMPRESS      = gzip -9f
 
COPY          = cp -f
 
SED           = sed
 
COPY_FILE     = $(COPY)
 
COPY_DIR      = $(COPY) -r
 
INSTALL_FILE  = install -m 644 -p
 
INSTALL_DIR   = $(COPY_DIR)
 
INSTALL_PROGRAM = install -m 755 -p
 
DEL_FILE      = rm -f
 
SYMLINK       = ln -sf
 
DEL_DIR       = rmdir
 
MOVE          = mv -f
 
CHK_DIR_EXISTS= test -d
 
MKDIR         = mkdir -p
 

	
 
plugin_auxingrowth: Makefile.plugin_auxingrowth
 
	make -f Makefile.plugin_auxingrowth
 
####### Output directory
 

	
 
OBJECTS_DIR   = ./
 

	
 
####### Files
 

	
 
Makefile.plugin_auxingrowth: plugin_auxingrowth.pro
 
	$(QMAKE) -makefile -o $@ $< 
 
SOURCES       = auxinsimon.cpp moc_auxinsimon.cpp
 
OBJECTS       = auxinsimon.o \
 
		moc_auxinsimon.o
 
DIST          = ../../../../Trolltech/Qt-4.4.1/mkspecs/common/g++.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/common/unix.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/common/linux.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/qconfig.pri \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_functions.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_config.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/exclusive_builds.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_pre.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/release.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_post.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/warn_on.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/unix/thread.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/moc.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/resources.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/uic.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/yacc.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/lex.prf \
 
		auxinsimon.pro
 
QMAKE_TARGET  = auxinsimon
 
DESTDIR       = ../../bin/models/
 
TARGET        = libauxinsimon.so
 
TARGETD       = libauxinsimon.so
 

	
 
plugin_leaf: Makefile.plugin_leaf
 
	make -f Makefile.plugin_leaf
 
first: all
 
####### Implicit rules
 

	
 
.SUFFIXES: .o .c .cpp .cc .cxx .C
 

	
 
.cpp.o:
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
 

	
 
.cc.o:
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
 

	
 
.cxx.o:
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
 

	
 
Makefile.plugin_leaf: plugin_leaf.pro
 
	$(QMAKE) -makefile -o $@ $< 
 
.C.o:
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<"
 

	
 
.c.o:
 
	$(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<"
 

	
 
####### Build rules
 

	
 
all: Makefile  ../../bin/models/$(TARGET)
 

	
 
../../bin/models/$(TARGET):  $(OBJECTS) $(SUBLIBS) $(OBJCOMP)  
 
	@$(CHK_DIR_EXISTS) ../../bin/models/ || $(MKDIR) ../../bin/models/ 
 
	-$(DEL_FILE) $(TARGET)
 
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP)
 
	-$(MOVE) $(TARGET) ../../bin/models/
 

	
 

	
 

	
 
plugin_meinhardt: Makefile.plugin_meinhardt
 
	make -f Makefile.plugin_meinhardt
 
Makefile: auxinsimon.pro  ../../../../Trolltech/Qt-4.4.1/mkspecs/linux-g++-64/qmake.conf ../../../../Trolltech/Qt-4.4.1/mkspecs/common/g++.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/common/unix.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/common/linux.conf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/qconfig.pri \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_functions.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_config.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/exclusive_builds.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_pre.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/release.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_post.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/warn_on.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/unix/thread.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/moc.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/resources.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/uic.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/yacc.prf \
 
		../../../../Trolltech/Qt-4.4.1/mkspecs/features/lex.prf \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQt3Support.prl \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtSql.prl \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtCore.prl \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtXml.prl \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtGui.prl \
 
		/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtNetwork.prl
 
	$(QMAKE) -unix -o Makefile auxinsimon.pro
 
../../../../Trolltech/Qt-4.4.1/mkspecs/common/g++.conf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/common/unix.conf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/common/linux.conf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/qconfig.pri:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_functions.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt_config.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/exclusive_builds.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_pre.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/release.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/default_post.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/warn_on.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/qt.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/unix/thread.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/moc.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/resources.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/uic.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/yacc.prf:
 
../../../../Trolltech/Qt-4.4.1/mkspecs/features/lex.prf:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQt3Support.prl:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtSql.prl:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtCore.prl:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtXml.prl:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtGui.prl:
 
/ufs/merks/Trolltech/Qt-4.4.1/lib/libQtNetwork.prl:
 
qmake:  FORCE
 
	@$(QMAKE) -unix -o Makefile auxinsimon.pro
 

	
 
Makefile.plugin_meinhardt: plugin_meinhardt.pro
 
	$(QMAKE) -makefile -o $@ $< 
 
dist: 
 
	@$(CHK_DIR_EXISTS) .tmp/auxinsimon1.0.0 || $(MKDIR) .tmp/auxinsimon1.0.0 
 
	$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/auxinsimon1.0.0/ && $(COPY_FILE) --parents ../simplugin.h auxinsimon.h .tmp/auxinsimon1.0.0/ && $(COPY_FILE) --parents auxinsimon.cpp .tmp/auxinsimon1.0.0/ && (cd `dirname .tmp/auxinsimon1.0.0` && $(TAR) auxinsimon1.0.0.tar auxinsimon1.0.0 && $(COMPRESS) auxinsimon1.0.0.tar) && $(MOVE) `dirname .tmp/auxinsimon1.0.0`/auxinsimon1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/auxinsimon1.0.0
 

	
 

	
 
plugin_test: Makefile.plugin_test
 
	make -f Makefile.plugin_test
 
clean:compiler_clean 
 
	-$(DEL_FILE) $(OBJECTS)
 
	-$(DEL_FILE) *~ core *.core
 

	
 

	
 
####### Sub-libraries
 

	
 
Makefile.plugin_test: plugin_test.pro
 
	$(QMAKE) -makefile -o $@ $< 
 
distclean: clean
 
	-$(DEL_FILE) $(TARGET) 
 
	-$(DEL_FILE) Makefile
 

	
 

	
 
mocclean: compiler_moc_header_clean compiler_moc_source_clean
 

	
 
mocables: compiler_moc_header_make_all compiler_moc_source_make_all
 

	
 
compiler_moc_header_make_all: moc_auxinsimon.cpp
 
compiler_moc_header_clean:
 
	-$(DEL_FILE) moc_auxinsimon.cpp
 
moc_auxinsimon.cpp: ../simplugin.h \
 
		../cellbase.h \
 
		../vector.h \
 
		../sqr.h \
 
		../parameter.h \
 
		../wall.h \
 
		../wallbase.h \
 
		../warning.h \
 
		auxinsimon.h
 
	/ufs/merks/Trolltech/Qt-4.4.1/bin/moc $(DEFINES) $(INCPATH) auxinsimon.h -o moc_auxinsimon.cpp
 

	
 
clean:
 
	make -f Makefile.plugin_auxingrowth clean
 
	make -f Makefile.plugin_leaf clean
 
	make -f Makefile.plugin_meinhardt clean
 
	make -f Makefile.plugin_test clean
 
compiler_rcc_make_all:
 
compiler_rcc_clean:
 
compiler_image_collection_make_all: qmake_image_collection.cpp
 
compiler_image_collection_clean:
 
	-$(DEL_FILE) qmake_image_collection.cpp
 
compiler_moc_source_make_all:
 
compiler_moc_source_clean:
 
compiler_uic_make_all:
 
compiler_uic_clean:
 
compiler_yacc_decl_make_all:
 
compiler_yacc_decl_clean:
 
compiler_yacc_impl_make_all:
 
compiler_yacc_impl_clean:
 
compiler_lex_make_all:
 
compiler_lex_clean:
 
compiler_clean: compiler_moc_header_clean 
 

	
 
####### Compile
 

	
 
#finis
 
auxinsimon.o: auxinsimon.cpp ../simplugin.h \
 
		../cellbase.h \
 
		../vector.h \
 
		../sqr.h \
 
		../parameter.h \
 
		../wall.h \
 
		../wallbase.h \
 
		../warning.h \
 
		auxinsimon.h
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o auxinsimon.o auxinsimon.cpp
 

	
 
moc_auxinsimon.o: moc_auxinsimon.cpp 
 
	$(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_auxinsimon.o moc_auxinsimon.cpp
 

	
 
####### Install
 

	
 
install:   FORCE
 

	
 
uninstall:   FORCE
 

	
 
FORCE:
 

	
src/canvas.cpp
Show inline comments
 
@@ -373,384 +373,386 @@ void FigureEditor::mouseReleaseEvent(QMo
 
      NodeSet *node_set = new NodeSet;
 
      
 
      for (vector<CellItem *>::iterator it = intersected_cells.begin();
 
	   it != intersected_cells.end();
 
	   it++) {
 
      
 
	//(*it)->Mark();
 
	(*it)->setBrush(QBrush("purple"));
 
       
 
	Cell &c=(*it)->getCell();
 
      
 
	// sometimes the cell hasn't properly divided yet before the
 
	// next division is called?  so check for it?  let's find a way
 
	// to do this later. Note that this functionality currently
 
	// might result in a segmentation fault for users who are
 
	// quickly dragging and releasing division lines...
 
	scene()->update();
 
	
 
	cerr << "Dividing Cell " << c.Index() << endl;
 
	c.DivideOverGivenLine( startpoint, endpoint, true, node_set);
 
      }
 
      
 
      node_set->CleanUp();
 
      mesh.AddNodeSet(node_set);
 
      
 
      cerr << "Done DivideOverGivenLine\n";
 
      mesh.TestIllegalWalls();
 
      // Do the actual cutting and removing
 
      if (intersected_cells.size()) {
 
	//      Mesh &m(intersected_cells.front()->getCell().getMesh());
 
	mesh.CutAwayBelowLine( startpoint, endpoint ); 
 
	
 
	// Correct flags of nodeset
 
	for (
 
	     NodeSet::iterator i = node_set->begin(); 
 
	     i != node_set->end();
 
	     i++) {
 
	  (*i)->SetSAM();
 
	  (*i)->SetBoundary();
 
	}
 

	
 
	// Make cells attached to nodeset part of the boundary
 
	// This is a temporary solution for the following:
 
	//   If a cell attached to a NodeSet divides (with a division plane intersecting the node set), 
 
	//   we must insert a new node into the node set.
 
	// For now, we add a layer of "virtual cells" inbetween. 
 
	list<Cell *> cells_attached_to_nodeset = node_set->getCells();
 
	for ( list<Cell *>::iterator c = cells_attached_to_nodeset.begin();
 
	      c != cells_attached_to_nodeset.end(); 
 
	      c++) {
 
	  (*c)->SetBoundary(Cell::SAM);
 
	}
 

	
 

	
 

	
 
	cerr << "Done CutAwayBelowLine\n";
 
	mesh.TestIllegalWalls();
 
	mesh.RepairBoundaryPolygon();
 
	cerr << "Done RepairBoundaryPolygon\n";
 
	mesh.TestIllegalWalls();
 
	mesh.CleanUpWalls();
 
	cerr << "Done CleanUpWalls\n";
 
	mesh.TestIllegalWalls();
 
      }
 
      
 
      dynamic_cast<Main *>(parent())->Plot();
 
      
 
      cerr << "NodeSet of cutting line: " << *node_set << endl;
 

	
 
    }
 
  } else 
 
    if (e->button()==Qt::RightButton) {
 
      
 
      if (intersection_line /* && !angle_line*/) {
 
	
 
	//QPointF p = matrix().inverted().map(e->pos());
 
	QPointF p = mapToScene(e->pos());
 
	QPointF sp = intersection_line->line().p1();
 
	
 
	viewport()->setMouseTracking( TRUE );
 
	/* angle_line = new QGraphicsLineItem( 0, scene() );
 
	angle_line->setPen( QPen( QColor("Blue"), 3, Qt::DashLine ) );
 
	angle_line->setLine( QLineF(sp, p) );
 
	angle_line->setZValue( 100 );
 
	angle_line->show();
 
	*/
 
      } 
 
            
 
    }
 
}
 

	
 

	
 
// returns a vector of pointer to cells colliding with intersection line
 
vector <CellItem *> FigureEditor::getIntersectedCells(void) { 
 
  
 
  vector <CellItem *> colliding_cells;
 
  
 
  QList<QGraphicsItem *> l = intersection_line->collidingItems( );
 
  
 
  cerr << "l.size() = " << l.size() << endl;
 
  for (QList<QGraphicsItem *>::Iterator it=l.begin(); it!=l.end(); ++it) {
 
    
 
    cerr << typeid(**it).name() << endl;
 
    
 
    if ( !strcmp(typeid(**it).name(),"8CellItem") ) {
 
      
 
      colliding_cells.push_back(dynamic_cast<CellItem *>(*it));
 
      
 
    }
 
  }
 
  
 
  delete intersection_line;
 
  intersection_line = 0;
 
  return colliding_cells;
 
    
 
}
 

	
 
void FigureEditor::FullRedraw(void) {
 
	QList<QRectF> rl;
 
	rl << sceneRect();
 
	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) {
 
    if ( !strcmp(typeid(**it).name(),"8NodeItem")) {
 
      // the object under the mouse click is a Nodeitem
 
      nodeItem = dynamic_cast<NodeItem *>(*it);
 
      // indicate we've selected it
 
      nodeItem->setBrush(dark_red);
 
      break;
 
    }
 
  }
 
  return nodeItem;
 
}
 

	
 

	
 
void FigureEditor::insertNode(QPointF p)
 
{
 
  Node *node = new Node(p.x(), p.y(), 0);
 
  mesh.AddNode(node);
 
  scene()->clearSelection();
 
  dynamic_cast<Main *>(parent())->Plot();
 
  FullRedraw();
 
#ifdef QDEBUG  
 
  qDebug() << "Node: " << p << endl;
 
#endif
 
}
 

	
 
static uint mainCount = 0;
 

	
 
Main::Main(QGraphicsScene& c, Mesh &m, QWidget* parent, const char* name, Qt::WindowFlags f) :
 
  Q3MainWindow(parent,name,f),
 
  MainBase(c,m),
 
  mesh(m)
 
	   
 
	  //canvas(c)
 
{
 
  editor = new FigureEditor(canvas,mesh, this);
 
  cerr << "Interactive = " << editor->isEnabled();
 
  working_dir = 0;
 
  QObject::connect( editor, SIGNAL(MousePressed()), this, SLOT(PauseIfRunning()));
 
  QObject::connect( editor, SIGNAL(MouseReleased()), this, SLOT(ContIfRunning()));
 
  QMenuBar* menu = menuBar();
 
  
 
  Q3PopupMenu* file = new Q3PopupMenu( menu );
 
 // file->insertItem("&Fill canvas", this, SLOT(init()), Qt::CTRL+Qt::Key_F);
 
	file->insertItem("&Read leaf", this, SLOT(readStateXML()));
 
	file->insertItem("&Save leaf", this, SLOT(saveStateXML()));
 
	file->insertItem("Snapshot", this, SLOT(snapshot()), Qt::CTRL+Qt::SHIFT+Qt::Key_S);
 
 // file->insertItem("&New view", this, SLOT(newView()), Qt::CTRL+Qt::Key_N);
 
   file->insertSeparator();
 
	file->insertItem("Read next leaf", this, SLOT(readNextStateXML()), Qt::Key_PageDown);
 
	file->insertItem("Read previous leaf", this, SLOT(readPrevStateXML()), Qt::Key_PageUp);
 
	file->insertItem("Read last leaf", this, SLOT(readLastStateXML()), Qt::Key_End);
 
	file->insertItem("Read first leaf", this, SLOT(readFirstStateXML()), Qt::Key_Home);
 
	//file->insertItem("Read &parameters", this, SLOT(readPars()));
 
  //file->insertItem("&Write parameters", this, SLOT(savePars()));
 
	
 
	file->insertSeparator();
 
	file->insertItem("&Print...", this, SLOT(print()), Qt::CTRL+Qt::Key_P);
 
	file->insertSeparator();
 
	file->insertItem("E&xit", qApp, SLOT(quit()), Qt::CTRL+Qt::Key_Q);
 
	menu->insertItem("&File", file);
 
	
 
	Q3PopupMenu* edit = new Q3PopupMenu( menu );
 
  edit->insertItem("Reset Chemicals and Transporters", this, SLOT( CleanMesh()), Qt::CTRL+Qt::Key_R );
 
	edit->insertItem("Reset Chemicals", this, SLOT( CleanMeshChemicals()) );
 
	edit->insertItem("Reset Transporters", this, SLOT( CleanMeshTransporters()) );
 
  edit->insertItem("Randomize PIN1 Transporters", this, SLOT( RandomizeMesh()) );
 
  edit->insertItem("Cut away SAM", this, SLOT( CutSAM() ));
 
  menu->insertItem("&Edit", edit);
 

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

	
 
  //run->insertItem("&Divide Cell", this, SLOT(Divide()), Qt::CTRL+Qt::Key_D);
 
 // run->insertItem("&Restart Simulation", this, SLOT(RestartSim())); 
 
  menu->insertItem("&Run", run);
 
  
 
  view = new Q3PopupMenu( menu );
 
  //view->insertItem("&Enlarge", this, SLOT(enlarge()), SHIFT+CTRL+Key_Plus);
 
  //view->insertItem("Shr&ink", this, SLOT(shrink()), SHIFT+CTRL+Key_Minus);
 
	view->insertItem("&Zoom in", this, SLOT(zoomIn()), Qt::CTRL+Qt::Key_Equal);
 
  view->insertItem("Zoom &out", this, SLOT(zoomOut()), Qt::CTRL+Qt::Key_Minus);
 
	view->insertSeparator();
 
	com_id = view->insertItem("Show cell &centers", this, SLOT(toggleShowCellCenters()));
 
  view->setItemChecked(com_id, FALSE);
 
  //view->insertItem("Cell monitor", this, SLOT(cellmonitor()));
 
  mesh_id = view->insertItem("Show &nodes", this, SLOT(toggleShowNodes()), Qt::CTRL+Qt::SHIFT+Qt::Key_N);
 
  view->setItemChecked(mesh_id, TRUE);
 
  node_number_id = view->insertItem("Show node numbers", this, SLOT(toggleNodeNumbers()), Qt::CTRL+Qt::SHIFT+Qt::Key_M);
 
  view->setItemChecked(node_number_id, TRUE);
 
  cell_number_id = view->insertItem("Show cell numbers", this, SLOT(toggleCellNumbers()));
 
  view->setItemChecked(cell_number_id, TRUE);
 
  hide_cells_id = view->insertItem("Hide cells", this, SLOT(toggleHideCells()));
 
  view->setItemChecked(hide_cells_id, FALSE);
 
  border_id = view->insertItem("Show &border cells", this, SLOT(toggleShowBorderCells()));
 
  view->setItemChecked(border_id, FALSE);
 
  cell_axes_id = view->insertItem("Show cell &axes", this, SLOT(toggleCellAxes()));
 
  cell_strain_id = view->insertItem("Show cell &strain", this, SLOT(toggleCellStrain()));
 
  view->setItemChecked(cell_axes_id, FALSE);
 
  fluxes_id = view->insertItem("Show &fluxes", this, SLOT(toggleShowFluxes()));
 
  view->setItemChecked(fluxes_id, FALSE);
 
  cell_walls_id = view->insertItem("Show transporters", this, SLOT(toggleShowWalls()));
 
	view->setItemChecked(cell_walls_id, FALSE);
 
	apoplasts_id = view->insertItem("Show apoplasts", this, SLOT(toggleShowApoplasts()));
 
  view->setItemChecked(apoplasts_id, FALSE);
 
 	view->insertSeparator();
 
	  only_boundary_id = view->insertItem("Show only leaf &boundary", this, SLOT(toggleLeafBoundary()));
 
  //only_boundary_id = view->insertItem("Show only leaf &boundary", 0,0);
 
	view->insertSeparator();
 
	movie_frames_id = view->insertItem("Start saving movie &frames", this, SLOT(toggleMovieFrames()));
 
  view->setItemChecked(movie_frames_id, par.movie);
 
	
 
	view->setItemChecked(only_boundary_id, FALSE);
 
  menu->insertItem("&View", view);
 
  
 
  
 
  options = new Q3PopupMenu( menu );
 
  /* dbf_id = options->insertItem("Double buffer", this, SLOT(toggleDoubleBuffer()));
 
     options->setItemChecked(dbf_id, TRUE);*/
 
  dyn_cells_id = options->insertItem("Cell growth", this, SLOT(toggleDynCells()));
 
  options->setItemChecked(dyn_cells_id, true);
 

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

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

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

	
 
  printer = 0;
 

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

	
 
}
 

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

	
 

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

	
 
  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() {
 
  
 
  ParameterDialog *pardial = new ParameterDialog(this, "stridediag");
 

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

	
 
}
 

	
 
void Main::savePars() {
 
  
 
  // bool timer_active;
 
  /* if (timer_active=timer->isActive())
 
@@ -1248,262 +1250,304 @@ void Main::toggleHideCells(void) {
 
  }
 

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

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

	
 

	
 
  void Main::print()
 
  {
 
    if ( !printer ) printer = new QPrinter;
 
    
 
    if ( printer->setup(this) ) {
 
    
 
      //    extern Mesh mesh;
 
      Vector bbll,bbur;
 
      mesh.BoundingBox(bbll,bbur);
 
      cerr << "bbll = " << bbll << endl;
 
      cerr << "bbur = " << bbur << endl;
 
      double cw = (bbur.x - bbll.x);
 
      double ch = (bbur.y - bbll.y);
 
      QPainter pp(printer);
 
      QRect vp=pp.viewport();
 
      cerr << "Paper width = " << vp.width() << " x " << vp.height() << endl;
 
    
 

	
 
      // 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) {
 
  
 
    static int t=0;
 
    TimeStep();
 
    t++;
 
    // check number of timesteps
 
    if (t==par.nit) {
 
      emit SimulationDone();
 
    }
 
  }
 

	
 

	
 
  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\n";
 
      //    extern Mesh mesh;
 
      mesh.Clear();
 
      Init();
 
		Plot();
 
		editor->FullRedraw();
 
    } 
 
    //startSimulation();
 
  }
 

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

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

	
 
       }*/
 

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

	
 
       }*/
 

	
 

	
 
void Main::FitCanvasToWindow(void) {
 
  
 
  double scale_factor_x = (double)editor->width()/(double)canvas.width();
 
  double scale_factor_y = (double)editor->height()/(double)canvas.height();
 
  double scale_factor = scale_factor_x > scale_factor_y ? scale_factor_x : scale_factor_y;
 
  QMatrix m = editor->matrix();
 
  
 
  cerr << "editor->width() = " << editor->width() << endl;
 
  cerr << "editor->height() = " << editor->height() << endl;
 
  
 
  cerr << "scale_factor = " << scale_factor << endl;
 
  cerr << "scale_factor_x = " << scale_factor_x << endl;
 
  cerr << "scale_factor_y = " << scale_factor_y << endl;
 
  m.scale( scale_factor, scale_factor );
 
  editor->setMatrix( m );
 
  editor->show();
 
}
 

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

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

	
 
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) {
 
  
 
  mesh.SettoInitVals();
 
	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();
 
 
 
	Plot();
 
	
 
	editor->FullRedraw();
 
	
 
  //  repaint();
 
}
 

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

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

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

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

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

	
 
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) {
 

	
 
  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
 
@@ -37,250 +37,253 @@
 
//Added by qt3to4:
 
#include <QMouseEvent>
 
#include <vector>
 
#include "simitembase.h"
 
#include "mainbase.h"
 
#include "cellitem.h"
 
#include "infobar.h"
 

	
 
#include "nodeitem.h"
 
#include "cell.h"
 

	
 
#ifdef HAVE_QWT
 
#include "data_plot.h"
 
#endif
 

	
 
#include <libxml/xpath.h>
 
#include <libxml/xmlreader.h>
 

	
 
#if defined(Q_OS_MAC)
 
  #define PREFIX "cmd"
 
#else
 
  #define PREFIX "crtl"
 
#endif
 

	
 

	
 
class QFile;
 
class QDir;
 
class ModelCatalogue;
 
class InfoBar;
 

	
 
class FigureEditor : public QGraphicsView {
 
  Q_OBJECT
 

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

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

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

	
 
 signals:
 
  void status(const QString&);
 
  void MousePressed(void);
 
  void MouseReleased(void);
 
 protected:
 
  Mesh &mesh;
 

	
 
 private:
 
  //NodeItem* moving;
 
  SimItemBase *moving;
 
  QPointF moving_start;
 
    
 
  QGraphicsLineItem *intersection_line;
 
  bool rotation_mode;
 
  bool insert_mode;
 
  double rot_angle;
 
};
 

	
 
class Main : public Q3MainWindow, public MainBase {
 
  Q_OBJECT
 
	friend class ModelCatalogue; // needs to populate menu item models
 
    public:
 
  Main(QGraphicsScene&, Mesh&, QWidget* parent=0, const char* name=0, Qt::WFlags f=0);
 
  ~Main();
 
  virtual bool ShowCentersP(void) {return view->isItemChecked(com_id);}
 
  virtual bool ShowMeshP(void) {return view->isItemChecked(mesh_id);}
 
  virtual bool ShowBorderCellsP(void) {return view->isItemChecked(border_id);}
 
  virtual bool PausedP(void) {return run->isItemChecked(paused_id);}
 
  virtual bool ShowNodeNumbersP(void) {return view->isItemChecked(node_number_id);}
 
  virtual bool ShowCellNumbersP(void) {return view->isItemChecked(cell_number_id);}
 
  virtual bool ShowCellAxesP(void) {return view->isItemChecked(cell_axes_id);}
 
  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) {
 
    return flux_arrow_size;
 
  }
 
  //void Save(const char *fname, const char *format);
 
  /*void StartGifAnim(QString fname);
 
    void SaveToGifAnim(void);
 
    void EndGifAnim(void);*/
 
    
 
  void FitCanvasToWindow();
 
  void FitLeafToCanvas(void);
 

	
 

	
 
  public slots:
 

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

	
 
  void EnterRotationMode(void) {
 

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

	
 
      // Exit rotation mode if mouse is clicked
 
      connect(editor, SIGNAL(MousePressed()), this, SLOT(ExitRotationMode()));
 
    }
 
  
 
  }
 
  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);
 
   
 
  private slots:
 
  void aboutQt();
 
  void newView();
 
  void EditParameters();
 
  void readStateXML();
 
  int readStateXML(const char *filename, bool geometry = true, bool pars=true, bool simtime = true);
 
  void readNextStateXML();
 
  void readPrevStateXML();
 
  void readFirstStateXML();
 
  void readLastStateXML();
 
  void saveStateXML();
 
  void snapshot();
 
  void savePars();
 
  void readPars();
 
  void clear();
 
  void init();
 
  virtual void CutSAM() { MainBase::CutSAM(); Refresh();}
 
/*   void cellmonitor() { */
 
/*     PlotDialog *plot = new PlotDialog(this); */
 
/*     cerr << "Attempting to launch a cell monitor\n"; */
 
/*   } */
 
  
 
  //void addPolygon();
 
  //void addLine();
 

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

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

	
 
  QPrinter* printer;
 
  const QDir *working_dir;
 
  QString currentFile;
 
  //  toggle item states 
 
  int dbf_id; // options->Double Buffer
 
  int com_id; // view->Show centers
 
  int mesh_id; // view->Show mesh
 
  int node_number_id; // view->Show Node numbers
 
  int cell_number_id; // view->Show Cell numbers
 
  int border_id; // view->Show border cells
 
  int paused_id; // run->Simulation paused
 
  int cell_axes_id; // view->Show cell axes
 
  int cell_strain_id; // view->Show cell strain
 
  int only_boundary_id; // view ->Show only leaf boundary
 
  int cell_walls_id; // view -> Show transporters
 
	int apoplasts_id; // view -> Show apoplasts
 
  int tooltips_id; // help -> Show Cell Info
 
  int hide_cells_id; // view->Hide Cells
 
  double flux_arrow_size;
 
  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
src/mesh.cpp
Show inline comments
 
@@ -1699,580 +1699,594 @@ Node* Mesh::findNextBoundaryNode(Node* b
 
      #endif
 

	
 
      break;
 
    }
 
  }
 

	
 
  #ifdef QDEBUG  
 
  if (!found_next_boundary_node) {
 
    qDebug() << "OOPS! Didn't find the next boundrary node!" << endl;
 
  }
 
  #endif
 

	
 
  return next_boundary_node;
 
}
 

	
 

	
 
void Mesh::CleanUpWalls(void) {
 
  for (list<Wall *>::iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 

	
 
    if ((*w)->DeadP()) {
 
      delete *w;
 
      (*w)=0;      
 
    }
 
  }
 
  walls.remove(0);
 
}
 

	
 
void Mesh::Rotate(double angle, Vector center) {
 

	
 
  // Rotate the mesh over the angle "angle", relative to center point "center".
 

	
 
  Matrix rotmat;
 

	
 
  rotmat.Rot2D(angle);
 
  
 
  for (vector<Node *>::iterator n=nodes.begin();
 
       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:
 
	SolveMesh(Mesh *m_) {
 
    
 
		m = m_;
 
				
 
		kmax=0;
 
		kount=0;
 
		xp=0; yp=0; dxsav=0;
 
		
 
    
 
	}
 
  
 
protected:
 
  virtual void derivs(double x, double *y, double *dydx) {
 
      
 
    // set mesh with new values given by ODESolver
 
    // (we must do this, because only mesh knows the connections
 
    // between the variables)
 
    
 
    m->setValues(x,y);
 
    m->Derivatives(dydx);
 
    
 
    /*static int c=0;
 
       QString fname("derivs%1.dat");
 
       
 
       ofstream of(fname.arg(++c).ascii());
 
       
 
       for (int i=0;i<m->NEqs();i++) {
 
       of << x << " " << dxdy[i] << endl;
 
       }
 
       of.close();
 
    */
 
    
 
    //cerr << "Calculated derivatives at " << x << "\n";    
 
  }
 
  
 
private:
 
  Mesh *m;
 
  int kmax,kount;
 
  double *xp,**yp,dxsav;
 
  bool monitor_window;
 
};
 
  
 

	
 

	
 
void Mesh::ReactDiffuse(double delta_t) {
 
  
 
  // Set Lengths of Walls
 
  for_each ( walls.begin(), walls.end(), 
 
	     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();
 
    
 
  }
 

	
 
  return moment / (double)cells.size();
 
}
 

	
 
/*! This member function deletes all walls connected to two dead cells from the mesh.
 
  It should be called before the Cells are actually removed.
 
  If the cell is connect to one dead cell only, that reference is substituted for a reference 
 
  to the boundary polygon.
 
*/
 
void Mesh::DeleteLooseWalls(void) {
 

	
 
  list<Wall *>::iterator w=walls.begin();
 
  
 
  while (w!=walls.end()) {
 
    
 
    // if both cells of the wall are dead, remove the wall
 
    if ((*w)->C1()->DeadP() || (*w)->C2()->DeadP()) {
 
      if ((*w)->C1()->DeadP() && (*w)->C2()->DeadP()) {
 
	delete *w;
 
	w=walls.erase(w);
 
      } 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;
 
  
 
  Cell::SetMagnification(factor); // smallest of scale_x and scale_y
 
  
 
  double offset_x = (width/Cell::Magnification()-(bbur.x-bbll.x))/2.;  
 
  double offset_y = (height/Cell::Magnification()-(bbur.y-bbll.y))/2.;
 
  
 
  Cell::setOffset(offset_x, offset_y);
 
  
 
  }*/
 

	
 

	
 
void Mesh::CleanChemicals(const vector<double> &clean_chem, const vector<double> &clean_transporters) {
 
  
 
  if (clean_chem.size()!=(unsigned)Cell::NChem() || clean_transporters.size()!=(unsigned)Cell::NChem()) {
 
    throw "Run time error in Mesh::CleanChemicals: size of clean_chem and clean_transporters 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::CleanChemicals(const vector<double> &clean_chem) {
 
	
 
	if (clean_chem.size()!=(unsigned)Cell::NChem()) {
 
		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]);
 
    }
 
  }
 
  
 
	
 
	// 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++) {
 
    
 
    for (int i=0;i<Cell::NChem();i++) {
 
      (*c)->SetChemical(i,max_chem[i]*RANDOM());
 
    }
 
    (*c)->SetNewChemToChem();
 

	
 
  }
 

	
 
  // 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
 
  // this by removing superfluous (empty) equations.
 
  int neqs = 2 * nwalls * nchems + ncells * nchems;
 
  
 
  //static double *derivs = 0; 
 
  // derivs is allocated by RungeKutta class.
 

	
 
  for (int i=0;i<neqs;i++) { derivs[i]=0.;}
 
  
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  int i=0;
 

	
 
  for (vector<Cell *>::iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
    //(*cr)(*c, &(derivs[i]));
 
	  plugin->CellDynamics(*c, &(derivs[i]));
 
	  i+=nchems;
 
  }
 
	
 
  for (list<Wall *>::iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 
   // (*wr)(*w, &(derivs[i]), &(derivs[i+nchems]));
 
	  plugin->WallDynamics(*w,  &(derivs[i]), &(derivs[i+nchems]));
 
    // Transport function adds to derivatives of cell chemicals
 
	  double *dchem_c1 = &(derivs[(*w)->c1->Index() * nchems]);
 
	  double *dchem_c2 = &(derivs[(*w)->c2->Index() * nchems]);
 
	  //plugin->CelltoCellTransport(*w, &(derivs[(*w)->c1->Index() * nchems]),
 
							//	  &(derivs[(*w)->c2->Index() * nchems]));
 
	  // quick fix: dummy values to prevent end user from writing into outer space and causing a crash :-)
 
	  // start here if you want to implement chemical input/output into environment over boundaries
 
	  double dummy1, dummy2;
 
	  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;
 
  
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  int i=0;
 
  static int emit_count=0;
 
  const int stride = 100;
 
  for (vector<Cell *>::iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*c)->SetChemical(ch, y[i+ch]);
 
    }
 
    if ( !(emit_count%stride)) {
 
      (*c)->EmitValues(x);
 
    }
 
    i+=nchems;
 
  }
 
  
 
  for (list<Wall *>::iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 
    
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*w)->setTransporters1(ch,y[i+ch]);
 
    }
 
    i+=nchems;
 
    
 
    for (int ch=0;ch<nchems;ch++) {
 
      (*w)->setTransporters2(ch,y[i+ch]);
 
    }
 
    i+=nchems;
 

	
 
  }
 

	
 
  emit_count++;
 
}
 

	
 
double *Mesh::getValues(int *neqs) {
 
  
 
  int nwalls = walls.size();
 
  int ncells = cells.size();
 
  int nchems = Cell::NChem();
 
  
 
  // two eqs per chemical for each wall, 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.
 
  (*neqs) = 2 * nwalls * nchems + ncells * nchems;
 
  
 
  // Layout of derivatives: cells [ chem1 ... chem n]  walls [ [ w1(chem 1) ... w1(chem n) ] [ w2(chem 1) ... w2(chem n) ] ]
 

	
 
  static double *values = 0;
 
  if (values!=0) { delete[] values; }
 
  
 
  values = new double[*neqs];
 
  
 
  int i=0;
 
  for (vector<Cell *>::iterator c=cells.begin();
 
       c!=cells.end();
 
       c++) {
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*c)->Chemical(ch);
 
    }
 
    i+=nchems;
 
  }
 
  
 
  for (list<Wall *>::iterator w=walls.begin();
 
       w!=walls.end();
 
       w++) {
 
    
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*w)->Transporters1(ch);
 
    }
 
    i+=nchems;
 
    
 
    for (int ch=0;ch<nchems;ch++) {
 
      values[i+ch]=(*w)->Transporters2(ch);
 
    }
 
    i+=nchems;
 

	
 
  }
 

	
 
  return values;
 
}
 

	
 
void Mesh::DrawNodes(QGraphicsScene *c) const {
 
  
 
  for (vector<Node *>::const_iterator n=nodes.begin();
 
       n!=nodes.end();
 
       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++) {
 
    sum_prot += (*w)->Transporters1(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, clean_transporters);
 
	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) {
 
	QVector<qreal> angles;
 
	for (vector<Node *>::const_iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		if ((*n)->Value()>2 && !(*n)->BoundaryP() ) {
 
			angles+=(*n)->NeighbourAngles();
 
		}
 
	}
 
	return angles;
 
}
 

	
 
QVector< QPair<qreal,int> > Mesh::VertexAnglesValues(void) {
 

	
 
	QVector< QPair<qreal,int> > anglesvalues;
 
	for (vector<Node *>::const_iterator n=nodes.begin();
 
		 n!=nodes.end();
 
		 n++) {
 
		if ((*n)->Value()>2 && !(*n)->BoundaryP() ) {
 
			
 
			QVector<qreal> angles = (*n)->NeighbourAngles();
 
			int value_vertex = angles.size();
 
			for (QVector<qreal>::ConstIterator i=angles.begin();
 
				 i!=angles.end();
 
				 i++) {
 
				
 
				anglesvalues += QPair< qreal, int > (*i, value_vertex);
 
			}
 
		}
 
	}
 
	return anglesvalues;
 
}
 

	
 
void Mesh::Clean(void) {
 
        #ifdef QDEBUG
 
        qDebug() << "Freeing nodes" << endl;
 
	#endif
 
	for (vector<Node *>::iterator i=nodes.begin();
 
		 i!=nodes.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	nodes.clear();
 
	Node::nnodes=0;
 
	
 
        #ifdef QDEBUG
 
        qDebug() << "Freeing node sets" << endl;
 
        #endif
 
	for (vector<NodeSet *>::iterator i=node_sets.begin();
 
		 i!=node_sets.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	node_sets.clear();
 

	
 

	
 
        #ifdef QDEBUG
 
        qDebug() << "Freeing cells" << endl;
 
        #endif	
 
	//CellsStaticDatamembers *old_static_data_mem = Cell::GetStaticDataMemberPointer();
 
	for (vector<Cell *>::iterator i=cells.begin();
 
		 i!=cells.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	//Cell::static_data_members = old_static_data_mem;
 
	
 
	cells.clear();
 
	Cell::NCells()=0;
 
	
 
	delete boundary_polygon; // (already deleted during cleaning of cells?)
 

	
 
        #ifdef QDEBUG
 
        qDebug() << "Freeing walls" << endl;
 
        #endif
 
	for (list<Wall *>::iterator i=walls.begin();
 
		 i!=walls.end();
 
		 i++) {
 
		delete *i;
 
	}
 
	walls.clear();
 
	Wall::nwalls=0;
 
	
 
	node_insertion_queue.clear();
 
	shuffled_nodes.clear();
 
	shuffled_cells.clear();
 
	time = 0.0;
 
}
 

	
 
void Mesh::StandardInit(void) {
 

	
 
	boundary_polygon = new BoundaryPolygon();
 
	Cell &circle=CircularCell(0,0,10,10);
 
	
 
	circle.SetTargetArea(circle.CalcArea());
 
	circle.SetTargetLength(par.target_length);
 
	circle.SetLambdaLength(par.lambda_celllength);
 
	SetBaseArea();
 
	// clean up chemicals 
 
	for (int c=0; c<Cell::NChem(); c++) {
 
		circle.SetChemical(c, 0.);
 
	}
 
}
 

	
 

	
src/mesh.h
Show inline comments
 
@@ -224,257 +224,258 @@ public:
 
			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();
 
			 i!=cells.end();
 
			 i++) {
 
			f(**i,g,h); 
 
		}
 
	}
 
	
 
	void DoCellHouseKeeping(void) {
 
		vector<Cell *> current_cells = cells;
 
		for (vector<Cell *>::iterator i = current_cells.begin();
 
			 i != current_cells.end();
 
			 i ++) {
 
			plugin->CellHouseKeeping(*i);
 
			
 
			// Call functions of Cell that cannot be called from CellBase, including Division
 
			if ((*i)->flag_for_divide) {
 
				if ((*i)->division_axis) {
 
					(*i)->DivideOverAxis(*(*i)->division_axis);
 
					delete (*i)->division_axis;
 
					(*i)->division_axis = 0;
 
				} else {
 
					(*i)->Divide();
 
				}
 
				(*i)->flag_for_divide=false;
 
			}
 
		}
 
	}
 
/*	template<class Op1, class Cont> void ExtractFromCells(Op1 f, Cont res) {
 
		for (vector<Cell>::iterator i=cells.begin();
 
			 i!=cells.end();
 
			 i++) {
 
			*(res++) = ( f(*i) );
 
		}
 
	}*/
 
	
 
	// Apply "f" to cell i
 
	// i.e. this is an adapter which allows you to call a function
 
	// operating on Cell on its numeric index index
 
	template<class Op> void cell_index_adapter(Op f,int i) {
 
		f(cells[i]);
 
	}
 
	
 
	double DisplaceNodes(void);
 
	
 
	void BoundingBox(Vector &LowerLeft, Vector &UpperRight);
 
	int NEqs(void) {     int nwalls = walls.size();
 
		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;
 
		
 
		return neqs;
 
	}
 
	void IncreaseCellCapacityIfNecessary(void) {
 
		
 
		return;
 
		// cerr << "Entering Mesh::IncreaseCellCapacityIfNecessary \n";
 
		// make sure we always have enough space 
 
		// to have each cell divide at least once
 
		//
 
		// Note that we must do this, because Cell::Divide pushes a new Cell
 
		// onto Mesh::cells. As a result, Mesh::cells might be relocated 
 
		// if we are _within_ a Cell object: i.e. pointer "this" will be changed!!
 
		// 
 
		// An alternative solution could be to make "Mesh::cells" a list,
 
		// but this won't work because we need random access for 
 
		// the Monte Carlo algorithm.
 
		
 
		if (2*cells.size()>cells.capacity()) {
 
			cerr << "Increasing capacity to "  << 2*cells.capacity() << endl;
 
			cerr << "Current capacity is " << cells.capacity() << endl;
 
			cells.reserve(cells.capacity()*2);
 
		}
 
	}
 
	
 
	void ReserveMoreCells(int n) {
 
		if (nodes.size()+n>nodes.capacity()) {
 
			nodes.reserve(size()+n);
 
		}
 
	}
 
	double Area(void);
 
	double MeanArea(void) {
 
		double sum=0.;
 
		for (vector<Cell *>::const_iterator i=cells.begin();
 
			 i!=cells.end();
 
			 i++) {
 
			sum+=(*i)->Area();
 
		}
 
		return sum/(double)NCells();
 
	}
 
	
 
	void SetBaseArea(void);
 
	int NCells(void) const {
 
		return cells.size();
 
	}
 
	inline int NNodes(void) const {
 
		return nodes.size();
 
	}
 
	void PrintQueue(ostream &os) {
 
		while (!node_insertion_queue.empty()) {
 
			os << node_insertion_queue.front() << endl;
 
			node_insertion_queue.pop();
 
		}
 
		//copy (node_insertion_queue.begin(),node_insertion_queue.end(),ostream_iterator<Edge>(cerr, " "));
 
	}
 
	
 
	void InsertNodes(void) {
 
		// insert the nodes in the insertion queue
 
		while (!node_insertion_queue.empty()) {
 
			
 
			//cerr << node_insertion_queue.front() << endl;
 
			InsertNode(node_insertion_queue.front());
 
			node_insertion_queue.pop();
 
		}
 
		
 
	}
 
	
 
	void Clear(); 
 
	
 
	//  template<class ReactFunction> ReactDiffuse(const double D, ReactFunction& react) {
 
	void ReactDiffuse( double delta_t = 1 );
 
	//void Diffuse(const double D);
 
	double SumChemical(int ch);
 
	void SetChemical(int ch, double value) {
 
		for (vector<Cell *>::iterator c=cells.begin();
 
			 c!=cells.end();
 
			 c++) {
 
			(*c)->chem[ch]=value;
 
		}
 
	}
 
	
 
	// used for interacing with ODE-solvers (e.g. NRCRungeKutta)
 
	void setValues(double x, double *y);
 
	double *getValues(int *neqs);
 
	void Derivatives(double *derivs);
 
#ifdef QTGRAPHICS
 
	inline void DrawBoundary(QGraphicsScene *c) {
 
		boundary_polygon->Draw(c);
 
	}
 
	void DrawNodes(QGraphicsScene *c) const;
 
	
 
#endif
 
	double max_chem;
 
	
 
	void XMLSave(const char *docname, xmlNode *settings=0) const;
 
	void XMLRead(const char *docname, xmlNode **settings=0, bool geometry = true, bool pars = true, bool simtime = true);
 
	void XMLReadPars(const xmlNode * root_node);
 
	void XMLReadGeometry(const xmlNode *root_node);
 
	void XMLReadSimtime(const xmlNode *root_node);
 
	void XMLReadNodes(xmlNode *cur);
 
	void XMLReadCells(xmlNode *cur);
 
	void XMLParseTree(const xmlNode * root_node);
 
	void XMLReadWalls(xmlNode *cur, vector<Wall *> *tmp_cells);
 
	void XMLReadWallsToCells(xmlNode *root, vector<Wall *> *tmp_walls);
 
	void XMLReadNodeSets(xmlNode *root);
 
	void XMLReadNodeSetsToNodes(xmlNode *root);
 
	void PerturbChem(int chemnum, double range);
 
	void CleanUpCellNodeLists(void);
 
	void CleanUpWalls(void);
 
	void CutAwayBelowLine( Vector startpoint, Vector endpoint );
 
	void CutAwaySAM(void);
 
	void RepairBoundaryPolygon(void);
 
	void Rotate(double angle, Vector center);
 
	void PrintWallList( void );
 
	void TestIllegalWalls(void);
 
	Vector FirstConcMoment(int chem);
 
	inline Vector Centroid(void) {
 
		return boundary_polygon->Centroid();
 
	}
 
	
 
	inline Vector Offset(void) {
 
		return boundary_polygon->Offset();
 
	}
 
	
 
	inline double Factor(void) {
 
		return boundary_polygon->Factor();
 
	}
 
	
 
	void DeleteLooseWalls(void);
 
	void FitLeafToCanvas(double width, double height);
 
	void AddNodeSet(NodeSet *node_set) {
 
		node_sets.push_back(node_set);
 
	}
 
	
 
	void CleanChemicals(const vector<double> &clean_chem, const vector<double> &clean_transporters);
 
	void CleanChemicals(const vector<double> &clean_chem);
 
	void CleanTransporters(const vector<double> &clean_transporters);
 
	void RandomizeChemicals(const vector<double> &max_chem, const vector<double> &max_transporters);
 
	inline double getTime(void) const { return time; }
 
	string getTimeHours(void) const; 
 
	inline void setTime(double t) { time = t; }
 
	double CalcProtCellsWalls(int ch) const;  
 
	void SettoInitVals(void);
 
	QVector<qreal> VertexAngles(void);
 
	QVector< QPair<qreal,int> > VertexAnglesValues(void);
 
	void SetSimPlugin(SimPluginInterface *new_plugin) {
 
		/* if (plugin) 
 
			delete plugin;*/
 
		plugin=new_plugin;
 
	}
 
	QString ModelID(void) { return plugin?plugin->ModelID():QString("undefined"); }
 
	void StandardInit(void);	
 

	
 
	Node* findNextBoundaryNode(Node*);
 

	
 
private:
 
	
 
	// Data members
 
	vector<Cell *> cells;
 
	vector<Node *> nodes;
 
	list<Wall *> walls; // we need to erase elements from this container frequently, hence a list.
 
public:
 
	vector<NodeSet *> node_sets;
 
private:
 
	vector<Node *> shuffled_nodes;
 
	vector<Cell *> shuffled_cells;
 
	unique_queue<Edge> node_insertion_queue;
 
	BoundaryPolygon *boundary_polygon;
 
	double time;
 
	SimPluginInterface *plugin;
 
	
 
	// Private member functions
 
	void AddNodeToCell(Cell *c, Node *n, Node *nb1 , Node *nb2);
 
	void AddNodeToCellAtIndex(Cell *c, Node *n, Node *nb1 , Node *nb2, list<Node *>::iterator ins_pos);
 
	void InsertNode(Edge &e);
 
	inline Node *AddNode(Node *n) {
 
		nodes.push_back(n);
 
		shuffled_nodes.push_back(n);
 
		n->m=this;
 
		return n;
 
	}
 
	
 
	inline Cell *AddCell(Cell *c) {
 
		cells.push_back(c);
 
		shuffled_cells.push_back(c);
 
		//cerr << "Shuffled cell indices:  ";
 
		/*copy(shuffled_cells.begin(),shuffled_cells.end(),ostream_iterator<int>(cerr," "));
 
		 cerr << endl;*/
 
		c->m=this;
 
		return c;
 
	}
 
	
 
	//int Delaunay(void);
 
	void CircumCircle(double x1,double y1,double x2,double y2,double x3,double y3,
 
					  double *xc,double *yc,double *r);
 
	
 
	
 
	// void RenumberCells(void);
 
	
 
};
 
#endif
0 comments (0 inline, 0 general)