Changeset 62bb91 for src/tesselation.cpp


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

Fixes for concave hull creation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/tesselation.cpp

    r03e57a r62bb91  
    143143bool BoundaryLineSet::CheckConvexityCriterion(ofstream *out)
    144144{
    145   Vector BaseLineNormal;
    146   double angle = 0;
     145  Vector BaseLineCenter, BaseLineNormal, BaseLine, helper[2];
    147146  // get the two triangles
    148147  if (TrianglesCount != 2) {
     
    151150  }
    152151  // have a normal vector on the base line pointing outwards
     152  *out << Verbose(3) << "INFO: " << *this << " has vectors at " << *(endpoints[0]->node->node) << " and at " << *(endpoints[1]->node->node) << "." << endl;
     153  BaseLineCenter.CopyVector(endpoints[0]->node->node);
     154  BaseLineCenter.AddVector(endpoints[1]->node->node);
     155  BaseLineCenter.Scale(1./2.);
     156  BaseLine.CopyVector(endpoints[0]->node->node);
     157  BaseLine.SubtractVector(endpoints[1]->node->node);
     158  *out << Verbose(3) << "INFO: Baseline is " << BaseLine << " and its center is at " << BaseLineCenter << "." << endl;
     159
    153160  BaseLineNormal.Zero();
    154   for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
    155     BaseLineNormal.AddVector(&runner->second->NormalVector);
    156   BaseLineNormal.Normalize();
    157   // and calculate the sum of the angles with this normal vector and each of the triangle ones'
    158   for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++)
    159     angle += BaseLineNormal.Angle(&runner->second->NormalVector);
    160 
     161  int i=0;
     162  class BoundaryPointSet *node = NULL;
     163  for(TriangleMap::iterator runner = triangles.begin(); runner != triangles.end(); runner++) {
     164    *out << Verbose(3) << "INFO: NormalVector of " << *(runner->second) << " is " << runner->second->NormalVector << "." << endl;
     165    BaseLineNormal.SubtractVector(&runner->second->NormalVector);   // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi]
     166    node = runner->second->GetThirdEndpoint(this);
     167    if (node != NULL) {
     168      *out << Verbose(3) << "INFO: Third node for triangle " << *(runner->second) << " is " << *node << " at " << *(node->node->node) << "." << endl;
     169      helper[i].CopyVector(node->node->node);
     170      helper[i].SubtractVector(&BaseLineCenter);
     171      helper[i].MakeNormalVector(&BaseLine);  // we want to compare the triangle's heights' angles!
     172      *out << Verbose(4) << "INFO: Height vector with respect to baseline is " << helper[i] << "." << endl;
     173      i++;
     174    } else {
     175      *out << Verbose(2) << "WARNING: I cannot find third node in triangle, something's wrong." << endl;
     176      return true;
     177    }
     178  }
     179  *out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl;
     180  double angle = helper[0].Angle(&helper[1]);
     181  if (BaseLineNormal.ScalarProduct(&helper[1]) > 0) {
     182    angle = 2.*M_PI - angle;
     183  }
     184  *out << Verbose(3) << "The angle is " << angle << "." << endl;
    161185  if ((angle - M_PI) > -MYEPSILON)
    162186    return true;
     
    176200  return false;
    177201};
     202
     203/** Returns other endpoint of the line.
     204 * \param *point other endpoint
     205 * \return NULL - if endpoint not contained in BoundaryLineSet, or pointer to BoundaryPointSet otherwise
     206 */
     207inline class BoundaryPointSet *BoundaryLineSet::GetOtherEndpoint(class BoundaryPointSet *point)
     208{
     209  if (endpoints[0] == point)
     210    return endpoints[1];
     211  else if (endpoints[1] == point)
     212    return endpoints[0];
     213  else
     214    return NULL;
     215};
     216
    178217
    179218ostream &
     
    360399            || (endpoints[2] == Points[1])
    361400            || (endpoints[2] == Points[2])
     401
    362402          ));
    363403};
     404
     405/** Returns the endpoint which is not contained in the given \a *line.
     406 * \param *line baseline defining two endpoints
     407 * \return pointer third endpoint or NULL if line does not belong to triangle.
     408 */
     409class BoundaryPointSet *BoundaryTriangleSet::GetThirdEndpoint(class BoundaryLineSet *line)
     410{
     411  // sanity check
     412  if (!ContainsBoundaryLine(line))
     413    return NULL;
     414  for(int i=0;i<3;i++)
     415    if (!line->ContainsBoundaryPoint(endpoints[i]))
     416      return endpoints[i];
     417  // actually, that' impossible :)
     418  return NULL;
     419};
     420
     421/** Calculates the center point of the triangle.
     422 * Is third of the sum of all endpoints.
     423 * \param *center central point on return.
     424 */
     425void BoundaryTriangleSet::GetCenter(Vector *center)
     426{
     427  center->Zero();
     428  for(int i=0;i<3;i++)
     429    center->AddVector(endpoints[i]->node->node);
     430  center->Scale(1./3.);
     431}
    364432
    365433ostream &
     
    809877            BLS[2] = LineChecker[1]->second;
    810878          BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     879          BTS->GetCenter(&helper);
     880          helper.SubtractVector(Center);
     881          helper.Scale(-1);
     882          BTS->GetNormalVector(helper);
    811883          TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    812884          TrianglesOnBoundaryCount++;
     
    824896};
    825897
    826 /** Inserts all atoms outside of the tesselated surface into it by adding new triangles.
     898/** Inserts all points outside of the tesselated surface into it by adding new triangles.
    827899 * \param *out output stream for debugging
    828900 * \param *cloud cluster of points
     901 * \param *LC LinkedCell structure to find nearest point quickly
    829902 * \return true - all straddling points insert, false - something went wrong
    830903 */
    831 bool Tesselation::InsertStraddlingPoints(ofstream *out, PointCloud *cloud)
     904bool Tesselation::InsertStraddlingPoints(ofstream *out, PointCloud *cloud, LinkedCell *LC)
    832905{
    833906  Vector Intersection;
    834907  TesselPoint *Walker = NULL;
    835908  Vector *Center = cloud->GetCenter(out);
     909  list<BoundaryTriangleSet*> *triangles = NULL;
     910
     911  *out << Verbose(1) << "Begin of InsertStraddlingPoints" << endl;
    836912
    837913  cloud->GoToFirst();
    838914  while (!cloud->IsLast()) {  // we only have to go once through all points, as boundary can become only bigger
    839915    Walker = cloud->GetPoint();
     916    *out << Verbose(2) << "Current point is " << *Walker << "." << endl;
    840917    // get the next triangle
    841     BTS = FindClosestTriangleToPoint(out, Walker->node);
    842     if (BTS == NULL) {
    843       *out << Verbose(1) << "ERROR: No triangle closest to " << Walker << " was found." << endl;
    844       return false;
    845     }
     918    triangles = FindClosestTrianglesToPoint(out, Walker->node, LC);
     919    if (triangles == NULL) {
     920      *out << Verbose(1) << "No triangles found, probably a tesselation point itself." << endl;
     921      cloud->GoToNext();
     922      continue;
     923    } else {
     924      BTS = triangles->front();
     925    }
     926    *out << Verbose(2) << "Closest triangle is " << BTS << "." << endl;
    846927    // get the intersection point
    847928    if (BTS->GetIntersectionInsideTriangle(out, Center, Walker->node, &Intersection)) {
     929      *out << Verbose(2) << "We have an intersection at " << Intersection << "." << endl;
    848930      // we have the intersection, check whether in- or outside of boundary
    849931      if ((Center->DistanceSquared(Walker->node) - Center->DistanceSquared(&Intersection)) < -MYEPSILON) {
     
    904986  // exit
    905987  delete(Center);
     988  *out << Verbose(1) << "End of InsertStraddlingPoints" << endl;
    906989  return true;
    907990};
    908991
    909 /** Adds an atom to the tesselation::PointsOnBoundary list.
    910  * \param *Walker atom to add
     992/** Adds an point to the tesselation::PointsOnBoundary list.
     993 * \param *Walker point to add
    911994 */
    912995void
     
    10201103
    10211104
    1022 /** Checks whether the triangle consisting of the three atoms is already present.
     1105/** Checks whether the triangle consisting of the three points is already present.
    10231106 * Searches for the points in Tesselation::PointsOnBoundary and checks their
    10241107 * lines. If any of the three edges already has two triangles attached, false is
     
    10751158
    10761159/** Finds the starting triangle for find_non_convex_border().
    1077  * Looks at the outermost atom per axis, then Find_second_point_for_Tesselation()
     1160 * Looks at the outermost point per axis, then Find_second_point_for_Tesselation()
    10781161 * for the second and Find_next_suitable_point_via_Angle_of_Sphere() for the third
    10791162 * point are called.
     
    10891172  TesselPoint* FirstPoint = NULL;
    10901173  TesselPoint* SecondPoint = NULL;
    1091   TesselPoint* MaxAtom[NDIM];
     1174  TesselPoint* MaxPoint[NDIM];
    10921175  double max_coordinate[NDIM];
    10931176  Vector Oben;
     
    10991182
    11001183  for (i = 0; i < 3; i++) {
    1101     MaxAtom[i] = NULL;
     1184    MaxPoint[i] = NULL;
    11021185    max_coordinate[i] = -1;
    11031186  }
    11041187
    1105   // 1. searching topmost atom with respect to each axis
     1188  // 1. searching topmost point with respect to each axis
    11061189  for (int i=0;i<NDIM;i++) { // each axis
    11071190    LC->n[i] = LC->N[i]-1; // current axis is topmost cell
     
    11151198              cout << Verbose(2) << "New maximal for axis " << i << " node is " << *(*Runner) << " at " << *(*Runner)->node << "." << endl;
    11161199              max_coordinate[i] = (*Runner)->node->x[i];
    1117               MaxAtom[i] = (*Runner);
     1200              MaxPoint[i] = (*Runner);
    11181201            }
    11191202          }
     
    11261209  cout << Verbose(2) << "Found maximum coordinates: ";
    11271210  for (int i=0;i<NDIM;i++)
    1128     cout << i << ": " << *MaxAtom[i] << "\t";
     1211    cout << i << ": " << *MaxPoint[i] << "\t";
    11291212  cout << endl;
    11301213
     
    11331216  for (int k=0;k<NDIM;k++) {
    11341217    Oben.x[k] = 1.;
    1135     FirstPoint = MaxAtom[k];
     1218    FirstPoint = MaxPoint[k];
    11361219    cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl;
    11371220
     
    12381321 * @param RADIUS radius of the rolling ball
    12391322 * @param N number of found triangles
    1240  * @param *LC LinkedCell structure with neighbouring atoms
     1323 * @param *LC LinkedCell structure with neighbouring points
    12411324 */
    12421325bool Tesselation::Find_next_suitable_triangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC)
     
    13271410
    13281411    // check whether all edges of the new triangle still have space for one more triangle (i.e. TriangleCount <2)
    1329     TesselPoint *AtomCandidates[3];
    1330     AtomCandidates[0] = (*it)->point;
    1331     AtomCandidates[1] = BaseRay->endpoints[0]->node;
    1332     AtomCandidates[2] = BaseRay->endpoints[1]->node;
    1333     int existentTrianglesCount = CheckPresenceOfTriangle(out, AtomCandidates);
     1412    TesselPoint *PointCandidates[3];
     1413    PointCandidates[0] = (*it)->point;
     1414    PointCandidates[1] = BaseRay->endpoints[0]->node;
     1415    PointCandidates[2] = BaseRay->endpoints[1]->node;
     1416    int existentTrianglesCount = CheckPresenceOfTriangle(out, PointCandidates);
    13341417
    13351418    BTS = NULL;
     
    14141497bool Tesselation::CorrectConcaveBaselines(ofstream *out)
    14151498{
    1416   class BoundaryTriangleSet *triangle[2];
    14171499  class BoundaryLineSet *OldLines[4], *NewLine;
    14181500  class BoundaryPointSet *OldPoints[2];
     
    14201502  class BoundaryLineSet *Base = NULL;
    14211503  int OldTriangles[2], OldBaseLine;
    1422   int i;
     1504  int i,m;
     1505
     1506  *out << Verbose(1) << "Begin of CorrectConcaveBaselines" << endl;
     1507
    14231508  for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) {
    14241509    Base = baseline->second;
    1425 
     1510    *out << Verbose(2) << "Current baseline is " << *Base << " ... " << endl;
    14261511    // check convexity
    14271512    if (Base->CheckConvexityCriterion(out)) { // triangles are convex
    1428       *out << Verbose(3) << Base << " has two convex triangles." << endl;
     1513      *out << Verbose(2) << "... has two convex triangles." << endl;
    14291514    } else { // not convex!
     1515      *out << Verbose(2) << "... has two concave triangles!" << endl;
    14301516      // get the two triangles
    1431       i=0;
    1432       for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)
    1433         triangle[i++] = runner->second;
    14341517      // gather four endpoints and four lines
    14351518      for (int j=0;j<4;j++)
     
    14381521        OldPoints[j] = NULL;
    14391522      i=0;
    1440       for (int m=0;m<2;m++) { // go over both triangles
    1441         for (int j=0;j<3;j++) { // all of their endpoints and baselines
    1442           if (triangle[m]->lines[j] != Base) // pick not the central baseline
    1443             OldLines[i++] = triangle[m]->lines[j];
    1444           if (!Base->ContainsBoundaryPoint(triangle[m]->endpoints[j])) // and neither of its endpoints
    1445             OldPoints[m] = triangle[m]->endpoints[j];
    1446         }
    1447       }
     1523      m=0;
     1524      *out << Verbose(3) << "The four old lines are: ";
     1525      for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)
     1526        for (int j=0;j<3;j++) // all of their endpoints and baselines
     1527          if (runner->second->lines[j] != Base) { // pick not the central baseline
     1528            OldLines[i++] = runner->second->lines[j];
     1529            *out << *runner->second->lines[j] << "\t";
     1530          }
     1531      *out << endl;
     1532      *out << Verbose(3) << "The two old points are: ";
     1533      for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++)
     1534        for (int j=0;j<3;j++) // all of their endpoints and baselines
     1535          if (!Base->ContainsBoundaryPoint(runner->second->endpoints[j])) { // and neither of its endpoints
     1536            OldPoints[m++] = runner->second->endpoints[j];
     1537            *out << *runner->second->endpoints[j] << "\t";
     1538          }
     1539      *out << endl;
    14481540      if (i<4) {
    14491541        *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
     
    14611553        }
    14621554
    1463       // remove triangles
    1464       for (int j=0;j<2;j++) {
    1465         OldTriangles[j] = triangle[j]->Nr;
    1466         TrianglesOnBoundary.erase(OldTriangles[j]);
    1467         triangle[j] = NULL;
    1468       }
    1469 
    1470       // remove baseline
     1555      // remove triangles and baseline removes itself
     1556      m=0;
    14711557      OldBaseLine = Base->Nr;
    14721558      LinesOnBoundary.erase(OldBaseLine);
    1473       Base = NULL;
     1559      for(TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) {
     1560        TrianglesOnBoundary.erase(OldTriangles[m++] = runner->second->Nr);
     1561        delete(runner->second);
     1562      }
    14741563
    14751564      // construct new baseline (with same number as old one)
     
    14811570      // construct new triangles with flipped baseline
    14821571      i=-1;
    1483       if (BLS[0]->IsConnectedTo(OldLines[2]))
     1572      if (OldLines[0]->IsConnectedTo(OldLines[2]))
    14841573        i=2;
    1485       if (BLS[0]->IsConnectedTo(OldLines[2]))
     1574      if (OldLines[0]->IsConnectedTo(OldLines[3]))
    14861575        i=3;
    14871576      if (i!=-1) {
     
    15031592    }
    15041593  }
     1594  *out << Verbose(1) << "End of CorrectConcaveBaselines" << endl;
    15051595  return true;
    15061596};
    1507 
    1508 
    1509 /** States whether point is in- or outside of a tesselated surface.
    1510  * \param *pointer point to be checked
    1511  * \return true - is inside, false - is outside
    1512  */
    1513 bool Tesselation::IsInside(Vector *pointer)
    1514 {
    1515 
    1516   // hier kommt dann Saskias Routine hin...
    1517 
    1518   return true;
    1519 };
    1520 
    1521 
    1522 /** Finds the closest triangle to a given point.
    1523  * \param *out output stream for debugging
    1524  * \param *x second endpoint of line
    1525  * \return pointer triangle that is closest, NULL if none was found
    1526  */
    1527 class BoundaryTriangleSet * Tesselation::FindClosestTriangleToPoint(ofstream *out, Vector *x)
    1528 {
    1529   class BoundaryTriangleSet *triangle = NULL;
    1530 
    1531   // hier kommt dann Saskias Routine hin...
    1532 
    1533   return triangle;
    1534 };
    1535 
    15361597
    15371598/** Finds the second point of starting triangle.
     
    15421603 * \param Storage[3] array storing angles and other candidate information
    15431604 * \param RADIUS radius of virtual sphere
    1544  * \param *LC LinkedCell structure with neighbouring atoms
     1605 * \param *LC LinkedCell structure with neighbouring points
    15451606 */
    15461607void Tesselation::Find_second_point_for_Tesselation(TesselPoint* a, TesselPoint* Candidate, Vector Oben, TesselPoint*& Opt_Candidate, double Storage[3], double RADIUS, LinkedCell *LC)
     
    15521613  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    15531614
    1554   if (LC->SetIndexToNode(a)) {  // get cell for the starting atom
     1615  if (LC->SetIndexToNode(a)) {  // get cell for the starting point
    15551616    for(int i=0;i<NDIM;i++) // store indices of this cell
    15561617      N[i] = LC->n[i];
    15571618  } else {
    1558     cerr << "ERROR: Atom " << *a << " is not found in cell " << LC->index << "." << endl;
     1619    cerr << "ERROR: Point " << *a << " is not found in cell " << LC->index << "." << endl;
    15591620    return;
    15601621  }
    1561   // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     1622  // then go through the current and all neighbouring cells and check the contained points for possible candidates
    15621623  cout << Verbose(3) << "LC Intervals from [";
    15631624  for (int i=0;i<NDIM;i++) {
     
    16571718 * @param OldSphereCenter center of sphere for base triangle, relative to center of BaseLine, giving null angle for the parameter circle
    16581719 * @param BaseLine BoundaryLineSet with the current base line
    1659  * @param ThirdNode third atom to avoid in search
     1720 * @param ThirdNode third point to avoid in search
    16601721 * @param candidates list of equally good candidates to return
    16611722 * @param ShortestAngle the current path length on this circle band for the current Opt_Candidate
    16621723 * @param RADIUS radius of sphere
    1663  * @param *LC LinkedCell structure with neighbouring atoms
     1724 * @param *LC LinkedCell structure with neighbouring points
    16641725 */
    16651726void Tesselation::Find_third_point_for_Tesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, class TesselPoint  *ThirdNode, CandidateList* &candidates, double *ShortestAngle, const double RADIUS, LinkedCell *LC)
     
    17141775      }
    17151776
    1716       // get cell for the starting atom
     1777      // get cell for the starting point
    17171778      if (LC->SetIndexToVector(&CircleCenter)) {
    17181779        for(int i=0;i<NDIM;i++) // store indices of this cell
     
    17231784        return;
    17241785      }
    1725       // then go through the current and all neighbouring cells and check the contained atoms for possible candidates
     1786      // then go through the current and all neighbouring cells and check the contained points for possible candidates
    17261787      //cout << Verbose(2) << "LC Intervals:";
    17271788      for (int i=0;i<NDIM;i++) {
     
    18741935};
    18751936
     1937/** Finds the triangle that is closest to a given Vector \a *x.
     1938 * \param *out output stream for debugging
     1939 * \param *x Vector to look from
     1940 * \return list of BoundaryTriangleSet of nearest triangles or NULL in degenerate case.
     1941 */
     1942list<BoundaryTriangleSet*> * Tesselation::FindClosestTrianglesToPoint(ofstream *out, Vector *x, LinkedCell* LC)
     1943{
     1944  class TesselPoint *trianglePoints[3];
     1945
     1946  if (LinesOnBoundary.empty()) {
     1947    *out << Verbose(0) << "Error: There is no tesselation structure to compare the point with, " << "please create one first.";
     1948    return NULL;
     1949  }
     1950
     1951  trianglePoints[0] = findClosestPoint(x, LC);
     1952  // check whether closest point is "too close" :), then it's inside
     1953  if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) {
     1954    *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl;
     1955    return NULL;
     1956  }
     1957  list<TesselPoint*> *connectedClosestPoints = getCircleOfConnectedPoints(out, trianglePoints[0], x);
     1958  trianglePoints[1] = connectedClosestPoints->front();
     1959  trianglePoints[2] = connectedClosestPoints->back();
     1960  for (int i=0;i<3;i++) {
     1961    if (trianglePoints[i] == NULL) {
     1962      *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl;
     1963    }
     1964    *out << Verbose(1) << "List of possible points:" << endl;
     1965    *out << *trianglePoints[i] << endl;
     1966  }
     1967  delete(connectedClosestPoints);
     1968
     1969  list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints);
     1970
     1971  if (triangles->empty()) {
     1972    *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
     1973    return NULL;
     1974  } else
     1975    return triangles;
     1976};
     1977
     1978/** Finds closest triangle to a point.
     1979 * This basically just takes care of the degenerate case, which is not handled in FindClosestTrianglesToPoint().
     1980 * \param *out output stream for debugging
     1981 * \param *x Vector to look from
     1982 * \return list of BoundaryTriangleSet of nearest triangles or NULL.
     1983 */
     1984class BoundaryTriangleSet * Tesselation::FindClosestTriangleToPoint(ofstream *out, Vector *x, LinkedCell* LC)
     1985{
     1986  class BoundaryTriangleSet *result = NULL;
     1987  list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC);
     1988
     1989  if (triangles == NULL)
     1990    return NULL;
     1991
     1992  if (x->ScalarProduct(&triangles->front()->NormalVector) < 0)
     1993    result = triangles->back();
     1994  else
     1995    result = triangles->front();
     1996
     1997  delete(triangles);
     1998  return result;
     1999};
     2000
     2001/** Checks whether the provided Vector is within the tesselation structure.
     2002 *
     2003 * @param point of which to check the position
     2004 * @param *LC LinkedCell structure
     2005 *
     2006 * @return true if the point is inside the tesselation structure, false otherwise
     2007 */
     2008bool Tesselation::IsInnerPoint(ofstream *out, Vector Point, LinkedCell* LC)
     2009{
     2010  class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC);
     2011  if (result == NULL)
     2012    return true;
     2013  if (Point.ScalarProduct(&result->NormalVector) < 0)
     2014    return true;
     2015  else
     2016    return false;
     2017}
     2018
     2019/** Checks whether the provided TesselPoint is within the tesselation structure.
     2020 *
     2021 * @param *Point of which to check the position
     2022 * @param *LC Linked Cell structure
     2023 *
     2024 * @return true if the point is inside the tesselation structure, false otherwise
     2025 */
     2026bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC)
     2027{
     2028  class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC);
     2029  if (result == NULL)
     2030    return true;
     2031  if (Point->node->ScalarProduct(&result->NormalVector) < 0)
     2032    return true;
     2033  else
     2034    return false;
     2035}
     2036
     2037/** Gets all points connected to the provided point by triangulation lines.
     2038 * Maps them down onto the plane designated by the axis \a *Point and \a *Reference. The center of all points
     2039 * connected in the tesselation to \a *Point is mapped to spherical coordinates with the zero angle being given
     2040 * by the mapped down \a *Reference. Hence, the biggest and the smallest angles are those of the two shanks of the
     2041 * triangle we are looking for.
     2042 *
     2043 * @param *Point of which get all connected points
     2044 * @param *Reference Vector to be checked whether it is an inner point
     2045 *
     2046 * @return list of the two points linked to the provided one and closest to the point to be checked,
     2047 */
     2048list<TesselPoint*> * Tesselation::getCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector* Reference)
     2049{
     2050  list<TesselPoint*> connectedPoints;
     2051  map<double, TesselPoint*> anglesOfPoints;
     2052  map<double, TesselPoint*>::iterator runner;
     2053  list<TesselPoint*>::iterator listRunner;
     2054  Vector center, planeNorm, currentPoint, OrthogonalVector, helper;
     2055  TesselPoint* current;
     2056  bool takePoint = false;
     2057
     2058  planeNorm.CopyVector(Point->node);
     2059  planeNorm.SubtractVector(Reference);
     2060  planeNorm.Normalize();
     2061
     2062  LineMap::iterator findLines = LinesOnBoundary.begin();
     2063  while (findLines != LinesOnBoundary.end()) {
     2064    takePoint = false;
     2065
     2066    if (findLines->second->endpoints[0]->Nr == Point->nr) {
     2067      takePoint = true;
     2068      current = findLines->second->endpoints[1]->node;
     2069    } else if (findLines->second->endpoints[1]->Nr == Point->nr) {
     2070      takePoint = true;
     2071      current = findLines->second->endpoints[0]->node;
     2072    }
     2073
     2074    if (takePoint) {
     2075      connectedPoints.push_back(current);
     2076      currentPoint.CopyVector(current->node);
     2077      currentPoint.ProjectOntoPlane(&planeNorm);
     2078      center.AddVector(&currentPoint);
     2079    }
     2080
     2081    findLines++;
     2082  }
     2083
     2084  *out << "Summed vectors " << center << "; number of points " << connectedPoints.size()
     2085    << "; scale factor " << 1.0/connectedPoints.size();
     2086
     2087  center.Scale(1.0/connectedPoints.size());
     2088  listRunner = connectedPoints.begin();
     2089
     2090  *out << " calculated center " << center <<  endl;
     2091
     2092  // construct one orthogonal vector
     2093  helper.CopyVector(Reference);
     2094  helper.ProjectOntoPlane(&planeNorm);
     2095  OrthogonalVector.MakeNormalVector(&center, &helper, (*listRunner)->node);
     2096  while (listRunner != connectedPoints.end()) {
     2097    double angle = getAngle(*((*listRunner)->node), *(Reference), center, OrthogonalVector);
     2098    *out << "Calculated angle " << angle << " for point " << **listRunner << endl;
     2099    anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner)));
     2100    listRunner++;
     2101  }
     2102
     2103  list<TesselPoint*> *result = new list<TesselPoint*>;
     2104  runner = anglesOfPoints.begin();
     2105  *out << "First value is " << *runner->second << endl;
     2106  result->push_back(runner->second);
     2107  runner = anglesOfPoints.end();
     2108  runner--;
     2109  *out << "Second value is " << *runner->second << endl;
     2110  result->push_back(runner->second);
     2111
     2112  *out << "List of closest points has " << result->size() << " elements, which are "
     2113    << *(result->front()) << " and " << *(result->back()) << endl;
     2114
     2115  return result;
     2116}
     2117
    18762118/** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
    18772119 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
     
    19572199
    19582200
     2201
    19592202/**
    1960  * Checks whether the provided atom is within the tesselation structure.
     2203 * Finds the point which is closest to the provided one.
    19612204 *
    1962  * @param *Atom of which to check the position
    1963  * @param tesselation structure
    1964  *
    1965  * @return true if the atom is inside the tesselation structure, false otherwise
    1966  */
    1967 bool IsInnerPoint(TesselPoint *Atom, class Tesselation *Tess, LinkedCell* LC)
    1968 {
    1969   if (Tess->LinesOnBoundary.begin() == Tess->LinesOnBoundary.end()) {
    1970     cout << Verbose(0) << "Error: There is no tesselation structure to compare the point with, "
    1971         << "please create one first.";
    1972     exit(1);
    1973   }
    1974 
    1975   class TesselPoint *trianglePoints[3];
    1976   trianglePoints[0] = findClosestAtom(Atom, LC);
    1977   // check whether closest atom is "too close" :), then it's inside
    1978   if (trianglePoints[0]->node->DistanceSquared(Atom->node) < MYEPSILON)
    1979     return true;
    1980   list<TesselPoint*> *connectedClosestPoints = Tess->getClosestConnectedAtoms(trianglePoints[0], Atom);
    1981   trianglePoints[1] = connectedClosestPoints->front();
    1982   trianglePoints[2] = connectedClosestPoints->back();
    1983   for (int i=0;i<3;i++) {
    1984     if (trianglePoints[i] == NULL) {
    1985       cout << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl;
    1986     }
    1987 
    1988     cout << Verbose(1) << "List of possible atoms:" << endl;
    1989     cout << *trianglePoints[i] << endl;
    1990 
    1991 //    for(list<TesselPoint*>::iterator runner = connectedClosestPoints->begin(); runner != connectedClosestPoints->end(); runner++)
    1992 //      cout << Verbose(2) << *(*runner) << endl;
    1993   }
    1994   delete(connectedClosestPoints);
    1995 
    1996   list<BoundaryTriangleSet*> *triangles = Tess->FindTriangles(trianglePoints);
    1997 
    1998   if (triangles->empty()) {
    1999     cout << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
    2000     exit(1);
    2001   }
    2002 
    2003   Vector helper;
    2004   helper.CopyVector(Atom->node);
    2005 
    2006   // Only in case of degeneration, there will be two different scalar products.
    2007   // If at least one scalar product is positive, the point is considered to be outside.
    2008   bool status = (helper.ScalarProduct(&triangles->front()->NormalVector) < 0)
    2009       && (helper.ScalarProduct(&triangles->back()->NormalVector) < 0);
    2010   delete(triangles);
    2011   return status;
    2012 }
    2013 
    2014 /**
    2015  * Finds the atom which is closest to the provided one.
    2016  *
    2017  * @param atom to which to find the closest other atom
     2205 * @param Point to which to find the closest other point
    20182206 * @param linked cell structure
    20192207 *
    2020  * @return atom which is closest to the provided one
    2021  */
    2022 TesselPoint* findClosestAtom(const TesselPoint* Atom, LinkedCell* LC)
     2208 * @return point which is closest to the provided one
     2209 */
     2210TesselPoint* findClosestPoint(const Vector* Point, LinkedCell* LC)
    20232211{
    20242212  LinkedNodes *List = NULL;
    2025   TesselPoint* closestAtom = NULL;
     2213  TesselPoint* closestPoint = NULL;
    20262214  double distance = 1e16;
    20272215  Vector helper;
    20282216  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    20292217
    2030   LC->SetIndexToVector(Atom->node); // ignore status as we calculate bounds below sensibly
     2218  LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
    20312219  for(int i=0;i<NDIM;i++) // store indices of this cell
    20322220    N[i] = LC->n[i];
     
    20422230        if (List != NULL) {
    20432231          for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2044             helper.CopyVector(Atom->node);
     2232            helper.CopyVector(Point);
    20452233            helper.SubtractVector((*Runner)->node);
    20462234            double currentNorm = helper. Norm();
    20472235            if (currentNorm < distance) {
    20482236              distance = currentNorm;
    2049               closestAtom = (*Runner);
     2237              closestPoint = (*Runner);
    20502238            }
    20512239          }
     
    20562244      }
    20572245
    2058   return closestAtom;
    2059 }
     2246  return closestPoint;
     2247}
     2248
    20602249
    20612250/**
    2062  * Gets all atoms connected to the provided atom by triangulation lines.
     2251 * Finds triangles belonging to the three provided points.
    20632252 *
    2064  * @param atom of which get all connected atoms
    2065  * @param atom to be checked whether it is an inner atom
     2253 * @param *Points[3] list, is expected to contain three points
    20662254 *
    2067  * @return list of the two atoms linked to the provided one and closest to the atom to be checked,
    2068  */
    2069 list<TesselPoint*> * Tesselation::getClosestConnectedAtoms(TesselPoint* Atom, TesselPoint* AtomToCheck)
    2070 {
    2071   list<TesselPoint*> connectedAtoms;
    2072   map<double, TesselPoint*> anglesOfAtoms;
    2073   map<double, TesselPoint*>::iterator runner;
    2074   LineMap::iterator findLines = LinesOnBoundary.begin();
    2075   list<TesselPoint*>::iterator listRunner;
    2076   Vector center, planeNorm, currentPoint, OrthogonalVector, helper;
    2077   TesselPoint* current;
    2078   bool takeAtom = false;
    2079 
    2080   planeNorm.CopyVector(Atom->node);
    2081   planeNorm.SubtractVector(AtomToCheck->node);
    2082   planeNorm.Normalize();
    2083 
    2084   while (findLines != LinesOnBoundary.end()) {
    2085     takeAtom = false;
    2086 
    2087     if (findLines->second->endpoints[0]->Nr == Atom->nr) {
    2088       takeAtom = true;
    2089       current = findLines->second->endpoints[1]->node;
    2090     } else if (findLines->second->endpoints[1]->Nr == Atom->nr) {
    2091       takeAtom = true;
    2092       current = findLines->second->endpoints[0]->node;
    2093     }
    2094 
    2095     if (takeAtom) {
    2096       connectedAtoms.push_back(current);
    2097       currentPoint.CopyVector(current->node);
    2098       currentPoint.ProjectOntoPlane(&planeNorm);
    2099       center.AddVector(&currentPoint);
    2100     }
    2101 
    2102     findLines++;
    2103   }
    2104 
    2105   cout << "Summed vectors " << center << "; number of atoms " << connectedAtoms.size()
    2106     << "; scale factor " << 1.0/connectedAtoms.size();
    2107 
    2108   center.Scale(1.0/connectedAtoms.size());
    2109   listRunner = connectedAtoms.begin();
    2110 
    2111   cout << " calculated center " << center <<  endl;
    2112 
    2113   // construct one orthogonal vector
    2114   helper.CopyVector(AtomToCheck->node);
    2115   helper.ProjectOntoPlane(&planeNorm);
    2116   OrthogonalVector.MakeNormalVector(&center, &helper, (*listRunner)->node);
    2117   while (listRunner != connectedAtoms.end()) {
    2118     double angle = getAngle(*((*listRunner)->node), *(AtomToCheck->node), center, OrthogonalVector);
    2119     cout << "Calculated angle " << angle << " for atom " << **listRunner << endl;
    2120     anglesOfAtoms.insert(pair<double, TesselPoint*>(angle, (*listRunner)));
    2121     listRunner++;
    2122   }
    2123 
    2124   list<TesselPoint*> *result = new list<TesselPoint*>;
    2125   runner = anglesOfAtoms.begin();
    2126   cout << "First value is " << *runner->second << endl;
    2127   result->push_back(runner->second);
    2128   runner = anglesOfAtoms.end();
    2129   runner--;
    2130   cout << "Second value is " << *runner->second << endl;
    2131   result->push_back(runner->second);
    2132 
    2133   cout << "List of closest atoms has " << result->size() << " elements, which are "
    2134     << *(result->front()) << " and " << *(result->back()) << endl;
    2135 
    2136   return result;
    2137 }
    2138 
    2139 /**
    2140  * Finds triangles belonging to the three provided atoms.
    2141  *
    2142  * @param atom list, is expected to contain three atoms
    2143  *
    2144  * @return triangles which belong to the provided atoms, will be empty if there are none,
     2255 * @return triangles which belong to the provided points, will be empty if there are none,
    21452256 *         will usually be one, in case of degeneration, there will be two
    21462257 */
     
    22022313}
    22032314
    2204 /**
    2205  * Gets the angle between a point and a reference relative to the provided center.
    2206  *
     2315/** Gets the angle between a point and a reference relative to the provided center.
     2316 * We have two shanks (point, center) and (reference, center) between which the angle is calculated
     2317 * and by scalar product with OrthogonalVector we decide the interval.
    22072318 * @param point to calculate the angle for
    22082319 * @param reference to which to calculate the angle
    22092320 * @param center for which to calculate the angle between the vectors
    2210  * @param OrthogonalVector helps discern between [0,pi] and [pi,2pi] in acos()
     2321 * @param OrthogonalVector points in direction of [pi,2pi] interval
    22112322 *
    22122323 * @return angle between point and reference
    22132324 */
    2214 double getAngle(Vector point, Vector reference, Vector center, Vector OrthogonalVector)
     2325double getAngle(const Vector &point, const Vector &reference, const Vector &center, Vector OrthogonalVector)
    22152326{
    22162327  Vector ReferenceVector, helper;
    2217   cout << Verbose(2) << reference << " is our reference " << endl;
    2218   cout << Verbose(2) << center << " is our center " << endl;
     2328  cout << Verbose(4) << center << " is our center " << endl;
    22192329  // create baseline vector
    22202330  ReferenceVector.CopyVector(&reference);
    22212331  ReferenceVector.SubtractVector(&center);
     2332  OrthogonalVector.MakeNormalVector(&ReferenceVector);
     2333  cout << Verbose(4) << ReferenceVector << " is our reference " << endl;
    22222334  if (ReferenceVector.IsNull())
    22232335    return M_PI;
     
    22332345  }
    22342346
    2235   cout << Verbose(2) << point << " has angle " << phi << endl;
     2347  cout << Verbose(3) << helper << " has angle " << phi << " with respect to reference." << endl;
    22362348
    22372349  return phi;
    22382350}
    22392351
    2240 /**
    2241  * Checks whether the provided point is within the tesselation structure.
    2242  *
    2243  * This is a wrapper function for IsInnerAtom, so it can be used with a simple
    2244  * vector, too.
    2245  *
    2246  * @param point of which to check the position
    2247  * @param tesselation structure
    2248  *
    2249  * @return true if the point is inside the tesselation structure, false otherwise
    2250  */
    2251 bool IsInnerPoint(Vector Point, class Tesselation *Tess, LinkedCell* LC)
    2252 {
    2253   TesselPoint *temp_atom = new TesselPoint;
    2254   bool status = false;
    2255   temp_atom->node->CopyVector(&Point);
    2256 
    2257   status = IsInnerPoint(temp_atom, Tess, LC);
    2258   delete(temp_atom);
    2259 
    2260   return status;
    2261 }
    2262 
Note: See TracChangeset for help on using the changeset viewer.