Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    • Property mode changed from 100644 to 100755
    red060e rcc2ee5  
    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
    410// ======================================== Points on Boundary =================================
    511
     
    814  LinesCount = 0;
    915  Nr = -1;
    10 };
     16}
     17;
    1118
    1219BoundaryPointSet::BoundaryPointSet(atom *Walker)
     
    1522  LinesCount = 0;
    1623  Nr = Walker->nr;
    17 };
     24}
     25;
    1826
    1927BoundaryPointSet::~BoundaryPointSet()
     
    2129  cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    2230  node = NULL;
    23 };
    24 
    25 void 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   }
     31  lines.clear();
     32}
     33;
     34
     35void
     36BoundaryPointSet::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    }
    3348  LinesCount++;
    34 };
    35 
    36 ostream & operator << (ostream &ost, BoundaryPointSet &a)
     49}
     50;
     51
     52ostream &
     53operator <<(ostream &ost, BoundaryPointSet &a)
    3754{
    3855  ost << "[" << a.Nr << "|" << a.node->Name << "]";
    3956  return ost;
    40 };
     57}
     58;
    4159
    4260// ======================================== Lines on Boundary =================================
     
    4462BoundaryLineSet::BoundaryLineSet()
    4563{
    46   for (int i=0;i<2;i++)
     64  for (int i = 0; i < 2; i++)
    4765    endpoints[i] = NULL;
    4866  TrianglesCount = 0;
    4967  Nr = -1;
    50 };
     68}
     69;
    5170
    5271BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
     
    5776  SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    5877  // add this line to the hash maps of both endpoints
    59   Point[0]->AddLine(this);
    60   Point[1]->AddLine(this);
     78  Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
     79  Point[1]->AddLine(this); //
    6180  // clear triangles list
    6281  TrianglesCount = 0;
    6382  cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    64 };
     83}
     84;
    6585
    6686BoundaryLineSet::~BoundaryLineSet()
    6787{
    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 
    81 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    82 {
    83   cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl;
    84   triangles.insert ( TrianglePair( TrianglesCount, triangle) );
     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
     106void
     107BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
     108{
     109  cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
     110      << endl;
     111  triangles.insert(TrianglePair(TrianglesCount, triangle));
    85112  TrianglesCount++;
    86 };
    87 
    88 ostream & operator << (ostream &ost, BoundaryLineSet &a)
    89 {
    90   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]";
     113}
     114;
     115
     116ostream &
     117operator <<(ostream &ost, BoundaryLineSet &a)
     118{
     119  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     120      << a.endpoints[1]->node->Name << "]";
    91121  return ost;
    92 };
     122}
     123;
    93124
    94125// ======================================== Triangles on Boundary =================================
     
    97128BoundaryTriangleSet::BoundaryTriangleSet()
    98129{
    99   for (int i=0;i<3;i++) {
    100     endpoints[i] = NULL;
    101     lines[i] = NULL;
    102   }
     130  for (int i = 0; i < 3; i++)
     131    {
     132      endpoints[i] = NULL;
     133      lines[i] = NULL;
     134    }
    103135  Nr = -1;
    104 };
    105 
    106 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number)
     136}
     137;
     138
     139BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
     140    int number)
    107141{
    108142  // set number
     
    110144  // set lines
    111145  cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    112   for (int i=0;i<3;i++) {
    113     lines[i] = line[i];
    114     lines[i]->AddTriangle(this);
    115   }
     146  for (int i = 0; i < 3; i++)
     147    {
     148      lines[i] = line[i];
     149      lines[i]->AddTriangle(this);
     150    }
    116151  // 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
    122     }
     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      }
    123161  // set endpoints
    124162  int Counter = 0;
    125163  cout << Verbose(6) << " with end points ";
    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   }
     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    }
    135177  cout << "." << endl;
    136 };
     178}
     179;
    137180
    138181BoundaryTriangleSet::~BoundaryTriangleSet()
    139182{
    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 
    153 void BoundaryTriangleSet::GetNormalVector(Vector &NormalVector)
     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
     199void
     200BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    154201{
    155202  // get normal vector
    156   NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x);
    157  
     203  NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
     204      &endpoints[2]->node->x);
     205
    158206  // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    159   if (endpoints[0]->node->x.Projection(&NormalVector) > 0)
     207  if (endpoints[0]->node->x.Projection(&OtherVector) > 0)
    160208    NormalVector.Scale(-1.);
    161 };
    162 
    163 ostream & 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 << "]";
     209}
     210;
     211
     212ostream &
     213operator <<(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 << "]";
    166217  return ost;
    167 };
     218}
     219;
    168220
    169221// ========================================== F U N C T I O N S =================================
     
    174226 * \return point which is shared or NULL if none
    175227 */
    176 class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    177 {
    178   class BoundaryLineSet * lines[2] = {line1, line2};
     228class BoundaryPointSet *
     229GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
     230{
     231  class BoundaryLineSet * lines[2] =
     232    { line1, line2 };
    179233  class BoundaryPointSet *node = NULL;
    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;
     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          }
    191251      }
    192     }
    193252  return node;
    194 };
     253}
     254;
    195255
    196256/** Determines the boundary points of a cluster.
     
    201261 * \param *mol molecule structure representing the cluster
    202262 */
    203 Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol)
     263Boundaries *
     264GetBoundaryPoints(ofstream *out, molecule *mol)
    204265{
    205266  atom *Walker = NULL;
     
    207268  LineMap LinesOnBoundary;
    208269  TriangleMap TrianglesOnBoundary;
    209  
     270
    210271  *out << Verbose(1) << "Finding all boundary points." << endl;
    211   Boundaries *BoundaryPoints = new Boundaries [NDIM]; // first is alpha, second is (r, nr)
     272  Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
    212273  BoundariesTestPair BoundaryTestPair;
    213274  Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    214275  double radius, angle;
    215276  // 3a. Go through every axis
    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;
     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)
     296        {
     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            }
    278360        }
    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;
     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            }
    307457        }
    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)
    317         {
    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           }
    363         }
    364       }
    365     } while (flag);
    366   }
     458      while (flag);
     459    }
    367460  return BoundaryPoints;
    368 };
     461}
     462;
    369463
    370464/** Determines greatest diameters of a cluster defined by its convex envelope.
     
    375469 * \param IsAngstroem whether we have angstroem or atomic units
    376470 * \return NDIM array of the diameters
    377  */
    378 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem)
     471 */
     472double *
     473GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
     474    bool IsAngstroem)
    379475{
    380476  // get points on boundary of NULL was given as parameter
    381477  bool BoundaryFreeFlag = false;
    382478  Boundaries *BoundaryPoints = BoundaryPtr;
    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  
     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    }
    390488  // determine biggest "diameter" of cluster for each axis
    391489  Boundaries::iterator Neighbour, OtherNeighbour;
    392490  double *GreatestDiameter = new double[NDIM];
    393   for(int i=0;i<NDIM;i++)
     491  for (int i = 0; i < NDIM; i++)
    394492    GreatestDiameter[i] = 0.;
    395493  double OldComponent, tmp, w1, w2;
    396494  Vector DistanceVector, OtherVector;
    397495  int component, Othercomponent;
    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       }
    443     }
    444   }
    445   *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl;
     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        }
     553    }
     554  *out << Verbose(0) << "RESULT: The biggest diameters are "
     555      << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
     556      << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
     557      : "atomiclength") << "." << endl;
    446558
    447559  // free reference lists
    448560  if (BoundaryFreeFlag)
    449     delete[](BoundaryPoints);
     561    delete[] (BoundaryPoints);
    450562
    451563  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 */
     573void 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);
    452619};
    453620
     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 */
     626void
     627write_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}
    454671
    455672/** Determines the volume of a cluster.
    456673 * Determines first the convex envelope, then tesselates it and calculates its volume.
    457674 * \param *out output stream for debugging
     675 * \param *tecplot output stream for tecplot data
    458676 * \param *configuration needed for path to store convex envelope file
    459677 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired
    460678 * \param *mol molecule structure representing the cluster
     679 * \return determined volume of the cluster in cubed config:GetIsAngstroem()
    461680 */
    462 double VolumeOfConvexEnvelope(ofstream *out, config *configuration, Boundaries *BoundaryPtr, molecule *mol)
     681double
     682VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration,
     683    Boundaries *BoundaryPtr, molecule *mol)
    463684{
    464685  bool IsAngstroem = configuration->GetIsAngstroem();
     
    469690  double volume = 0.;
    470691  double PyramidVolume = 0.;
    471   double G,h;
    472   Vector x,y;
    473   double a,b,c;
     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.
    474697
    475698  // 1. calculate center of gravity
    476699  *out << endl;
    477700  Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    478  
     701
    479702  // 2. translate all points into CoG
    480703  *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    481704  Walker = mol->start;
    482   while (Walker->next != mol->end) {
    483     Walker = Walker->next;
    484     Walker->x.Translate(CenterOfGravity);
    485   }
    486  
     705  while (Walker->next != mol->end)
     706    {
     707      Walker = Walker->next;
     708      Walker->x.Translate(CenterOfGravity);
     709    }
     710
    487711  // 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  
     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
    495722  // 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);
    499     }
    500 
    501   *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl;
     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;
    502732  // now we have the whole set of edge points in the BoundaryList
    503733
    504 
    505734  // listing for debugging
    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  
     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
    512741  // 5a. guess starting triangle
    513742  TesselStruct->GuessStartingTriangle(out);
    514  
     743
    515744  // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    516745  TesselStruct->TesselateOnBoundary(out, configuration, mol);
    517746
    518   *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl;
     747  *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
     748      << " triangles with " << TesselStruct->LinesOnBoundaryCount
     749      << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
     750      << endl;
    519751
    520752  // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
    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 
     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;
    540786
    541787  // 7. translate all points back from CoG
    542   *out << Verbose(1) << "Translating system back from Center of Gravity." << endl;
     788  *out << Verbose(1) << "Translating system back from Center of Gravity."
     789      << endl;
    543790  CenterOfGravity->Scale(-1);
    544791  Walker = mol->start;
    545   while (Walker->next != mol->end) {
    546     Walker = Walker->next;
    547     Walker->x.Translate(CenterOfGravity);
    548   }
     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);
    549800
    550801  // free reference lists
    551802  if (BoundaryFreeFlag)
    552     delete[](BoundaryPoints);
    553  
     803    delete[] (BoundaryPoints);
     804
    554805  return volume;
    555 };
    556 
     806}
     807;
    557808
    558809/** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density.
     
    564815 * \param celldensity desired average density in final cell
    565816 */
    566 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity)
     817void
     818PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
     819    double ClusterVolume, double celldensity)
    567820{
    568821  // transform to PAS
    569822  mol->PrincipalAxisSystem(out, true);
    570  
     823
    571824  // some preparations beforehand
    572825  bool IsAngstroem = configuration->GetIsAngstroem();
     
    574827  double clustervolume;
    575828  if (ClusterVolume == 0)
    576     clustervolume = VolumeOfConvexEnvelope(out, configuration, BoundaryPoints, mol);
    577   else
     829    clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
     830        BoundaryPoints, mol);
     831  else
    578832    clustervolume = ClusterVolume;
    579   double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem);
     833  double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
     834      IsAngstroem);
    580835  Vector BoxLengths;
    581   int repetition[NDIM] = {1, 1, 1};
     836  int repetition[NDIM] =
     837    { 1, 1, 1 };
    582838  int TotalNoClusters = 1;
    583   for (int i=0;i<NDIM;i++)
     839  for (int i = 0; i < NDIM; i++)
    584840    TotalNoClusters *= repetition[i];
    585841
     
    587843  double totalmass = 0.;
    588844  atom *Walker = mol->start;
    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  
     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
    597857  // solve cubic polynomial
    598   *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl;
     858  *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
     859      << endl;
    599860  double cellvolume;
    600861  if (IsAngstroem)
    601     cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1);
     862    cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
     863        / clustervolume)) / (celldensity - 1);
    602864  else
    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
    626     }
    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];
    632     }
    633  
    634     // set new box dimensions
    635     *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    636     mol->CenterInBox((ofstream *)&cout, &BoxLengths);
    637   }
     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);
     888    }
     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);
     920    }
    638921  // update Box of atoms by boundary
    639922  mol->SetBoxDimension(&BoxLengths);
    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 
     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;
    643929
    644930// =========================================================== class TESSELATION ===========================================
     
    648934Tesselation::Tesselation()
    649935{
    650   PointsOnBoundaryCount = 0; 
    651   LinesOnBoundaryCount = 0; 
     936  PointsOnBoundaryCount = 0;
     937  LinesOnBoundaryCount = 0;
    652938  TrianglesOnBoundaryCount = 0;
    653 };
     939  TriangleFilesWritten = 0;
     940}
     941;
    654942
    655943/** Constructor of class Tesselation.
     
    658946Tesselation::~Tesselation()
    659947{
    660   for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
    661     delete(runner->second);
    662   }
    663 };
     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;
    664972
    665973/** Gueses first starting triangle of the convex envelope.
     
    667975 * \param *out output stream for debugging
    668976 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster
    669  */
    670 void Tesselation::GuessStartingTriangle(ofstream *out)
     977 */
     978void
     979Tesselation::GuessStartingTriangle(ofstream *out)
    671980{
    672981  // 4b. create a starting triangle
    673982  // 4b1. create all distances
    674983  DistanceMultiMap DistanceMMap;
    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       }
    682     }
    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
     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        }
     1010    }
     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
    6941019  DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    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 
     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;
    7371135
    7381136/** Tesselates the convex envelope of a cluster from a single starting triangle.
     
    7491147 * \param *mol the cluster as a molecule structure
    7501148 */
    751 void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol)
     1149void
     1150Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
     1151    molecule *mol)
    7521152{
    7531153  bool flag;
     
    7551155  class BoundaryPointSet *peak = NULL;
    7561156  double SmallestAngle, TempAngle;
    757   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector;
     1157  Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
     1158      PropagationVector;
    7581159  LineMap::iterator LineChecker[2];
    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;
     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++;
    8611355              }
    862             }
     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
    8631364          }
    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 };
     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;
    9301374
    9311375/** Adds an atom to the tesselation::PointsOnBoundary list.
    9321376 * \param *Walker atom to add
    9331377 */
    934 void Tesselation::AddPoint(atom *Walker)
    935 {
     1378void
     1379Tesselation::AddPoint(atom *Walker)
     1380{
     1381  PointTestPair InsertUnique;
    9361382  BPS[0] = new class BoundaryPointSet(Walker);
    937   PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]) );
    938   PointsOnBoundaryCount++;
     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 */
     1394void
     1395Tesselation::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 */
     1421void
     1422Tesselation::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 */
     1466void
     1467Tesselation::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
     1584void 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   */
     1767void 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        }
    9391972};
     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 */
     1984bool 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 */
     2162bool 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
     2198void 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
     2244void 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
     2346void 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
Note: See TracChangeset for help on using the changeset viewer.