Changeset 6ac7ee for src/boundary.cpp


Ignore:
Timestamp:
Feb 9, 2009, 5:24:10 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:
d8b94a
Parents:
124df1
git-author:
Frederik Heber <heber@…> (02/09/09 15:55:37)
git-committer:
Frederik Heber <heber@…> (02/09/09 17:24:10)
Message:

Merge branch 'ConcaveHull' of ../espack2 into ConcaveHull

Conflicts:

molecuilder/src/boundary.cpp
molecuilder/src/boundary.hpp
molecuilder/src/builder.cpp
molecuilder/src/linkedcell.cpp
molecuilder/src/linkedcell.hpp
molecuilder/src/vector.cpp
molecuilder/src/vector.hpp
util/src/NanoCreator.c

Basically, this resulted from a lot of conversions two from spaces to one tab, which is my standard indentation. The mess was caused by eclipse auto-indenting. And in espack2:ConcaveHull was the new stuff, so all from ConcaveHull was replaced in case of doubt.
Additionally, vector had ofstream << operator instead ostream << ...

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    • Property mode changed from 100644 to 100755
    r124df1 r6ac7ee  
    1 #include "molecules.hpp"
    21#include "boundary.hpp"
    32
    43#define DEBUG 1
    5 #define DoTecplotOutput 0
     4#define DoSingleStepOutput 0
     5#define DoTecplotOutput 1
    66#define DoRaster3DOutput 1
     7#define DoVRMLOutput 1
    78#define TecplotSuffix ".dat"
    89#define Raster3DSuffix ".r3d"
     10#define VRMLSUffix ".wrl"
     11#define HULLEPSILON MYEPSILON
    912
    1013// ======================================== Points on Boundary =================================
     
    1215BoundaryPointSet::BoundaryPointSet()
    1316{
    14   LinesCount = 0;
    15   Nr = -1;
     17        LinesCount = 0;
     18        Nr = -1;
    1619}
    1720;
     
    1922BoundaryPointSet::BoundaryPointSet(atom *Walker)
    2023{
    21   node = Walker;
    22   LinesCount = 0;
    23   Nr = Walker->nr;
     24        node = Walker;
     25        LinesCount = 0;
     26        Nr = Walker->nr;
    2427}
    2528;
     
    2730BoundaryPointSet::~BoundaryPointSet()
    2831{
    29   cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    30   node = NULL;
    31 }
    32 ;
    33 
    34 void
    35 BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    36 {
    37   cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
    38       << endl;
    39   if (line->endpoints[0] == this)
    40     {
    41       lines.insert(LinePair(line->endpoints[1]->Nr, line));
    42     }
    43   else
    44     {
    45       lines.insert(LinePair(line->endpoints[0]->Nr, line));
    46     }
    47   LinesCount++;
     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;
     36}
     37;
     38
     39void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
     40{
     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++;
    4852}
    4953;
     
    5256operator <<(ostream &ost, BoundaryPointSet &a)
    5357{
    54   ost << "[" << a.Nr << "|" << a.node->Name << "]";
    55   return ost;
     58        ost << "[" << a.Nr << "|" << a.node->Name << "]";
     59        return ost;
    5660}
    5761;
     
    6165BoundaryLineSet::BoundaryLineSet()
    6266{
    63   for (int i = 0; i < 2; i++)
    64     endpoints[i] = NULL;
    65   TrianglesCount = 0;
    66   Nr = -1;
     67        for (int i = 0; i < 2; i++)
     68                endpoints[i] = NULL;
     69        TrianglesCount = 0;
     70        Nr = -1;
    6771}
    6872;
     
    7074BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number)
    7175{
    72   // set number
    73   Nr = number;
    74   // set endpoints in ascending order
    75   SetEndpointsOrdered(endpoints, Point[0], Point[1]);
    76   // add this line to the hash maps of both endpoints
    77   Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding.
    78   Point[1]->AddLine(this); //
    79   // clear triangles list
    80   TrianglesCount = 0;
    81   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;
    8286}
    8387;
     
    8589BoundaryLineSet::~BoundaryLineSet()
    8690{
    87   for (int i = 0; i < 2; i++)
    88     {
    89       cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point "
    90           << *endpoints[i] << "." << endl;
    91       endpoints[i]->lines.erase(Nr);
    92       LineMap::iterator tester = endpoints[i]->lines.begin();
    93       tester++;
    94       if (tester == endpoints[i]->lines.end())
    95         {
    96           cout << Verbose(5) << *endpoints[i]
    97               << " has no more lines it's attached to, erasing." << endl;
    98           //delete(endpoints[i]);
    99         }
    100       else
    101         cout << Verbose(5) << *endpoints[i]
    102             << " has still lines it's attached to." << endl;
    103     }
     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;
    104109}
    105110;
     
    108113BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle)
    109114{
    110   cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
    111       << endl;
    112   triangles.insert(TrianglePair(TrianglesCount, triangle));
    113   TrianglesCount++;
     115        cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "."
     116                        << endl;
     117        triangles.insert(TrianglePair(triangle->Nr, triangle));
     118        TrianglesCount++;
    114119}
    115120;
     
    118123operator <<(ostream &ost, BoundaryLineSet &a)
    119124{
    120   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    121       << a.endpoints[1]->node->Name << "]";
    122   return ost;
     125        ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
     126                        << a.endpoints[1]->node->Name << "]";
     127        return ost;
    123128}
    124129;
     
    129134BoundaryTriangleSet::BoundaryTriangleSet()
    130135{
    131   for (int i = 0; i < 3; i++)
    132     {
    133       endpoints[i] = NULL;
    134       lines[i] = NULL;
    135     }
    136   Nr = -1;
     136        for (int i = 0; i < 3; i++)
     137                {
     138                        endpoints[i] = NULL;
     139                        lines[i] = NULL;
     140                }
     141        Nr = -1;
    137142}
    138143;
    139144
    140145BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3],
    141     int number)
    142 {
    143   // set number
    144   Nr = number;
    145   // set lines
    146   cout << Verbose(5) << "New triangle " << Nr << ":" << endl;
    147   for (int i = 0; i < 3; i++)
    148     {
    149       lines[i] = line[i];
    150       lines[i]->AddTriangle(this);
    151     }
    152   // get ascending order of endpoints
    153   map<int, class BoundaryPointSet *> OrderMap;
    154   for (int i = 0; i < 3; i++)
    155     // for all three lines
    156     for (int j = 0; j < 2; j++)
    157       { // for both endpoints
    158         OrderMap.insert(pair<int, class BoundaryPointSet *> (
    159             line[i]->endpoints[j]->Nr, line[i]->endpoints[j]));
    160         // and we don't care whether insertion fails
    161       }
    162   // set endpoints
    163   int Counter = 0;
    164   cout << Verbose(6) << " with end points ";
    165   for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner
    166       != OrderMap.end(); runner++)
    167     {
    168       endpoints[Counter] = runner->second;
    169       cout << " " << *endpoints[Counter];
    170       Counter++;
    171     }
    172   if (Counter < 3)
    173     {
    174       cerr << "ERROR! We have a triangle with only two distinct endpoints!"
    175           << endl;
    176       //exit(1);
    177     }
    178   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;
    179184}
    180185;
     
    182187BoundaryTriangleSet::~BoundaryTriangleSet()
    183188{
    184   for (int i = 0; i < 3; i++)
    185     {
    186       cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl;
    187       lines[i]->triangles.erase(Nr);
    188       TriangleMap::iterator tester = lines[i]->triangles.begin();
    189       tester++;
    190       if (tester == lines[i]->triangles.end())
    191         {
    192           cout << Verbose(5) << *lines[i]
    193               << " is no more attached to any triangle, erasing." << endl;
    194           delete (lines[i]);
    195         }
    196       else
    197         cout << Verbose(5) << *lines[i] << " is still attached to a triangle."
    198             << endl;
    199     }
     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        }
    200202}
    201203;
     
    204206BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    205207{
    206   // get normal vector
    207   NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x,
    208       &endpoints[2]->node->x);
    209 
    210   // make it always point inward (any offset vector onto plane projected onto normal vector suffices)
    211   if (endpoints[0]->node->x.Projection(&OtherVector) > 0)
    212     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.);
    213215}
    214216;
     
    217219operator <<(ostream &ost, BoundaryTriangleSet &a)
    218220{
    219   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    220       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
    221   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;
    222224}
    223225;
     
    233235GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2)
    234236{
    235   class BoundaryLineSet * lines[2] =
    236     { line1, line2 };
    237   class BoundaryPointSet *node = NULL;
    238   map<int, class BoundaryPointSet *> OrderMap;
    239   pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest;
    240   for (int i = 0; i < 2; i++)
    241     // for both lines
    242     for (int j = 0; j < 2; j++)
    243       { // for both endpoints
    244         OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> (
    245             lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]));
    246         if (!OrderTest.second)
    247           { // if insertion fails, we have common endpoint
    248             node = OrderTest.first->second;
    249             cout << Verbose(5) << "Common endpoint of lines " << *line1
    250                 << " and " << *line2 << " is: " << *node << "." << endl;
    251             j = 2;
    252             i = 2;
    253             break;
    254           }
    255       }
    256   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;
    257259}
    258260;
     
    268270GetBoundaryPoints(ofstream *out, molecule *mol)
    269271{
    270   atom *Walker = NULL;
    271   PointMap PointsOnBoundary;
    272   LineMap LinesOnBoundary;
    273   TriangleMap TrianglesOnBoundary;
    274 
    275   *out << Verbose(1) << "Finding all boundary points." << endl;
    276   Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr)
    277   BoundariesTestPair BoundaryTestPair;
    278   Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector;
    279   double radius, angle;
    280   // 3a. Go through every axis
    281   for (int axis = 0; axis < NDIM; axis++)
    282     {
    283       AxisVector.Zero();
    284       AngleReferenceVector.Zero();
    285       AngleReferenceNormalVector.Zero();
    286       AxisVector.x[axis] = 1.;
    287       AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    288       AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    289       //    *out << Verbose(1) << "Axisvector is ";
    290       //    AxisVector.Output(out);
    291       //    *out << " and AngleReferenceVector is ";
    292       //    AngleReferenceVector.Output(out);
    293       //    *out << "." << endl;
    294       //    *out << " and AngleReferenceNormalVector is ";
    295       //    AngleReferenceNormalVector.Output(out);
    296       //    *out << "." << endl;
    297       // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    298       Walker = mol->start;
    299       while (Walker->next != mol->end)
    300         {
    301           Walker = Walker->next;
    302           Vector ProjectedVector;
    303           ProjectedVector.CopyVector(&Walker->x);
    304           ProjectedVector.ProjectOntoPlane(&AxisVector);
    305           // correct for negative side
    306           //if (Projection(y) < 0)
    307           //angle = 2.*M_PI - angle;
    308           radius = ProjectedVector.Norm();
    309           if (fabs(radius) > MYEPSILON)
    310             angle = ProjectedVector.Angle(&AngleReferenceVector);
    311           else
    312             angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    313 
    314           //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    315           if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
    316             {
    317               angle = 2. * M_PI - angle;
    318             }
    319           //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
    320           //ProjectedVector.Output(out);
    321           //*out << endl;
    322           BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
    323               DistancePair (radius, Walker)));
    324           if (BoundaryTestPair.second)
    325             { // successfully inserted
    326             }
    327           else
    328             { // same point exists, check first r, then distance of original vectors to center of gravity
    329               *out << Verbose(2)
    330                   << "Encountered two vectors whose projection onto axis "
    331                   << axis << " is equal: " << endl;
    332               *out << Verbose(2) << "Present vector: ";
    333               BoundaryTestPair.first->second.second->x.Output(out);
    334               *out << endl;
    335               *out << Verbose(2) << "New vector: ";
    336               Walker->x.Output(out);
    337               *out << endl;
    338               double tmp = ProjectedVector.Norm();
    339               if (tmp > BoundaryTestPair.first->second.first)
    340                 {
    341                   BoundaryTestPair.first->second.first = tmp;
    342                   BoundaryTestPair.first->second.second = Walker;
    343                   *out << Verbose(2) << "Keeping new vector." << endl;
    344                 }
    345               else if (tmp == BoundaryTestPair.first->second.first)
    346                 {
    347                   if (BoundaryTestPair.first->second.second->x.ScalarProduct(
    348                       &BoundaryTestPair.first->second.second->x)
    349                       < Walker->x.ScalarProduct(&Walker->x))
    350                     { // Norm() does a sqrt, which makes it a lot slower
    351                       BoundaryTestPair.first->second.second = Walker;
    352                       *out << Verbose(2) << "Keeping new vector." << endl;
    353                     }
    354                   else
    355                     {
    356                       *out << Verbose(2) << "Keeping present vector." << endl;
    357                     }
    358                 }
    359               else
    360                 {
    361                   *out << Verbose(2) << "Keeping present vector." << endl;
    362                 }
    363             }
    364         }
    365       // printing all inserted for debugging
    366       //    {
    367       //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    368       //      int i=0;
    369       //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    370       //        if (runner != BoundaryPoints[axis].begin())
    371       //          *out << ", " << i << ": " << *runner->second.second;
    372       //        else
    373       //          *out << i << ": " << *runner->second.second;
    374       //        i++;
    375       //      }
    376       //      *out << endl;
    377       //    }
    378       // 3c. throw out points whose distance is less than the mean of left and right neighbours
    379       bool flag = false;
    380       do
    381         { // do as long as we still throw one out per round
    382           *out << Verbose(1)
    383               << "Looking for candidates to kick out by convex condition ... "
    384               << endl;
    385           flag = false;
    386           Boundaries::iterator left = BoundaryPoints[axis].end();
    387           Boundaries::iterator right = BoundaryPoints[axis].end();
    388           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    389               != BoundaryPoints[axis].end(); runner++)
    390             {
    391               // set neighbours correctly
    392               if (runner == BoundaryPoints[axis].begin())
    393                 {
    394                   left = BoundaryPoints[axis].end();
    395                 }
    396               else
    397                 {
    398                   left = runner;
    399                 }
    400               left--;
    401               right = runner;
    402               right++;
    403               if (right == BoundaryPoints[axis].end())
    404                 {
    405                   right = BoundaryPoints[axis].begin();
    406                 }
    407               // check distance
    408 
    409               // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    410                 {
    411                   Vector SideA, SideB, SideC, SideH;
    412                   SideA.CopyVector(&left->second.second->x);
    413                   SideA.ProjectOntoPlane(&AxisVector);
    414                   //          *out << "SideA: ";
    415                   //          SideA.Output(out);
    416                   //          *out << endl;
    417 
    418                   SideB.CopyVector(&right->second.second->x);
    419                   SideB.ProjectOntoPlane(&AxisVector);
    420                   //          *out << "SideB: ";
    421                   //          SideB.Output(out);
    422                   //          *out << endl;
    423 
    424                   SideC.CopyVector(&left->second.second->x);
    425                   SideC.SubtractVector(&right->second.second->x);
    426                   SideC.ProjectOntoPlane(&AxisVector);
    427                   //          *out << "SideC: ";
    428                   //          SideC.Output(out);
    429                   //          *out << endl;
    430 
    431                   SideH.CopyVector(&runner->second.second->x);
    432                   SideH.ProjectOntoPlane(&AxisVector);
    433                   //          *out << "SideH: ";
    434                   //          SideH.Output(out);
    435                   //          *out << endl;
    436 
    437                   // calculate each length
    438                   double a = SideA.Norm();
    439                   //double b = SideB.Norm();
    440                   //double c = SideC.Norm();
    441                   double h = SideH.Norm();
    442                   // calculate the angles
    443                   double alpha = SideA.Angle(&SideH);
    444                   double beta = SideA.Angle(&SideC);
    445                   double gamma = SideB.Angle(&SideH);
    446                   double delta = SideC.Angle(&SideH);
    447                   double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
    448                       < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    449                   //          *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;
    450                   //*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;
    451                   if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
    452                       < MYEPSILON) && (h < MinDistance))
    453                     {
    454                       // throw out point
    455                       //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    456                       BoundaryPoints[axis].erase(runner);
    457                       flag = true;
    458                     }
    459                 }
    460             }
    461         }
    462       while (flag);
    463     }
    464   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;
    465467}
    466468;
     
    476478double *
    477479GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol,
    478     bool IsAngstroem)
    479 {
    480   // get points on boundary of NULL was given as parameter
    481   bool BoundaryFreeFlag = false;
    482   Boundaries *BoundaryPoints = BoundaryPtr;
    483   if (BoundaryPoints == NULL)
    484     {
    485       BoundaryFreeFlag = true;
    486       BoundaryPoints = GetBoundaryPoints(out, mol);
    487     }
    488   else
    489     {
    490       *out << Verbose(1) << "Using given boundary points set." << endl;
    491     }
    492   // determine biggest "diameter" of cluster for each axis
    493   Boundaries::iterator Neighbour, OtherNeighbour;
    494   double *GreatestDiameter = new double[NDIM];
    495   for (int i = 0; i < NDIM; i++)
    496     GreatestDiameter[i] = 0.;
    497   double OldComponent, tmp, w1, w2;
    498   Vector DistanceVector, OtherVector;
    499   int component, Othercomponent;
    500   for (int axis = 0; axis < NDIM; axis++)
    501     { // regard each projected plane
    502       //*out << Verbose(1) << "Current axis is " << axis << "." << endl;
    503       for (int j = 0; j < 2; j++)
    504         { // and for both axis on the current plane
    505           component = (axis + j + 1) % NDIM;
    506           Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM;
    507           //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl;
    508           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    509               != BoundaryPoints[axis].end(); runner++)
    510             {
    511               //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl;
    512               // seek for the neighbours pair where the Othercomponent sign flips
    513               Neighbour = runner;
    514               Neighbour++;
    515               if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    516                 Neighbour = BoundaryPoints[axis].begin();
    517               DistanceVector.CopyVector(&runner->second.second->x);
    518               DistanceVector.SubtractVector(&Neighbour->second.second->x);
    519               do
    520                 { // seek for neighbour pair where it flips
    521                   OldComponent = DistanceVector.x[Othercomponent];
    522                   Neighbour++;
    523                   if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around
    524                     Neighbour = BoundaryPoints[axis].begin();
    525                   DistanceVector.CopyVector(&runner->second.second->x);
    526                   DistanceVector.SubtractVector(&Neighbour->second.second->x);
    527                   //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl;
    528                 }
    529               while ((runner != Neighbour) && (fabs(OldComponent / fabs(
    530                   OldComponent) - DistanceVector.x[Othercomponent] / fabs(
    531                   DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip
    532               if (runner != Neighbour)
    533                 {
    534                   OtherNeighbour = Neighbour;
    535                   if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around
    536                     OtherNeighbour = BoundaryPoints[axis].end();
    537                   OtherNeighbour--;
    538                   //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl;
    539                   // now we have found the pair: Neighbour and OtherNeighbour
    540                   OtherVector.CopyVector(&runner->second.second->x);
    541                   OtherVector.SubtractVector(&OtherNeighbour->second.second->x);
    542                   //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl;
    543                   //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl;
    544                   // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour
    545                   w1 = fabs(OtherVector.x[Othercomponent]);
    546                   w2 = fabs(DistanceVector.x[Othercomponent]);
    547                   tmp = fabs((w1 * DistanceVector.x[component] + w2
    548                       * OtherVector.x[component]) / (w1 + w2));
    549                   // mark if it has greater diameter
    550                   //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl;
    551                   GreatestDiameter[component] = (GreatestDiameter[component]
    552                       > tmp) ? GreatestDiameter[component] : tmp;
    553                 } //else
    554               //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl;
    555             }
    556         }
    557     }
    558   *out << Verbose(0) << "RESULT: The biggest diameters are "
    559       << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and "
    560       << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom"
    561       : "atomiclength") << "." << endl;
    562 
    563   // free reference lists
    564   if (BoundaryFreeFlag)
    565     delete[] (BoundaryPoints);
    566 
    567   return GreatestDiameter;
    568 }
    569 ;
    570 
    571 /** Creates the objects in a raster3d file (renderable with a header.r3d)
     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;
     570}
     571;
     572
     573/** Creates the objects in a VRML file.
    572574 * \param *out output stream for debugging
    573  * \param *tecplot output stream for tecplot data
     575 * \param *vrmlfile output stream for tecplot data
     576 * \param *Tess Tesselation structure with constructed triangles
     577 * \param *mol molecule structure with atom positions
     578 */
     579void write_vrml_file(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
     580{
     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);
     625};
     626
     627/** Creates the objects in a raster3d file (renderable with a header.r3d).
     628 * \param *out output stream for debugging
     629 * \param *rasterfile output stream for tecplot data
    574630 * \param *Tess Tesselation structure with constructed triangles
    575631 * \param *mol molecule structure with atom positions
     
    577633void write_raster3d_file(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    578634{
    579   atom *Walker = mol->start;
    580   bond *Binder = mol->first;
    581   int i;
    582   Vector *center = mol->DetermineCenterOfAll(out);
    583   if (rasterfile != NULL) {
    584     //cout << Verbose(1) << "Writing Raster3D file ... ";
    585     *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    586     *rasterfile << "@header.r3d" << endl;
    587     *rasterfile << "# All atoms as spheres" << endl;
    588     while (Walker->next != mol->end) {
    589       Walker = Walker->next;
    590       *rasterfile << "2" << endl << "  "; // 2 is sphere type
    591       for (i=0;i<NDIM;i++)
    592         *rasterfile << Walker->x.x[i]+center->x[i] << " ";
    593       *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    594     }
    595 
    596     *rasterfile << "# All bonds as vertices" << endl;
    597     while (Binder->next != mol->last) {
    598       Binder = Binder->next;
    599       *rasterfile << "3" << endl << "  "; // 2 is round-ended cylinder type
    600       for (i=0;i<NDIM;i++)
    601         *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
    602       *rasterfile << "\t0.03\t";
    603       for (i=0;i<NDIM;i++)
    604         *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
    605       *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    606     }
    607 
    608     *rasterfile << "# All tesselation triangles" << endl;
    609     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    610       *rasterfile << "1" << endl << "  "; // 1 is triangle type
    611       for (i=0;i<3;i++) { // print each node
    612         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    613           *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
    614         *rasterfile << "\t";
    615       }
    616       *rasterfile << "1. 0. 0." << endl;  // red as colour
    617       *rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    618     }
    619   } else {
    620     cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    621   }
    622   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);
    623681};
    624682
    625 /*
    626  * This function creates the tecplot file, displaying the tesselation of the hull.
     683/** This function creates the tecplot file, displaying the tesselation of the hull.
    627684 * \param *out output stream for debugging
    628685 * \param *tecplot output stream for tecplot data
     
    631688void
    632689write_tecplot_file(ofstream *out, ofstream *tecplot,
    633     class Tesselation *TesselStruct, class molecule *mol, int N)
    634 {
    635   if (tecplot != NULL)
    636     {
    637       *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    638       *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
    639       *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
    640           << TesselStruct->PointsOnBoundaryCount << ", E="
    641           << TesselStruct->TrianglesOnBoundaryCount
    642           << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    643       int *LookupList = new int[mol->AtomCount];
    644       for (int i = 0; i < mol->AtomCount; i++)
    645         LookupList[i] = -1;
    646 
    647       // print atom coordinates
    648       *out << Verbose(2) << "The following triangles were created:";
    649       int Counter = 1;
    650       atom *Walker = NULL;
    651       for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
    652           != TesselStruct->PointsOnBoundary.end(); target++)
    653         {
    654           Walker = target->second->node;
    655           LookupList[Walker->nr] = Counter++;
    656           *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
    657               << Walker->x.x[2] << " " << endl;
    658         }
    659       *tecplot << endl;
    660       // print connectivity
    661       for (TriangleMap::iterator runner =
    662           TesselStruct->TrianglesOnBoundary.begin(); runner
    663           != TesselStruct->TrianglesOnBoundary.end(); runner++)
    664         {
    665           *out << " " << runner->second->endpoints[0]->node->Name << "<->"
    666               << runner->second->endpoints[1]->node->Name << "<->"
    667               << runner->second->endpoints[2]->node->Name;
    668           *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
    669               << LookupList[runner->second->endpoints[1]->node->nr] << " "
    670               << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    671         }
    672       delete[] (LookupList);
    673       *out << endl;
    674     }
     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                }
    675732}
    676733
     
    678735 * Determines first the convex envelope, then tesselates it and calculates its volume.
    679736 * \param *out output stream for debugging
    680  * \param *tecplot output stream for tecplot data
     737 * \param *filename filename prefix for output of vertex data
    681738 * \param *configuration needed for path to store convex envelope file
    682739 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired
     
    685742 */
    686743double
    687 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration,
    688     Boundaries *BoundaryPtr, molecule *mol)
    689 {
    690   bool IsAngstroem = configuration->GetIsAngstroem();
    691   atom *Walker = NULL;
    692   struct Tesselation *TesselStruct = new Tesselation;
    693   bool BoundaryFreeFlag = false;
    694   Boundaries *BoundaryPoints = BoundaryPtr;
    695   double volume = 0.;
    696   double PyramidVolume = 0.;
    697   double G, h;
    698   Vector x, y;
    699   double a, b, c;
    700 
    701   //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
    702 
    703   // 1. calculate center of gravity
    704   *out << endl;
    705   Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    706 
    707   // 2. translate all points into CoG
    708   *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    709   Walker = mol->start;
    710   while (Walker->next != mol->end)
    711     {
    712       Walker = Walker->next;
    713       Walker->x.Translate(CenterOfGravity);
    714     }
    715 
    716   // 3. Find all points on the boundary
    717   if (BoundaryPoints == NULL)
    718     {
    719       BoundaryFreeFlag = true;
    720       BoundaryPoints = GetBoundaryPoints(out, mol);
    721     }
    722   else
    723     {
    724       *out << Verbose(1) << "Using given boundary points set." << endl;
    725     }
    726 
    727   // 4. fill the boundary point list
    728   for (int axis = 0; axis < NDIM; axis++)
    729     for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    730         != BoundaryPoints[axis].end(); runner++)
    731       {
    732         TesselStruct->AddPoint(runner->second.second);
    733       }
    734 
    735   *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
    736       << " points on the convex boundary." << endl;
    737   // now we have the whole set of edge points in the BoundaryList
    738 
    739   // listing for debugging
    740   //  *out << Verbose(1) << "Listing PointsOnBoundary:";
    741   //  for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {
    742   //    *out << " " << *runner->second;
    743   //  }
    744   //  *out << endl;
    745 
    746   // 5a. guess starting triangle
    747   TesselStruct->GuessStartingTriangle(out);
    748 
    749   // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    750   TesselStruct->TesselateOnBoundary(out, configuration, mol);
    751 
    752   *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
    753       << " triangles with " << TesselStruct->LinesOnBoundaryCount
    754       << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
    755       << endl;
    756 
    757   // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
    758   *out << Verbose(1)
    759       << "Calculating the volume of the pyramids formed out of triangles and center of gravity."
    760       << endl;
    761   for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner
    762       != TesselStruct->TrianglesOnBoundary.end(); runner++)
    763     { // go through every triangle, calculate volume of its pyramid with CoG as peak
    764       x.CopyVector(&runner->second->endpoints[0]->node->x);
    765       x.SubtractVector(&runner->second->endpoints[1]->node->x);
    766       y.CopyVector(&runner->second->endpoints[0]->node->x);
    767       y.SubtractVector(&runner->second->endpoints[2]->node->x);
    768       a = sqrt(runner->second->endpoints[0]->node->x.Distance(
    769           &runner->second->endpoints[1]->node->x));
    770       b = sqrt(runner->second->endpoints[0]->node->x.Distance(
    771           &runner->second->endpoints[2]->node->x));
    772       c = sqrt(runner->second->endpoints[2]->node->x.Distance(
    773           &runner->second->endpoints[1]->node->x));
    774       G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a
    775           * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle
    776       x.MakeNormalVector(&runner->second->endpoints[0]->node->x,
    777           &runner->second->endpoints[1]->node->x,
    778           &runner->second->endpoints[2]->node->x);
    779       x.Scale(runner->second->endpoints[1]->node->x.Projection(&x));
    780       h = x.Norm(); // distance of CoG to triangle
    781       PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
    782       *out << Verbose(2) << "Area of triangle is " << G << " "
    783           << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is "
    784           << h << " and the volume is " << PyramidVolume << " "
    785           << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    786       volume += PyramidVolume;
    787     }
    788   *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10)
    789       << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3."
    790       << endl;
    791 
    792   // 7. translate all points back from CoG
    793   *out << Verbose(1) << "Translating system back from Center of Gravity."
    794       << endl;
    795   CenterOfGravity->Scale(-1);
    796   Walker = mol->start;
    797   while (Walker->next != mol->end)
    798     {
    799       Walker = Walker->next;
    800       Walker->x.Translate(CenterOfGravity);
    801     }
    802 
    803   // 8. Store triangles in tecplot file
    804   write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
    805 
    806   // free reference lists
    807   if (BoundaryFreeFlag)
    808     delete[] (BoundaryPoints);
    809 
    810   return volume;
     744VolumeOfConvexEnvelope(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;
    811872}
    812873;
     
    822883void
    823884PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol,
    824     double ClusterVolume, double celldensity)
    825 {
    826   // transform to PAS
    827   mol->PrincipalAxisSystem(out, true);
    828 
    829   // some preparations beforehand
    830   bool IsAngstroem = configuration->GetIsAngstroem();
    831   Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
    832   double clustervolume;
    833   if (ClusterVolume == 0)
    834     clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
    835         BoundaryPoints, mol);
    836   else
    837     clustervolume = ClusterVolume;
    838   double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
    839       IsAngstroem);
    840   Vector BoxLengths;
    841   int repetition[NDIM] =
    842     { 1, 1, 1 };
    843   int TotalNoClusters = 1;
    844   for (int i = 0; i < NDIM; i++)
    845     TotalNoClusters *= repetition[i];
    846 
    847   // sum up the atomic masses
    848   double totalmass = 0.;
    849   atom *Walker = mol->start;
    850   while (Walker->next != mol->end)
    851     {
    852       Walker = Walker->next;
    853       totalmass += Walker->type->mass;
    854     }
    855   *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10)
    856       << totalmass << " atomicmassunit." << endl;
    857 
    858   *out << Verbose(0) << "RESULT: The average density is " << setprecision(10)
    859       << totalmass / clustervolume << " atomicmassunit/"
    860       << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl;
    861 
    862   // solve cubic polynomial
    863   *out << Verbose(1) << "Solving equidistant suspension in water problem ..."
    864       << endl;
    865   double cellvolume;
    866   if (IsAngstroem)
    867     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass
    868         / clustervolume)) / (celldensity - 1);
    869   else
    870     cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass
    871         / clustervolume)) / (celldensity - 1);
    872   *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity
    873       << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom"
    874       : "atomiclength") << "^3." << endl;
    875 
    876   double minimumvolume = TotalNoClusters * (GreatestDiameter[0]
    877       * GreatestDiameter[1] * GreatestDiameter[2]);
    878   *out << Verbose(1)
    879       << "Minimum volume of the convex envelope contained in a rectangular box is "
    880       << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom"
    881       : "atomiclength") << "^3." << endl;
    882   if (minimumvolume > cellvolume)
    883     {
    884       cerr << Verbose(0)
    885           << "ERROR: the containing box already has a greater volume than the envisaged cell volume!"
    886           << endl;
    887       cout << Verbose(0)
    888           << "Setting Box dimensions to minimum possible, the greatest diameters."
    889           << endl;
    890       for (int i = 0; i < NDIM; i++)
    891         BoxLengths.x[i] = GreatestDiameter[i];
    892       mol->CenterEdge(out, &BoxLengths);
    893     }
    894   else
    895     {
    896       BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1]
    897           * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]);
    898       BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0]
    899           * GreatestDiameter[1] + repetition[0] * repetition[2]
    900           * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1]
    901           * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]);
    902       BoxLengths.x[2] = minimumvolume - cellvolume;
    903       double x0 = 0., x1 = 0., x2 = 0.;
    904       if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1],
    905           BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return
    906         *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0
    907             << " ." << endl;
    908       else
    909         {
    910           *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0
    911               << " and " << x1 << " and " << x2 << " ." << endl;
    912           x0 = x2; // sorted in ascending order
    913         }
    914 
    915       cellvolume = 1;
    916       for (int i = 0; i < NDIM; i++)
    917         {
    918           BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]);
    919           cellvolume *= BoxLengths.x[i];
    920         }
    921 
    922       // set new box dimensions
    923       *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    924       mol->CenterInBox((ofstream *) &cout, &BoxLengths);
    925     }
    926   // update Box of atoms by boundary
    927   mol->SetBoxDimension(&BoxLengths);
    928   *out << Verbose(0) << "RESULT: The resulting cell dimensions are: "
    929       << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and "
    930       << BoxLengths.x[2] << " with total volume of " << cellvolume << " "
    931       << (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;
    932993}
    933994;
     
    9391000Tesselation::Tesselation()
    9401001{
    941   PointsOnBoundaryCount = 0;
    942   LinesOnBoundaryCount = 0;
    943   TrianglesOnBoundaryCount = 0;
    944   TriangleFilesWritten = 0;
     1002        PointsOnBoundaryCount = 0;
     1003        LinesOnBoundaryCount = 0;
     1004        TrianglesOnBoundaryCount = 0;
     1005        TriangleFilesWritten = 0;
    9451006}
    9461007;
     
    9511012Tesselation::~Tesselation()
    9521013{
    953   cout << Verbose(1) << "Free'ing TesselStruct ... " << endl;
    954   for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner
    955       != TrianglesOnBoundary.end(); runner++)
    956     {
    957       delete (runner->second);
    958     }
     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        }
    9591022}
    9601023;
     
    9681031Tesselation::GuessStartingTriangle(ofstream *out)
    9691032{
    970   // 4b. create a starting triangle
    971   // 4b1. create all distances
    972   DistanceMultiMap DistanceMMap;
    973   double distance, tmp;
    974   Vector PlaneVector, TrialVector;
    975   PointMap::iterator A, B, C; // three nodes of the first triangle
    976   A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily
    977 
    978   // with A chosen, take each pair B,C and sort
    979   if (A != PointsOnBoundary.end())
    980     {
    981       B = A;
    982       B++;
    983       for (; B != PointsOnBoundary.end(); B++)
    984         {
    985           C = B;
    986           C++;
    987           for (; C != PointsOnBoundary.end(); C++)
    988             {
    989               tmp = A->second->node->x.Distance(&B->second->node->x);
    990               distance = tmp * tmp;
    991               tmp = A->second->node->x.Distance(&C->second->node->x);
    992               distance += tmp * tmp;
    993               tmp = B->second->node->x.Distance(&C->second->node->x);
    994               distance += tmp * tmp;
    995               DistanceMMap.insert(DistanceMultiMapPair(distance, pair<
    996                   PointMap::iterator, PointMap::iterator> (B, C)));
    997             }
    998         }
    999     }
    1000   //    // listing distances
    1001   //    *out << Verbose(1) << "Listing DistanceMMap:";
    1002   //    for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) {
    1003   //      *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")";
    1004   //    }
    1005   //    *out << endl;
    1006   // 4b2. pick three baselines forming a triangle
    1007   // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1008   DistanceMultiMap::iterator baseline = DistanceMMap.begin();
    1009   for (; baseline != DistanceMMap.end(); baseline++)
    1010     {
    1011       // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate
    1012       // 2. next, we have to check whether all points reside on only one side of the triangle
    1013       // 3. construct plane vector
    1014       PlaneVector.MakeNormalVector(&A->second->node->x,
    1015           &baseline->second.first->second->node->x,
    1016           &baseline->second.second->second->node->x);
    1017       *out << Verbose(2) << "Plane vector of candidate triangle is ";
    1018       PlaneVector.Output(out);
    1019       *out << endl;
    1020       // 4. loop over all points
    1021       double sign = 0.;
    1022       PointMap::iterator checker = PointsOnBoundary.begin();
    1023       for (; checker != PointsOnBoundary.end(); checker++)
    1024         {
    1025           // (neglecting A,B,C)
    1026           if ((checker == A) || (checker == baseline->second.first) || (checker
    1027               == baseline->second.second))
    1028             continue;
    1029           // 4a. project onto plane vector
    1030           TrialVector.CopyVector(&checker->second->node->x);
    1031           TrialVector.SubtractVector(&A->second->node->x);
    1032           distance = TrialVector.Projection(&PlaneVector);
    1033           if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok
    1034             continue;
    1035           *out << Verbose(3) << "Projection of " << checker->second->node->Name
    1036               << " yields distance of " << distance << "." << endl;
    1037           tmp = distance / fabs(distance);
    1038           // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle)
    1039           if ((sign != 0) && (tmp != sign))
    1040             {
    1041               // 4c. If so, break 4. loop and continue with next candidate in 1. loop
    1042               *out << Verbose(2) << "Current candidates: "
    1043                   << A->second->node->Name << ","
    1044                   << baseline->second.first->second->node->Name << ","
    1045                   << baseline->second.second->second->node->Name << " leave "
    1046                   << checker->second->node->Name << " outside the convex hull."
    1047                   << endl;
    1048               break;
    1049             }
    1050           else
    1051             { // note the sign for later
    1052               *out << Verbose(2) << "Current candidates: "
    1053                   << A->second->node->Name << ","
    1054                   << baseline->second.first->second->node->Name << ","
    1055                   << baseline->second.second->second->node->Name << " leave "
    1056                   << checker->second->node->Name << " inside the convex hull."
    1057                   << endl;
    1058               sign = tmp;
    1059             }
    1060           // 4d. Check whether the point is inside the triangle (check distance to each node
    1061           tmp = checker->second->node->x.Distance(&A->second->node->x);
    1062           int innerpoint = 0;
    1063           if ((tmp < A->second->node->x.Distance(
    1064               &baseline->second.first->second->node->x)) && (tmp
    1065               < A->second->node->x.Distance(
    1066                   &baseline->second.second->second->node->x)))
    1067             innerpoint++;
    1068           tmp = checker->second->node->x.Distance(
    1069               &baseline->second.first->second->node->x);
    1070           if ((tmp < baseline->second.first->second->node->x.Distance(
    1071               &A->second->node->x)) && (tmp
    1072               < baseline->second.first->second->node->x.Distance(
    1073                   &baseline->second.second->second->node->x)))
    1074             innerpoint++;
    1075           tmp = checker->second->node->x.Distance(
    1076               &baseline->second.second->second->node->x);
    1077           if ((tmp < baseline->second.second->second->node->x.Distance(
    1078               &baseline->second.first->second->node->x)) && (tmp
    1079               < baseline->second.second->second->node->x.Distance(
    1080                   &A->second->node->x)))
    1081             innerpoint++;
    1082           // 4e. If so, break 4. loop and continue with next candidate in 1. loop
    1083           if (innerpoint == 3)
    1084             break;
    1085         }
    1086       // 5. come this far, all on same side? Then break 1. loop and construct triangle
    1087       if (checker == PointsOnBoundary.end())
    1088         {
    1089           *out << "Looks like we have a candidate!" << endl;
    1090           break;
    1091         }
    1092     }
    1093   if (baseline != DistanceMMap.end())
    1094     {
    1095       BPS[0] = baseline->second.first->second;
    1096       BPS[1] = baseline->second.second->second;
    1097       BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1098       BPS[0] = A->second;
    1099       BPS[1] = baseline->second.second->second;
    1100       BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1101       BPS[0] = baseline->second.first->second;
    1102       BPS[1] = A->second;
    1103       BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1104 
    1105       // 4b3. insert created triangle
    1106       BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    1107       TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1108       TrianglesOnBoundaryCount++;
    1109       for (int i = 0; i < NDIM; i++)
    1110         {
    1111           LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i]));
    1112           LinesOnBoundaryCount++;
    1113         }
    1114 
    1115       *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl;
    1116     }
    1117   else
    1118     {
    1119       *out << Verbose(1) << "No starting triangle found." << endl;
    1120       exit(255);
    1121     }
     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                }
    11221185}
    11231186;
     
    11281191 * -# if the lines contains to only one triangle
    11291192 * -# We search all points in the boundary
    1130  *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
    1131  *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
    1132  *      baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
    1133  *    -# 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)
    11341197 * \param *out output stream for debugging
    11351198 * \param *configuration for IsAngstroem
     
    11381201void
    11391202Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    1140     molecule *mol)
    1141 {
    1142   bool flag;
    1143   PointMap::iterator winner;
    1144   class BoundaryPointSet *peak = NULL;
    1145   double SmallestAngle, TempAngle;
    1146   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
    1147       PropagationVector;
    1148   LineMap::iterator LineChecker[2];
    1149   do
    1150     {
    1151       flag = false;
    1152       for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
    1153           != LinesOnBoundary.end(); baseline++)
    1154         if (baseline->second->TrianglesCount == 1)
    1155           {
    1156             *out << Verbose(2) << "Current baseline is between "
    1157                 << *(baseline->second) << "." << endl;
    1158             // 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)
    1159             SmallestAngle = M_PI;
    1160             BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1161             // get peak point with respect to this base line's only triangle
    1162             for (int i = 0; i < 3; i++)
    1163               if ((BTS->endpoints[i] != baseline->second->endpoints[0])
    1164                   && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1165                 peak = BTS->endpoints[i];
    1166             *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1167             // normal vector of triangle
    1168             BTS->GetNormalVector(NormalVector);
    1169             *out << Verbose(4) << "NormalVector of base triangle is ";
    1170             NormalVector.Output(out);
    1171             *out << endl;
    1172             // offset to center of triangle
    1173             CenterVector.Zero();
    1174             for (int i = 0; i < 3; i++)
    1175               CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1176             CenterVector.Scale(1. / 3.);
    1177             *out << Verbose(4) << "CenterVector of base triangle is ";
    1178             CenterVector.Output(out);
    1179             *out << endl;
    1180             // vector in propagation direction (out of triangle)
    1181             // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
    1182             TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1183             TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1184             PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
    1185             TempVector.CopyVector(&CenterVector);
    1186             TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1187             //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1188             if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1189               PropagationVector.Scale(-1.);
    1190             *out << Verbose(4) << "PropagationVector of base triangle is ";
    1191             PropagationVector.Output(out);
    1192             *out << endl;
    1193             winner = PointsOnBoundary.end();
    1194             for (PointMap::iterator target = PointsOnBoundary.begin(); target
    1195                 != PointsOnBoundary.end(); target++)
    1196               if ((target->second != baseline->second->endpoints[0])
    1197                   && (target->second != baseline->second->endpoints[1]))
    1198                 { // don't take the same endpoints
    1199                   *out << Verbose(3) << "Target point is " << *(target->second)
    1200                       << ":";
    1201                   bool continueflag = true;
    1202 
    1203                   VirtualNormalVector.CopyVector(
    1204                       &baseline->second->endpoints[0]->node->x);
    1205                   VirtualNormalVector.AddVector(
    1206                       &baseline->second->endpoints[0]->node->x);
    1207                   VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
    1208                   VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
    1209                   TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1210                   continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
    1211                   if (!continueflag)
    1212                     {
    1213                       *out << Verbose(4)
    1214                           << "Angle between propagation direction and base line to "
    1215                           << *(target->second) << " is " << TempAngle
    1216                           << ", bad direction!" << endl;
    1217                       continue;
    1218                     }
    1219                   else
    1220                     *out << Verbose(4)
    1221                         << "Angle between propagation direction and base line to "
    1222                         << *(target->second) << " is " << TempAngle
    1223                         << ", good direction!" << endl;
    1224                   LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1225                       target->first);
    1226                   LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1227                       target->first);
    1228                   //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
    1229                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1230                   //            else
    1231                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1232                   //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
    1233                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1234                   //            else
    1235                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1236                   // check first endpoint (if any connecting line goes to target or at least not more than 1)
    1237                   continueflag = continueflag && (((LineChecker[0]
    1238                       == baseline->second->endpoints[0]->lines.end())
    1239                       || (LineChecker[0]->second->TrianglesCount == 1)));
    1240                   if (!continueflag)
    1241                     {
    1242                       *out << Verbose(4) << *(baseline->second->endpoints[0])
    1243                           << " has line " << *(LineChecker[0]->second)
    1244                           << " to " << *(target->second)
    1245                           << " as endpoint with "
    1246                           << LineChecker[0]->second->TrianglesCount
    1247                           << " triangles." << endl;
    1248                       continue;
    1249                     }
    1250                   // check second endpoint (if any connecting line goes to target or at least not more than 1)
    1251                   continueflag = continueflag && (((LineChecker[1]
    1252                       == baseline->second->endpoints[1]->lines.end())
    1253                       || (LineChecker[1]->second->TrianglesCount == 1)));
    1254                   if (!continueflag)
    1255                     {
    1256                       *out << Verbose(4) << *(baseline->second->endpoints[1])
    1257                           << " has line " << *(LineChecker[1]->second)
    1258                           << " to " << *(target->second)
    1259                           << " as endpoint with "
    1260                           << LineChecker[1]->second->TrianglesCount
    1261                           << " triangles." << endl;
    1262                       continue;
    1263                     }
    1264                   // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1265                   continueflag = continueflag && (!(((LineChecker[0]
    1266                       != baseline->second->endpoints[0]->lines.end())
    1267                       && (LineChecker[1]
    1268                           != baseline->second->endpoints[1]->lines.end())
    1269                       && (GetCommonEndpoint(LineChecker[0]->second,
    1270                           LineChecker[1]->second) == peak))));
    1271                   if (!continueflag)
    1272                     {
    1273                       *out << Verbose(4) << "Current target is peak!" << endl;
    1274                       continue;
    1275                     }
    1276                   // in case NOT both were found
    1277                   if (continueflag)
    1278                     { // create virtually this triangle, get its normal vector, calculate angle
    1279                       flag = true;
    1280                       VirtualNormalVector.MakeNormalVector(
    1281                           &baseline->second->endpoints[0]->node->x,
    1282                           &baseline->second->endpoints[1]->node->x,
    1283                           &target->second->node->x);
    1284                       // make it always point inward
    1285                       if (baseline->second->endpoints[0]->node->x.Projection(
    1286                           &VirtualNormalVector) > 0)
    1287                         VirtualNormalVector.Scale(-1.);
    1288                       // calculate angle
    1289                       TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1290                       *out << Verbose(4) << "NormalVector is ";
    1291                       VirtualNormalVector.Output(out);
    1292                       *out << " and the angle is " << TempAngle << "." << endl;
    1293                       if (SmallestAngle > TempAngle)
    1294                         { // set to new possible winner
    1295                           SmallestAngle = TempAngle;
    1296                           winner = target;
    1297                         }
    1298                     }
    1299                 }
    1300             // 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
    1301             if (winner != PointsOnBoundary.end())
    1302               {
    1303                 *out << Verbose(2) << "Winning target point is "
    1304                     << *(winner->second) << " with angle " << SmallestAngle
    1305                     << "." << endl;
    1306                 // create the lins of not yet present
    1307                 BLS[0] = baseline->second;
    1308                 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1309                 LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1310                     winner->first);
    1311                 LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1312                     winner->first);
    1313                 if (LineChecker[0]
    1314                     == baseline->second->endpoints[0]->lines.end())
    1315                   { // create
    1316                     BPS[0] = baseline->second->endpoints[0];
    1317                     BPS[1] = winner->second;
    1318                     BLS[1] = new class BoundaryLineSet(BPS,
    1319                         LinesOnBoundaryCount);
    1320                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1321                         BLS[1]));
    1322                     LinesOnBoundaryCount++;
    1323                   }
    1324                 else
    1325                   BLS[1] = LineChecker[0]->second;
    1326                 if (LineChecker[1]
    1327                     == baseline->second->endpoints[1]->lines.end())
    1328                   { // create
    1329                     BPS[0] = baseline->second->endpoints[1];
    1330                     BPS[1] = winner->second;
    1331                     BLS[2] = new class BoundaryLineSet(BPS,
    1332                         LinesOnBoundaryCount);
    1333                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1334                         BLS[2]));
    1335                     LinesOnBoundaryCount++;
    1336                   }
    1337                 else
    1338                   BLS[2] = LineChecker[1]->second;
    1339                 BTS = new class BoundaryTriangleSet(BLS,
    1340                     TrianglesOnBoundaryCount);
    1341                 TrianglesOnBoundary.insert(TrianglePair(
    1342                     TrianglesOnBoundaryCount, BTS));
    1343                 TrianglesOnBoundaryCount++;
    1344               }
    1345             else
    1346               {
    1347                 *out << Verbose(1)
    1348                     << "I could not determine a winner for this baseline "
    1349                     << *(baseline->second) << "." << endl;
    1350               }
    1351 
    1352             // 5d. If the set of lines is not yet empty, go to 5. and continue
    1353           }
    1354         else
    1355           *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
    1356               << " has a triangle count of "
    1357               << baseline->second->TrianglesCount << "." << endl;
    1358     }
    1359   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);
    13601423
    13611424}
     
    13681431Tesselation::AddPoint(atom *Walker)
    13691432{
    1370   PointTestPair InsertUnique;
    1371   BPS[0] = new class BoundaryPointSet(Walker);
    1372   InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1373   if (InsertUnique.second) // if new point was not present before, increase counter
    1374     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++;
    13751438}
    13761439;
     
    13841447Tesselation::AddTrianglePoint(atom* Candidate, int n)
    13851448{
    1386   PointTestPair InsertUnique;
    1387   TPS[n] = new class BoundaryPointSet(Candidate);
    1388   InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n]));
    1389   if (InsertUnique.second) // if new point was not present before, increase counter
    1390     {
    1391       PointsOnBoundaryCount++;
    1392     }
    1393   else
    1394     {
    1395       delete TPS[n];
    1396       cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node)
    1397           << " gibt's schon in der PointMap." << endl;
    1398       TPS[n] = (InsertUnique.first)->second;
    1399     }
     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                }
    14001463}
    14011464;
     
    14101473void
    14111474Tesselation::AddTriangleLine(class BoundaryPointSet *a,
    1412     class BoundaryPointSet *b, int n)
    1413 {
    1414   LineMap::iterator LineWalker;
    1415   //cout << "Manually checking endpoints for line." << endl;
    1416   if ((a->lines.find(b->node->nr))->first == b->node->nr)
    1417   //If a line is there, how do I recognize that beyond a shadow of a doubt?
    1418     {
    1419       //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl;
    1420 
    1421       LineWalker = LinesOnBoundary.end();
    1422       LineWalker--;
    1423 
    1424       while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr,
    1425           b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max(
    1426           a->node->nr, b->node->nr))
    1427         {
    1428           //cout << Verbose(1) << "Looking for line which already exists"<< endl;
    1429           LineWalker--;
    1430         }
    1431       BPS[0] = LineWalker->second->endpoints[0];
    1432       BPS[1] = LineWalker->second->endpoints[1];
    1433       BLS[n] = LineWalker->second;
    1434 
    1435     }
    1436   else
    1437     {
    1438       cout << Verbose(2)
    1439           << "Adding line which has not been used before between "
    1440           << *(a->node) << " and " << *(b->node) << "." << endl;
    1441       BPS[0] = a;
    1442       BPS[1] = b;
    1443       BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
    1444 
    1445       LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n]));
    1446       LinesOnBoundaryCount++;
    1447 
    1448     }
     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                }
    14491512}
    14501513;
     
    14571520{
    14581521
    1459   cout << Verbose(1) << "Adding triangle to its lines" << endl;
    1460   int i = 0;
    1461   TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    1462   TrianglesOnBoundaryCount++;
    1463 
    1464   /*
    1465    * this is apparently done when constructing triangle
    1466 
    1467    for (i=0; i<3; i++)
    1468    {
    1469    BLS[i]->AddTriangle(BTS);
    1470    }
    1471    */
    1472 }
    1473 ;
     1522        cout << Verbose(1) << "Adding triangle to its lines" << endl;
     1523        int i = 0;
     1524        TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1525        TrianglesOnBoundaryCount++;
     1526
     1527        /*
     1528         * this is apparently done when constructing triangle
     1529
     1530         for (i=0; i<3; i++)
     1531         {
     1532         BLS[i]->AddTriangle(BTS);
     1533         }
     1534         */
     1535}
     1536;
     1537
     1538
     1539double det_get(gsl_matrix *A, int inPlace) {
     1540        /*
     1541        inPlace = 1 => A is replaced with the LU decomposed copy.
     1542        inPlace = 0 => A is retained, and a copy is used for LU.
     1543        */
     1544
     1545        double det;
     1546        int signum;
     1547        gsl_permutation *p = gsl_permutation_alloc(A->size1);
     1548        gsl_matrix *tmpA;
     1549
     1550        if (inPlace)
     1551        tmpA = A;
     1552        else {
     1553        gsl_matrix *tmpA = gsl_matrix_alloc(A->size1, A->size2);
     1554        gsl_matrix_memcpy(tmpA , A);
     1555        }
     1556
     1557
     1558        gsl_linalg_LU_decomp(tmpA , p , &signum);
     1559        det = gsl_linalg_LU_det(tmpA , signum);
     1560        gsl_permutation_free(p);
     1561        if (! inPlace)
     1562        gsl_matrix_free(tmpA);
     1563
     1564        return det;
     1565};
     1566
     1567void get_sphere(Vector *center, Vector &a, Vector &b, Vector &c, double RADIUS)
     1568{
     1569        gsl_matrix *A = gsl_matrix_calloc(3,3);
     1570        double m11, m12, m13, m14;
     1571
     1572        for(int i=0;i<3;i++) {
     1573                gsl_matrix_set(A, i, 0, a.x[i]);
     1574                gsl_matrix_set(A, i, 1, b.x[i]);
     1575                gsl_matrix_set(A, i, 2, c.x[i]);
     1576        }
     1577        m11 = det_get(A, 1);
     1578
     1579        for(int i=0;i<3;i++) {
     1580                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1581                gsl_matrix_set(A, i, 1, b.x[i]);
     1582                gsl_matrix_set(A, i, 2, c.x[i]);
     1583        }
     1584        m12 = det_get(A, 1);
     1585
     1586        for(int i=0;i<3;i++) {
     1587                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1588                gsl_matrix_set(A, i, 1, a.x[i]);
     1589                gsl_matrix_set(A, i, 2, c.x[i]);
     1590        }
     1591        m13 = det_get(A, 1);
     1592
     1593        for(int i=0;i<3;i++) {
     1594                gsl_matrix_set(A, i, 0, a.x[i]*a.x[i] + b.x[i]*b.x[i] + c.x[i]*c.x[i]);
     1595                gsl_matrix_set(A, i, 1, a.x[i]);
     1596                gsl_matrix_set(A, i, 2, b.x[i]);
     1597        }
     1598        m14 = det_get(A, 1);
     1599
     1600        if (fabs(m11) < MYEPSILON)
     1601                cerr << "ERROR: three points are colinear." << endl;
     1602
     1603        center->x[0] =  0.5 * m12/ m11;
     1604        center->x[1] = -0.5 * m13/ m11;
     1605        center->x[2] =  0.5 * m14/ m11;
     1606
     1607        if (fabs(a.Distance(center) - RADIUS) > MYEPSILON)
     1608                cerr << "ERROR: The given center is further way by " << fabs(a.Distance(center) - RADIUS) << " from a than RADIUS." << endl;
     1609
     1610        gsl_matrix_free(A);
     1611};
     1612
     1613
    14741614
    14751615/**
     
    14891629 * @param Umkreisradius double radius of circumscribing circle
    14901630 */
    1491 
    1492   void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector* Direction, Vector* AlternativeDirection,
    1493       double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
    1494   {
    1495     Vector TempNormal, helper;
    1496     double Restradius;
    1497 
    1498     *Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
    1499     Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
    1500     // Here we calculated center of circumscribing circle, using barycentric coordinates
    1501 
    1502     TempNormal.CopyVector(&a);
    1503     TempNormal.SubtractVector(&b);
    1504     helper.CopyVector(&a);
    1505     helper.SubtractVector(&c);
    1506     TempNormal.VectorProduct(&helper);
    1507     if (fabs(HalfplaneIndicator) < MYEPSILON)
    1508       {
    1509         if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
    1510           {
    1511             TempNormal.Scale(-1);
    1512           }
    1513       }
    1514     else
    1515       {
    1516         if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
    1517           {
    1518             TempNormal.Scale(-1);
    1519           }
    1520       }
    1521 
    1522     TempNormal.Normalize();
    1523     Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1524     TempNormal.Scale(Restradius);
    1525 
    1526     Center->AddVector(&TempNormal);
    1527   }
    1528   ;
    1529 
     1631void Get_center_of_sphere(Vector* Center, Vector a, Vector b, Vector c, Vector *NewUmkreismittelpunkt, Vector* Direction, Vector* AlternativeDirection,
     1632                double HalfplaneIndicator, double AlternativeIndicator, double alpha, double beta, double gamma, double RADIUS, double Umkreisradius)
     1633{
     1634        Vector TempNormal, helper;
     1635        double Restradius;
     1636        Vector OtherCenter;
     1637        cout << Verbose(3) << "Begin of Get_center_of_sphere.\n";
     1638        Center->Zero();
     1639        helper.CopyVector(&a);
     1640        helper.Scale(sin(2.*alpha));
     1641        Center->AddVector(&helper);
     1642        helper.CopyVector(&b);
     1643        helper.Scale(sin(2.*beta));
     1644        Center->AddVector(&helper);
     1645        helper.CopyVector(&c);
     1646        helper.Scale(sin(2.*gamma));
     1647        Center->AddVector(&helper);
     1648        //*Center = a * sin(2.*alpha) + b * sin(2.*beta) + c * sin(2.*gamma) ;
     1649        Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1650        NewUmkreismittelpunkt->CopyVector(Center);
     1651        cout << Verbose(4) << "Center of new circumference is " << *NewUmkreismittelpunkt << ".\n";
     1652        // Here we calculated center of circumscribing circle, using barycentric coordinates
     1653        cout << Verbose(4) << "Center of circumference is " << *Center << " in direction " << *Direction << ".\n";
     1654
     1655        TempNormal.CopyVector(&a);
     1656        TempNormal.SubtractVector(&b);
     1657        helper.CopyVector(&a);
     1658        helper.SubtractVector(&c);
     1659        TempNormal.VectorProduct(&helper);
     1660        if (fabs(HalfplaneIndicator) < MYEPSILON)
     1661                {
     1662                        if ((TempNormal.ScalarProduct(AlternativeDirection) <0 and AlternativeIndicator >0) or (TempNormal.ScalarProduct(AlternativeDirection) >0 and AlternativeIndicator <0))
     1663                                {
     1664                                        TempNormal.Scale(-1);
     1665                                }
     1666                }
     1667        else
     1668                {
     1669                        if (TempNormal.ScalarProduct(Direction)<0 && HalfplaneIndicator >0 || TempNormal.ScalarProduct(Direction)>0 && HalfplaneIndicator<0)
     1670                                {
     1671                                        TempNormal.Scale(-1);
     1672                                }
     1673                }
     1674
     1675        TempNormal.Normalize();
     1676        Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
     1677        cout << Verbose(4) << "Height of center of circumference to center of sphere is " << Restradius << ".\n";
     1678        TempNormal.Scale(Restradius);
     1679        cout << Verbose(4) << "Shift vector to sphere of circumference is " << TempNormal << ".\n";
     1680
     1681        Center->AddVector(&TempNormal);
     1682        cout << Verbose(0) << "Center of sphere of circumference is " << *Center << ".\n";
     1683        get_sphere(&OtherCenter, a, b, c, RADIUS);
     1684        cout << Verbose(0) << "OtherCenter of sphere of circumference is " << OtherCenter << ".\n";
     1685        cout << Verbose(3) << "End of Get_center_of_sphere.\n";
     1686};
    15301687
    15311688/** This recursive function finds a third point, to form a triangle with two given ones.
    15321689 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1533  *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1534  *  upon which we operate.
    1535  *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1536  *  direction and angle into Storage.
    1537  *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1538  *  with all neighbours of the candidate.
     1690 *      supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
     1691 *      upon which we operate.
     1692 *      If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
     1693 *      direction and angle into Storage.
     1694 *      We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
     1695 *      with all neighbours of the candidate.
    15391696 * @param a first point
    15401697 * @param b second point
     
    15521709 * @param mol molecule structure with atoms and bonds
    15531710 */
    1554 
    1555 void Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
    1556     int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
    1557     atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
    1558 {
    1559   //cout << "ReferencePoint is " << ReferencePoint.x[0] << " "<< ReferencePoint.x[1] << " "<< ReferencePoint.x[2] << " "<< endl;
    1560   /* OldNormal is normal vector on the old triangle
    1561    * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1562    * Chord points from b to a!!!
    1563    */
    1564   Vector dif_a; //Vector from a to candidate
    1565   Vector dif_b; //Vector from b to candidate
    1566   Vector AngleCheck;
    1567   Vector TempNormal, Umkreismittelpunkt;
    1568   Vector Mittelpunkt;
    1569 
    1570   double CurrentEpsilon = 0.1;
    1571   double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1572   double BallAngle, AlternativeSign;
    1573   atom *Walker; // variable atom point
    1574 
    1575 
    1576   dif_a.CopyVector(&(a->x));
    1577   dif_a.SubtractVector(&(Candidate->x));
    1578   dif_b.CopyVector(&(b->x));
    1579   dif_b.SubtractVector(&(Candidate->x));
    1580   AngleCheck.CopyVector(&(Candidate->x));
    1581   AngleCheck.SubtractVector(&(a->x));
    1582   AngleCheck.ProjectOntoPlane(Chord);
    1583 
    1584   SideA = dif_b.Norm();
    1585   SideB = dif_a.Norm();
    1586   SideC = Chord->Norm();
    1587   //Chord->Scale(-1);
    1588 
    1589   alpha = Chord->Angle(&dif_a);
    1590   beta = M_PI - Chord->Angle(&dif_b);
    1591   gamma = dif_a.Angle(&dif_b);
    1592 
    1593 
    1594   if (a != Candidate and b != Candidate and c != Candidate)
    1595     {
    1596 
    1597       Umkreisradius = SideA / 2.0 / sin(alpha);
    1598       //cout << Umkreisradius << endl;
    1599       //cout << SideB / 2.0 / sin(beta) << endl;
    1600       //cout << SideC / 2.0 / sin(gamma) << endl;
    1601 
    1602       if (Umkreisradius < RADIUS) //Checking whether ball will at least rest on points.
    1603         {
    1604           cout << Verbose(1) << "Candidate is "<< *Candidate << endl;
    1605           sign = AngleCheck.ScalarProduct(direction1);
    1606           if (fabs(sign)<MYEPSILON)
    1607             {
    1608               if (AngleCheck.ScalarProduct(OldNormal)<0)
    1609                 {
    1610                   sign =0;
    1611                   AlternativeSign=1;
    1612                 }
    1613               else
    1614                 {
    1615                   sign =0;
    1616                   AlternativeSign=-1;
    1617                 }
    1618             }
    1619           else
    1620             {
    1621               sign /= fabs(sign);
    1622             }
    1623 
    1624 
    1625 
    1626           Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
    1627 
    1628           AngleCheck.CopyVector(&ReferencePoint);
    1629           AngleCheck.Scale(-1);
    1630           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1631           AngleCheck.AddVector(&Mittelpunkt);
    1632           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1633 
    1634           BallAngle = AngleCheck.Angle(OldNormal);
    1635 
    1636           //cout << "direction1 is " << direction1->x[0] <<" "<< direction1->x[1] <<" "<< direction1->x[2] <<" " << endl;
    1637           //cout << "AngleCheck is " << AngleCheck.x[0] << " "<< AngleCheck.x[1] << " "<< AngleCheck.x[2] << " "<< endl;
    1638 
    1639           cout << Verbose(1) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
    1640 
    1641           if (AngleCheck.ScalarProduct(direction1) >=0)
    1642             {
    1643               if (Storage[0]< -1.5) // first Candidate at all
    1644                 {
    1645 
    1646                   cout << "Next better candidate is " << *Candidate << " with ";
    1647                   Opt_Candidate = Candidate;
    1648                   Storage[0] = sign;
    1649                   Storage[1] = AlternativeSign;
    1650                   Storage[2] = BallAngle;
    1651                   cout << "Angle is " << Storage[2] << ", Halbraum ist "
    1652                     << Storage[0] << endl;
    1653 
    1654 
    1655                 }
    1656               else
    1657                 {
    1658                   if ( Storage[2] > BallAngle)
    1659                     {
    1660                       cout << "Next better candidate is " << *Candidate << " with ";
    1661                       Opt_Candidate = Candidate;
    1662                       Storage[0] = sign;
    1663                       Storage[1] = AlternativeSign;
    1664                       Storage[2] = BallAngle;
    1665                       cout << "Angle is " << Storage[2] << ", Halbraum ist "
    1666                         << Storage[0] << endl;
    1667                     }
    1668                   else
    1669                     {
    1670                       //if (DEBUG)
    1671                         cout << "Looses to better candidate" << endl;
    1672 
    1673                     }
    1674                 }
    1675               }
    1676             else
    1677               {
    1678                 //if (DEBUG)
    1679                   cout << "Refused due to bad direction of ball centre." << endl;
    1680               }
    1681           }
    1682         else
    1683           {
    1684             //if (DEBUG)
    1685               cout << "Doesn't satisfy requirements for circumscribing circle" << endl;
    1686           }
    1687       }
    1688     else
    1689       {
    1690         //if (DEBUG)
    1691           cout << "identisch mit Ursprungslinie" << endl;
    1692 
    1693       }
    1694 
    1695 
    1696 
    1697   if (RecursionLevel < 9) // Seven is the recursion level threshold.
    1698     {
    1699       for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond
    1700         {
    1701           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    1702               Candidate);
    1703           if (Walker == Parent)
    1704             { // don't go back the same bond
    1705               continue;
    1706             }
    1707           else
    1708             {
    1709               Find_next_suitable_point_via_Angle_of_Sphere(a, b, c, Walker, Candidate, RecursionLevel
    1710                   + 1, Chord, direction1, OldNormal, ReferencePoint, Opt_Candidate, Storage, RADIUS,
    1711                   mol); //call function again
    1712             }
    1713         }
    1714     }
    1715 }
    1716 ;
    1717 
    1718 
    1719   /** This recursive function finds a third point, to form a triangle with two given ones.
    1720    * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \
    1721    *  supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \
    1722    *  upon which we operate.
    1723    *  If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \
    1724    *  direction and angle into Storage.
    1725    *  We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \
    1726    *  with all neighbours of the candidate.
    1727    * @param a first point
    1728    * @param b second point
    1729    * @param Candidate base point along whose bonds to start looking from
    1730    * @param Parent point to avoid during search as its wrong direction
    1731    * @param RecursionLevel contains current recursion depth
    1732    * @param Chord baseline vector of first and second point
    1733    * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to
    1734    * @param OldNormal normal of the triangle which the baseline belongs to
    1735    * @param Opt_Candidate candidate reference to return
    1736    * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate
    1737    * @param Storage array containing two angles of current Opt_Candidate
    1738    * @param RADIUS radius of ball
    1739    * @param mol molecule structure with atoms and bonds
    1740    */
    1741 
    1742 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent,
    1743     int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal,
    1744     atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol)
    1745 {
    1746   /* OldNormal is normal vector on the old triangle
    1747    * d1 is normal on the triangle line, from which we come, as well as on OldNormal.
    1748    * Chord points from b to a!!!
    1749    */
    1750   Vector dif_a; //Vector from a to candidate
    1751   Vector dif_b; //Vector from b to candidate
    1752   Vector AngleCheck, AngleCheckReference, DirectionCheckPoint;
    1753   Vector TempNormal, Umkreismittelpunkt, Mittelpunkt;
    1754 
    1755   double CurrentEpsilon = 0.1;
    1756   double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
    1757   double BallAngle;
    1758   atom *Walker; // variable atom point
    1759 
    1760 
    1761   dif_a.CopyVector(&(a->x));
    1762   dif_a.SubtractVector(&(Candidate->x));
    1763   dif_b.CopyVector(&(b->x));
    1764   dif_b.SubtractVector(&(Candidate->x));
    1765   DirectionCheckPoint.CopyVector(&dif_a);
    1766   DirectionCheckPoint.Scale(-1);
    1767   DirectionCheckPoint.ProjectOntoPlane(Chord);
    1768 
    1769   SideA = dif_b.Norm();
    1770   SideB = dif_a.Norm();
    1771   SideC = Chord->Norm();
    1772   //Chord->Scale(-1);
    1773 
    1774   alpha = Chord->Angle(&dif_a);
    1775   beta = M_PI - Chord->Angle(&dif_b);
    1776   gamma = dif_a.Angle(&dif_b);
    1777 
    1778 
    1779   if (DEBUG)
    1780     {
    1781       cout << "Atom number" << Candidate->nr << endl;
    1782       Candidate->x.Output((ofstream *) &cout);
    1783       cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr]
    1784           << endl;
    1785     }
    1786 
    1787   if (a != Candidate and b != Candidate)
    1788     {
    1789       //      alpha = dif_a.Angle(&dif_b) / 2.;
    1790       //      SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha);
    1791       //      SideB = dif_a.Norm();
    1792       //      centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos(
    1793       //          alpha); // note this is squared of center line length
    1794       //      centerline = (Chord->Norm()/2.) / sin(0.5*alpha);
    1795       // Those are remains from Freddie. Needed?
    1796 
    1797 
    1798 
    1799       Umkreisradius = SideA / 2.0 / sin(alpha);
    1800       //cout << Umkreisradius << endl;
    1801       //cout << SideB / 2.0 / sin(beta) << endl;
    1802       //cout << SideC / 2.0 / sin(gamma) << endl;
    1803 
    1804       if (Umkreisradius < RADIUS && DirectionCheckPoint.ScalarProduct(&(Candidate->x))>0) //Checking whether ball will at least rest o points.
    1805         {
    1806 
    1807           // intermediate calculations to aquire centre of sphere, called Mittelpunkt:
    1808 
    1809           Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ;
    1810           Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    1811 
    1812           TempNormal.CopyVector(&dif_a);
    1813           TempNormal.VectorProduct(&dif_b);
    1814           if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0)
    1815             {
    1816               TempNormal.Scale(-1);
    1817             }
    1818           TempNormal.Normalize();
    1819           Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius);
    1820           TempNormal.Scale(Restradius);
    1821 
    1822           Mittelpunkt.CopyVector(&Umkreismittelpunkt);
    1823           Mittelpunkt.AddVector(&TempNormal);  //this is center of sphere supported by a, b and Candidate
    1824 
    1825           AngleCheck.CopyVector(Chord);
    1826           AngleCheck.Scale(-0.5);
    1827           AngleCheck.SubtractVector(&(b->x));
    1828           AngleCheckReference.CopyVector(&AngleCheck);
    1829           AngleCheckReference.AddVector(Opt_Mittelpunkt);
    1830           AngleCheck.AddVector(&Mittelpunkt);
    1831 
    1832           BallAngle = AngleCheck.Angle(&AngleCheckReference);
    1833 
    1834           d1->ProjectOntoPlane(&AngleCheckReference);
    1835           sign = AngleCheck.ScalarProduct(d1);
    1836           sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction...
    1837 
    1838 
    1839           if (Storage[0]< -1.5) // first Candidate at all
    1840             {
    1841 
    1842               cout << "Next better candidate is " << *Candidate << " with ";
    1843               Opt_Candidate = Candidate;
    1844               Storage[0] = sign;
    1845               Storage[1] = BallAngle;
    1846               Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1847               cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1848                   << Storage[0] << endl;
    1849 
    1850 
    1851             }
    1852           else
    1853             {
    1854               /*
    1855                * removed due to change in criterium, now checking angle of ball to old normal.
    1856               //We will now check for non interference, that is if the new candidate would have the Opt_Candidate
    1857               //within the ball.
    1858 
    1859               Distance = Opt_Candidate->x.Distance(&Mittelpunkt);
    1860               //cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl;
    1861 
    1862 
    1863               if (Distance >RADIUS) // We have no interference and may now check whether the new point is better.
    1864                 */
    1865                 {
    1866                   //cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl;
    1867 
    1868                   if (((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon)))  //This will give absolute preference to those in "right-hand" quadrants
    1869                       //(Candidate->x.Distance(Opt_Mittelpunkt) < RADIUS))    //and those where Candidate would be within old Sphere.
    1870                     {
    1871                       cout << "Next better candidate is " << *Candidate << " with ";
    1872                       Opt_Candidate = Candidate;
    1873                       Storage[0] = sign;
    1874                       Storage[1] = BallAngle;
    1875                       Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1876                       cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1877                           << Storage[0] << endl;
    1878 
    1879 
    1880                     }
    1881                   else
    1882                     {
    1883                       if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0
    1884                           && Storage[1] > BallAngle) ||
    1885                           (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0
    1886                           && Storage[1] < BallAngle))
    1887                       //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first.
    1888                         {
    1889                           cout << "Next better candidate is " << *Candidate << " with ";
    1890                           Opt_Candidate = Candidate;
    1891                           Storage[0] = sign;
    1892                           Storage[1] = BallAngle;
    1893                           Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1894                           cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1895                               << Storage[0] << endl;
    1896                         }
    1897 
    1898                     }
    1899                 }
    1900               /*
    1901                * This is for checking point-angle and presence of Candidates in Ball, currently we are checking the ball Angle.
    1902                *
    1903                 else
    1904                 {
    1905                   if (sign>0 && BallAngle>0 && Storage[0]<0)
    1906                     {
    1907                       cout << "Next better candidate is " << *Candidate << " with ";
    1908                       Opt_Candidate = Candidate;
    1909                       Storage[0] = sign;
    1910                       Storage[1] = BallAngle;
    1911                       Opt_Mittelpunkt->CopyVector(&Mittelpunkt);
    1912                       cout << "Angle is " << Storage[1] << ", Halbraum ist "
    1913                       << Storage[0] << endl;
    1914 
    1915 //Debugging purposes only
    1916                       cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl;
    1917                       cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl;
    1918                       cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl;
    1919                       cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl;
    1920                       cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " "  <<Mittelpunkt.x[2] << endl;
    1921                       cout << "Umkreisradius ist " << Umkreisradius << endl;
    1922                       cout << "Restradius ist " << Restradius << endl;
    1923                       cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl;
    1924                       cout << "OldNormal has coordinates " << OldNormal->x[0] << " " << OldNormal->x[1] << " " << OldNormal->x[2] << " " << endl;
    1925                       cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl;
    1926                       cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl;
    1927                       cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl;
    1928                       cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl;
    1929                       cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl;
    1930                       cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl;
    1931 
    1932 
    1933 
    1934                     }
    1935                   else
    1936                     {
    1937                       if (DEBUG)
    1938                         cout << "Looses to better candidate" << endl;
    1939                     }
    1940                 }
    1941                 */
    1942             }
    1943         }
    1944       else
    1945         {
    1946           if (DEBUG)
    1947             {
    1948               cout << "Doesn't satisfy requirements for circumscribing circle" << endl;
    1949             }
    1950         }
    1951     }
    1952 
    1953   else
    1954     {
    1955       if (DEBUG)
    1956         cout << "identisch mit Ursprungslinie" << endl;
    1957     }
    1958 
    1959   if (RecursionLevel < 9) // Five is the recursion level threshold.
    1960     {
    1961       for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond
    1962         {
    1963           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    1964               Candidate);
    1965           if (Walker == Parent)
    1966             { // don't go back the same bond
    1967               continue;
    1968             }
    1969           else
    1970             {
    1971               Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel
    1972                   + 1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS,
    1973                   mol); //call function again
    1974 
    1975             }
    1976         }
    1977     }
    1978 }
    1979 ;
     1711void Tesselation::Find_next_suitable_point_via_Angle_of_Sphere(atom* a, atom* b, atom* c, atom* Candidate, atom* Parent,
     1712                int RecursionLevel, Vector *Chord, Vector *direction1, Vector *OldNormal, Vector ReferencePoint,
     1713                atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol)
     1714{
     1715        cout << Verbose(2) << "Begin of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1716        cout << Verbose(3) << "Candidate is "<< *Candidate << endl;
     1717        cout << Verbose(4) << "Baseline vector is " << *Chord << "." << endl;
     1718        cout << Verbose(4) << "ReferencePoint is " << ReferencePoint << "." << endl;
     1719        cout << Verbose(4) << "Normal of base triangle is " << *OldNormal << "." << endl;
     1720        cout << Verbose(4) << "Search direction is " << *direction1 << "." << endl;
     1721        /* OldNormal is normal vector on the old triangle
     1722         * direction1 is normal on the triangle line, from which we come, as well as on OldNormal.
     1723         * Chord points from b to a!!!
     1724         */
     1725        Vector dif_a; //Vector from a to candidate
     1726        Vector dif_b; //Vector from b to candidate
     1727        Vector AngleCheck;
     1728        Vector TempNormal, Umkreismittelpunkt;
     1729        Vector Mittelpunkt;
     1730
     1731        double CurrentEpsilon = 0.1;
     1732        double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance;
     1733        double BallAngle, AlternativeSign;
     1734        atom *Walker; // variable atom point
     1735
     1736        Vector NewUmkreismittelpunkt;
     1737
     1738        if (a != Candidate and b != Candidate and c != Candidate) {
     1739                cout << Verbose(3) << "We have a unique candidate!" << endl;
     1740                dif_a.CopyVector(&(a->x));
     1741                dif_a.SubtractVector(&(Candidate->x));
     1742                dif_b.CopyVector(&(b->x));
     1743                dif_b.SubtractVector(&(Candidate->x));
     1744                AngleCheck.CopyVector(&(Candidate->x));
     1745                AngleCheck.SubtractVector(&(a->x));
     1746                AngleCheck.ProjectOntoPlane(Chord);
     1747
     1748                SideA = dif_b.Norm();
     1749                SideB = dif_a.Norm();
     1750                SideC = Chord->Norm();
     1751                //Chord->Scale(-1);
     1752
     1753                alpha = Chord->Angle(&dif_a);
     1754                beta = M_PI - Chord->Angle(&dif_b);
     1755                gamma = dif_a.Angle(&dif_b);
     1756
     1757                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;
     1758
     1759                if (fabs(M_PI - alpha - beta - gamma) > MYEPSILON) {
     1760                        cerr << Verbose(0) << "WARNING: sum of angles for base triangle " << (alpha + beta + gamma)/M_PI*180. << " != 180.\n";
     1761                        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;
     1762                }
     1763
     1764                if ((M_PI*179./180. > alpha) && (M_PI*179./180. > beta) && (M_PI*179./180. > gamma)) {
     1765                        Umkreisradius = SideA / 2.0 / sin(alpha);
     1766                        //cout << Umkreisradius << endl;
     1767                        //cout << SideB / 2.0 / sin(beta) << endl;
     1768                        //cout << SideC / 2.0 / sin(gamma) << endl;
     1769
     1770                        if (Umkreisradius < RADIUS) { //Checking whether ball will at least rest on points.
     1771                                cout << Verbose(3) << "Circle of circumference would fit: " << Umkreisradius << " < " << RADIUS << "." << endl;
     1772                                cout << Verbose(2) << "Candidate is "<< *Candidate << endl;
     1773                                sign = AngleCheck.ScalarProduct(direction1);
     1774                                if (fabs(sign)<MYEPSILON) {
     1775                                        if (AngleCheck.ScalarProduct(OldNormal)<0) {
     1776                                                sign =0;
     1777                                                AlternativeSign=1;
     1778                                        } else {
     1779                                                sign =0;
     1780                                                AlternativeSign=-1;
     1781                                        }
     1782                                } else {
     1783                                        sign /= fabs(sign);
     1784                                }
     1785                                if (sign >= 0) {
     1786                                        cout << Verbose(3) << "Candidate is in search direction: " << sign << "." << endl;
     1787                                        Get_center_of_sphere(&Mittelpunkt, (a->x), (b->x), (Candidate->x), &NewUmkreismittelpunkt, OldNormal, direction1, sign, AlternativeSign, alpha, beta, gamma, RADIUS, Umkreisradius);
     1788                                        Mittelpunkt.SubtractVector(&ReferencePoint);
     1789                                        cout << Verbose(3) << "Reference vector to sphere's center is " << Mittelpunkt << "." << endl;
     1790                                        BallAngle = Mittelpunkt.Angle(OldNormal);
     1791                                        cout << Verbose(3) << "Angle between normal of base triangle and center of ball sphere is :" << BallAngle << "." << endl;
     1792
     1793                                        //cout << "direction1 is " << *direction1 << "." << endl;
     1794                                        //cout << "Mittelpunkt is " << Mittelpunkt << "."<< endl;
     1795                                        //cout << Verbose(3) << "BallAngle is " << BallAngle << " Sign is " << sign << endl;
     1796
     1797                                        NewUmkreismittelpunkt.SubtractVector(&ReferencePoint);
     1798
     1799                                        if ((Mittelpunkt.ScalarProduct(direction1) >=0) || (fabs(NewUmkreismittelpunkt.Norm()) < MYEPSILON)) {
     1800                                                if (Storage[0]< -1.5) { // first Candidate at all
     1801                                                        if (1) {//if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1802                                                                cout << Verbose(2) << "First good candidate is " << *Candidate << " with ";
     1803                                                                Opt_Candidate = Candidate;
     1804                                                                Storage[0] = sign;
     1805                                                                Storage[1] = AlternativeSign;
     1806                                                                Storage[2] = BallAngle;
     1807                                                                cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1808                                                        } else
     1809                                                                cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1810                                                } else {
     1811                                                        if ( Storage[2] > BallAngle) {
     1812                                                                if (1) { //if (CheckPresenceOfTriangle((ofstream *)&cout,a,b,Candidate)) {
     1813                                                                        cout << Verbose(2) << "Next better candidate is " << *Candidate << " with ";
     1814                                                                        Opt_Candidate = Candidate;
     1815                                                                        Storage[0] = sign;
     1816                                                                        Storage[1] = AlternativeSign;
     1817                                                                        Storage[2] = BallAngle;
     1818                                                                        cout << " angle " << Storage[2] << " and Up/Down " << Storage[0] << endl;
     1819                                                                } else
     1820                                                                        cout << "Candidate " << *Candidate << " does not belong to a valid triangle." << endl;
     1821                                                        } else {
     1822                                                                if (DEBUG) {
     1823                                                                        cout << Verbose(3) << *Candidate << " looses against better candidate " << *Opt_Candidate << "." << endl;
     1824                                                                }
     1825                                                        }
     1826                                                }
     1827                                        } else {
     1828                                                if (DEBUG) {
     1829                                                        cout << Verbose(3) << *Candidate << " refused due to Up/Down sign which is " << sign << endl;
     1830                                                }
     1831                                        }
     1832                                } else {
     1833                                        if (DEBUG) {
     1834                                                cout << Verbose(3) << *Candidate << " is not in search direction." << endl;
     1835                                        }
     1836                                }
     1837                        } else {
     1838                                if (DEBUG) {
     1839                                        cout << Verbose(3) << *Candidate << " would have circumference of " << Umkreisradius << " bigger than ball's radius " << RADIUS << "." << endl;
     1840                                }
     1841                        }
     1842                } else {
     1843                        if (DEBUG) {
     1844                                cout << Verbose(0) << "Triangle consisting of " << *Candidate << ", " << *a << " and " << *b << " has an angle >150!" << endl;
     1845                        }
     1846                }
     1847        } else {
     1848                if (DEBUG) {
     1849                        cout << Verbose(3) << *Candidate << " is either " << *a << " or " << *b << "." << endl;
     1850                }
     1851        }
     1852
     1853        if (RecursionLevel < 5) { // Seven is the recursion level threshold.
     1854                for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) { // go through all bond
     1855                        Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate);
     1856                        if (Walker == Parent) { // don't go back the same bond
     1857                                continue;
     1858                        } else {
     1859                                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
     1860                        }
     1861                }
     1862        }
     1863        cout << Verbose(2) << "End of Find_next_suitable_point_via_Angle_of_Sphere, recursion level " << RecursionLevel << ".\n";
     1864}
     1865;
     1866
     1867
     1868/** Constructs the center of the circumcircle defined by three points \a *a, \a *b and \a *c.
     1869 * \param *Center new center on return
     1870 * \param *a first point
     1871 * \param *b second point
     1872 * \param *c third point
     1873 */
     1874void GetCenterofCircumcircle(Vector *Center, Vector *a, Vector *b, Vector *c)
     1875{
     1876        Vector helper;
     1877        double alpha, beta, gamma;
     1878        Vector SideA, SideB, SideC;
     1879        SideA.CopyVector(b);
     1880        SideA.SubtractVector(c);
     1881        SideB.CopyVector(c);
     1882        SideB.SubtractVector(a);
     1883        SideC.CopyVector(a);
     1884        SideC.SubtractVector(b);
     1885        alpha = M_PI - SideB.Angle(&SideC);
     1886        beta = M_PI - SideC.Angle(&SideA);
     1887        gamma = M_PI - SideA.Angle(&SideB);
     1888        cout << Verbose(3) << "INFO: alpha = " << alpha/M_PI*180. << ", beta = " << beta/M_PI*180. << ", gamma = " << gamma/M_PI*180. << "." << endl;
     1889        if (fabs(M_PI - alpha - beta - gamma) > HULLEPSILON)
     1890                cerr << "Sum of angles " << (alpha+beta+gamma)/M_PI*180. << " > 180 degrees by " << fabs(M_PI - alpha - beta - gamma)/M_PI*180. << "!" << endl;
     1891
     1892        Center->Zero();
     1893        helper.CopyVector(a);
     1894        helper.Scale(sin(2.*alpha));
     1895        Center->AddVector(&helper);
     1896        helper.CopyVector(b);
     1897        helper.Scale(sin(2.*beta));
     1898        Center->AddVector(&helper);
     1899        helper.CopyVector(c);
     1900        helper.Scale(sin(2.*gamma));
     1901        Center->AddVector(&helper);
     1902        Center->Scale(1./(sin(2.*alpha) + sin(2.*beta) + sin(2.*gamma)));
     1903};
     1904
     1905/** Returns the parameter "path length" for a given \a NewSphereCenter relative to \a OldSphereCenter on a circle on the plane \a CirclePlaneNormal with center \a CircleCenter and radius \a CircleRadius.
     1906 * Test whether the \a NewSphereCenter is really on the given plane and in distance \a CircleRadius from \a CircleCenter.
     1907 * It calculates the angle, making it unique on [0,2.*M_PI) by comparing to SearchDirection.
     1908 * Also the new center is invalid if it the same as the old one and does not lie right above (\a NormalVector) the base line (\a CircleCenter).
     1909 * \param CircleCenter Center of the parameter circle
     1910 * \param CirclePlaneNormal normal vector to plane of the parameter circle
     1911 * \param CircleRadius radius of the parameter circle
     1912 * \param NewSphereCenter new center of a circumcircle
     1913 * \param OldSphereCenter old center of a circumcircle, defining the zero "path length" on the parameter circle
     1914 * \param NormalVector normal vector
     1915 * \param SearchDirection search direction to make angle unique on return.
     1916 * \return Angle between \a NewSphereCenter and \a OldSphereCenter relative to \a CircleCenter, 2.*M_PI if one test fails
     1917 */
     1918double GetPathLengthonCircumCircle(Vector &CircleCenter, Vector &CirclePlaneNormal, double CircleRadius, Vector &NewSphereCenter, Vector &OldSphereCenter, Vector &NormalVector, Vector &SearchDirection)
     1919{
     1920        Vector helper;
     1921        double radius, alpha;
     1922
     1923        helper.CopyVector(&NewSphereCenter);
     1924        // test whether new center is on the parameter circle's plane
     1925        if (fabs(helper.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     1926                cerr << "ERROR: Something's very wrong here: NewSphereCenter is not on the band's plane as desired by " <<fabs(helper.ScalarProduct(&CirclePlaneNormal))        << "!" << endl;
     1927                helper.ProjectOntoPlane(&CirclePlaneNormal);
     1928        }
     1929        radius = helper.ScalarProduct(&helper);
     1930        // test whether the new center vector has length of CircleRadius
     1931        if (fabs(radius - CircleRadius) > HULLEPSILON)
     1932                cerr << Verbose(1) << "ERROR: The projected center of the new sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     1933        alpha = helper.Angle(&OldSphereCenter);
     1934        // make the angle unique by checking the halfplanes/search direction
     1935        if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // acos is not unique on [0, 2.*M_PI), hence extra check to decide between two half intervals
     1936                alpha = 2.*M_PI - alpha;
     1937        cout << Verbose(2) << "INFO: RelativeNewSphereCenter is " << helper << ", RelativeOldSphereCenter is " << OldSphereCenter << " and resulting angle is " << alpha << "." << endl;
     1938        radius = helper.Distance(&OldSphereCenter);
     1939        helper.ProjectOntoPlane(&NormalVector);
     1940        // check whether new center is somewhat away or at least right over the current baseline to prevent intersecting triangles
     1941        if ((radius > HULLEPSILON) || (helper.Norm() < HULLEPSILON)) {
     1942                cout << Verbose(2) << "INFO: Distance between old and new center is " << radius << " and between new center and baseline center is " << helper.Norm() << "." << endl;
     1943                return alpha;
     1944        } else {
     1945                cout << Verbose(1) << "ERROR: NewSphereCenter " << helper << " is too close to OldSphereCenter" << OldSphereCenter << "." << endl;
     1946                return 2.*M_PI;
     1947        }
     1948};
     1949
     1950
     1951/** This recursive function finds a third point, to form a triangle with two given ones.
     1952 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points
     1953 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then
     1954 * the center of the sphere is still fixed up to a single parameter. The band of possible values
     1955 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives
     1956 * us the "null" on this circle, the new center of the candidate point will be some way along this
     1957 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given
     1958 * by the normal vector of the base triangle that always points outwards by construction.
     1959 * Hence, we construct a Center of this circle which sits right in the middle of the current base line.
     1960 * We construct the normal vector that defines the plane this circle lies in, it is just in the
     1961 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest
     1962 * with respect to the length of the baseline and the sphere's fixed \a RADIUS.
     1963 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center
     1964 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check
     1965 * both.
     1966 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check
     1967 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check
     1968 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal
     1969 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality
     1970 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether
     1971 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).
     1972 * @param BaseTriangle BoundaryTriangleSet of the current base triangle with all three points
     1973 * @param BaseLine BoundaryLineSet of BaseTriangle with the current base line
     1974 * @param OptCandidate candidate reference on return
     1975 * @param OptCandidateCenter candidate's sphere center on return
     1976 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
     1977 * @param RADIUS radius of sphere
     1978 * @param *LC LinkedCell structure with neighbouring atoms
     1979 */
     1980// void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
     1981// {
     1982//       atom *Walker = NULL;
     1983//       Vector CircleCenter;   // center of the circle, i.e. of the band of sphere's centers
     1984//       Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     1985//       Vector OldSphereCenter;         // center of the sphere defined by the three points of BaseTriangle
     1986//       Vector NewSphereCenter;         // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     1987//       Vector OtherNewSphereCenter;    // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     1988//       Vector NewNormalVector;         // normal vector of the Candidate's triangle
     1989//       Vector SearchDirection;         // vector that points out of BaseTriangle and is orthonormal to its NormalVector (i.e. the desired direction for the best Candidate)
     1990//       Vector helper;
     1991//       LinkedAtoms *List = NULL;
     1992//       double CircleRadius; // radius of this circle
     1993//       double radius;
     1994//       double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     1995//       double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     1996//       int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     1997//       atom *Candidate = NULL;
     1998//
     1999//       cout << Verbose(1) << "Begin of Find_next_suitable_point" << endl;
     2000//
     2001//       cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << BaseTriangle->NormalVector << "." << endl;
     2002//
     2003//       // construct center of circle
     2004//       CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2005//       CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2006//       CircleCenter.Scale(0.5);
     2007//
     2008//       // construct normal vector of circle
     2009//       CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2010//       CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2011//
     2012//       // calculate squared radius of circle
     2013//       radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2014//       if (radius/4. < RADIUS*RADIUS) {
     2015//               CircleRadius = RADIUS*RADIUS - radius/4.;
     2016//               CirclePlaneNormal.Normalize();
     2017//               cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2018//
     2019//               // construct old center
     2020//               GetCenterofCircumcircle(&OldSphereCenter, &(BaseTriangle->endpoints[0]->node->x), &(BaseTriangle->endpoints[1]->node->x), &(BaseTriangle->endpoints[2]->node->x));
     2021//               helper.CopyVector(&BaseTriangle->NormalVector);        // normal vector ensures that this is correct center of the two possible ones
     2022//               radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2023//               helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2024//               OldSphereCenter.AddVector(&helper);
     2025//               OldSphereCenter.SubtractVector(&CircleCenter);
     2026//               cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2027//
     2028//               // test whether old center is on the band's plane
     2029//               if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2030//                       cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2031//                       OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2032//               }
     2033//               radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2034//               if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2035//
     2036//                       // construct SearchDirection
     2037//                       SearchDirection.MakeNormalVector(&BaseTriangle->NormalVector, &CirclePlaneNormal);
     2038//                       helper.CopyVector(&BaseLine->endpoints[0]->node->x);
     2039//                       for(int i=0;i<3;i++)   // just take next different endpoint
     2040//                               if ((BaseTriangle->endpoints[i]->node != BaseLine->endpoints[0]->node) && (BaseTriangle->endpoints[i]->node != BaseLine->endpoints[1]->node)) {
     2041//                                       helper.SubtractVector(&BaseTriangle->endpoints[i]->node->x);
     2042//                               }
     2043//                       if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)     // ohoh, SearchDirection points inwards!
     2044//                               SearchDirection.Scale(-1.);
     2045//                       SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2046//                       SearchDirection.Normalize();
     2047//                       cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2048//                       if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {     // rotated the wrong way!
     2049//                               cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2050//                       }
     2051//
     2052//                       if (LC->SetIndexToVector(&CircleCenter)) {     // get cell for the starting atom
     2053//                               for(int i=0;i<NDIM;i++) // store indices of this cell
     2054//                                       N[i] = LC->n[i];
     2055//                               cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2056//                       } else {
     2057//                               cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2058//                               return;
     2059//                       }
     2060//                       // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2061//                       cout << Verbose(2) << "LC Intervals:";
     2062//                       for (int i=0;i<NDIM;i++) {
     2063//                               Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2064//                               Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2065//                               cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2066//                       }
     2067//                       cout << endl;
     2068//                       for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2069//                               for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2070//                                       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2071//                                               List = LC->GetCurrentCell();
     2072//                                               cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2073//                                               if (List != NULL) {
     2074//                                                       for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2075//                                                               Candidate = (*Runner);
     2076//
     2077//                                                               // check for three unique points
     2078//                                                               if ((Candidate != BaseTriangle->endpoints[0]->node) && (Candidate != BaseTriangle->endpoints[1]->node) && (Candidate != BaseTriangle->endpoints[2]->node)) {
     2079//                                                                       cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2080//
     2081//                                                                       // construct both new centers
     2082//                                                                       GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2083//                                                                       OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2084//
     2085//                                                                       if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2086//                                                                               helper.CopyVector(&NewNormalVector);
     2087//                                                                               cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2088//                                                                               radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2089//                                                                               if (radius < RADIUS*RADIUS) {
     2090//                                                                                       helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2091//                                                                                       cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2092//                                                                                       NewSphereCenter.AddVector(&helper);
     2093//                                                                                       NewSphereCenter.SubtractVector(&CircleCenter);
     2094//                                                                                       cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2095//
     2096//                                                                                       helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2097//                                                                                       OtherNewSphereCenter.AddVector(&helper);
     2098//                                                                                       OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2099//                                                                                       cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2100//
     2101//                                                                                       // check both possible centers
     2102//                                                                                       alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2103//                                                                                       Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, BaseTriangle->NormalVector, SearchDirection);
     2104//                                                                                       alpha = min(alpha, Otheralpha);
     2105//                                                                                       if (*ShortestAngle > alpha) {
     2106//                                                                                                       OptCandidate = Candidate;
     2107//                                                                                                       *ShortestAngle = alpha;
     2108//                                                                                                       if (alpha != Otheralpha)
     2109//                                                                                                               OptCandidateCenter->CopyVector(&NewSphereCenter);
     2110//                                                                                                       else
     2111//                                                                                                               OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2112//                                                                                                       cout << Verbose(1) << "We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2113//                                                                                       } else {
     2114//                                                                                               if (OptCandidate != NULL)
     2115//                                                                                                       cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2116//                                                                                               else
     2117//                                                                                                       cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2118//                                                                                       }
     2119//
     2120//                                                                               } else {
     2121//                                                                                       cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2122//                                                                               }
     2123//                                                                       } else {
     2124//                                                                               cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2125//                                                                       }
     2126//                                                               } else {
     2127//                                                                       cout << Verbose(1) << "REJECT: Base triangle " << *BaseTriangle << " contains Candidate " << *Candidate << "." << endl;
     2128//                                                               }
     2129//                                                       }
     2130//                                               }
     2131//                                       }
     2132//               } else {
     2133//                       cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2134//               }
     2135//       } else {
     2136//               cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and base triangle " << *BaseTriangle << " is too big!" << endl;
     2137//       }
     2138//
     2139//       cout << Verbose(1) << "End of Find_next_suitable_point" << endl;
     2140// };
     2141
     2142
     2143/** Checks whether the triangle consisting of the three atoms is already present.
     2144 * Searches for the points in Tesselation::PointsOnBoundary and checks their
     2145 * lines. If any of the three edges already has two triangles attached, false is
     2146 * returned.
     2147 * \param *out output stream for debugging
     2148 * \param *Candidates endpoints of the triangle candidate
     2149 * \return false - triangle invalid due to edge criteria, true - triangle may be added.
     2150 */
     2151bool Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
     2152        LineMap::iterator FindLine;
     2153        PointMap::iterator FindPoint;
     2154        bool Present[3];
     2155
     2156        *out << Verbose(2) << "Begin of CheckPresenceOfTriangle" << endl;
     2157        for (int i=0;i<3;i++) { // check through all endpoints
     2158                FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     2159                if (FindPoint != PointsOnBoundary.end())
     2160                        TPS[i] = FindPoint->second;
     2161                else
     2162                        TPS[i] = NULL;
     2163        }
     2164
     2165        // check lines
     2166        for (int i=0;i<3;i++)
     2167                if (TPS[i] != NULL)
     2168                        for (int j=i;j<3;j++)
     2169                                if (TPS[j] != NULL) {
     2170                                        FindLine = TPS[i]->lines.find(TPS[j]->node->nr);
     2171                                        if ((FindLine != TPS[i]->lines.end()) && (FindLine->second->TrianglesCount > 1)) {
     2172                                                *out << "WARNING: Line " << *FindLine->second << " already present with " << FindLine->second->TrianglesCount << " triangles attached." << endl;
     2173                                                *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2174                                                return false;
     2175                                        }
     2176                                }
     2177        *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
     2178        return true;
     2179};
     2180
     2181/** This recursive function finds a third point, to form a triangle with two given ones.
     2182 * Note that this function is for the starting triangle.
     2183 * The idea is as follows: A sphere with fixed radius is (almost) uniquely defined in space by three points
     2184 * that sit on its boundary. Hence, when two points are given and we look for the (next) third point, then
     2185 * the center of the sphere is still fixed up to a single parameter. The band of possible values
     2186 * describes a circle in 3D-space. The old center of the sphere for the current base triangle gives
     2187 * us the "null" on this circle, the new center of the candidate point will be some way along this
     2188 * circle. The shorter the way the better is the candidate. Note that the direction is clearly given
     2189 * by the normal vector of the base triangle that always points outwards by construction.
     2190 * Hence, we construct a Center of this circle which sits right in the middle of the current base line.
     2191 * We construct the normal vector that defines the plane this circle lies in, it is just in the
     2192 * direction of the baseline. And finally, we need the radius of the circle, which is given by the rest
     2193 * with respect to the length of the baseline and the sphere's fixed \a RADIUS.
     2194 * Note that there is one difficulty: The circumcircle is uniquely defined, but for the circumsphere's center
     2195 * there are two possibilities which becomes clear from the construction as seen below. Hence, we must check
     2196 * both.
     2197 * Note also that the acos() function is not unique on [0, 2.*M_PI). Hence, we need an additional check
     2198 * to decide for one of the two possible angles. Therefore we need a SearchDirection and to make this check
     2199 * sensible we need OldSphereCenter to be orthogonal to it. Either we construct SearchDirection orthogonal
     2200 * right away, or -- what we do here -- we rotate the relative sphere centers such that this orthogonality
     2201 * holds. Then, the normalized projection onto the SearchDirection is either +1 or -1 and thus states whether
     2202 * the angle is uniquely in either (0,M_PI] or [M_PI, 2.*M_PI).
     2203 * @param NormalVector normal direction of the base triangle (here the unit axis vector, \sa Find_starting_triangle())
     2204 * @param SearchDirection general direction where to search for the next point, relative to center of BaseLine
     2205 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle
     2206 * @param BaseLine BoundaryLineSet with the current base line
     2207 * @param ThirdNode third atom to avoid in search
     2208 * @param OptCandidate candidate reference on return
     2209 * @param OptCandidateCenter candidate's sphere center on return
     2210 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
     2211 * @param RADIUS radius of sphere
     2212 * @param *LC LinkedCell structure with neighbouring atoms
     2213 */
     2214void 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)
     2215{
     2216        atom *Walker = NULL;
     2217        Vector CircleCenter;    // center of the circle, i.e. of the band of sphere's centers
     2218        Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
     2219        Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2220        Vector OtherNewSphereCenter;     // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2221        Vector NewNormalVector;  // normal vector of the Candidate's triangle
     2222        Vector helper;
     2223        LinkedAtoms *List = NULL;
     2224        double CircleRadius; // radius of this circle
     2225        double radius;
     2226        double alpha, Otheralpha; // angles (i.e. parameter for the circle).
     2227        double Nullalpha; // angle between OldSphereCenter and NormalVector of base triangle
     2228        int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2229        atom *Candidate = NULL;
     2230
     2231        cout << Verbose(1) << "Begin of Find_third_point_for_Tesselation" << endl;
     2232
     2233        cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2234
     2235        // construct center of circle
     2236        CircleCenter.CopyVector(&(BaseLine->endpoints[0]->node->x));
     2237        CircleCenter.AddVector(&BaseLine->endpoints[1]->node->x);
     2238        CircleCenter.Scale(0.5);
     2239
     2240        // construct normal vector of circle
     2241        CirclePlaneNormal.CopyVector(&BaseLine->endpoints[0]->node->x);
     2242        CirclePlaneNormal.SubtractVector(&BaseLine->endpoints[1]->node->x);
     2243
     2244        // calculate squared radius of circle
     2245        radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2246        if (radius/4. < RADIUS*RADIUS) {
     2247                CircleRadius = RADIUS*RADIUS - radius/4.;
     2248                CirclePlaneNormal.Normalize();
     2249                cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2250
     2251                // test whether old center is on the band's plane
     2252                if (fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) > HULLEPSILON) {
     2253                        cerr << "ERROR: Something's very wrong here: OldSphereCenter is not on the band's plane as desired by " << fabs(OldSphereCenter.ScalarProduct(&CirclePlaneNormal)) << "!" << endl;
     2254                        OldSphereCenter.ProjectOntoPlane(&CirclePlaneNormal);
     2255                }
     2256                radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
     2257                if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2258
     2259                        // check SearchDirection
     2260                        cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2261                        if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
     2262                                cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are not orthogonal!" << endl;
     2263                        }
     2264                        // get cell for the starting atom
     2265                        if (LC->SetIndexToVector(&CircleCenter)) {
     2266                                        for(int i=0;i<NDIM;i++) // store indices of this cell
     2267                                        N[i] = LC->n[i];
     2268                                cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     2269                        } else {
     2270                                cerr << "ERROR: Vector " << CircleCenter << " is outside of LinkedCell's bounding box." << endl;
     2271                                return;
     2272                        }
     2273                        // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2274                        cout << Verbose(2) << "LC Intervals:";
     2275                        for (int i=0;i<NDIM;i++) {
     2276                                Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2277                                Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2278                                cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2279                        }
     2280                        cout << endl;
     2281                        for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2282                                for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2283                                        for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2284                                                List = LC->GetCurrentCell();
     2285                                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2286                                                if (List != NULL) {
     2287                                                        for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2288                                                                Candidate = (*Runner);
     2289
     2290                                                                // check for three unique points
     2291                                                                if ((Candidate != BaseLine->endpoints[0]->node) && (Candidate != BaseLine->endpoints[1]->node) && (Candidate != ThirdNode)) {
     2292                                                                        cout << Verbose(1) << "INFO: Current Candidate is " << *Candidate << " at " << Candidate->x << "." << endl;
     2293
     2294                                                                        // construct both new centers
     2295                                                                        GetCenterofCircumcircle(&NewSphereCenter, &(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x));
     2296                                                                        OtherNewSphereCenter.CopyVector(&NewSphereCenter);
     2297
     2298                                                                        if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x))) && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)) {
     2299                                                                                helper.CopyVector(&NewNormalVector);
     2300                                                                                cout << Verbose(2) << "INFO: NewNormalVector is " << NewNormalVector << "." << endl;
     2301                                                                                radius = BaseLine->endpoints[0]->node->x.DistanceSquared(&NewSphereCenter);
     2302                                                                                if (radius < RADIUS*RADIUS) {
     2303                                                                                        helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2304                                                                                        cout << Verbose(3) << "INFO: Distance of NewCircleCenter to NewSphereCenter is " << helper.Norm() << "." << endl;
     2305                                                                                        NewSphereCenter.AddVector(&helper);
     2306                                                                                        NewSphereCenter.SubtractVector(&CircleCenter);
     2307                                                                                        cout << Verbose(2) << "INFO: NewSphereCenter is at " << NewSphereCenter << "." << endl;
     2308
     2309                                                                                        helper.Scale(-1.); // OtherNewSphereCenter is created by the same vector just in the other direction
     2310                                                                                        OtherNewSphereCenter.AddVector(&helper);
     2311                                                                                        OtherNewSphereCenter.SubtractVector(&CircleCenter);
     2312                                                                                        cout << Verbose(2) << "INFO: OtherNewSphereCenter is at " << OtherNewSphereCenter << "." << endl;
     2313
     2314                                                                                        // check both possible centers
     2315                                                                                        alpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, NewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2316                                                                                        Otheralpha = GetPathLengthonCircumCircle(CircleCenter, CirclePlaneNormal, CircleRadius, OtherNewSphereCenter, OldSphereCenter, NormalVector, SearchDirection);
     2317                                                                                        alpha = min(alpha, Otheralpha);
     2318                                                                                        if (*ShortestAngle > alpha) {
     2319                                                                                                        OptCandidate = Candidate;
     2320                                                                                                        *ShortestAngle = alpha;
     2321                                                                                                        if (alpha != Otheralpha)
     2322                                                                                                                OptCandidateCenter->CopyVector(&NewSphereCenter);
     2323                                                                                                        else
     2324                                                                                                                OptCandidateCenter->CopyVector(&OtherNewSphereCenter);
     2325                                                                                                        cout << Verbose(1) << "ACCEPT: We have found a better candidate: " << *OptCandidate << " with " << alpha << " and circumsphere's center at " << *OptCandidateCenter << "." << endl;
     2326                                                                                        } else {
     2327                                                                                                if (OptCandidate != NULL)
     2328                                                                                                        cout << Verbose(1) << "REJECT: Old candidate: " << *OptCandidate << " is better than " << alpha << " with " << *ShortestAngle << "." << endl;
     2329                                                                                                else
     2330                                                                                                        cout << Verbose(2) << "REJECT: Candidate " << *Candidate << " with " << alpha << " was rejected." << endl;
     2331                                                                                        }
     2332
     2333                                                                                } else {
     2334                                                                                        cout << Verbose(1) << "REJECT: NewSphereCenter " << NewSphereCenter << " is too far away: " << radius << "." << endl;
     2335                                                                                }
     2336                                                                        } else {
     2337                                                                                cout << Verbose(1) << "REJECT: Three points from " << *BaseLine << " and Candidate " << *Candidate << " are linear-dependent." << endl;
     2338                                                                        }
     2339                                                                } else {
     2340                                                                        if (ThirdNode != NULL)
     2341                                                                                cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " and " << *ThirdNode << " contains Candidate " << *Candidate << "." << endl;
     2342                                                                        else
     2343                                                                                cout << Verbose(1) << "REJECT: Base triangle " << *BaseLine << " contains Candidate " << *Candidate << "." << endl;
     2344                                                                }
     2345                                                        }
     2346                                                }
     2347                                        }
     2348                } else {
     2349                        cerr << Verbose(1) << "ERROR: The projected center of the old sphere has radius " << radius << " instead of " << CircleRadius << "." << endl;
     2350                }
     2351        } else {
     2352                if (ThirdNode != NULL)
     2353                        cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " and third node " << *ThirdNode << " is too big!" << endl;
     2354                else
     2355                        cout << Verbose(1) << "Circumcircle for base line " << *BaseLine << " is too big!" << endl;
     2356        }
     2357
     2358        cout << Verbose(1) << "End of Find_third_point_for_Tesselation" << endl;
     2359};
     2360
     2361/** Finds the second point of starting triangle.
     2362 * \param *a first atom
     2363 * \param *Candidate pointer to candidate atom on return
     2364 * \param Oben vector indicating the outside
     2365 * \param Opt_Candidate reference to recommended candidate on return
     2366 * \param Storage[3] array storing angles and other candidate information
     2367 * \param RADIUS radius of virtual sphere
     2368 * \param *LC LinkedCell structure with neighbouring atoms
     2369 */
     2370void Find_second_point_for_Tesselation(atom* a, atom* Candidate, Vector Oben, atom*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
     2371{
     2372        cout << Verbose(2) << "Begin of Find_second_point_for_Tesselation" << endl;
     2373        int i;
     2374        Vector AngleCheck;
     2375        atom* Walker;
     2376        double norm = -1., angle;
     2377        LinkedAtoms *List = NULL;
     2378        int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     2379
     2380        if (LC->SetIndexToAtom(a)) {    // get cell for the starting atom
     2381                for(int i=0;i<NDIM;i++) // store indices of this cell
     2382                        N[i] = LC->n[i];
     2383        } else {
     2384                cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     2385                return;
     2386        }
     2387        // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     2388        cout << Verbose(2) << "LC Intervals:";
     2389        for (int i=0;i<NDIM;i++) {
     2390                Nlower[i] = ((N[i]-1) >= 0) ? N[i]-1 : 0;
     2391                Nupper[i] = ((N[i]+1) < LC->N[i]) ? N[i]+1 : LC->N[i]-1;
     2392                cout << " [" << Nlower[i] << "," << Nupper[i] << "] ";
     2393        }
     2394        cout << endl;
     2395        for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     2396                for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     2397                        for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     2398                                List = LC->GetCurrentCell();
     2399                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2400                                if (List != NULL) {
     2401                                        for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     2402                                                Candidate = (*Runner);
     2403                                                                // check if we only have one unique point yet ...
     2404                                                                if (a != Candidate) {
     2405                        cout << Verbose(3) << "Current candidate is " << *Candidate << ": ";
     2406                        AngleCheck.CopyVector(&(Candidate->x));
     2407                        AngleCheck.SubtractVector(&(a->x));
     2408                        norm = AngleCheck.Norm();
     2409                                                        // second point shall have smallest angle with respect to Oben vector
     2410                                                        if (norm < RADIUS) {
     2411                                                                angle = AngleCheck.Angle(&Oben);
     2412                                                                if (angle < Storage[0]) {
     2413                                                                        //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]);
     2414                                                                        cout << "Is a better candidate with distance " << norm << " and " << angle << ".\n";
     2415                                                                        Opt_Candidate = Candidate;
     2416                                                                        Storage[0] = AngleCheck.Angle(&Oben);
     2417                                                                        //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
     2418                                                                } else {
     2419                                                                        cout << "Looses with angle " << angle << " to a better candidate " << *Opt_Candidate << endl;
     2420                                                                }
     2421                                                        } else {
     2422                                                                cout << "Refused due to Radius " << norm << endl;
     2423                                                        }
     2424                                                }
     2425                                        }
     2426                                }
     2427                        }
     2428        cout << Verbose(2) << "End of Find_second_point_for_Tesselation" << endl;
     2429};
     2430
     2431/** Finds the starting triangle for find_non_convex_border().
     2432 * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation()
     2433 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third
     2434 * point are called.
     2435 * \param RADIUS radius of virtual rolling sphere
     2436 * \param *LC LinkedCell structure with neighbouring atoms
     2437 */
     2438void Tesselation::Find_starting_triangle(ofstream *out, molecule *mol, const double RADIUS, LinkedCell *LC)
     2439{
     2440        cout << Verbose(1) << "Begin of Find_starting_triangle\n";
     2441        int i = 0;
     2442        LinkedAtoms *List = NULL;
     2443        atom* Walker;
     2444        atom* FirstPoint;
     2445        atom* SecondPoint;
     2446        atom* MaxAtom[NDIM];
     2447        double max_coordinate[NDIM];
     2448        Vector Oben;
     2449        Vector helper;
     2450        Vector Chord;
     2451        Vector SearchDirection;
     2452        Vector OptCandidateCenter;
     2453
     2454        Oben.Zero();
     2455
     2456        for (i = 0; i < 3; i++) {
     2457                MaxAtom[i] = NULL;
     2458                max_coordinate[i] = -1;
     2459        }
     2460
     2461        // 1. searching topmost atom with respect to each axis
     2462        for (int i=0;i<NDIM;i++) { // each axis
     2463                LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     2464                for (LC->n[(i+1)%NDIM]=0;LC->n[(i+1)%NDIM]<LC->N[(i+1)%NDIM];LC->n[(i+1)%NDIM]++)
     2465                        for (LC->n[(i+2)%NDIM]=0;LC->n[(i+2)%NDIM]<LC->N[(i+2)%NDIM];LC->n[(i+2)%NDIM]++) {
     2466                                List = LC->GetCurrentCell();
     2467                                //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
     2468                                if (List != NULL) {
     2469                                        for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
     2470                                                cout << Verbose(2) << "Current atom is " << *(*Runner) << "." << endl;
     2471                                                if ((*Runner)->x.x[i] > max_coordinate[i]) {
     2472                                                        max_coordinate[i] = (*Runner)->x.x[i];
     2473                                                        MaxAtom[i] = (*Runner);
     2474                                                }
     2475                                        }
     2476                                } else {
     2477                                        cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << " is invalid!" << endl;
     2478                                }
     2479                        }
     2480        }
     2481
     2482        cout << Verbose(2) << "Found maximum coordinates: ";
     2483        for (int i=0;i<NDIM;i++)
     2484                cout << i << ": " << *MaxAtom[i] << "\t";
     2485        cout << endl;
     2486        const int k = 1;                // arbitrary choice
     2487        Oben.x[k] = 1.;
     2488        FirstPoint = MaxAtom[k];
     2489        cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << " at " << FirstPoint->x << "." << endl;
     2490
     2491        // add first point
     2492        AddTrianglePoint(FirstPoint, 0);
     2493
     2494        double ShortestAngle;
     2495        atom* Opt_Candidate = NULL;
     2496        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.
     2497
     2498        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_...
     2499        SecondPoint = Opt_Candidate;
     2500        cout << Verbose(1) << "Found second point is " << *SecondPoint << " at " << SecondPoint->x << ".\n";
     2501
     2502        // add second point and first baseline
     2503        AddTrianglePoint(SecondPoint, 1);
     2504        AddTriangleLine(TPS[0], TPS[1], 0);
     2505
     2506        helper.CopyVector(&(FirstPoint->x));
     2507        helper.SubtractVector(&(SecondPoint->x));
     2508        helper.Normalize();
     2509        Oben.ProjectOntoPlane(&helper);
     2510        Oben.Normalize();
     2511        helper.VectorProduct(&Oben);
     2512        ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2513
     2514        Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
     2515        Chord.SubtractVector(&(SecondPoint->x));
     2516        double radius = Chord.ScalarProduct(&Chord);
     2517        double CircleRadius = sqrt(RADIUS*RADIUS - radius/4.);
     2518        helper.CopyVector(&Oben);
     2519        helper.Scale(CircleRadius);
     2520        // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
     2521
     2522        cout << Verbose(2) << "Looking for third point candidates \n";
     2523        // look in one direction of baseline for initial candidate
     2524        Opt_Candidate = NULL;
     2525        SearchDirection.MakeNormalVector(&Chord, &Oben);        // whether we look "left" first or "right" first is not important ...
     2526
     2527        cout << Verbose(1) << "Looking for third point candidates ...\n";
     2528        Find_third_point_for_Tesselation(Oben, SearchDirection, helper, BLS[0], NULL, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2529        cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
     2530
     2531        // add third point
     2532        AddTrianglePoint(Opt_Candidate, 2);
     2533
     2534        // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
     2535
     2536        // Finally, we only have to add the found further lines
     2537        AddTriangleLine(TPS[1], TPS[2], 1);
     2538        AddTriangleLine(TPS[0], TPS[2], 2);
     2539        // ... and triangles to the Maps of the Tesselation class
     2540        BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2541        AddTriangleToLines();
     2542        // ... and calculate its normal vector (with correct orientation)
     2543        OptCandidateCenter.Scale(-1.);
     2544        cout << Verbose(2) << "Oben is currently " << OptCandidateCenter << "." << endl;
     2545        BTS->GetNormalVector(OptCandidateCenter);
     2546        cout << Verbose(0) << "==> The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << " with normal vector " << BTS->NormalVector << ".\n";
     2547        cout << Verbose(2) << "Projection is " << BTS->NormalVector.Projection(&Oben) << "." << endl;
     2548        cout << Verbose(1) << "End of Find_starting_triangle\n";
     2549};
    19802550
    19812551/** This function finds a triangle to a line, adjacent to an existing one.
    1982  * @param out   output stream for debugging
    1983  * @param mol molecule structure with all atoms and bonds
     2552 * @param out output stream for debugging
     2553 * @param *mol molecule with Atom's and Bond's
    19842554 * @param Line current baseline to search from
    19852555 * @param T current triangle which \a Line is edge of
    19862556 * @param RADIUS radius of the rolling ball
    19872557 * @param N number of found triangles
     2558 * @param *filename filename base for intermediate envelopes
     2559 * @param *LC LinkedCell structure with neighbouring atoms
    19882560 */
    1989 void Tesselation::Find_next_suitable_triangle(ofstream *out,
    1990     molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
    1991     const double& RADIUS, int N, const char *tempbasename)
    1992 {
    1993   cout << Verbose(1) << "Looking for next suitable triangle \n";
    1994   Vector direction1;
    1995   Vector helper;
    1996   Vector Chord;
    1997   ofstream *tempstream = NULL;
    1998   char NumberName[255];
    1999   double tmp;
    2000   //atom* Walker;
    2001   atom* OldThirdPoint;
    2002 
    2003   double Storage[3];
    2004   Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values
    2005   Storage[1] = -2.; // This is also lower then any value produced by an eligible atom, which are all positive
    2006   Storage[2] = 9999999.;
    2007   atom* Opt_Candidate = NULL;
    2008   Vector Opt_Mittelpunkt;
    2009 
    2010   cout << Verbose(1) << "Constructing helpful vectors ... " << endl;
    2011   helper.CopyVector(&(Line.endpoints[0]->node->x));
    2012   for (int i = 0; i < 3; i++)
    2013     {
    2014       if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr
    2015           && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr)
    2016         {
    2017           OldThirdPoint = T.endpoints[i]->node;
    2018           helper.SubtractVector(&T.endpoints[i]->node->x);
    2019           break;
    2020         }
    2021     }
    2022 
    2023   direction1.CopyVector(&Line.endpoints[0]->node->x);
    2024   direction1.SubtractVector(&Line.endpoints[1]->node->x);
    2025   direction1.VectorProduct(&(T.NormalVector));
    2026 
    2027   if (direction1.ScalarProduct(&helper) < 0)
    2028     {
    2029       direction1.Scale(-1);
    2030     }
    2031 
    2032   Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function
    2033   Chord.SubtractVector(&(Line.endpoints[1]->node->x));
    2034 
    2035 
    2036     Vector Umkreismittelpunkt, a, b, c;
    2037     double alpha, beta, gamma;
    2038     a.CopyVector(&(T.endpoints[0]->node->x));
    2039     b.CopyVector(&(T.endpoints[1]->node->x));
    2040     c.CopyVector(&(T.endpoints[2]->node->x));
    2041     a.SubtractVector(&(T.endpoints[1]->node->x));
    2042     b.SubtractVector(&(T.endpoints[2]->node->x));
    2043     c.SubtractVector(&(T.endpoints[0]->node->x));
    2044 
    2045     alpha = M_PI - a.Angle(&c);
    2046     beta = M_PI - b.Angle(&a);
    2047     gamma = M_PI - c.Angle(&b);
    2048 
    2049     Umkreismittelpunkt = (T.endpoints[0]->node->x) * sin(2.*alpha) + T.endpoints[1]->node->x * sin(2.*beta) + (T.endpoints[2]->node->x) * sin(2.*gamma) ;
    2050     //cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2051     Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma)));
    2052     cout << "UmkreisMittelpunkt is " << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] << " "<< Umkreismittelpunkt.x[2] << " "<< endl;
    2053     cout << " We look over line " << Line << " in direction " << direction1.x[0] << " " << direction1.x[1] << " " << direction1.x[2] << " " << endl;
    2054     cout << " Old Normal is " <<  (T.NormalVector.x)[0] << " " << T.NormalVector.x[1] << " " << (T.NormalVector.x)[2] << " " << endl;
    2055 
    2056 
    2057   cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
    2058 
    2059   Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint,
    2060       Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1,
    2061       &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2062   Find_next_suitable_point_via_Angle_of_Sphere(Line.endpoints[0]->node, Line.endpoints[1]->node, OldThirdPoint,
    2063       Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1,
    2064       &(T.NormalVector), Umkreismittelpunkt, Opt_Candidate, Storage, RADIUS, mol);
    2065 
    2066 
    2067       cout << "Letzter Winkel bei " << TrianglesOnBoundaryCount << " Winkel ist " << Storage[2] << endl;
    2068 
    2069   if ((TrianglesOnBoundaryCount % 10) == 0) {
    2070     sprintf(NumberName, "-%d", TriangleFilesWritten);
    2071     if (DoTecplotOutput) {
    2072       string NameofTempFile(tempbasename);
    2073       NameofTempFile.append(NumberName);
    2074       NameofTempFile.append(TecplotSuffix);
    2075       cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2076       tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2077       write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
    2078       tempstream->close();
    2079       tempstream->flush();
    2080       delete(tempstream);
    2081     }
    2082     if (DoRaster3DOutput) {
    2083       string NameofTempFile(tempbasename);
    2084       NameofTempFile.append(NumberName);
    2085       NameofTempFile.append(Raster3DSuffix);
    2086       cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    2087       tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    2088       write_raster3d_file(out, tempstream, this, mol);
    2089       tempstream->close();
    2090       tempstream->flush();
    2091       delete(tempstream);
    2092     }
    2093     if (DoTecplotOutput || DoRaster3DOutput)
    2094       TriangleFilesWritten++;
    2095   }
    2096 
    2097       // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke
    2098 
    2099   cout << " Optimal candidate is " << *Opt_Candidate << endl;
    2100 
    2101   AddTrianglePoint(Opt_Candidate, 0);
    2102   AddTrianglePoint(Line.endpoints[0]->node, 1);
    2103   AddTrianglePoint(Line.endpoints[1]->node, 2);
    2104 
    2105   AddTriangleLine(TPS[0], TPS[1], 0);
    2106   AddTriangleLine(TPS[0], TPS[2], 1);
    2107   AddTriangleLine(TPS[1], TPS[2], 2);
    2108 
    2109   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2110   AddTriangleToLines();
    2111   cout << "New triangle with " << *BTS << endl;
    2112   cout << "We have "<< TrianglesOnBoundaryCount << endl;
    2113   cout << Verbose(1) << "Constructing normal vector for this triangle ... " << endl;
    2114 
    2115   BTS->GetNormalVector(BTS->NormalVector);
    2116 
    2117   if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0)  ||
    2118       (BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] < 0) ||
    2119       (fabs(Storage[0]) < MYEPSILON && Storage[1]*BTS->NormalVector.ScalarProduct(&direction1) < 0) )
    2120 
    2121     {
    2122       BTS->NormalVector.Scale(-1);
    2123     };
    2124 
    2125 }
    2126 ;
    2127 
    2128 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent,
    2129     int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[3],
    2130     molecule* mol, double RADIUS)
    2131 {
    2132   cout << Verbose(1)
    2133       << "Looking for second point of starting triangle, recursive level "
    2134       << RecursionLevel << endl;;
    2135   int i;
    2136   Vector AngleCheck;
    2137   atom* Walker;
    2138   double norm = -1.;
    2139 
    2140   // check if we only have one unique point yet ...
    2141   if (a != Candidate)
    2142     {
    2143       AngleCheck.CopyVector(&(Candidate->x));
    2144       AngleCheck.SubtractVector(&(a->x));
    2145       norm = AngleCheck.Norm();
    2146       // second point shall have smallest angle with respect to Oben vector
    2147       if (norm < RADIUS)
    2148         {
    2149           if (AngleCheck.Angle(&Oben) < Storage[0])
    2150             {
    2151               //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[2]);
    2152               cout << "Next better candidate is " << *Candidate
    2153                   << " with distance " << norm << ".\n";
    2154               Opt_Candidate = Candidate;
    2155               Storage[0] = AngleCheck.Angle(&Oben);
    2156               //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[2]);
    2157             }
    2158           else
    2159             {
    2160               cout << Verbose(1) << "Supposedly looses to a better candidate "
    2161                   << *Opt_Candidate << endl;
    2162             }
    2163         }
    2164       else
    2165         {
    2166           cout << Verbose(1) << *Candidate << " refused due to Radius " << norm
    2167               << endl;
    2168         }
    2169     }
    2170 
    2171   // if not recursed to deeply, look at all its bonds
    2172   if (RecursionLevel < 7)
    2173     {
    2174       for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++)
    2175         {
    2176           Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(
    2177               Candidate);
    2178           if (Walker == Parent) // don't go back along the bond we came from
    2179             continue;
    2180           else
    2181             Find_second_point_for_Tesselation(a, Walker, Candidate,
    2182                 RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS);
    2183         };
    2184     };
    2185 }
    2186 ;
    2187 
    2188 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS)
    2189 {
    2190   cout << Verbose(1) << "Looking for starting triangle \n";
    2191   int i = 0;
    2192   atom* Walker;
    2193   atom* FirstPoint;
    2194   atom* SecondPoint;
    2195   atom* max_index[3];
    2196   double max_coordinate[3];
    2197   Vector Oben;
    2198   Vector helper;
    2199   Vector Chord;
    2200   Vector CenterOfFirstLine;
    2201 
    2202   Oben.Zero();
    2203 
    2204   for (i = 0; i < 3; i++)
    2205     {
    2206       max_index[i] = NULL;
    2207       max_coordinate[i] = -1;
    2208     }
    2209   cout << Verbose(1) << "Molecule mol is there and has " << mol->AtomCount
    2210       << " Atoms \n";
    2211 
    2212   // 1. searching topmost atom with respect to each axis
    2213   Walker = mol->start;
    2214   while (Walker->next != mol->end)
    2215     {
    2216       Walker = Walker->next;
    2217       for (i = 0; i < 3; i++)
    2218         {
    2219           if (Walker->x.x[i] > max_coordinate[i])
    2220             {
    2221               max_coordinate[i] = Walker->x.x[i];
    2222               max_index[i] = Walker;
    2223             }
    2224         }
    2225     }
    2226 
    2227   cout << Verbose(1) << "Found maximum coordinates. " << endl;
    2228   //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0
    2229   const int k = 1;
    2230   Oben.x[k] = 1.;
    2231   FirstPoint = max_index[k];
    2232 
    2233   cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << ": "
    2234       << FirstPoint->x.x[0] << endl;
    2235   double Storage[3];
    2236   atom* Opt_Candidate = NULL;
    2237   Storage[0] = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    2238   Storage[1] = 999999.; // This will be an angle looking for the third point.
    2239   Storage[2] = 999999.;
    2240   cout << Verbose(1) << "Number of Bonds: "
    2241       << mol->NumberOfBondsPerAtom[FirstPoint->nr] << endl;
    2242 
    2243   Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0,
    2244       Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_...
    2245   SecondPoint = Opt_Candidate;
    2246   cout << Verbose(1) << "Found second point is " << *SecondPoint << ".\n";
    2247 
    2248   helper.CopyVector(&(FirstPoint->x));
    2249   helper.SubtractVector(&(SecondPoint->x));
    2250   helper.Normalize();
    2251   Oben.ProjectOntoPlane(&helper);
    2252   Oben.Normalize();
    2253   helper.VectorProduct(&Oben);
    2254   Storage[0] = -2.; // This will indicate the quadrant.
    2255   Storage[1] = 9999999.; // This will be an angle looking for the third point.
    2256   Storage[2] = 9999999.;
    2257 
    2258   Chord.CopyVector(&(FirstPoint->x)); // bring into calling function
    2259   Chord.SubtractVector(&(SecondPoint->x));
    2260   // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized)
    2261 
    2262   cout << Verbose(1) << "Looking for third point candidates \n";
    2263   cout << Verbose(1) << " In direction " << helper.x[0] << " " << helper.x[1] << " " << helper.x[2] << " " << endl;
    2264   // look in one direction of baseline for initial candidate
    2265   Opt_Candidate = NULL;
    2266   CenterOfFirstLine.CopyVector(&Chord);
    2267   CenterOfFirstLine.Scale(0.5);
    2268   CenterOfFirstLine.AddVector(&(SecondPoint->x));
    2269 
    2270   Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, SecondPoint, FirstPoint, 0,
    2271       &Chord, &helper, &Oben, CenterOfFirstLine,  Opt_Candidate, Storage, RADIUS, mol);
    2272   // look in other direction of baseline for possible better candidate
    2273   Find_next_suitable_point_via_Angle_of_Sphere(FirstPoint, SecondPoint, SecondPoint, FirstPoint, SecondPoint, 0,
    2274       &Chord, &helper, &Oben, CenterOfFirstLine, Opt_Candidate, Storage, RADIUS, mol);
    2275   cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl;
    2276 
    2277   // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate
    2278 
    2279   cout << Verbose(1) << "The found starting triangle consists of "
    2280       << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate
    2281       << "." << endl;
    2282 
    2283   // Finally, we only have to add the found points
    2284   AddTrianglePoint(FirstPoint, 0);
    2285   AddTrianglePoint(SecondPoint, 1);
    2286   AddTrianglePoint(Opt_Candidate, 2);
    2287   // ... and respective lines
    2288   AddTriangleLine(TPS[0], TPS[1], 0);
    2289   AddTriangleLine(TPS[1], TPS[2], 1);
    2290   AddTriangleLine(TPS[0], TPS[2], 2);
    2291   // ... and triangles to the Maps of the Tesselation class
    2292   BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
    2293   AddTriangleToLines();
    2294   // ... and calculate its normal vector (with correct orientation)
    2295   Oben.Scale(-1.);
    2296   BTS->GetNormalVector(Oben);
    2297 }
    2298 ;
    2299 
    2300 void Find_non_convex_border(ofstream *out, const char *filename, molecule* mol)
    2301 {
    2302   int N = 0;
    2303   struct Tesselation *Tess = new Tesselation;
    2304   cout << Verbose(1) << "Entering search for non convex hull. " << endl;
    2305   cout << flush;
    2306   const double RADIUS = 6.;
    2307   LineMap::iterator baseline;
    2308   cout << Verbose(0) << "Begin of Find_non_convex_border\n";
    2309   bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
    2310 
    2311   if ((mol->first->next == mol->last) || (mol->last->previous == mol->first))
    2312     mol->CreateAdjacencyList((ofstream *)&cout, 1.6, true);
    2313 
    2314   Tess->Find_starting_triangle(mol, RADIUS);
    2315 
    2316   baseline = Tess->LinesOnBoundary.begin();
    2317   while (baseline != Tess->LinesOnBoundary.end())
    2318     {
    2319       if (baseline->second->TrianglesCount == 1)
    2320         {
    2321           cout << Verbose(1) << "Begin of Tesselation ... " << endl;
    2322           Tess->Find_next_suitable_triangle(out, mol,
    2323               *(baseline->second),
    2324               *(((baseline->second->triangles.begin()))->second), RADIUS, N, filename); //the line is there, so there is a triangle, but only one.
    2325           flag = true;
    2326           cout << Verbose(1) << "End of Tesselation ... " << endl;
    2327         }
    2328       else
    2329         {
    2330           cout << Verbose(1) << "There is a line with "
    2331               << baseline->second->TrianglesCount << " triangles adjacent"
    2332               << endl;
    2333         }
    2334       N++;
    2335       baseline++;
    2336     }
    2337   cout << Verbose(1) << "Writing final tecplot file\n";
    2338   if (DoTecplotOutput) {
    2339     string Name(filename);
    2340     Name.append(TecplotSuffix);
    2341     ofstream tecplot(Name.c_str(), ios::trunc);
    2342     write_tecplot_file(out, &tecplot, Tess, mol, -1);
    2343     tecplot.close();
    2344   }
    2345   if (DoRaster3DOutput) {
    2346     string Name(filename);
    2347     Name.append(Raster3DSuffix);
    2348     ofstream raster(Name.c_str(), ios::trunc);
    2349     write_raster3d_file(out, &raster, Tess, mol);
    2350     raster.close();
    2351   }
    2352 }
    2353 ;
     2561bool Tesselation::Find_next_suitable_triangle(ofstream *out,
     2562                molecule *mol, BoundaryLineSet &Line, BoundaryTriangleSet &T,
     2563                const double& RADIUS, int N, const char *tempbasename, LinkedCell *LC)
     2564{
     2565        cout << Verbose(1) << "Begin of Find_next_suitable_triangle\n";
     2566        ofstream *tempstream = NULL;
     2567        char NumberName[255];
     2568        double tmp;
     2569
     2570        atom* Opt_Candidate = NULL;
     2571        Vector OptCandidateCenter;
     2572
     2573        Vector CircleCenter;
     2574        Vector CirclePlaneNormal;
     2575        Vector OldSphereCenter;
     2576        Vector SearchDirection;
     2577        Vector helper;
     2578        atom *ThirdNode = NULL;
     2579        double ShortestAngle = 2.*M_PI; // This will indicate the quadrant.
     2580        double radius, CircleRadius;
     2581
     2582        cout << Verbose(1) << "Current baseline is " << Line << " of triangle " << T << "." << endl;
     2583        for (int i=0;i<3;i++)
     2584                if ((T.endpoints[i]->node != Line.endpoints[0]->node) && (T.endpoints[i]->node != Line.endpoints[1]->node))
     2585                        ThirdNode = T.endpoints[i]->node;
     2586
     2587        // construct center of circle
     2588        CircleCenter.CopyVector(&Line.endpoints[0]->node->x);
     2589        CircleCenter.AddVector(&Line.endpoints[1]->node->x);
     2590        CircleCenter.Scale(0.5);
     2591
     2592        // construct normal vector of circle
     2593        CirclePlaneNormal.CopyVector(&Line.endpoints[0]->node->x);
     2594        CirclePlaneNormal.SubtractVector(&Line.endpoints[1]->node->x);
     2595
     2596        // calculate squared radius of circle
     2597        radius = CirclePlaneNormal.ScalarProduct(&CirclePlaneNormal);
     2598        if (radius/4. < RADIUS*RADIUS) {
     2599                CircleRadius = RADIUS*RADIUS - radius/4.;
     2600                CirclePlaneNormal.Normalize();
     2601                cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     2602
     2603                // construct old center
     2604                GetCenterofCircumcircle(&OldSphereCenter, &(T.endpoints[0]->node->x), &(T.endpoints[1]->node->x), &(T.endpoints[2]->node->x));
     2605                helper.CopyVector(&T.NormalVector);     // normal vector ensures that this is correct center of the two possible ones
     2606                radius = Line.endpoints[0]->node->x.DistanceSquared(&OldSphereCenter);
     2607                helper.Scale(sqrt(RADIUS*RADIUS - radius));
     2608                OldSphereCenter.AddVector(&helper);
     2609                OldSphereCenter.SubtractVector(&CircleCenter);
     2610                cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
     2611
     2612                // construct SearchDirection
     2613                SearchDirection.MakeNormalVector(&T.NormalVector, &CirclePlaneNormal);
     2614                helper.CopyVector(&Line.endpoints[0]->node->x);
     2615                helper.SubtractVector(&ThirdNode->x);
     2616                if (helper.ScalarProduct(&SearchDirection) < -HULLEPSILON)      // ohoh, SearchDirection points inwards!
     2617                        SearchDirection.Scale(-1.);
     2618                SearchDirection.ProjectOntoPlane(&OldSphereCenter);
     2619                SearchDirection.Normalize();
     2620                cout << Verbose(2) << "INFO: SearchDirection is " << SearchDirection << "." << endl;
     2621                if (fabs(OldSphereCenter.ScalarProduct(&SearchDirection)) > HULLEPSILON) {      // rotated the wrong way!
     2622                        cerr << "ERROR: SearchDirection and RelativeOldSphereCenter are still not orthogonal!" << endl;
     2623                }
     2624
     2625                // add third point
     2626                cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl;
     2627                Find_third_point_for_Tesselation(T.NormalVector, SearchDirection, OldSphereCenter, &Line, ThirdNode, Opt_Candidate, &OptCandidateCenter, &ShortestAngle, RADIUS, LC);
     2628
     2629        } else {
     2630                cout << Verbose(1) << "Circumcircle for base line " << Line << " and base triangle " << T << " is too big!" << endl;
     2631        }
     2632
     2633        if (Opt_Candidate == NULL) {
     2634                cerr << "WARNING: Could not find a suitable candidate." << endl;
     2635                return false;
     2636        }
     2637        cout << Verbose(1) << " Optimal candidate is " << *Opt_Candidate << " with circumsphere's center at " << OptCandidateCenter << "." << endl;
     2638
     2639        // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2640        atom *AtomCandidates[3];
     2641        AtomCandidates[0] = Opt_Candidate;
     2642        AtomCandidates[1] = Line.endpoints[0]->node;
     2643        AtomCandidates[2] = Line.endpoints[1]->node;
     2644        bool flag = CheckPresenceOfTriangle(out, AtomCandidates);
     2645
     2646        if (flag) { // if so, add
     2647                AddTrianglePoint(Opt_Candidate, 0);
     2648                AddTrianglePoint(Line.endpoints[0]->node, 1);
     2649                AddTrianglePoint(Line.endpoints[1]->node, 2);
     2650
     2651                AddTriangleLine(TPS[0], TPS[1], 0);
     2652                AddTriangleLine(TPS[0], TPS[2], 1);
     2653                AddTriangleLine(TPS[1], TPS[2], 2);
     2654
     2655                BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     2656                AddTriangleToLines();
     2657
     2658                OptCandidateCenter.Scale(-1.);
     2659                BTS->GetNormalVector(OptCandidateCenter);
     2660                OptCandidateCenter.Scale(-1.);
     2661
     2662                cout << "--> New triangle with " << *BTS << " and normal vector " << BTS->NormalVector << " for this triangle ... " << endl;
     2663                cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << Line << "." << endl;
     2664        } else { // else, yell and do nothing
     2665                cout << Verbose(1) << "This triangle consisting of ";
     2666                cout << *Opt_Candidate << ", ";
     2667                cout << *Line.endpoints[0]->node << " and ";
     2668                cout << *Line.endpoints[1]->node << " ";
     2669                cout << "is invalid!" << endl;
     2670                return false;
     2671        }
     2672
     2673        if (flag && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 10 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     2674                sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
     2675                if (DoTecplotOutput) {
     2676                        string NameofTempFile(tempbasename);
     2677                        NameofTempFile.append(NumberName);
     2678                        for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
     2679                                NameofTempFile.erase(npos, 1);
     2680                        NameofTempFile.append(TecplotSuffix);
     2681                        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2682                        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2683                        write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten);
     2684                        tempstream->close();
     2685                        tempstream->flush();
     2686                        delete(tempstream);
     2687                }
     2688
     2689                if (DoRaster3DOutput) {
     2690                        string NameofTempFile(tempbasename);
     2691                        NameofTempFile.append(NumberName);
     2692                        for(size_t npos = NameofTempFile.find_first_of(' '); npos != -1; npos = NameofTempFile.find(' ', npos))
     2693                                NameofTempFile.erase(npos, 1);
     2694                        NameofTempFile.append(Raster3DSuffix);
     2695                        cout << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     2696                        tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     2697                        write_raster3d_file(out, tempstream, this, mol);
     2698                        // include the current position of the virtual sphere in the temporary raster3d file
     2699                        // make the circumsphere's center absolute again
     2700                        helper.CopyVector(&Line.endpoints[0]->node->x);
     2701                        helper.AddVector(&Line.endpoints[1]->node->x);
     2702                        helper.Scale(0.5);
     2703                        OptCandidateCenter.AddVector(&helper);
     2704                        Vector *center = mol->DetermineCenterOfAll(out);
     2705                        OptCandidateCenter.AddVector(center);
     2706                        delete(center);
     2707                        // and add to file plus translucency object
     2708                        *tempstream << "# current virtual sphere\n";
     2709                        *tempstream << "8\n     25.0            0.6              -1.0 -1.0 -1.0          0.2                            0 0 0 0\n";
     2710                        *tempstream << "2\n     " << OptCandidateCenter.x[0] << " " << OptCandidateCenter.x[1] << " " << OptCandidateCenter.x[2] << "\t" << RADIUS << "\t1 0 0\n";
     2711                        *tempstream << "9\n     terminating special property\n";
     2712                        tempstream->close();
     2713                        tempstream->flush();
     2714                        delete(tempstream);
     2715                }
     2716                if (DoTecplotOutput || DoRaster3DOutput)
     2717                        TriangleFilesWritten++;
     2718        }
     2719
     2720        cout << Verbose(1) << "End of Find_next_suitable_triangle\n";
     2721        return true;
     2722};
     2723
     2724/** Tesselates the non convex boundary by rolling a virtual sphere along the surface of the molecule.
     2725 * \param *out output stream for debugging
     2726 * \param *mol molecule structure with Atom's and Bond's
     2727 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return
     2728 * \param *LCList linked cell list of all atoms
     2729 * \param *filename filename prefix for output of vertex data
     2730 * \para RADIUS radius of the virtual sphere
     2731 */
     2732void Find_non_convex_border(ofstream *out, molecule* mol, class Tesselation *Tess, class LinkedCell *LCList, const char *filename, const double RADIUS)
     2733{
     2734        int N = 0;
     2735        bool freeTess = false;
     2736        *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     2737        if (Tess == NULL) {
     2738                *out << Verbose(1) << "Allocating Tesselation struct ..." << endl;
     2739                Tess = new Tesselation;
     2740                freeTess = true;
     2741        }
     2742        bool freeLC = false;
     2743        LineMap::iterator baseline;
     2744        *out << Verbose(0) << "Begin of Find_non_convex_border\n";
     2745        bool flag = false;      // marks whether we went once through all baselines without finding any without two triangles
     2746        bool failflag = false;
     2747
     2748        if (LCList == NULL) {
     2749                LCList = new LinkedCell(mol, 2.*RADIUS);
     2750                freeLC = true;
     2751        }
     2752
     2753        Tess->Find_starting_triangle(out, mol, RADIUS, LCList);
     2754
     2755        baseline = Tess->LinesOnBoundary.begin();
     2756        while ((baseline != Tess->LinesOnBoundary.end()) || (flag)) {
     2757                if (baseline->second->TrianglesCount == 1) {
     2758                        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.
     2759                        flag = flag || failflag;
     2760                        if (!failflag)
     2761                                cerr << "WARNING: Find_next_suitable_triangle failed." << endl;
     2762                } else {
     2763                        cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->TrianglesCount << " triangles adjacent" << endl;
     2764                }
     2765                N++;
     2766                baseline++;
     2767                if ((baseline == Tess->LinesOnBoundary.end()) && (flag)) {
     2768                        baseline = Tess->LinesOnBoundary.begin();        // restart if we reach end due to newly inserted lines
     2769                        flag = false;
     2770                }
     2771        }
     2772        if (1) { //failflag) {
     2773                *out << Verbose(1) << "Writing final tecplot file\n";
     2774                if (DoTecplotOutput) {
     2775                        string OutputName(filename);
     2776                        OutputName.append(TecplotSuffix);
     2777                        ofstream *tecplot = new ofstream(OutputName.c_str());
     2778                        write_tecplot_file(out, tecplot, Tess, mol, -1);
     2779                        tecplot->close();
     2780                        delete(tecplot);
     2781                }
     2782                if (DoRaster3DOutput) {
     2783                        string OutputName(filename);
     2784                        OutputName.append(Raster3DSuffix);
     2785                        ofstream *raster = new ofstream(OutputName.c_str());
     2786                        write_raster3d_file(out, raster, Tess, mol);
     2787                        raster->close();
     2788                        delete(raster);
     2789                }
     2790        } else {
     2791                cerr << "ERROR: Could definately not find all necessary triangles!" << endl;
     2792        }
     2793        if (freeTess)
     2794                delete(Tess);
     2795        if (freeLC)
     2796                delete(LCList);
     2797        *out << Verbose(0) << "End of Find_non_convex_border\n";
     2798};
     2799
Note: See TracChangeset for help on using the changeset viewer.