Changeset ab1932 for src/boundary.cpp


Ignore:
Timestamp:
Aug 3, 2009, 8:21:05 PM (16 years ago)
Author:
Frederik Heber <heber@…>
Branches:
Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, Candidate_v1.7.0, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
Children:
03e57a
Parents:
0dbddc (diff), edb93c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'TesselationRefactoring' into ConcaveHull

Conflicts:

molecuilder/src/boundary.cpp
molecuilder/src/boundary.hpp
molecuilder/src/linkedcell.cpp
molecuilder/src/linkedcell.hpp
molecuilder/src/molecules.hpp

All of Saskia Metzler's new function were transfered from boundary.cpp to tesselation.cpp and the changes due to TesselPoint, LinkedCell and so on incorporated.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    r0dbddc rab1932  
     1/** \file boundary.hpp
     2 *
     3 * Implementations and super-function for envelopes
     4 */
     5
     6
    17#include "boundary.hpp"
    2 #include "linkedcell.hpp"
    3 #include "molecules.hpp"
    4 #include <gsl/gsl_matrix.h>
    5 #include <gsl/gsl_linalg.h>
    6 #include <gsl/gsl_multimin.h>
    7 #include <gsl/gsl_permutation.h>
    8 
    9 #define DEBUG 1
    10 #define DoSingleStepOutput 0
    11 #define DoTecplotOutput 1
    12 #define DoRaster3DOutput 1
    13 #define DoVRMLOutput 1
    14 #define TecplotSuffix ".dat"
    15 #define Raster3DSuffix ".r3d"
    16 #define VRMLSUffix ".wrl"
    17 #define HULLEPSILON 1e-7
    18 
    19 // ======================================== Points on Boundary =================================
    20 
    21 BoundaryPointSet::BoundaryPointSet()
    22 {
    23   LinesCount = 0;
    24   Nr = -1;
    25 }
    26 ;
    27 
    28 BoundaryPointSet::BoundaryPointSet(atom *Walker)
    29 {
    30   node = Walker;
    31   LinesCount = 0;
    32   Nr = Walker->nr;
    33 }
    34 ;
    35 
    36 BoundaryPointSet::~BoundaryPointSet()
    37 {
    38   cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    39   if (!lines.empty())
    40     cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
    41   node = NULL;
    42 }
    43 ;
    44 
    45 void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    46 {
    47   cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
    48       << endl;
    49   if (line->endpoints[0] == this)
    50     {
    51       lines.insert(LinePair(line->endpoints[1]->Nr, line));
    52     }
    53   else
    54     {
    55       lines.insert(LinePair(line->endpoints[0]->Nr, line));
    56     }
    57   LinesCount++;
    58 }
    59 ;
    60 
    61 ostream &
    62 operator <<(ostream &ost, BoundaryPointSet &a)
    63 {
    64   ost << "[" << a.Nr << "|" << a.node->Name << "]";
    65   return ost;
    66 }
    67 ;
    68 
    69 // ======================================== Lines on Boundary =================================
    70 
    71 BoundaryLineSet::BoundaryLineSet()
    72 {
    73   for (int i = 0; i < 2; i++)
    74     endpoints[i] = NULL;
    75   TrianglesCount = 0;
    76   Nr = -1;
    77 }
    78 ;
    79 
    80 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    81 {
    82   // set number
    83   Nr = number;
    84   // set endpoints in ascending order
    85   SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    86   // add this line to the hash maps of both endpoints
    87   Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
    88   Point[1]->AddLine(this); //
    89   // clear triangles list
    90   TrianglesCount = 0;
    91   cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    92 }
    93 ;
    94 
    95 BoundaryLineSet::~BoundaryLineSet()
    96 {
    97   int Numbers[2];
    98   Numbers[0] = endpoints[1]->Nr;
    99   Numbers[1] = endpoints[0]->Nr;
    100   for (int i = 0; i < 2; i++) {
    101     cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
    102     // as there may be multiple lines with same endpoints, we have to go through each and find in the endpoint's line list this line set
    103     pair<LineMap::iterator, LineMap::iterator> erasor = endpoints[i]->lines.equal_range(Numbers[i]);
    104     for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++)
    105       if ((*Runner).second == this) {
    106         endpoints[i]->lines.erase(Runner);
    107         break;
    108       }
    109     if (endpoints[i]->lines.empty()) {
    110       cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    111       if (endpoints[i] != NULL) {
    112         delete(endpoints[i]);
    113         endpoints[i] = NULL;
    114       } else
    115         cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
    116     } else
    117       cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
    118   }
    119   if (!triangles.empty())
    120     cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl;
    121 }
    122 ;
    123 
    124 void
    125 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    126 {
    127   cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    128       << endl;
    129   triangles.insert(TrianglePair(triangle->Nr, triangle));
    130   TrianglesCount++;
    131 }
    132 ;
    133 
    134 /** Checks whether we have a common endpoint with given \a *line.
    135  * \param *line other line to test
    136  * \return true - common endpoint present, false - not connected
    137  */
    138 bool BoundaryLineSet::IsConnectedTo(class BoundaryLineSet *line)
    139 {
    140   if ((endpoints[0] == line->endpoints[0]) || (endpoints[1] == line->endpoints[0]) || (endpoints[0] == line->endpoints[1]) || (endpoints[1] == line->endpoints[1]))
    141     return true;
    142   else
    143     return false;
    144 };
    145 
    146 /** Checks whether the adjacent triangles of a baseline are convex or not.
    147  * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.
    148  * If greater/equal M_PI than we are convex.
    149  * \param *out output stream for debugging
    150  * \return true - triangles are convex, false - concave or less than two triangles connected
    151  */
    152 bool BoundaryLineSet::CheckConvexityCriterion(ofstream *out)
    153 {
    154   Vector BaseLineNormal;
    155   double angle = 0;
    156   // get the two triangles
    157   if (TrianglesCount != 2) {
    158     *out << Verbose(1) << "ERROR: Baseline " << this << " is connect to less than two triangles, Tesselation incomplete!" << endl;
    159     return false;
    160   }
    161   // have a normal vector on the base line pointing outwards
    162   BaseLineNormal.Zero();
    163   for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
    164     BaseLineNormal.AddVector(&runner->second->NormalVector);
    165   BaseLineNormal.Normalize();
    166   // and calculate the sum of the angles with this normal vector and each of the triangle ones'
    167   for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
    168     angle += BaseLineNormal.Angle(&runner->second->NormalVector);
    169 
    170   if ((angle - M_PI) > -MYEPSILON)
    171     return true;
    172   else
    173     return false;
    174 }
    175 
    176 /** Checks whether point is any of the two endpoints this line contains.
    177  * \param *point point to test
    178  * \return true - point is of the line, false - is not
    179  */
    180 bool BoundaryLineSet::ContainsBoundaryPoint(class BoundaryPointSet *point)
    181 {
    182   for(int i=0;i<2;i++)
    183     if (point == endpoints[i])
    184       return true;
    185   return false;
    186 };
    187 
    188 ostream &
    189 operator <<(ostream &ost, BoundaryLineSet &a)
    190 {
    191   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    192       << a.endpoints[1]->node->Name << "]";
    193   return ost;
    194 }
    195 ;
    196 
    197 // ======================================== Triangles on Boundary =================================
    198 
    199 
    200 BoundaryTriangleSet::BoundaryTriangleSet()
    201 {
    202   for (int i = 0; i < 3; i++)
    203     {
    204       endpoints[i] = NULL;
    205       lines[i] = NULL;
    206     }
    207   Nr = -1;
    208 }
    209 ;
    210 
    211 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number)
    212 {
    213   // set number
    214   Nr = number;
    215   // set lines
    216   cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    217   for (int i = 0; i < 3; i++)
    218     {
    219       lines[i] = line[i];
    220       lines[i]->AddTriangle(this);
    221     }
    222   // get ascending order of endpoints
    223   map<int, class BoundaryPointSet *> OrderMap;
    224   for (int i = 0; i < 3; i++)
    225     // for all three lines
    226     for (int j = 0; j < 2; j++)
    227       { // for both endpoints
    228         OrderMap.insert(pair<int, class BoundaryPointSet *> (
    229             line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
    230         // and we don't care whether insertion fails
    231       }
    232   // set endpoints
    233   int Counter = 0;
    234   cout << Verbose(6) << " with end points ";
    235   for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
    236       != OrderMap.end(); runner++)
    237     {
    238       endpoints[Counter] = runner->second;
    239       cout << " " << *endpoints[Counter];
    240       Counter++;
    241     }
    242   if (Counter < 3)
    243     {
    244       cerr << "ERROR! We have a triangle with only two distinct endpoints!"
    245           << endl;
    246       //exit(1);
    247     }
    248   cout << "." << endl;
    249 }
    250 ;
    251 
    252 BoundaryTriangleSet::~BoundaryTriangleSet()
    253 {
    254   for (int i = 0; i < 3; i++) {
    255     cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
    256     lines[i]->triangles.erase(Nr);
    257     if (lines[i]->triangles.empty()) {
    258       if (lines[i] != NULL) {
    259         cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
    260         delete (lines[i]);
    261         lines[i] = NULL;
    262       } else
    263         cerr << "ERROR: This line " << i << " has already been free'd." << endl;
    264     } else
    265       cout << Verbose(5) << *lines[i] << " is still attached to another triangle." << endl;
    266   }
    267 }
    268 ;
    269 
    270 /** Calculates the normal vector for this triangle.
    271  * Is made unique by comparison with \a OtherVector to point in the other direction.
    272  * \param &OtherVector direction vector to make normal vector unique.
    273  */
    274 void BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    275 {
    276   // get normal vector
    277   NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
    278       &endpoints[2]->node->x);
    279 
    280   // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    281   if (NormalVector.Projection(&OtherVector) > 0)
    282     NormalVector.Scale(-1.);
    283 };
    284 
    285 /** Finds the point on the triangle \a *BTS the line defined by \a *MolCenter and \a *x crosses through.
    286  * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane
    287  * This we test if it's really on the plane and whether it's inside the triangle on the plane or not.
    288  * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite
    289  * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared()
    290  * smaller than the first line.
    291  * \param *out output stream for debugging
    292  * \param *MolCenter offset vector of line
    293  * \param *x second endpoint of line, minus \a *MolCenter is directional vector of line
    294  * \param *Intersection intersection on plane on return
    295  * \return true - \a *Intersection contains intersection on plane defined by triangle, false - zero vector if outside of triangle.
    296  */
    297 bool BoundaryTriangleSet::GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection)
    298 {
    299   Vector CrossPoint;
    300   Vector helper;
    301   int i=0;
    302 
    303   if (Intersection->GetIntersectionWithPlane(out, &NormalVector, &endpoints[0]->node->x, MolCenter, x)) {
    304     *out << Verbose(1) << "Alas! [Bronstein] failed - at least numerically - the intersection is not on the plane!" << endl;
    305     return false;
    306   }
    307 
    308   // Calculate cross point between one baseline and the line from the third endpoint to intersection
    309   do {
    310     CrossPoint.GetIntersectionOfTwoLinesOnPlane(out, &endpoints[i%3]->node->x, &endpoints[(i+1)%3]->node->x, &endpoints[(i+2)%3]->node->x, Intersection);
    311     helper.CopyVector(&endpoints[(i+1)%3]->node->x);
    312     helper.SubtractVector(&endpoints[i%3]->node->x);
    313     i++;
    314     if (i>3)
    315       break;
    316   } while (CrossPoint.NormSquared() < MYEPSILON);
    317   if (i>3) {
    318     *out << Verbose(1) << "ERROR: Could not find any cross points, something's utterly wrong here!" << endl;
    319     exit(255);
    320   }
    321   CrossPoint.SubtractVector(&endpoints[i%3]->node->x);
    322 
    323   // check whether intersection is inside or not by comparing length of intersection and length of cross point
    324   if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside
    325     return true;
    326   } else { // outside!
    327     Intersection->Zero();
    328     return false;
    329   }
    330 };
    331 
    332 /** Checks whether lines is any of the three boundary lines this triangle contains.
    333  * \param *line line to test
    334  * \return true - line is of the triangle, false - is not
    335  */
    336 bool BoundaryTriangleSet::ContainsBoundaryLine(class BoundaryLineSet *line)
    337 {
    338   for(int i=0;i<3;i++)
    339     if (line == lines[i])
    340       return true;
    341   return false;
    342 };
    343 
    344 /** Checks whether point is any of the three endpoints this triangle contains.
    345  * \param *point point to test
    346  * \return true - point is of the triangle, false - is not
    347  */
    348 bool BoundaryTriangleSet::ContainsBoundaryPoint(class BoundaryPointSet *point)
    349 {
    350   for(int i=0;i<3;i++)
    351     if (point == endpoints[i])
    352       return true;
    353   return false;
    354 };
    355 
    356 ostream &
    357 operator <<(ostream &ost, BoundaryTriangleSet &a)
    358 {
    359   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    360       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    361   return ost;
    362 }
    363 ;
    364 
    365 
    366 // ============================ CandidateForTesselation =============================
    367 
    368 CandidateForTesselation::CandidateForTesselation(
    369   atom *candidate, BoundaryLineSet* line, Vector OptCandidateCenter, Vector OtherOptCandidateCenter
    370 ) {
    371   point = candidate;
    372   BaseLine = line;
    373   OptCenter.CopyVector(&OptCandidateCenter);
    374   OtherOptCenter.CopyVector(&OtherOptCandidateCenter);
    375 }
    376 
    377 CandidateForTesselation::~CandidateForTesselation() {
    378   point = NULL;
    379   BaseLine = NULL;
    380 }
     8
     9#include<gsl/gsl_poly.h>
    38110
    38211// ========================================== F U N C T I O N S =================================
    38312
    384 /** Finds the endpoint two lines are sharing.
    385  * \param *line1 first line
    386  * \param *line2 second line
    387  * \return point which is shared or NULL if none
    388  */
    389 class BoundaryPointSet *
    390 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    391 {
    392   class BoundaryLineSet * lines[2] =
    393     { line1, line2 };
    394   class BoundaryPointSet *node = NULL;
    395   map<int, class BoundaryPointSet *> OrderMap;
    396   pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
    397   for (int i = 0; i < 2; i++)
    398     // for both lines
    399     for (int j = 0; j < 2; j++)
    400       { // for both endpoints
    401         OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
    402             lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
    403         if (!OrderTest.second)
    404           { // if insertion fails, we have common endpoint
    405             node = OrderTest.first->second;
    406             cout << Verbose(5) << "Common endpoint of lines " << *line1
    407                 << " and " << *line2 << " is: " << *node << "." << endl;
    408             j = 2;
    409             i = 2;
    410             break;
    411           }
    412       }
    413   return node;
    414 }
    415 ;
    416 
    417 /** Determines the boundary points of a cluster.
    418  * Does a projection per axis onto the orthogonal plane, transforms into spherical coordinates, sorts them by the angle
    419  * and looks at triples: if the middle has less a distance than the allowed maximum height of the triangle formed by the plane's
    420  * center and first and last point in the triple, it is thrown out.
    421  * \param *out output stream for debugging
    422  * \param *mol molecule structure representing the cluster
    423  */
    424 Boundaries *
    425 GetBoundaryPoints(ofstream *out, molecule *mol)
    426 {
    427   atom *Walker = NULL;
    428   PointMap PointsOnBoundary;
    429   LineMap LinesOnBoundary;
    430   TriangleMap TrianglesOnBoundary;
    431   Vector *MolCenter = mol->DetermineCenterOfAll(out);
    432   Vector helper;
    433 
    434   *out << Verbose(1) << "Finding all boundary points." << endl;
    435   Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
    436   BoundariesTestPair BoundaryTestPair;
    437   Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    438   double radius, angle;
    439   // 3a. Go through every axis
    440   for (int axis = 0; axis < NDIM; axis++) {
    441     AxisVector.Zero();
    442     AngleReferenceVector.Zero();
    443     AngleReferenceNormalVector.Zero();
    444     AxisVector.x[axis] = 1.;
    445     AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    446     AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    447 
    448     *out << Verbose(1) << "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << "." << endl;
    449 
    450     // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    451     Walker = mol->start;
    452     while (Walker->next != mol->end) {
    453       Walker = Walker->next;
    454       Vector ProjectedVector;
    455       ProjectedVector.CopyVector(&Walker->x);
    456       ProjectedVector.SubtractVector(MolCenter);
    457       ProjectedVector.ProjectOntoPlane(&AxisVector);
    458 
    459       // correct for negative side
    460       radius = ProjectedVector.NormSquared();
    461       if (fabs(radius) > MYEPSILON)
    462         angle = ProjectedVector.Angle(&AngleReferenceVector);
    463       else
    464         angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    465 
    466       //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    467       if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) {
    468         angle = 2. * M_PI - angle;
    469       }
    470       *out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector << endl;
    471       BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, DistancePair (radius, Walker)));
    472       if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity
    473         *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;
    474         *out << Verbose(2) << "Present vector: " << *BoundaryTestPair.first->second.second << endl;
    475         *out << Verbose(2) << "New vector: " << *Walker << endl;
    476         double tmp = ProjectedVector.NormSquared();
    477         if ((tmp - BoundaryTestPair.first->second.first) > MYEPSILON) {
    478           BoundaryTestPair.first->second.first = tmp;
    479           BoundaryTestPair.first->second.second = Walker;
    480           *out << Verbose(2) << "Keeping new vector due to larger projected distance " << tmp << "." << endl;
    481         } else if (fabs(tmp - BoundaryTestPair.first->second.first) < MYEPSILON) {
    482           helper.CopyVector(&Walker->x);
    483           helper.SubtractVector(MolCenter);
    484           tmp = helper.NormSquared();
    485           helper.CopyVector(&BoundaryTestPair.first->second.second->x);
    486           helper.SubtractVector(MolCenter);
    487           if (helper.NormSquared() < tmp) {
    488             BoundaryTestPair.first->second.second = Walker;
    489             *out << Verbose(2) << "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << "." << endl;
    490           } else {
    491             *out << Verbose(2) << "Keeping present vector due to larger distance to molecule center " << tmp << "." << endl;
    492           }
    493         } else {
    494           *out << Verbose(2) << "Keeping present vector due to larger projected distance " << tmp << "." << endl;
    495         }
    496       }
    497     }
    498     // printing all inserted for debugging
    499     //    {
    500     //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    501     //      int i=0;
    502     //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    503     //        if (runner != BoundaryPoints[axis].begin())
    504     //          *out << ", " << i << ": " << *runner->second.second;
    505     //        else
    506     //          *out << i << ": " << *runner->second.second;
    507     //        i++;
    508     //      }
    509     //      *out << endl;
    510     //    }
    511     // 3c. throw out points whose distance is less than the mean of left and right neighbours
    512     bool flag = false;
    513     *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl;
    514     do { // do as long as we still throw one out per round
    515       flag = false;
    516       Boundaries::iterator left = BoundaryPoints[axis].end();
    517       Boundaries::iterator right = BoundaryPoints[axis].end();
    518       for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    519         // set neighbours correctly
    520         if (runner == BoundaryPoints[axis].begin()) {
    521           left = BoundaryPoints[axis].end();
    522         } else {
    523           left = runner;
    524         }
    525         left--;
    526         right = runner;
    527         right++;
    528         if (right == BoundaryPoints[axis].end()) {
    529           right = BoundaryPoints[axis].begin();
    530         }
    531         // check distance
    532 
    533         // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    534         {
    535           Vector SideA, SideB, SideC, SideH;
    536           SideA.CopyVector(&left->second.second->x);
    537           SideA.SubtractVector(MolCenter);
    538           SideA.ProjectOntoPlane(&AxisVector);
    539           //          *out << "SideA: ";
    540           //          SideA.Output(out);
    541           //          *out << endl;
    542 
    543           SideB.CopyVector(&right->second.second->x);
    544           SideB.SubtractVector(MolCenter);
    545           SideB.ProjectOntoPlane(&AxisVector);
    546           //          *out << "SideB: ";
    547           //          SideB.Output(out);
    548           //          *out << endl;
    549 
    550           SideC.CopyVector(&left->second.second->x);
    551           SideC.SubtractVector(&right->second.second->x);
    552           SideC.ProjectOntoPlane(&AxisVector);
    553           //          *out << "SideC: ";
    554           //          SideC.Output(out);
    555           //          *out << endl;
    556 
    557           SideH.CopyVector(&runner->second.second->x);
    558           SideH.SubtractVector(MolCenter);
    559           SideH.ProjectOntoPlane(&AxisVector);
    560           //          *out << "SideH: ";
    561           //          SideH.Output(out);
    562           //          *out << endl;
    563 
    564           // calculate each length
    565           double a = SideA.Norm();
    566           //double b = SideB.Norm();
    567           //double c = SideC.Norm();
    568           double h = SideH.Norm();
    569           // calculate the angles
    570           double alpha = SideA.Angle(&SideH);
    571           double beta = SideA.Angle(&SideC);
    572           double gamma = SideB.Angle(&SideH);
    573           double delta = SideC.Angle(&SideH);
    574           double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    575           //*out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl;
    576           *out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl;
    577           if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) {
    578             // throw out point
    579             *out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    580             BoundaryPoints[axis].erase(runner);
    581             flag = true;
    582           }
    583         }
    584       }
    585     } while (flag);
    586   }
    587   delete(MolCenter);
    588   return BoundaryPoints;
    589 }
    590 ;
    59113
    59214/** Determines greatest diameters of a cluster defined by its convex envelope.
     
    60527  bool BoundaryFreeFlag = false;
    60628  Boundaries *BoundaryPoints = BoundaryPtr;
    607   if (BoundaryPoints == NULL)
    608     {
    609       BoundaryFreeFlag = true;
    610       BoundaryPoints = GetBoundaryPoints(out, mol);
    611     }
    612   else
    613     {
    614       *out << Verbose(1) << "Using given boundary points set." << endl;
    615     }
     29  if (BoundaryPoints == NULL) {
     30    BoundaryFreeFlag = true;
     31    BoundaryPoints = GetBoundaryPoints(out, mol);
     32  } else {
     33    *out << Verbose(1) << "Using given boundary points set." << endl;
     34  }
    61635  // determine biggest "diameter" of cluster for each axis
    61736  Boundaries::iterator Neighbour, OtherNeighbour;
     
    735154      for (i=0;i<3;i++) { // print each node
    736155        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    737           *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]-center->x[j] << " ";
     156          *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    738157        *vrmlfile << "\t";
    739158      }
     
    790209      for (i=0;i<3;i++) {  // print each node
    791210        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    792           *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]-center->x[j] << " ";
     211          *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    793212        *rasterfile << "\t";
    794213      }
     
    821240    *out << Verbose(2) << "The following triangles were created:";
    822241    int Counter = 1;
    823     atom *Walker = NULL;
     242    TesselPoint *Walker = NULL;
    824243    for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
    825244      Walker = target->second->node;
    826245      LookupList[Walker->nr] = Counter++;
    827       *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl;
     246      *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << endl;
    828247    }
    829248    *tecplot << endl;
     
    837256  }
    838257}
     258
     259
     260/** Determines the boundary points of a cluster.
     261 * Does a projection per axis onto the orthogonal plane, transforms into spherical coordinates, sorts them by the angle
     262 * and looks at triples: if the middle has less a distance than the allowed maximum height of the triangle formed by the plane's
     263 * center and first and last point in the triple, it is thrown out.
     264 * \param *out output stream for debugging
     265 * \param *mol molecule structure representing the cluster
     266 */
     267Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol)
     268{
     269  atom *Walker = NULL;
     270  PointMap PointsOnBoundary;
     271  LineMap LinesOnBoundary;
     272  TriangleMap TrianglesOnBoundary;
     273  Vector *MolCenter = mol->DetermineCenterOfAll(out);
     274  Vector helper;
     275
     276  *out << Verbose(1) << "Finding all boundary points." << endl;
     277  Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
     278  BoundariesTestPair BoundaryTestPair;
     279  Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
     280  double radius, angle;
     281  // 3a. Go through every axis
     282  for (int axis = 0; axis < NDIM; axis++) {
     283    AxisVector.Zero();
     284    AngleReferenceVector.Zero();
     285    AngleReferenceNormalVector.Zero();
     286    AxisVector.x[axis] = 1.;
     287    AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
     288    AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
     289
     290    *out << Verbose(1) << "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << "." << endl;
     291
     292    // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     293    Walker = mol->start;
     294    while (Walker->next != mol->end) {
     295      Walker = Walker->next;
     296      Vector ProjectedVector;
     297      ProjectedVector.CopyVector(&Walker->x);
     298      ProjectedVector.SubtractVector(MolCenter);
     299      ProjectedVector.ProjectOntoPlane(&AxisVector);
     300
     301      // correct for negative side
     302      radius = ProjectedVector.NormSquared();
     303      if (fabs(radius) > MYEPSILON)
     304        angle = ProjectedVector.Angle(&AngleReferenceVector);
     305      else
     306        angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
     307
     308      //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
     309      if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) {
     310        angle = 2. * M_PI - angle;
     311      }
     312      *out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector << endl;
     313      BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, DistancePair (radius, Walker)));
     314      if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity
     315        *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;
     316        *out << Verbose(2) << "Present vector: " << *BoundaryTestPair.first->second.second << endl;
     317        *out << Verbose(2) << "New vector: " << *Walker << endl;
     318        double tmp = ProjectedVector.NormSquared();
     319        if ((tmp - BoundaryTestPair.first->second.first) > MYEPSILON) {
     320          BoundaryTestPair.first->second.first = tmp;
     321          BoundaryTestPair.first->second.second = Walker;
     322          *out << Verbose(2) << "Keeping new vector due to larger projected distance " << tmp << "." << endl;
     323        } else if (fabs(tmp - BoundaryTestPair.first->second.first) < MYEPSILON) {
     324          helper.CopyVector(&Walker->x);
     325          helper.SubtractVector(MolCenter);
     326          tmp = helper.NormSquared();
     327          helper.CopyVector(&BoundaryTestPair.first->second.second->x);
     328          helper.SubtractVector(MolCenter);
     329          if (helper.NormSquared() < tmp) {
     330            BoundaryTestPair.first->second.second = Walker;
     331            *out << Verbose(2) << "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << "." << endl;
     332          } else {
     333            *out << Verbose(2) << "Keeping present vector due to larger distance to molecule center " << tmp << "." << endl;
     334          }
     335        } else {
     336          *out << Verbose(2) << "Keeping present vector due to larger projected distance " << tmp << "." << endl;
     337        }
     338      }
     339    }
     340    // printing all inserted for debugging
     341    //    {
     342    //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     343    //      int i=0;
     344    //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     345    //        if (runner != BoundaryPoints[axis].begin())
     346    //          *out << ", " << i << ": " << *runner->second.second;
     347    //        else
     348    //          *out << i << ": " << *runner->second.second;
     349    //        i++;
     350    //      }
     351    //      *out << endl;
     352    //    }
     353    // 3c. throw out points whose distance is less than the mean of left and right neighbours
     354    bool flag = false;
     355    *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl;
     356    do { // do as long as we still throw one out per round
     357      flag = false;
     358      Boundaries::iterator left = BoundaryPoints[axis].end();
     359      Boundaries::iterator right = BoundaryPoints[axis].end();
     360      for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     361        // set neighbours correctly
     362        if (runner == BoundaryPoints[axis].begin()) {
     363          left = BoundaryPoints[axis].end();
     364        } else {
     365          left = runner;
     366        }
     367        left--;
     368        right = runner;
     369        right++;
     370        if (right == BoundaryPoints[axis].end()) {
     371          right = BoundaryPoints[axis].begin();
     372        }
     373        // check distance
     374
     375        // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
     376        {
     377          Vector SideA, SideB, SideC, SideH;
     378          SideA.CopyVector(&left->second.second->x);
     379          SideA.SubtractVector(MolCenter);
     380          SideA.ProjectOntoPlane(&AxisVector);
     381          //          *out << "SideA: ";
     382          //          SideA.Output(out);
     383          //          *out << endl;
     384
     385          SideB.CopyVector(&right->second.second->x);
     386          SideB.SubtractVector(MolCenter);
     387          SideB.ProjectOntoPlane(&AxisVector);
     388          //          *out << "SideB: ";
     389          //          SideB.Output(out);
     390          //          *out << endl;
     391
     392          SideC.CopyVector(&left->second.second->x);
     393          SideC.SubtractVector(&right->second.second->x);
     394          SideC.ProjectOntoPlane(&AxisVector);
     395          //          *out << "SideC: ";
     396          //          SideC.Output(out);
     397          //          *out << endl;
     398
     399          SideH.CopyVector(&runner->second.second->x);
     400          SideH.SubtractVector(MolCenter);
     401          SideH.ProjectOntoPlane(&AxisVector);
     402          //          *out << "SideH: ";
     403          //          SideH.Output(out);
     404          //          *out << endl;
     405
     406          // calculate each length
     407          double a = SideA.Norm();
     408          //double b = SideB.Norm();
     409          //double c = SideC.Norm();
     410          double h = SideH.Norm();
     411          // calculate the angles
     412          double alpha = SideA.Angle(&SideH);
     413          double beta = SideA.Angle(&SideC);
     414          double gamma = SideB.Angle(&SideH);
     415          double delta = SideC.Angle(&SideH);
     416          double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
     417          //*out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl;
     418          *out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl;
     419          if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) {
     420            // throw out point
     421            *out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
     422            BoundaryPoints[axis].erase(runner);
     423            flag = true;
     424          }
     425        }
     426      }
     427    } while (flag);
     428  }
     429  delete(MolCenter);
     430  return BoundaryPoints;
     431};
    839432
    840433/** Tesselates the convex boundary by finding all boundary points.
     
    959552      << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
    960553      << endl;
    961   for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
    962       != TesselStruct->TrianglesOnBoundary.end(); runner++)
     554  for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++)
    963555    { // go through every triangle, calculate volume of its pyramid with CoG as peak
    964       x.CopyVector(&runner->second->endpoints[0]->node->x);
    965       x.SubtractVector(&runner->second->endpoints[1]->node->x);
    966       y.CopyVector(&runner->second->endpoints[0]->node->x);
    967       y.SubtractVector(&runner->second->endpoints[2]->node->x);
    968       a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
    969           &runner->second->endpoints[1]->node->x));
    970       b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
    971           &runner->second->endpoints[2]->node->x));
    972       c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared(
    973           &runner->second->endpoints[1]->node->x));
     556      x.CopyVector(runner->second->endpoints[0]->node->node);
     557      x.SubtractVector(runner->second->endpoints[1]->node->node);
     558      y.CopyVector(runner->second->endpoints[0]->node->node);
     559      y.SubtractVector(runner->second->endpoints[2]->node->node);
     560      a = sqrt(runner->second->endpoints[0]->node->node->DistanceSquared(runner->second->endpoints[1]->node->node));
     561      b = sqrt(runner->second->endpoints[0]->node->node->DistanceSquared(runner->second->endpoints[2]->node->node));
     562      c = sqrt(runner->second->endpoints[2]->node->node->DistanceSquared(runner->second->endpoints[1]->node->node));
    974563      G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle
    975       x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
    976           &runner->second->endpoints[1]->node->x,
    977           &runner->second->endpoints[2]->node->x);
    978       x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
     564      x.MakeNormalVector(runner->second->endpoints[0]->node->node, runner->second->endpoints[1]->node->node, runner->second->endpoints[2]->node->node);
     565      x.Scale(runner->second->endpoints[1]->node->node->Projection(&x));
    979566      h = x.Norm(); // distance of CoG to triangle
    980567      PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
     
    1164751        FillIt = true;
    1165752        for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {
    1166           //FillIt = FillIt && (!(*ListRunner)->TesselStruct->IsInside(&CurrentPosition));
     753          FillIt = FillIt && (!(*ListRunner)->TesselStruct->IsInside(&CurrentPosition));
    1167754        }
    1168755
     
    1228815
    1229816
    1230 // =========================================================== class TESSELATION ===========================================
    1231 
    1232 /** Constructor of class Tesselation.
    1233  */
    1234 Tesselation::Tesselation()
    1235 {
    1236   PointsOnBoundaryCount = 0;
    1237   LinesOnBoundaryCount = 0;
    1238   TrianglesOnBoundaryCount = 0;
    1239   TriangleFilesWritten = 0;
    1240 }
    1241 ;
    1242 
    1243 /** Constructor of class Tesselation.
    1244  * We have to free all points, lines and triangles.
    1245  */
    1246 Tesselation::~Tesselation()
    1247 {
    1248   cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
    1249   for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
    1250     if (runner->second != NULL) {
    1251       delete (runner->second);
    1252       runner->second = NULL;
    1253     } else
    1254       cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
    1255   }
    1256 }
    1257 ;
    1258 
    1259 /** Gueses first starting triangle of the convex envelope.
    1260  * We guess the starting triangle by taking the smallest distance between two points and looking for a fitting third.
    1261  * \param *out output stream for debugging
    1262  * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster
    1263  */
    1264 void
    1265 Tesselation::GuessStartingTriangle(ofstream *out)
    1266 {
    1267   // 4b. create a starting triangle
    1268   // 4b1. create all distances
    1269   DistanceMultiMap DistanceMMap;
    1270   double distance, tmp;
    1271   Vector PlaneVector, TrialVector;
    1272   PointMap::iterator A, B, C; // three nodes of the first triangle
    1273   A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
    1274 
    1275   // with A chosen, take each pair B,C and sort
    1276   if (A != PointsOnBoundary.end())
    1277     {
    1278       B = A;
    1279       B++;
    1280       for (; B != PointsOnBoundary.end(); B++)
    1281         {
    1282           C = B;
    1283           C++;
    1284           for (; C != PointsOnBoundary.end(); C++)
    1285             {
    1286               tmp = A->second->node->x.DistanceSquared(&B->second->node->x);
    1287               distance = tmp * tmp;
    1288               tmp = A->second->node->x.DistanceSquared(&C->second->node->x);
    1289               distance += tmp * tmp;
    1290               tmp = B->second->node->x.DistanceSquared(&C->second->node->x);
    1291               distance += tmp * tmp;
    1292               DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
    1293                   PointMap::iterator, PointMap::iterator> (B, C)));
    1294             }
    1295         }
    1296     }
    1297   //    // listing distances
    1298   //    *out << Verbose(1) << "Listing DistanceMMap:";
    1299   //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
    1300   //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
    1301   //    }
    1302   //    *out << endl;
    1303   // 4b2. pick three baselines forming a triangle
    1304   // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1305   DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    1306   for (; baseline != DistanceMMap.end(); baseline++)
    1307     {
    1308       // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1309       // 2. next, we have to check whether all points reside on only one side of the triangle
    1310       // 3. construct plane vector
    1311       PlaneVector.MakeNormalVector(&A->second->node->x,
    1312           &baseline->second.first->second->node->x,
    1313           &baseline->second.second->second->node->x);
    1314       *out << Verbose(2) << "Plane vector of candidate triangle is ";
    1315       PlaneVector.Output(out);
    1316       *out << endl;
    1317       // 4. loop over all points
    1318       double sign = 0.;
    1319       PointMap::iterator checker = PointsOnBoundary.begin();
    1320       for (; checker != PointsOnBoundary.end(); checker++)
    1321         {
    1322           // (neglecting A,B,C)
    1323           if ((checker == A) || (checker == baseline->second.first) || (checker
    1324               == baseline->second.second))
    1325             continue;
    1326           // 4a. project onto plane vector
    1327           TrialVector.CopyVector(&checker->second->node->x);
    1328           TrialVector.SubtractVector(&A->second->node->x);
    1329           distance = TrialVector.Projection(&PlaneVector);
    1330           if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
    1331             continue;
    1332           *out << Verbose(3) << "Projection of " << checker->second->node->Name
    1333               << " yields distance of " << distance << "." << endl;
    1334           tmp = distance / fabs(distance);
    1335           // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
    1336           if ((sign != 0) && (tmp != sign))
    1337             {
    1338               // 4c. If so, break 4. loop and continue with next candidate in 1. loop
    1339               *out << Verbose(2) << "Current candidates: "
    1340                   << A->second->node->Name << ","
    1341                   << baseline->second.first->second->node->Name << ","
    1342                   << baseline->second.second->second->node->Name << " leaves "
    1343                   << checker->second->node->Name << " outside the convex hull."
    1344                   << endl;
    1345               break;
    1346             }
    1347           else
    1348             { // note the sign for later
    1349               *out << Verbose(2) << "Current candidates: "
    1350                   << A->second->node->Name << ","
    1351                   << baseline->second.first->second->node->Name << ","
    1352                   << baseline->second.second->second->node->Name << " leave "
    1353                   << checker->second->node->Name << " inside the convex hull."
    1354                   << endl;
    1355               sign = tmp;
    1356             }
    1357           // 4d. Check whether the point is inside the triangle (check distance to each node
    1358           tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);
    1359           int innerpoint = 0;
    1360           if ((tmp < A->second->node->x.DistanceSquared(
    1361               &baseline->second.first->second->node->x)) && (tmp
    1362               < A->second->node->x.DistanceSquared(
    1363                   &baseline->second.second->second->node->x)))
    1364             innerpoint++;
    1365           tmp = checker->second->node->x.DistanceSquared(
    1366               &baseline->second.first->second->node->x);
    1367           if ((tmp < baseline->second.first->second->node->x.DistanceSquared(
    1368               &A->second->node->x)) && (tmp
    1369               < baseline->second.first->second->node->x.DistanceSquared(
    1370                   &baseline->second.second->second->node->x)))
    1371             innerpoint++;
    1372           tmp = checker->second->node->x.DistanceSquared(
    1373               &baseline->second.second->second->node->x);
    1374           if ((tmp < baseline->second.second->second->node->x.DistanceSquared(
    1375               &baseline->second.first->second->node->x)) && (tmp
    1376               < baseline->second.second->second->node->x.DistanceSquared(
    1377                   &A->second->node->x)))
    1378             innerpoint++;
    1379           // 4e. If so, break 4. loop and continue with next candidate in 1. loop
    1380           if (innerpoint == 3)
    1381             break;
    1382         }
    1383       // 5. come this far, all on same side? Then break 1. loop and construct triangle
    1384       if (checker == PointsOnBoundary.end())
    1385         {
    1386           *out << "Looks like we have a candidate!" << endl;
    1387           break;
    1388         }
    1389     }
    1390   if (baseline != DistanceMMap.end())
    1391     {
    1392       BPS[0] = baseline->second.first->second;
    1393       BPS[1] = baseline->second.second->second;
    1394       BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1395       BPS[0] = A->second;
    1396       BPS[1] = baseline->second.second->second;
    1397       BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1398       BPS[0] = baseline->second.first->second;
    1399       BPS[1] = A->second;
    1400       BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1401 
    1402       // 4b3. insert created triangle
    1403       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1404       TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1405       TrianglesOnBoundaryCount++;
    1406       for (int i = 0; i < NDIM; i++)
    1407         {
    1408           LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
    1409           LinesOnBoundaryCount++;
    1410         }
    1411 
    1412       *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
    1413     }
    1414   else
    1415     {
    1416       *out << Verbose(1) << "No starting triangle found." << endl;
    1417       exit(255);
    1418     }
    1419 }
    1420 ;
    1421 
    1422 /** Tesselates the convex envelope of a cluster from a single starting triangle.
    1423  * The starting triangle is made out of three baselines. Each line in the final tesselated cluster may belong to at most
    1424  * 2 triangles. Hence, we go through all current lines:
    1425  * -# if the lines contains to only one triangle
    1426  * -# We search all points in the boundary
    1427  *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
    1428  *       baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
    1429  *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors)
    1430  *    -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
    1431  * \param *out output stream for debugging
    1432  * \param *configuration for IsAngstroem
    1433  * \param *mol the cluster as a molecule structure
    1434  */
    1435 void Tesselation::TesselateOnBoundary(ofstream *out, molecule *mol)
    1436 {
    1437   bool flag;
    1438   PointMap::iterator winner;
    1439   class BoundaryPointSet *peak = NULL;
    1440   double SmallestAngle, TempAngle;
    1441   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, helper, PropagationVector, *MolCenter = NULL;
    1442   LineMap::iterator LineChecker[2];
    1443 
    1444   MolCenter = mol->DetermineCenterOfAll(out);
    1445   // create a first tesselation with the given BoundaryPoints
    1446   do {
    1447     flag = false;
    1448     for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++)
    1449       if (baseline->second->TrianglesCount == 1) {
    1450         // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles)
    1451         SmallestAngle = M_PI;
    1452 
    1453         // get peak point with respect to this base line's only triangle
    1454         BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1455         *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl;
    1456         for (int i = 0; i < 3; i++)
    1457           if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1458             peak = BTS->endpoints[i];
    1459         *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1460 
    1461         // prepare some auxiliary vectors
    1462         Vector BaseLineCenter, BaseLine;
    1463         BaseLineCenter.CopyVector(&baseline->second->endpoints[0]->node->x);
    1464         BaseLineCenter.AddVector(&baseline->second->endpoints[1]->node->x);
    1465         BaseLineCenter.Scale(1. / 2.); // points now to center of base line
    1466         BaseLine.CopyVector(&baseline->second->endpoints[0]->node->x);
    1467         BaseLine.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1468 
    1469         // offset to center of triangle
    1470         CenterVector.Zero();
    1471         for (int i = 0; i < 3; i++)
    1472           CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1473         CenterVector.Scale(1. / 3.);
    1474         *out << Verbose(4) << "CenterVector of base triangle is " << CenterVector << endl;
    1475 
    1476         // normal vector of triangle
    1477         NormalVector.CopyVector(MolCenter);
    1478         NormalVector.SubtractVector(&CenterVector);
    1479         BTS->GetNormalVector(NormalVector);
    1480         NormalVector.CopyVector(&BTS->NormalVector);
    1481         *out << Verbose(4) << "NormalVector of base triangle is " << NormalVector << endl;
    1482 
    1483         // vector in propagation direction (out of triangle)
    1484         // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
    1485         PropagationVector.MakeNormalVector(&BaseLine, &NormalVector);
    1486         TempVector.CopyVector(&CenterVector);
    1487         TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1488         //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1489         if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1490           PropagationVector.Scale(-1.);
    1491         *out << Verbose(4) << "PropagationVector of base triangle is " << PropagationVector << endl;
    1492         winner = PointsOnBoundary.end();
    1493 
    1494         // loop over all points and calculate angle between normal vector of new and present triangle
    1495         for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) {
    1496           if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints
    1497             *out << Verbose(3) << "Target point is " << *(target->second) << ":" << endl;
    1498 
    1499             // first check direction, so that triangles don't intersect
    1500             VirtualNormalVector.CopyVector(&target->second->node->x);
    1501             VirtualNormalVector.SubtractVector(&BaseLineCenter); // points from center of base line to target
    1502             VirtualNormalVector.ProjectOntoPlane(&NormalVector);
    1503             TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1504             *out << Verbose(4) << "VirtualNormalVector is " << VirtualNormalVector << " and PropagationVector is " << PropagationVector << "." << endl;
    1505             if (TempAngle > (M_PI/2.)) { // no bends bigger than Pi/2 (90 degrees)
    1506               *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl;
    1507               continue;
    1508             } else
    1509               *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl;
    1510 
    1511             // check first and second endpoint (if any connecting line goes to target has at least not more than 1 triangle)
    1512             LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first);
    1513             LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first);
    1514             if (((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[0]->second->TrianglesCount == 2))) {
    1515               *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1516               continue;
    1517             }
    1518             if (((LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (LineChecker[1]->second->TrianglesCount == 2))) {
    1519               *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1520               continue;
    1521             }
    1522 
    1523             // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1524             if ((((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)))) {
    1525               *out << Verbose(4) << "Current target is peak!" << endl;
    1526               continue;
    1527             }
    1528 
    1529             // check for linear dependence
    1530             TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1531             TempVector.SubtractVector(&target->second->node->x);
    1532             helper.CopyVector(&baseline->second->endpoints[1]->node->x);
    1533             helper.SubtractVector(&target->second->node->x);
    1534             helper.ProjectOntoPlane(&TempVector);
    1535             if (fabs(helper.NormSquared()) < MYEPSILON) {
    1536               *out << Verbose(4) << "Chosen set of vectors is linear dependent." << endl;
    1537               continue;
    1538             }
    1539 
    1540             // in case NOT both were found, create virtually this triangle, get its normal vector, calculate angle
    1541             flag = true;
    1542             VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x);
    1543             TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1544             TempVector.AddVector(&baseline->second->endpoints[1]->node->x);
    1545             TempVector.AddVector(&target->second->node->x);
    1546             TempVector.Scale(1./3.);
    1547             TempVector.SubtractVector(MolCenter);
    1548             // make it always point outward
    1549             if (VirtualNormalVector.Projection(&TempVector) < 0)
    1550               VirtualNormalVector.Scale(-1.);
    1551             // calculate angle
    1552             TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1553             *out << Verbose(4) << "NormalVector is " << VirtualNormalVector << " and the angle is " << TempAngle << "." << endl;
    1554             if ((SmallestAngle - TempAngle) > MYEPSILON) { // set to new possible winner
    1555               SmallestAngle = TempAngle;
    1556               winner = target;
    1557               *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;
    1558             } else if (fabs(SmallestAngle - TempAngle) < MYEPSILON) { // check the angle to propagation, both possible targets are in one plane! (their normals have same angle)
    1559               // hence, check the angles to some normal direction from our base line but in this common plane of both targets...
    1560               helper.CopyVector(&target->second->node->x);
    1561               helper.SubtractVector(&BaseLineCenter);
    1562               helper.ProjectOntoPlane(&BaseLine);
    1563               // ...the one with the smaller angle is the better candidate
    1564               TempVector.CopyVector(&target->second->node->x);
    1565               TempVector.SubtractVector(&BaseLineCenter);
    1566               TempVector.ProjectOntoPlane(&VirtualNormalVector);
    1567               TempAngle = TempVector.Angle(&helper);
    1568               TempVector.CopyVector(&winner->second->node->x);
    1569               TempVector.SubtractVector(&BaseLineCenter);
    1570               TempVector.ProjectOntoPlane(&VirtualNormalVector);
    1571               if (TempAngle < TempVector.Angle(&helper)) {
    1572                 TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1573                 SmallestAngle = TempAngle;
    1574                 winner = target;
    1575                 *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle " << TempAngle << " to propagation direction." << endl;
    1576               } else
    1577                 *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction." << endl;
    1578             } else
    1579               *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;
    1580           }
    1581         } // end of loop over all boundary points
    1582 
    1583         // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle
    1584         if (winner != PointsOnBoundary.end()) {
    1585           *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl;
    1586           // create the lins of not yet present
    1587           BLS[0] = baseline->second;
    1588           // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1589           LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first);
    1590           LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first);
    1591           if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create
    1592             BPS[0] = baseline->second->endpoints[0];
    1593             BPS[1] = winner->second;
    1594             BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1595             LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[1]));
    1596             LinesOnBoundaryCount++;
    1597           } else
    1598             BLS[1] = LineChecker[0]->second;
    1599           if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create
    1600             BPS[0] = baseline->second->endpoints[1];
    1601             BPS[1] = winner->second;
    1602             BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1603             LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[2]));
    1604             LinesOnBoundaryCount++;
    1605           } else
    1606             BLS[2] = LineChecker[1]->second;
    1607           BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1608           TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1609           TrianglesOnBoundaryCount++;
    1610         } else {
    1611           *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl;
    1612         }
    1613 
    1614         // 5d. If the set of lines is not yet empty, go to 5. and continue
    1615       } else
    1616         *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl;
    1617   } while (flag);
    1618 
    1619   // exit
    1620   delete(MolCenter);
    1621 };
    1622 
    1623 /** Inserts all atoms outside of the tesselated surface into it by adding new triangles.
    1624  * \param *out output stream for debugging
    1625  * \param *mol molecule structure with atoms
    1626  * \return true - all straddling points insert, false - something went wrong
    1627  */
    1628 bool Tesselation::InsertStraddlingPoints(ofstream *out, molecule *mol)
    1629 {
    1630   Vector Intersection;
    1631   atom *Walker = mol->start;
    1632   Vector *MolCenter = mol->DetermineCenterOfAll(out);
    1633   while (Walker->next != mol->end) {  // we only have to go once through all points, as boundary can become only bigger
    1634     // get the next triangle
    1635     BTS = FindClosestTriangleToPoint(out, &Walker->x);
    1636     if (BTS == NULL) {
    1637       *out << Verbose(1) << "ERROR: No triangle closest to " << Walker << " was found." << endl;
    1638       return false;
    1639     }
    1640     // get the intersection point
    1641     if (BTS->GetIntersectionInsideTriangle(out, MolCenter, &Walker->x, &Intersection)) {
    1642       // we have the intersection, check whether in- or outside of boundary
    1643       if ((MolCenter->DistanceSquared(&Walker->x) - MolCenter->DistanceSquared(&Intersection)) < -MYEPSILON) {
    1644         // inside, next!
    1645         *out << Verbose(4) << Walker << " is inside wrt triangle " << BTS << "." << endl;
    1646       } else {
    1647         // outside!
    1648         *out << Verbose(3) << Walker << " is outside wrt triangle " << BTS << "." << endl;
    1649         class BoundaryLineSet *OldLines[3], *NewLines[3];
    1650         class BoundaryPointSet *OldPoints[3], *NewPoint;
    1651         // store the three old lines and old points
    1652         for (int i=0;i<3;i++) {
    1653           OldLines[i] = BTS->lines[i];
    1654           OldPoints[i] = BTS->endpoints[i];
    1655         }
    1656         // add Walker to boundary points
    1657         AddPoint(Walker);
    1658         if (BPS[0] == NULL)
    1659           NewPoint = BPS[0];
    1660         else
    1661           continue;
    1662         // remove triangle
    1663         TrianglesOnBoundary.erase(BTS->Nr);
    1664         // create three new boundary lines
    1665         for (int i=0;i<3;i++) {
    1666           BPS[0] = NewPoint;
    1667           BPS[1] = OldPoints[i];
    1668           NewLines[i] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1669           LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, NewLines[i])); // no need for check for unique insertion as BPS[0] is definitely a new one
    1670           LinesOnBoundaryCount++;
    1671         }
    1672         // create three new triangle with new point
    1673         for (int i=0;i<3;i++) { // find all baselines
    1674           BLS[0] = OldLines[i];
    1675           int n = 1;
    1676           for (int j=0;j<3;j++) {
    1677             if (NewLines[j]->IsConnectedTo(BLS[0])) {
    1678               if (n>2) {
    1679                 *out << Verbose(1) << "ERROR: " << BLS[0] << " connects to all of the new lines?!" << endl;
    1680                 return false;
    1681               } else
    1682                 BLS[n++] = NewLines[j];
    1683             }
    1684           }
    1685           // create the triangle
    1686           BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1687           TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1688           TrianglesOnBoundaryCount++;
    1689         }
    1690       }
    1691     } else { // something is wrong with FindClosestTriangleToPoint!
    1692       *out << Verbose(1) << "ERROR: The closest triangle did not produce an intersection!" << endl;
    1693       return false;
    1694     }
    1695   }
    1696 
    1697   // exit
    1698   delete(MolCenter);
    1699   return true;
    1700 };
    1701 
    1702 /** Goes over all baselines and checks whether adjacent triangles and convex to each other.
    1703  * \param *out output stream for debugging
    1704  * \return true - all baselines were corrected, false - there are still concave pieces
    1705  */
    1706 bool Tesselation::CorrectConcaveBaselines(ofstream *out)
    1707 {
    1708   class BoundaryTriangleSet *triangle[2];
    1709   class BoundaryLineSet *OldLines[4], *NewLine;
    1710   class BoundaryPointSet *OldPoints[2];
    1711   Vector BaseLineNormal;
    1712   class BoundaryLineSet *Base = NULL;
    1713   int OldTriangles[2], OldBaseLine;
    1714   int i;
    1715   for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) {
    1716     Base = baseline->second;
    1717 
    1718     // check convexity
    1719     if (Base->CheckConvexityCriterion(out)) { // triangles are convex
    1720       *out << Verbose(3) << Base << " has two convex triangles." << endl;
    1721     } else { // not convex!
    1722       // get the two triangles
    1723       i=0;
    1724       for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)
    1725         triangle[i++] = runner->second;
    1726       // gather four endpoints and four lines
    1727       for (int j=0;j<4;j++)
    1728         OldLines[j] = NULL;
    1729       for (int j=0;j<2;j++)
    1730         OldPoints[j] = NULL;
    1731       i=0;
    1732       for (int m=0;m<2;m++) { // go over both triangles
    1733         for (int j=0;j<3;j++) { // all of their endpoints and baselines
    1734           if (triangle[m]->lines[j] != Base) // pick not the central baseline
    1735             OldLines[i++] = triangle[m]->lines[j];
    1736           if (!Base->ContainsBoundaryPoint(triangle[m]->endpoints[j])) // and neither of its endpoints
    1737             OldPoints[m] = triangle[m]->endpoints[j];
    1738         }
    1739       }
    1740       if (i<4) {
    1741         *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1742         return false;
    1743       }
    1744       for (int j=0;j<4;j++)
    1745         if (OldLines[j] == NULL) {
    1746           *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1747           return false;
    1748         }
    1749       for (int j=0;j<2;j++)
    1750         if (OldPoints[j] == NULL) {
    1751           *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl;
    1752           return false;
    1753         }
    1754 
    1755       // remove triangles
    1756       for (int j=0;j<2;j++) {
    1757         OldTriangles[j] = triangle[j]->Nr;
    1758         TrianglesOnBoundary.erase(OldTriangles[j]);
    1759         triangle[j] = NULL;
    1760       }
    1761 
    1762       // remove baseline
    1763       OldBaseLine = Base->Nr;
    1764       LinesOnBoundary.erase(OldBaseLine);
    1765       Base = NULL;
    1766 
    1767       // construct new baseline (with same number as old one)
    1768       BPS[0] = OldPoints[0];
    1769       BPS[1] = OldPoints[1];
    1770       NewLine = new class BoundaryLineSet(BPS, OldBaseLine);
    1771       LinesOnBoundary.insert(LinePair(OldBaseLine, NewLine)); // no need for check for unique insertion as NewLine is definitely a new one
    1772 
    1773       // construct new triangles with flipped baseline
    1774       i=-1;
    1775       if (BLS[0]->IsConnectedTo(OldLines[2]))
    1776         i=2;
    1777       if (BLS[0]->IsConnectedTo(OldLines[2]))
    1778         i=3;
    1779       if (i!=-1) {
    1780         BLS[0] = OldLines[0];
    1781         BLS[1] = OldLines[i];
    1782         BLS[2] = NewLine;
    1783         BTS = new class BoundaryTriangleSet(BLS, OldTriangles[0]);
    1784         TrianglesOnBoundary.insert(TrianglePair(OldTriangles[0], BTS));
    1785 
    1786         BLS[0] = (i==2 ? OldLines[3] : OldLines[2]);
    1787         BLS[1] = OldLines[1];
    1788         BLS[2] = NewLine;
    1789         BTS = new class BoundaryTriangleSet(BLS, OldTriangles[1]);
    1790         TrianglesOnBoundary.insert(TrianglePair(OldTriangles[1], BTS));
    1791       } else {
    1792         *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl;
    1793         return false;
    1794       }
    1795     }
    1796   }
    1797   return true;
    1798 };
    1799 
    1800 
    1801 /** States whether point is in- or outside of a tesselated surface.
    1802  * \param *pointer point to be checked
    1803  * \return true - is inside, false - is outside
    1804  */
    1805 bool Tesselation::IsInside(Vector *pointer)
    1806 {
    1807 
    1808   // hier kommt dann Saskias Routine hin...
    1809 
    1810   return true;
    1811 };
    1812 
    1813 /** Finds the closest triangle to a given point.
    1814  * \param *out output stream for debugging
    1815  * \param *x second endpoint of line
    1816  * \return pointer triangle that is closest, NULL if none was found
    1817  */
    1818 class BoundaryTriangleSet * Tesselation::FindClosestTriangleToPoint(ofstream *out, Vector *x)
    1819 {
    1820   class BoundaryTriangleSet *triangle = NULL;
    1821 
    1822   // hier kommt dann Saskias Routine hin...
    1823 
    1824   return triangle;
    1825 };
    1826 
    1827 /** Adds an atom to the tesselation::PointsOnBoundary list.
    1828  * \param *Walker atom to add
    1829  */
    1830 void
    1831 Tesselation::AddPoint(atom *Walker)
    1832 {
    1833   PointTestPair InsertUnique;
    1834   BPS[0] = new class BoundaryPointSet(Walker);
    1835   InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1836   if (InsertUnique.second) // if new point was not present before, increase counter
    1837     PointsOnBoundaryCount++;
    1838   else {
    1839     delete(BPS[0]);
    1840     BPS[0] = NULL;
    1841   }
    1842 }
    1843 ;
    1844 
    1845 /** Adds point to Tesselation::PointsOnBoundary if not yet present.
    1846  * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique.
    1847  * @param Candidate point to add
    1848  * @param n index for this point in Tesselation::TPS array
    1849  */
    1850 void
    1851 Tesselation::AddTrianglePoint(atom* Candidate, int n)
    1852 {
    1853   PointTestPair InsertUnique;
    1854   TPS[n] = new class BoundaryPointSet(Candidate);
    1855   InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
    1856   if (InsertUnique.second) { // if new point was not present before, increase counter
    1857     PointsOnBoundaryCount++;
    1858   } else {
    1859     delete TPS[n];
    1860     cout << Verbose(3) << "Atom " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;
    1861     TPS[n] = (InsertUnique.first)->second;
    1862   }
    1863 }
    1864 ;
    1865 
    1866 /** Function tries to add line from current Points in BPS to BoundaryLineSet.
    1867  * If successful it raises the line count and inserts the new line into the BLS,
    1868  * if unsuccessful, it writes the line which had been present into the BLS, deleting the new constructed one.
    1869  * @param *a first endpoint
    1870  * @param *b second endpoint
    1871  * @param n index of Tesselation::BLS giving the line with both endpoints
    1872  */
    1873 void Tesselation::AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) {
    1874   bool insertNewLine = true;
    1875 
    1876   if (a->lines.find(b->node->nr) != a->lines.end()) {
    1877     LineMap::iterator FindLine;
    1878     pair<LineMap::iterator,LineMap::iterator> FindPair;
    1879     FindPair = a->lines.equal_range(b->node->nr);
    1880 
    1881     for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
    1882       // If there is a line with less than two attached triangles, we don't need a new line.
    1883       if (FindLine->second->TrianglesCount < 2) {
    1884         insertNewLine = false;
    1885         cout << Verbose(3) << "Using existing line " << *FindLine->second << endl;
    1886 
    1887         BPS[0] = FindLine->second->endpoints[0];
    1888         BPS[1] = FindLine->second->endpoints[1];
    1889         BLS[n] = FindLine->second;
    1890 
    1891         break;
    1892       }
    1893     }
    1894   }
    1895 
    1896   if (insertNewLine) {
    1897     AlwaysAddTriangleLine(a, b, n);
    1898   }
    1899 }
    1900 ;
    1901 
    1902 /**
    1903  * Adds lines from each of the current points in the BPS to BoundaryLineSet.
    1904  * Raises the line count and inserts the new line into the BLS.
    1905  *
    1906  * @param *a first endpoint
    1907  * @param *b second endpoint
    1908  * @param n index of Tesselation::BLS giving the line with both endpoints
    1909  */
    1910 void Tesselation::AlwaysAddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n)
    1911 {
    1912   cout << Verbose(3) << "Adding line between " << *(a->node) << " and " << *(b->node) << "." << endl;
    1913   BPS[0] = a;
    1914   BPS[1] = b;
    1915   BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);  // this also adds the line to the local maps
    1916   // add line to global map
    1917   LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
    1918   // increase counter
    1919   LinesOnBoundaryCount++;
    1920 };
    1921 
    1922 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm).
    1923  * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later.
    1924  */
    1925 void
    1926 Tesselation::AddTriangle()
    1927 {
    1928   cout << Verbose(1) << "Adding triangle to global TrianglesOnBoundary map." << endl;
    1929 
    1930   // add triangle to global map
    1931   TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1932   TrianglesOnBoundaryCount++;
    1933 
    1934   // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet
    1935 }
    1936 ;
    1937 
    1938 
    1939 double det_get(gsl_matrix *A, int inPlace) {
    1940   /*
    1941   inPlace = 1 => A is replaced with the LU decomposed copy.
    1942   inPlace = 0 => A is retained, and a copy is used for LU.
    1943   */
    1944 
    1945   double det;
    1946   int signum;
    1947   gsl_permutation *p = gsl_permutation_alloc(A->size1);
    1948   gsl_matrix *tmpA;
    1949 
    1950   if (inPlace)
    1951   tmpA = A;
    1952   else {
    1953   gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
    1954   gsl_matrix_memcpy(tmpA , A);
    1955   }
    1956 
    1957 
    1958   gsl_linalg_LU_decomp(tmpA , p , &signum);
    1959   det = gsl_linalg_LU_det(tmpA , signum);
    1960   gsl_permutation_free(p);
    1961   if (! inPlace)
    1962   gsl_matrix_free(tmpA);
    1963 
    1964   return det;
    1965 };
    1966 
    1967 void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
    1968 {
    1969   gsl_matrix *A = gsl_matrix_calloc(3,3);
    1970   double m11, m12, m13, m14;
    1971 
    1972   for(int i=0;i<3;i++) {
    1973     gsl_matrix_set(A, i, 0, a.x[i]);
    1974     gsl_matrix_set(A, i, 1, b.x[i]);
    1975     gsl_matrix_set(A, i, 2, c.x[i]);
    1976   }
    1977   m11 = det_get(A, 1);
    1978 
    1979   for(int i=0;i<3;i++) {
    1980     gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1981     gsl_matrix_set(A, i, 1, b.x[i]);
    1982     gsl_matrix_set(A, i, 2, c.x[i]);
    1983   }
    1984   m12 = det_get(A, 1);
    1985 
    1986   for(int i=0;i<3;i++) {
    1987     gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1988     gsl_matrix_set(A, i, 1, a.x[i]);
    1989     gsl_matrix_set(A, i, 2, c.x[i]);
    1990   }
    1991   m13 = det_get(A, 1);
    1992 
    1993   for(int i=0;i<3;i++) {
    1994     gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1995     gsl_matrix_set(A, i, 1, a.x[i]);
    1996     gsl_matrix_set(A, i, 2, b.x[i]);
    1997   }
    1998   m14 = det_get(A, 1);
    1999 
    2000   if (fabs(m11) < MYEPSILON)
    2001     cerr << "ERROR: three points are colinear." << endl;
    2002 
    2003   center->x[0] =  0.5 * m12/ m11;
    2004   center->x[1] = -0.5 * m13/ m11;
    2005   center->x[2] =  0.5 * m14/ m11;
    2006 
    2007   if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
    2008     cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
    2009 
    2010   gsl_matrix_free(A);
    2011 };
    2012 
    2013 
    2014 
    2015 /**
    2016  * Function returns center of sphere with RADIUS, which rests on points a, b, c
    2017  * @param Center this vector will be used for return
    2018  * @param a vector first point of triangle
    2019  * @param b vector second point of triangle
    2020  * @param c vector third point of triangle
    2021  * @param *Umkreismittelpunkt new cneter point of circumference
    2022  * @param Direction vector indicates up/down
    2023  * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle
    2024  * @param Halfplaneindicator double indicates whether Direction is up or down
    2025  * @param AlternativeIndicator doube indicates in case of orthogonal triangles which direction of AlternativeDirection is suitable
    2026  * @param alpha double angle at a
    2027  * @param beta double, angle at b
    2028  * @param gamma, double, angle at c
    2029  * @param Radius, double
    2030  * @param Umkreisradius double radius of circumscribing circle
    2031  */
    2032 void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
    2033     double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    2034 {
    2035   Vector TempNormal, helper;
    2036   double Restradius;
    2037   Vector OtherCenter;
    2038   cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
    2039   Center->Zero();
    2040   helper.CopyVector(&a);
    2041   helper.Scale(sin(2.*alpha));
    2042   Center->AddVector(&helper);
    2043   helper.CopyVector(&b);
    2044   helper.Scale(sin(2.*beta));
    2045   Center->AddVector(&helper);
    2046   helper.CopyVector(&c);
    2047   helper.Scale(sin(2.*gamma));
    2048   Center->AddVector(&helper);
    2049   //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    2050   Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    2051   NewUmkreismittelpunkt->CopyVector(Center);
    2052   cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
    2053   // Here we calculated center of circumscribing circle, using barycentric coordinates
    2054   cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
    2055 
    2056   TempNormal.CopyVector(&a);
    2057   TempNormal.SubtractVector(&b);
    2058   helper.CopyVector(&a);
    2059   helper.SubtractVector(&c);
    2060   TempNormal.VectorProduct(&helper);
    2061   if (fabs(HalfplaneIndicator) < MYEPSILON)
    2062     {
    2063       if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    2064         {
    2065           TempNormal.Scale(-1);
    2066         }
    2067     }
    2068   else
    2069     {
    2070       if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    2071         {
    2072           TempNormal.Scale(-1);
    2073         }
    2074     }
    2075 
    2076   TempNormal.Normalize();
    2077   Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    2078   cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
    2079   TempNormal.Scale(Restradius);
    2080   cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
    2081 
    2082   Center->AddVector(&TempNormal);
    2083   cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
    2084   get_sphere(&OtherCenter, a, b, c, RADIUS);
    2085   cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
    2086   cout << Verbose(3) << "End of Get_center_of_sphere.\n";
    2087 };
    2088 
    2089 
    2090 /** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c.
    2091  * \param *Center new center on return
    2092  * \param *a first point
    2093  * \param *b second point
    2094  * \param *c third point
    2095  */
    2096 void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
    2097 {
    2098   Vector helper;
    2099   double alpha, beta, gamma;
    2100   Vector SideA, SideB, SideC;
    2101   SideA.CopyVector(b);
    2102   SideA.SubtractVector(c);
    2103   SideB.CopyVector(c);
    2104   SideB.SubtractVector(a);
    2105   SideC.CopyVector(a);
    2106   SideC.SubtractVector(b);
    2107   alpha = M_PI - SideB.Angle(&SideC);
    2108   beta = M_PI - SideC.Angle(&SideA);
    2109   gamma = M_PI - SideA.Angle(&SideB);
    2110   //cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
    2111   if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
    2112     cerr << "GetCenterofCircumcircle: Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
    2113 
    2114   Center->Zero();
    2115   helper.CopyVector(a);
    2116   helper.Scale(sin(2.*alpha));
    2117   Center->AddVector(&helper);
    2118   helper.CopyVector(b);
    2119   helper.Scale(sin(2.*beta));
    2120   Center->AddVector(&helper);
    2121   helper.CopyVector(c);
    2122   helper.Scale(sin(2.*gamma));
    2123   Center->AddVector(&helper);
    2124   Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    2125 };
    2126 
    2127 /** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius.
    2128  * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter.
    2129  * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection.
    2130  * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter).
    2131  * \param CircleCenter Center of the parameter circle
    2132  * \param CirclePlaneNormal normal vector to plane of the parameter circle
    2133  * \param CircleRadius radius of the parameter circle
    2134  * \param NewSphereCenter new center of a circumcircle
    2135  * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle
    2136  * \param NormalVector normal vector
    2137  * \param SearchDirection search direction to make angle unique on return.
    2138  * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails
    2139  */
    2140 double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
    2141 {
    2142   Vector helper;
    2143   double radius, alpha;
    2144 
    2145   helper.CopyVector(&NewSphereCenter);
    2146   // test whether new center is on the parameter circle's plane
    2147   if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2148     cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))  << "!" << endl;
    2149     helper.ProjectOntoPlane(&CirclePlaneNormal);
    2150   }
    2151   radius = helper.ScalarProduct(&helper);
    2152   // test whether the new center vector has length of CircleRadius
    2153   if (fabs(radius - CircleRadius) > HULLEPSILON)
    2154     cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2155   alpha = helper.Angle(&OldSphereCenter);
    2156   // make the angle unique by checking the halfplanes/search direction
    2157   if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
    2158     alpha = 2.*M_PI - alpha;
    2159   //cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
    2160   radius = helper.Distance(&OldSphereCenter);
    2161   helper.ProjectOntoPlane(&NormalVector);
    2162   // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
    2163   if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
    2164     //cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
    2165     return alpha;
    2166   } else {
    2167     //cout << Verbose(1) << "INFO: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
    2168     return 2.*M_PI;
    2169   }
    2170 };
    2171 
    2172 
    2173 /** Checks whether the triangle consisting of the three atoms is already present.
    2174  * Searches for the points in Tesselation::PointsOnBoundary and checks their
    2175  * lines. If any of the three edges already has two triangles attached, false is
    2176  * returned.
    2177  * \param *out output stream for debugging
    2178  * \param *Candidates endpoints of the triangle candidate
    2179  * \return integer 0 if no triangle exists, 1 if one triangle exists, 2 if two
    2180  *                 triangles exist which is the maximum for three points
    2181  */
    2182 int Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
    2183 // TODO: use findTriangles here and return result.size();
    2184   LineMap::iterator FindLine;
    2185   PointMap::iterator FindPoint;
    2186   TriangleMap::iterator FindTriangle;
    2187   int adjacentTriangleCount = 0;
    2188   class BoundaryPointSet *Points[3];
    2189 
    2190   //*out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
    2191   // builds a triangle point set (Points) of the end points
    2192   for (int i = 0; i < 3; i++) {
    2193     FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
    2194     if (FindPoint != PointsOnBoundary.end()) {
    2195       Points[i] = FindPoint->second;
    2196     } else {
    2197       Points[i] = NULL;
    2198     }
    2199   }
    2200 
    2201   // checks lines between the points in the Points for their adjacent triangles
    2202   for (int i = 0; i < 3; i++) {
    2203     if (Points[i] != NULL) {
    2204       for (int j = i; j < 3; j++) {
    2205         if (Points[j] != NULL) {
    2206           FindLine = Points[i]->lines.find(Points[j]->node->nr);
    2207           if (FindLine != Points[i]->lines.end()) {
    2208             for (; FindLine->first == Points[j]->node->nr; FindLine++) {
    2209               FindTriangle = FindLine->second->triangles.begin();
    2210               for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {
    2211                 if ((
    2212                   (FindTriangle->second->endpoints[0] == Points[0])
    2213                     || (FindTriangle->second->endpoints[0] == Points[1])
    2214                     || (FindTriangle->second->endpoints[0] == Points[2])
    2215                   ) && (
    2216                     (FindTriangle->second->endpoints[1] == Points[0])
    2217                     || (FindTriangle->second->endpoints[1] == Points[1])
    2218                     || (FindTriangle->second->endpoints[1] == Points[2])
    2219                   ) && (
    2220                     (FindTriangle->second->endpoints[2] == Points[0])
    2221                     || (FindTriangle->second->endpoints[2] == Points[1])
    2222                     || (FindTriangle->second->endpoints[2] == Points[2])
    2223                   )
    2224                 ) {
    2225                   adjacentTriangleCount++;
    2226                 }
    2227               }
    2228             }
    2229             // Only one of the triangle lines must be considered for the triangle count.
    2230             *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
    2231             return adjacentTriangleCount;
    2232 
    2233           }
    2234         }
    2235       }
    2236     }
    2237   }
    2238 
    2239   *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
    2240   return adjacentTriangleCount;
    2241 };
    2242 
    2243 /** This recursive function finds a third point, to form a triangle with two given ones.
    2244  * Note that this function is for the starting triangle.
    2245  * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points
    2246  * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then
    2247  * the center of the sphere is still fixed up to a single parameter. The band of possible values
    2248  * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives
    2249  * us the "null" on this circle, the new center of the candidate point will be some way along this
    2250  * circle. The shorter the way the better is the candidate. Note that the direction is clearly given
    2251  * by the normal vector of the base triangle that always points outwards by construction.
    2252  * Hence, we construct a Center of this circle which sits right in the middle of the current base line.
    2253  * We construct the normal vector that defines the plane this circle lies in, it is just in the
    2254  * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest
    2255  * with respect to the length of the baseline and the sphere's fixed \a RADIUS.
    2256  * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center
    2257  * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check
    2258  * both.
    2259  * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check
    2260  * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check
    2261  * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal
    2262  * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality
    2263  * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether
    2264  * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).
    2265  * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle())
    2266  * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine
    2267  * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle
    2268  * @param BaseLine BoundaryLineSet with the current base line
    2269  * @param ThirdNode third atom to avoid in search
    2270  * @param candidates list of equally good candidates to return
    2271  * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
    2272  * @param RADIUS radius of sphere
    2273  * @param *LC LinkedCell structure with neighbouring atoms
    2274  */
    2275 void Find_third_point_for_Tesselation(
    2276   Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter,
    2277   class BoundaryLineSet *BaseLine, atom *ThirdNode, CandidateList* &candidates,
    2278   double *ShortestAngle, const double RADIUS, LinkedCell *LC
    2279 ) {
    2280   Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
    2281   Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    2282   Vector SphereCenter;
    2283   Vector NewSphereCenter;   // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    2284   Vector OtherNewSphereCenter;   // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    2285   Vector NewNormalVector;   // normal vector of the Candidate's triangle
    2286   Vector helper, OptCandidateCenter, OtherOptCandidateCenter;
    2287   LinkedAtoms *List = NULL;
    2288   double CircleRadius; // radius of this circle
    2289   double radius;
    2290   double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    2291   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2292   atom *Candidate = NULL;
    2293   CandidateForTesselation *optCandidate = NULL;
    2294 
    2295   cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
    2296 
    2297   //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    2298 
    2299   // construct center of circle
    2300   CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2301   CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2302   CircleCenter.Scale(0.5);
    2303 
    2304   // construct normal vector of circle
    2305   CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2306   CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    2307 
    2308   // calculate squared radius atom *ThirdNode,f circle
    2309   radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2310   if (radius/4. < RADIUS*RADIUS) {
    2311     CircleRadius = RADIUS*RADIUS - radius/4.;
    2312     CirclePlaneNormal.Normalize();
    2313     //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2314 
    2315     // test whether old center is on the band's plane
    2316     if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2317       cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2318       OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2319     }
    2320     radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2321     if (fabs(radius - CircleRadius) < HULLEPSILON) {
    2322 
    2323       // check SearchDirection
    2324       //cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2325       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
    2326         cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
    2327       }
    2328 
    2329       // get cell for the starting atom
    2330       if (LC->SetIndexToVector(&CircleCenter)) {
    2331         for(int i=0;i<NDIM;i++) // store indices of this cell
    2332         N[i] = LC->n[i];
    2333         //cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2334       } else {
    2335         cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2336         return;
    2337       }
    2338       // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2339       //cout << Verbose(2) << "LC Intervals:";
    2340       for (int i=0;i<NDIM;i++) {
    2341         Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2342         Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2343         //cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2344       }
    2345       //cout << endl;
    2346       for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2347         for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2348           for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2349             List = LC->GetCurrentCell();
    2350             //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2351             if (List != NULL) {
    2352               for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2353                 Candidate = (*Runner);
    2354 
    2355                 // check for three unique points
    2356                 //cout << Verbose(2) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    2357                 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) ){
    2358 
    2359                   // construct both new centers
    2360                   GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2361                   OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    2362 
    2363                   if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)))
    2364                   && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)
    2365                   ) {
    2366                     helper.CopyVector(&NewNormalVector);
    2367                     //cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2368                     radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2369                     if (radius < RADIUS*RADIUS) {
    2370                       helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2371                       //cout << Verbose(2) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << " with sphere radius " << RADIUS << "." << endl;
    2372                       NewSphereCenter.AddVector(&helper);
    2373                       NewSphereCenter.SubtractVector(&CircleCenter);
    2374                       //cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    2375 
    2376                       // OtherNewSphereCenter is created by the same vector just in the other direction
    2377                       helper.Scale(-1.);
    2378                       OtherNewSphereCenter.AddVector(&helper);
    2379                       OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2380                       //cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    2381 
    2382                       alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2383                       Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2384                       alpha = min(alpha, Otheralpha);
    2385                       // if there is a better candidate, drop the current list and add the new candidate
    2386                       // otherwise ignore the new candidate and keep the list
    2387                       if (*ShortestAngle > (alpha - HULLEPSILON)) {
    2388                         optCandidate = new CandidateForTesselation(Candidate, BaseLine, OptCandidateCenter, OtherOptCandidateCenter);
    2389                         if (fabs(alpha - Otheralpha) > MYEPSILON) {
    2390                           optCandidate->OptCenter.CopyVector(&NewSphereCenter);
    2391                           optCandidate->OtherOptCenter.CopyVector(&OtherNewSphereCenter);
    2392                         } else {
    2393                           optCandidate->OptCenter.CopyVector(&OtherNewSphereCenter);
    2394                           optCandidate->OtherOptCenter.CopyVector(&NewSphereCenter);
    2395                         }
    2396                         // if there is an equal candidate, add it to the list without clearing the list
    2397                         if ((*ShortestAngle - HULLEPSILON) < alpha) {
    2398                           candidates->push_back(optCandidate);
    2399                           cout << Verbose(2) << "ACCEPT: We have found an equally good candidate: " << *(optCandidate->point) << " with "
    2400                             << alpha << " and circumsphere's center at " << optCandidate->OptCenter << "." << endl;
    2401                         } else {
    2402                           // remove all candidates from the list and then the list itself
    2403                           class CandidateForTesselation *remover = NULL;
    2404                           for (CandidateList::iterator it = candidates->begin(); it != candidates->end(); ++it) {
    2405                             remover = *it;
    2406                             delete(remover);
    2407                           }
    2408                           candidates->clear();
    2409                           candidates->push_back(optCandidate);
    2410                           cout << Verbose(2) << "ACCEPT: We have found a better candidate: " << *(optCandidate->point) << " with "
    2411                             << alpha << " and circumsphere's center at " << optCandidate->OptCenter << "." << endl;
    2412                         }
    2413                         *ShortestAngle = alpha;
    2414                         //cout << Verbose(2) << "INFO: There are " << candidates->size() << " candidates in the list now." << endl;
    2415                       } else {
    2416                         if ((optCandidate != NULL) && (optCandidate->point != NULL)) {
    2417                           //cout << Verbose(2) << "REJECT: Old candidate: " << *(optCandidate->point) << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2418                         } else {
    2419                           //cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2420                         }
    2421                       }
    2422 
    2423                     } else {
    2424                       //cout << Verbose(2) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2425                     }
    2426                   } else {
    2427                     //cout << Verbose(2) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2428                   }
    2429                 } else {
    2430                   if (ThirdNode != NULL) {
    2431                     //cout << Verbose(2) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
    2432                   } else {
    2433                     //cout << Verbose(2) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
    2434                   }
    2435                 }
    2436               }
    2437             }
    2438           }
    2439     } else {
    2440       cerr << Verbose(2) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2441     }
    2442   } else {
    2443     if (ThirdNode != NULL)
    2444       cout << Verbose(2) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
    2445     else
    2446       cout << Verbose(2) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
    2447   }
    2448 
    2449   //cout << Verbose(2) << "INFO: Sorting candidate list ..." << endl;
    2450   if (candidates->size() > 1) {
    2451     candidates->unique();
    2452     candidates->sort(sortCandidates);
    2453   }
    2454 
    2455   cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
    2456 };
    2457 
    2458 struct Intersection {
    2459   Vector x1;
    2460   Vector x2;
    2461   Vector x3;
    2462   Vector x4;
    2463 };
    2464 
    2465 /**
    2466  * Intersection calculation function.
    2467  *
    2468  * @param x to find the result for
    2469  * @param function parameter
    2470  */
    2471 double MinIntersectDistance(const gsl_vector * x, void *params) {
    2472   double retval = 0;
    2473   struct Intersection *I = (struct Intersection *)params;
    2474   Vector intersection;
    2475   Vector SideA,SideB,HeightA, HeightB;
    2476   for (int i=0;i<NDIM;i++)
    2477     intersection.x[i] = gsl_vector_get(x, i);
    2478 
    2479   SideA.CopyVector(&(I->x1));
    2480   SideA.SubtractVector(&I->x2);
    2481   HeightA.CopyVector(&intersection);
    2482   HeightA.SubtractVector(&I->x1);
    2483   HeightA.ProjectOntoPlane(&SideA);
    2484 
    2485   SideB.CopyVector(&I->x3);
    2486   SideB.SubtractVector(&I->x4);
    2487   HeightB.CopyVector(&intersection);
    2488   HeightB.SubtractVector(&I->x3);
    2489   HeightB.ProjectOntoPlane(&SideB);
    2490 
    2491   retval = HeightA.ScalarProduct(&HeightA) + HeightB.ScalarProduct(&HeightB);
    2492   //cout << Verbose(2) << "MinIntersectDistance called, result: " << retval << endl;
    2493 
    2494   return retval;
    2495 };
    2496 
    2497 
    2498 /**
    2499  * Calculates whether there is an intersection between two lines. The first line
    2500  * always goes through point 1 and point 2 and the second line is given by the
    2501  * connection between point 4 and point 5.
    2502  *
    2503  * @param point 1 of line 1
    2504  * @param point 2 of line 1
    2505  * @param point 1 of line 2
    2506  * @param point 2 of line 2
    2507  *
    2508  * @return true if there is an intersection between the given lines, false otherwise
    2509  */
    2510 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4) {
    2511   bool result;
    2512 
    2513   struct Intersection par;
    2514     par.x1.CopyVector(&point1);
    2515     par.x2.CopyVector(&point2);
    2516     par.x3.CopyVector(&point3);
    2517     par.x4.CopyVector(&point4);
    2518 
    2519     const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
    2520     gsl_multimin_fminimizer *s = NULL;
    2521     gsl_vector *ss, *x;
    2522     gsl_multimin_function minex_func;
    2523 
    2524     size_t iter = 0;
    2525     int status;
    2526     double size;
    2527 
    2528     /* Starting point */
    2529     x = gsl_vector_alloc(NDIM);
    2530     gsl_vector_set(x, 0, point1.x[0]);
    2531     gsl_vector_set(x, 1, point1.x[1]);
    2532     gsl_vector_set(x, 2, point1.x[2]);
    2533 
    2534     /* Set initial step sizes to 1 */
    2535     ss = gsl_vector_alloc(NDIM);
    2536     gsl_vector_set_all(ss, 1.0);
    2537 
    2538     /* Initialize method and iterate */
    2539     minex_func.n = NDIM;
    2540     minex_func.f = &MinIntersectDistance;
    2541     minex_func.params = (void *)&par;
    2542 
    2543     s = gsl_multimin_fminimizer_alloc(T, NDIM);
    2544     gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
    2545 
    2546     do {
    2547         iter++;
    2548         status = gsl_multimin_fminimizer_iterate(s);
    2549 
    2550         if (status) {
    2551           break;
    2552         }
    2553 
    2554         size = gsl_multimin_fminimizer_size(s);
    2555         status = gsl_multimin_test_size(size, 1e-2);
    2556 
    2557         if (status == GSL_SUCCESS) {
    2558           cout << Verbose(2) << "converged to minimum" <<  endl;
    2559         }
    2560     } while (status == GSL_CONTINUE && iter < 100);
    2561 
    2562     // check whether intersection is in between or not
    2563   Vector intersection, SideA, SideB, HeightA, HeightB;
    2564   double t1, t2;
    2565   for (int i = 0; i < NDIM; i++) {
    2566     intersection.x[i] = gsl_vector_get(s->x, i);
    2567   }
    2568 
    2569   SideA.CopyVector(&par.x2);
    2570   SideA.SubtractVector(&par.x1);
    2571   HeightA.CopyVector(&intersection);
    2572   HeightA.SubtractVector(&par.x1);
    2573 
    2574   t1 = HeightA.Projection(&SideA)/SideA.ScalarProduct(&SideA);
    2575 
    2576   SideB.CopyVector(&par.x4);
    2577   SideB.SubtractVector(&par.x3);
    2578   HeightB.CopyVector(&intersection);
    2579   HeightB.SubtractVector(&par.x3);
    2580 
    2581   t2 = HeightB.Projection(&SideB)/SideB.ScalarProduct(&SideB);
    2582 
    2583   cout << Verbose(2) << "Intersection " << intersection << " is at "
    2584     << t1 << " for (" << point1 << "," << point2 << ") and at "
    2585     << t2 << " for (" << point3 << "," << point4 << "): ";
    2586 
    2587   if (((t1 >= 0) && (t1 <= 1)) && ((t2 >= 0) && (t2 <= 1))) {
    2588     cout << "true intersection." << endl;
    2589     result = true;
    2590   } else {
    2591     cout << "intersection out of region of interest." << endl;
    2592     result = false;
    2593   }
    2594 
    2595   // free minimizer stuff
    2596     gsl_vector_free(x);
    2597     gsl_vector_free(ss);
    2598     gsl_multimin_fminimizer_free(s);
    2599 
    2600   return result;
    2601 }
    2602 
    2603 /** Finds the second point of starting triangle.
    2604  * \param *a first atom
    2605  * \param *Candidate pointer to candidate atom on return
    2606  * \param Oben vector indicating the outside
    2607  * \param Opt_Candidate reference to recommended candidate on return
    2608  * \param Storage[3] array storing angles and other candidate information
    2609  * \param RADIUS radius of virtual sphere
    2610  * \param *LC LinkedCell structure with neighbouring atoms
    2611  */
    2612 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
    2613 {
    2614   cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
    2615   Vector AngleCheck;
    2616   double norm = -1., angle;
    2617   LinkedAtoms *List = NULL;
    2618   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2619 
    2620   if (LC->SetIndexToAtom(a)) {  // get cell for the starting atom
    2621     for(int i=0;i<NDIM;i++) // store indices of this cell
    2622       N[i] = LC->n[i];
    2623   } else {
    2624     cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
    2625     return;
    2626   }
    2627   // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2628   cout << Verbose(3) << "LC Intervals from [";
    2629   for (int i=0;i<NDIM;i++) {
    2630   cout << " " << N[i] << "<->" << LC->N[i];
    2631   }
    2632   cout << "] :";
    2633   for (int i=0;i<NDIM;i++) {
    2634     Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2635     Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2636     cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2637   }
    2638   cout << endl;
    2639 
    2640 
    2641   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2642     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2643       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2644         List = LC->GetCurrentCell();
    2645         //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2646         if (List != NULL) {
    2647           for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2648             Candidate = (*Runner);
    2649             // check if we only have one unique point yet ...
    2650             if (a != Candidate) {
    2651               // Calculate center of the circle with radius RADIUS through points a and Candidate
    2652               Vector OrthogonalizedOben, a_Candidate, Center;
    2653               double distance, scaleFactor;
    2654 
    2655               OrthogonalizedOben.CopyVector(&Oben);
    2656               a_Candidate.CopyVector(&(a->x));
    2657               a_Candidate.SubtractVector(&(Candidate->x));
    2658               OrthogonalizedOben.ProjectOntoPlane(&a_Candidate);
    2659               OrthogonalizedOben.Normalize();
    2660               distance = 0.5 * a_Candidate.Norm();
    2661               scaleFactor = sqrt(((RADIUS * RADIUS) - (distance * distance)));
    2662               OrthogonalizedOben.Scale(scaleFactor);
    2663 
    2664               Center.CopyVector(&(Candidate->x));
    2665               Center.AddVector(&(a->x));
    2666               Center.Scale(0.5);
    2667               Center.AddVector(&OrthogonalizedOben);
    2668 
    2669               AngleCheck.CopyVector(&Center);
    2670               AngleCheck.SubtractVector(&(a->x));
    2671               norm = a_Candidate.Norm();
    2672               // second point shall have smallest angle with respect to Oben vector
    2673               if (norm < RADIUS*2.) {
    2674                 angle = AngleCheck.Angle(&Oben);
    2675                 if (angle < Storage[0]) {
    2676                   //cout << Verbose(3) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
    2677                   cout << Verbose(3) << "Current candidate is " << *Candidate << ": Is a better candidate with distance " << norm << " and angle " << angle << " to oben " << Oben << ".\n";
    2678                   Opt_Candidate = Candidate;
    2679                   Storage[0] = angle;
    2680                   //cout << Verbose(3) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2681                 } else {
    2682                   //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
    2683                 }
    2684               } else {
    2685                 //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Refused due to Radius " << norm << endl;
    2686               }
    2687             } else {
    2688               //cout << Verbose(3) << "Current candidate is " << *Candidate << ": Candidate is equal to first endpoint." << *a << "." << endl;
    2689             }
    2690           }
    2691         } else {
    2692           cout << Verbose(3) << "Linked cell list is empty." << endl;
    2693         }
    2694       }
    2695   cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
    2696 };
    2697 
    2698 /** Finds the starting triangle for find_non_convex_border().
    2699  * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation()
    2700  * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third
    2701  * point are called.
    2702  * \param RADIUS radius of virtual rolling sphere
    2703  * \param *LC LinkedCell structure with neighbouring atoms
    2704  */
    2705 void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
    2706 {
    2707   cout << Verbose(1) << "Begin of Find_starting_triangle\n";
    2708   int i = 0;
    2709   LinkedAtoms *List = NULL;
    2710   atom* FirstPoint = NULL;
    2711   atom* SecondPoint = NULL;
    2712   atom* MaxAtom[NDIM];
    2713   double max_coordinate[NDIM];
    2714   Vector Oben;
    2715   Vector helper;
    2716   Vector Chord;
    2717   Vector SearchDirection;
    2718 
    2719   Oben.Zero();
    2720 
    2721   for (i = 0; i < 3; i++) {
    2722     MaxAtom[i] = NULL;
    2723     max_coordinate[i] = -1;
    2724   }
    2725 
    2726   // 1. searching topmost atom with respect to each axis
    2727   for (int i=0;i<NDIM;i++) { // each axis
    2728     LC->n[i] = LC->N[i]-1; // current axis is topmost cell
    2729     for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
    2730       for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
    2731         List = LC->GetCurrentCell();
    2732         //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2733         if (List != NULL) {
    2734           for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
    2735             if ((*Runner)->x.x[i] > max_coordinate[i]) {
    2736               cout << Verbose(2) << "New maximal for axis " << i << " atom is " << *(*Runner) << " at " << (*Runner)->x << "." << endl;
    2737               max_coordinate[i] = (*Runner)->x.x[i];
    2738               MaxAtom[i] = (*Runner);
    2739             }
    2740           }
    2741         } else {
    2742           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
    2743         }
    2744       }
    2745   }
    2746 
    2747   cout << Verbose(2) << "Found maximum coordinates: ";
    2748   for (int i=0;i<NDIM;i++)
    2749     cout << i << ": " << *MaxAtom[i] << "\t";
    2750   cout << endl;
    2751 
    2752   BTS = NULL;
    2753   CandidateList *Opt_Candidates = new CandidateList();
    2754   for (int k=0;k<NDIM;k++) {
    2755     Oben.x[k] = 1.;
    2756     FirstPoint = MaxAtom[k];
    2757     cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
    2758 
    2759     double ShortestAngle;
    2760     atom* Opt_Candidate = NULL;
    2761     ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    2762 
    2763     Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    2764     SecondPoint = Opt_Candidate;
    2765     if (SecondPoint == NULL)  // have we found a second point?
    2766       continue;
    2767     else
    2768       cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
    2769 
    2770     helper.CopyVector(&(FirstPoint->x));
    2771     helper.SubtractVector(&(SecondPoint->x));
    2772     helper.Normalize();
    2773     Oben.ProjectOntoPlane(&helper);
    2774     Oben.Normalize();
    2775     helper.VectorProduct(&Oben);
    2776     ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2777 
    2778     Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2779     Chord.SubtractVector(&(SecondPoint->x));
    2780     double radius = Chord.ScalarProduct(&Chord);
    2781     double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
    2782     helper.CopyVector(&Oben);
    2783     helper.Scale(CircleRadius);
    2784     // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2785 
    2786     // look in one direction of baseline for initial candidate
    2787     SearchDirection.MakeNormalVector(&Chord, &Oben);  // whether we look "left" first or "right" first is not important ...
    2788 
    2789     // adding point 1 and point 2 and the line between them
    2790     AddTrianglePoint(FirstPoint, 0);
    2791     AddTrianglePoint(SecondPoint, 1);
    2792     AddTriangleLine(TPS[0], TPS[1], 0);
    2793 
    2794     //cout << Verbose(2) << "INFO: OldSphereCenter is at " << helper << ".\n";
    2795     Find_third_point_for_Tesselation(
    2796       Oben, SearchDirection, helper, BLS[0], NULL, *&Opt_Candidates, &ShortestAngle, RADIUS, LC
    2797     );
    2798     cout << Verbose(1) << "List of third Points is ";
    2799     for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2800         cout << " " << *(*it)->point;
    2801     }
    2802     cout << endl;
    2803 
    2804     for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2805       // add third triangle point
    2806       AddTrianglePoint((*it)->point, 2);
    2807       // add the second and third line
    2808       AddTriangleLine(TPS[1], TPS[2], 1);
    2809       AddTriangleLine(TPS[0], TPS[2], 2);
    2810       // ... and triangles to the Maps of the Tesselation class
    2811       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2812       AddTriangle();
    2813       // ... and calculate its normal vector (with correct orientation)
    2814       (*it)->OptCenter.Scale(-1.);
    2815       cout << Verbose(2) << "Anti-Oben is currently " << (*it)->OptCenter << "." << endl;
    2816       BTS->GetNormalVector((*it)->OptCenter);  // vector to compare with should point inwards
    2817       cout << Verbose(0) << "==> Found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and "
    2818       << *(*it)->point << " with normal vector " << BTS->NormalVector << ".\n";
    2819 
    2820       // if we do not reach the end with the next step of iteration, we need to setup a new first line
    2821       if (it != Opt_Candidates->end()--) {
    2822         FirstPoint = (*it)->BaseLine->endpoints[0]->node;
    2823         SecondPoint = (*it)->point;
    2824         // adding point 1 and point 2 and the line between them
    2825         AddTrianglePoint(FirstPoint, 0);
    2826         AddTrianglePoint(SecondPoint, 1);
    2827         AddTriangleLine(TPS[0], TPS[1], 0);
    2828       }
    2829       cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
    2830     }
    2831     if (BTS != NULL) // we have created one starting triangle
    2832       break;
    2833     else {
    2834       // remove all candidates from the list and then the list itself
    2835       class CandidateForTesselation *remover = NULL;
    2836       for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2837         remover = *it;
    2838         delete(remover);
    2839       }
    2840       Opt_Candidates->clear();
    2841     }
    2842   }
    2843 
    2844   // remove all candidates from the list and then the list itself
    2845   class CandidateForTesselation *remover = NULL;
    2846   for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2847     remover = *it;
    2848     delete(remover);
    2849   }
    2850   delete(Opt_Candidates);
    2851   cout << Verbose(1) << "End of Find_starting_triangle\n";
    2852 };
    2853 
    2854 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
    2855  * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
    2856  * make it bigger (i.e. closing one (the baseline) and opening two new ones).
    2857  * \param TPS[3] nodes of the triangle
    2858  * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)
    2859  */
    2860 bool CheckLineCriteriaforDegeneratedTriangle(class BoundaryPointSet *nodes[3])
    2861 {
    2862   bool result = false;
    2863   int counter = 0;
    2864 
    2865   // check all three points
    2866   for (int i=0;i<3;i++)
    2867     for (int j=i+1; j<3; j++) {
    2868       if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) {  // there already is a line
    2869         LineMap::iterator FindLine;
    2870         pair<LineMap::iterator,LineMap::iterator> FindPair;
    2871         FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);
    2872         for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
    2873           // If there is a line with less than two attached triangles, we don't need a new line.
    2874           if (FindLine->second->TrianglesCount < 2) {
    2875             counter++;
    2876             break;  // increase counter only once per edge
    2877           }
    2878         }
    2879       } else { // no line
    2880         cout << Verbose(1) << "ERROR: The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle!" << endl;
    2881         result = true;
    2882       }
    2883     }
    2884   if (counter > 1) {
    2885     cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;
    2886     result = true;
    2887   }
    2888   return result;
    2889 };
    2890 
    2891 
    2892 /** This function finds a triangle to a line, adjacent to an existing one.
    2893  * @param out output stream for debugging
    2894  * @param *mol molecule with Atom's and Bond's
    2895  * @param Line current baseline to search from
    2896  * @param T current triangle which \a Line is edge of
    2897  * @param RADIUS radius of the rolling ball
    2898  * @param N number of found triangles
    2899  * @param *filename filename base for intermediate envelopes
    2900  * @param *LC LinkedCell structure with neighbouring atoms
    2901  */
    2902 bool Tesselation::Find_next_suitable_triangle(ofstream *out,
    2903     molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    2904     const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
    2905 {
    2906   cout << Verbose(0) << "Begin of Find_next_suitable_triangle\n";
    2907   ofstream *tempstream = NULL;
    2908   char NumberName[255];
    2909   bool result = true;
    2910   CandidateList *Opt_Candidates = new CandidateList();
    2911 
    2912   Vector CircleCenter;
    2913   Vector CirclePlaneNormal;
    2914   Vector OldSphereCenter;
    2915   Vector SearchDirection;
    2916   Vector helper;
    2917   atom *ThirdNode = NULL;
    2918   LineMap::iterator testline;
    2919   double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2920   double radius, CircleRadius;
    2921 
    2922   cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
    2923   for (int i=0;i<3;i++)
    2924     if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
    2925       ThirdNode = T.endpoints[i]->node;
    2926 
    2927   // construct center of circle
    2928   CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
    2929   CircleCenter.AddVector(&Line.endpoints[1]->node->x);
    2930   CircleCenter.Scale(0.5);
    2931 
    2932   // construct normal vector of circle
    2933   CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
    2934   CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
    2935 
    2936   // calculate squared radius of circle
    2937   radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2938   if (radius/4. < RADIUS*RADIUS) {
    2939     CircleRadius = RADIUS*RADIUS - radius/4.;
    2940     CirclePlaneNormal.Normalize();
    2941     cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2942 
    2943     // construct old center
    2944     GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
    2945     helper.CopyVector(&T.NormalVector);  // normal vector ensures that this is correct center of the two possible ones
    2946     radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2947     helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2948     OldSphereCenter.AddVector(&helper);
    2949     OldSphereCenter.SubtractVector(&CircleCenter);
    2950     //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    2951 
    2952     // construct SearchDirection
    2953     SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
    2954     helper.CopyVector(&Line.endpoints[0]->node->x);
    2955     helper.SubtractVector(&ThirdNode->x);
    2956     if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)// ohoh, SearchDirection points inwards!
    2957       SearchDirection.Scale(-1.);
    2958     SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2959     SearchDirection.Normalize();
    2960     cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2961     if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {
    2962       // rotated the wrong way!
    2963       cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2964     }
    2965 
    2966     // add third point
    2967     Find_third_point_for_Tesselation(
    2968       T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidates,
    2969       &ShortestAngle, RADIUS, LC
    2970     );
    2971 
    2972   } else {
    2973     cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
    2974   }
    2975 
    2976   if (Opt_Candidates->begin() == Opt_Candidates->end()) {
    2977     cerr << "WARNING: Could not find a suitable candidate." << endl;
    2978     return false;
    2979   }
    2980   cout << Verbose(1) << "Third Points are ";
    2981   for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2982     cout << " " << *(*it)->point;
    2983   }
    2984   cout << endl;
    2985 
    2986   BoundaryLineSet *BaseRay = &Line;
    2987   for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2988     cout << Verbose(1) << " Third point candidate is " << *(*it)->point
    2989     << " with circumsphere's center at " << (*it)->OptCenter << "." << endl;
    2990     cout << Verbose(1) << " Baseline is " << *BaseRay << endl;
    2991 
    2992     // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2993     atom *AtomCandidates[3];
    2994     AtomCandidates[0] = (*it)->point;
    2995     AtomCandidates[1] = BaseRay->endpoints[0]->node;
    2996     AtomCandidates[2] = BaseRay->endpoints[1]->node;
    2997     int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates);
    2998 
    2999     BTS = NULL;
    3000     // If there is no triangle, add it regularly.
    3001     if (existentTrianglesCount == 0) {
    3002       AddTrianglePoint((*it)->point, 0);
    3003       AddTrianglePoint(BaseRay->endpoints[0]->node, 1);
    3004       AddTrianglePoint(BaseRay->endpoints[1]->node, 2);
    3005 
    3006       AddTriangleLine(TPS[0], TPS[1], 0);
    3007       AddTriangleLine(TPS[0], TPS[2], 1);
    3008       AddTriangleLine(TPS[1], TPS[2], 2);
    3009 
    3010       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    3011       AddTriangle();
    3012       (*it)->OptCenter.Scale(-1.);
    3013       BTS->GetNormalVector((*it)->OptCenter);
    3014       (*it)->OptCenter.Scale(-1.);
    3015 
    3016       cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector
    3017         << " for this triangle ... " << endl;
    3018       //cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << *BaseRay << "." << endl;
    3019     } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.
    3020         AddTrianglePoint((*it)->point, 0);
    3021         AddTrianglePoint(BaseRay->endpoints[0]->node, 1);
    3022         AddTrianglePoint(BaseRay->endpoints[1]->node, 2);
    3023 
    3024         // We demand that at most one new degenerate line is created and that this line also already exists (which has to be the case due to existentTrianglesCount == 1)
    3025         // i.e. at least one of the three lines must be present with TriangleCount <= 1
    3026         if (CheckLineCriteriaforDegeneratedTriangle(TPS)) {
    3027           AddTriangleLine(TPS[0], TPS[1], 0);
    3028           AddTriangleLine(TPS[0], TPS[2], 1);
    3029           AddTriangleLine(TPS[1], TPS[2], 2);
    3030 
    3031           BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    3032           AddTriangle();
    3033 
    3034           (*it)->OtherOptCenter.Scale(-1.);
    3035           BTS->GetNormalVector((*it)->OtherOptCenter);
    3036           (*it)->OtherOptCenter.Scale(-1.);
    3037 
    3038           cout << "--> WARNING: Special new triangle with " << *BTS << " and normal vector " << BTS->NormalVector
    3039           << " for this triangle ... " << endl;
    3040           cout << Verbose(1) << "We have "<< BaseRay->TrianglesCount << " for line " << BaseRay << "." << endl;
    3041         } else {
    3042           cout << Verbose(1) << "WARNING: This triangle consisting of ";
    3043           cout << *(*it)->point << ", ";
    3044           cout << *BaseRay->endpoints[0]->node << " and ";
    3045           cout << *BaseRay->endpoints[1]->node << " ";
    3046           cout << "exists and is not added, as it does not seem helpful!" << endl;
    3047           result = false;
    3048         }
    3049     } else {
    3050       cout << Verbose(1) << "This triangle consisting of ";
    3051       cout << *(*it)->point << ", ";
    3052       cout << *BaseRay->endpoints[0]->node << " and ";
    3053       cout << *BaseRay->endpoints[1]->node << " ";
    3054       cout << "is invalid!" << endl;
    3055       result = false;
    3056     }
    3057 
    3058     if ((result) && (existentTrianglesCount < 2) && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration
    3059       sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
    3060       if (DoTecplotOutput) {
    3061         string NameofTempFile(tempbasename);
    3062         NameofTempFile.append(NumberName);
    3063         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    3064         NameofTempFile.erase(npos, 1);
    3065         NameofTempFile.append(TecplotSuffix);
    3066         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    3067         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    3068         write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    3069         tempstream->close();
    3070         tempstream->flush();
    3071         delete(tempstream);
    3072       }
    3073 
    3074       if (DoRaster3DOutput) {
    3075         string NameofTempFile(tempbasename);
    3076         NameofTempFile.append(NumberName);
    3077         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    3078         NameofTempFile.erase(npos, 1);
    3079         NameofTempFile.append(Raster3DSuffix);
    3080         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    3081         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    3082         write_raster3d_file(out, tempstream, this, mol);
    3083         // include the current position of the virtual sphere in the temporary raster3d file
    3084         // make the circumsphere's center absolute again
    3085         helper.CopyVector(&BaseRay->endpoints[0]->node->x);
    3086         helper.AddVector(&BaseRay->endpoints[1]->node->x);
    3087         helper.Scale(0.5);
    3088         (*it)->OptCenter.AddVector(&helper);
    3089         Vector *center = mol->DetermineCenterOfAll(out);
    3090         (*it)->OptCenter.SubtractVector(center);
    3091         delete(center);
    3092         // and add to file plus translucency object
    3093         *tempstream << "# current virtual sphere\n";
    3094         *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
    3095         *tempstream << "2\n  " << (*it)->OptCenter.x[0] << " "
    3096           << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2]
    3097           << "\t" << RADIUS << "\t1 0 0\n";
    3098         *tempstream << "9\n  terminating special property\n";
    3099         tempstream->close();
    3100         tempstream->flush();
    3101         delete(tempstream);
    3102       }
    3103       if (DoTecplotOutput || DoRaster3DOutput)
    3104         TriangleFilesWritten++;
    3105     }
    3106 
    3107     // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point))
    3108     BaseRay = BLS[0];
    3109   }
    3110 
    3111   // remove all candidates from the list and then the list itself
    3112   class CandidateForTesselation *remover = NULL;
    3113   for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    3114     remover = *it;
    3115     delete(remover);
    3116   }
    3117   delete(Opt_Candidates);
    3118   cout << Verbose(0) << "End of Find_next_suitable_triangle\n";
    3119   return result;
    3120 };
    3121 
    3122 /**
    3123  * Sort function for the candidate list.
    3124  */
    3125 bool sortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2) {
    3126   // TODO: use get angle and remove duplicate code
    3127   Vector BaseLineVector, OrthogonalVector, helper;
    3128         if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
    3129           cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
    3130           //return false;
    3131           exit(1);
    3132         }
    3133         // create baseline vector
    3134         BaseLineVector.CopyVector(&(candidate1->BaseLine->endpoints[1]->node->x));
    3135         BaseLineVector.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    3136         BaseLineVector.Normalize();
    3137 
    3138   // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)
    3139   helper.CopyVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    3140   helper.SubtractVector(&(candidate1->point->x));
    3141   OrthogonalVector.CopyVector(&helper);
    3142   helper.VectorProduct(&BaseLineVector);
    3143   OrthogonalVector.SubtractVector(&helper);
    3144   OrthogonalVector.Normalize();
    3145 
    3146   // calculate both angles and correct with in-plane vector
    3147   helper.CopyVector(&(candidate1->point->x));
    3148   helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    3149   double phi = BaseLineVector.Angle(&helper);
    3150   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    3151     phi = 2.*M_PI - phi;
    3152   }
    3153   helper.CopyVector(&(candidate2->point->x));
    3154   helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    3155   double psi = BaseLineVector.Angle(&helper);
    3156   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    3157     psi = 2.*M_PI - psi;
    3158   }
    3159 
    3160   cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
    3161   cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
    3162 
    3163   // return comparison
    3164   return phi < psi;
    3165 }
    3166 
    3167 /**
    3168  * Checks whether the provided atom is within the tesselation structure.
    3169  *
    3170  * @param atom of which to check the position
    3171  * @param tesselation structure
    3172  *
    3173  * @return true if the atom is inside the tesselation structure, false otherwise
    3174  */
    3175 bool IsInnerAtom(atom *Atom, class Tesselation *Tess, LinkedCell* LC) {
    3176   if (Tess->LinesOnBoundary.begin() == Tess->LinesOnBoundary.end()) {
    3177     cout << Verbose(0) << "Error: There is no tesselation structure to compare the atom with, "
    3178         << "please create one first.";
    3179     exit(1);
    3180   }
    3181 
    3182   class atom *trianglePoints[3];
    3183   trianglePoints[0] = findClosestAtom(Atom, LC);
    3184   // check whether closest atom is "too close" :), then it's inside
    3185   if (trianglePoints[0]->x.DistanceSquared(&Atom->x) < MYEPSILON)
    3186     return true;
    3187   list<atom*> *connectedClosestAtoms = Tess->getClosestConnectedAtoms(trianglePoints[0], Atom);
    3188   trianglePoints[1] = connectedClosestAtoms->front();
    3189   trianglePoints[2] = connectedClosestAtoms->back();
    3190   for (int i=0;i<3;i++) {
    3191     if (trianglePoints[i] == NULL) {
    3192       cout << Verbose(1) << "IsInnerAtom encounters serious error, point " << i << " not found." << endl;
    3193     }
    3194 
    3195     cout << Verbose(1) << "List of possible atoms:" << endl;
    3196     cout << *trianglePoints[i] << endl;
    3197 
    3198 //    for(list<atom*>::iterator runner = connectedClosestAtoms->begin(); runner != connectedClosestAtoms->end(); runner++)
    3199 //      cout << Verbose(2) << *(*runner) << endl;
    3200   }
    3201   delete(connectedClosestAtoms);
    3202 
    3203   list<BoundaryTriangleSet*> *triangles = Tess->FindTriangles(trianglePoints);
    3204 
    3205   if (triangles->empty()) {
    3206     cout << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
    3207     exit(1);
    3208   }
    3209 
    3210   Vector helper;
    3211   helper.CopyVector(&Atom->x);
    3212 
    3213   // Only in case of degeneration, there will be two different scalar products.
    3214   // If at least one scalar product is positive, the point is considered to be outside.
    3215   bool status = (helper.ScalarProduct(&triangles->front()->NormalVector) < 0)
    3216       && (helper.ScalarProduct(&triangles->back()->NormalVector) < 0);
    3217   delete(triangles);
    3218   return status;
    3219 }
    3220 
    3221 /**
    3222  * Finds the atom which is closest to the provided one.
    3223  *
    3224  * @param atom to which to find the closest other atom
    3225  * @param linked cell structure
    3226  *
    3227  * @return atom which is closest to the provided one
    3228  */
    3229 atom* findClosestAtom(const atom* Atom, LinkedCell* LC) {
    3230   LinkedAtoms *List = NULL;
    3231   atom* closestAtom = NULL;
    3232   double distance = 1e16;
    3233   Vector helper;
    3234   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    3235 
    3236   LC->SetIndexToVector(&Atom->x); // ignore status as we calculate bounds below sensibly
    3237   for(int i=0;i<NDIM;i++) // store indices of this cell
    3238     N[i] = LC->n[i];
    3239   //cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    3240 
    3241   LC->GetNeighbourBounds(Nlower, Nupper);
    3242   //cout << endl;
    3243   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    3244     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    3245       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    3246         List = LC->GetCurrentCell();
    3247         //cout << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    3248         if (List != NULL) {
    3249           for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    3250             helper.CopyVector(&Atom->x);
    3251             helper.SubtractVector(&(*Runner)->x);
    3252             double currentNorm = helper. Norm();
    3253             if (currentNorm < distance) {
    3254               distance = currentNorm;
    3255               closestAtom = (*Runner);
    3256             }
    3257           }
    3258         } else {
    3259           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    3260             << LC->n[2] << " is invalid!" << endl;
    3261         }
    3262       }
    3263 
    3264   return closestAtom;
    3265 }
    3266 
    3267 /**
    3268  * Gets all atoms connected to the provided atom by triangulation lines.
    3269  *
    3270  * @param atom of which get all connected atoms
    3271  * @param atom to be checked whether it is an inner atom
    3272  *
    3273  * @return list of the two atoms linked to the provided one and closest to the atom to be checked,
    3274  */
    3275 list<atom*> * Tesselation::getClosestConnectedAtoms(atom* Atom, atom* AtomToCheck) {
    3276   list<atom*> connectedAtoms;
    3277   map<double, atom*> anglesOfAtoms;
    3278   map<double, atom*>::iterator runner;
    3279   LineMap::iterator findLines = LinesOnBoundary.begin();
    3280   list<atom*>::iterator listRunner;
    3281   Vector center, planeNorm, currentPoint, OrthogonalVector, helper;
    3282   atom* current;
    3283   bool takeAtom = false;
    3284 
    3285   planeNorm.CopyVector(&Atom->x);
    3286   planeNorm.SubtractVector(&AtomToCheck->x);
    3287   planeNorm.Normalize();
    3288 
    3289   while (findLines != LinesOnBoundary.end()) {
    3290     takeAtom = false;
    3291 
    3292     if (findLines->second->endpoints[0]->Nr == Atom->nr) {
    3293       takeAtom = true;
    3294       current = findLines->second->endpoints[1]->node;
    3295     } else if (findLines->second->endpoints[1]->Nr == Atom->nr) {
    3296       takeAtom = true;
    3297       current = findLines->second->endpoints[0]->node;
    3298     }
    3299 
    3300     if (takeAtom) {
    3301       connectedAtoms.push_back(current);
    3302       currentPoint.CopyVector(&current->x);
    3303       currentPoint.ProjectOntoPlane(&planeNorm);
    3304       center.AddVector(&currentPoint);
    3305     }
    3306 
    3307     findLines++;
    3308   }
    3309 
    3310   cout << "Summed vectors " << center << "; number of atoms " << connectedAtoms.size()
    3311     << "; scale factor " << 1.0/connectedAtoms.size();
    3312 
    3313   center.Scale(1.0/connectedAtoms.size());
    3314   listRunner = connectedAtoms.begin();
    3315 
    3316   cout << " calculated center " << center <<  endl;
    3317 
    3318   // construct one orthogonal vector
    3319   helper.CopyVector(&AtomToCheck->x);
    3320   helper.ProjectOntoPlane(&planeNorm);
    3321   OrthogonalVector.MakeNormalVector(&center, &helper, &(*listRunner)->x);
    3322   while (listRunner != connectedAtoms.end()) {
    3323     double angle = getAngle((*listRunner)->x, AtomToCheck->x, center, OrthogonalVector);
    3324     cout << "Calculated angle " << angle << " for atom " << **listRunner << endl;
    3325     anglesOfAtoms.insert(pair<double, atom*>(angle, (*listRunner)));
    3326     listRunner++;
    3327   }
    3328 
    3329   list<atom*> *result = new list<atom*>;
    3330   runner = anglesOfAtoms.begin();
    3331   cout << "First value is " << *runner->second << endl;
    3332   result->push_back(runner->second);
    3333   runner = anglesOfAtoms.end();
    3334   runner--;
    3335   cout << "Second value is " << *runner->second << endl;
    3336   result->push_back(runner->second);
    3337 
    3338   cout << "List of closest atoms has " << result->size() << " elements, which are "
    3339     << *(result->front()) << " and " << *(result->back()) << endl;
    3340 
    3341   return result;
    3342 }
    3343 
    3344 /**
    3345  * Finds triangles belonging to the three provided atoms.
    3346  *
    3347  * @param atom list, is expected to contain three atoms
    3348  *
    3349  * @return triangles which belong to the provided atoms, will be empty if there are none,
    3350  *         will usually be one, in case of degeneration, there will be two
    3351  */
    3352 list<BoundaryTriangleSet*> *Tesselation::FindTriangles(atom* Points[3]) {
    3353   list<BoundaryTriangleSet*> *result = new list<BoundaryTriangleSet*>;
    3354   LineMap::iterator FindLine;
    3355   PointMap::iterator FindPoint;
    3356   TriangleMap::iterator FindTriangle;
    3357   class BoundaryPointSet *TrianglePoints[3];
    3358 
    3359   for (int i = 0; i < 3; i++) {
    3360     FindPoint = PointsOnBoundary.find(Points[i]->nr);
    3361     if (FindPoint != PointsOnBoundary.end()) {
    3362       TrianglePoints[i] = FindPoint->second;
    3363     } else {
    3364       TrianglePoints[i] = NULL;
    3365     }
    3366   }
    3367 
    3368   // checks lines between the points in the Points for their adjacent triangles
    3369   for (int i = 0; i < 3; i++) {
    3370     if (TrianglePoints[i] != NULL) {
    3371       for (int j = i; j < 3; j++) {
    3372         if (TrianglePoints[j] != NULL) {
    3373           FindLine = TrianglePoints[i]->lines.find(TrianglePoints[j]->node->nr);
    3374           if (FindLine != TrianglePoints[i]->lines.end()) {
    3375             for (; FindLine->first == TrianglePoints[j]->node->nr; FindLine++) {
    3376               FindTriangle = FindLine->second->triangles.begin();
    3377               for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {
    3378                 if ((
    3379                   (FindTriangle->second->endpoints[0] == TrianglePoints[0])
    3380                     || (FindTriangle->second->endpoints[0] == TrianglePoints[1])
    3381                     || (FindTriangle->second->endpoints[0] == TrianglePoints[2])
    3382                   ) && (
    3383                     (FindTriangle->second->endpoints[1] == TrianglePoints[0])
    3384                     || (FindTriangle->second->endpoints[1] == TrianglePoints[1])
    3385                     || (FindTriangle->second->endpoints[1] == TrianglePoints[2])
    3386                   ) && (
    3387                     (FindTriangle->second->endpoints[2] == TrianglePoints[0])
    3388                     || (FindTriangle->second->endpoints[2] == TrianglePoints[1])
    3389                     || (FindTriangle->second->endpoints[2] == TrianglePoints[2])
    3390                   )
    3391                 ) {
    3392                   result->push_back(FindTriangle->second);
    3393                 }
    3394               }
    3395             }
    3396             // Is it sufficient to consider one of the triangle lines for this.
    3397             return result;
    3398 
    3399           }
    3400         }
    3401       }
    3402     }
    3403   }
    3404 
    3405   return result;
    3406 }
    3407 
    3408 /**
    3409  * Gets the angle between a point and a reference relative to the provided center.
    3410  *
    3411  * @param point to calculate the angle for
    3412  * @param reference to which to calculate the angle
    3413  * @param center for which to calculate the angle between the vectors
    3414  * @param OrthogonalVector helps discern between [0,pi] and [pi,2pi] in acos()
    3415  *
    3416  * @return angle between point and reference
    3417  */
    3418 double getAngle(Vector point, Vector reference, Vector center, Vector OrthogonalVector) {
    3419   Vector ReferenceVector, helper;
    3420   cout << Verbose(2) << reference << " is our reference " << endl;
    3421   cout << Verbose(2) << center << " is our center " << endl;
    3422   // create baseline vector
    3423   ReferenceVector.CopyVector(&reference);
    3424   ReferenceVector.SubtractVector(&center);
    3425   if (ReferenceVector.IsNull())
    3426     return M_PI;
    3427 
    3428   // calculate both angles and correct with in-plane vector
    3429   helper.CopyVector(&point);
    3430   helper.SubtractVector(&center);
    3431   if (helper.IsNull())
    3432     return M_PI;
    3433   double phi = ReferenceVector.Angle(&helper);
    3434   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    3435     phi = 2.*M_PI - phi;
    3436   }
    3437 
    3438   cout << Verbose(2) << point << " has angle " << phi << endl;
    3439 
    3440   return phi;
    3441 }
    3442 
    3443 /**
    3444  * Checks whether the provided point is within the tesselation structure.
    3445  *
    3446  * This is a wrapper function for IsInnerAtom, so it can be used with a simple
    3447  * vector, too.
    3448  *
    3449  * @param point of which to check the position
    3450  * @param tesselation structure
    3451  *
    3452  * @return true if the point is inside the tesselation structure, false otherwise
    3453  */
    3454 bool IsInnerPoint(Vector Point, class Tesselation *Tess, LinkedCell* LC) {
    3455   atom *temp_atom = new atom;
    3456   bool status = false;
    3457   temp_atom->x.CopyVector(&Point);
    3458 
    3459   status = IsInnerAtom(temp_atom, Tess, LC);
    3460   delete(temp_atom);
    3461 
    3462   return status;
    3463 }
    3464 
    3465817/** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule.
    3466818 * \param *out output stream for debugging
     
    3476828  bool freeTess = false;
    3477829  bool freeLC = false;
     830  ofstream *tempstream = NULL;
     831  char NumberName[255];
     832  int TriangleFilesWritten = 0;
     833
    3478834  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
    3479835  if (Tess == NULL) {
     
    3493849  }
    3494850
    3495   Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     851  Tess->Find_starting_triangle(out, RADIUS, LCList);
    3496852
    3497853  baseline = Tess->LinesOnBoundary.begin();
    3498854  while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
    3499855    if (baseline->second->TrianglesCount == 1) {
    3500       failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.
     856      failflag = Tess->Find_next_suitable_triangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, LCList); //the line is there, so there is a triangle, but only one.
    3501857      flag = flag || failflag;
    3502858      if (!failflag)
     
    3514870      flag = false;
    3515871    }
    3516   }
     872
     873    // write temporary envelope
     874    if ((DoSingleStepOutput && (Tess->TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     875      class BoundaryTriangleSet *triangle = (Tess->TrianglesOnBoundary.end()--)->second;
     876      sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, triangle->endpoints[0]->node->Name, triangle->endpoints[1]->node->Name, triangle->endpoints[2]->node->Name);
     877      if (DoTecplotOutput) {
     878        string NameofTempFile(filename);
     879        NameofTempFile.append(NumberName);
     880        for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     881        NameofTempFile.erase(npos, 1);
     882        NameofTempFile.append(TecplotSuffix);
     883        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     884        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     885        write_tecplot_file(out, tempstream, Tess, mol, TriangleFilesWritten);
     886        tempstream->close();
     887        tempstream->flush();
     888        delete(tempstream);
     889      }
     890
     891      if (DoRaster3DOutput) {
     892        string NameofTempFile(filename);
     893        NameofTempFile.append(NumberName);
     894        for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     895        NameofTempFile.erase(npos, 1);
     896        NameofTempFile.append(Raster3DSuffix);
     897        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     898        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     899        write_raster3d_file(out, tempstream, Tess, mol);
     900//        // include the current position of the virtual sphere in the temporary raster3d file
     901//        // make the circumsphere's center absolute again
     902//        helper.CopyVector(BaseRay->endpoints[0]->node->node);
     903//        helper.AddVector(BaseRay->endpoints[1]->node->node);
     904//        helper.Scale(0.5);
     905//        (*it)->OptCenter.AddVector(&helper);
     906//        Vector *center = mol->DetermineCenterOfAll(out);
     907//        (*it)->OptCenter.SubtractVector(center);
     908//        delete(center);
     909//        // and add to file plus translucency object
     910//        *tempstream << "# current virtual sphere\n";
     911//        *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     912//        *tempstream << "2\n  " << (*it)->OptCenter.x[0] << " "
     913//          << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2]
     914//          << "\t" << RADIUS << "\t1 0 0\n";
     915//        *tempstream << "9\n  terminating special property\n";
     916        tempstream->close();
     917        tempstream->flush();
     918        delete(tempstream);
     919      }
     920      if (DoTecplotOutput || DoRaster3DOutput)
     921        TriangleFilesWritten++;
     922    }
     923  }
     924
     925  // write final envelope
    3517926  if (filename != 0) {
    3518927    *out << Verbose(1) << "Writing final tecplot file\n";
     
    3553962  cout << Verbose(0) << "Check: IsInnerPoint() returns " << IsInnerPoint(x, Tess, LCList)
    3554963    << "for vector " << x << "." << endl;
    3555   atom* a = Tess->PointsOnBoundary.begin()->second->node;
     964  TesselPoint* a = Tess->PointsOnBoundary.begin()->second->node;
    3556965  cout << Verbose(0) << "Point to check: " << *a << " (on boundary)." << endl;
    3557   cout << Verbose(0) << "Check: IsInnerAtom() returns " << IsInnerAtom(a, Tess, LCList)
     966  cout << Verbose(0) << "Check: IsInnerAtom() returns " << IsInnerPoint(a, Tess, LCList)
    3558967    << "for atom " << a << " (on boundary)." << endl;
    3559   LinkedAtoms *List = NULL;
     968  LinkedNodes *List = NULL;
    3560969  for (int i=0;i<NDIM;i++) { // each axis
    3561970    LCList->n[i] = LCList->N[i]-1; // current axis is topmost cell
     
    3565974        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    3566975        if (List != NULL) {
    3567           for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     976          for (LinkedNodes::iterator Runner = List->begin();Runner != List->end();Runner++) {
    3568977            if (Tess->PointsOnBoundary.find((*Runner)->nr) == Tess->PointsOnBoundary.end()) {
    3569978              a = *Runner;
     
    3577986      }
    3578987  }
    3579   cout << Verbose(0) << "Check: IsInnerAtom() returns " << IsInnerAtom(a, Tess, LCList)
     988  cout << Verbose(0) << "Check: IsInnerPoint() returns " << IsInnerPoint(a, Tess, LCList)
    3580989    << "for atom " << a << " (inside)." << endl;
    3581990
Note: See TracChangeset for help on using the changeset viewer.