Changes in / [c0917c:a33931]
- Location:
- src
- Files:
-
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Makefile.am
rc0917c ra33931 2 2 HEADER = 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 3 3 4 noinst_PROGRAMS = VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest 4 noinst_PROGRAMS = VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest TesselationUnitTest 5 5 6 6 bin_PROGRAMS = molecuilder joiner analyzer … … 11 11 analyzer_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 12 12 13 TESTS = VectorUnitTest MemoryAllocatorUnitTest 13 TESTS = VectorUnitTest MemoryAllocatorUnitTest MemoryUsageObserverUnitTest TesselationUnitTest 14 14 check_PROGRAMS = $(TESTS) 15 15 VectorUnitTest_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 16 16 VectorUnitTest_CXXFLAGS = $(CPPUNIT_CFLAGS) 17 17 VectorUnitTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl 18 TesselationUnitTest_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 19 TesselationUnitTest_CXXFLAGS = $(CPPUNIT_CFLAGS) 20 TesselationUnitTest_LDFLAGS = $(CPPUNIT_LIBS) -ldl 18 21 19 22 MemoryAllocatorUnitTest_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 62 62 atom::~atom() 63 63 { 64 Free(&ComponentNr); 64 Free<int>(&ComponentNr, "atom::~atom: *ComponentNr"); 65 Free<char *>(&Name, "atom::~atom: *Name"); 65 66 }; 66 67 -
src/boundary.cpp
rc0917c ra33931 113 113 ; 114 114 115 /** Creates the objects in a VRML file.116 * \param *out output stream for debugging117 * \param *vrmlfile output stream for tecplot data118 * \param *Tess Tesselation structure with constructed triangles119 * \param *mol molecule structure with atom positions120 */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 type135 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 colour138 }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 type144 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 colour150 }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 type155 for (i=0;i<3;i++) { // print each node156 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates157 *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";158 *vrmlfile << "\t";159 }160 *vrmlfile << "1. 0. 0." << endl; // red as colour161 *vrmlfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object162 }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 debugging171 * \param *rasterfile output stream for tecplot data172 * \param *Tess Tesselation structure with constructed triangles173 * \param *mol molecule structure with atom positions174 */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 type189 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 colour192 }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 type198 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 colour204 }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 type210 for (i=0;i<3;i++) { // print each node211 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates212 *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";213 *rasterfile << "\t";214 }215 *rasterfile << "1. 0. 0." << endl; // red as colour216 //*rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object217 }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 debugging227 * \param *tecplot output stream for tecplot data228 * \param N arbitrary number to differentiate various zones in the tecplot format229 */230 void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol, int N)231 {232 if ((tecplot != NULL) && (TesselStruct != NULL)) {233 // write header234 *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 coordinates242 *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 connectivity252 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 261 115 262 116 /** Determines the boundary points of a cluster. … … 537 391 538 392 // flip the line 539 if ( !mol->TesselStruct->PickFarthestofTwoBaselines(out, line))393 if (mol->TesselStruct->PickFarthestofTwoBaselines(out, line) == 0.) 540 394 *out << Verbose(1) << "ERROR: Correction of concave baselines failed!" << endl; 541 else 395 else { 396 mol->TesselStruct->FlipBaseline(out, line); 542 397 *out << Verbose(1) << "INFO: Correction of concave baselines worked." << endl; 398 } 543 399 } 544 400 } … … 577 433 578 434 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 */ 444 bool 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; 579 471 }; 580 472 … … 609 501 class BoundaryLineSet *line = NULL; 610 502 bool Concavity; 503 char dummy[MAXSTRINGSIZE]; 611 504 PointMap::iterator PointRunner, PointAdvance; 612 505 LineMap::iterator LineRunner, LineAdvance; … … 621 514 } 622 515 623 //CalculateConcavityPerBoundaryPoint(out, TesselStruct);624 StoreTrianglesinFile(out, mol, filename, "-first");625 626 516 // First step: RemovePointFromTesselatedSurface 517 int run = 0; 518 double tmp; 627 519 do { 628 520 Concavity = false; 521 sprintf(dummy, "-first-%d", run); 522 //CalculateConcavityPerBoundaryPoint(out, TesselStruct); 523 StoreTrianglesinFile(out, mol, filename, dummy); 524 629 525 PointRunner = TesselStruct->PointsOnBoundary.begin(); 630 526 PointAdvance = PointRunner; // we need an advanced point, as the PointRunner might get removed … … 636 532 line = LineRunner->second; 637 533 *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 } 644 543 } 645 544 PointRunner = PointAdvance; 646 545 } 647 546 547 sprintf(dummy, "-second-%d", run); 648 548 //CalculateConcavityPerBoundaryPoint(out, TesselStruct); 649 //StoreTrianglesinFile(out, mol, filename, "-second");549 StoreTrianglesinFile(out, mol, filename, dummy); 650 550 651 551 // second step: PickFarthestofTwoBaselines … … 658 558 // take highest of both lines 659 559 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 } 662 566 } 663 567 LineRunner = LineAdvance; 664 568 } 569 run++; 665 570 } 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 666 594 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, ""); 691 596 692 597 // end 598 *out << Verbose(1) << "Volume is " << volume << "." << endl; 693 599 *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl; 694 600 return volume; 695 601 }; 696 602 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 debugging700 * \param *TesselStruct pointer to Tesselation structure701 */702 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct)703 {704 class BoundaryPointSet *point = NULL;705 class BoundaryLineSet *line = NULL;706 // calculate remaining concavity707 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 debugging722 * \param *mol molecule with atoms and bonds723 * \param *filename prefix of filename724 * \param *extraSuffix intermediate suffix725 */726 void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix)727 {728 // 4. Store triangles in tecplot file729 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 };750 603 751 604 /** Determines the volume of a cluster. … … 794 647 795 648 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 */ 657 void 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 }; 798 681 799 682 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density. … … 958 841 if ((*ListRunner)->TesselStruct == NULL) { 959 842 *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); 961 844 } 962 845 i++; … … 1080 963 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return 1081 964 * \param *LCList atoms in LinkedCell list 965 * \param RADIUS radius of the virtual sphere 1082 966 * \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 */ 968 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const double RADIUS, const char *filename = NULL) 1086 969 { 1087 int N = 0;1088 970 bool freeLC = false; 1089 ofstream *tempstream = NULL;1090 char NumberName[255];1091 int TriangleFilesWritten = 0;1092 971 1093 972 *out << Verbose(1) << "Entering search for non convex hull. " << endl; … … 1103 982 LineMap::iterator testline; 1104 983 *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 1108 988 if (LCList == NULL) { 1109 989 LCList = new LinkedCell(mol, 2.*RADIUS); … … 1111 991 } 1112 992 993 // 1. get starting triangle 1113 994 mol->TesselStruct->FindStartingTriangle(out, RADIUS, LCList); 1114 995 996 // 2. expand from there 1115 997 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)) { 1121 1000 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) 1125 1005 cerr << "WARNING: FindNextSuitableTriangle failed." << endl; 1006 1126 1007 // 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 } 1179 1012 } 1013 baseline = mol->TesselStruct->LinesOnBoundary.end(); 1014 *out << Verbose(2) << "Baseline set to end." << endl; 1180 1015 } else { 1181 1016 //cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->triangles.size() << " triangles adjacent" << endl; … … 1184 1019 } 1185 1020 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 } 1187 1025 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 // } 1193 1045 1194 1046 // Purges surplus triangles. 1195 1047 mol->TesselStruct->RemoveDegeneratedTriangles(); 1196 1048 1049 // check envelope for consistency 1050 CheckListOfBaselines(out, mol->TesselStruct); 1051 1197 1052 // 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, ""); 1262 1055 1263 1056 if (freeLC) … … 1265 1058 *out << Verbose(0) << "End of FindNonConvexBorder\n"; 1266 1059 }; 1060 1267 1061 1268 1062 /** Finds a hole of sufficient size in \a this molecule to embed \a *srcmol into it. -
src/boundary.hpp
rc0917c ra33931 16 16 17 17 #define DEBUG 1 18 #define DoSingleStepOutput 018 #define DoSingleStepOutput 1 19 19 #define SingleStepWidth 1 20 #define DoTecplotOutput 121 #define DoRaster3DOutput 122 #define DoVRMLOutput 123 #define TecplotSuffix ".dat"24 #define Raster3DSuffix ".r3d"25 #define VRMLSUffix ".wrl"26 20 27 21 #define DistancePair pair < double, atom* > … … 38 32 molecule * FillBoxWithMolecule(ofstream *out, MoleculeListClass *List, molecule *filler, config &configuration, double distance[NDIM], double RandAtomDisplacement, double RandMolDisplacement, bool DoRandomRotation); 39 33 void 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);34 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LC, const double RADIUS, const char *tempbasename); 41 35 double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename); 42 36 void FindNextSuitablePoint(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC); 43 37 Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol); 44 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct);45 38 void StoreTrianglesinFile(ofstream *out, molecule *mol, const char *filename, const char *extraSuffix); 39 bool RemoveAllBoundaryPoints(ofstream *out, class Tesselation *TesselStruct, molecule *mol, char *filename); 46 40 47 41 -
src/builder.cpp
rc0917c ra33931 1018 1018 cin >> nr; 1019 1019 count = 1; 1020 for( 1020 for(MoleculeList::iterator ListRunner = molecules->ListOfMolecules.begin(); ListRunner != molecules->ListOfMolecules.end(); ListRunner++) 1021 1021 if (nr == (*ListRunner)->IndexNr) { 1022 1022 mol = *ListRunner; 1023 1023 molecules->ListOfMolecules.erase(ListRunner); 1024 1024 delete(mol); 1025 break; 1025 1026 } 1026 1027 break; … … 1075 1076 1076 1077 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 } 1078 1094 break; 1079 1095 … … 1626 1642 cout << Verbose(0) << "Evaluating non-convex envelope."; 1627 1643 cout << Verbose(1) << "Using rolling ball of radius " << atof(argv[argptr]) << " and storing tecplot data in " << argv[argptr+1] << "." << endl; 1628 1644 start = clock(); 1629 1645 LinkedCell LCList(mol, atof(argv[argptr])*2.); 1630 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, a rgv[argptr+1], atof(argv[argptr]));1646 FindNonConvexBorder((ofstream *)&cout, mol, &LCList, atof(argv[argptr]), argv[argptr+1]); 1631 1647 //FindDistributionOfEllipsoids((ofstream *)&cout, &T, &LCList, N, number, filename.c_str()); 1632 1633 1648 end = clock(); 1649 cout << Verbose(0) << "Clocks for this operation: " << (end-start) << ", time: " << ((double)(end-start)/CLOCKS_PER_SEC) << "s." << endl; 1634 1650 argptr+=2; 1635 1651 } … … 1654 1670 case 'L': 1655 1671 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 } 1663 1686 break; 1664 1687 case 'P': … … 1710 1733 ExitFlag = 1; 1711 1734 SaveFlag = true; 1712 cout << Verbose(1) << "Translating all ions to new origin." << endl;1735 cout << Verbose(1) << "Translating all ions by given vector." << endl; 1713 1736 for (int i=NDIM;i--;) 1714 1737 x.x[i] = atof(argv[argptr+i]); … … 1716 1739 argptr+=3; 1717 1740 } 1741 break; 1718 1742 case 'T': 1719 1743 ExitFlag = 1; … … 1724 1748 ExitFlag = 1; 1725 1749 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; 1727 1751 for (int i=NDIM;i--;) 1728 1752 x.x[i] = atof(argv[argptr+i]); … … 1865 1889 case 'o': 1866 1890 ExitFlag = 1; 1867 if ((argptr >= argc) || (argv[argptr][0] == '-')){1891 if ((argptr+1 >= argc) || (argv[argptr][0] == '-')){ 1868 1892 ExitFlag = 255; 1869 cerr << "Not enough or invalid arguments given for convex envelope: -o < tecplotoutput file>" << endl;1893 cerr << "Not enough or invalid arguments given for convex envelope: -o <convex output file> <non-convex output file>" << endl; 1870 1894 } else { 1871 1895 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; 1873 1898 LinkedCell LCList(mol, 10.); 1874 1899 //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]); 1877 1902 double volumedifference = ConvexizeNonconvexEnvelope((ofstream *)&cout, mol->TesselStruct, mol, argv[argptr]); 1878 1903 double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, mol->TesselStruct, &configuration); 1879 1904 cout << Verbose(0) << "The tesselated volume area is " << clustervolume << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl; 1880 1905 cout << Verbose(0) << "The non-convex tesselated volume area is " << clustervolume-volumedifference << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl; 1881 argptr+= 1;1906 argptr+=2; 1882 1907 } 1883 1908 break; -
src/config.cpp
rc0917c ra33931 1011 1011 repetition--; 1012 1012 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; 1014 1017 } else { 1015 1018 // 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 96 96 //cout << Verbose(2) << *Walker << " goes into cell " << n[0] << ", " << n[1] << ", " << n[2] << " with No. " << index << "." << endl; 97 97 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 */ 108 LinkedCell::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; 98 168 } 99 169 cout << "done." << endl; -
src/linkedcell.hpp
rc0917c ra33931 44 44 LinkedCell(); 45 45 LinkedCell(PointCloud *set, double RADIUS); 46 LinkedCell(LinkedNodes *set, double radius); 46 47 ~LinkedCell(); 47 48 LinkedNodes* GetCurrentCell(); -
src/moleculelist.cpp
rc0917c ra33931 5 5 */ 6 6 7 #include "boundary.hpp" 7 8 #include "config.hpp" 8 9 #include "molecules.hpp" … … 292 293 /** Embedding merge of a given set of molecules into one. 293 294 * 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 center295 * \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! 298 299 */ 299 300 bool MoleculeListClass::EmbedMerge(molecule *mol, molecule *srcmol) 300 301 { 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; 302 304 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); 310 347 return true; 311 348 }; -
src/molecules.cpp
rc0917c ra33931 687 687 { 688 688 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 690 694 char *endname = strchr(molname, '.'); 691 695 if ((endname == NULL) || (endname < molname)) … … 1193 1197 /** Evaluates the potential energy used for constrained molecular dynamics. 1194 1198 * \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 between1199 * 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 1196 1200 * trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point. 1197 1201 * Note that for the second term we have to solve the following linear system: … … 1587 1591 * \param endstep stating final configuration in molecule::Trajectories 1588 1592 * \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() 1589 1594 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories 1590 1595 */ 1591 bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration )1596 bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration, bool MapByIdentity) 1592 1597 { 1593 1598 molecule *mol = NULL; … … 1598 1603 atom **PermutationMap = NULL; 1599 1604 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 } 1601 1615 1602 1616 // check whether we have sufficient space in Trajectories for each atom … … 3747 3761 * \param *&SortIndex Mapping array of size molecule::AtomCount 3748 3762 * \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 3749 3764 */ 3750 3765 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) -
src/molecules.hpp
rc0917c ra33931 182 182 double MinimiseConstrainedPotential(ofstream *out, atom **&permutation, int startstep, int endstep, bool IsAngstroem); 183 183 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); 185 185 186 186 bool CheckBounds(const Vector *x) const; -
src/tesselation.cpp
rc0917c ra33931 6 6 */ 7 7 8 #include "helpers.hpp" 9 #include "linkedcell.hpp" 10 #include "memoryallocator.hpp" 8 11 #include "tesselation.hpp" 9 #include "memoryallocator.hpp" 12 #include "tesselationhelpers.hpp" 13 #include "vector.hpp" 14 15 class molecule; 10 16 11 17 // ======================================== Points on Boundary ================================= … … 37 43 BoundaryPointSet::~BoundaryPointSet() 38 44 { 39 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;45 //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 40 46 if (!lines.empty()) 41 47 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; … … 67 73 ostream & operator <<(ostream &ost, BoundaryPointSet &a) 68 74 { 69 ost << "[" << a.Nr << "|" << a.node->Name << " ]";75 ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]"; 70 76 return ost; 71 77 } … … 125 131 for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++) 126 132 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; 128 134 endpoints[i]->lines.erase(Runner); 129 135 break; 130 136 } 131 137 } 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 } 134 141 } 135 142 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; 137 144 if (endpoints[i] != NULL) { 138 145 delete(endpoints[i]); … … 168 175 169 176 /** 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. 171 178 * If greater/equal M_PI than we are convex. 172 179 * \param *out output stream for debugging … … 178 185 // get the two triangles 179 186 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; 181 188 return true; 182 189 } … … 201 208 NormalCheck.Scale(sign); 202 209 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 } 204 216 node = runner->second->GetThirdEndpoint(this); 205 217 if (node != NULL) { … … 211 223 i++; 212 224 } 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; 214 226 return true; 215 227 } … … 217 229 //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl; 218 230 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; 220 232 return true; 221 233 } 234 BaseLineNormal.Scale(-1.); 222 235 double angle = GetAngle(helper[0], helper[1], BaseLineNormal); 223 236 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; 225 238 return true; 226 239 } 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; 228 241 return false; 229 242 } … … 262 275 ostream & operator <<(ostream &ost, BoundaryLineSet &a) 263 276 { 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 << "]"; 265 278 return ost; 266 279 }; … … 332 345 for (int i = 0; i < 3; i++) { 333 346 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 } 336 350 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; 338 352 delete (lines[i]); 339 353 lines[i] = NULL; … … 341 355 } 342 356 } 343 cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;357 //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl; 344 358 }; 345 359 … … 361 375 * We call Vector::GetIntersectionWithPlane() to receive the intersection point with the plane 362 376 * 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 opposite364 * 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. 366 380 * \param *out output stream for debugging 367 381 * \param *MolCenter offset vector of line … … 395 409 exit(255); 396 410 } 397 CrossPoint.SubtractVector(endpoints[i%3]->node->node); 411 CrossPoint.SubtractVector(endpoints[i%3]->node->node); // cross point was returned as absolute vector 398 412 399 413 // check whether intersection is inside or not by comparing length of intersection and length of cross point 400 if ((CrossPoint.NormSquared() - helper.NormSquared()) > -MYEPSILON) { // inside414 if ((CrossPoint.NormSquared() - helper.NormSquared()) < MYEPSILON) { // inside 401 415 return true; 402 416 } else { // outside! … … 426 440 for(int i=0;i<3;i++) 427 441 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 */ 450 bool BoundaryTriangleSet::ContainsBoundaryPoint(class TesselPoint *point) 451 { 452 for(int i=0;i<3;i++) 453 if (point == endpoints[i]->node) 428 454 return true; 429 455 return false; … … 451 477 }; 452 478 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 */ 483 bool 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 453 500 /** Returns the endpoint which is not contained in the given \a *line. 454 501 * \param *line baseline defining two endpoints … … 485 532 ostream &operator <<(ostream &ost, BoundaryTriangleSet &a) 486 533 { 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 << "]"; 489 536 return ost; 490 537 }; … … 505 552 TesselPoint::~TesselPoint() 506 553 { 507 Free (&Name);554 Free<char *>(&Name, "~TesselPoint - *Name"); 508 555 }; 509 556 … … 512 559 ostream & operator << (ostream &ost, const TesselPoint &a) 513 560 { 514 ost << "[" << (a.Name) << "|" << &a<< "]";561 ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node << "]"; 515 562 return ost; 516 563 }; … … 569 616 TrianglesOnBoundaryCount = 0; 570 617 InternalPointer = PointsOnBoundary.begin(); 618 LastTriangle = NULL; 619 TriangleFilesWritten = 0; 571 620 } 572 621 ; … … 585 634 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 586 635 } 636 cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl; 587 637 } 588 638 ; … … 1052 1102 Vector *Center = cloud->GetCenter(out); 1053 1103 list<BoundaryTriangleSet*> *triangles = NULL; 1104 bool AddFlag = false; 1105 LinkedCell *BoundaryPoints = NULL; 1054 1106 1055 1107 *out << Verbose(1) << "Begin of InsertStraddlingPoints" << endl; 1056 1108 1057 1109 cloud->GoToFirst(); 1110 BoundaryPoints = new LinkedCell(this, 5.); 1058 1111 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 } 1060 1117 Walker = cloud->GetPoint(); 1061 1118 *out << Verbose(2) << "Current point is " << *Walker << "." << endl; 1062 1119 // 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; 1066 1124 cloud->GoToNext(); 1067 1125 continue; 1068 1126 } else { 1069 BTS = triangles->front();1070 1127 } 1071 1128 *out << Verbose(2) << "Closest triangle is " << *BTS << "." << endl; … … 1090 1147 // add Walker to boundary points 1091 1148 *out << Verbose(2) << "Adding " << *Walker << " to BoundaryPoints." << endl; 1149 AddFlag = true; 1092 1150 if (AddBoundaryPoint(Walker,0)) 1093 1151 NewPoint = BPS[0]; … … 1180 1238 } else { 1181 1239 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; 1183 1241 TPS[n] = (InsertUnique.first)->second; 1184 1242 } … … 1197 1255 1198 1256 if (a->lines.find(b->node->nr) != a->lines.end()) { 1199 LineMap::iterator FindLine ;1257 LineMap::iterator FindLine = a->lines.find(b->node->nr); 1200 1258 pair<LineMap::iterator,LineMap::iterator> FindPair; 1201 1259 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++) { 1204 1263 // If there is a line with less than two attached triangles, we don't need a new line. 1205 1264 if (FindLine->second->triangles.size() < 2) { 1206 1265 insertNewLine = false; 1207 cout << Verbose( 3) << "Using existing line " << *FindLine->second << endl;1266 cout << Verbose(4) << "Using existing line " << *FindLine->second << endl; 1208 1267 1209 1268 BPS[0] = FindLine->second->endpoints[0]; … … 1232 1291 void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) 1233 1292 { 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; 1235 1294 BPS[0] = a; 1236 1295 BPS[1] = b; … … 1242 1301 }; 1243 1302 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. 1246 1305 */ 1247 1306 void Tesselation::AddTesselationTriangle() … … 1252 1311 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1253 1312 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 */ 1324 void 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; 1254 1333 1255 1334 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet … … 1272 1351 cout << Verbose(5) << *triangle->lines[i] << " is no more attached to any triangle, erasing." << endl; 1273 1352 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 1277 1366 } else 1278 1367 cerr << "ERROR: This line " << i << " has already been free'd." << endl; … … 1294 1383 if (line == NULL) 1295 1384 return; 1296 // get other endpoint number offinding copies of same line1385 // get other endpoint number for finding copies of same line 1297 1386 if (line->endpoints[1] != NULL) 1298 1387 Numbers[0] = line->endpoints[1]->Nr; … … 1321 1410 cout << Verbose(5) << *line->endpoints[i] << " has no more lines it's attached to, erasing." << endl; 1322 1411 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 1326 1419 } else 1327 1420 cerr << "ERROR: Endpoint " << i << " has already been free'd." << endl; … … 1390 1483 } 1391 1484 // 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; 1394 1487 } 1395 1488 } … … 1400 1493 *out << Verbose(2) << "End of CheckPresenceOfTriangle" << endl; 1401 1494 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 */ 1505 class 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; 1402 1544 }; 1403 1545 … … 1461 1603 CandidateList *OptCandidates = new CandidateList(); 1462 1604 for (int k=0;k<NDIM;k++) { 1605 Oben.Zero(); 1463 1606 Oben.x[k] = 1.; 1464 1607 FirstPoint = MaxPoint[k]; … … 1469 1612 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. 1470 1613 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_... 1472 1615 SecondPoint = OptCandidate; 1473 1616 if (SecondPoint == NULL) // have we found a second point? 1474 1617 continue; 1475 else1476 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";1477 1618 1478 1619 helper.CopyVector(FirstPoint->node); … … 1496 1637 1497 1638 // adding point 1 and point 2 and add the line between them 1639 cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl; 1498 1640 AddTesselationPoint(FirstPoint, 0); 1641 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n"; 1499 1642 AddTesselationPoint(SecondPoint, 1); 1500 1643 AddTesselationLine(TPS[0], TPS[1], 0); … … 1569 1712 * @param *LC LinkedCell structure with neighbouring points 1570 1713 */ 1571 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N,LinkedCell *LC)1714 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC) 1572 1715 { 1573 1716 cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n"; … … 1604 1747 CircleRadius = RADIUS*RADIUS - radius/4.; 1605 1748 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; 1607 1750 1608 1751 // construct old center … … 1691 1834 result = false; 1692 1835 } 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. 1694 1837 AddTesselationPoint((*it)->point, 0); 1695 1838 AddTesselationPoint(BaseRay->endpoints[0]->node, 1); … … 1732 1875 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point)) 1733 1876 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 1734 1882 } 1735 1883 … … 1750 1898 * \param *out output stream for debugging 1751 1899 * \param *Base line to be flipped 1752 * \return NULL - con cave, otherwise endpoint that makes it concave1900 * \return NULL - convex, otherwise endpoint that makes it concave 1753 1901 */ 1754 1902 class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base) … … 1827 1975 * \param *out output stream for debugging 1828 1976 * \param *Base line to be flipped 1829 * \return true - line was changed, false - same line as before1830 */ 1831 boolTesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)1977 * \return volume change due to flipping (0 - then no flipped occured) 1978 */ 1979 double Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base) 1832 1980 { 1833 1981 class BoundaryLineSet *OtherBase; 1834 1982 Vector *ClosestPoint[2]; 1983 double volume; 1835 1984 1836 1985 int m=0; … … 1852 2001 Distance.CopyVector(ClosestPoint[1]); 1853 2002 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); 1854 2006 1855 2007 // delete the temporary other base line and the closest points … … 1866 2018 if (Base->triangles.size() < 2) { 1867 2019 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 1868 return false;2020 return 0.; 1869 2021 } 1870 2022 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 1876 2028 if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip 1877 2029 *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; 1880 2032 } else { // Base higher than OtherBase -> do nothing 1881 2033 *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 } 1925 2037 }; 1926 2038 … … 1930 2042 * \param *out output stream for debugging 1931 2043 * \param *Base line to be flipped 1932 * \return true - flipping successful, false- something went awry1933 */ 1934 boolTesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)2044 * \return pointer to allocated new baseline - flipping successful, NULL - something went awry 2045 */ 2046 class BoundaryLineSet * Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base) 1935 2047 { 1936 2048 class BoundaryLineSet *OldLines[4], *NewLine; … … 1946 2058 if (Base->triangles.size() < 2) { 1947 2059 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 1948 return false;2060 return NULL; 1949 2061 } 1950 2062 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 1982 2094 if (i<4) { 1983 2095 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 1984 return false;2096 return NULL; 1985 2097 } 1986 2098 for (int j=0;j<4;j++) 1987 2099 if (OldLines[j] == NULL) { 1988 2100 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 1989 return false;2101 return NULL; 1990 2102 } 1991 2103 for (int j=0;j<2;j++) 1992 2104 if (OldPoints[j] == NULL) { 1993 2105 *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl; 1994 return false;2106 return NULL; 1995 2107 } 1996 2108 … … 2024 2136 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[0]); 2025 2137 BTS->GetNormalVector(BaseLineNormal); 2026 TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[0], BTS));2138 AddTesselationTriangle(OldTriangleNrs[0]); 2027 2139 *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl; 2028 2140 … … 2032 2144 BTS = new class BoundaryTriangleSet(BLS, OldTriangleNrs[1]); 2033 2145 BTS->GetNormalVector(BaseLineNormal); 2034 TrianglesOnBoundary.insert(TrianglePair(OldTriangleNrs[1], BTS));2146 AddTesselationTriangle(OldTriangleNrs[1]); 2035 2147 *out << Verbose(3) << "INFO: Created new triangle " << *BTS << "." << endl; 2036 2148 } else { 2037 2149 *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl; 2038 return false;2150 return NULL; 2039 2151 } 2040 2152 2041 2153 *out << Verbose(1) << "End of FlipBaseline" << endl; 2042 return true;2154 return NewLine; 2043 2155 }; 2044 2156 … … 2046 2158 /** Finds the second point of starting triangle. 2047 2159 * \param *a first node 2048 * \param *Candidate pointer to candidate node on return2049 2160 * \param Oben vector indicating the outside 2050 2161 * \param OptCandidate reference to recommended candidate on return … … 2053 2164 * \param *LC LinkedCell structure with neighbouring points 2054 2165 */ 2055 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate,Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)2166 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC) 2056 2167 { 2057 2168 cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl; 2058 2169 Vector AngleCheck; 2170 class TesselPoint* Candidate = NULL; 2059 2171 double norm = -1., angle; 2060 2172 LinkedNodes *List = NULL; … … 2191 2303 cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl; 2192 2304 2193 //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;2305 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2194 2306 2195 2307 // construct center of circle … … 2216 2328 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2217 2329 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2330 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2218 2331 2219 2332 // check SearchDirection … … 2392 2505 TesselPoint *trianglePoints[3]; 2393 2506 TesselPoint *SecondPoint = NULL; 2507 list<BoundaryTriangleSet*> *triangles = NULL; 2394 2508 2395 2509 if (LinesOnBoundary.empty()) { … … 2402 2516 // check whether closest point is "too close" :), then it's inside 2403 2517 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; 2405 2519 return NULL; 2406 2520 } 2407 2521 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 } 2427 2564 2428 2565 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); 2430 2568 return NULL; 2431 2569 } else … … 2443 2581 class BoundaryTriangleSet *result = NULL; 2444 2582 list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC); 2583 Vector Center; 2445 2584 2446 2585 if (triangles == NULL) 2447 2586 return NULL; 2448 2587 2449 if (x->ScalarProduct(&triangles->front()->NormalVector) < 0) 2450 result = triangles->back(); 2451 else 2588 if (triangles->size() == 1) { // there is no degenerate case 2452 2589 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 } 2454 2604 delete(triangles); 2455 2605 return result; … … 2466 2616 { 2467 2617 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; 2469 2631 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; 2473 2634 return false; 2635 } 2474 2636 } 2475 2637 … … 2483 2645 bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC) 2484 2646 { 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); 2492 2648 } 2493 2649 … … 2496 2652 * @param *Point of which get all connected points 2497 2653 * 2498 * @return list of the all points linked to the provided one2499 */ 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 */ 2656 set<TesselPoint*> * Tesselation::GetAllConnectedPoints(ofstream *out, TesselPoint* Point) 2657 { 2658 set<TesselPoint*> *connectedPoints = new set<TesselPoint*>; 2503 2659 class BoundaryPointSet *ReferencePoint = NULL; 2504 2660 TesselPoint* current; … … 2510 2666 ReferencePoint = PointRunner->second; 2511 2667 } 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; 2513 2669 ReferencePoint = NULL; 2514 2670 } 2515 2671 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 2517 2673 // OR fall-back to look through all lines if there is no such BoundaryPoint 2518 2674 LineMap *Lines = &LinesOnBoundary; … … 2521 2677 LineMap::iterator findLines = Lines->begin(); 2522 2678 while (findLines != Lines->end()) { 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 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 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++; 2539 2695 } 2540 2696 … … 2543 2699 return NULL; 2544 2700 } 2701 2545 2702 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. 2549 2707 * Maps them down onto the plane designated by the axis \a *Point and \a *Reference. The center of all points 2550 2708 * connected in the tesselation to \a *Point is mapped to spherical coordinates with the zero angle being given … … 2553 2711 * 2554 2712 * @param *out output stream for debugging 2555 * @param *connectedPoints list of connected points to the central \a *Point2556 2713 * @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 */ 2717 list<TesselPoint*> * Tesselation::GetCircleOfConnectedPoints(ofstream *out, TesselPoint* Point, Vector *Reference) 2562 2718 { 2563 2719 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; 2572 2727 2573 2728 // 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++) 2575 2730 center.AddVector((*TesselRunner)->node); 2576 2731 //*out << "Summed vectors " << center << "; number of points " << connectedPoints.size() … … 2586 2741 2587 2742 // construct one orthogonal vector 2588 AngleZero.CopyVector(Reference); 2743 if (Reference != NULL) 2744 AngleZero.CopyVector(Reference); 2745 else 2746 AngleZero.CopyVector((*connectedPoints->begin())->node); 2589 2747 AngleZero.SubtractVector(Point->node); 2590 2748 AngleZero.ProjectOntoPlane(&PlaneNormal); … … 2594 2752 2595 2753 // 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++) { 2597 2755 helper.CopyVector((*listRunner)->node); 2598 2756 helper.SubtractVector(Point->node); 2599 2757 helper.ProjectOntoPlane(&PlaneNormal); 2600 2758 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; 2602 2760 anglesOfPoints.insert(pair<double, TesselPoint*>(angle, (*listRunner))); 2603 2761 } 2604 2762 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; 2616 2769 } 2617 2770 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 */ 2777 list<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 */ 2892 list<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 */ 2953 set<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 2618 2971 /** 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). 2620 2978 * \param *out output stream for debugging 2621 2979 * \param *point point to be removed … … 2625 2983 class BoundaryLineSet *line = NULL; 2626 2984 class BoundaryTriangleSet *triangle = NULL; 2627 Vector OldPoint, TetraederVector[3];2985 Vector OldPoint, NormalVector; 2628 2986 double volume = 0; 2629 int *numbers = NULL;2630 2987 int count = 0; 2631 int i;2632 2988 2633 2989 if (point == NULL) { … … 2645 3001 return 0.; 2646 3002 } 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 2650 3008 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) 2651 3009 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++) { 2656 3012 line = LineRunner->second; 2657 3013 for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) { 2658 3014 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 } 2737 3078 } 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 } 2741 3150 } 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; 2838 3163 } 2839 3164 } 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.); 2844 3173 } 2845 3174 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 2905 3196 2906 3197 /** … … 2939 3230 FindTriangle = FindLine->second->triangles.begin(); 2940 3231 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)) { 2955 3233 result->push_back(FindTriangle->second); 2956 3234 } … … 2970 3248 2971 3249 /** 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 */ 3255 map<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 /** 2972 3287 * Finds all degenerated triangles within the tesselation structure. 2973 3288 * … … 2975 3290 * in the list, once as key and once as value 2976 3291 */ 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 } 3292 map<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) ); 3009 3315 } 3010 3316 } 3011 3317 } 3012 3318 } 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; 3015 3322 map<int,int>::iterator it; 3016 for (it = DegeneratedTriangles .begin(); it != DegeneratedTriangles.end(); it++)3323 for (it = DegeneratedTriangles->begin(); it != DegeneratedTriangles->end(); it++) 3017 3324 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3018 3325 … … 3026 3333 void Tesselation::RemoveDegeneratedTriangles() 3027 3334 { 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 3032 3344 ) { 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; 3035 3355 3036 3356 bool trianglesShareLine = false; … … 3044 3364 && (triangle->endpoints[0]->LinesCount > 2) 3045 3365 ) { 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); 3046 3399 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl; 3047 3400 RemoveTesselationTriangle(triangle); 3401 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr); 3048 3402 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl; 3049 3403 RemoveTesselationTriangle(partnerTriangle); 3050 DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr));3051 3404 } else { 3052 3405 cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle … … 3055 3408 } 3056 3409 } 3410 delete(DegeneratedTriangles); 3411 3412 cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl; 3413 cout << Verbose(1) << "End of RemoveDegeneratedTriangles" << endl; 3057 3414 } 3058 3415 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 */ 3424 void 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 */ 3526 void 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 34 34 class PointCloud; 35 35 class 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" 36 43 37 44 // ======================================================= some template functions ========================================= … … 115 122 116 123 void GetNormalVector(Vector &NormalVector); 124 void GetCenter(Vector *center); 117 125 bool GetIntersectionInsideTriangle(ofstream *out, Vector *MolCenter, Vector *x, Vector *Intersection); 118 126 bool ContainsBoundaryLine(class BoundaryLineSet *line); 119 127 bool ContainsBoundaryPoint(class BoundaryPointSet *point); 128 bool ContainsBoundaryPoint(class TesselPoint *point); 120 129 class BoundaryPointSet *GetThirdEndpoint(class BoundaryLineSet *line); 121 130 bool IsPresentTupel(class BoundaryPointSet *Points[3]); 122 void GetCenter(Vector *center);131 bool IsPresentTupel(class BoundaryTriangleSet *T); 123 132 124 133 class BoundaryPointSet *endpoints[3]; … … 196 205 void AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 197 206 void AddTesselationTriangle(); 207 void AddTesselationTriangle(int nr); 198 208 void RemoveTesselationTriangle(class BoundaryTriangleSet *triangle); 199 209 void RemoveTesselationLine(class BoundaryLineSet *line); 200 210 void RemoveTesselationPoint(class BoundaryPointSet *point); 201 211 202 bool IsInside(Vector *pointer);203 212 class BoundaryPointSet *GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2); 204 213 205 214 // concave envelope 206 215 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); 208 217 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); 210 219 int CheckPresenceOfTriangle(ofstream *out, class TesselPoint *Candidates[3]); 220 class BoundaryTriangleSet * GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3]); 211 221 212 222 // convex envelope … … 215 225 bool InsertStraddlingPoints(ofstream *out, PointCloud *cloud, LinkedCell *LC); 216 226 double RemovePointFromTesselatedSurface(ofstream *out, class BoundaryPointSet *point); 217 boolFlipBaseline(ofstream *out, class BoundaryLineSet *Base);218 boolPickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);227 class BoundaryLineSet * FlipBaseline(ofstream *out, class BoundaryLineSet *Base); 228 double PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base); 219 229 class BoundaryPointSet *IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base); 220 map<int, int> FindAllDegeneratedTriangles(); 230 map<int, int> * FindAllDegeneratedTriangles(); 231 map<int, int> * FindAllDegeneratedLines(); 221 232 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); 225 240 list<BoundaryTriangleSet*> *FindTriangles(TesselPoint* Points[3]); 226 241 list<BoundaryTriangleSet*> * FindClosestTrianglesToPoint(ofstream *out, Vector *x, LinkedCell* LC); … … 235 250 void PrintAllBoundaryTriangles(ofstream *out); 236 251 252 // store envelope in file 253 void Output(ofstream *out, const char *filename, PointCloud *cloud); 237 254 238 255 PointMap PointsOnBoundary; … … 257 274 class BoundaryLineSet *BLS[3]; 258 275 class BoundaryTriangleSet *BTS; 276 class BoundaryTriangleSet *LastTriangle; 277 int TriangleFilesWritten; 259 278 260 279 private: … … 264 283 }; 265 284 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);272 285 273 286 #endif /* TESSELATION_HPP_ */ -
src/tesselationhelpers.cpp
rc0917c ra33931 386 386 387 387 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 */ 399 double 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; 388 415 } 389 416 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 */ 425 double 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 */ 448 bool 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 */ 482 bool 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 */ 532 TesselPoint* 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 */ 587 TesselPoint* 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 */ 641 Vector * 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 */ 682 void 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 */ 725 void 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 */ 750 void 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 */ 795 void 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 */ 836 void 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 */ 863 bool 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 18 18 #endif 19 19 20 #define HULLEPSILON 1e-721 22 20 #include <gsl/gsl_linalg.h> 23 21 #include <gsl/gsl_matrix.h> … … 26 24 #include <gsl/gsl_vector.h> 27 25 26 #include "defs.hpp" 27 #include "tesselation.hpp" 28 28 #include "vector.hpp" 29 30 #define HULLEPSILON 1e-10 29 31 30 32 double DetGet(gsl_matrix *A, int inPlace); … … 35 37 double MinIntersectDistance(const gsl_vector * x, void *params); 36 38 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4); 39 double CalculateVolumeofGeneralTetraeder(Vector *a, Vector *b, Vector *c, Vector *d); 40 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector); 41 42 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]); 43 bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2); 44 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC); 45 TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*); 46 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase); 47 48 void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, PointCloud *cloud, int N); 49 void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud); 50 void IncludeSphereinRaster3D(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, PointCloud *cloud); 51 void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, PointCloud *cloud); 52 void CalculateConcavityPerBoundaryPoint(ofstream *out, class Tesselation *TesselStruct); 53 54 bool CheckListOfBaselines(ofstream *out, Tesselation *TesselStruct); 55 37 56 38 57 #endif /* TESSELATIONHELPERS_HPP_ */ -
src/tesselationunittest.cpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/tesselationunittest.hpp
-
Property mode
changed from
100755
to100644
-
Property mode
changed from
-
src/vector.cpp
rc0917c ra33931 225 225 Direction.CopyVector(LineVector); 226 226 Direction.SubtractVector(Origin); 227 Direction.Normalize(); 227 228 //*out << Verbose(4) << "INFO: Direction is " << Direction << "." << endl; 228 229 factor = Direction.ScalarProduct(PlaneNormal); … … 234 235 helper.SubtractVector(Origin); 235 236 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 } 236 242 //factor = Origin->ScalarProduct(PlaneNormal)*(-PlaneOffset->ScalarProduct(PlaneNormal))/(Direction.ScalarProduct(PlaneNormal)); 237 243 Direction.Scale(factor); -
src/vectorunittest.cpp
rc0917c ra33931 13 13 #include <cppunit/ui/text/TestRunner.h> 14 14 15 #include "defs.hpp" 16 #include "vector.hpp" 15 17 #include "vectorunittest.hpp" 16 #include "vector.hpp"17 #include "defs.hpp"18 18 19 19 /********************************************** Test classes **************************************/
Note:
See TracChangeset
for help on using the changeset viewer.