Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    r8c54a3 r2319ed  
    1010#define DoSingleStepOutput 0
    1111#define DoTecplotOutput 1
    12 #define DoRaster3DOutput 0
     12#define DoRaster3DOutput 1
    1313#define DoVRMLOutput 1
    1414#define TecplotSuffix ".dat"
     
    4545void BoundaryPointSet::AddLine(class BoundaryLineSet *line)
    4646{
    47   cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl;
     47  cout << Verbose(6) << "Adding " << *this << " to line " << *line << "."
     48      << endl;
    4849  if (line->endpoints[0] == this)
    4950    {
     
    131132;
    132133
     134/** Checks whether we have a common endpoint with given \a *line.
     135 * \param *line other line to test
     136 * \return true - common endpoint present, false - not connected
     137 */
     138bool BoundaryLineSet::IsConnectedTo(class BoundaryLineSet *line)
     139{
     140  if ((endpoints[0] == line->endpoints[0]) || (endpoints[1] == line->endpoints[0]) || (endpoints[0] == line->endpoints[1]) || (endpoints[1] == line->endpoints[1]))
     141    return true;
     142  else
     143    return false;
     144};
     145
     146/** Checks whether the adjacent triangles of a baseline are convex or not.
     147 * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.
     148 * If greater/equal M_PI than we are convex.
     149 * \param *out output stream for debugging
     150 * \return true - triangles are convex, false - concave or less than two triangles connected
     151 */
     152bool BoundaryLineSet::CheckConvexityCriterion(ofstream *out)
     153{
     154  Vector BaseLineNormal;
     155  double angle = 0;
     156  // get the two triangles
     157  if (TrianglesCount != 2) {
     158    *out << Verbose(1) << "ERROR: Baseline " << this << " is connect to less than two triangles, Tesselation incomplete!" << endl;
     159    return false;
     160  }
     161  // have a normal vector on the base line pointing outwards
     162  BaseLineNormal.Zero();
     163  for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
     164    BaseLineNormal.AddVector(&runner->second->NormalVector);
     165  BaseLineNormal.Normalize();
     166  // and calculate the sum of the angles with this normal vector and each of the triangle ones'
     167  for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
     168    angle += BaseLineNormal.Angle(&runner->second->NormalVector);
     169
     170  if ((angle - M_PI) > -MYEPSILON)
     171    return true;
     172  else
     173    return false;
     174}
     175
     176/** Checks whether point is any of the two endpoints this line contains.
     177 * \param *point point to test
     178 * \return true - point is of the line, false - is not
     179 */
     180bool BoundaryLineSet::ContainsBoundaryPoint(class BoundaryPointSet *point)
     181{
     182  for(int i=0;i<2;i++)
     183    if (point == endpoints[i])
     184      return true;
     185  return false;
     186};
     187
    133188ostream &
    134189operator <<(ostream &ost, BoundaryLineSet &a)
     
    213268;
    214269
    215 void
    216 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
     270/** Calculates the normal vector for this triangle.
     271 * Is made unique by comparison with \a OtherVector to point in the other direction.
     272 * \param &OtherVector direction vector to make normal vector unique.
     273 */
     274void BoundaryTriangleSet::GetNormalVector(Vector &OtherVector)
    217275{
    218276  // get normal vector
     
    223281  if (NormalVector.Projection(&OtherVector) > 0)
    224282    NormalVector.Scale(-1.);
    225 }
    226 ;
     283};
     284
     285/** Finds the point on the triangle \a *BTS the line defined by \a *MolCenter and \a *x crosses through.
     286 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane
     287 * This we test if it's really on the plane and whether it's inside the triangle on the plane or not.
     288 * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite
     289 * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared()
     290 * smaller than the first line.
     291 * \param *out output stream for debugging
     292 * \param *MolCenter offset vector of line
     293 * \param *x second endpoint of line, minus \a *MolCenter is directional vector of line
     294 * \param *Intersection intersection on plane on return
     295 * \return true - \a *Intersection contains intersection on plane defined by triangle, false - zero vector if outside of triangle.
     296 */
     297bool BoundaryTriangleSet::GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection)
     298{
     299  Vector CrossPoint;
     300  Vector helper;
     301  int i=0;
     302
     303  if (Intersection->GetIntersectionWithPlane(out, &NormalVector, &endpoints[0]->node->x, MolCenter, x)) {
     304    *out << Verbose(1) << "Alas! [Bronstein] failed - at least numerically - the intersection is not on the plane!" << endl;
     305    return false;
     306  }
     307
     308  // Calculate cross point between one baseline and the line from the third endpoint to intersection
     309  do {
     310    CrossPoint.GetIntersectionOfTwoLinesOnPlane(out, &endpoints[i%3]->node->x, &endpoints[(i+1)%3]->node->x, &endpoints[(i+2)%3]->node->x, Intersection);
     311    helper.CopyVector(&endpoints[(i+1)%3]->node->x);
     312    helper.SubtractVector(&endpoints[i%3]->node->x);
     313    i++;
     314    if (i>3)
     315      break;
     316  } while (CrossPoint.NormSquared() < MYEPSILON);
     317  if (i>3) {
     318    *out << Verbose(1) << "ERROR: Could not find any cross points, something's utterly wrong here!" << endl;
     319    exit(255);
     320  }
     321  CrossPoint.SubtractVector(&endpoints[i%3]->node->x);
     322
     323  // check whether intersection is inside or not by comparing length of intersection and length of cross point
     324  if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside
     325    return true;
     326  } else { // outside!
     327    Intersection->Zero();
     328    return false;
     329  }
     330};
     331
     332/** Checks whether lines is any of the three boundary lines this triangle contains.
     333 * \param *line line to test
     334 * \return true - line is of the triangle, false - is not
     335 */
     336bool BoundaryTriangleSet::ContainsBoundaryLine(class BoundaryLineSet *line)
     337{
     338  for(int i=0;i<3;i++)
     339    if (line == lines[i])
     340      return true;
     341  return false;
     342};
     343
     344/** Checks whether point is any of the three endpoints this triangle contains.
     345 * \param *point point to test
     346 * \return true - point is of the triangle, false - is not
     347 */
     348bool BoundaryTriangleSet::ContainsBoundaryPoint(class BoundaryPointSet *point)
     349{
     350  for(int i=0;i<3;i++)
     351    if (point == endpoints[i])
     352      return true;
     353  return false;
     354};
    227355
    228356ostream &
     
    239367
    240368CandidateForTesselation::CandidateForTesselation(
    241         atom *candidate, BoundaryLineSet* line, Vector OptCandidateCenter, Vector OtherOptCandidateCenter
     369  atom *candidate, BoundaryLineSet* line, Vector OptCandidateCenter, Vector OtherOptCandidateCenter
    242370) {
    243         point = candidate;
    244         BaseLine = line;
    245         OptCenter.CopyVector(&OptCandidateCenter);
    246         OtherOptCenter.CopyVector(&OtherOptCandidateCenter);
     371  point = candidate;
     372  BaseLine = line;
     373  OptCenter.CopyVector(&OptCandidateCenter);
     374  OtherOptCenter.CopyVector(&OtherOptCandidateCenter);
    247375}
    248376
    249377CandidateForTesselation::~CandidateForTesselation() {
    250         point = NULL;
    251         BaseLine = NULL;
     378  point = NULL;
     379  BaseLine = NULL;
    252380}
    253381
     
    301429  LineMap LinesOnBoundary;
    302430  TriangleMap TrianglesOnBoundary;
     431  Vector *MolCenter = mol->DetermineCenterOfAll(out);
     432  Vector helper;
    303433
    304434  *out << Verbose(1) << "Finding all boundary points." << endl;
     
    308438  double radius, angle;
    309439  // 3a. Go through every axis
    310   for (int axis = 0; axis < NDIM; axis++)
    311     {
    312       AxisVector.Zero();
    313       AngleReferenceVector.Zero();
    314       AngleReferenceNormalVector.Zero();
    315       AxisVector.x[axis] = 1.;
    316       AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
    317       AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
    318       //    *out << Verbose(1) << "Axisvector is ";
    319       //    AxisVector.Output(out);
    320       //    *out << " and AngleReferenceVector is ";
    321       //    AngleReferenceVector.Output(out);
    322       //    *out << "." << endl;
    323       //    *out << " and AngleReferenceNormalVector is ";
    324       //    AngleReferenceNormalVector.Output(out);
    325       //    *out << "." << endl;
    326       // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
    327       Walker = mol->start;
    328       while (Walker->next != mol->end)
     440  for (int axis = 0; axis < NDIM; axis++) {
     441    AxisVector.Zero();
     442    AngleReferenceVector.Zero();
     443    AngleReferenceNormalVector.Zero();
     444    AxisVector.x[axis] = 1.;
     445    AngleReferenceVector.x[(axis + 1) % NDIM] = 1.;
     446    AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.;
     447
     448    *out << Verbose(1) << "Axisvector is " << AxisVector << " and AngleReferenceVector is " << AngleReferenceVector << ", and AngleReferenceNormalVector is " << AngleReferenceNormalVector << "." << endl;
     449
     450    // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     451    Walker = mol->start;
     452    while (Walker->next != mol->end) {
     453      Walker = Walker->next;
     454      Vector ProjectedVector;
     455      ProjectedVector.CopyVector(&Walker->x);
     456      ProjectedVector.SubtractVector(MolCenter);
     457      ProjectedVector.ProjectOntoPlane(&AxisVector);
     458
     459      // correct for negative side
     460      radius = ProjectedVector.NormSquared();
     461      if (fabs(radius) > MYEPSILON)
     462        angle = ProjectedVector.Angle(&AngleReferenceVector);
     463      else
     464        angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
     465
     466      //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
     467      if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) {
     468        angle = 2. * M_PI - angle;
     469      }
     470      *out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): " << ProjectedVector << endl;
     471      BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, DistancePair (radius, Walker)));
     472      if (!BoundaryTestPair.second) { // same point exists, check first r, then distance of original vectors to center of gravity
     473        *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;
     474        *out << Verbose(2) << "Present vector: " << *BoundaryTestPair.first->second.second << endl;
     475        *out << Verbose(2) << "New vector: " << *Walker << endl;
     476        double tmp = ProjectedVector.NormSquared();
     477        if ((tmp - BoundaryTestPair.first->second.first) > MYEPSILON) {
     478          BoundaryTestPair.first->second.first = tmp;
     479          BoundaryTestPair.first->second.second = Walker;
     480          *out << Verbose(2) << "Keeping new vector due to larger projected distance " << tmp << "." << endl;
     481        } else if (fabs(tmp - BoundaryTestPair.first->second.first) < MYEPSILON) {
     482          helper.CopyVector(&Walker->x);
     483          helper.SubtractVector(MolCenter);
     484          tmp = helper.NormSquared();
     485          helper.CopyVector(&BoundaryTestPair.first->second.second->x);
     486          helper.SubtractVector(MolCenter);
     487          if (helper.NormSquared() < tmp) {
     488            BoundaryTestPair.first->second.second = Walker;
     489            *out << Verbose(2) << "Keeping new vector due to larger distance to molecule center " << helper.NormSquared() << "." << endl;
     490          } else {
     491            *out << Verbose(2) << "Keeping present vector due to larger distance to molecule center " << tmp << "." << endl;
     492          }
     493        } else {
     494          *out << Verbose(2) << "Keeping present vector due to larger projected distance " << tmp << "." << endl;
     495        }
     496      }
     497    }
     498    // printing all inserted for debugging
     499    //    {
     500    //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     501    //      int i=0;
     502    //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     503    //        if (runner != BoundaryPoints[axis].begin())
     504    //          *out << ", " << i << ": " << *runner->second.second;
     505    //        else
     506    //          *out << i << ": " << *runner->second.second;
     507    //        i++;
     508    //      }
     509    //      *out << endl;
     510    //    }
     511    // 3c. throw out points whose distance is less than the mean of left and right neighbours
     512    bool flag = false;
     513    *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl;
     514    do { // do as long as we still throw one out per round
     515      flag = false;
     516      Boundaries::iterator left = BoundaryPoints[axis].end();
     517      Boundaries::iterator right = BoundaryPoints[axis].end();
     518      for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     519        // set neighbours correctly
     520        if (runner == BoundaryPoints[axis].begin()) {
     521          left = BoundaryPoints[axis].end();
     522        } else {
     523          left = runner;
     524        }
     525        left--;
     526        right = runner;
     527        right++;
     528        if (right == BoundaryPoints[axis].end()) {
     529          right = BoundaryPoints[axis].begin();
     530        }
     531        // check distance
     532
     533        // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    329534        {
    330           Walker = Walker->next;
    331           Vector ProjectedVector;
    332           ProjectedVector.CopyVector(&Walker->x);
    333           ProjectedVector.ProjectOntoPlane(&AxisVector);
    334           // correct for negative side
    335           //if (Projection(y) < 0)
    336           //angle = 2.*M_PI - angle;
    337           radius = ProjectedVector.Norm();
    338           if (fabs(radius) > MYEPSILON)
    339             angle = ProjectedVector.Angle(&AngleReferenceVector);
    340           else
    341             angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues
    342 
    343           //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl;
    344           if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0)
    345             {
    346               angle = 2. * M_PI - angle;
    347             }
    348           //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): ";
    349           //ProjectedVector.Output(out);
    350           //*out << endl;
    351           BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle,
    352               DistancePair (radius, Walker)));
    353           if (BoundaryTestPair.second)
    354             { // successfully inserted
    355             }
    356           else
    357             { // same point exists, check first r, then distance of original vectors to center of gravity
    358               *out << Verbose(2)
    359                   << "Encountered two vectors whose projection onto axis "
    360                   << axis << " is equal: " << endl;
    361               *out << Verbose(2) << "Present vector: ";
    362               BoundaryTestPair.first->second.second->x.Output(out);
    363               *out << endl;
    364               *out << Verbose(2) << "New vector: ";
    365               Walker->x.Output(out);
    366               *out << endl;
    367               double tmp = ProjectedVector.Norm();
    368               if (tmp > BoundaryTestPair.first->second.first)
    369                 {
    370                   BoundaryTestPair.first->second.first = tmp;
    371                   BoundaryTestPair.first->second.second = Walker;
    372                   *out << Verbose(2) << "Keeping new vector." << endl;
    373                 }
    374               else if (tmp == BoundaryTestPair.first->second.first)
    375                 {
    376                   if (BoundaryTestPair.first->second.second->x.ScalarProduct(
    377                       &BoundaryTestPair.first->second.second->x)
    378                       < Walker->x.ScalarProduct(&Walker->x))
    379                     { // Norm() does a sqrt, which makes it a lot slower
    380                       BoundaryTestPair.first->second.second = Walker;
    381                       *out << Verbose(2) << "Keeping new vector." << endl;
    382                     }
    383                   else
    384                     {
    385                       *out << Verbose(2) << "Keeping present vector." << endl;
    386                     }
    387                 }
    388               else
    389                 {
    390                   *out << Verbose(2) << "Keeping present vector." << endl;
    391                 }
    392             }
     535          Vector SideA, SideB, SideC, SideH;
     536          SideA.CopyVector(&left->second.second->x);
     537          SideA.SubtractVector(MolCenter);
     538          SideA.ProjectOntoPlane(&AxisVector);
     539          //          *out << "SideA: ";
     540          //          SideA.Output(out);
     541          //          *out << endl;
     542
     543          SideB.CopyVector(&right->second.second->x);
     544          SideB.SubtractVector(MolCenter);
     545          SideB.ProjectOntoPlane(&AxisVector);
     546          //          *out << "SideB: ";
     547          //          SideB.Output(out);
     548          //          *out << endl;
     549
     550          SideC.CopyVector(&left->second.second->x);
     551          SideC.SubtractVector(&right->second.second->x);
     552          SideC.ProjectOntoPlane(&AxisVector);
     553          //          *out << "SideC: ";
     554          //          SideC.Output(out);
     555          //          *out << endl;
     556
     557          SideH.CopyVector(&runner->second.second->x);
     558          SideH.SubtractVector(MolCenter);
     559          SideH.ProjectOntoPlane(&AxisVector);
     560          //          *out << "SideH: ";
     561          //          SideH.Output(out);
     562          //          *out << endl;
     563
     564          // calculate each length
     565          double a = SideA.Norm();
     566          //double b = SideB.Norm();
     567          //double c = SideC.Norm();
     568          double h = SideH.Norm();
     569          // calculate the angles
     570          double alpha = SideA.Angle(&SideH);
     571          double beta = SideA.Angle(&SideC);
     572          double gamma = SideB.Angle(&SideH);
     573          double delta = SideC.Angle(&SideH);
     574          double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
     575          //*out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl;
     576          *out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl;
     577          if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) < MYEPSILON) && ((h - MinDistance)) < -MYEPSILON) {
     578            // throw out point
     579            *out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
     580            BoundaryPoints[axis].erase(runner);
     581            flag = true;
     582          }
    393583        }
    394       // printing all inserted for debugging
    395       //    {
    396       //      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
    397       //      int i=0;
    398       //      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
    399       //        if (runner != BoundaryPoints[axis].begin())
    400       //          *out << ", " << i << ": " << *runner->second.second;
    401       //        else
    402       //          *out << i << ": " << *runner->second.second;
    403       //        i++;
    404       //      }
    405       //      *out << endl;
    406       //    }
    407       // 3c. throw out points whose distance is less than the mean of left and right neighbours
    408       bool flag = false;
    409       do
    410         { // do as long as we still throw one out per round
    411           *out << Verbose(1)
    412               << "Looking for candidates to kick out by convex condition ... "
    413               << endl;
    414           flag = false;
    415           Boundaries::iterator left = BoundaryPoints[axis].end();
    416           Boundaries::iterator right = BoundaryPoints[axis].end();
    417           for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    418               != BoundaryPoints[axis].end(); runner++)
    419             {
    420               // set neighbours correctly
    421               if (runner == BoundaryPoints[axis].begin())
    422                 {
    423                   left = BoundaryPoints[axis].end();
    424                 }
    425               else
    426                 {
    427                   left = runner;
    428                 }
    429               left--;
    430               right = runner;
    431               right++;
    432               if (right == BoundaryPoints[axis].end())
    433                 {
    434                   right = BoundaryPoints[axis].begin();
    435                 }
    436               // check distance
    437 
    438               // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector)
    439                 {
    440                   Vector SideA, SideB, SideC, SideH;
    441                   SideA.CopyVector(&left->second.second->x);
    442                   SideA.ProjectOntoPlane(&AxisVector);
    443                   //          *out << "SideA: ";
    444                   //          SideA.Output(out);
    445                   //          *out << endl;
    446 
    447                   SideB.CopyVector(&right->second.second->x);
    448                   SideB.ProjectOntoPlane(&AxisVector);
    449                   //          *out << "SideB: ";
    450                   //          SideB.Output(out);
    451                   //          *out << endl;
    452 
    453                   SideC.CopyVector(&left->second.second->x);
    454                   SideC.SubtractVector(&right->second.second->x);
    455                   SideC.ProjectOntoPlane(&AxisVector);
    456                   //          *out << "SideC: ";
    457                   //          SideC.Output(out);
    458                   //          *out << endl;
    459 
    460                   SideH.CopyVector(&runner->second.second->x);
    461                   SideH.ProjectOntoPlane(&AxisVector);
    462                   //          *out << "SideH: ";
    463                   //          SideH.Output(out);
    464                   //          *out << endl;
    465 
    466                   // calculate each length
    467                   double a = SideA.Norm();
    468                   //double b = SideB.Norm();
    469                   //double c = SideC.Norm();
    470                   double h = SideH.Norm();
    471                   // calculate the angles
    472                   double alpha = SideA.Angle(&SideH);
    473                   double beta = SideA.Angle(&SideC);
    474                   double gamma = SideB.Angle(&SideH);
    475                   double delta = SideC.Angle(&SideH);
    476                   double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha
    477                       < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.);
    478                   //          *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;
    479                   //*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;
    480                   if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance))
    481                       < MYEPSILON) && (h < MinDistance))
    482                     {
    483                       // throw out point
    484                       //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl;
    485                       BoundaryPoints[axis].erase(runner);
    486                       flag = true;
    487                     }
    488                 }
    489             }
    490         }
    491       while (flag);
    492     }
     584      }
     585    } while (flag);
     586  }
     587  delete(MolCenter);
    493588  return BoundaryPoints;
    494589}
     
    619714      *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
    620715      for (i=0;i<NDIM;i++)
    621         *vrmlfile << Walker->x.x[i]+center->x[i] << " ";
     716        *vrmlfile << Walker->x.x[i]-center->x[i] << " ";
    622717      *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    623718    }
     
    628723      *vrmlfile << "3" << endl << "  "; // 2 is round-ended cylinder type
    629724      for (i=0;i<NDIM;i++)
    630         *vrmlfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     725        *vrmlfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    631726      *vrmlfile << "\t0.03\t";
    632727      for (i=0;i<NDIM;i++)
    633         *vrmlfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     728        *vrmlfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    634729      *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    635730    }
     
    640735      for (i=0;i<3;i++) { // print each node
    641736        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    642           *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     737          *vrmlfile << TriangleRunner->second->endpoints[i]->node->x.x[j]-center->x[j] << " ";
    643738        *vrmlfile << "\t";
    644739      }
     
    673768      *rasterfile << "2" << endl << "  ";  // 2 is sphere type
    674769      for (i=0;i<NDIM;i++)
    675         *rasterfile << Walker->x.x[i]+center->x[i] << " ";
     770        *rasterfile << Walker->x.x[i]-center->x[i] << " ";
    676771      *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    677772    }
     
    682777      *rasterfile << "3" << endl << "  ";  // 2 is round-ended cylinder type
    683778      for (i=0;i<NDIM;i++)
    684         *rasterfile << Binder->leftatom->x.x[i]+center->x[i] << " ";
     779        *rasterfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    685780      *rasterfile << "\t0.03\t";
    686781      for (i=0;i<NDIM;i++)
    687         *rasterfile << Binder->rightatom->x.x[i]+center->x[i] << " ";
     782        *rasterfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    688783      *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    689784    }
     
    695790      for (i=0;i<3;i++) {  // print each node
    696791        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    697           *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]+center->x[j] << " ";
     792          *rasterfile << TriangleRunner->second->endpoints[i]->node->x.x[j]-center->x[j] << " ";
    698793        *rasterfile << "\t";
    699794      }
     
    713808 * \param N arbitrary number to differentiate various zones in the tecplot format
    714809 */
    715 void
    716 write_tecplot_file(ofstream *out, ofstream *tecplot,
    717     class Tesselation *TesselStruct, class molecule *mol, int N)
    718 {
    719   if (tecplot != NULL)
    720     {
    721       *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    722       *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
    723       *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N="
    724           << TesselStruct->PointsOnBoundaryCount << ", E="
    725           << TesselStruct->TrianglesOnBoundaryCount
    726           << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    727       int *LookupList = new int[mol->AtomCount];
    728       for (int i = 0; i < mol->AtomCount; i++)
    729         LookupList[i] = -1;
    730 
    731       // print atom coordinates
    732       *out << Verbose(2) << "The following triangles were created:";
    733       int Counter = 1;
    734       atom *Walker = NULL;
    735       for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target
    736           != TesselStruct->PointsOnBoundary.end(); target++)
    737         {
    738           Walker = target->second->node;
    739           LookupList[Walker->nr] = Counter++;
    740           *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " "
    741               << Walker->x.x[2] << " " << endl;
    742         }
    743       *tecplot << endl;
    744       // print connectivity
    745       for (TriangleMap::iterator runner =
    746           TesselStruct->TrianglesOnBoundary.begin(); runner
    747           != TesselStruct->TrianglesOnBoundary.end(); runner++)
    748         {
    749           *out << " " << runner->second->endpoints[0]->node->Name << "<->"
    750               << runner->second->endpoints[1]->node->Name << "<->"
    751               << runner->second->endpoints[2]->node->Name;
    752           *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " "
    753               << LookupList[runner->second->endpoints[1]->node->nr] << " "
    754               << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    755         }
    756       delete[] (LookupList);
    757       *out << endl;
    758     }
     810void write_tecplot_file(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol, int N)
     811{
     812  if (tecplot != NULL) {
     813    *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
     814    *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl;
     815    *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" << TesselStruct->PointsOnBoundaryCount << ", E=" << TesselStruct->TrianglesOnBoundaryCount << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     816    int *LookupList = new int[mol->AtomCount];
     817    for (int i = 0; i < mol->AtomCount; i++)
     818      LookupList[i] = -1;
     819
     820    // print atom coordinates
     821    *out << Verbose(2) << "The following triangles were created:";
     822    int Counter = 1;
     823    atom *Walker = NULL;
     824    for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
     825      Walker = target->second->node;
     826      LookupList[Walker->nr] = Counter++;
     827      *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl;
     828    }
     829    *tecplot << endl;
     830    // print connectivity
     831    for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {
     832      *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
     833      *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     834    }
     835    delete[] (LookupList);
     836    *out << endl;
     837  }
    759838}
    760839
    761 /** Determines the volume of a cluster.
    762  * Determines first the convex envelope, then tesselates it and calculates its volume.
     840/** Tesselates the convex boundary by finding all boundary points.
    763841 * \param *out output stream for debugging
     842 * \param *mol molecule structure with Atom's and Bond's
     843 * \param *TesselStruct Tesselation filled with points, lines and triangles on boundary on return
     844 * \param *LCList atoms in LinkedCell list
    764845 * \param *filename filename prefix for output of vertex data
    765  * \param *configuration needed for path to store convex envelope file
    766  * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired
    767  * \param *mol molecule structure representing the cluster
    768  * \return determined volume of the cluster in cubed config:GetIsAngstroem()
    769  */
    770 double
    771 VolumeOfConvexEnvelope(ofstream *out, const char *filename, config *configuration,
    772     Boundaries *BoundaryPtr, molecule *mol)
    773 {
    774   bool IsAngstroem = configuration->GetIsAngstroem();
    775   atom *Walker = NULL;
    776   struct Tesselation *TesselStruct = new Tesselation;
     846 * \return *TesselStruct is filled with convex boundary and tesselation is stored under \a *filename.
     847 */
     848void Find_convex_border(ofstream *out, molecule* mol, class Tesselation *&TesselStruct, class LinkedCell *LCList, const char *filename)
     849{
    777850  bool BoundaryFreeFlag = false;
    778   Boundaries *BoundaryPoints = BoundaryPtr;
    779   double volume = 0.;
    780   double PyramidVolume = 0.;
    781   double G, h;
    782   Vector x, y;
    783   double a, b, c;
    784 
    785   //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line.
    786 
    787   // 1. calculate center of gravity
    788   *out << endl;
    789   Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out);
    790 
    791   // 2. translate all points into CoG
    792   *out << Verbose(1) << "Translating system to Center of Gravity." << endl;
    793   Walker = mol->start;
    794   while (Walker->next != mol->end)
    795     {
    796       Walker = Walker->next;
    797       Walker->x.Translate(CenterOfGravity);
    798     }
    799 
    800   // 3. Find all points on the boundary
    801   if (BoundaryPoints == NULL)
    802     {
     851  Boundaries *BoundaryPoints = NULL;
     852
     853  cout << Verbose(1) << "Begin of find_convex_border" << endl;
     854
     855  if (TesselStruct != NULL) // free if allocated
     856    delete(TesselStruct);
     857  TesselStruct = new class Tesselation;
     858
     859  // 1. Find all points on the boundary
     860  if (BoundaryPoints == NULL) {
    803861      BoundaryFreeFlag = true;
    804862      BoundaryPoints = GetBoundaryPoints(out, mol);
    805     }
    806   else
     863  } else {
     864      *out << Verbose(1) << "Using given boundary points set." << endl;
     865  }
     866
     867// printing all inserted for debugging
     868  for (int axis=0; axis < NDIM; axis++)
    807869    {
    808       *out << Verbose(1) << "Using given boundary points set." << endl;
    809     }
    810 
    811   // 4. fill the boundary point list
     870      *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl;
     871      int i=0;
     872      for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     873        if (runner != BoundaryPoints[axis].begin())
     874          *out << ", " << i << ": " << *runner->second.second;
     875        else
     876          *out << i << ": " << *runner->second.second;
     877        i++;
     878      }
     879      *out << endl;
     880    }
     881
     882  // 2. fill the boundary point list
    812883  for (int axis = 0; axis < NDIM; axis++)
    813     for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner
    814         != BoundaryPoints[axis].end(); runner++)
    815       {
     884    for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++)
    816885        TesselStruct->AddPoint(runner->second.second);
    817       }
    818 
    819   *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount
    820       << " points on the convex boundary." << endl;
     886
     887  *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl;
    821888  // now we have the whole set of edge points in the BoundaryList
    822889
     
    828895  //  *out << endl;
    829896
    830   // 5a. guess starting triangle
     897  // 3a. guess starting triangle
    831898  TesselStruct->GuessStartingTriangle(out);
    832899
    833   // 5b. go through all lines, that are not yet part of two triangles (only of one so far)
    834   TesselStruct->TesselateOnBoundary(out, configuration, mol);
    835 
    836   *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount
    837       << " triangles with " << TesselStruct->LinesOnBoundaryCount
    838       << " lines and " << TesselStruct->PointsOnBoundaryCount << " points."
    839       << endl;
     900  // 3b. go through all lines, that are not yet part of two triangles (only of one so far)
     901  TesselStruct->TesselateOnBoundary(out, mol);
     902
     903  // 3c. check whether all atoms lay inside the boundary, if not, add to boundary points, segment triangle into three with the new point
     904  if (!TesselStruct->InsertStraddlingPoints(out, mol))
     905    *out << Verbose(1) << "Insertion of straddling points failed!" << endl;
     906
     907  // 3d. check all baselines whether the peaks of the two adjacent triangles with respect to center of baseline are convex, if not, make the baseline between the two peaks and baseline endpoints become the new peaks
     908  if (!TesselStruct->CorrectConcaveBaselines(out))
     909    *out << Verbose(1) << "Correction of concave baselines failed!" << endl;
     910
     911  *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundary.size() << " triangles with " << TesselStruct->LinesOnBoundary.size() << " lines and " << TesselStruct->PointsOnBoundary.size() << " points." << endl;
     912
     913  // 4. Store triangles in tecplot file
     914  if (filename != NULL) {
     915    if (DoTecplotOutput) {
     916      string OutputName(filename);
     917      OutputName.append(TecplotSuffix);
     918      ofstream *tecplot = new ofstream(OutputName.c_str());
     919      write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
     920      tecplot->close();
     921      delete(tecplot);
     922    }
     923    if (DoRaster3DOutput) {
     924      string OutputName(filename);
     925      OutputName.append(Raster3DSuffix);
     926      ofstream *rasterplot = new ofstream(OutputName.c_str());
     927      write_raster3d_file(out, rasterplot, TesselStruct, mol);
     928      rasterplot->close();
     929      delete(rasterplot);
     930    }
     931  }
     932
     933  // free reference lists
     934  if (BoundaryFreeFlag)
     935    delete[] (BoundaryPoints);
     936
     937  cout << Verbose(1) << "End of find_convex_border" << endl;
     938};
     939
     940
     941/** Determines the volume of a cluster.
     942 * Determines first the convex envelope, then tesselates it and calculates its volume.
     943 * \param *out output stream for debugging
     944 * \param *TesselStruct Tesselation filled with points, lines and triangles on boundary on return
     945 * \param *configuration needed for path to store convex envelope file
     946 * \return determined volume of the cluster in cubed config:GetIsAngstroem()
     947 */
     948double VolumeOfConvexEnvelope(ofstream *out, class Tesselation *TesselStruct, class config *configuration)
     949{
     950  bool IsAngstroem = configuration->GetIsAngstroem();
     951  double volume = 0.;
     952  double PyramidVolume = 0.;
     953  double G, h;
     954  Vector x, y;
     955  double a, b, c;
    840956
    841957  // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
     
    873989      << endl;
    874990
    875   // 7. translate all points back from CoG
    876   *out << Verbose(1) << "Translating system back from Center of Gravity."
    877       << endl;
    878   CenterOfGravity->Scale(-1);
    879   Walker = mol->start;
    880   while (Walker->next != mol->end)
    881     {
    882       Walker = Walker->next;
    883       Walker->x.Translate(CenterOfGravity);
    884     }
    885 
    886   // 8. Store triangles in tecplot file
    887   string OutputName(filename);
    888   OutputName.append(TecplotSuffix);
    889   ofstream *tecplot = new ofstream(OutputName.c_str());
    890   write_tecplot_file(out, tecplot, TesselStruct, mol, 0);
    891   tecplot->close();
    892   delete(tecplot);
    893 
    894   // free reference lists
    895   if (BoundaryFreeFlag)
    896     delete[] (BoundaryPoints);
    897 
    898991  return volume;
    899992}
     
    9181011  bool IsAngstroem = configuration->GetIsAngstroem();
    9191012  Boundaries *BoundaryPoints = GetBoundaryPoints(out, mol);
     1013  class Tesselation *TesselStruct = NULL;
     1014  LinkedCell LCList(mol, 10.);
     1015  Find_convex_border(out, mol, TesselStruct, &LCList, NULL);
    9201016  double clustervolume;
    9211017  if (ClusterVolume == 0)
    922     clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration,
    923         BoundaryPoints, mol);
     1018    clustervolume = VolumeOfConvexEnvelope(out, TesselStruct, configuration);
    9241019  else
    9251020    clustervolume = ClusterVolume;
    926   double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol,
    927       IsAngstroem);
     1021  double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem);
    9281022  Vector BoxLengths;
    9291023  int repetition[NDIM] =
     
    10101104      // set new box dimensions
    10111105      *out << Verbose(0) << "Translating to box with these boundaries." << endl;
    1012       mol->CenterInBox((ofstream *) &cout, &BoxLengths);
     1106      mol->SetBoxDimension(&BoxLengths);
     1107      mol->CenterInBox((ofstream *) &cout);
    10131108    }
    10141109  // update Box of atoms by boundary
     
    10201115}
    10211116;
     1117
     1118
     1119/** Fills the empty space of the simulation box with water/
     1120 * \param *out output stream for debugging
     1121 * \param *List list of molecules already present in box
     1122 * \param *TesselStruct contains tesselated surface
     1123 * \param *filler molecule which the box is to be filled with
     1124 * \param configuration contains box dimensions
     1125 * \param distance[NDIM] distance between filling molecules in each direction
     1126 * \param RandAtomDisplacement maximum distance for random displacement per atom
     1127 * \param RandMolDisplacement maximum distance for random displacement per filler molecule
     1128 * \param DoRandomRotation true - do random rotiations, false - don't
     1129 * \return *mol pointer to new molecule with filled atoms
     1130 */
     1131molecule * FillBoxWithMolecule(ofstream *out, MoleculeListClass *List, molecule *filler, config &configuration, double distance[NDIM], double RandomAtomDisplacement, double RandomMolDisplacement, bool DoRandomRotation)
     1132{
     1133  molecule *Filling = new molecule(filler->elemente);
     1134  Vector CurrentPosition;
     1135  int N[NDIM];
     1136  int n[NDIM];
     1137  double *M =  filler->ReturnFullMatrixforSymmetric(filler->cell_size);
     1138  double Rotations[NDIM*NDIM];
     1139  Vector AtomTranslations;
     1140  Vector FillerTranslations;
     1141  Vector FillerDistance;
     1142  double FillIt = false;
     1143  atom *Walker = NULL, *Runner = NULL;
     1144  bond *Binder = NULL;
     1145
     1146  // Center filler at origin
     1147  filler->CenterOrigin(out);
     1148  filler->Center.Zero();
     1149
     1150  // calculate filler grid in [0,1]^3
     1151  FillerDistance.Init(distance[0], distance[1], distance[2]);
     1152  FillerDistance.InverseMatrixMultiplication(M);
     1153  for(int i=0;i<NDIM;i++)
     1154    N[i] = ceil(1./FillerDistance.x[i]);
     1155
     1156  // go over [0,1]^3 filler grid
     1157  for (n[0] = 0; n[0] < N[0]; n[0]++)
     1158    for (n[1] = 0; n[1] < N[1]; n[1]++)
     1159      for (n[2] = 0; n[2] < N[2]; n[2]++) {
     1160        // calculate position of current grid vector in untransformed box
     1161        CurrentPosition.Init(n[0], n[1], n[2]);
     1162        CurrentPosition.MatrixMultiplication(M);
     1163        // Check whether point is in- or outside
     1164        FillIt = true;
     1165        for (MoleculeList::iterator ListRunner = List->ListOfMolecules.begin(); ListRunner != List->ListOfMolecules.end(); ListRunner++) {
     1166          FillIt = FillIt && (!(*ListRunner)->TesselStruct->IsInside(&CurrentPosition));
     1167        }
     1168
     1169        if (FillIt) {
     1170          // fill in Filler
     1171          *out << Verbose(2) << "Space at " << CurrentPosition << " is unoccupied by any molecule, filling in." << endl;
     1172
     1173          // create molecule random translation vector ...
     1174          for (int i=0;i<NDIM;i++)
     1175            FillerTranslations.x[i] = RandomMolDisplacement*(rand()/(RAND_MAX/2.) - 1.);
     1176
     1177          // go through all atoms
     1178          Walker = filler->start;
     1179          while (Walker != filler->end) {
     1180            Walker = Walker->next;
     1181            // copy atom ...
     1182            *Runner = new atom(Walker);
     1183
     1184            // create atomic random translation vector ...
     1185            for (int i=0;i<NDIM;i++)
     1186              AtomTranslations.x[i] = RandomAtomDisplacement*(rand()/(RAND_MAX/2.) - 1.);
     1187
     1188            // ... and rotation matrix
     1189            if (DoRandomRotation) {
     1190              double phi[NDIM];
     1191              for (int i=0;i<NDIM;i++) {
     1192                phi[i] = rand()/(RAND_MAX/(2.*M_PI));
     1193              }
     1194
     1195              Rotations[0] =   cos(phi[0])            *cos(phi[2]) + (sin(phi[0])*sin(phi[1])*sin(phi[2]));
     1196              Rotations[3] =   sin(phi[0])            *cos(phi[2]) - (cos(phi[0])*sin(phi[1])*sin(phi[2]));
     1197              Rotations[6] =               cos(phi[1])*sin(phi[2])                                     ;
     1198              Rotations[1] = - sin(phi[0])*cos(phi[1])                                                ;
     1199              Rotations[4] =   cos(phi[0])*cos(phi[1])                                                ;
     1200              Rotations[7] =               sin(phi[1])                                                ;
     1201              Rotations[3] = - cos(phi[0])            *sin(phi[2]) + (sin(phi[0])*sin(phi[1])*cos(phi[2]));
     1202              Rotations[5] = - sin(phi[0])            *sin(phi[2]) - (cos(phi[0])*sin(phi[1])*cos(phi[2]));
     1203              Rotations[8] =               cos(phi[1])*cos(phi[2])                                     ;
     1204            }
     1205
     1206            // ... and put at new position
     1207            if (DoRandomRotation)
     1208              Runner->x.MatrixMultiplication(Rotations);
     1209            Runner->x.AddVector(&AtomTranslations);
     1210            Runner->x.AddVector(&FillerTranslations);
     1211            Runner->x.AddVector(&CurrentPosition);
     1212            // insert into Filling
     1213            Filling->AddAtom(Runner);
     1214          }
     1215
     1216          // go through all bonds and add as well
     1217          Binder = filler->first;
     1218          while(Binder != filler->last) {
     1219            Binder = Binder->next;
     1220          }
     1221        } else {
     1222          // leave empty
     1223          *out << Verbose(2) << "Space at " << CurrentPosition << " is occupied." << endl;
     1224        }
     1225      }
     1226  return Filling;
     1227};
     1228
    10221229
    10231230// =========================================================== class TESSELATION ===========================================
     
    11331340                  << A->second->node->Name << ","
    11341341                  << baseline->second.first->second->node->Name << ","
    1135                   << baseline->second.second->second->node->Name << " leave "
     1342                  << baseline->second.second->second->node->Name << " leaves "
    11361343                  << checker->second->node->Name << " outside the convex hull."
    11371344                  << endl;
     
    12181425 * -# if the lines contains to only one triangle
    12191426 * -# We search all points in the boundary
    1220  *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors
    12211427 *    -# if the triangle is in forward direction of the baseline (at most 90 degrees angle between vector orthogonal to
    12221428 *       baseline in triangle plane pointing out of the triangle and normal vector of new triangle)
     1429 *    -# if the triangle with the baseline and the current point has the smallest of angles (comparison between normal vectors)
    12231430 *    -# then we have a new triangle, whose baselines we again add (or increase their TriangleCount)
    12241431 * \param *out output stream for debugging
     
    12261433 * \param *mol the cluster as a molecule structure
    12271434 */
    1228 void
    1229 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration,
    1230     molecule *mol)
     1435void Tesselation::TesselateOnBoundary(ofstream *out, molecule *mol)
    12311436{
    12321437  bool flag;
     
    12341439  class BoundaryPointSet *peak = NULL;
    12351440  double SmallestAngle, TempAngle;
    1236   Vector NormalVector, VirtualNormalVector, CenterVector, TempVector,
    1237       PropagationVector;
     1441  Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, helper, PropagationVector, *MolCenter = NULL;
    12381442  LineMap::iterator LineChecker[2];
    1239   do
    1240     {
    1241       flag = false;
    1242       for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline
    1243           != LinesOnBoundary.end(); baseline++)
    1244         if (baseline->second->TrianglesCount == 1)
    1245           {
    1246             *out << Verbose(2) << "Current baseline is between "
    1247                 << *(baseline->second) << "." << endl;
    1248             // 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)
    1249             SmallestAngle = M_PI;
    1250             BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
    1251             // get peak point with respect to this base line's only triangle
    1252             for (int i = 0; i < 3; i++)
    1253               if ((BTS->endpoints[i] != baseline->second->endpoints[0])
    1254                   && (BTS->endpoints[i] != baseline->second->endpoints[1]))
    1255                 peak = BTS->endpoints[i];
    1256             *out << Verbose(3) << " and has peak " << *peak << "." << endl;
    1257             // normal vector of triangle
    1258             BTS->GetNormalVector(NormalVector);
    1259             *out << Verbose(4) << "NormalVector of base triangle is ";
    1260             NormalVector.Output(out);
    1261             *out << endl;
    1262             // offset to center of triangle
    1263             CenterVector.Zero();
    1264             for (int i = 0; i < 3; i++)
    1265               CenterVector.AddVector(&BTS->endpoints[i]->node->x);
    1266             CenterVector.Scale(1. / 3.);
    1267             *out << Verbose(4) << "CenterVector of base triangle is ";
    1268             CenterVector.Output(out);
    1269             *out << endl;
    1270             // vector in propagation direction (out of triangle)
    1271             // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     1443
     1444  MolCenter = mol->DetermineCenterOfAll(out);
     1445  // create a first tesselation with the given BoundaryPoints
     1446  do {
     1447    flag = false;
     1448    for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++)
     1449      if (baseline->second->TrianglesCount == 1) {
     1450        // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles)
     1451        SmallestAngle = M_PI;
     1452
     1453        // get peak point with respect to this base line's only triangle
     1454        BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far
     1455        *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl;
     1456        for (int i = 0; i < 3; i++)
     1457          if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1]))
     1458            peak = BTS->endpoints[i];
     1459        *out << Verbose(3) << " and has peak " << *peak << "." << endl;
     1460
     1461        // prepare some auxiliary vectors
     1462        Vector BaseLineCenter, BaseLine;
     1463        BaseLineCenter.CopyVector(&baseline->second->endpoints[0]->node->x);
     1464        BaseLineCenter.AddVector(&baseline->second->endpoints[1]->node->x);
     1465        BaseLineCenter.Scale(1. / 2.); // points now to center of base line
     1466        BaseLine.CopyVector(&baseline->second->endpoints[0]->node->x);
     1467        BaseLine.SubtractVector(&baseline->second->endpoints[1]->node->x);
     1468
     1469        // offset to center of triangle
     1470        CenterVector.Zero();
     1471        for (int i = 0; i < 3; i++)
     1472          CenterVector.AddVector(&BTS->endpoints[i]->node->x);
     1473        CenterVector.Scale(1. / 3.);
     1474        *out << Verbose(4) << "CenterVector of base triangle is " << CenterVector << endl;
     1475
     1476        // normal vector of triangle
     1477        NormalVector.CopyVector(MolCenter);
     1478        NormalVector.SubtractVector(&CenterVector);
     1479        BTS->GetNormalVector(NormalVector);
     1480        NormalVector.CopyVector(&BTS->NormalVector);
     1481        *out << Verbose(4) << "NormalVector of base triangle is " << NormalVector << endl;
     1482
     1483        // vector in propagation direction (out of triangle)
     1484        // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection)
     1485        PropagationVector.MakeNormalVector(&BaseLine, &NormalVector);
     1486        TempVector.CopyVector(&CenterVector);
     1487        TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
     1488        //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
     1489        if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
     1490          PropagationVector.Scale(-1.);
     1491        *out << Verbose(4) << "PropagationVector of base triangle is " << PropagationVector << endl;
     1492        winner = PointsOnBoundary.end();
     1493
     1494        // loop over all points and calculate angle between normal vector of new and present triangle
     1495        for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) {
     1496          if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints
     1497            *out << Verbose(3) << "Target point is " << *(target->second) << ":" << endl;
     1498
     1499            // first check direction, so that triangles don't intersect
     1500            VirtualNormalVector.CopyVector(&target->second->node->x);
     1501            VirtualNormalVector.SubtractVector(&BaseLineCenter); // points from center of base line to target
     1502            VirtualNormalVector.ProjectOntoPlane(&NormalVector);
     1503            TempAngle = VirtualNormalVector.Angle(&PropagationVector);
     1504            *out << Verbose(4) << "VirtualNormalVector is " << VirtualNormalVector << " and PropagationVector is " << PropagationVector << "." << endl;
     1505            if (TempAngle > (M_PI/2.)) { // no bends bigger than Pi/2 (90 degrees)
     1506              *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl;
     1507              continue;
     1508            } else
     1509              *out << Verbose(4) << "Angle on triangle plane between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl;
     1510
     1511            // check first and second endpoint (if any connecting line goes to target has at least not more than 1 triangle)
     1512            LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first);
     1513            LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first);
     1514            if (((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[0]->second->TrianglesCount == 2))) {
     1515              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
     1516              continue;
     1517            }
     1518            if (((LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (LineChecker[1]->second->TrianglesCount == 2))) {
     1519              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
     1520              continue;
     1521            }
     1522
     1523            // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
     1524            if ((((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)))) {
     1525              *out << Verbose(4) << "Current target is peak!" << endl;
     1526              continue;
     1527            }
     1528
     1529            // check for linear dependence
    12721530            TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
    1273             TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x);
    1274             PropagationVector.MakeNormalVector(&TempVector, &NormalVector);
    1275             TempVector.CopyVector(&CenterVector);
    1276             TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center!
    1277             //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl;
    1278             if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline
    1279               PropagationVector.Scale(-1.);
    1280             *out << Verbose(4) << "PropagationVector of base triangle is ";
    1281             PropagationVector.Output(out);
    1282             *out << endl;
    1283             winner = PointsOnBoundary.end();
    1284             for (PointMap::iterator target = PointsOnBoundary.begin(); target
    1285                 != PointsOnBoundary.end(); target++)
    1286               if ((target->second != baseline->second->endpoints[0])
    1287                   && (target->second != baseline->second->endpoints[1]))
    1288                 { // don't take the same endpoints
    1289                   *out << Verbose(3) << "Target point is " << *(target->second)
    1290                       << ":";
    1291                   bool continueflag = true;
    1292 
    1293                   VirtualNormalVector.CopyVector(
    1294                       &baseline->second->endpoints[0]->node->x);
    1295                   VirtualNormalVector.AddVector(
    1296                       &baseline->second->endpoints[0]->node->x);
    1297                   VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line
    1298                   VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target
    1299                   TempAngle = VirtualNormalVector.Angle(&PropagationVector);
    1300                   continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees)
    1301                   if (!continueflag)
    1302                     {
    1303                       *out << Verbose(4)
    1304                           << "Angle between propagation direction and base line to "
    1305                           << *(target->second) << " is " << TempAngle
    1306                           << ", bad direction!" << endl;
    1307                       continue;
    1308                     }
    1309                   else
    1310                     *out << Verbose(4)
    1311                         << "Angle between propagation direction and base line to "
    1312                         << *(target->second) << " is " << TempAngle
    1313                         << ", good direction!" << endl;
    1314                   LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1315                       target->first);
    1316                   LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1317                       target->first);
    1318                   //            if (LineChecker[0] != baseline->second->endpoints[0]->lines.end())
    1319                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl;
    1320                   //            else
    1321                   //              *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1322                   //            if (LineChecker[1] != baseline->second->endpoints[1]->lines.end())
    1323                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl;
    1324                   //            else
    1325                   //              *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl;
    1326                   // check first endpoint (if any connecting line goes to target or at least not more than 1)
    1327                   continueflag = continueflag && (((LineChecker[0]
    1328                       == baseline->second->endpoints[0]->lines.end())
    1329                       || (LineChecker[0]->second->TrianglesCount == 1)));
    1330                   if (!continueflag)
    1331                     {
    1332                       *out << Verbose(4) << *(baseline->second->endpoints[0])
    1333                           << " has line " << *(LineChecker[0]->second)
    1334                           << " to " << *(target->second)
    1335                           << " as endpoint with "
    1336                           << LineChecker[0]->second->TrianglesCount
    1337                           << " triangles." << endl;
    1338                       continue;
    1339                     }
    1340                   // check second endpoint (if any connecting line goes to target or at least not more than 1)
    1341                   continueflag = continueflag && (((LineChecker[1]
    1342                       == baseline->second->endpoints[1]->lines.end())
    1343                       || (LineChecker[1]->second->TrianglesCount == 1)));
    1344                   if (!continueflag)
    1345                     {
    1346                       *out << Verbose(4) << *(baseline->second->endpoints[1])
    1347                           << " has line " << *(LineChecker[1]->second)
    1348                           << " to " << *(target->second)
    1349                           << " as endpoint with "
    1350                           << LineChecker[1]->second->TrianglesCount
    1351                           << " triangles." << endl;
    1352                       continue;
    1353                     }
    1354                   // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint)
    1355                   continueflag = continueflag && (!(((LineChecker[0]
    1356                       != baseline->second->endpoints[0]->lines.end())
    1357                       && (LineChecker[1]
    1358                           != baseline->second->endpoints[1]->lines.end())
    1359                       && (GetCommonEndpoint(LineChecker[0]->second,
    1360                           LineChecker[1]->second) == peak))));
    1361                   if (!continueflag)
    1362                     {
    1363                       *out << Verbose(4) << "Current target is peak!" << endl;
    1364                       continue;
    1365                     }
    1366                   // in case NOT both were found
    1367                   if (continueflag)
    1368                     { // create virtually this triangle, get its normal vector, calculate angle
    1369                       flag = true;
    1370                       VirtualNormalVector.MakeNormalVector(
    1371                           &baseline->second->endpoints[0]->node->x,
    1372                           &baseline->second->endpoints[1]->node->x,
    1373                           &target->second->node->x);
    1374                       // make it always point inward
    1375                       if (baseline->second->endpoints[0]->node->x.Projection(
    1376                           &VirtualNormalVector) > 0)
    1377                         VirtualNormalVector.Scale(-1.);
    1378                       // calculate angle
    1379                       TempAngle = NormalVector.Angle(&VirtualNormalVector);
    1380                       *out << Verbose(4) << "NormalVector is ";
    1381                       VirtualNormalVector.Output(out);
    1382                       *out << " and the angle is " << TempAngle << "." << endl;
    1383                       if (SmallestAngle > TempAngle)
    1384                         { // set to new possible winner
    1385                           SmallestAngle = TempAngle;
    1386                           winner = target;
    1387                         }
    1388                     }
    1389                 }
    1390             // 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
    1391             if (winner != PointsOnBoundary.end())
    1392               {
    1393                 *out << Verbose(2) << "Winning target point is "
    1394                     << *(winner->second) << " with angle " << SmallestAngle
    1395                     << "." << endl;
    1396                 // create the lins of not yet present
    1397                 BLS[0] = baseline->second;
    1398                 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
    1399                 LineChecker[0] = baseline->second->endpoints[0]->lines.find(
    1400                     winner->first);
    1401                 LineChecker[1] = baseline->second->endpoints[1]->lines.find(
    1402                     winner->first);
    1403                 if (LineChecker[0]
    1404                     == baseline->second->endpoints[0]->lines.end())
    1405                   { // create
    1406                     BPS[0] = baseline->second->endpoints[0];
    1407                     BPS[1] = winner->second;
    1408                     BLS[1] = new class BoundaryLineSet(BPS,
    1409                         LinesOnBoundaryCount);
    1410                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1411                         BLS[1]));
    1412                     LinesOnBoundaryCount++;
    1413                   }
    1414                 else
    1415                   BLS[1] = LineChecker[0]->second;
    1416                 if (LineChecker[1]
    1417                     == baseline->second->endpoints[1]->lines.end())
    1418                   { // create
    1419                     BPS[0] = baseline->second->endpoints[1];
    1420                     BPS[1] = winner->second;
    1421                     BLS[2] = new class BoundaryLineSet(BPS,
    1422                         LinesOnBoundaryCount);
    1423                     LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount,
    1424                         BLS[2]));
    1425                     LinesOnBoundaryCount++;
    1426                   }
    1427                 else
    1428                   BLS[2] = LineChecker[1]->second;
    1429                 BTS = new class BoundaryTriangleSet(BLS,
    1430                     TrianglesOnBoundaryCount);
    1431                 TrianglesOnBoundary.insert(TrianglePair(
    1432                     TrianglesOnBoundaryCount, BTS));
    1433                 TrianglesOnBoundaryCount++;
    1434               }
    1435             else
    1436               {
    1437                 *out << Verbose(1)
    1438                     << "I could not determine a winner for this baseline "
    1439                     << *(baseline->second) << "." << endl;
    1440               }
    1441 
    1442             // 5d. If the set of lines is not yet empty, go to 5. and continue
     1531            TempVector.SubtractVector(&target->second->node->x);
     1532            helper.CopyVector(&baseline->second->endpoints[1]->node->x);
     1533            helper.SubtractVector(&target->second->node->x);
     1534            helper.ProjectOntoPlane(&TempVector);
     1535            if (fabs(helper.NormSquared()) < MYEPSILON) {
     1536              *out << Verbose(4) << "Chosen set of vectors is linear dependent." << endl;
     1537              continue;
     1538            }
     1539
     1540            // in case NOT both were found, create virtually this triangle, get its normal vector, calculate angle
     1541            flag = true;
     1542            VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x);
     1543            TempVector.CopyVector(&baseline->second->endpoints[0]->node->x);
     1544            TempVector.AddVector(&baseline->second->endpoints[1]->node->x);
     1545            TempVector.AddVector(&target->second->node->x);
     1546            TempVector.Scale(1./3.);
     1547            TempVector.SubtractVector(MolCenter);
     1548            // make it always point outward
     1549            if (VirtualNormalVector.Projection(&TempVector) < 0)
     1550              VirtualNormalVector.Scale(-1.);
     1551            // calculate angle
     1552            TempAngle = NormalVector.Angle(&VirtualNormalVector);
     1553            *out << Verbose(4) << "NormalVector is " << VirtualNormalVector << " and the angle is " << TempAngle << "." << endl;
     1554            if ((SmallestAngle - TempAngle) > MYEPSILON) { // set to new possible winner
     1555              SmallestAngle = TempAngle;
     1556              winner = target;
     1557              *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;
     1558            } else if (fabs(SmallestAngle - TempAngle) < MYEPSILON) { // check the angle to propagation, both possible targets are in one plane! (their normals have same angle)
     1559              // hence, check the angles to some normal direction from our base line but in this common plane of both targets...
     1560              helper.CopyVector(&target->second->node->x);
     1561              helper.SubtractVector(&BaseLineCenter);
     1562              helper.ProjectOntoPlane(&BaseLine);
     1563              // ...the one with the smaller angle is the better candidate
     1564              TempVector.CopyVector(&target->second->node->x);
     1565              TempVector.SubtractVector(&BaseLineCenter);
     1566              TempVector.ProjectOntoPlane(&VirtualNormalVector);
     1567              TempAngle = TempVector.Angle(&helper);
     1568              TempVector.CopyVector(&winner->second->node->x);
     1569              TempVector.SubtractVector(&BaseLineCenter);
     1570              TempVector.ProjectOntoPlane(&VirtualNormalVector);
     1571              if (TempAngle < TempVector.Angle(&helper)) {
     1572                TempAngle = NormalVector.Angle(&VirtualNormalVector);
     1573                SmallestAngle = TempAngle;
     1574                winner = target;
     1575                *out << Verbose(4) << "New winner " << *winner->second->node << " due to smaller angle " << TempAngle << " to propagation direction." << endl;
     1576              } else
     1577                *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle to propagation direction." << endl;
     1578            } else
     1579              *out << Verbose(4) << "Keeping old winner " << *winner->second->node << " due to smaller angle between normal vectors." << endl;
    14431580          }
     1581        } // end of loop over all boundary points
     1582
     1583        // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle
     1584        if (winner != PointsOnBoundary.end()) {
     1585          *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl;
     1586          // create the lins of not yet present
     1587          BLS[0] = baseline->second;
     1588          // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles)
     1589          LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first);
     1590          LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first);
     1591          if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create
     1592            BPS[0] = baseline->second->endpoints[0];
     1593            BPS[1] = winner->second;
     1594            BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1595            LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[1]));
     1596            LinesOnBoundaryCount++;
     1597          } else
     1598            BLS[1] = LineChecker[0]->second;
     1599          if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create
     1600            BPS[0] = baseline->second->endpoints[1];
     1601            BPS[1] = winner->second;
     1602            BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1603            LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[2]));
     1604            LinesOnBoundaryCount++;
     1605          } else
     1606            BLS[2] = LineChecker[1]->second;
     1607          BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     1608          TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1609          TrianglesOnBoundaryCount++;
     1610        } else {
     1611          *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl;
     1612        }
     1613
     1614        // 5d. If the set of lines is not yet empty, go to 5. and continue
     1615      } else
     1616        *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl;
     1617  } while (flag);
     1618
     1619  // exit
     1620  delete(MolCenter);
     1621};
     1622
     1623/** Inserts all atoms outside of the tesselated surface into it by adding new triangles.
     1624 * \param *out output stream for debugging
     1625 * \param *mol molecule structure with atoms
     1626 * \return true - all straddling points insert, false - something went wrong
     1627 */
     1628bool Tesselation::InsertStraddlingPoints(ofstream *out, molecule *mol)
     1629{
     1630  Vector Intersection;
     1631  atom *Walker = mol->start;
     1632  Vector *MolCenter = mol->DetermineCenterOfAll(out);
     1633  while (Walker->next != mol->end) {  // we only have to go once through all points, as boundary can become only bigger
     1634    // get the next triangle
     1635    BTS = FindClosestTriangleToPoint(out, &Walker->x);
     1636    if (BTS == NULL) {
     1637      *out << Verbose(1) << "ERROR: No triangle closest to " << Walker << " was found." << endl;
     1638      return false;
     1639    }
     1640    // get the intersection point
     1641    if (BTS->GetIntersectionInsideTriangle(out, MolCenter, &Walker->x, &Intersection)) {
     1642      // we have the intersection, check whether in- or outside of boundary
     1643      if ((MolCenter->DistanceSquared(&Walker->x) - MolCenter->DistanceSquared(&Intersection)) < -MYEPSILON) {
     1644        // inside, next!
     1645        *out << Verbose(4) << Walker << " is inside wrt triangle " << BTS << "." << endl;
     1646      } else {
     1647        // outside!
     1648        *out << Verbose(3) << Walker << " is outside wrt triangle " << BTS << "." << endl;
     1649        class BoundaryLineSet *OldLines[3], *NewLines[3];
     1650        class BoundaryPointSet *OldPoints[3], *NewPoint;
     1651        // store the three old lines and old points
     1652        for (int i=0;i<3;i++) {
     1653          OldLines[i] = BTS->lines[i];
     1654          OldPoints[i] = BTS->endpoints[i];
     1655        }
     1656        // add Walker to boundary points
     1657        AddPoint(Walker);
     1658        if (BPS[0] == NULL)
     1659          NewPoint = BPS[0];
    14441660        else
    1445           *out << Verbose(2) << "Baseline candidate " << *(baseline->second)
    1446               << " has a triangle count of "
    1447               << baseline->second->TrianglesCount << "." << endl;
    1448     }
    1449   while (flag);
    1450 
    1451 }
    1452 ;
     1661          continue;
     1662        // remove triangle
     1663        TrianglesOnBoundary.erase(BTS->Nr);
     1664        // create three new boundary lines
     1665        for (int i=0;i<3;i++) {
     1666          BPS[0] = NewPoint;
     1667          BPS[1] = OldPoints[i];
     1668          NewLines[i] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount);
     1669          LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, NewLines[i])); // no need for check for unique insertion as BPS[0] is definitely a new one
     1670          LinesOnBoundaryCount++;
     1671        }
     1672        // create three new triangle with new point
     1673        for (int i=0;i<3;i++) { // find all baselines
     1674          BLS[0] = OldLines[i];
     1675          int n = 1;
     1676          for (int j=0;j<3;j++) {
     1677            if (NewLines[j]->IsConnectedTo(BLS[0])) {
     1678              if (n>2) {
     1679                *out << Verbose(1) << "ERROR: " << BLS[0] << " connects to all of the new lines?!" << endl;
     1680                return false;
     1681              } else
     1682                BLS[n++] = NewLines[j];
     1683            }
     1684          }
     1685          // create the triangle
     1686          BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     1687          TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
     1688          TrianglesOnBoundaryCount++;
     1689        }
     1690      }
     1691    } else { // something is wrong with FindClosestTriangleToPoint!
     1692      *out << Verbose(1) << "ERROR: The closest triangle did not produce an intersection!" << endl;
     1693      return false;
     1694    }
     1695  }
     1696
     1697  // exit
     1698  delete(MolCenter);
     1699  return true;
     1700};
     1701
     1702/** Goes over all baselines and checks whether adjacent triangles and convex to each other.
     1703 * \param *out output stream for debugging
     1704 * \return true - all baselines were corrected, false - there are still concave pieces
     1705 */
     1706bool Tesselation::CorrectConcaveBaselines(ofstream *out)
     1707{
     1708  class BoundaryTriangleSet *triangle[2];
     1709  class BoundaryLineSet *OldLines[4], *NewLine;
     1710  class BoundaryPointSet *OldPoints[2];
     1711  Vector BaseLineNormal;
     1712  class BoundaryLineSet *Base = NULL;
     1713  int OldTriangles[2], OldBaseLine;
     1714  int i;
     1715  for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) {
     1716    Base = baseline->second;
     1717
     1718    // check convexity
     1719    if (Base->CheckConvexityCriterion(out)) { // triangles are convex
     1720      *out << Verbose(3) << Base << " has two convex triangles." << endl;
     1721    } else { // not convex!
     1722      // get the two triangles
     1723      i=0;
     1724      for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)
     1725        triangle[i++] = runner->second;
     1726      // gather four endpoints and four lines
     1727      for (int j=0;j<4;j++)
     1728        OldLines[j] = NULL;
     1729      for (int j=0;j<2;j++)
     1730        OldPoints[j] = NULL;
     1731      i=0;
     1732      for (int m=0;m<2;m++) { // go over both triangles
     1733        for (int j=0;j<3;j++) { // all of their endpoints and baselines
     1734          if (triangle[m]->lines[j] != Base) // pick not the central baseline
     1735            OldLines[i++] = triangle[m]->lines[j];
     1736          if (!Base->ContainsBoundaryPoint(triangle[m]->endpoints[j])) // and neither of its endpoints
     1737            OldPoints[m] = triangle[m]->endpoints[j];
     1738        }
     1739      }
     1740      if (i<4) {
     1741        *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
     1742        return false;
     1743      }
     1744      for (int j=0;j<4;j++)
     1745        if (OldLines[j] == NULL) {
     1746          *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
     1747          return false;
     1748        }
     1749      for (int j=0;j<2;j++)
     1750        if (OldPoints[j] == NULL) {
     1751          *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl;
     1752          return false;
     1753        }
     1754
     1755      // remove triangles
     1756      for (int j=0;j<2;j++) {
     1757        OldTriangles[j] = triangle[j]->Nr;
     1758        TrianglesOnBoundary.erase(OldTriangles[j]);
     1759        triangle[j] = NULL;
     1760      }
     1761
     1762      // remove baseline
     1763      OldBaseLine = Base->Nr;
     1764      LinesOnBoundary.erase(OldBaseLine);
     1765      Base = NULL;
     1766
     1767      // construct new baseline (with same number as old one)
     1768      BPS[0] = OldPoints[0];
     1769      BPS[1] = OldPoints[1];
     1770      NewLine = new class BoundaryLineSet(BPS, OldBaseLine);
     1771      LinesOnBoundary.insert(LinePair(OldBaseLine, NewLine)); // no need for check for unique insertion as NewLine is definitely a new one
     1772
     1773      // construct new triangles with flipped baseline
     1774      i=-1;
     1775      if (BLS[0]->IsConnectedTo(OldLines[2]))
     1776        i=2;
     1777      if (BLS[0]->IsConnectedTo(OldLines[2]))
     1778        i=3;
     1779      if (i!=-1) {
     1780        BLS[0] = OldLines[0];
     1781        BLS[1] = OldLines[i];
     1782        BLS[2] = NewLine;
     1783        BTS = new class BoundaryTriangleSet(BLS, OldTriangles[0]);
     1784        TrianglesOnBoundary.insert(TrianglePair(OldTriangles[0], BTS));
     1785
     1786        BLS[0] = (i==2 ? OldLines[3] : OldLines[2]);
     1787        BLS[1] = OldLines[1];
     1788        BLS[2] = NewLine;
     1789        BTS = new class BoundaryTriangleSet(BLS, OldTriangles[1]);
     1790        TrianglesOnBoundary.insert(TrianglePair(OldTriangles[1], BTS));
     1791      } else {
     1792        *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl;
     1793        return false;
     1794      }
     1795    }
     1796  }
     1797  return true;
     1798};
     1799
     1800
     1801/** States whether point is in- or outside of a tesselated surface.
     1802 * \param *pointer point to be checked
     1803 * \return true - is inside, false - is outside
     1804 */
     1805bool Tesselation::IsInside(Vector *pointer)
     1806{
     1807
     1808  // hier kommt dann Saskias Routine hin...
     1809
     1810  return true;
     1811};
     1812
     1813/** Finds the closest triangle to a given point.
     1814 * \param *out output stream for debugging
     1815 * \param *x second endpoint of line
     1816 * \return pointer triangle that is closest, NULL if none was found
     1817 */
     1818class BoundaryTriangleSet * Tesselation::FindClosestTriangleToPoint(ofstream *out, Vector *x)
     1819{
     1820  class BoundaryTriangleSet *triangle = NULL;
     1821
     1822  // hier kommt dann Saskias Routine hin...
     1823
     1824  return triangle;
     1825};
    14531826
    14541827/** Adds an atom to the tesselation::PointsOnBoundary list.
     
    14631836  if (InsertUnique.second) // if new point was not present before, increase counter
    14641837    PointsOnBoundaryCount++;
     1838  else {
     1839    delete(BPS[0]);
     1840    BPS[0] = NULL;
     1841  }
    14651842}
    14661843;
     
    18042181 */
    18052182int Tesselation::CheckPresenceOfTriangle(ofstream *out, atom *Candidates[3]) {
    1806 // TODO: use findTriangles here and return result.size();
    18072183  LineMap::iterator FindLine;
    18082184  PointMap::iterator FindPoint;
     
    19042280  Vector CirclePlaneNormal; // normal vector defining the plane this circle lives in
    19052281  Vector SphereCenter;
    1906   Vector NewSphereCenter;        // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
    1907   Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
     2282  Vector NewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, first possibility
     2283  Vector OtherNewSphereCenter;  // center of the sphere defined by the two points of BaseLine and the one of Candidate, second possibility
    19082284  Vector NewNormalVector;   // normal vector of the Candidate's triangle
    19092285  Vector helper, OptCandidateCenter, OtherOptCandidateCenter;
     
    19852361
    19862362                  if ((NewNormalVector.MakeNormalVector(&(BaseLine->endpoints[0]->node->x), &(BaseLine->endpoints[1]->node->x), &(Candidate->x)))
    1987                         && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)
     2363                  && (fabs(NewNormalVector.ScalarProduct(&NewNormalVector)) > HULLEPSILON)
    19882364                  ) {
    19892365                    helper.CopyVector(&NewNormalVector);
     
    20722448  //cout << Verbose(2) << "INFO: Sorting candidate list ..." << endl;
    20732449  if (candidates->size() > 1) {
    2074           candidates->unique();
    2075           candidates->sort(sortCandidates);
     2450    candidates->unique();
     2451    candidates->sort(sortCandidates);
    20762452  }
    20772453
     
    20802456
    20812457struct Intersection {
    2082         Vector x1;
    2083         Vector x2;
    2084         Vector x3;
    2085         Vector x4;
     2458  Vector x1;
     2459  Vector x2;
     2460  Vector x3;
     2461  Vector x4;
    20862462};
    20872463
     
    20932469 */
    20942470double MinIntersectDistance(const gsl_vector * x, void *params) {
    2095         double retval = 0;
    2096         struct Intersection *I = (struct Intersection *)params;
    2097         Vector intersection;
    2098         Vector SideA,SideB,HeightA, HeightB;
    2099         for (int i=0;i<NDIM;i++)
    2100                 intersection.x[i] = gsl_vector_get(x, i);
    2101 
    2102         SideA.CopyVector(&(I->x1));
    2103         SideA.SubtractVector(&I->x2);
    2104         HeightA.CopyVector(&intersection);
    2105         HeightA.SubtractVector(&I->x1);
    2106         HeightA.ProjectOntoPlane(&SideA);
    2107 
    2108         SideB.CopyVector(&I->x3);
    2109         SideB.SubtractVector(&I->x4);
    2110         HeightB.CopyVector(&intersection);
    2111         HeightB.SubtractVector(&I->x3);
    2112         HeightB.ProjectOntoPlane(&SideB);
    2113 
    2114         retval = HeightA.ScalarProduct(&HeightA) + HeightB.ScalarProduct(&HeightB);
    2115         //cout << Verbose(2) << "MinIntersectDistance called, result: " << retval << endl;
    2116 
    2117         return retval;
     2471  double retval = 0;
     2472  struct Intersection *I = (struct Intersection *)params;
     2473  Vector intersection;
     2474  Vector SideA,SideB,HeightA, HeightB;
     2475  for (int i=0;i<NDIM;i++)
     2476    intersection.x[i] = gsl_vector_get(x, i);
     2477
     2478  SideA.CopyVector(&(I->x1));
     2479  SideA.SubtractVector(&I->x2);
     2480  HeightA.CopyVector(&intersection);
     2481  HeightA.SubtractVector(&I->x1);
     2482  HeightA.ProjectOntoPlane(&SideA);
     2483
     2484  SideB.CopyVector(&I->x3);
     2485  SideB.SubtractVector(&I->x4);
     2486  HeightB.CopyVector(&intersection);
     2487  HeightB.SubtractVector(&I->x3);
     2488  HeightB.ProjectOntoPlane(&SideB);
     2489
     2490  retval = HeightA.ScalarProduct(&HeightA) + HeightB.ScalarProduct(&HeightB);
     2491  //cout << Verbose(2) << "MinIntersectDistance called, result: " << retval << endl;
     2492
     2493  return retval;
    21182494};
    21192495
     
    21322508 */
    21332509bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4) {
    2134         bool result;
    2135 
    2136         struct Intersection par;
    2137                 par.x1.CopyVector(&point1);
    2138                 par.x2.CopyVector(&point2);
    2139                 par.x3.CopyVector(&point3);
    2140                 par.x4.CopyVector(&point4);
     2510  bool result;
     2511
     2512  struct Intersection par;
     2513    par.x1.CopyVector(&point1);
     2514    par.x2.CopyVector(&point2);
     2515    par.x3.CopyVector(&point3);
     2516    par.x4.CopyVector(&point4);
    21412517
    21422518    const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
     
    21792555
    21802556        if (status == GSL_SUCCESS) {
    2181                 cout << Verbose(2) << "converged to minimum" <<  endl;
     2557          cout << Verbose(2) << "converged to minimum" <<  endl;
    21822558        }
    21832559    } while (status == GSL_CONTINUE && iter < 100);
    21842560
    21852561    // check whether intersection is in between or not
    2186         Vector intersection, SideA, SideB, HeightA, HeightB;
    2187         double t1, t2;
    2188         for (int i = 0; i < NDIM; i++) {
    2189                 intersection.x[i] = gsl_vector_get(s->x, i);
    2190         }
    2191 
    2192         SideA.CopyVector(&par.x2);
    2193         SideA.SubtractVector(&par.x1);
    2194         HeightA.CopyVector(&intersection);
    2195         HeightA.SubtractVector(&par.x1);
    2196 
    2197         t1 = HeightA.Projection(&SideA)/SideA.ScalarProduct(&SideA);
    2198 
    2199         SideB.CopyVector(&par.x4);
    2200         SideB.SubtractVector(&par.x3);
    2201         HeightB.CopyVector(&intersection);
    2202         HeightB.SubtractVector(&par.x3);
    2203 
    2204         t2 = HeightB.Projection(&SideB)/SideB.ScalarProduct(&SideB);
    2205 
    2206         cout << Verbose(2) << "Intersection " << intersection << " is at "
    2207                 << t1 << " for (" << point1 << "," << point2 << ") and at "
    2208                 << t2 << " for (" << point3 << "," << point4 << "): ";
    2209 
    2210         if (((t1 >= 0) && (t1 <= 1)) && ((t2 >= 0) && (t2 <= 1))) {
    2211                 cout << "true intersection." << endl;
    2212                 result = true;
    2213         } else {
    2214                 cout << "intersection out of region of interest." << endl;
    2215                 result = false;
    2216         }
    2217 
    2218         // free minimizer stuff
     2562  Vector intersection, SideA, SideB, HeightA, HeightB;
     2563  double t1, t2;
     2564  for (int i = 0; i < NDIM; i++) {
     2565    intersection.x[i] = gsl_vector_get(s->x, i);
     2566  }
     2567
     2568  SideA.CopyVector(&par.x2);
     2569  SideA.SubtractVector(&par.x1);
     2570  HeightA.CopyVector(&intersection);
     2571  HeightA.SubtractVector(&par.x1);
     2572
     2573  t1 = HeightA.Projection(&SideA)/SideA.ScalarProduct(&SideA);
     2574
     2575  SideB.CopyVector(&par.x4);
     2576  SideB.SubtractVector(&par.x3);
     2577  HeightB.CopyVector(&intersection);
     2578  HeightB.SubtractVector(&par.x3);
     2579
     2580  t2 = HeightB.Projection(&SideB)/SideB.ScalarProduct(&SideB);
     2581
     2582  cout << Verbose(2) << "Intersection " << intersection << " is at "
     2583    << t1 << " for (" << point1 << "," << point2 << ") and at "
     2584    << t2 << " for (" << point3 << "," << point4 << "): ";
     2585
     2586  if (((t1 >= 0) && (t1 <= 1)) && ((t2 >= 0) && (t2 <= 1))) {
     2587    cout << "true intersection." << endl;
     2588    result = true;
     2589  } else {
     2590    cout << "intersection out of region of interest." << endl;
     2591    result = false;
     2592  }
     2593
     2594  // free minimizer stuff
    22192595    gsl_vector_free(x);
    22202596    gsl_vector_free(ss);
    22212597    gsl_multimin_fminimizer_free(s);
    22222598
    2223         return result;
     2599  return result;
    22242600}
    22252601
     
    22412617  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    22422618
    2243   if (LC->SetIndexToAtom(*a)) {  // get cell for the starting atom
     2619  if (LC->SetIndexToAtom(a)) {  // get cell for the starting atom
    22442620    for(int i=0;i<NDIM;i++) // store indices of this cell
    22452621      N[i] = LC->n[i];
     
    26032979  cout << Verbose(1) << "Third Points are ";
    26042980  for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2605           cout << " " << *(*it)->point;
     2981    cout << " " << *(*it)->point;
    26062982  }
    26072983  cout << endl;
     
    26092985  BoundaryLineSet *BaseRay = &Line;
    26102986  for (CandidateList::iterator it = Opt_Candidates->begin(); it != Opt_Candidates->end(); ++it) {
    2611           cout << Verbose(1) << " Third point candidate is " << *(*it)->point
    2612                 << " with circumsphere's center at " << (*it)->OptCenter << "." << endl;
    2613           cout << Verbose(1) << " Baseline is " << *BaseRay << endl;
    2614 
    2615           // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    2616           atom *AtomCandidates[3];
    2617           AtomCandidates[0] = (*it)->point;
    2618           AtomCandidates[1] = BaseRay->endpoints[0]->node;
    2619           AtomCandidates[2] = BaseRay->endpoints[1]->node;
    2620           int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates);
    2621 
    2622           BTS = NULL;
    2623           // If there is no triangle, add it regularly.
    2624           if (existentTrianglesCount == 0) {
     2987    cout << Verbose(1) << " Third point candidate is " << *(*it)->point
     2988    << " with circumsphere's center at " << (*it)->OptCenter << "." << endl;
     2989    cout << Verbose(1) << " Baseline is " << *BaseRay << endl;
     2990
     2991    // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
     2992    atom *AtomCandidates[3];
     2993    AtomCandidates[0] = (*it)->point;
     2994    AtomCandidates[1] = BaseRay->endpoints[0]->node;
     2995    AtomCandidates[2] = BaseRay->endpoints[1]->node;
     2996    int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates);
     2997
     2998    BTS = NULL;
     2999    // If there is no triangle, add it regularly.
     3000    if (existentTrianglesCount == 0) {
    26253001      AddTrianglePoint((*it)->point, 0);
    26263002      AddTrianglePoint(BaseRay->endpoints[0]->node, 1);
     
    26403016        << " for this triangle ... " << endl;
    26413017      //cout << Verbose(1) << "We have "<< TrianglesOnBoundaryCount << " for line " << *BaseRay << "." << endl;
    2642           } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.
     3018    } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.
    26433019        AddTrianglePoint((*it)->point, 0);
    26443020        AddTrianglePoint(BaseRay->endpoints[0]->node, 1);
     
    26793055    }
    26803056
    2681           if ((result) && (existentTrianglesCount < 2) && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration
     3057    if ((result) && (existentTrianglesCount < 2) && (DoSingleStepOutput && (TrianglesOnBoundaryCount % 1 == 0))) { // if we have a new triangle and want to output each new triangle configuration
    26823058      sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, BTS->endpoints[0]->node->Name, BTS->endpoints[1]->node->Name, BTS->endpoints[2]->node->Name);
    26833059      if (DoTecplotOutput) {
     
    27113087        (*it)->OptCenter.AddVector(&helper);
    27123088        Vector *center = mol->DetermineCenterOfAll(out);
    2713         (*it)->OptCenter.AddVector(center);
     3089        (*it)->OptCenter.SubtractVector(center);
    27143090        delete(center);
    27153091        // and add to file plus translucency object
     
    27263102      if (DoTecplotOutput || DoRaster3DOutput)
    27273103        TriangleFilesWritten++;
    2728           }
     3104    }
    27293105
    27303106    // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point))
    2731           BaseRay = BLS[0];
     3107    BaseRay = BLS[0];
    27323108  }
    27333109
     
    27473123 */
    27483124bool sortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2) {
    2749   // TODO: use get angle and remove duplicate code
    27503125  Vector BaseLineVector, OrthogonalVector, helper;
    2751         if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
    2752           cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
    2753           //return false;
    2754           exit(1);
    2755         }
    2756         // create baseline vector
    2757         BaseLineVector.CopyVector(&(candidate1->BaseLine->endpoints[1]->node->x));
    2758         BaseLineVector.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    2759         BaseLineVector.Normalize();
     3126  if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
     3127    cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
     3128    //return false;
     3129    exit(1);
     3130  }
     3131  // create baseline vector
     3132  BaseLineVector.CopyVector(&(candidate1->BaseLine->endpoints[1]->node->x));
     3133  BaseLineVector.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
     3134  BaseLineVector.Normalize();
    27603135
    27613136  // create normal in-plane vector to cope with acos() non-uniqueness on [0,2pi] (note that is pointing in the "right" direction already, hence ">0" test!)
    2762         helper.CopyVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    2763         helper.SubtractVector(&(candidate1->point->x));
    2764         OrthogonalVector.CopyVector(&helper);
    2765         helper.VectorProduct(&BaseLineVector);
    2766         OrthogonalVector.SubtractVector(&helper);
    2767         OrthogonalVector.Normalize();
     3137  helper.CopyVector(&(candidate1->BaseLine->endpoints[0]->node->x));
     3138  helper.SubtractVector(&(candidate1->point->x));
     3139  OrthogonalVector.CopyVector(&helper);
     3140  helper.VectorProduct(&BaseLineVector);
     3141  OrthogonalVector.SubtractVector(&helper);
     3142  OrthogonalVector.Normalize();
    27683143
    27693144  // calculate both angles and correct with in-plane vector
    2770         helper.CopyVector(&(candidate1->point->x));
    2771         helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    2772         double phi = BaseLineVector.Angle(&helper);
     3145  helper.CopyVector(&(candidate1->point->x));
     3146  helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
     3147  double phi = BaseLineVector.Angle(&helper);
    27733148  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    27743149    phi = 2.*M_PI - phi;
    27753150  }
    27763151  helper.CopyVector(&(candidate2->point->x));
    2777         helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
    2778         double psi = BaseLineVector.Angle(&helper);
     3152  helper.SubtractVector(&(candidate1->BaseLine->endpoints[0]->node->x));
     3153  double psi = BaseLineVector.Angle(&helper);
    27793154  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    2780                 psi = 2.*M_PI - psi;
    2781         }
    2782 
    2783         cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
    2784         cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
    2785 
    2786         // return comparison
    2787         return phi < psi;
    2788 }
    2789 
    2790 /**
    2791  * Checks whether the provided atom is within the tesselation structure.
    2792  *
    2793  * @param atom of which to check the position
    2794  * @param tesselation structure
    2795  *
    2796  * @return true if the atom is inside the tesselation structure, false otherwise
    2797  */
    2798 bool IsInnerAtom(atom *Atom, class Tesselation *Tess, LinkedCell* LC) {
    2799   if (Tess->LinesOnBoundary.begin() == Tess->LinesOnBoundary.end()) {
    2800     cout << Verbose(0) << "Error: There is no tesselation structure to compare the atom with, "
    2801         << "please create one first.";
    2802     exit(1);
    2803   }
    2804 
    2805   class atom *trianglePoints[3];
    2806   trianglePoints[0] = findClosestAtom(Atom, LC);
    2807   // check whether closest atom is "too close" :), then it's inside
    2808   if (trianglePoints[0]->x.DistanceSquared(&Atom->x) < MYEPSILON)
    2809     return true;
    2810   list<atom*> *connectedClosestAtoms = Tess->getClosestConnectedAtoms(trianglePoints[0], Atom);
    2811   trianglePoints[1] = connectedClosestAtoms->front();
    2812   trianglePoints[2] = connectedClosestAtoms->back();
    2813   for (int i=0;i<3;i++) {
    2814     if (trianglePoints[i] == NULL) {
    2815       cout << Verbose(1) << "IsInnerAtom encounters serious error, point " << i << " not found." << endl;
    2816     }
    2817 
    2818     cout << Verbose(1) << "List of possible atoms:" << endl;
    2819     cout << *trianglePoints[i] << endl;
    2820 
    2821 //    for(list<atom*>::iterator runner = connectedClosestAtoms->begin(); runner != connectedClosestAtoms->end(); runner++)
    2822 //      cout << Verbose(2) << *(*runner) << endl;
    2823   }
    2824   delete(connectedClosestAtoms);
    2825 
    2826   list<BoundaryTriangleSet*> *triangles = Tess->FindTriangles(trianglePoints);
    2827 
    2828   if (triangles->empty()) {
    2829     cout << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
    2830     exit(1);
    2831   }
    2832 
    2833   Vector helper;
    2834   helper.CopyVector(&Atom->x);
    2835 
    2836   // Only in case of degeneration, there will be two different scalar products.
    2837   // If at least one scalar product is positive, the point is considered to be outside.
    2838   bool status = (helper.ScalarProduct(&triangles->front()->NormalVector) < 0)
    2839       && (helper.ScalarProduct(&triangles->back()->NormalVector) < 0);
    2840   delete(triangles);
    2841   return status;
    2842 }
    2843 
    2844 /**
    2845  * Finds the atom which is closest to the provided one.
    2846  *
    2847  * @param atom to which to find the closest other atom
    2848  * @param linked cell structure
    2849  *
    2850  * @return atom which is closest to the provided one
    2851  */
    2852 atom* findClosestAtom(const atom* Atom, LinkedCell* LC) {
    2853   LinkedAtoms *List = NULL;
    2854   atom* closestAtom = NULL;
    2855   double distance = 1e16;
    2856   Vector helper;
    2857   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2858 
    2859   LC->SetIndexToVector(&Atom->x); // ignore status as we calculate bounds below sensibly
    2860   for(int i=0;i<NDIM;i++) // store indices of this cell
    2861     N[i] = LC->n[i];
    2862   //cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2863 
    2864   LC->GetNeighbourBounds(Nlower, Nupper);
    2865   //cout << endl;
    2866   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2867     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2868       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2869         List = LC->GetCurrentCell();
    2870         //cout << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    2871         if (List != NULL) {
    2872           for (LinkedAtoms::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2873             helper.CopyVector(&Atom->x);
    2874             helper.SubtractVector(&(*Runner)->x);
    2875             double currentNorm = helper. Norm();
    2876             if (currentNorm < distance) {
    2877               distance = currentNorm;
    2878               closestAtom = (*Runner);
    2879             }
    2880           }
    2881         } else {
    2882           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    2883             << LC->n[2] << " is invalid!" << endl;
    2884         }
    2885       }
    2886 
    2887   return closestAtom;
    2888 }
    2889 
    2890 /**
    2891  * Gets all atoms connected to the provided atom by triangulation lines.
    2892  *
    2893  * @param atom of which get all connected atoms
    2894  * @param atom to be checked whether it is an inner atom
    2895  *
    2896  * @return list of the two atoms linked to the provided one and closest to the atom to be checked,
    2897  */
    2898 list<atom*> * Tesselation::getClosestConnectedAtoms(atom* Atom, atom* AtomToCheck) {
    2899   list<atom*> connectedAtoms;
    2900   map<double, atom*> anglesOfAtoms;
    2901   map<double, atom*>::iterator runner;
    2902   LineMap::iterator findLines = LinesOnBoundary.begin();
    2903   list<atom*>::iterator listRunner;
    2904   Vector center, planeNorm, currentPoint, OrthogonalVector, helper;
    2905   atom* current;
    2906   bool takeAtom = false;
    2907 
    2908   planeNorm.CopyVector(&Atom->x);
    2909   planeNorm.SubtractVector(&AtomToCheck->x);
    2910   planeNorm.Normalize();
    2911 
    2912   while (findLines != LinesOnBoundary.end()) {
    2913     takeAtom = false;
    2914 
    2915     if (findLines->second->endpoints[0]->Nr == Atom->nr) {
    2916       takeAtom = true;
    2917       current = findLines->second->endpoints[1]->node;
    2918     } else if (findLines->second->endpoints[1]->Nr == Atom->nr) {
    2919       takeAtom = true;
    2920       current = findLines->second->endpoints[0]->node;
    2921     }
    2922 
    2923     if (takeAtom) {
    2924       connectedAtoms.push_back(current);
    2925       currentPoint.CopyVector(&current->x);
    2926       currentPoint.ProjectOntoPlane(&planeNorm);
    2927       center.AddVector(&currentPoint);
    2928     }
    2929 
    2930     findLines++;
    2931   }
    2932 
    2933   cout << "Summed vectors " << center << "; number of atoms " << connectedAtoms.size()
    2934     << "; scale factor " << 1.0/connectedAtoms.size();
    2935 
    2936   center.Scale(1.0/connectedAtoms.size());
    2937   listRunner = connectedAtoms.begin();
    2938 
    2939   cout << " calculated center " << center <<  endl;
    2940 
    2941   // construct one orthogonal vector
    2942   helper.CopyVector(&AtomToCheck->x);
    2943   helper.ProjectOntoPlane(&planeNorm);
    2944   OrthogonalVector.MakeNormalVector(&center, &helper, &(*listRunner)->x);
    2945   while (listRunner != connectedAtoms.end()) {
    2946     double angle = getAngle((*listRunner)->x, AtomToCheck->x, center, OrthogonalVector);
    2947     cout << "Calculated angle " << angle << " for atom " << **listRunner << endl;
    2948     anglesOfAtoms.insert(pair<double, atom*>(angle, (*listRunner)));
    2949     listRunner++;
    2950   }
    2951 
    2952   list<atom*> *result = new list<atom*>;
    2953   runner = anglesOfAtoms.begin();
    2954   cout << "First value is " << *runner->second << endl;
    2955   result->push_back(runner->second);
    2956   runner = anglesOfAtoms.end();
    2957   runner--;
    2958   cout << "Second value is " << *runner->second << endl;
    2959   result->push_back(runner->second);
    2960 
    2961   cout << "List of closest atoms has " << result->size() << " elements, which are "
    2962     << *(result->front()) << " and " << *(result->back()) << endl;
    2963 
    2964   return result;
    2965 }
    2966 
    2967 /**
    2968  * Finds triangles belonging to the three provided atoms.
    2969  *
    2970  * @param atom list, is expected to contain three atoms
    2971  *
    2972  * @return triangles which belong to the provided atoms, will be empty if there are none,
    2973  *         will usually be one, in case of degeneration, there will be two
    2974  */
    2975 list<BoundaryTriangleSet*> *Tesselation::FindTriangles(atom* Points[3]) {
    2976   list<BoundaryTriangleSet*> *result = new list<BoundaryTriangleSet*>;
    2977   LineMap::iterator FindLine;
    2978   PointMap::iterator FindPoint;
    2979   TriangleMap::iterator FindTriangle;
    2980   class BoundaryPointSet *TrianglePoints[3];
    2981 
    2982   for (int i = 0; i < 3; i++) {
    2983     FindPoint = PointsOnBoundary.find(Points[i]->nr);
    2984     if (FindPoint != PointsOnBoundary.end()) {
    2985       TrianglePoints[i] = FindPoint->second;
    2986     } else {
    2987       TrianglePoints[i] = NULL;
    2988     }
    2989   }
    2990 
    2991   // checks lines between the points in the Points for their adjacent triangles
    2992   for (int i = 0; i < 3; i++) {
    2993     if (TrianglePoints[i] != NULL) {
    2994       for (int j = i; j < 3; j++) {
    2995         if (TrianglePoints[j] != NULL) {
    2996           FindLine = TrianglePoints[i]->lines.find(TrianglePoints[j]->node->nr);
    2997           if (FindLine != TrianglePoints[i]->lines.end()) {
    2998             for (; FindLine->first == TrianglePoints[j]->node->nr; FindLine++) {
    2999               FindTriangle = FindLine->second->triangles.begin();
    3000               for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {
    3001                 if ((
    3002                   (FindTriangle->second->endpoints[0] == TrianglePoints[0])
    3003                     || (FindTriangle->second->endpoints[0] == TrianglePoints[1])
    3004                     || (FindTriangle->second->endpoints[0] == TrianglePoints[2])
    3005                   ) && (
    3006                     (FindTriangle->second->endpoints[1] == TrianglePoints[0])
    3007                     || (FindTriangle->second->endpoints[1] == TrianglePoints[1])
    3008                     || (FindTriangle->second->endpoints[1] == TrianglePoints[2])
    3009                   ) && (
    3010                     (FindTriangle->second->endpoints[2] == TrianglePoints[0])
    3011                     || (FindTriangle->second->endpoints[2] == TrianglePoints[1])
    3012                     || (FindTriangle->second->endpoints[2] == TrianglePoints[2])
    3013                   )
    3014                 ) {
    3015                   result->push_back(FindTriangle->second);
    3016                 }
    3017               }
    3018             }
    3019             // Is it sufficient to consider one of the triangle lines for this.
    3020             return result;
    3021 
    3022           }
    3023         }
    3024       }
    3025     }
    3026   }
    3027 
    3028   return result;
    3029 }
    3030 
    3031 /**
    3032  * Gets the angle between a point and a reference relative to the provided center.
    3033  *
    3034  * @param point to calculate the angle for
    3035  * @param reference to which to calculate the angle
    3036  * @param center for which to calculate the angle between the vectors
    3037  * @param OrthogonalVector helps discern between [0,pi] and [pi,2pi] in acos()
    3038  *
    3039  * @return angle between point and reference
    3040  */
    3041 double getAngle(Vector point, Vector reference, Vector center, Vector OrthogonalVector) {
    3042   Vector ReferenceVector, helper;
    3043   cout << Verbose(2) << reference << " is our reference " << endl;
    3044   cout << Verbose(2) << center << " is our center " << endl;
    3045   // create baseline vector
    3046   ReferenceVector.CopyVector(&reference);
    3047   ReferenceVector.SubtractVector(&center);
    3048   if (ReferenceVector.IsNull())
    3049     return M_PI;
    3050 
    3051   // calculate both angles and correct with in-plane vector
    3052   helper.CopyVector(&point);
    3053   helper.SubtractVector(&center);
    3054   if (helper.IsNull())
    3055     return M_PI;
    3056   double phi = ReferenceVector.Angle(&helper);
    3057   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    3058     phi = 2.*M_PI - phi;
    3059   }
    3060 
    3061   cout << Verbose(2) << point << " has angle " << phi << endl;
    3062 
    3063   return phi;
    3064 }
    3065 
    3066 /**
    3067  * Checks whether the provided point is within the tesselation structure.
    3068  *
    3069  * This is a wrapper function for IsInnerAtom, so it can be used with a simple
    3070  * vector, too.
    3071  *
    3072  * @param point of which to check the position
    3073  * @param tesselation structure
    3074  *
    3075  * @return true if the point is inside the tesselation structure, false otherwise
    3076  */
    3077 bool IsInnerPoint(Vector Point, class Tesselation *Tess, LinkedCell* LC) {
    3078   atom *temp_atom = new atom;
    3079   bool status = false;
    3080   temp_atom->x.CopyVector(&Point);
    3081 
    3082   status = IsInnerAtom(temp_atom, Tess, LC);
    3083   delete(temp_atom);
    3084 
    3085   return status;
     3155    psi = 2.*M_PI - psi;
     3156  }
     3157
     3158  cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
     3159  cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
     3160
     3161  // return comparison
     3162  return phi < psi;
    30863163}
    30873164
     
    30903167 * \param *mol molecule structure with Atom's and Bond's
    30913168 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return
     3169 * \param *LCList atoms in LinkedCell list
    30923170 * \param *filename filename prefix for output of vertex data
    30933171 * \para RADIUS radius of the virtual sphere
     
    31373215    }
    31383216  }
    3139   if (1) { //failflag) {
     3217  if (filename != 0) {
    31403218    *out << Verbose(1) << "Writing final tecplot file\n";
    31413219    if (DoTecplotOutput) {
     
    31703248    cout << Verbose(2) << "None." << endl;
    31713249
    3172   // Tests the IsInnerAtom() function.
    3173   Vector x (0, 0, 0);
    3174   cout << Verbose(0) << "Point to check: " << x << endl;
    3175   cout << Verbose(0) << "Check: IsInnerPoint() returns " << IsInnerPoint(x, Tess, LCList)
    3176     << "for vector " << x << "." << endl;
    3177   atom* a = Tess->PointsOnBoundary.begin()->second->node;
    3178   cout << Verbose(0) << "Point to check: " << *a << " (on boundary)." << endl;
    3179   cout << Verbose(0) << "Check: IsInnerAtom() returns " << IsInnerAtom(a, Tess, LCList)
    3180     << "for atom " << a << " (on boundary)." << endl;
    3181   LinkedAtoms *List = NULL;
    3182   for (int i=0;i<NDIM;i++) { // each axis
    3183     LCList->n[i] = LCList->N[i]-1; // current axis is topmost cell
    3184     for (LCList->n[(i+1)%NDIM]=0;LCList->n[(i+1)%NDIM]<LCList->N[(i+1)%NDIM];LCList->n[(i+1)%NDIM]++)
    3185       for (LCList->n[(i+2)%NDIM]=0;LCList->n[(i+2)%NDIM]<LCList->N[(i+2)%NDIM];LCList->n[(i+2)%NDIM]++) {
    3186         List = LCList->GetCurrentCell();
    3187         //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    3188         if (List != NULL) {
    3189           for (LinkedAtoms::iterator Runner = List->begin();Runner != List->end();Runner++) {
    3190             if (Tess->PointsOnBoundary.find((*Runner)->nr) == Tess->PointsOnBoundary.end()) {
    3191               a = *Runner;
    3192               i=3;
    3193               for (int j=0;j<NDIM;j++)
    3194                 LCList->n[j] = LCList->N[j];
    3195               break;
    3196             }
    3197           }
    3198         }
    3199       }
    3200   }
    3201   cout << Verbose(0) << "Check: IsInnerAtom() returns " << IsInnerAtom(a, Tess, LCList)
    3202     << "for atom " << a << " (inside)." << endl;
    3203 
    3204 
    32053250  if (freeTess)
    32063251    delete(Tess);
Note: See TracChangeset for help on using the changeset viewer.