Changeset 57066a
- Timestamp:
- Sep 28, 2009, 8:00:33 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- e4a379
- Parents:
- 91e7e4a
- git-author:
- Frederik Heber <heber@…> (09/28/09 18:47:54)
- git-committer:
- Frederik Heber <heber@…> (09/28/09 20:00:33)
- Location:
- src
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/boundary.cpp
r91e7e4a r57066a 112 112 ; 113 113 114 /** Creates the objects in a VRML file.115 * \param *out output stream for debugging116 * \param *vrmlfile output stream for tecplot data117 * \param *Tess Tesselation structure with constructed triangles118 * \param *mol molecule structure with atom positions119 */120 void WriteVrmlFile(ofstream *out, ofstream *vrmlfile, class Tesselation *Tess, class molecule *mol)121 {122 atom *Walker = mol->start;123 bond *Binder = mol->first;124 int i;125 Vector *center = mol->DetermineCenterOfAll(out);126 if (vrmlfile != NULL) {127 //cout << Verbose(1) << "Writing Raster3D file ... ";128 *vrmlfile << "#VRML V2.0 utf8" << endl;129 *vrmlfile << "#Created by molecuilder" << endl;130 *vrmlfile << "#All atoms as spheres" << endl;131 while (Walker->next != mol->end) {132 Walker = Walker->next;133 *vrmlfile << "Sphere {" << endl << " "; // 2 is sphere type134 for (i=0;i<NDIM;i++)135 *vrmlfile << Walker->x.x[i]-center->x[i] << " ";136 *vrmlfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour137 }138 139 *vrmlfile << "# All bonds as vertices" << endl;140 while (Binder->next != mol->last) {141 Binder = Binder->next;142 *vrmlfile << "3" << endl << " "; // 2 is round-ended cylinder type143 for (i=0;i<NDIM;i++)144 *vrmlfile << Binder->leftatom->x.x[i]-center->x[i] << " ";145 *vrmlfile << "\t0.03\t";146 for (i=0;i<NDIM;i++)147 *vrmlfile << Binder->rightatom->x.x[i]-center->x[i] << " ";148 *vrmlfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour149 }150 151 *vrmlfile << "# All tesselation triangles" << endl;152 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {153 *vrmlfile << "1" << endl << " "; // 1 is triangle type154 for (i=0;i<3;i++) { // print each node155 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates156 *vrmlfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";157 *vrmlfile << "\t";158 }159 *vrmlfile << "1. 0. 0." << endl; // red as colour160 *vrmlfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object161 }162 } else {163 cerr << "ERROR: Given vrmlfile is " << vrmlfile << "." << endl;164 }165 delete(center);166 };167 168 /** Creates the objects in a raster3d file (renderable with a header.r3d).169 * \param *out output stream for debugging170 * \param *rasterfile output stream for tecplot data171 * \param *Tess Tesselation structure with constructed triangles172 * \param *mol molecule structure with atom positions173 */174 void WriteRaster3dFile(ofstream *out, ofstream *rasterfile, class Tesselation *Tess, class molecule *mol)175 {176 atom *Walker = mol->start;177 bond *Binder = mol->first;178 int i;179 Vector *center = mol->DetermineCenterOfAll(out);180 if (rasterfile != NULL) {181 //cout << Verbose(1) << "Writing Raster3D file ... ";182 *rasterfile << "# Raster3D object description, created by MoleCuilder" << endl;183 *rasterfile << "@header.r3d" << endl;184 *rasterfile << "# All atoms as spheres" << endl;185 while (Walker->next != mol->end) {186 Walker = Walker->next;187 *rasterfile << "2" << endl << " "; // 2 is sphere type188 for (i=0;i<NDIM;i++)189 *rasterfile << Walker->x.x[i]-center->x[i] << " ";190 *rasterfile << "\t0.1\t1. 1. 1." << endl; // radius 0.05 and white as colour191 }192 193 *rasterfile << "# All bonds as vertices" << endl;194 while (Binder->next != mol->last) {195 Binder = Binder->next;196 *rasterfile << "3" << endl << " "; // 2 is round-ended cylinder type197 for (i=0;i<NDIM;i++)198 *rasterfile << Binder->leftatom->x.x[i]-center->x[i] << " ";199 *rasterfile << "\t0.03\t";200 for (i=0;i<NDIM;i++)201 *rasterfile << Binder->rightatom->x.x[i]-center->x[i] << " ";202 *rasterfile << "\t0.03\t0. 0. 1." << endl; // radius 0.05 and blue as colour203 }204 205 *rasterfile << "# All tesselation triangles" << endl;206 *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";207 for (TriangleMap::iterator TriangleRunner = Tess->TrianglesOnBoundary.begin(); TriangleRunner != Tess->TrianglesOnBoundary.end(); TriangleRunner++) {208 *rasterfile << "1" << endl << " "; // 1 is triangle type209 for (i=0;i<3;i++) { // print each node210 for (int j=0;j<NDIM;j++) // and for each node all NDIM coordinates211 *rasterfile << TriangleRunner->second->endpoints[i]->node->node->x[j]-center->x[j] << " ";212 *rasterfile << "\t";213 }214 *rasterfile << "1. 0. 0." << endl; // red as colour215 //*rasterfile << "18" << endl << " 0.5 0.5 0.5" << endl; // 18 is transparency type for previous object216 }217 *rasterfile << "9\n# terminating special property\n";218 } else {219 cerr << "ERROR: Given rasterfile is " << rasterfile << "." << endl;220 }221 delete(center);222 };223 224 /** This function creates the tecplot file, displaying the tesselation of the hull.225 * \param *out output stream for debugging226 * \param *tecplot output stream for tecplot data227 * \param N arbitrary number to differentiate various zones in the tecplot format228 */229 void WriteTecplotFile(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol, int N)230 {231 if ((tecplot != NULL) && (TesselStruct != NULL)) {232 // write header233 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl;234 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\" \"U\"" << endl;235 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" << TesselStruct->PointsOnBoundary.size() << ", E=" << TesselStruct->TrianglesOnBoundary.size() << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl;236 int *LookupList = new int[mol->AtomCount];237 for (int i = 0; i < mol->AtomCount; i++)238 LookupList[i] = -1;239 240 // print atom coordinates241 *out << Verbose(2) << "The following triangles were created:";242 int Counter = 1;243 TesselPoint *Walker = NULL;244 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) {245 Walker = target->second->node;246 LookupList[Walker->nr] = Counter++;247 *tecplot << Walker->node->x[0] << " " << Walker->node->x[1] << " " << Walker->node->x[2] << " " << target->second->value << endl;248 }249 *tecplot << endl;250 // print connectivity251 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) {252 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name;253 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl;254 }255 delete[] (LookupList);256 *out << endl;257 }258 }259 260 114 261 115 /** Determines the boundary points of a cluster. … … 536 390 537 391 // flip the line 538 if ( !mol->TesselStruct->PickFarthestofTwoBaselines(out, line))392 if (mol->TesselStruct->PickFarthestofTwoBaselines(out, line) == 0.) 539 393 *out << Verbose(1) << "ERROR: Correction of concave baselines failed!" << endl; 540 else 394 else { 395 mol->TesselStruct->FlipBaseline(out, line); 541 396 *out << Verbose(1) << "INFO: Correction of concave baselines worked." << endl; 397 } 542 398 } 543 399 } … … 644 500 class BoundaryLineSet *line = NULL; 645 501 bool Concavity; 502 char dummy[MAXSTRINGSIZE]; 646 503 PointMap::iterator PointRunner, PointAdvance; 647 504 LineMap::iterator LineRunner, LineAdvance; … … 656 513 } 657 514 658 //CalculateConcavityPerBoundaryPoint(out, TesselStruct);659 StoreTrianglesinFile(out, mol, filename, "-first");660 661 515 // First step: RemovePointFromTesselatedSurface 516 int run = 0; 517 double tmp; 662 518 do { 663 519 Concavity = false; 520 sprintf(dummy, "-first-%d", run); 521 //CalculateConcavityPerBoundaryPoint(out, TesselStruct); 522 StoreTrianglesinFile(out, mol, filename, dummy); 523 664 524 PointRunner = TesselStruct->PointsOnBoundary.begin(); 665 525 PointAdvance = PointRunner; // we need an advanced point, as the PointRunner might get removed … … 671 531 line = LineRunner->second; 672 532 *out << Verbose(2) << "INFO: Current line of point " << *point << " is " << *line << "." << endl; 673 } 674 if (!line->CheckConvexityCriterion(out)) { 675 *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl; 676 // remove the point 677 Concavity = true; 678 TesselStruct->RemovePointFromTesselatedSurface(out, point); 533 if (!line->CheckConvexityCriterion(out)) { 534 // remove the point if needed 535 *out << Verbose(1) << "... point " << *point << " cannot be on convex envelope." << endl; 536 volume += TesselStruct->RemovePointFromTesselatedSurface(out, point); 537 sprintf(dummy, "-first-%d", ++run); 538 StoreTrianglesinFile(out, mol, filename, dummy); 539 Concavity = true; 540 break; 541 } 679 542 } 680 543 PointRunner = PointAdvance; 681 544 } 682 545 546 sprintf(dummy, "-second-%d", run); 683 547 //CalculateConcavityPerBoundaryPoint(out, TesselStruct); 684 //StoreTrianglesinFile(out, mol, filename, "-second");548 StoreTrianglesinFile(out, mol, filename, dummy); 685 549 686 550 // second step: PickFarthestofTwoBaselines … … 693 557 // take highest of both lines 694 558 if (TesselStruct->IsConvexRectangle(out, line) == NULL) { 695 TesselStruct->PickFarthestofTwoBaselines(out, line); 696 Concavity = true; 559 tmp = TesselStruct->PickFarthestofTwoBaselines(out, line); 560 volume += tmp; 561 if (tmp != 0) { 562 mol->TesselStruct->FlipBaseline(out, line); 563 Concavity = true; 564 } 697 565 } 698 566 LineRunner = LineAdvance; 699 567 } 568 run++; 700 569 } while (Concavity); 701 CalculateConcavityPerBoundaryPoint(out, TesselStruct);702 StoreTrianglesinFile(out, mol, filename, "-third");570 //CalculateConcavityPerBoundaryPoint(out, TesselStruct); 571 //StoreTrianglesinFile(out, mol, filename, "-third"); 703 572 704 573 // third step: IsConvexRectangle … … 717 586 point = TesselStruct->IsConvexRectangle(out, line); 718 587 if (point != NULL) 719 TesselStruct->RemovePointFromTesselatedSurface(out, point);588 volume += TesselStruct->RemovePointFromTesselatedSurface(out, point); 720 589 } 721 590 LineRunner = LineAdvance; … … 723 592 724 593 CalculateConcavityPerBoundaryPoint(out, TesselStruct); 725 StoreTrianglesinFile(out, mol, filename, " -fourth");594 StoreTrianglesinFile(out, mol, filename, ""); 726 595 727 596 // end 597 *out << Verbose(1) << "Volume is " << volume << "." << endl; 728 598 *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl; 729 599 return volume; … … 993 863 if ((*ListRunner)->TesselStruct == NULL) { 994 864 *out << Verbose(1) << "Pre-creating tesselation for molecule " << *ListRunner << "." << endl; 995 FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], NULL, 5.);865 FindNonConvexBorder((ofstream *)&cout, (*ListRunner), LCList[i], 5., NULL); 996 866 } 997 867 i++; … … 1115 985 * \param *Tess Tesselation filled with points, lines and triangles on boundary on return 1116 986 * \param *LCList atoms in LinkedCell list 987 * \param RADIUS radius of the virtual sphere 1117 988 * \param *filename filename prefix for output of vertex data 1118 * \para RADIUS radius of the virtual sphere 1119 */ 1120 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename, const double RADIUS) 989 */ 990 void FindNonConvexBorder(ofstream *out, molecule* mol, class LinkedCell *LCList, const double RADIUS, const char *filename = NULL) 1121 991 { 1122 992 int N = 0; 1123 993 bool freeLC = false; 1124 ofstream *tempstream = NULL;1125 char NumberName[255];1126 int TriangleFilesWritten = 0;1127 994 1128 995 *out << Verbose(1) << "Entering search for non convex hull. " << endl; … … 1141 1008 bool failflag = false; 1142 1009 1010 // initialise Linked Cell 1143 1011 if (LCList == NULL) { 1144 1012 LCList = new LinkedCell(mol, 2.*RADIUS); … … 1146 1014 } 1147 1015 1016 // 1. get starting triangle 1148 1017 mol->TesselStruct->FindStartingTriangle(out, RADIUS, LCList); 1149 1018 1019 // 2. expand from there 1150 1020 baseline = mol->TesselStruct->LinesOnBoundary.begin(); 1151 // the outward most line is dangerous, as we may end up with wrapping up the starting triangle, hence 1152 // terminating the algorithm too early. 1153 if (baseline != mol->TesselStruct->LinesOnBoundary.end()) // skip first line as it its the outwardmost! 1154 baseline++; 1021 baseline++; // skip first line 1155 1022 while ((baseline != mol->TesselStruct->LinesOnBoundary.end()) || (flag)) { 1156 1023 if (baseline->second->triangles.size() == 1) { 1157 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. 1024 // 3. find next triangle 1025 failflag = 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. 1158 1026 flag = flag || failflag; 1159 1027 if (!failflag) 1160 1028 cerr << "WARNING: FindNextSuitableTriangle failed." << endl; 1029 1161 1030 // write temporary envelope 1162 if ((DoSingleStepOutput && (mol->TesselStruct->TrianglesOnBoundaryCount % SingleStepWidth == 0))) { // if we have a new triangle and want to output each new triangle configuration 1163 TriangleMap::iterator runner = mol->TesselStruct->TrianglesOnBoundary.end(); 1164 runner--; 1165 class BoundaryTriangleSet *triangle = runner->second; 1166 if (triangle != NULL) { 1167 sprintf(NumberName, "-%04d-%s_%s_%s", TriangleFilesWritten, triangle->endpoints[0]->node->Name, triangle->endpoints[1]->node->Name, triangle->endpoints[2]->node->Name); 1168 if (DoTecplotOutput) { 1169 string NameofTempFile(filename); 1170 NameofTempFile.append(NumberName); 1171 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 1172 NameofTempFile.erase(npos, 1); 1173 NameofTempFile.append(TecplotSuffix); 1174 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 1175 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 1176 WriteTecplotFile(out, tempstream, mol->TesselStruct, mol, TriangleFilesWritten); 1177 tempstream->close(); 1178 tempstream->flush(); 1179 delete(tempstream); 1180 } 1181 1182 if (DoRaster3DOutput) { 1183 string NameofTempFile(filename); 1184 NameofTempFile.append(NumberName); 1185 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 1186 NameofTempFile.erase(npos, 1); 1187 NameofTempFile.append(Raster3DSuffix); 1188 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 1189 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 1190 WriteRaster3dFile(out, tempstream, mol->TesselStruct, mol); 1191 // // include the current position of the virtual sphere in the temporary raster3d file 1192 // // make the circumsphere's center absolute again 1193 // helper.CopyVector(BaseRay->endpoints[0]->node->node); 1194 // helper.AddVector(BaseRay->endpoints[1]->node->node); 1195 // helper.Scale(0.5); 1196 // (*it)->OptCenter.AddVector(&helper); 1197 // Vector *center = mol->DetermineCenterOfAll(out); 1198 // (*it)->OptCenter.SubtractVector(center); 1199 // delete(center); 1200 // // and add to file plus translucency object 1201 // *tempstream << "# current virtual sphere\n"; 1202 // *tempstream << "8\n 25.0 0.6 -1.0 -1.0 -1.0 0.2 0 0 0 0\n"; 1203 // *tempstream << "2\n " << (*it)->OptCenter.x[0] << " " 1204 // << (*it)->OptCenter.x[1] << " " << (*it)->OptCenter.x[2] 1205 // << "\t" << RADIUS << "\t1 0 0\n"; 1206 // *tempstream << "9\n terminating special property\n"; 1207 tempstream->close(); 1208 tempstream->flush(); 1209 delete(tempstream); 1210 } 1211 } 1212 if (DoTecplotOutput || DoRaster3DOutput) 1213 TriangleFilesWritten++; 1031 if (filename != NULL) { 1032 if ((DoSingleStepOutput && ((mol->TesselStruct->TrianglesOnBoundary.size() % SingleStepWidth == 0) || (mol->TesselStruct->TrianglesOnBoundary.size() > 8520 && mol->TesselStruct->TrianglesOnBoundary.size() <= 8530)))) { // if we have a new triangle and want to output each new triangle configuration 1033 mol->TesselStruct->Output(out, filename, mol); 1034 } 1214 1035 } 1036 baseline = mol->TesselStruct->LinesOnBoundary.end(); 1215 1037 } else { 1216 1038 //cout << Verbose(1) << "Line " << *baseline->second << " has " << baseline->second->triangles.size() << " triangles adjacent" << endl; … … 1220 1042 1221 1043 N++; 1222 baseline++;1223 1044 if ((baseline == mol->TesselStruct->LinesOnBoundary.end()) && (flag)) { 1224 1045 baseline = mol->TesselStruct->LinesOnBoundary.begin(); // restart if we reach end due to newly inserted lines 1046 baseline++; 1225 1047 flag = false; 1226 1048 } 1227 1049 } 1050 // look whether all points are inside of the convex envelope, otherwise add them via degenerated triangles 1051 mol->TesselStruct->InsertStraddlingPoints(out, mol, LCList); 1052 // mol->GoToFirst(); 1053 // class TesselPoint *Runner = NULL; 1054 // while (!mol->IsEnd()) { 1055 // Runner = mol->GetPoint(); 1056 // *out << Verbose(1) << "Checking on " << Runner->Name << " ... " << endl; 1057 // if (!mol->TesselStruct->IsInnerPoint(out, Runner, LCList)) { 1058 // *out << Verbose(2) << Runner->Name << " is outside of envelope, adding via degenerated triangles." << endl; 1059 // mol->TesselStruct->AddBoundaryPointByDegeneratedTriangle(out, Runner, LCList); 1060 // } else { 1061 // *out << Verbose(2) << Runner->Name << " is inside of or on envelope." << endl; 1062 // } 1063 // mol->GoToNext(); 1064 // } 1228 1065 1229 1066 // Purges surplus triangles. 1230 1067 mol->TesselStruct->RemoveDegeneratedTriangles(); 1231 1232 // write final envelope1233 if (filename != 0) {1234 *out << Verbose(1) << "Writing final tecplot file\n";1235 if (DoTecplotOutput) {1236 string OutputName(filename);1237 OutputName.append(TecplotSuffix);1238 ofstream *tecplot = new ofstream(OutputName.c_str());1239 WriteTecplotFile(out, tecplot, mol->TesselStruct, mol, -1);1240 tecplot->close();1241 delete(tecplot);1242 }1243 if (DoRaster3DOutput) {1244 string OutputName(filename);1245 OutputName.append(Raster3DSuffix);1246 ofstream *raster = new ofstream(OutputName.c_str());1247 WriteRaster3dFile(out, raster, mol->TesselStruct, mol);1248 raster->close();1249 delete(raster);1250 }1251 } else {1252 cerr << "ERROR: Could definitively not find all necessary triangles!" << endl;1253 }1254 1068 1255 1069 cout << Verbose(2) << "Check: List of Baselines with not two connected triangles:" << endl; … … 1264 1078 *out << Verbose(2) << "None." << endl; 1265 1079 1266 // // Tests the IsInnerAtom() function. 1267 // Vector x (0, 0, 0); 1268 // *out << Verbose(0) << "Point to check: " << x << endl; 1269 // *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, x, LCList) 1270 // << "for vector " << x << "." << endl; 1271 // TesselPoint* a = mol->TesselStruct->PointsOnBoundary.begin()->second->node; 1272 // *out << Verbose(0) << "Point to check: " << *a << " (on boundary)." << endl; 1273 // *out << Verbose(0) << "Check: IsInnerAtom() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList) 1274 // << "for atom " << a << " (on boundary)." << endl; 1275 // LinkedNodes *List = NULL; 1276 // for (int i=0;i<NDIM;i++) { // each axis 1277 // LCList->n[i] = LCList->N[i]-1; // current axis is topmost cell 1278 // for (LCList->n[(i+1)%NDIM]=0;LCList->n[(i+1)%NDIM]<LCList->N[(i+1)%NDIM];LCList->n[(i+1)%NDIM]++) 1279 // for (LCList->n[(i+2)%NDIM]=0;LCList->n[(i+2)%NDIM]<LCList->N[(i+2)%NDIM];LCList->n[(i+2)%NDIM]++) { 1280 // List = LCList->GetCurrentCell(); 1281 // //cout << Verbose(2) << "Current cell is " << LC->n[0] << ", " << LC->n[1] << ", " << LC->n[2] << " with No. " << LC->index << "." << endl; 1282 // if (List != NULL) { 1283 // for (LinkedNodes::iterator Runner = List->begin();Runner != List->end();Runner++) { 1284 // if (mol->TesselStruct->PointsOnBoundary.find((*Runner)->nr) == mol->TesselStruct->PointsOnBoundary.end()) { 1285 // a = *Runner; 1286 // i=3; 1287 // for (int j=0;j<NDIM;j++) 1288 // LCList->n[j] = LCList->N[j]; 1289 // break; 1290 // } 1291 // } 1292 // } 1293 // } 1294 // } 1295 // *out << Verbose(0) << "Check: IsInnerPoint() returns " << mol->TesselStruct->IsInnerPoint(out, a, LCList) 1296 // << "for atom " << a << " (inside)." << endl; 1080 // write final envelope 1081 CalculateConcavityPerBoundaryPoint(out, mol->TesselStruct); 1082 StoreTrianglesinFile(out, mol, filename, ""); 1297 1083 1298 1084 if (freeLC) … … 1300 1086 *out << Verbose(0) << "End of FindNonConvexBorder\n"; 1301 1087 }; 1088 1302 1089 1303 1090 /** Finds a hole of sufficient size in \a this molecule to embed \a *srcmol into it. -
src/boundary.hpp
r91e7e4a r57066a 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); -
src/tesselation.cpp
r91e7e4a r57066a 6 6 */ 7 7 8 #include "helpers.hpp" 9 #include "linkedcell.hpp" 8 10 #include "tesselation.hpp" 11 #include "tesselationhelpers.hpp" 12 #include "vector.hpp" 13 14 class molecule; 9 15 10 16 // ======================================== Points on Boundary ================================= … … 36 42 BoundaryPointSet::~BoundaryPointSet() 37 43 { 38 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl;44 //cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 39 45 if (!lines.empty()) 40 46 cerr << "WARNING: Memory Leak! I " << *this << " am still connected to some lines." << endl; … … 66 72 ostream & operator <<(ostream &ost, BoundaryPointSet &a) 67 73 { 68 ost << "[" << a.Nr << "|" << a.node->Name << " ]";74 ost << "[" << a.Nr << "|" << a.node->Name << " at " << *a.node->node << "]"; 69 75 return ost; 70 76 } … … 124 130 for (LineMap::iterator Runner = erasor.first; Runner != erasor.second; Runner++) 125 131 if ((*Runner).second == this) { 126 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl;132 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 127 133 endpoints[i]->lines.erase(Runner); 128 134 break; 129 135 } 130 136 } else { // there's just a single line left 131 if (endpoints[i]->lines.erase(Nr)) 132 cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 137 if (endpoints[i]->lines.erase(Nr)) { 138 //cout << Verbose(5) << "Removing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 139 } 133 140 } 134 141 if (endpoints[i]->lines.empty()) { 135 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl;142 //cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 136 143 if (endpoints[i] != NULL) { 137 144 delete(endpoints[i]); … … 167 174 168 175 /** Checks whether the adjacent triangles of a baseline are convex or not. 169 * We sum the two angles of each normal vector with a ficticious normnal vector from this baselinbe pointing outwards.176 * We sum the two angles of each height vector with respect to the center of the baseline. 170 177 * If greater/equal M_PI than we are convex. 171 178 * \param *out output stream for debugging … … 177 184 // get the two triangles 178 185 if (triangles.size() != 2) { 179 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connect to less than two triangles, Tesselation incomplete!" << endl;186 *out << Verbose(1) << "ERROR: Baseline " << *this << " is connected to less than two triangles, Tesselation incomplete!" << endl; 180 187 return true; 181 188 } … … 200 207 NormalCheck.Scale(sign); 201 208 sign = -sign; 202 BaseLineNormal.SubtractVector(&runner->second->NormalVector); // we subtract as BaseLineNormal has to point inward in direction of [pi,2pi] 209 if (runner->second->NormalVector.NormSquared() > MYEPSILON) 210 BaseLineNormal.CopyVector(&runner->second->NormalVector); // yes, copy second on top of first 211 else { 212 *out << Verbose(1) << "CRITICAL: Triangle " << *runner->second << " has zero normal vector!" << endl; 213 exit(255); 214 } 203 215 node = runner->second->GetThirdEndpoint(this); 204 216 if (node != NULL) { 205 //*out << Verbose(3) << "INFO: Third node for triangle " << *(runner->second) << " is " << *node << " at " << *(node->node->node) << "." << endl;217 *out << Verbose(3) << "INFO: Third node for triangle " << *(runner->second) << " is " << *node << " at " << *(node->node->node) << "." << endl; 206 218 helper[i].CopyVector(node->node->node); 207 219 helper[i].SubtractVector(&BaseLineCenter); 208 220 helper[i].MakeNormalVector(&BaseLine); // we want to compare the triangle's heights' angles! 209 //*out << Verbose(4) << "INFO: Height vector with respect to baseline is " << helper[i] << "." << endl;221 *out << Verbose(4) << "INFO: Height vector with respect to baseline is " << helper[i] << "." << endl; 210 222 i++; 211 223 } else { 212 //*out << Verbose(2) << " WARNING: I cannot find third node in triangle, something's wrong." << endl;224 //*out << Verbose(2) << "ERROR: I cannot find third node in triangle, something's wrong." << endl; 213 225 return true; 214 226 } 215 227 } 216 //*out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl;228 *out << Verbose(3) << "INFO: BaselineNormal is " << BaseLineNormal << "." << endl; 217 229 if (NormalCheck.NormSquared() < MYEPSILON) { 218 *out << Verbose( 2) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl;230 *out << Verbose(3) << "ACCEPT: Normalvectors of both triangles are the same: convex." << endl; 219 231 return true; 220 232 } 233 BaseLineNormal.Scale(-1.); 221 234 double angle = GetAngle(helper[0], helper[1], BaseLineNormal); 222 235 if ((angle - M_PI) > -MYEPSILON) { 223 *out << Verbose( 2) << "ACCEPT: Angle is greater than pi: convex." << endl;236 *out << Verbose(3) << "ACCEPT: Angle is greater than pi: convex." << endl; 224 237 return true; 225 238 } else { 226 *out << Verbose( 2) << "REJECT: Angle is less than pi: concave." << endl;239 *out << Verbose(3) << "REJECT: Angle is less than pi: concave." << endl; 227 240 return false; 228 241 } … … 261 274 ostream & operator <<(ostream &ost, BoundaryLineSet &a) 262 275 { 263 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " ," << a.endpoints[1]->node->Name << "]";276 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 << "]"; 264 277 return ost; 265 278 }; … … 331 344 for (int i = 0; i < 3; i++) { 332 345 if (lines[i] != NULL) { 333 if (lines[i]->triangles.erase(Nr)) 334 cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 346 if (lines[i]->triangles.erase(Nr)) { 347 //cout << Verbose(5) << "Triangle Nr." << Nr << " erased in line " << *lines[i] << "." << endl; 348 } 335 349 if (lines[i]->triangles.empty()) { 336 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl;350 //cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 337 351 delete (lines[i]); 338 352 lines[i] = NULL; … … 340 354 } 341 355 } 342 cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl;356 //cout << Verbose(5) << "Erasing triangle Nr." << Nr << " itself." << endl; 343 357 }; 344 358 … … 450 464 }; 451 465 466 /** Checks whether three given \a *Points coincide with triangle's endpoints. 467 * \param *Points[3] pointer to BoundaryPointSet 468 * \return true - is the very triangle, false - is not 469 */ 470 bool BoundaryTriangleSet::IsPresentTupel(class BoundaryTriangleSet *T) 471 { 472 return (((endpoints[0] == T->endpoints[0]) 473 || (endpoints[0] == T->endpoints[1]) 474 || (endpoints[0] == T->endpoints[2]) 475 ) && ( 476 (endpoints[1] == T->endpoints[0]) 477 || (endpoints[1] == T->endpoints[1]) 478 || (endpoints[1] == T->endpoints[2]) 479 ) && ( 480 (endpoints[2] == T->endpoints[0]) 481 || (endpoints[2] == T->endpoints[1]) 482 || (endpoints[2] == T->endpoints[2]) 483 484 )); 485 }; 486 452 487 /** Returns the endpoint which is not contained in the given \a *line. 453 488 * \param *line baseline defining two endpoints … … 484 519 ostream &operator <<(ostream &ost, BoundaryTriangleSet &a) 485 520 { 486 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " ,"487 << a.endpoints[1]->node->Name << " ," << a.endpoints[2]->node->Name << "]";521 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << " at " << *a.endpoints[0]->node->node << "," 522 << a.endpoints[1]->node->Name << " at " << *a.endpoints[1]->node->node << "," << a.endpoints[2]->node->Name << " at " << *a.endpoints[2]->node->node << "]"; 488 523 return ost; 489 524 }; … … 504 539 TesselPoint::~TesselPoint() 505 540 { 506 Free((void **)&Name, "TesselPoint::~TesselPoint: *Name");507 541 }; 508 542 … … 511 545 ostream & operator << (ostream &ost, const TesselPoint &a) 512 546 { 513 ost << "[" << (a.Name) << "|" << &a<< "]";547 ost << "[" << (a.Name) << "|" << a.Name << " at " << *a.node << "]"; 514 548 return ost; 515 549 }; … … 568 602 TrianglesOnBoundaryCount = 0; 569 603 InternalPointer = PointsOnBoundary.begin(); 604 LastTriangle = NULL; 605 TriangleFilesWritten = 0; 570 606 } 571 607 ; … … 584 620 cerr << "ERROR: The triangle " << runner->first << " has already been free'd." << endl; 585 621 } 622 cout << "This envelope was written to file " << TriangleFilesWritten << " times(s)." << endl; 586 623 } 587 624 ; … … 1232 1269 void Tesselation::AlwaysAddTesselationTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n) 1233 1270 { 1234 cout << Verbose(4) << "Adding line between" << *(a->node) << " and " << *(b->node) << "." << endl;1271 cout << Verbose(4) << "Adding line [" << LinesOnBoundaryCount << "|" << *(a->node) << " and " << *(b->node) << "." << endl; 1235 1272 BPS[0] = a; 1236 1273 BPS[1] = b; … … 1252 1289 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1253 1290 TrianglesOnBoundaryCount++; 1291 1292 // set as last new triangle 1293 LastTriangle = BTS; 1254 1294 1255 1295 // NOTE: add triangle to local maps is done in constructor of BoundaryTriangleSet … … 1524 1564 CandidateList *OptCandidates = new CandidateList(); 1525 1565 for (int k=0;k<NDIM;k++) { 1566 Oben.Zero(); 1526 1567 Oben.x[k] = 1.; 1527 1568 FirstPoint = MaxPoint[k]; … … 1532 1573 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. 1533 1574 1534 FindSecondPointForTesselation(FirstPoint, NULL,Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_...1575 FindSecondPointForTesselation(FirstPoint, Oben, OptCandidate, &ShortestAngle, RADIUS, LC); // we give same point as next candidate as its bonds are looked into in find_second_... 1535 1576 SecondPoint = OptCandidate; 1536 1577 if (SecondPoint == NULL) // have we found a second point? 1537 1578 continue; 1538 else1539 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n";1540 1579 1541 1580 helper.CopyVector(FirstPoint->node); … … 1559 1598 1560 1599 // adding point 1 and point 2 and add the line between them 1600 cout << Verbose(1) << "Coordinates of start node at " << *FirstPoint->node << "." << endl; 1561 1601 AddTesselationPoint(FirstPoint, 0); 1602 cout << Verbose(1) << "Found second point is at " << *SecondPoint->node << ".\n"; 1562 1603 AddTesselationPoint(SecondPoint, 1); 1563 1604 AddTesselationLine(TPS[0], TPS[1], 0); … … 1632 1673 * @param *LC LinkedCell structure with neighbouring points 1633 1674 */ 1634 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N,LinkedCell *LC)1675 bool Tesselation::FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC) 1635 1676 { 1636 1677 cout << Verbose(0) << "Begin of FindNextSuitableTriangle\n"; … … 1667 1708 CircleRadius = RADIUS*RADIUS - radius/4.; 1668 1709 CirclePlaneNormal.Normalize(); 1669 cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl;1710 //cout << Verbose(2) << "INFO: CircleCenter is at " << CircleCenter << ", CirclePlaneNormal is " << CirclePlaneNormal << " with circle radius " << sqrt(CircleRadius) << "." << endl; 1670 1711 1671 1712 // construct old center … … 1754 1795 result = false; 1755 1796 } 1756 } else if ( existentTrianglesCount == 1) { // If there is a planar region within the structure, we need this triangle a second time.1797 } else if ((existentTrianglesCount >= 1) && (existentTrianglesCount <= 3)) { // If there is a planar region within the structure, we need this triangle a second time. 1757 1798 AddTesselationPoint((*it)->point, 0); 1758 1799 AddTesselationPoint(BaseRay->endpoints[0]->node, 1); … … 1795 1836 // set baseline to new ray from ref point (here endpoints[0]->node) to current candidate (here (*it)->point)) 1796 1837 BaseRay = BLS[0]; 1838 if ((BTS != NULL) && (BTS->NormalVector.NormSquared() < MYEPSILON)) { 1839 *out << Verbose(1) << "CRITICAL: Triangle " << *BTS << " has zero normal vector!" << endl; 1840 exit(255); 1841 } 1842 1797 1843 } 1798 1844 … … 1813 1859 * \param *out output stream for debugging 1814 1860 * \param *Base line to be flipped 1815 * \return NULL - con cave, otherwise endpoint that makes it concave1861 * \return NULL - convex, otherwise endpoint that makes it concave 1816 1862 */ 1817 1863 class BoundaryPointSet *Tesselation::IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base) … … 1890 1936 * \param *out output stream for debugging 1891 1937 * \param *Base line to be flipped 1892 * \return true - line was changed, false - same line as before1893 */ 1894 boolTesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base)1938 * \return volume change due to flipping (0 - then no flipped occured) 1939 */ 1940 double Tesselation::PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base) 1895 1941 { 1896 1942 class BoundaryLineSet *OtherBase; 1897 1943 Vector *ClosestPoint[2]; 1944 double volume; 1898 1945 1899 1946 int m=0; … … 1915 1962 Distance.CopyVector(ClosestPoint[1]); 1916 1963 Distance.SubtractVector(ClosestPoint[0]); 1964 1965 // calculate volume 1966 volume = CalculateVolumeofGeneralTetraeder(Base->endpoints[1]->node->node, OtherBase->endpoints[0]->node->node, OtherBase->endpoints[1]->node->node, Base->endpoints[0]->node->node); 1917 1967 1918 1968 // delete the temporary other base line and the closest points … … 1929 1979 if (Base->triangles.size() < 2) { 1930 1980 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 1931 return false;1981 return 0.; 1932 1982 } 1933 1983 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 1939 1989 if (Distance.ScalarProduct(&BaseLineNormal) > MYEPSILON) { // Distance points outwards, hence OtherBase higher than Base -> flip 1940 1990 *out << Verbose(2) << "ACCEPT: Other base line would be higher: Flipping baseline." << endl; 1941 FlipBaseline(out, Base);1942 return true;1991 // calculate volume summand as a general tetraeder 1992 return volume; 1943 1993 } else { // Base higher than OtherBase -> do nothing 1944 1994 *out << Verbose(2) << "REJECT: Base line is higher: Nothing to do." << endl; 1945 return false; 1946 } 1947 } 1948 }; 1949 1950 /** Returns the closest point on \a *Base with respect to \a *OtherBase. 1951 * \param *out output stream for debugging 1952 * \param *Base reference line 1953 * \param *OtherBase other base line 1954 * \return Vector on reference line that has closest distance 1955 */ 1956 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase) 1957 { 1958 // construct the plane of the two baselines (i.e. take both their directional vectors) 1959 Vector Normal; 1960 Vector Baseline, OtherBaseline; 1961 Baseline.CopyVector(Base->endpoints[1]->node->node); 1962 Baseline.SubtractVector(Base->endpoints[0]->node->node); 1963 OtherBaseline.CopyVector(OtherBase->endpoints[1]->node->node); 1964 OtherBaseline.SubtractVector(OtherBase->endpoints[0]->node->node); 1965 Normal.CopyVector(&Baseline); 1966 Normal.VectorProduct(&OtherBaseline); 1967 Normal.Normalize(); 1968 *out << Verbose(4) << "First direction is " << Baseline << ", second direction is " << OtherBaseline << ", normal of intersection plane is " << Normal << "." << endl; 1969 1970 // project one offset point of OtherBase onto this plane (and add plane offset vector) 1971 Vector NewOffset; 1972 NewOffset.CopyVector(OtherBase->endpoints[0]->node->node); 1973 NewOffset.SubtractVector(Base->endpoints[0]->node->node); 1974 NewOffset.ProjectOntoPlane(&Normal); 1975 NewOffset.AddVector(Base->endpoints[0]->node->node); 1976 Vector NewDirection; 1977 NewDirection.CopyVector(&NewOffset); 1978 NewDirection.AddVector(&OtherBaseline); 1979 1980 // calculate the intersection between this projected baseline and Base 1981 Vector *Intersection = new Vector; 1982 Intersection->GetIntersectionOfTwoLinesOnPlane(out, Base->endpoints[0]->node->node, Base->endpoints[1]->node->node, &NewOffset, &NewDirection, &Normal); 1983 Normal.CopyVector(Intersection); 1984 Normal.SubtractVector(Base->endpoints[0]->node->node); 1985 *out << Verbose(3) << "Found closest point on " << *Base << " at " << *Intersection << ", factor in line is " << fabs(Normal.ScalarProduct(&Baseline)/Baseline.NormSquared()) << "." << endl; 1986 1987 return Intersection; 1995 return 0.; 1996 } 1997 } 1988 1998 }; 1989 1999 … … 1993 2003 * \param *out output stream for debugging 1994 2004 * \param *Base line to be flipped 1995 * \return true - flipping successful, false- something went awry1996 */ 1997 boolTesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base)2005 * \return pointer to allocated new baseline - flipping successful, NULL - something went awry 2006 */ 2007 class BoundaryLineSet * Tesselation::FlipBaseline(ofstream *out, class BoundaryLineSet *Base) 1998 2008 { 1999 2009 class BoundaryLineSet *OldLines[4], *NewLine; … … 2009 2019 if (Base->triangles.size() < 2) { 2010 2020 *out << Verbose(2) << "ERROR: Less than two triangles are attached to this baseline!" << endl; 2011 return false;2021 return NULL; 2012 2022 } 2013 2023 for (TriangleMap::iterator runner = Base->triangles.begin(); runner != Base->triangles.end(); runner++) { … … 2045 2055 if (i<4) { 2046 2056 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2047 return false;2057 return NULL; 2048 2058 } 2049 2059 for (int j=0;j<4;j++) 2050 2060 if (OldLines[j] == NULL) { 2051 2061 *out << Verbose(1) << "ERROR: We have not gathered enough baselines!" << endl; 2052 return false;2062 return NULL; 2053 2063 } 2054 2064 for (int j=0;j<2;j++) 2055 2065 if (OldPoints[j] == NULL) { 2056 2066 *out << Verbose(1) << "ERROR: We have not gathered enough endpoints!" << endl; 2057 return false;2067 return NULL; 2058 2068 } 2059 2069 … … 2099 2109 } else { 2100 2110 *out << Verbose(1) << "The four old lines do not connect, something's utterly wrong here!" << endl; 2101 return false;2111 return NULL; 2102 2112 } 2103 2113 2104 2114 *out << Verbose(1) << "End of FlipBaseline" << endl; 2105 return true;2115 return NewLine; 2106 2116 }; 2107 2117 … … 2109 2119 /** Finds the second point of starting triangle. 2110 2120 * \param *a first node 2111 * \param *Candidate pointer to candidate node on return2112 2121 * \param Oben vector indicating the outside 2113 2122 * \param OptCandidate reference to recommended candidate on return … … 2116 2125 * \param *LC LinkedCell structure with neighbouring points 2117 2126 */ 2118 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, TesselPoint* Candidate,Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC)2127 void Tesselation::FindSecondPointForTesselation(TesselPoint* a, Vector Oben, TesselPoint*& OptCandidate, double Storage[3], double RADIUS, LinkedCell *LC) 2119 2128 { 2120 2129 cout << Verbose(2) << "Begin of FindSecondPointForTesselation" << endl; 2121 2130 Vector AngleCheck; 2131 class TesselPoint* Candidate = NULL; 2122 2132 double norm = -1., angle; 2123 2133 LinkedNodes *List = NULL; … … 2254 2264 cout << Verbose(1) << "Begin of FindThirdPointForTesselation" << endl; 2255 2265 2256 //cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl;2266 cout << Verbose(2) << "INFO: NormalVector of BaseTriangle is " << NormalVector << "." << endl; 2257 2267 2258 2268 // construct center of circle … … 2279 2289 radius = OldSphereCenter.ScalarProduct(&OldSphereCenter); 2280 2290 if (fabs(radius - CircleRadius) < HULLEPSILON) { 2291 //cout << Verbose(2) << "INFO: OldSphereCenter is at " << OldSphereCenter << "." << endl; 2281 2292 2282 2293 // check SearchDirection … … 2455 2466 TesselPoint *trianglePoints[3]; 2456 2467 TesselPoint *SecondPoint = NULL; 2468 list<BoundaryTriangleSet*> *triangles = NULL; 2457 2469 2458 2470 if (LinesOnBoundary.empty()) { … … 2465 2477 // check whether closest point is "too close" :), then it's inside 2466 2478 if (trianglePoints[0] == NULL) { 2467 *out << Verbose( 1) << "Is the only point, no one else is closeby." << endl;2479 *out << Verbose(2) << "Is the only point, no one else is closeby." << endl; 2468 2480 return NULL; 2469 2481 } 2470 2482 if (trianglePoints[0]->node->DistanceSquared(x) < MYEPSILON) { 2471 *out << Verbose(1) << "Point is right on a tesselation point, no nearest triangle." << endl; 2472 return NULL; 2473 } 2474 list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x); 2475 trianglePoints[1] = connectedClosestPoints->front(); 2476 trianglePoints[2] = connectedClosestPoints->back(); 2477 for (int i=0;i<3;i++) { 2478 if (trianglePoints[i] == NULL) { 2479 *out << Verbose(1) << "IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2480 } 2481 //*out << Verbose(1) << "List of possible points:" << endl; 2482 //*out << Verbose(2) << *trianglePoints[i] << endl; 2483 } 2484 2485 list<BoundaryTriangleSet*> *triangles = FindTriangles(trianglePoints); 2486 2487 delete(connectedClosestPoints); 2483 *out << Verbose(2) << "Point is right on a tesselation point, no nearest triangle." << endl; 2484 PointMap::iterator PointRunner = PointsOnBoundary.find(trianglePoints[0]->nr); 2485 triangles = new list<BoundaryTriangleSet*>; 2486 if (PointRunner != PointsOnBoundary.end()) { 2487 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2488 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2489 triangles->push_back(TriangleRunner->second); 2490 triangles->sort(); 2491 triangles->unique(); 2492 } else { 2493 PointRunner = PointsOnBoundary.find(SecondPoint->nr); 2494 trianglePoints[0] = SecondPoint; 2495 if (PointRunner != PointsOnBoundary.end()) { 2496 for(LineMap::iterator LineRunner = PointRunner->second->lines.begin(); LineRunner != PointRunner->second->lines.end(); LineRunner++) 2497 for(TriangleMap::iterator TriangleRunner = LineRunner->second->triangles.begin(); TriangleRunner != LineRunner->second->triangles.end(); TriangleRunner++) 2498 triangles->push_back(TriangleRunner->second); 2499 triangles->sort(); 2500 triangles->unique(); 2501 } else { 2502 *out << Verbose(1) << "ERROR: I cannot find a boundary point to the tessel point " << *trianglePoints[0] << "." << endl; 2503 return NULL; 2504 } 2505 } 2506 } else { 2507 list<TesselPoint*> *connectedClosestPoints = GetCircleOfConnectedPoints(out, trianglePoints[0], x); 2508 trianglePoints[1] = connectedClosestPoints->front(); 2509 trianglePoints[2] = connectedClosestPoints->back(); 2510 for (int i=0;i<3;i++) { 2511 if (trianglePoints[i] == NULL) { 2512 *out << Verbose(1) << "ERROR: IsInnerPoint encounters serious error, point " << i << " not found." << endl; 2513 } 2514 *out << Verbose(1) << "List of triangle points:" << endl; 2515 *out << Verbose(2) << *trianglePoints[i] << endl; 2516 } 2517 2518 triangles = FindTriangles(trianglePoints); 2519 *out << Verbose(1) << "List of possible triangles:" << endl; 2520 for(list<BoundaryTriangleSet*>::iterator Runner = triangles->begin(); Runner != triangles->end(); Runner++) 2521 *out << Verbose(2) << **Runner << endl; 2522 2523 delete(connectedClosestPoints); 2524 } 2488 2525 2489 2526 if (triangles->empty()) { 2490 *out << Verbose(0) << "Error: There is no nearest triangle. Please check the tesselation structure."; 2527 *out << Verbose(0) << "ERROR: There is no nearest triangle. Please check the tesselation structure."; 2528 delete(triangles); 2491 2529 return NULL; 2492 2530 } else … … 2504 2542 class BoundaryTriangleSet *result = NULL; 2505 2543 list<BoundaryTriangleSet*> *triangles = FindClosestTrianglesToPoint(out, x, LC); 2544 Vector Center; 2506 2545 2507 2546 if (triangles == NULL) 2508 2547 return NULL; 2509 2548 2510 if (x->ScalarProduct(&triangles->front()->NormalVector) < 0) 2511 result = triangles->back(); 2512 else 2549 if (triangles->size() == 1) { // there is no degenerate case 2513 2550 result = triangles->front(); 2514 2551 *out << Verbose(2) << "Normal Vector of this triangle is " << result->NormalVector << "." << endl; 2552 } else { 2553 result = triangles->front(); 2554 result->GetCenter(&Center); 2555 Center.SubtractVector(x); 2556 *out << Verbose(2) << "Normal Vector of this front side is " << result->NormalVector << "." << endl; 2557 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2558 result = triangles->back(); 2559 *out << Verbose(2) << "Normal Vector of this back side is " << result->NormalVector << "." << endl; 2560 if (Center.ScalarProduct(&result->NormalVector) < 0) { 2561 *out << Verbose(1) << "ERROR: Front and back side yield NormalVector in wrong direction!" << endl; 2562 } 2563 } 2564 } 2515 2565 delete(triangles); 2516 2566 return result; … … 2527 2577 { 2528 2578 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, &Point, LC); 2529 if (result == NULL) 2579 Vector Center; 2580 2581 if (result == NULL) {// is boundary point or only point in point cloud? 2582 *out << Verbose(1) << Point << " is the only point in vicinity." << endl; 2583 return false; 2584 } 2585 2586 result->GetCenter(&Center); 2587 *out << Verbose(3) << "INFO: Central point of the triangle is " << Center << "." << endl; 2588 Center.SubtractVector(&Point); 2589 *out << Verbose(3) << "INFO: Vector from center to point to test is " << Center << "." << endl; 2590 if (Center.ScalarProduct(&result->NormalVector) > -MYEPSILON) { 2591 *out << Verbose(1) << Point << " is an inner point." << endl; 2530 2592 return true; 2531 if (Point.ScalarProduct(&result->NormalVector) < 0) 2532 return true; 2533 else 2593 } else { 2594 *out << Verbose(1) << Point << " is NOT an inner point." << endl; 2534 2595 return false; 2596 } 2535 2597 } 2536 2598 … … 2544 2606 bool Tesselation::IsInnerPoint(ofstream *out, TesselPoint *Point, LinkedCell* LC) 2545 2607 { 2546 class BoundaryTriangleSet *result = FindClosestTriangleToPoint(out, Point->node, LC); 2547 if (result == NULL) 2548 return true; 2549 if (Point->node->ScalarProduct(&result->NormalVector) < 0) 2550 return true; 2551 else 2552 return false; 2608 return IsInnerPoint(out, *(Point->node), LC); 2553 2609 } 2554 2610 … … 2705 2761 } 2706 2762 2707 map <class BoundaryLineSet *, bool> Touched; 2708 map <class BoundaryLineSet *, bool>::iterator line; 2709 for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) 2710 Touched.insert( pair <class BoundaryLineSet *, bool>(runner->second, false) ); 2763 map <class BoundaryLineSet *, bool> TouchedLine; 2764 map <class BoundaryTriangleSet *, bool> TouchedTriangle; 2765 map <class BoundaryLineSet *, bool>::iterator LineRunner; 2766 map <class BoundaryTriangleSet *, bool>::iterator TriangleRunner; 2767 for (LineMap::iterator Runner = ReferencePoint->lines.begin(); Runner != ReferencePoint->lines.end(); Runner++) { 2768 TouchedLine.insert( pair <class BoundaryLineSet *, bool>(Runner->second, false) ); 2769 for (TriangleMap::iterator Sprinter = Runner->second->triangles.begin(); Sprinter != Runner->second->triangles.end(); Sprinter++) 2770 TouchedTriangle.insert( pair <class BoundaryTriangleSet *, bool>(Sprinter->second, false) ); 2771 } 2711 2772 if (!ReferencePoint->lines.empty()) { 2712 2773 for (LineMap::iterator runner = ReferencePoint->lines.begin(); runner != ReferencePoint->lines.end(); runner++) { 2713 line = Touched.find(runner->second);2714 if ( line == Touched.end()) {2774 LineRunner = TouchedLine.find(runner->second); 2775 if (LineRunner == TouchedLine.end()) { 2715 2776 *out << Verbose(2) << "ERROR: I could not find " << *runner->second << " in the touched list." << endl; 2716 } else if (! line->second) {2717 line->second = true;2777 } else if (!LineRunner->second) { 2778 LineRunner->second = true; 2718 2779 connectedPath = new list<TesselPoint*>; 2719 2780 triangle = NULL; … … 2728 2789 2729 2790 // find next triangle 2730 for (TriangleMap::iterator TriangleRunner = CurrentLine->triangles.begin(); TriangleRunner != CurrentLine->triangles.end(); TriangleRunner++) { 2731 if (TriangleRunner->second != triangle) { // look for first triangle not equal to old one 2732 triangle = TriangleRunner->second; 2733 break; 2791 for (TriangleMap::iterator Runner = CurrentLine->triangles.begin(); Runner != CurrentLine->triangles.end(); Runner++) { 2792 *out << Verbose(3) << "INFO: Inspecting triangle " << *Runner->second << "." << endl; 2793 if ((Runner->second != triangle)) { // look for first triangle not equal to old one 2794 triangle = Runner->second; 2795 TriangleRunner = TouchedTriangle.find(triangle); 2796 if (TriangleRunner != TouchedTriangle.end()) { 2797 if (!TriangleRunner->second) { 2798 TriangleRunner->second = true; 2799 *out << Verbose(3) << "INFO: Connecting triangle is " << *triangle << "." << endl; 2800 break; 2801 } else { 2802 *out << Verbose(3) << "INFO: Skipping " << *triangle << ", as we have already visited it." << endl; 2803 triangle = NULL; 2804 } 2805 } else { 2806 *out << Verbose(2) << "ERROR: I could not find " << *triangle << " in the touched list." << endl; 2807 triangle = NULL; 2808 } 2734 2809 } 2735 2810 } 2811 if (triangle == NULL) 2812 break; 2736 2813 // find next line 2737 2814 for (int i=0;i<3;i++) { 2738 2815 if ((triangle->lines[i] != CurrentLine) && (triangle->lines[i]->ContainsBoundaryPoint(ReferencePoint))) { // not the current line and still containing Point 2739 2816 CurrentLine = triangle->lines[i]; 2740 2817 *out << Verbose(3) << "INFO: Connecting line is " << *CurrentLine << "." << endl; 2741 2818 break; 2742 2819 } 2743 2820 } 2744 line = Touched.find(CurrentLine);2745 if ( line == Touched.end())2821 LineRunner = TouchedLine.find(CurrentLine); 2822 if (LineRunner == TouchedLine.end()) 2746 2823 *out << Verbose(2) << "ERROR: I could not find " << *CurrentLine << " in the touched list." << endl; 2747 2824 else 2748 line->second = true;2825 LineRunner->second = true; 2749 2826 // find next point 2750 2827 CurrentPoint = CurrentLine->GetOtherEndpoint(ReferencePoint); … … 2753 2830 // last point is missing, as it's on start line 2754 2831 *out << Verbose(3) << "INFO: Putting " << *CurrentPoint << " at end of path." << endl; 2755 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 2832 if (StartLine->GetOtherEndpoint(ReferencePoint)->node != connectedPath->back()) 2833 connectedPath->push_back(StartLine->GetOtherEndpoint(ReferencePoint)->node); 2756 2834 2757 2835 ListOfPaths->push_back(connectedPath); … … 2853 2931 2854 2932 /** Removes a boundary point from the envelope while keeping it closed. 2855 * We create new triangles and remove the old ones connected to the point. 2933 * We remove the old triangles connected to the point and re-create new triangles to close the surface following this ansatz: 2934 * -# a closed path(s) of boundary points surrounding the point to be removed is constructed 2935 * -# on each closed path, we pick three adjacent points, create a triangle with them and subtract the middle point from the path 2936 * -# we advance two points (i.e. the next triangle will start at the ending point of the last triangle) and continue as before 2937 * -# the surface is closed, when the path is empty 2938 * Thereby, we (hopefully) make sure that the removed points remains beneath the surface (this is checked via IsInnerPoint eventually). 2856 2939 * \param *out output stream for debugging 2857 2940 * \param *point point to be removed … … 2861 2944 class BoundaryLineSet *line = NULL; 2862 2945 class BoundaryTriangleSet *triangle = NULL; 2863 Vector OldPoint, TetraederVector[3];2946 Vector OldPoint, NormalVector; 2864 2947 double volume = 0; 2865 2948 int count = 0; … … 2887 2970 count+=LineRunner->second->triangles.size(); 2888 2971 map<class BoundaryTriangleSet *, int> Candidates; 2889 for (LineMap::iterator LineRunner = point->lines.begin(); (point != NULL) && (LineRunner != point->lines.end()); LineRunner++) {2972 for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) { 2890 2973 line = LineRunner->second; 2891 2974 for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) { … … 2897 2980 // remove all triangles 2898 2981 count=0; 2982 NormalVector.Zero(); 2899 2983 for (map<class BoundaryTriangleSet *, int>::iterator Runner = Candidates.begin(); Runner != Candidates.end(); Runner++) { 2900 2984 *out << Verbose(3) << "INFO: Removing triangle " << *(Runner->first) << "." << endl; 2985 NormalVector.SubtractVector(&Runner->first->NormalVector); // has to point inward 2901 2986 RemoveTesselationTriangle(Runner->first); 2902 2987 count++; … … 2907 2992 list<list<TesselPoint*> *>::iterator ListRunner = ListAdvance; 2908 2993 map<class BoundaryTriangleSet *, int>::iterator NumberRunner = Candidates.begin(); 2994 list<TesselPoint*>::iterator StartNode, MiddleNode, EndNode; 2995 double angle; 2996 double smallestangle; 2997 Vector Point, Reference, OrthogonalVector; 2909 2998 if (count > 2) { // less than three triangles, then nothing will be created 2910 2999 class TesselPoint *TriangleCandidates[3]; … … 2915 3004 2916 3005 connectedPath = *ListRunner; 2917 // initialize the path to start2918 list<TesselPoint*>::iterator CircleRunner = connectedPath->begin();2919 list<TesselPoint*>::iterator OtherCircleRunner = connectedPath->begin();2920 class TesselPoint *CentralNode = *CircleRunner;2921 3006 2922 3007 // re-create all triangles by going through connected points list 2923 // advance two with CircleRunner and one with OtherCircleRunner 2924 CircleRunner++; 2925 CircleRunner++; 2926 OtherCircleRunner++; 2927 cout << Verbose(3) << "INFO: CentralNode is " << *CentralNode << "." << endl; 2928 for (; (OtherCircleRunner != connectedPath->end()) && (CircleRunner != connectedPath->end()); (CircleRunner++), (OtherCircleRunner++)) { 2929 cout << Verbose(4) << "INFO: CircleRunner's node is " << **CircleRunner << "." << endl; 2930 cout << Verbose(4) << "INFO: OtherCircleRunner's node is " << **OtherCircleRunner << "." << endl; 2931 *out << Verbose(3) << "INFO: Creating triangle " << CentralNode->Name << ", " << (*OtherCircleRunner)->Name << " and " << (*CircleRunner)->Name << "." << endl; 3008 list<class BoundaryLineSet *> NewLines; 3009 for (;!connectedPath->empty();) { 3010 // search middle node with widest angle to next neighbours 3011 EndNode = connectedPath->end(); 3012 smallestangle = 0.; 3013 for (MiddleNode = connectedPath->begin(); MiddleNode != connectedPath->end(); MiddleNode++) { 3014 cout << Verbose(3) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3015 // construct vectors to next and previous neighbour 3016 StartNode = MiddleNode; 3017 if (StartNode == connectedPath->begin()) 3018 StartNode = connectedPath->end(); 3019 StartNode--; 3020 //cout << Verbose(3) << "INFO: StartNode is " << **StartNode << "." << endl; 3021 Point.CopyVector((*StartNode)->node); 3022 Point.SubtractVector((*MiddleNode)->node); 3023 StartNode = MiddleNode; 3024 StartNode++; 3025 if (StartNode == connectedPath->end()) 3026 StartNode = connectedPath->begin(); 3027 //cout << Verbose(3) << "INFO: EndNode is " << **StartNode << "." << endl; 3028 Reference.CopyVector((*StartNode)->node); 3029 Reference.SubtractVector((*MiddleNode)->node); 3030 OrthogonalVector.CopyVector((*MiddleNode)->node); 3031 OrthogonalVector.SubtractVector(&OldPoint); 3032 OrthogonalVector.MakeNormalVector(&Reference); 3033 angle = GetAngle(Point, Reference, OrthogonalVector); 3034 //if (angle < M_PI) // no wrong-sided triangles, please? 3035 if(fabs(angle - M_PI) < fabs(smallestangle - M_PI)) { // get straightest angle (i.e. construct those triangles with smallest area first) 3036 smallestangle = angle; 3037 EndNode = MiddleNode; 3038 } 3039 } 3040 MiddleNode = EndNode; 3041 if (MiddleNode == connectedPath->end()) { 3042 cout << Verbose(1) << "CRITICAL: Could not find a smallest angle!" << endl; 3043 exit(255); 3044 } 3045 StartNode = MiddleNode; 3046 if (StartNode == connectedPath->begin()) 3047 StartNode = connectedPath->end(); 3048 StartNode--; 3049 EndNode++; 3050 if (EndNode == connectedPath->end()) 3051 EndNode = connectedPath->begin(); 3052 cout << Verbose(4) << "INFO: StartNode is " << **StartNode << "." << endl; 3053 cout << Verbose(4) << "INFO: MiddleNode is " << **MiddleNode << "." << endl; 3054 cout << Verbose(4) << "INFO: EndNode is " << **EndNode << "." << endl; 3055 *out << Verbose(3) << "INFO: Attempting to create triangle " << (*StartNode)->Name << ", " << (*MiddleNode)->Name << " and " << (*EndNode)->Name << "." << endl; 3056 TriangleCandidates[0] = *StartNode; 3057 TriangleCandidates[1] = *MiddleNode; 3058 TriangleCandidates[2] = *EndNode; 3059 triangle = GetPresentTriangle(out, TriangleCandidates); 3060 if (triangle != NULL) { 3061 cout << Verbose(1) << "WARNING: New triangle already present, skipping!" << endl; 3062 StartNode++; 3063 MiddleNode++; 3064 EndNode++; 3065 if (StartNode == connectedPath->end()) 3066 StartNode = connectedPath->begin(); 3067 if (MiddleNode == connectedPath->end()) 3068 MiddleNode = connectedPath->begin(); 3069 if (EndNode == connectedPath->end()) 3070 EndNode = connectedPath->begin(); 3071 continue; 3072 } 2932 3073 *out << Verbose(5) << "Adding new triangle points."<< endl; 2933 TriangleCandidates[0] = CentralNode; 2934 TriangleCandidates[1] = *OtherCircleRunner; 2935 TriangleCandidates[2] = *CircleRunner; 2936 triangle = GetPresentTriangle(out, TriangleCandidates); 2937 AddTesselationPoint(CentralNode, 0); 2938 AddTesselationPoint(*OtherCircleRunner, 1); 2939 AddTesselationPoint(*CircleRunner, 2); 3074 AddTesselationPoint(*StartNode, 0); 3075 AddTesselationPoint(*MiddleNode, 1); 3076 AddTesselationPoint(*EndNode, 2); 2940 3077 *out << Verbose(5) << "Adding new triangle lines."<< endl; 2941 3078 AddTesselationLine(TPS[0], TPS[1], 0); 2942 3079 AddTesselationLine(TPS[0], TPS[2], 1); 3080 NewLines.push_back(BLS[1]); 2943 3081 AddTesselationLine(TPS[1], TPS[2], 2); 2944 3082 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3083 BTS->GetNormalVector(NormalVector); 2945 3084 AddTesselationTriangle(); 2946 3085 // calculate volume summand as a general tetraeder 2947 for (int j=0;j<3;j++) { 2948 TetraederVector[j].CopyVector(TPS[j]->node->node); 2949 TetraederVector[j].SubtractVector(&OldPoint); 3086 volume += CalculateVolumeofGeneralTetraeder(TPS[0]->node->node, TPS[1]->node->node, TPS[2]->node->node, &OldPoint); 3087 // advance number 3088 count++; 3089 3090 // prepare nodes for next triangle 3091 StartNode = EndNode; 3092 cout << Verbose(4) << "Removing " << **MiddleNode << " from closed path, remaining points: " << connectedPath->size() << "." << endl; 3093 connectedPath->remove(*MiddleNode); // remove the middle node (it is surrounded by triangles) 3094 if (connectedPath->size() == 2) { // we are done 3095 connectedPath->remove(*StartNode); // remove the start node 3096 connectedPath->remove(*EndNode); // remove the end node 3097 break; 3098 } else if (connectedPath->size() < 2) { // something's gone wrong! 3099 cout << Verbose(1) << "CRITICAL: There are only two endpoints left!" << endl; 3100 exit(255); 3101 } else { 3102 MiddleNode = StartNode; 3103 MiddleNode++; 3104 if (MiddleNode == connectedPath->end()) 3105 MiddleNode = connectedPath->begin(); 3106 EndNode = MiddleNode; 3107 EndNode++; 3108 if (EndNode == connectedPath->end()) 3109 EndNode = connectedPath->begin(); 2950 3110 } 2951 OldPoint.CopyVector(&TetraederVector[0]);2952 OldPoint.VectorProduct(&TetraederVector[1]);2953 volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));2954 // advance number2955 NumberRunner++;2956 count++;2957 if (NumberRunner == Candidates.end())2958 *out << Verbose(2) << "WARN: Maximum of numbers reached!" << endl;2959 3111 } 3112 // maximize the inner lines (we preferentially created lines with a huge angle, which is for the tesselation not wanted though useful for the closing) 3113 if (NewLines.size() > 1) { 3114 list<class BoundaryLineSet *>::iterator Candidate; 3115 class BoundaryLineSet *OtherBase = NULL; 3116 double tmp, maxgain; 3117 do { 3118 maxgain = 0; 3119 for(list<class BoundaryLineSet *>::iterator Runner = NewLines.begin(); Runner != NewLines.end(); Runner++) { 3120 tmp = PickFarthestofTwoBaselines(out, *Runner); 3121 if (maxgain < tmp) { 3122 maxgain = tmp; 3123 Candidate = Runner; 3124 } 3125 } 3126 if (maxgain != 0) { 3127 volume += maxgain; 3128 cout << Verbose(3) << "Flipping baseline with highest volume" << **Candidate << "." << endl; 3129 OtherBase = FlipBaseline(out, *Candidate); 3130 NewLines.erase(Candidate); 3131 NewLines.push_back(OtherBase); 3132 } 3133 } while (maxgain != 0.); 3134 } 3135 2960 3136 ListOfClosedPaths->remove(connectedPath); 2961 3137 delete(connectedPath); … … 2971 3147 *out << Verbose(1) << "No need to create any triangles." << endl; 2972 3148 } 2973 2974 3149 delete(ListOfClosedPaths); 2975 3150 3151 *out << Verbose(1) << "Removed volume is " << volume << "." << endl; 3152 2976 3153 return volume; 2977 3154 }; 2978 3155 2979 3156 2980 2981 /** Checks for a new special triangle whether one of its edges is already present with one one triangle connected.2982 * This enforces that special triangles (i.e. degenerated ones) should at last close the open-edge frontier and not2983 * make it bigger (i.e. closing one (the baseline) and opening two new ones).2984 * \param TPS[3] nodes of the triangle2985 * \return true - there is such a line (i.e. creation of degenerated triangle is valid), false - no such line (don't create)2986 */2987 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3])2988 {2989 bool result = false;2990 int counter = 0;2991 2992 // check all three points2993 for (int i=0;i<3;i++)2994 for (int j=i+1; j<3; j++) {2995 if (nodes[i]->lines.find(nodes[j]->node->nr) != nodes[i]->lines.end()) { // there already is a line2996 LineMap::iterator FindLine;2997 pair<LineMap::iterator,LineMap::iterator> FindPair;2998 FindPair = nodes[i]->lines.equal_range(nodes[j]->node->nr);2999 for (FindLine = FindPair.first; FindLine != FindPair.second; ++FindLine) {3000 // If there is a line with less than two attached triangles, we don't need a new line.3001 if (FindLine->second->triangles.size() < 2) {3002 counter++;3003 break; // increase counter only once per edge3004 }3005 }3006 } else { // no line3007 cout << Verbose(1) << "The line between " << nodes[i] << " and " << nodes[j] << " is not yet present, hence no need for a degenerate triangle." << endl;3008 result = true;3009 }3010 }3011 if (counter > 1) {3012 cout << Verbose(2) << "INFO: Degenerate triangle is ok, at least two, here " << counter << ", existing lines are used." << endl;3013 result = true;3014 }3015 return result;3016 };3017 3018 3019 /** Sort function for the candidate list.3020 */3021 bool SortCandidates(CandidateForTesselation* candidate1, CandidateForTesselation* candidate2)3022 {3023 Vector BaseLineVector, OrthogonalVector, helper;3024 if (candidate1->BaseLine != candidate2->BaseLine) { // sanity check3025 cout << Verbose(0) << "ERROR: sortCandidates was called for two different baselines: " << candidate1->BaseLine << " and " << candidate2->BaseLine << "." << endl;3026 //return false;3027 exit(1);3028 }3029 // create baseline vector3030 BaseLineVector.CopyVector(candidate1->BaseLine->endpoints[1]->node->node);3031 BaseLineVector.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3032 BaseLineVector.Normalize();3033 3034 // 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!)3035 helper.CopyVector(candidate1->BaseLine->endpoints[0]->node->node);3036 helper.SubtractVector(candidate1->point->node);3037 OrthogonalVector.CopyVector(&helper);3038 helper.VectorProduct(&BaseLineVector);3039 OrthogonalVector.SubtractVector(&helper);3040 OrthogonalVector.Normalize();3041 3042 // calculate both angles and correct with in-plane vector3043 helper.CopyVector(candidate1->point->node);3044 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3045 double phi = BaseLineVector.Angle(&helper);3046 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3047 phi = 2.*M_PI - phi;3048 }3049 helper.CopyVector(candidate2->point->node);3050 helper.SubtractVector(candidate1->BaseLine->endpoints[0]->node->node);3051 double psi = BaseLineVector.Angle(&helper);3052 if (OrthogonalVector.ScalarProduct(&helper) > 0) {3053 psi = 2.*M_PI - psi;3054 }3055 3056 cout << Verbose(2) << *candidate1->point << " has angle " << phi << endl;3057 cout << Verbose(2) << *candidate2->point << " has angle " << psi << endl;3058 3059 // return comparison3060 return phi < psi;3061 };3062 3063 /**3064 * Finds the point which is second closest to the provided one.3065 *3066 * @param Point to which to find the second closest other point3067 * @param linked cell structure3068 *3069 * @return point which is second closest to the provided one3070 */3071 TesselPoint* FindSecondClosestPoint(const Vector* Point, LinkedCell* LC)3072 {3073 LinkedNodes *List = NULL;3074 TesselPoint* closestPoint = NULL;3075 TesselPoint* secondClosestPoint = NULL;3076 double distance = 1e16;3077 double secondDistance = 1e16;3078 Vector helper;3079 int N[NDIM], Nlower[NDIM], Nupper[NDIM];3080 3081 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly3082 for(int i=0;i<NDIM;i++) // store indices of this cell3083 N[i] = LC->n[i];3084 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;3085 3086 LC->GetNeighbourBounds(Nlower, Nupper);3087 //cout << endl;3088 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)3089 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)3090 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {3091 List = LC->GetCurrentCell();3092 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;3093 if (List != NULL) {3094 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {3095 helper.CopyVector(Point);3096 helper.SubtractVector((*Runner)->node);3097 double currentNorm = helper. Norm();3098 if (currentNorm < distance) {3099 // remember second point3100 secondDistance = distance;3101 secondClosestPoint = closestPoint;3102 // mark down new closest point3103 distance = currentNorm;3104 closestPoint = (*Runner);3105 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;3106 }3107 }3108 } else {3109 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","3110 << LC->n[2] << " is invalid!" << endl;3111 }3112 }3113 3114 return secondClosestPoint;3115 };3116 3117 /**3118 * Finds the point which is closest to the provided one.3119 *3120 * @param Point to which to find the closest other point3121 * @param SecondPoint the second closest other point on return, NULL if none found3122 * @param linked cell structure3123 *3124 * @return point which is closest to the provided one, NULL if none found3125 */3126 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC)3127 {3128 LinkedNodes *List = NULL;3129 TesselPoint* closestPoint = NULL;3130 SecondPoint = NULL;3131 double distance = 1e16;3132 double secondDistance = 1e16;3133 Vector helper;3134 int N[NDIM], Nlower[NDIM], Nupper[NDIM];3135 3136 LC->SetIndexToVector(Point); // ignore status as we calculate bounds below sensibly3137 for(int i=0;i<NDIM;i++) // store indices of this cell3138 N[i] = LC->n[i];3139 cout << Verbose(2) << "INFO: Center cell is " << N[0] << ", " << N[1] << ", " << N[2] << " with No. " << LC->index << "." << endl;3140 3141 LC->GetNeighbourBounds(Nlower, Nupper);3142 //cout << endl;3143 for (LC->n[0] = Nlower[0]; LC->n[0] <= Nupper[0]; LC->n[0]++)3144 for (LC->n[1] = Nlower[1]; LC->n[1] <= Nupper[1]; LC->n[1]++)3145 for (LC->n[2] = Nlower[2]; LC->n[2] <= Nupper[2]; LC->n[2]++) {3146 List = LC->GetCurrentCell();3147 cout << Verbose(3) << "The current cell " << LC->n[0] << "," << LC->n[1] << "," << LC->n[2] << endl;3148 if (List != NULL) {3149 for (LinkedNodes::iterator Runner = List->begin(); Runner != List->end(); Runner++) {3150 helper.CopyVector(Point);3151 helper.SubtractVector((*Runner)->node);3152 double currentNorm = helper. Norm();3153 if (currentNorm < distance) {3154 secondDistance = distance;3155 SecondPoint = closestPoint;3156 distance = currentNorm;3157 closestPoint = (*Runner);3158 cout << Verbose(2) << "INFO: New Nearest Neighbour is " << *closestPoint << "." << endl;3159 } else if (currentNorm < secondDistance) {3160 secondDistance = currentNorm;3161 SecondPoint = (*Runner);3162 cout << Verbose(2) << "INFO: New Second Nearest Neighbour is " << *SecondPoint << "." << endl;3163 }3164 }3165 } else {3166 cerr << "ERROR: The current cell " << LC->n[0] << "," << LC->n[1] << ","3167 << LC->n[2] << " is invalid!" << endl;3168 }3169 }3170 3171 return closestPoint;3172 };3173 3157 3174 3158 /** … … 3207 3191 FindTriangle = FindLine->second->triangles.begin(); 3208 3192 for (; FindTriangle != FindLine->second->triangles.end(); FindTriangle++) { 3209 if (( 3210 (FindTriangle->second->endpoints[0] == TrianglePoints[0]) 3211 || (FindTriangle->second->endpoints[0] == TrianglePoints[1]) 3212 || (FindTriangle->second->endpoints[0] == TrianglePoints[2]) 3213 ) && ( 3214 (FindTriangle->second->endpoints[1] == TrianglePoints[0]) 3215 || (FindTriangle->second->endpoints[1] == TrianglePoints[1]) 3216 || (FindTriangle->second->endpoints[1] == TrianglePoints[2]) 3217 ) && ( 3218 (FindTriangle->second->endpoints[2] == TrianglePoints[0]) 3219 || (FindTriangle->second->endpoints[2] == TrianglePoints[1]) 3220 || (FindTriangle->second->endpoints[2] == TrianglePoints[2]) 3221 ) 3222 ) { 3193 if (FindTriangle->second->IsPresentTupel(TrianglePoints)) { 3223 3194 result->push_back(FindTriangle->second); 3224 3195 } … … 3238 3209 3239 3210 /** 3211 * Finds all degenerated lines within the tesselation structure. 3212 * 3213 * @return map of keys of degenerated line pairs, each line occurs twice 3214 * in the list, once as key and once as value 3215 */ 3216 map<int, int> * Tesselation::FindAllDegeneratedLines() 3217 { 3218 map<int, class BoundaryLineSet *> AllLines; 3219 map<int, int> * DegeneratedLines = new map<int, int>; 3220 3221 // sanity check 3222 if (LinesOnBoundary.empty()) { 3223 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure."; 3224 return DegeneratedLines; 3225 } 3226 3227 LineMap::iterator LineRunner1; 3228 pair<LineMap::iterator, bool> tester; 3229 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3230 tester = AllLines.insert( pair<int,BoundaryLineSet *> (LineRunner1->second->endpoints[0]->Nr, LineRunner1->second) ); 3231 if ((!tester.second) && (tester.first->second->endpoints[1]->Nr == LineRunner1->second->endpoints[1]->Nr)) { // found degenerated line 3232 DegeneratedLines->insert ( pair<int, int> (LineRunner1->second->Nr, tester.first->second->Nr) ); 3233 DegeneratedLines->insert ( pair<int, int> (tester.first->second->Nr, LineRunner1->second->Nr) ); 3234 } 3235 } 3236 3237 AllLines.clear(); 3238 3239 cout << Verbose(1) << "FindAllDegeneratedLines() found " << DegeneratedLines->size() << " lines." << endl; 3240 map<int,int>::iterator it; 3241 for (it = DegeneratedLines->begin(); it != DegeneratedLines->end(); it++) 3242 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3243 3244 return DegeneratedLines; 3245 } 3246 3247 /** 3240 3248 * Finds all degenerated triangles within the tesselation structure. 3241 3249 * … … 3243 3251 * in the list, once as key and once as value 3244 3252 */ 3245 map<int, int> Tesselation::FindAllDegeneratedTriangles() 3246 { 3247 map<int, int> DegeneratedTriangles; 3248 3249 // sanity check 3250 if (LinesOnBoundary.empty()) { 3251 cout << Verbose(1) << "Warning: FindAllDegeneratedTriangles() was called without any tesselation structure."; 3252 return DegeneratedTriangles; 3253 } 3254 3255 LineMap::iterator LineRunner1, LineRunner2; 3256 3257 for (LineRunner1 = LinesOnBoundary.begin(); LineRunner1 != LinesOnBoundary.end(); ++LineRunner1) { 3258 for (LineRunner2 = LinesOnBoundary.begin(); LineRunner2 != LinesOnBoundary.end(); ++LineRunner2) { 3259 if ((LineRunner1->second != LineRunner2->second) 3260 && (LineRunner1->second->endpoints[0] == LineRunner2->second->endpoints[0]) 3261 && (LineRunner1->second->endpoints[1] == LineRunner2->second->endpoints[1]) 3262 ) { 3263 TriangleMap::iterator TriangleRunner1 = LineRunner1->second->triangles.begin(), 3264 TriangleRunner2 = LineRunner2->second->triangles.begin(); 3265 3266 for (; TriangleRunner1 != LineRunner1->second->triangles.end(); ++TriangleRunner1) { 3267 for (; TriangleRunner2 != LineRunner2->second->triangles.end(); ++TriangleRunner2) { 3268 if ((TriangleRunner1->second != TriangleRunner2->second) 3269 && (TriangleRunner1->second->endpoints[0] == TriangleRunner2->second->endpoints[0]) 3270 && (TriangleRunner1->second->endpoints[1] == TriangleRunner2->second->endpoints[1]) 3271 && (TriangleRunner1->second->endpoints[2] == TriangleRunner2->second->endpoints[2]) 3272 ) { 3273 DegeneratedTriangles[TriangleRunner1->second->Nr] = TriangleRunner2->second->Nr; 3274 DegeneratedTriangles[TriangleRunner2->second->Nr] = TriangleRunner1->second->Nr; 3275 } 3276 } 3253 map<int, int> * Tesselation::FindAllDegeneratedTriangles() 3254 { 3255 map<int, int> * DegeneratedLines = FindAllDegeneratedLines(); 3256 map<int, int> * DegeneratedTriangles = new map<int, int>; 3257 3258 TriangleMap::iterator TriangleRunner1, TriangleRunner2; 3259 LineMap::iterator Liner; 3260 class BoundaryLineSet *line1 = NULL, *line2 = NULL; 3261 3262 for (map<int, int>::iterator LineRunner = DegeneratedLines->begin(); LineRunner != DegeneratedLines->end(); ++LineRunner) { 3263 // run over both lines' triangles 3264 Liner = LinesOnBoundary.find(LineRunner->first); 3265 if (Liner != LinesOnBoundary.end()) 3266 line1 = Liner->second; 3267 Liner = LinesOnBoundary.find(LineRunner->second); 3268 if (Liner != LinesOnBoundary.end()) 3269 line2 = Liner->second; 3270 for (TriangleRunner1 = line1->triangles.begin(); TriangleRunner1 != line1->triangles.end(); ++TriangleRunner1) { 3271 for (TriangleRunner2 = line2->triangles.begin(); TriangleRunner2 != line2->triangles.end(); ++TriangleRunner2) { 3272 if ((TriangleRunner1->second != TriangleRunner2->second) 3273 && (TriangleRunner1->second->IsPresentTupel(TriangleRunner2->second))) { 3274 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner1->second->Nr, TriangleRunner2->second->Nr) ); 3275 DegeneratedTriangles->insert( pair<int, int> (TriangleRunner2->second->Nr, TriangleRunner1->second->Nr) ); 3277 3276 } 3278 3277 } 3279 3278 } 3280 3279 } 3281 3282 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles.size() << " triangles." << endl; 3280 delete(DegeneratedLines); 3281 3282 cout << Verbose(1) << "FindAllDegeneratedTriangles() found " << DegeneratedTriangles->size() << " triangles:" << endl; 3283 3283 map<int,int>::iterator it; 3284 for (it = DegeneratedTriangles .begin(); it != DegeneratedTriangles.end(); it++)3284 for (it = DegeneratedTriangles->begin(); it != DegeneratedTriangles->end(); it++) 3285 3285 cout << Verbose(2) << (*it).first << " => " << (*it).second << endl; 3286 3286 … … 3294 3294 void Tesselation::RemoveDegeneratedTriangles() 3295 3295 { 3296 map<int, int> DegeneratedTriangles = FindAllDegeneratedTriangles(); 3297 3298 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles.begin(); 3299 TriangleKeyRunner != DegeneratedTriangles.end(); ++TriangleKeyRunner 3296 map<int, int> * DegeneratedTriangles = FindAllDegeneratedTriangles(); 3297 TriangleMap::iterator finder; 3298 BoundaryTriangleSet *triangle = NULL, *partnerTriangle = NULL; 3299 int count = 0; 3300 3301 for (map<int, int>::iterator TriangleKeyRunner = DegeneratedTriangles->begin(); 3302 TriangleKeyRunner != DegeneratedTriangles->end(); ++TriangleKeyRunner 3300 3303 ) { 3301 BoundaryTriangleSet *triangle = TrianglesOnBoundary.find(TriangleKeyRunner->first)->second, 3302 *partnerTriangle = TrianglesOnBoundary.find(TriangleKeyRunner->second)->second; 3304 finder = TrianglesOnBoundary.find(TriangleKeyRunner->first); 3305 if (finder != TrianglesOnBoundary.end()) 3306 triangle = finder->second; 3307 else 3308 break; 3309 finder = TrianglesOnBoundary.find(TriangleKeyRunner->second); 3310 if (finder != TrianglesOnBoundary.end()) 3311 partnerTriangle = finder->second; 3312 else 3313 break; 3303 3314 3304 3315 bool trianglesShareLine = false; … … 3312 3323 && (triangle->endpoints[0]->LinesCount > 2) 3313 3324 ) { 3325 // check whether we have to fix lines 3326 BoundaryTriangleSet *Othertriangle = NULL; 3327 BoundaryTriangleSet *OtherpartnerTriangle = NULL; 3328 TriangleMap::iterator TriangleRunner; 3329 for (int i = 0; i < 3; ++i) 3330 for (int j = 0; j < 3; ++j) 3331 if (triangle->lines[i] != partnerTriangle->lines[j]) { 3332 // get the other two triangles 3333 for (TriangleRunner = triangle->lines[i]->triangles.begin(); TriangleRunner != triangle->lines[i]->triangles.end(); ++TriangleRunner) 3334 if (TriangleRunner->second != triangle) { 3335 Othertriangle = TriangleRunner->second; 3336 } 3337 for (TriangleRunner = partnerTriangle->lines[i]->triangles.begin(); TriangleRunner != partnerTriangle->lines[i]->triangles.end(); ++TriangleRunner) 3338 if (TriangleRunner->second != partnerTriangle) { 3339 OtherpartnerTriangle = TriangleRunner->second; 3340 } 3341 /// interchanges their lines so that triangle->lines[i] == partnerTriangle->lines[j] 3342 // the line of triangle receives the degenerated ones 3343 triangle->lines[i]->triangles.erase(Othertriangle->Nr); 3344 triangle->lines[i]->triangles.insert( TrianglePair( partnerTriangle->Nr, partnerTriangle) ); 3345 for (int k=0;k<3;k++) 3346 if (triangle->lines[i] == Othertriangle->lines[k]) { 3347 Othertriangle->lines[k] = partnerTriangle->lines[j]; 3348 break; 3349 } 3350 // the line of partnerTriangle receives the non-degenerated ones 3351 partnerTriangle->lines[j]->triangles.erase( partnerTriangle->Nr); 3352 partnerTriangle->lines[j]->triangles.insert( TrianglePair( Othertriangle->Nr, Othertriangle) ); 3353 partnerTriangle->lines[j] = triangle->lines[i]; 3354 } 3355 3356 // erase the pair 3357 count += (int) DegeneratedTriangles->erase(triangle->Nr); 3314 3358 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *triangle << "." << endl; 3315 3359 RemoveTesselationTriangle(triangle); 3360 count += (int) DegeneratedTriangles->erase(partnerTriangle->Nr); 3316 3361 cout << Verbose(1) << "RemoveDegeneratedTriangles() removes triangle " << *partnerTriangle << "." << endl; 3317 3362 RemoveTesselationTriangle(partnerTriangle); 3318 DegeneratedTriangles.erase(DegeneratedTriangles.find(partnerTriangle->Nr));3319 3363 } else { 3320 3364 cout << Verbose(1) << "RemoveDegeneratedTriangles() does not remove triangle " << *triangle … … 3323 3367 } 3324 3368 } 3369 delete(DegeneratedTriangles); 3370 3371 cout << Verbose(1) << "RemoveDegeneratedTriangles() removed " << count << " triangles:" << endl; 3325 3372 } 3326 3373 3327 /** Gets the angle between a point and a reference relative to the provided center. 3328 * We have two shanks point and reference between which the angle is calculated 3329 * and by scalar product with OrthogonalVector we decide the interval. 3330 * @param point to calculate the angle for 3331 * @param reference to which to calculate the angle 3332 * @param OrthogonalVector points in direction of [pi,2pi] interval 3333 * 3334 * @return angle between point and reference 3335 */ 3336 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector) 3337 { 3338 if (reference.IsZero()) 3339 return M_PI; 3340 3341 // calculate both angles and correct with in-plane vector 3342 if (point.IsZero()) 3343 return M_PI; 3344 double phi = point.Angle(&reference); 3345 if (OrthogonalVector.ScalarProduct(&point) > 0) { 3346 phi = 2.*M_PI - phi; 3347 } 3348 3349 cout << Verbose(4) << "INFO: " << point << " has angle " << phi << " with respect to reference " << reference << "." << endl; 3350 3351 return phi; 3352 } 3353 3374 /** Adds an outside Tesselpoint to the envelope via (two) degenerated triangles. 3375 * We look for the closest point on the boundary, we look through its connected boundary lines and 3376 * seek the one with the minimum angle between its center point and the new point and this base line. 3377 * We open up the line by adding a degenerated triangle, whose other side closes the base line again. 3378 * \param *out output stream for debugging 3379 * \param *point point to add 3380 * \param *LC Linked Cell structure to find nearest point 3381 */ 3382 void Tesselation::AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC) 3383 { 3384 *out << Verbose(2) << "Begin of AddBoundaryPointByDegeneratedTriangle" << endl; 3385 3386 // find nearest boundary point 3387 class TesselPoint *BackupPoint = NULL; 3388 class TesselPoint *NearestPoint = FindClosestPoint(point->node, BackupPoint, LC); 3389 class BoundaryPointSet *NearestBoundaryPoint = NULL; 3390 PointMap::iterator PointRunner; 3391 3392 if (NearestPoint == point) 3393 NearestPoint = BackupPoint; 3394 PointRunner = PointsOnBoundary.find(NearestPoint->nr); 3395 if (PointRunner != PointsOnBoundary.end()) { 3396 NearestBoundaryPoint = PointRunner->second; 3397 } else { 3398 *out << Verbose(1) << "ERROR: I cannot find the boundary point." << endl; 3399 return; 3400 } 3401 *out << Verbose(2) << "Nearest point on boundary is " << NearestPoint->Name << "." << endl; 3402 3403 // go through its lines and find the best one to split 3404 Vector CenterToPoint; 3405 Vector BaseLine; 3406 double angle, BestAngle = 0.; 3407 class BoundaryLineSet *BestLine = NULL; 3408 for (LineMap::iterator Runner = NearestBoundaryPoint->lines.begin(); Runner != NearestBoundaryPoint->lines.end(); Runner++) { 3409 BaseLine.CopyVector(Runner->second->endpoints[0]->node->node); 3410 BaseLine.SubtractVector(Runner->second->endpoints[1]->node->node); 3411 CenterToPoint.CopyVector(Runner->second->endpoints[0]->node->node); 3412 CenterToPoint.AddVector(Runner->second->endpoints[1]->node->node); 3413 CenterToPoint.Scale(0.5); 3414 CenterToPoint.SubtractVector(point->node); 3415 angle = CenterToPoint.Angle(&BaseLine); 3416 if (fabs(angle - M_PI/2.) < fabs(BestAngle - M_PI/2.)) { 3417 BestAngle = angle; 3418 BestLine = Runner->second; 3419 } 3420 } 3421 3422 // remove one triangle from the chosen line 3423 class BoundaryTriangleSet *TempTriangle = (BestLine->triangles.begin())->second; 3424 BestLine->triangles.erase(TempTriangle->Nr); 3425 int nr = -1; 3426 for (int i=0;i<3; i++) { 3427 if (TempTriangle->lines[i] == BestLine) { 3428 nr = i; 3429 break; 3430 } 3431 } 3432 3433 // create new triangle to connect point (connects automatically with the missing spot of the chosen line) 3434 *out << Verbose(5) << "Adding new triangle points."<< endl; 3435 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3436 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3437 AddTesselationPoint(point, 2); 3438 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3439 AddTesselationLine(TPS[0], TPS[1], 0); 3440 AddTesselationLine(TPS[0], TPS[2], 1); 3441 AddTesselationLine(TPS[1], TPS[2], 2); 3442 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3443 BTS->GetNormalVector(TempTriangle->NormalVector); 3444 BTS->NormalVector.Scale(-1.); 3445 *out << Verbose(3) << "INFO: NormalVector of new triangle is " << BTS->NormalVector << "." << endl; 3446 AddTesselationTriangle(); 3447 3448 // create other side of this triangle and close both new sides of the first created triangle 3449 *out << Verbose(5) << "Adding new triangle points."<< endl; 3450 AddTesselationPoint((BestLine->endpoints[0]->node), 0); 3451 AddTesselationPoint((BestLine->endpoints[1]->node), 1); 3452 AddTesselationPoint(point, 2); 3453 *out << Verbose(5) << "Adding new triangle lines."<< endl; 3454 AddTesselationLine(TPS[0], TPS[1], 0); 3455 AddTesselationLine(TPS[0], TPS[2], 1); 3456 AddTesselationLine(TPS[1], TPS[2], 2); 3457 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 3458 BTS->GetNormalVector(TempTriangle->NormalVector); 3459 *out << Verbose(3) << "INFO: NormalVector of other new triangle is " << BTS->NormalVector << "." << endl; 3460 AddTesselationTriangle(); 3461 3462 // add removed triangle to the last open line of the second triangle 3463 for (int i=0;i<3;i++) { // look for the same line as BestLine (only it's its degenerated companion) 3464 if ((BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[0])) && (BTS->lines[i]->ContainsBoundaryPoint(BestLine->endpoints[1]))) { 3465 if (BestLine == BTS->lines[i]){ 3466 *out << Verbose(1) << "CRITICAL: BestLine is same as found line, something's wrong here!" << endl; 3467 exit(255); 3468 } 3469 BTS->lines[i]->triangles.insert( pair<int, class BoundaryTriangleSet *> (TempTriangle->Nr, TempTriangle) ); 3470 TempTriangle->lines[nr] = BTS->lines[i]; 3471 break; 3472 } 3473 } 3474 3475 // exit 3476 *out << Verbose(2) << "End of AddBoundaryPointByDegeneratedTriangle" << endl; 3477 }; 3478 3479 /** Writes the envelope to file. 3480 * \param *out otuput stream for debugging 3481 * \param *filename basename of output file 3482 * \param *cloud PointCloud structure with all nodes 3483 */ 3484 void Tesselation::Output(ofstream *out, const char *filename, PointCloud *cloud) 3485 { 3486 ofstream *tempstream = NULL; 3487 string NameofTempFile; 3488 char NumberName[255]; 3489 3490 if (LastTriangle != NULL) { 3491 sprintf(NumberName, "-%04d-%s_%s_%s", (int)TrianglesOnBoundary.size(), LastTriangle->endpoints[0]->node->Name, LastTriangle->endpoints[1]->node->Name, LastTriangle->endpoints[2]->node->Name); 3492 if (DoTecplotOutput) { 3493 string NameofTempFile(filename); 3494 NameofTempFile.append(NumberName); 3495 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3496 NameofTempFile.erase(npos, 1); 3497 NameofTempFile.append(TecplotSuffix); 3498 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3499 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3500 WriteTecplotFile(out, tempstream, this, cloud, TriangleFilesWritten); 3501 tempstream->close(); 3502 tempstream->flush(); 3503 delete(tempstream); 3504 } 3505 3506 if (DoRaster3DOutput) { 3507 string NameofTempFile(filename); 3508 NameofTempFile.append(NumberName); 3509 for(size_t npos = NameofTempFile.find_first_of(' '); npos != string::npos; npos = NameofTempFile.find(' ', npos)) 3510 NameofTempFile.erase(npos, 1); 3511 NameofTempFile.append(Raster3DSuffix); 3512 *out << Verbose(1) << "Writing temporary non convex hull to file " << NameofTempFile << ".\n"; 3513 tempstream = new ofstream(NameofTempFile.c_str(), ios::trunc); 3514 WriteRaster3dFile(out, tempstream, this, cloud); 3515 IncludeSphereinRaster3D(out, tempstream, this, cloud); 3516 tempstream->close(); 3517 tempstream->flush(); 3518 delete(tempstream); 3519 } 3520 } 3521 if (DoTecplotOutput || DoRaster3DOutput) 3522 TriangleFilesWritten++; 3523 }; -
src/tesselation.hpp
r91e7e4a r57066a 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); … … 120 128 class BoundaryPointSet *GetThirdEndpoint(class BoundaryLineSet *line); 121 129 bool IsPresentTupel(class BoundaryPointSet *Points[3]); 122 void GetCenter(Vector *center);130 bool IsPresentTupel(class BoundaryTriangleSet *T); 123 131 124 132 class BoundaryPointSet *endpoints[3]; … … 200 208 void RemoveTesselationPoint(class BoundaryPointSet *point); 201 209 202 bool IsInside(Vector *pointer);203 210 class BoundaryPointSet *GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2); 204 211 205 212 // concave envelope 206 213 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);214 void FindSecondPointForTesselation(class TesselPoint* a, Vector Oben, class TesselPoint*& OptCandidate, double Storage[3], double RADIUS, class LinkedCell *LC); 208 215 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);216 bool FindNextSuitableTriangle(ofstream *out, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, LinkedCell *LC); 210 217 int CheckPresenceOfTriangle(ofstream *out, class TesselPoint *Candidates[3]); 211 218 class BoundaryTriangleSet * GetPresentTriangle(ofstream *out, TesselPoint *Candidates[3]); … … 216 223 bool InsertStraddlingPoints(ofstream *out, PointCloud *cloud, LinkedCell *LC); 217 224 double RemovePointFromTesselatedSurface(ofstream *out, class BoundaryPointSet *point); 218 boolFlipBaseline(ofstream *out, class BoundaryLineSet *Base);219 boolPickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base);225 class BoundaryLineSet * FlipBaseline(ofstream *out, class BoundaryLineSet *Base); 226 double PickFarthestofTwoBaselines(ofstream *out, class BoundaryLineSet *Base); 220 227 class BoundaryPointSet *IsConvexRectangle(ofstream *out, class BoundaryLineSet *Base); 221 map<int, int> FindAllDegeneratedTriangles(); 228 map<int, int> * FindAllDegeneratedTriangles(); 229 map<int, int> * FindAllDegeneratedLines(); 222 230 void RemoveDegeneratedTriangles(); 231 void AddBoundaryPointByDegeneratedTriangle(ofstream *out, class TesselPoint *point, LinkedCell *LC); 223 232 224 233 set<TesselPoint*> * GetAllConnectedPoints(ofstream *out, TesselPoint* Point); … … 239 248 void PrintAllBoundaryTriangles(ofstream *out); 240 249 250 // store envelope in file 251 void Output(ofstream *out, const char *filename, PointCloud *cloud); 241 252 242 253 PointMap PointsOnBoundary; … … 261 272 class BoundaryLineSet *BLS[3]; 262 273 class BoundaryTriangleSet *BTS; 274 class BoundaryTriangleSet *LastTriangle; 275 int TriangleFilesWritten; 263 276 264 277 private: … … 268 281 }; 269 282 270 bool CheckLineCriteriaForDegeneratedTriangle(class BoundaryPointSet *nodes[3]);271 bool SortCandidates(class CandidateForTesselation* candidate1, class CandidateForTesselation* candidate2);272 TesselPoint* FindClosestPoint(const Vector* Point, TesselPoint *&SecondPoint, LinkedCell* LC);273 TesselPoint* FindSecondClosestPoint(const Vector*, LinkedCell*);274 double GetAngle(const Vector &point, const Vector &reference, const Vector OrthogonalVector);275 Vector * GetClosestPointBetweenLine(ofstream *out, class BoundaryLineSet *Base, class BoundaryLineSet *OtherBase);276 283 277 284 #endif /* TESSELATION_HPP_ */ -
src/tesselationhelpers.cpp
r91e7e4a r57066a 388 388 }; 389 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; 415 } 416 390 417 391 418 /** Calculates the volume of a general tetraeder. … … 412 439 }; 413 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(2) << "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 }; -
src/tesselationhelpers.hpp
r91e7e4a r57066a 25 25 26 26 #include "defs.hpp" 27 #include "tesselation.hpp" 27 28 #include "vector.hpp" 28 29 … … 37 38 bool existsIntersection(Vector point1, Vector point2, Vector point3, Vector point4); 38 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); 39 52 40 53
Note:
See TracChangeset
for help on using the changeset viewer.