Changeset e4ea46
- Timestamp:
- Dec 16, 2008, 6:39:28 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:
- 10af0d
- Parents:
- caf5d6
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
configure.ac
rcaf5d6 re4ea46 14 14 AC_PROG_CC 15 15 AM_MISSING_PROG([DOXYGEN], [doxygen]) 16 17 AC_ARG_ENABLE([debug],AS_HELP_STRING([--enable-debug],[debugging level of compiler. Argument is yes or debugging level. (default is no)]),18 [enable_debugging=$enableval], [enable_debugging=no])19 AC_ARG_ENABLE([optimization],AS_HELP_STRING([--enable-optimization],[Optimization level of compiler. Argument is yes or optimization. (default is 2)]),20 [enable_optimization=$enableval], [enable_optimization=2])21 AC_ARG_ENABLE([warnings], AS_HELP_STRING([--enable-warnings],[Output compiler warnings, argument is none, some or full (default is some).]),22 [enable_warnings=$enableval], [enable_warnings=some])23 AC_SET_COMPILER_FLAGS([$enable_optimization], [$enable_debugging], [$enable_warnings])24 16 25 17 # Checks for libraries. -
src/boundary.cpp
rcaf5d6 re4ea46 2 2 #include "boundary.hpp" 3 3 4 5 4 #define DEBUG 0 6 5 7 6 // ======================================== Points on Boundary ================================= … … 11 10 LinesCount = 0; 12 11 Nr = -1; 13 }; 12 } 13 ; 14 14 15 15 BoundaryPointSet::BoundaryPointSet(atom *Walker) … … 18 18 LinesCount = 0; 19 19 Nr = Walker->nr; 20 }; 20 } 21 ; 21 22 22 23 BoundaryPointSet::~BoundaryPointSet() … … 24 25 cout << Verbose(5) << "Erasing point nr. " << Nr << "." << endl; 25 26 node = NULL; 26 }; 27 28 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 29 { 30 cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl; 31 if (line->endpoints[0] == this) { 32 lines.insert ( LinePair( line->endpoints[1]->Nr, line) ); 33 } else { 34 lines.insert ( LinePair( line->endpoints[0]->Nr, line) ); 35 } 27 } 28 ; 29 30 void 31 BoundaryPointSet::AddLine(class BoundaryLineSet *line) 32 { 33 cout << Verbose(6) << "Adding " << *this << " to line " << *line << "." 34 << endl; 35 if (line->endpoints[0] == this) 36 { 37 lines.insert(LinePair(line->endpoints[1]->Nr, line)); 38 } 39 else 40 { 41 lines.insert(LinePair(line->endpoints[0]->Nr, line)); 42 } 36 43 LinesCount++; 37 }; 38 39 ostream & operator << (ostream &ost, BoundaryPointSet &a) 44 } 45 ; 46 47 ostream & 48 operator <<(ostream &ost, BoundaryPointSet &a) 40 49 { 41 50 ost << "[" << a.Nr << "|" << a.node->Name << "]"; 42 51 return ost; 43 }; 52 } 53 ; 44 54 45 55 // ======================================== Lines on Boundary ================================= … … 47 57 BoundaryLineSet::BoundaryLineSet() 48 58 { 49 for (int i =0;i<2;i++)59 for (int i = 0; i < 2; i++) 50 60 endpoints[i] = NULL; 51 61 TrianglesCount = 0; 52 62 Nr = -1; 53 }; 63 } 64 ; 54 65 55 66 BoundaryLineSet::BoundaryLineSet(class BoundaryPointSet *Point[2], int number) … … 60 71 SetEndpointsOrdered(endpoints, Point[0], Point[1]); 61 72 // add this line to the hash maps of both endpoints 62 Point[0]->AddLine(this); 63 Point[1]->AddLine(this); 73 Point[0]->AddLine(this); //Taken out, to check whether we can avoid unwanted double adding. 74 Point[1]->AddLine(this); // 64 75 // clear triangles list 65 76 TrianglesCount = 0; 66 77 cout << Verbose(5) << "New Line with endpoints " << *this << "." << endl; 67 }; 78 } 79 ; 68 80 69 81 BoundaryLineSet::~BoundaryLineSet() 70 82 { 71 for (int i=0;i<2;i++) { 72 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 73 endpoints[i]->lines.erase(Nr); 74 LineMap::iterator tester = endpoints[i]->lines.begin(); 75 tester++; 76 if (tester == endpoints[i]->lines.end()) { 77 cout << Verbose(5) << *endpoints[i] << " has no more lines it's attached to, erasing." << endl; 78 delete(endpoints[i]); 79 } else 80 cout << Verbose(5) << *endpoints[i] << " has still lines it's attached to." << endl; 81 } 82 }; 83 84 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 85 { 86 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl; 87 triangles.insert ( TrianglePair( TrianglesCount, triangle) ); 83 for (int i = 0; i < 2; i++) 84 { 85 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " 86 << *endpoints[i] << "." << endl; 87 endpoints[i]->lines.erase(Nr); 88 LineMap::iterator tester = endpoints[i]->lines.begin(); 89 tester++; 90 if (tester == endpoints[i]->lines.end()) 91 { 92 cout << Verbose(5) << *endpoints[i] 93 << " has no more lines it's attached to, erasing." << endl; 94 //delete(endpoints[i]); 95 } 96 else 97 cout << Verbose(5) << *endpoints[i] 98 << " has still lines it's attached to." << endl; 99 } 100 } 101 ; 102 103 void 104 BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 105 { 106 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." 107 << endl; 108 triangles.insert(TrianglePair(TrianglesCount, triangle)); 88 109 TrianglesCount++; 89 }; 90 91 ostream & operator << (ostream &ost, BoundaryLineSet &a) 92 { 93 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; 110 } 111 ; 112 113 ostream & 114 operator <<(ostream &ost, BoundaryLineSet &a) 115 { 116 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 117 << a.endpoints[1]->node->Name << "]"; 94 118 return ost; 95 }; 119 } 120 ; 96 121 97 122 // ======================================== Triangles on Boundary ================================= … … 100 125 BoundaryTriangleSet::BoundaryTriangleSet() 101 126 { 102 for (int i=0;i<3;i++) { 103 endpoints[i] = NULL; 104 lines[i] = NULL; 105 } 127 for (int i = 0; i < 3; i++) 128 { 129 endpoints[i] = NULL; 130 lines[i] = NULL; 131 } 106 132 Nr = -1; 107 }; 108 109 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], int number) 133 } 134 ; 135 136 BoundaryTriangleSet::BoundaryTriangleSet(class BoundaryLineSet *line[3], 137 int number) 110 138 { 111 139 // set number … … 113 141 // set lines 114 142 cout << Verbose(5) << "New triangle " << Nr << ":" << endl; 115 for (int i=0;i<3;i++) { 116 lines[i] = line[i]; 117 lines[i]->AddTriangle(this); 118 } 143 for (int i = 0; i < 3; i++) 144 { 145 lines[i] = line[i]; 146 lines[i]->AddTriangle(this); 147 } 119 148 // get ascending order of endpoints 120 map <int, class BoundaryPointSet * > OrderMap; 121 for(int i=0;i<3;i++) // for all three lines 122 for (int j=0;j<2;j++) { // for both endpoints 123 OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) ); 124 // and we don't care whether insertion fails 125 } 149 map<int, class BoundaryPointSet *> OrderMap; 150 for (int i = 0; i < 3; i++) 151 // for all three lines 152 for (int j = 0; j < 2; j++) 153 { // for both endpoints 154 OrderMap.insert(pair<int, class BoundaryPointSet *> ( 155 line[i]->endpoints[j]->Nr, line[i]->endpoints[j])); 156 // and we don't care whether insertion fails 157 } 126 158 // set endpoints 127 159 int Counter = 0; 128 160 cout << Verbose(6) << " with end points "; 129 for (map <int, class BoundaryPointSet * >::iterator runner = OrderMap.begin(); runner != OrderMap.end(); runner++) { 130 endpoints[Counter] = runner->second; 131 cout << " " << *endpoints[Counter]; 132 Counter++; 133 } 134 if (Counter < 3) { 135 cerr << "ERROR! We have a triangle with only two distinct endpoints!" << endl; 136 //exit(1); 137 } 161 for (map<int, class BoundaryPointSet *>::iterator runner = OrderMap.begin(); runner 162 != OrderMap.end(); runner++) 163 { 164 endpoints[Counter] = runner->second; 165 cout << " " << *endpoints[Counter]; 166 Counter++; 167 } 168 if (Counter < 3) 169 { 170 cerr << "ERROR! We have a triangle with only two distinct endpoints!" 171 << endl; 172 //exit(1); 173 } 138 174 cout << "." << endl; 139 }; 175 } 176 ; 140 177 141 178 BoundaryTriangleSet::~BoundaryTriangleSet() 142 179 { 143 for (int i=0;i<3;i++) { 144 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 145 lines[i]->triangles.erase(Nr); 146 TriangleMap::iterator tester = lines[i]->triangles.begin(); 147 tester++; 148 if (tester == lines[i]->triangles.end()) { 149 cout << Verbose(5) << *lines[i] << " is no more attached to any triangle, erasing." << endl; 150 delete(lines[i]); 151 } else 152 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." << endl; 153 } 154 }; 155 156 void BoundaryTriangleSet::GetNormalVector(Vector &NormalVector) 180 for (int i = 0; i < 3; i++) 181 { 182 cout << Verbose(5) << "Erasing triangle Nr." << Nr << endl; 183 lines[i]->triangles.erase(Nr); 184 TriangleMap::iterator tester = lines[i]->triangles.begin(); 185 tester++; 186 if (tester == lines[i]->triangles.end()) 187 { 188 cout << Verbose(5) << *lines[i] 189 << " is no more attached to any triangle, erasing." << endl; 190 delete (lines[i]); 191 } 192 else 193 cout << Verbose(5) << *lines[i] << " is still attached to a triangle." 194 << endl; 195 } 196 } 197 ; 198 199 void 200 BoundaryTriangleSet::GetNormalVector(Vector &OtherVector) 157 201 { 158 202 // get normal vector 159 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 203 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, 204 &endpoints[2]->node->x); 160 205 161 206 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 162 if (endpoints[0]->node->x.Projection(& NormalVector) > 0)207 if (endpoints[0]->node->x.Projection(&OtherVector) > 0) 163 208 NormalVector.Scale(-1.); 164 }; 165 166 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 167 { 168 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 209 } 210 ; 211 212 ostream & 213 operator <<(ostream &ost, BoundaryTriangleSet &a) 214 { 215 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," 216 << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; 169 217 return ost; 170 }; 218 } 219 ; 171 220 172 221 // ========================================== F U N C T I O N S ================================= … … 177 226 * \return point which is shared or NULL if none 178 227 */ 179 class BoundaryPointSet * GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 180 { 181 class BoundaryLineSet * lines[2] = {line1, line2}; 228 class BoundaryPointSet * 229 GetCommonEndpoint(class BoundaryLineSet * line1, class BoundaryLineSet * line2) 230 { 231 class BoundaryLineSet * lines[2] = 232 { line1, line2 }; 182 233 class BoundaryPointSet *node = NULL; 183 map <int, class BoundaryPointSet * > OrderMap; 184 pair < map <int, class BoundaryPointSet * >::iterator, bool > OrderTest; 185 for(int i=0;i<2;i++) // for both lines 186 for (int j=0;j<2;j++) { // for both endpoints 187 OrderTest = OrderMap.insert ( pair <int, class BoundaryPointSet * >( lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j]) ); 188 if (!OrderTest.second) { // if insertion fails, we have common endpoint 189 node = OrderTest.first->second; 190 cout << Verbose(5) << "Common endpoint of lines " << *line1 << " and " << *line2 << " is: " << *node << "." << endl; 191 j=2; 192 i=2; 193 break; 234 map<int, class BoundaryPointSet *> OrderMap; 235 pair<map<int, class BoundaryPointSet *>::iterator, bool> OrderTest; 236 for (int i = 0; i < 2; i++) 237 // for both lines 238 for (int j = 0; j < 2; j++) 239 { // for both endpoints 240 OrderTest = OrderMap.insert(pair<int, class BoundaryPointSet *> ( 241 lines[i]->endpoints[j]->Nr, lines[i]->endpoints[j])); 242 if (!OrderTest.second) 243 { // if insertion fails, we have common endpoint 244 node = OrderTest.first->second; 245 cout << Verbose(5) << "Common endpoint of lines " << *line1 246 << " and " << *line2 << " is: " << *node << "." << endl; 247 j = 2; 248 i = 2; 249 break; 250 } 194 251 } 195 }196 252 return node; 197 }; 253 } 254 ; 198 255 199 256 /** Determines the boundary points of a cluster. … … 204 261 * \param *mol molecule structure representing the cluster 205 262 */ 206 Boundaries * GetBoundaryPoints(ofstream *out, molecule *mol) 263 Boundaries * 264 GetBoundaryPoints(ofstream *out, molecule *mol) 207 265 { 208 266 atom *Walker = NULL; … … 212 270 213 271 *out << Verbose(1) << "Finding all boundary points." << endl; 214 Boundaries *BoundaryPoints = new Boundaries [NDIM];// first is alpha, second is (r, nr)272 Boundaries *BoundaryPoints = new Boundaries[NDIM]; // first is alpha, second is (r, nr) 215 273 BoundariesTestPair BoundaryTestPair; 216 274 Vector AxisVector, AngleReferenceVector, AngleReferenceNormalVector; 217 275 double radius, angle; 218 276 // 3a. Go through every axis 219 for (int axis=0; axis<NDIM; axis++) { 220 AxisVector.Zero(); 221 AngleReferenceVector.Zero(); 222 AngleReferenceNormalVector.Zero(); 223 AxisVector.x[axis] = 1.; 224 AngleReferenceVector.x[(axis+1)%NDIM] = 1.; 225 AngleReferenceNormalVector.x[(axis+2)%NDIM] = 1.; 226 // *out << Verbose(1) << "Axisvector is "; 227 // AxisVector.Output(out); 228 // *out << " and AngleReferenceVector is "; 229 // AngleReferenceVector.Output(out); 230 // *out << "." << endl; 231 // *out << " and AngleReferenceNormalVector is "; 232 // AngleReferenceNormalVector.Output(out); 233 // *out << "." << endl; 234 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 235 Walker = mol->start; 236 while (Walker->next != mol->end) { 237 Walker = Walker->next; 238 Vector ProjectedVector; 239 ProjectedVector.CopyVector(&Walker->x); 240 ProjectedVector.ProjectOntoPlane(&AxisVector); 241 // correct for negative side 242 //if (Projection(y) < 0) 243 //angle = 2.*M_PI - angle; 244 radius = ProjectedVector.Norm(); 245 if (fabs(radius) > MYEPSILON) 246 angle = ProjectedVector.Angle(&AngleReferenceVector); 247 else 248 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 249 250 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 251 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { 252 angle = 2.*M_PI - angle; 253 } 254 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 255 //ProjectedVector.Output(out); 256 //*out << endl; 257 BoundaryTestPair = BoundaryPoints[axis].insert( BoundariesPair (angle, DistancePair (radius, Walker) ) ); 258 if (BoundaryTestPair.second) { // successfully inserted 259 } else { // same point exists, check first r, then distance of original vectors to center of gravity 260 *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl; 261 *out << Verbose(2) << "Present vector: "; 262 BoundaryTestPair.first->second.second->x.Output(out); 263 *out << endl; 264 *out << Verbose(2) << "New vector: "; 265 Walker->x.Output(out); 266 *out << endl; 267 double tmp = ProjectedVector.Norm(); 268 if (tmp > BoundaryTestPair.first->second.first) { 269 BoundaryTestPair.first->second.first = tmp; 270 BoundaryTestPair.first->second.second = Walker; 271 *out << Verbose(2) << "Keeping new vector." << endl; 272 } else if (tmp == BoundaryTestPair.first->second.first) { 273 if (BoundaryTestPair.first->second.second->x.ScalarProduct(&BoundaryTestPair.first->second.second->x) < Walker->x.ScalarProduct(&Walker->x)) { // Norm() does a sqrt, which makes it a lot slower 274 BoundaryTestPair.first->second.second = Walker; 275 *out << Verbose(2) << "Keeping new vector." << endl; 276 } else { 277 *out << Verbose(2) << "Keeping present vector." << endl; 278 } 279 } else { 280 *out << Verbose(2) << "Keeping present vector." << endl; 281 } 282 } 283 } 284 // printing all inserted for debugging 285 // { 286 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 287 // int i=0; 288 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 289 // if (runner != BoundaryPoints[axis].begin()) 290 // *out << ", " << i << ": " << *runner->second.second; 291 // else 292 // *out << i << ": " << *runner->second.second; 293 // i++; 294 // } 295 // *out << endl; 296 // } 297 // 3c. throw out points whose distance is less than the mean of left and right neighbours 298 bool flag = false; 299 do { // do as long as we still throw one out per round 300 *out << Verbose(1) << "Looking for candidates to kick out by convex condition ... " << endl; 301 flag = false; 302 Boundaries::iterator left = BoundaryPoints[axis].end(); 303 Boundaries::iterator right = BoundaryPoints[axis].end(); 304 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 305 // set neighbours correctly 306 if (runner == BoundaryPoints[axis].begin()) { 307 left = BoundaryPoints[axis].end(); 308 } else { 309 left = runner; 310 } 311 left--; 312 right = runner; 313 right++; 314 if (right == BoundaryPoints[axis].end()) { 315 right = BoundaryPoints[axis].begin(); 316 } 317 // check distance 318 319 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 320 { 321 Vector SideA, SideB, SideC, SideH; 322 SideA.CopyVector(&left->second.second->x); 323 SideA.ProjectOntoPlane(&AxisVector); 324 // *out << "SideA: "; 325 // SideA.Output(out); 326 // *out << endl; 327 328 SideB.CopyVector(&right->second.second->x); 329 SideB.ProjectOntoPlane(&AxisVector); 330 // *out << "SideB: "; 331 // SideB.Output(out); 332 // *out << endl; 333 334 SideC.CopyVector(&left->second.second->x); 335 SideC.SubtractVector(&right->second.second->x); 336 SideC.ProjectOntoPlane(&AxisVector); 337 // *out << "SideC: "; 338 // SideC.Output(out); 339 // *out << endl; 340 341 SideH.CopyVector(&runner->second.second->x); 342 SideH.ProjectOntoPlane(&AxisVector); 343 // *out << "SideH: "; 344 // SideH.Output(out); 345 // *out << endl; 346 347 // calculate each length 348 double a = SideA.Norm(); 349 //double b = SideB.Norm(); 350 //double c = SideC.Norm(); 351 double h = SideH.Norm(); 352 // calculate the angles 353 double alpha = SideA.Angle(&SideH); 354 double beta = SideA.Angle(&SideC); 355 double gamma = SideB.Angle(&SideH); 356 double delta = SideC.Angle(&SideH); 357 double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.); 358 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 359 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 360 if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h < MinDistance)) { 361 // throw out point 362 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 363 BoundaryPoints[axis].erase(runner); 364 flag = true; 365 } 366 } 367 } 368 } while (flag); 369 } 277 for (int axis = 0; axis < NDIM; axis++) 278 { 279 AxisVector.Zero(); 280 AngleReferenceVector.Zero(); 281 AngleReferenceNormalVector.Zero(); 282 AxisVector.x[axis] = 1.; 283 AngleReferenceVector.x[(axis + 1) % NDIM] = 1.; 284 AngleReferenceNormalVector.x[(axis + 2) % NDIM] = 1.; 285 // *out << Verbose(1) << "Axisvector is "; 286 // AxisVector.Output(out); 287 // *out << " and AngleReferenceVector is "; 288 // AngleReferenceVector.Output(out); 289 // *out << "." << endl; 290 // *out << " and AngleReferenceNormalVector is "; 291 // AngleReferenceNormalVector.Output(out); 292 // *out << "." << endl; 293 // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours 294 Walker = mol->start; 295 while (Walker->next != mol->end) 296 { 297 Walker = Walker->next; 298 Vector ProjectedVector; 299 ProjectedVector.CopyVector(&Walker->x); 300 ProjectedVector.ProjectOntoPlane(&AxisVector); 301 // correct for negative side 302 //if (Projection(y) < 0) 303 //angle = 2.*M_PI - angle; 304 radius = ProjectedVector.Norm(); 305 if (fabs(radius) > MYEPSILON) 306 angle = ProjectedVector.Angle(&AngleReferenceVector); 307 else 308 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 309 310 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 311 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) 312 { 313 angle = 2. * M_PI - angle; 314 } 315 //*out << Verbose(2) << "Inserting " << *Walker << ": (r, alpha) = (" << radius << "," << angle << "): "; 316 //ProjectedVector.Output(out); 317 //*out << endl; 318 BoundaryTestPair = BoundaryPoints[axis].insert(BoundariesPair(angle, 319 DistancePair (radius, Walker))); 320 if (BoundaryTestPair.second) 321 { // successfully inserted 322 } 323 else 324 { // same point exists, check first r, then distance of original vectors to center of gravity 325 *out << Verbose(2) 326 << "Encountered two vectors whose projection onto axis " 327 << axis << " is equal: " << endl; 328 *out << Verbose(2) << "Present vector: "; 329 BoundaryTestPair.first->second.second->x.Output(out); 330 *out << endl; 331 *out << Verbose(2) << "New vector: "; 332 Walker->x.Output(out); 333 *out << endl; 334 double tmp = ProjectedVector.Norm(); 335 if (tmp > BoundaryTestPair.first->second.first) 336 { 337 BoundaryTestPair.first->second.first = tmp; 338 BoundaryTestPair.first->second.second = Walker; 339 *out << Verbose(2) << "Keeping new vector." << endl; 340 } 341 else if (tmp == BoundaryTestPair.first->second.first) 342 { 343 if (BoundaryTestPair.first->second.second->x.ScalarProduct( 344 &BoundaryTestPair.first->second.second->x) 345 < Walker->x.ScalarProduct(&Walker->x)) 346 { // Norm() does a sqrt, which makes it a lot slower 347 BoundaryTestPair.first->second.second = Walker; 348 *out << Verbose(2) << "Keeping new vector." << endl; 349 } 350 else 351 { 352 *out << Verbose(2) << "Keeping present vector." << endl; 353 } 354 } 355 else 356 { 357 *out << Verbose(2) << "Keeping present vector." << endl; 358 } 359 } 360 } 361 // printing all inserted for debugging 362 // { 363 // *out << Verbose(2) << "Printing list of candidates for axis " << axis << " which we have inserted so far." << endl; 364 // int i=0; 365 // for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 366 // if (runner != BoundaryPoints[axis].begin()) 367 // *out << ", " << i << ": " << *runner->second.second; 368 // else 369 // *out << i << ": " << *runner->second.second; 370 // i++; 371 // } 372 // *out << endl; 373 // } 374 // 3c. throw out points whose distance is less than the mean of left and right neighbours 375 bool flag = false; 376 do 377 { // do as long as we still throw one out per round 378 *out << Verbose(1) 379 << "Looking for candidates to kick out by convex condition ... " 380 << endl; 381 flag = false; 382 Boundaries::iterator left = BoundaryPoints[axis].end(); 383 Boundaries::iterator right = BoundaryPoints[axis].end(); 384 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 385 != BoundaryPoints[axis].end(); runner++) 386 { 387 // set neighbours correctly 388 if (runner == BoundaryPoints[axis].begin()) 389 { 390 left = BoundaryPoints[axis].end(); 391 } 392 else 393 { 394 left = runner; 395 } 396 left--; 397 right = runner; 398 right++; 399 if (right == BoundaryPoints[axis].end()) 400 { 401 right = BoundaryPoints[axis].begin(); 402 } 403 // check distance 404 405 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 406 { 407 Vector SideA, SideB, SideC, SideH; 408 SideA.CopyVector(&left->second.second->x); 409 SideA.ProjectOntoPlane(&AxisVector); 410 // *out << "SideA: "; 411 // SideA.Output(out); 412 // *out << endl; 413 414 SideB.CopyVector(&right->second.second->x); 415 SideB.ProjectOntoPlane(&AxisVector); 416 // *out << "SideB: "; 417 // SideB.Output(out); 418 // *out << endl; 419 420 SideC.CopyVector(&left->second.second->x); 421 SideC.SubtractVector(&right->second.second->x); 422 SideC.ProjectOntoPlane(&AxisVector); 423 // *out << "SideC: "; 424 // SideC.Output(out); 425 // *out << endl; 426 427 SideH.CopyVector(&runner->second.second->x); 428 SideH.ProjectOntoPlane(&AxisVector); 429 // *out << "SideH: "; 430 // SideH.Output(out); 431 // *out << endl; 432 433 // calculate each length 434 double a = SideA.Norm(); 435 //double b = SideB.Norm(); 436 //double c = SideC.Norm(); 437 double h = SideH.Norm(); 438 // calculate the angles 439 double alpha = SideA.Angle(&SideH); 440 double beta = SideA.Angle(&SideC); 441 double gamma = SideB.Angle(&SideH); 442 double delta = SideC.Angle(&SideH); 443 double MinDistance = a * sin(beta) / (sin(delta)) * (((alpha 444 < M_PI / 2.) || (gamma < M_PI / 2.)) ? 1. : -1.); 445 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 446 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 447 if ((fabs(h / fabs(h) - MinDistance / fabs(MinDistance)) 448 < MYEPSILON) && (h < MinDistance)) 449 { 450 // throw out point 451 //*out << Verbose(1) << "Throwing out " << *runner->second.second << "." << endl; 452 BoundaryPoints[axis].erase(runner); 453 flag = true; 454 } 455 } 456 } 457 } 458 while (flag); 459 } 370 460 return BoundaryPoints; 371 }; 461 } 462 ; 372 463 373 464 /** Determines greatest diameters of a cluster defined by its convex envelope. … … 379 470 * \return NDIM array of the diameters 380 471 */ 381 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 472 double * 473 GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, 474 bool IsAngstroem) 382 475 { 383 476 // get points on boundary of NULL was given as parameter 384 477 bool BoundaryFreeFlag = false; 385 478 Boundaries *BoundaryPoints = BoundaryPtr; 386 if (BoundaryPoints == NULL) { 387 BoundaryFreeFlag = true; 388 BoundaryPoints = GetBoundaryPoints(out, mol); 389 } else { 390 *out << Verbose(1) << "Using given boundary points set." << endl; 391 } 392 479 if (BoundaryPoints == NULL) 480 { 481 BoundaryFreeFlag = true; 482 BoundaryPoints = GetBoundaryPoints(out, mol); 483 } 484 else 485 { 486 *out << Verbose(1) << "Using given boundary points set." << endl; 487 } 393 488 // determine biggest "diameter" of cluster for each axis 394 489 Boundaries::iterator Neighbour, OtherNeighbour; 395 490 double *GreatestDiameter = new double[NDIM]; 396 for (int i=0;i<NDIM;i++)491 for (int i = 0; i < NDIM; i++) 397 492 GreatestDiameter[i] = 0.; 398 493 double OldComponent, tmp, w1, w2; 399 494 Vector DistanceVector, OtherVector; 400 495 int component, Othercomponent; 401 for(int axis=0;axis<NDIM;axis++) { // regard each projected plane 402 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 403 for (int j=0;j<2;j++) { // and for both axis on the current plane 404 component = (axis+j+1)%NDIM; 405 Othercomponent = (axis+1+((j+1) & 1))%NDIM; 406 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 407 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 408 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 409 // seek for the neighbours pair where the Othercomponent sign flips 410 Neighbour = runner; 411 Neighbour++; 412 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 413 Neighbour = BoundaryPoints[axis].begin(); 414 DistanceVector.CopyVector(&runner->second.second->x); 415 DistanceVector.SubtractVector(&Neighbour->second.second->x); 416 do { // seek for neighbour pair where it flips 417 OldComponent = DistanceVector.x[Othercomponent]; 418 Neighbour++; 419 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 420 Neighbour = BoundaryPoints[axis].begin(); 421 DistanceVector.CopyVector(&runner->second.second->x); 422 DistanceVector.SubtractVector(&Neighbour->second.second->x); 423 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 424 } while ((runner != Neighbour) && ( fabs( OldComponent/fabs(OldComponent) - DistanceVector.x[Othercomponent]/fabs(DistanceVector.x[Othercomponent]) ) < MYEPSILON)); // as long as sign does not flip 425 if (runner != Neighbour) { 426 OtherNeighbour = Neighbour; 427 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 428 OtherNeighbour = BoundaryPoints[axis].end(); 429 OtherNeighbour--; 430 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 431 // now we have found the pair: Neighbour and OtherNeighbour 432 OtherVector.CopyVector(&runner->second.second->x); 433 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 434 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 435 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 436 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 437 w1 = fabs(OtherVector.x[Othercomponent]); 438 w2 = fabs(DistanceVector.x[Othercomponent]); 439 tmp = fabs((w1*DistanceVector.x[component] + w2*OtherVector.x[component])/(w1+w2)); 440 // mark if it has greater diameter 441 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 442 GreatestDiameter[component] = (GreatestDiameter[component] > tmp) ? GreatestDiameter[component] : tmp; 443 } //else 444 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 445 } 446 } 447 } 448 *out << Verbose(0) << "RESULT: The biggest diameters are " << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "." << endl; 496 for (int axis = 0; axis < NDIM; axis++) 497 { // regard each projected plane 498 //*out << Verbose(1) << "Current axis is " << axis << "." << endl; 499 for (int j = 0; j < 2; j++) 500 { // and for both axis on the current plane 501 component = (axis + j + 1) % NDIM; 502 Othercomponent = (axis + 1 + ((j + 1) & 1)) % NDIM; 503 //*out << Verbose(1) << "Current component is " << component << ", Othercomponent is " << Othercomponent << "." << endl; 504 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 505 != BoundaryPoints[axis].end(); runner++) 506 { 507 //*out << Verbose(2) << "Current runner is " << *(runner->second.second) << "." << endl; 508 // seek for the neighbours pair where the Othercomponent sign flips 509 Neighbour = runner; 510 Neighbour++; 511 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 512 Neighbour = BoundaryPoints[axis].begin(); 513 DistanceVector.CopyVector(&runner->second.second->x); 514 DistanceVector.SubtractVector(&Neighbour->second.second->x); 515 do 516 { // seek for neighbour pair where it flips 517 OldComponent = DistanceVector.x[Othercomponent]; 518 Neighbour++; 519 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around 520 Neighbour = BoundaryPoints[axis].begin(); 521 DistanceVector.CopyVector(&runner->second.second->x); 522 DistanceVector.SubtractVector(&Neighbour->second.second->x); 523 //*out << Verbose(3) << "OldComponent is " << OldComponent << ", new one is " << DistanceVector.x[Othercomponent] << "." << endl; 524 } 525 while ((runner != Neighbour) && (fabs(OldComponent / fabs( 526 OldComponent) - DistanceVector.x[Othercomponent] / fabs( 527 DistanceVector.x[Othercomponent])) < MYEPSILON)); // as long as sign does not flip 528 if (runner != Neighbour) 529 { 530 OtherNeighbour = Neighbour; 531 if (OtherNeighbour == BoundaryPoints[axis].begin()) // make it wrap around 532 OtherNeighbour = BoundaryPoints[axis].end(); 533 OtherNeighbour--; 534 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 535 // now we have found the pair: Neighbour and OtherNeighbour 536 OtherVector.CopyVector(&runner->second.second->x); 537 OtherVector.SubtractVector(&OtherNeighbour->second.second->x); 538 //*out << Verbose(2) << "Distances to Neighbour and OtherNeighbour are " << DistanceVector.x[component] << " and " << OtherVector.x[component] << "." << endl; 539 //*out << Verbose(2) << "OtherComponents to Neighbour and OtherNeighbour are " << DistanceVector.x[Othercomponent] << " and " << OtherVector.x[Othercomponent] << "." << endl; 540 // do linear interpolation between points (is exact) to extract exact intersection between Neighbour and OtherNeighbour 541 w1 = fabs(OtherVector.x[Othercomponent]); 542 w2 = fabs(DistanceVector.x[Othercomponent]); 543 tmp = fabs((w1 * DistanceVector.x[component] + w2 544 * OtherVector.x[component]) / (w1 + w2)); 545 // mark if it has greater diameter 546 //*out << Verbose(2) << "Comparing current greatest " << GreatestDiameter[component] << " to new " << tmp << "." << endl; 547 GreatestDiameter[component] = (GreatestDiameter[component] 548 > tmp) ? GreatestDiameter[component] : tmp; 549 } //else 550 //*out << Verbose(2) << "Saw no sign flip, probably top or bottom node." << endl; 551 } 552 } 553 } 554 *out << Verbose(0) << "RESULT: The biggest diameters are " 555 << GreatestDiameter[0] << " and " << GreatestDiameter[1] << " and " 556 << GreatestDiameter[2] << " " << (IsAngstroem ? "angstrom" 557 : "atomiclength") << "." << endl; 449 558 450 559 // free reference lists 451 560 if (BoundaryFreeFlag) 452 delete[] (BoundaryPoints);561 delete[] (BoundaryPoints); 453 562 454 563 return GreatestDiameter; 455 } ;456 564 } 565 ; 457 566 458 567 /* … … 460 569 * \param *out output stream for debugging 461 570 * \param *tecplot output stream for tecplot data 571 * \param N arbitrary number to differentiate various zones in the tecplot format 462 572 */ 463 void write_tecplot_file(ofstream *out, ofstream *tecplot, class Tesselation *TesselStruct, class molecule *mol) 464 { 465 // 8. Store triangles in tecplot file 466 if (tecplot != NULL) { 467 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 468 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 469 *tecplot << "ZONE T=\"TRIANGLES\", N=" << TesselStruct->PointsOnBoundaryCount << ", E=" << TesselStruct->TrianglesOnBoundaryCount << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 470 int *LookupList = new int[mol->AtomCount]; 471 for (int i=0;i<mol->AtomCount;i++) 472 LookupList[i] = -1; 473 474 // print atom coordinates 475 *out << Verbose(2) << "The following triangles were created:"; 476 int Counter = 1; 477 atom *Walker = NULL; 478 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target != TesselStruct->PointsOnBoundary.end(); target++) { 479 Walker = target->second->node; 480 LookupList[Walker->nr] = Counter++; 481 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " << Walker->x.x[2] << " " << endl; 482 } 483 *tecplot << endl; 573 void 574 write_tecplot_file(ofstream *out, ofstream *tecplot, 575 class Tesselation *TesselStruct, class molecule *mol, int N) 576 { 577 if (tecplot != NULL) 578 { 579 *tecplot << "TITLE = \"3D CONVEX SHELL\"" << endl; 580 *tecplot << "VARIABLES = \"X\" \"Y\" \"Z\"" << endl; 581 *tecplot << "ZONE T=\"TRIANGLES" << N << "\", N=" 582 << TesselStruct->PointsOnBoundaryCount << ", E=" 583 << TesselStruct->TrianglesOnBoundaryCount 584 << ", DATAPACKING=POINT, ZONETYPE=FETRIANGLE" << endl; 585 int *LookupList = new int[mol->AtomCount]; 586 for (int i = 0; i < mol->AtomCount; i++) 587 LookupList[i] = -1; 588 589 // print atom coordinates 590 *out << Verbose(2) << "The following triangles were created:"; 591 int Counter = 1; 592 atom *Walker = NULL; 593 for (PointMap::iterator target = TesselStruct->PointsOnBoundary.begin(); target 594 != TesselStruct->PointsOnBoundary.end(); target++) 595 { 596 Walker = target->second->node; 597 LookupList[Walker->nr] = Counter++; 598 *tecplot << Walker->x.x[0] << " " << Walker->x.x[1] << " " 599 << Walker->x.x[2] << " " << endl; 600 } 601 *tecplot << endl; 484 602 // print connectivity 485 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { 486 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name; 487 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 488 } 489 delete[](LookupList); 490 *out << endl; 491 } 603 for (TriangleMap::iterator runner = 604 TesselStruct->TrianglesOnBoundary.begin(); runner 605 != TesselStruct->TrianglesOnBoundary.end(); runner++) 606 { 607 *out << " " << runner->second->endpoints[0]->node->Name << "<->" 608 << runner->second->endpoints[1]->node->Name << "<->" 609 << runner->second->endpoints[2]->node->Name; 610 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " 611 << LookupList[runner->second->endpoints[1]->node->nr] << " " 612 << LookupList[runner->second->endpoints[2]->node->nr] << endl; 613 } 614 delete[] (LookupList); 615 *out << endl; 616 } 492 617 } 493 618 … … 501 626 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 502 627 */ 503 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 628 double 629 VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, 630 Boundaries *BoundaryPtr, molecule *mol) 504 631 { 505 632 bool IsAngstroem = configuration->GetIsAngstroem(); … … 510 637 double volume = 0.; 511 638 double PyramidVolume = 0.; 512 double G, h;513 Vector x, y;514 double a, b,c;639 double G, h; 640 Vector x, y; 641 double a, b, c; 515 642 516 643 //Find_non_convex_border(out, tecplot, *TesselStruct, mol); // Is now called from command line. … … 523 650 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; 524 651 Walker = mol->start; 525 while (Walker->next != mol->end) { 526 Walker = Walker->next; 527 Walker->x.Translate(CenterOfGravity); 528 } 652 while (Walker->next != mol->end) 653 { 654 Walker = Walker->next; 655 Walker->x.Translate(CenterOfGravity); 656 } 529 657 530 658 // 3. Find all points on the boundary 531 if (BoundaryPoints == NULL) { 532 BoundaryFreeFlag = true; 533 BoundaryPoints = GetBoundaryPoints(out, mol); 534 } else { 535 *out << Verbose(1) << "Using given boundary points set." << endl; 536 } 659 if (BoundaryPoints == NULL) 660 { 661 BoundaryFreeFlag = true; 662 BoundaryPoints = GetBoundaryPoints(out, mol); 663 } 664 else 665 { 666 *out << Verbose(1) << "Using given boundary points set." << endl; 667 } 537 668 538 669 // 4. fill the boundary point list 539 for (int axis=0;axis<NDIM;axis++) 540 for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) { 541 TesselStruct->AddPoint(runner->second.second); 542 } 543 544 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl; 670 for (int axis = 0; axis < NDIM; axis++) 671 for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner 672 != BoundaryPoints[axis].end(); runner++) 673 { 674 TesselStruct->AddPoint(runner->second.second); 675 } 676 677 *out << Verbose(2) << "I found " << TesselStruct->PointsOnBoundaryCount 678 << " points on the convex boundary." << endl; 545 679 // now we have the whole set of edge points in the BoundaryList 546 680 547 681 // listing for debugging 548 // *out << Verbose(1) << "Listing PointsOnBoundary:";549 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) {550 // *out << " " << *runner->second;551 // }552 // *out << endl;682 // *out << Verbose(1) << "Listing PointsOnBoundary:"; 683 // for(PointMap::iterator runner = PointsOnBoundary.begin(); runner != PointsOnBoundary.end(); runner++) { 684 // *out << " " << *runner->second; 685 // } 686 // *out << endl; 553 687 554 688 // 5a. guess starting triangle … … 558 692 TesselStruct->TesselateOnBoundary(out, configuration, mol); 559 693 560 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount << " triangles with " << TesselStruct->LinesOnBoundaryCount << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." << endl; 561 562 694 *out << Verbose(2) << "I created " << TesselStruct->TrianglesOnBoundaryCount 695 << " triangles with " << TesselStruct->LinesOnBoundaryCount 696 << " lines and " << TesselStruct->PointsOnBoundaryCount << " points." 697 << endl; 563 698 564 699 // 6a. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes 565 *out << Verbose(1) << "Calculating the volume of the pyramids formed out of triangles and center of gravity." << endl; 566 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { // go through every triangle, calculate volume of its pyramid with CoG as peak 567 x.CopyVector(&runner->second->endpoints[0]->node->x); 568 x.SubtractVector(&runner->second->endpoints[1]->node->x); 569 y.CopyVector(&runner->second->endpoints[0]->node->x); 570 y.SubtractVector(&runner->second->endpoints[2]->node->x); 571 a = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 572 b = sqrt(runner->second->endpoints[0]->node->x.Distance(&runner->second->endpoints[2]->node->x)); 573 c = sqrt(runner->second->endpoints[2]->node->x.Distance(&runner->second->endpoints[1]->node->x)); 574 G = sqrt( ( (a*a+b*b+c*c)*(a*a+b*b+c*c) - 2*(a*a*a*a + b*b*b*b + c*c*c*c) )/16.); // area of tesselated triangle 575 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, &runner->second->endpoints[1]->node->x, &runner->second->endpoints[2]->node->x); 576 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 577 h = x.Norm(); // distance of CoG to triangle 578 PyramidVolume = (1./3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 579 *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 580 volume += PyramidVolume; 581 } 582 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 583 700 *out << Verbose(1) 701 << "Calculating the volume of the pyramids formed out of triangles and center of gravity." 702 << endl; 703 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner 704 != TesselStruct->TrianglesOnBoundary.end(); runner++) 705 { // go through every triangle, calculate volume of its pyramid with CoG as peak 706 x.CopyVector(&runner->second->endpoints[0]->node->x); 707 x.SubtractVector(&runner->second->endpoints[1]->node->x); 708 y.CopyVector(&runner->second->endpoints[0]->node->x); 709 y.SubtractVector(&runner->second->endpoints[2]->node->x); 710 a = sqrt(runner->second->endpoints[0]->node->x.Distance( 711 &runner->second->endpoints[1]->node->x)); 712 b = sqrt(runner->second->endpoints[0]->node->x.Distance( 713 &runner->second->endpoints[2]->node->x)); 714 c = sqrt(runner->second->endpoints[2]->node->x.Distance( 715 &runner->second->endpoints[1]->node->x)); 716 G = sqrt(((a * a + b * b + c * c) * (a * a + b * b + c * c) - 2 * (a * a 717 * a * a + b * b * b * b + c * c * c * c)) / 16.); // area of tesselated triangle 718 x.MakeNormalVector(&runner->second->endpoints[0]->node->x, 719 &runner->second->endpoints[1]->node->x, 720 &runner->second->endpoints[2]->node->x); 721 x.Scale(runner->second->endpoints[1]->node->x.Projection(&x)); 722 h = x.Norm(); // distance of CoG to triangle 723 PyramidVolume = (1. / 3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 724 *out << Verbose(2) << "Area of triangle is " << G << " " 725 << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " 726 << h << " and the volume is " << PyramidVolume << " " 727 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 728 volume += PyramidVolume; 729 } 730 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) 731 << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." 732 << endl; 584 733 585 734 // 7. translate all points back from CoG 586 *out << Verbose(1) << "Translating system back from Center of Gravity." << endl; 735 *out << Verbose(1) << "Translating system back from Center of Gravity." 736 << endl; 587 737 CenterOfGravity->Scale(-1); 588 738 Walker = mol->start; 589 while (Walker->next != mol->end) { 590 Walker = Walker->next; 591 Walker->x.Translate(CenterOfGravity); 592 } 593 594 595 596 597 598 write_tecplot_file(out, tecplot, TesselStruct, mol); 599 739 while (Walker->next != mol->end) 740 { 741 Walker = Walker->next; 742 Walker->x.Translate(CenterOfGravity); 743 } 744 745 // 8. Store triangles in tecplot file 746 write_tecplot_file(out, tecplot, TesselStruct, mol, 0); 600 747 601 748 // free reference lists 602 749 if (BoundaryFreeFlag) 603 delete[] (BoundaryPoints);750 delete[] (BoundaryPoints); 604 751 605 752 return volume; 606 } ;607 753 } 754 ; 608 755 609 756 /** Creates multiples of the by \a *mol given cluster and suspends them in water with a given final density. … … 615 762 * \param celldensity desired average density in final cell 616 763 */ 617 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity) 764 void 765 PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, 766 double ClusterVolume, double celldensity) 618 767 { 619 768 // transform to PAS … … 625 774 double clustervolume; 626 775 if (ClusterVolume == 0) 627 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, BoundaryPoints, mol); 776 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, 777 BoundaryPoints, mol); 628 778 else 629 779 clustervolume = ClusterVolume; 630 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); 780 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, 781 IsAngstroem); 631 782 Vector BoxLengths; 632 int repetition[NDIM] = {1, 1, 1}; 783 int repetition[NDIM] = 784 { 1, 1, 1 }; 633 785 int TotalNoClusters = 1; 634 for (int i =0;i<NDIM;i++)786 for (int i = 0; i < NDIM; i++) 635 787 TotalNoClusters *= repetition[i]; 636 788 … … 638 790 double totalmass = 0.; 639 791 atom *Walker = mol->start; 640 while (Walker->next != mol->end) { 641 Walker = Walker->next; 642 totalmass += Walker->type->mass; 643 } 644 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl; 645 646 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 792 while (Walker->next != mol->end) 793 { 794 Walker = Walker->next; 795 totalmass += Walker->type->mass; 796 } 797 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) 798 << totalmass << " atomicmassunit." << endl; 799 800 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) 801 << totalmass / clustervolume << " atomicmassunit/" 802 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 647 803 648 804 // solve cubic polynomial 649 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; 805 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." 806 << endl; 650 807 double cellvolume; 651 808 if (IsAngstroem) 652 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_A - (totalmass/clustervolume))/(celldensity-1); 809 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_A - (totalmass 810 / clustervolume)) / (celldensity - 1); 653 811 else 654 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1); 655 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 656 657 double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]); 658 *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 659 if (minimumvolume > cellvolume) { 660 cerr << Verbose(0) << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" << endl; 661 cout << Verbose(0) << "Setting Box dimensions to minimum possible, the greatest diameters." << endl; 662 for(int i=0;i<NDIM;i++) 663 BoxLengths.x[i] = GreatestDiameter[i]; 664 mol->CenterEdge(out, &BoxLengths); 665 } else { 666 BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]); 667 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 668 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 669 + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]); 670 BoxLengths.x[2] = minimumvolume - cellvolume; 671 double x0 = 0.,x1 = 0.,x2 = 0.; 672 if (gsl_poly_solve_cubic(BoxLengths.x[0],BoxLengths.x[1],BoxLengths.x[2],&x0,&x1,&x2) == 1) // either 1 or 3 on return 673 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 << " ." << endl; 674 else { 675 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 << " and " << x1 << " and " << x2 << " ." << endl; 676 x0 = x2; // sorted in ascending order 677 } 678 679 cellvolume = 1; 680 for(int i=0;i<NDIM;i++) { 681 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 682 cellvolume *= BoxLengths.x[i]; 683 } 684 685 // set new box dimensions 686 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 687 mol->CenterInBox((ofstream *)&cout, &BoxLengths); 688 } 812 cellvolume = (TotalNoClusters * totalmass / SOLVENTDENSITY_a0 - (totalmass 813 / clustervolume)) / (celldensity - 1); 814 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity 815 << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" 816 : "atomiclength") << "^3." << endl; 817 818 double minimumvolume = TotalNoClusters * (GreatestDiameter[0] 819 * GreatestDiameter[1] * GreatestDiameter[2]); 820 *out << Verbose(1) 821 << "Minimum volume of the convex envelope contained in a rectangular box is " 822 << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" 823 : "atomiclength") << "^3." << endl; 824 if (minimumvolume > cellvolume) 825 { 826 cerr << Verbose(0) 827 << "ERROR: the containing box already has a greater volume than the envisaged cell volume!" 828 << endl; 829 cout << Verbose(0) 830 << "Setting Box dimensions to minimum possible, the greatest diameters." 831 << endl; 832 for (int i = 0; i < NDIM; i++) 833 BoxLengths.x[i] = GreatestDiameter[i]; 834 mol->CenterEdge(out, &BoxLengths); 835 } 836 else 837 { 838 BoxLengths.x[0] = (repetition[0] * GreatestDiameter[0] + repetition[1] 839 * GreatestDiameter[1] + repetition[2] * GreatestDiameter[2]); 840 BoxLengths.x[1] = (repetition[0] * repetition[1] * GreatestDiameter[0] 841 * GreatestDiameter[1] + repetition[0] * repetition[2] 842 * GreatestDiameter[0] * GreatestDiameter[2] + repetition[1] 843 * repetition[2] * GreatestDiameter[1] * GreatestDiameter[2]); 844 BoxLengths.x[2] = minimumvolume - cellvolume; 845 double x0 = 0., x1 = 0., x2 = 0.; 846 if (gsl_poly_solve_cubic(BoxLengths.x[0], BoxLengths.x[1], 847 BoxLengths.x[2], &x0, &x1, &x2) == 1) // either 1 or 3 on return 848 *out << Verbose(0) << "RESULT: The resulting spacing is: " << x0 849 << " ." << endl; 850 else 851 { 852 *out << Verbose(0) << "RESULT: The resulting spacings are: " << x0 853 << " and " << x1 << " and " << x2 << " ." << endl; 854 x0 = x2; // sorted in ascending order 855 } 856 857 cellvolume = 1; 858 for (int i = 0; i < NDIM; i++) 859 { 860 BoxLengths.x[i] = repetition[i] * (x0 + GreatestDiameter[i]); 861 cellvolume *= BoxLengths.x[i]; 862 } 863 864 // set new box dimensions 865 *out << Verbose(0) << "Translating to box with these boundaries." << endl; 866 mol->CenterInBox((ofstream *) &cout, &BoxLengths); 867 } 689 868 // update Box of atoms by boundary 690 869 mol->SetBoxDimension(&BoxLengths); 691 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " << BoxLengths.x[2] << " with total volume of " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 692 }; 693 870 *out << Verbose(0) << "RESULT: The resulting cell dimensions are: " 871 << BoxLengths.x[0] << " and " << BoxLengths.x[1] << " and " 872 << BoxLengths.x[2] << " with total volume of " << cellvolume << " " 873 << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 874 } 875 ; 694 876 695 877 // =========================================================== class TESSELATION =========================================== … … 702 884 LinesOnBoundaryCount = 0; 703 885 TrianglesOnBoundaryCount = 0; 704 }; 886 TriangleFilesWritten = 0; 887 } 888 ; 705 889 706 890 /** Constructor of class Tesselation. … … 709 893 Tesselation::~Tesselation() 710 894 { 711 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 712 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner != TrianglesOnBoundary.end(); runner++) { 713 delete(runner->second); 714 } 715 }; 895 cout << Verbose(1) << "Free'ing TesselStruct ... " << endl; 896 for (TriangleMap::iterator runner = TrianglesOnBoundary.begin(); runner 897 != TrianglesOnBoundary.end(); runner++) 898 { 899 delete (runner->second); 900 } 901 } 902 ; 716 903 717 904 /** Gueses first starting triangle of the convex envelope. … … 720 907 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 721 908 */ 722 void Tesselation::GuessStartingTriangle(ofstream *out) 909 void 910 Tesselation::GuessStartingTriangle(ofstream *out) 723 911 { 724 912 // 4b. create a starting triangle … … 731 919 732 920 // with A chosen, take each pair B,C and sort 733 if (A != PointsOnBoundary.end()) { 734 B = A; 735 B++; 736 for (; B != PointsOnBoundary.end(); B++) { 737 C = B; 738 C++; 739 for (; C != PointsOnBoundary.end(); C++) { 740 tmp = A->second->node->x.Distance(&B->second->node->x); 741 distance = tmp*tmp; 742 tmp = A->second->node->x.Distance(&C->second->node->x); 743 distance += tmp*tmp; 744 tmp = B->second->node->x.Distance(&C->second->node->x); 745 distance += tmp*tmp; 746 DistanceMMap.insert( DistanceMultiMapPair(distance, pair<PointMap::iterator, PointMap::iterator>(B,C) ) ); 747 } 748 } 749 } 750 // // listing distances 751 // *out << Verbose(1) << "Listing DistanceMMap:"; 752 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 753 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 754 // } 755 // *out << endl; 756 921 if (A != PointsOnBoundary.end()) 922 { 923 B = A; 924 B++; 925 for (; B != PointsOnBoundary.end(); B++) 926 { 927 C = B; 928 C++; 929 for (; C != PointsOnBoundary.end(); C++) 930 { 931 tmp = A->second->node->x.Distance(&B->second->node->x); 932 distance = tmp * tmp; 933 tmp = A->second->node->x.Distance(&C->second->node->x); 934 distance += tmp * tmp; 935 tmp = B->second->node->x.Distance(&C->second->node->x); 936 distance += tmp * tmp; 937 DistanceMMap.insert(DistanceMultiMapPair(distance, pair< 938 PointMap::iterator, PointMap::iterator> (B, C))); 939 } 940 } 941 } 942 // // listing distances 943 // *out << Verbose(1) << "Listing DistanceMMap:"; 944 // for(DistanceMultiMap::iterator runner = DistanceMMap.begin(); runner != DistanceMMap.end(); runner++) { 945 // *out << " " << runner->first << "(" << *runner->second.first->second << ", " << *runner->second.second->second << ")"; 946 // } 947 // *out << endl; 757 948 // 4b2. pick three baselines forming a triangle 758 949 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 759 950 DistanceMultiMap::iterator baseline = DistanceMMap.begin(); 760 for (; baseline != DistanceMMap.end(); baseline++) { 761 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 762 // 2. next, we have to check whether all points reside on only one side of the triangle 763 // 3. construct plane vector 764 PlaneVector.MakeNormalVector(&A->second->node->x, &baseline->second.first->second->node->x, &baseline->second.second->second->node->x); 765 *out << Verbose(2) << "Plane vector of candidate triangle is "; 766 PlaneVector.Output(out); 767 *out << endl; 768 // 4. loop over all points 769 double sign = 0.; 770 PointMap::iterator checker = PointsOnBoundary.begin(); 771 for (; checker != PointsOnBoundary.end(); checker++) { 772 // (neglecting A,B,C) 773 if ((checker == A) || (checker == baseline->second.first) || (checker == baseline->second.second)) 774 continue; 775 // 4a. project onto plane vector 776 TrialVector.CopyVector(&checker->second->node->x); 777 TrialVector.SubtractVector(&A->second->node->x); 778 distance = TrialVector.Projection(&PlaneVector); 779 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 780 continue; 781 *out << Verbose(3) << "Projection of " << checker->second->node->Name << " yields distance of " << distance << "." << endl; 782 tmp = distance/fabs(distance); 783 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 784 if ((sign != 0) && (tmp != sign)) { 785 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 786 *out << Verbose(2) << "Current candidates: " << A->second->node->Name << "," << baseline->second.first->second->node->Name << "," << baseline->second.second->second->node->Name << " leave " << checker->second->node->Name << " outside the convex hull." << endl; 787 break; 788 } else { // note the sign for later 789 *out << Verbose(2) << "Current candidates: " << A->second->node->Name << "," << baseline->second.first->second->node->Name << "," << baseline->second.second->second->node->Name << " leave " << checker->second->node->Name << " inside the convex hull." << endl; 790 sign = tmp; 791 } 792 // 4d. Check whether the point is inside the triangle (check distance to each node 793 tmp = checker->second->node->x.Distance(&A->second->node->x); 794 int innerpoint = 0; 795 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 796 && (tmp < A->second->node->x.Distance(&baseline->second.second->second->node->x))) 797 innerpoint++; 798 tmp = checker->second->node->x.Distance(&baseline->second.first->second->node->x); 799 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 800 && (tmp < baseline->second.first->second->node->x.Distance(&baseline->second.second->second->node->x))) 801 innerpoint++; 802 tmp = checker->second->node->x.Distance(&baseline->second.second->second->node->x); 803 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 804 && (tmp < baseline->second.second->second->node->x.Distance(&A->second->node->x))) 805 innerpoint++; 806 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 807 if (innerpoint == 3) 808 break; 809 } 810 // 5. come this far, all on same side? Then break 1. loop and construct triangle 811 if (checker == PointsOnBoundary.end()) { 812 *out << "Looks like we have a candidate!" << endl; 813 break; 814 } 815 } 816 if (baseline != DistanceMMap.end()) { 817 BPS[0] = baseline->second.first->second; 818 BPS[1] = baseline->second.second->second; 819 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 820 BPS[0] = A->second; 821 BPS[1] = baseline->second.second->second; 822 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 823 BPS[0] = baseline->second.first->second; 824 BPS[1] = A->second; 825 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 826 827 // 4b3. insert created triangle 828 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 829 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 830 TrianglesOnBoundaryCount++; 831 for(int i=0;i<NDIM;i++) { 832 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 833 LinesOnBoundaryCount++; 834 } 835 836 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 837 } else { 838 *out << Verbose(1) << "No starting triangle found." << endl; 839 exit(255); 840 } 841 }; 842 951 for (; baseline != DistanceMMap.end(); baseline++) 952 { 953 // we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate 954 // 2. next, we have to check whether all points reside on only one side of the triangle 955 // 3. construct plane vector 956 PlaneVector.MakeNormalVector(&A->second->node->x, 957 &baseline->second.first->second->node->x, 958 &baseline->second.second->second->node->x); 959 *out << Verbose(2) << "Plane vector of candidate triangle is "; 960 PlaneVector.Output(out); 961 *out << endl; 962 // 4. loop over all points 963 double sign = 0.; 964 PointMap::iterator checker = PointsOnBoundary.begin(); 965 for (; checker != PointsOnBoundary.end(); checker++) 966 { 967 // (neglecting A,B,C) 968 if ((checker == A) || (checker == baseline->second.first) || (checker 969 == baseline->second.second)) 970 continue; 971 // 4a. project onto plane vector 972 TrialVector.CopyVector(&checker->second->node->x); 973 TrialVector.SubtractVector(&A->second->node->x); 974 distance = TrialVector.Projection(&PlaneVector); 975 if (fabs(distance) < 1e-4) // we need to have a small epsilon around 0 which is still ok 976 continue; 977 *out << Verbose(3) << "Projection of " << checker->second->node->Name 978 << " yields distance of " << distance << "." << endl; 979 tmp = distance / fabs(distance); 980 // 4b. Any have different sign to than before? (i.e. would lie outside convex hull with this starting triangle) 981 if ((sign != 0) && (tmp != sign)) 982 { 983 // 4c. If so, break 4. loop and continue with next candidate in 1. loop 984 *out << Verbose(2) << "Current candidates: " 985 << A->second->node->Name << "," 986 << baseline->second.first->second->node->Name << "," 987 << baseline->second.second->second->node->Name << " leave " 988 << checker->second->node->Name << " outside the convex hull." 989 << endl; 990 break; 991 } 992 else 993 { // note the sign for later 994 *out << Verbose(2) << "Current candidates: " 995 << A->second->node->Name << "," 996 << baseline->second.first->second->node->Name << "," 997 << baseline->second.second->second->node->Name << " leave " 998 << checker->second->node->Name << " inside the convex hull." 999 << endl; 1000 sign = tmp; 1001 } 1002 // 4d. Check whether the point is inside the triangle (check distance to each node 1003 tmp = checker->second->node->x.Distance(&A->second->node->x); 1004 int innerpoint = 0; 1005 if ((tmp < A->second->node->x.Distance( 1006 &baseline->second.first->second->node->x)) && (tmp 1007 < A->second->node->x.Distance( 1008 &baseline->second.second->second->node->x))) 1009 innerpoint++; 1010 tmp = checker->second->node->x.Distance( 1011 &baseline->second.first->second->node->x); 1012 if ((tmp < baseline->second.first->second->node->x.Distance( 1013 &A->second->node->x)) && (tmp 1014 < baseline->second.first->second->node->x.Distance( 1015 &baseline->second.second->second->node->x))) 1016 innerpoint++; 1017 tmp = checker->second->node->x.Distance( 1018 &baseline->second.second->second->node->x); 1019 if ((tmp < baseline->second.second->second->node->x.Distance( 1020 &baseline->second.first->second->node->x)) && (tmp 1021 < baseline->second.second->second->node->x.Distance( 1022 &A->second->node->x))) 1023 innerpoint++; 1024 // 4e. If so, break 4. loop and continue with next candidate in 1. loop 1025 if (innerpoint == 3) 1026 break; 1027 } 1028 // 5. come this far, all on same side? Then break 1. loop and construct triangle 1029 if (checker == PointsOnBoundary.end()) 1030 { 1031 *out << "Looks like we have a candidate!" << endl; 1032 break; 1033 } 1034 } 1035 if (baseline != DistanceMMap.end()) 1036 { 1037 BPS[0] = baseline->second.first->second; 1038 BPS[1] = baseline->second.second->second; 1039 BLS[0] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1040 BPS[0] = A->second; 1041 BPS[1] = baseline->second.second->second; 1042 BLS[1] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1043 BPS[0] = baseline->second.first->second; 1044 BPS[1] = A->second; 1045 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1046 1047 // 4b3. insert created triangle 1048 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1049 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1050 TrianglesOnBoundaryCount++; 1051 for (int i = 0; i < NDIM; i++) 1052 { 1053 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BTS->lines[i])); 1054 LinesOnBoundaryCount++; 1055 } 1056 1057 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 1058 } 1059 else 1060 { 1061 *out << Verbose(1) << "No starting triangle found." << endl; 1062 exit(255); 1063 } 1064 } 1065 ; 843 1066 844 1067 /** Tesselates the convex envelope of a cluster from a single starting triangle. … … 855 1078 * \param *mol the cluster as a molecule structure 856 1079 */ 857 void Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, molecule *mol) 1080 void 1081 Tesselation::TesselateOnBoundary(ofstream *out, config *configuration, 1082 molecule *mol) 858 1083 { 859 1084 bool flag; … … 861 1086 class BoundaryPointSet *peak = NULL; 862 1087 double SmallestAngle, TempAngle; 863 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, PropagationVector; 1088 Vector NormalVector, VirtualNormalVector, CenterVector, TempVector, 1089 PropagationVector; 864 1090 LineMap::iterator LineChecker[2]; 865 do { 866 flag = false; 867 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 868 if (baseline->second->TrianglesCount == 1) { 869 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 870 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 871 SmallestAngle = M_PI; 872 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 873 // get peak point with respect to this base line's only triangle 874 for(int i=0;i<3;i++) 875 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) && (BTS->endpoints[i] != baseline->second->endpoints[1])) 876 peak = BTS->endpoints[i]; 877 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 878 // normal vector of triangle 879 BTS->GetNormalVector(NormalVector); 880 *out << Verbose(4) << "NormalVector of base triangle is "; 881 NormalVector.Output(out); 882 *out << endl; 883 // offset to center of triangle 884 CenterVector.Zero(); 885 for(int i=0;i<3;i++) 886 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 887 CenterVector.Scale(1./3.); 888 *out << Verbose(4) << "CenterVector of base triangle is "; 889 CenterVector.Output(out); 890 *out << endl; 891 // vector in propagation direction (out of triangle) 892 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 893 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 894 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 895 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 896 TempVector.CopyVector(&CenterVector); 897 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 898 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 899 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 900 PropagationVector.Scale(-1.); 901 *out << Verbose(4) << "PropagationVector of base triangle is "; 902 PropagationVector.Output(out); 903 *out << endl; 904 winner = PointsOnBoundary.end(); 905 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 906 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints 907 *out << Verbose(3) << "Target point is " << *(target->second) << ":"; 908 bool continueflag = true; 909 910 VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x); 911 VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x); 912 VirtualNormalVector.Scale(-1./2.); // points now to center of base line 913 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 914 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 915 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 916 if (!continueflag) { 917 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", bad direction!" << endl; 918 continue; 919 } else 920 *out << Verbose(4) << "Angle between propagation direction and base line to " << *(target->second) << " is " << TempAngle << ", good direction!" << endl; 921 LineChecker[0] = baseline->second->endpoints[0]->lines.find(target->first); 922 LineChecker[1] = baseline->second->endpoints[1]->lines.find(target->first); 923 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 924 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 925 // else 926 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 927 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 928 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 929 // else 930 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 931 // check first endpoint (if any connecting line goes to target or at least not more than 1) 932 continueflag = continueflag && (( (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) || (LineChecker[0]->second->TrianglesCount == 1))); 933 if (!continueflag) { 934 *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 935 continue; 936 } 937 // check second endpoint (if any connecting line goes to target or at least not more than 1) 938 continueflag = continueflag && (( (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) || (LineChecker[1]->second->TrianglesCount == 1))); 939 if (!continueflag) { 940 *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 941 continue; 942 } 943 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 944 continueflag = continueflag && (!( 945 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 946 && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)) 947 )); 948 if (!continueflag) { 949 *out << Verbose(4) << "Current target is peak!" << endl; 950 continue; 951 } 952 // in case NOT both were found 953 if (continueflag) { // create virtually this triangle, get its normal vector, calculate angle 954 flag = true; 955 VirtualNormalVector.MakeNormalVector(&baseline->second->endpoints[0]->node->x, &baseline->second->endpoints[1]->node->x, &target->second->node->x); 956 // make it always point inward 957 if (baseline->second->endpoints[0]->node->x.Projection(&VirtualNormalVector) > 0) 958 VirtualNormalVector.Scale(-1.); 959 // calculate angle 960 TempAngle = NormalVector.Angle(&VirtualNormalVector); 961 *out << Verbose(4) << "NormalVector is "; 962 VirtualNormalVector.Output(out); 963 *out << " and the angle is " << TempAngle << "." << endl; 964 if (SmallestAngle > TempAngle) { // set to new possible winner 965 SmallestAngle = TempAngle; 966 winner = target; 1091 do 1092 { 1093 flag = false; 1094 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline 1095 != LinesOnBoundary.end(); baseline++) 1096 if (baseline->second->TrianglesCount == 1) 1097 { 1098 *out << Verbose(2) << "Current baseline is between " 1099 << *(baseline->second) << "." << endl; 1100 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 1101 SmallestAngle = M_PI; 1102 BTS = baseline->second->triangles.begin()->second; // there is only one triangle so far 1103 // get peak point with respect to this base line's only triangle 1104 for (int i = 0; i < 3; i++) 1105 if ((BTS->endpoints[i] != baseline->second->endpoints[0]) 1106 && (BTS->endpoints[i] != baseline->second->endpoints[1])) 1107 peak = BTS->endpoints[i]; 1108 *out << Verbose(3) << " and has peak " << *peak << "." << endl; 1109 // normal vector of triangle 1110 BTS->GetNormalVector(NormalVector); 1111 *out << Verbose(4) << "NormalVector of base triangle is "; 1112 NormalVector.Output(out); 1113 *out << endl; 1114 // offset to center of triangle 1115 CenterVector.Zero(); 1116 for (int i = 0; i < 3; i++) 1117 CenterVector.AddVector(&BTS->endpoints[i]->node->x); 1118 CenterVector.Scale(1. / 3.); 1119 *out << Verbose(4) << "CenterVector of base triangle is "; 1120 CenterVector.Output(out); 1121 *out << endl; 1122 // vector in propagation direction (out of triangle) 1123 // project center vector onto triangle plane (points from intersection plane-NormalVector to plane-CenterVector intersection) 1124 TempVector.CopyVector(&baseline->second->endpoints[0]->node->x); 1125 TempVector.SubtractVector(&baseline->second->endpoints[1]->node->x); 1126 PropagationVector.MakeNormalVector(&TempVector, &NormalVector); 1127 TempVector.CopyVector(&CenterVector); 1128 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 1129 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 1130 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 1131 PropagationVector.Scale(-1.); 1132 *out << Verbose(4) << "PropagationVector of base triangle is "; 1133 PropagationVector.Output(out); 1134 *out << endl; 1135 winner = PointsOnBoundary.end(); 1136 for (PointMap::iterator target = PointsOnBoundary.begin(); target 1137 != PointsOnBoundary.end(); target++) 1138 if ((target->second != baseline->second->endpoints[0]) 1139 && (target->second != baseline->second->endpoints[1])) 1140 { // don't take the same endpoints 1141 *out << Verbose(3) << "Target point is " << *(target->second) 1142 << ":"; 1143 bool continueflag = true; 1144 1145 VirtualNormalVector.CopyVector( 1146 &baseline->second->endpoints[0]->node->x); 1147 VirtualNormalVector.AddVector( 1148 &baseline->second->endpoints[0]->node->x); 1149 VirtualNormalVector.Scale(-1. / 2.); // points now to center of base line 1150 VirtualNormalVector.AddVector(&target->second->node->x); // points from center of base line to target 1151 TempAngle = VirtualNormalVector.Angle(&PropagationVector); 1152 continueflag = continueflag && (TempAngle < (M_PI/2.)); // no bends bigger than Pi/2 (90 degrees) 1153 if (!continueflag) 1154 { 1155 *out << Verbose(4) 1156 << "Angle between propagation direction and base line to " 1157 << *(target->second) << " is " << TempAngle 1158 << ", bad direction!" << endl; 1159 continue; 1160 } 1161 else 1162 *out << Verbose(4) 1163 << "Angle between propagation direction and base line to " 1164 << *(target->second) << " is " << TempAngle 1165 << ", good direction!" << endl; 1166 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1167 target->first); 1168 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1169 target->first); 1170 // if (LineChecker[0] != baseline->second->endpoints[0]->lines.end()) 1171 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has line " << *(LineChecker[0]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[0]->second->TrianglesCount << " triangles." << endl; 1172 // else 1173 // *out << Verbose(4) << *(baseline->second->endpoints[0]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1174 // if (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 1175 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has line " << *(LineChecker[1]->second) << " to " << *(target->second) << " as endpoint with " << LineChecker[1]->second->TrianglesCount << " triangles." << endl; 1176 // else 1177 // *out << Verbose(4) << *(baseline->second->endpoints[1]) << " has no line to " << *(target->second) << " as endpoint." << endl; 1178 // check first endpoint (if any connecting line goes to target or at least not more than 1) 1179 continueflag = continueflag && (((LineChecker[0] 1180 == baseline->second->endpoints[0]->lines.end()) 1181 || (LineChecker[0]->second->TrianglesCount == 1))); 1182 if (!continueflag) 1183 { 1184 *out << Verbose(4) << *(baseline->second->endpoints[0]) 1185 << " has line " << *(LineChecker[0]->second) 1186 << " to " << *(target->second) 1187 << " as endpoint with " 1188 << LineChecker[0]->second->TrianglesCount 1189 << " triangles." << endl; 1190 continue; 1191 } 1192 // check second endpoint (if any connecting line goes to target or at least not more than 1) 1193 continueflag = continueflag && (((LineChecker[1] 1194 == baseline->second->endpoints[1]->lines.end()) 1195 || (LineChecker[1]->second->TrianglesCount == 1))); 1196 if (!continueflag) 1197 { 1198 *out << Verbose(4) << *(baseline->second->endpoints[1]) 1199 << " has line " << *(LineChecker[1]->second) 1200 << " to " << *(target->second) 1201 << " as endpoint with " 1202 << LineChecker[1]->second->TrianglesCount 1203 << " triangles." << endl; 1204 continue; 1205 } 1206 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 1207 continueflag = continueflag && (!(((LineChecker[0] 1208 != baseline->second->endpoints[0]->lines.end()) 1209 && (LineChecker[1] 1210 != baseline->second->endpoints[1]->lines.end()) 1211 && (GetCommonEndpoint(LineChecker[0]->second, 1212 LineChecker[1]->second) == peak)))); 1213 if (!continueflag) 1214 { 1215 *out << Verbose(4) << "Current target is peak!" << endl; 1216 continue; 1217 } 1218 // in case NOT both were found 1219 if (continueflag) 1220 { // create virtually this triangle, get its normal vector, calculate angle 1221 flag = true; 1222 VirtualNormalVector.MakeNormalVector( 1223 &baseline->second->endpoints[0]->node->x, 1224 &baseline->second->endpoints[1]->node->x, 1225 &target->second->node->x); 1226 // make it always point inward 1227 if (baseline->second->endpoints[0]->node->x.Projection( 1228 &VirtualNormalVector) > 0) 1229 VirtualNormalVector.Scale(-1.); 1230 // calculate angle 1231 TempAngle = NormalVector.Angle(&VirtualNormalVector); 1232 *out << Verbose(4) << "NormalVector is "; 1233 VirtualNormalVector.Output(out); 1234 *out << " and the angle is " << TempAngle << "." << endl; 1235 if (SmallestAngle > TempAngle) 1236 { // set to new possible winner 1237 SmallestAngle = TempAngle; 1238 winner = target; 1239 } 1240 } 1241 } 1242 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 1243 if (winner != PointsOnBoundary.end()) 1244 { 1245 *out << Verbose(2) << "Winning target point is " 1246 << *(winner->second) << " with angle " << SmallestAngle 1247 << "." << endl; 1248 // create the lins of not yet present 1249 BLS[0] = baseline->second; 1250 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 1251 LineChecker[0] = baseline->second->endpoints[0]->lines.find( 1252 winner->first); 1253 LineChecker[1] = baseline->second->endpoints[1]->lines.find( 1254 winner->first); 1255 if (LineChecker[0] 1256 == baseline->second->endpoints[0]->lines.end()) 1257 { // create 1258 BPS[0] = baseline->second->endpoints[0]; 1259 BPS[1] = winner->second; 1260 BLS[1] = new class BoundaryLineSet(BPS, 1261 LinesOnBoundaryCount); 1262 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1263 BLS[1])); 1264 LinesOnBoundaryCount++; 1265 } 1266 else 1267 BLS[1] = LineChecker[0]->second; 1268 if (LineChecker[1] 1269 == baseline->second->endpoints[1]->lines.end()) 1270 { // create 1271 BPS[0] = baseline->second->endpoints[1]; 1272 BPS[1] = winner->second; 1273 BLS[2] = new class BoundaryLineSet(BPS, 1274 LinesOnBoundaryCount); 1275 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, 1276 BLS[2])); 1277 LinesOnBoundaryCount++; 1278 } 1279 else 1280 BLS[2] = LineChecker[1]->second; 1281 BTS = new class BoundaryTriangleSet(BLS, 1282 TrianglesOnBoundaryCount); 1283 TrianglesOnBoundary.insert(TrianglePair( 1284 TrianglesOnBoundaryCount, BTS)); 1285 TrianglesOnBoundaryCount++; 967 1286 } 968 } 1287 else 1288 { 1289 *out << Verbose(1) 1290 << "I could not determine a winner for this baseline " 1291 << *(baseline->second) << "." << endl; 1292 } 1293 1294 // 5d. If the set of lines is not yet empty, go to 5. and continue 969 1295 } 970 // 5b. The point of the above whose triangle has the greatest angle with the triangle the current line belongs to (it only belongs to one, remember!): New triangle 971 if (winner != PointsOnBoundary.end()) { 972 *out << Verbose(2) << "Winning target point is " << *(winner->second) << " with angle " << SmallestAngle << "." << endl; 973 // create the lins of not yet present 974 BLS[0] = baseline->second; 975 // 5c. add lines to the line set if those were new (not yet part of a triangle), delete lines that belong to two triangles) 976 LineChecker[0] = baseline->second->endpoints[0]->lines.find(winner->first); 977 LineChecker[1] = baseline->second->endpoints[1]->lines.find(winner->first); 978 if (LineChecker[0] == baseline->second->endpoints[0]->lines.end()) { // create 979 BPS[0] = baseline->second->endpoints[0]; 980 BPS[1] = winner->second; 981 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 982 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[1]) ); 983 LinesOnBoundaryCount++; 984 } else 985 BLS[1] = LineChecker[0]->second; 986 if (LineChecker[1] == baseline->second->endpoints[1]->lines.end()) { // create 987 BPS[0] = baseline->second->endpoints[1]; 988 BPS[1] = winner->second; 989 BLS[2] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 990 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[2]) ); 991 LinesOnBoundaryCount++; 992 } else 993 BLS[2] = LineChecker[1]->second; 994 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 995 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 996 TrianglesOnBoundaryCount++; 997 } else { 998 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl; 999 } 1000 1001 // 5d. If the set of lines is not yet empty, go to 5. and continue 1002 } else 1003 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 1004 } while (flag); 1005 1006 }; 1296 else 1297 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) 1298 << " has a triangle count of " 1299 << baseline->second->TrianglesCount << "." << endl; 1300 } 1301 while (flag); 1302 1303 } 1304 ; 1007 1305 1008 1306 /** Adds an atom to the tesselation::PointsOnBoundary list. 1009 1307 * \param *Walker atom to add 1010 1308 */ 1011 void Tesselation::AddPoint(atom *Walker) 1309 void 1310 Tesselation::AddPoint(atom *Walker) 1012 1311 { 1013 1312 PointTestPair InsertUnique; 1014 1313 BPS[0] = new class BoundaryPointSet(Walker); 1015 InsertUnique = PointsOnBoundary.insert( PointPair(Walker->nr, BPS[0]));1016 if (InsertUnique.second) 1314 InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0])); 1315 if (InsertUnique.second) // if new point was not present before, increase counter 1017 1316 PointsOnBoundaryCount++; 1018 }; 1019 1020 void Tesselation::AddTrianglePoint(atom* Candidate, int n) 1021 { 1022 PointTestPair InsertUnique; 1023 TPS[n] = new class BoundaryPointSet(Candidate); 1024 InsertUnique = PointsOnBoundary.insert( PointPair(Candidate->nr, TPS[n]) ); 1025 if (InsertUnique.second) // if new point was not present before, increase counter 1026 { 1027 PointsOnBoundaryCount++; 1028 } 1029 else 1030 { 1031 delete TPS[n]; 1032 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) << " gibt's schon in der PointMap." << endl; 1033 TPS[n] = (InsertUnique.first)->second; 1034 } 1035 }; 1036 1037 /* 1038 * Function tries to add line from current Points in BPS to BoundaryLineSet. 1039 * If succesfull it raises the line count and iserts the new line into the BLS, 1040 * if unsuccesfull, it writes the line which had been present into the BLS, deleting the new constructed one. 1317 } 1318 ; 1319 1320 /** Adds point to Tesselation::PointsOnBoundary if not yet present. 1321 * Tesselation::TPS is set to either this new BoundaryPointSet or to the existing one of not unique. 1322 * @param Candidate point to add 1323 * @param n index for this point in Tesselation::TPS array 1041 1324 */ 1042 1043 void Tesselation::AddTriangleLine(int n) 1044 { 1045 LineMap::iterator LineWalker; 1046 BLS[n] = new class BoundaryLineSet(BPS, BPS[1]->node->nr); 1047 if ((BPS[0]->lines.find(BPS[1]->node->nr))->second->endpoints[0] == BLS[n]->endpoints[0] 1048 and (BPS[0]->lines.find(BPS[1]->node->nr))->second->endpoints[1] == BLS[n]->endpoints[1]) 1049 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1050 { 1051 delete BLS[n]; 1052 cout << Verbose(2) << "Tried to add an existing line, handled it." << endl; 1053 LineWalker = LinesOnBoundary.end(); 1054 1055 while(LineWalker->second->endpoints[0] != BLS[n]->endpoints[0] or LineWalker->second->endpoints[1] != BLS[n]->endpoints[1]) 1056 { 1057 cout << Verbose(1) << "Looking for line which already exists"<< endl; 1058 LineWalker--; 1059 } 1060 BLS[n]=LineWalker->second; 1061 } 1062 else 1063 { 1064 cout << Verbose(2) << "Adding line which has not been used before." << endl; 1065 BPS[1]->lines.insert( LinePair(BPS[0]->node->nr, BLS[n]) ); 1066 BPS[2]->lines.insert( LinePair(BPS[1]->node->nr, BLS[n]) ); 1067 1068 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BLS[n])); 1069 LinesOnBoundaryCount++; 1070 1071 } 1072 }; 1073 1074 /* 1075 * Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm). 1325 void 1326 Tesselation::AddTrianglePoint(atom* Candidate, int n) 1327 { 1328 PointTestPair InsertUnique; 1329 TPS[n] = new class BoundaryPointSet(Candidate); 1330 InsertUnique = PointsOnBoundary.insert(PointPair(Candidate->nr, TPS[n])); 1331 if (InsertUnique.second) // if new point was not present before, increase counter 1332 { 1333 PointsOnBoundaryCount++; 1334 } 1335 else 1336 { 1337 delete TPS[n]; 1338 cout << Verbose(2) << "Atom " << *((InsertUnique.first)->second->node) 1339 << " gibt's schon in der PointMap." << endl; 1340 TPS[n] = (InsertUnique.first)->second; 1341 } 1342 } 1343 ; 1344 1345 /** Function tries to add line from current Points in BPS to BoundaryLineSet. 1346 * If succesful it raises the line count and inserts the new line into the BLS, 1347 * if unsuccesful, it writes the line which had been present into the BLS, deleting the new constructed one. 1348 * @param *a first endpoint 1349 * @param *b second endpoint 1350 * @param n index of Tesselation::BLS giving the line with both endpoints 1351 */ 1352 void 1353 Tesselation::AddTriangleLine(class BoundaryPointSet *a, 1354 class BoundaryPointSet *b, int n) 1355 { 1356 LineMap::iterator LineWalker; 1357 //cout << "Manually checking endpoints for line." << endl; 1358 if ((a->lines.find(b->node->nr))->first == b->node->nr) 1359 //If a line is there, how do I recognize that beyond a shadow of a doubt? 1360 { 1361 //cout << Verbose(2) << "Line exists already, retrieving it from LinesOnBoundarySet" << endl; 1362 1363 LineWalker = LinesOnBoundary.end(); 1364 LineWalker--; 1365 1366 while (LineWalker->second->endpoints[0]->node->nr != min(a->node->nr, 1367 b->node->nr) or LineWalker->second->endpoints[1]->node->nr != max( 1368 a->node->nr, b->node->nr)) 1369 { 1370 //cout << Verbose(1) << "Looking for line which already exists"<< endl; 1371 LineWalker--; 1372 } 1373 BPS[0] = LineWalker->second->endpoints[0]; 1374 BPS[1] = LineWalker->second->endpoints[1]; 1375 BLS[n] = LineWalker->second; 1376 1377 } 1378 else 1379 { 1380 cout << Verbose(2) 1381 << "Adding line which has not been used before between " 1382 << *(a->node) << " and " << *(b->node) << "." << endl; 1383 BPS[0] = a; 1384 BPS[1] = b; 1385 BLS[n] = new class BoundaryLineSet(BPS, LinesOnBoundaryCount); 1386 1387 LinesOnBoundary.insert(LinePair(LinesOnBoundaryCount, BLS[n])); 1388 LinesOnBoundaryCount++; 1389 1390 } 1391 } 1392 ; 1393 1394 /** Function tries to add Triangle just created to Triangle and remarks if already existent (Failure of algorithm). 1076 1395 * Furthermore it adds the triangle to all of its lines, in order to recognize those which are saturated later. 1077 1396 */ 1078 1079 void Tesselation::AddTriangleToLines() 1080 { 1081 cout <<Verbose(1) << "Adding triangle to its lines" <<endl; 1082 int i=0; 1083 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1084 TrianglesOnBoundaryCount++; 1085 for (i=0; i<3; i++) 1086 { 1087 BLS[i]->AddTriangle(BTS); 1088 } 1089 }; 1090 1091 1092 1093 /*! 1094 * This recursive function finds a third point, to form a triangle with two given ones. 1397 void 1398 Tesselation::AddTriangleToLines() 1399 { 1400 1401 cout << Verbose(1) << "Adding triangle to its lines" << endl; 1402 int i = 0; 1403 TrianglesOnBoundary.insert(TrianglePair(TrianglesOnBoundaryCount, BTS)); 1404 TrianglesOnBoundaryCount++; 1405 1406 /* 1407 * this is apparently done when constructing triangle 1408 1409 for (i=0; i<3; i++) 1410 { 1411 BLS[i]->AddTriangle(BTS); 1412 } 1413 */ 1414 } 1415 ; 1416 1417 /** This recursive function finds a third point, to form a triangle with two given ones. 1095 1418 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1096 1419 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1097 1420 * upon which we operate. 1098 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its id, itsgeneral \1421 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its general \ 1099 1422 * direction and angle into Storage. 1100 1423 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1101 1424 * with all neighbours of the candidate. 1425 * @param a first point 1426 * @param b second point 1427 * @param Candidate base point along whose bonds to start looking from 1428 * @param Parent point to avoid during search as its wrong direction 1429 * @param RecursionLevel contains current recursion depth 1430 * @param Chord baseline vector of first and second point 1431 * @param d1 second in plane vector (along with \a Chord) of the triangle the baseline belongs to 1432 * @param OldNormal normal of the triangle which the baseline belongs to 1433 * @param Opt_Candidate candidate reference to return 1434 * @param Opt_Mittelpunkt Centerpoint of ball, when resting on Opt_Candidate 1435 * @param Storage array containing two angles of current Opt_Candidate 1436 * @param RADIUS radius of ball 1437 * @param mol molecule structure with atoms and bonds 1102 1438 */ 1103 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, int n, Vector *Chord, Vector *d1, Vector *OldNormal, atom*& Opt_Candidate, double *Storage, const double RADIUS, molecule* mol, bool problem) 1439 void 1440 Find_next_suitable_point(atom* a, atom* b, atom* Candidate, atom* Parent, 1441 int RecursionLevel, Vector *Chord, Vector *d1, Vector *OldNormal, 1442 atom*& Opt_Candidate, Vector *Opt_Mittelpunkt, double *Storage, const double RADIUS, molecule* mol) 1104 1443 { 1105 1444 /* OldNormal is normal vector on the old triangle 1106 1445 * d1 is normal on the triangle line, from which we come, as well as on OldNormal. 1446 * Chord points from a to b. 1107 1447 */ 1108 1448 Vector dif_a; //Vector from a to candidate 1109 1449 Vector dif_b; //Vector from b to candidate 1110 1450 Vector AngleCheck; // Projection of a difference vector on plane orthogonal on triangle side. 1451 Vector TempNormal, Umkreismittelpunkt, Mittelpunkt; 1452 1453 double CurrentEpsilon = 0.1; 1454 double alpha, beta, gamma, SideA, SideB, SideC, sign, Umkreisradius, Restradius, Distance; 1111 1455 atom *Walker; // variable atom point 1456 1112 1457 1113 1458 dif_a.CopyVector(&(a->x)); … … 1116 1461 dif_b.SubtractVector(&(Candidate->x)); 1117 1462 AngleCheck.CopyVector(&dif_a); 1463 AngleCheck.Scale(-1); 1118 1464 AngleCheck.ProjectOntoPlane(Chord); 1119 1465 1120 if (problem) 1121 { 1122 cout << "Atom number" << Candidate->nr << endl; 1123 Candidate->x.Output((ofstream *)&cout); 1124 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] << endl; 1125 } 1466 SideA = dif_b.Norm(); 1467 SideB = dif_a.Norm(); 1468 SideC = Chord->Norm(); 1469 //Chord->Scale(-1); 1470 1471 alpha = Chord->Angle(&dif_a); 1472 beta = M_PI - Chord->Angle(&dif_b); 1473 gamma = dif_a.Angle(&dif_b); 1474 1475 1476 if (DEBUG) 1477 { 1478 cout << "Atom number" << Candidate->nr << endl; 1479 Candidate->x.Output((ofstream *) &cout); 1480 cout << "number of bonds " << mol->NumberOfBondsPerAtom[Candidate->nr] 1481 << endl; 1482 } 1126 1483 1127 1484 if (a != Candidate and b != Candidate) 1128 { 1129 1130 if (Chord->Norm()/(2*sin(0.5*dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find if Ball will touch atom 1131 { 1132 if (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1))>Storage[0]) //This will give absolute preference to those in "right-hand" quadrants 1133 { 1134 Opt_Candidate = Candidate; 1135 Storage[0]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1136 Storage[1]=AngleCheck.Angle(OldNormal); 1137 } 1138 else 1139 { 1140 if ((dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)) == Storage[0] && Storage[0]>0 && Storage[1]> AngleCheck.Angle(OldNormal)) or \ 1141 (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)) == Storage[0] && Storage[0]<0 && Storage[1]< AngleCheck.Angle(OldNormal))) 1142 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1143 { 1144 Opt_Candidate = Candidate; 1145 Storage[0]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1146 Storage[1]=AngleCheck.Angle(OldNormal); 1147 } 1148 else 1149 { 1150 if (problem) 1151 cout << "Looses to better candidate" << endl; 1152 } 1153 } 1154 } 1155 else 1156 { 1157 if (problem) 1158 cout << "erfuellt Dreiecksbedingung fuer sehne nicht" <<endl; 1159 } 1160 } 1485 { 1486 // alpha = dif_a.Angle(&dif_b) / 2.; 1487 // SideA = Chord->Norm() / 2.;// (Chord->Norm()/2.) / sin(0.5*alpha); 1488 // SideB = dif_a.Norm(); 1489 // centerline = SideA * SideA + SideB * SideB - 2. * SideA * SideB * cos( 1490 // alpha); // note this is squared of center line length 1491 // Those are remains from Freddie. Needed? 1492 1493 // centerline = (Chord->Norm()/2.) / sin(0.5*alpha); 1494 // Old Chordtest. Replaced by test for Radius of Circumscribing circle 1495 1496 Umkreisradius = SideA / 2.0 / sin(alpha); 1497 cout << Umkreisradius << endl; 1498 cout << SideB / 2.0 / sin(beta) << endl; 1499 cout << SideC / 2.0 / sin(gamma) << endl; 1500 1501 if (Umkreisradius < RADIUS) 1502 { 1503 1504 sign = AngleCheck.ScalarProduct(d1); 1505 sign /= fabs(sign); // +1 if in direction of triangle plane, -1 if in other direction... 1506 1507 // intermediate calculations: 1508 1509 Umkreismittelpunkt = (a->x) * sin(2.*alpha) + b->x * sin(2.*beta) + (Candidate->x) * sin(2.*gamma) ; 1510 Umkreismittelpunkt.Scale(1/(sin(2*alpha) + sin(2*beta) + sin(2*gamma))); 1511 1512 cout << "Umkreismittelpunkt has coordinates" << Umkreismittelpunkt.x[0] << " "<< Umkreismittelpunkt.x[1] <<" "<<Umkreismittelpunkt.x[2] << endl; 1513 cout << "Candidate has coordinates" << Candidate->x.x[0]<< " " << Candidate->x.x[1] << " " << Candidate->x.x[2] << endl; 1514 cout << "a has coordinates" << a->x.x[0]<< " " << a->x.x[1] << " " << a->x.x[2] << endl; 1515 cout << "b has coordinates" << b->x.x[0]<< " " << b->x.x[1] << " " << b->x.x[2] << endl; 1516 1517 TempNormal.CopyVector(&dif_a); 1518 TempNormal.VectorProduct(&dif_b); 1519 if (TempNormal.ScalarProduct(OldNormal)<0 && sign>0 || TempNormal.ScalarProduct(OldNormal)>0 && sign<0) 1520 { 1521 TempNormal.Scale(-1); 1522 } 1523 TempNormal.Normalize(); 1524 Restradius = sqrt(RADIUS*RADIUS - Umkreisradius*Umkreisradius); 1525 cout << "Umkreisradius ist " << Umkreisradius << endl; 1526 cout << "Restradius ist " << Restradius << endl; 1527 TempNormal.Scale(Restradius); 1528 cout << "TempNormal has coordinates " << TempNormal.x[0] << " " << TempNormal.x[1] << " " << TempNormal.x[2] << " " << endl; 1529 Mittelpunkt.CopyVector(&Umkreismittelpunkt); 1530 Mittelpunkt.AddVector(&TempNormal); //this is center of sphere supported by a, b and Candidate 1531 cout << "Mittelpunkt has coordinates" << Mittelpunkt.x[0] << " " << Mittelpunkt.x[1]<< " " <<Mittelpunkt.x[2] << endl; 1532 cout << "Dist a to UmkreisMittelpunkt " << a->x.Distance(&Umkreismittelpunkt) << endl; 1533 cout << "Dist b to UmkreisMittelpunkt " << b->x.Distance(&Umkreismittelpunkt) << endl; 1534 cout << "Dist Candidate to UmkreisMittelpunkt " << Candidate->x.Distance(&Umkreismittelpunkt) << endl; 1535 cout << "Dist a to Mittelpunkt " << a->x.Distance(&Mittelpunkt) << endl; 1536 cout << "Dist b to Mittelpunkt " << b->x.Distance(&Mittelpunkt) << endl; 1537 cout << "Dist Candidate to Mittelpunkt " << Candidate->x.Distance(&Mittelpunkt) << endl; 1538 1539 if (Storage[0]< -1.5) // first Candidate at all 1540 { 1541 1542 cout << "Next better candidate is " << *Candidate << " with "; 1543 Opt_Candidate = Candidate; 1544 Storage[0] = sign; 1545 Storage[1] = AngleCheck.Angle(OldNormal); 1546 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1547 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1548 << Storage[0] << endl; 1549 } 1550 else 1551 { 1552 //We will now check for non interference, that is if the new candidate would have the Opt_Candidate 1553 //within the ball. 1554 1555 Distance = Opt_Candidate->x.Distance(&Mittelpunkt); 1556 cout << "Opt_Candidate " << Opt_Candidate << " has distance " << Distance << " to Center of Candidate " << endl; 1557 1558 1559 if (Distance >RADIUS) // We have no interference and may now check whether the new point is better. 1560 { 1561 cout << "Atom " << Candidate << " has distance " << Candidate->x.Distance(Opt_Mittelpunkt) << " to Center of Candidate " << endl; 1562 1563 if ((Storage[0] < 0 && fabs(sign - Storage[0]) > CurrentEpsilon))// || //This will give absolute preference to those in "right-hand" quadrants 1564 //sqrt(Candidate->x.Distance(Opt_Mittelpunkt)) < RADIUS) //and those where Candidate would be within old Sphere. 1565 { 1566 cout << "Next better candidate is " << *Candidate << " with "; 1567 Opt_Candidate = Candidate; 1568 Storage[0] = sign; 1569 Storage[1] = AngleCheck.Angle(OldNormal); 1570 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1571 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1572 << Storage[0] << endl; 1573 } 1574 else 1575 { 1576 if ((fabs(sign - Storage[0]) < CurrentEpsilon && sign > 0 1577 && Storage[1] > AngleCheck.Angle(OldNormal)) || 1578 (fabs(sign - Storage[0]) < CurrentEpsilon && sign < 0 1579 && Storage[1] < AngleCheck.Angle(OldNormal))) 1580 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1581 { 1582 cout << "Next better candidate is " << *Candidate << " with "; 1583 Opt_Candidate = Candidate; 1584 Storage[0] = sign; 1585 Storage[1] = AngleCheck.Angle(OldNormal); 1586 Opt_Mittelpunkt->CopyVector(&Mittelpunkt); 1587 cout << "Angle is " << Storage[1] << ", Halbraum ist " 1588 << Storage[0] << endl; 1589 } 1590 } 1591 } 1592 else 1593 { 1594 if (DEBUG) 1595 cout << "Looses to better candidate" << endl; 1596 } 1597 } 1598 } 1599 else 1600 { 1601 if (DEBUG) 1602 { 1603 cout << "Doesn't satisfy requirements for circumscribing circle" << endl; 1604 } 1605 } 1606 } 1607 1161 1608 else 1162 { 1163 if (problem) 1164 cout << "identisch mit Ursprungslinie" << endl; 1165 } 1166 1167 if (n<5) // Five is the recursion level threshold. 1168 { 1169 for(int i=0; i<mol->NumberOfBondsPerAtom[Candidate->nr];i++) // go through all bond 1170 { 1171 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1172 if (Walker->nr == Parent->nr){ 1173 continue; 1174 } 1175 else{ 1176 Find_next_suitable_point(a, b, Walker, Candidate, n+1, Chord, d1, OldNormal, Opt_Candidate, Storage, RADIUS, mol, problem); //call function again 1177 } 1178 } 1179 } 1180 }; 1181 1182 /*! 1183 * this function fins a triangle to a line, adjacent to an existing one. 1609 { 1610 if (DEBUG) 1611 cout << "identisch mit Ursprungslinie" << endl; 1612 } 1613 1614 if (RecursionLevel < 7) // Five is the recursion level threshold. 1615 { 1616 for (int i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) // go through all bond 1617 { 1618 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom( 1619 Candidate); 1620 if (Walker == Parent) 1621 { // don't go back the same bond 1622 continue; 1623 } 1624 else 1625 { 1626 Find_next_suitable_point(a, b, Walker, Candidate, RecursionLevel 1627 + 1, Chord, d1, OldNormal, Opt_Candidate, Opt_Mittelpunkt, Storage, RADIUS, 1628 mol); //call function again 1629 } 1630 } 1631 } 1632 } 1633 ; 1634 1635 /** This function finds a triangle to a line, adjacent to an existing one. 1636 * @param out output stream for debugging 1637 * @param tecplot output stream for writing found triangles in TecPlot format 1638 * @param mol molecule structure with all atoms and bonds 1639 * @param Line current baseline to search from 1640 * @param T current triangle which \a Line is edge of 1641 * @param RADIUS radius of the rolling ball 1642 * @param N number of found triangles 1184 1643 */ 1185 void Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, const double& RADIUS, int N) 1186 { 1187 cout << Verbose(1) << "Looking for next suitable triangle \n"; 1644 void 1645 Tesselation::Find_next_suitable_triangle(ofstream *out, ofstream *tecplot, 1646 molecule* mol, BoundaryLineSet &Line, BoundaryTriangleSet &T, 1647 const double& RADIUS, int N) 1648 { 1649 cout << Verbose(1) << "Looking for next suitable triangle \n"; 1188 1650 Vector direction1; 1189 1651 Vector helper; 1190 1652 Vector Chord; 1653 ofstream *tempstream = NULL; 1654 char filename[255]; 1191 1655 //atom* Walker; 1192 1656 1193 1657 double Storage[2]; 1194 Storage[0] =-2.;// This direction is either +1 or -1 one, so any result will take precedence over initial values1195 Storage[1] =9999999.;// This is also lower then any value produced by an eligible atom, which are all positive1658 Storage[0] = -2.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 1659 Storage[1] = 9999999.; // This is also lower then any value produced by an eligible atom, which are all positive 1196 1660 atom* Opt_Candidate = NULL; 1197 1661 Vector Opt_Mittelpunkt; 1198 1662 1199 1663 cout << Verbose(1) << "Constructing helpful vectors ... " << endl; 1200 1664 helper.CopyVector(&(Line.endpoints[0]->node->x)); 1201 for (int i = 0; i<3; i++)1202 { 1203 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr && T.endpoints[i]->node->nr!=Line.endpoints[1]->node->nr)1204 { 1205 helper.SubtractVector(&T.endpoints[i]->node->x); 1206 break;1207 } 1208 }1209 1665 for (int i = 0; i < 3; i++) 1666 { 1667 if (T.endpoints[i]->node->nr != Line.endpoints[0]->node->nr 1668 && T.endpoints[i]->node->nr != Line.endpoints[1]->node->nr) 1669 { 1670 helper.SubtractVector(&T.endpoints[i]->node->x); 1671 break; 1672 } 1673 } 1210 1674 1211 1675 direction1.CopyVector(&Line.endpoints[0]->node->x); … … 1213 1677 direction1.VectorProduct(&(T.NormalVector)); 1214 1678 1215 if (direction1.ScalarProduct(&helper) <0)1679 if (direction1.ScalarProduct(&helper) < 0) 1216 1680 { 1217 1681 direction1.Scale(-1); … … 1221 1685 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 1222 1686 1223 cout << Verbose(1) << "Looking for third point candidates for triangle ... " << endl; 1224 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), Opt_Candidate, Storage, RADIUS, mol,0); 1225 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), Opt_Candidate, Storage, RADIUS, mol,0); 1226 1227 if (N>7) 1228 { 1229 cout << Verbose(1) << "No new Atom found, triangle construction will crash" << endl; 1230 write_tecplot_file(out, tecplot, this, mol); 1231 tecplot->flush(); 1232 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), Opt_Candidate, Storage, RADIUS, mol, 1); 1233 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), Opt_Candidate, Storage, RADIUS, mol, 1); 1687 cout << Verbose(1) << "Looking for third point candidates for triangle ... " 1688 << endl; 1689 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, 1690 Line.endpoints[0]->node, Line.endpoints[1]->node, 0, &Chord, &direction1, 1691 &(T.NormalVector), Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1692 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, 1693 Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, 1694 &(T.NormalVector), Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1695 1696 if ((TrianglesOnBoundaryCount % 10) == 0) 1697 { 1698 sprintf(filename, "testEnvelope-%d.dat", TriangleFilesWritten); 1699 tempstream = new ofstream(filename, ios::trunc); 1700 write_tecplot_file(out, tempstream, this, mol, TriangleFilesWritten++); 1701 tempstream->close(); 1702 tempstream->flush(); 1703 delete(tempstream); 1234 1704 } 1705 1706 if ((Opt_Candidate == NULL) || (N<12)) 1707 { 1708 cout << Verbose(1) 1709 << "No new Atom found, triangle construction will crash" << endl; 1710 write_tecplot_file(out, tecplot, this, mol, TriangleFilesWritten); 1711 Find_next_suitable_point(Line.endpoints[0]->node, 1712 Line.endpoints[1]->node, Line.endpoints[0]->node, 1713 Line.endpoints[1]->node, 0, &Chord, &direction1, &(T.NormalVector), 1714 Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1715 Find_next_suitable_point(Line.endpoints[0]->node, 1716 Line.endpoints[1]->node, Line.endpoints[1]->node, 1717 Line.endpoints[0]->node, 0, &Chord, &direction1, &(T.NormalVector), 1718 Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1719 } 1235 1720 // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke 1236 1721 1237 cout << Verbose(1) << "Adding exactly one Walker for reasons completely unknown to me ... " << endl;1238 1722 cout << " Optimal candidate is " << *Opt_Candidate << endl; 1239 1723 … … 1241 1725 AddTrianglePoint(Line.endpoints[0]->node, 1); 1242 1726 AddTrianglePoint(Line.endpoints[1]->node, 2); 1243 1244 BPS[0] = TPS[0]; 1245 BPS[1] = TPS[1]; 1246 AddTriangleLine(0); 1247 BPS[0] = TPS[0]; 1248 BPS[1] = TPS[2]; 1249 AddTriangleLine(1); 1250 BPS[0] = TPS[1]; 1251 BPS[1] = TPS[2]; 1252 AddTriangleLine(2); 1727 1728 AddTriangleLine(TPS[0], TPS[1], 0); 1729 AddTriangleLine(TPS[0], TPS[2], 1); 1730 AddTriangleLine(TPS[1], TPS[2], 2); 1253 1731 1254 1732 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1255 1733 AddTriangleToLines(); 1256 1257 1258 cout << Verbose(1) << "Constructing normal vector for this triangle ... " << endl; 1734 cout << "New triangle with " << *BTS << endl; 1735 1736 cout << Verbose(1) << "Constructing normal vector for this triangle ... " 1737 << endl; 1259 1738 1260 1739 BTS->GetNormalVector(BTS->NormalVector); 1261 1740 1262 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector))<0 && Storage[0]>0) || 1263 ((BTS->NormalVector.ScalarProduct(&(T.NormalVector))>0 && Storage[0]<0)) ) 1741 if ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) < 0 && Storage[0] > 0) 1742 || ((BTS->NormalVector.ScalarProduct(&(T.NormalVector)) > 0 && Storage[0] 1743 < 0))) 1264 1744 { 1265 1745 BTS->NormalVector.Scale(-1); 1266 1746 }; 1267 1747 1268 }; 1269 1270 1271 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, int n, Vector Oben, atom*& Opt_Candidate, double Storage[2], molecule* mol, double RADIUS) 1272 { 1273 cout << Verbose(1) << "Looking for second point of starting triangle, recursive level "<< n <<endl;; 1274 int i; 1275 Vector AngleCheck; 1276 atom* Walker; 1277 1278 if (a->nr !=Candidate->nr) 1279 { 1280 AngleCheck.CopyVector(&(Candidate->x)); 1281 AngleCheck.SubtractVector(&(a->x)); 1282 if (AngleCheck.Norm() < RADIUS and AngleCheck.Angle(&Oben) < Storage[0]) 1283 { 1284 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 1285 Opt_Candidate=Candidate; 1286 Storage[0]=AngleCheck.Angle(&Oben); 1287 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[1]); 1288 } 1289 else{ 1290 if (AngleCheck.Norm() > RADIUS) 1291 { 1292 cout << Verbose(1) << "refused due to Radius" << AngleCheck.Norm() << endl; 1293 } 1294 else{ 1295 cout << Verbose(1) << "Supposedly looses to a better candidate" << Opt_Candidate->nr << endl; 1296 } 1297 } 1298 } 1299 1300 if (n<5) 1301 { 1302 for (i = 0; i< mol->NumberOfBondsPerAtom[Candidate->nr]; i++) 1303 { 1304 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom(Candidate); 1305 if (Walker->nr == Parent->nr) 1306 continue; 1307 else 1308 Find_second_point_for_Tesselation(a, Walker, Candidate, n+1, Oben, Opt_Candidate, Storage, mol, RADIUS); 1309 }; 1748 } 1749 ; 1750 1751 void 1752 Find_second_point_for_Tesselation(atom* a, atom* Candidate, atom* Parent, 1753 int RecursionLevel, Vector Oben, atom*& Opt_Candidate, double Storage[2], 1754 molecule* mol, double RADIUS) 1755 { 1756 cout << Verbose(1) 1757 << "Looking for second point of starting triangle, recursive level " 1758 << RecursionLevel << endl;; 1759 int i; 1760 Vector AngleCheck; 1761 atom* Walker; 1762 double norm = -1.; 1763 1764 // check if we only have one unique point yet ... 1765 if (a != Candidate) 1766 { 1767 AngleCheck.CopyVector(&(Candidate->x)); 1768 AngleCheck.SubtractVector(&(a->x)); 1769 norm = AngleCheck.Norm(); 1770 // second point shall have smallest angle with respect to Oben vector 1771 if (norm < RADIUS) 1772 { 1773 if (AngleCheck.Angle(&Oben) < Storage[0]) 1774 { 1775 //cout << Verbose(1) << "Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 1776 cout << "Next better candidate is " << *Candidate 1777 << " with distance " << norm << ".\n"; 1778 Opt_Candidate = Candidate; 1779 Storage[0] = AngleCheck.Angle(&Oben); 1780 //cout << Verbose(1) << "Changing something in Storage: %lf %lf. \n", Storage[0], Storage[1]); 1781 } 1782 else 1783 { 1784 cout << Verbose(1) << "Supposedly looses to a better candidate " 1785 << *Opt_Candidate << endl; 1786 } 1787 } 1788 else 1789 { 1790 cout << Verbose(1) << *Candidate << " refused due to Radius " << norm 1791 << endl; 1792 } 1793 } 1794 1795 // if not recursed to deeply, look at all its bonds 1796 if (RecursionLevel < 7) 1797 { 1798 for (i = 0; i < mol->NumberOfBondsPerAtom[Candidate->nr]; i++) 1799 { 1800 Walker = mol->ListOfBondsPerAtom[Candidate->nr][i]->GetOtherAtom( 1801 Candidate); 1802 if (Walker == Parent) // don't go back along the bond we came from 1803 continue; 1804 else 1805 Find_second_point_for_Tesselation(a, Walker, Candidate, 1806 RecursionLevel + 1, Oben, Opt_Candidate, Storage, mol, RADIUS); 1807 }; 1310 1808 }; 1311 1312 1313 }; 1314 1315 1316 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 1317 { 1318 cout << Verbose(1) << "Looking for starting triangle \n"; 1319 int i=0; 1809 } 1810 ; 1811 1812 void 1813 Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 1814 { 1815 cout << Verbose(1) << "Looking for starting triangle \n"; 1816 int i = 0; 1320 1817 atom* Walker; 1321 1818 atom* FirstPoint; 1322 1819 atom* SecondPoint; 1323 intmax_index[3];1820 atom* max_index[3]; 1324 1821 double max_coordinate[3]; 1325 1822 Vector Oben; 1326 1823 Vector helper; 1327 1824 Vector Chord; 1825 Vector Opt_Mittelpunkt; 1328 1826 1329 1827 Oben.Zero(); 1330 1828 1331 1332 for(i =0; i<3; i++) 1333 { 1334 max_index[i] =-1; 1335 max_coordinate[i] =-1; 1336 } 1337 cout << Verbose(1) << "Molecule mol is there and has " << mol->AtomCount << " Atoms \n"; 1829 for (i = 0; i < 3; i++) 1830 { 1831 max_index[i] = NULL; 1832 max_coordinate[i] = -1; 1833 } 1834 cout << Verbose(1) << "Molecule mol is there and has " << mol->AtomCount 1835 << " Atoms \n"; 1836 1837 // 1. searching topmost atom with respect to each axis 1338 1838 Walker = mol->start; 1339 1839 while (Walker->next != mol->end) 1340 1840 { 1341 1342 for (i=0; i<3; i++)1343 1344 1345 1346 max_coordinate[i]=Walker->x.x[i];1347 max_index[i]=Walker->nr;1348 1349 1350 } 1351 1352 cout << Verbose(1) << "Found maximum coordinates. " << endl;1841 Walker = Walker->next; 1842 for (i = 0; i < 3; i++) 1843 { 1844 if (Walker->x.x[i] > max_coordinate[i]) 1845 { 1846 max_coordinate[i] = Walker->x.x[i]; 1847 max_index[i] = Walker; 1848 } 1849 } 1850 } 1851 1852 cout << Verbose(1) << "Found maximum coordinates. " << endl; 1353 1853 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 1354 const int k=0; 1355 1356 Oben.x[k]=1.; 1357 FirstPoint = mol->start; 1358 FirstPoint = FirstPoint->next; 1359 while (FirstPoint->nr != max_index[k]) 1360 { 1361 FirstPoint = FirstPoint->next; 1362 } 1363 cout << Verbose(1) << "Coordinates of start atom: " << FirstPoint->x.x[0] << endl; 1854 const int k = 1; 1855 Oben.x[k] = 1.; 1856 FirstPoint = max_index[k]; 1857 1858 cout << Verbose(1) << "Coordinates of start atom " << *FirstPoint << ": " 1859 << FirstPoint->x.x[0] << endl; 1364 1860 double Storage[2]; 1365 1861 atom* Opt_Candidate = NULL; 1366 Storage[0] =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.1367 Storage[1] =999999.;// This will be an angle looking for the third point.1368 cout << Verbose(1) << "Number of Bonds: " << mol->NumberOfBondsPerAtom[FirstPoint->nr] << endl;1369 1370 Find_second_point_for_Tesselation(FirstPoint, mol->ListOfBondsPerAtom[FirstPoint->nr][0]->GetOtherAtom(FirstPoint), FirstPoint, 0, Oben, Opt_Candidate, Storage, mol, RADIUS); 1371 1372 1862 Storage[0] = 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. 1863 Storage[1] = 999999.; // This will be an angle looking for the third point. 1864 cout << Verbose(1) << "Number of Bonds: " 1865 << mol->NumberOfBondsPerAtom[FirstPoint->nr] << endl; 1866 1867 Find_second_point_for_Tesselation(FirstPoint, FirstPoint, FirstPoint, 0, 1868 Oben, Opt_Candidate, Storage, mol, RADIUS); // we give same point as next candidate as its bonds are looked into in find_second_... 1373 1869 SecondPoint = Opt_Candidate; 1374 Opt_Candidate=NULL; 1870 cout << Verbose(1) << "Found second point is " << *SecondPoint << ".\n"; 1871 1375 1872 helper.CopyVector(&(FirstPoint->x)); 1376 1873 helper.SubtractVector(&(SecondPoint->x)); 1874 helper.Normalize(); 1377 1875 Oben.ProjectOntoPlane(&helper); 1876 Oben.Normalize(); 1378 1877 helper.VectorProduct(&Oben); 1379 Storage[0] =-2.;// This will indicate the quadrant.1380 Storage[1] = 9999999.; // This will be an angle looking for the third point.1878 Storage[0] = -2.; // This will indicate the quadrant. 1879 Storage[1] = 9999999.; // This will be an angle looking for the third point. 1381 1880 1382 1881 Chord.CopyVector(&(FirstPoint->x)); // bring into calling function 1383 1882 Chord.SubtractVector(&(SecondPoint->x)); 1883 // Now, oben and helper are two orthonormalized vectors in the plane defined by Chord (not normalized) 1384 1884 1385 1885 cout << Verbose(1) << "Looking for third point candidates \n"; 1386 Find_next_suitable_point(FirstPoint, SecondPoint, SecondPoint, FirstPoint, 0, &Chord, &helper, &Oben, Opt_Candidate, Storage, RADIUS, mol, 0); 1387 1388 1389 //Starting Triangle is Walker, SecondPoint, Opt_Candidate 1390 1391 cout << Verbose(1) << "The found starting triangle consists of " << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate << "." << endl; 1392 1886 // look in one direction of baseline for initial candidate 1887 Opt_Candidate = NULL; 1888 Opt_Mittelpunkt; 1889 Find_next_suitable_point(FirstPoint, SecondPoint, SecondPoint, FirstPoint, 0, 1890 &Chord, &helper, &Oben, Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1891 // look in other direction of baseline for possible better candidate 1892 Find_next_suitable_point(FirstPoint, SecondPoint, FirstPoint, SecondPoint, 0, 1893 &Chord, &helper, &Oben, Opt_Candidate, &Opt_Mittelpunkt, Storage, RADIUS, mol); 1894 cout << Verbose(1) << "Third Point is " << *Opt_Candidate << endl; 1895 1896 // FOUND Starting Triangle: FirstPoint, SecondPoint, Opt_Candidate 1897 1898 cout << Verbose(1) << "The found starting triangle consists of " 1899 << *FirstPoint << ", " << *SecondPoint << " and " << *Opt_Candidate 1900 << "." << endl; 1901 1902 // Finally, we only have to add the found points 1393 1903 AddTrianglePoint(FirstPoint, 0); 1394 1904 AddTrianglePoint(SecondPoint, 1); 1395 1905 AddTrianglePoint(Opt_Candidate, 2); 1396 1397 BPS[0] = TPS[0]; 1398 BPS[1] = TPS[1]; 1399 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1400 BPS[0] = TPS[1]; 1401 BPS[1] = TPS[2]; 1402 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1403 BPS[0] = TPS[0]; 1404 BPS[1] = TPS[2]; 1405 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1406 1407 Tesselation::BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1408 TrianglesOnBoundary.insert( TrianglePair(TrianglesOnBoundaryCount, BTS) ); 1409 TrianglesOnBoundaryCount++; 1410 1411 for(int i=0;i<NDIM;i++) 1412 { 1413 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 1414 LinesOnBoundaryCount++; 1415 }; 1416 1417 BTS->GetNormalVector(BTS->NormalVector); 1418 1419 if( BTS->NormalVector.ScalarProduct(&Oben)<0) 1420 { 1421 BTS->NormalVector.Scale(-1); 1422 } 1423 }; 1424 1425 1426 void Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol) 1427 { 1428 int N =0; 1429 struct Tesselation *Tess = new Tesselation; 1430 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 1431 cout << flush; 1432 const double RADIUS =6.; 1433 LineMap::iterator baseline; 1434 Tess->Find_starting_triangle(mol, RADIUS); 1435 1436 baseline = Tess->LinesOnBoundary.begin(); 1437 while (baseline != Tess->LinesOnBoundary.end()) { 1438 if (baseline->second->TrianglesCount == 1) 1439 { 1440 cout << Verbose(1) << "Begin of Tesselation ... " << endl; 1441 Tess->Find_next_suitable_triangle(out, tecplot, mol, *(baseline->second), *(baseline->second->triangles.begin()->second), RADIUS, N); //the line is there, so there is a triangle, but only one. 1442 cout << Verbose(1) << "End of Tesselation ... " << endl; 1443 } 1444 else 1445 { 1446 cout << Verbose(1) << "There is a line with " << baseline->second->TrianglesCount << " triangles adjacent"; 1447 } 1448 N++; 1449 baseline++; 1450 } 1451 1452 }; 1906 // ... and respective lines 1907 AddTriangleLine(TPS[0], TPS[1], 0); 1908 AddTriangleLine(TPS[1], TPS[2], 1); 1909 AddTriangleLine(TPS[0], TPS[2], 2); 1910 // ... and triangles to the Maps of the Tesselation class 1911 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); 1912 AddTriangleToLines(); 1913 // ... and calculate its normal vector (with correct orientation) 1914 Oben.Scale(-1.); 1915 BTS->GetNormalVector(Oben); 1916 } 1917 ; 1918 1919 void 1920 Find_non_convex_border(ofstream *out, ofstream *tecplot, molecule* mol) 1921 { 1922 int N = 0; 1923 struct Tesselation *Tess = new Tesselation; 1924 cout << Verbose(1) << "Entering search for non convex hull. " << endl; 1925 cout << flush; 1926 const double RADIUS = 6.; 1927 LineMap::iterator baseline; 1928 Tess->Find_starting_triangle(mol, RADIUS); 1929 1930 baseline = Tess->LinesOnBoundary.begin(); 1931 while (baseline != Tess->LinesOnBoundary.end()) 1932 { 1933 if (baseline->second->TrianglesCount == 1) 1934 { 1935 cout << Verbose(1) << "Begin of Tesselation ... " << endl; 1936 Tess->Find_next_suitable_triangle(out, tecplot, mol, 1937 *(baseline->second), 1938 *(((baseline->second->triangles.begin()))->second), RADIUS, N); //the line is there, so there is a triangle, but only one. 1939 cout << Verbose(1) << "End of Tesselation ... " << endl; 1940 } 1941 else 1942 { 1943 cout << Verbose(1) << "There is a line with " 1944 << baseline->second->TrianglesCount << " triangles adjacent" 1945 << endl; 1946 } 1947 N++; 1948 baseline++; 1949 } 1950 write_tecplot_file(out, tecplot, Tess, mol, -1); 1951 1952 } 1953 ; -
src/boundary.hpp
rcaf5d6 re4ea46 83 83 void AddPoint(atom * Walker); 84 84 void AddTrianglePoint(atom* Candidate, int n); 85 void AddTriangleLine( int n);85 void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n); 86 86 void AddTriangleToLines(); 87 87 void Find_starting_triangle(molecule* mol, const double RADIUS); … … 91 91 LineMap LinesOnBoundary; 92 92 TriangleMap TrianglesOnBoundary; 93 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 93 class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions 94 94 class BoundaryPointSet *BPS[2]; 95 95 class BoundaryLineSet *BLS[3]; … … 98 98 int LinesOnBoundaryCount; 99 99 int TrianglesOnBoundaryCount; 100 int TriangleFilesWritten; 100 101 }; 101 102 -
src/vector.cpp
rcaf5d6 re4ea46 22 22 Vector::~Vector() {}; 23 23 24 /** Calculates square of distance between this and another vector. 25 * \param *y array to second vector 26 * \return \f$| x - y |^2\f$ 27 */ 28 double Vector::DistanceSquared(const Vector *y) const 29 { 30 double res = 0.; 31 for (int i=NDIM;i--;) 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 34 }; 35 24 36 /** Calculates distance between this and another vector. 25 37 * \param *y array to second vector 26 * \return \f$| x - y | ^2\f$38 * \return \f$| x - y |\f$ 27 39 */ 28 40 double Vector::Distance(const Vector *y) const … … 31 43 for (int i=NDIM;i--;) 32 44 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return ( res);45 return (sqrt(res)); 34 46 }; 35 47 -
src/vector.hpp
rcaf5d6 re4ea46 7 7 * basically, just a x[3] but with helpful functions 8 8 */ 9 class Vector { 9 class Vector { 10 10 public: 11 11 double x[NDIM]; … … 16 16 17 17 double Distance(const Vector *y) const; 18 double DistanceSquared(const Vector *y) const; 18 19 double PeriodicDistance(const Vector *y, const double *cell_size) const; 19 20 double ScalarProduct(const Vector *y) const; … … 28 29 void VectorProduct(const Vector *y); 29 30 void ProjectOntoPlane(const Vector *y); 30 void Zero(); 31 void Zero(); 31 32 void One(double one); 32 33 void Init(double x1, double x2, double x3); … … 41 42 void KeepPeriodic(ofstream *out, double *matrix); 42 43 void LinearCombinationOfVectors(const Vector *x1, const Vector *x2, const Vector *x3, double *factors); 43 44 44 45 double CutsPlaneAt(Vector *A, Vector *B, Vector *C); 45 46 bool GetOneNormalVector(const Vector *x1);
Note:
See TracChangeset
for help on using the changeset viewer.