Changeset 437922 for src/boundary.cpp


Ignore:
Timestamp:
Jul 23, 2009, 12:14:13 PM (16 years ago)
Author:
Frederik Heber <heber@…>
Branches:
Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
Children:
d067d45
Parents:
178f92
Message:

Fix indentation from tab to two spaces.

The trouble was caused at the merge e08f45e4539ffcc30e039dec5606cf06b45ab6be. Seemingly, I thought eclipse had pulled some shit which i didn't

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    r178f92 r437922  
    1515BoundaryPointSet::BoundaryPointSet()
    1616{
    17         LinesCount = 0;
    18         Nr = -1;
     17  LinesCount = 0;
     18  Nr = -1;
    1919}
    2020;
     
    2222BoundaryPointSet::BoundaryPointSet(atom *Walker)
    2323{
    24         node = Walker;
    25         LinesCount = 0;
    26         Nr = Walker->nr;
     24  node = Walker;
     25  LinesCount = 0;
     26  Nr = Walker->nr;
    2727}
    2828;
     
    3030BoundaryPointSet::~BoundaryPointSet()
    3131{
    32         cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    33         if (!lines.empty())
    34                 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
    35         node = NULL;
     32  cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
     33  if (!lines.empty())
     34    cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
     35  node = NULL;
    3636}
    3737;
     
    3939void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    4040{
    41         cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
    42                         << endl;
    43         if (line->endpoints[0] == this)
    44                 {
    45                         lines.insert(LinePair(line->endpoints[1]->Nr, line));
    46                 }
    47         else
    48                 {
    49                         lines.insert(LinePair(line->endpoints[0]->Nr, line));
    50                 }
    51         LinesCount++;
     41  cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
     42      << endl;
     43  if (line->endpoints[0] == this)
     44    {
     45      lines.insert(LinePair(line->endpoints[1]->Nr, line));
     46    }
     47  else
     48    {
     49      lines.insert(LinePair(line->endpoints[0]->Nr, line));
     50    }
     51  LinesCount++;
    5252}
    5353;
     
    5656operator <<(ostream &ost, BoundaryPointSet &a)
    5757{
    58         ost << "[" << a.Nr << "|" << a.node->Name << "]";
    59         return ost;
     58  ost << "[" << a.Nr << "|" << a.node->Name << "]";
     59  return ost;
    6060}
    6161;
     
    6565BoundaryLineSet::BoundaryLineSet()
    6666{
    67         for (int i = 0; i < 2; i++)
    68                 endpoints[i] = NULL;
    69         TrianglesCount = 0;
    70         Nr = -1;
     67  for (int i = 0; i < 2; i++)
     68    endpoints[i] = NULL;
     69  TrianglesCount = 0;
     70  Nr = -1;
    7171}
    7272;
     
    7474BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    7575{
    76         // set number
    77         Nr = number;
    78         // set endpoints in ascending order
    79         SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    80         // add this line to the hash maps of both endpoints
    81         Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
    82         Point[1]->AddLine(this); //
    83         // clear triangles list
    84         TrianglesCount = 0;
    85         cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
     76  // set number
     77  Nr = number;
     78  // set endpoints in ascending order
     79  SetEndpointsOrdered(endpoints, Point[0], Point[1]);
     80  // add this line to the hash maps of both endpoints
     81  Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
     82  Point[1]->AddLine(this); //
     83  // clear triangles list
     84  TrianglesCount = 0;
     85  cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl;
    8686}
    8787;
     
    8989BoundaryLineSet::~BoundaryLineSet()
    9090{
    91         int Numbers[2];
    92         Numbers[0] = endpoints[1]->Nr;
    93         Numbers[1] = endpoints[0]->Nr;
    94         for (int i = 0; i < 2; i++) {
    95                 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
    96                 endpoints[i]->lines.erase(Numbers[i]);
    97                 if (endpoints[i]->lines.empty()) {
    98                         cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    99                         if (endpoints[i] != NULL) {
    100                                 delete(endpoints[i]);
    101                                 endpoints[i] = NULL;
    102                         } else
    103                                 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
    104                 } else
    105                         cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
    106         }
    107         if (!triangles.empty())
    108                 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl;
     91  int Numbers[2];
     92  Numbers[0] = endpoints[1]->Nr;
     93  Numbers[1] = endpoints[0]->Nr;
     94  for (int i = 0; i < 2; i++) {
     95    cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     96    endpoints[i]->lines.erase(Numbers[i]);
     97    if (endpoints[i]->lines.empty()) {
     98      cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
     99      if (endpoints[i] != NULL) {
     100        delete(endpoints[i]);
     101        endpoints[i] = NULL;
     102      } else
     103        cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
     104    } else
     105      cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl;
     106  }
     107  if (!triangles.empty())
     108    cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some triangles." << endl;
    109109}
    110110;
     
    113113BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    114114{
    115         cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    116                         << endl;
    117         triangles.insert(TrianglePair(triangle->Nr, triangle));
    118         TrianglesCount++;
     115  cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
     116      << endl;
     117  triangles.insert(TrianglePair(triangle->Nr, triangle));
     118  TrianglesCount++;
    119119}
    120120;
     
    123123operator <<(ostream &ost, BoundaryLineSet &a)
    124124{
    125         ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    126                         << a.endpoints[1]->node->Name << "]";
    127         return ost;
     125  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     126      << a.endpoints[1]->node->Name << "]";
     127  return ost;
    128128}
    129129;
     
    134134BoundaryTriangleSet::BoundaryTriangleSet()
    135135{
    136         for (int i = 0; i < 3; i++)
    137                 {
    138                         endpoints[i] = NULL;
    139                         lines[i] = NULL;
    140                 }
    141         Nr = -1;
     136  for (int i = 0; i < 3; i++)
     137    {
     138      endpoints[i] = NULL;
     139      lines[i] = NULL;
     140    }
     141  Nr = -1;
    142142}
    143143;
    144144
    145145BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
    146                 int number)
    147 {
    148         // set number
    149         Nr = number;
    150         // set lines
    151         cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    152         for (int i = 0; i < 3; i++)
    153                 {
    154                         lines[i] = line[i];
    155                         lines[i]->AddTriangle(this);
    156                 }
    157         // get ascending order of endpoints
    158         map<int, class BoundaryPointSet *> OrderMap;
    159         for (int i = 0; i < 3; i++)
    160                 // for all three lines
    161                 for (int j = 0; j < 2; j++)
    162                         { // for both endpoints
    163                                 OrderMap.insert(pair<int, class BoundaryPointSet *> (
    164                                                 line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
    165                                 // and we don't care whether insertion fails
    166                         }
    167         // set endpoints
    168         int Counter = 0;
    169         cout << Verbose(6) << " with end points ";
    170         for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
    171                         != OrderMap.end(); runner++)
    172                 {
    173                         endpoints[Counter] = runner->second;
    174                         cout << " " << *endpoints[Counter];
    175                         Counter++;
    176                 }
    177         if (Counter < 3)
    178                 {
    179                         cerr << "ERROR! We have a triangle with only two distinct endpoints!"
    180                                         << endl;
    181                         //exit(1);
    182                 }
    183         cout << "." << endl;
     146    int number)
     147{
     148  // set number
     149  Nr = number;
     150  // set lines
     151  cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
     152  for (int i = 0; i < 3; i++)
     153    {
     154      lines[i] = line[i];
     155      lines[i]->AddTriangle(this);
     156    }
     157  // get ascending order of endpoints
     158  map<int, class BoundaryPointSet *> OrderMap;
     159  for (int i = 0; i < 3; i++)
     160    // for all three lines
     161    for (int j = 0; j < 2; j++)
     162      { // for both endpoints
     163        OrderMap.insert(pair<int, class BoundaryPointSet *> (
     164            line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
     165        // and we don't care whether insertion fails
     166      }
     167  // set endpoints
     168  int Counter = 0;
     169  cout << Verbose(6) << " with end points ";
     170  for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
     171      != OrderMap.end(); runner++)
     172    {
     173      endpoints[Counter] = runner->second;
     174      cout << " " << *endpoints[Counter];
     175      Counter++;
     176    }
     177  if (Counter < 3)
     178    {
     179      cerr << "ERROR! We have a triangle with only two distinct endpoints!"
     180          << endl;
     181      //exit(1);
     182    }
     183  cout << "." << endl;
    184184}
    185185;
     
    187187BoundaryTriangleSet::~BoundaryTriangleSet()
    188188{
    189         for (int i = 0; i < 3; i++) {
    190                 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
    191                 lines[i]->triangles.erase(Nr);
    192                 if (lines[i]->triangles.empty()) {
    193                         cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
    194                         if (lines[i] != NULL) {
    195                                 delete (lines[i]);
    196                                 lines[i] = NULL;
    197                         } else
    198                                 cerr << "ERROR: This line " << i << " has already been free'd." << endl;
    199                 } else
    200                         cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl;
    201         }
     189  for (int i = 0; i < 3; i++) {
     190    cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
     191    lines[i]->triangles.erase(Nr);
     192    if (lines[i]->triangles.empty()) {
     193      cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
     194      if (lines[i] != NULL) {
     195        delete (lines[i]);
     196        lines[i] = NULL;
     197      } else
     198        cerr << "ERROR: This line " << i << " has already been free'd." << endl;
     199    } else
     200      cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl;
     201  }
    202202}
    203203;
     
    206206BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    207207{
    208         // get normal vector
    209         NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
    210                         &endpoints[2]->node->x);
    211 
    212         // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    213         if (NormalVector.Projection(&OtherVector) > 0)
    214                 NormalVector.Scale(-1.);
     208  // get normal vector
     209  NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
     210      &endpoints[2]->node->x);
     211
     212  // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
     213  if (NormalVector.Projection(&OtherVector) > 0)
     214    NormalVector.Scale(-1.);
    215215}
    216216;
     
    219219operator <<(ostream &ost, BoundaryTriangleSet &a)
    220220{
    221         ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    222                         << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    223         return ost;
     221  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     222      << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
     223  return ost;
    224224}
    225225;
     
    235235GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    236236{
    237         class BoundaryLineSet * lines[2] =
    238                 { line1, line2 };
    239         class BoundaryPointSet *node = NULL;
    240         map<int, class BoundaryPointSet *> OrderMap;
    241         pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
    242         for (int i = 0; i < 2; i++)
    243                 // for both lines
    244                 for (int j = 0; j < 2; j++)
    245                         { // for both endpoints
    246                                 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
    247                                                 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
    248                                 if (!OrderTest.second)
    249                                         { // if insertion fails, we have common endpoint
    250                                                 node = OrderTest.first->second;
    251                                                 cout << Verbose(5) << "Common endpoint of lines " << *line1
    252                                                                 << " and " << *line2 << " is: " << *node << "." << endl;
    253                                                 j = 2;
    254                                                 i = 2;
    255                                                 break;
    256                                         }
    257                         }
    258         return node;
     237  class BoundaryLineSet * lines[2] =
     238    { line1, line2 };
     239  class BoundaryPointSet *node = NULL;
     240  map<int, class BoundaryPointSet *> OrderMap;
     241  pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
     242  for (int i = 0; i < 2; i++)
     243    // for both lines
     244    for (int j = 0; j < 2; j++)
     245      { // for both endpoints
     246        OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
     247            lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
     248        if (!OrderTest.second)
     249          { // if insertion fails, we have common endpoint
     250            node = OrderTest.first->second;
     251            cout << Verbose(5) << "Common endpoint of lines " << *line1
     252                << " and " << *line2 << " is: " << *node << "." << endl;
     253            j = 2;
     254            i = 2;
     255            break;
     256          }
     257      }
     258  return node;
    259259}
    260260;
     
    270270GetBoundaryPoints(ofstream *out, molecule *mol)
    271271{
    272         atom *Walker = NULL;
    273         PointMap PointsOnBoundary;
    274         LineMap LinesOnBoundary;
    275         TriangleMap TrianglesOnBoundary;
    276 
    277         *out << Verbose(1) << "Finding all boundary points." << endl;
    278         Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
    279         BoundariesTestPair BoundaryTestPair;
    280         Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    281         double radius, angle;
    282         // 3a. Go through every axis
    283         for (int axis = 0; axis < NDIM; axis++)
    284                 {
    285                         AxisVector.Zero();
    286                         AngleReferenceVector.Zero();
    287                         AngleReferenceNormalVector.Zero();
    288                         AxisVector.x[axis] = 1.;
    289                         AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    290                         AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    291                         //              *out << Verbose(1) << "Axisvector is ";
    292                         //              AxisVector.Output(out);
    293                         //              *out << " and AngleReferenceVector is ";
    294                         //              AngleReferenceVector.Output(out);
    295                         //              *out << "." << endl;
    296                         //              *out << " and AngleReferenceNormalVector is ";
    297                         //              AngleReferenceNormalVector.Output(out);
    298                         //              *out << "." << endl;
    299                         // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    300                         Walker = mol->start;
    301                         while (Walker->next != mol->end)
    302                                 {
    303                                         Walker = Walker->next;
    304                                         Vector ProjectedVector;
    305                                         ProjectedVector.CopyVector(&Walker->x);
    306                                         ProjectedVector.ProjectOntoPlane(&AxisVector);
    307                                         // correct for negative side
    308                                         //if (Projection(y) < 0)
    309                                         //angle = 2.*M_PI - angle;
    310                                         radius = ProjectedVector.Norm();
    311                                         if (fabs(radius) > MYEPSILON)
    312                                                 angle = ProjectedVector.Angle(&AngleReferenceVector);
    313                                         else
    314                                                 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    315 
    316                                         //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    317                                         if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
    318                                                 {
    319                                                         angle = 2. * M_PI - angle;
    320                                                 }
    321                                         //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
    322                                         //ProjectedVector.Output(out);
    323                                         //*out << endl;
    324                                         BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
    325                                                         DistancePair (radius, Walker)));
    326                                         if (BoundaryTestPair.second)
    327                                                 { // successfully inserted
    328                                                 }
    329                                         else
    330                                                 { // same point exists, check first r, then distance of original vectors to center of gravity
    331                                                         *out << Verbose(2)
    332                                                                         << "Encountered two vectors whose projection onto axis "
    333                                                                         << axis << " is equal: " << endl;
    334                                                         *out << Verbose(2) << "Present vector: ";
    335                                                         BoundaryTestPair.first->second.second->x.Output(out);
    336                                                         *out << endl;
    337                                                         *out << Verbose(2) << "New vector: ";
    338                                                         Walker->x.Output(out);
    339                                                         *out << endl;
    340                                                         double tmp = ProjectedVector.Norm();
    341                                                         if (tmp > BoundaryTestPair.first->second.first)
    342                                                                 {
    343                                                                         BoundaryTestPair.first->second.first = tmp;
    344                                                                         BoundaryTestPair.first->second.second = Walker;
    345                                                                         *out << Verbose(2) << "Keeping new vector." << endl;
    346                                                                 }
    347                                                         else if (tmp == BoundaryTestPair.first->second.first)
    348                                                                 {
    349                                                                         if (BoundaryTestPair.first->second.second->x.ScalarProduct(
    350                                                                                         &BoundaryTestPair.first->second.second->x)
    351                                                                                         < Walker->x.ScalarProduct(&Walker->x))
    352                                                                                 { // Norm() does a sqrt, which makes it a lot slower
    353                                                                                         BoundaryTestPair.first->second.second = Walker;
    354                                                                                         *out << Verbose(2) << "Keeping new vector." << endl;
    355                                                                                 }
    356                                                                         else
    357                                                                                 {
    358                                                                                         *out << Verbose(2) << "Keeping present vector." << endl;
    359                                                                                 }
    360                                                                 }
    361                                                         else
    362                                                                 {
    363                                                                         *out << Verbose(2) << "Keeping present vector." << endl;
    364                                                                 }
    365                                                 }
    366                                 }
    367                         // printing all inserted for debugging
    368                         //              {
    369                         //                      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    370                         //                      int i=0;
    371                         //                      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    372                         //                              if (runner != BoundaryPoints[axis].begin())
    373                         //                                      *out << ", " << i << ": " << *runner->second.second;
    374                         //                              else
    375                         //                                      *out << i << ": " << *runner->second.second;
    376                         //                              i++;
    377                         //                      }
    378                         //                      *out << endl;
    379                         //              }
    380                         // 3c. throw out points whose distance is less than the mean of left and right neighbours
    381                         bool flag = false;
    382                         do
    383                                 { // do as long as we still throw one out per round
    384                                         *out << Verbose(1)
    385                                                         << "Looking for candidates to kick out by convex condition ... "
    386                                                         << endl;
    387                                         flag = false;
    388                                         Boundaries::iterator left = BoundaryPoints[axis].end();
    389                                         Boundaries::iterator right = BoundaryPoints[axis].end();
    390                                         for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    391                                                         != BoundaryPoints[axis].end(); runner++)
    392                                                 {
    393                                                         // set neighbours correctly
    394                                                         if (runner == BoundaryPoints[axis].begin())
    395                                                                 {
    396                                                                         left = BoundaryPoints[axis].end();
    397                                                                 }
    398                                                         else
    399                                                                 {
    400                                                                         left = runner;
    401                                                                 }
    402                                                         left--;
    403                                                         right = runner;
    404                                                         right++;
    405                                                         if (right == BoundaryPoints[axis].end())
    406                                                                 {
    407                                                                         right = BoundaryPoints[axis].begin();
    408                                                                 }
    409                                                         // check distance
    410 
    411                                                         // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    412                                                                 {
    413                                                                         Vector SideA, SideB, SideC, SideH;
    414                                                                         SideA.CopyVector(&left->second.second->x);
    415                                                                         SideA.ProjectOntoPlane(&AxisVector);
    416                                                                         //                                      *out << "SideA: ";
    417                                                                         //                                      SideA.Output(out);
    418                                                                         //                                      *out << endl;
    419 
    420                                                                         SideB.CopyVector(&right->second.second->x);
    421                                                                         SideB.ProjectOntoPlane(&AxisVector);
    422                                                                         //                                      *out << "SideB: ";
    423                                                                         //                                      SideB.Output(out);
    424                                                                         //                                      *out << endl;
    425 
    426                                                                         SideC.CopyVector(&left->second.second->x);
    427                                                                         SideC.SubtractVector(&right->second.second->x);
    428                                                                         SideC.ProjectOntoPlane(&AxisVector);
    429                                                                         //                                      *out << "SideC: ";
    430                                                                         //                                      SideC.Output(out);
    431                                                                         //                                      *out << endl;
    432 
    433                                                                         SideH.CopyVector(&runner->second.second->x);
    434                                                                         SideH.ProjectOntoPlane(&AxisVector);
    435                                                                         //                                      *out << "SideH: ";
    436                                                                         //                                      SideH.Output(out);
    437                                                                         //                                      *out << endl;
    438 
    439                                                                         // calculate each length
    440                                                                         double a = SideA.Norm();
    441                                                                         //double b = SideB.Norm();
    442                                                                         //double c = SideC.Norm();
    443                                                                         double h = SideH.Norm();
    444                                                                         // calculate the angles
    445                                                                         double alpha = SideA.Angle(&SideH);
    446                                                                         double beta = SideA.Angle(&SideC);
    447                                                                         double gamma = SideB.Angle(&SideH);
    448                                                                         double delta = SideC.Angle(&SideH);
    449                                                                         double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
    450                                                                                         < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    451                                                                         //                                      *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;
    452                                                                         //*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;
    453                                                                         if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
    454                                                                                         < MYEPSILON) && (h < MinDistance))
    455                                                                                 {
    456                                                                                         // throw out point
    457                                                                                         //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    458                                                                                         BoundaryPoints[axis].erase(runner);
    459                                                                                         flag = true;
    460                                                                                 }
    461                                                                 }
    462                                                 }
    463                                 }
    464                         while (flag);
    465                 }
    466         return BoundaryPoints;
     272  atom *Walker = NULL;
     273  PointMap PointsOnBoundary;
     274  LineMap LinesOnBoundary;
     275  TriangleMap TrianglesOnBoundary;
     276
     277  *out << Verbose(1) << "Finding all boundary points." << endl;
     278  Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
     279  BoundariesTestPair BoundaryTestPair;
     280  Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
     281  double radius, angle;
     282  // 3a. Go through every axis
     283  for (int axis = 0; axis < NDIM; axis++)
     284    {
     285      AxisVector.Zero();
     286      AngleReferenceVector.Zero();
     287      AngleReferenceNormalVector.Zero();
     288      AxisVector.x[axis] = 1.;
     289      AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
     290      AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
     291      //    *out << Verbose(1) << "Axisvector is ";
     292      //    AxisVector.Output(out);
     293      //    *out << " and AngleReferenceVector is ";
     294      //    AngleReferenceVector.Output(out);
     295      //    *out << "." << endl;
     296      //    *out << " and AngleReferenceNormalVector is ";
     297      //    AngleReferenceNormalVector.Output(out);
     298      //    *out << "." << endl;
     299      // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     300      Walker = mol->start;
     301      while (Walker->next != mol->end)
     302        {
     303          Walker = Walker->next;
     304          Vector ProjectedVector;
     305          ProjectedVector.CopyVector(&Walker->x);
     306          ProjectedVector.ProjectOntoPlane(&AxisVector);
     307          // correct for negative side
     308          //if (Projection(y) < 0)
     309          //angle = 2.*M_PI - angle;
     310          radius = ProjectedVector.Norm();
     311          if (fabs(radius) > MYEPSILON)
     312            angle = ProjectedVector.Angle(&AngleReferenceVector);
     313          else
     314            angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
     315
     316          //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
     317          if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
     318            {
     319              angle = 2. * M_PI - angle;
     320            }
     321          //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
     322          //ProjectedVector.Output(out);
     323          //*out << endl;
     324          BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
     325              DistancePair (radius, Walker)));
     326          if (BoundaryTestPair.second)
     327            { // successfully inserted
     328            }
     329          else
     330            { // same point exists, check first r, then distance of original vectors to center of gravity
     331              *out << Verbose(2)
     332                  << "Encountered two vectors whose projection onto axis "
     333                  << axis << " is equal: " << endl;
     334              *out << Verbose(2) << "Present vector: ";
     335              BoundaryTestPair.first->second.second->x.Output(out);
     336              *out << endl;
     337              *out << Verbose(2) << "New vector: ";
     338              Walker->x.Output(out);
     339              *out << endl;
     340              double tmp = ProjectedVector.Norm();
     341              if (tmp > BoundaryTestPair.first->second.first)
     342                {
     343                  BoundaryTestPair.first->second.first = tmp;
     344                  BoundaryTestPair.first->second.second = Walker;
     345                  *out << Verbose(2) << "Keeping new vector." << endl;
     346                }
     347              else if (tmp == BoundaryTestPair.first->second.first)
     348                {
     349                  if (BoundaryTestPair.first->second.second->x.ScalarProduct(
     350                      &BoundaryTestPair.first->second.second->x)
     351                      < Walker->x.ScalarProduct(&Walker->x))
     352                    { // Norm() does a sqrt, which makes it a lot slower
     353                      BoundaryTestPair.first->second.second = Walker;
     354                      *out << Verbose(2) << "Keeping new vector." << endl;
     355                    }
     356                  else
     357                    {
     358                      *out << Verbose(2) << "Keeping present vector." << endl;
     359                    }
     360                }
     361              else
     362                {
     363                  *out << Verbose(2) << "Keeping present vector." << endl;
     364                }
     365            }
     366        }
     367      // printing all inserted for debugging
     368      //    {
     369      //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     370      //      int i=0;
     371      //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     372      //        if (runner != BoundaryPoints[axis].begin())
     373      //          *out << ", " << i << ": " << *runner->second.second;
     374      //        else
     375      //          *out << i << ": " << *runner->second.second;
     376      //        i++;
     377      //      }
     378      //      *out << endl;
     379      //    }
     380      // 3c. throw out points whose distance is less than the mean of left and right neighbours
     381      bool flag = false;
     382      do
     383        { // do as long as we still throw one out per round
     384          *out << Verbose(1)
     385              << "Looking for candidates to kick out by convex condition ... "
     386              << endl;
     387          flag = false;
     388          Boundaries::iterator left = BoundaryPoints[axis].end();
     389          Boundaries::iterator right = BoundaryPoints[axis].end();
     390          for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     391              != BoundaryPoints[axis].end(); runner++)
     392            {
     393              // set neighbours correctly
     394              if (runner == BoundaryPoints[axis].begin())
     395                {
     396                  left = BoundaryPoints[axis].end();
     397                }
     398              else
     399                {
     400                  left = runner;
     401                }
     402              left--;
     403              right = runner;
     404              right++;
     405              if (right == BoundaryPoints[axis].end())
     406                {
     407                  right = BoundaryPoints[axis].begin();
     408                }
     409              // check distance
     410
     411              // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
     412                {
     413                  Vector SideA, SideB, SideC, SideH;
     414                  SideA.CopyVector(&left->second.second->x);
     415                  SideA.ProjectOntoPlane(&AxisVector);
     416                  //          *out << "SideA: ";
     417                  //          SideA.Output(out);
     418                  //          *out << endl;
     419
     420                  SideB.CopyVector(&right->second.second->x);
     421                  SideB.ProjectOntoPlane(&AxisVector);
     422                  //          *out << "SideB: ";
     423                  //          SideB.Output(out);
     424                  //          *out << endl;
     425
     426                  SideC.CopyVector(&left->second.second->x);
     427                  SideC.SubtractVector(&right->second.second->x);
     428                  SideC.ProjectOntoPlane(&AxisVector);
     429                  //          *out << "SideC: ";
     430                  //          SideC.Output(out);
     431                  //          *out << endl;
     432
     433                  SideH.CopyVector(&runner->second.second->x);
     434                  SideH.ProjectOntoPlane(&AxisVector);
     435                  //          *out << "SideH: ";
     436                  //          SideH.Output(out);
     437                  //          *out << endl;
     438
     439                  // calculate each length
     440                  double a = SideA.Norm();
     441                  //double b = SideB.Norm();
     442                  //double c = SideC.Norm();
     443                  double h = SideH.Norm();
     444                  // calculate the angles
     445                  double alpha = SideA.Angle(&SideH);
     446                  double beta = SideA.Angle(&SideC);
     447                  double gamma = SideB.Angle(&SideH);
     448                  double delta = SideC.Angle(&SideH);
     449                  double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
     450                      < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
     451                  //          *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;
     452                  //*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;
     453                  if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
     454                      < MYEPSILON) && (h < MinDistance))
     455                    {
     456                      // throw out point
     457                      //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
     458                      BoundaryPoints[axis].erase(runner);
     459                      flag = true;
     460                    }
     461                }
     462            }
     463        }
     464      while (flag);
     465    }
     466  return BoundaryPoints;
    467467}
    468468;
     
    478478double *
    479479GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    480                 bool IsAngstroem)
    481 {
    482         // get points on boundary of NULL was given as parameter
    483         bool BoundaryFreeFlag = false;
    484         Boundaries *BoundaryPoints = BoundaryPtr;
    485         if (BoundaryPoints == NULL)
    486                 {
    487                         BoundaryFreeFlag = true;
    488                         BoundaryPoints = GetBoundaryPoints(out, mol);
    489                 }
    490         else
    491                 {
    492                         *out << Verbose(1) << "Using given boundary points set." << endl;
    493                 }
    494         // determine biggest "diameter" of cluster for each axis
    495         Boundaries::iterator Neighbour, OtherNeighbour;
    496         double *GreatestDiameter = new double[NDIM];
    497         for (int i = 0; i < NDIM; i++)
    498                 GreatestDiameter[i] = 0.;
    499         double OldComponent, tmp, w1, w2;
    500         Vector DistanceVector, OtherVector;
    501         int component, Othercomponent;
    502         for (int axis = 0; axis < NDIM; axis++)
    503                 { // regard each projected plane
    504                         //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
    505                         for (int j = 0; j < 2; j++)
    506                                 { // and for both axis on the current plane
    507                                         component = (axis + j + 1) % NDIM;
    508                                         Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
    509                                         //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
    510                                         for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    511                                                         != BoundaryPoints[axis].end(); runner++)
    512                                                 {
    513                                                         //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
    514                                                         // seek for the neighbours pair where the Othercomponent sign flips
    515                                                         Neighbour = runner;
    516                                                         Neighbour++;
    517                                                         if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    518                                                                 Neighbour = BoundaryPoints[axis].begin();
    519                                                         DistanceVector.CopyVector(&runner->second.second->x);
    520                                                         DistanceVector.SubtractVector(&Neighbour->second.second->x);
    521                                                         do
    522                                                                 { // seek for neighbour pair where it flips
    523                                                                         OldComponent = DistanceVector.x[Othercomponent];
    524                                                                         Neighbour++;
    525                                                                         if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    526                                                                                 Neighbour = BoundaryPoints[axis].begin();
    527                                                                         DistanceVector.CopyVector(&runner->second.second->x);
    528                                                                         DistanceVector.SubtractVector(&Neighbour->second.second->x);
    529                                                                         //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
    530                                                                 }
    531                                                         while ((runner != Neighbour) && (fabs(OldComponent / fabs(
    532                                                                         OldComponent) - DistanceVector.x[Othercomponent] / fabs(
    533                                                                         DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
    534                                                         if (runner != Neighbour)
    535                                                                 {
    536                                                                         OtherNeighbour = Neighbour;
    537                                                                         if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
    538                                                                                 OtherNeighbour = BoundaryPoints[axis].end();
    539                                                                         OtherNeighbour--;
    540                                                                         //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
    541                                                                         // now we have found the pair: Neighbour and OtherNeighbour
    542                                                                         OtherVector.CopyVector(&runner->second.second->x);
    543                                                                         OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
    544                                                                         //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
    545                                                                         //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
    546                                                                         // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
    547                                                                         w1 = fabs(OtherVector.x[Othercomponent]);
    548                                                                         w2 = fabs(DistanceVector.x[Othercomponent]);
    549                                                                         tmp = fabs((w1 * DistanceVector.x[component] + w2
    550                                                                                         * OtherVector.x[component]) / (w1 + w2));
    551                                                                         // mark if it has greater diameter
    552                                                                         //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
    553                                                                         GreatestDiameter[component] = (GreatestDiameter[component]
    554                                                                                         > tmp) ? GreatestDiameter[component] : tmp;
    555                                                                 } //else
    556                                                         //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
    557                                                 }
    558                                 }
    559                 }
    560         *out << Verbose(0) << "RESULT: The biggest diameters are "
    561                         << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
    562                         << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
    563                         : "atomiclength") << "." << endl;
    564 
    565         // free reference lists
    566         if (BoundaryFreeFlag)
    567                 delete[] (BoundaryPoints);
    568 
    569         return GreatestDiameter;
     480    bool IsAngstroem)
     481{
     482  // get points on boundary of NULL was given as parameter
     483  bool BoundaryFreeFlag = false;
     484  Boundaries *BoundaryPoints = BoundaryPtr;
     485  if (BoundaryPoints == NULL)
     486    {
     487      BoundaryFreeFlag = true;
     488      BoundaryPoints = GetBoundaryPoints(out, mol);
     489    }
     490  else
     491    {
     492      *out << Verbose(1) << "Using given boundary points set." << endl;
     493    }
     494  // determine biggest "diameter" of cluster for each axis
     495  Boundaries::iterator Neighbour, OtherNeighbour;
     496  double *GreatestDiameter = new double[NDIM];
     497  for (int i = 0; i < NDIM; i++)
     498    GreatestDiameter[i] = 0.;
     499  double OldComponent, tmp, w1, w2;
     500  Vector DistanceVector, OtherVector;
     501  int component, Othercomponent;
     502  for (int axis = 0; axis < NDIM; axis++)
     503    { // regard each projected plane
     504      //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
     505      for (int j = 0; j < 2; j++)
     506        { // and for both axis on the current plane
     507          component = (axis + j + 1) % NDIM;
     508          Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
     509          //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
     510          for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     511              != BoundaryPoints[axis].end(); runner++)
     512            {
     513              //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
     514              // seek for the neighbours pair where the Othercomponent sign flips
     515              Neighbour = runner;
     516              Neighbour++;
     517              if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
     518                Neighbour = BoundaryPoints[axis].begin();
     519              DistanceVector.CopyVector(&runner->second.second->x);
     520              DistanceVector.SubtractVector(&Neighbour->second.second->x);
     521              do
     522                { // seek for neighbour pair where it flips
     523                  OldComponent = DistanceVector.x[Othercomponent];
     524                  Neighbour++;
     525                  if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
     526                    Neighbour = BoundaryPoints[axis].begin();
     527                  DistanceVector.CopyVector(&runner->second.second->x);
     528                  DistanceVector.SubtractVector(&Neighbour->second.second->x);
     529                  //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
     530                }
     531              while ((runner != Neighbour) && (fabs(OldComponent / fabs(
     532                  OldComponent) - DistanceVector.x[Othercomponent] / fabs(
     533                  DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
     534              if (runner != Neighbour)
     535                {
     536                  OtherNeighbour = Neighbour;
     537                  if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
     538                    OtherNeighbour = BoundaryPoints[axis].end();
     539                  OtherNeighbour--;
     540                  //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
     541                  // now we have found the pair: Neighbour and OtherNeighbour
     542                  OtherVector.CopyVector(&runner->second.second->x);
     543                  OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
     544                  //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
     545                  //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
     546                  // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
     547                  w1 = fabs(OtherVector.x[Othercomponent]);
     548                  w2 = fabs(DistanceVector.x[Othercomponent]);
     549                  tmp = fabs((w1 * DistanceVector.x[component] + w2
     550                      * OtherVector.x[component]) / (w1 + w2));
     551                  // mark if it has greater diameter
     552                  //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
     553                  GreatestDiameter[component] = (GreatestDiameter[component]
     554                      > tmp) ? GreatestDiameter[component] : tmp;
     555                } //else
     556              //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
     557            }
     558        }
     559    }
     560  *out << Verbose(0) << "RESULT: The biggest diameters are "
     561      << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
     562      << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
     563      : "atomiclength") << "." << endl;
     564
     565  // free reference lists
     566  if (BoundaryFreeFlag)
     567    delete[] (BoundaryPoints);
     568
     569  return GreatestDiameter;
    570570}
    571571;
     
    579579void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
    580580{
    581         atom *Walker = mol->start;
    582         bond *Binder = mol->first;
    583         int i;
    584         Vector *center = mol->DetermineCenterOfAll(out);
    585         if (vrmlfile != NULL) {
    586                 //cout << Verbose(1) << "Writing Raster3D file ... ";
    587                 *vrmlfile << "#VRML V2.0 utf8" << endl;
    588                 *vrmlfile << "#Created by molecuilder" << endl;
    589                 *vrmlfile << "#All atoms as spheres" << endl;
    590                 while (Walker->next != mol->end) {
    591                         Walker = Walker->next;
    592                         *vrmlfile << "Sphere {" << endl << "    "; // 2 is sphere type
    593                         for (i=0;i<NDIM;i++)
    594                                 *vrmlfile << Walker->x.x[i]+center->x[i] << " ";
    595                         *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    596                 }
    597 
    598                 *vrmlfile << "# All bonds as vertices" << endl;
    599                 while (Binder->next != mol->last) {
    600                         Binder = Binder->next;
    601                         *vrmlfile << "3" << endl << "   "; // 2 is round-ended cylinder type
    602                         for (i=0;i<NDIM;i++)
    603                                 *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
    604                         *vrmlfile << "\t0.03\t";
    605                         for (i=0;i<NDIM;i++)
    606                                 *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
    607                         *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    608                 }
    609 
    610                 *vrmlfile << "# All tesselation triangles" << endl;
    611                 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    612                         *vrmlfile << "1" << endl << "   "; // 1 is triangle type
    613                         for (i=0;i<3;i++) { // print each node
    614                                 for (int j=0;j<NDIM;j++)        // and for each node all NDIM coordinates
    615                                         *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
    616                                 *vrmlfile << "\t";
    617                         }
    618                         *vrmlfile << "1. 0. 0." << endl;        // red as colour
    619                         *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    620                 }
    621         } else {
    622                 cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
    623         }
    624         delete(center);
     581  atom *Walker = mol->start;
     582  bond *Binder = mol->first;
     583  int i;
     584  Vector *center = mol->DetermineCenterOfAll(out);
     585  if (vrmlfile != NULL) {
     586    //cout << Verbose(1) << "Writing Raster3D file ... ";
     587    *vrmlfile << "#VRML V2.0 utf8" << endl;
     588    *vrmlfile << "#Created by molecuilder" << endl;
     589    *vrmlfile << "#All atoms as spheres" << endl;
     590    while (Walker->next != mol->end) {
     591      Walker = Walker->next;
     592      *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
     593      for (i=0;i<NDIM;i++)
     594        *vrmlfile << Walker->x.x[i]+center->x[i] << " ";
     595      *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     596    }
     597
     598    *vrmlfile << "# All bonds as vertices" << endl;
     599    while (Binder->next != mol->last) {
     600      Binder = Binder->next;
     601      *vrmlfile << "3" << endl << "  "; // 2 is round-ended cylinder type
     602      for (i=0;i<NDIM;i++)
     603        *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     604      *vrmlfile << "\t0.03\t";
     605      for (i=0;i<NDIM;i++)
     606        *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     607      *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
     608    }
     609
     610    *vrmlfile << "# All tesselation triangles" << endl;
     611    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     612      *vrmlfile << "1" << endl << "  "; // 1 is triangle type
     613      for (i=0;i<3;i++) { // print each node
     614        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     615          *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     616        *vrmlfile << "\t";
     617      }
     618      *vrmlfile << "1. 0. 0." << endl;  // red as colour
     619      *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
     620    }
     621  } else {
     622    cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
     623  }
     624  delete(center);
    625625};
    626626
     
    633633void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    634634{
    635         atom *Walker = mol->start;
    636         bond *Binder = mol->first;
    637         int i;
    638         Vector *center = mol->DetermineCenterOfAll(out);
    639         if (rasterfile != NULL) {
    640                 //cout << Verbose(1) << "Writing Raster3D file ... ";
    641                 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    642                 *rasterfile << "@header.r3d" << endl;
    643                 *rasterfile << "# All atoms as spheres" << endl;
    644                 while (Walker->next != mol->end) {
    645                         Walker = Walker->next;
    646                         *rasterfile << "2" << endl << " ";      // 2 is sphere type
    647                         for (i=0;i<NDIM;i++)
    648                                 *rasterfile << Walker->x.x[i]+center->x[i] << " ";
    649                         *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    650                 }
    651 
    652                 *rasterfile << "# All bonds as vertices" << endl;
    653                 while (Binder->next != mol->last) {
    654                         Binder = Binder->next;
    655                         *rasterfile << "3" << endl << " ";      // 2 is round-ended cylinder type
    656                         for (i=0;i<NDIM;i++)
    657                                 *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
    658                         *rasterfile << "\t0.03\t";
    659                         for (i=0;i<NDIM;i++)
    660                                 *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
    661                         *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    662                 }
    663 
    664                 *rasterfile << "# All tesselation triangles" << endl;
    665                 *rasterfile << "8\n     25. -1.  1. 1. 1.        0.0            0 0 0 2\n       SOLID            1.0 0.0 0.0\n  BACKFACE        0.3 0.3 1.0      0 0\n";
    666                 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    667                         *rasterfile << "1" << endl << " ";      // 1 is triangle type
    668                         for (i=0;i<3;i++) {     // print each node
    669                                 for (int j=0;j<NDIM;j++)        // and for each node all NDIM coordinates
    670                                         *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
    671                                 *rasterfile << "\t";
    672                         }
    673                         *rasterfile << "1. 0. 0." << endl;      // red as colour
    674                         //*rasterfile << "18" << endl << "      0.5 0.5 0.5" << endl;   // 18 is transparency type for previous object
    675                 }
    676                 *rasterfile << "9\n     terminating special property\n";
    677         } else {
    678                 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    679         }
    680         delete(center);
     635  atom *Walker = mol->start;
     636  bond *Binder = mol->first;
     637  int i;
     638  Vector *center = mol->DetermineCenterOfAll(out);
     639  if (rasterfile != NULL) {
     640    //cout << Verbose(1) << "Writing Raster3D file ... ";
     641    *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
     642    *rasterfile << "@header.r3d" << endl;
     643    *rasterfile << "# All atoms as spheres" << endl;
     644    while (Walker->next != mol->end) {
     645      Walker = Walker->next;
     646      *rasterfile << "2" << endl << "  ";  // 2 is sphere type
     647      for (i=0;i<NDIM;i++)
     648        *rasterfile << Walker->x.x[i]+center->x[i] << " ";
     649      *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     650    }
     651
     652    *rasterfile << "# All bonds as vertices" << endl;
     653    while (Binder->next != mol->last) {
     654      Binder = Binder->next;
     655      *rasterfile << "3" << endl << "  ";  // 2 is round-ended cylinder type
     656      for (i=0;i<NDIM;i++)
     657        *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     658      *rasterfile << "\t0.03\t";
     659      for (i=0;i<NDIM;i++)
     660        *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     661      *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
     662    }
     663
     664    *rasterfile << "# All tesselation triangles" << endl;
     665    *rasterfile << "8\n  25. -1.   1. 1. 1.   0.0    0 0 0 2\n  SOLID     1.0 0.0 0.0\n  BACKFACE  0.3 0.3 1.0  0 0\n";
     666    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     667      *rasterfile << "1" << endl << "  ";  // 1 is triangle type
     668      for (i=0;i<3;i++) {  // print each node
     669        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     670          *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     671        *rasterfile << "\t";
     672      }
     673      *rasterfile << "1. 0. 0." << endl;  // red as colour
     674      //*rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl;  // 18 is transparency type for previous object
     675    }
     676    *rasterfile << "9\n  terminating special property\n";
     677  } else {
     678    cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
     679  }
     680  delete(center);
    681681};
    682682
     
    688688void
    689689write_tecplot_file(ofstream *out, ofstream *tecplot,
    690                 class Tesselation *TesselStruct, class molecule *mol, int N)
    691 {
    692         if (tecplot != NULL)
    693                 {
    694                         *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    695                         *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
    696                         *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
    697                                         << TesselStruct->PointsOnBoundaryCount << ", E="
    698                                         << TesselStruct->TrianglesOnBoundaryCount
    699                                         << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    700                         int *LookupList = new int[mol->AtomCount];
    701                         for (int i = 0; i < mol->AtomCount; i++)
    702                                 LookupList[i] = -1;
    703 
    704                         // print atom coordinates
    705                         *out << Verbose(2) << "The following triangles were created:";
    706                         int Counter = 1;
    707                         atom *Walker = NULL;
    708                         for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
    709                                         != TesselStruct->PointsOnBoundary.end(); target++)
    710                                 {
    711                                         Walker = target->second->node;
    712                                         LookupList[Walker->nr] = Counter++;
    713                                         *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
    714                                                         << Walker->x.x[2] << " " << endl;
    715                                 }
    716                         *tecplot << endl;
    717                         // print connectivity
    718                         for (TriangleMap::iterator runner =
    719                                         TesselStruct->TrianglesOnBoundary.begin(); runner
    720                                         != TesselStruct->TrianglesOnBoundary.end(); runner++)
    721                                 {
    722                                         *out << " " << runner->second->endpoints[0]->node->Name << "<->"
    723                                                         << runner->second->endpoints[1]->node->Name << "<->"
    724                                                         << runner->second->endpoints[2]->node->Name;
    725                                         *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
    726                                                         << LookupList[runner->second->endpoints[1]->node->nr] << " "
    727                                                         << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    728                                 }
    729                         delete[] (LookupList);
    730                         *out << endl;
    731                 }
     690    class Tesselation *TesselStruct, class molecule *mol, int N)
     691{
     692  if (tecplot != NULL)
     693    {
     694      *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
     695      *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
     696      *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
     697          << TesselStruct->PointsOnBoundaryCount << ", E="
     698          << TesselStruct->TrianglesOnBoundaryCount
     699          << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     700      int *LookupList = new int[mol->AtomCount];
     701      for (int i = 0; i < mol->AtomCount; i++)
     702        LookupList[i] = -1;
     703
     704      // print atom coordinates
     705      *out << Verbose(2) << "The following triangles were created:";
     706      int Counter = 1;
     707      atom *Walker = NULL;
     708      for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
     709          != TesselStruct->PointsOnBoundary.end(); target++)
     710        {
     711          Walker = target->second->node;
     712          LookupList[Walker->nr] = Counter++;
     713          *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
     714              << Walker->x.x[2] << " " << endl;
     715        }
     716      *tecplot << endl;
     717      // print connectivity
     718      for (TriangleMap::iterator runner =
     719          TesselStruct->TrianglesOnBoundary.begin(); runner
     720          != TesselStruct->TrianglesOnBoundary.end(); runner++)
     721        {
     722          *out << " " << runner->second->endpoints[0]->node->Name << "<->"
     723              << runner->second->endpoints[1]->node->Name << "<->"
     724              << runner->second->endpoints[2]->node->Name;
     725          *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
     726              << LookupList[runner->second->endpoints[1]->node->nr] << " "
     727              << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     728        }
     729      delete[] (LookupList);
     730      *out << endl;
     731    }
    732732}
    733733
     
    743743double
    744744VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration,
    745                 Boundaries *BoundaryPtr, molecule *mol)
    746 {
    747         bool IsAngstroem = configuration->GetIsAngstroem();
    748         atom *Walker = NULL;
    749         struct Tesselation *TesselStruct = new Tesselation;
    750         bool BoundaryFreeFlag = false;
    751         Boundaries *BoundaryPoints = BoundaryPtr;
    752         double volume = 0.;
    753         double PyramidVolume = 0.;
    754         double G, h;
    755         Vector x, y;
    756         double a, b, c;
    757 
    758         //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
    759 
    760         // 1. calculate center of gravity
    761         *out << endl;
    762         Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    763 
    764         // 2. translate all points into CoG
    765         *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    766         Walker = mol->start;
    767         while (Walker->next != mol->end)
    768                 {
    769                         Walker = Walker->next;
    770                         Walker->x.Translate(CenterOfGravity);
    771                 }
    772 
    773         // 3. Find all points on the boundary
    774         if (BoundaryPoints == NULL)
    775                 {
    776                         BoundaryFreeFlag = true;
    777                         BoundaryPoints = GetBoundaryPoints(out, mol);
    778                 }
    779         else
    780                 {
    781                         *out << Verbose(1) << "Using given boundary points set." << endl;
    782                 }
    783 
    784         // 4. fill the boundary point list
    785         for (int axis = 0; axis < NDIM; axis++)
    786                 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    787                                 != BoundaryPoints[axis].end(); runner++)
    788                         {
    789                                 TesselStruct->AddPoint(runner->second.second);
    790                         }
    791 
    792         *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
    793                         << " points on the convex boundary." << endl;
    794         // now we have the whole set of edge points in the BoundaryList
    795 
    796         // listing for debugging
    797         //      *out << Verbose(1) << "Listing PointsOnBoundary:";
    798         //      for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
    799         //              *out << " " << *runner->second;
    800         //      }
    801         //      *out << endl;
    802 
    803         // 5a. guess starting triangle
    804         TesselStruct->GuessStartingTriangle(out);
    805 
    806         // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    807         TesselStruct->TesselateOnBoundary(out, configuration, mol);
    808 
    809         *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
    810                         << " triangles with " << TesselStruct->LinesOnBoundaryCount
    811                         << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
    812                         << endl;
    813 
    814         // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
    815         *out << Verbose(1)
    816                         << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
    817                         << endl;
    818         for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
    819                         != TesselStruct->TrianglesOnBoundary.end(); runner++)
    820                 { // go through every triangle, calculate volume of its pyramid with CoG as peak
    821                         x.CopyVector(&runner->second->endpoints[0]->node->x);
    822                         x.SubtractVector(&runner->second->endpoints[1]->node->x);
    823                         y.CopyVector(&runner->second->endpoints[0]->node->x);
    824                         y.SubtractVector(&runner->second->endpoints[2]->node->x);
    825                         a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
    826                                         &runner->second->endpoints[1]->node->x));
    827                         b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
    828                                         &runner->second->endpoints[2]->node->x));
    829                         c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared(
    830                                         &runner->second->endpoints[1]->node->x));
    831                         G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle
    832                         x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
    833                                         &runner->second->endpoints[1]->node->x,
    834                                         &runner->second->endpoints[2]->node->x);
    835                         x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
    836                         h = x.Norm(); // distance of CoG to triangle
    837                         PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
    838                         *out << Verbose(2) << "Area of triangle is " << G << " "
    839                                         << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
    840                                         << h << " and the volume is " << PyramidVolume << " "
    841                                         << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    842                         volume += PyramidVolume;
    843                 }
    844         *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
    845                         << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
    846                         << endl;
    847 
    848         // 7. translate all points back from CoG
    849         *out << Verbose(1) << "Translating system back from Center of Gravity."
    850                         << endl;
    851         CenterOfGravity->Scale(-1);
    852         Walker = mol->start;
    853         while (Walker->next != mol->end)
    854                 {
    855                         Walker = Walker->next;
    856                         Walker->x.Translate(CenterOfGravity);
    857                 }
    858 
    859         // 8. Store triangles in tecplot file
    860         string OutputName(filename);
    861         OutputName.append(TecplotSuffix);
    862         ofstream *tecplot = new ofstream(OutputName.c_str());
    863         write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
    864         tecplot->close();
    865         delete(tecplot);
    866 
    867         // free reference lists
    868         if (BoundaryFreeFlag)
    869                 delete[] (BoundaryPoints);
    870 
    871         return volume;
     745    Boundaries *BoundaryPtr, molecule *mol)
     746{
     747  bool IsAngstroem = configuration->GetIsAngstroem();
     748  atom *Walker = NULL;
     749  struct Tesselation *TesselStruct = new Tesselation;
     750  bool BoundaryFreeFlag = false;
     751  Boundaries *BoundaryPoints = BoundaryPtr;
     752  double volume = 0.;
     753  double PyramidVolume = 0.;
     754  double G, h;
     755  Vector x, y;
     756  double a, b, c;
     757
     758  //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
     759
     760  // 1. calculate center of gravity
     761  *out << endl;
     762  Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
     763
     764  // 2. translate all points into CoG
     765  *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
     766  Walker = mol->start;
     767  while (Walker->next != mol->end)
     768    {
     769      Walker = Walker->next;
     770      Walker->x.Translate(CenterOfGravity);
     771    }
     772
     773  // 3. Find all points on the boundary
     774  if (BoundaryPoints == NULL)
     775    {
     776      BoundaryFreeFlag = true;
     777      BoundaryPoints = GetBoundaryPoints(out, mol);
     778    }
     779  else
     780    {
     781      *out << Verbose(1) << "Using given boundary points set." << endl;
     782    }
     783
     784  // 4. fill the boundary point list
     785  for (int axis = 0; axis < NDIM; axis++)
     786    for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
     787        != BoundaryPoints[axis].end(); runner++)
     788      {
     789        TesselStruct->AddPoint(runner->second.second);
     790      }
     791
     792  *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
     793      << " points on the convex boundary." << endl;
     794  // now we have the whole set of edge points in the BoundaryList
     795
     796  // listing for debugging
     797  //  *out << Verbose(1) << "Listing PointsOnBoundary:";
     798  //  for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
     799  //    *out << " " << *runner->second;
     800  //  }
     801  //  *out << endl;
     802
     803  // 5a. guess starting triangle
     804  TesselStruct->GuessStartingTriangle(out);
     805
     806  // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
     807  TesselStruct->TesselateOnBoundary(out, configuration, mol);
     808
     809  *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
     810      << " triangles with " << TesselStruct->LinesOnBoundaryCount
     811      << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
     812      << endl;
     813
     814  // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
     815  *out << Verbose(1)
     816      << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
     817      << endl;
     818  for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
     819      != TesselStruct->TrianglesOnBoundary.end(); runner++)
     820    { // go through every triangle, calculate volume of its pyramid with CoG as peak
     821      x.CopyVector(&runner->second->endpoints[0]->node->x);
     822      x.SubtractVector(&runner->second->endpoints[1]->node->x);
     823      y.CopyVector(&runner->second->endpoints[0]->node->x);
     824      y.SubtractVector(&runner->second->endpoints[2]->node->x);
     825      a = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
     826          &runner->second->endpoints[1]->node->x));
     827      b = sqrt(runner->second->endpoints[0]->node->x.DistanceSquared(
     828          &runner->second->endpoints[2]->node->x));
     829      c = sqrt(runner->second->endpoints[2]->node->x.DistanceSquared(
     830          &runner->second->endpoints[1]->node->x));
     831      G = sqrt(((a + b + c) * (a + b + c) - 2 * (a * a + b * b + c * c)) / 16.); // area of tesselated triangle
     832      x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
     833          &runner->second->endpoints[1]->node->x,
     834          &runner->second->endpoints[2]->node->x);
     835      x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
     836      h = x.Norm(); // distance of CoG to triangle
     837      PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
     838      *out << Verbose(2) << "Area of triangle is " << G << " "
     839          << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
     840          << h << " and the volume is " << PyramidVolume << " "
     841          << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     842      volume += PyramidVolume;
     843    }
     844  *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
     845      << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
     846      << endl;
     847
     848  // 7. translate all points back from CoG
     849  *out << Verbose(1) << "Translating system back from Center of Gravity."
     850      << endl;
     851  CenterOfGravity->Scale(-1);
     852  Walker = mol->start;
     853  while (Walker->next != mol->end)
     854    {
     855      Walker = Walker->next;
     856      Walker->x.Translate(CenterOfGravity);
     857    }
     858
     859  // 8. Store triangles in tecplot file
     860  string OutputName(filename);
     861  OutputName.append(TecplotSuffix);
     862  ofstream *tecplot = new ofstream(OutputName.c_str());
     863  write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
     864  tecplot->close();
     865  delete(tecplot);
     866
     867  // free reference lists
     868  if (BoundaryFreeFlag)
     869    delete[] (BoundaryPoints);
     870
     871  return volume;
    872872}
    873873;
     
    883883void
    884884PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
    885                 double ClusterVolume, double celldensity)
    886 {
    887         // transform to PAS
    888         mol->PrincipalAxisSystem(out, true);
    889 
    890         // some preparations beforehand
    891         bool IsAngstroem = configuration->GetIsAngstroem();
    892         Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
    893         double clustervolume;
    894         if (ClusterVolume == 0)
    895                 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
    896                                 BoundaryPoints, mol);
    897         else
    898                 clustervolume = ClusterVolume;
    899         double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
    900                         IsAngstroem);
    901         Vector BoxLengths;
    902         int repetition[NDIM] =
    903                 { 1, 1, 1 };
    904         int TotalNoClusters = 1;
    905         for (int i = 0; i < NDIM; i++)
    906                 TotalNoClusters *= repetition[i];
    907 
    908         // sum up the atomic masses
    909         double totalmass = 0.;
    910         atom *Walker = mol->start;
    911         while (Walker->next != mol->end)
    912                 {
    913                         Walker = Walker->next;
    914                         totalmass += Walker->type->mass;
    915                 }
    916         *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
    917                         << totalmass << " atomicmassunit." << endl;
    918 
    919         *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
    920                         << totalmass / clustervolume << " atomicmassunit/"
    921                         << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    922 
    923         // solve cubic polynomial
    924         *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
    925                         << endl;
    926         double cellvolume;
    927         if (IsAngstroem)
    928                 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
    929                                 / clustervolume)) / (celldensity - 1);
    930         else
    931                 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
    932                                 / clustervolume)) / (celldensity - 1);
    933         *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
    934                         << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
    935                         : "atomiclength") << "^3." << endl;
    936 
    937         double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
    938                         * GreatestDiameter[1] * GreatestDiameter[2]);
    939         *out << Verbose(1)
    940                         << "Minimum volume of the convex envelope contained in a rectangular box is "
    941                         << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
    942                         : "atomiclength") << "^3." << endl;
    943         if (minimumvolume > cellvolume)
    944                 {
    945                         cerr << Verbose(0)
    946                                         << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
    947                                         << endl;
    948                         cout << Verbose(0)
    949                                         << "Setting Box dimensions to minimum possible, the greatest diameters."
    950                                         << endl;
    951                         for (int i = 0; i < NDIM; i++)
    952                                 BoxLengths.x[i] = GreatestDiameter[i];
    953                         mol->CenterEdge(out, &BoxLengths);
    954                 }
    955         else
    956                 {
    957                         BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
    958                                         * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
    959                         BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
    960                                         * GreatestDiameter[1] + repetition[0] * repetition[2]
    961                                         * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
    962                                         * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
    963                         BoxLengths.x[2] = minimumvolume - cellvolume;
    964                         double x0 = 0., x1 = 0., x2 = 0.;
    965                         if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
    966                                         BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
    967                                 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
    968                                                 << " ." << endl;
    969                         else
    970                                 {
    971                                         *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
    972                                                         << " and " << x1 << " and " << x2 << " ." << endl;
    973                                         x0 = x2; // sorted in ascending order
    974                                 }
    975 
    976                         cellvolume = 1;
    977                         for (int i = 0; i < NDIM; i++)
    978                                 {
    979                                         BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
    980                                         cellvolume *= BoxLengths.x[i];
    981                                 }
    982 
    983                         // set new box dimensions
    984                         *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    985                         mol->CenterInBox((ofstream *) &cout, &BoxLengths);
    986                 }
    987         // update Box of atoms by boundary
    988         mol->SetBoxDimension(&BoxLengths);
    989         *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
    990                         << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
    991                         << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
    992                         << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     885    double ClusterVolume, double celldensity)
     886{
     887  // transform to PAS
     888  mol->PrincipalAxisSystem(out, true);
     889
     890  // some preparations beforehand
     891  bool IsAngstroem = configuration->GetIsAngstroem();
     892  Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
     893  double clustervolume;
     894  if (ClusterVolume == 0)
     895    clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
     896        BoundaryPoints, mol);
     897  else
     898    clustervolume = ClusterVolume;
     899  double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
     900      IsAngstroem);
     901  Vector BoxLengths;
     902  int repetition[NDIM] =
     903    { 1, 1, 1 };
     904  int TotalNoClusters = 1;
     905  for (int i = 0; i < NDIM; i++)
     906    TotalNoClusters *= repetition[i];
     907
     908  // sum up the atomic masses
     909  double totalmass = 0.;
     910  atom *Walker = mol->start;
     911  while (Walker->next != mol->end)
     912    {
     913      Walker = Walker->next;
     914      totalmass += Walker->type->mass;
     915    }
     916  *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
     917      << totalmass << " atomicmassunit." << endl;
     918
     919  *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
     920      << totalmass / clustervolume << " atomicmassunit/"
     921      << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
     922
     923  // solve cubic polynomial
     924  *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
     925      << endl;
     926  double cellvolume;
     927  if (IsAngstroem)
     928    cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
     929        / clustervolume)) / (celldensity - 1);
     930  else
     931    cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
     932        / clustervolume)) / (celldensity - 1);
     933  *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
     934      << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
     935      : "atomiclength") << "^3." << endl;
     936
     937  double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
     938      * GreatestDiameter[1] * GreatestDiameter[2]);
     939  *out << Verbose(1)
     940      << "Minimum volume of the convex envelope contained in a rectangular box is "
     941      << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
     942      : "atomiclength") << "^3." << endl;
     943  if (minimumvolume > cellvolume)
     944    {
     945      cerr << Verbose(0)
     946          << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
     947          << endl;
     948      cout << Verbose(0)
     949          << "Setting Box dimensions to minimum possible, the greatest diameters."
     950          << endl;
     951      for (int i = 0; i < NDIM; i++)
     952        BoxLengths.x[i] = GreatestDiameter[i];
     953      mol->CenterEdge(out, &BoxLengths);
     954    }
     955  else
     956    {
     957      BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
     958          * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
     959      BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
     960          * GreatestDiameter[1] + repetition[0] * repetition[2]
     961          * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
     962          * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
     963      BoxLengths.x[2] = minimumvolume - cellvolume;
     964      double x0 = 0., x1 = 0., x2 = 0.;
     965      if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
     966          BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
     967        *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
     968            << " ." << endl;
     969      else
     970        {
     971          *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
     972              << " and " << x1 << " and " << x2 << " ." << endl;
     973          x0 = x2; // sorted in ascending order
     974        }
     975
     976      cellvolume = 1;
     977      for (int i = 0; i < NDIM; i++)
     978        {
     979          BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
     980          cellvolume *= BoxLengths.x[i];
     981        }
     982
     983      // set new box dimensions
     984      *out << Verbose(0) << "Translating to box with these boundaries." << endl;
     985      mol->CenterInBox((ofstream *) &cout, &BoxLengths);
     986    }
     987  // update Box of atoms by boundary
     988  mol->SetBoxDimension(&BoxLengths);
     989  *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
     990      << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
     991      << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
     992      << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    993993}
    994994;
     
    10001000Tesselation::Tesselation()
    10011001{
    1002         PointsOnBoundaryCount = 0;
    1003         LinesOnBoundaryCount = 0;
    1004         TrianglesOnBoundaryCount = 0;
    1005         TriangleFilesWritten = 0;
     1002  PointsOnBoundaryCount = 0;
     1003  LinesOnBoundaryCount = 0;
     1004  TrianglesOnBoundaryCount = 0;
     1005  TriangleFilesWritten = 0;
    10061006}
    10071007;
     
    10121012Tesselation::~Tesselation()
    10131013{
    1014         cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
    1015         for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
    1016                 if (runner->second != NULL) {
    1017                         delete (runner->second);
    1018                         runner->second = NULL;
    1019                 } else
    1020                         cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
    1021         }
     1014  cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
     1015  for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) {
     1016    if (runner->second != NULL) {
     1017      delete (runner->second);
     1018      runner->second = NULL;
     1019    } else
     1020      cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
     1021  }
    10221022}
    10231023;
     
    10311031Tesselation::GuessStartingTriangle(ofstream *out)
    10321032{
    1033         // 4b. create a starting triangle
    1034         // 4b1. create all distances
    1035         DistanceMultiMap DistanceMMap;
    1036         double distance, tmp;
    1037         Vector PlaneVector, TrialVector;
    1038         PointMap::iterator A, B, C; // three nodes of the first triangle
    1039         A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
    1040 
    1041         // with A chosen, take each pair B,C and sort
    1042         if (A != PointsOnBoundary.end())
    1043                 {
    1044                         B = A;
    1045                         B++;
    1046                         for (; B != PointsOnBoundary.end(); B++)
    1047                                 {
    1048                                         C = B;
    1049                                         C++;
    1050                                         for (; C != PointsOnBoundary.end(); C++)
    1051                                                 {
    1052                                                         tmp = A->second->node->x.DistanceSquared(&B->second->node->x);
    1053                                                         distance = tmp * tmp;
    1054                                                         tmp = A->second->node->x.DistanceSquared(&C->second->node->x);
    1055                                                         distance += tmp * tmp;
    1056                                                         tmp = B->second->node->x.DistanceSquared(&C->second->node->x);
    1057                                                         distance += tmp * tmp;
    1058                                                         DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
    1059                                                                         PointMap::iterator, PointMap::iterator> (B, C)));
    1060                                                 }
    1061                                 }
    1062                 }
    1063         //              // listing distances
    1064         //              *out << Verbose(1) << "Listing DistanceMMap:";
    1065         //              for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
    1066         //                      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
    1067         //              }
    1068         //              *out << endl;
    1069         // 4b2. pick three baselines forming a triangle
    1070         // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1071         DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    1072         for (; baseline != DistanceMMap.end(); baseline++)
    1073                 {
    1074                         // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1075                         // 2. next, we have to check whether all points reside on only one side of the triangle
    1076                         // 3. construct plane vector
    1077                         PlaneVector.MakeNormalVector(&A->second->node->x,
    1078                                         &baseline->second.first->second->node->x,
    1079                                         &baseline->second.second->second->node->x);
    1080                         *out << Verbose(2) << "Plane vector of candidate triangle is ";
    1081                         PlaneVector.Output(out);
    1082                         *out << endl;
    1083                         // 4. loop over all points
    1084                         double sign = 0.;
    1085                         PointMap::iterator checker = PointsOnBoundary.begin();
    1086                         for (; checker != PointsOnBoundary.end(); checker++)
    1087                                 {
    1088                                         // (neglecting A,B,C)
    1089                                         if ((checker == A) || (checker == baseline->second.first) || (checker
    1090                                                         == baseline->second.second))
    1091                                                 continue;
    1092                                         // 4a. project onto plane vector
    1093                                         TrialVector.CopyVector(&checker->second->node->x);
    1094                                         TrialVector.SubtractVector(&A->second->node->x);
    1095                                         distance = TrialVector.Projection(&PlaneVector);
    1096                                         if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
    1097                                                 continue;
    1098                                         *out << Verbose(3) << "Projection of " << checker->second->node->Name
    1099                                                         << " yields distance of " << distance << "." << endl;
    1100                                         tmp = distance / fabs(distance);
    1101                                         // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
    1102                                         if ((sign != 0) && (tmp != sign))
    1103                                                 {
    1104                                                         // 4c. If so, break 4. loop and continue with next candidate in 1. loop
    1105                                                         *out << Verbose(2) << "Current candidates: "
    1106                                                                         << A->second->node->Name << ","
    1107                                                                         << baseline->second.first->second->node->Name << ","
    1108                                                                         << baseline->second.second->second->node->Name << " leave "
    1109                                                                         << checker->second->node->Name << " outside the convex hull."
    1110                                                                         << endl;
    1111                                                         break;
    1112                                                 }
    1113                                         else
    1114                                                 { // note the sign for later
    1115                                                         *out << Verbose(2) << "Current candidates: "
    1116                                                                         << A->second->node->Name << ","
    1117                                                                         << baseline->second.first->second->node->Name << ","
    1118                                                                         << baseline->second.second->second->node->Name << " leave "
    1119                                                                         << checker->second->node->Name << " inside the convex hull."
    1120                                                                         << endl;
    1121                                                         sign = tmp;
    1122                                                 }
    1123                                         // 4d. Check whether the point is inside the triangle (check distance to each node
    1124                                         tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);
    1125                                         int innerpoint = 0;
    1126                                         if ((tmp < A->second->node->x.DistanceSquared(
    1127                                                         &baseline->second.first->second->node->x)) && (tmp
    1128                                                         < A->second->node->x.DistanceSquared(
    1129                                                                         &baseline->second.second->second->node->x)))
    1130                                                 innerpoint++;
    1131                                         tmp = checker->second->node->x.DistanceSquared(
    1132                                                         &baseline->second.first->second->node->x);
    1133                                         if ((tmp < baseline->second.first->second->node->x.DistanceSquared(
    1134                                                         &A->second->node->x)) && (tmp
    1135                                                         < baseline->second.first->second->node->x.DistanceSquared(
    1136                                                                         &baseline->second.second->second->node->x)))
    1137                                                 innerpoint++;
    1138                                         tmp = checker->second->node->x.DistanceSquared(
    1139                                                         &baseline->second.second->second->node->x);
    1140                                         if ((tmp < baseline->second.second->second->node->x.DistanceSquared(
    1141                                                         &baseline->second.first->second->node->x)) && (tmp
    1142                                                         < baseline->second.second->second->node->x.DistanceSquared(
    1143                                                                         &A->second->node->x)))
    1144                                                 innerpoint++;
    1145                                         // 4e. If so, break 4. loop and continue with next candidate in 1. loop
    1146                                         if (innerpoint == 3)
    1147                                                 break;
    1148                                 }
    1149                         // 5. come this far, all on same side? Then break 1. loop and construct triangle
    1150                         if (checker == PointsOnBoundary.end())
    1151                                 {
    1152                                         *out << "Looks like we have a candidate!" << endl;
    1153                                         break;
    1154                                 }
    1155                 }
    1156         if (baseline != DistanceMMap.end())
    1157                 {
    1158                         BPS[0] = baseline->second.first->second;
    1159                         BPS[1] = baseline->second.second->second;
    1160                         BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1161                         BPS[0] = A->second;
    1162                         BPS[1] = baseline->second.second->second;
    1163                         BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1164                         BPS[0] = baseline->second.first->second;
    1165                         BPS[1] = A->second;
    1166                         BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1167 
    1168                         // 4b3. insert created triangle
    1169                         BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1170                         TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1171                         TrianglesOnBoundaryCount++;
    1172                         for (int i = 0; i < NDIM; i++)
    1173                                 {
    1174                                         LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
    1175                                         LinesOnBoundaryCount++;
    1176                                 }
    1177 
    1178                         *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
    1179                 }
    1180         else
    1181                 {
    1182                         *out << Verbose(1) << "No starting triangle found." << endl;
    1183                         exit(255);
    1184                 }
     1033  // 4b. create a starting triangle
     1034  // 4b1. create all distances
     1035  DistanceMultiMap DistanceMMap;
     1036  double distance, tmp;
     1037  Vector PlaneVector, TrialVector;
     1038  PointMap::iterator A, B, C; // three nodes of the first triangle
     1039  A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
     1040
     1041  // with A chosen, take each pair B,C and sort
     1042  if (A != PointsOnBoundary.end())
     1043    {
     1044      B = A;
     1045      B++;
     1046      for (; B != PointsOnBoundary.end(); B++)
     1047        {
     1048          C = B;
     1049          C++;
     1050          for (; C != PointsOnBoundary.end(); C++)
     1051            {
     1052              tmp = A->second->node->x.DistanceSquared(&B->second->node->x);
     1053              distance = tmp * tmp;
     1054              tmp = A->second->node->x.DistanceSquared(&C->second->node->x);
     1055              distance += tmp * tmp;
     1056              tmp = B->second->node->x.DistanceSquared(&C->second->node->x);
     1057              distance += tmp * tmp;
     1058              DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
     1059                  PointMap::iterator, PointMap::iterator> (B, C)));
     1060            }
     1061        }
     1062    }
     1063  //    // listing distances
     1064  //    *out << Verbose(1) << "Listing DistanceMMap:";
     1065  //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
     1066  //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
     1067  //    }
     1068  //    *out << endl;
     1069  // 4b2. pick three baselines forming a triangle
     1070  // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1071  DistanceMultiMap::iterator baseline = DistanceMMap.begin();
     1072  for (; baseline != DistanceMMap.end(); baseline++)
     1073    {
     1074      // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
     1075      // 2. next, we have to check whether all points reside on only one side of the triangle
     1076      // 3. construct plane vector
     1077      PlaneVector.MakeNormalVector(&A->second->node->x,
     1078          &baseline->second.first->second->node->x,
     1079          &baseline->second.second->second->node->x);
     1080      *out << Verbose(2) << "Plane vector of candidate triangle is ";
     1081      PlaneVector.Output(out);
     1082      *out << endl;
     1083      // 4. loop over all points
     1084      double sign = 0.;
     1085      PointMap::iterator checker = PointsOnBoundary.begin();
     1086      for (; checker != PointsOnBoundary.end(); checker++)
     1087        {
     1088          // (neglecting A,B,C)
     1089          if ((checker == A) || (checker == baseline->second.first) || (checker
     1090              == baseline->second.second))
     1091            continue;
     1092          // 4a. project onto plane vector
     1093          TrialVector.CopyVector(&checker->second->node->x);
     1094          TrialVector.SubtractVector(&A->second->node->x);
     1095          distance = TrialVector.Projection(&PlaneVector);
     1096          if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
     1097            continue;
     1098          *out << Verbose(3) << "Projection of " << checker->second->node->Name
     1099              << " yields distance of " << distance << "." << endl;
     1100          tmp = distance / fabs(distance);
     1101          // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
     1102          if ((sign != 0) && (tmp != sign))
     1103            {
     1104              // 4c. If so, break 4. loop and continue with next candidate in 1. loop
     1105              *out << Verbose(2) << "Current candidates: "
     1106                  << A->second->node->Name << ","
     1107                  << baseline->second.first->second->node->Name << ","
     1108                  << baseline->second.second->second->node->Name << " leave "
     1109                  << checker->second->node->Name << " outside the convex hull."
     1110                  << endl;
     1111              break;
     1112            }
     1113          else
     1114            { // note the sign for later
     1115              *out << Verbose(2) << "Current candidates: "
     1116                  << A->second->node->Name << ","
     1117                  << baseline->second.first->second->node->Name << ","
     1118                  << baseline->second.second->second->node->Name << " leave "
     1119                  << checker->second->node->Name << " inside the convex hull."
     1120                  << endl;
     1121              sign = tmp;
     1122            }
     1123          // 4d. Check whether the point is inside the triangle (check distance to each node
     1124          tmp = checker->second->node->x.DistanceSquared(&A->second->node->x);
     1125          int innerpoint = 0;
     1126          if ((tmp < A->second->node->x.DistanceSquared(
     1127              &baseline->second.first->second->node->x)) && (tmp
     1128              < A->second->node->x.DistanceSquared(
     1129                  &baseline->second.second->second->node->x)))
     1130            innerpoint++;
     1131          tmp = checker->second->node->x.DistanceSquared(
     1132              &baseline->second.first->second->node->x);
     1133          if ((tmp < baseline->second.first->second->node->x.DistanceSquared(
     1134              &A->second->node->x)) && (tmp
     1135              < baseline->second.first->second->node->x.DistanceSquared(
     1136                  &baseline->second.second->second->node->x)))
     1137            innerpoint++;
     1138          tmp = checker->second->node->x.DistanceSquared(
     1139              &baseline->second.second->second->node->x);
     1140          if ((tmp < baseline->second.second->second->node->x.DistanceSquared(
     1141              &baseline->second.first->second->node->x)) && (tmp
     1142              < baseline->second.second->second->node->x.DistanceSquared(
     1143                  &A->second->node->x)))
     1144            innerpoint++;
     1145          // 4e. If so, break 4. loop and continue with next candidate in 1. loop
     1146          if (innerpoint == 3)
     1147            break;
     1148        }
     1149      // 5. come this far, all on same side? Then break 1. loop and construct triangle
     1150      if (checker == PointsOnBoundary.end())
     1151        {
     1152          *out << "Looks like we have a candidate!" << endl;
     1153          break;
     1154        }
     1155    }
     1156  if (baseline != DistanceMMap.end())
     1157    {
     1158      BPS[0] = baseline->second.first->second;
     1159      BPS[1] = baseline->second.second->second;
     1160      BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1161      BPS[0] = A->second;
     1162      BPS[1] = baseline->second.second->second;
     1163      BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1164      BPS[0] = baseline->second.first->second;
     1165      BPS[1] = A->second;
     1166      BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1167
     1168      // 4b3. insert created triangle
     1169      BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     1170      TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1171      TrianglesOnBoundaryCount++;
     1172      for (int i = 0; i < NDIM; i++)
     1173        {
     1174          LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
     1175          LinesOnBoundaryCount++;
     1176        }
     1177
     1178      *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
     1179    }
     1180  else
     1181    {
     1182      *out << Verbose(1) << "No starting triangle found." << endl;
     1183      exit(255);
     1184    }
    11851185}
    11861186;
     
    11911191 * -# if the lines contains to only one triangle
    11921192 * -# We search all points in the boundary
    1193  *              -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
    1194  *              -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
    1195  *                      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
    1196  *              -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
     1193 *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
     1194 *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
     1195 *      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
     1196 *    -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
    11971197 * \param *out output stream for debugging
    11981198 * \param *configuration for IsAngstroem
     
    12011201void
    12021202Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    1203                 molecule *mol)
    1204 {
    1205         bool flag;
    1206         PointMap::iterator winner;
    1207         class BoundaryPointSet *peak = NULL;
    1208         double SmallestAngle, TempAngle;
    1209         Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
    1210                         PropagationVector;
    1211         LineMap::iterator LineChecker[2];
    1212         do
    1213                 {
    1214                         flag = false;
    1215                         for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
    1216                                         != LinesOnBoundary.end(); baseline++)
    1217                                 if (baseline->second->TrianglesCount == 1)
    1218                                         {
    1219                                                 *out << Verbose(2) << "Current baseline is between "
    1220                                                                 << *(baseline->second) << "." << endl;
    1221                                                 // 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)
    1222                                                 SmallestAngle = M_PI;
    1223                                                 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1224                                                 // get peak point with respect to this base line's only triangle
    1225                                                 for (int i = 0; i < 3; i++)
    1226                                                         if ((BTS->endpoints[i] != baseline->second->endpoints[0])
    1227                                                                         && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1228                                                                 peak = BTS->endpoints[i];
    1229                                                 *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1230                                                 // normal vector of triangle
    1231                                                 BTS->GetNormalVector(NormalVector);
    1232                                                 *out << Verbose(4) << "NormalVector of base triangle is ";
    1233                                                 NormalVector.Output(out);
    1234                                                 *out << endl;
    1235                                                 // offset to center of triangle
    1236                                                 CenterVector.Zero();
    1237                                                 for (int i = 0; i < 3; i++)
    1238                                                         CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1239                                                 CenterVector.Scale(1. / 3.);
    1240                                                 *out << Verbose(4) << "CenterVector of base triangle is ";
    1241                                                 CenterVector.Output(out);
    1242                                                 *out << endl;
    1243                                                 // vector in propagation direction (out of triangle)
    1244                                                 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
    1245                                                 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1246                                                 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1247                                                 PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
    1248                                                 TempVector.CopyVector(&CenterVector);
    1249                                                 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1250                                                 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1251                                                 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1252                                                         PropagationVector.Scale(-1.);
    1253                                                 *out << Verbose(4) << "PropagationVector of base triangle is ";
    1254                                                 PropagationVector.Output(out);
    1255                                                 *out << endl;
    1256                                                 winner = PointsOnBoundary.end();
    1257                                                 for (PointMap::iterator target = PointsOnBoundary.begin(); target
    1258                                                                 != PointsOnBoundary.end(); target++)
    1259                                                         if ((target->second != baseline->second->endpoints[0])
    1260                                                                         && (target->second != baseline->second->endpoints[1]))
    1261                                                                 { // don't take the same endpoints
    1262                                                                         *out << Verbose(3) << "Target point is " << *(target->second)
    1263                                                                                         << ":";
    1264                                                                         bool continueflag = true;
    1265 
    1266                                                                         VirtualNormalVector.CopyVector(
    1267                                                                                         &baseline->second->endpoints[0]->node->x);
    1268                                                                         VirtualNormalVector.AddVector(
    1269                                                                                         &baseline->second->endpoints[0]->node->x);
    1270                                                                         VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
    1271                                                                         VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
    1272                                                                         TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1273                                                                         continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
    1274                                                                         if (!continueflag)
    1275                                                                                 {
    1276                                                                                         *out << Verbose(4)
    1277                                                                                                         << "Angle between propagation direction and base line to "
    1278                                                                                                         << *(target->second) << " is " << TempAngle
    1279                                                                                                         << ", bad direction!" << endl;
    1280                                                                                         continue;
    1281                                                                                 }
    1282                                                                         else
    1283                                                                                 *out << Verbose(4)
    1284                                                                                                 << "Angle between propagation direction and base line to "
    1285                                                                                                 << *(target->second) << " is " << TempAngle
    1286                                                                                                 << ", good direction!" << endl;
    1287                                                                         LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1288                                                                                         target->first);
    1289                                                                         LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1290                                                                                         target->first);
    1291                                                                         //                                              if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
    1292                                                                         //                                                      *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1293                                                                         //                                              else
    1294                                                                         //                                                      *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1295                                                                         //                                              if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
    1296                                                                         //                                                      *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1297                                                                         //                                              else
    1298                                                                         //                                                      *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1299                                                                         // check first endpoint (if any connecting line goes to target or at least not more than 1)
    1300                                                                         continueflag = continueflag && (((LineChecker[0]
    1301                                                                                         == baseline->second->endpoints[0]->lines.end())
    1302                                                                                         || (LineChecker[0]->second->TrianglesCount == 1)));
    1303                                                                         if (!continueflag)
    1304                                                                                 {
    1305                                                                                         *out << Verbose(4) << *(baseline->second->endpoints[0])
    1306                                                                                                         << " has line " << *(LineChecker[0]->second)
    1307                                                                                                         << " to " << *(target->second)
    1308                                                                                                         << " as endpoint with "
    1309                                                                                                         << LineChecker[0]->second->TrianglesCount
    1310                                                                                                         << " triangles." << endl;
    1311                                                                                         continue;
    1312                                                                                 }
    1313                                                                         // check second endpoint (if any connecting line goes to target or at least not more than 1)
    1314                                                                         continueflag = continueflag && (((LineChecker[1]
    1315                                                                                         == baseline->second->endpoints[1]->lines.end())
    1316                                                                                         || (LineChecker[1]->second->TrianglesCount == 1)));
    1317                                                                         if (!continueflag)
    1318                                                                                 {
    1319                                                                                         *out << Verbose(4) << *(baseline->second->endpoints[1])
    1320                                                                                                         << " has line " << *(LineChecker[1]->second)
    1321                                                                                                         << " to " << *(target->second)
    1322                                                                                                         << " as endpoint with "
    1323                                                                                                         << LineChecker[1]->second->TrianglesCount
    1324                                                                                                         << " triangles." << endl;
    1325                                                                                         continue;
    1326                                                                                 }
    1327                                                                         // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1328                                                                         continueflag = continueflag && (!(((LineChecker[0]
    1329                                                                                         != baseline->second->endpoints[0]->lines.end())
    1330                                                                                         && (LineChecker[1]
    1331                                                                                                         != baseline->second->endpoints[1]->lines.end())
    1332                                                                                         && (GetCommonEndpoint(LineChecker[0]->second,
    1333                                                                                                         LineChecker[1]->second) == peak))));
    1334                                                                         if (!continueflag)
    1335                                                                                 {
    1336                                                                                         *out << Verbose(4) << "Current target is peak!" << endl;
    1337                                                                                         continue;
    1338                                                                                 }
    1339                                                                         // in case NOT both were found
    1340                                                                         if (continueflag)
    1341                                                                                 { // create virtually this triangle, get its normal vector, calculate angle
    1342                                                                                         flag = true;
    1343                                                                                         VirtualNormalVector.MakeNormalVector(
    1344                                                                                                         &baseline->second->endpoints[0]->node->x,
    1345                                                                                                         &baseline->second->endpoints[1]->node->x,
    1346                                                                                                         &target->second->node->x);
    1347                                                                                         // make it always point inward
    1348                                                                                         if (baseline->second->endpoints[0]->node->x.Projection(
    1349                                                                                                         &VirtualNormalVector) > 0)
    1350                                                                                                 VirtualNormalVector.Scale(-1.);
    1351                                                                                         // calculate angle
    1352                                                                                         TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1353                                                                                         *out << Verbose(4) << "NormalVector is ";
    1354                                                                                         VirtualNormalVector.Output(out);
    1355                                                                                         *out << " and the angle is " << TempAngle << "." << endl;
    1356                                                                                         if (SmallestAngle > TempAngle)
    1357                                                                                                 { // set to new possible winner
    1358                                                                                                         SmallestAngle = TempAngle;
    1359                                                                                                         winner = target;
    1360                                                                                                 }
    1361                                                                                 }
    1362                                                                 }
    1363                                                 // 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
    1364                                                 if (winner != PointsOnBoundary.end())
    1365                                                         {
    1366                                                                 *out << Verbose(2) << "Winning target point is "
    1367                                                                                 << *(winner->second) << " with angle " << SmallestAngle
    1368                                                                                 << "." << endl;
    1369                                                                 // create the lins of not yet present
    1370                                                                 BLS[0] = baseline->second;
    1371                                                                 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1372                                                                 LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1373                                                                                 winner->first);
    1374                                                                 LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1375                                                                                 winner->first);
    1376                                                                 if (LineChecker[0]
    1377                                                                                 == baseline->second->endpoints[0]->lines.end())
    1378                                                                         { // create
    1379                                                                                 BPS[0] = baseline->second->endpoints[0];
    1380                                                                                 BPS[1] = winner->second;
    1381                                                                                 BLS[1] = new class BoundaryLineSet(BPS,
    1382                                                                                                 LinesOnBoundaryCount);
    1383                                                                                 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1384                                                                                                 BLS[1]));
    1385                                                                                 LinesOnBoundaryCount++;
    1386                                                                         }
    1387                                                                 else
    1388                                                                         BLS[1] = LineChecker[0]->second;
    1389                                                                 if (LineChecker[1]
    1390                                                                                 == baseline->second->endpoints[1]->lines.end())
    1391                                                                         { // create
    1392                                                                                 BPS[0] = baseline->second->endpoints[1];
    1393                                                                                 BPS[1] = winner->second;
    1394                                                                                 BLS[2] = new class BoundaryLineSet(BPS,
    1395                                                                                                 LinesOnBoundaryCount);
    1396                                                                                 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1397                                                                                                 BLS[2]));
    1398                                                                                 LinesOnBoundaryCount++;
    1399                                                                         }
    1400                                                                 else
    1401                                                                         BLS[2] = LineChecker[1]->second;
    1402                                                                 BTS = new class BoundaryTriangleSet(BLS,
    1403                                                                                 TrianglesOnBoundaryCount);
    1404                                                                 TrianglesOnBoundary.insert(TrianglePair(
    1405                                                                                 TrianglesOnBoundaryCount, BTS));
    1406                                                                 TrianglesOnBoundaryCount++;
    1407                                                         }
    1408                                                 else
    1409                                                         {
    1410                                                                 *out << Verbose(1)
    1411                                                                                 << "I could not determine a winner for this baseline "
    1412                                                                                 << *(baseline->second) << "." << endl;
    1413                                                         }
    1414 
    1415                                                 // 5d. If the set of lines is not yet empty, go to 5. and continue
    1416                                         }
    1417                                 else
    1418                                         *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
    1419                                                         << " has a triangle count of "
    1420                                                         << baseline->second->TrianglesCount << "." << endl;
    1421                 }
    1422         while (flag);
     1203    molecule *mol)
     1204{
     1205  bool flag;
     1206  PointMap::iterator winner;
     1207  class BoundaryPointSet *peak = NULL;
     1208  double SmallestAngle, TempAngle;
     1209  Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
     1210      PropagationVector;
     1211  LineMap::iterator LineChecker[2];
     1212  do
     1213    {
     1214      flag = false;
     1215      for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
     1216          != LinesOnBoundary.end(); baseline++)
     1217        if (baseline->second->TrianglesCount == 1)
     1218          {
     1219            *out << Verbose(2) << "Current baseline is between "
     1220                << *(baseline->second) << "." << endl;
     1221            // 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)
     1222            SmallestAngle = M_PI;
     1223            BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
     1224            // get peak point with respect to this base line's only triangle
     1225            for (int i = 0; i < 3; i++)
     1226              if ((BTS->endpoints[i] != baseline->second->endpoints[0])
     1227                  && (BTS->endpoints[i] != baseline->second->endpoints[1]))
     1228                peak = BTS->endpoints[i];
     1229            *out << Verbose(3) << " and has peak " << *peak << "." << endl;
     1230            // normal vector of triangle
     1231            BTS->GetNormalVector(NormalVector);
     1232            *out << Verbose(4) << "NormalVector of base triangle is ";
     1233            NormalVector.Output(out);
     1234            *out << endl;
     1235            // offset to center of triangle
     1236            CenterVector.Zero();
     1237            for (int i = 0; i < 3; i++)
     1238              CenterVector.AddVector(&BTS->endpoints[i]->node->x);
     1239            CenterVector.Scale(1. / 3.);
     1240            *out << Verbose(4) << "CenterVector of base triangle is ";
     1241            CenterVector.Output(out);
     1242            *out << endl;
     1243            // vector in propagation direction (out of triangle)
     1244            // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     1245            TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     1246            TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
     1247            PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
     1248            TempVector.CopyVector(&CenterVector);
     1249            TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
     1250            //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
     1251            if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
     1252              PropagationVector.Scale(-1.);
     1253            *out << Verbose(4) << "PropagationVector of base triangle is ";
     1254            PropagationVector.Output(out);
     1255            *out << endl;
     1256            winner = PointsOnBoundary.end();
     1257            for (PointMap::iterator target = PointsOnBoundary.begin(); target
     1258                != PointsOnBoundary.end(); target++)
     1259              if ((target->second != baseline->second->endpoints[0])
     1260                  && (target->second != baseline->second->endpoints[1]))
     1261                { // don't take the same endpoints
     1262                  *out << Verbose(3) << "Target point is " << *(target->second)
     1263                      << ":";
     1264                  bool continueflag = true;
     1265
     1266                  VirtualNormalVector.CopyVector(
     1267                      &baseline->second->endpoints[0]->node->x);
     1268                  VirtualNormalVector.AddVector(
     1269                      &baseline->second->endpoints[0]->node->x);
     1270                  VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
     1271                  VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
     1272                  TempAngle = VirtualNormalVector.Angle(&PropagationVector);
     1273                  continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
     1274                  if (!continueflag)
     1275                    {
     1276                      *out << Verbose(4)
     1277                          << "Angle between propagation direction and base line to "
     1278                          << *(target->second) << " is " << TempAngle
     1279                          << ", bad direction!" << endl;
     1280                      continue;
     1281                    }
     1282                  else
     1283                    *out << Verbose(4)
     1284                        << "Angle between propagation direction and base line to "
     1285                        << *(target->second) << " is " << TempAngle
     1286                        << ", good direction!" << endl;
     1287                  LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1288                      target->first);
     1289                  LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1290                      target->first);
     1291                  //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
     1292                  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     1293                  //            else
     1294                  //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1295                  //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
     1296                  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     1297                  //            else
     1298                  //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
     1299                  // check first endpoint (if any connecting line goes to target or at least not more than 1)
     1300                  continueflag = continueflag && (((LineChecker[0]
     1301                      == baseline->second->endpoints[0]->lines.end())
     1302                      || (LineChecker[0]->second->TrianglesCount == 1)));
     1303                  if (!continueflag)
     1304                    {
     1305                      *out << Verbose(4) << *(baseline->second->endpoints[0])
     1306                          << " has line " << *(LineChecker[0]->second)
     1307                          << " to " << *(target->second)
     1308                          << " as endpoint with "
     1309                          << LineChecker[0]->second->TrianglesCount
     1310                          << " triangles." << endl;
     1311                      continue;
     1312                    }
     1313                  // check second endpoint (if any connecting line goes to target or at least not more than 1)
     1314                  continueflag = continueflag && (((LineChecker[1]
     1315                      == baseline->second->endpoints[1]->lines.end())
     1316                      || (LineChecker[1]->second->TrianglesCount == 1)));
     1317                  if (!continueflag)
     1318                    {
     1319                      *out << Verbose(4) << *(baseline->second->endpoints[1])
     1320                          << " has line " << *(LineChecker[1]->second)
     1321                          << " to " << *(target->second)
     1322                          << " as endpoint with "
     1323                          << LineChecker[1]->second->TrianglesCount
     1324                          << " triangles." << endl;
     1325                      continue;
     1326                    }
     1327                  // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
     1328                  continueflag = continueflag && (!(((LineChecker[0]
     1329                      != baseline->second->endpoints[0]->lines.end())
     1330                      && (LineChecker[1]
     1331                          != baseline->second->endpoints[1]->lines.end())
     1332                      && (GetCommonEndpoint(LineChecker[0]->second,
     1333                          LineChecker[1]->second) == peak))));
     1334                  if (!continueflag)
     1335                    {
     1336                      *out << Verbose(4) << "Current target is peak!" << endl;
     1337                      continue;
     1338                    }
     1339                  // in case NOT both were found
     1340                  if (continueflag)
     1341                    { // create virtually this triangle, get its normal vector, calculate angle
     1342                      flag = true;
     1343                      VirtualNormalVector.MakeNormalVector(
     1344                          &baseline->second->endpoints[0]->node->x,
     1345                          &baseline->second->endpoints[1]->node->x,
     1346                          &target->second->node->x);
     1347                      // make it always point inward
     1348                      if (baseline->second->endpoints[0]->node->x.Projection(
     1349                          &VirtualNormalVector) > 0)
     1350                        VirtualNormalVector.Scale(-1.);
     1351                      // calculate angle
     1352                      TempAngle = NormalVector.Angle(&VirtualNormalVector);
     1353                      *out << Verbose(4) << "NormalVector is ";
     1354                      VirtualNormalVector.Output(out);
     1355                      *out << " and the angle is " << TempAngle << "." << endl;
     1356                      if (SmallestAngle > TempAngle)
     1357                        { // set to new possible winner
     1358                          SmallestAngle = TempAngle;
     1359                          winner = target;
     1360                        }
     1361                    }
     1362                }
     1363            // 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
     1364            if (winner != PointsOnBoundary.end())
     1365              {
     1366                *out << Verbose(2) << "Winning target point is "
     1367                    << *(winner->second) << " with angle " << SmallestAngle
     1368                    << "." << endl;
     1369                // create the lins of not yet present
     1370                BLS[0] = baseline->second;
     1371                // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
     1372                LineChecker[0] = baseline->second->endpoints[0]->lines.find(
     1373                    winner->first);
     1374                LineChecker[1] = baseline->second->endpoints[1]->lines.find(
     1375                    winner->first);
     1376                if (LineChecker[0]
     1377                    == baseline->second->endpoints[0]->lines.end())
     1378                  { // create
     1379                    BPS[0] = baseline->second->endpoints[0];
     1380                    BPS[1] = winner->second;
     1381                    BLS[1] = new class BoundaryLineSet(BPS,
     1382                        LinesOnBoundaryCount);
     1383                    LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1384                        BLS[1]));
     1385                    LinesOnBoundaryCount++;
     1386                  }
     1387                else
     1388                  BLS[1] = LineChecker[0]->second;
     1389                if (LineChecker[1]
     1390                    == baseline->second->endpoints[1]->lines.end())
     1391                  { // create
     1392                    BPS[0] = baseline->second->endpoints[1];
     1393                    BPS[1] = winner->second;
     1394                    BLS[2] = new class BoundaryLineSet(BPS,
     1395                        LinesOnBoundaryCount);
     1396                    LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
     1397                        BLS[2]));
     1398                    LinesOnBoundaryCount++;
     1399                  }
     1400                else
     1401                  BLS[2] = LineChecker[1]->second;
     1402                BTS = new class BoundaryTriangleSet(BLS,
     1403                    TrianglesOnBoundaryCount);
     1404                TrianglesOnBoundary.insert(TrianglePair(
     1405                    TrianglesOnBoundaryCount, BTS));
     1406                TrianglesOnBoundaryCount++;
     1407              }
     1408            else
     1409              {
     1410                *out << Verbose(1)
     1411                    << "I could not determine a winner for this baseline "
     1412                    << *(baseline->second) << "." << endl;
     1413              }
     1414
     1415            // 5d. If the set of lines is not yet empty, go to 5. and continue
     1416          }
     1417        else
     1418          *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
     1419              << " has a triangle count of "
     1420              << baseline->second->TrianglesCount << "." << endl;
     1421    }
     1422  while (flag);
    14231423
    14241424}
     
    14311431Tesselation::AddPoint(atom *Walker)
    14321432{
    1433         PointTestPair InsertUnique;
    1434         BPS[0] = new class BoundaryPointSet(Walker);
    1435         InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1436         if (InsertUnique.second) // if new point was not present before, increase counter
    1437                 PointsOnBoundaryCount++;
     1433  PointTestPair InsertUnique;
     1434  BPS[0] = new class BoundaryPointSet(Walker);
     1435  InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
     1436  if (InsertUnique.second) // if new point was not present before, increase counter
     1437    PointsOnBoundaryCount++;
    14381438}
    14391439;
     
    14471447Tesselation::AddTrianglePoint(atom* Candidate, int n)
    14481448{
    1449         PointTestPair InsertUnique;
    1450         TPS[n] = new class BoundaryPointSet(Candidate);
    1451         InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
    1452         if (InsertUnique.second) // if new point was not present before, increase counter
    1453                 {
    1454                         PointsOnBoundaryCount++;
    1455                 }
    1456         else
    1457                 {
    1458                         delete TPS[n];
    1459                         cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
    1460                                         << " gibt's schon in der PointMap." << endl;
    1461                         TPS[n] = (InsertUnique.first)->second;
    1462                 }
     1449  PointTestPair InsertUnique;
     1450  TPS[n] = new class BoundaryPointSet(Candidate);
     1451  InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
     1452  if (InsertUnique.second) // if new point was not present before, increase counter
     1453    {
     1454      PointsOnBoundaryCount++;
     1455    }
     1456  else
     1457    {
     1458      delete TPS[n];
     1459      cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
     1460          << " gibt's schon in der PointMap." << endl;
     1461      TPS[n] = (InsertUnique.first)->second;
     1462    }
    14631463}
    14641464;
     
    14731473void
    14741474Tesselation::AddTriangleLine(class BoundaryPointSet *a,
    1475                 class BoundaryPointSet *b, int n)
    1476 {
    1477         LineMap::iterator LineWalker;
    1478         //cout << "Manually checking endpoints for line." << endl;
    1479         if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr)
    1480         //If a line is there, how do I recognize that beyond a shadow of a doubt?
    1481                 {
    1482                         //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
    1483 
    1484                         LineWalker = LinesOnBoundary.end();
    1485                         LineWalker--;
    1486 
    1487                         while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
    1488                                         b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
    1489                                         a->node->nr, b->node->nr))
    1490                                 {
    1491                                         //cout << Verbose(1) << "Looking for line which already exists"<< endl;
    1492                                         LineWalker--;
    1493                                 }
    1494                         BPS[0] = LineWalker->second->endpoints[0];
    1495                         BPS[1] = LineWalker->second->endpoints[1];
    1496                         BLS[n] = LineWalker->second;
    1497 
    1498                 }
    1499         else
    1500                 {
    1501                         cout << Verbose(2)
    1502                                         << "Adding line which has not been used before between "
    1503                                         << *(a->node) << " and " << *(b->node) << "." << endl;
    1504                         BPS[0] = a;
    1505                         BPS[1] = b;
    1506                         BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1507 
    1508                         LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
    1509                         LinesOnBoundaryCount++;
    1510 
    1511                 }
     1475    class BoundaryPointSet *b, int n)
     1476{
     1477  LineMap::iterator LineWalker;
     1478  //cout << "Manually checking endpoints for line." << endl;
     1479  if ((a->lines.find(b->node->nr)) != a->lines.end()) // ->first == b->node->nr)
     1480  //If a line is there, how do I recognize that beyond a shadow of a doubt?
     1481    {
     1482      //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
     1483
     1484      LineWalker = LinesOnBoundary.end();
     1485      LineWalker--;
     1486
     1487      while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
     1488          b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
     1489          a->node->nr, b->node->nr))
     1490        {
     1491          //cout << Verbose(1) << "Looking for line which already exists"<< endl;
     1492          LineWalker--;
     1493        }
     1494      BPS[0] = LineWalker->second->endpoints[0];
     1495      BPS[1] = LineWalker->second->endpoints[1];
     1496      BLS[n] = LineWalker->second;
     1497
     1498    }
     1499  else
     1500    {
     1501      cout << Verbose(2)
     1502          << "Adding line which has not been used before between "
     1503          << *(a->node) << " and " << *(b->node) << "." << endl;
     1504      BPS[0] = a;
     1505      BPS[1] = b;
     1506      BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1507
     1508      LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
     1509      LinesOnBoundaryCount++;
     1510
     1511    }
    15121512}
    15131513;
     
    15201520{
    15211521
    1522         cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1523         TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1524         TrianglesOnBoundaryCount++;
    1525 
    1526         /*
    1527         * this is apparently done when constructing triangle
    1528 
    1529         for (i=0; i<3; i++)
    1530         {
    1531         BLS[i]->AddTriangle(BTS);
    1532         }
    1533         */
     1522  cout << Verbose(1) << "Adding triangle to its lines" << endl;
     1523  TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1524  TrianglesOnBoundaryCount++;
     1525
     1526  /*
     1527  * this is apparently done when constructing triangle
     1528
     1529  for (i=0; i<3; i++)
     1530  {
     1531  BLS[i]->AddTriangle(BTS);
     1532  }
     1533  */
    15341534}
    15351535;
     
    15371537
    15381538double det_get(gsl_matrix *A, int inPlace) {
    1539         /*
    1540         inPlace = 1 => A is replaced with the LU decomposed copy.
    1541         inPlace = 0 => A is retained, and a copy is used for LU.
    1542         */
    1543 
    1544         double det;
    1545         int signum;
    1546         gsl_permutation *p = gsl_permutation_alloc(A->size1);
    1547         gsl_matrix *tmpA;
    1548 
    1549         if (inPlace)
    1550         tmpA = A;
    1551         else {
    1552         gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
    1553         gsl_matrix_memcpy(tmpA , A);
    1554         }
    1555 
    1556 
    1557         gsl_linalg_LU_decomp(tmpA , p , &signum);
    1558         det = gsl_linalg_LU_det(tmpA , signum);
    1559         gsl_permutation_free(p);
    1560         if (! inPlace)
    1561         gsl_matrix_free(tmpA);
    1562 
    1563         return det;
     1539  /*
     1540  inPlace = 1 => A is replaced with the LU decomposed copy.
     1541  inPlace = 0 => A is retained, and a copy is used for LU.
     1542  */
     1543
     1544  double det;
     1545  int signum;
     1546  gsl_permutation *p = gsl_permutation_alloc(A->size1);
     1547  gsl_matrix *tmpA;
     1548
     1549  if (inPlace)
     1550  tmpA = A;
     1551  else {
     1552  gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
     1553  gsl_matrix_memcpy(tmpA , A);
     1554  }
     1555
     1556
     1557  gsl_linalg_LU_decomp(tmpA , p , &signum);
     1558  det = gsl_linalg_LU_det(tmpA , signum);
     1559  gsl_permutation_free(p);
     1560  if (! inPlace)
     1561  gsl_matrix_free(tmpA);
     1562
     1563  return det;
    15641564};
    15651565
    15661566void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
    15671567{
    1568         gsl_matrix *A = gsl_matrix_calloc(3,3);
    1569         double m11, m12, m13, m14;
    1570 
    1571         for(int i=0;i<3;i++) {
    1572                 gsl_matrix_set(A, i, 0, a.x[i]);
    1573                 gsl_matrix_set(A, i, 1, b.x[i]);
    1574                 gsl_matrix_set(A, i, 2, c.x[i]);
    1575         }
    1576         m11 = det_get(A, 1);
    1577 
    1578         for(int i=0;i<3;i++) {
    1579                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1580                 gsl_matrix_set(A, i, 1, b.x[i]);
    1581                 gsl_matrix_set(A, i, 2, c.x[i]);
    1582         }
    1583         m12 = det_get(A, 1);
    1584 
    1585         for(int i=0;i<3;i++) {
    1586                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1587                 gsl_matrix_set(A, i, 1, a.x[i]);
    1588                 gsl_matrix_set(A, i, 2, c.x[i]);
    1589         }
    1590         m13 = det_get(A, 1);
    1591 
    1592         for(int i=0;i<3;i++) {
    1593                 gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
    1594                 gsl_matrix_set(A, i, 1, a.x[i]);
    1595                 gsl_matrix_set(A, i, 2, b.x[i]);
    1596         }
    1597         m14 = det_get(A, 1);
    1598 
    1599         if (fabs(m11) < MYEPSILON)
    1600                 cerr << "ERROR: three points are colinear." << endl;
    1601 
    1602         center->x[0] =  0.5 * m12/ m11;
    1603         center->x[1] = -0.5 * m13/ m11;
    1604         center->x[2] =  0.5 * m14/ m11;
    1605 
    1606         if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
    1607                 cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
    1608 
    1609         gsl_matrix_free(A);
     1568  gsl_matrix *A = gsl_matrix_calloc(3,3);
     1569  double m11, m12, m13, m14;
     1570
     1571  for(int i=0;i<3;i++) {
     1572    gsl_matrix_set(A, i, 0, a.x[i]);
     1573    gsl_matrix_set(A, i, 1, b.x[i]);
     1574    gsl_matrix_set(A, i, 2, c.x[i]);
     1575  }
     1576  m11 = det_get(A, 1);
     1577
     1578  for(int i=0;i<3;i++) {
     1579    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1580    gsl_matrix_set(A, i, 1, b.x[i]);
     1581    gsl_matrix_set(A, i, 2, c.x[i]);
     1582  }
     1583  m12 = det_get(A, 1);
     1584
     1585  for(int i=0;i<3;i++) {
     1586    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1587    gsl_matrix_set(A, i, 1, a.x[i]);
     1588    gsl_matrix_set(A, i, 2, c.x[i]);
     1589  }
     1590  m13 = det_get(A, 1);
     1591
     1592  for(int i=0;i<3;i++) {
     1593    gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1594    gsl_matrix_set(A, i, 1, a.x[i]);
     1595    gsl_matrix_set(A, i, 2, b.x[i]);
     1596  }
     1597  m14 = det_get(A, 1);
     1598
     1599  if (fabs(m11) < MYEPSILON)
     1600    cerr << "ERROR: three points are colinear." << endl;
     1601
     1602  center->x[0] =  0.5 * m12/ m11;
     1603  center->x[1] = -0.5 * m13/ m11;
     1604  center->x[2] =  0.5 * m14/ m11;
     1605
     1606  if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
     1607    cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
     1608
     1609  gsl_matrix_free(A);
    16101610};
    16111611
     
    16291629 */
    16301630void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
    1631                 double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1632 {
    1633         Vector TempNormal, helper;
    1634         double Restradius;
    1635         Vector OtherCenter;
    1636         cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
    1637         Center->Zero();
    1638         helper.CopyVector(&a);
    1639         helper.Scale(sin(2.*alpha));
    1640         Center->AddVector(&helper);
    1641         helper.CopyVector(&b);
    1642         helper.Scale(sin(2.*beta));
    1643         Center->AddVector(&helper);
    1644         helper.CopyVector(&c);
    1645         helper.Scale(sin(2.*gamma));
    1646         Center->AddVector(&helper);
    1647         //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1648         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1649         NewUmkreismittelpunkt->CopyVector(Center);
    1650         cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
    1651         // Here we calculated center of circumscribing circle, using barycentric coordinates
    1652         cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
    1653 
    1654         TempNormal.CopyVector(&a);
    1655         TempNormal.SubtractVector(&b);
    1656         helper.CopyVector(&a);
    1657         helper.SubtractVector(&c);
    1658         TempNormal.VectorProduct(&helper);
    1659         if (fabs(HalfplaneIndicator) < MYEPSILON)
    1660                 {
    1661                         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1662                                 {
    1663                                         TempNormal.Scale(-1);
    1664                                 }
    1665                 }
    1666         else
    1667                 {
    1668                         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1669                                 {
    1670                                         TempNormal.Scale(-1);
    1671                                 }
    1672                 }
    1673 
    1674         TempNormal.Normalize();
    1675         Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1676         cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
    1677         TempNormal.Scale(Restradius);
    1678         cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
    1679 
    1680         Center->AddVector(&TempNormal);
    1681         cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
    1682         get_sphere(&OtherCenter, a, b, c, RADIUS);
    1683         cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
    1684         cout << Verbose(3) << "End of Get_center_of_sphere.\n";
     1631    double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
     1632{
     1633  Vector TempNormal, helper;
     1634  double Restradius;
     1635  Vector OtherCenter;
     1636  cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
     1637  Center->Zero();
     1638  helper.CopyVector(&a);
     1639  helper.Scale(sin(2.*alpha));
     1640  Center->AddVector(&helper);
     1641  helper.CopyVector(&b);
     1642  helper.Scale(sin(2.*beta));
     1643  Center->AddVector(&helper);
     1644  helper.CopyVector(&c);
     1645  helper.Scale(sin(2.*gamma));
     1646  Center->AddVector(&helper);
     1647  //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
     1648  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1649  NewUmkreismittelpunkt->CopyVector(Center);
     1650  cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
     1651  // Here we calculated center of circumscribing circle, using barycentric coordinates
     1652  cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
     1653
     1654  TempNormal.CopyVector(&a);
     1655  TempNormal.SubtractVector(&b);
     1656  helper.CopyVector(&a);
     1657  helper.SubtractVector(&c);
     1658  TempNormal.VectorProduct(&helper);
     1659  if (fabs(HalfplaneIndicator) < MYEPSILON)
     1660    {
     1661      if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
     1662        {
     1663          TempNormal.Scale(-1);
     1664        }
     1665    }
     1666  else
     1667    {
     1668      if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
     1669        {
     1670          TempNormal.Scale(-1);
     1671        }
     1672    }
     1673
     1674  TempNormal.Normalize();
     1675  Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
     1676  cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
     1677  TempNormal.Scale(Restradius);
     1678  cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
     1679
     1680  Center->AddVector(&TempNormal);
     1681  cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
     1682  get_sphere(&OtherCenter, a, b, c, RADIUS);
     1683  cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
     1684  cout << Verbose(3) << "End of Get_center_of_sphere.\n";
    16851685};
    16861686
    16871687/** This recursive function finds a third point, to form a triangle with two given ones.
    16881688 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1689  *      supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1690  *      upon which we operate.
    1691  *      If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1692  *      direction and angle into Storage.
    1693  *      We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1694  *      with all neighbours of the candidate.
     1689 *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
     1690 *  upon which we operate.
     1691 *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
     1692 *  direction and angle into Storage.
     1693 *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
     1694 *  with all neighbours of the candidate.
    16951695 * @param a first point
    16961696 * @param b second point
     
    17091709 */
    17101710void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1711                 int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1712                 atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1713 {
    1714         cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    1715         cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
    1716         cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
    1717         cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
    1718         cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
    1719         cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
    1720         /* OldNormal is normal vector on the old triangle
    1721         * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1722         * Chord points from b to a!!!
    1723         */
    1724         Vector dif_a; //Vector from a to candidate
    1725         Vector dif_b; //Vector from b to candidate
    1726         Vector AngleCheck;
    1727         Vector TempNormal, Umkreismittelpunkt;
    1728         Vector Mittelpunkt;
    1729 
    1730         double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius;
    1731         double BallAngle, AlternativeSign;
    1732         atom *Walker; // variable atom point
    1733 
    1734         Vector NewUmkreismittelpunkt;
    1735 
    1736         if (a != Candidate and b != Candidate and c != Candidate) {
    1737                 cout << Verbose(3) << "We have a unique candidate!" << endl;
    1738                 dif_a.CopyVector(&(a->x));
    1739                 dif_a.SubtractVector(&(Candidate->x));
    1740                 dif_b.CopyVector(&(b->x));
    1741                 dif_b.SubtractVector(&(Candidate->x));
    1742                 AngleCheck.CopyVector(&(Candidate->x));
    1743                 AngleCheck.SubtractVector(&(a->x));
    1744                 AngleCheck.ProjectOntoPlane(Chord);
    1745 
    1746                 SideA = dif_b.Norm();
    1747                 SideB = dif_a.Norm();
    1748                 SideC = Chord->Norm();
    1749                 //Chord->Scale(-1);
    1750 
    1751                 alpha = Chord->Angle(&dif_a);
    1752                 beta = M_PI - Chord->Angle(&dif_b);
    1753                 gamma = dif_a.Angle(&dif_b);
    1754 
    1755                 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;
    1756 
    1757                 if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
    1758                         cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
    1759                         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;
    1760                 }
    1761 
    1762                 if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
    1763                         Umkreisradius = SideA / 2.0 / sin(alpha);
    1764                         //cout << Umkreisradius << endl;
    1765                         //cout << SideB / 2.0 / sin(beta) << endl;
    1766                         //cout << SideC / 2.0 / sin(gamma) << endl;
    1767 
    1768                         if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
    1769                                 cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
    1770                                 cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
    1771                                 sign = AngleCheck.ScalarProduct(direction1);
    1772                                 if (fabs(sign)<MYEPSILON) {
    1773                                         if (AngleCheck.ScalarProduct(OldNormal)<0) {
    1774                                                 sign =0;
    1775                                                 AlternativeSign=1;
    1776                                         } else {
    1777                                                 sign =0;
    1778                                                 AlternativeSign=-1;
    1779                                         }
    1780                                 } else {
    1781                                         sign /= fabs(sign);
    1782                                 }
    1783                                 if (sign >= 0) {
    1784                                         cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
    1785                                         Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1786                                         Mittelpunkt.SubtractVector(&ReferencePoint);
    1787                                         cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
    1788                                         BallAngle = Mittelpunkt.Angle(OldNormal);
    1789                                         cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
    1790 
    1791                                         //cout << "direction1 is " << *direction1 << "." << endl;
    1792                                         //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
    1793                                         //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1794 
    1795                                         NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
    1796 
    1797                                         if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
    1798                                                 if (Storage[0]< -1.5) { // first Candidate at all
    1799                                                         if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1800                                                                 cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
    1801                                                                 Opt_Candidate = Candidate;
    1802                                                                 Storage[0] = sign;
    1803                                                                 Storage[1] = AlternativeSign;
    1804                                                                 Storage[2] = BallAngle;
    1805                                                                 cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1806                                                         } else
    1807                                                                 cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1808                                                 } else {
    1809                                                         if ( Storage[2] > BallAngle) {
    1810                                                                 if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
    1811                                                                         cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
    1812                                                                         Opt_Candidate = Candidate;
    1813                                                                         Storage[0] = sign;
    1814                                                                         Storage[1] = AlternativeSign;
    1815                                                                         Storage[2] = BallAngle;
    1816                                                                         cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
    1817                                                                 } else
    1818                                                                         cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
    1819                                                         } else {
    1820                                                                 if (DEBUG) {
    1821                                                                         cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
    1822                                                                 }
    1823                                                         }
    1824                                                 }
    1825                                         } else {
    1826                                                 if (DEBUG) {
    1827                                                         cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
    1828                                                 }
    1829                                         }
    1830                                 } else {
    1831                                         if (DEBUG) {
    1832                                                 cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
    1833                                         }
    1834                                 }
    1835                         } else {
    1836                                 if (DEBUG) {
    1837                                         cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
    1838                                 }
    1839                         }
    1840                 } else {
    1841                         if (DEBUG) {
    1842                                 cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
    1843                         }
    1844                 }
    1845         } else {
    1846                 if (DEBUG) {
    1847                         cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
    1848                 }
    1849         }
    1850 
    1851         if (RecursionLevel < 5) { // Seven is the recursion level threshold.
    1852                 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
    1853                         Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
    1854                         if (Walker == Parent) { // don't go back the same bond
    1855                                 continue;
    1856                         } else {
    1857                                 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
    1858                         }
    1859                 }
    1860         }
    1861         cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1711    int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
     1712    atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
     1713{
     1714  cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1715  cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
     1716  cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
     1717  cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
     1718  cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
     1719  cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
     1720  /* OldNormal is normal vector on the old triangle
     1721  * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
     1722  * Chord points from b to a!!!
     1723  */
     1724  Vector dif_a; //Vector from a to candidate
     1725  Vector dif_b; //Vector from b to candidate
     1726  Vector AngleCheck;
     1727  Vector TempNormal, Umkreismittelpunkt;
     1728  Vector Mittelpunkt;
     1729
     1730  double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius;
     1731  double BallAngle, AlternativeSign;
     1732  atom *Walker; // variable atom point
     1733
     1734  Vector NewUmkreismittelpunkt;
     1735
     1736  if (a != Candidate and b != Candidate and c != Candidate) {
     1737    cout << Verbose(3) << "We have a unique candidate!" << endl;
     1738    dif_a.CopyVector(&(a->x));
     1739    dif_a.SubtractVector(&(Candidate->x));
     1740    dif_b.CopyVector(&(b->x));
     1741    dif_b.SubtractVector(&(Candidate->x));
     1742    AngleCheck.CopyVector(&(Candidate->x));
     1743    AngleCheck.SubtractVector(&(a->x));
     1744    AngleCheck.ProjectOntoPlane(Chord);
     1745
     1746    SideA = dif_b.Norm();
     1747    SideB = dif_a.Norm();
     1748    SideC = Chord->Norm();
     1749    //Chord->Scale(-1);
     1750
     1751    alpha = Chord->Angle(&dif_a);
     1752    beta = M_PI - Chord->Angle(&dif_b);
     1753    gamma = dif_a.Angle(&dif_b);
     1754
     1755    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;
     1756
     1757    if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
     1758      cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
     1759      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;
     1760    }
     1761
     1762    if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
     1763      Umkreisradius = SideA / 2.0 / sin(alpha);
     1764      //cout << Umkreisradius << endl;
     1765      //cout << SideB / 2.0 / sin(beta) << endl;
     1766      //cout << SideC / 2.0 / sin(gamma) << endl;
     1767
     1768      if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
     1769        cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
     1770        cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
     1771        sign = AngleCheck.ScalarProduct(direction1);
     1772        if (fabs(sign)<MYEPSILON) {
     1773          if (AngleCheck.ScalarProduct(OldNormal)<0) {
     1774            sign =0;
     1775            AlternativeSign=1;
     1776          } else {
     1777            sign =0;
     1778            AlternativeSign=-1;
     1779          }
     1780        } else {
     1781          sign /= fabs(sign);
     1782        }
     1783        if (sign >= 0) {
     1784          cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1785          Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
     1786          Mittelpunkt.SubtractVector(&ReferencePoint);
     1787          cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
     1788          BallAngle = Mittelpunkt.Angle(OldNormal);
     1789          cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
     1790
     1791          //cout << "direction1 is " << *direction1 << "." << endl;
     1792          //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
     1793          //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
     1794
     1795          NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
     1796
     1797          if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
     1798            if (Storage[0]< -1.5) { // first Candidate at all
     1799              if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1800                cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
     1801                Opt_Candidate = Candidate;
     1802                Storage[0] = sign;
     1803                Storage[1] = AlternativeSign;
     1804                Storage[2] = BallAngle;
     1805                cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1806              } else
     1807                cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1808            } else {
     1809              if ( Storage[2] > BallAngle) {
     1810                if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1811                  cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
     1812                  Opt_Candidate = Candidate;
     1813                  Storage[0] = sign;
     1814                  Storage[1] = AlternativeSign;
     1815                  Storage[2] = BallAngle;
     1816                  cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1817                } else
     1818                  cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1819              } else {
     1820                if (DEBUG) {
     1821                  cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
     1822                }
     1823              }
     1824            }
     1825          } else {
     1826            if (DEBUG) {
     1827              cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
     1828            }
     1829          }
     1830        } else {
     1831          if (DEBUG) {
     1832            cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
     1833          }
     1834        }
     1835      } else {
     1836        if (DEBUG) {
     1837          cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
     1838        }
     1839      }
     1840    } else {
     1841      if (DEBUG) {
     1842        cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
     1843      }
     1844    }
     1845  } else {
     1846    if (DEBUG) {
     1847      cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
     1848    }
     1849  }
     1850
     1851  if (RecursionLevel < 5) { // Seven is the recursion level threshold.
     1852    for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
     1853      Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
     1854      if (Walker == Parent) { // don't go back the same bond
     1855        continue;
     1856      } else {
     1857        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
     1858      }
     1859    }
     1860  }
     1861  cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
    18621862}
    18631863;
     
    18721872void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
    18731873{
    1874         Vector helper;
    1875         double alpha, beta, gamma;
    1876         Vector SideA, SideB, SideC;
    1877         SideA.CopyVector(b);
    1878         SideA.SubtractVector(c);
    1879         SideB.CopyVector(c);
    1880         SideB.SubtractVector(a);
    1881         SideC.CopyVector(a);
    1882         SideC.SubtractVector(b);
    1883         alpha = M_PI - SideB.Angle(&SideC);
    1884         beta = M_PI - SideC.Angle(&SideA);
    1885         gamma = M_PI - SideA.Angle(&SideB);
    1886         cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
    1887         if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
    1888                 cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
    1889 
    1890         Center->Zero();
    1891         helper.CopyVector(a);
    1892         helper.Scale(sin(2.*alpha));
    1893         Center->AddVector(&helper);
    1894         helper.CopyVector(b);
    1895         helper.Scale(sin(2.*beta));
    1896         Center->AddVector(&helper);
    1897         helper.CopyVector(c);
    1898         helper.Scale(sin(2.*gamma));
    1899         Center->AddVector(&helper);
    1900         Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1874  Vector helper;
     1875  double alpha, beta, gamma;
     1876  Vector SideA, SideB, SideC;
     1877  SideA.CopyVector(b);
     1878  SideA.SubtractVector(c);
     1879  SideB.CopyVector(c);
     1880  SideB.SubtractVector(a);
     1881  SideC.CopyVector(a);
     1882  SideC.SubtractVector(b);
     1883  alpha = M_PI - SideB.Angle(&SideC);
     1884  beta = M_PI - SideC.Angle(&SideA);
     1885  gamma = M_PI - SideA.Angle(&SideB);
     1886  cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
     1887  if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
     1888    cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
     1889
     1890  Center->Zero();
     1891  helper.CopyVector(a);
     1892  helper.Scale(sin(2.*alpha));
     1893  Center->AddVector(&helper);
     1894  helper.CopyVector(b);
     1895  helper.Scale(sin(2.*beta));
     1896  Center->AddVector(&helper);
     1897  helper.CopyVector(c);
     1898  helper.Scale(sin(2.*gamma));
     1899  Center->AddVector(&helper);
     1900  Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    19011901};
    19021902
     
    19161916double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
    19171917{
    1918         Vector helper;
    1919         double radius, alpha;
    1920 
    1921         helper.CopyVector(&NewSphereCenter);
    1922         // test whether new center is on the parameter circle's plane
    1923         if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    1924                 cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))        << "!" << endl;
    1925                 helper.ProjectOntoPlane(&CirclePlaneNormal);
    1926         }
    1927         radius = helper.ScalarProduct(&helper);
    1928         // test whether the new center vector has length of CircleRadius
    1929         if (fabs(radius - CircleRadius) > HULLEPSILON)
    1930                 cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    1931         alpha = helper.Angle(&OldSphereCenter);
    1932         // make the angle unique by checking the halfplanes/search direction
    1933         if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
    1934                 alpha = 2.*M_PI - alpha;
    1935         cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
    1936         radius = helper.Distance(&OldSphereCenter);
    1937         helper.ProjectOntoPlane(&NormalVector);
    1938         // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
    1939         if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
    1940                 cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
    1941                 return alpha;
    1942         } else {
    1943                 cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
    1944                 return 2.*M_PI;
    1945         }
     1918  Vector helper;
     1919  double radius, alpha;
     1920
     1921  helper.CopyVector(&NewSphereCenter);
     1922  // test whether new center is on the parameter circle's plane
     1923  if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     1924    cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))  << "!" << endl;
     1925    helper.ProjectOntoPlane(&CirclePlaneNormal);
     1926  }
     1927  radius = helper.ScalarProduct(&helper);
     1928  // test whether the new center vector has length of CircleRadius
     1929  if (fabs(radius - CircleRadius) > HULLEPSILON)
     1930    cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     1931  alpha = helper.Angle(&OldSphereCenter);
     1932  // make the angle unique by checking the halfplanes/search direction
     1933  if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
     1934    alpha = 2.*M_PI - alpha;
     1935  cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     1936  radius = helper.Distance(&OldSphereCenter);
     1937  helper.ProjectOntoPlane(&NormalVector);
     1938  // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
     1939  if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
     1940    cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     1941    return alpha;
     1942  } else {
     1943    cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     1944    return 2.*M_PI;
     1945  }
    19461946};
    19471947
     
    19781978// void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
    19791979// {
    1980 //      atom *Walker = NULL;
    1981 //       Vector CircleCenter;   // center of the circle, i.e. of the band of sphere's centers
    1982 //      Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    1983 //       Vector OldSphereCenter;        // center of the sphere defined by the three points of BaseTriangle
    1984 //       Vector NewSphereCenter;        // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    1985 //       Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    1986 //       Vector NewNormalVector;        // normal vector of the Candidate's triangle
    1987 //       Vector SearchDirection;        // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
    1988 //      Vector helper;
    1989 //      LinkedAtoms *List = NULL;
    1990 //      double CircleRadius; // radius of this circle
    1991 //      double radius;
    1992 //      double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    1993 //      double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
    1994 //      int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    1995 //      atom *Candidate = NULL;
     1980//  atom *Walker = NULL;
     1981//   Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     1982//  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1983//   Vector OldSphereCenter;  // center of the sphere defined by the three points of BaseTriangle
     1984//   Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     1985//   Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     1986//   Vector NewNormalVector;  // normal vector of the Candidate's triangle
     1987//   Vector SearchDirection;  // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
     1988//  Vector helper;
     1989//  LinkedAtoms *List = NULL;
     1990//  double CircleRadius; // radius of this circle
     1991//  double radius;
     1992//  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     1993//  double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     1994//  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     1995//  atom *Candidate = NULL;
    19961996//
    1997 //      cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
     1997//  cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
    19981998//
    1999 //      cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
     1999//  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
    20002000//
    2001 //      // construct center of circle
    2002 //      CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2003 //      CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2004 //      CircleCenter.Scale(0.5);
     2001//  // construct center of circle
     2002//  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2003//  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2004//  CircleCenter.Scale(0.5);
    20052005//
    2006 //      // construct normal vector of circle
    2007 //      CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2008 //      CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2006//  // construct normal vector of circle
     2007//  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2008//  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    20092009//
    2010 //      // calculate squared radius of circle
    2011 //      radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2012 //      if (radius/4. < RADIUS*RADIUS) {
    2013 //              CircleRadius = RADIUS*RADIUS - radius/4.;
    2014 //              CirclePlaneNormal.Normalize();
    2015 //              cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2010//  // calculate squared radius of circle
     2011//  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2012//  if (radius/4. < RADIUS*RADIUS) {
     2013//    CircleRadius = RADIUS*RADIUS - radius/4.;
     2014//    CirclePlaneNormal.Normalize();
     2015//    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    20162016//
    2017 //              // construct old center
    2018 //              GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
    2019 //               helper.CopyVector(&BaseTriangle->NormalVector);        // normal vector ensures that this is correct center of the two possible ones
    2020 //              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2021 //              helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2022 //              OldSphereCenter.AddVector(&helper);
    2023 //              OldSphereCenter.SubtractVector(&CircleCenter);
    2024 //              cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2017//    // construct old center
     2018//    GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
     2019//     helper.CopyVector(&BaseTriangle->NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2020//    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2021//    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2022//    OldSphereCenter.AddVector(&helper);
     2023//    OldSphereCenter.SubtractVector(&CircleCenter);
     2024//    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    20252025//
    2026 //              // test whether old center is on the band's plane
    2027 //              if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2028 //                      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2029 //                      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2030 //              }
    2031 //              radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2032 //              if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2026//    // test whether old center is on the band's plane
     2027//    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2028//      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2029//      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2030//    }
     2031//    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2032//    if (fabs(radius - CircleRadius) < HULLEPSILON) {
    20332033//
    2034 //                      // construct SearchDirection
    2035 //                      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
    2036 //                      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
    2037 //                       for(int i=0;i<3;i++)   // just take next different endpoint
    2038 //                              if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
    2039 //                                      helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
    2040 //                              }
    2041 //                       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)     // ohoh, SearchDirection points inwards!
    2042 //                              SearchDirection.Scale(-1.);
    2043 //                      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2044 //                      SearchDirection.Normalize();
    2045 //                      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2046 //                       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {     // rotated the wrong way!
    2047 //                              cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2048 //                      }
     2034//      // construct SearchDirection
     2035//      SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
     2036//      helper.CopyVector(&BaseLine->endpoints[0]->node->x);
     2037//       for(int i=0;i<3;i++)  // just take next different endpoint
     2038//        if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
     2039//          helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
     2040//        }
     2041//       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2042//        SearchDirection.Scale(-1.);
     2043//      SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2044//      SearchDirection.Normalize();
     2045//      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2046//       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2047//        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2048//      }
    20492049//
    2050 //                       if (LC->SetIndexToVector(&CircleCenter)) {     // get cell for the starting atom
    2051 //                              for(int i=0;i<NDIM;i++) // store indices of this cell
    2052 //                                      N[i] = LC->n[i];
    2053 //                              cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2054 //                      } else {
    2055 //                              cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2056 //                              return;
    2057 //                      }
    2058 //                      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2059 //                      cout << Verbose(2) << "LC Intervals:";
    2060 //                      for (int i=0;i<NDIM;i++) {
    2061 //                              Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2062 //                              Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2063 //                              cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2064 //                      }
    2065 //                      cout << endl;
    2066 //                      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2067 //                              for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2068 //                                      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2069 //                                              List = LC->GetCurrentCell();
    2070 //                                              cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2071 //                                              if (List != NULL) {
    2072 //                                                      for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2073 //                                                              Candidate = (*Runner);
     2050//       if (LC->SetIndexToVector(&CircleCenter)) {  // get cell for the starting atom
     2051//        for(int i=0;i<NDIM;i++) // store indices of this cell
     2052//          N[i] = LC->n[i];
     2053//        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2054//      } else {
     2055//        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2056//        return;
     2057//      }
     2058//      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2059//      cout << Verbose(2) << "LC Intervals:";
     2060//      for (int i=0;i<NDIM;i++) {
     2061//        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2062//        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2063//        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2064//      }
     2065//      cout << endl;
     2066//      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2067//        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2068//          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2069//            List = LC->GetCurrentCell();
     2070//            cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2071//            if (List != NULL) {
     2072//              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2073//                Candidate = (*Runner);
    20742074//
    2075 //                                                              // check for three unique points
    2076 //                                                              if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
    2077 //                                                                      cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2075//                // check for three unique points
     2076//                if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
     2077//                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    20782078//
    2079 //                                                                      // construct both new centers
    2080 //                                                                      GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2081 //                                                                      OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2079//                  // construct both new centers
     2080//                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2081//                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    20822082//
    2083 //                                                                      if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2084 //                                                                              helper.CopyVector(&NewNormalVector);
    2085 //                                                                              cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2086 //                                                                              radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2087 //                                                                              if (radius < RADIUS*RADIUS) {
    2088 //                                                                                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2089 //                                                                                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2090 //                                                                                      NewSphereCenter.AddVector(&helper);
    2091 //                                                                                      NewSphereCenter.SubtractVector(&CircleCenter);
    2092 //                                                                                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2083//                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2084//                    helper.CopyVector(&NewNormalVector);
     2085//                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2086//                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2087//                    if (radius < RADIUS*RADIUS) {
     2088//                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2089//                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2090//                      NewSphereCenter.AddVector(&helper);
     2091//                      NewSphereCenter.SubtractVector(&CircleCenter);
     2092//                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    20932093//
    2094 //                                                                                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2095 //                                                                                      OtherNewSphereCenter.AddVector(&helper);
    2096 //                                                                                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2097 //                                                                                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2094//                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2095//                      OtherNewSphereCenter.AddVector(&helper);
     2096//                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2097//                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    20982098//
    2099 //                                                                                      // check both possible centers
    2100 //                                                                                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2101 //                                                                                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
    2102 //                                                                                      alpha = min(alpha, Otheralpha);
    2103 //                                                                                      if (*ShortestAngle > alpha) {
    2104 //                                                                                                      OptCandidate = Candidate;
    2105 //                                                                                                      *ShortestAngle = alpha;
    2106 //                                                                                                      if (alpha != Otheralpha)
    2107 //                                                                                                              OptCandidateCenter->CopyVector(&NewSphereCenter);
    2108 //                                                                                                      else
    2109 //                                                                                                              OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2110 //                                                                                                      cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2111 //                                                                                      } else {
    2112 //                                                                                              if (OptCandidate != NULL)
    2113 //                                                                                                      cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2114 //                                                                                              else
    2115 //                                                                                                      cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2116 //                                                                                      }
     2099//                      // check both possible centers
     2100//                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2101//                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2102//                      alpha = min(alpha, Otheralpha);
     2103//                      if (*ShortestAngle > alpha) {
     2104//                          OptCandidate = Candidate;
     2105//                          *ShortestAngle = alpha;
     2106//                          if (alpha != Otheralpha)
     2107//                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2108//                          else
     2109//                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2110//                          cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2111//                      } else {
     2112//                        if (OptCandidate != NULL)
     2113//                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2114//                        else
     2115//                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2116//                      }
    21172117//
    2118 //                                                                              } else {
    2119 //                                                                                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2120 //                                                                              }
    2121 //                                                                      } else {
    2122 //                                                                              cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2123 //                                                                      }
    2124 //                                                              } else {
    2125 //                                                                      cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
    2126 //                                                              }
    2127 //                                                      }
    2128 //                                              }
    2129 //                                      }
    2130 //              } else {
    2131 //                      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2132 //              }
    2133 //      } else {
    2134 //              cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
    2135 //      }
     2118//                    } else {
     2119//                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2120//                    }
     2121//                  } else {
     2122//                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2123//                  }
     2124//                } else {
     2125//                  cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
     2126//                }
     2127//              }
     2128//            }
     2129//          }
     2130//    } else {
     2131//      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2132//    }
     2133//  } else {
     2134//    cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
     2135//  }
    21362136//
    2137 //      cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
     2137//  cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
    21382138// };
    21392139
     
    21482148 */
    21492149bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
    2150         LineMap::iterator FindLine;
    2151         PointMap::iterator FindPoint;
    2152 
    2153         *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
    2154         for (int i=0;i<3;i++) { // check through all endpoints
    2155                 FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
    2156                 if (FindPoint != PointsOnBoundary.end())
    2157                         TPS[i] = FindPoint->second;
    2158                 else
    2159                         TPS[i] = NULL;
    2160         }
    2161 
    2162         // check lines
    2163         for (int i=0;i<3;i++)
    2164                 if (TPS[i] != NULL)
    2165                         for (int j=i;j<3;j++)
    2166                                 if (TPS[j] != NULL) {
    2167                                         FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
    2168                                         if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
    2169                                                 *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
    2170                                                 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2171                                                 return false;
    2172                                         }
    2173                                 }
    2174         *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    2175         return true;
     2150  LineMap::iterator FindLine;
     2151  PointMap::iterator FindPoint;
     2152
     2153  *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
     2154  for (int i=0;i<3;i++) { // check through all endpoints
     2155    FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     2156    if (FindPoint != PointsOnBoundary.end())
     2157      TPS[i] = FindPoint->second;
     2158    else
     2159      TPS[i] = NULL;
     2160  }
     2161
     2162  // check lines
     2163  for (int i=0;i<3;i++)
     2164    if (TPS[i] != NULL)
     2165      for (int j=i;j<3;j++)
     2166        if (TPS[j] != NULL) {
     2167          FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
     2168          if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
     2169            *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
     2170            *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2171            return false;
     2172          }
     2173        }
     2174  *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2175  return true;
    21762176};
    21772177
     
    22112211void Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, atom *ThirdNode, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
    22122212{
    2213         Vector CircleCenter;    // center of the circle, i.e. of the band of sphere's centers
    2214         Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    2215         Vector NewSphereCenter; // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    2216         Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    2217         Vector NewNormalVector; // normal vector of the Candidate's triangle
    2218         Vector helper;
    2219         LinkedAtoms *List = NULL;
    2220         double CircleRadius; // radius of this circle
    2221         double radius;
    2222         double alpha, Otheralpha; // angles (i.e. parameter for the circle).
    2223         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2224         atom *Candidate = NULL;
    2225 
    2226         cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
    2227 
    2228         cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    2229 
    2230         // construct center of circle
    2231         CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
    2232         CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
    2233         CircleCenter.Scale(0.5);
    2234 
    2235         // construct normal vector of circle
    2236         CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
    2237         CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
    2238 
    2239         // calculate squared radius of circle
    2240         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2241         if (radius/4. < RADIUS*RADIUS) {
    2242                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2243                 CirclePlaneNormal.Normalize();
    2244                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2245 
    2246                 // test whether old center is on the band's plane
    2247                 if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
    2248                         cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
    2249                         OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
    2250                 }
    2251                 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    2252                 if (fabs(radius - CircleRadius) < HULLEPSILON) {
    2253 
    2254                         // check SearchDirection
    2255                         cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2256                         if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2257                                 cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
    2258                         }
    2259                         // get cell for the starting atom
    2260                         if (LC->SetIndexToVector(&CircleCenter)) {
    2261                                         for(int i=0;i<NDIM;i++) // store indices of this cell
    2262                                         N[i] = LC->n[i];
    2263                                 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2264                         } else {
    2265                                 cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
    2266                                 return;
    2267                         }
    2268                         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2269                         cout << Verbose(2) << "LC Intervals:";
    2270                         for (int i=0;i<NDIM;i++) {
    2271                                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2272                                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2273                                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2274                         }
    2275                         cout << endl;
    2276                         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2277                                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2278                                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2279                                                 List = LC->GetCurrentCell();
    2280                                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2281                                                 if (List != NULL) {
    2282                                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2283                                                                 Candidate = (*Runner);
    2284 
    2285                                                                 // check for three unique points
    2286                                                                 if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
    2287                                                                         cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
    2288 
    2289                                                                         // construct both new centers
    2290                                                                         GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
    2291                                                                         OtherNewSphereCenter.CopyVector(&NewSphereCenter);
    2292 
    2293                                                                         if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
    2294                                                                                 helper.CopyVector(&NewNormalVector);
    2295                                                                                 cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
    2296                                                                                 radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
    2297                                                                                 if (radius < RADIUS*RADIUS) {
    2298                                                                                         helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2299                                                                                         cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
    2300                                                                                         NewSphereCenter.AddVector(&helper);
    2301                                                                                         NewSphereCenter.SubtractVector(&CircleCenter);
    2302                                                                                         cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
    2303 
    2304                                                                                         helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
    2305                                                                                         OtherNewSphereCenter.AddVector(&helper);
    2306                                                                                         OtherNewSphereCenter.SubtractVector(&CircleCenter);
    2307                                                                                         cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
    2308 
    2309                                                                                         // check both possible centers
    2310                                                                                         alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2311                                                                                         Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
    2312                                                                                         alpha = min(alpha, Otheralpha);
    2313                                                                                         if (*ShortestAngle > alpha) {
    2314                                                                                                         OptCandidate = Candidate;
    2315                                                                                                         *ShortestAngle = alpha;
    2316                                                                                                         if (alpha != Otheralpha)
    2317                                                                                                                 OptCandidateCenter->CopyVector(&NewSphereCenter);
    2318                                                                                                         else
    2319                                                                                                                 OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
    2320                                                                                                         cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
    2321                                                                                         } else {
    2322                                                                                                 if (OptCandidate != NULL)
    2323                                                                                                         cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
    2324                                                                                                 else
    2325                                                                                                         cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
    2326                                                                                         }
    2327 
    2328                                                                                 } else {
    2329                                                                                         cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
    2330                                                                                 }
    2331                                                                         } else {
    2332                                                                                 cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
    2333                                                                         }
    2334                                                                 } else {
    2335                                                                         if (ThirdNode != NULL)
    2336                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
    2337                                                                         else
    2338                                                                                 cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
    2339                                                                 }
    2340                                                         }
    2341                                                 }
    2342                                         }
    2343                 } else {
    2344                         cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
    2345                 }
    2346         } else {
    2347                 if (ThirdNode != NULL)
    2348                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
    2349                 else
    2350                         cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
    2351         }
    2352 
    2353         cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
     2213  Vector CircleCenter;  // center of the circle, i.e. of the band of sphere's centers
     2214  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     2215  Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2216  Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2217  Vector NewNormalVector;  // normal vector of the Candidate's triangle
     2218  Vector helper;
     2219  LinkedAtoms *List = NULL;
     2220  double CircleRadius; // radius of this circle
     2221  double radius;
     2222  double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2223  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2224  atom *Candidate = NULL;
     2225
     2226  cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
     2227
     2228  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2229
     2230  // construct center of circle
     2231  CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2232  CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2233  CircleCenter.Scale(0.5);
     2234
     2235  // construct normal vector of circle
     2236  CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2237  CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2238
     2239  // calculate squared radius of circle
     2240  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2241  if (radius/4. < RADIUS*RADIUS) {
     2242    CircleRadius = RADIUS*RADIUS - radius/4.;
     2243    CirclePlaneNormal.Normalize();
     2244    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2245
     2246    // test whether old center is on the band's plane
     2247    if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2248      cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2249      OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2250    }
     2251    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2252    if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2253
     2254      // check SearchDirection
     2255      cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2256      if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2257        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
     2258      }
     2259      // get cell for the starting atom
     2260      if (LC->SetIndexToVector(&CircleCenter)) {
     2261          for(int i=0;i<NDIM;i++) // store indices of this cell
     2262          N[i] = LC->n[i];
     2263        cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2264      } else {
     2265        cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2266        return;
     2267      }
     2268      // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2269      cout << Verbose(2) << "LC Intervals:";
     2270      for (int i=0;i<NDIM;i++) {
     2271        Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2272        Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2273        cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2274      }
     2275      cout << endl;
     2276      for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2277        for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2278          for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2279            List = LC->GetCurrentCell();
     2280            //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2281            if (List != NULL) {
     2282              for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2283                Candidate = (*Runner);
     2284
     2285                // check for three unique points
     2286                if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
     2287                  cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2288
     2289                  // construct both new centers
     2290                  GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2291                  OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2292
     2293                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2294                    helper.CopyVector(&NewNormalVector);
     2295                    cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2296                    radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2297                    if (radius < RADIUS*RADIUS) {
     2298                      helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2299                      cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2300                      NewSphereCenter.AddVector(&helper);
     2301                      NewSphereCenter.SubtractVector(&CircleCenter);
     2302                      cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2303
     2304                      helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2305                      OtherNewSphereCenter.AddVector(&helper);
     2306                      OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2307                      cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2308
     2309                      // check both possible centers
     2310                      alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2311                      Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2312                      alpha = min(alpha, Otheralpha);
     2313                      if (*ShortestAngle > alpha) {
     2314                          OptCandidate = Candidate;
     2315                          *ShortestAngle = alpha;
     2316                          if (alpha != Otheralpha)
     2317                            OptCandidateCenter->CopyVector(&NewSphereCenter);
     2318                          else
     2319                            OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2320                          cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2321                      } else {
     2322                        if (OptCandidate != NULL)
     2323                          cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2324                        else
     2325                          cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2326                      }
     2327
     2328                    } else {
     2329                      cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2330                    }
     2331                  } else {
     2332                    cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2333                  }
     2334                } else {
     2335                  if (ThirdNode != NULL)
     2336                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
     2337                  else
     2338                    cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
     2339                }
     2340              }
     2341            }
     2342          }
     2343    } else {
     2344      cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2345    }
     2346  } else {
     2347    if (ThirdNode != NULL)
     2348      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
     2349    else
     2350      cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
     2351  }
     2352
     2353  cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
    23542354};
    23552355
     
    23652365void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
    23662366{
    2367         cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
    2368         Vector AngleCheck;
    2369         double norm = -1., angle;
    2370         LinkedAtoms *List = NULL;
    2371         int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2372 
    2373         if (LC->SetIndexToAtom(a)) {    // get cell for the starting atom
    2374                 for(int i=0;i<NDIM;i++) // store indices of this cell
    2375                         N[i] = LC->n[i];
    2376         } else {
    2377                 cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
    2378                 return;
    2379         }
    2380         // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
    2381         cout << Verbose(2) << "LC Intervals:";
    2382         for (int i=0;i<NDIM;i++) {
    2383                 Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
    2384                 Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
    2385                 cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
    2386         }
    2387         cout << endl;
    2388         for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2389                 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2390                         for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2391                                 List = LC->GetCurrentCell();
    2392                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2393                                 if (List != NULL) {
    2394                                         for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2395                                                 Candidate = (*Runner);
    2396                                                                 // check if we only have one unique point yet ...
    2397                                                                 if (a != Candidate) {
    2398                         cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
    2399                         AngleCheck.CopyVector(&(Candidate->x));
    2400                         AngleCheck.SubtractVector(&(a->x));
    2401                         norm = AngleCheck.Norm();
    2402                                                         // second point shall have smallest angle with respect to Oben vector
    2403                                                         if (norm < RADIUS) {
    2404                                                                 angle = AngleCheck.Angle(&Oben);
    2405                                                                 if (angle < Storage[0]) {
    2406                                                                         //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
    2407                                                                         cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
    2408                                                                         Opt_Candidate = Candidate;
    2409                                                                         Storage[0] = AngleCheck.Angle(&Oben);
    2410                                                                         //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2411                                                                 } else {
    2412                                                                         cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
    2413                                                                 }
    2414                                                         } else {
    2415                                                                 cout << "Refused due to Radius " << norm << endl;
    2416                                                         }
    2417                                                 }
    2418                                         }
    2419                                 }
    2420                         }
    2421         cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
     2367  cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
     2368  Vector AngleCheck;
     2369  double norm = -1., angle;
     2370  LinkedAtoms *List = NULL;
     2371  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2372
     2373  if (LC->SetIndexToAtom(a)) {  // get cell for the starting atom
     2374    for(int i=0;i<NDIM;i++) // store indices of this cell
     2375      N[i] = LC->n[i];
     2376  } else {
     2377    cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     2378    return;
     2379  }
     2380  // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2381  cout << Verbose(2) << "LC Intervals:";
     2382  for (int i=0;i<NDIM;i++) {
     2383    Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2384    Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2385    cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2386  }
     2387  cout << endl;
     2388  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2389    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2390      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2391        List = LC->GetCurrentCell();
     2392        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2393        if (List != NULL) {
     2394          for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2395            Candidate = (*Runner);
     2396                // check if we only have one unique point yet ...
     2397                if (a != Candidate) {
     2398      cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
     2399      AngleCheck.CopyVector(&(Candidate->x));
     2400      AngleCheck.SubtractVector(&(a->x));
     2401      norm = AngleCheck.Norm();
     2402              // second point shall have smallest angle with respect to Oben vector
     2403              if (norm < RADIUS) {
     2404                angle = AngleCheck.Angle(&Oben);
     2405                if (angle < Storage[0]) {
     2406                  //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
     2407                  cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
     2408                  Opt_Candidate = Candidate;
     2409                  Storage[0] = AngleCheck.Angle(&Oben);
     2410                  //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
     2411                } else {
     2412                  cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
     2413                }
     2414              } else {
     2415                cout << "Refused due to Radius " << norm << endl;
     2416              }
     2417            }
     2418          }
     2419        }
     2420      }
     2421  cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
    24222422};
    24232423
     
    24312431void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
    24322432{
    2433         cout << Verbose(1) << "Begin of Find_starting_triangle\n";
    2434         int i = 0;
    2435         LinkedAtoms *List = NULL;
    2436         atom* FirstPoint;
    2437         atom* SecondPoint;
    2438         atom* MaxAtom[NDIM];
    2439         double max_coordinate[NDIM];
    2440         Vector Oben;
    2441         Vector helper;
    2442         Vector Chord;
    2443         Vector SearchDirection;
    2444         Vector OptCandidateCenter;
    2445 
    2446         Oben.Zero();
    2447 
    2448         for (i = 0; i < 3; i++) {
    2449                 MaxAtom[i] = NULL;
    2450                 max_coordinate[i] = -1;
    2451         }
    2452 
    2453         // 1. searching topmost atom with respect to each axis
    2454         for (int i=0;i<NDIM;i++) { // each axis
    2455                 LC->n[i] = LC->N[i]-1; // current axis is topmost cell
    2456                 for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
    2457                         for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
    2458                                 List = LC->GetCurrentCell();
    2459                                 //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    2460                                 if (List != NULL) {
    2461                                         for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
    2462                                                 cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
    2463                                                 if ((*Runner)->x.x[i] > max_coordinate[i]) {
    2464                                                         max_coordinate[i] = (*Runner)->x.x[i];
    2465                                                         MaxAtom[i] = (*Runner);
    2466                                                 }
    2467                                         }
    2468                                 } else {
    2469                                         cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
    2470                                 }
    2471                         }
    2472         }
    2473 
    2474         cout << Verbose(2) << "Found maximum coordinates: ";
    2475         for (int i=0;i<NDIM;i++)
    2476                 cout << i << ": " << *MaxAtom[i] << "\t";
    2477         cout << endl;
    2478         const int k = 1;                // arbitrary choice
    2479         Oben.x[k] = 1.;
    2480         FirstPoint = MaxAtom[k];
    2481         cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
    2482 
    2483         // add first point
    2484         AddTrianglePoint(FirstPoint, 0);
    2485 
    2486         double ShortestAngle;
    2487         atom* Opt_Candidate = NULL;
    2488         ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    2489 
    2490         Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    2491         SecondPoint = Opt_Candidate;
    2492         cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
    2493 
    2494         // add second point and first baseline
    2495         AddTrianglePoint(SecondPoint, 1);
    2496         AddTriangleLine(TPS[0], TPS[1], 0);
    2497 
    2498         helper.CopyVector(&(FirstPoint->x));
    2499         helper.SubtractVector(&(SecondPoint->x));
    2500         helper.Normalize();
    2501         Oben.ProjectOntoPlane(&helper);
    2502         Oben.Normalize();
    2503         helper.VectorProduct(&Oben);
    2504         ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2505 
    2506         Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2507         Chord.SubtractVector(&(SecondPoint->x));
    2508         double radius = Chord.ScalarProduct(&Chord);
    2509         double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
    2510         helper.CopyVector(&Oben);
    2511         helper.Scale(CircleRadius);
    2512         // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2513 
    2514         cout << Verbose(2) << "Looking for third point candidates \n";
    2515         // look in one direction of baseline for initial candidate
    2516         Opt_Candidate = NULL;
    2517         SearchDirection.MakeNormalVector(&Chord, &Oben);        // whether we look "left" first or "right" first is not important ...
    2518 
    2519         cout << Verbose(1) << "Looking for third point candidates ...\n";
    2520         Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2521         cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2522 
    2523         // add third point
    2524         AddTrianglePoint(Opt_Candidate, 2);
    2525 
    2526         // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2527 
    2528         // Finally, we only have to add the found further lines
    2529         AddTriangleLine(TPS[1], TPS[2], 1);
    2530         AddTriangleLine(TPS[0], TPS[2], 2);
    2531         // ... and triangles to the Maps of the Tesselation class
    2532         BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2533         AddTriangleToLines();
    2534         // ... and calculate its normal vector (with correct orientation)
    2535         OptCandidateCenter.Scale(-1.);
    2536         cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
    2537         BTS->GetNormalVector(OptCandidateCenter);
    2538         cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
    2539         cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
    2540         cout << Verbose(1) << "End of Find_starting_triangle\n";
     2433  cout << Verbose(1) << "Begin of Find_starting_triangle\n";
     2434  int i = 0;
     2435  LinkedAtoms *List = NULL;
     2436  atom* FirstPoint;
     2437  atom* SecondPoint;
     2438  atom* MaxAtom[NDIM];
     2439  double max_coordinate[NDIM];
     2440  Vector Oben;
     2441  Vector helper;
     2442  Vector Chord;
     2443  Vector SearchDirection;
     2444  Vector OptCandidateCenter;
     2445
     2446  Oben.Zero();
     2447
     2448  for (i = 0; i < 3; i++) {
     2449    MaxAtom[i] = NULL;
     2450    max_coordinate[i] = -1;
     2451  }
     2452
     2453  // 1. searching topmost atom with respect to each axis
     2454  for (int i=0;i<NDIM;i++) { // each axis
     2455    LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     2456    for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
     2457      for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
     2458        List = LC->GetCurrentCell();
     2459        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2460        if (List != NULL) {
     2461          for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     2462            cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
     2463            if ((*Runner)->x.x[i] > max_coordinate[i]) {
     2464              max_coordinate[i] = (*Runner)->x.x[i];
     2465              MaxAtom[i] = (*Runner);
     2466            }
     2467          }
     2468        } else {
     2469          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
     2470        }
     2471      }
     2472  }
     2473
     2474  cout << Verbose(2) << "Found maximum coordinates: ";
     2475  for (int i=0;i<NDIM;i++)
     2476    cout << i << ": " << *MaxAtom[i] << "\t";
     2477  cout << endl;
     2478  const int k = 1;    // arbitrary choice
     2479  Oben.x[k] = 1.;
     2480  FirstPoint = MaxAtom[k];
     2481  cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
     2482
     2483  // add first point
     2484  AddTrianglePoint(FirstPoint, 0);
     2485
     2486  double ShortestAngle;
     2487  atom* Opt_Candidate = NULL;
     2488  ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
     2489
     2490  Find_second_point_for_Tesselation(FirstPoint, NULL, Oben, Opt_Candidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
     2491  SecondPoint = Opt_Candidate;
     2492  cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
     2493
     2494  // add second point and first baseline
     2495  AddTrianglePoint(SecondPoint, 1);
     2496  AddTriangleLine(TPS[0], TPS[1], 0);
     2497
     2498  helper.CopyVector(&(FirstPoint->x));
     2499  helper.SubtractVector(&(SecondPoint->x));
     2500  helper.Normalize();
     2501  Oben.ProjectOntoPlane(&helper);
     2502  Oben.Normalize();
     2503  helper.VectorProduct(&Oben);
     2504  ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2505
     2506  Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
     2507  Chord.SubtractVector(&(SecondPoint->x));
     2508  double radius = Chord.ScalarProduct(&Chord);
     2509  double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     2510  helper.CopyVector(&Oben);
     2511  helper.Scale(CircleRadius);
     2512  // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     2513
     2514  cout << Verbose(2) << "Looking for third point candidates \n";
     2515  // look in one direction of baseline for initial candidate
     2516  Opt_Candidate = NULL;
     2517  SearchDirection.MakeNormalVector(&Chord, &Oben);  // whether we look "left" first or "right" first is not important ...
     2518
     2519  cout << Verbose(1) << "Looking for third point candidates ...\n";
     2520  Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2521  cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
     2522
     2523  // add third point
     2524  AddTrianglePoint(Opt_Candidate, 2);
     2525
     2526  // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
     2527
     2528  // Finally, we only have to add the found further lines
     2529  AddTriangleLine(TPS[1], TPS[2], 1);
     2530  AddTriangleLine(TPS[0], TPS[2], 2);
     2531  // ... and triangles to the Maps of the Tesselation class
     2532  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2533  AddTriangleToLines();
     2534  // ... and calculate its normal vector (with correct orientation)
     2535  OptCandidateCenter.Scale(-1.);
     2536  cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
     2537  BTS->GetNormalVector(OptCandidateCenter);
     2538  cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
     2539  cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
     2540  cout << Verbose(1) << "End of Find_starting_triangle\n";
    25412541};
    25422542
     
    25522552 */
    25532553bool Tesselation::Find_next_suitable_triangle(ofstream *out,
    2554                 molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    2555                 const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
    2556 {
    2557         cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
    2558         ofstream *tempstream = NULL;
    2559         char NumberName[255];
    2560 
    2561         atom* Opt_Candidate = NULL;
    2562         Vector OptCandidateCenter;
    2563 
    2564         Vector CircleCenter;
    2565         Vector CirclePlaneNormal;
    2566         Vector OldSphereCenter;
    2567         Vector SearchDirection;
    2568         Vector helper;
    2569         atom *ThirdNode = NULL;
    2570         double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
    2571         double radius, CircleRadius;
    2572 
    2573         cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
    2574         for (int i=0;i<3;i++)
    2575                 if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
    2576                         ThirdNode = T.endpoints[i]->node;
    2577 
    2578         // construct center of circle
    2579         CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
    2580         CircleCenter.AddVector(&Line.endpoints[1]->node->x);
    2581         CircleCenter.Scale(0.5);
    2582 
    2583         // construct normal vector of circle
    2584         CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
    2585         CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
    2586 
    2587         // calculate squared radius of circle
    2588         radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
    2589         if (radius/4. < RADIUS*RADIUS) {
    2590                 CircleRadius = RADIUS*RADIUS - radius/4.;
    2591                 CirclePlaneNormal.Normalize();
    2592                 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    2593 
    2594                 // construct old center
    2595                 GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
    2596                 helper.CopyVector(&T.NormalVector);     // normal vector ensures that this is correct center of the two possible ones
    2597                 radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
    2598                 helper.Scale(sqrt(RADIUS*RADIUS - radius));
    2599                 OldSphereCenter.AddVector(&helper);
    2600                 OldSphereCenter.SubtractVector(&CircleCenter);
    2601                 cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    2602 
    2603                 // construct SearchDirection
    2604                 SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
    2605                 helper.CopyVector(&Line.endpoints[0]->node->x);
    2606                 helper.SubtractVector(&ThirdNode->x);
    2607                 if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // ohoh, SearchDirection points inwards!
    2608                         SearchDirection.Scale(-1.);
    2609                 SearchDirection.ProjectOntoPlane(&OldSphereCenter);
    2610                 SearchDirection.Normalize();
    2611                 cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
    2612                 if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
    2613                         cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
    2614                 }
    2615 
    2616                 // add third point
    2617                 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2618                 Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
    2619 
    2620         } else {
    2621                 cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
    2622         }
    2623 
    2624         if (Opt_Candidate == NULL) {
    2625                 cerr << "WARNING: Could not find a suitable candidate." << endl;
    2626                 return false;
    2627         }
    2628         cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
    2629 
    2630         // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2631         atom *AtomCandidates[3];
    2632         AtomCandidates[0] = Opt_Candidate;
    2633         AtomCandidates[1] = Line.endpoints[0]->node;
    2634         AtomCandidates[2] = Line.endpoints[1]->node;
    2635         bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
    2636 
    2637         if (flag) { // if so, add
    2638                 AddTrianglePoint(Opt_Candidate, 0);
    2639                 AddTrianglePoint(Line.endpoints[0]->node, 1);
    2640                 AddTrianglePoint(Line.endpoints[1]->node, 2);
    2641 
    2642                 AddTriangleLine(TPS[0], TPS[1], 0);
    2643                 AddTriangleLine(TPS[0], TPS[2], 1);
    2644                 AddTriangleLine(TPS[1], TPS[2], 2);
    2645 
    2646                 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2647                 AddTriangleToLines();
    2648 
    2649                 OptCandidateCenter.Scale(-1.);
    2650                 BTS->GetNormalVector(OptCandidateCenter);
    2651                 OptCandidateCenter.Scale(-1.);
    2652 
    2653                 cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
    2654                 cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
    2655         } else { // else, yell and do nothing
    2656                 cout << Verbose(1) << "This triangle consisting of ";
    2657                 cout << *Opt_Candidate << ", ";
    2658                 cout << *Line.endpoints[0]->node << " and ";
    2659                 cout << *Line.endpoints[1]->node << " ";
    2660                 cout << "is invalid!" << endl;
    2661                 return false;
    2662         }
    2663 
    2664         if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
    2665                 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
    2666                 if (DoTecplotOutput) {
    2667                         string NameofTempFile(tempbasename);
    2668                         NameofTempFile.append(NumberName);
    2669                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    2670                                 NameofTempFile.erase(npos, 1);
    2671                         NameofTempFile.append(TecplotSuffix);
    2672                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2673                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2674                         write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2675                         tempstream->close();
    2676                         tempstream->flush();
    2677                         delete(tempstream);
    2678                 }
    2679 
    2680                 if (DoRaster3DOutput) {
    2681                         string NameofTempFile(tempbasename);
    2682                         NameofTempFile.append(NumberName);
    2683                         for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    2684                                 NameofTempFile.erase(npos, 1);
    2685                         NameofTempFile.append(Raster3DSuffix);
    2686                         cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2687                         tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2688                         write_raster3d_file(out, tempstream, this, mol);
    2689                         // include the current position of the virtual sphere in the temporary raster3d file
    2690                         // make the circumsphere's center absolute again
    2691                         helper.CopyVector(&Line.endpoints[0]->node->x);
    2692                         helper.AddVector(&Line.endpoints[1]->node->x);
    2693                         helper.Scale(0.5);
    2694                         OptCandidateCenter.AddVector(&helper);
    2695                         Vector *center = mol->DetermineCenterOfAll(out);
    2696                         OptCandidateCenter.AddVector(center);
    2697                         delete(center);
    2698                         // and add to file plus translucency object
    2699                         *tempstream << "# current virtual sphere\n";
    2700                         *tempstream << "8\n     25.0            0.6              -1.0 -1.0 -1.0          0.2                            0 0 0 0\n";
    2701                         *tempstream << "2\n     " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
    2702                         *tempstream << "9\n     terminating special property\n";
    2703                         tempstream->close();
    2704                         tempstream->flush();
    2705                         delete(tempstream);
    2706                 }
    2707                 if (DoTecplotOutput || DoRaster3DOutput)
    2708                         TriangleFilesWritten++;
    2709         }
    2710 
    2711         cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
    2712         return true;
     2554    molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
     2555    const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
     2556{
     2557  cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
     2558  ofstream *tempstream = NULL;
     2559  char NumberName[255];
     2560
     2561  atom* Opt_Candidate = NULL;
     2562  Vector OptCandidateCenter;
     2563
     2564  Vector CircleCenter;
     2565  Vector CirclePlaneNormal;
     2566  Vector OldSphereCenter;
     2567  Vector SearchDirection;
     2568  Vector helper;
     2569  atom *ThirdNode = NULL;
     2570  double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2571  double radius, CircleRadius;
     2572
     2573  cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
     2574  for (int i=0;i<3;i++)
     2575    if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
     2576      ThirdNode = T.endpoints[i]->node;
     2577
     2578  // construct center of circle
     2579  CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
     2580  CircleCenter.AddVector(&Line.endpoints[1]->node->x);
     2581  CircleCenter.Scale(0.5);
     2582
     2583  // construct normal vector of circle
     2584  CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
     2585  CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
     2586
     2587  // calculate squared radius of circle
     2588  radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2589  if (radius/4. < RADIUS*RADIUS) {
     2590    CircleRadius = RADIUS*RADIUS - radius/4.;
     2591    CirclePlaneNormal.Normalize();
     2592    cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2593
     2594    // construct old center
     2595    GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
     2596    helper.CopyVector(&T.NormalVector);  // normal vector ensures that this is correct center of the two possible ones
     2597    radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2598    helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2599    OldSphereCenter.AddVector(&helper);
     2600    OldSphereCenter.SubtractVector(&CircleCenter);
     2601    cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2602
     2603    // construct SearchDirection
     2604    SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
     2605    helper.CopyVector(&Line.endpoints[0]->node->x);
     2606    helper.SubtractVector(&ThirdNode->x);
     2607    if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)  // ohoh, SearchDirection points inwards!
     2608      SearchDirection.Scale(-1.);
     2609    SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2610    SearchDirection.Normalize();
     2611    cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2612    if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {  // rotated the wrong way!
     2613      cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2614    }
     2615
     2616    // add third point
     2617    cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
     2618    Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2619
     2620  } else {
     2621    cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
     2622  }
     2623
     2624  if (Opt_Candidate == NULL) {
     2625    cerr << "WARNING: Could not find a suitable candidate." << endl;
     2626    return false;
     2627  }
     2628  cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
     2629
     2630  // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2631  atom *AtomCandidates[3];
     2632  AtomCandidates[0] = Opt_Candidate;
     2633  AtomCandidates[1] = Line.endpoints[0]->node;
     2634  AtomCandidates[2] = Line.endpoints[1]->node;
     2635  bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
     2636
     2637  if (flag) { // if so, add
     2638    AddTrianglePoint(Opt_Candidate, 0);
     2639    AddTrianglePoint(Line.endpoints[0]->node, 1);
     2640    AddTrianglePoint(Line.endpoints[1]->node, 2);
     2641
     2642    AddTriangleLine(TPS[0], TPS[1], 0);
     2643    AddTriangleLine(TPS[0], TPS[2], 1);
     2644    AddTriangleLine(TPS[1], TPS[2], 2);
     2645
     2646    BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2647    AddTriangleToLines();
     2648
     2649    OptCandidateCenter.Scale(-1.);
     2650    BTS->GetNormalVector(OptCandidateCenter);
     2651    OptCandidateCenter.Scale(-1.);
     2652
     2653    cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
     2654    cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
     2655  } else { // else, yell and do nothing
     2656    cout << Verbose(1) << "This triangle consisting of ";
     2657    cout << *Opt_Candidate << ", ";
     2658    cout << *Line.endpoints[0]->node << " and ";
     2659    cout << *Line.endpoints[1]->node << " ";
     2660    cout << "is invalid!" << endl;
     2661    return false;
     2662  }
     2663
     2664  if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     2665    sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
     2666    if (DoTecplotOutput) {
     2667      string NameofTempFile(tempbasename);
     2668      NameofTempFile.append(NumberName);
     2669      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2670        NameofTempFile.erase(npos, 1);
     2671      NameofTempFile.append(TecplotSuffix);
     2672      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2673      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2674      write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
     2675      tempstream->close();
     2676      tempstream->flush();
     2677      delete(tempstream);
     2678    }
     2679
     2680    if (DoRaster3DOutput) {
     2681      string NameofTempFile(tempbasename);
     2682      NameofTempFile.append(NumberName);
     2683      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     2684        NameofTempFile.erase(npos, 1);
     2685      NameofTempFile.append(Raster3DSuffix);
     2686      cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2687      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2688      write_raster3d_file(out, tempstream, this, mol);
     2689      // include the current position of the virtual sphere in the temporary raster3d file
     2690      // make the circumsphere's center absolute again
     2691      helper.CopyVector(&Line.endpoints[0]->node->x);
     2692      helper.AddVector(&Line.endpoints[1]->node->x);
     2693      helper.Scale(0.5);
     2694      OptCandidateCenter.AddVector(&helper);
     2695      Vector *center = mol->DetermineCenterOfAll(out);
     2696      OptCandidateCenter.AddVector(center);
     2697      delete(center);
     2698      // and add to file plus translucency object
     2699      *tempstream << "# current virtual sphere\n";
     2700      *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     2701      *tempstream << "2\n  " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
     2702      *tempstream << "9\n  terminating special property\n";
     2703      tempstream->close();
     2704      tempstream->flush();
     2705      delete(tempstream);
     2706    }
     2707    if (DoTecplotOutput || DoRaster3DOutput)
     2708      TriangleFilesWritten++;
     2709  }
     2710
     2711  cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
     2712  return true;
    27132713};
    27142714
     
    27232723void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS)
    27242724{
    2725         int N = 0;
    2726         bool freeTess = false;
    2727         *out << Verbose(1) << "Entering search for non convex hull. " << endl;
    2728         if (Tess == NULL) {
    2729                 *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
    2730                 Tess = new Tesselation;
    2731                 freeTess = true;
    2732         }
    2733         bool freeLC = false;
    2734         LineMap::iterator baseline;
    2735         *out << Verbose(0) << "Begin of Find_non_convex_border\n";
    2736         bool flag = false;      // marks whether we went once through all baselines without finding any without two triangles
    2737         bool failflag = false;
    2738 
    2739         if (LCList == NULL) {
    2740                 LCList = new LinkedCell(mol, 2.*RADIUS);
    2741                 freeLC = true;
    2742         }
    2743 
    2744         Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
    2745 
    2746         baseline = Tess->LinesOnBoundary.begin();
    2747         while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
    2748                 if (baseline->second->TrianglesCount == 1) {
    2749                         failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.
    2750                         flag = flag || failflag;
    2751                         if (!failflag)
    2752                                 cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
    2753                 } else {
    2754                         cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
    2755                 }
    2756                 N++;
    2757                 baseline++;
    2758                 if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
    2759                         baseline = Tess->LinesOnBoundary.begin();        // restart if we reach end due to newly inserted lines
    2760                         flag = false;
    2761                 }
    2762         }
    2763         if (1) { //failflag) {
    2764                 *out << Verbose(1) << "Writing final tecplot file\n";
    2765                 if (DoTecplotOutput) {
    2766                         string OutputName(filename);
    2767                         OutputName.append(TecplotSuffix);
    2768                         ofstream *tecplot = new ofstream(OutputName.c_str());
    2769                         write_tecplot_file(out, tecplot, Tess, mol, -1);
    2770                         tecplot->close();
    2771                         delete(tecplot);
    2772                 }
    2773                 if (DoRaster3DOutput) {
    2774                         string OutputName(filename);
    2775                         OutputName.append(Raster3DSuffix);
    2776                         ofstream *raster = new ofstream(OutputName.c_str());
    2777                         write_raster3d_file(out, raster, Tess, mol);
    2778                         raster->close();
    2779                         delete(raster);
    2780                 }
    2781         } else {
    2782                 cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
    2783         }
    2784         if (freeTess)
    2785                 delete(Tess);
    2786         if (freeLC)
    2787                 delete(LCList);
    2788         *out << Verbose(0) << "End of Find_non_convex_border\n";
     2725  int N = 0;
     2726  bool freeTess = false;
     2727  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     2728  if (Tess == NULL) {
     2729    *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
     2730    Tess = new Tesselation;
     2731    freeTess = true;
     2732  }
     2733  bool freeLC = false;
     2734  LineMap::iterator baseline;
     2735  *out << Verbose(0) << "Begin of Find_non_convex_border\n";
     2736  bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
     2737  bool failflag = false;
     2738
     2739  if (LCList == NULL) {
     2740    LCList = new LinkedCell(mol, 2.*RADIUS);
     2741    freeLC = true;
     2742  }
     2743
     2744  Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     2745
     2746  baseline = Tess->LinesOnBoundary.begin();
     2747  while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
     2748    if (baseline->second->TrianglesCount == 1) {
     2749      failflag = Tess->Find_next_suitable_triangle(out, mol, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename, LCList); //the line is there, so there is a triangle, but only one.
     2750      flag = flag || failflag;
     2751      if (!failflag)
     2752        cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
     2753    } else {
     2754      cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
     2755    }
     2756    N++;
     2757    baseline++;
     2758    if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
     2759      baseline = Tess->LinesOnBoundary.begin();  // restart if we reach end due to newly inserted lines
     2760      flag = false;
     2761    }
     2762  }
     2763  if (1) { //failflag) {
     2764    *out << Verbose(1) << "Writing final tecplot file\n";
     2765    if (DoTecplotOutput) {
     2766      string OutputName(filename);
     2767      OutputName.append(TecplotSuffix);
     2768      ofstream *tecplot = new ofstream(OutputName.c_str());
     2769      write_tecplot_file(out, tecplot, Tess, mol, -1);
     2770      tecplot->close();
     2771      delete(tecplot);
     2772    }
     2773    if (DoRaster3DOutput) {
     2774      string OutputName(filename);
     2775      OutputName.append(Raster3DSuffix);
     2776      ofstream *raster = new ofstream(OutputName.c_str());
     2777      write_raster3d_file(out, raster, Tess, mol);
     2778      raster->close();
     2779      delete(raster);
     2780    }
     2781  } else {
     2782    cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
     2783  }
     2784  if (freeTess)
     2785    delete(Tess);
     2786  if (freeLC)
     2787    delete(LCList);
     2788  *out << Verbose(0) << "End of Find_non_convex_border\n";
    27892789};
    27902790
Note: See TracChangeset for help on using the changeset viewer.