Changes in / [c0917c:a33931]


Ignore:
Location:
src
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • src/Makefile.am

    rc0917c ra33931  
    22HEADER = atom.hpp bond.hpp boundary.hpp config.hpp defs.hpp element.hpp ellipsoid.hpp helpers.hpp leastsquaremin.hpp linkedcell.hpp memoryallocator.hpp memoryusageobserver.cpp memoryusageobserver.hpp molecules.hpp parser.hpp periodentafel.hpp stackclass.hpp tesselation.hpp tesselationhelpers.hpp vector.hpp verbose.hpp
    33
    4 noinst_PROGRAMS =  VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest
     4noinst_PROGRAMS =  VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest TesselationUnitTest
    55
    66bin_PROGRAMS = molecuilder joiner analyzer
     
    1111analyzer_SOURCES = analyzer.cpp datacreator.cpp element.cpp helpers.cpp memoryallocator.hpp memoryusageobserver.cpp memoryusageobserver.hpp periodentafel.cpp parser.cpp verbose.cpp helpers.hpp periodentafel.hpp parser.hpp datacreator.hpp
    1212
    13 TESTS = VectorUnitTest MemoryAllocatorUnitTest
     13TESTS = VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest TesselationUnitTest
    1414check_PROGRAMS = $(TESTS)
    1515VectorUnitTest_SOURCES = defs.hpp helpers.cpp helpers.hpp leastsquaremin.cpp leastsquaremin.hpp memoryallocator.hpp memoryusageobserver.cpp memoryusageobserver.hpp vectorunittest.cpp vectorunittest.hpp vector.cpp vector.hpp verbose.cpp verbose.hpp
    1616VectorUnitTest_CXXFLAGS = $(CPPUNIT_CFLAGS)
    1717VectorUnitTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl
     18TesselationUnitTest_SOURCES = defs.hpp helpers.cpp helpers.hpp leastsquaremin.cpp leastsquaremin.hpp linkedcell.cpp linkedcell.hpp tesselation.cpp tesselation.hpp tesselationhelpers.cpp tesselationhelpers.hpp tesselationunittest.cpp tesselationunittest.hpp vector.cpp vector.hpp verbose.cpp verbose.hpp
     19TesselationUnitTest_CXXFLAGS = $(CPPUNIT_CFLAGS)
     20TesselationUnitTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl
    1821
    1922MemoryAllocatorUnitTest_SOURCES = defs.hpp helpers.cpp helpers.hpp memoryallocatorunittest.cpp memoryallocatorunittest.hpp memoryallocator.hpp memoryusageobserver.cpp memoryusageobserver.hpp verbose.cpp verbose.hpp
  • src/atom.cpp

    rc0917c ra33931  
    6262atom::~atom()
    6363{
    64   Free(&ComponentNr);
     64  Free<int>(&ComponentNr, "atom::~atom: *ComponentNr");
     65  Free<char *>(&Name, "atom::~atom: *Name");
    6566};
    6667
  • src/boundary.cpp

    rc0917c ra33931  
    113113;
    114114
    115 /** Creates the objects in a VRML file.
    116  * \param *out output stream for debugging
    117  * \param *vrmlfile output stream for tecplot data
    118  * \param *Tess Tesselation structure with constructed triangles
    119  * \param *mol molecule structure with atom positions
    120  */
    121 void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)
    122 {
    123   atom *Walker = mol->start;
    124   bond *Binder = mol->first;
    125   int i;
    126   Vector *center = mol->DetermineCenterOfAll(out);
    127   if (vrmlfile != NULL) {
    128     //cout << Verbose(1) << "Writing Raster3D file ... ";
    129     *vrmlfile << "#VRML V2.0 utf8" << endl;
    130     *vrmlfile << "#Created by molecuilder" << endl;
    131     *vrmlfile << "#All atoms as spheres" << endl;
    132     while (Walker->next != mol->end) {
    133       Walker = Walker->next;
    134       *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
    135       for (i=0;i<NDIM;i++)
    136         *vrmlfile << Walker->x.x[i]-center->x[i] << " ";
    137       *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    138     }
    139 
    140     *vrmlfile << "# All bonds as vertices" << endl;
    141     while (Binder->next != mol->last) {
    142       Binder = Binder->next;
    143       *vrmlfile << "3" << endl << "  "; // 2 is round-ended cylinder type
    144       for (i=0;i<NDIM;i++)
    145         *vrmlfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    146       *vrmlfile << "\t0.03\t";
    147       for (i=0;i<NDIM;i++)
    148         *vrmlfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    149       *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    150     }
    151 
    152     *vrmlfile << "# All tesselation triangles" << endl;
    153     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    154       *vrmlfile << "1" << endl << "  "; // 1 is triangle type
    155       for (i=0;i<3;i++) { // print each node
    156         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    157           *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    158         *vrmlfile << "\t";
    159       }
    160       *vrmlfile << "1. 0. 0." << endl;  // red as colour
    161       *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
    162     }
    163   } else {
    164     cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
    165   }
    166   delete(center);
    167 };
    168 
    169 /** Creates the objects in a raster3d file (renderable with a header.r3d).
    170  * \param *out output stream for debugging
    171  * \param *rasterfile output stream for tecplot data
    172  * \param *Tess Tesselation structure with constructed triangles
    173  * \param *mol molecule structure with atom positions
    174  */
    175 void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)
    176 {
    177   atom *Walker = mol->start;
    178   bond *Binder = mol->first;
    179   int i;
    180   Vector *center = mol->DetermineCenterOfAll(out);
    181   if (rasterfile != NULL) {
    182     //cout << Verbose(1) << "Writing Raster3D file ... ";
    183     *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
    184     *rasterfile << "@header.r3d" << endl;
    185     *rasterfile << "# All atoms as spheres" << endl;
    186     while (Walker->next != mol->end) {
    187       Walker = Walker->next;
    188       *rasterfile << "2" << endl << "  ";  // 2 is sphere type
    189       for (i=0;i<NDIM;i++)
    190         *rasterfile << Walker->x.x[i]-center->x[i] << " ";
    191       *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
    192     }
    193 
    194     *rasterfile << "# All bonds as vertices" << endl;
    195     while (Binder->next != mol->last) {
    196       Binder = Binder->next;
    197       *rasterfile << "3" << endl << "  ";  // 2 is round-ended cylinder type
    198       for (i=0;i<NDIM;i++)
    199         *rasterfile << Binder->leftatom->x.x[i]-center->x[i] << " ";
    200       *rasterfile << "\t0.03\t";
    201       for (i=0;i<NDIM;i++)
    202         *rasterfile << Binder->rightatom->x.x[i]-center->x[i] << " ";
    203       *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour
    204     }
    205 
    206     *rasterfile << "# All tesselation triangles" << endl;
    207     *rasterfile << "8\n  25. -1.   1. 1. 1.   0.0    0 0 0 2\n  SOLID     1.0 0.0 0.0\n  BACKFACE  0.3 0.3 1.0   0 0\n";
    208     for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
    209       *rasterfile << "1" << endl << "  ";  // 1 is triangle type
    210       for (i=0;i<3;i++) {  // print each node
    211         for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
    212           *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
    213         *rasterfile << "\t";
    214       }
    215       *rasterfile << "1. 0. 0." << endl;  // red as colour
    216       //*rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl;  // 18 is transparency type for previous object
    217     }
    218     *rasterfile << "9\n#  terminating special property\n";
    219   } else {
    220     cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
    221   }
    222   delete(center);
    223 };
    224 
    225 /** This function creates the tecplot file, displaying the tesselation of the hull.
    226  * \param *out output stream for debugging
    227  * \param *tecplot output stream for tecplot data
    228  * \param N arbitrary number to differentiate various zones in the tecplot format
    229  */
    230 void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol, int N)
    231 {
    232   if ((tecplot != NULL) && (TesselStruct != NULL)) {
    233     // write header
    234     *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
    235     *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\" \"U\"" << endl;
    236     *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" << TesselStruct->PointsOnBoundary.size() << ", E=" << TesselStruct->TrianglesOnBoundary.size() << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
    237     int *LookupList = new int[mol->AtomCount];
    238     for (int i = 0; i < mol->AtomCount; i++)
    239       LookupList[i] = -1;
    240 
    241     // print atom coordinates
    242     *out << Verbose(2) << "The following triangles were created:";
    243     int Counter = 1;
    244     TesselPoint *Walker = NULL;
    245     for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
    246       Walker = target->second->node;
    247       LookupList[Walker->nr] = Counter++;
    248       *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << target->second->value << endl;
    249     }
    250     *tecplot << endl;
    251     // print connectivity
    252     for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {
    253       *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
    254       *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
    255     }
    256     delete[] (LookupList);
    257     *out << endl;
    258   }
    259 }
    260 
    261115
    262116/** Determines the boundary points of a cluster.
     
    537391
    538392        // flip the line
    539         if (!mol->TesselStruct->PickFarthestofTwoBaselines(out, line))
     393        if (mol->TesselStruct->PickFarthestofTwoBaselines(out, line) == 0.)
    540394          *out << Verbose(1) << "ERROR: Correction of concave baselines failed!" << endl;
    541         else
     395        else {
     396          mol->TesselStruct->FlipBaseline(out, line);
    542397          *out << Verbose(1) << "INFO: Correction of concave baselines worked." << endl;
     398        }
    543399      }
    544400    }
     
    577433
    578434  cout << Verbose(1) << "End of FindConvexBorder" << endl;
     435};
     436
     437/** For testing removes one boundary point after another to check for leaks.
     438 * \param *out output stream for debugging
     439 * \param *TesselStruct Tesselation containing envelope with boundary points
     440 * \param *mol molecule
     441 * \param *filename name of file
     442 * \return true - all removed, false - something went wrong
     443 */
     444bool RemoveAllBoundaryPoints(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename)
     445{
     446  int i=0;
     447  char number[MAXSTRINGSIZE];
     448
     449  if ((TesselStruct == NULL) || (TesselStruct->PointsOnBoundary.empty())) {
     450    *out << Verbose(2) << "ERROR: TesselStruct is empty." << endl;
     451    return false;
     452  }
     453
     454  PointMap::iterator PointRunner;
     455  while (!TesselStruct->PointsOnBoundary.empty()) {
     456    *out << Verbose(2) << "Remaining points are: ";
     457    for (PointMap::iterator PointSprinter = TesselStruct->PointsOnBoundary.begin(); PointSprinter != TesselStruct->PointsOnBoundary.end(); PointSprinter++)
     458      *out << *(PointSprinter->second) << "\t";
     459      *out << endl;
     460
     461    PointRunner = TesselStruct->PointsOnBoundary.begin();
     462    // remove point
     463    TesselStruct->RemovePointFromTesselatedSurface(out, PointRunner->second);
     464
     465    // store envelope
     466    sprintf(number, "-%04d", i++);
     467    StoreTrianglesinFile(out, mol, filename, number);
     468  }
     469
     470  return true;
    579471};
    580472
     
    609501  class BoundaryLineSet *line = NULL;
    610502  bool Concavity;
     503  char dummy[MAXSTRINGSIZE];
    611504  PointMap::iterator PointRunner, PointAdvance;
    612505  LineMap::iterator LineRunner, LineAdvance;
     
    621514  }
    622515
    623   //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    624   StoreTrianglesinFile(out, mol, filename, "-first");
    625 
    626516  // First step: RemovePointFromTesselatedSurface
     517  int run = 0;
     518  double tmp;
    627519  do {
    628520    Concavity = false;
     521    sprintf(dummy, "-first-%d", run);
     522    //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
     523    StoreTrianglesinFile(out, mol, filename, dummy);
     524
    629525    PointRunner = TesselStruct->PointsOnBoundary.begin();
    630526    PointAdvance = PointRunner; // we need an advanced point, as the PointRunner might get removed
     
    636532        line = LineRunner->second;
    637533        *out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
    638       }
    639       if (!line->CheckConvexityCriterion(out)) {
    640         *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl;
    641         // remove the point
    642         Concavity = true;
    643         TesselStruct->RemovePointFromTesselatedSurface(out, point);
     534        if (!line->CheckConvexityCriterion(out)) {
     535          // remove the point if needed
     536          *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl;
     537          volume += TesselStruct->RemovePointFromTesselatedSurface(out, point);
     538          sprintf(dummy, "-first-%d", ++run);
     539          StoreTrianglesinFile(out, mol, filename, dummy);
     540          Concavity = true;
     541          break;
     542        }
    644543      }
    645544      PointRunner = PointAdvance;
    646545    }
    647546
     547    sprintf(dummy, "-second-%d", run);
    648548    //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    649     //StoreTrianglesinFile(out, mol, filename, "-second");
     549    StoreTrianglesinFile(out, mol, filename, dummy);
    650550
    651551    // second step: PickFarthestofTwoBaselines
     
    658558      // take highest of both lines
    659559      if (TesselStruct->IsConvexRectangle(out, line) == NULL) {
    660         TesselStruct->PickFarthestofTwoBaselines(out, line);
    661         Concavity = true;
     560        tmp = TesselStruct->PickFarthestofTwoBaselines(out, line);
     561        volume += tmp;
     562        if (tmp != 0) {
     563          mol->TesselStruct->FlipBaseline(out, line);
     564          Concavity = true;
     565        }
    662566      }
    663567      LineRunner = LineAdvance;
    664568    }
     569    run++;
    665570  } while (Concavity);
     571  //CalculateConcavityPerBoundaryPoint(out, TesselStruct);
     572  //StoreTrianglesinFile(out, mol, filename, "-third");
     573
     574  // third step: IsConvexRectangle
     575//  LineRunner = TesselStruct->LinesOnBoundary.begin();
     576//  LineAdvance = LineRunner;  // we need an advanced line, as the LineRunner might get removed
     577//  while (LineRunner != TesselStruct->LinesOnBoundary.end()) {
     578//    LineAdvance++;
     579//    line = LineRunner->second;
     580//    *out << Verbose(1) << "INFO: Current line is " << *line << "." << endl;
     581//    //if (LineAdvance != TesselStruct->LinesOnBoundary.end())
     582//      //*out << Verbose(1) << "INFO: Next line will be " << *(LineAdvance->second) << "." << endl;
     583//    if (!line->CheckConvexityCriterion(out)) {
     584//      *out << Verbose(1) << "... line " << *line << " is concave, flipping it." << endl;
     585//
     586//      // take highest of both lines
     587//      point = TesselStruct->IsConvexRectangle(out, line);
     588//      if (point != NULL)
     589//        volume += TesselStruct->RemovePointFromTesselatedSurface(out, point);
     590//    }
     591//    LineRunner = LineAdvance;
     592//  }
     593
    666594  CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    667   StoreTrianglesinFile(out, mol, filename, "-third");
    668 
    669   // third step: IsConvexRectangle
    670   LineRunner = TesselStruct->LinesOnBoundary.begin();
    671   LineAdvance = LineRunner;  // we need an advanced line, as the LineRunner might get removed
    672   while (LineRunner != TesselStruct->LinesOnBoundary.end()) {
    673     LineAdvance++;
    674     line = LineRunner->second;
    675     *out << Verbose(1) << "INFO: Current line is " << *line << "." << endl;
    676     //if (LineAdvance != TesselStruct->LinesOnBoundary.end())
    677       //*out << Verbose(1) << "INFO: Next line will be " << *(LineAdvance->second) << "." << endl;
    678     if (!line->CheckConvexityCriterion(out)) {
    679       *out << Verbose(1) << "... line " << *line << " is concave, flipping it." << endl;
    680 
    681       // take highest of both lines
    682       point = TesselStruct->IsConvexRectangle(out, line);
    683       if (point != NULL)
    684         TesselStruct->RemovePointFromTesselatedSurface(out, point);
    685     }
    686     LineRunner = LineAdvance;
    687   }
    688 
    689   CalculateConcavityPerBoundaryPoint(out, TesselStruct);
    690   StoreTrianglesinFile(out, mol, filename, "-fourth");
     595  StoreTrianglesinFile(out, mol, filename, "");
    691596
    692597  // end
     598  *out << Verbose(1) << "Volume is " << volume << "." << endl;
    693599  *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl;
    694600  return volume;
    695601};
    696602
    697 /** Calculates the concavity for each of the BoundaryPointSet's in a Tesselation.
    698  * Sets BoundaryPointSet::value equal to the number of connected lines that are not convex.
    699  * \param *out output stream for debugging
    700  * \param *TesselStruct pointer to Tesselation structure
    701  */
    702 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct)
    703 {
    704   class BoundaryPointSet *point = NULL;
    705   class BoundaryLineSet *line = NULL;
    706   // calculate remaining concavity
    707   for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
    708     point = PointRunner->second;
    709     *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
    710     point->value = 0;
    711     for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
    712       line = LineRunner->second;
    713       *out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
    714       if (!line->CheckConvexityCriterion(out))
    715         point->value += 1;
    716     }
    717   }
    718 };
    719 
    720 /** Stores triangles to file.
    721  * \param *out output stream for debugging
    722  * \param *mol molecule with atoms and bonds
    723  * \param *filename prefix of filename
    724  * \param *extraSuffix intermediate suffix
    725  */
    726 void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix)
    727 {
    728   // 4. Store triangles in tecplot file
    729   if (filename != NULL) {
    730     if (DoTecplotOutput) {
    731       string OutputName(filename);
    732       OutputName.append(extraSuffix);
    733       OutputName.append(TecplotSuffix);
    734       ofstream *tecplot = new ofstream(OutputName.c_str());
    735       WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, 0);
    736       tecplot->close();
    737       delete(tecplot);
    738     }
    739     if (DoRaster3DOutput) {
    740       string OutputName(filename);
    741       OutputName.append(extraSuffix);
    742       OutputName.append(Raster3DSuffix);
    743       ofstream *rasterplot = new ofstream(OutputName.c_str());
    744       WriteRaster3dFile(out, rasterplot, mol->TesselStruct, mol);
    745       rasterplot->close();
    746       delete(rasterplot);
    747     }
    748   }
    749 };
    750603
    751604/** Determines the volume of a cluster.
     
    794647
    795648  return volume;
    796 }
    797 ;
     649};
     650
     651/** Stores triangles to file.
     652 * \param *out output stream for debugging
     653 * \param *mol molecule with atoms and bonds
     654 * \param *filename prefix of filename
     655 * \param *extraSuffix intermediate suffix
     656 */
     657void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix)
     658{
     659  // 4. Store triangles in tecplot file
     660  if (filename != NULL) {
     661    if (DoTecplotOutput) {
     662      string OutputName(filename);
     663      OutputName.append(extraSuffix);
     664      OutputName.append(TecplotSuffix);
     665      ofstream *tecplot = new ofstream(OutputName.c_str());
     666      WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, 0);
     667      tecplot->close();
     668      delete(tecplot);
     669    }
     670    if (DoRaster3DOutput) {
     671      string OutputName(filename);
     672      OutputName.append(extraSuffix);
     673      OutputName.append(Raster3DSuffix);
     674      ofstream *rasterplot = new ofstream(OutputName.c_str());
     675      WriteRaster3dFile(out, rasterplot, mol->TesselStruct, mol);
     676      rasterplot->close();
     677      delete(rasterplot);
     678    }
     679  }
     680};
    798681
    799682/** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density.
     
    958841    if ((*ListRunner)->TesselStruct == NULL) {
    959842      *out << Verbose(1) << "Pre-creating tesselation for molecule " << *ListRunner << "." << endl;
    960       FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], NULL, 5.);
     843      FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], 5., NULL);
    961844    }
    962845    i++;
     
    1080963 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return
    1081964 * \param *LCList atoms in LinkedCell list
     965 * \param RADIUS radius of the virtual sphere
    1082966 * \param *filename filename prefix for output of vertex data
    1083  * \para RADIUS radius of the virtual sphere
    1084  */
    1085 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename, const double RADIUS)
     967 */
     968void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const double RADIUS, const char *filename = NULL)
    1086969{
    1087   int N = 0;
    1088970  bool freeLC = false;
    1089   ofstream *tempstream = NULL;
    1090   char NumberName[255];
    1091   int TriangleFilesWritten = 0;
    1092971
    1093972  *out << Verbose(1) << "Entering search for non convex hull. " << endl;
     
    1103982  LineMap::iterator testline;
    1104983  *out << Verbose(0) << "Begin of FindNonConvexBorder\n";
    1105   bool flag = false;  // marks whether we went once through all baselines without finding any without two triangles
    1106   bool failflag = false;
    1107 
     984  bool OneLoopWithoutSuccessFlag = false;  // marks whether we went once through all baselines without finding any without two triangles
     985  bool TesselationFailFlag = false;
     986
     987  // initialise Linked Cell
    1108988  if (LCList == NULL) {
    1109989    LCList = new LinkedCell(mol, 2.*RADIUS);
     
    1111991  }
    1112992
     993  // 1. get starting triangle
    1113994  mol->TesselStruct->FindStartingTriangle(out, RADIUS, LCList);
    1114995
     996  // 2. expand from there
    1115997  baseline = mol->TesselStruct->LinesOnBoundary.begin();
    1116   // the outward most line is dangerous, as we may end up with wrapping up the starting triangle, hence
    1117   // terminating the algorithm too early.
    1118   if (baseline != mol->TesselStruct->LinesOnBoundary.end()) // skip first line as it its the outwardmost!
    1119         baseline++;
    1120   while ((baseline != mol->TesselStruct->LinesOnBoundary.end()) || (flag)) {
     998  baseline++; // skip first line
     999  while ((baseline != mol->TesselStruct->LinesOnBoundary.end()) || (OneLoopWithoutSuccessFlag)) {
    11211000    if (baseline->second->triangles.size() == 1) {
    1122       failflag = mol->TesselStruct->FindNextSuitableTriangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, N, LCList); //the line is there, so there is a triangle, but only one.
    1123       flag = flag || failflag;
    1124       if (!failflag)
     1001      // 3. find next triangle
     1002      TesselationFailFlag = mol->TesselStruct->FindNextSuitableTriangle(out, *(baseline->second), *(((baseline->second->triangles.begin()))->second), RADIUS, LCList); //the line is there, so there is a triangle, but only one.
     1003      OneLoopWithoutSuccessFlag = OneLoopWithoutSuccessFlag || TesselationFailFlag;
     1004      if (!TesselationFailFlag)
    11251005        cerr << "WARNING: FindNextSuitableTriangle failed." << endl;
     1006
    11261007      // write temporary envelope
    1127       if ((DoSingleStepOutput && (mol->TesselStruct->TrianglesOnBoundaryCount % SingleStepWidth == 0))) { // if we have a new triangle and want to output each new triangle configuration
    1128         TriangleMap::iterator runner = mol->TesselStruct->TrianglesOnBoundary.end();
    1129         runner--;
    1130         class BoundaryTriangleSet *triangle = runner->second;
    1131         if (triangle != NULL) {
    1132           sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, triangle->endpoints[0]->node->Name, triangle->endpoints[1]->node->Name, triangle->endpoints[2]->node->Name);
    1133           if (DoTecplotOutput) {
    1134             string NameofTempFile(filename);
    1135             NameofTempFile.append(NumberName);
    1136             for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    1137             NameofTempFile.erase(npos, 1);
    1138             NameofTempFile.append(TecplotSuffix);
    1139             *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    1140             tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    1141             WriteTecplotFile(out, tempstream, mol->TesselStruct, mol, TriangleFilesWritten);
    1142             tempstream->close();
    1143             tempstream->flush();
    1144             delete(tempstream);
    1145           }
    1146 
    1147           if (DoRaster3DOutput) {
    1148             string NameofTempFile(filename);
    1149             NameofTempFile.append(NumberName);
    1150             for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
    1151             NameofTempFile.erase(npos, 1);
    1152             NameofTempFile.append(Raster3DSuffix);
    1153             *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
    1154             tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
    1155             WriteRaster3dFile(out, tempstream, mol->TesselStruct, mol);
    1156     //        // include the current position of the virtual sphere in the temporary raster3d file
    1157     //        // make the circumsphere's center absolute again
    1158     //        helper.CopyVector(BaseRay->endpoints[0]->node->node);
    1159     //        helper.AddVector(BaseRay->endpoints[1]->node->node);
    1160     //        helper.Scale(0.5);
    1161     //        (*it)->OptCenter.AddVector(&helper);
    1162     //        Vector *center = mol->DetermineCenterOfAll(out);
    1163     //        (*it)->OptCenter.SubtractVector(center);
    1164     //        delete(center);
    1165     //        // and add to file plus translucency object
    1166     //        *tempstream << "# current virtual sphere\n";
    1167     //        *tempstream << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
    1168     //        *tempstream << "2\n  " << (*it)->OptCenter.x[0] << " "
    1169     //          << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2]
    1170     //          << "\t" << RADIUS << "\t1 0 0\n";
    1171     //        *tempstream << "9\n  terminating special property\n";
    1172             tempstream->close();
    1173             tempstream->flush();
    1174             delete(tempstream);
    1175           }
    1176         }
    1177         if (DoTecplotOutput || DoRaster3DOutput)
    1178           TriangleFilesWritten++;
     1008      if (filename != NULL) {
     1009        if ((DoSingleStepOutput && ((mol->TesselStruct->TrianglesOnBoundary.size() % SingleStepWidth == 0)))) { // if we have a new triangle and want to output each new triangle configuration
     1010          mol->TesselStruct->Output(out, filename, mol);
     1011        }
    11791012      }
     1013      baseline = mol->TesselStruct->LinesOnBoundary.end();
     1014      *out << Verbose(2) << "Baseline set to end." << endl;
    11801015    } else {
    11811016      //cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->triangles.size() << " triangles adjacent" << endl;
     
    11841019    }
    11851020
    1186     N++;
     1021    if ((baseline == mol->TesselStruct->LinesOnBoundary.end()) && (OneLoopWithoutSuccessFlag)) {
     1022      baseline = mol->TesselStruct->LinesOnBoundary.begin();   // restart if we reach end due to newly inserted lines
     1023      OneLoopWithoutSuccessFlag = false;
     1024    }
    11871025    baseline++;
    1188     if ((baseline == mol->TesselStruct->LinesOnBoundary.end()) && (flag)) {
    1189       baseline = mol->TesselStruct->LinesOnBoundary.begin();   // restart if we reach end due to newly inserted lines
    1190       flag = false;
    1191     }
    1192   }
     1026  }
     1027  // check envelope for consistency
     1028  CheckListOfBaselines(out, mol->TesselStruct);
     1029
     1030  // look whether all points are inside of the convex envelope, otherwise add them via degenerated triangles
     1031  mol->TesselStruct->InsertStraddlingPoints(out, mol, LCList);
     1032//  mol->GoToFirst();
     1033//  class TesselPoint *Runner = NULL;
     1034//  while (!mol->IsEnd()) {
     1035//    Runner = mol->GetPoint();
     1036//    *out << Verbose(1) << "Checking on " << Runner->Name << " ... " << endl;
     1037//    if (!mol->TesselStruct->IsInnerPoint(out, Runner, LCList)) {
     1038//      *out << Verbose(2) << Runner->Name << " is outside of envelope, adding via degenerated triangles." << endl;
     1039//      mol->TesselStruct->AddBoundaryPointByDegeneratedTriangle(out, Runner, LCList);
     1040//    } else {
     1041//      *out << Verbose(2) << Runner->Name << " is inside of or on envelope." << endl;
     1042//    }
     1043//    mol->GoToNext();
     1044//  }
    11931045
    11941046  // Purges surplus triangles.
    11951047  mol->TesselStruct->RemoveDegeneratedTriangles();
    11961048
     1049  // check envelope for consistency
     1050  CheckListOfBaselines(out, mol->TesselStruct);
     1051
    11971052  // write final envelope
    1198   if (filename != 0) {
    1199     *out << Verbose(1) << "Writing final tecplot file\n";
    1200     if (DoTecplotOutput) {
    1201       string OutputName(filename);
    1202       OutputName.append(TecplotSuffix);
    1203       ofstream *tecplot = new ofstream(OutputName.c_str());
    1204       WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, -1);
    1205       tecplot->close();
    1206       delete(tecplot);
    1207     }
    1208     if (DoRaster3DOutput) {
    1209       string OutputName(filename);
    1210       OutputName.append(Raster3DSuffix);
    1211       ofstream *raster = new ofstream(OutputName.c_str());
    1212       WriteRaster3dFile(out, raster, mol->TesselStruct, mol);
    1213       raster->close();
    1214       delete(raster);
    1215     }
    1216   } else {
    1217     cerr << "ERROR: Could definitively not find all necessary triangles!" << endl;
    1218   }
    1219 
    1220   cout << Verbose(2) << "Check: List of Baselines with not two connected triangles:" << endl;
    1221   int counter = 0;
    1222   for (testline = mol->TesselStruct->LinesOnBoundary.begin(); testline != mol->TesselStruct->LinesOnBoundary.end(); testline++) {
    1223     if (testline->second->triangles.size() != 2) {
    1224       cout << Verbose(2) << *testline->second << "\t" << testline->second->triangles.size() << endl;
    1225       counter++;
    1226     }
    1227   }
    1228   if (counter == 0)
    1229     *out << Verbose(2) << "None." << endl;
    1230 
    1231 //  // Tests the IsInnerAtom() function.
    1232 //  Vector x (0, 0, 0);
    1233 //  *out << Verbose(0) << "Point to check: " << x << endl;
    1234 //  *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, x, LCList)
    1235 //    << "for vector " << x << "." << endl;
    1236 //  TesselPoint* a = mol->TesselStruct->PointsOnBoundary.begin()->second->node;
    1237 //  *out << Verbose(0) << "Point to check: " << *a << " (on boundary)." << endl;
    1238 //  *out << Verbose(0) << "Check: IsInnerAtom() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList)
    1239 //    << "for atom " << a << " (on boundary)." << endl;
    1240 //  LinkedNodes *List = NULL;
    1241 //  for (int i=0;i<NDIM;i++) { // each axis
    1242 //    LCList->n[i] = LCList->N[i]-1; // current axis is topmost cell
    1243 //    for (LCList->n[(i+1)%NDIM]=0;LCList->n[(i+1)%NDIM]<LCList->N[(i+1)%NDIM];LCList->n[(i+1)%NDIM]++)
    1244 //      for (LCList->n[(i+2)%NDIM]=0;LCList->n[(i+2)%NDIM]<LCList->N[(i+2)%NDIM];LCList->n[(i+2)%NDIM]++) {
    1245 //        List = LCList->GetCurrentCell();
    1246 //        //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl;
    1247 //        if (List != NULL) {
    1248 //          for (LinkedNodes::iterator Runner = List->begin();Runner != List->end();Runner++) {
    1249 //            if (mol->TesselStruct->PointsOnBoundary.find((*Runner)->nr) == mol->TesselStruct->PointsOnBoundary.end()) {
    1250 //              a = *Runner;
    1251 //              i=3;
    1252 //              for (int j=0;j<NDIM;j++)
    1253 //                LCList->n[j] = LCList->N[j];
    1254 //              break;
    1255 //            }
    1256 //          }
    1257 //        }
    1258 //      }
    1259 //  }
    1260 //  *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList)
    1261 //    << "for atom " << a << " (inside)." << endl;
     1053  CalculateConcavityPerBoundaryPoint(out, mol->TesselStruct);
     1054  StoreTrianglesinFile(out, mol, filename, "");
    12621055
    12631056  if (freeLC)
     
    12651058  *out << Verbose(0) << "End of FindNonConvexBorder\n";
    12661059};
     1060
    12671061
    12681062/** Finds a hole of sufficient size in \a this molecule to embed \a *srcmol into it.
  • src/boundary.hpp

    rc0917c ra33931  
    1616
    1717#define DEBUG 1
    18 #define DoSingleStepOutput 0
     18#define DoSingleStepOutput 1
    1919#define SingleStepWidth 1
    20 #define DoTecplotOutput 1
    21 #define DoRaster3DOutput 1
    22 #define DoVRMLOutput 1
    23 #define TecplotSuffix ".dat"
    24 #define Raster3DSuffix ".r3d"
    25 #define VRMLSUffix ".wrl"
    2620
    2721#define DistancePair pair < double, atom* >
     
    3832molecule * FillBoxWithMolecule(ofstream *out, MoleculeListClass *List, molecule *filler, config &configuration, double distance[NDIM], double RandAtomDisplacement, double RandMolDisplacement, bool DoRandomRotation);
    3933void FindConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename);
    40 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LC, const char *tempbasename, const double RADIUS);
     34void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LC, const double RADIUS, const char *tempbasename);
    4135double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename);
    4236void FindNextSuitablePoint(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC);
    4337Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol);
    44 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct);
    4538void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix);
     39bool RemoveAllBoundaryPoints(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename);
    4640
    4741
  • src/builder.cpp

    rc0917c ra33931  
    10181018      cin >> nr;
    10191019      count = 1;
    1020       for( MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
     1020      for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++)
    10211021        if (nr == (*ListRunner)->IndexNr) {
    10221022          mol = *ListRunner;
    10231023          molecules->ListOfMolecules.erase(ListRunner);
    10241024          delete(mol);
     1025          break;
    10251026        }
    10261027      break;
     
    10751076
    10761077    case 'e':
    1077       cout << Verbose(0) << "Not implemented yet." << endl;
     1078      {
     1079        int src, dest;
     1080        molecule *srcmol = NULL, *destmol = NULL;
     1081        do {
     1082          cout << Verbose(0) << "Enter index of matrix molecule (the variable one): ";
     1083          cin >> src;
     1084          srcmol = molecules->ReturnIndex(src);
     1085        } while ((srcmol == NULL) && (src != -1));
     1086        do {
     1087          cout << Verbose(0) << "Enter index of molecule to merge into (the fixed one): ";
     1088          cin >> dest;
     1089          destmol = molecules->ReturnIndex(dest);
     1090        } while ((destmol == NULL) && (dest != -1));
     1091        if ((src != -1) && (dest != -1))
     1092          molecules->EmbedMerge(destmol, srcmol);
     1093      }
    10781094      break;
    10791095
     
    16261642                cout << Verbose(0) << "Evaluating non-convex envelope.";
    16271643                cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl;
    1628                 start = clock();
     1644                start = clock();
    16291645                LinkedCell LCList(mol, atof(argv[argptr])*2.);
    1630                 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr+1], atof(argv[argptr]));
     1646                FindNonConvexBorder((ofstream *)&cout, mol, &LCList, atof(argv[argptr]), argv[argptr+1]);
    16311647                //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str());
    1632                 end = clock();
    1633                 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
     1648                end = clock();
     1649                cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl;
    16341650                argptr+=2;
    16351651              }
     
    16541670            case 'L':
    16551671              ExitFlag = 1;
    1656               SaveFlag = true;
    1657               cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
    1658               if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration))
    1659                 cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
    1660               else
    1661                 cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
    1662               argptr+=3;
     1672              if ((argptr >= argc) || (argv[argptr][0] == '-')) {
     1673                ExitFlag = 255;
     1674                cerr << "Not enough or invalid arguments given for storing tempature: -L <step0> <step1> <prefix> <identity mapping?>" << endl;
     1675              } else {
     1676                SaveFlag = true;
     1677                cout << Verbose(1) << "Linear interpolation between configuration " << argv[argptr] << " and " << argv[argptr+1] << "." << endl;
     1678                if (atoi(argv[argptr+3]) == 1)
     1679                  cout << Verbose(1) << "Using Identity for the permutation map." << endl;
     1680                if (!mol->LinearInterpolationBetweenConfiguration((ofstream *)&cout, atoi(argv[argptr]), atoi(argv[argptr+1]), argv[argptr+2], configuration, atoi(argv[argptr+3])) == 1 ? true : false)
     1681                  cout << Verbose(2) << "Could not store " << argv[argptr+2] << " files." << endl;
     1682                else
     1683                  cout << Verbose(2) << "Steps created and " << argv[argptr+2] << " files stored." << endl;
     1684                argptr+=4;
     1685              }
    16631686              break;
    16641687            case 'P':
     
    17101733                ExitFlag = 1;
    17111734                SaveFlag = true;
    1712                 cout << Verbose(1) << "Translating all ions to new origin." << endl;
     1735                cout << Verbose(1) << "Translating all ions by given vector." << endl;
    17131736                for (int i=NDIM;i--;)
    17141737                  x.x[i] = atof(argv[argptr+i]);
     
    17161739                argptr+=3;
    17171740              }
     1741              break;
    17181742            case 'T':
    17191743              ExitFlag = 1;
     
    17241748                ExitFlag = 1;
    17251749                SaveFlag = true;
    1726                 cout << Verbose(1) << "Translating all ions periodically to new origin." << endl;
     1750                cout << Verbose(1) << "Translating all ions periodically by given vector." << endl;
    17271751                for (int i=NDIM;i--;)
    17281752                  x.x[i] = atof(argv[argptr+i]);
     
    18651889            case 'o':
    18661890              ExitFlag = 1;
    1867               if ((argptr >= argc) || (argv[argptr][0] == '-')){
     1891              if ((argptr+1 >= argc) || (argv[argptr][0] == '-')){
    18681892                ExitFlag = 255;
    1869                 cerr << "Not enough or invalid arguments given for convex envelope: -o <tecplot output file>" << endl;
     1893                cerr << "Not enough or invalid arguments given for convex envelope: -o <convex output file> <non-convex output file>" << endl;
    18701894              } else {
    18711895                cout << Verbose(0) << "Evaluating volume of the convex envelope.";
    1872                 cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
     1896                cout << Verbose(1) << "Storing tecplot convex data in " << argv[argptr] << "." << endl;
     1897                cout << Verbose(1) << "Storing tecplot non-convex data in " << argv[argptr+1] << "." << endl;
    18731898                LinkedCell LCList(mol, 10.);
    18741899                //FindConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr]);
    1875                 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, argv[argptr], 10.);
    1876 
     1900                FindNonConvexBorder((ofstream *)&cout, mol, &LCList, 5., argv[argptr+1]);
     1901//                RemoveAllBoundaryPoints((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
    18771902                double volumedifference = ConvexizeNonconvexEnvelope((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]);
    18781903                double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, mol->TesselStruct, &configuration);
    18791904                cout << Verbose(0) << "The tesselated volume area is " << clustervolume << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
    18801905                cout << Verbose(0) << "The non-convex tesselated volume area is " << clustervolume-volumedifference << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
    1881                 argptr+=1;
     1906                argptr+=2;
    18821907              }
    18831908              break;
  • src/config.cpp

    rc0917c ra33931  
    10111011      repetition--;
    10121012      cout << "Found " << repetition << " trajectory steps." << endl;
    1013       mol->MDSteps = repetition;
     1013      if (repetition <= 1)  // if onyl one step, desactivate use of trajectories
     1014        mol->MDSteps = 0;
     1015      else
     1016        mol->MDSteps = repetition;
    10141017    } else {
    10151018      // find the maximum number of MD steps so that we may parse last one (Ion_Type1_1 must always be present, because is the first atom)
  • src/linkedcell.cpp

    rc0917c ra33931  
    9696    //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    9797    set->GoToNext();
     98  }
     99  cout << "done."  << endl;
     100  cout << Verbose(1) << "End of LinkedCell" << endl;
     101};
     102
     103
     104/** Puts all atoms in \a *mol into a linked cell list with cell's lengths of \a RADIUS
     105 * \param *set LCNodeSet class with all LCNode's
     106 * \param RADIUS edge length of cells
     107 */
     108LinkedCell::LinkedCell(LinkedNodes *set, double radius)
     109{
     110  class TesselPoint *Walker = NULL;
     111  RADIUS = radius;
     112  LC = NULL;
     113  for(int i=0;i<NDIM;i++)
     114    N[i] = 0;
     115  index = -1;
     116  max.Zero();
     117  min.Zero();
     118  cout << Verbose(1) << "Begin of LinkedCell" << endl;
     119  if (set->empty()) {
     120    cerr << "ERROR: set contains no linked cell nodes!" << endl;
     121    return;
     122  }
     123  // 1. find max and min per axis of atoms
     124  LinkedNodes::iterator Runner = set->begin();
     125  for (int i=0;i<NDIM;i++) {
     126    max.x[i] = (*Runner)->node->x[i];
     127    min.x[i] = (*Runner)->node->x[i];
     128  }
     129  for (LinkedNodes::iterator Runner = set->begin(); Runner != set->end(); Runner++) {
     130    Walker = *Runner;
     131    for (int i=0;i<NDIM;i++) {
     132      if (max.x[i] < Walker->node->x[i])
     133        max.x[i] = Walker->node->x[i];
     134      if (min.x[i] > Walker->node->x[i])
     135        min.x[i] = Walker->node->x[i];
     136    }
     137  }
     138  cout << Verbose(2) << "Bounding box is " << min << " and " << max << "." << endl;
     139
     140  // 2. find then number of cells per axis
     141  for (int i=0;i<NDIM;i++) {
     142    N[i] = (int)floor((max.x[i] - min.x[i])/RADIUS)+1;
     143  }
     144  cout << Verbose(2) << "Number of cells per axis are " << N[0] << ", " << N[1] << " and " << N[2] << "." << endl;
     145
     146  // 3. allocate the lists
     147  cout << Verbose(2) << "Allocating cells ... ";
     148  if (LC != NULL) {
     149    cout << Verbose(1) << "ERROR: Linked Cell list is already allocated, I do nothing." << endl;
     150    return;
     151  }
     152  LC = new LinkedNodes[N[0]*N[1]*N[2]];
     153  for (index=0;index<N[0]*N[1]*N[2];index++) {
     154    LC [index].clear();
     155  }
     156  cout << "done."  << endl;
     157
     158  // 4. put each atom into its respective cell
     159  cout << Verbose(2) << "Filling cells ... ";
     160  for (LinkedNodes::iterator Runner = set->begin(); Runner != set->end(); Runner++) {
     161    Walker = *Runner;
     162    for (int i=0;i<NDIM;i++) {
     163      n[i] = (int)floor((Walker->node->x[i] - min.x[i])/RADIUS);
     164    }
     165    index = n[0] * N[1] * N[2] + n[1] * N[2] + n[2];
     166    LC[index].push_back(Walker);
     167    //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl;
    98168  }
    99169  cout << "done."  << endl;
  • src/linkedcell.hpp

    rc0917c ra33931  
    4444    LinkedCell();
    4545    LinkedCell(PointCloud *set, double RADIUS);
     46    LinkedCell(LinkedNodes *set, double radius);
    4647    ~LinkedCell();
    4748    LinkedNodes* GetCurrentCell();
  • src/moleculelist.cpp

    rc0917c ra33931  
    55 */
    66
     7#include "boundary.hpp"
    78#include "config.hpp"
    89#include "molecules.hpp"
     
    292293/** Embedding merge of a given set of molecules into one.
    293294 * Embedding merge inserts one molecule into the other.
    294  * \param *mol destination molecule
    295  * \param *srcmol source molecule
    296  * \return true - merge successful, false - merge failed (probably due to non-existant indices
    297  * \TODO find embedding center
     295 * \param *mol destination molecule (fixed one)
     296 * \param *srcmol source molecule (variable one, where atoms are taken from)
     297 * \return true - merge successful, false - merge failed (probably due to non-existant indices)
     298 * \TODO linked cell dimensions for boundary points has to be as big as inner diameter!
    298299 */
    299300bool MoleculeListClass::EmbedMerge(molecule *mol, molecule *srcmol)
    300301{
    301   if (srcmol == NULL)
     302  if ((srcmol == NULL) || (mol == NULL)) {
     303    cout << Verbose(1) << "ERROR: Either fixed or variable molecule is given as NULL." << endl;
    302304    return false;
    303 
    304   // calculate center for merge
    305   srcmol->Center.CopyVector(mol->FindEmbeddingHole((ofstream *)&cout, srcmol));
    306   srcmol->Center.Zero();
    307 
    308   // perform simple merge
    309   SimpleMerge(mol, srcmol);
     305  }
     306
     307  // calculate envelope for *mol
     308  LinkedCell *LCList = new LinkedCell(mol, 8.);
     309  FindNonConvexBorder((ofstream *)&cout, mol, LCList, 4., NULL);
     310  if (mol->TesselStruct == NULL) {
     311    cout << Verbose(1) << "ERROR: Could not tesselate the fixed molecule." << endl;
     312    return false;
     313  }
     314  delete(LCList);
     315  LCList = new LinkedCell(mol->TesselStruct, 8.);  // re-create with boundary points only!
     316
     317  // prepare index list for bonds
     318  srcmol->CountAtoms((ofstream *)&cout);
     319  atom ** CopyAtoms = new atom*[srcmol->AtomCount];
     320  for(int i=0;i<srcmol->AtomCount;i++)
     321    CopyAtoms[i] = NULL;
     322
     323  // for each of the source atoms check whether we are in- or outside and add copy atom
     324  atom *Walker = srcmol->start;
     325  int nr=0;
     326  while (Walker->next != srcmol->end) {
     327    Walker = Walker->next;
     328    cout << Verbose(2) << "INFO: Current Walker is " << *Walker << "." << endl;
     329    if (!mol->TesselStruct->IsInnerPoint((ofstream *)&cout, Walker->x, LCList)) {
     330      CopyAtoms[Walker->nr] = new atom(Walker);
     331      mol->AddAtom(CopyAtoms[Walker->nr]);
     332      nr++;
     333    } else {
     334      // do nothing
     335    }
     336  }
     337  cout << Verbose(1) << nr << " of " << srcmol->AtomCount << " atoms have been merged.";
     338
     339  // go through all bonds and add as well
     340  bond *Binder = srcmol->first;
     341  while(Binder->next != srcmol->last) {
     342    Binder = Binder->next;
     343    cout << Verbose(3) << "Adding Bond between " << *CopyAtoms[Binder->leftatom->nr] << " and " << *CopyAtoms[Binder->rightatom->nr]<< "." << endl;
     344    mol->AddBond(CopyAtoms[Binder->leftatom->nr], CopyAtoms[Binder->rightatom->nr], Binder->BondDegree);
     345  }
     346  delete(LCList);
    310347  return true;
    311348};
  • src/molecules.cpp

    rc0917c ra33931  
    687687{
    688688  int length = 0;
    689   char *molname = strrchr(filename, '/')+sizeof(char);  // search for filename without dirs
     689  const char *molname = strrchr(filename, '/');
     690  if (molname != NULL)
     691    molname += sizeof(char);  // search for filename without dirs
     692  else
     693    molname = filename; // contains no slashes
    690694  char *endname = strchr(molname, '.');
    691695  if ((endname == NULL) || (endname < molname))
     
    11931197/** Evaluates the potential energy used for constrained molecular dynamics.
    11941198 * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \frac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$
    1195  *     where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}$ is minimum distance between
     1199 *     where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}\f$ is minimum distance between
    11961200 *     trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.
    11971201 * Note that for the second term we have to solve the following linear system:
     
    15871591 * \param endstep stating final configuration in molecule::Trajectories
    15881592 * \param &config configuration structure
     1593 * \param MapByIdentity if true we just use the identity to map atoms in start config to end config, if not we find mapping by \sa MinimiseConstrainedPotential()
    15891594 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories
    15901595 */
    1591 bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration)
     1596bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration, bool MapByIdentity)
    15921597{
    15931598  molecule *mol = NULL;
     
    15981603  atom **PermutationMap = NULL;
    15991604  atom *Walker = NULL, *Sprinter = NULL;
    1600   MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
     1605  if (!MapByIdentity)
     1606    MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());
     1607  else {
     1608    PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::LinearInterpolationBetweenConfiguration: **PermutationMap");
     1609    Walker = start;
     1610    while (Walker->next != end) {
     1611      Walker = Walker->next;
     1612      PermutationMap[Walker->nr] = Walker;   // always pick target with the smallest distance
     1613    }
     1614  }
    16011615
    16021616  // check whether we have sufficient space in Trajectories for each atom
     
    37473761 * \param *&SortIndex Mapping array of size molecule::AtomCount
    37483762 * \return true - success, false - failure of SortIndex alloc
     3763 * \todo do we really need this still as the IonType may appear in any order due to recent changes
    37493764 */
    37503765bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex)
  • src/molecules.hpp

    rc0917c ra33931  
    182182  double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem);
    183183  void EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force);
    184   bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration);
     184  bool LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration, bool MapByIdentity);
    185185       
    186186  bool CheckBounds(const Vector *x) const;
  • src/tesselation.cpp

    rc0917c ra33931  
    66 */
    77
     8#include "helpers.hpp"
     9#include "linkedcell.hpp"
     10#include "memoryallocator.hpp"
    811#include "tesselation.hpp"
    9 #include "memoryallocator.hpp"
     12#include "tesselationhelpers.hpp"
     13#include "vector.hpp"
     14
     15class molecule;
    1016
    1117// ======================================== Points on Boundary =================================
     
    3743BoundaryPointSet::~BoundaryPointSet()
    3844{
    39   cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
     45  //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;
    4046  if (!lines.empty())
    4147    cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl;
     
    6773ostream & operator <<(ostream &ost, BoundaryPointSet &a)
    6874{
    69   ost << "[" << a.Nr << "|" << a.node->Name << "]";
     75  ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]";
    7076  return ost;
    7177}
     
    125131        for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++)
    126132          if ((*Runner).second == this) {
    127             cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     133            //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
    128134            endpoints[i]->lines.erase(Runner);
    129135            break;
    130136          }
    131137      } else { // there's just a single line left
    132         if (endpoints[i]->lines.erase(Nr))
    133           cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     138        if (endpoints[i]->lines.erase(Nr)) {
     139          //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;
     140        }
    134141      }
    135142      if (endpoints[i]->lines.empty()) {
    136         cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
     143        //cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    137144        if (endpoints[i] != NULL) {
    138145          delete(endpoints[i]);
     
    168175
    169176/** Checks whether the adjacent triangles of a baseline are convex or not.
    170  * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.
     177 * We sum the two angles of each height vector with respect to the center of the baseline.
    171178 * If greater/equal M_PI than we are convex.
    172179 * \param *out output stream for debugging
     
    178185  // get the two triangles
    179186  if (triangles.size() != 2) {
    180     *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect to less than two triangles, Tesselation incomplete!" << endl;
     187    *out << Verbose(1) << "ERROR: Baseline " << *this << " is connected to less than two triangles, Tesselation incomplete!" << endl;
    181188    return true;
    182189  }
     
    201208    NormalCheck.Scale(sign);
    202209    sign = -sign;
    203     BaseLineNormal.SubtractVector(&runner->second->NormalVector);   // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi]
     210    if (runner->second->NormalVector.NormSquared() > MYEPSILON)
     211      BaseLineNormal.CopyVector(&runner->second->NormalVector);   // yes, copy second on top of first
     212    else {
     213      *out << Verbose(1) << "CRITICAL: Triangle " << *runner->second << " has zero normal vector!" << endl;
     214      exit(255);
     215    }
    204216    node = runner->second->GetThirdEndpoint(this);
    205217    if (node != NULL) {
     
    211223      i++;
    212224    } else {
    213       //*out << Verbose(2) << "WARNING: I cannot find third node in triangle, something's wrong." << endl;
     225      //*out << Verbose(2) << "ERROR: I cannot find third node in triangle, something's wrong." << endl;
    214226      return true;
    215227    }
     
    217229  //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl;
    218230  if (NormalCheck.NormSquared() < MYEPSILON) {
    219     *out << Verbose(2) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;
     231    *out << Verbose(3) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;
    220232    return true;
    221233  }
     234  BaseLineNormal.Scale(-1.);
    222235  double angle = GetAngle(helper[0], helper[1], BaseLineNormal);
    223236  if ((angle - M_PI) > -MYEPSILON) {
    224     *out << Verbose(2) << "ACCEPT: Angle is greater than pi: convex." << endl;
     237    *out << Verbose(3) << "ACCEPT: Angle is greater than pi: convex." << endl;
    225238    return true;
    226239  } else {
    227     *out << Verbose(2) << "REJECT: Angle is less than pi: concave." << endl;
     240    *out << Verbose(3) << "REJECT: Angle is less than pi: concave." << endl;
    228241    return false;
    229242  }
     
    262275ostream & operator <<(ostream &ost, BoundaryLineSet &a)
    263276{
    264   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]";
     277  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << "," << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "]";
    265278  return ost;
    266279};
     
    332345  for (int i = 0; i < 3; i++) {
    333346    if (lines[i] != NULL) {
    334       if (lines[i]->triangles.erase(Nr))
    335         cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl;
     347      if (lines[i]->triangles.erase(Nr)) {
     348        //cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl;
     349      }
    336350      if (lines[i]->triangles.empty()) {
    337           cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
     351          //cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;
    338352          delete (lines[i]);
    339353          lines[i] = NULL;
     
    341355    }
    342356  }
    343   cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;
     357  //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;
    344358};
    345359
     
    361375 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane
    362376 * This we test if it's really on the plane and whether it's inside the triangle on the plane or not.
    363  * The latter is done as follows: if it's really outside, then for any endpoint of the triangle and it's opposite
    364  * base line, the intersection between the line from endpoint to intersection and the base line will have a Vector::NormSquared()
    365  * smaller than the first line.
     377 * The latter is done as follows: We calculate the cross point of one of the triangle's baseline with the line
     378 * given by the intersection and the third basepoint. Then, we check whether it's on the baseline (i.e. between
     379 * the first two basepoints) or not.
    366380 * \param *out output stream for debugging
    367381 * \param *MolCenter offset vector of line
     
    395409    exit(255);
    396410  }
    397   CrossPoint.SubtractVector(endpoints[i%3]->node->node);
     411  CrossPoint.SubtractVector(endpoints[i%3]->node->node);  // cross point was returned as absolute vector
    398412
    399413  // check whether intersection is inside or not by comparing length of intersection and length of cross point
    400   if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside
     414  if ((CrossPoint.NormSquared() - helper.NormSquared()) < MYEPSILON) { // inside
    401415    return true;
    402416  } else { // outside!
     
    426440  for(int i=0;i<3;i++)
    427441    if (point == endpoints[i])
     442      return true;
     443  return false;
     444};
     445
     446/** Checks whether point is any of the three endpoints this triangle contains.
     447 * \param *point TesselPoint to test
     448 * \return true - point is of the triangle, false - is not
     449 */
     450bool BoundaryTriangleSet::ContainsBoundaryPoint(class TesselPoint *point)
     451{
     452  for(int i=0;i<3;i++)
     453    if (point == endpoints[i]->node)
    428454      return true;
    429455  return false;
     
    451477};
    452478
     479/** Checks whether three given \a *Points coincide with triangle's endpoints.
     480 * \param *Points[3] pointer to BoundaryPointSet
     481 * \return true - is the very triangle, false - is not
     482 */
     483bool BoundaryTriangleSet::IsPresentTupel(class BoundaryTriangleSet *T)
     484{
     485  return (((endpoints[0] == T->endpoints[0])
     486            || (endpoints[0] == T->endpoints[1])
     487            || (endpoints[0] == T->endpoints[2])
     488          ) && (
     489            (endpoints[1] == T->endpoints[0])
     490            || (endpoints[1] == T->endpoints[1])
     491            || (endpoints[1] == T->endpoints[2])
     492          ) && (
     493            (endpoints[2] == T->endpoints[0])
     494            || (endpoints[2] == T->endpoints[1])
     495            || (endpoints[2] == T->endpoints[2])
     496
     497          ));
     498};
     499
    453500/** Returns the endpoint which is not contained in the given \a *line.
    454501 * \param *line baseline defining two endpoints
     
    485532ostream &operator <<(ostream &ost, BoundaryTriangleSet &a)
    486533{
    487   ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << ","
    488       << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]";
     534  ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << ","
     535      << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "," << a.endpoints[2]->node->Name << " at " << *a.endpoints[2]->node->node << "]";
    489536  return ost;
    490537};
     
    505552TesselPoint::~TesselPoint()
    506553{
    507   Free(&Name);
     554  Free<char *>(&Name, "~TesselPoint - *Name");
    508555};
    509556
     
    512559ostream & operator << (ostream &ost, const TesselPoint &a)
    513560{
    514   ost << "[" << (a.Name) << "|" << &a << "]";
     561  ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node << "]";
    515562  return ost;
    516563};
     
    569616  TrianglesOnBoundaryCount = 0;
    570617  InternalPointer = PointsOnBoundary.begin();
     618  LastTriangle = NULL;
     619  TriangleFilesWritten = 0;
    571620}
    572621;
     
    585634      cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl;
    586635  }
     636  cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl;
    587637}
    588638;
     
    10521102  Vector *Center = cloud->GetCenter(out);
    10531103  list<BoundaryTriangleSet*> *triangles = NULL;
     1104  bool AddFlag = false;
     1105  LinkedCell *BoundaryPoints = NULL;
    10541106
    10551107  *out << Verbose(1) << "Begin of InsertStraddlingPoints" << endl;
    10561108
    10571109  cloud->GoToFirst();
     1110  BoundaryPoints = new LinkedCell(this, 5.);
    10581111  while (!cloud->IsEnd()) {  // we only have to go once through all points, as boundary can become only bigger
    1059     LinkedCell BoundaryPoints(this, 5.);
     1112    if (AddFlag) {
     1113      delete(BoundaryPoints);
     1114      BoundaryPoints = new LinkedCell(this, 5.);
     1115      AddFlag = false;
     1116    }
    10601117    Walker = cloud->GetPoint();
    10611118    *out << Verbose(2) << "Current point is " << *Walker << "." << endl;
    10621119    // get the next triangle
    1063     triangles = FindClosestTrianglesToPoint(out, Walker->node, &BoundaryPoints);
    1064     if (triangles == NULL) {
    1065       *out << Verbose(1) << "No triangles found, probably a tesselation point itself." << endl;
     1120    triangles = FindClosestTrianglesToPoint(out, Walker->node, BoundaryPoints);
     1121    BTS = triangles->front();
     1122    if ((triangles == NULL) || (BTS->ContainsBoundaryPoint(Walker))) {
     1123      *out << Verbose(2) << "No triangles found, probably a tesselation point itself." << endl;
    10661124      cloud->GoToNext();
    10671125      continue;
    10681126    } else {
    1069       BTS = triangles->front();
    10701127    }
    10711128    *out << Verbose(2) << "Closest triangle is " << *BTS << "." << endl;
     
    10901147        // add Walker to boundary points
    10911148        *out << Verbose(2) << "Adding " << *Walker << " to BoundaryPoints." << endl;
     1149        AddFlag = true;
    10921150        if (AddBoundaryPoint(Walker,0))
    10931151          NewPoint = BPS[0];
     
    11801238  } else {
    11811239    delete TPS[n];
    1182     cout << Verbose(3) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;
     1240    cout << Verbose(4) << "Node " << *((InsertUnique.first)->second->node) << " is already present in PointsOnBoundary." << endl;
    11831241    TPS[n] = (InsertUnique.first)->second;
    11841242  }
     
    11971255
    11981256  if (a->lines.find(b->node->nr) != a->lines.end()) {
    1199     LineMap::iterator FindLine;
     1257    LineMap::iterator FindLine = a->lines.find(b->node->nr);
    12001258    pair<LineMap::iterator,LineMap::iterator> FindPair;
    12011259    FindPair = a->lines.equal_range(b->node->nr);
    1202 
    1203     for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
     1260    cout << Verbose(5) << "INFO: There is at least one line between " << *a << " and " << *b << ": " << *(FindLine->second) << "." << endl;
     1261
     1262    for (FindLine = FindPair.first; FindLine != FindPair.second; FindLine++) {
    12041263      // If there is a line with less than two attached triangles, we don't need a new line.
    12051264      if (FindLine->second->triangles.size() < 2) {
    12061265        insertNewLine = false;
    1207         cout << Verbose(3) << "Using existing line " << *FindLine->second << endl;
     1266        cout << Verbose(4) << "Using existing line " << *FindLine->second << endl;
    12081267
    12091268        BPS[0] = FindLine->second->endpoints[0];
     
    12321291void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n)
    12331292{
    1234   cout << Verbose(3) << "Adding line between " << *(a->node) << " and " << *(b->node) << "." << endl;
     1293  cout << Verbose(4) << "Adding line [" << LinesOnBoundaryCount << "|" << *(a->node) << " and " << *(b->node) << "." << endl;
    12351294  BPS[0] = a;
    12361295  BPS[1] = b;
     
    12421301};
    12431302
    1244 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm).
    1245  * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later.
     1303/** Function adds triangle to global list.
     1304 * Furthermore, the triangle receives the next free id and id counter \a TrianglesOnBoundaryCount is increased.
    12461305 */
    12471306void Tesselation::AddTesselationTriangle()
     
    12521311  TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS));
    12531312  TrianglesOnBoundaryCount++;
     1313
     1314  // set as last new triangle
     1315  LastTriangle = BTS;
     1316
     1317  // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet
     1318};
     1319
     1320/** Function adds triangle to global list.
     1321 * Furthermore, the triangle number is set to \a nr.
     1322 * \param nr triangle number
     1323 */
     1324void Tesselation::AddTesselationTriangle(int nr)
     1325{
     1326  cout << Verbose(1) << "Adding triangle to global TrianglesOnBoundary map." << endl;
     1327
     1328  // add triangle to global map
     1329  TrianglesOnBoundary.insert(TrianglePair(nr, BTS));
     1330
     1331  // set as last new triangle
     1332  LastTriangle = BTS;
    12541333
    12551334  // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet
     
    12721351          cout << Verbose(5) << *triangle->lines[i] << " is no more attached to any triangle, erasing." << endl;
    12731352          RemoveTesselationLine(triangle->lines[i]);
    1274           triangle->lines[i] = NULL;
    1275       } else
    1276         cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle." << endl;
     1353      } else {
     1354        cout << Verbose(5) << *triangle->lines[i] << " is still attached to another triangle: ";
     1355        for(TriangleMap::iterator TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); TriangleRunner++)
     1356          cout << "[" << (TriangleRunner->second)->Nr << "|" << *((TriangleRunner->second)->endpoints[0]) << ", " << *((TriangleRunner->second)->endpoints[1]) << ", " << *((TriangleRunner->second)->endpoints[2]) << "] \t";
     1357        cout << endl;
     1358//        for (int j=0;j<2;j++) {
     1359//          cout << Verbose(5) << "Lines of endpoint " << *(triangle->lines[i]->endpoints[j]) << ": ";
     1360//          for(LineMap::iterator LineRunner = triangle->lines[i]->endpoints[j]->lines.begin(); LineRunner != triangle->lines[i]->endpoints[j]->lines.end(); LineRunner++)
     1361//            cout << "[" << *(LineRunner->second) << "] \t";
     1362//          cout << endl;
     1363//        }
     1364      }
     1365      triangle->lines[i] = NULL;  // free'd or not: disconnect
    12771366    } else
    12781367      cerr << "ERROR: This line " << i << " has already been free'd." << endl;
     
    12941383  if (line == NULL)
    12951384    return;
    1296   // get other endpoint number of finding copies of same line
     1385  // get other endpoint number for finding copies of same line
    12971386  if (line->endpoints[1] != NULL)
    12981387    Numbers[0] = line->endpoints[1]->Nr;
     
    13211410        cout << Verbose(5) << *line->endpoints[i] << " has no more lines it's attached to, erasing." << endl;
    13221411        RemoveTesselationPoint(line->endpoints[i]);
    1323         line->endpoints[i] = NULL;
    1324       } else
    1325         cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to." << endl;
     1412      } else {
     1413        cout << Verbose(5) << *line->endpoints[i] << " has still lines it's attached to: ";
     1414        for(LineMap::iterator LineRunner = line->endpoints[i]->lines.begin(); LineRunner != line->endpoints[i]->lines.end(); LineRunner++)
     1415          cout << "[" << *(LineRunner->second) << "] \t";
     1416        cout << endl;
     1417      }
     1418      line->endpoints[i] = NULL;  // free'd or not: disconnect
    13261419    } else
    13271420      cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl;
     
    13901483          }
    13911484          // Only one of the triangle lines must be considered for the triangle count.
    1392           *out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
    1393           return adjacentTriangleCount;
     1485          //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
     1486          //return adjacentTriangleCount;
    13941487        }
    13951488      }
     
    14001493  *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl;
    14011494  return adjacentTriangleCount;
     1495};
     1496
     1497/** Checks whether the triangle consisting of the three points is already present.
     1498 * Searches for the points in Tesselation::PointsOnBoundary and checks their
     1499 * lines. If any of the three edges already has two triangles attached, false is
     1500 * returned.
     1501 * \param *out output stream for debugging
     1502 * \param *Candidates endpoints of the triangle candidate
     1503 * \return NULL - none found or pointer to triangle
     1504 */
     1505class BoundaryTriangleSet * Tesselation::GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3])
     1506{
     1507  class BoundaryTriangleSet *triangle = NULL;
     1508  class BoundaryPointSet *Points[3];
     1509
     1510  // builds a triangle point set (Points) of the end points
     1511  for (int i = 0; i < 3; i++) {
     1512    PointMap::iterator FindPoint = PointsOnBoundary.find(Candidates[i]->nr);
     1513    if (FindPoint != PointsOnBoundary.end()) {
     1514      Points[i] = FindPoint->second;
     1515    } else {
     1516      Points[i] = NULL;
     1517    }
     1518  }
     1519
     1520  // checks lines between the points in the Points for their adjacent triangles
     1521  for (int i = 0; i < 3; i++) {
     1522    if (Points[i] != NULL) {
     1523      for (int j = i; j < 3; j++) {
     1524        if (Points[j] != NULL) {
     1525          LineMap::iterator FindLine = Points[i]->lines.find(Points[j]->node->nr);
     1526          for (; (FindLine != Points[i]->lines.end()) && (FindLine->first == Points[j]->node->nr); FindLine++) {
     1527            TriangleMap *triangles = &FindLine->second->triangles;
     1528            for (TriangleMap::iterator FindTriangle = triangles->begin(); FindTriangle != triangles->end(); FindTriangle++) {
     1529              if (FindTriangle->second->IsPresentTupel(Points)) {
     1530                if ((triangle == NULL) || (triangle->Nr > FindTriangle->second->Nr))
     1531                  triangle = FindTriangle->second;
     1532              }
     1533            }
     1534          }
     1535          // Only one of the triangle lines must be considered for the triangle count.
     1536          //*out << Verbose(2) << "Found " << adjacentTriangleCount << " adjacent triangles for the point set." << endl;
     1537          //return adjacentTriangleCount;
     1538        }
     1539      }
     1540    }
     1541  }
     1542
     1543  return triangle;
    14021544};
    14031545
     
    14611603  CandidateList *OptCandidates = new CandidateList();
    14621604  for (int k=0;k<NDIM;k++) {
     1605    Oben.Zero();
    14631606    Oben.x[k] = 1.;
    14641607    FirstPoint = MaxPoint[k];
     
    14691612    ShortestAngle = 999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant.
    14701613
    1471     FindSecondPointForTesselation(FirstPoint, NULL, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
     1614    FindSecondPointForTesselation(FirstPoint, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...
    14721615    SecondPoint = OptCandidate;
    14731616    if (SecondPoint == NULL)  // have we found a second point?
    14741617      continue;
    1475     else
    1476       cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";
    14771618
    14781619    helper.CopyVector(FirstPoint->node);
     
    14961637
    14971638    // adding point 1 and point 2 and add the line between them
     1639    cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl;
    14981640    AddTesselationPoint(FirstPoint, 0);
     1641    cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";
    14991642    AddTesselationPoint(SecondPoint, 1);
    15001643    AddTesselationLine(TPS[0], TPS[1], 0);
     
    15691712 * @param *LC LinkedCell structure with neighbouring points
    15701713 */
    1571 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC)
     1714bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC)
    15721715{
    15731716  cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n";
     
    16041747    CircleRadius = RADIUS*RADIUS - radius/4.;
    16051748    CirclePlaneNormal.Normalize();
    1606     cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
     1749    //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;
    16071750
    16081751    // construct old center
     
    16911834        result = false;
    16921835      }
    1693     } else if (existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.
     1836    } else if ((existentTrianglesCount >= 1) && (existentTrianglesCount <= 3)) { // If there is a planar region within the structure, we need this triangle a second time.
    16941837        AddTesselationPoint((*it)->point, 0);
    16951838        AddTesselationPoint(BaseRay->endpoints[0]->node, 1);
     
    17321875    // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point))
    17331876    BaseRay = BLS[0];
     1877    if ((BTS != NULL) && (BTS->NormalVector.NormSquared() < MYEPSILON)) {
     1878      *out << Verbose(1) << "CRITICAL: Triangle " << *BTS << " has zero normal vector!" << endl;
     1879      exit(255);
     1880    }
     1881
    17341882  }
    17351883
     
    17501898 * \param *out output stream for debugging
    17511899 * \param *Base line to be flipped
    1752  * \return NULL - concave, otherwise endpoint that makes it concave
     1900 * \return NULL - convex, otherwise endpoint that makes it concave
    17531901 */
    17541902class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base)
     
    18271975 * \param *out output stream for debugging
    18281976 * \param *Base line to be flipped
    1829  * \return true - line was changed, false - same line as before
    1830  */
    1831 bool Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)
     1977 * \return volume change due to flipping (0 - then no flipped occured)
     1978 */
     1979double Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)
    18321980{
    18331981  class BoundaryLineSet *OtherBase;
    18341982  Vector *ClosestPoint[2];
     1983  double volume;
    18351984
    18361985  int m=0;
     
    18522001  Distance.CopyVector(ClosestPoint[1]);
    18532002  Distance.SubtractVector(ClosestPoint[0]);
     2003
     2004  // calculate volume
     2005  volume = CalculateVolumeofGeneralTetraeder(Base->endpoints[1]->node->node, OtherBase->endpoints[0]->node->node, OtherBase->endpoints[1]->node->node, Base->endpoints[0]->node->node);
    18542006
    18552007  // delete the temporary other base line and the closest points
     
    18662018    if (Base->triangles.size() < 2) {
    18672019      *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl;
    1868       return false;
     2020      return 0.;
    18692021    }
    18702022    for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) {
     
    18762028    if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip
    18772029      *out << Verbose(2) << "ACCEPT: Other base line would be higher: Flipping baseline." << endl;
    1878       FlipBaseline(out, Base);
    1879       return true;
     2030      // calculate volume summand as a general tetraeder
     2031      return volume;
    18802032    } else {  // Base higher than OtherBase -> do nothing
    18812033      *out << Verbose(2) << "REJECT: Base line is higher: Nothing to do." << endl;
    1882       return false;
    1883     }
    1884   }
    1885 };
    1886 
    1887 /** Returns the closest point on \a *Base with respect to \a *OtherBase.
    1888  * \param *out output stream for debugging
    1889  * \param *Base reference line
    1890  * \param *OtherBase other base line
    1891  * \return Vector on reference line that has closest distance
    1892  */
    1893 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase)
    1894 {
    1895   // construct the plane of the two baselines (i.e. take both their directional vectors)
    1896   Vector Normal;
    1897   Vector Baseline, OtherBaseline;
    1898   Baseline.CopyVector(Base->endpoints[1]->node->node);
    1899   Baseline.SubtractVector(Base->endpoints[0]->node->node);
    1900   OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node);
    1901   OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node);
    1902   Normal.CopyVector(&Baseline);
    1903   Normal.VectorProduct(&OtherBaseline);
    1904   Normal.Normalize();
    1905   *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl;
    1906 
    1907   // project one offset point of OtherBase onto this plane (and add plane offset vector)
    1908   Vector NewOffset;
    1909   NewOffset.CopyVector(OtherBase->endpoints[0]->node->node);
    1910   NewOffset.SubtractVector(Base->endpoints[0]->node->node);
    1911   NewOffset.ProjectOntoPlane(&Normal);
    1912   NewOffset.AddVector(Base->endpoints[0]->node->node);
    1913   Vector NewDirection;
    1914   NewDirection.CopyVector(&NewOffset);
    1915   NewDirection.AddVector(&OtherBaseline);
    1916 
    1917   // calculate the intersection between this projected baseline and Base
    1918   Vector *Intersection = new Vector;
    1919   Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal);
    1920   Normal.CopyVector(Intersection);
    1921   Normal.SubtractVector(Base->endpoints[0]->node->node);
    1922   *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl;
    1923 
    1924   return Intersection;
     2034      return 0.;
     2035    }
     2036  }
    19252037};
    19262038
     
    19302042 * \param *out output stream for debugging
    19312043 * \param *Base line to be flipped
    1932  * \return true - flipping successful, false - something went awry
    1933  */
    1934 bool Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)
     2044 * \return pointer to allocated new baseline - flipping successful, NULL - something went awry
     2045 */
     2046class BoundaryLineSet * Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)
    19352047{
    19362048  class BoundaryLineSet *OldLines[4], *NewLine;
     
    19462058  if (Base->triangles.size() < 2) {
    19472059    *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl;
    1948     return false;
     2060    return NULL;
    19492061  }
    19502062  for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) {
     
    19822094  if (i<4) {
    19832095    *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1984     return false;
     2096    return NULL;
    19852097  }
    19862098  for (int j=0;j<4;j++)
    19872099    if (OldLines[j] == NULL) {
    19882100      *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl;
    1989       return false;
     2101      return NULL;
    19902102    }
    19912103  for (int j=0;j<2;j++)
    19922104    if (OldPoints[j] == NULL) {
    19932105      *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl;
    1994       return false;
     2106      return NULL;
    19952107    }
    19962108
     
    20242136    BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]);
    20252137    BTS->GetNormalVector(BaseLineNormal);
    2026     TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[0], BTS));
     2138    AddTesselationTriangle(OldTriangleNrs[0]);
    20272139    *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl;
    20282140
     
    20322144    BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]);
    20332145    BTS->GetNormalVector(BaseLineNormal);
    2034     TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[1], BTS));
     2146    AddTesselationTriangle(OldTriangleNrs[1]);
    20352147    *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl;
    20362148  } else {
    20372149    *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl;
    2038     return false;
     2150    return NULL;
    20392151  }
    20402152
    20412153  *out << Verbose(1) << "End of FlipBaseline" << endl;
    2042   return true;
     2154  return NewLine;
    20432155};
    20442156
     
    20462158/** Finds the second point of starting triangle.
    20472159 * \param *a first node
    2048  * \param *Candidate pointer to candidate node on return
    20492160 * \param Oben vector indicating the outside
    20502161 * \param OptCandidate reference to recommended candidate on return
     
    20532164 * \param *LC LinkedCell structure with neighbouring points
    20542165 */
    2055 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)
     2166void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)
    20562167{
    20572168  cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl;
    20582169  Vector AngleCheck;
     2170  class TesselPoint* Candidate = NULL;
    20592171  double norm = -1., angle;
    20602172  LinkedNodes *List = NULL;
     
    21912303  cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl;
    21922304
    2193   //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
     2305  cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;
    21942306
    21952307  // construct center of circle
     
    22162328    radius = OldSphereCenter.ScalarProduct(&OldSphereCenter);
    22172329    if (fabs(radius - CircleRadius) < HULLEPSILON) {
     2330      //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl;
    22182331
    22192332      // check SearchDirection
     
    23922505  TesselPoint *trianglePoints[3];
    23932506  TesselPoint *SecondPoint = NULL;
     2507  list<BoundaryTriangleSet*> *triangles = NULL;
    23942508
    23952509  if (LinesOnBoundary.empty()) {
     
    24022516  // check whether closest point is "too close" :), then it's inside
    24032517  if (trianglePoints[0] == NULL) {
    2404     *out << Verbose(1) << "Is the only point, no one else is closeby." << endl;
     2518    *out << Verbose(2) << "Is the only point, no one else is closeby." << endl;
    24052519    return NULL;
    24062520  }
    24072521  if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) {
    2408     *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl;
    2409     return NULL;
    2410   }
    2411   list<TesselPoint*> *connectedPoints = GetCircleOfConnectedPoints(out, trianglePoints[0]);
    2412   list<TesselPoint*> *connectedClosestPoints = GetNeighboursOnCircleOfConnectedPoints(out, connectedPoints, trianglePoints[0], x);
    2413   delete(connectedPoints);
    2414   trianglePoints[1] = connectedClosestPoints->front();
    2415   trianglePoints[2] = connectedClosestPoints->back();
    2416   for (int i=0;i<3;i++) {
    2417     if (trianglePoints[i] == NULL) {
    2418       *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl;
    2419     }
    2420     //*out << Verbose(1) << "List of possible points:" << endl;
    2421     //*out << Verbose(2) << *trianglePoints[i] << endl;
    2422   }
    2423 
    2424   list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints);
    2425 
    2426   delete(connectedClosestPoints);
     2522    *out << Verbose(3) << "Point is right on a tesselation point, no nearest triangle." << endl;
     2523    PointMap::iterator PointRunner = PointsOnBoundary.find(trianglePoints[0]->nr);
     2524    triangles = new list<BoundaryTriangleSet*>;
     2525    if (PointRunner != PointsOnBoundary.end()) {
     2526      for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++)
     2527        for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++)
     2528          triangles->push_back(TriangleRunner->second);
     2529      triangles->sort();
     2530      triangles->unique();
     2531    } else {
     2532      PointRunner = PointsOnBoundary.find(SecondPoint->nr);
     2533      trianglePoints[0] = SecondPoint;
     2534      if (PointRunner != PointsOnBoundary.end()) {
     2535        for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++)
     2536          for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++)
     2537            triangles->push_back(TriangleRunner->second);
     2538        triangles->sort();
     2539        triangles->unique();
     2540      } else {
     2541        *out << Verbose(1) << "ERROR: I cannot find a boundary point to the tessel point " << *trianglePoints[0] << "." << endl;
     2542        return NULL;
     2543      }
     2544    }
     2545  } else {
     2546    list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x);
     2547    trianglePoints[1] = connectedClosestPoints->front();
     2548    trianglePoints[2] = connectedClosestPoints->back();
     2549    for (int i=0;i<3;i++) {
     2550      if (trianglePoints[i] == NULL) {
     2551        *out << Verbose(1) << "ERROR: IsInnerPoint encounters serious error, point " << i << " not found." << endl;
     2552      }
     2553      //*out << Verbose(2) << "List of triangle points:" << endl;
     2554      //*out << Verbose(3) << *trianglePoints[i] << endl;
     2555    }
     2556
     2557    triangles = FindTriangles(trianglePoints);
     2558    *out << Verbose(2) << "List of possible triangles:" << endl;
     2559    for(list<BoundaryTriangleSet*>::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++)
     2560      *out << Verbose(3) << **Runner << endl;
     2561
     2562    delete(connectedClosestPoints);
     2563  }
    24272564 
    24282565  if (triangles->empty()) {
    2429     *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure.";
     2566    *out << Verbose(0) << "ERROR: There is no nearest triangle. Please check the tesselation structure.";
     2567    delete(triangles);
    24302568    return NULL;
    24312569  } else
     
    24432581  class BoundaryTriangleSet *result = NULL;
    24442582  list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC);
     2583  Vector Center;
    24452584
    24462585  if (triangles == NULL)
    24472586    return NULL;
    24482587
    2449   if (x->ScalarProduct(&triangles->front()->NormalVector) < 0)
    2450     result = triangles->back();
    2451   else
     2588  if (triangles->size() == 1) { // there is no degenerate case
    24522589    result = triangles->front();
    2453 
     2590    *out << Verbose(2) << "Normal Vector of this triangle is " << result->NormalVector << "." << endl;
     2591  } else {
     2592    result = triangles->front();
     2593    result->GetCenter(&Center);
     2594    Center.SubtractVector(x);
     2595    *out << Verbose(2) << "Normal Vector of this front side is " << result->NormalVector << "." << endl;
     2596    if (Center.ScalarProduct(&result->NormalVector) < 0) {
     2597      result = triangles->back();
     2598      *out << Verbose(2) << "Normal Vector of this back side is " << result->NormalVector << "." << endl;
     2599      if (Center.ScalarProduct(&result->NormalVector) < 0) {
     2600        *out << Verbose(1) << "ERROR: Front and back side yield NormalVector in wrong direction!" << endl;
     2601      }
     2602    }
     2603  }
    24542604  delete(triangles);
    24552605  return result;
     
    24662616{
    24672617  class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC);
    2468   if (result == NULL)
     2618  Vector Center;
     2619
     2620  if (result == NULL) {// is boundary point or only point in point cloud?
     2621    *out << Verbose(1) << Point << " is the only point in vicinity." << endl;
     2622    return false;
     2623  }
     2624
     2625  result->GetCenter(&Center);
     2626  *out << Verbose(3) << "INFO: Central point of the triangle is " << Center << "." << endl;
     2627  Center.SubtractVector(&Point);
     2628  *out << Verbose(3) << "INFO: Vector from center to point to test is " << Center << "." << endl;
     2629  if (Center.ScalarProduct(&result->NormalVector) > -MYEPSILON) {
     2630    *out << Verbose(1) << Point << " is an inner point." << endl;
    24692631    return true;
    2470   if (Point.ScalarProduct(&result->NormalVector) < 0)
    2471     return true;
    2472   else
     2632  } else {
     2633    *out << Verbose(1) << Point << " is NOT an inner point." << endl;
    24732634    return false;
     2635  }
    24742636}
    24752637
     
    24832645bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC)
    24842646{
    2485   class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC);
    2486   if (result == NULL)
    2487     return true;
    2488   if (Point->node->ScalarProduct(&result->NormalVector) < 0)
    2489     return true;
    2490   else
    2491     return false;
     2647  return IsInnerPoint(out, *(Point->node), LC);
    24922648}
    24932649
     
    24962652 * @param *Point of which get all connected points
    24972653 *
    2498  * @return list of the all points linked to the provided one
    2499  */
    2500 list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point)
    2501 {
    2502   list<TesselPoint*> *connectedPoints = new list<TesselPoint*>;
     2654 * @return set of the all points linked to the provided one
     2655 */
     2656set<TesselPoint*> * Tesselation::GetAllConnectedPoints(ofstream *out, TesselPoint* Point)
     2657{
     2658  set<TesselPoint*> *connectedPoints = new set<TesselPoint*>;
    25032659  class BoundaryPointSet *ReferencePoint = NULL;
    25042660  TesselPoint* current;
     
    25102666    ReferencePoint = PointRunner->second;
    25112667  } else {
    2512     *out << Verbose(2) << "getCircleOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
     2668    *out << Verbose(2) << "GetAllConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
    25132669    ReferencePoint = NULL;
    25142670  }
    25152671
    2516   // little trick so that we look just through lines connect to the BoundaryPoint 
     2672  // little trick so that we look just through lines connect to the BoundaryPoint
    25172673  // OR fall-back to look through all lines if there is no such BoundaryPoint
    25182674  LineMap *Lines = &LinesOnBoundary;
     
    25212677  LineMap::iterator findLines = Lines->begin();
    25222678  while (findLines != Lines->end()) {
    2523     takePoint = false;
    2524 
    2525     if (findLines->second->endpoints[0]->Nr == Point->nr) {
    2526       takePoint = true;
    2527       current = findLines->second->endpoints[1]->node;
    2528     } else if (findLines->second->endpoints[1]->Nr == Point->nr) {
    2529       takePoint = true;
    2530       current = findLines->second->endpoints[0]->node;
    2531     }
    2532    
    2533     if (takePoint) {
    2534       *out << Verbose(3) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is taken into the circle." << endl;
    2535       connectedPoints->push_back(current);
    2536     }
    2537 
    2538     findLines++;
     2679   takePoint = false;
     2680
     2681   if (findLines->second->endpoints[0]->Nr == Point->nr) {
     2682     takePoint = true;
     2683     current = findLines->second->endpoints[1]->node;
     2684   } else if (findLines->second->endpoints[1]->Nr == Point->nr) {
     2685     takePoint = true;
     2686     current = findLines->second->endpoints[0]->node;
     2687   }
     2688
     2689   if (takePoint) {
     2690     *out << Verbose(5) << "INFO: Endpoint " << *current << " of line " << *(findLines->second) << " is enlisted." << endl;
     2691     connectedPoints->insert(current);
     2692   }
     2693
     2694   findLines++;
    25392695  }
    25402696
     
    25432699    return NULL;
    25442700  }
     2701
    25452702  return connectedPoints;
    2546 }
    2547 
    2548 /** Gets the two neighbouring points with respect to a reference line to the provided point.
     2703};
     2704
     2705
     2706/** Gets all points connected to the provided point by triangulation lines, ordered such that we have the circle round the point.
    25492707 * Maps them down onto the plane designated by the axis \a *Point and \a *Reference. The center of all points
    25502708 * connected in the tesselation to \a *Point is mapped to spherical coordinates with the zero angle being given
     
    25532711 *
    25542712 * @param *out output stream for debugging
    2555  * @param *connectedPoints list of connected points to the central \a *Point
    25562713 * @param *Point of which get all connected points
    2557  * @param *Reference Vector to be checked whether it is an inner point
    2558  *
    2559  * @return list of the two points linked to the provided one and closest to the point to be checked,
    2560  */
    2561 list<TesselPoint*> * Tesselation::GetNeighboursOnCircleOfConnectedPoints(ofstream *out, list<TesselPoint*> *connectedPoints, TesselPoint* Point, Vector* Reference)
     2714 * @param *Reference Reference vector for zero angle or NULL for no preference
     2715 * @return list of the all points linked to the provided one
     2716 */
     2717list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference)
    25622718{
    25632719  map<double, TesselPoint*> anglesOfPoints;
    2564   map<double, TesselPoint*>::iterator runner;
    2565   ;
    2566   Vector center, PlaneNormal, OrthogonalVector, helper, AngleZero;
    2567 
    2568   if (connectedPoints->size() == 0) { // if have not found any points
    2569     *out << Verbose(1) << "ERROR: We have not found any connected points to " << *Point<< "." << endl;
    2570     return NULL;
    2571   }
     2720  set<TesselPoint*> *connectedPoints = GetAllConnectedPoints(out, Point);
     2721  list<TesselPoint*> *connectedCircle = new list<TesselPoint*>;
     2722  Vector center;
     2723  Vector PlaneNormal;
     2724  Vector AngleZero;
     2725  Vector OrthogonalVector;
     2726  Vector helper;
    25722727
    25732728  // calculate central point
    2574   for (list<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++)
     2729  for (set<TesselPoint*>::iterator TesselRunner = connectedPoints->begin(); TesselRunner != connectedPoints->end(); TesselRunner++)
    25752730    center.AddVector((*TesselRunner)->node);
    25762731  //*out << "Summed vectors " << center << "; number of points " << connectedPoints.size()
     
    25862741
    25872742  // construct one orthogonal vector
    2588   AngleZero.CopyVector(Reference);
     2743  if (Reference != NULL)
     2744    AngleZero.CopyVector(Reference);
     2745  else
     2746    AngleZero.CopyVector((*connectedPoints->begin())->node);
    25892747  AngleZero.SubtractVector(Point->node);
    25902748  AngleZero.ProjectOntoPlane(&PlaneNormal);
     
    25942752
    25952753  // go through all connected points and calculate angle
    2596   for (list<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) {
     2754  for (set<TesselPoint*>::iterator listRunner = connectedPoints->begin(); listRunner != connectedPoints->end(); listRunner++) {
    25972755    helper.CopyVector((*listRunner)->node);
    25982756    helper.SubtractVector(Point->node);
    25992757    helper.ProjectOntoPlane(&PlaneNormal);
    26002758    double angle = GetAngle(helper, AngleZero, OrthogonalVector);
    2601     *out << Verbose(2) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl;
     2759    *out << Verbose(3) << "INFO: Calculated angle is " << angle << " for point " << **listRunner << "." << endl;
    26022760    anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner)));
    26032761  }
    26042762
    2605   list<TesselPoint*> *result = new list<TesselPoint*>;
    2606   runner = anglesOfPoints.begin();
    2607   result->push_back(runner->second);
    2608   runner = anglesOfPoints.end();
    2609   runner--;
    2610   result->push_back(runner->second);
    2611 
    2612   *out << Verbose(2) << "List of closest points has " << result->size() << " elements, which are "
    2613     << *(result->front()) << " and " << *(result->back()) << endl;
    2614 
    2615   return result;
     2763  for(map<double, TesselPoint*>::iterator AngleRunner = anglesOfPoints.begin(); AngleRunner != anglesOfPoints.end(); AngleRunner++) {
     2764    connectedCircle->push_back(AngleRunner->second);
     2765  }
     2766
     2767  delete(connectedPoints);
     2768  return connectedCircle;
    26162769}
    26172770
     2771/** Gets all points connected to the provided point by triangulation lines, ordered such that we walk along a closed path.
     2772 *
     2773 * @param *out output stream for debugging
     2774 * @param *Point of which get all connected points
     2775 * @return list of the all points linked to the provided one
     2776 */
     2777list<list<TesselPoint*> *> * Tesselation::GetPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)
     2778{
     2779  map<double, TesselPoint*> anglesOfPoints;
     2780  list<list<TesselPoint*> *> *ListOfPaths = new list<list<TesselPoint*> *>;
     2781  list<TesselPoint*> *connectedPath = NULL;
     2782  Vector center;
     2783  Vector PlaneNormal;
     2784  Vector AngleZero;
     2785  Vector OrthogonalVector;
     2786  Vector helper;
     2787  class BoundaryPointSet *ReferencePoint = NULL;
     2788  class BoundaryPointSet *CurrentPoint = NULL;
     2789  class BoundaryTriangleSet *triangle = NULL;
     2790  class BoundaryLineSet *CurrentLine = NULL;
     2791  class BoundaryLineSet *StartLine = NULL;
     2792
     2793  // find the respective boundary point
     2794  PointMap::iterator PointRunner = PointsOnBoundary.find(Point->nr);
     2795  if (PointRunner != PointsOnBoundary.end()) {
     2796    ReferencePoint = PointRunner->second;
     2797  } else {
     2798    *out << Verbose(2) << "ERROR: GetPathOfConnectedPoints() could not find the BoundaryPoint belonging to " << *Point << "." << endl;
     2799    return NULL;
     2800  }
     2801
     2802  map <class BoundaryLineSet *, bool> TouchedLine;
     2803  map <class BoundaryTriangleSet *, bool> TouchedTriangle;
     2804  map <class BoundaryLineSet *, bool>::iterator LineRunner;
     2805  map <class BoundaryTriangleSet *, bool>::iterator TriangleRunner;
     2806  for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) {
     2807    TouchedLine.insert( pair <class BoundaryLineSet *, bool>(Runner->second, false) );
     2808    for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++)
     2809      TouchedTriangle.insert( pair <class BoundaryTriangleSet *, bool>(Sprinter->second, false) );
     2810  }
     2811  if (!ReferencePoint->lines.empty()) {
     2812    for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) {
     2813      LineRunner = TouchedLine.find(runner->second);
     2814      if (LineRunner == TouchedLine.end()) {
     2815        *out << Verbose(2) << "ERROR: I could not find " << *runner->second << " in the touched list." << endl;
     2816      } else if (!LineRunner->second) {
     2817        LineRunner->second = true;
     2818        connectedPath = new list<TesselPoint*>;
     2819        triangle = NULL;
     2820        CurrentLine = runner->second;
     2821        StartLine = CurrentLine;
     2822        CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);
     2823        *out << Verbose(3)<< "INFO: Beginning path retrieval at " << *CurrentPoint << " of line " << *CurrentLine << "." << endl;
     2824        do {
     2825          // push current one
     2826          *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;
     2827          connectedPath->push_back(CurrentPoint->node);
     2828
     2829          // find next triangle
     2830          for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) {
     2831            *out << Verbose(3) << "INFO: Inspecting triangle " << *Runner->second << "." << endl;
     2832            if ((Runner->second != triangle)) { // look for first triangle not equal to old one
     2833              triangle = Runner->second;
     2834              TriangleRunner = TouchedTriangle.find(triangle);
     2835              if (TriangleRunner != TouchedTriangle.end()) {
     2836                if (!TriangleRunner->second) {
     2837                  TriangleRunner->second = true;
     2838                  *out << Verbose(3) << "INFO: Connecting triangle is " << *triangle << "." << endl;
     2839                  break;
     2840                } else {
     2841                  *out << Verbose(3) << "INFO: Skipping " << *triangle << ", as we have already visited it." << endl;
     2842                  triangle = NULL;
     2843                }
     2844              } else {
     2845                *out << Verbose(2) << "ERROR: I could not find " << *triangle << " in the touched list." << endl;
     2846                triangle = NULL;
     2847              }
     2848            }
     2849          }
     2850          if (triangle == NULL)
     2851            break;
     2852          // find next line
     2853          for (int i=0;i<3;i++) {
     2854            if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point
     2855              CurrentLine = triangle->lines[i];
     2856              *out << Verbose(3) << "INFO: Connecting line is " << *CurrentLine << "." << endl;
     2857              break;
     2858            }
     2859          }
     2860          LineRunner = TouchedLine.find(CurrentLine);
     2861          if (LineRunner == TouchedLine.end())
     2862            *out << Verbose(2) << "ERROR: I could not find " << *CurrentLine << " in the touched list." << endl;
     2863          else
     2864            LineRunner->second = true;
     2865          // find next point
     2866          CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint);
     2867
     2868        } while (CurrentLine != StartLine);
     2869        // last point is missing, as it's on start line
     2870        *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl;
     2871        if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back())
     2872          connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node);
     2873
     2874        ListOfPaths->push_back(connectedPath);
     2875      } else {
     2876        *out << Verbose(3) << "INFO: Skipping " << *runner->second << ", as we have already visited it." << endl;
     2877      }
     2878    }
     2879  } else {
     2880    *out << Verbose(1) << "ERROR: There are no lines attached to " << *ReferencePoint << "." << endl;
     2881  }
     2882
     2883  return ListOfPaths;
     2884}
     2885
     2886/** Gets all closed paths on the circle of points connected to the provided point by triangulation lines, if this very point is removed.
     2887 * From GetPathsOfConnectedPoints() extracts all single loops of intracrossing paths in the list of closed paths.
     2888 * @param *out output stream for debugging
     2889 * @param *Point of which get all connected points
     2890 * @return list of the closed paths
     2891 */
     2892list<list<TesselPoint*> *> * Tesselation::GetClosedPathsOfConnectedPoints(ofstream *out, TesselPoint* Point)
     2893{
     2894  list<list<TesselPoint*> *> *ListofPaths = GetPathsOfConnectedPoints(out, Point);
     2895  list<list<TesselPoint*> *> *ListofClosedPaths = new list<list<TesselPoint*> *>;
     2896  list<TesselPoint*> *connectedPath = NULL;
     2897  list<TesselPoint*> *newPath = NULL;
     2898  int count = 0;
     2899
     2900
     2901  list<TesselPoint*>::iterator CircleRunner;
     2902  list<TesselPoint*>::iterator CircleStart;
     2903
     2904  for(list<list<TesselPoint*> *>::iterator ListRunner = ListofPaths->begin(); ListRunner != ListofPaths->end(); ListRunner++) {
     2905    connectedPath = *ListRunner;
     2906
     2907    *out << Verbose(2) << "INFO: Current path is " << connectedPath << "." << endl;
     2908
     2909    // go through list, look for reappearance of starting Point and count
     2910    CircleStart = connectedPath->begin();
     2911
     2912    // go through list, look for reappearance of starting Point and create list
     2913    list<TesselPoint*>::iterator Marker = CircleStart;
     2914    for (CircleRunner = CircleStart; CircleRunner != connectedPath->end(); CircleRunner++) {
     2915      if ((*CircleRunner == *CircleStart) && (CircleRunner != CircleStart)) { // is not the very first point
     2916        // we have a closed circle from Marker to new Marker
     2917        *out << Verbose(3) << count+1 << ". closed path consists of: ";
     2918        newPath = new list<TesselPoint*>;
     2919        list<TesselPoint*>::iterator CircleSprinter = Marker;
     2920        for (; CircleSprinter != CircleRunner; CircleSprinter++) {
     2921          newPath->push_back(*CircleSprinter);
     2922          *out << (**CircleSprinter) << " <-> ";
     2923        }
     2924        *out << ".." << endl;
     2925        count++;
     2926        Marker = CircleRunner;
     2927
     2928        // add to list
     2929        ListofClosedPaths->push_back(newPath);
     2930      }
     2931    }
     2932  }
     2933  *out << Verbose(3) << "INFO: " << count << " closed additional path(s) have been created." << endl;
     2934
     2935  // delete list of paths
     2936  while (!ListofPaths->empty()) {
     2937    connectedPath = *(ListofPaths->begin());
     2938    ListofPaths->remove(connectedPath);
     2939    delete(connectedPath);
     2940  }
     2941  delete(ListofPaths);
     2942
     2943  // exit
     2944  return ListofClosedPaths;
     2945};
     2946
     2947
     2948/** Gets all belonging triangles for a given BoundaryPointSet.
     2949 * \param *out output stream for debugging
     2950 * \param *Point BoundaryPoint
     2951 * \return pointer to allocated list of triangles
     2952 */
     2953set<BoundaryTriangleSet*> *Tesselation::GetAllTriangles(ofstream *out, class BoundaryPointSet *Point)
     2954{
     2955  set<BoundaryTriangleSet*> *connectedTriangles = new set<BoundaryTriangleSet*>;
     2956
     2957  if (Point == NULL) {
     2958    *out << Verbose(1) << "ERROR: Point given is NULL." << endl;
     2959  } else {
     2960    // go through its lines and insert all triangles
     2961    for (LineMap::iterator LineRunner = Point->lines.begin(); LineRunner != Point->lines.end(); LineRunner++)
     2962      for (TriangleMap::iterator TriangleRunner = (LineRunner->second)->triangles.begin(); TriangleRunner != (LineRunner->second)->triangles.end(); TriangleRunner++) {
     2963      connectedTriangles->insert(TriangleRunner->second);
     2964    }
     2965  }
     2966
     2967  return connectedTriangles;
     2968};
     2969
     2970
    26182971/** Removes a boundary point from the envelope while keeping it closed.
    2619  * We create new triangles and remove the old ones connected to the point.
     2972 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz:
     2973 *  -# a closed path(s) of boundary points surrounding the point to be removed is constructed
     2974 *  -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path
     2975 *  -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before
     2976 *  -# the surface is closed, when the path is empty
     2977 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually).
    26202978 * \param *out output stream for debugging
    26212979 * \param *point point to be removed
     
    26252983  class BoundaryLineSet *line = NULL;
    26262984  class BoundaryTriangleSet *triangle = NULL;
    2627   Vector OldPoint, TetraederVector[3];
     2985  Vector OldPoint, NormalVector;
    26282986  double volume = 0;
    2629   int *numbers = NULL;
    26302987  int count = 0;
    2631   int i;
    26322988
    26332989  if (point == NULL) {
     
    26453001    return 0.;
    26463002  }
    2647   list<TesselPoint*> *CircleofPoints = GetCircleOfConnectedPoints(out, point->node);
    2648 
    2649   // remove all triangles
     3003
     3004  list<list<TesselPoint*> *> *ListOfClosedPaths = GetClosedPathsOfConnectedPoints(out, point->node);
     3005  list<TesselPoint*> *connectedPath = NULL;
     3006
     3007  // gather all triangles
    26503008  for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++)
    26513009    count+=LineRunner->second->triangles.size();
    2652   numbers = new int[count];
    2653   class BoundaryTriangleSet **Candidates = new BoundaryTriangleSet*[count];
    2654   i=0;
    2655   for (LineMap::iterator LineRunner = point->lines.begin(); (point != NULL) && (LineRunner != point->lines.end()); LineRunner++) {
     3010  map<class BoundaryTriangleSet *, int> Candidates;
     3011  for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
    26563012    line = LineRunner->second;
    26573013    for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) {
    26583014      triangle = TriangleRunner->second;
    2659       Candidates[i] = triangle;
    2660       numbers[i++] = triangle->Nr;
    2661     }
    2662   }
    2663   for (int j=0;j<i;j++) {
    2664     RemoveTesselationTriangle(Candidates[j]);
    2665   }
    2666   delete[](Candidates);
    2667   *out << Verbose(1) << i << " triangles were removed." << endl;
    2668 
    2669   // re-create all triangles by going through connected points list
    2670   list<TesselPoint*>::iterator CircleRunner = CircleofPoints->begin();
    2671   list<TesselPoint*>::iterator OtherCircleRunner = CircleofPoints->begin();
    2672   class TesselPoint *CentralNode = *CircleRunner;
    2673   // advance two with CircleRunner and one with OtherCircleRunner
    2674   CircleRunner++;
    2675   CircleRunner++;
    2676   OtherCircleRunner++;
    2677   i=0;
    2678   cout << Verbose(2) << "INFO: CentralNode is " << *CentralNode << "." << endl;
    2679   for (; (OtherCircleRunner != CircleofPoints->end()) && (CircleRunner != CircleofPoints->end()); (CircleRunner++), (OtherCircleRunner++)) {
    2680     cout << Verbose(3) << "INFO: CircleRunner's node is " << **CircleRunner << "." << endl;
    2681     cout << Verbose(3) << "INFO: OtherCircleRunner's node is " << **OtherCircleRunner << "." << endl;
    2682     *out << Verbose(4) << "Adding new triangle points."<< endl;
    2683     AddTesselationPoint(CentralNode, 0);
    2684     AddTesselationPoint(*OtherCircleRunner, 1);
    2685     AddTesselationPoint(*CircleRunner, 2);
    2686     *out << Verbose(4) << "Adding new triangle lines."<< endl;
    2687     AddTesselationLine(TPS[0], TPS[1], 0);
    2688     AddTesselationLine(TPS[0], TPS[2], 1);
    2689     AddTesselationLine(TPS[1], TPS[2], 2);
    2690     BTS = new class BoundaryTriangleSet(BLS, numbers[i]);
    2691     TrianglesOnBoundary.insert(TrianglePair(numbers[i], BTS));
    2692     *out << Verbose(4) << "Created triangle " << *BTS << "." << endl;
    2693     // calculate volume summand as a general tetraeder
    2694     for (int j=0;j<3;j++) {
    2695       TetraederVector[j].CopyVector(TPS[j]->node->node);
    2696       TetraederVector[j].SubtractVector(&OldPoint);
    2697     }
    2698     OldPoint.CopyVector(&TetraederVector[0]);
    2699     OldPoint.VectorProduct(&TetraederVector[1]);
    2700     volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));
    2701     // advance number
    2702     i++;
    2703     if (i >= count)
    2704       *out << Verbose(2) << "WARNING: Maximum of numbers reached!" << endl;
    2705   }
    2706   *out << Verbose(1) << i << " triangles were created." << endl;
    2707 
    2708   delete[](numbers);
    2709 
    2710   return volume;
    2711 };
    2712 
    2713 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
    2714  * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
    2715  * make it bigger (i.e. closing one (the baseline) and opening two new ones).
    2716  * \param TPS[3] nodes of the triangle
    2717  * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)
    2718  */
    2719 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])
    2720 {
    2721   bool result = false;
    2722   int counter = 0;
    2723 
    2724   // check all three points
    2725   for (int i=0;i<3;i++)
    2726     for (int j=i+1; j<3; j++) {
    2727       if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) {  // there already is a line
    2728         LineMap::iterator FindLine;
    2729         pair<LineMap::iterator,LineMap::iterator> FindPair;
    2730         FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);
    2731         for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
    2732           // If there is a line with less than two attached triangles, we don't need a new line.
    2733           if (FindLine->second->triangles.size() < 2) {
    2734             counter++;
    2735             break;  // increase counter only once per edge
    2736           }
     3015      Candidates.insert( pair<class BoundaryTriangleSet *, int> (triangle, triangle->Nr) );
     3016    }
     3017  }
     3018
     3019  // remove all triangles
     3020  count=0;
     3021  NormalVector.Zero();
     3022  for (map<class BoundaryTriangleSet *, int>::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) {
     3023    *out << Verbose(3) << "INFO: Removing triangle " << *(Runner->first) << "." << endl;
     3024    NormalVector.SubtractVector(&Runner->first->NormalVector); // has to point inward
     3025    RemoveTesselationTriangle(Runner->first);
     3026    count++;
     3027  }
     3028  *out << Verbose(1) << count << " triangles were removed." << endl;
     3029
     3030  list<list<TesselPoint*> *>::iterator ListAdvance = ListOfClosedPaths->begin();
     3031  list<list<TesselPoint*> *>::iterator ListRunner = ListAdvance;
     3032  map<class BoundaryTriangleSet *, int>::iterator NumberRunner = Candidates.begin();
     3033  list<TesselPoint*>::iterator StartNode, MiddleNode, EndNode;
     3034  double angle;
     3035  double smallestangle;
     3036  Vector Point, Reference, OrthogonalVector;
     3037  if (count > 2) {  // less than three triangles, then nothing will be created
     3038    class TesselPoint *TriangleCandidates[3];
     3039    count = 0;
     3040    for ( ; ListRunner != ListOfClosedPaths->end(); ListRunner = ListAdvance) {  // go through all closed paths
     3041      if (ListAdvance != ListOfClosedPaths->end())
     3042        ListAdvance++;
     3043
     3044      connectedPath = *ListRunner;
     3045
     3046      // re-create all triangles by going through connected points list
     3047      list<class BoundaryLineSet *> NewLines;
     3048      for (;!connectedPath->empty();) {
     3049        // search middle node with widest angle to next neighbours
     3050        EndNode = connectedPath->end();
     3051        smallestangle = 0.;
     3052        for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) {
     3053          cout << Verbose(3) << "INFO: MiddleNode is " << **MiddleNode << "." << endl;
     3054          // construct vectors to next and previous neighbour
     3055          StartNode = MiddleNode;
     3056          if (StartNode == connectedPath->begin())
     3057            StartNode = connectedPath->end();
     3058          StartNode--;
     3059          //cout << Verbose(3) << "INFO: StartNode is " << **StartNode << "." << endl;
     3060          Point.CopyVector((*StartNode)->node);
     3061          Point.SubtractVector((*MiddleNode)->node);
     3062          StartNode = MiddleNode;
     3063          StartNode++;
     3064          if (StartNode == connectedPath->end())
     3065            StartNode = connectedPath->begin();
     3066          //cout << Verbose(3) << "INFO: EndNode is " << **StartNode << "." << endl;
     3067          Reference.CopyVector((*StartNode)->node);
     3068          Reference.SubtractVector((*MiddleNode)->node);
     3069          OrthogonalVector.CopyVector((*MiddleNode)->node);
     3070          OrthogonalVector.SubtractVector(&OldPoint);
     3071          OrthogonalVector.MakeNormalVector(&Reference);
     3072          angle = GetAngle(Point, Reference, OrthogonalVector);
     3073          //if (angle < M_PI)  // no wrong-sided triangles, please?
     3074            if(fabs(angle - M_PI) < fabs(smallestangle - M_PI)) {  // get straightest angle (i.e. construct those triangles with smallest area first)
     3075              smallestangle = angle;
     3076              EndNode = MiddleNode;
     3077            }
    27373078        }
    2738       } else { // no line
    2739         cout << Verbose(1) << "The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;
    2740         result = true;
     3079        MiddleNode = EndNode;
     3080        if (MiddleNode == connectedPath->end()) {
     3081          cout << Verbose(1) << "CRITICAL: Could not find a smallest angle!" << endl;
     3082          exit(255);
     3083        }
     3084        StartNode = MiddleNode;
     3085        if (StartNode == connectedPath->begin())
     3086          StartNode = connectedPath->end();
     3087        StartNode--;
     3088        EndNode++;
     3089        if (EndNode == connectedPath->end())
     3090          EndNode = connectedPath->begin();
     3091        cout << Verbose(4) << "INFO: StartNode is " << **StartNode << "." << endl;
     3092        cout << Verbose(4) << "INFO: MiddleNode is " << **MiddleNode << "." << endl;
     3093        cout << Verbose(4) << "INFO: EndNode is " << **EndNode << "." << endl;
     3094        *out << Verbose(3) << "INFO: Attempting to create triangle " << (*StartNode)->Name << ", " << (*MiddleNode)->Name << " and " << (*EndNode)->Name << "." << endl;
     3095        TriangleCandidates[0] = *StartNode;
     3096        TriangleCandidates[1] = *MiddleNode;
     3097        TriangleCandidates[2] = *EndNode;
     3098        triangle = GetPresentTriangle(out, TriangleCandidates);
     3099        if (triangle != NULL) {
     3100          cout << Verbose(1) << "WARNING: New triangle already present, skipping!" << endl;
     3101          StartNode++;
     3102          MiddleNode++;
     3103          EndNode++;
     3104          if (StartNode == connectedPath->end())
     3105            StartNode = connectedPath->begin();
     3106          if (MiddleNode == connectedPath->end())
     3107            MiddleNode = connectedPath->begin();
     3108          if (EndNode == connectedPath->end())
     3109            EndNode = connectedPath->begin();
     3110          continue;
     3111        }
     3112        *out << Verbose(5) << "Adding new triangle points."<< endl;
     3113        AddTesselationPoint(*StartNode, 0);
     3114        AddTesselationPoint(*MiddleNode, 1);
     3115        AddTesselationPoint(*EndNode, 2);
     3116        *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3117        AddTesselationLine(TPS[0], TPS[1], 0);
     3118        AddTesselationLine(TPS[0], TPS[2], 1);
     3119        NewLines.push_back(BLS[1]);
     3120        AddTesselationLine(TPS[1], TPS[2], 2);
     3121        BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3122        BTS->GetNormalVector(NormalVector);
     3123        AddTesselationTriangle();
     3124        // calculate volume summand as a general tetraeder
     3125        volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->node, TPS[1]->node->node, TPS[2]->node->node, &OldPoint);
     3126        // advance number
     3127        count++;
     3128
     3129        // prepare nodes for next triangle
     3130        StartNode = EndNode;
     3131        cout << Verbose(4) << "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "." << endl;
     3132        connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles)
     3133        if (connectedPath->size() == 2) { // we are done
     3134          connectedPath->remove(*StartNode); // remove the start node
     3135          connectedPath->remove(*EndNode); // remove the end node
     3136          break;
     3137        } else if (connectedPath->size() < 2) { // something's gone wrong!
     3138          cout << Verbose(1) << "CRITICAL: There are only two endpoints left!" << endl;
     3139          exit(255);
     3140        } else {
     3141          MiddleNode = StartNode;
     3142          MiddleNode++;
     3143          if (MiddleNode == connectedPath->end())
     3144            MiddleNode = connectedPath->begin();
     3145          EndNode = MiddleNode;
     3146          EndNode++;
     3147          if (EndNode == connectedPath->end())
     3148            EndNode = connectedPath->begin();
     3149        }
    27413150      }
    2742     }
    2743   if (counter > 1) {
    2744     cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;
    2745     result = true;
    2746   }
    2747   return result;
    2748 };
    2749 
    2750 
    2751 /** Sort function for the candidate list.
    2752  */
    2753 bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)
    2754 {
    2755   Vector BaseLineVector, OrthogonalVector, helper;
    2756   if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
    2757     cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
    2758     //return false;
    2759     exit(1);
    2760   }
    2761   // create baseline vector
    2762   BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);
    2763   BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2764   BaseLineVector.Normalize();
    2765 
    2766   // 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!)
    2767   helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);
    2768   helper.SubtractVector(candidate1->point->node);
    2769   OrthogonalVector.CopyVector(&helper);
    2770   helper.VectorProduct(&BaseLineVector);
    2771   OrthogonalVector.SubtractVector(&helper);
    2772   OrthogonalVector.Normalize();
    2773 
    2774   // calculate both angles and correct with in-plane vector
    2775   helper.CopyVector(candidate1->point->node);
    2776   helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2777   double phi = BaseLineVector.Angle(&helper);
    2778   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    2779     phi = 2.*M_PI - phi;
    2780   }
    2781   helper.CopyVector(candidate2->point->node);
    2782   helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
    2783   double psi = BaseLineVector.Angle(&helper);
    2784   if (OrthogonalVector.ScalarProduct(&helper) > 0) {
    2785     psi = 2.*M_PI - psi;
    2786   }
    2787 
    2788   cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
    2789   cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
    2790 
    2791   // return comparison
    2792   return phi < psi;
    2793 };
    2794 
    2795 /**
    2796  * Finds the point which is second closest to the provided one.
    2797  *
    2798  * @param Point to which to find the second closest other point
    2799  * @param linked cell structure
    2800  *
    2801  * @return point which is second closest to the provided one
    2802  */
    2803 TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)
    2804 {
    2805   LinkedNodes *List = NULL;
    2806   TesselPoint* closestPoint = NULL;
    2807   TesselPoint* secondClosestPoint = NULL;
    2808   double distance = 1e16;
    2809   double secondDistance = 1e16;
    2810   Vector helper;
    2811   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2812 
    2813   LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
    2814   for(int i=0;i<NDIM;i++) // store indices of this cell
    2815     N[i] = LC->n[i];
    2816   cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2817 
    2818   LC->GetNeighbourBounds(Nlower, Nupper);
    2819   //cout << endl;
    2820   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2821     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2822       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2823         List = LC->GetCurrentCell();
    2824         cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    2825         if (List != NULL) {
    2826           for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2827             helper.CopyVector(Point);
    2828             helper.SubtractVector((*Runner)->node);
    2829             double currentNorm = helper. Norm();
    2830             if (currentNorm < distance) {
    2831               // remember second point
    2832               secondDistance = distance;
    2833               secondClosestPoint = closestPoint;
    2834               // mark down new closest point
    2835               distance = currentNorm;
    2836               closestPoint = (*Runner);
    2837               cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
     3151      // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing)
     3152      if (NewLines.size() > 1) {
     3153        list<class BoundaryLineSet *>::iterator Candidate;
     3154        class BoundaryLineSet *OtherBase = NULL;
     3155        double tmp, maxgain;
     3156        do {
     3157          maxgain = 0;
     3158          for(list<class BoundaryLineSet *>::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) {
     3159            tmp = PickFarthestofTwoBaselines(out, *Runner);
     3160            if (maxgain < tmp) {
     3161              maxgain = tmp;
     3162              Candidate = Runner;
    28383163            }
    28393164          }
    2840         } else {
    2841           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    2842             << LC->n[2] << " is invalid!" << endl;
    2843         }
     3165          if (maxgain != 0) {
     3166            volume += maxgain;
     3167            cout << Verbose(3) << "Flipping baseline with highest volume" << **Candidate << "." << endl;
     3168            OtherBase = FlipBaseline(out, *Candidate);
     3169            NewLines.erase(Candidate);
     3170            NewLines.push_back(OtherBase);
     3171          }
     3172        } while (maxgain != 0.);
    28443173      }
    28453174
    2846   return secondClosestPoint;
    2847 };
    2848 
    2849 /**
    2850  * Finds the point which is closest to the provided one.
    2851  *
    2852  * @param Point to which to find the closest other point
    2853  * @param SecondPoint the second closest other point on return, NULL if none found
    2854  * @param linked cell structure
    2855  *
    2856  * @return point which is closest to the provided one, NULL if none found
    2857  */
    2858 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)
    2859 {
    2860   LinkedNodes *List = NULL;
    2861   TesselPoint* closestPoint = NULL;
    2862   SecondPoint = NULL;
    2863   double distance = 1e16;
    2864   double secondDistance = 1e16;
    2865   Vector helper;
    2866   int N[NDIM], Nlower[NDIM], Nupper[NDIM];
    2867 
    2868   LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
    2869   for(int i=0;i<NDIM;i++) // store indices of this cell
    2870     N[i] = LC->n[i];
    2871   cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
    2872 
    2873   LC->GetNeighbourBounds(Nlower, Nupper);
    2874   //cout << endl;
    2875   for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
    2876     for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
    2877       for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
    2878         List = LC->GetCurrentCell();
    2879         cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
    2880         if (List != NULL) {
    2881           for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
    2882             helper.CopyVector(Point);
    2883             helper.SubtractVector((*Runner)->node);
    2884             double currentNorm = helper. Norm();
    2885             if (currentNorm < distance) {
    2886               secondDistance = distance;
    2887               SecondPoint = closestPoint;
    2888               distance = currentNorm;
    2889               closestPoint = (*Runner);
    2890               cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
    2891             } else if (currentNorm < secondDistance) {
    2892               secondDistance = currentNorm;
    2893               SecondPoint = (*Runner);
    2894               cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;
    2895             }
    2896           }
    2897         } else {
    2898           cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
    2899             << LC->n[2] << " is invalid!" << endl;
    2900         }
    2901       }
    2902 
    2903   return closestPoint;
    2904 };
     3175      ListOfClosedPaths->remove(connectedPath);
     3176      delete(connectedPath);
     3177    }
     3178    *out << Verbose(1) << count << " triangles were created." << endl;
     3179  } else {
     3180    while (!ListOfClosedPaths->empty()) {
     3181      ListRunner = ListOfClosedPaths->begin();
     3182      connectedPath = *ListRunner;
     3183      ListOfClosedPaths->remove(connectedPath);
     3184      delete(connectedPath);
     3185    }
     3186    *out << Verbose(1) << "No need to create any triangles." << endl;
     3187  }
     3188  delete(ListOfClosedPaths);
     3189
     3190  *out << Verbose(1) << "Removed volume is " << volume << "." << endl;
     3191
     3192  return volume;
     3193};
     3194
     3195
    29053196
    29063197/**
     
    29393230              FindTriangle = FindLine->second->triangles.begin();
    29403231              for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) {
    2941                 if ((
    2942                   (FindTriangle->second->endpoints[0] == TrianglePoints[0])
    2943                     || (FindTriangle->second->endpoints[0] == TrianglePoints[1])
    2944                     || (FindTriangle->second->endpoints[0] == TrianglePoints[2])
    2945                   ) && (
    2946                     (FindTriangle->second->endpoints[1] == TrianglePoints[0])
    2947                     || (FindTriangle->second->endpoints[1] == TrianglePoints[1])
    2948                     || (FindTriangle->second->endpoints[1] == TrianglePoints[2])
    2949                   ) && (
    2950                     (FindTriangle->second->endpoints[2] == TrianglePoints[0])
    2951                     || (FindTriangle->second->endpoints[2] == TrianglePoints[1])
    2952                     || (FindTriangle->second->endpoints[2] == TrianglePoints[2])
    2953                   )
    2954                 ) {
     3232                if (FindTriangle->second->IsPresentTupel(TrianglePoints)) {
    29553233                  result->push_back(FindTriangle->second);
    29563234                }
     
    29703248
    29713249/**
     3250 * Finds all degenerated lines within the tesselation structure.
     3251 *
     3252 * @return map of keys of degenerated line pairs, each line occurs twice
     3253 *         in the list, once as key and once as value
     3254 */
     3255map<int, int> * Tesselation::FindAllDegeneratedLines()
     3256{
     3257  map<int, class BoundaryLineSet *> AllLines;
     3258  map<int, int> * DegeneratedLines = new map<int, int>;
     3259
     3260  // sanity check
     3261  if (LinesOnBoundary.empty()) {
     3262    cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure.";
     3263    return DegeneratedLines;
     3264  }
     3265
     3266  LineMap::iterator LineRunner1;
     3267  pair<LineMap::iterator, bool> tester;
     3268  for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) {
     3269    tester = AllLines.insert( pair<int,BoundaryLineSet *> (LineRunner1->second->endpoints[0]->Nr, LineRunner1->second) );
     3270    if ((!tester.second) && (tester.first->second->endpoints[1]->Nr == LineRunner1->second->endpoints[1]->Nr)) { // found degenerated line
     3271      DegeneratedLines->insert ( pair<int, int> (LineRunner1->second->Nr, tester.first->second->Nr) );
     3272      DegeneratedLines->insert ( pair<int, int> (tester.first->second->Nr, LineRunner1->second->Nr) );
     3273    }
     3274  }
     3275
     3276  AllLines.clear();
     3277
     3278  cout << Verbose(1) << "FindAllDegeneratedLines() found " << DegeneratedLines->size() << " lines." << endl;
     3279  map<int,int>::iterator it;
     3280  for (it = DegeneratedLines->begin(); it != DegeneratedLines->end(); it++)
     3281      cout << Verbose(2) << (*it).first << " => " << (*it).second << endl;
     3282
     3283  return DegeneratedLines;
     3284}
     3285
     3286/**
    29723287 * Finds all degenerated triangles within the tesselation structure.
    29733288 *
     
    29753290 *         in the list, once as key and once as value
    29763291 */
    2977 map<int, int> Tesselation::FindAllDegeneratedTriangles()
    2978 {
    2979   map<int, int> DegeneratedTriangles;
    2980 
    2981   // sanity check
    2982   if (LinesOnBoundary.empty()) {
    2983     cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure.";
    2984     return DegeneratedTriangles;
    2985   }
    2986 
    2987   LineMap::iterator LineRunner1, LineRunner2;
    2988 
    2989   for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) {
    2990     for (LineRunner2 = LinesOnBoundary.begin(); LineRunner2 != LinesOnBoundary.end(); ++LineRunner2) {
    2991       if ((LineRunner1->second != LineRunner2->second)
    2992         && (LineRunner1->second->endpoints[0] == LineRunner2->second->endpoints[0])
    2993         && (LineRunner1->second->endpoints[1] == LineRunner2->second->endpoints[1])
    2994       ) {
    2995         TriangleMap::iterator TriangleRunner1 = LineRunner1->second->triangles.begin(),
    2996           TriangleRunner2 = LineRunner2->second->triangles.begin();
    2997 
    2998         for (; TriangleRunner1 != LineRunner1->second->triangles.end(); ++TriangleRunner1) {
    2999           for (; TriangleRunner2 != LineRunner2->second->triangles.end(); ++TriangleRunner2) {
    3000             if ((TriangleRunner1->second != TriangleRunner2->second)
    3001               && (TriangleRunner1->second->endpoints[0] == TriangleRunner2->second->endpoints[0])
    3002               && (TriangleRunner1->second->endpoints[1] == TriangleRunner2->second->endpoints[1])
    3003               && (TriangleRunner1->second->endpoints[2] == TriangleRunner2->second->endpoints[2])
    3004             ) {
    3005               DegeneratedTriangles[TriangleRunner1->second->Nr] = TriangleRunner2->second->Nr;
    3006               DegeneratedTriangles[TriangleRunner2->second->Nr] = TriangleRunner1->second->Nr;
    3007             }
    3008           }
     3292map<int, int> * Tesselation::FindAllDegeneratedTriangles()
     3293{
     3294  map<int, int> * DegeneratedLines = FindAllDegeneratedLines();
     3295  map<int, int> * DegeneratedTriangles = new map<int, int>;
     3296
     3297  TriangleMap::iterator TriangleRunner1, TriangleRunner2;
     3298  LineMap::iterator Liner;
     3299  class BoundaryLineSet *line1 = NULL, *line2 = NULL;
     3300
     3301  for (map<int, int>::iterator LineRunner = DegeneratedLines->begin(); LineRunner != DegeneratedLines->end(); ++LineRunner) {
     3302    // run over both lines' triangles
     3303    Liner = LinesOnBoundary.find(LineRunner->first);
     3304    if (Liner != LinesOnBoundary.end())
     3305      line1 = Liner->second;
     3306    Liner = LinesOnBoundary.find(LineRunner->second);
     3307    if (Liner != LinesOnBoundary.end())
     3308      line2 = Liner->second;
     3309    for (TriangleRunner1 = line1->triangles.begin(); TriangleRunner1 != line1->triangles.end(); ++TriangleRunner1) {
     3310      for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) {
     3311        if ((TriangleRunner1->second != TriangleRunner2->second)
     3312          && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) {
     3313          DegeneratedTriangles->insert( pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr) );
     3314          DegeneratedTriangles->insert( pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr) );
    30093315        }
    30103316      }
    30113317    }
    30123318  }
    3013 
    3014   cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles.size() << " triangles." << endl;
     3319  delete(DegeneratedLines);
     3320
     3321  cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles->size() << " triangles:" << endl;
    30153322  map<int,int>::iterator it;
    3016   for (it = DegeneratedTriangles.begin(); it != DegeneratedTriangles.end(); it++)
     3323  for (it = DegeneratedTriangles->begin(); it != DegeneratedTriangles->end(); it++)
    30173324      cout << Verbose(2) << (*it).first << " => " << (*it).second << endl;
    30183325
     
    30263333void Tesselation::RemoveDegeneratedTriangles()
    30273334{
    3028   map<int, int> DegeneratedTriangles = FindAllDegeneratedTriangles();
    3029 
    3030   for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles.begin();
    3031     TriangleKeyRunner != DegeneratedTriangles.end(); ++TriangleKeyRunner
     3335  map<int, int> * DegeneratedTriangles = FindAllDegeneratedTriangles();
     3336  TriangleMap::iterator finder;
     3337  BoundaryTriangleSet *triangle = NULL, *partnerTriangle = NULL;
     3338  int count  = 0;
     3339
     3340  cout << Verbose(1) << "Begin of RemoveDegeneratedTriangles" << endl;
     3341
     3342  for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles->begin();
     3343    TriangleKeyRunner != DegeneratedTriangles->end(); ++TriangleKeyRunner
    30323344  ) {
    3033     BoundaryTriangleSet *triangle = TrianglesOnBoundary.find(TriangleKeyRunner->first)->second,
    3034       *partnerTriangle = TrianglesOnBoundary.find(TriangleKeyRunner->second)->second;
     3345    finder = TrianglesOnBoundary.find(TriangleKeyRunner->first);
     3346    if (finder != TrianglesOnBoundary.end())
     3347      triangle = finder->second;
     3348    else
     3349      break;
     3350    finder = TrianglesOnBoundary.find(TriangleKeyRunner->second);
     3351    if (finder != TrianglesOnBoundary.end())
     3352      partnerTriangle = finder->second;
     3353    else
     3354      break;
    30353355
    30363356    bool trianglesShareLine = false;
     
    30443364      && (triangle->endpoints[0]->LinesCount > 2)
    30453365    ) {
     3366      // check whether we have to fix lines
     3367      BoundaryTriangleSet *Othertriangle = NULL;
     3368      BoundaryTriangleSet *OtherpartnerTriangle = NULL;
     3369      TriangleMap::iterator TriangleRunner;
     3370      for (int i = 0; i < 3; ++i)
     3371        for (int j = 0; j < 3; ++j)
     3372          if (triangle->lines[i] != partnerTriangle->lines[j]) {
     3373            // get the other two triangles
     3374            for (TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); ++TriangleRunner)
     3375              if (TriangleRunner->second != triangle) {
     3376                Othertriangle = TriangleRunner->second;
     3377              }
     3378            for (TriangleRunner = partnerTriangle->lines[i]->triangles.begin(); TriangleRunner != partnerTriangle->lines[i]->triangles.end(); ++TriangleRunner)
     3379              if (TriangleRunner->second != partnerTriangle) {
     3380                OtherpartnerTriangle = TriangleRunner->second;
     3381              }
     3382            /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j]
     3383            // the line of triangle receives the degenerated ones
     3384            triangle->lines[i]->triangles.erase(Othertriangle->Nr);
     3385            triangle->lines[i]->triangles.insert( TrianglePair( partnerTriangle->Nr, partnerTriangle) );
     3386            for (int k=0;k<3;k++)
     3387              if (triangle->lines[i] == Othertriangle->lines[k]) {
     3388                Othertriangle->lines[k] = partnerTriangle->lines[j];
     3389                break;
     3390              }
     3391            // the line of partnerTriangle receives the non-degenerated ones
     3392            partnerTriangle->lines[j]->triangles.erase( partnerTriangle->Nr);
     3393            partnerTriangle->lines[j]->triangles.insert( TrianglePair( Othertriangle->Nr, Othertriangle) );
     3394            partnerTriangle->lines[j] = triangle->lines[i];
     3395          }
     3396
     3397      // erase the pair
     3398      count += (int) DegeneratedTriangles->erase(triangle->Nr);
    30463399      cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl;
    30473400      RemoveTesselationTriangle(triangle);
     3401      count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr);
    30483402      cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl;
    30493403      RemoveTesselationTriangle(partnerTriangle);
    3050       DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr));
    30513404    } else {
    30523405      cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle
     
    30553408    }
    30563409  }
     3410  delete(DegeneratedTriangles);
     3411
     3412  cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl;
     3413  cout << Verbose(1) << "End of RemoveDegeneratedTriangles" << endl;
    30573414}
    30583415
    3059 /** Gets the angle between a point and a reference relative to the provided center.
    3060  * We have two shanks point and reference between which the angle is calculated
    3061  * and by scalar product with OrthogonalVector we decide the interval.
    3062  * @param point to calculate the angle for
    3063  * @param reference to which to calculate the angle
    3064  * @param OrthogonalVector points in direction of [pi,2pi] interval
    3065  *
    3066  * @return angle between point and reference
    3067  */
    3068 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector)
    3069 {
    3070   if (reference.IsZero())
    3071     return M_PI;
    3072 
    3073   // calculate both angles and correct with in-plane vector
    3074   if (point.IsZero())
    3075     return M_PI;
    3076   double phi = point.Angle(&reference);
    3077   if (OrthogonalVector.ScalarProduct(&point) > 0) {
    3078     phi = 2.*M_PI - phi;
    3079   }
    3080 
    3081   cout << Verbose(3) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl;
    3082 
    3083   return phi;
    3084 }
    3085 
     3416/** Adds an outside Tesselpoint to the envelope via (two) degenerated triangles.
     3417 * We look for the closest point on the boundary, we look through its connected boundary lines and
     3418 * seek the one with the minimum angle between its center point and the new point and this base line.
     3419 * We open up the line by adding a degenerated triangle, whose other side closes the base line again.
     3420 * \param *out output stream for debugging
     3421 * \param *point point to add
     3422 * \param *LC Linked Cell structure to find nearest point
     3423 */
     3424void Tesselation::AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC)
     3425{
     3426  *out << Verbose(2) << "Begin of AddBoundaryPointByDegeneratedTriangle" << endl;
     3427
     3428  // find nearest boundary point
     3429  class TesselPoint *BackupPoint = NULL;
     3430  class TesselPoint *NearestPoint = FindClosestPoint(point->node, BackupPoint, LC);
     3431  class BoundaryPointSet *NearestBoundaryPoint = NULL;
     3432  PointMap::iterator PointRunner;
     3433
     3434  if (NearestPoint == point)
     3435    NearestPoint = BackupPoint;
     3436  PointRunner = PointsOnBoundary.find(NearestPoint->nr);
     3437  if (PointRunner != PointsOnBoundary.end()) {
     3438    NearestBoundaryPoint = PointRunner->second;
     3439  } else {
     3440    *out << Verbose(1) << "ERROR: I cannot find the boundary point." << endl;
     3441    return;
     3442  }
     3443  *out << Verbose(2) << "Nearest point on boundary is " << NearestPoint->Name << "." << endl;
     3444
     3445  // go through its lines and find the best one to split
     3446  Vector CenterToPoint;
     3447  Vector BaseLine;
     3448  double angle, BestAngle = 0.;
     3449  class BoundaryLineSet *BestLine = NULL;
     3450  for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) {
     3451    BaseLine.CopyVector(Runner->second->endpoints[0]->node->node);
     3452    BaseLine.SubtractVector(Runner->second->endpoints[1]->node->node);
     3453    CenterToPoint.CopyVector(Runner->second->endpoints[0]->node->node);
     3454    CenterToPoint.AddVector(Runner->second->endpoints[1]->node->node);
     3455    CenterToPoint.Scale(0.5);
     3456    CenterToPoint.SubtractVector(point->node);
     3457    angle = CenterToPoint.Angle(&BaseLine);
     3458    if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) {
     3459      BestAngle = angle;
     3460      BestLine = Runner->second;
     3461    }
     3462  }
     3463
     3464  // remove one triangle from the chosen line
     3465  class BoundaryTriangleSet *TempTriangle = (BestLine->triangles.begin())->second;
     3466  BestLine->triangles.erase(TempTriangle->Nr);
     3467  int nr = -1;
     3468  for (int i=0;i<3; i++) {
     3469    if (TempTriangle->lines[i] == BestLine) {
     3470      nr = i;
     3471      break;
     3472    }
     3473  }
     3474
     3475  // create new triangle to connect point (connects automatically with the missing spot of the chosen line)
     3476  *out << Verbose(5) << "Adding new triangle points."<< endl;
     3477  AddTesselationPoint((BestLine->endpoints[0]->node), 0);
     3478  AddTesselationPoint((BestLine->endpoints[1]->node), 1);
     3479  AddTesselationPoint(point, 2);
     3480  *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3481  AddTesselationLine(TPS[0], TPS[1], 0);
     3482  AddTesselationLine(TPS[0], TPS[2], 1);
     3483  AddTesselationLine(TPS[1], TPS[2], 2);
     3484  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3485  BTS->GetNormalVector(TempTriangle->NormalVector);
     3486  BTS->NormalVector.Scale(-1.);
     3487  *out << Verbose(3) << "INFO: NormalVector of new triangle is " << BTS->NormalVector << "." << endl;
     3488  AddTesselationTriangle();
     3489
     3490  // create other side of this triangle and close both new sides of the first created triangle
     3491  *out << Verbose(5) << "Adding new triangle points."<< endl;
     3492  AddTesselationPoint((BestLine->endpoints[0]->node), 0);
     3493  AddTesselationPoint((BestLine->endpoints[1]->node), 1);
     3494  AddTesselationPoint(point, 2);
     3495  *out << Verbose(5) << "Adding new triangle lines."<< endl;
     3496  AddTesselationLine(TPS[0], TPS[1], 0);
     3497  AddTesselationLine(TPS[0], TPS[2], 1);
     3498  AddTesselationLine(TPS[1], TPS[2], 2);
     3499  BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount);
     3500  BTS->GetNormalVector(TempTriangle->NormalVector);
     3501  *out << Verbose(3) << "INFO: NormalVector of other new triangle is " << BTS->NormalVector << "." << endl;
     3502  AddTesselationTriangle();
     3503
     3504  // add removed triangle to the last open line of the second triangle
     3505  for (int i=0;i<3;i++) { // look for the same line as BestLine (only it's its degenerated companion)
     3506    if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) {
     3507      if (BestLine == BTS->lines[i]){
     3508        *out << Verbose(1) << "CRITICAL: BestLine is same as found line, something's wrong here!" << endl;
     3509        exit(255);
     3510      }
     3511      BTS->lines[i]->triangles.insert( pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle) );
     3512      TempTriangle->lines[nr] = BTS->lines[i];
     3513      break;
     3514    }
     3515  }
     3516
     3517  // exit
     3518  *out << Verbose(2) << "End of AddBoundaryPointByDegeneratedTriangle" << endl;
     3519};
     3520
     3521/** Writes the envelope to file.
     3522 * \param *out otuput stream for debugging
     3523 * \param *filename basename of output file
     3524 * \param *cloud PointCloud structure with all nodes
     3525 */
     3526void Tesselation::Output(ofstream *out, const char *filename, PointCloud *cloud)
     3527{
     3528  ofstream *tempstream = NULL;
     3529  string NameofTempFile;
     3530  char NumberName[255];
     3531
     3532  if (LastTriangle != NULL) {
     3533    sprintf(NumberName, "-%04d-%s_%s_%s", (int)TrianglesOnBoundary.size(), LastTriangle->endpoints[0]->node->Name, LastTriangle->endpoints[1]->node->Name, LastTriangle->endpoints[2]->node->Name);
     3534    if (DoTecplotOutput) {
     3535      string NameofTempFile(filename);
     3536      NameofTempFile.append(NumberName);
     3537      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     3538      NameofTempFile.erase(npos, 1);
     3539      NameofTempFile.append(TecplotSuffix);
     3540      *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     3541      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     3542      WriteTecplotFile(out, tempstream, this, cloud, TriangleFilesWritten);
     3543      tempstream->close();
     3544      tempstream->flush();
     3545      delete(tempstream);
     3546    }
     3547
     3548    if (DoRaster3DOutput) {
     3549      string NameofTempFile(filename);
     3550      NameofTempFile.append(NumberName);
     3551      for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos))
     3552      NameofTempFile.erase(npos, 1);
     3553      NameofTempFile.append(Raster3DSuffix);
     3554      *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n";
     3555      tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc);
     3556      WriteRaster3dFile(out, tempstream, this, cloud);
     3557      IncludeSphereinRaster3D(out, tempstream, this, cloud);
     3558      tempstream->close();
     3559      tempstream->flush();
     3560      delete(tempstream);
     3561    }
     3562  }
     3563  if (DoTecplotOutput || DoRaster3DOutput)
     3564    TriangleFilesWritten++;
     3565};
  • src/tesselation.hpp

    rc0917c ra33931  
    3434class PointCloud;
    3535class Tesselation;
     36
     37#define DoTecplotOutput 1
     38#define DoRaster3DOutput 1
     39#define DoVRMLOutput 1
     40#define TecplotSuffix ".dat"
     41#define Raster3DSuffix ".r3d"
     42#define VRMLSUffix ".wrl"
    3643
    3744// ======================================================= some template functions =========================================
     
    115122
    116123    void GetNormalVector(Vector &NormalVector);
     124    void GetCenter(Vector *center);
    117125    bool GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection);
    118126    bool ContainsBoundaryLine(class BoundaryLineSet *line);
    119127    bool ContainsBoundaryPoint(class BoundaryPointSet *point);
     128    bool ContainsBoundaryPoint(class TesselPoint *point);
    120129    class BoundaryPointSet *GetThirdEndpoint(class BoundaryLineSet *line);
    121130    bool IsPresentTupel(class BoundaryPointSet *Points[3]);
    122     void GetCenter(Vector *center);
     131    bool IsPresentTupel(class BoundaryTriangleSet *T);
    123132
    124133    class BoundaryPointSet *endpoints[3];
     
    196205    void AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n);
    197206    void AddTesselationTriangle();
     207    void AddTesselationTriangle(int nr);
    198208    void RemoveTesselationTriangle(class BoundaryTriangleSet *triangle);
    199209    void RemoveTesselationLine(class BoundaryLineSet *line);
    200210    void RemoveTesselationPoint(class BoundaryPointSet *point);
    201211
    202     bool IsInside(Vector *pointer);
    203212    class BoundaryPointSet *GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2);
    204213
    205214    // concave envelope
    206215    void FindStartingTriangle(ofstream *out, const double RADIUS, class LinkedCell *LC);
    207     void FindSecondPointForTesselation(class TesselPoint* a, class TesselPoint* Candidate, Vector Oben, class TesselPoint*& OptCandidate, double Storage[3], double RADIUS, class LinkedCell *LC);
     216    void FindSecondPointForTesselation(class TesselPoint* a, Vector Oben, class TesselPoint*& OptCandidate, double Storage[3], double RADIUS, class LinkedCell *LC);
    208217    void FindThirdPointForTesselation(Vector NormalVector, Vector SearchDirection, Vector OldSphereCenter, class BoundaryLineSet *BaseLine, class TesselPoint *ThirdNode, CandidateList* &candidates, double *ShortestAngle, const double RADIUS, class LinkedCell *LC);
    209     bool FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N, LinkedCell *LC);
     218    bool FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC);
    210219    int CheckPresenceOfTriangle(ofstream *out, class TesselPoint *Candidates[3]);
     220    class BoundaryTriangleSet * GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3]);
    211221
    212222    // convex envelope
     
    215225    bool InsertStraddlingPoints(ofstream *out, PointCloud *cloud, LinkedCell *LC);
    216226    double RemovePointFromTesselatedSurface(ofstream *out, class BoundaryPointSet *point);
    217     bool FlipBaseline(ofstream *out, class BoundaryLineSet *Base);
    218     bool PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);
     227    class BoundaryLineSet * FlipBaseline(ofstream *out, class BoundaryLineSet *Base);
     228    double PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);
    219229    class BoundaryPointSet *IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base);
    220     map<int, int> FindAllDegeneratedTriangles();
     230    map<int, int> * FindAllDegeneratedTriangles();
     231    map<int, int> * FindAllDegeneratedLines();
    221232    void RemoveDegeneratedTriangles();
    222 
    223     list<TesselPoint*> * GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point);
    224     list<TesselPoint*> * GetNeighboursOnCircleOfConnectedPoints(ofstream *out, list<TesselPoint*> *connectedPoints, TesselPoint* Point, Vector* Reference);
     233    void AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC);
     234
     235    set<TesselPoint*> * GetAllConnectedPoints(ofstream *out, TesselPoint* Point);
     236    set<BoundaryTriangleSet*> *GetAllTriangles(ofstream *out, class BoundaryPointSet *Point);
     237    list<list<TesselPoint*> *> * GetPathsOfConnectedPoints(ofstream *out, TesselPoint* Point);
     238    list<list<TesselPoint*> *> * GetClosedPathsOfConnectedPoints(ofstream *out, TesselPoint* Point);
     239    list<TesselPoint*> * GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference = NULL);
    225240    list<BoundaryTriangleSet*> *FindTriangles(TesselPoint* Points[3]);
    226241    list<BoundaryTriangleSet*> * FindClosestTrianglesToPoint(ofstream *out, Vector *x, LinkedCell* LC);
     
    235250    void PrintAllBoundaryTriangles(ofstream *out);
    236251
     252    // store envelope in file
     253    void Output(ofstream *out, const char *filename, PointCloud *cloud);
    237254
    238255    PointMap PointsOnBoundary;
     
    257274    class BoundaryLineSet *BLS[3];
    258275    class BoundaryTriangleSet *BTS;
     276    class BoundaryTriangleSet *LastTriangle;
     277    int TriangleFilesWritten;
    259278
    260279  private:
     
    264283};
    265284
    266 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]);
    267 bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2);
    268 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC);
    269 TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*);
    270 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector);
    271 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase);
    272285
    273286#endif /* TESSELATION_HPP_ */
  • src/tesselationhelpers.cpp

    rc0917c ra33931  
    386386
    387387  return result;
     388};
     389
     390/** Gets the angle between a point and a reference relative to the provided center.
     391 * We have two shanks point and reference between which the angle is calculated
     392 * and by scalar product with OrthogonalVector we decide the interval.
     393 * @param point to calculate the angle for
     394 * @param reference to which to calculate the angle
     395 * @param OrthogonalVector points in direction of [pi,2pi] interval
     396 *
     397 * @return angle between point and reference
     398 */
     399double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector)
     400{
     401  if (reference.IsZero())
     402    return M_PI;
     403
     404  // calculate both angles and correct with in-plane vector
     405  if (point.IsZero())
     406    return M_PI;
     407  double phi = point.Angle(&reference);
     408  if (OrthogonalVector.ScalarProduct(&point) > 0) {
     409    phi = 2.*M_PI - phi;
     410  }
     411
     412  cout << Verbose(4) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl;
     413
     414  return phi;
    388415}
    389416
     417
     418/** Calculates the volume of a general tetraeder.
     419 * \param *a first vector
     420 * \param *a first vector
     421 * \param *a first vector
     422 * \param *a first vector
     423 * \return \f$ \frac{1}{6} \cdot ((a-d) \times (a-c) \cdot  (a-b)) \f$
     424 */
     425double CalculateVolumeofGeneralTetraeder(Vector *a, Vector *b, Vector *c, Vector *d)
     426{
     427  Vector Point, TetraederVector[3];
     428  double volume;
     429
     430  TetraederVector[0].CopyVector(a);
     431  TetraederVector[1].CopyVector(b);
     432  TetraederVector[2].CopyVector(c);
     433  for (int j=0;j<3;j++)
     434    TetraederVector[j].SubtractVector(d);
     435  Point.CopyVector(&TetraederVector[0]);
     436  Point.VectorProduct(&TetraederVector[1]);
     437  volume = 1./6. * fabs(Point.ScalarProduct(&TetraederVector[2]));
     438  return volume;
     439};
     440
     441
     442/** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.
     443 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not
     444 * make it bigger (i.e. closing one (the baseline) and opening two new ones).
     445 * \param TPS[3] nodes of the triangle
     446 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)
     447 */
     448bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])
     449{
     450  bool result = false;
     451  int counter = 0;
     452
     453  // check all three points
     454  for (int i=0;i<3;i++)
     455    for (int j=i+1; j<3; j++) {
     456      if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) {  // there already is a line
     457        LineMap::iterator FindLine;
     458        pair<LineMap::iterator,LineMap::iterator> FindPair;
     459        FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);
     460        for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {
     461          // If there is a line with less than two attached triangles, we don't need a new line.
     462          if (FindLine->second->triangles.size() < 2) {
     463            counter++;
     464            break;  // increase counter only once per edge
     465          }
     466        }
     467      } else { // no line
     468        cout << Verbose(1) << "The line between " << *nodes[i] << " and " << *nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;
     469        result = true;
     470      }
     471    }
     472  if ((!result) && (counter > 1)) {
     473    cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;
     474    result = true;
     475  }
     476  return result;
     477};
     478
     479
     480/** Sort function for the candidate list.
     481 */
     482bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)
     483{
     484  Vector BaseLineVector, OrthogonalVector, helper;
     485  if (candidate1->BaseLine != candidate2->BaseLine) {  // sanity check
     486    cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;
     487    //return false;
     488    exit(1);
     489  }
     490  // create baseline vector
     491  BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);
     492  BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     493  BaseLineVector.Normalize();
     494
     495  // 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!)
     496  helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);
     497  helper.SubtractVector(candidate1->point->node);
     498  OrthogonalVector.CopyVector(&helper);
     499  helper.VectorProduct(&BaseLineVector);
     500  OrthogonalVector.SubtractVector(&helper);
     501  OrthogonalVector.Normalize();
     502
     503  // calculate both angles and correct with in-plane vector
     504  helper.CopyVector(candidate1->point->node);
     505  helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     506  double phi = BaseLineVector.Angle(&helper);
     507  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
     508    phi = 2.*M_PI - phi;
     509  }
     510  helper.CopyVector(candidate2->point->node);
     511  helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);
     512  double psi = BaseLineVector.Angle(&helper);
     513  if (OrthogonalVector.ScalarProduct(&helper) > 0) {
     514    psi = 2.*M_PI - psi;
     515  }
     516
     517  cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;
     518  cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;
     519
     520  // return comparison
     521  return phi < psi;
     522};
     523
     524/**
     525 * Finds the point which is second closest to the provided one.
     526 *
     527 * @param Point to which to find the second closest other point
     528 * @param linked cell structure
     529 *
     530 * @return point which is second closest to the provided one
     531 */
     532TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)
     533{
     534  LinkedNodes *List = NULL;
     535  TesselPoint* closestPoint = NULL;
     536  TesselPoint* secondClosestPoint = NULL;
     537  double distance = 1e16;
     538  double secondDistance = 1e16;
     539  Vector helper;
     540  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     541
     542  LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
     543  for(int i=0;i<NDIM;i++) // store indices of this cell
     544    N[i] = LC->n[i];
     545  cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     546
     547  LC->GetNeighbourBounds(Nlower, Nupper);
     548  //cout << endl;
     549  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     550    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     551      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     552        List = LC->GetCurrentCell();
     553        //cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
     554        if (List != NULL) {
     555          for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     556            helper.CopyVector(Point);
     557            helper.SubtractVector((*Runner)->node);
     558            double currentNorm = helper. Norm();
     559            if (currentNorm < distance) {
     560              // remember second point
     561              secondDistance = distance;
     562              secondClosestPoint = closestPoint;
     563              // mark down new closest point
     564              distance = currentNorm;
     565              closestPoint = (*Runner);
     566              //cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *secondClosestPoint << "." << endl;
     567            }
     568          }
     569        } else {
     570          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
     571            << LC->n[2] << " is invalid!" << endl;
     572        }
     573      }
     574
     575  return secondClosestPoint;
     576};
     577
     578/**
     579 * Finds the point which is closest to the provided one.
     580 *
     581 * @param Point to which to find the closest other point
     582 * @param SecondPoint the second closest other point on return, NULL if none found
     583 * @param linked cell structure
     584 *
     585 * @return point which is closest to the provided one, NULL if none found
     586 */
     587TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)
     588{
     589  LinkedNodes *List = NULL;
     590  TesselPoint* closestPoint = NULL;
     591  SecondPoint = NULL;
     592  double distance = 1e16;
     593  double secondDistance = 1e16;
     594  Vector helper;
     595  int N[NDIM], Nlower[NDIM], Nupper[NDIM];
     596
     597  LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly
     598  for(int i=0;i<NDIM;i++) // store indices of this cell
     599    N[i] = LC->n[i];
     600  cout << Verbose(3) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;
     601
     602  LC->GetNeighbourBounds(Nlower, Nupper);
     603  //cout << endl;
     604  for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)
     605    for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)
     606      for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {
     607        List = LC->GetCurrentCell();
     608        //cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;
     609        if (List != NULL) {
     610          for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {
     611            helper.CopyVector(Point);
     612            helper.SubtractVector((*Runner)->node);
     613            double currentNorm = helper. Norm();
     614            if (currentNorm < distance) {
     615              secondDistance = distance;
     616              SecondPoint = closestPoint;
     617              distance = currentNorm;
     618              closestPoint = (*Runner);
     619              //cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;
     620            } else if (currentNorm < secondDistance) {
     621              secondDistance = currentNorm;
     622              SecondPoint = (*Runner);
     623              //cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;
     624            }
     625          }
     626        } else {
     627          cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","
     628            << LC->n[2] << " is invalid!" << endl;
     629        }
     630      }
     631
     632  return closestPoint;
     633};
     634
     635/** Returns the closest point on \a *Base with respect to \a *OtherBase.
     636 * \param *out output stream for debugging
     637 * \param *Base reference line
     638 * \param *OtherBase other base line
     639 * \return Vector on reference line that has closest distance
     640 */
     641Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase)
     642{
     643  // construct the plane of the two baselines (i.e. take both their directional vectors)
     644  Vector Normal;
     645  Vector Baseline, OtherBaseline;
     646  Baseline.CopyVector(Base->endpoints[1]->node->node);
     647  Baseline.SubtractVector(Base->endpoints[0]->node->node);
     648  OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node);
     649  OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node);
     650  Normal.CopyVector(&Baseline);
     651  Normal.VectorProduct(&OtherBaseline);
     652  Normal.Normalize();
     653  *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl;
     654
     655  // project one offset point of OtherBase onto this plane (and add plane offset vector)
     656  Vector NewOffset;
     657  NewOffset.CopyVector(OtherBase->endpoints[0]->node->node);
     658  NewOffset.SubtractVector(Base->endpoints[0]->node->node);
     659  NewOffset.ProjectOntoPlane(&Normal);
     660  NewOffset.AddVector(Base->endpoints[0]->node->node);
     661  Vector NewDirection;
     662  NewDirection.CopyVector(&NewOffset);
     663  NewDirection.AddVector(&OtherBaseline);
     664
     665  // calculate the intersection between this projected baseline and Base
     666  Vector *Intersection = new Vector;
     667  Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal);
     668  Normal.CopyVector(Intersection);
     669  Normal.SubtractVector(Base->endpoints[0]->node->node);
     670  *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl;
     671
     672  return Intersection;
     673};
     674
     675
     676/** Creates the objects in a VRML file.
     677 * \param *out output stream for debugging
     678 * \param *vrmlfile output stream for tecplot data
     679 * \param *Tess Tesselation structure with constructed triangles
     680 * \param *mol molecule structure with atom positions
     681 */
     682void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, PointCloud *cloud)
     683{
     684  TesselPoint *Walker = NULL;
     685  int i;
     686  Vector *center = cloud->GetCenter(out);
     687  if (vrmlfile != NULL) {
     688    //cout << Verbose(1) << "Writing Raster3D file ... ";
     689    *vrmlfile << "#VRML V2.0 utf8" << endl;
     690    *vrmlfile << "#Created by molecuilder" << endl;
     691    *vrmlfile << "#All atoms as spheres" << endl;
     692    cloud->GoToFirst();
     693    while (!cloud->IsEnd()) {
     694      Walker = cloud->GetPoint();
     695      *vrmlfile << "Sphere {" << endl << "  "; // 2 is sphere type
     696      for (i=0;i<NDIM;i++)
     697        *vrmlfile << Walker->node->x[i]-center->x[i] << " ";
     698      *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     699      cloud->GoToNext();
     700    }
     701
     702    *vrmlfile << "# All tesselation triangles" << endl;
     703    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     704      *vrmlfile << "1" << endl << "  "; // 1 is triangle type
     705      for (i=0;i<3;i++) { // print each node
     706        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     707          *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
     708        *vrmlfile << "\t";
     709      }
     710      *vrmlfile << "1. 0. 0." << endl;  // red as colour
     711      *vrmlfile << "18" << endl << "  0.5 0.5 0.5" << endl; // 18 is transparency type for previous object
     712    }
     713  } else {
     714    cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;
     715  }
     716  delete(center);
     717};
     718
     719/** Writes additionally the current sphere (i.e. the last triangle to file).
     720 * \param *out output stream for debugging
     721 * \param *rasterfile output stream for tecplot data
     722 * \param *Tess Tesselation structure with constructed triangles
     723 * \param *mol molecule structure with atom positions
     724 */
     725void IncludeSphereinRaster3D(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud)
     726{
     727  Vector helper;
     728  // include the current position of the virtual sphere in the temporary raster3d file
     729  Vector *center = cloud->GetCenter(out);
     730  // make the circumsphere's center absolute again
     731  helper.CopyVector(Tess->LastTriangle->endpoints[0]->node->node);
     732  helper.AddVector(Tess->LastTriangle->endpoints[1]->node->node);
     733  helper.AddVector(Tess->LastTriangle->endpoints[2]->node->node);
     734  helper.Scale(1./3.);
     735  helper.SubtractVector(center);
     736  // and add to file plus translucency object
     737  *rasterfile << "# current virtual sphere\n";
     738  *rasterfile << "8\n  25.0    0.6     -1.0 -1.0 -1.0     0.2        0 0 0 0\n";
     739  *rasterfile << "2\n  " << helper.x[0] << " " << helper.x[1] << " " << helper.x[2] << "\t" << 5. << "\t1 0 0\n";
     740  *rasterfile << "9\n  terminating special property\n";
     741  delete(center);
     742};
     743
     744/** Creates the objects in a raster3d file (renderable with a header.r3d).
     745 * \param *out output stream for debugging
     746 * \param *rasterfile output stream for tecplot data
     747 * \param *Tess Tesselation structure with constructed triangles
     748 * \param *mol molecule structure with atom positions
     749 */
     750void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud)
     751{
     752  TesselPoint *Walker = NULL;
     753  int i;
     754  Vector *center = cloud->GetCenter(out);
     755  if (rasterfile != NULL) {
     756    //cout << Verbose(1) << "Writing Raster3D file ... ";
     757    *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;
     758    *rasterfile << "@header.r3d" << endl;
     759    *rasterfile << "# All atoms as spheres" << endl;
     760    cloud->GoToFirst();
     761    while (!cloud->IsEnd()) {
     762      Walker = cloud->GetPoint();
     763      *rasterfile << "2" << endl << "  ";  // 2 is sphere type
     764      for (i=0;i<NDIM;i++)
     765        *rasterfile << Walker->node->x[i]-center->x[i] << " ";
     766      *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour
     767      cloud->GoToNext();
     768    }
     769
     770    *rasterfile << "# All tesselation triangles" << endl;
     771    *rasterfile << "8\n  25. -1.   1. 1. 1.   0.0    0 0 0 2\n  SOLID     1.0 0.0 0.0\n  BACKFACE  0.3 0.3 1.0   0 0\n";
     772    for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {
     773      *rasterfile << "1" << endl << "  ";  // 1 is triangle type
     774      for (i=0;i<3;i++) {  // print each node
     775        for (int j=0;j<NDIM;j++)  // and for each node all NDIM coordinates
     776          *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";
     777        *rasterfile << "\t";
     778      }
     779      *rasterfile << "1. 0. 0." << endl;  // red as colour
     780      //*rasterfile << "18" << endl << "  0.5 0.5 0.5" << endl;  // 18 is transparency type for previous object
     781    }
     782    *rasterfile << "9\n#  terminating special property\n";
     783  } else {
     784    cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;
     785  }
     786  IncludeSphereinRaster3D(out, rasterfile, Tess, cloud);
     787  delete(center);
     788};
     789
     790/** This function creates the tecplot file, displaying the tesselation of the hull.
     791 * \param *out output stream for debugging
     792 * \param *tecplot output stream for tecplot data
     793 * \param N arbitrary number to differentiate various zones in the tecplot format
     794 */
     795void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, PointCloud *cloud, int N)
     796{
     797  if ((tecplot != NULL) && (TesselStruct != NULL)) {
     798    // write header
     799    *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;
     800    *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\" \"U\"" << endl;
     801    *tecplot << "ZONE T=\"" << N << "-";
     802    for (int i=0;i<3;i++)
     803      *tecplot << (i==0 ? "" : "_") << TesselStruct->LastTriangle->endpoints[i]->node->Name;
     804    *tecplot << "\", N=" << TesselStruct->PointsOnBoundary.size() << ", E=" << TesselStruct->TrianglesOnBoundary.size() << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;
     805    int i=0;
     806    for (cloud->GoToFirst(); !cloud->IsEnd(); cloud->GoToNext(), i++);
     807    int *LookupList = new int[i];
     808    for (cloud->GoToFirst(), i=0; !cloud->IsEnd(); cloud->GoToNext(), i++)
     809      LookupList[i] = -1;
     810
     811    // print atom coordinates
     812    *out << Verbose(2) << "The following triangles were created:";
     813    int Counter = 1;
     814    TesselPoint *Walker = NULL;
     815    for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {
     816      Walker = target->second->node;
     817      LookupList[Walker->nr] = Counter++;
     818      *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << target->second->value << endl;
     819    }
     820    *tecplot << endl;
     821    // print connectivity
     822    for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {
     823      *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;
     824      *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;
     825    }
     826    delete[] (LookupList);
     827    *out << endl;
     828  }
     829};
     830
     831/** Calculates the concavity for each of the BoundaryPointSet's in a Tesselation.
     832 * Sets BoundaryPointSet::value equal to the number of connected lines that are not convex.
     833 * \param *out output stream for debugging
     834 * \param *TesselStruct pointer to Tesselation structure
     835 */
     836void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct)
     837{
     838  class BoundaryPointSet *point = NULL;
     839  class BoundaryLineSet *line = NULL;
     840
     841  //*out << Verbose(2) << "Begin of CalculateConcavityPerBoundaryPoint" << endl;
     842  // calculate remaining concavity
     843  for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
     844    point = PointRunner->second;
     845    *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
     846    point->value = 0;
     847    for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     848      line = LineRunner->second;
     849      //*out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl;
     850      if (!line->CheckConvexityCriterion(out))
     851        point->value += 1;
     852    }
     853  }
     854  //*out << Verbose(2) << "End of CalculateConcavityPerBoundaryPoint" << endl;
     855};
     856
     857
     858/** Checks whether each BoundaryLineSet in the Tesselation has two triangles.
     859 * \param *out output stream for debugging
     860 * \param *TesselStruct
     861 * \return true - all have exactly two triangles, false - some not, list is printed to screen
     862 */
     863bool CheckListOfBaselines(ofstream *out, Tesselation *TesselStruct)
     864{
     865  LineMap::iterator testline;
     866  bool result = false;
     867  int counter = 0;
     868
     869  *out << Verbose(1) << "Check: List of Baselines with not two connected triangles:" << endl;
     870  for (testline = TesselStruct->LinesOnBoundary.begin(); testline != TesselStruct->LinesOnBoundary.end(); testline++) {
     871    if (testline->second->triangles.size() != 2) {
     872      *out << Verbose(1) << *testline->second << "\t" << testline->second->triangles.size() << endl;
     873      counter++;
     874    }
     875  }
     876  if (counter == 0) {
     877    *out << Verbose(1) << "None." << endl;
     878    result = true;
     879  }
     880  return result;
     881}
     882
  • src/tesselationhelpers.hpp

    rc0917c ra33931  
    1818#endif
    1919
    20 #define HULLEPSILON 1e-7
    21 
    2220#include <gsl/gsl_linalg.h>
    2321#include <gsl/gsl_matrix.h>
     
    2624#include <gsl/gsl_vector.h>
    2725
     26#include "defs.hpp"
     27#include "tesselation.hpp"
    2828#include "vector.hpp"
     29
     30#define HULLEPSILON 1e-10
    2931
    3032double DetGet(gsl_matrix *A, int inPlace);
     
    3537double MinIntersectDistance(const gsl_vector * x, void *params);
    3638bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4);
     39double CalculateVolumeofGeneralTetraeder(Vector *a, Vector *b, Vector *c, Vector *d);
     40double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector);
     41
     42bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]);
     43bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2);
     44TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC);
     45TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*);
     46Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase);
     47
     48void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, PointCloud *cloud, int N);
     49void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud);
     50void IncludeSphereinRaster3D(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud);
     51void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, PointCloud *cloud);
     52void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct);
     53
     54bool CheckListOfBaselines(ofstream *out, Tesselation *TesselStruct);
     55
    3756
    3857#endif /* TESSELATIONHELPERS_HPP_ */
  • src/tesselationunittest.cpp

    • Property mode changed from 100755 to 100644
  • src/tesselationunittest.hpp

    • Property mode changed from 100755 to 100644
  • src/vector.cpp

    rc0917c ra33931  
    225225  Direction.CopyVector(LineVector);
    226226  Direction.SubtractVector(Origin);
     227  Direction.Normalize();
    227228  //*out << Verbose(4) << "INFO: Direction is " << Direction << "." << endl;
    228229  factor = Direction.ScalarProduct(PlaneNormal);
     
    234235  helper.SubtractVector(Origin);
    235236  factor = helper.ScalarProduct(PlaneNormal)/factor;
     237  if (factor < MYEPSILON) { // Origin is in-plane
     238    //*out << Verbose(2) << "Origin of line is in-plane, simple." << endl;
     239    CopyVector(Origin);
     240    return true;
     241  }
    236242  //factor = Origin->ScalarProduct(PlaneNormal)*(-PlaneOffset->ScalarProduct(PlaneNormal))/(Direction.ScalarProduct(PlaneNormal));
    237243  Direction.Scale(factor);
  • src/vectorunittest.cpp

    rc0917c ra33931  
    1313#include <cppunit/ui/text/TestRunner.h>
    1414
     15#include "defs.hpp"
     16#include "vector.hpp"
    1517#include "vectorunittest.hpp"
    16 #include "vector.hpp"
    17 #include "defs.hpp"
    1818
    1919/********************************************** Test classes **************************************/
Note: See TracChangeset for help on using the changeset viewer.