Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    • Property mode changed from 100755 to 100644
    rcc2ee5 red060e  
    22#include "boundary.hpp"
    33
    4 #define DEBUG 1
    5 #define DoTecplotOutput 0
    6 #define DoRaster3DOutput 1
    7 #define TecplotSuffix ".dat"
    8 #define Raster3DSuffix ".r3d"
    9 
    104// ======================================== Points on Boundary =================================
    115
     
    148  LinesCount = 0;
    159  Nr = -1;
    16 }
    17 ;
     10};
    1811
    1912BoundaryPointSet::BoundaryPointSet(atom *Walker)
     
    2215  LinesCount = 0;
    2316  Nr = Walker->nr;
    24 }
    25 ;
     17};
    2618
    2719BoundaryPointSet::~BoundaryPointSet()
     
    2921  cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    3022  node = NULL;
    31   lines.clear();
    32 }
    33 ;
    34 
    35 void
    36 BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    37 {
    38   cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
    39       << endl;
    40   if (line->endpoints[0] == this)
    41     {
    42       lines.insert(LinePair(line->endpoints[1]->Nr, line));
    43     }
    44   else
    45     {
    46       lines.insert(LinePair(line->endpoints[0]->Nr, line));
    47     }
     23};
     24
     25void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
     26{
     27  cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl;
     28  if (line->endpoints[0] == this) {
     29    lines.insert ( LinePair( line->endpoints[1]->Nr, line) );
     30  } else {
     31    lines.insert ( LinePair( line->endpoints[0]->Nr, line) );
     32  }
    4833  LinesCount++;
    49 }
    50 ;
    51 
    52 ostream &
    53 operator <<(ostream &ost, BoundaryPointSet &a)
     34};
     35
     36ostream & operator << (ostream &ost, BoundaryPointSet &a)
    5437{
    5538  ost << "[" << a.Nr << "|" << a.node->Name << "]";
    5639  return ost;
    57 }
    58 ;
     40};
    5941
    6042// ======================================== Lines on Boundary =================================
     
    6244BoundaryLineSet::BoundaryLineSet()
    6345{
    64   for (int i = 0; i < 2; i++)
     46  for (int i=0;i<2;i++)
    6547    endpoints[i] = NULL;
    6648  TrianglesCount = 0;
    6749  Nr = -1;
    68 }
    69 ;
     50};
    7051
    7152BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
     
    7657  SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    7758  // add this line to the hash maps of both endpoints
    78   Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
    79   Point[1]->AddLine(this); //
     59  Point[0]->AddLine(this);
     60  Point[1]->AddLine(this);
    8061  // clear triangles list
    8162  TrianglesCount = 0;
    8263  cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    83 }
    84 ;
     64};
    8565
    8666BoundaryLineSet::~BoundaryLineSet()
    8767{
    88         for (int i = 0; i < 2; i++) {
    89                 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
    90                 endpoints[i]->lines.erase(Nr);
    91                 LineMap::iterator tester = endpoints[i]->lines.begin();
    92                 tester++;
    93                 if (tester == endpoints[i]->lines.end()) {
    94                         cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    95                         if (endpoints[i] != NULL) {
    96                                 delete(endpoints[i]);
    97                                 endpoints[i] = NULL;
    98                         } else
    99                                 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
    100                 } else
    101                         cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
    102         }
    103 }
    104 ;
    105 
    106 void
    107 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    108 {
    109   cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    110       << endl;
    111   triangles.insert(TrianglePair(TrianglesCount, triangle));
     68  for (int i=0;i<2;i++) {
     69    cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     70    endpoints[i]->lines.erase(Nr);
     71    LineMap::iterator tester = endpoints[i]->lines.begin();
     72    tester++;
     73    if (tester == endpoints[i]->lines.end()) {
     74      cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
     75      delete(endpoints[i]);
     76    } else
     77      cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
     78  }
     79};
     80
     81void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
     82{
     83  cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl;
     84  triangles.insert ( TrianglePair( TrianglesCount, triangle) );
    11285  TrianglesCount++;
    113 }
    114 ;
    115 
    116 ostream &
    117 operator <<(ostream &ost, BoundaryLineSet &a)
    118 {
    119   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    120       << a.endpoints[1]->node->Name << "]";
     86};
     87
     88ostream & operator << (ostream &ost, BoundaryLineSet &a)
     89{
     90  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]";
    12191  return ost;
    122 }
    123 ;
     92};
    12493
    12594// ======================================== Triangles on Boundary =================================
     
    12897BoundaryTriangleSet::BoundaryTriangleSet()
    12998{
    130   for (int i = 0; i < 3; i++)
    131     {
    132       endpoints[i] = NULL;
    133       lines[i] = NULL;
    134     }
     99  for (int i=0;i<3;i++) {
     100    endpoints[i] = NULL;
     101    lines[i] = NULL;
     102  }
    135103  Nr = -1;
    136 }
    137 ;
    138 
    139 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
    140     int number)
     104};
     105
     106BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number)
    141107{
    142108  // set number
     
    144110  // set lines
    145111  cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    146   for (int i = 0; i < 3; i++)
    147     {
    148       lines[i] = line[i];
    149       lines[i]->AddTriangle(this);
     112  for (int i=0;i<3;i++) {
     113    lines[i] = line[i];
     114    lines[i]->AddTriangle(this);
     115  }
     116  // get ascending order of endpoints
     117  map <int, class BoundaryPointSet * > OrderMap;
     118  for(int i=0;i<3;i++)  // for all three lines
     119    for (int j=0;j<2;j++) { // for both endpoints
     120      OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) );
     121      // and we don't care whether insertion fails
    150122    }
    151   // get ascending order of endpoints
    152   map<int, class BoundaryPointSet *> OrderMap;
    153   for (int i = 0; i < 3; i++)
    154     // for all three lines
    155     for (int j = 0; j < 2; j++)
    156       { // for both endpoints
    157         OrderMap.insert(pair<int, class BoundaryPointSet *> (
    158             line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
    159         // and we don't care whether insertion fails
    160       }
    161123  // set endpoints
    162124  int Counter = 0;
    163125  cout << Verbose(6) << " with end points ";
    164   for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
    165       != OrderMap.end(); runner++)
    166     {
    167       endpoints[Counter] = runner->second;
    168       cout << " " << *endpoints[Counter];
    169       Counter++;
    170     }
    171   if (Counter < 3)
    172     {
    173       cerr << "ERROR! We have a triangle with only two distinct endpoints!"
    174           << endl;
    175       //exit(1);
    176     }
     126  for (map <int, class BoundaryPointSet * >::iterator runner = OrderMap.begin(); runner != OrderMap.end(); runner++) {
     127    endpoints[Counter] = runner->second;
     128    cout << " " << *endpoints[Counter];
     129    Counter++;
     130  }
     131  if (Counter < 3) {
     132    cerr << "ERROR! We have a triangle with only two distinct endpoints!" << endl;
     133    //exit(1);
     134  }
    177135  cout << "." << endl;
    178 }
    179 ;
     136};
    180137
    181138BoundaryTriangleSet::~BoundaryTriangleSet()
    182139{
    183         for (int i = 0; i < 3; i++) {
    184                 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
    185                 lines[i]->triangles.erase(Nr);
    186                 if (lines[i]->triangles.empty()) {
    187                         cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
    188                         if (lines[i] != NULL) {
    189                                 delete (lines[i]);
    190                                 lines[i] = NULL;
    191                         } else
    192                                 cerr << "ERROR: This line " << i << " has already been free'd." << endl;
    193                 } else
    194                         cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl;
    195         }
    196 }
    197 ;
    198 
    199 void
    200 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
     140  for (int i=0;i<3;i++) {
     141    cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
     142    lines[i]->triangles.erase(Nr);
     143    TriangleMap::iterator tester = lines[i]->triangles.begin();
     144    tester++;
     145    if (tester == lines[i]->triangles.end()) {
     146      cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
     147      delete(lines[i]);
     148    } else
     149      cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl;
     150  }
     151};
     152
     153void BoundaryTriangleSet::GetNormalVector(Vector &NormalVector)
    201154{
    202155  // get normal vector
    203   NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
    204       &endpoints[2]->node->x);
    205 
     156  NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x);
     157 
    206158  // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    207   if (endpoints[0]->node->x.Projection(&OtherVector) > 0)
     159  if (endpoints[0]->node->x.Projection(&NormalVector) > 0)
    208160    NormalVector.Scale(-1.);
    209 }
    210 ;
    211 
    212 ostream &
    213 operator <<(ostream &ost, BoundaryTriangleSet &a)
    214 {
    215   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    216       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
     161};
     162
     163ostream & operator << (ostream &ost, BoundaryTriangleSet &a)
     164{
     165  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    217166  return ost;
    218 }
    219 ;
     167};
    220168
    221169// ========================================== F U N C T I O N S =================================
     
    226174 * \return point which is shared or NULL if none
    227175 */
    228 class BoundaryPointSet *
    229 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    230 {
    231   class BoundaryLineSet * lines[2] =
    232     { line1, line2 };
     176class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
     177{
     178  class BoundaryLineSet * lines[2] = {line1, line2};
    233179  class BoundaryPointSet *node = NULL;
    234   map<int, class BoundaryPointSet *> OrderMap;
    235   pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
    236   for (int i = 0; i < 2; i++)
    237     // for both lines
    238     for (int j = 0; j < 2; j++)
    239       { // for both endpoints
    240         OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
    241             lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
    242         if (!OrderTest.second)
    243           { // if insertion fails, we have common endpoint
    244             node = OrderTest.first->second;
    245             cout << Verbose(5) << "Common endpoint of lines " << *line1
    246                 << " and " << *line2 << " is: " << *node << "." << endl;
    247             j = 2;
    248             i = 2;
    249             break;
    250           }
     180  map <int, class BoundaryPointSet * > OrderMap;
     181  pair < map <int, class BoundaryPointSet * >::iterator, bool > OrderTest;
     182  for(int i=0;i<2;i++)  // for both lines
     183    for (int j=0;j<2;j++) { // for both endpoints
     184      OrderTest = OrderMap.insert ( pair <int, class BoundaryPointSet * >( lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]) );
     185      if (!OrderTest.second) { // if insertion fails, we have common endpoint
     186        node = OrderTest.first->second;
     187        cout << Verbose(5) << "Common endpoint of lines " << *line1 << " and " << *line2 << " is: " << *node << "." << endl;
     188        j=2;
     189        i=2;
     190        break;
    251191      }
     192    }
    252193  return node;
    253 }
    254 ;
     194};
    255195
    256196/** Determines the boundary points of a cluster.
     
    261201 * \param *mol molecule structure representing the cluster
    262202 */
    263 Boundaries *
    264 GetBoundaryPoints(ofstream *out, molecule *mol)
     203Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol)
    265204{
    266205  atom *Walker = NULL;
     
    268207  LineMap LinesOnBoundary;
    269208  TriangleMap TrianglesOnBoundary;
    270 
     209 
    271210  *out << Verbose(1) << "Finding all boundary points." << endl;
    272   Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
     211  Boundaries *BoundaryPoints = new Boundaries [NDIM]; // first is alpha, second is (r, nr)
    273212  BoundariesTestPair BoundaryTestPair;
    274213  Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    275214  double radius, angle;
    276215  // 3a. Go through every axis
    277   for (int axis = 0; axis < NDIM; axis++)
    278     {
    279       AxisVector.Zero();
    280       AngleReferenceVector.Zero();
    281       AngleReferenceNormalVector.Zero();
    282       AxisVector.x[axis] = 1.;
    283       AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    284       AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    285       //    *out << Verbose(1) << "Axisvector is ";
    286       //    AxisVector.Output(out);
    287       //    *out << " and AngleReferenceVector is ";
    288       //    AngleReferenceVector.Output(out);
    289       //    *out << "." << endl;
    290       //    *out << " and AngleReferenceNormalVector is ";
    291       //    AngleReferenceNormalVector.Output(out);
    292       //    *out << "." << endl;
    293       // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    294       Walker = mol->start;
    295       while (Walker->next != mol->end)
     216  for (int axis=0; axis<NDIM; axis++)  {
     217    AxisVector.Zero();
     218    AngleReferenceVector.Zero();
     219    AngleReferenceNormalVector.Zero();
     220    AxisVector.x[axis] = 1.;
     221    AngleReferenceVector.x[(axis+1)%NDIM] = 1.;
     222    AngleReferenceNormalVector.x[(axis+2)%NDIM] = 1.;
     223  //    *out << Verbose(1) << "Axisvector is ";
     224  //    AxisVector.Output(out);
     225  //    *out << " and AngleReferenceVector is ";
     226  //    AngleReferenceVector.Output(out);
     227  //    *out << "." << endl;
     228  //    *out << " and AngleReferenceNormalVector is ";
     229  //    AngleReferenceNormalVector.Output(out);
     230  //    *out << "." << endl;
     231    // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     232    Walker = mol->start;
     233    while (Walker->next != mol->end) {
     234      Walker = Walker->next;
     235      Vector ProjectedVector;
     236      ProjectedVector.CopyVector(&Walker->x);
     237      ProjectedVector.ProjectOntoPlane(&AxisVector);
     238      // correct for negative side
     239      //if (Projection(y) < 0)
     240        //angle = 2.*M_PI - angle;
     241      radius = ProjectedVector.Norm();
     242      if (fabs(radius) > MYEPSILON)
     243        angle = ProjectedVector.Angle(&AngleReferenceVector);
     244      else
     245        angle = 0.;  // otherwise it's a vector in Axis Direction and unimportant for boundary issues
     246       
     247      //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
     248      if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) {
     249        angle = 2.*M_PI - angle;
     250      }
     251      //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
     252      //ProjectedVector.Output(out);
     253      //*out << endl;
     254      BoundaryTestPair = BoundaryPoints[axis].insert( BoundariesPair (angle, DistancePair (radius, Walker) ) );
     255      if (BoundaryTestPair.second) { // successfully inserted
     256      } else { // same point exists, check first r, then distance of original vectors to center of gravity
     257        *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;
     258        *out << Verbose(2) << "Present vector: ";
     259        BoundaryTestPair.first->second.second->x.Output(out);
     260        *out << endl;
     261        *out << Verbose(2) << "New vector: ";
     262        Walker->x.Output(out);
     263        *out << endl;
     264        double tmp = ProjectedVector.Norm();
     265        if (tmp > BoundaryTestPair.first->second.first) {
     266          BoundaryTestPair.first->second.first = tmp;
     267          BoundaryTestPair.first->second.second = Walker;
     268          *out << Verbose(2) << "Keeping new vector." << endl;
     269        } else if (tmp == BoundaryTestPair.first->second.first) {
     270          if (BoundaryTestPair.first->second.second->x.ScalarProduct(&BoundaryTestPair.first->second.second->x) < Walker->x.ScalarProduct(&Walker->x)) { // Norm() does a sqrt, which makes it a lot slower
     271            BoundaryTestPair.first->second.second = Walker;
     272            *out << Verbose(2) << "Keeping new vector." << endl;
     273          } else {
     274            *out << Verbose(2) << "Keeping present vector." << endl;
     275          }
     276        } else {
     277            *out << Verbose(2) << "Keeping present vector." << endl;
     278        }
     279      }
     280    }
     281    // printing all inserted for debugging
     282  //    {
     283  //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     284  //      int i=0;
     285  //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     286  //        if (runner != BoundaryPoints[axis].begin())
     287  //          *out << ", " << i << ": " << *runner->second.second;
     288  //        else
     289  //          *out << i << ": " << *runner->second.second;
     290  //        i++;
     291  //      }
     292  //      *out << endl;
     293  //    }
     294    // 3c. throw out points whose distance is less than the mean of left and right neighbours
     295    bool flag = false;
     296    do { // do as long as we still throw one out per round
     297      *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl;
     298      flag = false;
     299      Boundaries::iterator left = BoundaryPoints[axis].end();
     300      Boundaries::iterator right = BoundaryPoints[axis].end();
     301      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     302        // set neighbours correctly
     303        if (runner == BoundaryPoints[axis].begin()) {
     304          left = BoundaryPoints[axis].end();
     305        } else {
     306          left = runner;
     307        }
     308        left--;
     309        right = runner;
     310        right++;
     311        if (right == BoundaryPoints[axis].end()) {
     312          right = BoundaryPoints[axis].begin();
     313        }
     314        // check distance
     315       
     316        // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    296317        {
    297           Walker = Walker->next;
    298           Vector ProjectedVector;
    299           ProjectedVector.CopyVector(&Walker->x);
    300           ProjectedVector.ProjectOntoPlane(&AxisVector);
    301           // correct for negative side
    302           //if (Projection(y) < 0)
    303           //angle = 2.*M_PI - angle;
    304           radius = ProjectedVector.Norm();
    305           if (fabs(radius) > MYEPSILON)
    306             angle = ProjectedVector.Angle(&AngleReferenceVector);
    307           else
    308             angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    309 
    310           //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    311           if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
    312             {
    313               angle = 2. * M_PI - angle;
    314             }
    315           //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
    316           //ProjectedVector.Output(out);
    317           //*out << endl;
    318           BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
    319               DistancePair (radius, Walker)));
    320           if (BoundaryTestPair.second)
    321             { // successfully inserted
    322             }
    323           else
    324             { // same point exists, check first r, then distance of original vectors to center of gravity
    325               *out << Verbose(2)
    326                   << "Encountered two vectors whose projection onto axis "
    327                   << axis << " is equal: " << endl;
    328               *out << Verbose(2) << "Present vector: ";
    329               BoundaryTestPair.first->second.second->x.Output(out);
    330               *out << endl;
    331               *out << Verbose(2) << "New vector: ";
    332               Walker->x.Output(out);
    333               *out << endl;
    334               double tmp = ProjectedVector.Norm();
    335               if (tmp > BoundaryTestPair.first->second.first)
    336                 {
    337                   BoundaryTestPair.first->second.first = tmp;
    338                   BoundaryTestPair.first->second.second = Walker;
    339                   *out << Verbose(2) << "Keeping new vector." << endl;
    340                 }
    341               else if (tmp == BoundaryTestPair.first->second.first)
    342                 {
    343                   if (BoundaryTestPair.first->second.second->x.ScalarProduct(
    344                       &BoundaryTestPair.first->second.second->x)
    345                       < Walker->x.ScalarProduct(&Walker->x))
    346                     { // Norm() does a sqrt, which makes it a lot slower
    347                       BoundaryTestPair.first->second.second = Walker;
    348                       *out << Verbose(2) << "Keeping new vector." << endl;
    349                     }
    350                   else
    351                     {
    352                       *out << Verbose(2) << "Keeping present vector." << endl;
    353                     }
    354                 }
    355               else
    356                 {
    357                   *out << Verbose(2) << "Keeping present vector." << endl;
    358                 }
    359             }
     318          Vector SideA, SideB, SideC, SideH;
     319          SideA.CopyVector(&left->second.second->x);
     320          SideA.ProjectOntoPlane(&AxisVector);
     321  //          *out << "SideA: ";
     322  //          SideA.Output(out);
     323  //          *out << endl;
     324         
     325          SideB.CopyVector(&right->second.second->x);
     326          SideB.ProjectOntoPlane(&AxisVector);
     327  //          *out << "SideB: ";
     328  //          SideB.Output(out);
     329  //          *out << endl;
     330         
     331          SideC.CopyVector(&left->second.second->x);
     332          SideC.SubtractVector(&right->second.second->x);
     333          SideC.ProjectOntoPlane(&AxisVector);
     334  //          *out << "SideC: ";
     335  //          SideC.Output(out);
     336  //          *out << endl;
     337 
     338          SideH.CopyVector(&runner->second.second->x);
     339          SideH.ProjectOntoPlane(&AxisVector);
     340  //          *out << "SideH: ";
     341  //          SideH.Output(out);
     342  //          *out << endl;
     343         
     344          // calculate each length
     345          double a = SideA.Norm();
     346          //double b = SideB.Norm();
     347          //double c = SideC.Norm();
     348          double h = SideH.Norm();
     349          // calculate the angles
     350          double alpha = SideA.Angle(&SideH);
     351          double beta = SideA.Angle(&SideC);
     352          double gamma = SideB.Angle(&SideH);
     353          double delta = SideC.Angle(&SideH);
     354          double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.);
     355  //          *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;
     356          //*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;
     357          if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h <  MinDistance)) {
     358            // throw out point
     359            //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
     360            BoundaryPoints[axis].erase(runner);
     361            flag = true;
     362          }
    360363        }
    361       // printing all inserted for debugging
    362       //    {
    363       //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    364       //      int i=0;
    365       //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    366       //        if (runner != BoundaryPoints[axis].begin())
    367       //          *out << ", " << i << ": " << *runner->second.second;
    368       //        else
    369       //          *out << i << ": " << *runner->second.second;
    370       //        i++;
    371       //      }
    372       //      *out << endl;
    373       //    }
    374       // 3c. throw out points whose distance is less than the mean of left and right neighbours
    375       bool flag = false;
    376       do
    377         { // do as long as we still throw one out per round
    378           *out << Verbose(1)
    379               << "Looking for candidates to kick out by convex condition ... "
    380               << endl;
    381           flag = false;
    382           Boundaries::iterator left = BoundaryPoints[axis].end();
    383           Boundaries::iterator right = BoundaryPoints[axis].end();
    384           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    385               != BoundaryPoints[axis].end(); runner++)
    386             {
    387               // set neighbours correctly
    388               if (runner == BoundaryPoints[axis].begin())
    389                 {
    390                   left = BoundaryPoints[axis].end();
    391                 }
    392               else
    393                 {
    394                   left = runner;
    395                 }
    396               left--;
    397               right = runner;
    398               right++;
    399               if (right == BoundaryPoints[axis].end())
    400                 {
    401                   right = BoundaryPoints[axis].begin();
    402                 }
    403               // check distance
    404 
    405               // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    406                 {
    407                   Vector SideA, SideB, SideC, SideH;
    408                   SideA.CopyVector(&left->second.second->x);
    409                   SideA.ProjectOntoPlane(&AxisVector);
    410                   //          *out << "SideA: ";
    411                   //          SideA.Output(out);
    412                   //          *out << endl;
    413 
    414                   SideB.CopyVector(&right->second.second->x);
    415                   SideB.ProjectOntoPlane(&AxisVector);
    416                   //          *out << "SideB: ";
    417                   //          SideB.Output(out);
    418                   //          *out << endl;
    419 
    420                   SideC.CopyVector(&left->second.second->x);
    421                   SideC.SubtractVector(&right->second.second->x);
    422                   SideC.ProjectOntoPlane(&AxisVector);
    423                   //          *out << "SideC: ";
    424                   //          SideC.Output(out);
    425                   //          *out << endl;
    426 
    427                   SideH.CopyVector(&runner->second.second->x);
    428                   SideH.ProjectOntoPlane(&AxisVector);
    429                   //          *out << "SideH: ";
    430                   //          SideH.Output(out);
    431                   //          *out << endl;
    432 
    433                   // calculate each length
    434                   double a = SideA.Norm();
    435                   //double b = SideB.Norm();
    436                   //double c = SideC.Norm();
    437                   double h = SideH.Norm();
    438                   // calculate the angles
    439                   double alpha = SideA.Angle(&SideH);
    440                   double beta = SideA.Angle(&SideC);
    441                   double gamma = SideB.Angle(&SideH);
    442                   double delta = SideC.Angle(&SideH);
    443                   double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
    444                       < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    445                   //          *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;
    446                   //*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;
    447                   if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
    448                       < MYEPSILON) && (h < MinDistance))
    449                     {
    450                       // throw out point
    451                       //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    452                       BoundaryPoints[axis].erase(runner);
    453                       flag = true;
    454                     }
    455                 }
    456             }
    457         }
    458       while (flag);
    459     }
     364      }
     365    } while (flag);
     366  }
    460367  return BoundaryPoints;
    461 }
    462 ;
     368};
    463369
    464370/** Determines greatest diameters of a cluster defined by its convex envelope.
     
    469375 * \param IsAngstroem whether we have angstroem or atomic units
    470376 * \return NDIM array of the diameters
    471  */
    472 double *
    473 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    474     bool IsAngstroem)
     377 */
     378double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem)
    475379{
    476380  // get points on boundary of NULL was given as parameter
    477381  bool BoundaryFreeFlag = false;
    478382  Boundaries *BoundaryPoints = BoundaryPtr;
    479   if (BoundaryPoints == NULL)
    480     {
    481       BoundaryFreeFlag = true;
    482       BoundaryPoints = GetBoundaryPoints(out, mol);
    483     }
    484   else
    485     {
    486       *out << Verbose(1) << "Using given boundary points set." << endl;
    487     }
     383  if (BoundaryPoints == NULL) {
     384    BoundaryFreeFlag = true;
     385    BoundaryPoints = GetBoundaryPoints(out, mol);
     386  } else {
     387    *out << Verbose(1) << "Using given boundary points set." << endl;
     388  }
     389 
    488390  // determine biggest "diameter" of cluster for each axis
    489391  Boundaries::iterator Neighbour, OtherNeighbour;
    490392  double *GreatestDiameter = new double[NDIM];
    491   for (int i = 0; i < NDIM; i++)
     393  for(int i=0;i<NDIM;i++)
    492394    GreatestDiameter[i] = 0.;
    493395  double OldComponent, tmp, w1, w2;
    494396  Vector DistanceVector, OtherVector;
    495397  int component, Othercomponent;
    496   for (int axis = 0; axis < NDIM; axis++)
    497     { // regard each projected plane
    498       //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
    499       for (int j = 0; j < 2; j++)
    500         { // and for both axis on the current plane
    501           component = (axis + j + 1) % NDIM;
    502           Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
    503           //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
    504           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    505               != BoundaryPoints[axis].end(); runner++)
    506             {
    507               //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
    508               // seek for the neighbours pair where the Othercomponent sign flips
    509               Neighbour = runner;
    510               Neighbour++;
    511               if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    512                 Neighbour = BoundaryPoints[axis].begin();
    513               DistanceVector.CopyVector(&runner->second.second->x);
    514               DistanceVector.SubtractVector(&Neighbour->second.second->x);
    515               do
    516                 { // seek for neighbour pair where it flips
    517                   OldComponent = DistanceVector.x[Othercomponent];
    518                   Neighbour++;
    519                   if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    520                     Neighbour = BoundaryPoints[axis].begin();
    521                   DistanceVector.CopyVector(&runner->second.second->x);
    522                   DistanceVector.SubtractVector(&Neighbour->second.second->x);
    523                   //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
    524                 }
    525               while ((runner != Neighbour) && (fabs(OldComponent / fabs(
    526                   OldComponent) - DistanceVector.x[Othercomponent] / fabs(
    527                   DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
    528               if (runner != Neighbour)
    529                 {
    530                   OtherNeighbour = Neighbour;
    531                   if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
    532                     OtherNeighbour = BoundaryPoints[axis].end();
    533                   OtherNeighbour--;
    534                   //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
    535                   // now we have found the pair: Neighbour and OtherNeighbour
    536                   OtherVector.CopyVector(&runner->second.second->x);
    537                   OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
    538                   //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
    539                   //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
    540                   // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
    541                   w1 = fabs(OtherVector.x[Othercomponent]);
    542                   w2 = fabs(DistanceVector.x[Othercomponent]);
    543                   tmp = fabs((w1 * DistanceVector.x[component] + w2
    544                       * OtherVector.x[component]) / (w1 + w2));
    545                   // mark if it has greater diameter
    546                   //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
    547                   GreatestDiameter[component] = (GreatestDiameter[component]
    548                       > tmp) ? GreatestDiameter[component] : tmp;
    549                 } //else
    550               //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
    551             }
    552         }
     398  for(int axis=0;axis<NDIM;axis++) { // regard each projected plane
     399    //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
     400    for (int j=0;j<2;j++) { // and for both axis on the current plane
     401      component = (axis+j+1)%NDIM;
     402      Othercomponent = (axis+1+((j+1) & 1))%NDIM;
     403      //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
     404      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     405        //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
     406        // seek for the neighbours pair where the Othercomponent sign flips
     407        Neighbour = runner;
     408        Neighbour++;
     409        if (Neighbour == BoundaryPoints[axis].end())  // make it wrap around
     410          Neighbour = BoundaryPoints[axis].begin();
     411        DistanceVector.CopyVector(&runner->second.second->x);
     412        DistanceVector.SubtractVector(&Neighbour->second.second->x);
     413        do {  // seek for neighbour pair where it flips
     414          OldComponent = DistanceVector.x[Othercomponent];
     415          Neighbour++;
     416          if (Neighbour == BoundaryPoints[axis].end())  // make it wrap around
     417            Neighbour = BoundaryPoints[axis].begin();
     418          DistanceVector.CopyVector(&runner->second.second->x);
     419          DistanceVector.SubtractVector(&Neighbour->second.second->x);
     420          //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
     421        } while ((runner != Neighbour) && ( fabs( OldComponent/fabs(OldComponent) - DistanceVector.x[Othercomponent]/fabs(DistanceVector.x[Othercomponent]) ) < MYEPSILON)); // as long as sign does not flip
     422        if (runner != Neighbour) {
     423          OtherNeighbour = Neighbour;
     424          if (OtherNeighbour == BoundaryPoints[axis].begin())  // make it wrap around
     425            OtherNeighbour = BoundaryPoints[axis].end();
     426          OtherNeighbour--;
     427          //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
     428          // now we have found the pair: Neighbour and OtherNeighbour
     429          OtherVector.CopyVector(&runner->second.second->x);
     430          OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
     431          //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
     432          //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
     433          // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
     434          w1 = fabs(OtherVector.x[Othercomponent]);
     435          w2 = fabs(DistanceVector.x[Othercomponent]);
     436          tmp = fabs((w1*DistanceVector.x[component] + w2*OtherVector.x[component])/(w1+w2));
     437          // mark if it has greater diameter
     438          //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
     439          GreatestDiameter[component] = (GreatestDiameter[component] > tmp) ? GreatestDiameter[component] : tmp;
     440        } //else
     441          //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
     442      }
    553443    }
    554   *out << Verbose(0) << "RESULT: The biggest diameters are "
    555       << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
    556       << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
    557       : "atomiclength") << "." << endl;
     444  }
     445  *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl;
    558446
    559447  // free reference lists
    560448  if (BoundaryFreeFlag)
    561     delete[] (BoundaryPoints);
     449    delete[](BoundaryPoints);
    562450
    563451  return GreatestDiameter;
    564 }
    565 ;
    566 
    567 /** Creates the objects in a raster3d file (renderable with a header.r3d)
    568  * \param *out output stream for debugging
    569  * \param *tecplot output stream for tecplot data
    570  * \param *Tess Tesselation structure with constructed triangles
    571  * \param *mol molecule structure with atom positions
    572  */
    573 void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    574 {
    575         atom *Walker = mol->start;
    576         bond *Binder = mol->first;
    577         int i;
    578         Vector *center = mol->DetermineCenterOfAll(out);
    579         if (rasterfile != NULL) {
    580                 //cout << Verbose(1) << "Writing Raster3D file ... ";
    581                 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    582                 *rasterfile << "@header.r3d" << endl;
    583                 *rasterfile << "# All atoms as spheres" << endl;
    584                 while (Walker->next != mol->end) {
    585                         Walker = Walker->next;
    586                         *rasterfile << "2" << endl << "  ";     // 2 is sphere type
    587                         for (i=0;i<NDIM;i++)
    588                                 *rasterfile << Walker->x.x[i]+center->x[i] << " ";
    589                         *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    590                 }
    591 
    592                 *rasterfile << "# All bonds as vertices" << endl;
    593                 while (Binder->next != mol->last) {
    594                         Binder = Binder->next;
    595                         *rasterfile << "3" << endl << "  ";     // 2 is round-ended cylinder type
    596                         for (i=0;i<NDIM;i++)
    597                                 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
    598                         *rasterfile << "\t0.03\t";
    599                         for (i=0;i<NDIM;i++)
    600                                 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
    601                         *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    602                 }
    603 
    604                 *rasterfile << "# All tesselation triangles" << endl;
    605                 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    606                         *rasterfile << "1" << endl << "  ";     // 1 is triangle type
    607                         for (i=0;i<3;i++) {     // print each node
    608                                 for (int j=0;j<NDIM;j++)        // and for each node all NDIM coordinates
    609                                         *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
    610                                 *rasterfile << "\t";
    611                         }
    612                         *rasterfile << "1. 0. 0." << endl;      // red as colour
    613                         *rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    614                 }
    615         } else {
    616                 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    617         }
    618         delete(center);
    619 };
    620 
    621 /** This function creates the tecplot file, displaying the tesselation of the hull.
    622  * \param *out output stream for debugging
    623  * \param *tecplot output stream for tecplot data
    624  * \param N arbitrary number to differentiate various zones in the tecplot format
    625  */
    626 void
    627 write_tecplot_file(ofstream *out, ofstream *tecplot,
    628     class Tesselation *TesselStruct, class molecule *mol, int N)
    629 {
    630   if (tecplot != NULL)
    631     {
    632       *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    633       *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
    634       *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
    635           << TesselStruct->PointsOnBoundaryCount << ", E="
    636           << TesselStruct->TrianglesOnBoundaryCount
    637           << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    638       int *LookupList = new int[mol->AtomCount];
    639       for (int i = 0; i < mol->AtomCount; i++)
    640         LookupList[i] = -1;
    641 
    642       // print atom coordinates
    643       *out << Verbose(2) << "The following triangles were created:";
    644       int Counter = 1;
    645       atom *Walker = NULL;
    646       for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
    647           != TesselStruct->PointsOnBoundary.end(); target++)
    648         {
    649           Walker = target->second->node;
    650           LookupList[Walker->nr] = Counter++;
    651           *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
    652               << Walker->x.x[2] << " " << endl;
    653         }
    654       *tecplot << endl;
    655       // print connectivity
    656       for (TriangleMap::iterator runner =
    657           TesselStruct->TrianglesOnBoundary.begin(); runner
    658           != TesselStruct->TrianglesOnBoundary.end(); runner++)
    659         {
    660           *out << " " << runner->second->endpoints[0]->node->Name << "<->"
    661               << runner->second->endpoints[1]->node->Name << "<->"
    662               << runner->second->endpoints[2]->node->Name;
    663           *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
    664               << LookupList[runner->second->endpoints[1]->node->nr] << " "
    665               << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    666         }
    667       delete[] (LookupList);
    668       *out << endl;
    669     }
    670 }
     452};
     453
    671454
    672455/** Determines the volume of a cluster.
    673456 * Determines first the convex envelope, then tesselates it and calculates its volume.
    674457 * \param *out output stream for debugging
    675  * \param *tecplot output stream for tecplot data
    676458 * \param *configuration needed for path to store convex envelope file
    677459 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired
    678460 * \param *mol molecule structure representing the cluster
    679  * \return determined volume of the cluster in cubed config:GetIsAngstroem()
    680461 */
    681 double
    682 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration,
    683     Boundaries *BoundaryPtr, molecule *mol)
     462double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPtr, molecule *mol)
    684463{
    685464  bool IsAngstroem = configuration->GetIsAngstroem();
     
    690469  double volume = 0.;
    691470  double PyramidVolume = 0.;
    692   double G, h;
    693   Vector x, y;
    694   double a, b, c;
    695 
    696   //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
     471  double G,h;
     472  Vector x,y;
     473  double a,b,c;
    697474
    698475  // 1. calculate center of gravity
    699476  *out << endl;
    700477  Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    701 
     478 
    702479  // 2. translate all points into CoG
    703480  *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    704481  Walker = mol->start;
    705   while (Walker->next != mol->end)
    706     {
    707       Walker = Walker->next;
    708       Walker->x.Translate(CenterOfGravity);
     482  while (Walker->next != mol->end) {
     483    Walker = Walker->next;
     484    Walker->x.Translate(CenterOfGravity);
     485  }
     486 
     487  // 3. Find all points on the boundary
     488  if (BoundaryPoints == NULL) {
     489    BoundaryFreeFlag = true;
     490    BoundaryPoints = GetBoundaryPoints(out, mol);
     491  } else {
     492    *out << Verbose(1) << "Using given boundary points set." << endl;
     493  }
     494 
     495  // 4. fill the boundary point list
     496  for (int axis=0;axis<NDIM;axis++)
     497    for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     498      TesselStruct->AddPoint(runner->second.second);
    709499    }
    710500
    711   // 3. Find all points on the boundary
    712   if (BoundaryPoints == NULL)
    713     {
    714       BoundaryFreeFlag = true;
    715       BoundaryPoints = GetBoundaryPoints(out, mol);
    716     }
    717   else
    718     {
    719       *out << Verbose(1) << "Using given boundary points set." << endl;
    720     }
    721 
    722   // 4. fill the boundary point list
    723   for (int axis = 0; axis < NDIM; axis++)
    724     for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    725         != BoundaryPoints[axis].end(); runner++)
    726       {
    727         TesselStruct->AddPoint(runner->second.second);
    728       }
    729 
    730   *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
    731       << " points on the convex boundary." << endl;
     501  *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl;
    732502  // now we have the whole set of edge points in the BoundaryList
    733503
     504
    734505  // listing for debugging
    735   //  *out << Verbose(1) << "Listing PointsOnBoundary:";
    736   //  for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
    737   //    *out << " " << *runner->second;
    738   //  }
    739   //  *out << endl;
    740 
     506//  *out << Verbose(1) << "Listing PointsOnBoundary:";
     507//  for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
     508//    *out << " " << *runner->second;
     509//  }
     510//  *out << endl;
     511 
    741512  // 5a. guess starting triangle
    742513  TesselStruct->GuessStartingTriangle(out);
    743 
     514 
    744515  // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    745516  TesselStruct->TesselateOnBoundary(out, configuration, mol);
    746517
    747   *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
    748       << " triangles with " << TesselStruct->LinesOnBoundaryCount
    749       << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
    750       << endl;
     518  *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl;
    751519
    752520  // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
    753   *out << Verbose(1)
    754       << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
    755       << endl;
    756   for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
    757       != TesselStruct->TrianglesOnBoundary.end(); runner++)
    758     { // go through every triangle, calculate volume of its pyramid with CoG as peak
    759       x.CopyVector(&runner->second->endpoints[0]->node->x);
    760       x.SubtractVector(&runner->second->endpoints[1]->node->x);
    761       y.CopyVector(&runner->second->endpoints[0]->node->x);
    762       y.SubtractVector(&runner->second->endpoints[2]->node->x);
    763       a = sqrt(runner->second->endpoints[0]->node->x.Distance(
    764           &runner->second->endpoints[1]->node->x));
    765       b = sqrt(runner->second->endpoints[0]->node->x.Distance(
    766           &runner->second->endpoints[2]->node->x));
    767       c = sqrt(runner->second->endpoints[2]->node->x.Distance(
    768           &runner->second->endpoints[1]->node->x));
    769       G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a
    770           * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle
    771       x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
    772           &runner->second->endpoints[1]->node->x,
    773           &runner->second->endpoints[2]->node->x);
    774       x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
    775       h = x.Norm(); // distance of CoG to triangle
    776       PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
    777       *out << Verbose(2) << "Area of triangle is " << G << " "
    778           << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
    779           << h << " and the volume is " << PyramidVolume << " "
    780           << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    781       volume += PyramidVolume;
    782     }
    783   *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
    784       << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
    785       << endl;
     521  *out << Verbose(1) << "Calculating the volume of the pyramids formed out of triangles and center of gravity." << endl;
     522  for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak
     523    x.CopyVector(&runner->second->endpoints[0]->node->x);
     524    x.SubtractVector(&runner->second->endpoints[1]->node->x);
     525    y.CopyVector(&runner->second->endpoints[0]->node->x);
     526    y.SubtractVector(&runner->second->endpoints[2]->node->x);
     527    a = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[1]->node->x));
     528    b = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[2]->node->x));
     529    c = sqrt(runner->second->endpoints[2]->node->x.Distance(&runner->second->endpoints[1]->node->x));
     530    G =  sqrt( ( (a*a+b*b+c*c)*(a*a+b*b+c*c) - 2*(a*a*a*a + b*b*b*b + c*c*c*c) )/16.); // area of tesselated triangle
     531    x.MakeNormalVector(&runner->second->endpoints[0]->node->x, &runner->second->endpoints[1]->node->x, &runner->second->endpoints[2]->node->x);
     532    x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
     533    h = x.Norm(); // distance of CoG to triangle
     534    PyramidVolume = (1./3.) * G * h;    // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
     535    *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     536    volume += PyramidVolume;
     537  }
     538  *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     539
    786540
    787541  // 7. translate all points back from CoG
    788   *out << Verbose(1) << "Translating system back from Center of Gravity."
    789       << endl;
     542  *out << Verbose(1) << "Translating system back from Center of Gravity." << endl;
    790543  CenterOfGravity->Scale(-1);
    791544  Walker = mol->start;
    792   while (Walker->next != mol->end)
    793     {
    794       Walker = Walker->next;
    795       Walker->x.Translate(CenterOfGravity);
    796     }
    797 
    798   // 8. Store triangles in tecplot file
    799   write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
     545  while (Walker->next != mol->end) {
     546    Walker = Walker->next;
     547    Walker->x.Translate(CenterOfGravity);
     548  }
    800549
    801550  // free reference lists
    802551  if (BoundaryFreeFlag)
    803     delete[] (BoundaryPoints);
    804 
     552    delete[](BoundaryPoints);
     553 
    805554  return volume;
    806 }
    807 ;
     555};
     556
    808557
    809558/** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density.
     
    815564 * \param celldensity desired average density in final cell
    816565 */
    817 void
    818 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
    819     double ClusterVolume, double celldensity)
     566void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity)
    820567{
    821568  // transform to PAS
    822569  mol->PrincipalAxisSystem(out, true);
    823 
     570 
    824571  // some preparations beforehand
    825572  bool IsAngstroem = configuration->GetIsAngstroem();
     
    827574  double clustervolume;
    828575  if (ClusterVolume == 0)
    829     clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
    830         BoundaryPoints, mol);
    831   else
     576    clustervolume = VolumeOfConvexEnvelope(out, configuration, BoundaryPoints, mol);
     577  else
    832578    clustervolume = ClusterVolume;
    833   double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
    834       IsAngstroem);
     579  double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem);
    835580  Vector BoxLengths;
    836   int repetition[NDIM] =
    837     { 1, 1, 1 };
     581  int repetition[NDIM] = {1, 1, 1};
    838582  int TotalNoClusters = 1;
    839   for (int i = 0; i < NDIM; i++)
     583  for (int i=0;i<NDIM;i++)
    840584    TotalNoClusters *= repetition[i];
    841585
     
    843587  double totalmass = 0.;
    844588  atom *Walker = mol->start;
    845   while (Walker->next != mol->end)
    846     {
    847       Walker = Walker->next;
    848       totalmass += Walker->type->mass;
    849     }
    850   *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
    851       << totalmass << " atomicmassunit." << endl;
    852 
    853   *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
    854       << totalmass / clustervolume << " atomicmassunit/"
    855       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    856 
     589  while (Walker->next != mol->end) {
     590    Walker = Walker->next;
     591    totalmass += Walker->type->mass;
     592  }
     593  *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl;
     594 
     595  *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     596 
    857597  // solve cubic polynomial
    858   *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
    859       << endl;
     598  *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl;
    860599  double cellvolume;
    861600  if (IsAngstroem)
    862     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
    863         / clustervolume)) / (celldensity - 1);
     601    cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1);
    864602  else
    865     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
    866         / clustervolume)) / (celldensity - 1);
    867   *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
    868       << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
    869       : "atomiclength") << "^3." << endl;
    870 
    871   double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
    872       * GreatestDiameter[1] * GreatestDiameter[2]);
    873   *out << Verbose(1)
    874       << "Minimum volume of the convex envelope contained in a rectangular box is "
    875       << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
    876       : "atomiclength") << "^3." << endl;
    877   if (minimumvolume > cellvolume)
    878     {
    879       cerr << Verbose(0)
    880           << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
    881           << endl;
    882       cout << Verbose(0)
    883           << "Setting Box dimensions to minimum possible, the greatest diameters."
    884           << endl;
    885       for (int i = 0; i < NDIM; i++)
    886         BoxLengths.x[i] = GreatestDiameter[i];
    887       mol->CenterEdge(out, &BoxLengths);
     603    cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1);
     604  *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     605 
     606  double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]);
     607  *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     608  if (minimumvolume > cellvolume) {
     609    cerr << Verbose(0) << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" << endl;
     610    cout << Verbose(0) << "Setting Box dimensions to minimum possible, the greatest diameters." << endl;
     611    for(int i=0;i<NDIM;i++)
     612      BoxLengths.x[i] = GreatestDiameter[i];
     613    mol->CenterEdge(out, &BoxLengths);
     614  } else {
     615    BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]);
     616    BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1]
     617              + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2]
     618              + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]);
     619    BoxLengths.x[2] = minimumvolume - cellvolume;
     620    double x0 = 0.,x1 = 0.,x2 = 0.;
     621    if (gsl_poly_solve_cubic(BoxLengths.x[0],BoxLengths.x[1],BoxLengths.x[2],&x0,&x1,&x2) == 1) // either 1 or 3 on return
     622      *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 << " ." << endl;
     623    else {
     624      *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " ." << endl;
     625      x0 = x2;  // sorted in ascending order
    888626    }
    889   else
    890     {
    891       BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
    892           * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
    893       BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
    894           * GreatestDiameter[1] + repetition[0] * repetition[2]
    895           * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
    896           * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
    897       BoxLengths.x[2] = minimumvolume - cellvolume;
    898       double x0 = 0., x1 = 0., x2 = 0.;
    899       if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
    900           BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
    901         *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
    902             << " ." << endl;
    903       else
    904         {
    905           *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
    906               << " and " << x1 << " and " << x2 << " ." << endl;
    907           x0 = x2; // sorted in ascending order
    908         }
    909 
    910       cellvolume = 1;
    911       for (int i = 0; i < NDIM; i++)
    912         {
    913           BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
    914           cellvolume *= BoxLengths.x[i];
    915         }
    916 
    917       // set new box dimensions
    918       *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    919       mol->CenterInBox((ofstream *) &cout, &BoxLengths);
     627 
     628    cellvolume = 1;
     629    for(int i=0;i<NDIM;i++) {
     630      BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
     631      cellvolume *= BoxLengths.x[i];
    920632    }
     633 
     634    // set new box dimensions
     635    *out << Verbose(0) << "Translating to box with these boundaries." << endl;
     636    mol->CenterInBox((ofstream *)&cout, &BoxLengths);
     637  }
    921638  // update Box of atoms by boundary
    922639  mol->SetBoxDimension(&BoxLengths);
    923   *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
    924       << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
    925       << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
    926       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    927 }
    928 ;
     640  *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " << BoxLengths.x[2] << " with total volume of " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     641};
     642
    929643
    930644// =========================================================== class TESSELATION ===========================================
     
    934648Tesselation::Tesselation()
    935649{
    936   PointsOnBoundaryCount = 0;
    937   LinesOnBoundaryCount = 0;
     650  PointsOnBoundaryCount = 0; 
     651  LinesOnBoundaryCount = 0; 
    938652  TrianglesOnBoundaryCount = 0;
    939   TriangleFilesWritten = 0;
    940 }
    941 ;
     653};
    942654
    943655/** Constructor of class Tesselation.
     
    946658Tesselation::~Tesselation()
    947659{
    948         cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
    949         for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
    950                 if (runner->second != NULL) {
    951                         delete (runner->second);
    952                         runner->second = NULL;
    953                 } else
    954                         cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
    955         }
    956         for (LineMap::iterator runner = LinesOnBoundary.begin(); runner != LinesOnBoundary.end(); runner++) {
    957                 if (runner->second != NULL) {
    958                         delete (runner->second);
    959                         runner->second = NULL;
    960                 } else
    961                         cerr << "ERROR: The line " << runner->first << " has already been free'd." << endl;
    962         }
    963         for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
    964                 if (runner->second != NULL) {
    965                         delete (runner->second);
    966                         runner->second = NULL;
    967                 } else
    968                         cerr << "ERROR: The point " << runner->first << " has already been free'd." << endl;
    969         }
    970 }
    971 ;
     660  for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
     661    delete(runner->second);
     662  }
     663};
    972664
    973665/** Gueses first starting triangle of the convex envelope.
     
    975667 * \param *out output stream for debugging
    976668 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster
    977  */
    978 void
    979 Tesselation::GuessStartingTriangle(ofstream *out)
     669 */
     670void Tesselation::GuessStartingTriangle(ofstream *out)
    980671{
    981672  // 4b. create a starting triangle
    982673  // 4b1. create all distances
    983674  DistanceMultiMap DistanceMMap;
    984   double distance, tmp;
    985   Vector PlaneVector, TrialVector;
    986   PointMap::iterator A, B, C; // three nodes of the first triangle
    987   A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
    988 
    989   // with A chosen, take each pair B,C and sort
    990   if (A != PointsOnBoundary.end())
    991     {
    992       B = A;
    993       B++;
    994       for (; B != PointsOnBoundary.end(); B++)
    995         {
    996           C = B;
    997           C++;
    998           for (; C != PointsOnBoundary.end(); C++)
    999             {
    1000               tmp = A->second->node->x.Distance(&B->second->node->x);
    1001               distance = tmp * tmp;
    1002               tmp = A->second->node->x.Distance(&C->second->node->x);
    1003               distance += tmp * tmp;
    1004               tmp = B->second->node->x.Distance(&C->second->node->x);
    1005               distance += tmp * tmp;
    1006               DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
    1007                   PointMap::iterator, PointMap::iterator> (B, C)));
    1008             }
    1009         }
     675  double distance;
     676  for (PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
     677    for(PointMap::iterator sprinter = PointsOnBoundary.begin(); sprinter != PointsOnBoundary.end(); sprinter++) {
     678      if (runner->first < sprinter->first) {
     679        distance = runner->second->node->x.Distance(&sprinter->second->node->x);
     680        DistanceMMap.insert( DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator>(runner,sprinter) ) );
     681      }
    1010682    }
    1011   //    // listing distances
    1012   //    *out << Verbose(1) << "Listing DistanceMMap:";
    1013   //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
    1014   //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
    1015   //    }
    1016   //    *out << endl;
    1017   // 4b2. pick three baselines forming a triangle
    1018   // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     683  }
     684
     685//    // listing distances
     686//    *out << Verbose(1) << "Listing DistanceMMap:";
     687//    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
     688//      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
     689//    }
     690//    *out << endl;
     691 
     692  // 4b2. take three smallest distance that form a triangle
     693  // we take the smallest distance as the base line
    1019694  DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    1020   for (; baseline != DistanceMMap.end(); baseline++)
    1021     {
    1022       // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1023       // 2. next, we have to check whether all points reside on only one side of the triangle
    1024       // 3. construct plane vector
    1025       PlaneVector.MakeNormalVector(&A->second->node->x,
    1026           &baseline->second.first->second->node->x,
    1027           &baseline->second.second->second->node->x);
    1028       *out << Verbose(2) << "Plane vector of candidate triangle is ";
    1029       PlaneVector.Output(out);
    1030       *out << endl;
    1031       // 4. loop over all points
    1032       double sign = 0.;
    1033       PointMap::iterator checker = PointsOnBoundary.begin();
    1034       for (; checker != PointsOnBoundary.end(); checker++)
    1035         {
    1036           // (neglecting A,B,C)
    1037           if ((checker == A) || (checker == baseline->second.first) || (checker
    1038               == baseline->second.second))
    1039             continue;
    1040           // 4a. project onto plane vector
    1041           TrialVector.CopyVector(&checker->second->node->x);
    1042           TrialVector.SubtractVector(&A->second->node->x);
    1043           distance = TrialVector.Projection(&PlaneVector);
    1044           if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
    1045             continue;
    1046           *out << Verbose(3) << "Projection of " << checker->second->node->Name
    1047               << " yields distance of " << distance << "." << endl;
    1048           tmp = distance / fabs(distance);
    1049           // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
    1050           if ((sign != 0) && (tmp != sign))
    1051             {
    1052               // 4c. If so, break 4. loop and continue with next candidate in 1. loop
    1053               *out << Verbose(2) << "Current candidates: "
    1054                   << A->second->node->Name << ","
    1055                   << baseline->second.first->second->node->Name << ","
    1056                   << baseline->second.second->second->node->Name << " leave "
    1057                   << checker->second->node->Name << " outside the convex hull."
    1058                   << endl;
    1059               break;
    1060             }
    1061           else
    1062             { // note the sign for later
    1063               *out << Verbose(2) << "Current candidates: "
    1064                   << A->second->node->Name << ","
    1065                   << baseline->second.first->second->node->Name << ","
    1066                   << baseline->second.second->second->node->Name << " leave "
    1067                   << checker->second->node->Name << " inside the convex hull."
    1068                   << endl;
    1069               sign = tmp;
    1070             }
    1071           // 4d. Check whether the point is inside the triangle (check distance to each node
    1072           tmp = checker->second->node->x.Distance(&A->second->node->x);
    1073           int innerpoint = 0;
    1074           if ((tmp < A->second->node->x.Distance(
    1075               &baseline->second.first->second->node->x)) && (tmp
    1076               < A->second->node->x.Distance(
    1077                   &baseline->second.second->second->node->x)))
    1078             innerpoint++;
    1079           tmp = checker->second->node->x.Distance(
    1080               &baseline->second.first->second->node->x);
    1081           if ((tmp < baseline->second.first->second->node->x.Distance(
    1082               &A->second->node->x)) && (tmp
    1083               < baseline->second.first->second->node->x.Distance(
    1084                   &baseline->second.second->second->node->x)))
    1085             innerpoint++;
    1086           tmp = checker->second->node->x.Distance(
    1087               &baseline->second.second->second->node->x);
    1088           if ((tmp < baseline->second.second->second->node->x.Distance(
    1089               &baseline->second.first->second->node->x)) && (tmp
    1090               < baseline->second.second->second->node->x.Distance(
    1091                   &A->second->node->x)))
    1092             innerpoint++;
    1093           // 4e. If so, break 4. loop and continue with next candidate in 1. loop
    1094           if (innerpoint == 3)
    1095             break;
    1096         }
    1097       // 5. come this far, all on same side? Then break 1. loop and construct triangle
    1098       if (checker == PointsOnBoundary.end())
    1099         {
    1100           *out << "Looks like we have a candidate!" << endl;
    1101           break;
    1102         }
    1103     }
    1104   if (baseline != DistanceMMap.end())
    1105     {
    1106       BPS[0] = baseline->second.first->second;
    1107       BPS[1] = baseline->second.second->second;
    1108       BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1109       BPS[0] = A->second;
    1110       BPS[1] = baseline->second.second->second;
    1111       BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1112       BPS[0] = baseline->second.first->second;
    1113       BPS[1] = A->second;
    1114       BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1115 
    1116       // 4b3. insert created triangle
    1117       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1118       TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1119       TrianglesOnBoundaryCount++;
    1120       for (int i = 0; i < NDIM; i++)
    1121         {
    1122           LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
    1123           LinesOnBoundaryCount++;
    1124         }
    1125 
    1126       *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
    1127     }
    1128   else
    1129     {
    1130       *out << Verbose(1) << "No starting triangle found." << endl;
    1131       exit(255);
    1132     }
    1133 }
    1134 ;
     695  BPS[0] = baseline->second.first->second;
     696  BPS[1] = baseline->second.second->second;
     697  BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
     698
     699  // take the second smallest as the second base line
     700  DistanceMultiMap::iterator secondline = DistanceMMap.begin();
     701  do {
     702    secondline++;
     703  } while (!(
     704      ((BPS[0] == secondline->second.first->second) && (BPS[1] != secondline->second.second->second)) ||
     705      ((BPS[0] == secondline->second.second->second) && (BPS[1] != secondline->second.first->second)) ||
     706      ((BPS[1] == secondline->second.first->second) && (BPS[0] != secondline->second.second->second)) ||
     707      ((BPS[1] == secondline->second.second->second) && (BPS[0] != secondline->second.first->second))
     708    ));
     709  BPS[0] = secondline->second.first->second;
     710  BPS[1] = secondline->second.second->second;
     711  BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
     712
     713  // connection yields the third line (note: first and second endpoint are sorted!)
     714  if (baseline->second.first->second == secondline->second.first->second) {
     715    SetEndpointsOrdered(BPS, baseline->second.second->second, secondline->second.second->second);
     716  } else if (baseline->second.first->second == secondline->second.second->second) {
     717    SetEndpointsOrdered(BPS, baseline->second.second->second, secondline->second.first->second);
     718  } else if (baseline->second.second->second == secondline->second.first->second) {
     719    SetEndpointsOrdered(BPS, baseline->second.first->second, baseline->second.second->second);
     720  } else if (baseline->second.second->second == secondline->second.second->second) {
     721    SetEndpointsOrdered(BPS, baseline->second.first->second, baseline->second.first->second);
     722  }
     723  BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     724 
     725  // 4b3. insert created triangle
     726  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     727  TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) );
     728  TrianglesOnBoundaryCount++;
     729  for(int i=0;i<NDIM;i++) {
     730    LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) );
     731    LinesOnBoundaryCount++;
     732  }
     733
     734  *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
     735};
     736
    1135737
    1136738/** Tesselates the convex envelope of a cluster from a single starting triangle.
     
    1147749 * \param *mol the cluster as a molecule structure
    1148750 */
    1149 void
    1150 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    1151     molecule *mol)
     751void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol)
    1152752{
    1153753  bool flag;
     
    1155755  class BoundaryPointSet *peak = NULL;
    1156756  double SmallestAngle, TempAngle;
    1157   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
    1158       PropagationVector;
     757  Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector;
    1159758  LineMap::iterator LineChecker[2];
    1160   do
    1161     {
    1162       flag = false;
    1163       for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
    1164           != LinesOnBoundary.end(); baseline++)
    1165         if (baseline->second->TrianglesCount == 1)
    1166           {
    1167             *out << Verbose(2) << "Current baseline is between "
    1168                 << *(baseline->second) << "." << endl;
    1169             // 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)
    1170             SmallestAngle = M_PI;
    1171             BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1172             // get peak point with respect to this base line's only triangle
    1173             for (int i = 0; i < 3; i++)
    1174               if ((BTS->endpoints[i] != baseline->second->endpoints[0])
    1175                   && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1176                 peak = BTS->endpoints[i];
    1177             *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1178             // normal vector of triangle
    1179             BTS->GetNormalVector(NormalVector);
    1180             *out << Verbose(4) << "NormalVector of base triangle is ";
    1181             NormalVector.Output(out);
    1182             *out << endl;
    1183             // offset to center of triangle
    1184             CenterVector.Zero();
    1185             for (int i = 0; i < 3; i++)
    1186               CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1187             CenterVector.Scale(1. / 3.);
    1188             *out << Verbose(4) << "CenterVector of base triangle is ";
    1189             CenterVector.Output(out);
    1190             *out << endl;
    1191             // vector in propagation direction (out of triangle)
    1192             // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
    1193             TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1194             TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1195             PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
    1196             TempVector.CopyVector(&CenterVector);
    1197             TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1198             //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1199             if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1200               PropagationVector.Scale(-1.);
    1201             *out << Verbose(4) << "PropagationVector of base triangle is ";
    1202             PropagationVector.Output(out);
    1203             *out << endl;
    1204             winner = PointsOnBoundary.end();
    1205             for (PointMap::iterator target = PointsOnBoundary.begin(); target
    1206                 != PointsOnBoundary.end(); target++)
    1207               if ((target->second != baseline->second->endpoints[0])
    1208                   && (target->second != baseline->second->endpoints[1]))
    1209                 { // don't take the same endpoints
    1210                   *out << Verbose(3) << "Target point is " << *(target->second)
    1211                       << ":";
    1212                   bool continueflag = true;
    1213 
    1214                   VirtualNormalVector.CopyVector(
    1215                       &baseline->second->endpoints[0]->node->x);
    1216                   VirtualNormalVector.AddVector(
    1217                       &baseline->second->endpoints[0]->node->x);
    1218                   VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
    1219                   VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
    1220                   TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1221                   continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
    1222                   if (!continueflag)
    1223                     {
    1224                       *out << Verbose(4)
    1225                           << "Angle between propagation direction and base line to "
    1226                           << *(target->second) << " is " << TempAngle
    1227                           << ", bad direction!" << endl;
    1228                       continue;
    1229                     }
    1230                   else
    1231                     *out << Verbose(4)
    1232                         << "Angle between propagation direction and base line to "
    1233                         << *(target->second) << " is " << TempAngle
    1234                         << ", good direction!" << endl;
    1235                   LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1236                       target->first);
    1237                   LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1238                       target->first);
    1239                   //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
    1240                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1241                   //            else
    1242                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1243                   //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
    1244                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1245                   //            else
    1246                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1247                   // check first endpoint (if any connecting line goes to target or at least not more than 1)
    1248                   continueflag = continueflag && (((LineChecker[0]
    1249                       == baseline->second->endpoints[0]->lines.end())
    1250                       || (LineChecker[0]->second->TrianglesCount == 1)));
    1251                   if (!continueflag)
    1252                     {
    1253                       *out << Verbose(4) << *(baseline->second->endpoints[0])
    1254                           << " has line " << *(LineChecker[0]->second)
    1255                           << " to " << *(target->second)
    1256                           << " as endpoint with "
    1257                           << LineChecker[0]->second->TrianglesCount
    1258                           << " triangles." << endl;
    1259                       continue;
    1260                     }
    1261                   // check second endpoint (if any connecting line goes to target or at least not more than 1)
    1262                   continueflag = continueflag && (((LineChecker[1]
    1263                       == baseline->second->endpoints[1]->lines.end())
    1264                       || (LineChecker[1]->second->TrianglesCount == 1)));
    1265                   if (!continueflag)
    1266                     {
    1267                       *out << Verbose(4) << *(baseline->second->endpoints[1])
    1268                           << " has line " << *(LineChecker[1]->second)
    1269                           << " to " << *(target->second)
    1270                           << " as endpoint with "
    1271                           << LineChecker[1]->second->TrianglesCount
    1272                           << " triangles." << endl;
    1273                       continue;
    1274                     }
    1275                   // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1276                   continueflag = continueflag && (!(((LineChecker[0]
    1277                       != baseline->second->endpoints[0]->lines.end())
    1278                       && (LineChecker[1]
    1279                           != baseline->second->endpoints[1]->lines.end())
    1280                       && (GetCommonEndpoint(LineChecker[0]->second,
    1281                           LineChecker[1]->second) == peak))));
    1282                   if (!continueflag)
    1283                     {
    1284                       *out << Verbose(4) << "Current target is peak!" << endl;
    1285                       continue;
    1286                     }
    1287                   // in case NOT both were found
    1288                   if (continueflag)
    1289                     { // create virtually this triangle, get its normal vector, calculate angle
    1290                       flag = true;
    1291                       VirtualNormalVector.MakeNormalVector(
    1292                           &baseline->second->endpoints[0]->node->x,
    1293                           &baseline->second->endpoints[1]->node->x,
    1294                           &target->second->node->x);
    1295                       // make it always point inward
    1296                       if (baseline->second->endpoints[0]->node->x.Projection(
    1297                           &VirtualNormalVector) > 0)
    1298                         VirtualNormalVector.Scale(-1.);
    1299                       // calculate angle
    1300                       TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1301                       *out << Verbose(4) << "NormalVector is ";
    1302                       VirtualNormalVector.Output(out);
    1303                       *out << " and the angle is " << TempAngle << "." << endl;
    1304                       if (SmallestAngle > TempAngle)
    1305                         { // set to new possible winner
    1306                           SmallestAngle = TempAngle;
    1307                           winner = target;
    1308                         }
    1309                     }
    1310                 }
    1311             // 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
    1312             if (winner != PointsOnBoundary.end())
    1313               {
    1314                 *out << Verbose(2) << "Winning target point is "
    1315                     << *(winner->second) << " with angle " << SmallestAngle
    1316                     << "." << endl;
    1317                 // create the lins of not yet present
    1318                 BLS[0] = baseline->second;
    1319                 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1320                 LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1321                     winner->first);
    1322                 LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1323                     winner->first);
    1324                 if (LineChecker[0]
    1325                     == baseline->second->endpoints[0]->lines.end())
    1326                   { // create
    1327                     BPS[0] = baseline->second->endpoints[0];
    1328                     BPS[1] = winner->second;
    1329                     BLS[1] = new class BoundaryLineSet(BPS,
    1330                         LinesOnBoundaryCount);
    1331                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1332                         BLS[1]));
    1333                     LinesOnBoundaryCount++;
    1334                   }
    1335                 else
    1336                   BLS[1] = LineChecker[0]->second;
    1337                 if (LineChecker[1]
    1338                     == baseline->second->endpoints[1]->lines.end())
    1339                   { // create
    1340                     BPS[0] = baseline->second->endpoints[1];
    1341                     BPS[1] = winner->second;
    1342                     BLS[2] = new class BoundaryLineSet(BPS,
    1343                         LinesOnBoundaryCount);
    1344                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1345                         BLS[2]));
    1346                     LinesOnBoundaryCount++;
    1347                   }
    1348                 else
    1349                   BLS[2] = LineChecker[1]->second;
    1350                 BTS = new class BoundaryTriangleSet(BLS,
    1351                     TrianglesOnBoundaryCount);
    1352                 TrianglesOnBoundary.insert(TrianglePair(
    1353                     TrianglesOnBoundaryCount, BTS));
    1354                 TrianglesOnBoundaryCount++;
     759  do {
     760    flag = false;
     761    for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++)
     762      if (baseline->second->TrianglesCount == 1) {
     763        *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl;
     764        // 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)
     765        SmallestAngle = M_PI;
     766        BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
     767        // get peak point with respect to this base line's only triangle
     768        for(int i=0;i<3;i++)
     769          if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1]))
     770            peak = BTS->endpoints[i];
     771        *out << Verbose(3) << " and has peak " << *peak << "." << endl;
     772        // normal vector of triangle
     773        BTS->GetNormalVector(NormalVector);
     774        *out << Verbose(4) << "NormalVector of base triangle is ";
     775        NormalVector.Output(out);
     776        *out << endl;
     777        // offset to center of triangle
     778        CenterVector.Zero();
     779        for(int i=0;i<3;i++)
     780          CenterVector.AddVector(&BTS->endpoints[i]->node->x);
     781        CenterVector.Scale(1./3.);
     782        *out << Verbose(4) << "CenterVector of base triangle is ";
     783        CenterVector.Output(out);
     784        *out << endl;
     785        // vector in propagation direction (out of triangle)
     786        // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     787        TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     788        TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
     789        PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
     790        TempVector.CopyVector(&CenterVector);
     791        TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x);  // TempVector is vector on triangle plane pointing from one baseline egde towards center!
     792        //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
     793        if (PropagationVector.Projection(&TempVector) > 0)  // make sure normal propagation vector points outward from baseline
     794          PropagationVector.Scale(-1.);
     795        *out << Verbose(4) << "PropagationVector of base triangle is ";
     796        PropagationVector.Output(out);
     797        *out << endl;
     798        winner = PointsOnBoundary.end();
     799        for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++)
     800          if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints
     801            *out << Verbose(3) << "Target point is " << *(target->second) << ":";
     802            bool continueflag = true;
     803           
     804            VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     805            VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x);
     806            VirtualNormalVector.Scale(-1./2.);   // points now to center of base line
     807            VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
     808            TempAngle = VirtualNormalVector.Angle(&PropagationVector);
     809            continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
     810            if (!continueflag) {
     811              *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl;
     812              continue;
     813            } else
     814              *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl;
     815            LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first);
     816            LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first);
     817  //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
     818  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     819  //            else
     820  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     821  //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
     822  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     823  //            else
     824  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     825            // check first endpoint (if any connecting line goes to target or at least not more than 1)
     826            continueflag = continueflag && (( (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) || (LineChecker[0]->second->TrianglesCount == 1)));
     827            if (!continueflag) {
     828              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     829              continue;
     830            }
     831            // check second endpoint (if any connecting line goes to target or at least not more than 1)
     832            continueflag = continueflag && (( (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) || (LineChecker[1]->second->TrianglesCount == 1)));
     833            if (!continueflag) {
     834              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     835              continue;
     836            }
     837            // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
     838            continueflag = continueflag && (!(
     839                ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
     840                && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak))
     841               ));
     842            if (!continueflag) {
     843              *out << Verbose(4) << "Current target is peak!" << endl;
     844              continue;
     845            }
     846            // in case NOT both were found
     847            if (continueflag) {  // create virtually this triangle, get its normal vector, calculate angle
     848              flag = true;
     849              VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x);
     850              // make it always point inward
     851              if (baseline->second->endpoints[0]->node->x.Projection(&VirtualNormalVector) > 0)
     852                VirtualNormalVector.Scale(-1.);
     853              // calculate angle
     854              TempAngle = NormalVector.Angle(&VirtualNormalVector);
     855              *out << Verbose(4) << "NormalVector is ";
     856              VirtualNormalVector.Output(out);
     857              *out << " and the angle is " << TempAngle << "." << endl;
     858              if (SmallestAngle > TempAngle) {  // set to new possible winner
     859                SmallestAngle = TempAngle;
     860                winner = target;
    1355861              }
    1356             else
    1357               {
    1358                 *out << Verbose(1)
    1359                     << "I could not determine a winner for this baseline "
    1360                     << *(baseline->second) << "." << endl;
    1361               }
    1362 
    1363             // 5d. If the set of lines is not yet empty, go to 5. and continue
     862            }
    1364863          }
    1365         else
    1366           *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
    1367               << " has a triangle count of "
    1368               << baseline->second->TrianglesCount << "." << endl;
    1369     }
    1370   while (flag);
    1371 
    1372 }
    1373 ;
     864        // 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
     865        if (winner != PointsOnBoundary.end()) {
     866          *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl;
     867          // create the lins of not yet present
     868          BLS[0] = baseline->second;
     869          // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
     870          LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first);
     871          LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first);
     872          if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create
     873            BPS[0] = baseline->second->endpoints[0];
     874            BPS[1] = winner->second;
     875            BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount);
     876            LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[1]) );
     877            LinesOnBoundaryCount++;
     878          } else
     879            BLS[1] = LineChecker[0]->second;
     880          if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create
     881            BPS[0] = baseline->second->endpoints[1];
     882            BPS[1] = winner->second;
     883            BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     884            LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[2]) );
     885            LinesOnBoundaryCount++;
     886          } else
     887            BLS[2] = LineChecker[1]->second;
     888          BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     889          TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) );
     890          TrianglesOnBoundaryCount++;
     891        } else {
     892          *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl;
     893        }
     894 
     895        // 5d. If the set of lines is not yet empty, go to 5. and continue
     896      } else
     897        *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl;
     898  } while (flag);
     899 
     900  stringstream line;
     901  line << configuration->configpath << "/" << CONVEXENVELOPE;
     902  *out << Verbose(1) << "Storing convex envelope in tecplot data file " << line.str() << "." << endl;
     903  ofstream output(line.str().c_str());
     904  output << "TITLE = \"3D CONVEX SHELL\"" << endl;
     905  output << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
     906  output << "ZONE T=\"TRIANGLES\", N=" << PointsOnBoundaryCount << ", E=" << TrianglesOnBoundaryCount << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     907  int *LookupList = new int[mol->AtomCount];
     908  for (int i=0;i<mol->AtomCount;i++)
     909    LookupList[i] = -1;
     910 
     911  // print atom coordinates
     912  *out << Verbose(2) << "The following triangles were created:";
     913  int Counter = 1;
     914  atom *Walker = NULL;
     915  for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) {
     916    Walker = target->second->node;
     917    LookupList[Walker->nr] = Counter++;
     918    output << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl;
     919  }
     920  output << endl;
     921    // print connectivity
     922  for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
     923    *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
     924    output << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     925  }
     926  output.close();
     927  delete[](LookupList);
     928  *out << endl;
     929};
    1374930
    1375931/** Adds an atom to the tesselation::PointsOnBoundary list.
    1376932 * \param *Walker atom to add
    1377933 */
    1378 void
    1379 Tesselation::AddPoint(atom *Walker)
    1380 {
    1381   PointTestPair InsertUnique;
     934void Tesselation::AddPoint(atom *Walker)
     935{
    1382936  BPS[0] = new class BoundaryPointSet(Walker);
    1383   InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1384   if (InsertUnique.second) // if new point was not present before, increase counter
    1385     PointsOnBoundaryCount++;
    1386 }
    1387 ;
    1388 
    1389 /** Adds point to Tesselation::PointsOnBoundary if not yet present.
    1390  * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique.
    1391  * @param Candidate point to add
    1392  * @param n index for this point in Tesselation::TPS array
    1393  */
    1394 void
    1395 Tesselation::AddTrianglePoint(atom* Candidate, int n)
    1396 {
    1397   PointTestPair InsertUnique;
    1398   TPS[n] = new class BoundaryPointSet(Candidate);
    1399   InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
    1400   if (InsertUnique.second) // if new point was not present before, increase counter
    1401     {
    1402       PointsOnBoundaryCount++;
    1403     }
    1404   else
    1405     {
    1406       delete TPS[n];
    1407       cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
    1408           << " gibt's schon in der PointMap." << endl;
    1409       TPS[n] = (InsertUnique.first)->second;
    1410     }
    1411 }
    1412 ;
    1413 
    1414 /** Function tries to add line from current Points in BPS to BoundaryLineSet.
    1415  * If succesful it raises the line count and inserts the new line into the BLS,
    1416  * if unsuccesful, it writes the line which had been present into the BLS, deleting the new constructed one.
    1417  * @param *a first endpoint
    1418  * @param *b second endpoint
    1419  * @param n index of Tesselation::BLS giving the line with both endpoints
    1420  */
    1421 void
    1422 Tesselation::AddTriangleLine(class BoundaryPointSet *a,
    1423     class BoundaryPointSet *b, int n)
    1424 {
    1425   LineMap::iterator LineWalker;
    1426   //cout << "Manually checking endpoints for line." << endl;
    1427   if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr)
    1428   //If a line is there, how do I recognize that beyond a shadow of a doubt?
    1429     {
    1430       //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
    1431 
    1432       LineWalker = LinesOnBoundary.end();
    1433       LineWalker--;
    1434 
    1435       while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
    1436           b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
    1437           a->node->nr, b->node->nr))
    1438         {
    1439           //cout << Verbose(1) << "Looking for line which already exists"<< endl;
    1440           LineWalker--;
    1441         }
    1442       BPS[0] = LineWalker->second->endpoints[0];
    1443       BPS[1] = LineWalker->second->endpoints[1];
    1444       BLS[n] = LineWalker->second;
    1445 
    1446     }
    1447   else
    1448     {
    1449       cout << Verbose(2)
    1450           << "Adding line which has not been used before between "
    1451           << *(a->node) << " and " << *(b->node) << "." << endl;
    1452       BPS[0] = a;
    1453       BPS[1] = b;
    1454       BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1455 
    1456       LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
    1457       LinesOnBoundaryCount++;
    1458 
    1459     }
    1460 }
    1461 ;
    1462 
    1463 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm).
    1464  * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later.
    1465  */
    1466 void
    1467 Tesselation::AddTriangleToLines()
    1468 {
    1469 
    1470   cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1471   int i = 0;
    1472   TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1473   TrianglesOnBoundaryCount++;
    1474 
    1475   /*
    1476    * this is apparently done when constructing triangle
    1477 
    1478    for (i=0; i<3; i++)
    1479    {
    1480    BLS[i]->AddTriangle(BTS);
    1481    }
    1482    */
    1483 }
    1484 ;
    1485 
    1486 /**
    1487  * Function returns center of sphere with RADIUS, which rests on points a, b, c
    1488  * @param Center this vector will be used for return
    1489  * @param a vector first point of triangle
    1490  * @param b vector second point of triangle
    1491  * @param c vector third point of triangle
    1492  * @param *Umkreismittelpunkt new cneter point of circumference
    1493  * @param Direction vector indicates up/down
    1494  * @param AlternativeDirection vecotr, needed in case the triangles have 90 deg angle
    1495  * @param Halfplaneindicator double indicates whether Direction is up or down
    1496  * @param AlternativeIndicator doube indicates in case of orthogonal triangles which direction of AlternativeDirection is suitable
    1497  * @param alpha double angle at a
    1498  * @param beta double, angle at b
    1499  * @param gamma, double, angle at c
    1500  * @param Radius, double
    1501  * @param Umkreisradius double radius of circumscribing circle
    1502  */
    1503 
    1504   void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
    1505       double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1506   {
    1507     Vector TempNormal, helper;
    1508     double Restradius;
    1509     cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
    1510     Center->Zero();
    1511     helper.CopyVector(&a);
    1512     helper.Scale(sin(2.*alpha));
    1513     Center->AddVector(&helper);
    1514     helper.CopyVector(&b);
    1515     helper.Scale(sin(2.*beta));
    1516     Center->AddVector(&helper);
    1517     helper.CopyVector(&c);
    1518     helper.Scale(sin(2.*gamma));
    1519     Center->AddVector(&helper);
    1520     //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1521     Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1522     NewUmkreismittelpunkt->CopyVector(Center);
    1523     cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
    1524     // Here we calculated center of circumscribing circle, using barycentric coordinates
    1525     cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
    1526 
    1527     TempNormal.CopyVector(&a);
    1528     TempNormal.SubtractVector(&b);
    1529     helper.CopyVector(&a);
    1530     helper.SubtractVector(&c);
    1531     TempNormal.VectorProduct(&helper);
    1532     if (fabs(HalfplaneIndicator) < MYEPSILON)
    1533       {
    1534         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1535           {
    1536             TempNormal.Scale(-1);
    1537           }
    1538       }
    1539     else
    1540       {
    1541         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1542           {
    1543             TempNormal.Scale(-1);
    1544           }
    1545       }
    1546 
    1547     TempNormal.Normalize();
    1548     Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1549     cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
    1550     TempNormal.Scale(Restradius);
    1551     cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
    1552 
    1553     Center->AddVector(&TempNormal);
    1554     cout << Verbose(4) << "Center of sphere of circumference is " << *Center << ".\n";
    1555     cout << Verbose(3) << "End of Get_center_of_sphere.\n";
    1556   }
    1557   ;
    1558 
    1559 
    1560 /** This recursive function finds a third point, to form a triangle with two given ones.
    1561  * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1562  *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1563  *  upon which we operate.
    1564  *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1565  *  direction and angle into Storage.
    1566  *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1567  *  with all neighbours of the candidate.
    1568  * @param a first point
    1569  * @param b second point
    1570  * *param c atom old third point of old triangle
    1571  * @param Candidate base point along whose bonds to start looking from
    1572  * @param Parent point to avoid during search as its wrong direction
    1573  * @param RecursionLevel contains current recursion depth
    1574  * @param Chord baseline vector of first and second point
    1575  * @param direction1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to
    1576  * @param OldNormal normal of the triangle which the baseline belongs to
    1577  * @param ReferencePoint Vector of center of circumscribing circle from which we look towards center of sphere
    1578  * @param Opt_Candidate candidate reference to return
    1579  * @param Storage array containing two angles of current Opt_Candidate
    1580  * @param RADIUS radius of ball
    1581  * @param mol molecule structure with atoms and bonds
    1582  */
    1583 
    1584 void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1585     int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1586     atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1587 {
    1588         cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    1589         cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
    1590         cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
    1591         cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
    1592         cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
    1593         cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
    1594         /* OldNormal is normal vector on the old triangle
    1595          * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1596          * Chord points from b to a!!!
    1597          */
    1598         Vector dif_a; //Vector from a to candidate
    1599         Vector dif_b; //Vector from b to candidate
    1600         Vector AngleCheck;
    1601         Vector TempNormal, Umkreismittelpunkt;
    1602         Vector Mittelpunkt;
    1603 
    1604         double CurrentEpsilon = 0.1;
    1605         double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1606         double BallAngle, AlternativeSign;
    1607         atom *Walker; // variable atom point
    1608 
    1609         Vector NewUmkreismittelpunkt;
    1610 
    1611         if (a != Candidate and b != Candidate and c != Candidate) {
    1612                 cout << Verbose(3) << "We have a unique candidate!" << endl;
    1613                 dif_a.CopyVector(&(a->x));
    1614                 dif_a.SubtractVector(&(Candidate->x));
    1615                 dif_b.CopyVector(&(b->x));
    1616                 dif_b.SubtractVector(&(Candidate->x));
    1617                 AngleCheck.CopyVector(&(Candidate->x));
    1618                 AngleCheck.SubtractVector(&(a->x));
    1619                 AngleCheck.ProjectOntoPlane(Chord);
    1620 
    1621                 SideA = dif_b.Norm();
    1622                 SideB = dif_a.Norm();
    1623                 SideC = Chord->Norm();
    1624                 //Chord->Scale(-1);
    1625 
    1626                 alpha = Chord->Angle(&dif_a);
    1627                 beta = M_PI - Chord->Angle(&dif_b);
    1628                 gamma = dif_a.Angle(&dif_b);
    1629 
    1630                 cout << Verbose(2) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
    1631 
    1632                 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
    1633                         cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
    1634                         cout << Verbose(1) << "Base triangle has sides " << dif_a << ", " << dif_b << ", " << *Chord << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
    1635                 }
    1636 
    1637                 if ((M_PI*4. > alpha*5.) && (M_PI*4. > beta*5.) && (M_PI*4 > gamma*5.)) {
    1638                         Umkreisradius = SideA / 2.0 / sin(alpha);
    1639                         //cout << Umkreisradius << endl;
    1640                         //cout << SideB / 2.0 / sin(beta) << endl;
    1641                         //cout << SideC / 2.0 / sin(gamma) << endl;
    1642 
    1643                         if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
    1644                                 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
    1645                                 cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
    1646                                 sign = AngleCheck.ScalarProduct(direction1);
    1647                                 if (fabs(sign)<MYEPSILON) {
    1648                                         if (AngleCheck.ScalarProduct(OldNormal)<0) {
    1649                                                 sign =0;
    1650                                                 AlternativeSign=1;
    1651                                         } else {
    1652                                                 sign =0;
    1653                                                 AlternativeSign=-1;
    1654                                         }
    1655                                 } else {
    1656                                         sign /= fabs(sign);
    1657                                         cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
    1658                                 }
    1659 
    1660                                 Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1661 
    1662                                 AngleCheck.CopyVector(&ReferencePoint);
    1663                                 AngleCheck.Scale(-1);
    1664                                 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1665                                 AngleCheck.AddVector(&Mittelpunkt);
    1666                                 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1667                                 cout << Verbose(4) << "Reference vector to sphere's center is " << AngleCheck << "." << endl;
    1668 
    1669                                 BallAngle = AngleCheck.Angle(OldNormal);
    1670                                 cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
    1671 
    1672                                 //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl;
    1673                                 //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1674 
    1675                                 cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1676 
    1677                                 NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
    1678 
    1679                                 if ((AngleCheck.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
    1680                                         if (Storage[0]< -1.5) { // first Candidate at all
    1681                                                 if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1682                                                         cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
    1683                                                         Opt_Candidate = Candidate;
    1684                                                         Storage[0] = sign;
    1685                                                         Storage[1] = AlternativeSign;
    1686                                                         Storage[2] = BallAngle;
    1687                                                         cout << " angle " << Storage[2] << " and Up/Down "
    1688                                                         << Storage[0] << endl;
    1689                                                 } else
    1690                                                         cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1691                                         } else {
    1692                                                 if ( Storage[2] > BallAngle) {
    1693                                                         if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1694                                                                 cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
    1695                                                                 Opt_Candidate = Candidate;
    1696                                                                 Storage[0] = sign;
    1697                                                                 Storage[1] = AlternativeSign;
    1698                                                                 Storage[2] = BallAngle;
    1699                                                                 cout << " angle " << Storage[2] << " and Up/Down "
    1700                                                                 << Storage[0] << endl;
    1701                                                         } else
    1702                                                                 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1703                                                 } else {
    1704                                                         if (DEBUG) {
    1705                                                                 cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
    1706                                                         }
    1707                                                 }
    1708                                         }
    1709                                 } else {
    1710                                         if (DEBUG) {
    1711                                                 cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
    1712                                         }
    1713                                 }
    1714                         } else {
    1715                                 if (DEBUG) {
    1716                                         cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
    1717                                 }
    1718                         }
    1719                 } else {
    1720                         if (DEBUG) {
    1721                                 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
    1722                         }
    1723                 }
    1724         } else {
    1725                 if (DEBUG) {
    1726                         cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
    1727                 }
    1728         }
    1729 
    1730         if (RecursionLevel < 5) { // Seven is the recursion level threshold.
    1731                 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
    1732                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    1733                         if (Walker == Parent) { // don't go back the same bond
    1734                                 continue;
    1735                         } else {
    1736                                 Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel+1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS, mol); //call function again
    1737                         }
    1738                 }
    1739         }
    1740         cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    1741 }
    1742 ;
    1743 
    1744 
    1745   /** This recursive function finds a third point, to form a triangle with two given ones.
    1746    * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1747    *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1748    *  upon which we operate.
    1749    *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1750    *  direction and angle into Storage.
    1751    *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1752    *  with all neighbours of the candidate.
    1753    * @param a first point
    1754    * @param b second point
    1755    * @param Candidate base point along whose bonds to start looking from
    1756    * @param Parent point to avoid during search as its wrong direction
    1757    * @param RecursionLevel contains current recursion depth
    1758    * @param Chord baseline vector of first and second point
    1759    * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to
    1760    * @param OldNormal normal of the triangle which the baseline belongs to
    1761    * @param Opt_Candidate candidate reference to return
    1762    * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate
    1763    * @param Storage array containing two angles of current Opt_Candidate
    1764    * @param RADIUS radius of ball
    1765    * @param mol molecule structure with atoms and bonds
    1766    */
    1767 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent,
    1768     int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal,
    1769     atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol)
    1770 {
    1771         /* OldNormal is normal vector on the old triangle
    1772          * d1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1773          * Chord points from b to a!!!
    1774          */
    1775         Vector dif_a; //Vector from a to candidate
    1776         Vector dif_b; //Vector from b to candidate
    1777         Vector AngleCheck, AngleCheckReference, DirectionCheckPoint;
    1778         Vector TempNormal, Umkreismittelpunkt, Mittelpunkt, helper;
    1779 
    1780         double CurrentEpsilon = 0.1;
    1781         double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1782         double BallAngle;
    1783         atom *Walker; // variable atom point
    1784 
    1785 
    1786         dif_a.CopyVector(&(a->x));
    1787         dif_a.SubtractVector(&(Candidate->x));
    1788         dif_b.CopyVector(&(b->x));
    1789         dif_b.SubtractVector(&(Candidate->x));
    1790         DirectionCheckPoint.CopyVector(&dif_a);
    1791         DirectionCheckPoint.Scale(-1);
    1792         DirectionCheckPoint.ProjectOntoPlane(Chord);
    1793 
    1794         SideA = dif_b.Norm();
    1795         SideB = dif_a.Norm();
    1796         SideC = Chord->Norm();
    1797         //Chord->Scale(-1);
    1798 
    1799         alpha = Chord->Angle(&dif_a);
    1800         beta = M_PI - Chord->Angle(&dif_b);
    1801         gamma = dif_a.Angle(&dif_b);
    1802 
    1803 
    1804         if (DEBUG) {
    1805                 cout << "Atom number" << Candidate->nr << endl;
    1806                 Candidate->x.Output((ofstream *) &cout);
    1807                 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] << endl;
    1808         }
    1809 
    1810         if (a != Candidate and b != Candidate) {
    1811                 //      alpha = dif_a.Angle(&dif_b) / 2.;
    1812                 //      SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha);
    1813                 //      SideB = dif_a.Norm();
    1814                 //      centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos(
    1815                 //          alpha); // note this is squared of center line length
    1816                 //      centerline = (Chord->Norm()/2.) / sin(0.5*alpha);
    1817                 // Those are remains from Freddie. Needed?
    1818 
    1819                 Umkreisradius = SideA / 2.0 / sin(alpha);
    1820                 //cout << Umkreisradius << endl;
    1821                 //cout << SideB / 2.0 / sin(beta) << endl;
    1822                 //cout << SideC / 2.0 / sin(gamma) << endl;
    1823 
    1824                 if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) { //Checking whether ball will at least rest o points.
    1825                         // intermediate calculations to aquire centre of sphere, called Mittelpunkt:
    1826                         Umkreismittelpunkt.Zero();
    1827                         helper.CopyVector(&a->x);
    1828                         helper.Scale(sin(2.*alpha));
    1829                         Umkreismittelpunkt.AddVector(&helper);
    1830                         helper.CopyVector(&b->x);
    1831                         helper.Scale(sin(2.*beta));
    1832                         Umkreismittelpunkt.AddVector(&helper);
    1833                         helper.CopyVector(&Candidate->x);
    1834                         helper.Scale(sin(2.*gamma));
    1835                         Umkreismittelpunkt.AddVector(&helper);
    1836                         //Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ;
    1837                         Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    1838 
    1839                         TempNormal.CopyVector(&dif_a);
    1840                         TempNormal.VectorProduct(&dif_b);
    1841                         if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) {
    1842                                 TempNormal.Scale(-1);
    1843                         }
    1844                         TempNormal.Normalize();
    1845                         Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1846                         TempNormal.Scale(Restradius);
    1847 
    1848                         Mittelpunkt.CopyVector(&Umkreismittelpunkt);
    1849                         Mittelpunkt.AddVector(&TempNormal);  //this is center of sphere supported by a, b and Candidate
    1850 
    1851                         AngleCheck.CopyVector(Chord);
    1852                         AngleCheck.Scale(-0.5);
    1853                         AngleCheck.SubtractVector(&(b->x));
    1854                         AngleCheckReference.CopyVector(&AngleCheck);
    1855                         AngleCheckReference.AddVector(Opt_Mittelpunkt);
    1856                         AngleCheck.AddVector(&Mittelpunkt);
    1857 
    1858                         BallAngle = AngleCheck.Angle(&AngleCheckReference);
    1859 
    1860                         d1->ProjectOntoPlane(&AngleCheckReference);
    1861                         sign = AngleCheck.ScalarProduct(d1);
    1862                         if (fabs(sign) < MYEPSILON)
    1863                                 sign = 0;
    1864                         else
    1865                                 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction...
    1866 
    1867 
    1868                         if (Storage[0]< -1.5) { // first Candidate at all
    1869                                 cout << "Next better candidate is " << *Candidate << " with ";
    1870                                 Opt_Candidate = Candidate;
    1871                                 Storage[0] = sign;
    1872                                 Storage[1] = BallAngle;
    1873                                 Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1874                                 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl;
    1875                         } else {
    1876                                 /*
    1877                                  * removed due to change in criterium, now checking angle of ball to old normal.
    1878                                 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate
    1879                                 //within the ball.
    1880 
    1881                                 Distance = Opt_Candidate->x.Distance(&Mittelpunkt);
    1882                                 //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl;
    1883 
    1884 
    1885                                 if (Distance >RADIUS) { // We have no interference and may now check whether the new point is better.
    1886                                  */
    1887                                         //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl;
    1888 
    1889                                 if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))) { //This will give absolute preference to those in "right-hand" quadrants
    1890                                         //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS))    //and those where Candidate would be within old Sphere.
    1891                                         cout << "Next better candidate is " << *Candidate << " with ";
    1892                                         Opt_Candidate = Candidate;
    1893                                         Storage[0] = sign;
    1894                                         Storage[1] = BallAngle;
    1895                                         Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1896                                         cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl;
    1897                                 } else {
    1898                                         if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 && Storage[1] > BallAngle) || (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 && Storage[1] < BallAngle)) {
    1899                                                 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first.
    1900                                                 cout << "Next better candidate is " << *Candidate << " with ";
    1901                                                 Opt_Candidate = Candidate;
    1902                                                 Storage[0] = sign;
    1903                                                 Storage[1] = BallAngle;
    1904                                                 Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1905                                                 cout << "Angle is " << Storage[1] << ", Halbraum ist " << Storage[0] << endl;
    1906                                         }
    1907                                 }
    1908                         }
    1909 /*
    1910                * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle.
    1911                *
    1912                 else
    1913                 {
    1914                   if (sign>0 && BallAngle>0 && Storage[0]<0)
    1915                     {
    1916                       cout << "Next better candidate is " << *Candidate << " with ";
    1917                       Opt_Candidate = Candidate;
    1918                       Storage[0] = sign;
    1919                       Storage[1] = BallAngle;
    1920                       Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1921                       cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1922                       << Storage[0] << endl;
    1923 
    1924 //Debugging purposes only
    1925                       cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl;
    1926                       cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl;
    1927                       cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl;
    1928                       cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl;
    1929                       cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " "  <<Mittelpunkt.x[2] << endl;
    1930                       cout << "Umkreisradius ist " << Umkreisradius << endl;
    1931                       cout << "Restradius ist " << Restradius << endl;
    1932                       cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl;
    1933                       cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl;
    1934                       cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl;
    1935                       cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl;
    1936                       cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl;
    1937                       cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl;
    1938                       cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl;
    1939                       cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl;
    1940 
    1941 
    1942 
    1943                     }
    1944                   else
    1945                     {
    1946                       if (DEBUG)
    1947                         cout << "Looses to better candidate" << endl;
    1948                     }
    1949                 }
    1950                 */
    1951                 } else {
    1952                         if (DEBUG) {
    1953                                 cout << "Doesn't satisfy requirements for circumscribing circle" << endl;
    1954                         }
    1955                 }
    1956         } else {
    1957                 if (DEBUG) {
    1958                         cout << "identisch mit Ursprungslinie" << endl;
    1959                 }
    1960         }
    1961 
    1962         if (RecursionLevel < 9) { // Five is the recursion level threshold.
    1963                 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
    1964                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    1965                         if (Walker == Parent) { // don't go back the same bond
    1966                                 continue;
    1967                         } else {
    1968                                 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel+1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, mol); //call function again
    1969                         }
    1970                 }
    1971         }
    1972 };
    1973 
    1974 /** This function finds a triangle to a line, adjacent to an existing one.
    1975  * @param out   output stream for debugging
    1976  * @param tecplot output stream for writing found triangles in TecPlot format
    1977  * @param mol molecule structure with all atoms and bonds
    1978  * @param Line current baseline to search from
    1979  * @param T current triangle which \a Line is edge of
    1980  * @param RADIUS radius of the rolling ball
    1981  * @param N number of found triangles
    1982  * @param *filename filename base for intermediate envelopes
    1983  */
    1984 bool Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot,
    1985     molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    1986     const double& RADIUS, int N, const char *tempbasename)
    1987 {
    1988         cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
    1989         Vector direction1;
    1990         Vector helper;
    1991         Vector Chord;
    1992         ofstream *tempstream = NULL;
    1993         char NumberName[255];
    1994         double tmp;
    1995         //atom* Walker;
    1996         atom* OldThirdPoint;
    1997 
    1998         double Storage[3];
    1999         Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values
    2000         Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive
    2001         Storage[2] = 9999999.;
    2002         atom* Opt_Candidate = NULL;
    2003         Vector Opt_Mittelpunkt;
    2004 
    2005         cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
    2006 
    2007         helper.CopyVector(&(Line.endpoints[0]->node->x));
    2008         for (int i = 0; i < 3; i++) {
    2009                 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) {
    2010                         OldThirdPoint = T.endpoints[i]->node;
    2011                         helper.SubtractVector(&T.endpoints[i]->node->x);
    2012                         break;
    2013                 }
    2014         }
    2015 
    2016         direction1.CopyVector(&Line.endpoints[0]->node->x);
    2017         direction1.SubtractVector(&Line.endpoints[1]->node->x);
    2018         direction1.VectorProduct(&(T.NormalVector));
    2019 
    2020         if (direction1.ScalarProduct(&helper) < 0) {
    2021                 direction1.Scale(-1);
    2022         }
    2023         cout << Verbose(2) << "Looking in direction " << direction1 << " for candidates.\n";
    2024 
    2025         Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function
    2026         Chord.SubtractVector(&(Line.endpoints[1]->node->x));
    2027         cout << Verbose(2) << "Baseline vector is " << Chord << ".\n";
    2028 
    2029 
    2030         Vector Umkreismittelpunkt, a, b, c;
    2031         double alpha, beta, gamma;
    2032         a.CopyVector(&(T.endpoints[0]->node->x));
    2033         b.CopyVector(&(T.endpoints[1]->node->x));
    2034         c.CopyVector(&(T.endpoints[2]->node->x));
    2035         a.SubtractVector(&(T.endpoints[1]->node->x));
    2036         b.SubtractVector(&(T.endpoints[2]->node->x));
    2037         c.SubtractVector(&(T.endpoints[0]->node->x));
    2038 
    2039         alpha = M_PI - a.Angle(&c);
    2040         beta = M_PI - b.Angle(&a);
    2041         gamma = M_PI - c.Angle(&b);
    2042         if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON)
    2043                 cerr << Verbose(0) << "WARNING: sum of angles for candidate triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
    2044 
    2045         Umkreismittelpunkt.Zero();
    2046         helper.CopyVector(&T.endpoints[0]->node->x);
    2047         helper.Scale(sin(2.*alpha));
    2048         Umkreismittelpunkt.AddVector(&helper);
    2049         helper.CopyVector(&T.endpoints[1]->node->x);
    2050         helper.Scale(sin(2.*beta));
    2051         Umkreismittelpunkt.AddVector(&helper);
    2052         helper.CopyVector(&T.endpoints[2]->node->x);
    2053         helper.Scale(sin(2.*gamma));
    2054         Umkreismittelpunkt.AddVector(&helper);
    2055         //Umkreismittelpunkt = (T.endpoints[0]->node->x) * sin(2.*alpha) + T.endpoints[1]->node->x * sin(2.*beta) + (T.endpoints[2]->node->x) * sin(2.*gamma) ;
    2056         //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2057         Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    2058         //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2059         cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl;
    2060         cout << " Old Normal is " <<  (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl;
    2061 
    2062         cout << Verbose(2) << "Base triangle has sides " << a << ", " << b << ", " << c << " with angles " << alpha/M_PI*180. << ", " << beta/M_PI*180. << ", " << gamma/M_PI*180. << "." << endl;
    2063         cout << Verbose(2) << "Center of circumference is " << Umkreismittelpunkt << "." << endl;
    2064         if (DEBUG)
    2065                 cout << Verbose(3) << "Check of relative endpoints (same distance, equally spreaded): "<< endl;
    2066         tmp = 0;
    2067         for (int i=0;i<NDIM;i++) {
    2068                 helper.CopyVector(&T.endpoints[i]->node->x);
    2069                 helper.SubtractVector(&Umkreismittelpunkt);
    2070                 if (DEBUG)
    2071                         cout << Verbose(3) << "Endpoint[" << i << "]: " << helper << " with length " << helper.Norm() << "." << endl;
    2072                 if (tmp == 0) // set on first time for comparison against next ones
    2073                         tmp = helper.Norm();
    2074                 if (fabs(helper.Norm() - tmp) > MYEPSILON)
    2075                         cerr << Verbose(1) << "WARNING: center of circumference is wrong!" << endl;
    2076         }
    2077 
    2078         cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2079 
    2080         Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2081         Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2082         if (Opt_Candidate == NULL) {
    2083                 cerr << "WARNING: Could not find a suitable candidate." << endl;
    2084                 return false;
    2085         }
    2086         cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << endl;
    2087 
    2088         // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2089         bool flag = CheckPresenceOfTriangle(out, Opt_Candidate, Line.endpoints[0]->node, Line.endpoints[1]->node);
    2090 
    2091         if (flag) { // if so, add
    2092                 AddTrianglePoint(Opt_Candidate, 0);
    2093                 AddTrianglePoint(Line.endpoints[0]->node, 1);
    2094                 AddTrianglePoint(Line.endpoints[1]->node, 2);
    2095 
    2096                 AddTriangleLine(TPS[0], TPS[1], 0);
    2097                 AddTriangleLine(TPS[0], TPS[2], 1);
    2098                 AddTriangleLine(TPS[1], TPS[2], 2);
    2099 
    2100                 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2101                 AddTriangleToLines();
    2102 
    2103                 BTS->GetNormalVector(BTS->NormalVector);
    2104 
    2105                 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0)  || (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) || (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) ) {
    2106                         BTS->NormalVector.Scale(-1);
    2107                 };
    2108                 cout << Verbose(1) << "New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
    2109                 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
    2110         } else { // else, yell and do nothing
    2111                 cout << Verbose(1) << "This triangle consisting of ";
    2112                 cout << *Opt_Candidate << ", ";
    2113                 cout << *Line.endpoints[0]->node << " and ";
    2114                 cout << *Line.endpoints[1]->node << " ";
    2115                 cout << "is invalid!" << endl;
    2116                 return false;
    2117         }
    2118 
    2119         if ((TrianglesOnBoundaryCount % 10) == 0) {
    2120                 sprintf(NumberName, "-%d", TriangleFilesWritten);
    2121                 if (DoTecplotOutput) {
    2122                         string NameofTempFile(tempbasename);
    2123                         NameofTempFile.append(NumberName);
    2124                         NameofTempFile.append(TecplotSuffix);
    2125                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2126                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2127                         write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2128                         tempstream->close();
    2129                         tempstream->flush();
    2130                         delete(tempstream);
    2131                 }
    2132 
    2133                 if (DoRaster3DOutput) {
    2134                         string NameofTempFile(tempbasename);
    2135                         NameofTempFile.append(NumberName);
    2136                         NameofTempFile.append(Raster3DSuffix);
    2137                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2138                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2139                         write_raster3d_file(out, tempstream, this, mol);
    2140                         tempstream->close();
    2141                         tempstream->flush();
    2142                         delete(tempstream);
    2143                 }
    2144                 if (DoTecplotOutput || DoRaster3DOutput)
    2145                         TriangleFilesWritten++;
    2146         }
    2147 
    2148         cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
    2149         return true;
    2150 };
    2151 
    2152 /** Checks whether the triangle consisting of the three atoms is already present.
    2153  * Searches for the points in Tesselation::PointsOnBoundary and checks their
    2154  * lines. If any of the three edges already has two triangles attached, false is
    2155  * returned.
    2156  * \param *out output stream for debugging
    2157  * \param *a first endpoint
    2158  * \param *b second endpoint
    2159  * \param *c third endpoint
    2160  * \return false - triangle invalid due to edge criteria, true - triangle may be added.
    2161  */
    2162 bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *a, atom *b, atom *c) {
    2163         LineMap::iterator TryAndError;
    2164         PointTestPair InsertPoint;
    2165         bool Present[3];
    2166 
    2167         *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
    2168         TPS[0] = new class BoundaryPointSet(a);
    2169         TPS[1] = new class BoundaryPointSet(b);
    2170         TPS[2] = new class BoundaryPointSet(c);
    2171         for (int i=0;i<3;i++) { // check through all endpoints
    2172                 InsertPoint = PointsOnBoundary.insert(PointPair(TPS[i]->node->nr, TPS[i]));
    2173                 Present[i] = !InsertPoint.second;
    2174                 if (Present[i]) { // if new point was not present before, increase counter
    2175                         delete TPS[i];
    2176                         *out << Verbose(2) << "Atom " << *((InsertPoint.first)->second->node) << " gibt's schon in der PointMap." << endl;
    2177                         TPS[i] = (InsertPoint.first)->second;
    2178                 }
    2179         }
    2180 
    2181         // check lines
    2182         for (int i=0;i<3;i++)
    2183                 if (Present[i])
    2184                         for (int j=i;j<3;j++)
    2185                                 if (Present[j]) {
    2186                                         TryAndError = TPS[i]->lines.find(TPS[j]->node->nr);
    2187                                         if ((TryAndError != TPS[i]->lines.end()) && (TryAndError->second->TrianglesCount > 1)) {
    2188                                                 *out << "WARNING: Line " << *TryAndError->second << " already present with " << TryAndError->second->TrianglesCount << " triangles attached." << endl;
    2189                                                 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2190                                                 return false;
    2191                                         }
    2192                                 }
    2193         *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2194         return true;
    2195 };
    2196 
    2197 
    2198 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent,
    2199     int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3],
    2200     molecule* mol, double RADIUS)
    2201 {
    2202         cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl;
    2203         int i;
    2204         Vector AngleCheck;
    2205         atom* Walker;
    2206         double norm = -1., angle;
    2207 
    2208         // check if we only have one unique point yet ...
    2209         if (a != Candidate) {
    2210                 cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
    2211                 AngleCheck.CopyVector(&(Candidate->x));
    2212                 AngleCheck.SubtractVector(&(a->x));
    2213                 norm = AngleCheck.Norm();
    2214                 // second point shall have smallest angle with respect to Oben vector
    2215                 if (norm < RADIUS) {
    2216                         angle = AngleCheck.Angle(&Oben);
    2217                         if (angle < Storage[0]) {
    2218                                 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
    2219                                 cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
    2220                                 Opt_Candidate = Candidate;
    2221                                 Storage[0] = AngleCheck.Angle(&Oben);
    2222                                 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2223                         } else {
    2224                                 cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
    2225                         }
    2226                 } else {
    2227                         cout << "Refused due to Radius " << norm << endl;
    2228                 }
    2229         }
    2230 
    2231         // if not recursed to deeply, look at all its bonds
    2232         if (RecursionLevel < 7) {
    2233                 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) {
    2234                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    2235                         if (Walker == Parent) // don't go back along the bond we came from
    2236                                 continue;
    2237                         else
    2238                                 Find_second_point_for_Tesselation(a, Walker, Candidate, RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS);
    2239                 }
    2240         }
    2241         cout << Verbose(2) << "End of Find_second_point_for_Tesselation, recursive level " << RecursionLevel << endl;
    2242 };
    2243 
    2244 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS)
    2245 {
    2246         cout << Verbose(1) << "Begin of Find_starting_triangle\n";
    2247         int i = 0;
    2248         atom* Walker;
    2249         atom* FirstPoint;
    2250         atom* SecondPoint;
    2251         atom* max_index[NDIM];
    2252         double max_coordinate[NDIM];
    2253         Vector Oben;
    2254         Vector helper;
    2255         Vector Chord;
    2256         Vector CenterOfFirstLine;
    2257 
    2258         Oben.Zero();
    2259 
    2260         for (i = 0; i < 3; i++) {
    2261                 max_index[i] = NULL;
    2262                 max_coordinate[i] = -1;
    2263         }
    2264         cout << Verbose(2) << "Molecule mol is there and has " << mol->AtomCount << " Atoms \n";
    2265 
    2266         // 1. searching topmost atom with respect to each axis
    2267         Walker = mol->start;
    2268         while (Walker->next != mol->end) {
    2269                 Walker = Walker->next;
    2270                 for (i = 0; i < 3; i++) {
    2271                         if (Walker->x.x[i] > max_coordinate[i]) {
    2272                                 max_coordinate[i] = Walker->x.x[i];
    2273                                 max_index[i] = Walker;
    2274                         }
    2275                 }
    2276         }
    2277 
    2278         cout << Verbose(2) << "Found maximum coordinates: ";
    2279         for (int i=0;i<NDIM;i++)
    2280                 cout << i << ": " << *max_index[i] << "\t";
    2281         cout << endl;
    2282   //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0
    2283         const int k = 1;
    2284         Oben.x[k] = 1.;
    2285         FirstPoint = max_index[k];
    2286 
    2287         cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << " with " << mol->NumberOfBondsPerAtom[FirstPoint->nr] << " bonds." << endl;
    2288         double Storage[3];
    2289         atom* Opt_Candidate = NULL;
    2290         Storage[0] = 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.
    2291         Storage[1] = 999999.; // This will be an angle looking for the third point.
    2292         Storage[2] = 999999.;
    2293 
    2294         Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0, Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_...
    2295         SecondPoint = Opt_Candidate;
    2296         cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
    2297 
    2298         helper.CopyVector(&(FirstPoint->x));
    2299         helper.SubtractVector(&(SecondPoint->x));
    2300         helper.Normalize();
    2301         Oben.ProjectOntoPlane(&helper);
    2302         Oben.Normalize();
    2303         helper.VectorProduct(&Oben);
    2304         Storage[0] = -2.; // This will indicate the quadrant.
    2305         Storage[1] = 9999999.; // This will be an angle looking for the third point.
    2306         Storage[2] = 9999999.;
    2307 
    2308         Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2309         Chord.SubtractVector(&(SecondPoint->x));
    2310         // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2311 
    2312         cout << Verbose(2) << "Looking for third point candidates \n";
    2313         // look in one direction of baseline for initial candidate
    2314         Opt_Candidate = NULL;
    2315         CenterOfFirstLine.CopyVector(&Chord);
    2316         CenterOfFirstLine.Scale(0.5);
    2317         CenterOfFirstLine.AddVector(&(SecondPoint->x));
    2318 
    2319         cout << Verbose(1) << "Looking for third point candidates from " << *FirstPoint << " onward ...\n";
    2320         Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine,  Opt_Candidate, Storage, RADIUS, mol);
    2321         // look in other direction of baseline for possible better candidate
    2322         cout << Verbose(1) << "Looking for third point candidates from " << *SecondPoint << " onward ...\n";
    2323         Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0, &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol);
    2324         cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2325 
    2326         // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2327 
    2328         // Finally, we only have to add the found points
    2329         AddTrianglePoint(FirstPoint, 0);
    2330         AddTrianglePoint(SecondPoint, 1);
    2331         AddTrianglePoint(Opt_Candidate, 2);
    2332         // ... and respective lines
    2333         AddTriangleLine(TPS[0], TPS[1], 0);
    2334         AddTriangleLine(TPS[1], TPS[2], 1);
    2335         AddTriangleLine(TPS[0], TPS[2], 2);
    2336         // ... and triangles to the Maps of the Tesselation class
    2337         BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2338         AddTriangleToLines();
    2339         // ... and calculate its normal vector (with correct orientation)
    2340         Oben.Scale(-1.);
    2341         BTS->GetNormalVector(Oben);
    2342         cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
    2343         cout << Verbose(1) << "End of Find_starting_triangle\n";
    2344 };
    2345 
    2346 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol, const char *filename, const double RADIUS)
    2347 {
    2348         int N = 0;
    2349         struct Tesselation *Tess = new Tesselation;
    2350         cout << Verbose(1) << "Entering search for non convex hull. " << endl;
    2351         cout << flush;
    2352         LineMap::iterator baseline;
    2353         cout << Verbose(0) << "Begin of Find_non_convex_border\n";
    2354         bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
    2355         bool failflag = false;
    2356         if ((mol->first->next == mol->last) || (mol->last->previous == mol->first))
    2357                 mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true);
    2358 
    2359         Tess->Find_starting_triangle(mol, RADIUS);
    2360 
    2361         baseline = Tess->LinesOnBoundary.begin();
    2362         while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
    2363                 if (baseline->second->TrianglesCount == 1) {
    2364                         failflag = Tess->Find_next_suitable_triangle(out, tecplot, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one.
    2365                         flag = flag || failflag;
    2366                         if (!failflag)
    2367                                 cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
    2368                 } else {
    2369                         cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
    2370                 }
    2371                 N++;
    2372                 baseline++;
    2373                 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
    2374                         baseline = Tess->LinesOnBoundary.begin();   // restart if we reach end due to newly inserted lines
    2375                         flag = false;
    2376                 }
    2377         }
    2378         if (failflag) {
    2379                 cout << Verbose(1) << "Writing final tecplot file\n";
    2380                 if (DoTecplotOutput)
    2381                         write_tecplot_file(out, tecplot, Tess, mol, -1);
    2382                 if (DoRaster3DOutput)
    2383                         write_raster3d_file(out, tecplot, Tess, mol);
    2384         } else {
    2385                 cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
    2386         }
    2387 
    2388         cout << Verbose(0) << "End of Find_non_convex_border\n";
    2389         delete(Tess);
    2390 };
    2391 
     937  PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]) );
     938  PointsOnBoundaryCount++;
     939};
Note: See TracChangeset for help on using the changeset viewer.