Changeset - d4a19fde7f8d
[Not reviewed]
default
0 7 0
Michael Guravage - 15 years ago 2010-06-23 09:32:29
michael.guravage@cwi.nl
Corrected several small problems with qDebug. See ChangeLogs for details.

--
user: Michael Guravage <michael.guravage@cwi.nl>
branch 'default'
changed doc/installation.pdf
changed doc/installation.rst
changed src/ChangeLog
changed src/canvas.cpp
changed src/mesh.cpp
changed src/random.cpp
changed src/wall.cpp
7 files changed with 44 insertions and 35 deletions:
0 comments (0 inline, 0 general)
doc/installation.pdf
Show inline comments
 
%PDF-1.3
 
%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
 
% 'BasicFonts': class PDFDictionary 
 
1 0 obj
 
% The standard fonts dictionary
 
<< /F1 2 0 R
 
 /F2 3 0 R
 
 /F3 5 0 R >>
 
endobj
 
% 'F1': class PDFType1Font 
 
2 0 obj
 
% Font Helvetica
 
<< /BaseFont /Helvetica
 
 /Encoding /WinAnsiEncoding
 
 /Name /F1
 
 /Subtype /Type1
 
 /Type /Font >>
 
endobj
 
% 'F2': class PDFType1Font 
 
3 0 obj
 
% Font Helvetica-Bold
 
<< /BaseFont /Helvetica-Bold
 
 /Encoding /WinAnsiEncoding
 
 /Name /F2
 
 /Subtype /Type1
 
 /Type /Font >>
 
endobj
 
% 'Annot.NUMBER1': class PDFDictionary 
 
4 0 obj
 
<< /A << /S /URI
 
 /Type /Action
 
 /URI (http://qt.nokia.com/downloads/downloads#lgpl/) >>
 
 /Border [ 0
 
 0
 
 0 ]
 
 /Rect [ 332.4149
 
 /Rect [ 367.7599
 
 657.5936
 
 411.372
 
 447.6713
 
 669.5936 ]
 
 /Subtype /Link
 
 /Type /Annot >>
 
endobj
 
% 'F3': class PDFType1Font 
 
5 0 obj
 
% Font Courier
 
<< /BaseFont /Courier
 
 /Encoding /WinAnsiEncoding
 
 /Name /F3
 
 /Subtype /Type1
 
 /Type /Font >>
 
endobj
 
% 'Page1': class PDFPage 
 
6 0 obj
 
% Page dictionary
 
<< /Annots [ 4 0 R ]
 
 /Contents 17 0 R
 
 /MediaBox [ 0
 
 0
 
 595.2756
 
 841.8898 ]
 
 /Parent 16 0 R
 
 /Resources << /Font 1 0 R
 
 /ProcSet [ /PDF
 
 /Text
 
 /ImageB
 
 /ImageC
 
 /ImageI ] >>
 
 /Rotate 0
 
 /Trans <<  >>
 
 /Type /Page >>
 
endobj
 
% 'Page2': class PDFPage 
 
7 0 obj
 
% Page dictionary
 
<< /Contents 18 0 R
 
 /MediaBox [ 0
 
 0
 
 595.2756
 
 841.8898 ]
 
 /Parent 16 0 R
 
 /Resources << /Font 1 0 R
 
 /ProcSet [ /PDF
 
 /Text
 
 /ImageB
 
 /ImageC
 
 /ImageI ] >>
 
 /Rotate 0
 
 /Trans <<  >>
 
 /Type /Page >>
 
endobj
 
% 'R8': class PDFCatalog 
 
8 0 obj
 
% Document Root
 
<< /Outlines 10 0 R
 
 /PageLabels 19 0 R
 
 /PageMode /UseNone
 
 /Pages 16 0 R
 
 /Type /Catalog >>
 
endobj
 
% 'R9': class PDFInfo 
 
9 0 obj
 
<< /Author ()
 
 /CreationDate (D:20100622164642-01'00')
 
 /CreationDate (D:20100623080642-01'00')
 
 /Keywords ()
 
 /Producer (ReportLab http://www.reportlab.com)
 
 /Subject (\(unspecified\))
 
 /Title (Installation Instructions) >>
 
endobj
 
% 'R10': class PDFOutlines 
 
10 0 obj
 
<< /Count 5
 
 /First 11 0 R
 
 /Last 15 0 R
 
 /Type /Outlines >>
 
endobj
 
% 'Outline.0': class OutlineEntryObject 
 
11 0 obj
 
<< /Dest [ 6 0 R
 
 /XYZ
 
 62.69291
 
 717.0236
 
 0 ]
 
 /Next 12 0 R
 
 /Parent 10 0 R
 
 /Title (Requirements) >>
 
endobj
 
% 'Outline.1': class OutlineEntryObject 
 
12 0 obj
 
<< /Dest [ 6 0 R
 
 /XYZ
 
 62.69291
 
 618.0236
 
 0 ]
 
 /Next 13 0 R
 
 /Parent 10 0 R
 
 /Prev 11 0 R
 
 /Title (All Platforms) >>
 
endobj
 
% 'Outline.2': class OutlineEntryObject 
 
13 0 obj
 
<< /Dest [ 6 0 R
 
 /XYZ
 
 62.69291
 
 507.0236
 
 0 ]
 
 /Next 14 0 R
 
 /Parent 10 0 R
 
 /Prev 12 0 R
 
 /Title (Linux) >>
 
endobj
 
% 'Outline.3': class OutlineEntryObject 
 
14 0 obj
 
<< /Dest [ 6 0 R
 
 /XYZ
 
 62.69291
 
 260.4236
 
 0 ]
 
 /Next 15 0 R
 
 /Parent 10 0 R
 
 /Prev 13 0 R
 
 /Title (Windows) >>
 
endobj
 
% 'Outline.4': class OutlineEntryObject 
 
15 0 obj
 
<< /Dest [ 7 0 R
 
 /XYZ
 
 62.69291
 
 753.0236
 
 0 ]
 
 /Parent 10 0 R
 
 /Prev 14 0 R
 
 /Title (MacOS) >>
 
endobj
 
% 'R16': class PDFPages 
 
16 0 obj
 
% page tree
 
<< /Count 2
 
 /Kids [ 6 0 R
 
 7 0 R ]
 
 /Type /Pages >>
 
endobj
 
% 'R17': class PDFStream 
 
17 0 obj
 
% page stream
 
<< /Length 5681 >>
 
<< /Length 5687 >>
 
stream
 
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
 
q
 
1 0 0 1 62.69291 729.0236 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 9.64 Tm /F2 20 Tf 24 TL 122.1449 0 Td (Installation Instructions) Tj T* -122.1449 0 Td ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 696.0236 cm
 
q
 
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Requirements) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 630.0236 cm
 
q
 
BT 1 0 0 1 0 52.82 Tm .076098 Tw 12 TL /F1 10 Tf 0 0 0 rg (The Virtual Leaf is written with the QT Cross platform application and UI framework, and can run on Linux,) Tj T* 0 Tw 1.85686 Tw (Apple Macintosh and Windows machines. To compile the Virtual Leaf you will need to install the QT) Tj T* 0 Tw .573555 Tw (software development kit which you can download from the ) Tj 0 0 .501961 rg (QT download site) Tj 0 0 0 rg (. Whether installed globally) Tj T* 0 Tw .669986 Tw (by a system administrator our locally in your own user space, make sure the QT bin directory containing) Tj T* 0 Tw (qmake is in your execution path.) Tj T* ET
 
BT 1 0 0 1 0 52.82 Tm .076098 Tw 12 TL /F1 10 Tf 0 0 0 rg (The Virtual Leaf is written with the QT Cross platform application and UI framework, and can run on Linux,) Tj T* 0 Tw 1.85686 Tw (Apple Macintosh and Windows machines. To compile the Virtual Leaf you will need to install the QT) Tj T* 0 Tw 1.050697 Tw (software development kit \(SDK\) which you can download from the ) Tj 0 0 .501961 rg (QT download site) Tj 0 0 0 rg (. Whether installed) Tj T* 0 Tw 1.357045 Tw (globally by a system administrator our locally in your own user space, make sure the QT bin directory) Tj T* 0 Tw (containing qmake is in your execution path.) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 597.0236 cm
 
q
 
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (All Platforms) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 519.0236 cm
 
q
 
BT 1 0 0 1 0 64.82 Tm 4.093984 Tw 12 TL /F1 10 Tf 0 0 0 rg (Compilation is effected with make, either the native ) Tj /F3 10 Tf (make ) Tj /F1 10 Tf (on UNIX and MAC systems or the) Tj T* 0 Tw .268735 Tw /F3 10 Tf (mingw32-make ) Tj /F1 10 Tf (distributed with the windows version of QT. In the Virtual Leaf ) Tj /F3 10 Tf (src ) Tj /F1 10 Tf (directory you will find) Tj T* 0 Tw 1.243516 Tw (a ) Tj /F3 10 Tf (Makefile) Tj /F1 10 Tf (, the root of a hierarchy of makefiles, that will guide the compilation and installation of the) Tj T* 0 Tw 4.280814 Tw (VirtualLeaf executable, its default plugins and the tutorial examples. To facilitate cross platform) Tj T* 0 Tw .276651 Tw (compatibility, the makefiles expect an environment variable named ) Tj /F3 10 Tf (MAKE ) Tj /F1 10 Tf (to name the make utility to use.) Tj T* 0 Tw (The fallback default is 'make.' Platform specific instructions follow.) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 486.0236 cm
 
q
 
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Linux) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 468.0236 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL (Prepend the QT bin directory to your path, for example:) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 434.8236 cm
 
q
 
q
 
1 0 0 1 0 0 cm
 
q
 
1 0 0 1 6.6 6.6 cm
 
q
 
.662745 .662745 .662745 RG
 
.5 w
 
.960784 .960784 .862745 rg
 
n -6 -6 468.6898 24 re B*
 
Q
 
q
 
BT 1 0 0 1 0 5.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj ( PATH=/opt/QT/qt/bin:$PATH) Tj T* ET
 
Q
 
Q
 
Q
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 402.8236 cm
 
q
 
BT 1 0 0 1 0 16.82 Tm .87686 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you wish to use some other make utility than make, instantiate an environment variable named ) Tj /F3 10 Tf (MAKE) Tj /F1 10 Tf (,) Tj T* 0 Tw (for example:) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 369.6236 cm
 
q
 
q
 
1 0 0 1 0 0 cm
 
q
 
1 0 0 1 6.6 6.6 cm
 
q
 
.662745 .662745 .662745 RG
 
.5 w
 
.960784 .960784 .862745 rg
 
n -6 -6 468.6898 24 re B*
 
Q
 
q
 
BT 1 0 0 1 0 5.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj ( export MAKE=gmake.) Tj T* ET
 
Q
 
Q
 
Q
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 349.6236 cm
 
q
 
BT 1 0 0 1 0 4.82 Tm 12 TL /F1 10 Tf 0 0 0 rg (Go to the ) Tj /F3 10 Tf (src ) Tj /F1 10 Tf (directory and invoke make, for example:) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 304.4236 cm
 
q
 
q
 
1 0 0 1 0 0 cm
 
q
 
1 0 0 1 6.6 6.6 cm
 
q
 
.662745 .662745 .662745 RG
 
.5 w
 
.960784 .960784 .862745 rg
 
n -6 -6 468.6898 36 re B*
 
Q
 
q
 
BT 1 0 0 1 0 17.71 Tm 12 TL /F3 10 Tf 0 0 0 rg (>) Tj ( cd /home/michael/VirtualLeaf/v1.0/src) Tj T* (>) Tj ( make) Tj T* ET
 
Q
 
Q
 
Q
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 272.4236 cm
 
q
 
BT 1 0 0 1 0 16.82 Tm 6.059213 Tw 12 TL /F1 10 Tf 0 0 0 rg (When complete, you will find the ) Tj /F3 10 Tf (VirtualLeaf ) Tj /F1 10 Tf (binary in ) Tj /F3 10 Tf (v1.0/bin ) Tj /F1 10 Tf (and the plugins in) Tj T* 0 Tw /F3 10 Tf (v1.0/bin/models) Tj /F1 10 Tf (.) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 239.4236 cm
 
q
 
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Windows) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 185.4236 cm
 
q
 
BT 1 0 0 1 0 40.82 Tm 2.017984 Tw 12 TL /F1 10 Tf 0 0 0 rg (For convenience sake the libiconv, libxml2 and libz header files and libraries are distributed with the) Tj T* 0 Tw .669986 Tw (Virtual Leaf code, and Virtual Leaf will compile correctly with them. If, however, you wish to compile with) Tj T* 0 Tw 3.246136 Tw (other versions of these libraries, you will need to reassign the ) Tj /F3 10 Tf (LIBZML2DIR) Tj /F1 10 Tf (, ) Tj /F3 10 Tf (LIBICONVDIR ) Tj /F1 10 Tf (and) Tj T* 0 Tw /F3 10 Tf (LIBZDIR ) Tj /F1 10 Tf (variables in all the project files.) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 143.4236 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 28.82 Tm /F1 10 Tf 12 TL .878876 Tw (After installing QT you should be able to invoke a QT command window from the start menu. This shell) Tj T* 0 Tw .456412 Tw (automatically includes the necessary QT folder in your execution PATH. Within this command window go) Tj T* 0 Tw (to the Virtual Leaf's src directory. The) Tj T* ET
 
BT 1 0 0 1 0 28.82 Tm /F1 10 Tf 12 TL .878876 Tw (After installing QT you should be able to invoke a QT command window from the start menu. This shell) Tj T* 0 Tw .25784 Tw (automatically includes the necessary QT folder in your execution PATH. Within this command window, go) Tj T* 0 Tw (to the Virtual Leaf's src directory,) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 62.69291 113.4236 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 16.82 Tm /F1 10 Tf 12 TL 1.927765 Tw (In the start menu, right click on My Computer and choose properties from the drop down list. In the) Tj T* 0 Tw (advanced tab click on environment variables. Append the QT) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 56.69291 773.1969 cm
 
q
 
BT 1 0 0 1 0 4.82 Tm 160.0749 0 Td 12 TL /F1 10 Tf 0 0 0 rg (Installation Instructions - 2010-06-22) Tj T* -160.0749 0 Td ET
 
BT 1 0 0 1 0 4.82 Tm 160.0749 0 Td 12 TL /F1 10 Tf 0 0 0 rg (Installation Instructions - 2010-06-23) Tj T* -160.0749 0 Td ET
 
Q
 
Q
 
q
 
1 0 0 1 56.69291 56.69291 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (1) Tj T* -238.1649 0 Td ET
 
Q
 
Q
 
 
 
endstream
 
 
endobj
 
% 'R18': class PDFStream 
 
18 0 obj
 
% page stream
 
<< /Length 452 >>
 
stream
 
1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
 
q
 
1 0 0 1 62.69291 732.0236 cm
 
q
 
BT 1 0 0 1 0 8.435 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (MacOS) Tj T* ET
 
Q
 
Q
 
q
 
1 0 0 1 56.69291 773.1969 cm
 
q
 
BT 1 0 0 1 0 4.82 Tm 160.0749 0 Td 12 TL /F1 10 Tf 0 0 0 rg (Installation Instructions - 2010-06-22) Tj T* -160.0749 0 Td ET
 
BT 1 0 0 1 0 4.82 Tm 160.0749 0 Td 12 TL /F1 10 Tf 0 0 0 rg (Installation Instructions - 2010-06-23) Tj T* -160.0749 0 Td ET
 
Q
 
Q
 
q
 
1 0 0 1 56.69291 56.69291 cm
 
q
 
0 0 0 rg
 
BT 1 0 0 1 0 4.82 Tm /F1 10 Tf 12 TL 238.1649 0 Td (2) Tj T* -238.1649 0 Td ET
 
Q
 
Q
 
 
 
endstream
 
 
endobj
 
% 'R19': class PDFPageLabels 
 
19 0 obj
 
% Document Root
 
<< /Nums [ 0
 
 20 0 R
 
 1
 
 21 0 R ] >>
 
endobj
 
% 'R20': class PDFPageLabel 
 
20 0 obj
 
% None
 
<< /S /D
 
 /St 1 >>
 
endobj
 
% 'R21': class PDFPageLabel 
 
21 0 obj
 
% None
 
<< /S /D
 
 /St 2 >>
 
endobj
 
xref
 
0 22
 
0000000000 65535 f
 
0000000113 00000 n
 
0000000233 00000 n
 
0000000398 00000 n
 
0000000585 00000 n
 
0000000835 00000 n
 
0000000994 00000 n
 
0000001293 00000 n
 
0000001572 00000 n
 
0000001729 00000 n
 
0000001965 00000 n
 
0000002090 00000 n
 
0000002262 00000 n
 
0000002450 00000 n
 
0000002630 00000 n
 
0000002812 00000 n
 
0000002961 00000 n
 
0000003076 00000 n
 
0000008858 00000 n
 
0000009414 00000 n
 
0000009520 00000 n
 
0000009597 00000 n
 
0000000836 00000 n
 
0000000995 00000 n
 
0000001294 00000 n
 
0000001573 00000 n
 
0000001730 00000 n
 
0000001966 00000 n
 
0000002091 00000 n
 
0000002263 00000 n
 
0000002451 00000 n
 
0000002631 00000 n
 
0000002813 00000 n
 
0000002962 00000 n
 
0000003077 00000 n
 
0000008865 00000 n
 
0000009421 00000 n
 
0000009527 00000 n
 
0000009604 00000 n
 
trailer
 
<< /ID 
 
 % ReportLab generated PDF document -- digest (http://www.reportlab.com) 
 
 [(>z\325b\242\314%\325\301\315\254\356\270\004a\252) (>z\325b\242\314%\325\301\315\254\356\270\004a\252)] 
 
 [(\030\0369*\371\251A7q\357\344\306\204\322.\262) (\030\0369*\371\251A7q\357\344\306\204\322.\262)] 
 
 
 /Info 9 0 R
 
 /Root 8 0 R
 
 /Size 22 >>
 
startxref
 
9644
 
9651
 
%%EOF
doc/installation.rst
Show inline comments
 
.. $Id$
 

	
 
.. |date| date::
 
.. |time| date:: %H:%M
 

	
 
.. header::
 
  ###Title###  -  |date|
 

	
 
.. footer::
 
  ###Page### 
 

	
 

	
 
Installation Instructions
 
=========================
 

	
 
Requirements
 
------------
 

	
 
The Virtual Leaf is written with the QT Cross platform application and
 
UI framework, and can run on Linux, Apple Macintosh and Windows
 
machines. To compile the Virtual Leaf you will need to install the QT
 
software development kit which you can download from the `QT download
 
software development kit (SDK) which you can download from the `QT download
 
site <http://qt.nokia.com/downloads/downloads#lgpl/>`_. Whether
 
installed globally by a system administrator our locally in your own
 
user space, make sure the QT bin directory containing qmake is in your
 
execution path.
 

	
 

	
 
All Platforms
 
-------------
 

	
 
Compilation is effected with make, either the native ``make`` on UNIX
 
and MAC systems or the ``mingw32-make`` distributed with the windows
 
version of QT. In the Virtual Leaf ``src`` directory you will find a
 
``Makefile``, the root of a hierarchy of makefiles, that will guide
 
the compilation and installation of the VirtualLeaf executable, its
 
default plugins and the tutorial examples.  To facilitate cross
 
platform compatibility, the makefiles expect an environment variable
 
named ``MAKE`` to name the make utility to use. The fallback default
 
is 'make.' Platform specific instructions follow.
 

	
 

	
 
Linux
 
-----
 

	
 
Prepend the QT bin directory to your path, for example::
 

	
 
 > PATH=/opt/QT/qt/bin:$PATH 
 

	
 
If you wish to use some other make utility than make, instantiate an
 
environment variable named ``MAKE``, for example::
 

	
 
 > export MAKE=gmake.
 

	
 
Go to the ``src`` directory and invoke make, for example::
 

	
 
 > cd /home/michael/VirtualLeaf/v1.0/src
 
 > make
 

	
 
When complete, you will find the ``VirtualLeaf`` binary in
 
``v1.0/bin`` and the plugins in ``v1.0/bin/models``.
 

	
 

	
 
Windows
 
-------
 

	
 
For convenience sake the libiconv, libxml2 and libz header files and
 
libraries are distributed with the Virtual Leaf code, and Virtual Leaf
 
will compile correctly with them. If, however, you wish to compile
 
with other versions of these libraries, you will need to reassign the
 
``LIBZML2DIR``, ``LIBICONVDIR`` and ``LIBZDIR`` variables in all the
 
project files.
 

	
 
After installing QT you should be able to invoke a QT command window
 
from the start menu. This shell automatically includes the necessary
 
QT folder in your execution PATH. Within this command window, go to the
 
Virtual Leaf's src directory, 
 

	
 
In the start menu, right click on My Computer and choose properties
 
from the drop down list. In the advanced tab click on environment
 
variables. Append the QT
 

	
 

	
 
MacOS
 
-----
 

	
 

	
 

	
src/ChangeLog
Show inline comments
 
2010-06-23    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* mesh.cpp (Clear): Added parentheses to qDebug statments.
 
	(TestIllegalWalls): Replaced qDebug().
 

	
 
	* canvas.cpp (mouseReleaseEvent): Replaced qDebug() with cerr since qDebug complains about *node_set.
 

	
 
	* wall.cpp (CorrectWall): Rplaced gDebug() with cerr in transform call and when printing *this.
 

	
 
2010-06-22    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* Makefile (tutorials): Add tutorials target.
 

	
 
2010-06-21    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* parameter.cpp: Added particular reassignment of datadir.
 

	
 
	* canvas.cpp (gpl): Added GPL3 License text. Display detail text only if the source text file exists.
 

	
 
2010-06-18    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* canvas.cpp (gpl): Added gpl slot to display GPL license.
 

	
 
	* VirtualLeaf.pro: Changed default LIBXML2DIR, LIBICONVDIR and LIBZDIR to corresponding distribution lib directories.
 
	* libplugin.pro: Ditto.
 

	
 
	* Makefile (clean): add if stmt not to `touch` on windows.
 

	
 
2010-06-17    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed perl references.
 
	* libplugin.pro: Ditto.
 

	
 
2010-06-15    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed xmlwritecode.cpp from SOURCES list.
 

	
 
	* xmlwrite.cpp (XMLSave): Removed references to XMLWriteLeafSourceCode and XMLWriteReactionsCode.
 
	* xmlwrite.h (XMLIO): Ditto!
 

	
 
	* mesh.cpp (findNextBoundaryNode): Initialize Node *next_boundary_node = NULL;
 

	
 
	* xmlwrite.cpp (XMLReadSimtime): Removed unused variable cur
 
	(XMLReadWalls): viz_flux need not be declared twice; default value of 0.0.
 
	(XMLReadCells): Removed unused count variable.
 
	(XMLReadSimtime): Removed unused cur variable.
 
	(XMLRead): Removed unused v_str variable.
 

	
 
	* simitembase.cpp (userMove): Use assignment merely to obviate compilation warning.
 
	(SimItemBase) Ditto.
 

	
 
	* qcanvasarrow.h (QGraphicsLineItem): Use assignment merely to obviate compilation warning.
 

	
 
	* output.cpp (OpenWriteFile): Removed unused par variable.
 

	
 
	* nodeitem.cpp (paint): Use assignment merely to obviate compilation warning.
 

	
 
	* forwardeuler.cpp (odeint): Use assignment merely to obviate compilation warning.
 

	
 
	* cell.cpp (DivideOverGivenLine): Use assignment merely to obviate compilation warning.
 

	
 
	* canvas.cpp (FigureEditor): Use assignments merely to obviate compilation errors.
 
	(mousePressEvent): Removed unused item variable.
 

	
 
	* apoplastitem.cpp
 
	(ApoplastItem): Removed unused par variable.
 
	(OnClick): Use NULL assignment merely to obviate compilation warning.
 

	
 
	* mainbase.h (MainBase): Use assignment merely to obviate compilation warning.
 

	
 
	* cellbase.h (CellsStaticDatamembers): Use assignment merely to obviate compilation warning.
 

	
 

	
 
	* cell.cpp: Wrapped diagnostic output in QDEBUG blocks.
 
	* VirtualLeaf.cpp ditto.
 
	* canvas.cpp ditto.
 
	* cell.cpp ditto.
 
	* data_plot.cpp ditto.
 
	* forwardeuler.cpp ditto.
 
	* mesh.cpp ditto.
 
	* mesh.h
 
	* random.cpp ditto.
 
	* wall.cpp ditto.
 
	* wallbase.cpp ditto.
 
	* wallitem.cpp ditto.
 

	
 

	
 
2010-06-07    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Removed explicit perl invocation to regerenerate parameter files.
 
	* libplugin.pro: ditto.
 

	
 
2010-06-03    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* pardialog.h: Added default versions of this automatically generated file.
 
	* pardialog.cpp: ditto.
 
	* parameter.h: ditto.
 
	* parameter.cpp: ditto.
 

	
 
	* VirtualLeaf.pro: delete/generate  parameter.{h,cpp}and pardialog.{h,cpp} only if perl is installed.
 
 	* libplugin.pro: dito.
 

	
 
	* Makefile: Added top-level Makefile
 

	
 
2010-05-10    <guravage@caterpie.sen.cwi.nl>
 

	
 
	* VirtualLeaf.pro: Added -fPIC option to QMAKE_CXXFLAGS.
 

	
src/canvas.cpp
Show inline comments
 
@@ -180,385 +180,385 @@ void FigureEditor::mousePressEvent(QMous
 
    intersection_line->setLine( QLineF(p,p) );
 
    intersection_line->setZValue( 100 );
 
    intersection_line->show();
 
  }
 

	
 
  for (QList<QGraphicsItem *>::Iterator it=l.begin(); it!=l.end(); ++it) {
 
#ifdef QDEBUG
 
    qDebug() << typeid(**it).name() << endl;
 
#endif
 

	
 
    if ( !strcmp(typeid(**it).name(),"8NodeItem")) {
 

	
 
      stringstream data_strstream;
 
      data_strstream << (dynamic_cast<NodeItem*>(*it))->getNode();
 
      dynamic_cast<Main *>(parent())->UserMessage(QString(data_strstream.str().c_str()));
 

	
 
      (dynamic_cast<NodeItem*>(*it))->OnClick(e->button());
 
    }
 
    else 
 
      if ( !strcmp(typeid(**it).name(),"8CellItem") ) {
 

	
 
	Cell &c=((dynamic_cast<CellItem *>(*it))->getCell());      
 
	// OnClick to be defined in end-user code
 
	c.OnClick(e);
 
      } else {
 
	if ( !strcmp(typeid(**it).name(),"8WallItem") ) {
 
	  (dynamic_cast<WallItem *>(*it))->OnClick(e);
 
	} 
 
      }
 
  }
 

	
 
  FullRedraw();
 
  moving = 0;
 
}
 

	
 
void FigureEditor::mouseMoveEvent(QMouseEvent* e)
 
{
 

	
 
  // User chooses "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
 
    QPointF rotation_midpoint = mesh.Centroid()*Cell::Factor() - Cell::Offset();
 

	
 

	
 
    // calculate rotation angle
 
    double dy = (rotation_midpoint.y() - p.y());
 
    double dx = (rotation_midpoint.x() - p.x());
 
    double new_rot_angle = atan2(dx, dy);
 
    double d_alpha = new_rot_angle - rot_angle;
 
    rot_angle = new_rot_angle;
 

	
 
    mesh.Rotate(d_alpha, ( Vector(rotation_midpoint) + Cell::Offset() ) / Cell::Factor() );
 

	
 
    dynamic_cast<Main *>(parent())->Plot(0);
 
    FullRedraw();
 
    return;
 
  }
 
 
 
  
 
  if ( moving ) {
 

	
 
    QPointF p = mapToScene(e->pos());
 
    moving->userMove(p.x() - moving_start.x(),
 
		     p.y() - moving_start.y());
 
    moving_start = p;
 
    scene()->update();
 

	
 
  }
 

	
 
  //cerr << "event";
 

	
 
  // keep track of intersection line to interactively cut a growing leaf
 

	
 
  if ( intersection_line ) {
 

	
 
    QPointF sp = intersection_line -> line().p1(); // startpoint
 
    QPointF ep = mapToScene(e->pos()); // endpoint
 
    intersection_line -> setLine( QLineF(sp, ep) ); 
 
    scene()->update();
 
    // Need this for Mac
 
    FullRedraw();
 
  }
 
}
 

	
 
//void FigureEditor::contentsMouseReleaseEvent(QMouseEvent* e)
 
void FigureEditor::mouseReleaseEvent(QMouseEvent* e)
 
{
 

	
 
  emit MouseReleased();
 
  // intersection line for leaf was finished now.
 

	
 
  if (e->button()==Qt::LeftButton) { 
 
    if (intersection_line ) {
 
#ifdef QDEBUG
 
      qDebug() << "Trying to cut leaf" << endl;
 
#endif
 
      QPointF sp = intersection_line -> line().p1(); // startpoint
 
      QPointF ep = mapToScene(e->pos());
 

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

	
 
      vector <CellItem *> intersected_cells = getIntersectedCells();
 

	
 
      // no cells selected, do nothing
 
      if (intersected_cells.size()==0) {
 
#ifdef QDEBUG
 
	qDebug() << "No cells detected :-(" << endl;
 
#endif
 
	return;
 
      }
 

	
 

	
 
      Vector startpoint = Vector(sp.x(), sp.y()) / Cell::Factor() - Cell::Offset();
 
      Vector endpoint = Vector(ep.x(), ep.y()) / Cell::Factor() - Cell::Offset();
 

	
 
      NodeSet *node_set = new NodeSet;
 

	
 
      for (vector<CellItem *>::iterator it = intersected_cells.begin(); it != intersected_cells.end(); it++) {
 
	(*it)->setBrush(QBrush("purple"));
 
	
 
	Cell &c=(*it)->getCell();
 

	
 
	// sometimes the cell hasn't properly divided yet before the
 
	// next division is called?  so check for it?  let's find a way
 
	// to do this later. Note that this functionality currently
 
	// might result in a segmentation fault for users who are
 
	// quickly dragging and releasing division lines...
 
	scene()->update();
 

	
 
#ifdef QDEBUG
 
	qDebug() << "Dividing Cell " << c.Index() << endl;
 
#endif
 

	
 
	c.DivideOverGivenLine( startpoint, endpoint, true, node_set);
 
      }
 

	
 
      node_set->CleanUp();
 
      mesh.AddNodeSet(node_set);
 

	
 
#ifdef QDEBUG
 
      qDebug() << "Done DivideOverGivenLine" << endl;
 
#endif
 

	
 
      mesh.TestIllegalWalls();
 
      // Do the actual cutting and removing
 
      if (intersected_cells.size()) {
 
	mesh.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);
 
	}
 

	
 

	
 

	
 
#ifdef QDEBUG
 
	qDebug() << "Done CutAwayBelowLine" << endl;
 
#endif
 
	mesh.TestIllegalWalls();
 
	mesh.RepairBoundaryPolygon();
 
#ifdef QDEBUG
 
	qDebug() << "Done RepairBoundaryPolygon" << endl;
 
#endif
 
	mesh.TestIllegalWalls();
 
	mesh.CleanUpWalls();
 
#ifdef QDEBUG
 
	qDebug() << "Done CleanUpWalls" << endl;
 
#endif
 
	mesh.TestIllegalWalls();
 
      }
 

	
 
      dynamic_cast<Main *>(parent())->Plot();
 

	
 
#ifdef QDEBUG
 
      qDebug() << "NodeSet of cutting line: " << *node_set << endl;
 
      cerr << "NodeSet of cutting line: " << *node_set << endl;
 
#endif
 
    }
 
  } else 
 
    if (e->button()==Qt::RightButton) {
 

	
 
      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 *> colliding_cells;
 

	
 
  QList<QGraphicsItem *> l = intersection_line->collidingItems( );
 

	
 
#ifdef QDEBUG
 
  qDebug() <<  "l.size() = " << l.size() << endl;
 
#endif
 

	
 
  for (QList<QGraphicsItem *>::Iterator it=l.begin(); it!=l.end(); ++it) {
 

	
 
#ifdef QDEBUG
 
    qDebug() << typeid(**it).name() << endl;
 
#endif
 

	
 
    if ( !strcmp(typeid(**it).name(),"8CellItem") ) {
 
      colliding_cells.push_back(dynamic_cast<CellItem *>(*it));
 
    }
 
  }
 

	
 
  delete intersection_line;
 
  intersection_line = 0;
 
  return colliding_cells;
 
}
 

	
 
void FigureEditor::FullRedraw(void)
 
{
 
  QList<QRectF> rl;
 
  rl << sceneRect();
 
  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)
 
{
 
  editor = new FigureEditor(canvas,mesh, this);
 

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

	
 
  working_dir = 0;
 
  QObject::connect( editor, SIGNAL(MousePressed()), this, SLOT(PauseIfRunning()));
 
  QObject::connect( editor, SIGNAL(MouseReleased()), this, SLOT(ContIfRunning()));
 
  QMenuBar* menu = menuBar();
 

	
 
  Q3PopupMenu* file = new Q3PopupMenu( menu );
 

	
 
  file->insertItem("&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->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->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 );
 
  running = false;
 
  paused_id = run->insertItem("&Simulation paused", this, SLOT(togglePaused()), Qt::Key_S);
 
  run->setItemChecked(paused_id, FALSE);
 

	
 
  menu->insertItem("&Run", run);
 

	
 
  view = new Q3PopupMenu( menu );
 
  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);
 

	
 
  mesh_id = view->insertItem("Show &nodes", this, SLOT(toggleShowNodes()), Qt::CTRL+Qt::SHIFT+Qt::Key_N);
 
  view->setItemChecked(mesh_id, TRUE);
 
  node_number_id = view->insertItem("Show node numbers", this, SLOT(toggleNodeNumbers()), Qt::CTRL+Qt::SHIFT+Qt::Key_M);
 
  view->setItemChecked(node_number_id, FALSE);
 
  cell_number_id = view->insertItem("Show cell numbers", this, SLOT(toggleCellNumbers()));
 
  view->setItemChecked(cell_number_id, FALSE);
 
  hide_cells_id = view->insertItem("Hide cells", this, SLOT(toggleHideCells()));
 
  view->setItemChecked(hide_cells_id, FALSE);
 
  border_id = view->insertItem("Show &border cells", this, SLOT(toggleShowBorderCells()));
 
  view->setItemChecked(border_id, FALSE);
 
  cell_axes_id = view->insertItem("Show cell &axes", this, SLOT(toggleCellAxes()));
 
  cell_strain_id = view->insertItem("Show cell &strain", this, SLOT(toggleCellStrain()));
 
  view->setItemChecked(cell_axes_id, FALSE);
 
  fluxes_id = view->insertItem("Show &fluxes", this, SLOT(toggleShowFluxes()));
 
  view->setItemChecked(fluxes_id, FALSE);
 
  cell_walls_id = view->insertItem("Show transporters", this, SLOT(toggleShowWalls()));
 
  view->setItemChecked(cell_walls_id, FALSE);
 
  apoplasts_id = view->insertItem("Show apoplasts", this, SLOT(toggleShowApoplasts()));
 
  view->setItemChecked(apoplasts_id, FALSE);
 
  view->insertSeparator();
 
  only_boundary_id = view->insertItem("Show only leaf &boundary", this, SLOT(toggleLeafBoundary()));
 
  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 );
 
  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(about()) ); //, Key_F1);
 
  helpmenu->insertSeparator();
src/mesh.cpp
Show inline comments
 
@@ -306,386 +306,386 @@ Cell &Mesh::LeafPrimordium(int nnodes, d
 
  Node *n1 = *it_n1;
 
  Node *n2 = *it_n2;
 

	
 
  Node *n3=AddNode( new Node ( *n2 + Vector( 0, pet_length, 0) ) );
 
  Node *n4=AddNode( new Node ( *n1 + Vector( 0, pet_length, 0) ) );
 

	
 
  n3->boundary=true;
 
  n4->boundary=true;
 

	
 
  AddNodeToCell(petiole, *it_n1, 
 
		n4,
 
		nodes[(*it_n2)->Index() 
 
		      + (( (*it_n1)->Index() - (*it_n2)->Index() )-1+nnodes)%nnodes]);
 

	
 

	
 

	
 
  list<Node *>::reverse_iterator i=it_n1; i++;
 
  for (; i!=it_n2; ++i) {
 
    AddNodeToCell(petiole, *i,
 
		  nodes[(*it_n2)->Index() + (((*i)->Index()-(*it_n2)->Index()) + 1)%nnodes],
 
		  nodes[(*it_n2)->Index() + (((*i)->Index()-(*it_n2)->Index())-1+nnodes)%nnodes]);
 
  }
 

	
 
  AddNodeToCell(petiole, *it_n2, *it_n2 + 1, n3);
 

	
 
  (*it_n2)->boundary=true;
 

	
 
  AddNodeToCell(petiole, n3, n2, n4);
 
  AddNodeToCell(petiole, n4, n3, n1);
 

	
 

	
 
#ifdef QDEBUG  
 
  qDebug() << circle << endl;
 
  qDebug() << petiole << endl;
 
#endif
 

	
 
  AddNodeToCell(boundary_polygon, *it_n1, n4, *it_n2 + ((*it_n1-*it_n2)+1)%nnodes); // is this gonna work?
 

	
 
  (*it_n1)->boundary=true;
 

	
 
  for (int i=0;i<nnodes;i++) {
 

	
 
    if (nodes[(first_node + i)]->owners.size()==1) {
 
      AddNodeToCell(boundary_polygon,
 
		    nodes[first_node +i],
 
		    nodes[first_node+ (nnodes+i-1)%nnodes],
 
		    nodes[first_node+ (i + 1)%nnodes]);
 

	
 
      nodes[first_node+i]->boundary=true;
 
    }
 
  }
 

	
 
  AddNodeToCell(boundary_polygon, *it_n2, nodes[(nnodes+(*it_n2)->Index() - 1)%nnodes], n3);
 
  AddNodeToCell(boundary_polygon, n3, n2, n4);
 
  AddNodeToCell(boundary_polygon, n4, n3, n1);
 

	
 
  // make petiole solid
 
  for (list<Node *>::iterator i=petiole->nodes.begin(); i!=petiole->nodes.end(); i++) {
 
    (*i)->Fix();
 
  }
 
  petiole->Fix();
 

	
 
  petiole->area=petiole->CalcArea();
 
  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;
 
}
 

	
 
void Mesh::SetBaseArea(void) {
 

	
 
  // Set base area to mean area. 
 
  // This method is typically called during initiation, after
 
  // defining the first cell
 
  Cell::BaseArea() = Area()/cells.size();
 
}
 

	
 
// for optimization, we moved Displace to Mesh
 

	
 
class DeltaIntgrl {
 

	
 
public:
 
  double area;
 
  double ix, iy;
 
  double ixx,ixy,iyy;
 
  DeltaIntgrl(double sarea,double six,double siy,double sixx,double sixy,double siyy) {
 
    area=sarea;
 
    ix=six;
 
    iy=siy;
 
    ixx=sixx;
 
    ixy=sixy;
 
    iyy=siyy;
 
  }
 
};
 

	
 
void Mesh::Clear(void) {
 

	
 
  // clear nodes
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  nodes.clear();
 
  Node::nnodes=0;
 

	
 
  node_insertion_queue.clear();
 
  // Clear NodeSets
 
  for (vector<NodeSet *>::iterator i=node_sets.begin(); i!=node_sets.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  node_sets.clear();
 
  time = 0;
 

	
 
  // clear cells
 

	
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  cells.clear();
 
  Cell::NCells() = 0;
 

	
 
  delete boundary_polygon;
 

	
 
  // Clear walls
 
  for (list<Wall *>::iterator i=walls.begin(); i!=walls.end(); i++) {
 
    delete *i;
 
  }
 

	
 
  walls.clear();
 
  WallBase::nwalls = 0;
 
  //tmp_walls->clear();
 

	
 
  shuffled_cells.clear();
 
  shuffled_nodes.clear();
 
  //Cell::ncells=0;
 
  /*    Cell::ClearNCells();
 
	Node::nnodes=0;
 

	
 
	cells.clear();
 
	nodes.clear();
 
	shuffled_cells.clear();
 
	shuffled_nodes.clear();
 
	node_insertion_queue.empty();
 

	
 
	cerr << "Meshed cleared: cells: " << cells.size() << ", nodes: " << nodes.size() << endl;
 
  */
 

	
 
#ifdef QDEBUG
 
  qDebug() << "cells.size() = " << cells.size() << endl;
 
  qDebug << "walls.size() = " << walls.size() << endl;
 
  qDebug << "nodes.size() = " << nodes.size() << endl;
 
  qDebug() << "walls.size() = " << walls.size() << endl;
 
  qDebug() << "nodes.size() = " << nodes.size() << endl;
 
#endif
 
}
 

	
 
double Mesh::DisplaceNodes(void) {
 

	
 
  MyUrand r(shuffled_nodes.size());
 
  random_shuffle(shuffled_nodes.begin(),shuffled_nodes.end(),r);
 

	
 
  double sum_dh=0;
 

	
 
  list<DeltaIntgrl> delta_intgrl_list;
 

	
 
  for_each( node_sets.begin(), node_sets.end(), mem_fun( &NodeSet::ResetDone ) );
 

	
 
  for (vector<Node *>::const_iterator i=shuffled_nodes.begin(); i!=shuffled_nodes.end(); i++) {
 

	
 
    //int n=shuffled_nodes[*i];
 
    Node &node(**i);
 

	
 
    // Do not allow displacement if fixed
 
    //if (node.fixed) continue;
 

	
 
    if (node.DeadP()) continue;
 

	
 
    // Attempt to move this cell in a random direction
 
    double rx=par.mc_stepsize*(RANDOM()-0.5); // was 100.
 
    double ry=par.mc_stepsize*(RANDOM()-0.5);
 

	
 
    // Uniform with a circle of radius par.mc_stepsize
 
    /* double r = RANDOM() * par.mc_stepsize;
 
       double th = RANDOM()*2*Pi;
 

	
 
       double rx = r * cos(th);
 
       double ry = r * sin(th);
 
    */
 
    Vector new_p(node.x+rx,node.y+ry,0);
 
    Vector old_p(node.x,node.y,0);
 

	
 
    /* if (node.boundary  && boundary_polygon->MoveSelfIntersectsP(n,  new_p )) {
 
    // reject if move of boundary results in self intersection
 
    continue;
 
    }*/
 

	
 

	
 
    if (node.node_set) {
 
      // move each node set only once
 
      if (!node.node_set->DoneP()) 
 
	node.node_set->AttemptMove(rx,ry);
 

	
 
    } else {
 

	
 
      // for all cells to which this node belongs:
 
      //   calculate energy difference
 

	
 
      double area_dh=0.;
 
      double length_dh=0.;
 
      double bending_dh=0.;
 
      double cell_length_dh=0.;
 
      double alignment_dh=0.;
 

	
 
      double old_l1=0.,old_l2=0.,new_l1=0.,new_l2=0.;
 

	
 
      double sum_stiff=0.;
 
      double dh=0.;
 

	
 
      for (list<Neighbor>::const_iterator cit=node.owners.begin(); cit!=node.owners.end(); cit++) {
 

	
 
	//Cell &c=m->getCell(cit->cell);
 
	//Cell &c=cit->cell->BoundaryPolP()?*boundary_polygon:*(cit->cell);
 
	Cell &c=*((Cell *)(cit->cell));
 
	//Cell &c=cells[cit->cell];
 
	if (c.MoveSelfIntersectsP(&node,  new_p )) {
 
	  // reject if move results in self intersection
 
	  //
 
	  // I know: using goto's is bad practice... except when jumping out
 
	  // of deeply nested loops :-)
 
	  //cerr << "Rejecting due to self-intersection\n";
 
	  goto next_node;
 
	}
 

	
 
	// summing stiffnesses of cells. Move has to overcome this minimum required energy.
 
	sum_stiff += c.stiffness;
 
	// area - (area after displacement): see notes for derivation
 
	//Vector i_min_1 = m->getNode(cit->nb1);
 

	
 
	Vector i_min_1 = *(cit->nb1);
 
	//Vector i_plus_1 = m->getNode(cit->nb2);
 
	Vector i_plus_1 = *(cit->nb2);
 

	
 

	
 
	// We must double the weights for the perimeter (otherwise they start bulging...)
 
	double w1, w2;
 
	if (node.boundary && cit->nb1->boundary) 
 
#ifdef FLEMING
 
	  w1 = par.rel_perimeter_stiffness;
 
#else
 
	w1=2;
 
#endif
 
	else
 
	  w1 = 1;
 

	
 
	if (node.boundary && cit->nb2->boundary) 
 
#ifdef FLEMING
 
	  w2 = par.rel_perimeter_stiffness;
 
#else
 
	w2 = 2;
 
#endif
 
	else 
 
	  w2 = 1;
 

	
 
	//if (cit->cell>=0) {
 
	if (!cit->cell->BoundaryPolP()) {
 
	  double delta_A = 0.5 * ( ( new_p.x - old_p.x ) * (i_min_1.y - i_plus_1.y) +
 
				   ( new_p.y - old_p.y ) * ( i_plus_1.x - i_min_1.x ) );
 

	
 
	  area_dh +=  delta_A * (2 * c.target_area - 2 * c.area + delta_A);
 

	
 

	
 
	  // cell length constraint
 
	  // expensive and not always needed
 
	  // so we check the value of lambda_celllength
 

	
 
	  if (/* par.lambda_celllength */  cit->cell->lambda_celllength) {
 

	
 
	    double delta_ix = 
 
	      (i_min_1.x + new_p.x)
 
	      * (new_p.x * i_min_1.y- i_min_1.x * new_p.y) +
 
	      (new_p.x + i_plus_1.x)
 
	      * (i_plus_1.x * new_p.y- new_p.x * i_plus_1.y) -
 

	
 
	      (i_min_1.x + old_p.x)
 
	      * (old_p.x * i_min_1.y- i_min_1.x * old_p.y) -
 
	      (old_p.x + i_plus_1.x)
 
	      * (i_plus_1.x * old_p.y - old_p.x * i_plus_1.y);
 

	
 

	
 
	    double delta_iy =
 
	      (i_min_1.y + new_p.y)
 
	      * (new_p.x * i_min_1.y- i_min_1.x * new_p.y) +
 
	      (new_p.y + i_plus_1.y)
 
	      * (i_plus_1.x * new_p.y- new_p.x * i_plus_1.y) -
 

	
 
	      (i_min_1.y + old_p.y)
 
	      * (old_p.x * i_min_1.y- i_min_1.x * old_p.y) -
 
	      (old_p.y + i_plus_1.y)
 
	      * (i_plus_1.x * old_p.y - old_p.x * i_plus_1.y);
 

	
 

	
 
	    double delta_ixx = 
 
	      (new_p.x*new_p.x+
 
	       i_min_1.x*new_p.x+
 
	       i_min_1.x*i_min_1.x ) *
 
	      (new_p.x*i_min_1.y - i_min_1.x*new_p.y) +
 

	
 
	      (i_plus_1.x*i_plus_1.x+
 
	       new_p.x*i_plus_1.x+
 
	       new_p.x*new_p.x ) *
 
	      (i_plus_1.x*new_p.y - new_p.x*i_plus_1.y) -
 

	
 
	      (old_p.x*old_p.x+
 
	       i_min_1.x*old_p.x+
 
	       i_min_1.x*i_min_1.x ) *
 
	      (old_p.x*i_min_1.y - i_min_1.x*old_p.y) -
 

	
 
	      (i_plus_1.x*i_plus_1.x+
 
	       old_p.x*i_plus_1.x+
 
	       old_p.x*old_p.x ) *
 
	      (i_plus_1.x*old_p.y - old_p.x*i_plus_1.y);
 

	
 

	
 
	    double delta_ixy =
 
	      (i_min_1.x*new_p.y-
 
	       new_p.x*i_min_1.y)*
 
	      (new_p.x*(2*new_p.y+i_min_1.y)+
 
	       i_min_1.x*(new_p.y+2*i_min_1.y)) +
 

	
 
	      (new_p.x*i_plus_1.y-
 
	       i_plus_1.x*new_p.y)*
 
	      (i_plus_1.x*(2*i_plus_1.y+new_p.y)+
 
	       new_p.x*(i_plus_1.y+2*new_p.y)) -
 

	
 
	      (i_min_1.x*old_p.y-
 
	       old_p.x*i_min_1.y)*
 
	      (old_p.x*(2*old_p.y+i_min_1.y)+
 
	       i_min_1.x*(old_p.y+2*i_min_1.y)) -
 

	
 
	      (old_p.x*i_plus_1.y-
 
	       i_plus_1.x*old_p.y)*
 
	      (i_plus_1.x*(2*i_plus_1.y+old_p.y)+
 
	       old_p.x*(i_plus_1.y+2*old_p.y));
 

	
 

	
 
@@ -1136,385 +1136,385 @@ void Mesh::CircumCircle(double x1,double
 
  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.
 
  //DeleteLooseWalls();
 
  // collect all dead cells that need to be removed from the simulation
 
  for (vector<Cell *>::iterator i=cells.begin(); i!=cells.end(); i++) {
 
    if ((*i)->DeadP()) {
 
      // collect the iterators
 
      cellstoberemoved.push_back(i);
 

	
 
      // collect the indices
 
      cellind.push_back((*i)->index);
 
    } else {
 
      // Remove pointers to dead Walls
 
      for (list<Wall *>::iterator w=(*i)->walls.begin(); w!=(*i)->walls.end(); w++) {
 
	if ((*w)->DeadP()) {
 
	  (*w)=0;
 
	}
 
      }
 
      (*i)->walls.remove(0);
 
    }
 
  }
 

	
 
  // Remove pointers to dead Walls from BoundaryPolygon
 
  for (list<Wall *>::iterator w=boundary_polygon->walls.begin(); w!=boundary_polygon->walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      (*w)=0;
 
    }
 
  }
 
  boundary_polygon->walls.remove(0);
 

	
 

	
 
  // Renumber cells; this is most efficient if the list of dead cell indices is sorted
 
  sort(cellind.begin(),cellind.end());
 

	
 

	
 
  // Reindexing of Cells
 
  for (vector<int>::reverse_iterator j=cellind.rbegin(); j!=cellind.rend(); j++) {
 
    for (vector<Cell *>::reverse_iterator i=cells.rbegin(); i!=cells.rend(); i++) {
 
      if (*j < (*i)->index) (*i)->index--;
 
    }
 
  }
 

	
 

	
 
  // Actual deleting of Cells
 
  // We must delete in reverse order, otherwise the iterators become redefined
 
  for ( CellItVect::reverse_iterator i=cellstoberemoved.rbegin(); i!=cellstoberemoved.rend(); i++) {
 
    Cell::NCells()--;
 
    cells.erase(*i);
 
  }
 

	
 

	
 
  // same for nodes
 
  typedef vector <vector<Node *>::iterator> NodeItVect;
 

	
 
  NodeItVect nodestoberemoved;
 
  vector<int> nodeindlist;
 

	
 
  // collect iterators and indices of dead nodes
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    if ((*i)->DeadP()) {
 
      nodestoberemoved.push_back( i );
 
      nodeindlist.push_back((*i)->index);
 
    }
 
  }
 

	
 
  // sort the list of dead nodes for renumbering
 
  sort(nodeindlist.begin(),nodeindlist.end());
 

	
 

	
 
  // Reindicing of Nodes
 
  for (vector<int>::reverse_iterator j=nodeindlist.rbegin(); j!=nodeindlist.rend(); j++) {
 
    for (vector<Node *>::reverse_iterator i=nodes.rbegin(); i!=nodes.rend(); i++) {
 
      if (*j < (*i)->index) { 
 
	(*i)->index--;
 
      } 
 
    }
 
  }
 

	
 
  // Actual deleting of nodes
 
  // We must delete in reverse order, otherwise the iterators become redefined
 
  for ( NodeItVect::reverse_iterator i=nodestoberemoved.rbegin(); i!=nodestoberemoved.rend(); i++) {
 
    Node::nnodes--;
 
    nodes.erase(*i);
 
  }
 

	
 

	
 

	
 
  for (list<Wall *>::iterator w=walls.begin(); w!=walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      Wall::nwalls--;
 
      delete *w;
 
      *w = 0;
 
    }
 
  }
 

	
 
  walls.remove( 0 );
 

	
 

	
 

	
 
  // Clean up all intercellular connections and redo everything
 
  for (vector<Node *>::iterator i=nodes.begin(); i!=nodes.end(); i++) {
 
    (*i)->owners.clear();
 
  }
 

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

	
 
  boundary_polygon->ConstructConnections();
 

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

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

	
 
    // do some vector geometry to check whether the cell is below the cutting line
 
    Vector cellvec = ((*i)->Centroid()-startpoint);
 

	
 
    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;
 
      cerr << "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
 
  // scratch.
 

	
 
  Node *boundary_node=0, *next_boundary_node=0, *internal_node;
 
  set<int> original_boundary_nodes, repaired_boundary_nodes;
 
  vector<int> difference; // set difference result
 

	
 
  // Step 0: print out current boundary polygon
 
#ifdef QDEBUG
 
  qDebug() << endl << "Original Boundary Polygon node indices: ";
 
  foreach (Node* node, boundary_polygon->nodes) {
 
    qDebug() << node->Index() << " " ;
 
  }    
 
  qDebug() << endl << endl;
 
#endif
 

	
 
  // Step 1a: Create a set containing the current boundary polygon nodes' Indices.
 
  foreach (Node* node, boundary_polygon->nodes) {
 
    original_boundary_nodes.insert(node->Index());
 
  }
 

	
 
  // Step 1b: remove all nodes from boundary polygon
 
  boundary_polygon->nodes.clear();
 

	
 
  // Step 2: Remove all references to the boundary polygon from the Mesh's current list of nodes
 
  foreach (Node* node, nodes) {
 
    node->Unmark(); // remove marks, we need them to determine if we have closed the circle
 
    list<Neighbor>::iterator boundary_ref_pos;
 
    if ((boundary_ref_pos = find_if (node->owners.begin(), node->owners.end(), 
 
				     bind2nd(mem_fun_ref(&Neighbor::CellEquals), -1))) != node->owners.end()) {
 
      // i.e. if one of the node's owners is the boundary polygon 
 
      node->owners.erase(boundary_ref_pos); // remove the reference
 
    }
 
  }
 

	
 
  // Step 3: Search for the first boundary node.  We reconstruct the
 
  // boundary polygon by moving along the boundary nodes until we've
 
  // encircled the polygon. Since manually adding nodes may have
 
  // turned nodes previously along the boundary into internal nodes,
 
  // we search through all the node until we find first boundary node
 
  // and proceed from there. If findNextBoundaryNode() returns a node
 
  // other than the one passed to it, the original node is the first
 
  // boundary node.
 
  foreach (Node* node, nodes) {
 
    if ((findNextBoundaryNode(node))->index != node->index){
 
      next_boundary_node = node;
 
      break;
 
    }
 
  }
 

	
 
  // We have a problem if we arrive here without having found a boundary node.
 
  if (!next_boundary_node) throw("Cannot find a boundary node!.");
 

	
 
  // Reconstruct the list of boundary polygon nodes.
 
  do {
 
    boundary_node = next_boundary_node;
 
    boundary_node->Mark();
 
    boundary_polygon->nodes.push_back(boundary_node);
 
    next_boundary_node = findNextBoundaryNode(boundary_node);
 
  } while ( !next_boundary_node->Marked() );
 

	
 

	
 
  // Create a set containing the reconstructed boundary polygon nodes' Indices.
 
  for (list<Node *>::iterator it = boundary_polygon->nodes.begin(); it!=boundary_polygon->nodes.end(); ++it) {
 
    repaired_boundary_nodes.insert((*it)->Index());
 
  }
 

	
 
  // Calculate the difference between the original and repaired sets of boundary nodes
 
  // yielding the set of nodes that are no longer part of the boundary polygon.
 
  set_difference(original_boundary_nodes.begin(), original_boundary_nodes.end(),
 
                 repaired_boundary_nodes.begin(), repaired_boundary_nodes.end(), back_inserter(difference));
 

	
 
  // Tell each node in the difference that it's no longer part of the boundary polygon
 
  vector<Node *>::iterator internal_node_it;
 
  foreach (int i, difference){
 
    internal_node_it = find_if (nodes.begin(), nodes.end(), bind2nd(mem_fun(&Node::IndexEquals), i));
 
    internal_node = *internal_node_it; // dereference the itterator to get to the node pointer
 
    if (!internal_node) throw("Found a null Node pointer.");
 
    internal_node->UnsetBoundary();
 
  }
 

	
 
  boundary_polygon->ConstructConnections();
 
  for (list<Wall *>::iterator w=boundary_polygon->walls.begin(); w!=boundary_polygon->walls.end(); w++) {
 
    if ((*w)->DeadP()) {
 
      (*w)=0;
 
    }
 
  }
 
  boundary_polygon->walls.remove(0);
 
  boundary_polygon->ConstructNeighborList();
 

	
 
#ifdef QDEBUG
 
  qDebug() << "Repaired Boundary Polygon node indices: ";
 
  foreach (Node* node, boundary_polygon->nodes){
 
    qDebug() << node->Index() << " " ;
 
  }
 
  qDebug() << endl ;
 

	
 
#ifdef _undefined_
 
  qDebug() << "NODES:" << endl;
 
  foreach(Node* node, nodes) {
 
    qDebug() << *node;
 
  }
 
  qDebug() << endl;
 

	
 
  qDebug() << "WALLS:" << endl;
 
  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
 
  for (list<Neighbor>::iterator it=boundary_node->owners.begin(); it!=boundary_node->owners.end(); ++it) {
 
    if (it->cell->Index() != -1) boundary_node_owners.insert(it->cell->Index()); // Save each of the current boundary node's owners' Ids - except the boundary polygon 
 
    set<int> *owners = new set<int>; // create a set to hold a 2nd neighbor's owners' Ids
 
    nodeOwners.push_back(owners);
 
    neighborIds.push_back(it->nb2->Index());
 
    foreach(Neighbor neighbor, it->nb2->owners){
 
      if (neighbor.cell->Index() != -1) owners->insert(neighbor.cell->Index()); // Save second neighbors' owners' Ids - except the boundary polygon 
 
    }
 
  }
 
  vector<int>::iterator itt = neighborIds.begin();
 
  vector<set<int> *>::iterator it = nodeOwners.begin();
 

	
 
#ifdef QDEBUG  
 
  qDebug() << "Boundary node: " <<  boundary_node->Index() << " is owned by the following cells: ";
 
  foreach (int i, boundary_node_owners){
 
    qDebug() << i << "  ";
 
  }
 
  qDebug() << endl;
 
#endif
 

	
 
  for (; it < nodeOwners.end(); it++, itt++) {
 
    intersection.clear();
 
    set_intersection(boundary_node_owners.begin(), boundary_node_owners.end(), (*it)->begin(), (*it)->end(), back_inserter(intersection));
 

	
 
#ifdef QDEBUG  
 
    qDebug() << "The intersection of the boundary node(" << boundary_node->Index() << ") owners and its 2nd neighbor(" <<  *itt << ") owners is: ";
 
    foreach (int i, intersection){
 
      qDebug() << i << "  ";
 
    }
 
    qDebug() << endl;
 
#endif
 

	
 
    if (intersection.size() == 1){
src/random.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 
 
#include <QDebug>
 
#include <string>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <sys/timeb.h>
 
#include <iostream>
 
#include "random.h"
 
 
static const std::string _module_id("$Id$");
 
 
static int idum = -1;
 
using namespace std;
 
 
static int counter=0;
 
/*! \return A random double between 0 and 1
 
**/
 
double RANDOM(void)
 
/* Knuth's substrative method, see Numerical Recipes */
 
{
 
  static int inext,inextp;
 
  static long ma[56];
 
  static int iff=0;
 
  counter++;
 
  long mj,mk;
 
  int i,ii,k;
 
 
  if (idum < 0 || iff == 0) {
 
    iff=1;
 
    mj=MSEED-(idum < 0 ? -idum : idum);
 
    mj %= MBIG;
 
    ma[55]=mj;
 
    mk=1;
 
    i=1;
 
    do {
 
      ii=(21*i) % 55;
 
      ma[ii]=mk;
 
      mk=mj-mk;
 
      if (mk < MZ) mk += MBIG;
 
      mj=ma[ii];
 
    } while ( ++i <= 54 );
 
    k=1;
 
    do {
 
      i=1;
 
      do {
 
        ma[i] -= ma[1+(i+30) % 55];
 
        if (ma[i] < MZ) ma[i] += MBIG;
 
      } while ( ++i <= 55 );
 
    } while ( ++k <= 4 );
 
    inext=0;
 
    inextp=31;
 
    idum=1;
 
  }
 
  if (++inext == 56) inext=1;
 
  if (++inextp == 56) inextp=1;
 
  mj=ma[inext]-ma[inextp];
 
  if (mj < MZ) mj += MBIG;
 
  ma[inext]=mj;
 
  return mj*FAC;
 
}
 
 
/*! \param An integer random seed
 
  \return the random seed
 
**/
 
int Seed(int seed)
 
{
 
  if (seed < 0) {
 
    int rseed=Randomize();
 
#ifdef QDEBUG
 
    qDebug() << "Randomizing random generator, seed is " << rseed << endl;
 
#endif
 
    return rseed;
 
  } else {
 
    int i;
 
    idum = -seed;
 
    for (i=0; i <100; i++)
 
      RANDOM();
 
    return seed;
 
  }
 
}
 
 
 
/*! Returns a random integer value between 1 and 'max'
 
  \param The maximum value (long)
 
  \return A random integer (long)
 
**/
 
long RandomNumber(long max)
 
{
 
  return((long)(RANDOM()*max+1));
 
}
 
 
/*! Interactively ask for the seed
 
  \param void
 
  \return void
 
**/
 
void AskSeed(void)
 
{
 
  int seed;
 
  printf("Please enter a random seed: ");
 
  scanf("%d",&seed);
 
  printf("\n");
 
  Seed(seed);
 
}
 
 
int RandomCounter(void) {
 
  return counter;
 
}
 
 
/*! Make a random seed based on the local time
 
  \param void
 
  \return void
 
**/
 
 
int Randomize(void) {
 
 
  // Set the seed according to the local time
 
  struct timeb t;
 
  int seed;
 
 
  ftime(&t);
 
 
  seed=abs((int)((t.time*t.millitm)%655337));
 
  Seed(seed);
 
#ifdef QDEBUG
 
  qdebug() << "Random seed is " << seed << endl;
 
  qDebug() << "Random seed is " << seed << endl;
 
#endif
 
  return seed;
 
}
 
 
/* finis */
src/wall.cpp
Show inline comments
 
/*
 
 *
 
 *  This file is part of the Virtual Leaf.
 
 *
 
 *  The Virtual Leaf is free software: you can redistribute it and/or modify
 
 *  it under the terms of the GNU General Public License as published by
 
 *  the Free Software Foundation, either version 3 of the License, or
 
 *  (at your option) any later version.
 
 *
 
 *  The Virtual Leaf is distributed in the hope that it will be useful,
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 *  GNU General Public License for more details.
 
 *
 
 *  You should have received a copy of the GNU General Public License
 
 *  along with the Virtual Leaf.  If not, see <http://www.gnu.org/licenses/>.
 
 *
 
 *  Copyright 2010 Roeland Merks.
 
 *
 
 */
 

	
 
#include <string>
 
#include "wall.h"
 
#include "cell.h"
 
#include "wallitem.h"
 
#include "node.h"
 
#include "apoplastitem.h"
 
#include <algorithm>
 
#include <QGraphicsScene>
 

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

	
 
/*! Check if this Wall still belongs to Cell a, otherwise gives it to Cell b.
 
  \return true: Wall was corrected
 
  \return false: Wall was still correct
 
*/
 
bool Wall::CorrectWall( void ) {
 

	
 

	
 
  // collect all cells to which my nodes are connected on one list
 
  list<CellBase *> owners;
 
  transform(n1->owners.begin(),n1->owners.end(), back_inserter(owners), mem_fun_ref(&Neighbor::getCell));
 
  transform(n2->owners.begin(),n2->owners.end(), back_inserter(owners), mem_fun_ref(&Neighbor::getCell));
 

	
 
  // get the list of duplicates
 
  list<CellBase *> wall_owners;
 
  owners.sort();
 
  //transform(owners.begin(), owners.end(), ostream_iterator<int>(cerr, ", "), mem_fun(&Cell::Index));
 
  duplicates_copy( owners.begin(), owners.end(), back_inserter(wall_owners) );
 

	
 
  // duplicates are the cells to which the Wall belongs
 
  // For the first division, wall finds three "owners", including the boundary_polygon.
 
  // Remove that one from the list.
 
  //cerr << "wall_owners.size() = " << wall_owners.size() << endl;
 
  if (wall_owners.size() == 3 && nwalls==1 /* bug-fix 22/10/2007; confine this condition to first division only */) {
 

	
 
#ifdef QDEBUG
 
    qDebug() << "nwalls = " << nwalls << endl;
 
#endif
 
    // special case for first cleavage
 

	
 
    // find boundary polygon in the wall owners list
 
    list<CellBase *>::iterator bpit = find_if (
 
					       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;
 
      cerr << "Wall: " << *this << endl;
 
      qDebug() << "Owners are: ";
 
      transform(wall_owners.begin(), wall_owners.end(), ostream_iterator<int>(qDebug(), "  "), mem_fun (&CellBase::Index) );
 
      transform(wall_owners.begin(), wall_owners.end(), ostream_iterator<int>(cerr, "  "), 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) ) {
 

	
 
    return false;
 
  }
 

	
 
  if ( c1 == cell1 ) {
 
    //cerr << "Block 1\n";
 
    ((Cell *)c2) -> RemoveWall(this);
 
    c2 = cell2;
 
    ((Cell *)c2) -> AddWall(this);
 
  } else {
 
    if ( c1 == cell2 ) {
 
      //	cerr << "Block 2\n";
 
      ((Cell *)c2) -> RemoveWall(this);
 
      c2 = cell1;
 
      ((Cell *)c2) -> AddWall(this);
 
    } else {
 
      if ( c2 == cell1) {
 
	((Cell *)c1)->RemoveWall(this);
 
	c1 = cell2;
 
	((Cell *)c1) -> AddWall(this);
 
	//  cerr << "Block 3\n";
 
      } else {
 
	if ( c2 == cell2) {
 
	  ((Cell *)c1)->RemoveWall(this);
 
	  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.;
 
  Vector perpvec = linevec.Normalised().Perp2D();
 
  Vector textpos1 = midline + 100 * perpvec;
 
  Vector textpos2 = midline - 100 * perpvec;
 

	
 
  QGraphicsLineItem *line = new QGraphicsLineItem(0,c);
 

	
 
  line->setPen( QPen(QColor(par.arrowcolor),2) );
 
  line->setLine(startpoint.x, startpoint.y, endpoint.x, endpoint.y );
 
  line->setZValue(10);
 
  line->show();
 

	
 
  QGraphicsSimpleTextItem *text1 = new QGraphicsSimpleTextItem( QString("%1").arg(c2->Index()),0,c);
 
  QGraphicsSimpleTextItem *text2 = new QGraphicsSimpleTextItem( QString("%1").arg(c1->Index()),0,c);
 

	
 
  text1 -> setPos( textpos1.x, textpos1.y );
 
  text2 -> setPos( textpos2.x, textpos2.y );
 
  text1->setZValue(20); text2->setZValue(20);
 

	
 
  text1->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 
  text2->setFont( QFont( "Helvetica", par.nodenumsize, QFont::Bold) );
 

	
 
  text1->setPen ( QColor(par.textcolor) );
 
  text2->setPen ( text1->pen() );
 
  text1->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 */
0 comments (0 inline, 0 general)